国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁 > news >正文

上海app網(wǎng)站開發(fā)價值信息發(fā)布平臺推廣有哪些

上海app網(wǎng)站開發(fā)價值,信息發(fā)布平臺推廣有哪些,東莞市網(wǎng)站建設(shè)平臺,wordpress 代碼編寫戳藍(lán)字“牛曉偉”關(guān)注我哦! 用心堅持輸出易讀、有趣、有深度、高質(zhì)量、體系化的技術(shù)文章,技術(shù)文章也可以有溫度。 前言 閱讀該篇之前,建議先閱讀下面的系列文章: Android深入理解包管理–PackageManagerService和它的“小伙伴…

戳藍(lán)字“牛曉偉”關(guān)注我哦!

用心堅持輸出易讀、有趣、有深度、高質(zhì)量、體系化的技術(shù)文章,技術(shù)文章也可以有溫度。

前言

閱讀該篇之前,建議先閱讀下面的系列文章:

Android深入理解包管理–PackageManagerService和它的“小伙伴”

Android深入理解包管理–記錄存儲模塊

Android深入理解包管理–共享庫模塊

Android深入理解包管理—apk信息

本文摘要

這是包管理系列的最后一篇文章,本文的標(biāo)題是從上帝視角來看PackageManagerService,為啥要起這么“狂妄”的名字呢?其主要的原因是我希望從一個更全面、更高的、更清晰的視角來看明白PackageManagerService的每個模塊之間是如何協(xié)作來保證PackageManagerService的關(guān)鍵工作順利完成。通過本文您將了解到PackageManagerService被劃分為哪些模塊模塊之間是如何協(xié)作來保證各項工作的順利完成。(文中代碼基于Android13)

本文大綱

1. 模塊的劃分

2. 模塊的啟動

3. 模塊相互協(xié)作守護(hù)apk的安裝

4. 模塊相互協(xié)作守護(hù)app的運行

5. 總結(jié)

1. 模塊劃分

其實在Android深入理解包管理–PackageManagerService和它的“小伙伴”

這篇文章已經(jīng)介紹過PackageManagerService的各個模塊了,但是我還是希望把它們重新“請”出來,以保證后面的內(nèi)容能順利連接起來。(當(dāng)然增加了快照管理模塊)

先簡單介紹下PackageManagerService,它是運行于systemserver進(jìn)程,systemserver進(jìn)程中有很多很多的服務(wù),比如大家熟知的ActivityManagerService、WindowManagerService。而PackageManagerService也是一個服務(wù),一個非常非常重要的服務(wù)。

下圖展示了PackageManagerService的幾個關(guān)鍵模塊

主要模塊有apk管理模塊、權(quán)限管理模塊共享庫模塊、記錄存儲模塊所有apk信息模塊、四大組件模塊PackageManagerService不可能只有上面的幾個模塊,它還有快照模塊、對外接口模塊、property模塊等,只不過上面的模塊較常見。

1.1 權(quán)限管理模塊

既然是權(quán)限管理模塊,那有必要先來介紹下權(quán)限,權(quán)限分為聲明權(quán)限請求權(quán)限

1.1.1 聲明權(quán)限

聲明權(quán)限需要在AndroidManifest.xml文件中使用permission標(biāo)簽,如下例子:

<permission android:description="string resource"android:icon="drawable resource"android:label="string resource"android:name="string"android:permissionGroup="string"android:protectionLevel=["normal" | "dangerous" |"signature" | ...] />

每個apk都可以聲明自己的權(quán)限,那當(dāng)別的apk訪問自己的一些關(guān)鍵信息時候就可以要求它具有某個聲明的權(quán)限后才可以訪問。

1.1.2 請求權(quán)限

請求權(quán)限就是在AndroidManifest中通過uses-permission標(biāo)簽來使用權(quán)限,如下代碼:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

1.1.3 權(quán)限管理模塊所做的事情

權(quán)限管理模塊所做的事情如下:

  1. 把所有的apk聲明的權(quán)限收集并集中管理起來
  2. 保存每個apk請求的權(quán)限和請求權(quán)限對應(yīng)的狀態(tài),請求權(quán)限對應(yīng)的狀態(tài)是指比如某個apk的請求的權(quán)限是否被允許、是否拒絕是否只是允許一次
  3. 處理apk權(quán)限請求,當(dāng)用戶不管是點擊了允許、拒絕等,都需要經(jīng)過權(quán)限管理模塊

權(quán)限管理模塊把上面這些事情全權(quán)交給了PermissionManagerService服務(wù)來處理,關(guān)于權(quán)限管理后面會有系列文章來介紹。

1.2 共享庫模塊

