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之後在添加屬性時,也沒有對是不是系統應用判斷,普通應用也可以設置這個屬性了,所以9.0之後死亡重新拉起可能對普通應用也會有效,這個地方那個大佬可以說一下,在哪裏有對系統應用的處理,我沒找到。
推薦
要看源碼的話推薦Android 官方的CodeSearch