基于Android 12的force-stop流程分析

force-stop可以强制结束一个package进程及其相关的信息。可以通过adb命令和设置中的入口来使用。如果想结束进程,主要的adb命令有以下几种:

(1)adb shell kill -9 <进程号>

这种方式只会结束一个进程

(2)adb shell am force-stop <包名>

这种方式会结束package进程及其相关的进程,也就是说可能不止结束一个进程。

(3)adb shell pm clear <包名>

这种方法不仅会停止APP进程,而且会清除这个APP进程产生的所有数据。

这里,只分析force-stop的流程

从adb shell am命令来开始分析,force-stop是一个am的命令,所以可以从ActivityManagerShellCommand.java来开始分析,这个文件里定义了各种am命令会执行的原生方法,我们可以通过这个类来很快的判断am命令最终调用的方法。

frameworks/base/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
case "force-stop":
    return runForceStop(pw);
 
int runForceStop(PrintWriter pw) throws RemoteException {
        int userId = UserHandle.USER_ALL;//当不指定userId时,则默认为UserHandle.USER_ALL
 
        String opt;
        while ((opt = getNextOption()) != null) {
            if (opt.equals("--user")) {//是否需要指定userId
                userId = UserHandle.parseUserArg(getNextArgRequired());
            } else {
                getErrPrintWriter().println("Error: Unknown option: " + opt);
                return -1;
            }
        }
        mInterface.forceStopPackage(getNextArgRequired(), userId);//binder访问AMS中的方法
        return 0;
    }

adb shell force-stop命令有两种使用方法:

(1)adb shell force-stop <包名>

(2)adb shell force-stop --user <userid>  <包名> :停止某个userId下某个包名的进程信息,指定userId

无论哪种方法,都是通过binder调用了AMS的forceStopPackage()方法

AMS
@Override
public void forceStopPackage(final String packageName, int userId) {
    if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
            != PackageManager.PERMISSION_GRANTED) {//force-stop需要FORCE_STOP_PACKAGES权限
        String msg = "Permission Denial: forceStopPackage() from pid="
                + Binder.getCallingPid()
                + ", uid=" + Binder.getCallingUid()
                + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
        Slog.w(TAG, msg);
        throw new SecurityException(msg);//缺少权限的情况下需要抛出异常
    }
    final int callingPid = Binder.getCallingPid();
    userId = mUserController.handleIncomingUser(callingPid, Binder.getCallingUid(),
            userId, true, ALLOW_FULL_ONLY, "forceStopPackage", null);
    final long callingId = Binder.clearCallingIdentity();
    try {
        IPackageManager pm = AppGlobals.getPackageManager();
        synchronized(this) {
            int[] users = userId == UserHandle.USER_ALL
                    ? mUserController.getUsers() : new int[] { userId };
            for (int user : users) {//遍历所有用户,可能涉及到多用户
                if (getPackageManagerInternal().isPackageStateProtected(
                        packageName, user)) {//如果package的状态是受保护的,那么不能被force-stop
                    Slog.w(TAG, "Ignoring request to force stop protected package "
                            + packageName + " u" + user);
                    return;
                }
 
                int pkgUid = -1;
                try {
                    pkgUid = pm.getPackageUid(packageName, MATCH_DEBUG_TRIAGED_MISSING,
                            user);
                } catch (RemoteException e) {
                }
                if (pkgUid == -1) {
                    Slog.w(TAG, "Invalid packageName: " + packageName);
                    continue;
                }
                try {
                    pm.setPackageStoppedState(packageName, true, user);//将包的状态设置为stopped
                } catch (RemoteException e) {
                } catch (IllegalArgumentException e) {
                    Slog.w(TAG, "Failed trying to unstop package "
                            + packageName + ": " + e);
                }
                if (mUserController.isUserRunning(user, 0)) {
                    forceStopPackageLocked(packageName, pkgUid, "from pid " + callingPid);//主要实现方法
                    finishForceStopPackageLocked(packageName, pkgUid);//结束force-stop之后的广播发送
                }
            }
        }
    } finally {
        Binder.restoreCallingIdentity(callingId);
    }
}