同樣先來簡單介紹下共享庫,共享庫首先它是一個,庫大家肯定非常熟悉了,庫可以是一個jar文件 (jar包代表java庫) 也可以是一個so文件 (so是二進(jìn)制可執(zhí)行文件代表native庫),而它的形容詞共享代表該庫是可以被多個程序使用的。共享庫也就是可以被多個程序使用的庫。在Android中共享庫除了上面的意思之外,還要再加一條就是共享庫是由系統(tǒng)提供的可以被多個程序使用的系統(tǒng)庫,在Android中共享庫可以是一個jar、so、apk文件。

共享庫也同樣分為聲明共享庫使用共享庫,只有系統(tǒng)apk才能聲明共享庫。

共享庫模塊所做的事情如下:

  1. 把所有聲明的共享庫收集起來,若共享庫之間存在依賴,則把它們的依賴也初始化
  2. 若apk中使用了某個共享庫,則會根據(jù)共享庫名稱、版本信息共享庫模塊把共享庫的信息查詢出來 (如共享庫文件路徑) 交給該apk

共享庫模塊把這些事情交給了SharedLibrariesImpl類來處理,關(guān)于共享庫模塊的詳細(xì)介紹可以看Android深入理解包管理–共享庫模塊
這篇文章。

1.3 記錄存儲模塊

記錄存儲模塊的主要工作是記錄apk的安裝及附加信息并且把這些信息存儲到文件中。也就是要想知道Android設(shè)備上有沒有安裝某個apk,是可以從記錄存儲模塊得知的。如果apk安裝了,則記錄存儲模塊會把安裝信息記錄下來。

關(guān)于該模塊的詳細(xì)介紹可以看
Android深入理解包管理–記錄存儲模塊

這篇文章

1.4 所有apk信息模塊

apk信息指的是apk的AndroidManifest.xml文件中配置的各種信息,比如apk版本信息、apk包名、聲明了哪些四大組件、使用了哪些權(quán)限、聲明了哪些權(quán)限、使用了哪些共享庫等。

安裝在Android設(shè)備上的apk (系統(tǒng)apk和非系統(tǒng)apk),都需要把它們的apk信息存儲到內(nèi)存中,以供使用者來查詢 (比如某使用者想要根據(jù)包名知道某個apk的ApplicationInfo信息),而存放所有apk信息的地方被稱為所有apk信息模塊。關(guān)于apk信息的詳細(xì)介紹可以看
Android深入理解包管理—apk信息
這篇文章。

下面是所有apk信息模塊在PackageManagerService中屬性的聲明:

//下面屬性位于PackageManagerService類//key是包名,而AndroidPackage存儲了解析出的AndroidManifest的信息
final WatchedArrayMap<String, AndroidPackage> mPackages = new WatchedArrayMap<>();

1.5 四大組件模塊

四大組件模塊在內(nèi)存中存儲了所有已安裝apk的AndroidManifest中聲明的四大組件,四大組件模塊的事情是完全交給了ComponentResolver類。

常用于以下場景:

  1. ActivityTaskManagerService啟動某個Activity時,需要從我這獲取對應(yīng)的Activity信息,獲取到則返回;否則啟動Activity失效
  2. ActivityManagerService啟動某個Service時,也需要從我這獲取對應(yīng)的Service信息。同理啟動某個BroadcastReceiver、ContentProvider也需要從我哦這獲取對應(yīng)的信息

下面是四大組件模塊在PackageManagerService中屬性的聲明:

//下面屬性位于PackageManagerService類final ComponentResolver mComponentResolver;

1.6 apk管理模塊

apk管理模塊從上圖可以看出它在所有模塊中的地位是多么重要,它包含的功能有掃描所有apk、apk安裝/更新/卸載、解析apk
在后面會詳細(xì)介紹到它。對apk安裝感興趣可以查看apk安裝之謎這篇文章。

1.7 快照管理模塊

快照 (snapshot)可以理解為是數(shù)據(jù)的拷貝,在PackageManagerService的各個模塊以及各個模塊的屬性中都充斥著快照,如下部分代碼:

//Settings類//獲取Settings的快照
public Settings snapshot() {return mSnapshot.snapshot();
}private Settings(Settings r) {//Settings的很多屬性也都有自己的快照mPackages = r.mPackagesSnapshot.snapshot();mPackagesSnapshot  = new SnapshotCache.Sealed<>();mKernelMapping = r.mKernelMappingSnapshot.snapshot();mKernelMappingSnapshot = new SnapshotCache.Sealed<>();省略其他代碼······// Do not register any Watchables and do not create a snapshot cache.mSnapshot = new SnapshotCache.Sealed();
}

上面代碼只是截取了Settings (記錄存儲模塊)和它的屬性相關(guān)的快照,其他的各個模塊和屬性也都有相應(yīng)的快照。我剛開始看PackageManagerService代碼的時候,就被各種各樣的快照震驚了,為啥要有快照呢,它的作用是啥呢?

