android應用程式管理機制

來源:互聯網
上載者:User

         android應用程式管理主要由PackageManager這個類來管理,實現PackageManager這個抽象類別的是ContextImpl.java。在ContextImpl.java中,有一個內部靜態類叫ApplicationPackageManager,實現了所有PackageManager的介面。

 static final class ApplicationPackageManager extends PackageManager {..........}

ApplicationPackageManager又是通過對IPackageManager封裝調用,來實現的。

 public PackageInfo getPackageInfo(String packageName, int flags)                throws NameNotFoundException {            try {                PackageInfo pi = mPM.getPackageInfo(packageName, flags);                if (pi != null) {                    return pi;                }            } catch (RemoteException e) {                throw new RuntimeException("Package manager has died", e);            }            throw new NameNotFoundException(packageName);        }

這裡的mPM就是IPackageManager,PackageManagerService就是對IPackageManager的實現。所以我們平時對PackageManager的調用,最終是的在PackageManagerService.java中實現的。在PackageManagerService.java每個方法的實現。

PackageManagerService啟動流程:

PackageManagerService(context, factoryTest)是包管理服務的主進程。它完成了對/system/app,/data/app,/system/framework,/data/app-private下的apk檔案的解析。詳細流程如下:

1.建立java層的installer與c層的installd的socket聯結,使得在上層的install,remove,dexopt等功能最終由installd在底層實現

2.建立PackageHandler訊息迴圈,用於處理外部的apk安裝請求訊息,如adb install,packageinstaller安裝apk時會發送訊息

3.解析/system/etc/permission下xml檔案(framework/base/data/etc/),包括platform.xml和系統支援的各種硬體模組的feature.主要工作:

(1)建立底層user ids和group ids 同上層permissions之間的映射;可以指定一個許可權與幾個組ID對應。當一個APK被授予這個許可權時,它也同時屬於這幾個組。

(2)給一些底層使用者指派許可權,如給shell授予各種permission許可權;把一個許可權賦予一個UID,當進程使用這個UID運行時,就具備了這個許可權。

(3) library,系統增加的一些應用需要link的擴充jar庫;

(4) feature,系統每增加一個硬體,都要添加相應的feature.將解析結果放入mSystemPermissions,mSharedLibraries,mSettings.mPermissions,mAvailableFeatures等幾個集合中供系統查詢和許可權配置使用。

4.檢查/data/system/packages.xml是否存在,這個檔案是在解析apk時由

writeLP()建立的,裡面記錄了系統的permissions,以及每個apk的name,codePath,flags,version,uesrid等資訊,這些資訊主要通過apk的

AndroidManifest.xml解析擷取,解析完apk後將更新資訊寫入這個檔案並保

存到flash,下次開機直接從裡面讀取相關資訊添加到記憶體相關列表中。當有apk

升級,安裝或刪除時會更新這個檔案。

5.檢查BootClassPath,mSharedLibraries及/system/framework下的jar

是否需要dexopt,需要的則通過dexopt進行最佳化

6.啟動AppDirObserver線程監測/system/framework,/system/app,/data/app,/data/

app-private目錄的事件,主要監聽add和remove事件。對於目錄監聽底層通過

inotify機制實現,inotify 是一種檔案系統的變化通知機制,如檔案增加、刪除

等事件可以立刻讓使用者態得知,它為使用者態監視檔案系統的變化提供了強大的支援。

當有add event時調用scanPackageLI(File , int , int)處理;

當有remove event時調用removePackageLI()處理;

7.對於以上幾個目錄下的apk逐個解析,主要是解析每個apk的AndroidMa-

nifest.xml檔案,處理asset/res等資源檔,建立起每個apk的配置結構資訊,

並將每個apk的配置資訊添加到全域列表進行管理。f

8.將解析的每個apk的資訊儲存到packages.xml和packages.list檔案裡,

packages.xml記錄了如下資料:pkgName,userId,debugFlag,dataPath(包的資料路徑)

dexopt:

      如果我們想要求運行時的效能有進一步提高,就仍然需要對DEX檔案進行進一步最佳化。最佳化DEX會產生一個可以快速載入執行的classes.dex檔案,會進行包括byte-swapping,structure realigning與basic structure checks,更新ODEX header ,為了確保產生ODEX流程的正確性,Android提供了一個dexopt工具,用來做為虛擬機器的協助工具輔助,可以在系統啟動時,透過Dalvik虛擬機器對載入的DEX檔案執行佳化操作。
 

最佳化發生的時機有兩個:

對於預置應用,可以在系統編譯後,產生最佳化檔案,以ODEX 結尾。這樣在發布時除

APK 檔案(不包含 DEX)以外,還有一個相應的 ODEX 檔案;
  對於非預置應用,包含在 APK 檔案裡的 DEX 檔案會在運行時通過dexopt進行最佳化,最佳化後的檔案將被儲存在緩衝中(data/dalvik-cache)。   