setPackageStoppedState()方法会将包的状态设置为stopped(被force-stop或者没有被启动过的三方应用都是stopped状态),这个状态下所有广播都无法被接收,除非带有标记FLAG_INCLUDE_STOPPED_PACKAGES的广播。系统默认的广播几乎都是不带有该标志,也就意味着一般情况下被force-stop的应用是无法通过广播来拉起进程的,但是我们可以通过给广播添加FLAG_INCLUDE_STOPPED_PACKAGES标识来让stopped状态下的应用接收到此广播。

finishForceStopPackageLocked()方法,主要是发送ACTION_PACKAGE_RESTARTED广播,这个广播的作用是用户重新开始一个包,包的所有进程将被杀死,所有与其联系的运行时间状态应该被移除,包括包名(重新开始包程序不能接收到这个广播)

主要来看下forceStopPackageLocked()方法

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
@GuardedBy("this")
private void forceStopPackageLocked(final String packageName, int uid, String reason) {
    forceStopPackageLocked(packageName, UserHandle.getAppId(uid), false,
            false, true, false, false, UserHandle.getUserId(uid), reason);
}
 
 
@GuardedBy("this")
final boolean forceStopPackageLocked(String packageName, int appId,
        boolean callerWillRestart, boolean purgeCache, boolean doit,
        boolean evenPersistent, boolean uninstalling, int userId, String reason) {
    int i;
 
    if (userId == UserHandle.USER_ALL && packageName == null) {
        Slog.w(TAG, "Can't force stop all processes of all users, that is insane!");//不允许stop 所有用户的所有进程
    }
 
    if (appId < 0 && packageName != null) {
        try {
            appId = UserHandle.getAppId(AppGlobals.getPackageManager()
                    .getPackageUid(packageName, MATCH_DEBUG_TRIAGED_MISSING, 0));
        } catch (RemoteException e) {
        }
    }
 
    boolean didSomething;//当方法中有所行为,则返回true。只要杀过一个进程则代表didSomething为true.
    if (doit) {
        if (packageName != null) {
            Slog.i(TAG, "Force stopping " + packageName + " appid=" + appId
                    + " user=" + userId + ": " + reason);//log打印,会打印出stop的reason
        } else {
            Slog.i(TAG, "Force stopping u" + userId + ": " + reason);
        }
 
        mAppErrors.resetProcessCrashTime(packageName == null, appId, userId);
    }
 
    synchronized (mProcLock) {
        // Notify first that the package is stopped, so its process won't be restarted
        // unexpectedly if there is an activity of the package without attached process
        // becomes visible when killing its other processes with visible activities.
        didSomething = mAtmInternal.onForceStopPackage(
                packageName, doit, evenPersistent, userId);//主要方法:强制停止该package
 
        didSomething |= mProcessList.killPackageProcessesLSP(packageName, appId, userId,
                ProcessList.INVALID_ADJ, callerWillRestart, false /* allowRestart */, doit,
                evenPersistent, true /* setRemoved */,
                packageName == null ? ApplicationExitInfo.REASON_USER_STOPPED
                : ApplicationExitInfo.REASON_USER_REQUESTED,
                ApplicationExitInfo.SUBREASON_UNKNOWN,
                (packageName == null ? ("stop user " + userId) : ("stop " + packageName))
                + " due to " + reason);//主要方法:停止该pakcage所涉及的进程
    }
 
    if (mServices.bringDownDisabledPackageServicesLocked(
            packageName, null /* filterByClasses */, userId, evenPersistent, doit)) {//主要方法:清理该package所涉及的Service
        if (!doit) {
            return true;
        }
        didSomething = true;
    }
 
    if (packageName == null) {
        // Remove all sticky broadcasts from this user.
        mStickyBroadcasts.remove(userId);//删除粘性广播
    }
 
    ArrayList<ContentProviderRecord> providers = new ArrayList<>();
    if (mCpHelper.getProviderMap().collectPackageProvidersLocked(packageName, null, doit,
            evenPersistent, userId, providers)) {//收集该package相关的provider
        if (!doit) {
            return true;
        }
        didSomething = true;
    }
    for (i = providers.size() - 1; i >= 0; i--) {
        mCpHelper.removeDyingProviderLocked(null, providers.get(i), true);//主要方法:清理该package所涉及的Provider
    }
 
    // Remove transient permissions granted from/to this package/user
    mUgmInternal.removeUriPermissionsForPackage(packageName, userId, false, false);//主要方法:删除授予/授予此包/用户的临时权限
 
    if (doit) {
        for (i = mBroadcastQueues.length - 1; i >= 0; i--) {
            didSomething |= mBroadcastQueues[i].cleanupDisabledPackageReceiversLocked(
                    packageName, null, userId, doit);//主要方法:清理该package所涉及的广播
        }
    }
 
    if (packageName == null || uninstallbringDownDisabledPackageServicesLockeding) {
        didSomething |= mPendingIntentController.removePendingIntentsForPackage(
                packageName, userId, appId, doit);//主要方法:移除所涉及到的intent
    }
 
    if (doit) {
        if (purgeCache && packageName != null) {
            AttributeCache ac = AttributeCache.instance();
            if (ac != null) {
                ac.removePackage(packageName);
            }
        }
        if (mBooted) {
            mAtmInternal.resumeTopActivities(true /* scheduleIdle */);
        }
    }
 
    return didSomething;
}

