日本搞逼视频_黄色一级片免费在线观看_色99久久_性明星video另类hd_欧美77_综合在线视频

國(guó)內(nèi)最全I(xiàn)T社區(qū)平臺(tái) 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2
您當(dāng)前位置:首頁(yè) > php開源 > 綜合技術(shù) > 說(shuō)說(shuō)Android應(yīng)用的persistent屬性

說(shuō)說(shuō)Android應(yīng)用的persistent屬性

來(lái)源:程序員人生   發(fā)布時(shí)間:2015-01-07 08:18:35 閱讀次數(shù):9243次

說(shuō)說(shuō)Android利用的persistent屬性

 

侯 亮

 

 

1 啟動(dòng)persistent利用

    在Android系統(tǒng)中,有1種永久性利用。它們對(duì)應(yīng)的AndroidManifest.xml文件里,會(huì)將persistent屬性設(shè)為true,比如:

<application android:name="PhoneApp" android:persistent="true" android:label="@string/dialerIconLabel" android:icon="@drawable/ic_launcher_phone">


    在系統(tǒng)啟動(dòng)之時(shí),AMS的systemReady()會(huì)加載所有persistent為true的利用。

public void systemReady(final Runnable goingCallback) { . . . . . . . . . . . . try{ List apps = AppGlobals.getPackageManager(). getPersistentApplications(STOCK_PM_FLAGS); if(apps != null) { intN = apps.size(); inti; for(i=0; i<N; i++) { ApplicationInfo info = (ApplicationInfo)apps.get(i); if(info != null&& !info.packageName.equals("android")) { addAppLocked(info,false); } } } } catch(RemoteException ex) { // pm is in same process, this will never happen. }

其中的STOCK_PM_FLAGS的定義以下:

// The flags that are set for all calls we make to the package manager. static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;


上面代碼中的getPersistentApplications()函數(shù)的定義以下:

public List<ApplicationInfo> getPersistentApplications(int flags) { final ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>(); // reader synchronized (mPackages) { final Iterator<PackageParser.Package> i = mPackages.values().iterator(); final int userId = UserId.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); finalList.add(PackageParser.generateApplicationInfo(p, flags, ps != null ? ps.getStopped(userId) : false, ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT, userId)); } } } return finalList; }

     在PKMS中,有1個(gè)記錄所有的程序包信息的哈希表(mPackages),每一個(gè)表項(xiàng)中含有ApplicationInfo信息,該信息的flags(int型)數(shù)據(jù)中有1個(gè)專門的bit用于表示persistent。getPersistentApplications()函數(shù)會(huì)遍歷這張表,找出所有persistent包,并返回ArrayList<ApplicationInfo>。


     從代碼里可以看出,帶persistent標(biāo)志的系統(tǒng)利用(即flags中設(shè)置了FLAG_SYSTEM)是1定會(huì)被選上的,但如果不是系統(tǒng)利用的話,則要進(jìn)1步判斷當(dāng)前是不是處于“安全模式”,1旦處于安全模式,那末就算利用設(shè)置了persistent屬性,也不會(huì)被選中。

     隨后systemReady()開始遍歷選中的ApplicationInfo,并對(duì)包名不為“android”的結(jié)點(diǎn)履行addAppLocked()。addAppLocked()的代碼以下:

<pre name="code" class="java">final ProcessRecord addAppLocked(ApplicationInfo info, boolean isolated) { ProcessRecord app; if (!isolated) { app = getProcessRecordLocked(info.processName, info.uid); } else { app = null; } if (app == null) { app = newProcessRecordLocked(null, info, null, isolated); mProcessNames.put(info.processName, app.uid, app); if (isolated) { mIsolatedProcesses.put(app.uid, app); } updateLruProcessLocked(app, true, true); } // This package really, really can not be stopped. try { AppGlobals.getPackageManager().setPackageStoppedState( info.packageName, false, UserId.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); } return app; }


?
    在AMS中,所謂的“add App”主要是指“添加1個(gè)與App進(jìn)程對(duì)應(yīng)的ProcessRecord節(jié)點(diǎn)”。固然,如果該節(jié)點(diǎn)已添加過(guò)了,那末是不會(huì)重復(fù)添加的。在添加節(jié)點(diǎn)的動(dòng)作完成以后,addAppLocked()還會(huì)檢查App進(jìn)程是不是已啟動(dòng)好了,如果還沒(méi)有開始啟動(dòng),此時(shí)就會(huì)調(diào)用startProcessLocked()啟動(dòng)這個(gè)進(jìn)程。既然addAppLocked()試圖確認(rèn)App“正在正常運(yùn)作”或“將被正常啟動(dòng)”,那末其對(duì)應(yīng)的package就不可能處于stopped狀態(tài),這就是上面代碼調(diào)用setPackageStoppedState(...,false,...)的意思。


    現(xiàn)在,我們就清楚了,那些persistent屬性為true的利用,基本上都是在系統(tǒng)啟動(dòng)伊始就啟動(dòng)起來(lái)的。

    由于啟動(dòng)進(jìn)程的進(jìn)程是異步的,所以我們需要1個(gè)緩沖列表(即上面代碼中的mPersistentStartingProcesses列表)來(lái)記錄那些“正處于啟動(dòng)狀態(tài),而又沒(méi)有啟動(dòng)終了的”ProcessRecord結(jié)點(diǎn)。1旦目標(biāo)進(jìn)程啟動(dòng)終了后,目標(biāo)進(jìn)程會(huì)attach系統(tǒng),因而走到AMS的attachApplicationLocked(),在這個(gè)函數(shù)里,會(huì)把目標(biāo)進(jìn)程對(duì)應(yīng)的ProcessRecord結(jié)點(diǎn)從mPersistentStartingProcesses緩沖列表里刪除。

private final boolean attachApplicationLocked(IApplicationThread thread, intpid) { // Find the application record that is being attached... either via // the pid if we are running in multiple processes, or just pull the // next app record if we are emulating process with anonymous threads. ProcessRecord app; . . . . . . thread.asBinder().linkToDeath(adr,0); . . . . . . thread.bindApplication(processName, appInfo, providers, app.instrumentationClass, profileFile, profileFd, profileAutoStop, app.instrumentationArguments, app.instrumentationWatcher, testMode, enableOpenGlTrace, isRestrictedBackupMode || !normalMode, app.persistent, newConfiguration(mConfiguration), app.compat, getCommonServicesLocked(), mCoreSettingsObserver.getCoreSettingsLocked()); . . . . . . . . . . . . // Remove this record from the list of starting applications. mPersistentStartingProcesses.remove(app); . . . . . .

?

2 如何保證利用的持久性(persistent)

    我們知道,persistent1詞的意思是“持久”,那末persistent利用的意思又是甚么呢?簡(jiǎn)單地說(shuō),這類利用會(huì)固執(zhí)地運(yùn)行于系統(tǒng)當(dāng)中,從系統(tǒng)1啟動(dòng),1直到系統(tǒng)關(guān)機(jī)。

    為了保證這類持久性,persistent利用必須能夠在異常出現(xiàn)時(shí),自動(dòng)重新啟動(dòng)。在Android里是這樣實(shí)現(xiàn)的。每一個(gè)ActivityThread中會(huì)有1個(gè)專門和AMS通訊的binder實(shí)體――final ApplicationThread mAppThread。這個(gè)實(shí)體在AMS中對(duì)應(yīng)的代理接口為IApplicationThread。

    當(dāng)AMS履行到attachApplicationLocked()時(shí),會(huì)針對(duì)目標(biāo)用戶進(jìn)程的IApplicationThread接口,注冊(cè)1個(gè)binder訃告監(jiān)聽(tīng)器,1旦往后用戶進(jìn)程意外掛掉,AMS就可以在第1時(shí)間感知到,并采取相應(yīng)的措施。如果AMS發(fā)現(xiàn)意外掛掉的利用是persistent的,它會(huì)嘗試重新啟動(dòng)這個(gè)利用。

    注冊(cè)訃告監(jiān)聽(tīng)器的代碼以下:

AppDeathRecipient adr = new AppDeathRecipient(app, pid, thread); thread.asBinder().linkToDeath(adr,0); app.deathRecipient = adr;

其中的thread就是IApplicationThread代理。

    AppDeathRecipient的定義以下:

private final class AppDeathRecipient implementsIBinder.DeathRecipient { final ProcessRecord mApp; final int mPid; final IApplicationThread mAppThread; AppDeathRecipient(ProcessRecord app, intpid, IApplicationThread thread) { if(localLOGV) Slog.v(TAG,"New death recipient " + this +" for thread " + thread.asBinder()); mApp = app; mPid = pid; mAppThread = thread; } publicvoidbinderDied() { if(localLOGV) Slog.v(TAG,"Death received in " + this +" for thread " + mAppThread.asBinder()); synchronized(ActivityManagerService.this) { appDiedLocked(mApp, mPid, mAppThread); } } }

當(dāng)其監(jiān)聽(tīng)的binder實(shí)體死亡時(shí),系統(tǒng)會(huì)回調(diào)AppDeathRecipient的binderDied()。這個(gè)回調(diào)函數(shù)會(huì)展轉(zhuǎn)重啟persistent利用,調(diào)用關(guān)系以下:



    1般情況下,當(dāng)1個(gè)利用進(jìn)程掛掉后,AMS固然會(huì)清算掉其對(duì)應(yīng)的ProcessRecord,這就是cleanUpApplicationRecordLocked()的主要工作。但是,對(duì)persistent利用,cleanUpApplicationRecordLocked()會(huì)嘗試再次啟動(dòng)對(duì)應(yīng)的利用進(jìn)程。代碼截選以下:

private final void cleanUpApplicationRecordLocked(ProcessRecord app, boolean restarting, boolean allowRestart,int index) { . . . . . . . . . . . . if (!app.persistent || app.isolated) { . . . . . . mProcessNames.remove(app.processName, app.uid); mIsolatedProcesses.remove(app.uid); . . . . . . } else if(!app.removed) { if(mPersistentStartingProcesses.indexOf(app) < 0) { mPersistentStartingProcesses.add(app); restart = true; } } . . . . . . . . . . . . if (restart && !app.isolated) { mProcessNames.put(app.processName, app.uid, app); startProcessLocked(app,"restart", app.processName); } else if(app.pid > 0&& app.pid != MY_PID) { . . . . . . } . . . . . . }

    現(xiàn)在我們可以畫1張關(guān)于“啟動(dòng)persistent利用”的示意圖:


 

3 補(bǔ)充知識(shí)點(diǎn)

3.1 persistent利用可以在系統(tǒng)未準(zhǔn)備好時(shí)啟動(dòng)

    在AMS中,有1個(gè)isAllowedWhileBooting()函數(shù),其代碼以下:

boolean isAllowedWhileBooting(ApplicationInfo ai) { return (ai.flags & ApplicationInfo.FLAG_PERSISTENT) != 0; }

    從這個(gè)函數(shù)可以看到,將persistent屬性設(shè)為true的利用,是允許在boot的進(jìn)程中啟動(dòng)的。我們可以查看前文提到的startProcessLocked()函數(shù):

final ProcessRecord startProcessLocked(String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName, boolean allowWhileBooting, boolean isolated) { ProcessRecord app; if(!isolated) { app = getProcessRecordLocked(processName, info.uid); } else { // If this is an isolated process, it can't re-use an existing process. app = null; } . . . . . . . . . . . . if(!mProcessesReady && !isAllowedWhileBooting(info) && !allowWhileBooting) { if(!mProcessesOnHold.contains(app)) { mProcessesOnHold.add(app); } if(DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app); return app; } startProcessLocked(app, hostingType, hostingNameStr); return (app.pid != 0) ? app : null; }

?

其中的最后幾句可以改寫為以下更容易理解的情勢(shì):

if (mProcessesReady || isAllowedWhileBooting(info) || allowWhileBooting) { startProcessLocked(app, hostingType, hostingNameStr); return (app.pid != 0) ? app : null; } else { . . . . . . returnapp; }

?

    也就是說(shuō),當(dāng)系統(tǒng)已處于以下幾種情況時(shí),多參數(shù)的startProcessLocked()會(huì)進(jìn)1步調(diào)用另外一個(gè)只有3個(gè)參數(shù)的startProcessLocked():
1)系統(tǒng)已處于ready狀態(tài);
2)想要啟動(dòng)persistent利用;
3)參數(shù)中明確指定可以在boot進(jìn)程中啟動(dòng)利用。

    補(bǔ)充說(shuō)1下,1般情況下,當(dāng)AMS調(diào)用startProcessLocked()時(shí),傳入的allowWhileBooting參數(shù)都為false。比如說(shuō),當(dāng)系統(tǒng)需要啟動(dòng)“某個(gè)content provider或某個(gè)service或某個(gè)特定activity”時(shí),此時(shí)傳給startProcessLocked()的allowWhileBooting參數(shù)是寫死為false的。只有1種特殊情況下會(huì)在該參數(shù)中傳入true,那就是當(dāng)系統(tǒng)發(fā)出的廣播intent中攜帶有Intent.FLAG_RECEIVER_BOOT_UPGRADE標(biāo)記時(shí),此時(shí)允許在系統(tǒng)未ready時(shí),啟動(dòng)接受廣播的目標(biāo)進(jìn)程。

4 結(jié)束

    有關(guān)Android利用的persistent屬性,我們就先說(shuō)這么多。希望對(duì)大家有點(diǎn)兒幫助。

生活不易,碼農(nóng)辛苦
如果您覺(jué)得本網(wǎng)站對(duì)您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈(zèng)
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關(guān)閉
程序員人生
主站蜘蛛池模板: 欧美一区二区在线看 | 国产午夜视频在线观看 | www.久久精品| 一区日韩 | 日韩一区二区三 | 国产成人影院 | 日韩一级精品 | 欧美高清dvd | 久热国产精品 | 久久久久久国产精品久久 | 一本一本久久a久久精品综合小说 | 首页 国产 欧美 日韩 丝袜 | 中文字幕精品一区二区三区精品 | 国产日韩一区二区三区 | 精品成人av| 亚洲精品国产一区 | 亚洲欧美在线视频 | 国产在线网 | 爱情岛论坛成人av | 欧美日韩国产大片 | 国产精品18hdxxxⅹ在线 | 黄色带一级片 | 麻豆精品国产传媒mv男同 | 一区二区三区在线免费视频 | 日韩视频久久 | 一级毛片视频在线 | 91久久精品一区二区二区 | 精品成人一区 | 天天天天操 | 一区二区三区国产 | 国产精品成人国产乱一区 | 日韩精品久久久久久 | 在线国产精品视频 | 99视频一区 | 久草美女视频 | 中文激情网 | 日韩av中文在线 | 亚洲精品综合 | 国产成人免费视频 | 91精品久久久久久久99软件 | 福利四区 |