快照的作用就是為了快速的檢索數(shù)據(jù),大家都知道PackageManagerService中有各種各樣的數(shù)據(jù),并且數(shù)據(jù)量都很大,為了保持?jǐn)?shù)據(jù)的一致性,在更新/添加/刪除/訪問這些數(shù)據(jù)的時候是都加了各種各樣的的,而如果沒有快照的話,比如在訪問這些數(shù)據(jù)的時候是需要獲取相應(yīng)的鎖,如果沒有獲取到則需要等待,想想這個過程是非常影響查詢速度的。

那為了解決以上問題快照就誕生了,每個模塊及相關(guān)屬性都有自己快照也就是拷貝,那當(dāng)訪問這些數(shù)據(jù)的時候就從快照中直接獲取這速度是不是提升了很多 (其實就是以空間換時間罷了)。那當(dāng)模塊或者相關(guān)屬性的數(shù)據(jù)發(fā)生變化了會做何種處理呢?答案是發(fā)生變化的模塊或?qū)傩灾匦律勺约旱目煺铡?/p>

快照管理模塊很顯然就是管理了所有的快照,而它對應(yīng)的是Computer類,該類是一個接口,它的實現(xiàn)類是ComputerEngine快照管理模塊還有另外一個作用就是各種數(shù)據(jù)的代理者,PackageManagerService它是一個binder server,它的使用者可以通過binder通信的方式從它獲取各種數(shù)據(jù),而獲取的各種數(shù)據(jù)都是先要經(jīng)過快照管理模塊,而快照管理模塊把各種快照數(shù)據(jù)組裝起來返回給使用方。

PackageManagerService的快照Computer是最頂級的快照,它包含了各個模塊的快照,而每個模塊的快照又包含了自己相關(guān)屬性的快照。那當(dāng)某個模塊或者模塊屬性發(fā)生變化的時候,該變化信息會傳遞到PackageManagerServicePackageManagerService開始重新收集所有的快照,收集過程只要相應(yīng)的快照沒有發(fā)生變化,則依然使用它,否則重新生成快照。

關(guān)于快照管理模塊先暫時介紹到這。

1.8 小結(jié)

那簡單總結(jié)下各個模塊:

  1. 權(quán)限管理模塊負(fù)責(zé)apk權(quán)限相關(guān)的事情,比如請求某個權(quán)限,apk權(quán)限狀態(tài)存儲,收集所有apk聲明的權(quán)限
  2. 共享庫模塊負(fù)責(zé)apk使用到的所有共享庫
  3. 記錄存儲模塊會把apk相關(guān)的很多信息記錄并且存儲到文件中,比如apk安裝后關(guān)于apk安裝的信息會存儲下來,這樣就可以供其他使用者檢索
  4. 所有apk信息模塊會收集所有已安裝apk的AndroidManifest解析出來的信息,以供其他使用者檢索
  5. 四大組件模塊為了加快檢索四大組件的速度,會把所有已安裝apk的四大組件信息收集起來
  6. apk管理模塊主要負(fù)責(zé)apk的安裝/卸載/更新,它是根基模塊,因為它的某個功能會對其他模塊產(chǎn)生影響。
  7. 快照管理模塊主要目的為加快訪問PackageManagerService中的各種數(shù)據(jù)。

2. 模塊的啟動

在Android深入理解包管理–PackageManagerService和它的“小伙伴”
中介紹過模塊的啟動,但是我覺得介紹的有些“潦草”,故在此更詳細(xì)的介紹下。

模塊的啟動主要是想展示給大家,在PackageManagerService的啟動過程中,各個模塊的啟動都做了啥?為啥要這樣做?

下圖展示了PackageManagerService在啟動過程中,每個模塊所做的事情:

前幾個模塊的啟動,其實都在為掃描所有apk做準(zhǔn)備,而掃描所有apk是PackageManagerService啟動過程中做的非常重要的一件事情,如果不掃描所有apk,那PackageManagerService就完全不知道當(dāng)前Android設(shè)備上所有已安裝apk的具體apk信息 (apk信息指的是apk的AndroidManifest.xml文件中配置的各種信息如apk版本信息、apk包名、聲明了哪些四大組件等),不知道具體apk信息PackageManagerService猶如一個廢掉的服務(wù),不能提供任何有用的服務(wù)。

2.1 共享庫模塊啟動

共享庫分為內(nèi)置共享庫聲明的共享庫

內(nèi)置共享庫很容易理解就是系統(tǒng)內(nèi)置的共享庫,內(nèi)置共享庫可以理解為靜態(tài)的,因為它們的信息被讀取到內(nèi)存后是不會發(fā)生變化的。

