当前位置 : 主页 > 网络编程 > 其它编程 >

Android关键字persistent原理分析

来源:互联网 收集:自由互联 发布时间:2023-07-02
在Android程序开发时我们会接触到一些系统为了某些功能而定义的关键属性,例如在AndroidManifest.xml文件中经常看到的persistent、process等,下面 在Android程序开发时我们会接触到一些系统为
在Android程序开发时我们会接触到一些系统为了某些功能而定义的关键属性,例如在AndroidManifest.xml文件中经常看到的persistent、process等,下面

在Android程序开发时我们会接触到一些系统为了某些功能而定义的关键属性,例如在AndroidManifest.xml文件中

经常看到的persistent、process等,下面是自己对persistent关键字的分析,直奔主题。

一、persistent属性作用

1、定义

该属性的定义在frameworks/base/core/res/res/values/attrs_manifest.xml中,其定义如下:

通过官方注释我知道该属性用于是否让你的应用一直处于运行状态(通常说的常驻内存)。设置 该属性为true的app具有如下特点:

  • 在系统启动的时候会被系统启动起来

  • 在该app被强制杀掉后系统会重新启动该app,这种情况只针对系统内置app,第三方安装的app不会被重启

2、使用

persistent属性是用于application标签上的,用法为:

AndroidManifest.xml

android:persistent="true|false">

persistent的值默认为false

二、原理分析

通过第一点对persistent的功能说明后我们通过源码来分析一下它的工作原理

1、persistent属性的解析

该属性的解析主要在app被安装或者系统启动的时候发生

解析代码:

frameworks/base/core/java/com/android/content/pm/PackageParser.java

private boolean parseBaseApplication(Package owner, Resources res, XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException, IOException {final ApplicationInfo ai = owner.applicationInfo; //....................... if ((flags } }//.............}

在解析完包信息之后系统会将解析好的所有包信息存放到PKMS中的mPackages的map中,而ApplicationInfo的flag中有一个bit位用于保存该app是否是persistent的。这里只是把保存persistent的flag设置为FLAG_PERSISTENT。在AndroidManifest设置了persistent为true的app是否能够在被异常杀死后能够得到重启的权力需要取决于该app对应的ProcessRecord的persistent属性,该属性只有在你的app既在AndroidManifest中配置了persistent=“true”,又是系统内置app时才会被设置为true。

2、系统启动时启动persistent为true的app

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

在系统启动时ActivityManagerService的systemReady()方法会将所有在AndroidManifest设置了persistent为true的app拉起来

public void systemReady(final Runnable goingCallback) {......synchronized (this) { // Only start up encryption-aware persistent apps; once user is // unlocked we'll come back around and start unaware apps startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE); // Start up initial activity. mBooting = true; // Enable home activity for system user, so that the system can always boot if (UserManager.isSplitSystemUser()) { ComponentName cName = new ComponentName(mContext, SystemUserHomeActivity.class); try { AppGlobals.getPackageManager().setComponentEnabledSetting(cName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0, UserHandle.USER_SYSTEM); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } }......}

systemReady中调用了startPersistentApps() 方法

private 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, false, null /* ABI override */); } } } catch (RemoteException ex) { } } }

在startPersistentApps方法中首先是调用PackageManageServices的getPersistentApplications方法获取到所有在AndroidManifest设置了persistent为true的app,然后调用addAppLocked方法去启动他们。这样在AndroidManifest设置了persistent为true的app就随着系统的启动而启动了。 下面看一下getPersistentApplications方法,该方法调用了PKMS中的getPersistentApplicationsInternal方法。

private @NonNull List getPersistentApplicationsInternal(int flags) { final ArrayList finalList = new ArrayList(); // reader synchronized (mPackages) { final Iterator 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 final boolean matchesAware = ((flags if ((p.applicationInfo.flags if (ps != null) { ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags, ps.readUserState(userId), userId); if (ai != null) { finalList.add(ai); } } } } } return finalList; }

该方法会遍历mPackages中的所有app,并找到其中在AndroidManifest设置了persistent为true的应用。从代码中可以看到,persistent为true并且是系统app的话一定会被选中,但是如果是第三方安装的应用的话只能在非“安全模式”下才会被选中。

之后调用addAppLocked方法启动app:

final ProcessRecord addAppLocked(ApplicationInfo info, boolean isolated, String abiOverride) { ProcessRecord app; //传递进来的isolated=false,所有一定会调用getProcessRecordLocked方法,但是由于是第一次启动,所有返回的app = null if (!isolated) { app = getProcessRecordLocked(info.processName, info.uid, true); } else { app = null; } if (app == null) { //为新的app创建新的ProcessRecord对象 app = newProcessRecordLocked(info, null, isolated, 0); updateLruProcessLocked(app, false, null); updateOomAdjLocked(); } // This package really, really can not be stopped. try { //由于是开机第一次启动,所以新的app的启动状态是将要被启动状态,所以 //该app的停止状态stoped被设置为false 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); } //在这里对persistent的app进行过滤,只有既是系统app,persistent为true的app才会在 //异常死亡之后被重启 if ((info.flags app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ; } //如果该app已经启动了,则不用处理,否则调用startProcessLocked方法启动app。 //由于启动app是异步进行的,会将正在启动而还没有启动完成的app添加到 //mPersistentStartingProcesses列表中。当启动完成后 再移除 if (app.thread == null //启动该app startProcessLocked(app, "added application", app.processName, abiOverride, null /* entryPoint */, null /* entryPointArgs */); } return app; }}

接下来调用startProcessLocked方法启动app进程,在app启动完成后会在ActivityThread中调用AMS的attachApplication,将该app从mPersistentStartingProcesses中移除,并注册一个死亡讣告监听器AppDeathRecipient,用于在app异常被杀后的处理工作。

private final boolean attachApplicationLocked(IApplicationThread thread, int pid) {......try { //注册死亡讣告监听器AppDeathRecipient 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; }......}

3、app被异常结束后系统重新启动persistent为true的app

进程启动时为app注册了一个死亡讣告,当该app被杀掉之后会调用AppDeathRecipient的binderDied方法,该方法会调用appDiedLocked方法进行善后处理,系统在进程死掉之后会对死掉的进程进行清理和资源回收,但是在这个过程中如果你的app是persistent的话会被重启:

binderDied

| |——appDiedLocked | |——handleAppDiedLocked | |——cleanUpApplicationRecordLocked

在cleanUpApplicationRecordLocked中对persistent为true的app进行重启

private final boolean cleanUpApplicationRecordLocked(ProcessRecord app, boolean restarting, boolean allowRestart, int index, boolean replacingPid) {............... //非persistent的app被杀死后就被清理掉 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. //该app是persistent的,需要对其进行重启,并把它添加到正在启动的列表中,并 //设置restart=true if (mPersistentStartingProcesses.indexOf(app) <0) { mPersistentStartingProcesses.add(app); restart = true; } }....//经过上面的过滤,会调用这个分支条件重启persistent为true的app if (restart } addProcessNameLocked(app); startProcessLocked(app, "restart", app.processName); return true; } else if (app.pid > 0 synchronized (mPidsSelfLocked) { mPidsSelfLocked.remove(app.pid); 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); } return false;}

上一篇:数据采用非Ajax方式,随意添加联动
下一篇:没有了
网友评论