forceStopPackageLocked()方法是force-stop的主要方法,这个方法会清理跟该包名相关的进程和四大组件。可以看到,主要流程可以分为以下几个部分:

(1).onForceStopPackage():强制停止该package,主要是没有绑定进程的activities,绑定进程的activity会随着进程消亡而消亡,第一步执行这个方法主要是为了防止这个package中中没有绑定进程的activity重新启动该package

(2).killPackageProcessesLSP():停止该pakcage所涉及的进程

(3).bringDownDisabledPackageServicesLocked():停止该pakcage所涉及的服务

(4).removeDyingProviderLocked():停止该pakcage所涉及的provider

(5).cleanupDisabledPackageReceiversLocked():停止该package所涉及的广播

(6).removePendingIntentsForPackage():停止该package所涉及的pending intent

下面依次分析这几个流程

1.onForceStopPackage;强制停止该package,主要是没有绑定进程的activities

frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@Override
public boolean onForceStopPackage(String packageName, boolean doit, boolean evenPersistent,
        int userId) {//doit传过来的值为true,evenPersistent值为false
    synchronized (mGlobalLock) {
 
        return mRootWindowContainer.finishDisabledPackageActivities(packageName,
                null /* filterByClasses */, doit, evenPersistent, userId,
                // Only remove the activities without process because the activities with
                // attached process will be removed when handling process died with
                // WindowProcessController#isRemoved == true.
                true /* onlyRemoveNoProcess */);
    }
}

调用了RootWindowContainer.java里的finishDisabledPackageActivities()方法,主要是强制停止所涉及的无进程activities.。在这里,只移除没有进程的activity,因为那些有进程的activity,后面将会通过kill process的方法随着进程一起被kill

frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
boolean finishDisabledPackageActivities(String packageName, Set<String> filterByClasses,
        boolean doit, boolean evenPersistent, int userId, boolean onlyRemoveNoProcess) {
    return mFinishDisabledPackageActivitiesHelper.process(packageName, filterByClasses, doit,
            evenPersistent, userId, onlyRemoveNoProcess);
}

交给了内部类FinishDisabledPackageActivitiesHelper去处理finsh的操作

frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
boolean process(String packageName, Set<String> filterByClasses,
        boolean doit, boolean evenPersistent, int userId, boolean onlyRemoveNoProcess) {
    reset(packageName, filterByClasses, doit, evenPersistent, userId, onlyRemoveNoProcess);
 
    final PooledFunction f = PooledLambda.obtainFunction(
            FinishDisabledPackageActivitiesHelper::collectActivity, this,
            PooledLambda.__(ActivityRecord.class));//collectActivity获取所涉及的activities,可以从这个方法中看出哪些activity符合被finsh的条件
    forAllActivities(f);
    f.recycle();
 
    boolean didSomething = false;
    final int size = mCollectedActivities.size();//被finsh的activity的数量
    // Keep the finishing order from top to bottom.
    for (int i = 0; i < size; i++) {
        final ActivityRecord r = mCollectedActivities.get(i);
        if (mOnlyRemoveNoProcess) {//是否只移除没有进程的activity,传过来的值为true
            if (!r.hasProcess()) {
                didSomething = true;
                Slog.i(TAG, "  Force removing " + r);
                r.cleanUp(false /* cleanServices */, false /* setState */);
                r.removeFromHistory("force-stop");//清除activity
            }
        } else {
            didSomething = true;
            Slog.i(TAG, "  Force finishing " + r);
            r.finishIfPossible("force-stop", true /* oomAdj */);//清除activity
        }
    }
    mCollectedActivities.clear();
 
    return didSomething;
}

