惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
Cyberwarzone
Cyberwarzone
The GitHub Blog
The GitHub Blog
云风的 BLOG
云风的 BLOG
P
Proofpoint News Feed
小众软件
小众软件
Recent Announcements
Recent Announcements
博客园 - 三生石上(FineUI控件)
Security Archives - TechRepublic
Security Archives - TechRepublic
W
WeLiveSecurity
Cloudbric
Cloudbric
博客园 - 司徒正美
美团技术团队
N
News and Events Feed by Topic
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
PCI Perspectives
PCI Perspectives
宝玉的分享
宝玉的分享
H
Help Net Security
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Google DeepMind News
Google DeepMind News
Help Net Security
Help Net Security
Last Week in AI
Last Week in AI
S
Schneier on Security
N
News | PayPal Newsroom
B
Blog RSS Feed
L
LINUX DO - 最新话题
T
Troy Hunt's Blog
S
Secure Thoughts
雷峰网
雷峰网
aimingoo的专栏
aimingoo的专栏
L
Lohrmann on Cybersecurity
G
Google Developers Blog
Microsoft Azure Blog
Microsoft Azure Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
T
Tenable Blog
S
Securelist
L
LangChain Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
I
InfoQ
H
Heimdal Security Blog
Cisco Talos Blog
Cisco Talos Blog
F
Full Disclosure
Y
Y Combinator Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
K
Kaspersky official blog
T
Tailwind CSS Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
阮一峰的网络日志
阮一峰的网络日志
C
Cisco Blogs

Android Performance