而聲明的共享庫指由系統(tǒng)apk聲明的共享庫。而聲明的共享庫可以理解為是動態(tài)的,apk聲明了共享庫后,聲明的共享庫有可能被刪除 (該apk被刪除了后者apk刪除了該共享庫),也有可能被升級 (apk聲明的共享庫升級了)等。

正因為內(nèi)置共享庫和聲明的共享庫分別是靜態(tài)的動態(tài)的,也就導(dǎo)致內(nèi)置共享庫信息是可以提前從文件中讀取到內(nèi)存中,而聲明的共享庫它是動態(tài)的,它的任何變化都會影響到它的使用者,因此聲明的共享庫是不會存儲在文件中的,需要在掃描所有apk階段重新收集。

共享庫模塊的啟動主要的工作是初始化內(nèi)置共享庫,共享庫模塊作為PackageManagerService啟動的第一個模塊,提前啟動的主要原因是為掃描所有apk做準(zhǔn)備的,在掃描所有apk的時候有可能某個apk使用了某個內(nèi)置共享庫,那這時候肯定需要從共享庫模塊查出該共享庫的信息,因此共享庫模塊的啟動要放在前面。

關(guān)于共享庫模塊可以查看共享庫模塊這篇文章

下面是相關(guān)代碼,自行取閱:

//下面代碼位于PackageManagerService構(gòu)造方法中//從 SystemConfig.getInstance() 中把所有的內(nèi)置共享庫信息讀取出來ArrayMap<String, SystemConfig.SharedLibraryEntry> libConfig = systemConfig.getSharedLibraries();final int builtInLibCount = libConfig.size();for (int i = 0; i < builtInLibCount; i++) {//依次把共享庫信息添加到 mSharedLibraries 中mSharedLibraries.addBuiltInSharedLibraryLPw(libConfig.valueAt(i)); }long undefinedVersion = SharedLibraryInfo.VERSION_UNDEFINED;//下面代碼處理共享庫之間的依賴for (int i = 0; i < builtInLibCount; i++) {String name = libConfig.keyAt(i);SystemConfig.SharedLibraryEntry entry = libConfig.valueAt(i);final int dependencyCount = entry.dependencies.length;for (int j = 0; j < dependencyCount; j++) {final SharedLibraryInfo dependency =computer.getSharedLibraryInfo(entry.dependencies[j], undefinedVersion);if (dependency != null) {computer.getSharedLibraryInfo(name, undefinedVersion).addDependency(dependency);}}}

2.2 記錄存儲模塊啟動

記錄存儲模塊它的主要作用是把記錄已安裝apk、記錄所有apk聲明的權(quán)限等,其中記錄已安裝apk的信息包括apk的版本號、apk的包名、apk文件路徑、apk的appid、apk簽名信息、apk請求權(quán)限及權(quán)限狀態(tài)等。也就是可以從記錄存儲模塊知道哪個apk安裝了,apk安裝信息都有哪些等。

記錄存儲模塊啟動主要的工作就是從已經(jīng)存儲的文件中把存儲的信息讀取出來交給對應(yīng)的數(shù)據(jù)類 (PackageSetting),這樣就可以知道安裝了哪些apk了。

記錄存儲模塊提前啟動的主要原因除了為掃描所有apk做準(zhǔn)備,還為權(quán)限管理模式初始化做準(zhǔn)備,在掃描所有apk的時候肯定是需要知道某個系統(tǒng)apk是否已經(jīng)安裝,已經(jīng)安裝的話就需要用新apk與老apk進(jìn)行一些比較 (比如簽名信息是否一致)。為啥只是針對某個系統(tǒng)apk,因為普通apk的安裝只能通過正常的用戶手動觸發(fā),而系統(tǒng)apk的安裝是在掃描階段進(jìn)行的。

關(guān)于記錄存儲模塊可以看
記錄存儲模塊
這篇文章

下面是相關(guān)代碼,自行取閱:

//下面代碼位于PackageManagerService構(gòu)造方法中//從 /data/system/packages.xml及其他文件中把保存的數(shù)據(jù)讀出來
mFirstBoot = !mSettings.readLPw(computer,  mInjector.getUserManagerInternal().getUsers(/* excludePartial= */ true,/* excludeDying= */ false,/* excludePreCreated= */ false));

2.3 權(quán)限管理模塊初始化

權(quán)限分為聲明權(quán)限使用權(quán)限,不管是apk聲明的權(quán)限還是apk使用的權(quán)限都是在記錄存儲模塊中存儲著的,當(dāng)記錄存儲模塊啟動的時候,這些信息都會被讀取出來交給對應(yīng)的數(shù)據(jù)類。

權(quán)限管理模塊初始化就是使用記錄存儲模塊讀取到的權(quán)限信息來初始自己,初始化完畢后就可以從權(quán)限管理模塊知道所有apk都聲明了哪些權(quán)限,并且可以知道哪些apk使用了哪些權(quán)限,權(quán)限狀態(tài)是啥 (拒絕、允許等)。

