Android Framework 分析---PackageManager 分析

來源:互聯網
上載者:User

標籤:android   style   blog   class   c   code   

在windowphone,ios和android中到目前為止,還是android的市場份額最大。個人認為除了google開源外,廣大開發人員早就了android的霸主地位。各位兄弟姐妹開發出各種各樣的apk,才組成android的廣闊天下。本篇主要分析一下android系統是針對處理這些apk的,主要涉及到pm這塊的代碼。分析這種底層服務,最好從android的開啟啟動流程中開始分析。因為這樣才能更清楚的瞭解服務的啟動流程。

1.在SystemServer.java 中啟動PM

  android 開機啟動後載入的第一個java的程式就是SystemServer,在包含android系統的最主要的一些底層服務。在4.4kk之前都是建一個Thread線程來啟動。4.4KK的啟動機制就變了,具體後續的文章會講解。

Installer installer = null;   Slog.i(TAG, "Waiting for installd to be ready.");            installer = new Installer();            installer.ping(); pm = PackageManagerService.main(context, installer,                    factoryTest != SystemServer.FACTORY_TEST_OFF,                    onlyCore);            boolean firstBoot = false;            try {                firstBoot = pm.isFirstBoot();            } catch (RemoteException e) {            }
 public static final IPackageManager main(Context context, Installer installer,            boolean factoryTest, boolean onlyCore) {        PackageManagerService m = new PackageManagerService(context, installer,                factoryTest, onlyCore);        ServiceManager.addService("package", m);        return m;    }
在systemServer中初始化了Installer,並將它傳入PackageManagerService.main()中。在main函數中將pm添加到ServiceManager中,供開發人員調用。

2.PackageManagerService啟動安裝分析

啟動PackageManagerService後,主要完成以下幾個步驟

2.1.初始化PackageSetting,設定sharedUserID

 

mSettings = new Settings(context);        mSettings.addSharedUserLPw("android.uid.system",                Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM);        mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID, ApplicationInfo.FLAG_SYSTEM);
2.2.擷取螢幕參數:

 WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);        Display d = wm.getDefaultDisplay();        d.getMetrics(mMetrics);
2.3.使用HandlerThread開啟packagemanager背景工作執行緒和初始化app目錄

mHandlerThread.start();            mHandler = new PackageHandler(mHandlerThread.getLooper());            File dataDir = Environment.getDataDirectory();            mAppDataDir = new File(dataDir, "data");            mAppInstallDir = new File(dataDir, "app");            mAppLibInstallDir = new File(dataDir, "app-lib");            mAsecInternalPath = new File(dataDir, "app-asec").getPath();            mUserAppDataDir = new File(dataDir, "user");            mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
2.4.載入Framework的主要jar和BOOTCLASSPATH

 mFrameworkDir = new File(Environment.getRootDirectory(), "framework");            mDalvikCacheDir = new File(dataDir, "dalvik-cache");            boolean didDexOpt = false;            /**             * Out of paranoia, ensure that everything in the boot class             * path has been dexed.             */            String bootClassPath = System.getProperty("java.boot.class.path");
2.5.安裝system/app,vendor/app和data/app目錄下apk

// Collect all system packages.            mSystemAppDir = new File(Environment.getRootDirectory(), "app");            mSystemInstallObserver = new AppDirObserver(                mSystemAppDir.getPath(), OBSERVER_EVENTS, true);            mSystemInstallObserver.startWatching();            scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM                    | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);            // Collect all vendor packages.            mVendorAppDir = new File("/vendor/app");            mVendorInstallObserver = new AppDirObserver(                mVendorAppDir.getPath(), OBSERVER_EVENTS, true);            mVendorInstallObserver.startWatching();            scanDirLI(mVendorAppDir, PackageParser.PARSE_IS_SYSTEM                    | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);...... mAppInstallObserver = new AppDirObserver(                    mAppInstallDir.getPath(), OBSERVER_EVENTS, false);                mAppInstallObserver.startWatching();                scanDirLI(mAppInstallDir, 0, scanMode, 0);    

其中具體如果安裝代碼在scanDirLI()函數,最終調用scanPackageLI()進行安裝。在安裝過程中會搜集ApplicationInfo和ActivityInfo資訊,比較簽名,匹配本地so的目錄。

具體細節參看PackageManagerService.java 中的

private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
            int parseFlags, int scanMode, long currentTime, UserHandle user) {

函數。

3.在Activity使用PackageManger的分析

   我們在應用經常通過

   PackageManager pm = this.getPackageManager() 來擷取pm。這部分主要從它的來源來深入分析。

  由於我們在Activity中使用this來擷取pm,很容易想到到context類裡去尋找實現。

 

 /** Return PackageManager instance to find global package information. */    public abstract PackageManager getPackageManager();
但是context是虛函數,因此要找到它的實現,由於context的實現採用 設計模式裡面的 "橋接模式‘ 因此很容易想到從contextImpl.java 中尋找實現。

果然找到。

   public PackageManager getPackageManager() {        if (mPackageManager != null) {            return mPackageManager;        }        IPackageManager pm = ActivityThread.getPackageManager();        if (pm != null) {            // Doesn‘t matter if we make more than one instance.            return (mPackageManager = new ApplicationPackageManager(this, pm));        }        return null;    }

從代碼上看擷取IPackageManager,還是需要從ActivityThread中擷取。我在Activity裡面擷取嗎出現在ActivityThread 也不意外。

那我們就看看他是怎麼實現的

 public static IPackageManager getPackageManager() {        if (sPackageManager != null) {            //Slog.v("PackageManager", "returning cur default = " + sPackageManager);            return sPackageManager;        }        IBinder b = ServiceManager.getService("package");        //Slog.v("PackageManager", "default service binder = " + b);        sPackageManager = IPackageManager.Stub.asInterface(b);        //Slog.v("PackageManager", "default service = " + sPackageManager);        return sPackageManager;    }
原來是通過ServiceManager.getService("package").從上你們的代碼知道,這句其實就是擷取PackageManagerService 並賦給IBinder ,成為一個binder對象。

通過asInterface()函數,通過binder對象擷取介面類IPackageManager的執行個體。並返回回去。

if (pm != null) {            // Doesn‘t matter if we make more than one instance.            return (mPackageManager = new ApplicationPackageManager(this, pm));        }


在接著同ApplicationPackageManager 建立PackageManager 對象。到此我們在Activity中就可以使用pm這個對象作業系統中的各種包。


4.Android 系統中PackageManager的關鍵類和UML的類圖。

 在pm中主要涉及的類和路徑如下:

 frameworks\base\services\java\com\android\server\pm\PackageManagerService.java 和 其他檔案

frameworks\base\core\java\android\content\pm\IPackageManager.aidl

frameworks\base\core\java\android\app\ActivityThread.java ,context.java ,contextimpl.java

frameworks\base\core\java\android\content\pm\PackageManager.java





 






 



聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.