SmartPerfetto 架构文章 Q&A:8 个深度技术问答 从 Trace 到洞察:SmartPerfetto AI Agent 的 Harness Engineering 实战 OpenClaw 常见问题解答:Token 消耗、能干什么、本地模型、隐私安全、使用体验 我把 OpenClaw 跑在本地三周后,发现它根本不是聊天机器人 Android Perfetto 系列 10 - Binder 调度与锁竞争 Android Perfetto 系列 9 - CPU 信息解读 Android Perfetto 系列 8:深入理解 Vsync 机制与性能分析 Android Perfetto 系列 7 - MainThread 和 RenderThread 解读 Android Perfetto 系列 6:为什么是 120Hz?高刷新率的优势与挑战 Android Perfetto 系列 5:Android App 基于 Choreographer 的渲染流程 Android Perfetto 系列 4:使用命令行在本地打开超大 Trace Android ANR 系列 3 :ANR 案例分享 Android ANR 系列 2 :ANR 分析套路和关键 Log 介绍 Android ANR 系列 1 :理解 Android ANR 设计思想 Android Perfetto 系列 3:熟悉 Perfetto View Android Perfetto 系列 2:Perfetto Trace 抓取 Android Perfetto 系列 1:Perfetto 工具简介 Android Perfetto 系列目录 2023 年的方方面面 关于 The Android Performance 知识星球介绍 The Performance Design Of OS OS 设计之性能设计 当 App 有了系统权限,真的可以为所欲为? The Performance 星球茶话会 - 第一期 Systrace 线程 CPU 运行状态分析技巧 - Sleep 和 Uninterruptible Sleep 篇 Systrace 线程 CPU 运行状态分析技巧 - Running 篇 Systrace 线程 CPU 运行状态分析技巧 - Runnable 篇 Android 性能优化的术、道、器 Techniques, Philosophy, and Tools for Android Performance Optimization 回顾 2021 一本讲 Android 流畅性的书,应该有什么内容? Android 系统开发系列(1):Android 12 源代码下载、编译和刷机 Android Systrace 响应速度实战 3 :响应速度延伸知识 Android Systrace 响应速度实战 2 :响应速度实战分析-以启动速度为例 Android Systrace 响应速度实战 1 :了解响应速度原理 Android Systrace 流畅性实战 3 :卡顿分析过程中的一些疑问 Android Systrace 流畅性实战 2 :案例分析 - MIUI 桌面滑动卡顿分析 Android Systrace 流畅性实战 1 :了解卡顿原理 华为手机刷微博体验更好?技术角度的一些分析和思考 一个「闰」字引发的事故 - 三星系统重启分析 Android Systrace 基础知识 - SurfaceFlinger 解读 Android 开发者学习路线(2020 版本) 我的 2020 年读书单 Android Systrace 基础知识 - CPU Info 解读 Android Systrace 基础知识 - Triple Buffer 解读 Android Systrace 基础知识 - Binder 和锁竞争解读 「置顶」博客文章目录 Android Systrace 基础知识 - Vsync 解读 Android App 启动优化全记录 Android Systrace 基础知识 - MainThread 和 RenderThread 解读 Android Systrace 基础知识 - Input 解读 Android 中的“后台无效动画“行为分析 Android 基于 Choreographer 的渲染机制详解 Android 中的卡顿丢帧原因概述 - 低内存篇 Android 桌面被杀问题分析案例 Android 中的卡顿丢帧原因概述 - 应用篇 Android 中的卡顿丢帧原因概述 - 系统篇 Android 中的卡顿丢帧原因概述 - 方法论 Android 中的 Activity Launch Mode 详解 Android 中的 Hardware Layer 详解 Android Systrace 基础知识 -- 分析 Systrace 预备知识 Android Systrace 基础知识 - SystemServer 解读 Android Systrace 基础知识 -- Systrace 简介 Android Systrace 基础知识 -- Why 60 fps ? Android Systrace -- 系列文章目录 Android 新的流畅体验,90Hz 漫谈 利器 - 高效工具推荐 Android 无障碍服务导致的整机卡顿案例分析 2018 年度好物推荐 - 给辛勤工作的自己一点奖励 Android 系统开发源码环境搭建 陆奇:除了好代码,工程师怎样才算优秀? 程序员的修炼-08-阅读之美 程序员的修炼-07-游戏与编程 程序员的修炼-06-互联网那些事 程序员的修炼-05-了解你的用户 程序员的修炼-04-关于测试的一些思考 程序员的修炼-03-Web 设计原则 程序员的修炼-02-编程之道 程序员的修炼-01-绝地反击之术 Android 系统不释放内存吗? 关于 Android 系统流畅性的一些思考 知乎 救救你的 StartingWindow 「置顶」Android 性能优化必知必会 2017 年度好物推荐 - 给辛勤工作的自己一点奖励 2017 Android Bottom navigation 规范二:样式、行为与规格 Android Bottom Navigation 规范一:使用方法 Android 中如何计算 App 的启动时间? Android 应用启动优化:一种 DelayLoad 的实现和原理(下篇) Android 应用启动优化 - 一种 DelayLoad 的实现和原理(上篇) Android hwui 中 RenderThread 工作流程 Java7 HashMap 源码分析 Android 代码内存优化建议 - OnTrimMemory 优化 Android 代码内存优化建议 - Android 资源篇 Android 代码内存优化建议 - Android 官方篇 Android 代码内存优化建议 - Java 官方篇 Nexus6 with Android M 开启多窗口模式 细说 Java 单例模式 Android 性能优化典范 - Profile GPU Rendering Android 性能优化典范 - Understanding VSYNC
Android App 链式唤醒分析
Gracker · 2020-05-07 · via Android Performance

MIUI 12 的发布, 将之前一直是应用开发者和 Rom 开发者斗争最激烈的部分展示给了普通消费者, 让普通消费者也知道了这场斗争的细节, 正所谓 “魔高一尺道高一丈”, Rom 开发者由于有更高的代码修改权限, 始终占据着上风 ; App 开发者当然也不甘示弱, 各种保活拉起黑科技层出不穷,甚至 Google 都参与到了这部分斗争中, 居中调和, 制定各种规则来规范双方. 当然斗争对双方来说都算是好事, 毕竟任何一方完全的胜利都会导致 “狡兔死走狗烹,飞鸟尽良弓藏”

