android 进程被杀广播,Android 进程绝杀技forceStop(一)

本文详细探讨了Android系统中的force-stop命令,通过adb指令来停止应用进程的内部机理。首先,介绍了force-stop如何通过Am.java中的onRun方法触发,并详细解析了force-stop的执行流程,涉及到ActivityManagerService(AMS)中的多个关键方法,如forceStopPackageLocked。接着,讲解了force-stop如何清理进程、Activity、Service、Provider和BroadcastReceiver,并重点阐述了killPackageProcessesLocked方法。最后,通过举例说明了finishActivityLocked方法在处理Activity销毁过程中的作用。整个force-stop过程展示了Android系统如何彻底停止应用程序及其相关组件,确保系统资源的有效管理。
摘要由CSDN通过智能技术生成

一.概述

1.1 引言

话说Android开源系统拥有着App不计其数,百家争鸣,都想在这“大争之世”寻得系统存活的一席之地。然则系统资源有限,如若都割据为王,再强劲的CPU也会忙不过来,再庞大的内存终会消耗殆尽,再大容量的电池续航终会昙花一现。

面对芸芸众生,无尽变数,系统以不变应万变,一招绝杀神技forceStop腾空出世,此处以adb指令的方式为例来说说其内部机理:am force-stop pkgName

am force-stop --user 2 pkgName //只杀用户userId=2的相关信息

force-stop命令杀掉所有用户空间下的包名pkgName相关的信息,也可以通过--user来指定用户Id。 当执行上述am指令时,则会触发调用Am.java的main()方法,接下来从main方法开始说起。

1.2 Am.main

[-> Am.java]public static void main(String[] args) {

(new Am()).run(args); //【见小节1.3】

}

1.3 Am.run

[-> Am.java]public void run(String[] args) {

...

mArgs = args;

mNextArg = 0;

mCurArgData = null;

onRun(); //【见小节1.4】

...

}

1.4 Am.onRun

[-> Am.java]public void onRun() throws Exception {

//获取的是Binder proxy对象AMP

mAm = ActivityManagerNative.getDefault();

String op = nextArgRequired();

if (op.equals("start")) {

...

} else if (op.equals("force-stop")) {

runForceStop(); //【见小节1.5】

}

...

}

1.5 Am.runForceStop

[-> Am.java]private void runForceStop() throws Exception {

int userId = UserHandle.USER_ALL;

String opt;

// 当指定用户时,则解析相应userId

while ((opt=nextOption()) != null) {

if (opt.equals("--user")) {

userId = parseUserArg(nextArgRequired());

}

}

//【见小节1.6】

mAm.forceStopPackage(nextArgRequired(), userId);

}

当不指定userId时,则默认为UserHandle.USER_ALL。

1.6 AMP.forceStopPackage

[-> ActivityManagerNative.java ::AMP]public void forceStopPackage(String packageName, int userId) throws RemoteException {

Parcel data = Parcel.obtain();

Parcel reply = Parcel.obtain();

data.writeInterfaceToken(IActivityManager.descriptor);

data.writeString(packageName);

data.writeInt(userId);

//【见小节1.7】

mRemote.transact(FORCE_STOP_PACKAGE_TRANSACTION, data, reply, 0);

reply.readException();

data.recycle();

reply.recycle();

}

1.7 AMN.onTransact

[-> ActivityManagerNative.java]public boolean onTransact(int code, Parcel data, Parcel reply, int flags)

throws RemoteException {

switch (code) {

case FORCE_STOP_PACKAGE_TRANSACTION: {

data.enforceInterface(IActivityManager.descriptor);

String packageName = data.readString();

int userId = data.readInt();

//【见小节2.1】

forceStopPackage(packageName, userId);

reply.writeNoException();

return true;

}

...

}

}

AMP.forceStopPackage来运行在执行adb时所创建的进程,经过Binder Driver后,进入system_server进程的一个binder线程来执行AMN.forceStopPackage,从这开始的操作(包括当前操作)便都运行在system_server系统进程。

1.8 小节

进程绝杀技force-stop,并非任意app可直接调用, 否则App间可以相互停止对方,则岂非天下大乱。该方法的存在便是供系统差遣。一般地,点击home弹出的清理用户最近使用app采取的策略便是force-stop.

至于force-stop的触发方式,除了adb的方式,还可通过获取ActivityManager再调用其方法forceStopPackage(),不过这是@hide隐藏方法,同样是需要具有FORCE_STOP_PACKAGES权限。虽然第三方普通app不能直接调用,但对于深入理解Android,还是很有必要知道系统是如何彻底清理进程的过程。接下来,进入AMS来深入探查force-stop的内部机理。

二. force-stop内部机理

2.1 AMS.forceStopPackage

[-> ActivityManagerService.java]public void forceStopPackage(final String packageName, int userId) {

if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)

!= PackageManager.PERMISSION_GRANTED) {

//需要权限permission.FORCE_STOP_PACKAGES

throw new SecurityException();

}

final int callingPid = Binder.getCallingPid();

userId = handleIncomingUser(callingPid, Binder.getCallingUid(),

userId, true, ALLOW_FULL_ONLY, "forceStopPackage", null);

long callingId = Binder.clearCallingIdentity();

try {

IPackageManager pm = AppGlobals.getPackageManager();

synchronized(this) {

int[] users = userId == UserHandle.USER_ALL

? getUsersLocked() : new int[] { userId };

for (int user : users) {

int pkgUid = -1;

//根据包名和userId来查询相应的uid

pkgUid = pm.getPackageUid(packageName, user);

//设置包的状态为stopped

pm.setPackageStoppedState(packageName, true, user);

if (isUserRunningLocked(user, false)) {

//【见流程2.2】

forceStopPackageLocked(packageName, pkgUid, "from pid " + callingPid);

}

}

}

} finally {

Binder.restoreCallingIdentity(callingId);

}

}

这里有一个过程非常重要,那就是setPackageStoppedState()将包的状态设置为stopped,那么所有广播都无法接收,除非带有标记FLAG_INCLUDE_STOPPED_PACKAGES的广播,系统默认的广播几乎都是不带有该标志,也就意味着被force-stop的应用是无法通过建立手机网络状态或者亮灭的广播来拉起进程。

当使用force stop方式来结束进程时, reason一般都是"from pid " + callingPid. 当然也有另外,那就是AMS.clearApplicationUserData方法调用forceStopPackageLocked的reason为"clear data".

2.2 AMS.forceStopPackageLockedprivate void forceStopPackageLocked(final String packageName, int uid, String reason) {

//[见流程2.3]

forceStopPackageLocked(packageName, UserHandle.getAppId(uid), false,

false, true, false, false, UserHandle.getUserId(uid), reason);

Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,

Uri.fromParts("package", packageName, null));

//系统启动完毕后,则mProcessesReady=

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值