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

根据这篇文章作的笔记

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

在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-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/938937.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

uniapp连接蓝牙操作(蓝牙设备地锁)

介绍&#xff1a; 本文采用uni-app框架来创建一个简单的用户界面&#xff0c;用于搜索、连接和发送命令给蓝牙设备。 1.打开蓝牙适配器 function openBluetooth() {uni.openBluetoothAdapter({success() {uni.offBluetoothDeviceFound();// 监听新设备发现事件uni.onBlueto…

《拉依达的嵌入式\驱动面试宝典》—前言目录篇

《拉依达的嵌入式\驱动面试宝典》—前言&目录篇 你好&#xff0c;我是拉依达。 感谢所有阅读关注我的同学支持&#xff0c;目前博客累计阅读 27w&#xff0c;关注1.5w人。其中博客《最全Linux驱动开发全流程详细解析&#xff08;持续更新&#xff09;-CSDN博客》已经是 Lin…

【博弈模型】古诺模型、stackelberg博弈模型、伯特兰德模型、价格领导模型

博弈模型 1、古诺模型&#xff08;cournot&#xff09;&#xff08;1&#xff09;假设&#xff08;2&#xff09;行为分析&#xff08;3&#xff09;经济后果&#xff08;4&#xff09;例题 2、stackelberg博弈模型&#xff08;产量领导模型&#xff09;&#xff08;1&#xff…

如何利用Python爬虫获得1688商品详情

在这个信息爆炸的时代&#xff0c;数据就像是一块块美味的奶酪&#xff0c;而爬虫就是我们手中的瑞士军刀。今天&#xff0c;我要带你一起潜入1688这个巨大的奶酪洞穴&#xff0c;用Python爬虫捞起那些香气四溢的商品详情。别担心&#xff0c;我们的工具箱里有各种各样的工具&a…

blender 制作莫比乌斯带

创建 Curve -> Cycle 在 Edit 模式下&#xff0c;选择&#xff1a; 选中两个点&#xff0c;按 delete 删除 Segment 如下选中&#xff1a; 选中最上面的点&#xff0c;然后按 E 将它拖到右边的点上。 按 R 旋转 90 度。 依次调整参数&#xff1a; 回到 Object 模式下&#x…

《云原生安全攻防》-- K8s安全框架:认证、鉴权与准入控制

从本节课程开始&#xff0c;我们将来介绍K8s安全框架&#xff0c;这是保障K8s集群安全比较关键的安全机制。接下来&#xff0c;让我们一起来探索K8s安全框架的运行机制。 在这个课程中&#xff0c;我们将学习以下内容&#xff1a; K8s安全框架&#xff1a;由认证、鉴权和准入控…

研华运动控制卡 (如PCI1245)单轴编辑路

问题描述: 单轴如何编辑路径&#xff1f; n 问题分析及处理办法– 步骤 在utility软件中&#xff0c;编辑路径和运行路径只能在多轴运动这个界面&#xff0c;而且&#xff0c;使用函数来加载路径Acm_GpLoadPath&#xff0c;也是需要多个轴 ​ 如果只运行一个轴&#xff0c;需…

LM芯片学习

1、LM7805稳压器 https://zhuanlan.zhihu.com/p/626577102?utm_campaignshareopn&utm_mediumsocial&utm_psn1852815231102873600&utm_sourcewechat_sessionhttps://zhuanlan.zhihu.com/p/626577102?utm_campaignshareopn&utm_mediumsocial&utm_psn18528…

ChromeOS 131 版本更新

ChromeOS 131 版本更新 1. ChromeOS Flex 自动注册 在 ChromeOS 131 中&#xff0c;ChromeOS Flex 的自动注册功能现已允许大规模部署 ChromeOS Flex 设备。与 ChromeOS 零接触注册类似&#xff0c;自动注册将通过组织管理员创建的注册令牌嵌入到 ChromeOS Flex 镜像中。这将…

electron打包linux环境