首先通过collectActivity()方法获取所涉及的activities,可以从这个方法中看出哪些activity符合被finsh的条件,看一下这个方法。

private boolean collectActivity(ActivityRecord r) {
        final boolean sameComponent =
                (r.packageName.equals(mPackageName) && (mFilterByClasses == null
                        || mFilterByClasses.contains(r.mActivityComponent.getClassName())))
                        || (mPackageName == null && r.mUserId == mUserId);//具有相同包名的activity需要被finsh
        final boolean noProcess = !r.hasProcess();//没有进程绑定的activity
        if ((mUserId == UserHandle.USER_ALL || r.mUserId == mUserId)
                && (sameComponent || r.getTask() == mLastTask)
                && (noProcess || mEvenPersistent || !r.app.isPersistent())) {
            if (!mDoit) {//mDoit表示是否有操作
                if (r.finishing) {//如果次activity正在finsh,不做重复操作
                    // If this activity is just finishing, then it is not
                    // interesting as far as something to stop.
                    return false;
                }
                return true;
            }
            mCollectedActivities.add(r);//将符合条件的activity添加到mCollectedActivities中
            mLastTask = r.getTask();
        }
 
        return false;
    }
}

2.killPackageProcessesLSP:停止该pakcage所涉及的进程

frameworks/base/services/core/java/com/android/server/am/ProcessList.java
boolean killPackageProcessesLSP(String packageName, int appId,
        int userId, int minOomAdj, boolean callerWillRestart, boolean allowRestart,
        boolean doit, boolean evenPersistent, boolean setRemoved, int reasonCode,
        int subReason, String reason) {
    ArrayList<ProcessRecord> procs = new ArrayList<>();
 
    // Remove all processes this package may have touched: all with the
    // same UID (except for the system or root user), and all whose name
    // matches the package name.
    final int NP = mProcessNames.getMap().size();//移除这个package可能接触的所有进程:具有相同uid(除非系统或者root用户)、所有名称的package名相同的进程
    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.isPersistent() && !evenPersistent) {//如果是persistent进程,则不会被kill掉
                // we don't kill persistent processes
                continue;
            }
            if (app.isRemoved()) {//应用被移除,则不会被kill
                if (doit) {
                    procs.add(app);
                }
                continue;
            }
 
            // Skip process if it doesn't meet our oom adj requirement.
            if (app.mState.getSetAdj() < minOomAdj) {//进程setAdj < minOomAdj则不会被kill,minOomAdj值为-10000
                // Note it is still possible to have a process with oom adj 0 in the killed
                // processes, but it does not mean misjudgment. E.g. a bound service process
                // and its client activity process are both in the background, so they are
                // collected to be killed. If the client activity is killed first, the service
                // may be scheduled to unbind and become an executing service (oom adj 0).
                continue;
            }
 
            // If no package is specified, we call all processes under the
            // give user id.
            if (packageName == null) {//如果没有指定包,下面情况不会被kill。
                if (userId != UserHandle.USER_ALL && app.userId != userId) {//非UserHandle.USER_ALL同时, 且进程的userId不相等,不kill,因为多用户模型下,不同用户下不能相互杀
                    continue;
                }
                if (appId >= 0 && UserHandle.getAppId(app.uid) != appId) {
                    continue;
                }
                // Package has been specified, we want to hit all processes
                // that match it.  We need to qualify this by the processes
                // that are running under the specified app and user ID.
            } else {//包名不为null
                final boolean isDep = app.getPkgDeps() != null
                        && app.getPkgDeps().contains(packageName);//进程的pkgDeps中不包含该packageName,则会被杀
                if (!isDep && UserHandle.getAppId(app.uid) != appId) {
                    continue;
                }
                if (userId != UserHandle.USER_ALL && app.userId != userId) {
                    continue;
                }
                if (!app.getPkgList().containsKey(packageName) && !isDep) {
                    continue;
                }
            }
 
            // Process has passed all conditions, kill it!//以下情况全部会被kill
            if (!doit) {
                return true;
            }
            if (setRemoved) {
                app.setRemoved(true);
            }
            procs.add(app);//将会被kill的进程添加到procs
        }
    }
 
    int N = procs.size();
    for (int i=0; i<N; i++) {
        removeProcessLocked(procs.get(i), callerWillRestart, allowRestart,
                reasonCode, subReason, reason);
    /**
    removeProcessLocked方法的主要功能:
    1.从mProcessNames, mPidsSelfLocked队列移除该进程;
    2.移除进程启动超时的消息PROC_START_TIMEOUT_MSG;
    3.调用app.killLocked()来杀进程会同时调用Process.kill和Process.killProcessGroup.
    4.调用handleAppDiedLocked()来清理进程相关的信息
    */
    }
    killAppZygotesLocked(packageName, appId, userId, false /* force */);//查看是否有任何app zygotes 正在为此 packageName / UID 组合运行,如果有,则将其杀死。
    mService.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_PROCESS_END);//更新oomadj,reason是OOM_ADJ_REASON_PROCESS_END
    return N > 0;
}

