最新消息:欢迎访问Android开发中文站!商务联系QQ:1304524325

微信团队原创分享:Android版微信后台保活实战分享(进程保活篇)

新手入门 loading 13661浏览 0评论

哪些部分需要“保活”?

按照我们的理解包含两部分:

进程保活概述

在Android系统里,进程被杀的原因通常为以下几个方面:

  • a. 应用Crash
  • b. 系统回收内存
  • c. 用户触发
  • d. 第三方root权限app.

原因a可以单独作为一个课题研究。原因c、d目前在微信上没有特殊处理。这里讨论的就是如何应对Android Low Memory Killer。

进程保活实施:进程拆分

微信团队原创分享:Android版微信后台保活实战分享(进程保活篇)_0 (3).png

上图表述的是微信主要的几个进程:

  • a. push主要用于网络交互,没有UI
  • b. worker就是用户看到的主要UI
  • c. tools主要包含gallery和webview

拆分网络进程,确实就是为了减少进程回收带来的网络断开。

微信团队原创分享:Android版微信后台保活实战分享(进程保活篇)_0 (4).png

可以看到push的内存要远远小于worker。而且push的工作性质稳定,内存增长会非常少。这样就可以保证,尽量的减少push 被杀的可能。这里有个思路,但限制比较多,也抛砖引玉。启动一个纯C/C++ 的进程,没有Java run time ,内存使用极低。

这种做法限制很明显,如:没有Java run time ,所以无法使用Android系统接口。缺乏权限,也无法使用各种shell命令操作(如am)。但可以考虑一下用途:高强度运算,网络连接,心跳维持等。比如Shadow***-android就如此,通过纯c命令行进程,维护着socks5代理 (Android M运行正常)。

tools进程的拆分也同样是内存的原因:

  • a. 老版本的webview 是有内存泄漏的
  • b. Gallery大量缩略图导致内存使用大

微信在进入后台后,会主动把tools进程kill掉。

进程保活实施:及时拉起

系统回收不可避免,及时重新拉起的手段主要依赖系统特性。从上图看到, push有AlarmReceiver, ConnectReceiver,BootReceiver。这些receiver 都可以在push被杀后,重新拉起。特别AlarmReceiver ,结合心跳逻辑,微信被杀后,重新拉起最多一个心跳周期。

而对于worker,除了用户UI操作启动。在接收消息,或者网络切换等事件, push也会通过LocalBroadcast,重新拉起worker。这种拉起的worker ,大部分初始化已经完成,也能大大提高用户点击微信的启动速度。

历史原因,我们在push和worker通信使用Broadcast和AIDL。实际上,我一直不喜欢这里的实现,AIDL代码冗余多, broadcast效率低。欢迎大家分享更好的思路或者方法。

进程保活实施:进程优先级

Low Memory Killer 决定是否杀进程除了内存大小,还有进程优先级:
微信团队原创分享:Android版微信后台保活实战分享(进程保活篇)_0 (5).png

上表的数字可能在不同系统会有一定的出入,但明确的是,数值越小,优先级越高。对于优先级相同的进程,总是会把内存占用多的先kill。提高进程优先级是保活的最好手段。

正常情况下微信的oom_adj:
微信团队原创分享:Android版微信后台保活实战分享(进程保活篇)_0 (6).png

而被提高优先级后:
微信团队原创分享:Android版微信后台保活实战分享(进程保活篇)_0 (7).png

从统计上报看,提高后的效果极佳。原理:Android 的前台service机制。但该机制的缺陷是通知栏保留了图标。

对于 API level < 18 :调用startForeground(ID, new Notification()),发送空的Notification ,图标则不会显示。对于 API level >= 18:在需要提优先级的service A启动一个InnerService,两个服务同时startForeground,且绑定同样的 ID。Stop 掉InnerService ,这样通知栏图标即被移除。

这方案实际利用了Android前台service的漏洞。微信在评估了国内不少app已经使用后,才进行了部署。其实目标是让大家站同一起跑线上,哪天google 把漏洞堵了,效果也是一样的。

QA环节

Q:之前看微信的架构分享,貌似是通过单一Activity,用多个Fragment切换来实现的多窗口。如果分进程的话,看起来Gallery和
WebView是单独的一个Activity,我的理解是否正确呢?以及进入后台之后,为何只kill tools而不一起释放work呢?

A:Fragment的改造只是用在有限的几个UI上,大部分的UI,对于切换时间要求不高,还是保留成activity,Gallery和WebView都是单独的
activity,所以才可能另外一个进程的。对于我们来说worker的保活仅次于网络的push,worker如果频繁被杀,用户每次启动微信都需要
等待,这个就不好了。所以,我们在后台,只会kill tools,不会主动kill worker。

Q:除了提高进程的优先级,微信在内存方面有什么处理或优化的技术吗?

A:不可否认,其实微信是内存大户了,现阶段我们主要关注内存泄漏,没有专门去减少内存的使用,毕竟内存意味着cache,意味着用户体验更快,后续对于内存优化我们有一些规划,比如说,在cache这块照顾一些低端机。

Q:我记得很久以前听说过微信使用一个像素的浮动窗口来保活,不知道现在还有没有呢?

A:我们有想过,也听说过有其他app是这样做的,但从来没实现过这个方案。

Q:你们push进程与worker进程采用过socket通信方案么?采用的话效果怎么样?

A:有考虑过用socket,后续也可能会有这种尝试,但因为push和worker依赖代码太多,伤筋动骨了,但估计也要比AIDL好,AIDL对于应用出问题后能做的事情太少了。

转载请注明:Android开发中文站 » 微信团队原创分享:Android版微信后台保活实战分享(进程保活篇)

您必须 登录 才能发表评论!