大家说说散打强拳是哪个技能的绝杀技会是什么样的

Android进程绝杀技--forceStop
话说Android开源系统拥有着App不计其数,百家争鸣,都想在这“大争之世”寻得系统存活的一席之地。然则系统资源有限,如若都割据为王,再强劲的CPU也会忙不过来,再庞大的内存终会消耗殆尽,再大容量的电池续航终会昙花一现。
面对芸芸众生,无尽变数,系统以不变应万变,一招绝杀神技forceStop腾空出世,此处以adb指令的方式为例来说说其内部机理:
am force-stop pkgName
am force-stop
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 Am.run
[-& Am.java]
public void run(String[] args) {
mNextArg = 0;
mCurArgData = null;
1.4 Am.onRun
[-& Am.java]
public void onRun() throws Exception {
mAm = ActivityManagerNative.getDefault();
String op = nextArgRequired();
if (op.equals(&start&)) {
} else if (op.equals(&force-stop&)) {
runForceStop();
1.5 Am.runForceStop
[-& Am.java]
private void runForceStop() throws Exception {
int userId = UserHandle.USER_ALL;
while ((opt=nextOption()) != null) {
if (opt.equals(&--user&)) {
userId = parseUserArg(nextArgRequired());
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);
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();
forceStopPackage(packageName, userId);
reply.writeNoException();
return true;
AMP.forceStopPackage来运行在执行adb时所创建的进程,经过Binder Driver后,进入system_server进程的一个binder线程来执行AMN.forceStopPackage,从这开始的操作(包括当前操作)便都运行在system_server系统进程。
进程绝杀技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) {
throw new SecurityException();
final int callingPid = Binder.getCallingPid();
userId = handleIncomingUser(callingPid, Binder.getCallingUid(),
userId, true, ALLOW_FULL_ONLY, &forceStopPackage&, null);
long callingId = Binder.clearCallingIdentity();
IPackageManager pm = AppGlobals.getPackageManager();
synchronized(this) {
int[] users = userId == UserHandle.USER_ALL
? getUsersLocked() : new int[] { userId };
for (int user : users) {
int pkgUid = -1;
pkgUid = pm.getPackageUid(packageName, user);
pm.setPackageStoppedState(packageName, true, user);
if (isUserRunningLocked(user, false)) {
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.forceStopPackageLocked
private void forceStopPackageLocked(final String packageName, int uid, String reason) {
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));
if (!mProcessesReady) {
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
| Intent.FLAG_RECEIVER_FOREGROUND);
intent.putExtra(Intent.EXTRA_UID, uid);
intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(uid));
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null, AppOpsManager.OP_NONE,
null, false, false, MY_PID, Process.SYSTEM_UID, UserHandle.getUserId(uid));
清理跟该包名相关的进程和四大组件之外,还会发送广播ACTION_PACKAGE_RESTARTED,用于清理已注册的alarm,notification信息。
2.3 AMS.forceStopPackageLocked
private final boolean forceStopPackageLocked(String packageName, int appId,
boolean callerWillRestart, boolean purgeCache, boolean doit,
boolean evenPersistent, boolean uninstalling, int userId, String reason) {
if (appId & 0 && packageName != null) {
appId = UserHandle.getAppId(
AppGlobals.getPackageManager().getPackageUid(packageName, 0));
if (doit) {
final ArrayMap&String, SparseArray&Long&& pmap = mProcessCrashTimes.getMap();
for (int ip = pmap.size() - 1; ip &= 0; ip--) {
SparseArray&Long& ba = pmap.valueAt(ip);
for (i = ba.size() - 1; i &= 0; i--) {
boolean remove = false;
final int entUid = ba.keyAt(i);
if (packageName != null) {
if (userId == UserHandle.USER_ALL) {
if (UserHandle.getAppId(entUid) == appId) {
remove = true;
if (entUid == UserHandle.getUid(userId, appId)) {
remove = true;
} else if (UserHandle.getUserId(entUid) == userId) {
remove = true;
if (remove) {
ba.removeAt(i);
if (ba.size() == 0) {
pmap.removeAt(ip);
boolean didSomething = killPackageProcessesLocked(packageName, appId, userId,
-100, callerWillRestart, true, doit, evenPersistent,
packageName == null ? (&stop user & + userId) : (&stop & + packageName));
if (mStackSupervisor.finishDisabledPackageActivitiesLocked(
packageName, null, doit, evenPersistent, userId)) {
didSomething = true;
if (mServices.bringDownDisabledPackageServicesLocked(
packageName, null, userId, evenPersistent, true, doit)) {
didSomething = true;
if (packageName == null) {
mStickyBroadcasts.remove(userId);
ArrayList&ContentProviderRecord& providers = new ArrayList&&();
if (mProviderMap.collectPackageProvidersLocked(packageName, null, doit, evenPersistent,
userId, providers)) {
didSomething = true;
for (i = providers.size() - 1; i &= 0; i--) {
removeDyingProviderLocked(null, providers.get(i), true);
removeUriPermissionsForPackageLocked(packageName, userId, false);
if (doit) {
for (i = mBroadcastQueues.length - 1; i &= 0; i--) {
didSomething |= mBroadcastQueues[i].cleanupDisabledPackageReceiversLocked(
packageName, null, userId, doit);
if (packageName == null || uninstalling) {
if (doit) {
if (purgeCache && packageName != null) {
if (mBooted) {
mStackSupervisor.resumeTopActivitiesLocked();
mStackSupervisor.scheduleIdleLocked();
return didS
对于didSomething只指当方法中所有行为,则返回true.比如killPackageProcessesLocked(),只要杀过一个进程则代表didSomething为true.
该方法的主要功能:
Process: 调用AMS.killPackageProcessesLocked()清理该package所涉及的进程;Activity: 调用ASS.finishDisabledPackageActivitiesLocked()清理该package所涉及的AService: 调用AS.bringDownDisabledPackageServicesLocked()清理该package所涉及的SProvider: 调用AMS.removeDyingProviderLocked()清理该package所涉及的PBroadcastRecevier: 调用BQ.cleanupDisabledPackageReceiversLocked()清理该package所涉及的广播
接下来,从这5个角度来分别说说force-stop的执行过程.
三. Process
3.1 AMS.killPackageProcessesLocked
private final boolean killPackageProcessesLocked(String packageName, int appId,
int userId, int minOomAdj, boolean callerWillRestart, boolean allowRestart,
boolean doit, boolean evenPersistent, String reason) {
ArrayList&ProcessRecord& procs = new ArrayList&&();
final int NP = mProcessNames.getMap().size();
for (int ip=0; ip&NP; ip++) {
SparseArray&ProcessRecord& apps = mProcessNames.getMap().valueAt(ip);
final int NA = apps.size();
for (int ia=0; ia&NA; ia++) {
ProcessRecord app = apps.valueAt(ia);
if (app.persistent && !evenPersistent) {
if (app.removed) {
if (doit) {
procs.add(app);
if (app.setAdj & minOomAdj) {
if (packageName == null) {
final boolean isDep = app.pkgDeps != null
&& app.pkgDeps.contains(packageName);
if (!isDep && UserHandle.getAppId(app.uid) != appId) {
if (userId != UserHandle.USER_ALL && app.userId != userId) {
if (!app.pkgList.containsKey(packageName) && !isDep) {
app.removed = true;
procs.add(app);
int N = procs.size();
for (int i=0; i&N; i++) {
removeProcessLocked(procs.get(i), callerWillRestart, allowRestart, reason);
updateOomAdjLocked();
return N & 0;
一般地force-stop会指定包名,该方法会遍历当前所有运行中的进程mProcessNames,以下条件同时都不满足的进程,则会成为被杀的目标进程:(也就是说满足以下任一条件都可以免死)
persistent进程:进程setAdj & minOomAdj(默认为-100):非UserHandle.USER_ALL同时, 且进程的userId不相等:多用户模型下,不同用户下不能相互杀;进程没有依赖该packageName, 且进程的AppId不相等;进程没有依赖该packageName, 且该packageName没有运行在该进程.
通俗地来说就是:
forceStop不杀系统persistent进程;当指定用户userId时,不杀其他用户空间的进程;
除此之外,以下情况则必然会成为被杀进程:
进程已标记remove=true的进程,则会被杀;进程的pkgDeps中包含该packageName,则会被杀;进程的pkgList中包含该packageName,且该进程与包名所指定的AppId相等则会被杀;
进程的pkgList是在启动组件或者创建进程的过程向该队列添加的,代表的是该应用下有组件运行在该进程。那么pkgDeps是指该进程所依赖的包名,调用ClassLoader的过程添加。
3.2 AMS.removeProcessLocked
private final boolean removeProcessLocked(ProcessRecord app,
boolean callerWillRestart, boolean allowRestart, String reason) {
final String name = app.processN
final int uid = app.
removeProcessNameLocked(name, uid);
if (mHeavyWeightProcess == app) {
boolean needRestart = false;
if (app.pid & 0 && app.pid != MY_PID) {
int pid = app.
synchronized (mPidsSelfLocked) {
mPidsSelfLocked.remove(pid);
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
if (app.isolated) {
mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid);
boolean willRestart = false;
if (app.persistent && !app.isolated) {
if (!callerWillRestart) {
willRestart = true;
needRestart = true;
app.kill(reason, true);
handleAppDiedLocked(app, willRestart, allowRestart);
if (willRestart) {
removeLruProcessLocked(app);
addAppLocked(app.info, false, null );
mRemovedProcesses.add(app);
return needR
该方法的主要功能:
从mProcessNames, mPidsSelfLocked队列移除该进程;移除进程启动超时的消息PROC_START_TIMEOUT_MSG;调用app.kill()来杀进程会同时调用Process.kill和Process.killProcessGroup, 该过程详见调用handleAppDiedLocked()来清理进程相关的信息, 该过程详见
四. Activity
4.1 ASS.finishDisabledPackageActivitiesLocked
[-& ActivityStackSupervisor.java]
boolean finishDisabledPackageActivitiesLocked(String packageName, Set&String& filterByClasses,
boolean doit, boolean evenPersistent, int userId) {
boolean didSomething = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx &= 0; --displayNdx) {
final ArrayList&ActivityStack& stacks = mActivityDisplays.valueAt(displayNdx).mS
final int numStacks = stacks.size();
for (int stackNdx = 0; stackNdx & numS ++stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
if (stack.finishDisabledPackageActivitiesLocked(
packageName, filterByClasses, doit, evenPersistent, userId)) {
didSomething = true;
return didS
4.2 AS.finishDisabledPackageActivitiesLocked
[-& ActivityStack.java]
boolean finishDisabledPackageActivitiesLocked(String packageName, Set&String& filterByClasses,
boolean doit, boolean evenPersistent, int userId) {
boolean didSomething = false;
TaskRecord lastTask = null;
ComponentName homeActivity = null;
for (int taskNdx = mTaskHistory.size() - 1; taskNdx &= 0; --taskNdx) {
final ArrayList&ActivityRecord& activities = mTaskHistory.get(taskNdx).mA
int numActivities = activities.size();
for (int activityNdx = 0; activityNdx & numA ++activityNdx) {
ActivityRecord r = activities.get(activityNdx);
final boolean sameComponent =
(r.packageName.equals(packageName) && (filterByClasses == null
|| filterByClasses.contains(r.realActivity.getClassName())))
|| (packageName == null && r.userId == userId);
if ((userId == UserHandle.USER_ALL || r.userId == userId)
&& (sameComponent || r.task == lastTask)
&& (r.app == null || evenPersistent || !r.app.persistent)) {
if (r.isHomeActivity()) {
if (homeActivity != null && homeActivity.equals(r.realActivity)) {
homeActivity = r.realA
didSomething = true;
if (sameComponent) {
if (r.app != null) {
r.app.removed = true;
r.app = null;
lastTask = r.
if (finishActivityLocked(r, Activity.RESULT_CANCELED, null, &force-stop&,
--activityN
return didS
4.3 AS.finishActivityLocked
[-& ActivityStack.java]
final boolean finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData,
String reason, boolean oomAdj) {
if (r.finishing) {
return false;
r.makeFinishingLocked();
final TaskRecord task = r.
final ArrayList&ActivityRecord& activities = task.mA
final int index = activities.indexOf(r);
if (index & (activities.size() - 1)) {
task.setFrontOfTask();
if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
ActivityRecord next = activities.get(index+1);
next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
r.pauseKeyDispatchingLocked();
adjustFocusedActivityLocked(r, &finishActivity&);
finishActivityResultsLocked(r, resultCode, resultData);
if (mResumedActivity == r) {
boolean endTask = index &= 0;
mWindowManager.prepareAppTransition(endTask
? AppTransition.TRANSIT_TASK_CLOSE
: AppTransition.TRANSIT_ACTIVITY_CLOSE, false);
mWindowManager.setAppVisibility(r.appToken, false);
if (mPausingActivity == null) {
startPausingLocked(false, false, false, false);
if (endTask) {
mStackSupervisor.removeLockedTaskLocked(task);
} else if (r.state != ActivityState.PAUSING) {
return finishCurrentActivityLocked(r, FINISH_AFTER_PAUSE, oomAdj) == null;
return false;
4.3.1 AR.makeFinishingLocked
[-& ActivityRecord.java]
void makeFinishingLocked() {
if (!finishing) {
if (task != null && task.stack != null
&& this == task.stack.getVisibleBehindActivity()) {
mStackSupervisor.requestVisibleBehindLocked(this, false);
finishing = true;
if (stopped) {
clearOptionsLocked();
4.3.2 ASS.requestVisibleBehindLocked
boolean requestVisibleBehindLocked(ActivityRecord r, boolean visible) {
final ActivityStack stack = r.task.
if (stack == null) {
return false;
final boolean isVisible = stack.hasVisibleBehindActivity();
final ActivityRecord top = topRunningActivityLocked();
if (top == null || top == r || (visible == isVisible)) {
stack.setVisibleBehindActivity(visible ? r : null);
return true;
if (visible && top.fullscreen) {
} else if (!visible && stack.getVisibleBehindActivity() != r) {
return false;
stack.setVisibleBehindActivity(visible ? r : null);
if (!visible) {
final ActivityRecord next = stack.findNextTranslucentActivity(r);
if (next != null) {
mService.convertFromTranslucent(next.appToken);
if (top.app != null && top.app.thread != null) {
top.app.thread.scheduleBackgroundVisibleBehindChanged(top.appToken, visible);
return true;
4.3.3 TaskRecord.setFrontOfTask
[-& TaskRecord.java]
final void setFrontOfTask() {
boolean foundFront = false;
final int numActivities = mActivities.size();
for (int activityNdx = 0; activityNdx & numA ++activityNdx) {
final ActivityRecord r = mActivities.get(activityNdx);
if (foundFront || r.finishing) {
r.frontOfTask = false;
r.frontOfTask = true;
foundFront = true;
if (!foundFront && numActivities & 0) {
mActivities.get(0).frontOfTask = true;
将该Task中从底部往上查询, 第一个处于非finishing状态的ActivityRecord,则设置为根Activity(即r.frontOfTask = true),其他都为当所有的activity都处于finishing状态,则把最底部的activity设置成跟Activity.
4.3.4 AS.adjustFocusedActivityLocked
[-& ActivityStack.java]
private void adjustFocusedActivityLocked(ActivityRecord r, String reason) {
if (mStackSupervisor.isFrontStack(this) && mService.mFocusedActivity == r) {
ActivityRecord next = topRunningActivityLocked(null);
final String myReason = reason + & adjustFocus&;
if (next != r) {
final TaskRecord task = r.
boolean adjust = false;
if ((next == null || next.task != task) && r.frontOfTask) {
if (task.isOverHomeStack() && task == topTask()) {
adjust = true;
for (int taskNdx = mTaskHistory.size() - 1; taskNdx &= 0; --taskNdx) {
final TaskRecord tr = mTaskHistory.get(taskNdx);
if (tr.getTopActivity() != null) {
} else if (tr.isOverHomeStack()) {
adjust = true;
if (adjust) {
if (!mFullscreen
&& adjustFocusToNextVisibleStackLocked(null, myReason)) {
if (mStackSupervisor.moveHomeStackTaskToTop(
task.getTaskToReturnTo(), myReason)) {
final ActivityRecord top = mStackSupervisor.topRunningActivityLocked();
if (top != null) {
mService.setFocusedActivityLocked(top, myReason);
4.3.5 AS.finishCurrentActivityLocked
final ActivityRecord finishCurrentActivityLocked(ActivityRecord r, int mode, boolean oomAdj) {
if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
if (!mStackSupervisor.mStoppingActivities.contains(r)) {
mStackSupervisor.mStoppingActivities.add(r);
if (mStackSupervisor.mStoppingActivities.size() & 3
|| r.frontOfTask && mTaskHistory.size() &= 1) {
mStackSupervisor.scheduleIdleLocked();
mStackSupervisor.checkReadyForSleepLocked();
r.state = ActivityState.STOPPING;
if (oomAdj) {
mService.updateOomAdjLocked();
mStackSupervisor.mStoppingActivities.remove(r);
mStackSupervisor.mGoingToSleepActivities.remove(r);
mStackSupervisor.mWaitingVisibleActivities.remove(r);
if (mResumedActivity == r) {
mResumedActivity = null;
final ActivityState prevState = r.
r.state = ActivityState.FINISHING;
if (mode == FINISH_IMMEDIATELY
|| (mode == FINISH_AFTER_PAUSE && prevState == ActivityState.PAUSED)
|| prevState == ActivityState.STOPPED
|| prevState == ActivityState.INITIALIZING) {
r.makeFinishingLocked();
boolean activityRemoved = destroyActivityLocked(r, true, &finish-imm&);
if (activityRemoved) {
mStackSupervisor.resumeTopActivitiesLocked();
return activityRemoved ? null :
mStackSupervisor.mFinishingActivities.add(r);
r.resumeKeyDispatchingLocked();
mStackSupervisor.getFocusedStack().resumeTopActivityLocked(null);
满足下面其中之一的条件,则会执行finish以及destroy Activity.
模式为FINISH_IMMEDIATELY模式为FINISH_AFTER_PAUSE, 且Activity状态已处于PAUSED;Activity的状态为STOPPED或INITIALIZING.
4.3.6 AS.destroyActivityLocked
final boolean destroyActivityLocked(ActivityRecord r, boolean removeFromApp, String reason) {
boolean removedFromHistory = false;
cleanUpActivityLocked(r, false, false);
final boolean hadApp = r.app != null;
if (hadApp) {
if (removeFromApp) {
r.app.activities.remove(r);
if (mService.mHeavyWeightProcess == r.app && r.app.activities.size() &= 0) {
mService.mHeavyWeightProcess = null;
mService.mHandler.sendEmptyMessage(ActivityManagerService.CANCEL_HEAVY_NOTIFICATION_MSG);
if (r.app.activities.isEmpty()) {
mService.mServices.updateServiceConnectionActivitiesLocked(r.app);
mService.updateLruProcessLocked(r.app, false, null);
mService.updateOomAdjLocked();
boolean skipDestroy = false;
r.app.thread.scheduleDestroyActivity(r.appToken, r.finishing,
r.configChangeFlags);
} catch (Exception e) {
if (r.finishing) {
removeActivityFromHistoryLocked(r, reason + & exceptionInScheduleDestroy&);
removedFromHistory = true;
skipDestroy = true;
r.nowVisible = false;
if (r.finishing && !skipDestroy) {
r.state = ActivityState.DESTROYING;
Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG, r);
mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
r.state = ActivityState.DESTROYED;
r.app = null;
if (r.finishing) {
removeActivityFromHistoryLocked(r, reason + & hadNoApp&);
removedFromHistory = true;
r.state = ActivityState.DESTROYED;
r.app = null;
r.configChangeFlags = 0;
return removedFromH
五. Service
5.1 bringDownDisabledPackageServicesLocked
[-& ActiveServices.java]
boolean bringDownDisabledPackageServicesLocked(String packageName, Set&String& filterByClasses,
int userId, boolean evenPersistent, boolean killProcess, boolean doit) {
boolean didSomething = false;
if (mTmpCollectionResults != null) {
mTmpCollectionResults.clear();
if (userId == UserHandle.USER_ALL) {
for (int i = mServiceMap.size() - 1; i &= 0; i--) {
didSomething |= collectPackageServicesLocked(packageName, filterByClasses,
evenPersistent, doit, killProcess, mServiceMap.valueAt(i).mServicesByName);
if (!doit && didSomething) {
ServiceMap smap = mServiceMap.get(userId);
if (smap != null) {
ArrayMap&ComponentName, ServiceRecord& items = smap.mServicesByN
didSomething = collectPackageServicesLocked(packageName, filterByClasses,
evenPersistent, doit, killProcess, items);
if (mTmpCollectionResults != null) {
for (int i = mTmpCollectionResults.size() - 1; i &= 0; i--) {
bringDownServiceLocked(mTmpCollectionResults.get(i));
mTmpCollectionResults.clear();
return didS
5.2 collectPackageServicesLocked
[-& ActiveServices.java]
private boolean collectPackageServicesLocked(String packageName, Set&String& filterByClasses,
boolean evenPersistent, boolean doit, boolean killProcess,
ArrayMap&ComponentName, ServiceRecord& services) {
boolean didSomething = false;
for (int i = services.size() - 1; i &= 0; i--) {
ServiceRecord service = services.valueAt(i);
final boolean sameComponent = packageName == null
|| (service.packageName.equals(packageName)
&& (filterByClasses == null
|| filterByClasses.contains(service.name.getClassName())));
if (sameComponent
&& (service.app == null || evenPersistent || !service.app.persistent)) {
if (!doit) {
didSomething = true;
if (service.app != null) {
service.app.removed = killP
if (!service.app.persistent) {
service.app.services.remove(service);
service.app = null;
service.isolatedProc = null;
if (mTmpCollectionResults == null) {
mTmpCollectionResults = new ArrayList&&();
mTmpCollectionResults.add(service);
return didS
该方法的主要功能就是收集该满足条件service放入mTmpCollectionResults.
5.3 bringDownServiceLocked
[-& ActiveServices.java]
private final void bringDownServiceLocked(ServiceRecord r) {
for (int conni=r.connections.size()-1; conni&=0; conni--) {
ArrayList&ConnectionRecord& c = r.connections.valueAt(conni);
for (int i=0; i&c.size(); i++) {
ConnectionRecord cr = c.get(i);
cr.serviceDead = true;
cr.conn.connected(r.name, null);
if (r.app != null && r.app.thread != null) {
for (int i=r.bindings.size()-1; i&=0; i--) {
IntentBindRecord ibr = r.bindings.valueAt(i);
if (ibr.hasBound) {
bumpServiceExecutingLocked(r, false, &bring down unbind&);
mAm.updateOomAdjLocked(r.app);
ibr.hasBound = false;
r.app.thread.scheduleUnbindService(r, ibr.intent.getIntent());
r.destroyTime = SystemClock.uptimeMillis();
final ServiceMap smap = getServiceMap(r.userId);
smap.mServicesByName.remove(r.name);
smap.mServicesByIntent.remove(r.intent);
r.totalRestartCount = 0;
unscheduleServiceRestartLocked(r, 0, true);
for (int i=mPendingServices.size()-1; i&=0; i--) {
if (mPendingServices.get(i) == r) {
mPendingServices.remove(i);
r.cancelNotification();
r.isForeground = false;
r.foregroundId = 0;
r.foregroundNoti = null;
r.clearDeliveredStartsLocked();
r.pendingStarts.clear();
if (r.app != null) {
synchronized (r.stats.getBatteryStats()) {
r.stats.stopLaunchedLocked();
r.app.services.remove(r);
if (r.app.thread != null) {
updateServiceForegroundLocked(r.app, false);
bumpServiceExecutingLocked(r, false, &destroy&);
mDestroyingServices.add(r);
r.destroying = true;
mAm.updateOomAdjLocked(r.app);
r.app.thread.scheduleStopService(r);
if (r.bindings.size() & 0) {
r.bindings.clear();
if (r.restarter instanceof ServiceRestarter) {
((ServiceRestarter)r.restarter).setService(null);
int memFactor = mAm.mProcessStats.getMemFactorLocked();
long now = SystemClock.uptimeMillis();
if (r.tracker != null) {
r.tracker.setStarted(false, memFactor, now);
r.tracker.setBound(false, memFactor, now);
if (r.executeNesting == 0) {
r.tracker.clearCurrentOwner(r, false);
r.tracker = null;
smap.ensureNotStartingBackground(r);
5.4 unscheduleServiceRestartLocked
private final boolean unscheduleServiceRestartLocked(ServiceRecord r, int callingUid,
boolean force) {
if (!force && r.restartDelay == 0) {
return false;
boolean removed = mRestartingServices.remove(r);
if (removed || callingUid != r.appInfo.uid) {
r.resetRestartCounter();
if (removed) {
clearRestartingIfNeededLocked(r);
mAm.mHandler.removeCallbacks(r.restarter);
return true;
六. Provider
6.1 PM.collectPackageProvidersLocked
[-& ProviderMap.java]
boolean collectPackageProvidersLocked(String packageName, Set&String& filterByClasses,
boolean doit, boolean evenPersistent, int userId,
ArrayList&ContentProviderRecord& result) {
boolean didSomething = false;
if (userId == UserHandle.USER_ALL || userId == UserHandle.USER_OWNER) {
didSomething = collectPackageProvidersLocked(packageName, filterByClasses,
doit, evenPersistent, mSingletonByClass, result);
if (!doit && didSomething) {
if (userId == UserHandle.USER_ALL) {
for (int i = 0; i & mProvidersByClassPerUser.size(); i++) {
if (collectPackageProvidersLocked(packageName, filterByClasses,
doit, evenPersistent, mProvidersByClassPerUser.valueAt(i), result)) {
didSomething = true;
HashMap&ComponentName, ContentProviderRecord& items
= getProvidersByClass(userId);
if (items != null) {
didSomething |= collectPackageProvidersLocked(packageName, filterByClasses,
doit, evenPersistent, items, result);
return didS
当userId = UserHandle.USER_ALL时, 则会mSingletonByClass和mProvidersByClassPerUser结构中查询所有属于该package的providers.当userId = UserHandle.USER_OWNER时,则会从mSingletonByClass和mProvidersByClassPerUser中userId相等的
数据结构中查询所有属于该package的providers.当userId不属于上述两者之一时,则会从mProvidersByClassPerUser中userId相等的查询所有属于该package的providers.
6.2 PM.collectPackageProvidersLocked
[-& ProviderMap.java]
private boolean collectPackageProvidersLocked(String packageName,
Set&String& filterByClasses, boolean doit, boolean evenPersistent,
HashMap&ComponentName, ContentProviderRecord& providers,
ArrayList&ContentProviderRecord& result) {
boolean didSomething = false;
for (ContentProviderRecord provider : providers.values()) {
final boolean sameComponent = packageName == null
|| (provider.info.packageName.equals(packageName)
&& (filterByClasses == null
|| filterByClasses.contains(provider.name.getClassName())));
if (sameComponent
&& (provider.proc == null || evenPersistent || !provider.proc.persistent)) {
if (!doit) {
didSomething = true;
result.add(provider);
return didS
6.3 AMS.removeDyingProviderLocked
private final boolean removeDyingProviderLocked(ProcessRecord proc,
ContentProviderRecord cpr, boolean always) {
final boolean inLaunching = mLaunchingProviders.contains(cpr);
if (!inLaunching || always) {
synchronized (cpr) {
cpr.launchingApp = null;
cpr.notifyAll();
mProviderMap.removeProviderByClass(cpr.name, UserHandle.getUserId(cpr.uid));
String names[] = cpr.info.authority.split(&;&);
for (int j = 0; j & names. j++) {
mProviderMap.removeProviderByName(names[j], UserHandle.getUserId(cpr.uid));
for (int i = cpr.connections.size() - 1; i &= 0; i--) {
ContentProviderConnection conn = cpr.connections.get(i);
if (conn.waiting) {
if (inLaunching && !always) {
ProcessRecord capp = conn.
conn.dead = true;
if (conn.stableCount & 0) {
if (!capp.persistent && capp.thread != null
&& capp.pid != 0
&& capp.pid != MY_PID) {
capp.kill(&depends on provider &
+ cpr.name.flattenToShortString()
+ & in dying proc & + (proc != null ? proc.processName : &??&), true);
} else if (capp.thread != null && conn.provider.provider != null) {
capp.thread.unstableProviderDied(conn.provider.provider.asBinder());
cpr.connections.remove(i);
if (conn.client.conProviders.remove(conn)) {
stopAssociationLocked(capp.uid, capp.processName, cpr.uid, cpr.name);
if (inLaunching && always) {
mLaunchingProviders.remove(cpr);
return inL
当其他app使用该provider, 且建立stable的连接, 那么对于非persistent进程,则会由于依赖该provider的缘故而被杀.
七. Broadcast
7.1 BQ.cleanupDisabledPackageReceiversLocked
[-& BroadcastQueue.java]
boolean cleanupDisabledPackageReceiversLocked(
String packageName, Set&String& filterByClasses, int userId, boolean doit) {
boolean didSomething = false;
for (int i = mParallelBroadcasts.size() - 1; i &= 0; i--) {
didSomething |= mParallelBroadcasts.get(i).cleanupDisabledPackageReceiversLocked(
packageName, filterByClasses, userId, doit);
if (!doit && didSomething) {
return true;
for (int i = mOrderedBroadcasts.size() - 1; i &= 0; i--) {
didSomething |= mOrderedBroadcasts.get(i).cleanupDisabledPackageReceiversLocked(
packageName, filterByClasses, userId, doit);
if (!doit && didSomething) {
return true;
return didS
该方法主要功能:
清理并行广播队列mParallelBroadcasts;清理有序广播队列mOrderedBroadcasts
7.2 BR.cleanupDisabledPackageReceiversLocked
[-& BroadcastRecord.java]
boolean cleanupDisabledPackageReceiversLocked(
String packageName, Set&String& filterByClasses, int userId, boolean doit) {
if ((userId != UserHandle.USER_ALL && this.userId != userId) || receivers == null) {
return false;
boolean didSomething = false;
for (int i = receivers.size() - 1; i &= 0; i--) {
o = receivers.get(i);
if (!(o instanceof ResolveInfo)) {
ActivityInfo info = ((ResolveInfo)o).activityI
final boolean sameComponent = packageName == null
|| (info.applicationInfo.packageName.equals(packageName)
&& (filterByClasses == null || filterByClasses.contains(info.name)));
if (sameComponent) {
didSomething = true;
receivers.remove(i);
if (i & nextReceiver) {
nextReceiver--;
nextReceiver = Math.min(nextReceiver, receivers.size());
return didS
八. Alarm和Notification
在前面[小节2.2]介绍到处理完forceStopPackageLocked(),紧接着便是发送广播ACTION_PACKAGE_RESTARTED,经过,最终调用到注册过该广播的接收者。
8.1 Alarm清理
[-& AlarmManagerService.java]
class UninstallReceiver extends BroadcastReceiver {
public UninstallReceiver() {
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
filter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
filter.addDataScheme(&package&);
getContext().registerReceiver(this, filter);
public void onReceive(Context context, Intent intent) {
synchronized (mLock) {
String action = intent.getAction();
String pkgList[] = null;
if (Intent.ACTION_QUERY_PACKAGE_RESTART.equals(action)) {
Uri data = intent.getData();
if (data != null) {
String pkg = data.getSchemeSpecificPart();
if (pkg != null) {
pkgList = new String[]{pkg};
if (pkgList != null && (pkgList.length & 0)) {
for (String pkg : pkgList) {
removeLocked(pkg);
mPriorities.remove(pkg);
for (int i=mBroadcastStats.size()-1; i&=0; i--) {
ArrayMap&String, BroadcastStats& uidStats = mBroadcastStats.valueAt(i);
if (uidStats.remove(pkg) != null) {
if (uidStats.size() &= 0) {
mBroadcastStats.removeAt(i);
调用AlarmManagerService中的removeLocked()方法,从mAlarmBatches和mPendingWhileIdleAlarms队列中移除包所相关的alarm.
8.2 Notification清理
[-& NotificationManagerService.java]
private final BroadcastReceiver mPackageIntentReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(Intent.ACTION_PACKAGE_ADDED)
|| (queryRemove=action.equals(Intent.ACTION_PACKAGE_REMOVED))
|| action.equals(Intent.ACTION_PACKAGE_RESTARTED)
|| (packageChanged=action.equals(Intent.ACTION_PACKAGE_CHANGED))
|| (queryRestart=action.equals(Intent.ACTION_QUERY_PACKAGE_RESTART))
|| action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) {
int changeUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
UserHandle.USER_ALL);
String pkgList[] = null;
boolean queryReplace = queryRemove &&
intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
if (action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) {
Uri uri = intent.getData();
String pkgName = uri.getSchemeSpecificPart();
if (packageChanged) {
pkgList = new String[]{pkgName};
if (pkgList != null && (pkgList.length & 0)) {
for (String pkgName : pkgList) {
if (cancelNotifications) {
cancelAllNotificationsInt(MY_UID, MY_PID, pkgName, 0, 0, !queryRestart,
changeUserId, REASON_PACKAGE_CHANGED, null);
mListeners.onPackagesChanged(queryReplace, pkgList);
mConditionProviders.onPackagesChanged(queryReplace, pkgList);
mRankingHelper.onPackagesChanged(queryReplace, pkgList);
调用NotificationManagerService.java 中的cancelAllNotificationsInt()方法,从mNotificationList队列中移除包所相关的Notification.
九. 级联诛杀
这里就跟大家分享一段经历吧,记得之前有BAT的某浏览器大厂(具体名称就匿了),浏览器会因为另一个app被杀而导致自己无辜被牵连所杀,并怀疑是ROM定制化导致的bug,于是发邮件向我厂请教缘由。
遇到这个问题,首先将两个app安装到Google原生系统,结果是依然会被级联诛杀,很显然可以排除厂商ROM定制的缘故,按常理说bug应该可以让app自行解决。出于好奇,帮他们进一步调查了下这个问题,发现并非无辜被杀,而是force-stop的级联诛杀所导致的。
简单来说就是App1调用了getClassLoader()来加载App2,那么App1所运行的进程便会在其pkgDeps队列中增加App2的包名,在前面[小节3.2]已经提到pkgDeps,杀进程的过程中会遍历该队列,当App2被forceStop所杀时,便是级联诛杀App1。App1既然会调用App2的ClassLoader来加载其方法,那么就建立了一定的联系,这是Google有意赋予forceStop这个强力杀的功能。
这个故事是想告诉大家在插件化或者反射的过程中要注意这种情况,防止不必要的误伤。接下来具体说说这个过程是如何建立依赖的。
9.1 CI.getClassLoader
[-& ContextImpl.java]
public ClassLoader getClassLoader() {
return mPackageInfo != null ?
mPackageInfo.getClassLoader() : ClassLoader.getSystemClassLoader();
9.2 LA.getClassLoader
[-& LoadedApk.java]
public ClassLoader getClassLoader() {
synchronized (this) {
if (mClassLoader != null) {
return mClassL
if (mPackageName.equals(&android&)) {
if (mBaseClassLoader == null) {
mClassLoader = ClassLoader.getSystemClassLoader();
mClassLoader = mBaseClassL
return mClassL
if (mRegisterPackage) {
ActivityManagerNative.getDefault().addPackageDependency(mPackageName);
mClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip,
mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
libraryPermittedPath, mBaseClassLoader);
return mClassL
9.3 AMS.addPackageDependency
public void addPackageDependency(String packageName) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
if (callingPid == Process.myPid()) {
synchronized (mPidsSelfLocked) {
proc = mPidsSelfLocked.get(Binder.getCallingPid());
if (proc != null) {
if (proc.pkgDeps == null) {
proc.pkgDeps = new ArraySet&String&(1);
proc.pkgDeps.add(packageName);
调用ClassLoader来加载启动包名时,则会将该包名加入到进程的pkgDeps。
forceStop的功能如下:
Process: 调用AMS.killPackageProcessesLocked()清理该package所涉及的进程;Activity: 调用ASS.finishDisabledPackageActivitiesLocked()清理该package所涉及的AService: 调用AS.bringDownDisabledPackageServicesLocked()清理该package所涉及的SProvider: 调用AMS.removeDyingProviderLocked()清理该package所涉及的PBroadcastRecevier: 调用BQ.cleanupDisabledPackageReceiversLocked()清理该package所涉及的广播发送广播ACTION_PACKAGE_RESTARTED,用于停止已注册的alarm,notification.
功能点归纳:
force-stop并不会杀persistent进程;当app被force-stop后,无法接收到任何普通广播,那么也就常见的监听手机网络状态的变化或者屏幕亮灭的广播来拉起进程肯定是不可行;当app被force-stop后,那么alarm闹钟一并被清理,无法实现定时响起的功能;app被force-stop后,四大组件以及相关进程都被一一剪除清理,即便多进程架构的app也无法拉起自己;级联诛杀:当app通过ClassLoader加载另一个app,则会在force-stop的过程中会被级联诛杀;生死与共:当app与另个app使用了share uid,则会在force-stop的过程,任意一方被杀则另一方也被杀,建立起生死与共的强关系。
既然force-stop多次提到杀进程,那最后简单说两句关于保活:正确的保活姿态,应该是在用户需要时保证千万别被杀,用户不需要时别强保活,一切以用户为出发点。
进程是否需要存活,系统上层有AMS来管理缓存进程和空进程,底层有LowMemoryKiller来根据系统可用内存的情况来管理进程是否存活,这样的策略是从系统整体性角度考虑,为了是给用户提供更好更流畅的用户体验。用户需要的时候千万别被杀:谨慎使用插件化和共享uid,除非愿意接受级联诛杀和生死与共的场景;还有就是提高自身app的稳定性,减少crash和anr的发生频率,这才是正道。用户不需要的时候别强保活:为了保活,多进程架构,利用各种小技巧来提升优先级等都是不可取的,一招force-stop足以干掉90%以上的保活策略,当然还有一些其他手段及漏洞来保活,系统层面往往还会采取一些特别的方法来禁止保活。博主曾经干过手机底层的性能与功耗优化工作,深知不少app的流氓行径,严重系统的流畅度与手机续航能力。
为了android有更好的用户体验,为了不影响手机系统性能,为了不降低手机续航能力,建议大家花更多时间精力在如何提高app的稳健性,如何优化app性能,共同打造Android的良好生态圈。
没有更多推荐了,

我要回帖

更多关于 散打技能加点图 的文章

 

随机推荐