不过双方斗争的受害者无疑还是使用手机的消费者, App 如果斗争成功, 那么手机上各种后台进程乱跑, 杀不掉, 占用 CPU 和内存, 这不是消费者想看到的 ; 如果 Rom 开发者斗争成功, App 的体验必定会大打折扣, 各位 App 开发者应该深有体会.

从文章最后一段可以看到, 其实各个手机厂商对付这一套都有自己的策略, 基本上都可以搞定自启动和关联启动. 至于隐私, 李彦宏曾经说过 “中国人对隐私问题的态度更加开放,也相对来说没那么敏感。如果他们可以用隐私换取便利、安全或者效率。在很多情况下,他们就愿意这么做“ . 大家想想在微信里面复制一段话打开到淘宝就可以自动跳转到这个物品, 方不方便? 好不好用? 还想不想用? 剪贴板再借我看一看?

希望大家在隐私问题上不要打哈哈, 技术是把双刃剑, 如果隐私落到别有用心的人手上, 后果是很严重的, 就算不是为了自己, 为了下一代. 欧盟为什么要搞《通用数据保护条例》(General Data Protection Regulation,简称 GDPR), 就是为了隐私. 举个例子, 国内很多厂商的产品现在要区分是否在欧盟买, 如果是在欧盟卖的话, 就得把里面那些收集用户数据的功能都关掉, 否则抓住了就能罚你罚到吐血 . 至于中国和印度, 随便收集.

本篇文章不涉及到隐私部分, 我是对隐私保护无条件支持的 . 这里只从技术的角度, 来讲一下 MIUI 12 爆出来的应用自启动和关联唤醒的问题.

PS: 大家在自己的手机上可能看不到我列的一些例子, 是因为我是用的 Android 10 的 AOSP 代码, 大部分的国产 Rom 都已经阻断了应用的这些行为.

技术名词解释

首先解释几个技术名词, 方便大家对号入座

进程启动

在 Android 中, 一个 App 包含六部分, 进程(必选) + Activity (可选) + BroadcastReceiver (可选)+Service (可选)+ContentProvider (可选) + 子进程(可选)

一个必选项加五个可选项, 组成了一个 App, 其中 Activity(可选) + BroadcastReceiver(可选)+Service(可选)+ContentProvider(可选) 这四个又称为 Android 的四大组件, 之所以这四兄弟这么特殊, 是因为这四个组件都可以单独启动,

但是这四兄弟启动之前, 系统都会检查对应的进程是否存在, 如果进程不存在, 那么就需要先启动进程, 再启动这个组件. 我们在桌面上点击一个应用图标, 其实启动的就是他的 Activity, 系统会先创建进程, 然后再启动 Activity, 我们才可以看到对应的界面

一般自启动和关联启动, 一般不会直接启动 Activity, 因为 Activity 是用户可感知的, 你在后台莫名其妙起了一个界面到前台, 用户分分钟卸了你 . 所以一般自启动和关联启动都是在 BroadcastReceiver (可选) + Service (可选) + ContentProvider (可选) 三个上面做文章.

自启动

自启动指的是不借助其他的应用, 通过监听系统的一些事件, 或者文件变化, 通过系统的机制, 把自己的进程拉起来处理事情.

关联启动

关联启动指的是借助其他应用来启动自己, 比如大家列出来的起点读书启动作家助手\电信营业厅\百词斩这种.

启动阻断

启动阻断也叫切断唤醒, Rom 开发人员在四大组件启动的地方加入逻辑判断, 符合条件的组件才能拉起自己的进程, 不符合条件的组件直接返回, 这样就达到了启动阻断的目的.

当然这里面还有很多工作要做, 比如工作状态判断, 拉起合理性判断, 一旦错误的阻断必然会引起用户的使用逻辑的断裂, 比如用户在一个 App 里面要拉起支付宝进行支付, 结果启动支付宝的支付组件的时候被你给阻断了, 可以想象用户的愤怒