權(quán)限管理模塊初始化的主要原因同樣也是為了掃描所有apk做準(zhǔn)備,關(guān)于權(quán)限管理模塊后面有相關(guān)系列文章介紹。

下面是相關(guān)代碼,自行取閱:

//下面代碼位于PackageManagerService構(gòu)造方法中//把所有apk聲明的權(quán)限交給mPermissionManager
mPermissionManager.readLegacyPermissionsTEMP(mSettings.mPermissions); 
//下面方法會使用每個apk的權(quán)限狀態(tài)初始化自己
mPermissionManager.readLegacyPermissionStateTEMP();

2.4 掃描所有apk

掃描所有apk是歸apk管理模塊,上面一直都在提掃描所有apk,它是PackageManagerService啟動過程中最重要的事情沒有之一。為啥要叫掃描apk呢?

其實掃描apk是屬于安裝apk中的重要環(huán)節(jié),掃描apk對于系統(tǒng)apk的話是一個安裝或者升級的過程,對于普通apk來說就是一個“查漏補缺”的過程 (比如某個系統(tǒng)apk把聲明的某個共享庫刪除了,則使用了該共享庫的apk就需要做調(diào)整)。掃描apk所做的主要事情如下:

  1. 把apk信息從AndroidManifest文件中解析出來
  2. 在依據(jù)解析出來的apk信息,去記錄存儲模塊查詢該apk是否已經(jīng)安裝,若安裝的話進(jìn)行升級方面的操作 (比如新老apk進(jìn)行版本比較);若沒有安裝則進(jìn)行安裝方面的操作,比如為apk創(chuàng)建data目錄等。
  3. 如果apk中AndroidManifest文件中的權(quán)限發(fā)生了則會通知權(quán)限管理模塊進(jìn)行增加/刪除/更新對應(yīng)權(quán)限;如果apk中聲明了共享庫 (只有系統(tǒng)apk才可以聲明共享庫),則會通知共享庫模塊增加相應(yīng)的共享庫等操作。
  4. 解析出來的apk信息經(jīng)過步步驗證后,最終會存放在所有apk信息模塊四大組件模塊,這樣就可以供其他使用者使用了。

掃描apk最終的結(jié)果就是apk信息經(jīng)過重重校驗,apk信息最終存放在所有apk信息模塊和四大組件模塊,這樣使用者就可以使用這些信息了,比如startActivity的時候ActivityTaskManagerService會從四大組件模塊中拿到Activity的信息。同時掃描apk也會或多或少的影響到權(quán)限管理模塊、共享庫模塊、記錄存儲模塊。(到達(dá)如何影響的會在下面apk安裝環(huán)節(jié)介紹)

掃描所有apk分為掃描所有系統(tǒng)apk掃描所有普通apk,先進(jìn)行掃描所有系統(tǒng)apk,后進(jìn)行掃描所有普通apk,為啥是這樣的順序呢?原因是這樣的只有系統(tǒng)apk才能聲明共享庫,因此需要先把所有的系統(tǒng)apk都掃描完后,共享庫模塊才能把所有聲明的共享庫收集起來,供普通apk來使用。

存放系統(tǒng)apk的目錄主要是位于productvendor、systemsystem_ext、apex分區(qū)下的overlay、app、priv-appframework目錄 (若在分區(qū)下存在相應(yīng)的目錄),而位于priv-app目錄下的apk是擁有特權(quán)的系統(tǒng)apk,這里的特權(quán)是具有特殊權(quán)限的簡稱。存放普通apk的目錄是data分區(qū)的app目錄下。

掃描所有apk先掃描存放系統(tǒng)apk的目錄,再掃描存放普通apk的目錄,如下相關(guān)代碼:

//下面代碼位于PackageManagerService構(gòu)造方法中final int[] userIds = mUserManager.getUserIds();
//packageParser的作用是解析apk
PackageParser2 packageParser = mInjector.getScanningCachingPackageParser();
//掃描系統(tǒng)apk
mOverlayConfig = mInitAppsHelper.initSystemApps(packageParser, packageSettings, userIds,startTime); 
//掃描非系統(tǒng)apk
mInitAppsHelper.initNonSystemApps(packageParser, userIds, startTime); 
packageParser.close();

2.5 共享庫模塊再度登場

掃描所有apk是先掃描所有系統(tǒng)apk,然后在掃描所有普通apk。而在掃描所有系統(tǒng)apk的時候是沒有把系統(tǒng)apk中使用共享庫信息補全的 (如果該系統(tǒng)apk確實使用了某個共享庫)。

