Android persistent屬性原理分析

以下代碼基于Android9.0

persistent屬性的定義

開發(fā)系統(tǒng)應(yīng)用時,有時我們需要應(yīng)用常駐,被殺死后能夠自動重啟,此時就需要使用到persistent屬性,
下面是關(guān)于該屬性在framework層的定義,屬性的定義位于
persistent屬性定義在platform/frameworks/base/core/res/res/values/attrs_manifest.xml文件內(nèi):

    <!-- 控制應(yīng)用程序是否處于特殊持久模式的標志,通常情況下不應(yīng)該被使用,該標志位能夠保證應(yīng)用程序一直運行 -->
    <attr name="persistent" format="boolean" />

persistent屬性的使用

開發(fā)系統(tǒng)應(yīng)用時,有時我們需要應(yīng)用常駐,被殺死后能夠自動重啟,此時我們就要在應(yīng)用的AndroidManifest.xml中設(shè)置

android:persistent="true"

設(shè)置后應(yīng)用就具備了以下兩個特性:

  1. 系統(tǒng)啟動時該應(yīng)用也會啟動
  2. 應(yīng)用被殺死后,系統(tǒng)會重啟該應(yīng)用

persistent屬性的原理

persistent屬性的解析

當我們應(yīng)用安裝或啟動的過程中,會對AndroidManifest.xml進行解析,解析相關(guān)的代碼位于
platform/frameworks/base/core/java/android/content/pm/PackageParser.java

public class PackageParser {
    ....
    private boolean parseBaseApplication(Package owner, Resources res,
            XmlResourceParser parser, int flags, String[] outError)
            throws XmlPullParserException, IOException {
                final ApplicationInfo ai = owner.applicationInfo;
                final String pkgName = owner.applicationInfo.packageName;
        
                // 獲取 AndroidManifest 的屬性
                TypedArray sa = res.obtainAttributes(parser,
                com.android.internal.R.styleable.AndroidManifestApplication);
                ....
                // 獲取所設(shè)置的 persistent 值,默認為 false
                if (sa.getBoolean(
                    com.android.internal.R.styleable.AndroidManifestApplication_persistent,
                    false)) {
                // 檢查應(yīng)用是否支持這個權(quán)限
                final String requiredFeature = sa.getNonResourceString(com.android.internal.R.styleable
                    .AndroidManifestApplication_persistentWhenFeatureAvailable);
                    if (requiredFeature == null || mCallback.hasFeature(requiredFeature)) {
                        // 將 persistent 的 flag 設(shè)置到應(yīng)用信息中
                        ai.flags |= ApplicationInfo.FLAG_PERSISTENT;
                    }
                }
                ....
    }
    ....
    
}

解析后就會將應(yīng)用的各種信息保存在PKMS中的一個存儲所有應(yīng)用信息的一個Map中,其中設(shè)置了persistent的應(yīng)用就包含了ApplicationInfo.FLAG_PERSISTENT標志位,之后在系統(tǒng)的啟動過程中就會根據(jù)這個標志位控制應(yīng)用的啟動。

persistent應(yīng)用的啟動

persistent應(yīng)用的啟動發(fā)生在AMSsystemReady方法內(nèi),這一部分通過PKMS獲取到所有persistent為true的應(yīng)用列表,之后對列表進行遍歷,通過addAppLocked方法將應(yīng)用一個個啟動起來。
對應(yīng)代碼的位于
/platform/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

public class ActivityManagerService extends IActivityManager.Stub
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
    ....
    // 該靜態(tài)常量用于判斷應(yīng)用是否persistent應(yīng)用
    private static final int PERSISTENT_MASK =
            ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT;
            
    // 當系統(tǒng)服務(wù)啟動時,AMS執(zhí)行systemReady方法
    public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {
            ....
            synchronized (this) {
                // 1.啟動所有persistent屬性為true的應(yīng)用
                startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE);
                ....
            }
            
    }
    ....
    void startPersistentApps(int matchFlags) {
        if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL) return;

        synchronized (this) {
            try {
                // 從PKMS的應(yīng)用MAP中拿到所有具有FLAG_PERSISTENT標志位的應(yīng)用
                final List<ApplicationInfo> apps = AppGlobals.getPackageManager()
                        .getPersistentApplications(STOCK_PM_FLAGS | matchFlags).getList();
                for (ApplicationInfo app : apps) {
                    // 過濾掉包名為android的應(yīng)用
                    if (!"android".equals(app.packageName)) {
                        //2. 添加并啟動該APP進程
                        addAppLocked(app, null, false, null /* ABI override */);
                    }
                }
            } catch (RemoteException ex) {
            }
        }
    }
            
}

