首次开机android.intent.action.BOOT_COMPLETED开机广播发送慢的问题

embedded/2024/11/15 6:05:09/

1. 背景
做过android开发的同学相信一定做个这种逻辑:app接收BOOT_COMPLETED开机广播,自启动,或者收到广播做一些事情。目前在我们的项目上遇到首次开机,BOOT_COMPLETED开机广播发送慢的问题。接下来分享记录下如何定位这类问题。

2. 分析过程

01-01 08:00:33.689247 1014 1840 I wm_create_activity:[0,42774215,7,com.android.launcher/.activity.LauncherActivity,android.intent.action.MAIN,NULL,NULL,268435712]
launcer界面的创建时间点为08:00:33

01-01 08:00:39.384523 1014 1855 I ActivityManager: Posting BOOT_COMPLETED user #0
系统发送开机广播的时间为08:00:39
中间有6秒多的间隔,需要看看开机广播发送慢的问题。

1.第一次开机,boot_completed广播之前,会先执行PreBoot 耗时6s,这是google原生行为。
行 24354: 01-01 08:00:33.293553 1014 1288 I uc_finish_user_unlocked: 0
行 24429: 01-01 08:00:33.302932 1014 1288 I PreBootBroadcaster: Pre-boot of {com.android.documentsui/com.android.documentsui.PreBootReceiver} for user 0
行 25647: 01-01 08:00:33.659771 1014 2704 I PreBootBroadcaster: Pre-boot of {com.android.managedprovisioning/com.android.managedprovisioning.ota.PreBootListener} for user 0
行 27224: 01-01 08:00:34.296557 1014 2907 I PreBootBroadcaster: Pre-boot of {com.android.providers.contacts/com.android.providers.contacts.ContactsUpgradeReceiver} for user 0
行 33427: 01-01 08:00:37.224144 1014 1856 I PreBootBroadcaster: Pre-boot of {com.android.providers.media.module/com.android.providers.media.MediaUpgradeReceiver} for user 0
行 37494: 01-01 08:00:39.384308 1014 1855 I uc_finish_user_unlocked_completed: 0

  1. 后面重启,不会有preboot动作,正常。
    行 68220: 11-01 08:00:18.937687 960 1142 I uc_finish_user_unlocked: 0
    行 68294: 11-01 08:00:18.943890 960 1142 I uc_finish_user_unlocked_completed: 0
    行 115214: 11-01 08:01:17.388510 969 1098 I uc_finish_user_unlocked: 0
    行 115407: 11-01 08:01:17.482497 969 1098 I uc_finish_user_unlocked_completed: 0
    /*** Step from {@link UserState#STATE_RUNNING_UNLOCKING} to* {@link UserState#STATE_RUNNING_UNLOCKED}.*/void finishUserUnlocked(final UserState uss) {final int userId = uss.mHandle.getIdentifier();EventLog.writeEvent(EventLogTags.UC_FINISH_USER_UNLOCKED, userId);// Only keep marching forward if user is actually unlockedif (!StorageManager.isUserKeyUnlocked(userId)) return;synchronized (mLock) {// Bail if we ended up with a stale userif (mStartedUsers.get(uss.mHandle.getIdentifier()) != uss) return;// Do not proceed if unexpected stateif (!uss.setState(STATE_RUNNING_UNLOCKING, STATE_RUNNING_UNLOCKED)) {return;}}mInjector.getUserManagerInternal().setUserState(userId, uss.state);uss.mUnlockProgress.finish();// Get unaware persistent apps running and start any unaware providers// in already-running apps that are partially awareif (userId == UserHandle.USER_SYSTEM) {mInjector.startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_UNAWARE);}mInjector.installEncryptionUnawareProviders(userId);// Dispatch unlocked to external appsfinal Intent unlockedIntent = new Intent(Intent.ACTION_USER_UNLOCKED);unlockedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);unlockedIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);mInjector.broadcastIntent(unlockedIntent, null, null, 0, null,null, null, AppOpsManager.OP_NONE, null, false, false, MY_PID, SYSTEM_UID,Binder.getCallingUid(), Binder.getCallingPid(), userId);if (getUserInfo(userId).isManagedProfile()) {UserInfo parent = mInjector.getUserManager().getProfileParent(userId);if (parent != null) {final Intent profileUnlockedIntent = new Intent(Intent.ACTION_MANAGED_PROFILE_UNLOCKED);profileUnlockedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(userId));profileUnlockedIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY| Intent.FLAG_RECEIVER_FOREGROUND);mInjector.broadcastIntent(profileUnlockedIntent,null, null, 0, null, null, null, AppOpsManager.OP_NONE,null, false, false, MY_PID, SYSTEM_UID, Binder.getCallingUid(),Binder.getCallingPid(), parent.id);}}// Send PRE_BOOT broadcasts if user fingerprint changed; we// purposefully block sending BOOT_COMPLETED until after all// PRE_BOOT receivers are finished to avoid ANR'ing appsfinal UserInfo info = getUserInfo(userId);if (!Objects.equals(info.lastLoggedInFingerprint, Build.FINGERPRINT)) {// Suppress double notifications for managed profiles that// were unlocked automatically as part of their parent user// being unlocked.final boolean quiet;if (info.isManagedProfile()) {quiet = !uss.tokenProvided|| !mLockPatternUtils.isSeparateProfileChallengeEnabled(userId);} else {quiet = false;}mInjector.sendPreBootBroadcast(userId, quiet,() -> finishUserUnlockedCompleted(uss));} else {finishUserUnlockedCompleted(uss);}}

关键log记录:
01-01 08:00:32.310344 1014 1265 D ActivityManager: Started unlocking user 0
01-01 08:00:32.310389 1014 1265 D ActivityManager: Unlocking user 0 progress 0
01-01 08:00:32.310526 1014 1265 D ActivityManager: Unlocking user 0 progress 5
01-01 08:00:33.245283 1014 1261 I ActivityManager: User 0 state changed from RUNNING_LOCKED to RUNNING_UNLOCKING
01-01 08:00:33.246592 1014 1261 D ActivityManager: Unlocking user 0 progress 20

unlockUserCleared
finishUserUnlocking
finishUserUnlocked
finishUserUnlockedCompleted


http://www.ppmy.cn/embedded/114149.html

相关文章

高级实时通信:基于 Python 的 WebSocket 实现与异步推送解决方案

高级实时通信:基于 Python 的 WebSocket 实现与异步推送解决方案 目录 🟢 WebSocket 协议概述🔵 在 FastAPI 中实现 WebSocket🟣 Django Channels 实现异步实时通信🔴 使用 Redis 实现实时推送 🟢 1. WebS…

Spring Boot-消息队列相关问题

Spring Boot 消息队列相关问题及解决方案 消息队列(Message Queue, MQ)在分布式系统中的应用越来越广泛,尤其是在解耦系统、异步通信、负载均衡等场景中起到了至关重要的作用。消息队列为不同的服务提供了一种异步通信的机制,使得…

【Verilog学习日常】—牛客网刷题—Verilog快速入门—VL23

ROM的简单实现 描述 实现一个深度为8,位宽为4bit的ROM,数据初始化为0,2,4,6,8,10,12,14。可以通过输入地址addr,输出相应的数据data。 接口信号图如下&…

【MySQL】表的相关操作

目录 1. 表的创建1.1 创建表语法1.2 创建表案例1.3 查看表 2. 表的修改2.1 修改表名2.2 插入数据2.3 新增一列2.4 修改某列2.4.1 修改列的类型2.4.2 修改列名 2.5 删除某列 3. 表的删除4. 注意 1. 表的创建 1.1 创建表语法 create table student ( 列属性名1 列数据类型, 列属…

优化Web性能:Varnish中精准识别并缓存移动与桌面请求

引言 在现代Web开发中,为了提升用户体验,针对不同类型的设备提供定制化的内容是一项重要的策略。Varnish作为HTTP加速器和缓存代理服务器,能够帮助我们实现这一目标。本文将详细介绍如何利用Varnish来实现基于设备类型(PC端与移动…

【C语言】(指针系列3)数组指针+函数指针+typedef+函数数组指针+转移表

前言:前言:开始之前先感谢一位大佬,清风~徐~来-CSDN博客,由于是时间久远,博主指针的系列忘的差不多了,所以有顺序部分借鉴了该播主的,同时也加入了博主自己的理解,有些地方如果解释的…

Qt学习之旅 I

构建一个跨平台的应用(Create A Cross-Platform Application) 目录 构建一个跨平台的应用(Create A Cross-Platform Application) 设计模式 开始构建 Qt是跨平台的C框架,这里,我们将会构建一个简单的C跨平台项目来熟悉QT是如何实现简单的跨平台的。 …

上传富文本插入文件时报错:JSON parse error: Unexpected character解决办法

方式一(加密解密): 1.前端 (1)安装 crypto-js npm install crypto-js(2)util下引入asc.js asc.js import CryptoJS from crypto-js// 需要和后端一致 const KEY CryptoJS.enc.Utf8.parse(…