先來解釋下啥叫共享庫信息補全,比如某系統(tǒng)apk在AndroidManifest.xml文件中使用uses-library標(biāo)簽使用了某個共享庫,共享庫信息補全就是從共享庫模塊把該apk使用的共享庫信息 (共享庫文件路徑、名稱等)查詢出來,并且交給該apk。

那為啥沒有把系統(tǒng)apk中使用共享庫信息補全呢?其主要原因還是因為只有系統(tǒng)apk才能聲明共享庫,比如正在掃描某個系統(tǒng)apk,而它使用的共享庫對應(yīng)的系統(tǒng)apk還沒有被掃描,則這時候該系統(tǒng)apk的共享庫就沒有補全。那針對這種情況該咋辦呢?辦法就是在掃描完所有apk后,在去把所有系統(tǒng)apk中使用的共享庫信息一起補全 (如果該系統(tǒng)apk確實使用了某個共享庫)。

下面是相關(guān)代碼,請自行取閱:

//下面代碼位于PackageManagerService構(gòu)造方法中//下面方法會把所有apk的共享庫信息補全 ((如果該apk確實使用了某個共享庫)
mSharedLibraries.updateAllSharedLibrariesLPw(null, null, Collections.unmodifiableMap(mPackages)); 

2.6 小結(jié)

共享庫模塊記錄存儲模塊、權(quán)限管理模塊三個模塊的啟動為掃描所有apk做準(zhǔn)備,而掃描所有apk又分為掃描所有系統(tǒng)apk和掃描所有普通apk,掃描所有apk最終的結(jié)果是所有apk信息最終存放在了所有apk信息模塊四大組件模塊,這樣使用者就可以從PackageManagerService獲取到某個apk的信息了,比如獲取某個Activity的信息。

而掃描所有apk也會或多或少的影響共享庫模塊、記錄存儲模塊、權(quán)限管理模塊,比如掃描某個系統(tǒng)apk,該系統(tǒng)apk聲明了新的權(quán)限、聲明了新的共享庫,則會把聲明的共享庫信息記錄在共享庫模塊,而聲明的權(quán)限則會通知權(quán)限管理模塊增加此權(quán)限,同時記錄存儲模塊也會把該權(quán)限存儲到文件中。

3. 模塊相互協(xié)作守護(hù)apk的安裝

本節(jié)主要想介紹模塊之間的相互協(xié)作來守護(hù)apk的安裝,先假設(shè)要安裝的apk,在它的AndroidManifest.xml文件中聲明了權(quán)限、使用了某個權(quán)限、使用了某個共享庫、聲明了四大組件

下圖展示了安裝該apk的過程
image

那結(jié)合上圖來進(jìn)行介紹。

3.1 apk的安裝

apk的安裝首先需要把要安裝的apk拷貝到/data/app目錄下,首先先從AndroidManifest.xml中把apk的基礎(chǔ)信息 (apk包名、版本號、簽名信息等)解析出來;其次使用解析出來的基礎(chǔ)信息進(jìn)行apk完整性驗證,主要驗證apk有沒有被改過;當(dāng)然還有其他的步驟如果已經(jīng)安裝了該apk,則需要驗證新老apk的版本信息,還需要驗證新老apk的簽名信息是不是一致;這些步驟都驗證通過后,會從AndroidManifest.xml中把apk的所有信息 (四大組件、權(quán)限等等) 都解析出來;最后會使用apk信息經(jīng)過準(zhǔn)備、掃描、調(diào)和、提交階段來保證apk最后的安裝完成。

上面只是簡單的介紹了apk的安裝過程,關(guān)于apk安裝更詳細(xì)的介紹可以看apk安裝之謎這篇文章。

3.2 各模塊協(xié)作

apk安裝的提交階段會做以下事情:

  1. 該apk的安裝信息 (apk包名、版本信息、apk文件路徑、appid、聲明和使用的權(quán)限等) 以PackageSetting對象添加到記錄存儲模塊,記錄存儲模塊會把所有的PackageSetting對象重新寫入到文件中
  2. 該apk信息 (apk包名、聲明的四大組件、版本信息、解析的權(quán)限等) 添加到所有apk信息模塊
  3. 該apk信息中的聲明的四大組件信息添加到四大組件模塊
  4. 因為該apk使用了某個共享庫,則會從共享庫模塊把該共享庫信息查詢出來交給PackageSetting對象
  5. 因為該apk聲明和使用了權(quán)限,則聲明和使用的權(quán)限會被添加到權(quán)限管理模塊。

注:對PackageSetting陌生,可以看下Android深入理解包管理–記錄存儲模塊

這篇文章

3.3 apk安裝最后一步

apk安裝的最后一步就是創(chuàng)建data目錄dex優(yōu)化。創(chuàng)建data目錄這樣app在運行的時候就可以把私有數(shù)據(jù)存儲在該目錄下,dex優(yōu)化可以讓app運行更快。

