【阅读笔记】Android AMS forcestop停止应用

根据这篇文章作的笔记

基于Android 12的force-stop流程分析_android forcestop-优快云博客

在AMS中,停止指定的应用是一个常用的功能,在代码里可以看到

    @Override
6806    public void forceStopPackage(final String packageName, int userId) {
6807        if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
6808                != PackageManager.PERMISSION_GRANTED) {
6809            String msg = "Permission Denial: forceStopPackage() from pid="
6810                    + Binder.getCallingPid()
6811                    + ", uid=" + Binder.getCallingUid()
6812                    + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
6813            Slog.w(TAG, msg);
6814            throw new SecurityException(msg);
6815        }
6816        final int callingPid = Binder.getCallingPid();
6817        userId = mUserController.handleIncomingUser(callingPid, Binder.getCallingUid(),
6818                userId, true, ALLOW_FULL_ONLY, "forceStopPackage", null);
6819        long callingId = Binder.clearCallingIdentity();
6820        try {
6821            IPackageManager pm = AppGlobals.getPackageManager();
6822            synchronized(this) {
6823                int[] users = userId == UserHandle.USER_ALL
6824                        ? mUserController.getUsers() : new int[] { userId };
6825                for (int user : users) {
6826                    if (getPackageManagerInternalLocked().isPackageStateProtected(
6827                            packageName, user)) {
6828                        Slog.w(TAG, "Ignoring request to force stop protected package "
6829                                + packageName + " u" + user);
6830                        return;
6831                    }
6832
6833                    int pkgUid = -1;
6834                    try {
6835                        pkgUid = pm.getPackageUid(packageName, MATCH_DEBUG_TRIAGED_MISSING,
6836                                user);
6837                    } catch (RemoteException e) {
6838                    }
6839                    if (pkgUid == -1) {
6840                        Slog.w(TAG, "Invalid packageName: " + packageName);
6841                        continue;
6842                    }
6843                    try {
6844                        pm.setPackageStoppedState(packageName, true, user);
6845                    } catch (RemoteException e) {
6846                    } catch (IllegalArgumentException e) {
6847                        Slog.w(TAG, "Failed trying to unstop package "
6848                                + packageName + ": " + e);
6849                    }
6850                    if (mUserController.isUserRunning(user, 0)) {
6851                        forceStopPackageLocked(packageName, pkgUid, "from pid " + callingPid);
6852                        finishForceStopPackageLocked(packageName, pkgUid);
6853                    }
6854                }
6855            }
6856        } finally {
6857            Binder.restoreCallingIdentity(callingId);
6858        }
6859    }

里面调用到forceStopPackageLocked方法,

通过am命令force-stop 也可以调用forcestop,查看help信息,

am -h

  force-stop [--user <USER_ID> | all | current] <PACKAGE>
      Completely stop the given application package.
  stop-app [--user <USER_ID> | all | current] <PACKAGE>
      Stop an app and all of its services.  Unlike `force-stop` this does
      not cancel the app's scheduled alarms and jobs.

注意看这个解释信息,如果不需要取消应用的scheduled alarms和jobs,可以使用stop-app

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;
}

这里还有释放资源

很多年前,曾经遇到一个卸载应用导致的重启问题,就是因为卸载的时候,没有及时的执行

ac.removePackage(packageName)导致的。

参考资料:

基于Android 12的force-stop流程分析_android forcestop-优快云博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值