Persistent常驻内存分析
简介
通过官方注释我知道该属性用于是否让你的应用一直处于运行状态(通常说的常驻内存)。设置android:persistent
属性为true的app具有如下特点:
- 在系统启动的时候会被系统启动起来。
- 在该app被强制杀掉后系统会重新启动该app,这种情况只针对系统内置app,第三方安装的app不会被重启这个地方在9.0以后包括9.0我不知道是否还有效,看源码我有点困惑。
这里我们分析的代码是Android10.0的源码。
使用
在AndroidManifest文件下的application标签中添加 android:persistent=“true”,默认是false。
1 2 3 | <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是判断是不是系统应用的:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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并没有判断:
1 2 3 4 5 6 7 8 9 10 | 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。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | //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的实现里边判断了是否是系统应用或者是否是安全模式,是的话才会在系统启动的时候自动拉起来:
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 | 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(缓存的正在启动的常驻内存进程列表)移除掉。
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 33 34 35 36 37 38 39 40 41 | //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的应用处理如下:
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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | //如果正在启动不处理 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之后在添加属性时,也没有对是不是系统应用判断,普通应用也可以设置这个属性了,所以9.0之后死亡重新拉起可能对普通应用也会有效,这个地方那个大佬可以说一下,在哪里有对系统应用的处理,我没找到。
推荐
要看源码的话推荐Android 官方的CodeSearch
参考
Persistence解析包含一些应用启动的东西比较全
Persistence属性解析