在android系统开发过程中,我们有时候需要配置我们的某个应用,在开机后自动启动,并在设备低内存时不被kill。
我们可以配置应用的AndroidManifest.xml
配置peristent属性。
ActivityManagerService.java
public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {traceLog.traceBegin("PhaseActivityManagerReady");...// Only start up encryption-aware persistent apps; once user is// unlocked we'll come back around and start unaware apps//启动persist应用,在启动launcher之前startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE); ... if (bootingSystemUser) {//启动lunchermAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady");}..}
继续看startPersistentApps 函数
void startPersistentApps(int matchFlags) {if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL) return;synchronized (this) {try {final List 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 */);}}} catch (RemoteException ex) {}}}
startPersistentApps 函数中,遍历当前系统中persistent属性的app,非android进程时执行addApplocked;
@GuardedBy("this")final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated,String abiOverride) {return addAppLocked(info, customProcess, isolated, false /* disableHiddenApiChecks */,false /* mountExtStorageFull */, abiOverride);}// TODO: Move to ProcessList?@GuardedBy("this")final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated,boolean disableHiddenApiChecks, boolean mountExtStorageFull, String abiOverride) {ProcessRecord app;if (!isolated) {app = getProcessRecordLocked(customProcess != null ? customProcess : info.processName,info.uid, true);} else {app = null;}if (app == null) {app = mProcessList.newProcessRecordLocked(info, customProcess, isolated, 0,new HostingRecord("added application",customProcess != null ? customProcess : info.processName));mProcessList.updateLruProcessLocked(app, false, null);updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_PROCESS_BEGIN);}// This package really, really can not be stopped.try {AppGlobals.getPackageManager().setPackageStoppedState(info.packageName, false, UserHandle.getUserId(app.uid));} catch (RemoteException e) {} catch (IllegalArgumentException e) {Slog.w(TAG, "Failed trying to unstop package "+ info.packageName + ": " + e);}if ((info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {app.setPersistent(true);app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;}if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {mPersistentStartingProcesses.add(app);mProcessList.startProcessLocked(app, new HostingRecord("added application",customProcess != null ? customProcess : app.processName),disableHiddenApiChecks, mountExtStorageFull, abiOverride);}return app;}
addAppLocked 启动persistent应用,并配置maxAdj = PERSISTENT_PROC_ADJ = -800;
同时将app,添加到mPersistentStartingProcesses 列表中
-800 表示进程属于高优先级,当系统资源紧张时,lowmemorykiller机制回收应用时会跳过persistent进程。
虽然我们设置了persistent 应用的adj = -800,但是并不能保证100%不会被kill,例如通过adb kill pids kill。
google 对persistent应用做了重启机制。
重启机制
android在进程启动后调用到attachApplicationLocked时会创建一个进程死亡监听器AppDeathRecipient
/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
@GuardedBy("this")private boolean attachApplicationLocked(@NonNull IApplicationThread thread,int pid, int callingUid, long startSeq) {......final String processName = app.processName;try {//app死亡监听器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));return false;}......} 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;}@Overridepublic void binderDied() {//当应用死亡后,调用binderDiedif (DEBUG_ALL) Slog.v(TAG, "Death received in " + this+ " for thread " + mAppThread.asBinder());synchronized(ActivityManagerService.this) {appDiedLocked(mApp, mPid, mAppThread, true);}}} // appDiedLocked@GuardedBy("this")final void appDiedLocked(ProcessRecord app, int pid, IApplicationThread thread,boolean fromBinderDied) {......if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,"Dying app: " + app + ", pid: " + pid + ", thread: " + thread.asBinder());//处理app diedhandleAppDiedLocked(app, false, true); ......}//hadlerAppDiedLocked@GuardedBy("this")final void handleAppDiedLocked(ProcessRecord app,boolean restarting, boolean allowRestart) {int pid = app.pid;//boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1,false /*replacingPid*/);if (!kept && !restarting) {removeLruProcessLocked(app);if (pid > 0) {ProcessList.remove(pid);}}if (mProfileData.getProfileProc() == app) {clearProfilerLocked();}mAtmInternal.handleAppDied(app.getWindowProcessController(), restarting, () -> {Slog.w(TAG, "Crash of app " + app.processName+ " running instrumentation " + app.getActiveInstrumentation().mClass);Bundle info = new Bundle();info.putString("shortMsg", "Process crashed.");finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);});}
appDiedLocked()最终会执行到cleanUpApplicationRecordLocked(),我们可以看一下这个方法做了什么
@GuardedBy("this")final boolean cleanUpApplicationRecordLocked(ProcessRecord app,boolean restarting, boolean allowRestart, int index, boolean replacingPid) {......} 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 列表中的应用时,restart = trueif (mPersistentStartingProcesses.indexOf(app) < 0) {mPersistentStartingProcesses.add(app);restart = true;}}//restart = true app应用重启 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));return true;
我们看到发现是persistent应用时,设置restart = true,并调用重启。