首次开机android.intent.action.BOOT_COMPLETED开机广播发送慢的问题
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
- 后面重启,不会有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
相关文章:
首次开机android.intent.action.BOOT_COMPLETED开机广播发送慢的问题
1. 背景 做过android开发的同学相信一定做个这种逻辑:app接收BOOT_COMPLETED开机广播,自启动,或者收到广播做一些事情。目前在我们的项目上遇到首次开机,BOOT_COMPLETED开机广播发送慢的问题。接下来分享记录下如何定位这类问题。 2. 分析过…...
通信工程学习:什么是OLT光线路终端
OLT:光线路终端 OLT(Optical Line Terminal,光线路终端)是光纤通信系统中的核心局端设备,特别是在无源光网络(Passive Optical Network, PON)架构中扮演着至关重要的角色。以下是关于OLT光线路终…...
Unity的Button组件进行扩展
废话不多说,在Untiy中,如果想要对Button等组件进行扩展的话,那么不仅仅只需要将新增的属性设置为public或者增加SerializeField字段就行了的,同时需要对Inspector的GUI面板进行修改,以下直接展示代码: usi…...
前端vue-插值表达式和v-html的区别
创建vue实例的时候,可以有两种形式。 1.let appnew Vue({}) 2 const appnew Vue({}) 3 el是挂载点,是上面div的id值 4 data中的值可以展示在上面div中 5 v-html标签里面如果有内容,则我们的新内容会把标签里面的内容覆盖掉...
【开发心得】筑梦上海:项目风云录(4)
不知不觉已经写到了第4篇,天下大事,必作于细。 其实项目管理也是如此,成功都在细节之处。自从博士离开以后,项目逐步开始进入了正常轨道。来来回回的30多人,也不能一一列举的记流水账。 目录 会海和MSN 小娇往事 …...
el-table使用el-switch选择器没效果
出现问题的代码: 0表示启用,1表示禁用,发现页面根本没有效果,百思不得其解,查阅资料,恍然大悟。 <el-table :data"userList" stripe border style"width: 100%" height"500"><…...
libserailport交叉编译适配说明
1:libserialport简介 github路径 自己的gitee路径 libserialport 是一个跨平台的串口通信库,由 sigrok 项目开发。它简洁、易用,并且支持多种操作系统。 libserialport 支持阻塞和非阻塞模式,可以根据你的需求选择适当的模式。阻…...
C语言中的一些小知识(二)
一、"%"运算符两侧只能是整数 在C语言中,% 运算符称为模运算符或取余运算符,它用于计算两个整数相除后的余数。当使用 % 运算符时,操作数必须是整数类型(包括 char、int、long 等)。 语法 remainder div…...
使用 Go 语言实现简单聊天系统
在互联网时代,聊天系统是常见的应用场景之一。无论是即时通讯、在线客服还是多人游戏中的消息系统,聊天功能的实现都是必不可少的。本文将使用 Go 语言,结合 WebSocket 来构建一个简单的多人聊天室系统。 一、项目结构 首先,我们…...
用友U8二次开发工具KK-FULL-*****-EFWeb使用方法
1、安装: 下一步,下一步即可。弹出黑框不要关闭,让其自动执行并关闭。 2、服务配置: 输入服务器IP地址,选择U8数据源,输入U8用户名及账号,U8登录日期勾选系统日期。测试参数有效性,提示测试通过…...
【经验帖】脏读和不可重复读的概念及影响
脏读和不可重复读是数据库事务并发执行时可能出现的两种数据一致性问题,它们对数据的一致性和完整性有着显著的影响。以下是脏读和不可重复读的具体影响: 脏读的影响 脏读发生在一个事务读取了另一个事务未提交的数据时。由于这些数据尚未被提交&#x…...
MTK zephyr平台:USB升级、枚举流程
一、USB升级流程 通过代码及log分析,当前平台升级过程在PL阶段进行 USB download相关代码 mtk/modules/hal/boot/preloader/platform/flashc/ mtk/modules/hal/boot/preloader/platform/board_name/flash/ mtk/modules/hal/boot/preloader/platform/board_name/src/drive…...
golang操作mysql利器-gorm
1、傻瓜示例 GORM通过将数据库表中的数据映射到面向对象的模型中,简化了数据库操作,使得开发者可以很方便的使用代码来操作数据库,而无需编写SQL语句。 目前有个mysql表:miniprogram_orders,其存储了所有用户对应的订…...
09 Shell Scriptfor循环结构语句
Shell Scriptfor循环结构语句 一、Shell FOR循环语句概述 属于shell的符合语句 可以看出帮助信息给出了两种语法 [rootlocalhost ~]# help for for: for NAME [in WORDS ... ] ; do COMMANDS; doneExecute commands for each member in a list.The for loop executes…...
【Java】并发集合
并发集合(java.util.concurrent) 一、List CopyOnWriteArrayList(ReentrantLock实现线程安全) (1)并发修改(写操作)时保证线程安全: 通过ReentrantLock实现多个线程并…...
活动邀请|景联文科技与您相约华为全联接大会2024
2024年9月19-21日,第九届华为全联接大会(简称:HUAWEICONNECT2024)将在上海世博展览馆和上海世博中心举办。 作为华为的旗舰盛会,本次大会以“共赢行业智能化”为主题将邀请思想领袖、商业精英、技术专家、合作伙伴、开发者等业界同仁…...
周边游|基于springBoot的周边游平台设计与实现(附项目源码+论文+数据库)
私信或留言即免费送开题报告和任务书(可指定任意题目) 目录 一、摘要 二、相关技术 三、系统设计 四、数据库设计 五、核心代码 六、论文参考 七、源码获取 一、摘要 在如今社会上,关于信息上面的处理,没有任…...
【编程基础知识】mysql是怎样执行一条sql语句的,涉及到哪些环节步骤是,mysql的整体体系结构是啥样的,有哪些组件
一、步骤 MySQL执行一条SQL语句的过程涉及多个环节和步骤。以下是这一过程的概述: 客户端连接:客户端通过连接器(Connector)向MySQL服务器发起连接请求。身份验证:连接器对用户身份进行验证,确保用户有权…...
如何上传tauri项目到csdn gitcode
如何上传tauri项目到csdn gitcode 首先保证项目目录有.gitignore,避免不必要的文件上传分享。 gitignore文件 # Logs logs *.log npm-debug.log* yarn-debug.log* yarn-error.log* pnpm-debug.log* lerna-debug.log*node_modules dist dist-ssr *.local# Editor …...
【速成Redis】02 Redis 五大基本数据类型常用命令
前言: 上一节课,我们对redis进行了初步了解,和安装好了redis。【速成Redis】01 Redis简介及windows上如何安装redishttps://blog.csdn.net/weixin_71246590/article/details/142319358?spm1001.2014.3001.5501 该篇博客,我们正…...
大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...
基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...
376. Wiggle Subsequence
376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...
ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
sqlserver 根据指定字符 解析拼接字符串
DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...
10-Oracle 23 ai Vector Search 概述和参数
一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI,使用客户端或是内部自己搭建集成大模型的终端,加速与大型语言模型(LLM)的结合,同时使用检索增强生成(Retrieval Augmented Generation &#…...
push [特殊字符] present
push 🆚 present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中,push 和 present 是两种不同的视图控制器切换方式,它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...