有了上面几个简单的概念, 下面我们就简单说一下自启动和关联启动的技术分析 .

分析手段

Monkey

要分析应用启动,首先需要安装大量应用,然后执行 Monkey,让大部分进程都跑起来。我使用的 Monkey 命令如下,跑完就自己去睡觉了

1
adb shell monkey --kill-process-after-error --ignore-security-exceptions --ignore-crashes --pct-appswitch 90 --pct-touch 10 --throttle 10000 --ignore-timeouts --ignore-native-crashes 100000000

EventLog

首先可以用 EventLog 来查看进程的启动信息,EventLog 会如实记录每个进程的启动、死亡信息。我使用下面的命令来进行进程启动和死亡的过滤

1
adb logcat -b events | egrep "am_proc_died|am_proc_start"

Dumpsys

这里主要是使用了 Dumpsys activity ,主要是用来分析进程的各个组件的信息

1
adb shell dumpsys activity

自启动的技术分析

自启动指的是不借助其他的应用, 通过监听系统的一些事件, 或者文件变化, 通过系统的机制, 把自己的进程拉起来处理事情. 这些系统的事件就包括开机广播 / 网络变化 / 媒体库扫描等(这里只列了一部分) .

开机广播

用户重启手机后, 系统会向注册了开机广播的应用发广播, 收到广播的应用就可以把自己拉起来, 开始处理对应的逻辑(拉起更多的进程), 对应的广播如下:

1
android.intent.action.BOOT_COMPLETED

应用可以监听这个广播, 在用户重启手机后, 将自己唤醒, 处理自己的逻辑, 比如说继续图片备份/ 继续同步联系人 / 检查是否有固件更新 / 推送最新的新闻等操作

当然监听这个广播也是应用自启动的一个手段

案例: 腾讯新闻监听开机广播拉起后台进程

典型的广播接受处理记录 : com.tencent.news 的 com.tencent.news.system.BootBroadcastReceiver 组件接收了 android.intent.action.BOOT_COMPLETED 广播,处理了 7s,至于怎么处理, 当然是先把 com.tencent.news 这个进程拉起来, 然后执行 BootBroadcastReceiver  的 onReceive 方法 . 这是一个典型的自启动的例子

网络变化

网络变化包括网络连接 / 断开 / wifi 移动网络切换等操作, 一旦发生这些事件, 系统会向对应注册了这个事件的应用发送广播 . 对应的广播如下:

1
android.net.conn.CONNECTIVITY_CHANGE

应用就可以监听这个广播来执行对应的逻辑, 比如你在看直播,突然 wifi 断了切换成了 4G 网络, 应用就可以提醒用户是否使用移动网络继续观看, 毕竟网络直播还是很耗流量的.

当然监听这个广播也是应用自启动的一个手段

案例

下图可以看到五个监听了网络变大的广播接收器 (只显示了五个, 其实有 200 多个), 监听到网络变化后拉起自身

  1. 包名: com.alibaba.android.rimet(钉钉)
  2. 接收器 : com.xiaomi.push.service.receivers.NetworkStatusReceiver
  3. 包名: cn.xuexi.android
  4. 接收器: com.xiaomi.push.service.receivers.NetworkStatusReceiver
  5. 包名: com.sina.weibo
  6. 接收器: com.xiaomi.push.service.receivers.NetworkStatusReceiver
  7. 包名: com.sdu.didi.psnger
  8. 接收器 : com.didi.sdk.push.PushNetReceiver
  9. 包名: com.meelive.ingkee
  10. 接收器 : com.network_optimization.NetWorkStateReceiver

图中 packageName 就是对于的应用的包名, name 是启动的组件

1
android.net.wifi.STATE_CHANGE

媒体库扫描

系统监听到文件变化或者存储盘变化也会发通知给各个应用, 比如说增加了一个图片或者文档, 其对于的广播如下

