Android 系统persist应用

引入
在Android系统App中(注意是系统App),都会添加一个persistent 属性,表明此应用是一个永久性应用,就是从系统一开机就一直运行,直到系统关机。他的另外一个特写是,服务被杀死后会自动重启,本篇就来一探究竟。

AndroidManifest.xml
android:persistent="true" 

启动

Android系统在启动时,ActivityManagerService 会调用systemReady 方法,在这里会调起所谓的 永久性应用:

public void systemReady(final Runnable goingCallback) {...       try {List apps = AppGlobals.getPackageManager().getPersistentApplications(STOCK_PM_FLAGS);if (apps != null) {int N = apps.size();int i;                for (i=0; i<N; i++) {ApplicationInfo info= (ApplicationInfo)apps.get(i);   if (info != null &&!info.packageName.equals("android")) {addAppLocked(info, false, null /* ABI override */);}}}} catch (RemoteException ex) { }...}

先来看看 getPersistentApplications(),它的定义在PKMS中:

public List<ApplicationInfo> getPersistentApplications(int flags) {final ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();// readersynchronized (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&& (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0&& (!mSafeMode || isSystemApp(p))) {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;}

注意这里有过滤非系统App:isSystemApp§,只有系统App 才会添加到列表里面。
再回到传给AMS的addAppLocked()方法:

final ProcessRecord addAppLocked(ApplicationInfo info, boolean isolated,String abiOverride) {ProcessRecord app;...if (app == null) {//这里启动进程app = newProcessRecordLocked(info, null, isolated, 0);mProcessNames.put(info.processName, app.uid, app);if (isolated) {mIsolatedProcesses.put(app.uid, app);}updateLruProcessLocked(app, false, null);updateOomAdjLocked();}// 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&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))== (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {app.persistent = true;app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;}if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {mPersistentStartingProcesses.add(app);startProcessLocked(app, "added application", app.processName, abiOverride,null /* entryPoint */, null /* entryPointArgs */);}return app;}

这里再次通过ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT 过滤非系统APP.
并设置 app.persistent = true;最后调用startProcessLocked()启动进程。
当进程启动成功之后,便会从mPersistentStartingProcesses里删除这个进程。

private final boolean attachApplicationLocked() {...//下面这段代码很关键,与Persisten服务重启有关final String processName = app.processName;try {AppDeathRecipient adr = new AppDeathRecipient(app, pid, thread);thread.asBinder().linkToDeath(adr, 0);app.deathRecipient = adr;} catch (RemoteException e) {app.resetPackageList(mProcessStats);startProcessLocked(app, "link fail", processName);return false;}mPersistentStartingProcesses.remove(app);mProcessesOnHold.remove(app);if (!didSomething) {updateOomAdjLocked();}...
}

补充:第三方应用及时带有persist属性,在进程创建时,也会被拦截

private static final int PERSISTENT_MASK =ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT;
final ProcessRecord newProcessRecordLocked(ApplicationInfo info, String customProcess,boolean isolated, int isolatedUid) {...final ProcessRecord r = new ProcessRecord(this, stats, info, proc, uid);if (!mBooted && !mBooting&& userId == UserHandle.USER_SYSTEM&& (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {// The system process is initialized to SCHED_GROUP_DEFAULT in init.rc.r.curSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;r.setSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;r.persistent = true;r.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;}...addProcessNameLocked(r);return r;}

服务重启

我们知道每一个应用进程里都会有一个ApplicationThread mAppThread对象,AMS通过它在AMS里的代理接口IApplicationThread与应用进程进行通信。(attachApplicationLocked 函数里面的第一个参数thread,就是一个应用进程在AMS里的代理对象)
在应用进程启动时,会调用ActivityThread的attach()方法将自己依附于AMS当中,也就是由AMS启动它并对它进行管理,attach()最终通过binder机制调用到AMS的attachApplicationLocked()方法。
再次贴出上面的关键代码:

private final boolean attachApplicationLocked(IApplicationThread thread...) {...//下面这段代码很关键,与Persisten服务重启有关final String processName = app.processName;try {AppDeathRecipient adr = new AppDeathRecipient(app, pid, thread);thread.asBinder().linkToDeath(adr, 0);app.deathRecipient = adr;} catch (RemoteException e) {app.resetPackageList(mProcessStats);startProcessLocked(app, "link fail", processName);return false;}...
}

上面AppDeathRecipient 在AMS中声明如下:

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
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() {if (DEBUG_ALL) Slog.v(TAG, "Death received in " + this+ " for thread " + mAppThread.asBinder());synchronized(ActivityManagerService.this) {appDiedLocked(mApp, mPid, mAppThread, true);}}}

当应用进程死掉时,系统会回调由linkToDeath()注册的AppDeathRecipient对象的binderDied()方法。
有如下调用关系

binderDied();appDiedLocked();handleAppDiedLocked();cleanUpApplicationRecordLocked();

在cleanUpApplicationRecordLocked() 函数里面,我们看到了关键处理:

private final boolean cleanUpApplicationRecordLocked(ProcessRecord app,boolean restarting, boolean allowRestart, int index, boolean replacingPid) {...if (!app.persistent || app.isolated) {if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,"Removing non-persistent process during cleanup: " + app);if (!replacingPid) {removeProcessNameLocked(app.processName, app.uid, app);}if (mHeavyWeightProcess == app) {mHandler.sendMessage(mHandler.obtainMessage(CANCEL_HEAVY_NOTIFICATION_MSG,mHeavyWeightProcess.userId, 0));mHeavyWeightProcess = null;}} 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.if (mPersistentStartingProcesses.indexOf(app) < 0) {mPersistentStartingProcesses.add(app);restart = true;}}...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);}addProcessNameLocked(app);app.pendingStart = false;startProcessLocked(app, "restart", app.processName);return true;} else if (app.pid > 0 && app.pid != MY_PID) {...}

可以看到,如果是非persist的进程死亡,则直接回收所有的进程资源。
persist的进程,就会再加入mPersistentStartingProcesses队列,然后等待重启。


彩蛋:利用persist 属性可以自启动的原理,我们也可以利用增加白名单方式,将进程加入persist属性, 实现常驻和自启动:

final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,...if (app == null) {checkTime(startTime, "startProcess: creating new process record");app = newProcessRecordLocked(info, processName, isolated, isolatedUid);if (app == null) {Slog.w(TAG, "Failed making new process record for "+ processName + "/" + info.uid + " isolated=" + isolated);return null;}// Begin  add for white list.//自定义的白名单List<String> persistentAdList = ThirdPartyPermissions.getPersistentAdApps(mContext);if (app != null && null != persistentAdList && persistentAdList.contains(processName)) {app.persistent = true;app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;if (mPersistentStartingProcesses.indexOf(app) < 0) {mPersistentStartingProcesses.add(app);}}// End add for white list.app.crashHandler = crashHandler;mProcessNames.put(processName, app.uid, app);if (isolated) {mIsolatedProcesses.put(app.uid, app);}checkTime(startTime, "startProcess: done creating new process record");}...


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部