一般地force-stop会指定包名,该方法会遍历当前所有运行中的进程mProcessNames,以下条件同时都不满足的进程,则会成为被杀的目标进程:(也就是说满足以下任一条件都可以免死)
(1)persistent进程:
(2)进程setAdj < minOomAdj(默认为-10000):
(3)非UserHandle.USER_ALL同时, 且进程的userId不相等:多用户模型下,不同用户下不能相互杀;
(4)进程没有依赖该packageName, 且进程的AppId不相等;
(5)进程没有依赖该packageName, 且该packageName没有运行在该进程.

也就是就是:

(1)forceStop不杀系统persistent进程;

(2)当指定用户userId时,不杀其他用户空间的进程;

除此之外,以下情况则必然会成为被杀进程:

(1)进程已标记remove=true的进程,则会被杀;

(2)进程的pkgDeps中包含该packageName,则会被杀;

(3)进程的pkgList中包含该packageName,且该进程与包名所指定的AppId相等则会被杀;

进程的pkgList是在启动组件或者创建进程的过程向该队列添加的,代表的是该应用下有组件运行在该进程。那么pkgDeps是指该进程所依赖的包名,调用ClassLoader的过程添加。

3.bringDownDisabledPackageServicesLocked():停止该pakcage所涉及的服务

frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
boolean bringDownDisabledPackageServicesLocked(String packageName, Set<String> filterByClasses,
        int userId, boolean evenPersistent, boolean doit) {
    boolean didSomething = false;
 
    if (mTmpCollectionResults != null) {//mTmpCollectionResults这个是符合条件的services
        mTmpCollectionResults.clear();
    }
 
    if (userId == UserHandle.USER_ALL) {
        for (int i = mServiceMap.size() - 1; i >= 0; i--) {
            didSomething |= collectPackageServicesLocked(packageName, filterByClasses,
                    evenPersistent, doit, mServiceMap.valueAt(i).mServicesByInstanceName);//收集满足条件的service到mTmpCollectionResults并kill
            if (!doit && didSomething) {
                return true;
            }
            if (doit && filterByClasses == null) {
                forceStopPackageLocked(packageName, mServiceMap.valueAt(i).mUserId);
            }
        }
    } else {
        ServiceMap smap = mServiceMap.get(userId);
        if (smap != null) {
            ArrayMap<ComponentName, ServiceRecord> items = smap.mServicesByInstanceName;
            didSomething = collectPackageServicesLocked(packageName, filterByClasses,
                    evenPersistent, doit, items);
        }
        if (doit && filterByClasses == null) {
            forceStopPackageLocked(packageName, userId);
        }
    }
 
    if (mTmpCollectionResults != null) {
        final int size = mTmpCollectionResults.size();
        for (int i = size - 1; i >= 0; i--) {
            bringDownServiceLocked(mTmpCollectionResults.get(i), true);//主要方法:遍历mTmpCollectionResults,通过bringDownServiceLocked来kill service
        }
        if (size > 0) {
            mAm.updateOomAdjPendingTargetsLocked(OomAdjuster.OOM_ADJ_REASON_UNBIND_SERVICE);
        }
        mTmpCollectionResults.clear();
    }
 
    return didSomething;
}