注意:新版的electron已经不支持在win上直接打包Linux的环境了,服务会卡住,会一直生成文件占用磁盘(我发现的时候占了我100G&#xff0c;而且文件夹很深&#xff0c;找了java代码while循环&#xff0c;好不容易删除的o(╥﹏╥)o) electron有一个专门打包的docker镜像&#xff0c…

【SAP FICO】物料分类账详述

系列文章目录 文章目录 系列文章目录前言一、必备基础1、标准价和移动平均价2、概念3、意义4、功能 二、工作原理三、差异的种类与来源1、采用S价可能产生的差异2、单层价格差异和多层价格差异 四、后台配置总结 前言 业务背景&#xff1a;中国会计准则规定&#xff0c;对存货…

电脑文档损坏:原因剖析和修复方法

在使用电脑的过程中&#xff0c;许多用户可能会遇到文档突然提示损坏、无法打开的情况。这种情况的发生往往让人感到困惑&#xff0c;特别是当并未进行任何明显错误操作时。以下是一些常见的原因以及应对方法。 一、文档损坏的常见原因 1、非人为的异常操作&#xff1a; 在编…

使用国内镜像网站在线下载安装Qt(解决官网慢的问题)——Qt

国内镜像网站 中国科学技术大学&#xff1a;http://mirrors.ustc.edu.cn/qtproject/清华大学&#xff1a;https://mirrors.tuna.tsinghua.edu.cn/qt/北京理工大学&#xff1a;http://mirror.bit.edu.cn/qtproject/ 南京大学&#xff1a;https://mirror.nju.edu.cn/qt腾讯镜像&…

活动预告|云原生创新论坛:知乎携手 AutoMQ、OceanBase、快猫星云的实践分享

近年来&#xff0c;云原生技术迅猛发展&#xff0c;成为企业数字化转型的关键动力&#xff0c;云原生不仅极大地提升了系统的灵活性和可扩展性&#xff0c;还为企业带来了前所未有的创新机遇。 12 月 28 日 知乎携手 AutoMQ、OceanBase 和快猫星云推出“云原生创新论坛”主题的…

02-2.python入门语法一变量与数据类型2

四、Python 整数数据类型 &#xff08;一&#xff09;整数的表示方式 1. 十进制表示 十进制是我们在日常生活中最常用的数字表示形式&#xff0c;由 0 到 9 这十个数字排列组合而成。 2. 二进制表示 二进制数由 0 和 1 这两个数字组成&#xff0c;在 Python 中&#xff0c;…

如果在 Swift 数组中寻找最大相邻差值的线性时间算法

文章目录 摘要问题描述解决方案Swift 代码实现代码解析测试用例及结果时间复杂度空间复杂度总结 摘要 本文探讨如何在未排序的数组中&#xff0c;通过线性时间算法找到排序后相邻元素之间的最大差值。我们采用桶排序的思想&#xff0c;给出一个高效的 Swift 实现&#xff0c;并…

EasyExcel 动态设置表格的背景颜色和排列

项目中使用EasyExcel把数据以excel格式导出&#xff0c;其中设置某一行、某一列单元格的背景颜色、排列方式十分常用&#xff0c;记录下来方便以后查阅。 1. 导入maven依赖&#xff1a; <dependency><groupId>com.alibaba</groupId><artifactId>easy…

如何在谷歌浏览器中设置标签页分组

在日常浏览网页时&#xff0c;我们常常会打开多个标签页。随着标签页数量的增加&#xff0c;管理它们变得越来越困难。幸运的是&#xff0c;谷歌浏览器提供了一些实用的功能&#xff0c;可以帮助我们更好地组织和分组标签页。本教程将向您展示如何设置标签页分组&#xff0c;并…

多协议视频监控汇聚/视频安防系统Liveweb搭建智慧园区视频管理平台

智慧园区作为现代化城市发展的重要组成部分&#xff0c;不仅承载着产业升级的使命&#xff0c;更是智慧城市建设的重要体现。随着产业园区竞争的逐渐白热化&#xff0c;将项目打造成完善的智慧园区是越来越多用户关注的内容。 然而我们往往在规划前期就开始面临众多难题&#…

vscode中同时运行两个python文件(不用安装插件)

如何在vscode中同时运行两个python文件呢&#xff1f;今天在工作中遇到了这个问题。 查了网上的方法是安装coder runner插件&#xff0c;后来发现自身就有这个功能。所以记录一下,方便后续查找: 这是我的第一个文件&#xff0c;点击右上角的运行旁边的小箭头&#xff0c;有一…