Persistent常驻内存分析
简介
通过官方注释我知道该属性用于是否让你的应用一直处于运行状态(通常说的常驻内存)。设置android:persistent
属性为true的app具有如下特点:
- 在系统启动的时候会被系统启动起来。
- 在该app被强制杀掉后系统会重新启动该app,这种情况只针对系统内置app,第三方安装的app不会被重启这个地方在9.0以后包括9.0我不知道是否还有效,看源码我有点困惑。
这里我们分析的代码是Android10.0的源码。
使用
在AndroidManifest文件下的application标签中添加 android:persistent=“true”,默认是false。
<application
android:persistent="true|false">
</application>
源码分析
分析过程中我们可以思考一个问题: 设置android:persistent属性,一定需要是系统App才生效吗?
首先,App的AndroidManifest解析是在frameworks/base/core/java/android/content/pm/PackageParser.java中,我们找到persistence属性所在的地方。
persistentWhenFeatureAvailable这个属性我们可以忽略,他为null的时候也可以执行到下边的属性设置 ai.flags |= ApplicationInfo.FLAG_PERSISTENT。
- 解析设置属性
8.0以前包括8.0是判断是不是系统应用的:
if ((flags&PARSE_IS_SYSTEM) != 0) {
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_persistent,
false)) {
// Check if persistence is based on a feature being present
final String requiredFeature = sa.getNonResourceString(
com.android.internal.R.styleable.
AndroidManifestApplication_persistentWhenFeatureAvailable);
if (requiredFeature == null || mCallback.hasFeature(requiredFeature)) {
ai.flags |= ApplicationInfo.FLAG_PERSISTENT;
}
}
}
9.0以后包括9.0并没有判断:
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_persistent,
false)) {
// Check if persistence is based on a feature being present
final String requiredFeature = sa.getNonResourceString(com.android.internal.R.styleable
.AndroidManifestApplication_persistentWhenFeatureAvailable);
if (requiredFeature == null || mCallback.hasFeature(requiredFeature)) {
ai.flags |= ApplicationInfo.FLAG_PERSISTENT;
}
}
- 系统启动时
我们知道Android中管理Activity的是AMS,而Activity又是应用界面的承载体,Activity是和用户交互的组件,那么讲解应用启动,必定要谈到AMS,而android:persistent="true"标识着系统的自启动应用,那么这些应用也不例外应该在系统启动的时候自启动我们去查看下AMS。
//AMS中,SystemReady中调用startPersistentApps他的详细代码如下:
void startPersistentApps(int matchFlags) {
if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL) return;
synchronized (this) {
try {
final List<ApplicationInfo> apps = AppGlobals.getPackageManager()
.getPersistentApplications(STOCK_PM_FLAGS | matchFlags).getList();
for (ApplicationInfo app : apps) {
if (!"android".equals(app.packageName)) {
addAppLocked(app, null, false, null /* ABI override */,
ZYGOTE_POLICY_FLAG_BATCH_LAUNCH);
}
}
} catch (RemoteException ex) {
}
}
}
我们可以看到getPersistentApplications是通过AppGlobals.getPackageManager调用的我们直接去查看PMS,最终找到PMS中getPersistentApplicationsInternal的实现里边判断了是否是系统应用或者是否是安全模式,是的话才会在系统启动的时候自动拉起来:
private @NonNull List<ApplicationInfo> getPersistentApplicationsInternal(int flags) {
final ArrayList<ApplicationInfo> finalList = new ArrayList<>();
// reader
synchronized (mPackages) {
final Iterator<PackageParser.Package> i = mPackages.values().iterator();
final int userId = UserHandle.getCallingUserId();
while (i.hasNext()) {
final PackageParser.Package p = i.next();
if (p.applicationInfo == null) continue;
final boolean matchesUnaware = ((flags & MATCH_DIRECT_BOOT_UNAWARE) != 0)
&& !p.applicationInfo.isDirectBootAware();
final boolean matchesAware = ((flags & MATCH_DIRECT_BOOT_AWARE) != 0)
&& p.applicationInfo.isDirectBootAware();
if ((p.applicationInfo.flags & ApplicationInfo.FLAG_PERSISTENT) != 0
&& (!mSafeMode || isSystemApp(p))
&& (matchesUnaware || matchesAware)) {
PackageSetting ps = mSettings.mPackages.get(p.packageName);
if (ps != null) {
ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags,
ps.readUserState(userId), userId);
if (ai != null) {
finalList.add(ai);
}
}
}
}
}
return finalList;
}
- 应用被杀死时被重新拉起时
在ActivityManagerService中AMS.startPersistentApps -> AMS.addAppLocked -> AMS.startProcessLocked -> ProcessList.startProcessLocked -> Process.start 调用链最后调用Process.start 通过socket通知zygote fork出新的进程,然后通过ActivityThread中的main方法启动应用。
ActivityThread中调用attach方法最终调用到AMS中的attachApplicationLocked,会为应用程序的binder注册一个AppDeathRecipient死亡代理,其实就是AIDL中的IBinder.DeathRecipient,在attachApplicationLocked中绑定好应用之后,会把启动的常驻内存应用进程从mPersistentStartingProcesses(缓存的正在启动的常驻内存进程列表)移除掉。
//attachApplicationLocked 绑定应用前注册死亡代理
try {
AppDeathRecipient adr = new AppDeathRecipient(
app, pid, thread);
thread.asBinder().linkToDeath(adr, 0);
app.deathRecipient = adr;
} catch (RemoteException e) {
app.resetPackageList(mProcessStats);
mProcessList.startProcessLocked(app,
new HostingRecord("link fail", processName),
ZYGOTE_POLICY_FLAG_EMPTY);
return false;
}
// Remove this record from the list of starting applications. mPersistentStartingProcesses.remove(app);
//是AMS中的一个内部类
private final class AppDeathRecipient implements IBinder.DeathRecipient {
final ProcessRecord mApp;
final int mPid;
final IApplicationThread mAppThread;
AppDeathRecipient(ProcessRecord app, int pid,
IApplicationThread thread) {
if (DEBUG_ALL) Slog.v(
TAG, "New death recipient " + this
+ " for thread " + thread.asBinder());
mApp = app;
mPid = pid;
mAppThread = thread;
}
@Override
public void binderDied() {
if (DEBUG_ALL) Slog.v(
TAG, "Death received in " + this
+ " for thread " + mAppThread.asBinder());
synchronized(ActivityManagerService.this) {
appDiedLocked(mApp, mPid, mAppThread, true);
}
}
}
当应用死亡时会回调AppDeathRecipient中的binderDied方法,然后会执行AMS中的appDiedLocked -> handleAppDiedLocked 在handleAppDiedLocked中有个cleanUpApplicationRecordLocked对persistence的应用处理如下:
//如果正在启动不处理
if (restarting) {
return false;
}
//如果应用不是常驻应用则移除进程
if (!app.isPersistent() || app.isolated) {
if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
"Removing non-persistent process during cleanup: " + app);
if (!replacingPid) {
mProcessList.removeProcessNameLocked(app.processName, app.uid, app);
}
mAtmInternal.clearHeavyWeightProcessIfEquals(app.getWindowProcessController());
} else if (!app.removed) {
// This app is persistent, so we need to keep its record around.
// If it is not already on the pending app list, add it there
// and start a new process for it.
//这个app是常驻内存的,所以我们需要去保持他存活。如果他已经不存在于mPersistentStartingProcesses(正在启动的app进程缓存列表)中了,把它添加进去,并标记restart = true,后边重开进程,重新启动
if (mPersistentStartingProcesses.indexOf(app) < 0) {
mPersistentStartingProcesses.add(app);
restart = true;
}
}
if ((DEBUG_PROCESSES || DEBUG_CLEANUP) && mProcessesOnHold.contains(app)) Slog.v(
TAG_CLEANUP, "Clean-up removing on hold: " + app);
mProcessesOnHold.remove(app);
mAtmInternal.onCleanUpApplicationRecord(app.getWindowProcessController());
//需要重启则重新启动
if (restart && !app.isolated) {
// We have components that still need to be running in the
// process, so re-launch it.
if (index < 0) {
ProcessList.remove(app.pid);
}
mProcessList.addProcessNameLocked(app);
app.pendingStart = false;
mProcessList.startProcessLocked(app,
new HostingRecord("restart", app.processName),
ZYGOTE_POLICY_FLAG_EMPTY);
return true;
//否则移除掉
} else if (app.pid > 0 && app.pid != MY_PID) {
// Goodbye!
mPidsSelfLocked.remove(app);
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
mBatteryStatsService.noteProcessFinish(app.processName, app.info.uid);
if (app.isolated) {
mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid);
}
app.setPid(0);
}
总结
系统版本 < 9.0设置时就会判断是不是系统应用,系统版本 >= 9.0
设置时随便设置;但是在启动时既要判断是不是系统应用又要判断persistence是否为true;死亡重新拉起时,并没有看到判断是否为系统应用,在9.0之后在添加属性时,也没有对是不是系统应用判断,普通应用也可以设置这个属性了,而且普通应用也走了attachApplicationLocked绑定了死亡代理,所以9.0之后死亡重新拉起可能对普通应用也会有效,这个地方那个大佬可以说一下,在哪里有对系统应用的处理,我没找到。
推荐
要看源码的话推荐Android 官方的CodeSearch