android App保活技术调研报告
Android系统核心App需要在Android开机期间一直后台运行,如果被杀死会立即重启。这个功能的实现是在App的AndroidManifest.xml添加android:persistent="true"属性控制。但是Android 8.0之后含有Persist的App禁止升级。如果我们把翻译服务相关的Ap设置android:persistent="true"属性就无法升级,如果不添加android:persistent="true"属性就无法保证一直运行会影响翻译功能。所以需要设计一种新的机制保证翻译服务不仅可以一直运行而且可以正常升级。
1.3 类型
调研报告为技术可行性调研,从方案对系统稳定性的影响和对需要保活的App的综合讨论,后台需保活App 启动由APP Store和Launcher完成,保活和升级等其他功能由Framework完成。
1.4 定义
AMS(ActivityManagerService):是Android Framework层的核心系统服务之一,负责App和Service的启动、删除和保活等工作。
PMS(PackageManagerService):是Android Framework层的核心系统服务之一,主要用于APP和Service升级和权限管理等功能。
KPP(App Store和Launcher ):主要用于启动需要保活的后台Service和App。
APP:需要被保活的后台App和Service。
1.5 参考资料

说明:
1、列出要用到的参考资料(网站、书籍、已有项目资产)
2. 调研过程
2.1 思路介绍
APP整体保活思路按照下图所示,本文以下所有内容均是按照此思路实现保活机制。

在这里插入图片描述

一、Android系统APP保活主要有两个因素决定:
1、APP预置到system分区下的app、priv-app或Vendor-app下,预置到/data/app目录下APP的的不能被保活。
2、APP的AndroidManifest.xml添加android:persistent="true"属性。
该属性的定义在frameworks/base/core/res/res/values/attrs_manifest.xml中,其定义如下:

1.	<!-- Flag to control special persistent mode of an application.  This should  
2.	  
3.	        not normally be used by applications; it requires that the system keep  
4.	  
5.	        your application running at all times. -->  
6.	  
7.	<attr name="persistent" format="boolean" />  

通过官方注释我知道该属性用于是否让你的应用一直处于运行状态(通常说的常驻内存)。设置
该属性为true的app具有如下特点:
1、在系统启动的时候会被系统启动起来
2、在该app被强制杀掉后系统会重新启动该app,这种情况只针对系统内置app,第三方安装app不会被重启
二、Persistent属性的解析
1、persistent属性的解析该属性的解析主要在app被安装或者系统启动的时候发生
解析代码:

frameworks/base/core/java/com/android/content/pm/PackageParser.java
1.	private boolean parseBaseApplication(Package owner, Resources res,  
2.	  
3.	            XmlResourceParser parser, int flags, String[] outError)  
4.	  
5.	        throws XmlPullParserException, IOException {  
6.	  
7.	final ApplicationInfo ai = owner.applicationInfo;  
8.	  
9.	    //.......................  
10.	  
11.	      
12.	  
13.	    if ((flags&PARSE_IS_SYSTEM) != 0) {  //只有system app才会添加Persist属性
14.	  
15.	            if (sa.getBoolean(  
16.	  
17.	                    com.android.internal.R.styleable.AndroidManifestApplication_persistent,  //如果含有persistent 。ApplicationInfo 添加 FLAG_PERSISTENT 标志
18.	  
19.	                    false)) {  
20.	  
21.	                ai.flags |= ApplicationInfo.FLAG_PERSISTENT;  
22.	  
23.	            }  
24.	  
25.	        }  

在解析完包信息之后系统会将解析好的所有包信息存放到PKMS中的mPackages的map中,而ApplicationInfo的flag中有一个bit位用于保存该app是否是persistent的。这里只是把保存persistent的flag设置为FLAG_PERSISTENT。在AndroidManifest设置了persistent为true的app是否能够在被异常杀死后能够得到重启的权力需要取决于该app对应的ProcessRecord的persistent属性,该属性只有在你的app既在AndroidManifest中配置了persistent=“true”,又是系统内置app时才会被设置为true。
2、app被异常结束后系统重新启动persistent为true的app进程启动时为app注册了一个死亡讣告,当该app被杀掉之后会调用AppDeathRecipient的binderDied方法,该方法会调用appDiedLocked方法进行善后处理,系统在进程死掉之后会对死掉的进程进行清理和资源回收,但是在这个过程中如果你的APP是persistent的话会被重启。
在cleanUpApplicationRecordLocked中对persistent为true的app进行重启
在这里插入图片描述
2.2 方案介绍
一、 机器开机阶段:

  1. PMS函数parseBaseApplication默认只解析system app 下的Persistent,修改源码支持解析/data/app下APK的persistent属性解析代码。

在这里插入图片描述

  1. AMS启动属性persistent的APP。
    二、 PMS升级阶段:
  2. APP更新时,解析升级APP是否含有persistent属性,有则ApplicationInfo对应标志FLAG_PERSISTENT位置1。
1.		 if ((flags&PARSE_IS_SYSTEM) != 0) {  
2.	             if (sa.getBoolean(  
3.	@@ -3658,8 +3663,22 @@ public class PackageParser {  
4.	                     ai.flags |= ApplicationInfo.FLAG_PERSISTENT;  
5.	                 }  
6.	             }  
7.	-        }  
8.	-  //对第三方/data/app的APP的persistent属性解析
9.	+        }else if (owner.mSharedUserId.equals("android.uid.system")) {  
10.	+                        if (sa.getBoolean(  
11.	+                    com.android.internal.R.styleable.AndroidManifestApplication_persistent,  
12.	+                    false)) {  
13.	+                // Check if persistence is based on a feature being present  
14.	+                final String requiredFeature = sa.getNonResourceString(  
15.	+                    com.android.internal.R.styleable.  
16.	+                    AndroidManifestApplication_persistentWhenFeatureAvailable);  
 
21.	+                      
22.	+   }  
  1. 升级APP含有persistent属性。升级前调用AMS.killApplication杀死APP
  2. 升级APP不含有persistent属性,执行默认Android升级流程
  3. 确保APP已被杀死后,正式开始升级保活的APP
    三、 AMS保活阶段:
  4. 若APP函数Persistent属性,则添加APP到保活列表中,启动保活APP。
  5. 若PMS调用AMS的killApplication函数,则添加killPersist进程处理逻辑,主要代码如下
3)	public void killPersist (String pkg){  
4)	         final ArrayMap<String, SparseArray<ProcessRecord>> dmap = mProcessNames.getMap();  
5)	         if(dmap.containsKey(pkg)){  
6)	            Slog.e(TAG,"delProcessPersist del app persist start");  
7)	            final int NP = mProcessNames.getMap().size();  
8)	             for (int ip=0; ip<NP; ip++) {  //遍历当前正在运行进程
9)	                SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip);  
10)	                final int NA = apps.size();  
11)	                for (int ia=0; ia<NA; ia++) {  
12)	                    ProcessRecord app = apps.valueAt(ia);  
13)	                    if (app.processName.equals(pkg)){  //如果此进程名字和要升级app相同
14)	                        if (app.persistent){  
15)	                            Slog.e(TAG,"delProcessPersist del app persist " + pkg);  
//删除要升级app进程的persistent属性
1  ............ 详细代码在最后连接下载
20)	                            }  
21)	                        }  
22)	                    }  
23)	                }  
24)	             }  
25)	         }  
26)	    }  
  1. AMS添加升级成功APP的保活功能
    四、KPP功能:
    升级完成收到广播唤醒APP。
    此方案需要AMS和PMS以及KPP三个模块配合完成APP系统保活和升级功能,在AMS模块主要工作是保活APP,在升级的时候取消升级APP的Persistent属性并杀死此APP进程。PMS模块,开机时解析system 和 data APP,若含有Persistent=true,添加相关标志位,升级保活APP前,调用AMS.killApplication
    杀死对应APP进程。
    完整逻辑流程如图所示:

在这里插入图片描述
此功能完全经过测试验证。完全符合产品需求。产品在高通8953 android 8.1 版本验证通过。如有需要相关代码 已上传到百度网盘

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