1
2
3
android.intent.action.MEDIA_SCANNER_STARTED
android.intent.action.MEDIA_SCANNER_FINISHED
android.intent.action.MEDIA_EJECT

当然监听这个广播也是应用自启动的一个手段

案例: jd 监听 MEDIA_SCANNER_STARTED 广播自启

下面是一个典型的监听媒体库扫描广播进行自启动的案例:

com.jd.jrapp 的广播接收器 com.jd.jrapp.library.longconnection.receiver.BootReceiver 监听到 android.intent.action.MEDIA_SCANNER_STARTED 广播后, 启动自己进程开始处理

三方 SDK - 个推

个推是各个应用接入的一个三方 SDK, 用于消息推送, 但其实个推也集成了上面说的哪几种自启动的方式, 包括 BOOT_COMPLETED,CONNECTIVITY_CHANGE,USER_PRESENT 这些

关于个推,由于可定制型比较强, 比如 在项目源码中添加一个继承自 com.igexin.sdk.PushService 的自定义 Service 就可以, 所以从 EventLog 和 Dumpsys 没法直接看出来哪个用了个推来保活或者相互唤醒, 不过其对于的子进程得设置为 :pushservice, 可以根据这个做判断(有可能不准)

所以我们直接看个推的配置文档

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<service
android:name="com.igexin.sdk.PushService"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="false"
android:label="NotificationCenter"
android:process=":pushservice"/>
<receiver android:name="com.igexin.sdk.PushReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
<action android:name="android.intent.action.USER_PRESENT" />

<action android:name="android.intent.action.MEDIA_MOUNTED" />
<action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />
</intent-filter>
</receiver>
<activity
android:name="com.igexin.sdk.PushActivity"
android:excludeFromRecents="true"
android:exported="false"
android:process=":pushservice"
android:taskAffinity="com.igexin.sdk.PushActivityTask"
android:theme="@android:style/Theme.Translucent.NoTitleBar" >
</activity>
<activity
android:name="com.igexin.sdk.GActivity"
android:excludeFromRecents="true"
android:exported="true"
android:process=":pushservice"
android:taskAffinity="com.igexin.sdk.PushActivityTask"
android:theme="@android:style/Theme.Translucent.NoTitleBar"/>

像最前面同提到的 BootComplete, com.ss.android.ugc.aweme:pushservice 可能就是接入了个推

关联启动的技术分析

关联启动指的是借助其他应用来启动自己, 比如说很多 App 接入了同一个 SDK, 那么一旦你启动了接入这个 SDK 的应用,那么这个 SDK 就可以启动同样接入了这个 SDK 的其他应用, 达到关联唤醒的目的

这个 SDK 可以是 BAT 集团内部自研的通用 SDK, 也可以是三方提供的 SDK, 根据我自己的调试来看, 大家提到的 xxx 启动了 xxx, 大部分都是通过三方 SDK 来实现的, 大部分是用了极光推送.

下面就以一个案例来看极光推送是怎么利用一个已经启动的 App 来启动另外一个没有启动的 App 的.

首先我们看 EventLog 可以看到进程的启动信息, 包括进程名, 进程 pid, 启动的组件, 启动的组件类型.

1
[0,19428,10195,com.qq.reader,service,{com.qq.reader/cn.jpush.android.service.DaemonService}] 

上面这条 Log 解释一下就是

  1. 启动进程 : com.qq.reader(QQ 阅读)
  2. 启动 pid :19428
  3. 启动组件: cn.jpush.android.service.DaemonService
  4. 组件类型: service

案例:起点 App 通过极光推送拉起 QQ 阅读

执行 adb shell am force-stop com.qq.reader , 强制杀掉 QQ 阅读, 观察 EventLog, 从下面的可以看到, QQ 阅读的进程被拉起, 拉起的是 Service 这个组件, 其具体的内容是 com.qq.reader/cn.jpush.android.service.DaemonService

