当前位置: 首页 > news >正文

安卓14系统应用收不到开机广播

安卓14系统应用收不到开机广播 - Wesley’s Blog

前段时间有测试反馈在安卓14 上面某系统应用恢复出厂设置后没有自启动,究竟是什么原因呢?
请添加图片描述

回顾

Android 从3.1开始,会将新安装并且从未被启动的应用置为“STOPPED”状态,或者被force stop的应用,这种状态下的应用是无法接收到广播的。但发送方可以通过添加FLAG_INCLUDE_STOPPED_PACKAGES 来豁免,但一般情况下,系统会默认添加FLAG_EXCLUDE_STOPPED_PACKAGES flag。

http://xrefandroid.com/android-16.0.0_r2/s?refs=FLAG_EXCLUDE_STOPPED_PACKAGES&project=frameworks

    /*** If set, this intent will not match any components in packages that* are currently* {@linkplain android.content.pm.ApplicationInfo#FLAG_STOPPED stopped}.* If this is not set, then the default behavior is to include such* applications in the result.*/public static final int FLAG_EXCLUDE_STOPPED_PACKAGES = 0x00000010;/*** If set, this intent will always match any components in packages that* are currently* {@linkplain android.content.pm.ApplicationInfo#FLAG_STOPPED stopped}.* This is the default behavior when* {@link #FLAG_EXCLUDE_STOPPED_PACKAGES} is not set.  If both of these* flags are set, this one wins (it allows overriding of exclude for* places where the framework may automatically set the exclude flag,* such as broadcasts).*/public static final int FLAG_INCLUDE_STOPPED_PACKAGES = 0x00000020;

豁免

IntentResolver.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server/IntentResolver.java

private void buildResolveList(@NonNull Computer computer, Intent intent,FastImmutableArraySet<String> categories, boolean debug, boolean defaultOnly,String resolvedType, String scheme, F[] src, List<R> dest, int userId,long customFlags) { ...........if (excludingStopped && isFilterStopped(computer.getPackageStateInternal(packageName),userId)) {if (debug) {Slog.v(TAG, "  Filter's target is stopped; skipping");}continue;}..................
}