首先看哪些条件下的service符合条件

frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
private boolean collectPackageServicesLocked(String packageName, Set<String> filterByClasses,
        boolean evenPersistent, boolean doit, 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())));//相同包名进程下的service
        if (sameComponent
                && (service.app == null || evenPersistent || !service.app.isPersistent())) {//具有相同包名时,以下情况会被kill掉1.service没有绑定的app、2.evenPersistent为true 、3.service绑定的app不是persistent
            if (!doit) {
                return true;
            }
            didSomething = true;
            Slog.i(TAG, "  Force stopping service " + service);
            if (service.app != null && !service.app.isPersistent()) {
                stopServiceAndUpdateAllowlistManagerLocked(service);//stop 对应的service
            }
            service.setProcess(null, null, 0, null);
            service.isolatedProc = null;
            if (mTmpCollectionResults == null) {
                mTmpCollectionResults = new ArrayList<>();
            }
            mTmpCollectionResults.add(service);
        }
    }
    return didSomething;
}

然后通过bringDownServiceLocked()方法来kill掉所涉及的service

intent、广播和provider的流程类似,不做分析

需要注意:

广播:

(1)清理并行广播队列

(2)清理有序广播队列

provider:

当其他app使用该provider, 且建立stable的连接, 那么对于非persistent进程,则会由于依赖该provider的缘故而被杀.

intent:

主要移除待处理的intent。

补充:系统查杀进程方式

方法方法所在类使用层描述
System.exit(int status)System.java应用层退出虚拟机。status=0为正常退出、非0为异常退出。
Process.killProcess(int pid)Process.java系统、应用层调用sendSignal发送信号9,杀死指定pid进程。app调用只能自杀,系统能够杀掉指定pid进程。
Process.killProcessGroup(int uid, int pid)Process.java系统杀掉pid所在的进程组内的全部进程。
killApplicationProcess(String processName, int uid)AMS系统系统uid应用才能调用,binder call到客户端自杀:app.thread.scheduleSuicide();
killApplication(String pkg, int appId, int userId, String reason)AMS系统系统uid应用才能调用,会将目标应用强杀,做用于指定用户空间。
killAllBackgroundProcesses()AMS系统须要KILL_BACKGROUND_PROCESS权限,杀死系统全部优先级小于等于CACHED进程。
killBackgroundProcesses(final String packageName, int userId, String reason)AMS系统、应用层须要KILL_BACKGROUND_PROCESS权限,杀死指定package全部优先级小于等于SERVICE进程,做用于指定用户空间。
killProcessesBelowForeground(String reason)AMS系统系统uid应用才能调用,杀死系统全部优先级小于FOREGROUND的进程。
killPackageDependents(String packageName, int userId)AMS系统须要KILL_UID权限,杀死指定package全部优先级小于等于FOREGROUND进程,做用于指定用户空间。
killPids(int[] pids, String pReason, boolean secure)AMS系统系统UID应用才能调用,首先找出全部进程全部worstType(跟adj相关的一个判断值),杀死小于等于这个优先级的进程。很保守的查杀方法,并不保证进程被杀
killUid(int appId, int userId, String reason)AMS系统、应用层须要KILL_UID权限,杀死UID下全部进程,system_server与native进程除外
killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog)AMS系统系统发生异常后调用,例如ANR ,多为用户主动触发
forceStopPackage(final String packageName, int userId)AMS系统须要FORCE_STOP_PACKAGE权限,杀死应用全部进程,并清除各个进程组件信息,做用于指定用户空间,强杀以后连根拔起,寸草不生。属于终极Kill。
Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