当然从 Event Log 里面我们看不出来是谁拉起了这个 Service,这时候就需要 dumpsys activity 的帮助了, 由于是 Service 组件被拉起, 那么我们可以看 com.qq.reader 的 ServiceRecord, 其内容如下, 可以看到其 Connections 一栏, 是被 com.qidian.QDReader:pushcore 这个进程拉起的

那么对应的, 在小米的 MIUI 12 关联启动界面就会显示 : 起点读书 在 8:48 分拉起了 QQ 阅读(由于没有小米手机, 所以没法截图, 大家自己看高票答案 https://www.zhihu.com/question/391494145 自己脑补一下就可以了)

极光推送的官方文档其实也说的很清楚, 提供了被拉起和拉起别人的功能, 看你自己怎么用.

极光官方文档唤醒配置

极光关联启动文档

手机厂商应对

最前面的有说到, 进程管理是应用开发者和 Rom 开发者斗争最激烈的部分, MIUI 选择了将斗争的过程展示给了普通消费者, 让普通消费者也知道了这场斗争的细节 . 其他的厂商也做了相同的事情, 否则整个系统基本上是没法用的, 就像我手上现在这台测试用的 pixel, 不断有进程因为整机内存太小被 LMK 杀掉, 然后马上被各种手段重新启动, 耗电极快, 卡的连娘都不认识了.

我们从极光和个推的官方文档就可以看到各个手机厂商的应对方法和开关的界面, 这里列出来是方便大家进去看一下, 因为各个手机厂商的白名单配置不一样, 或者有时候用户自己改过但是忘记了, 都可以进去重新设置一下, 对于那些你退出了就不想让他继续活动的应用,果断去掉白名单.

极光推送白名单配置

个推白名单配置

EMUI OS(华为)

  • 自启动管理:需要把应用加到【自启动管理】列表,否则杀进程或重新开机后进程不会开启,只能手动开启应用
  • 后台应用保护:需要手动把应用加到此列表,否则设备进入睡眠后会自动杀掉应用进程,只有手动开启应用才能恢复运行
  • 通知管理:应用状态有三种:提示、允许、禁止。禁止应用则通知栏不会有任何提醒

Flyme OS(魅族)

  • 自启动管理:需要把应用加到【自启动管理】列表,否则杀进程或重新开机后进程无法开启
  • 通知栏推送:关闭应用通知则收到消息不会有任何展示

Funtouch OS(VIVO)

  • 自启动管理:需要将应用加入“i 管家”中的【自启动管理】列表,否则重启手机后进程不会自启。但强制手动杀进程,即使加了这个列表中,后续进程也无法自启动。

Color OS(OPPO)

  • 冻结应用管理:需要将应用加入纯净后台,否则锁屏状态下无法及时收到消息
  • 自启动管理:将应用加入【自启动管理】列表的同时,还需要到设置-应用程序-正在运行里锁定应用进程,否则杀进程或者开机后进程不会开启,只能手动开启应用

MIUI OS (小米)

  • 自启动管理:需要把应用加到【自启动管理】列表,否则杀进程或重新开机后进程无法开启
  • 省电策略:需要禁用应用省电策略,否则后台几分钟后会被系统限制联网
  • MIUI 7 神隐模式: 允许用户设置后台联网应用,开启后应用即可在后台保持联网,否则应用进入后台时,应用无法正常接收消息。【设置】->【电量和性能】->【神隐模式】

关于我 && 博客

下面是个人的介绍和相关的链接,期望与同行的各位多多交流,三人行,则必有我师!

  1. 博主个人介绍 :里面有个人的微信和微信群链接。
  2. 本博客内容导航 :个人博客内容的一个导航。
  3. 个人整理和搜集的优秀博客文章 - Android 性能优化必知必会 :欢迎大家自荐和推荐 (微信私聊即可)
  4. Android性能优化知识星球 : 欢迎加入,多谢支持~

一个人可以走的更快 , 一群人可以走的更远

微信扫一扫