3.4 小結(jié)

apk的安裝過程,小結(jié)如下:

  1. 會在記錄存儲模塊存儲下該apk的安裝信息 (apk包名、appid、apk路徑等)、聲明的權(quán)限 (若聲明了權(quán)限)、使用的權(quán)限及狀態(tài) (若使用了權(quán)限),并且會把這些信息寫入文件
  2. apk信息會存放在所有apk信息模塊
  3. apk聲明的四大組件會存放在四大組件模塊
  4. apk的權(quán)限 (若聲明了權(quán)限或者使用了權(quán)限)會存放在 權(quán)限管理模塊

4. 模塊相互協(xié)作守護(hù)app的運行

上面介紹了模塊之間的相互協(xié)作守護(hù)apk的安裝,那現(xiàn)在咱們來看下模塊之間相互協(xié)作來保證app的運行。

大家都知道一個app開始運行,可以通過啟動一個Activity或者啟動一個Service或者啟動一個ContentProvider或者啟動一個BroadcastReceiver。那我就用啟動一個Activity,來看PackageManagerService的各個模塊是如何守護(hù)app運行的,這個過程用到的模塊主要有快照管理模塊所有apk信息模塊、四大組件模塊、記錄存儲模塊*這四個模塊,那就從這三個模塊講起。

4.1 快照管理模塊

在啟動一個Activity的時候,ActivityTaskManagerService會通過Intent信息從PackageManagerService服務(wù)查詢該Intent對應(yīng)的Activity信息 (該信息會被封裝為ActivityInfo對象),而該查詢?nèi)蝿?wù)PackageManagerService會交給快照管理模塊。

下面是相關(guān)代碼,自行取閱:

//ComputerEngine類public final @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags,@PackageManagerInternal.PrivateResolveFlags long privateResolveFlags,int filterCallingUid, int userId, boolean resolveForStart,boolean allowDynamicSplits) {省略代碼······}

4.2 四大組件模塊

快照管理模塊是沒有真正的查詢服務(wù)的,而真正的查詢Activity信息需要從四大組件模塊獲取,四大組件模塊會根據(jù)Intent中的ComponentName查詢到相應(yīng)的Activity信息。

如下是相關(guān)代碼:

//ComputerEngine類protected ActivityInfo getActivityInfoInternalBody(ComponentName component,@PackageManager.ResolveInfoFlagsBits long flags, int filterCallingUid, int userId) {//四大組件模塊的實現(xiàn)者就是mComponentResolver,調(diào)用它的getActivity方法查詢到Activity信息ParsedActivity a = mComponentResolver.getActivity(component);省略代碼······}

4.3 所有apk信息模塊和記錄存儲模塊

通過啟動一個Activity來啟動一個app,不僅僅只需要Activity的信息,還需要Application的信息 (該信息存放在ApplicationInfo對象),為啥還需要ApplicationInfo信息呢?

主要原因是當(dāng)app第一次運行的時候,它需要知道apk文件路徑、共享庫文件路徑 (若使用共享庫)、包名app的data目錄等等。比如知道了apk文件路徑、共享庫文件路徑 便可以把它們加入到自己的ClassLoader,這樣app運行時就可以找到自己的類了;比如知道了app的data目錄就可以知道當(dāng)前app運行時候存放數(shù)據(jù)的私有目錄在哪了。而以上這些信息都存放在ApplicationInfo對象,是需要提前獲取到的,以便app從ActivityManagerService獲取這些信息的時候可以順利獲取到。

ApplicationInfo的獲取是從所有apk信息模塊記錄存儲模塊拿到的,記錄存儲模塊存儲了共享庫信息 (若存在使用共享庫)等。

如下代碼:

//ComputerEngine類protected ActivityInfo getActivityInfoInternalBody(ComponentName component,@PackageManager.ResolveInfoFlagsBits long flags, int filterCallingUid, int userId) {//四大組件模塊的實現(xiàn)者就是mComponentResolver,調(diào)用它的getActivity方法查詢到Activity信息ParsedActivity a = mComponentResolver.getActivity(component);AndroidPackage pkg = a == null ? null : mPackages.get(a.getPackageName());if (pkg != null && mSettings.isEnabledAndMatch(pkg, a, flags, userId)) {PackageStateInternal ps = mSettings.getPackage(component.getPackageName());if (ps == null) return null;if (shouldFilterApplication(ps, filterCallingUid, component, TYPE_ACTIVITY, userId)) {return null;}//調(diào)用generateActivityInfo方法return PackageInfoUtils.generateActivityInfo(pkg,a, flags, ps.getUserStateOrDefault(userId), userId, ps);}省略代碼······}//PackageInfoUtils類private static ActivityInfo generateActivityInfo(AndroidPackage pkg, ParsedActivity a,@PackageManager.ComponentInfoFlagsBits long flags,@NonNull PackageUserStateInternal state, @Nullable ApplicationInfo applicationInfo,@UserIdInt int userId, @Nullable PackageStateInternal pkgSetting) {省略代碼······//構(gòu)建ApplicationInfoif (applicationInfo == null) {applicationInfo = generateApplicationInfo(pkg, flags, state, userId, pkgSetting);}if (applicationInfo == null) {return null;}//構(gòu)建ActivityInfofinal ActivityInfo info = PackageInfoWithoutStateUtils.generateActivityInfoUnchecked(a, flags, applicationInfo);assignSharedFieldsForComponentInfo(info, a, pkgSetting, userId);return info;}

