Android关键字persistent原理分析

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

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

一、persistent属性作用

1、定义

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


    <!-- Flag to control special persistent mode of an application.  This should

         not normally be used by applications; it requires that the system keep

         your application running at all times. -->

    <attr name="persistent" format="boolean" />



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

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

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

2、使用

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

AndroidManifest.xml


<application

    android:persistent="true|false"

>



</application>



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&PARSE_IS_SYSTEM) != 0) {

            if (sa.getBoolean(

                    com.android.internal.R.styleable.AndroidManifestApplication_persistent,

                    false)) {

                ai.flags |= ApplicationInfo.FLAG_PERSISTENT;

            }

        }





//.............








}

在解析完包信息之后系统会将解析好的所有包信息存放到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<ApplicationInfo> 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<ApplicationInfo> getPersistentApplicationsInternal(int flags) {

        final ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();



        // 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;

    }



该方法会遍历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 & PERSISTENT_MASK) == PERSISTENT_MASK) {

            app.persistent = true;

            app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;

        }

        //如果该app已经启动了,则不用处理,否则调用startProcessLocked方法启动app。

        //由于启动app是异步进行的,会将正在启动而还没有启动完成的app添加到

        //mPersistentStartingProcesses列表中。当启动完成后 再移除

        if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {

            mPersistentStartingProcesses.add(app);

            //启动该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 && !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);

            startProcessLocked(app, "restart", app.processName);

            return true;

        } else if (app.pid > 0 && app.pid != MY_PID) {

            // Goodbye!

            boolean removed;

            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;



}





    原文作者:奔跑的小猫
    原文地址: https://www.jianshu.com/p/02aeac34e2c8
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