android安全機制概述:

      Android是一個許可權分離的系統 ,這是利用Linux已有的許可權管理機制,通過為每一個Application分配不同的uid和gid, 從而使得不同的Application之間的私人資料和訪問(native以及java層通過這種sandbox機制)達到隔離的目的 。與此同時,Android還在此基礎上進行擴充,提供了permission機制,它主要是用來對Application可以執行的某些具體操作進行許可權細分和存取控制,同時提供了per-URI permission機制,用來提供對某些特定的資料區塊進行訪問。
       Application 層級通過user ID和group Id實現安全控制;component層級通過permission來限制對於某一組件的訪問;在data層級通過基於permission的per URI進行安全控制。

 uid  gid  gids:

       Android 的許可權分離的基礎是建立在 Linux 已有的 uid 、 gid 、 gids 基礎上的 。
UID :Android 在 安裝一個應用程式,就會為 它 分配一個 uid 。其中普通 Android 應用程式的 uid 是從 10000 開始分配 (Process.FIRST_APPLICATION_UID ), 10000 以下是系統進程的 uid 。
GID :對 於普通應用程式來說, gid 等於 uid 。由於每個應用程式的 uid 和 gid 都不相同, 因此不管是 native 層還是 java 層都能夠達到保護私人資料的作用 。
GIDS : gids 是由架構在 Application 安裝過程中產生,與 Application 申請的具體許可權相關。 如果 Application 申請的相應的 permission 被 granted ,而且中有對應的 gids , 那麼這個Application 的 gids 中將包含這個gids 。

installer類:

構造方法中,首先會進行一些成員變數的初始化,比如mContext, mFactoryTest, mMetrics, mSettings等。
最重要的是初始化mInstaller這個變數:

  Installer installer = new Installer();        if (installer.ping() && Process.supportsProcesses()) {            mInstaller = installer;        } else {            mInstaller = null;        }

Installer這個是PackageManager與底層C模組進行通訊的工具類,同socket進行通訊,PackageManager所有對apk的安裝,卸載等操作都是通過Installer進行的。對Installer的調用首先會調用ping()來判斷socket是否已經串連。

串連方法:connect:

 private boolean connect() {        if (mSocket != null) {            return true;        }        Slog.i(TAG, "connecting...");        try {            mSocket = new LocalSocket();            LocalSocketAddress address = new LocalSocketAddress(                "installd", LocalSocketAddress.Namespace.RESERVED);            mSocket.connect(address);            mIn = mSocket.getInputStream();            mOut = mSocket.getOutputStream();        } catch (IOException ex) {            disconnect();            return false;        }        return true;    }

transaction首先會判斷串連,如果socket串連正常,就將cmd命令寫入socket檔案,並且接收返回資訊,並且返回給execute:

private synchronized String transaction(String cmd) {        if (!connect()) {            Slog.e(TAG, "connection failed");            return "-1";        }        if (!writeCommand(cmd)) {                /* If installd died and restarted in the background                 * (unlikely but possible) we'll fail on the next                 * write (this one).  Try to reconnect and write                 * the command one more time before giving up.                 */            Slog.e(TAG, "write command failed? reconnect!");            if (!connect() || !writeCommand(cmd)) {                return "-1";            }        }//        Slog.i(TAG,"send: '"+cmd+"'");        if (readReply()) {            String s = new String(buf, 0, buflen);//            Slog.i(TAG,"recv: '"+s+"'");            return s;        } else {//            Slog.i(TAG,"fail");            return "-1";        }    }

執行命令的方法:execute(String cmd):

 

  private int execute(String cmd) {        String res = transaction(cmd);        try {            return Integer.parseInt(res);        } catch (NumberFormatException ex) {            return -1;        }    }

install()方法:

    public int install(String name, int uid, int gid) {        StringBuilder builder = new StringBuilder("install");        builder.append(' ');        builder.append(name);        builder.append(' ');        builder.append(uid);        builder.append(' ');        builder.append(gid);        return execute(builder.toString());    }

其他方法:

(1)  dexopt(String apkPath, int uid, boolean isPublic);最佳化dex檔案
(2)movedex(String srcPath, String dstPath); 移動dex檔案
(3)rmdex(String codePath);刪除dex檔案
(4)remove(String name) ;刪除apk
(5)rename(String oldname, String newname);重新命名
(6)deleteCacheFiles(String name);刪除cache檔案
(7)clearUserData(String name);刪除user data
(8)freeCache(long freeStorageSize);釋放cache空間
(9)setForwardLockPerm(String packagePathSuffix, int gid) 為apk檔案增加首碼
(10)getSizeInfo(String pkgName, String apkPath, String fwdLockApkPath, PackageStats pStats)  擷取apk資訊
(11) moveFiles();移動檔案。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.