4.4 小結(jié)

不論是啟動一個Activity或者啟動一個Service或者啟動一個ContentProvider或者啟動一個BroadcastReceiver的方式來啟動一個app,都需要去PackageManagerService查詢相應(yīng)的組件信息和ApplicationInfo信息,只有查詢到正確的信息后,才能執(zhí)行下一步操作;否則停止啟動過程。

5. 總結(jié)

本文主要是通過“上帝的視角”來看清楚PackageManagerService的各模塊是如何保證PackageManagerService的主要工作如何進(jìn)行的,在PackageManagerService啟動過程,每個模塊都做了哪些提前的準(zhǔn)備工作來保證掃描所有apk工作的順利完成;在apk安裝過程中,apk信息會存儲在所有apk信息模塊四大組件模塊,當(dāng)然在安裝過程中或多或少還會用到其他模塊;在app運行時,需要從PackageManagerService的相關(guān)模塊中獲取對應(yīng)組件和ApplicationInfo信息來保證后面啟動流程的正確執(zhí)行,關(guān)于包管理系列的文章就全部介紹完畢。

請?zhí)砑訄D片描述

http://aloenet.com.cn/news/35966.html

相關(guān)文章:

  • 浙江網(wǎng)站建設(shè)報價seo指的是搜索引擎
  • 湖北中牛建設(shè)有限公司網(wǎng)站網(wǎng)站搜索
  • 哪個網(wǎng)站有ae免費模板競價托管咨詢微競價
  • 現(xiàn)在幫人做網(wǎng)站賺錢嗎bt種子bt天堂
  • 建設(shè)政府信息網(wǎng)站如何注冊網(wǎng)站平臺
  • 做航空產(chǎn)品的網(wǎng)站有哪些搜索量用什么工具查詢
  • 如何將網(wǎng)站指向404太原百度網(wǎng)站快速優(yōu)化
  • 煙臺網(wǎng)站建設(shè)哪家好呢網(wǎng)絡(luò)顧問
  • 手機網(wǎng)站js特效個人博客登錄入口
  • 廣州建站模板搭建西安百度競價開戶
  • 作風(fēng)建設(shè)網(wǎng)站海曙seo關(guān)鍵詞優(yōu)化方案
  • 東莞微網(wǎng)站建設(shè)費用深圳seo優(yōu)化公司排名
  • 成都市建設(shè)局官網(wǎng)seo優(yōu)化方式包括
  • 邯鄲網(wǎng)站建設(shè)安聯(lián)網(wǎng)絡(luò)nb抖音推廣引流平臺
  • 網(wǎng)站開發(fā) 招標(biāo)采購參數(shù)愛站網(wǎng)關(guān)鍵詞
  • 網(wǎng)站怎樣做優(yōu)化調(diào)整百度公司招聘崗位
  • 國內(nèi)建網(wǎng)站知名企業(yè)網(wǎng)站制作廠家有哪些
  • 網(wǎng)站開發(fā)運用到的相關(guān)技術(shù)百度競價推廣方案的制定
  • 網(wǎng)站制作公司上海微信引流推廣
  • 做好網(wǎng)站建設(shè)的重要性app優(yōu)化建議
  • 做壞事小視頻網(wǎng)站企業(yè)培訓(xùn)計劃
  • 泰安百度做網(wǎng)站的百度搜索熱度排名
  • 涼山網(wǎng)站開發(fā)推廣計劃怎么做
  • dreamweaver教程做網(wǎng)站新浪網(wǎng)今日烏魯木齊新聞
  • 網(wǎng)站搭建 審查重慶搜索排名提升
  • 做代還的人都聚集在哪些網(wǎng)站怎么開網(wǎng)店
  • 渭南做網(wǎng)站怎么免費創(chuàng)建個人網(wǎng)站
  • 自己0基礎(chǔ)怎么創(chuàng)業(yè)seo搜索引擎優(yōu)化人員
  • 網(wǎng)站建設(shè) 北京優(yōu)化網(wǎng)站建設(shè)
  • 東莞做網(wǎng)站那家好網(wǎng)站優(yōu)化聯(lián)系