獲得所有具有FLAG_PERSISTENT標志位的應(yīng)用

platform/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

public class PackageManagerService extends IPackageManager.Stub
        implements PackageSender {
    ....
    // 存放所有應(yīng)用的信息的Map
    final ArrayMap<String, PackageParser.Package> mPackages =
            new ArrayMap<String, PackageParser.Package>();
    ....
        
    @Override
    public @NonNull ParceledListSlice<ApplicationInfo> getPersistentApplications(int flags) {
        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
            return ParceledListSlice.emptyList();
        }
        return new ParceledListSlice<>(getPersistentApplicationsInternal(flags));
    }

    private @NonNull List<ApplicationInfo> getPersistentApplicationsInternal(int flags) {
        final ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();

        synchronized (mPackages) {
            final Iterator<PackageParser.Package> i = mPackages.values().iterator();
            final int userId = UserHandle.getCallingUserId();\
            // 遍歷mPackages
            while (i.hasNext()) {
                final PackageParser.Package p = i.next();
                if (p.applicationInfo == null) continue;

                ....
                // 判斷應(yīng)用信息是否有FLAG_PERSISTENT標志位
                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) {
                            // 將應(yīng)用的ApplicationInfo添加進列表
                            finalList.add(ai);
                        }
                    }
                }
            }
        }

        return finalList;
    }
}

添加并啟動應(yīng)用進程

AMS內(nèi)有一個存放所有正在啟動的persistent應(yīng)用ListmPersistentStartingProcesses,后續(xù)在啟動應(yīng)用重啟應(yīng)用時都會使用到該List。

public class ActivityManagerService extends IActivityManager.Stub
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
        
    /**
     * 正在啟動的persistent應(yīng)用程序列表。
     */
    final ArrayList<ProcessRecord> mPersistentStartingProcesses = new ArrayList<ProcessRecord>();
    
    ....
    final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated,
            String abiOverride) {
        return addAppLocked(info, customProcess, isolated, false /* disableHiddenApiChecks */,
                abiOverride);
    }
    
 final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated,
            boolean disableHiddenApiChecks, String abiOverride) {
        // ProcessRecord是用于描述進程的數(shù)據(jù)結(jié)構(gòu)
        ProcessRecord app;
        // 傳入的isolated為false
        if (!isolated) {
            // 第一次啟動,這里查找應(yīng)用所在的進程返回都為null
            app = getProcessRecordLocked(customProcess != null ? customProcess : info.processName,
                    info.uid, true);
        } else {
            app = null;
        }
        if (app == null) {
            // 為應(yīng)用創(chuàng)建ProcessRecord
            app = newProcessRecordLocked(info, customProcess, isolated, 0);
            updateLruProcessLocked(app, false, null);
            updateOomAdjLocked();
        }
        ....
        
        if ((info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
            app.persistent = true;
            app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
        }
        // 整個啟動過程是異步的,所以這里仍需要判斷應(yīng)用線程是否為null,同時判斷應(yīng)用是否正在啟動中(在mPersistentStartingProcesses列表內(nèi))
        if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
            // 應(yīng)用沒有在啟動,則將應(yīng)用添加到mPersistentStartingProcesses列表
            mPersistentStartingProcesses.add(app);
            // 啟動應(yīng)用
            startProcessLocked(app, "added application",
                    customProcess != null ? customProcess : app.processName, disableHiddenApiChecks,
                    abiOverride);
        }

        return app;
    }
    ....
}

