Android Persistent常驻内存分析

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的应用处理如下:

扫描二维码关注公众号,回复: 11785740 查看本文章
//如果正在启动不处理
		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之后在添加属性时,也没有对是不是系统应用判断,普通应用也可以设置这个属性了,而且普通应用也走了attachApplicationLocked绑定了死亡代理,所以9.0之后死亡重新拉起可能对普通应用也会有效,这个地方那个大佬可以说一下,在哪里有对系统应用的处理,我没找到

推荐

要看源码的话推荐Android 官方的CodeSearch

参考

Persistence解析包含一些应用启动的东西比较全
Persistence属性解析

猜你喜欢

转载自blog.csdn.net/u011148116/article/details/106926779