ComponentResolver.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server/pm/resolution/ComponentResolver.java

        @Overrideprotected boolean isFilterStopped(@Nullable PackageStateInternal packageState,@UserIdInt int userId) {if (!mUserManager.exists(userId)) {return true;}if (packageState == null || packageState.getPkg() == null) {return false;}// System apps are never considered stopped for purposes of// filtering, because there may be no way for the user to// actually re-launch them.return !packageState.isSystem()&& packageState.getUserStateOrDefault(userId).isStopped();}

安卓 14 之前的代码表明系统应用(系统标记为ApplicationInfo.FLAG_SYSTEM 的应用)是可以豁免的。

注意: 直接安装在 data 分区的 system uid 应用是不会被标记为ApplicationInfo.FLAG_SYSTEM 的。但更新在 data 分区的系统应用依然有效。

安卓 14 的变化

ComponentResolver.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server/pm/resolution/ComponentResolver.java

        @Overrideprotected boolean isFilterStopped(@NonNull Computer computer, F filter,@UserIdInt int userId) {if (!mUserManager.exists(userId)) {return true;}final PackageStateInternal packageState = computer.getPackageStateInternal(filter.first.getPackageName());if (packageState == null || packageState.getPkg() == null) {return false;}return packageState.getUserStateOrDefault(userId).isStopped();}

系统应用不能豁免了,一刀切了。🤣 当然,这里可以打补丁让原来的修改有效。

安卓 15 峰回路转

ComponentResolver.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server/pm/resolution/ComponentResolver.java

        @Overrideprotected boolean isFilterStopped(@NonNull Computer computer, F filter,@UserIdInt int userId) {if (!mUserManager.exists(userId)) {return true;}final PackageStateInternal packageState = computer.getPackageStateInternal(filter.first.getPackageName());if (packageState == null || packageState.getPkg() == null) {return false;}if (packageState.isSystem()) {// A system app can be considered in the stopped state only if it was originally// scanned in the stopped state.return packageState.isScannedAsStoppedSystemApp() &&packageState.getUserStateOrDefault(userId).isStopped();}return packageState.getUserStateOrDefault(userId).isStopped();}}

安卓 15 开始,又把系统应用的豁免加回来了,但有了更加精细化的控制。不仅需要满足是系统应用,同时也要满足不是被第一次开机标记为停止状态的系统应用。

isScannedAsStoppedSystemApp() 是用来检查一个系统应用在系统首次启动时,是否被自动置于“强制停止”(stopped)状态。

那么这个状态是怎么标记的呢?

哪些应用会被标记?

adb可以通过 dumpsys package 包名 | grep isScannedAsStoppedSystemApp来查看

主要看PackageSettingsetScannedAsStoppedSystemApp 的调用关系

«interface»
PackageState
«interface»
PackageStateInternal
SettingBase
PackageSetting

最后确认为扫描系统 apk 时添加了SCAN_AS_STOPPED_SYSTEM_APP 的扫描标志位的应用会标记为停止状态。

InstallPackageHelper.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java

private Pair<ScanResult, Boolean> scanSystemPackageLI(ParsedPackage parsedPackage,@ParsingPackageUtils.ParseFlags int parseFlags,@PackageManagerService.ScanFlags int scanFlags,@Nullable UserHandle user) throws PackageManagerException { // A new application appeared on /system, and we are seeing it for the first time.// Its also not updated as we don't have a copy of it on /data. So, scan it in a// STOPPED state.// We'll skip this step under the following conditions://   - It's "android"//   - It's an APEX or overlay package since stopped state does not affect them.//   - It is enumerated with a <initial-package-state> tag having the stopped attribute//     set to false//   - It doesn't have an enabled and exported launcher activity, which means the user//     wouldn't have a way to un-stop itfinal boolean isApexPkg = (scanFlags & SCAN_AS_APEX) != 0;if (mPm.mShouldStopSystemPackagesByDefault&& scanSystemPartition&& !pkgAlreadyExists&& !isApexPkg&& !parsedPackage.isOverlayIsStatic()) {String packageName = parsedPackage.getPackageName();if (!"android".contentEquals(packageName)&& !mPm.mInitialNonStoppedSystemPackages.contains(packageName)&& hasLauncherEntry(parsedPackage)) {scanFlags |= SCAN_AS_STOPPED_SYSTEM_APP;}}
}

根据函数的注释,一个应用会被标记为“停止的系统应用”(Scanned As Stopped System App)需要满足以下所有条件

  1. 是系统应用:即系统标记为ApplicationInfo.FLAG_SYSTEM 的应用。

  2. 在core/res/res/values/config.xml 配置config_stopSystemPackagesByDefault为 true,默认启用。

        <!-- Whether system apps should be scanned in the stopped state during initial boot.Packages can be added by OEMs in an allowlist, to prevent them from being scanned as"stopped" during initial boot of a device, or after an OTA update. Stopped state ofan app is not changed during subsequent reboots.  --><bool name="config_stopSystemPackagesByDefault">true</bool>
    
  3. 应用不存在

  4. 不是 system_server(包名为 android )

  5. 不是 APEX 包和静态资源覆盖包(Overlay)

  6. 有启动入口 (Launcher Entry)。

  7. 没有在initial-package-stopped-states.xml 配置中被豁免。

initial-package-stopped-states.xml - OpenGrok cross reference for /frameworks/base/data/etc/initial-package-stopped-states.xml

<?xml version="1.0" encoding="utf-8"?>
<!--
This XML defines an allowlist for packages that should not be scanned in a "stopped" state.
When this feature is turned on (indicated by the config config_stopSystemPackagesByDefault in
core/res/res/values/config.xml) packages on the system partition that are encountered by
the PackageManagerService for the first time are scanned in the "stopped" state. This allowlist
is also considered while creating new users on the device. Stopped state is not set during
subsequent reboots.Example usage1. <initial-package-state package="com.example.app" stopped="false"/>Indicates that a system package - com.example.app's initial stopped state should not be setby the Package Manager. By default, system apps are marked as stopped.2. <initial-package-state package="com.example.app" stopped="true"/>Indicates that a system package - com.example.app's initial state should be set by thePackage Manager to "stopped=true". It will have the same effect on thepackage's stopped state even if this package was not included in the allow list.3. <initial-package-state package="com.example.app"/>Invalid usage.
--><config></config>

参考

stop应用无法收到广播问题_应用未启动接收广播-CSDN博客

关于Android中App的停止状态 - 技术小黑屋

PMS 第 4 篇 - PMS_DATA_SCAN_START 阶段 | Coolqi`s Blog

http://www.dtcms.com/a/335800.html

相关文章:

  • HTTP请求参数类型及对应的后端注解
  • AMBA-AXI and ACE协议详解(七)
  • 【学习笔记】面向AI安全的26个缓解措施
  • API网关实施中典型陷阱
  • 【数据结构与算法】单调队列的定义和运用
  • 整体设计 之“凝聚式中心点”原型 --整除:智能合约和DBMS的深层联合 之1
  • Android Jetpack | Livedata
  • Gradle快速入门学习
  • 【算法】模拟专题
  • riscv中断处理软硬件流程总结
  • C++算法题目分享:二叉搜索树相关的习题
  • 原子指标、派生指标和复合指标
  • nodejs 中间件
  • 【Jenkins】01 - Jenkins安装
  • C语言网络编程TCP通信实战:客户端↔服务器双向键盘互动全流程解析
  • [GWCTF 2019]枯燥的抽奖
  • Java线程的6种状态和JVM状态打印
  • [TryHackMe]Brainpan1( 内存溢出)
  • PERCEIVER IO:一种用于结构化输入与输出的通用架构
  • 脉冲计数实现
  • 深入剖析ROS参数服务器通信机制 ——共享全局数据的“云端仓库”实现原理
  • Node.js安装教程
  • MySQL的事务日志:
  • java之 junit4单元测试Mockito的使用
  • 26. Object.defineProperty 和 Proxy 用法
  • 中级统计师-会计学基础知识-第五章 财务报告
  • 计算机算术6-SRT2除法
  • Linux817 shell:until,nfs,random
  • TypeScript中的import语法详解
  • 6.Ansible自动化之-管理变量和事实