当前位置: 首页 > 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.xdnf.cn/news/1315783.html

相关文章:

  • 【Java后端】Spring Boot 集成 MyBatis-Plus 全攻略
  • 大模型算法岗面试准备经验分享
  • (机器学习)监督学习 vs 非监督学习
  • 智能制造——解读37页 案例分享灯塔工厂解决方案【附全文阅读】
  • 电子电气架构 --- 自动驾驶汽车的下一步发展是什么?
  • LeetCode 分类刷题:2962. 统计最大元素出现至少 K 次的子数组
  • 零墨云A4mini打印机设置电脑通过局域网络进行打印
  • 详解flink java基础(一)
  • Flink作业执行的第一步:DataFlow graph的构建
  • nodejs 错误处理
  • Gradle快速入门学习
  • 数据结构初阶(19)外排序·文件归并排序的实现
  • 机器学习案例——对好评和差评进行预测
  • error #include<cuda_runtime_api.h>解决方案
  • Java基础 8.17
  • 2023年全国研究生数学建模竞赛华为杯F题强对流降水临近预报求解全过程文档及程序
  • RAG 分块中表格填补简明示例:Markdown、HTML、Excel、Doc
  • 机器学习--数据清洗
  • 北京JAVA基础面试30天打卡12
  • STM32CUBEMX配置stm32工程
  • 五、redis入门 之 客户端连接redis
  • Go语言并发编程 ------ 临界区
  • 批次号规则
  • Mac(四)自定义按键工具 Hammerspoon 的安装和使用
  • FX10/20 (CYUSB401X)开发笔记5 固件架构
  • 基于DSP+ARM+FPGA架构的储能协调控制器解决方案,支持全国产化
  • 【完整源码+数据集+部署教程】无人机航拍视角洪水检测与受灾房屋识别图像分割救援指导系统源码和数据集:改进yolo11-DCNV2
  • Tomcat下载、安装及配置详细教程
  • STL 容器
  • Kotlin集合概述