系統(tǒng)啟動時應(yīng)用的ProcessRecord都未創(chuàng)建,所以在addAppLocked內(nèi)首先通過newProcessRecordLocked為應(yīng)用程序創(chuàng)建ProcessRecord,之后調(diào)用startProcessLocked來啟動應(yīng)用程序,啟動的過程不是這部分的重點,就不再詳細說明。

persistent應(yīng)用啟動完成

當應(yīng)用啟動完畢后就會調(diào)用到ActivityThread.java內(nèi)的attach方法,方法內(nèi)調(diào)用了AMSattachApplication方法,之后再到attachApplicationLocked,該方法內(nèi)部就會將應(yīng)用移除mPersistentStartingProcesses列表,表明應(yīng)用啟動完畢,同時為應(yīng)用并注冊一個死亡監(jiān)聽器AppDeathRecipient,用于應(yīng)用被異常殺死后的重啟。

public class ActivityManagerService extends IActivityManager.Stub
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
        ....    

        private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
            int pid, int callingUid, long startSeq) {
            ....
            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);
                //如果注冊死亡接收器失敗,也會重新啟動App進程
                startProcessLocked(app, "link fail", processName);
                return false;
            }
            ....
            // 將應(yīng)用移除正在啟動的持久性應(yīng)用列表
            mPersistentStartingProcesses.remove(app);
            ....
        }
}

persistent應(yīng)用死亡后重啟

當應(yīng)用被殺死后,就會調(diào)用死亡接收器AppDeathRecipientbinderDied方法,方法內(nèi)根據(jù)應(yīng)用是否是persistent應(yīng)用來控制是否重啟,整個流程如下:

public class ActivityManagerService extends IActivityManager.Stub
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
    ....   
    private final class AppDeathRecipient implements IBinder.DeathRecipient {
        final ProcessRecord mApp;
        final int mPid;
        final IApplicationThread mAppThread;

        AppDeathRecipient(ProcessRecord app, int pid,
                IApplicationThread thread) {
            mApp = app;
            mPid = pid;
            mAppThread = thread;
        }

        @Override
        public void binderDied() {
            synchronized(ActivityManagerService.this) {
                // 1. 調(diào)用appDiedLocked
                appDiedLocked(mApp, mPid, mAppThread, true);
            }
        }
    }
    
    final void appDiedLocked(ProcessRecord app, int pid, IApplicationThread thread,
            boolean fromBinderDied) {
        ....
        if (app.pid == pid && app.thread != null &&
                app.thread.asBinder() == thread.asBinder()) {
            ....
            // 2. 調(diào)用appDiedLocked
            handleAppDiedLocked(app, false, true);
            ....
        }
        ....
    }
    
    private final void handleAppDiedLocked(ProcessRecord app,
            boolean restarting, boolean allowRestart) {
        int pid = app.pid;
        // 3. 調(diào)用appDiedLocked
        boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1,
                false /*replacingPid*/);
        ....
    }
 
    private final boolean cleanUpApplicationRecordLocked(ProcessRecord app,
            boolean restarting, boolean allowRestart, int index, boolean replacingPid) {
        ....
        // 判斷應(yīng)用是否是persistent應(yīng)用
        if (!app.persistent || app.isolated) {
            // 如果不是persistent應(yīng)用,則直接被清理掉
            ....
        } else if (!app.removed) {
            // 如果是persistent應(yīng)用,則保留相應(yīng)的信息
            // 判斷其是否在待啟動應(yīng)用程序mPersistentStartingProcesses列表
            // 不在的話則添加,并設(shè)置restart為true
            if (mPersistentStartingProcesses.indexOf(app) < 0) {
                mPersistentStartingProcesses.add(app);
                restart = true;
            }
        }
        
        if (restart && !app.isolated) {
            // 重新啟動我們的應(yīng)用進程
            if (index < 0) {
                ProcessList.remove(app.pid);
            }
            addProcessNameLocked(app);
            app.pendingStart = false;
            // 啟動應(yīng)用程序進程
            startProcessLocked(app, "restart", app.processName);
            return true;
        } else if (app.pid > 0 && app.pid != MY_PID) {
            // 不需要重啟的應(yīng)用
            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);
        }
    }
}

經(jīng)過這個過程之后,persistent屬性為true的應(yīng)用程序進程就會被重啟。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容