程序員自我修養(yǎng)之PMS 啟動流程

一、關(guān)鍵類的介紹

1祠锣、核心類介紹

/frameworks/base/core/java/android/app/ApplicationPackageManager.java
/frameworks/base/services/java/com/android/server/SystemServer.java
/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
/frameworks/base/services/core/java/com/android/server/pm/PackageInstallerService.java
/frameworks/base/services/core/java/com/android/server/pm/PackageDexOptimizer.java
/frameworks/base/services/core/java/com/android/server/pm/Installer.java
/frameworks/base/services/core/java/com/android/server/pm/Settings.java
/frameworks/base/services/core/java/com/android/server/pm/permission/BasePermission.java
/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
/frameworks/base/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
/frameworks/base/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
/frameworks/base/core/java/android/content/pm/IPackageManager.aidl
/frameworks/base/core/java/android/content/pm/PackageManager.java
/frameworks/base/core/java/com/android/server/SystemConfig.java

2淹遵、PackageManager

  • 提供一個(gè)ApplicationInfo的所有信息

  • 提供權(quán)限相關(guān)信息

  • 提供一個(gè)安裝包信息

  • 安裝继找、卸載遂跟、更新app功能

3、Installer :對app進(jìn)行操作

  • 安裝

  • 卸載

  • 更新

  • 遷移

3婴渡、Settings

  • 創(chuàng)建”data/system”目錄
  • 創(chuàng)建一些xml文件

    packages.xml 記錄所有安裝app的信息幻锁,當(dāng)系統(tǒng)進(jìn)行程序安裝、卸載和更新等操作時(shí)边臼,均會更新該文件哄尔。
    packages-backup.xml 備份文件
    packages-stopped.xml 記錄被用戶強(qiáng)行停止的應(yīng)用的Package信息
    packages-stopped-backup.xml 備份文件
    packages.list 記錄非系統(tǒng)自帶的APK的數(shù)據(jù)信息,這些APK有變化時(shí)會更新該文件

  • 配置相應(yīng)的權(quán)限
  • readLPw()函數(shù):

從/data/system/packages.xml或packages-backup.xml文件中獲得packages柠并、permissions相關(guān)信息岭接,添加到相關(guān)內(nèi)存列表中。packages.xml文件記錄了系統(tǒng)的permisssions以及每個(gè)APK的name臼予、codePath鸣戴、flags、version等信息這些信息主要通過APK的AndroidManifest.xml解析獲取粘拾,解析完APK后將更新信息寫入這個(gè)文件窄锅,下次開機(jī)直接從里面讀取相關(guān)信息添加到內(nèi)存相關(guān)結(jié)構(gòu)中。當(dāng)有APK升級缰雇、安裝或刪除時(shí)會更新這個(gè)文件入偷。

  • writeLPr函數(shù):

將解析出的每個(gè)APK的配置信息(mSetting.mPackages)保存到packages.xml和packages.list文件追驴。packages.list記錄了如下數(shù)據(jù):pkgName, userId, debugFlag, dataPath(包的數(shù)據(jù)路徑)

4、SystemConfig

通過readPermissions解析指定目錄下的xml文件:

  • /system/etc/sysconfig
  • /system/etc/permissions
  • /odm/etc/sysconfig
  • /odm/etc/permissions
  • /oem/etc/sysconfig
  • /oem/etc/permissions

readPermissions函數(shù)最終會調(diào)用readPermissionsFromXml()使用XMLPullParser的方式解析這些XML文件疏之,然后把解析出來的數(shù)據(jù)結(jié)構(gòu)保存到PMS中殿雪。

5、DefaultPermissionGrantPolicy

默認(rèn)組件提前授予運(yùn)行時(shí)權(quán)限体捏,DefaultPermissionGrantPolicy在PermissionManagerService的構(gòu)造函數(shù)中被創(chuàng)建冠摄。

6、PackageInstallerService

管理應(yīng)用的安裝過程几缭。

二河泳、PMS初始化

查看系統(tǒng)網(wǎng)址: http://androidxref.com/9.0.0_r3/

1、啟動SystemServer服務(wù)

frameworks/base/services/java/com/android/server/SystemServer.java

 /**
     * The main entry point from zygote.  SystemServer啟動入口
     */
    public static void main(String[] args) {
        new SystemServer().run();
    }

    private void run() {
     .........
        // Start services : 分開啟動目的:加快手機(jī)啟動速度
        try {
            //啟動AMS年栓、PMS拆挥、WMS
            startBootstrapServices();
            //啟動核心服務(wù)
            startCoreServices();
            //啟動三方服務(wù)(Launcher啟動)
            startOtherServices();
            SystemServerInitThreadPool.shutdown();
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        } finally {
            traceEnd();
        }
        .........
    }


    private void startBootstrapServices() {
        .......
        /**
         * 以便它有機(jī)會創(chuàng)建關(guān)鍵目錄,如/data/user具有適當(dāng)?shù)臋?quán)限某抓。其他service都會用到此對象
         **/
        traceBeginAndSlog("StartInstaller");  //加系統(tǒng)日志纸兔,起始位置
        Installer installer = mSystemServiceManager.startService(Installer.class);
        traceEnd();  // 日志結(jié)束
        .......

        // Start the package manager.   啟動PMS服務(wù)
        if (!mRuntimeRestart) {
            MetricsLogger.histogram(null, "boot_package_manager_init_start",
                    (int) SystemClock.elapsedRealtime());
        }
        traceBeginAndSlog("StartPackageManagerService"); 
        mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
                mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
        mFirstBoot = mPackageManagerService.isFirstBoot();
        mPackageManager = mSystemContext.getPackageManager();
        traceEnd();

        ......
    }

2、初始化PMS

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

  • 創(chuàng)建類時(shí)候會把Data分區(qū)一些目錄創(chuàng)建好,比如/data/app否副。
  • PackageManagerService構(gòu)造方法
    /**
      加載類之前在Data分區(qū)創(chuàng)建一些目錄
    **/
    /**
     * Directory where installed applications are stored
     */
    private static final File sAppInstallDir =
            new File(Environment.getDataDirectory(), "app");
    /**
     * Directory where installed application's 32-bit native libraries are copied.
     */
    private static final File sAppLib32InstallDir =
            new File(Environment.getDataDirectory(), "app-lib");
    /**
     * Directory where code and non-resource assets of forward-locked applications are stored
     */
    private static final File sDrmAppPrivateInstallDir =
            new File(Environment.getDataDirectory(), "app-private");

    //PackageManagerService的入口
      public static PackageManagerService main(Context context, Installer installer,
                                             boolean factoryTest, boolean onlyCore) {
        // Self-check for initial settings.
        PackageManagerServiceCompilerMapping.checkProperties();

        PackageManagerService m = new PackageManagerService(context, installer,
                factoryTest, onlyCore);
        m.enableSystemUserPackages();
        ServiceManager.addService("package", m);
        final PackageManagerNative pmn = m.new PackageManagerNative();
        ServiceManager.addService("package_native", pmn);
        return m;
    }

3汉矿、PMS構(gòu)造方法

  • BOOT_PROGRESS_PMS_START : PMS開始掃描安裝的應(yīng)用

UserManagerService :多用戶管理服務(wù)類。主要功能是創(chuàng)建和刪除用戶备禀,以及查詢用戶信息
PermissionManagerService :權(quán)限管理類洲拇。創(chuàng)建PermissionSettings類,它是記錄所有權(quán)限相關(guān)信息
Settings :保存安裝包信息類曲尸。主要涉及/data/system/目錄的packages.xml(逆向工程掣承看文件),packages-backup.xml另患,packages.list纽乱,packages-stopped.xml,packages-stopped-backup.xml等文件昆箕。
PackageDexOptimizer :創(chuàng)建Dex優(yōu)化工具類
PackageHandler : APK的復(fù)制和安裝工作類

        public PackageManagerService(Context context, Installer installer,
                                 // Create sub-components that provide services / data. Order here is important.
                                 synchronized (mInstallLock) {
        //打印開始階段日志
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
                SystemClock.uptimeMillis())
        ........
        synchronized (mPackages) {
            // Expose private service for system components to use.
            LocalServices.addService(
                    PackageManagerInternal.class, new PackageManagerInternalImpl());
            //UserManagerService的主要功能是創(chuàng)建和刪除用戶鸦列,以及查詢用戶信息。
            sUserManager = new UserManagerService(context, this,
                    new UserDataPreparer(mInstaller, mInstallLock, mContext, mOnlyCore), mPackages);
            //PermissionManagerService 權(quán)限管理類鹏倘,創(chuàng)建PermissionSettings類敛熬,它是記錄所有權(quán)限相關(guān)信息
            mPermissionManager = PermissionManagerService.create(context,
                    new DefaultPermissionGrantedCallback() {
                        @Override
                        public void onDefaultRuntimePermissionsGranted(int userId) {
                            synchronized (mPackages) {
                                mSettings.onDefaultRuntimePermissionsGrantedLPr(userId);
                            }
                        }
                    }, mPackages /*externalLock*/);
            mDefaultPermissionPolicy = mPermissionManager.getDefaultPermissionGrantPolicy();
            //它是Android全局管理者,用于協(xié)助PMS保存所有的安裝包信息
            mSettings = new Settings(mPermissionManager.getPermissionSettings(), mPackages);
        }
          ........
          //創(chuàng)建Dex優(yōu)化工具類
          mPackageDexOptimizer = new PackageDexOptimizer(installer, mInstallLock, context,
                "*dexopt*");
          // 權(quán)限變化監(jiān)聽器
          mOnPermissionChangeListeners = new OnPermissionChangeListeners(FgThread.get().getLooper());
          ........
         //得到全局系統(tǒng)配置信息第股。
         SystemConfig systemConfig = SystemConfig.getInstance();
         mAvailableFeatures = systemConfig.getAvailableFeatures();
         Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    }
        ........
        synchronized (mInstallLock) {
            // writer
            synchronized (mPackages) {
                mHandlerThread = new ServiceThread(TAG,
                        Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
                mHandlerThread.start();
                // PMS通過PackageHandler驅(qū)動APK的復(fù)制和安裝工作
                mHandler = new PackageHandler(mHandlerThread.getLooper());
                mProcessLoggingHandler = new ProcessLoggingHandler();
                //mHandler添加到Watchdog的監(jiān)測導(dǎo)致系統(tǒng)卡住
                Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);
                mInstantAppRegistry = new InstantAppRegistry(this);
                // 通過 systemConfig 獲取系統(tǒng)中的共享庫列表
                ArrayMap<String, String> libConfig = systemConfig.getSharedLibraries();
                final int builtInLibCount = libConfig.size();
                for (int i = 0; i < builtInLibCount; i++) {
                    String name = libConfig.keyAt(i);
                    String path = libConfig.valueAt(i);
                    //把共享庫寫入系統(tǒng)路徑    L: lock    P: packages一系列xml文件   w: write
                    addSharedLibraryLPw(path, null, name, SharedLibraryInfo.VERSION_UNDEFINED,
                            SharedLibraryInfo.TYPE_BUILTIN, PLATFORM_PACKAGE_NAME, 0);
                }
            }
        }
  • BOOT_PROGRESS_PMS_SYSTEM_SCAN_START :PMS掃描/system目錄下的安裝包

app : 存放系統(tǒng)App应民,包括了谷歌內(nèi)置的App也有廠商或者運(yùn)營商提供的App
framework : 存放應(yīng)用框架層的jar包
priv-app: 存放特權(quán)App
lib : 存放so文件
fonts: 存放系統(tǒng)字體文件
media: 存放系統(tǒng)的各種聲音,比如鈴聲、提示音诲锹,以及系統(tǒng)啟動播放的動畫
vendor: 它用來存儲廠商對Android系統(tǒng)的定制部分繁仁。

系統(tǒng)掃描階段的主要工作有以下3點(diǎn):

  • 創(chuàng)建/system的子目錄,比如/system/framework归园、/system/priv-app和/system/app等等
  • 掃描系統(tǒng)文件黄虱,比如/vendor/overlay、/system/framework庸诱、/system/app等等目錄下的文件捻浦。
  • 對掃描到的系統(tǒng)文件做后續(xù)處理。
public PackageManagerService(Context context, Installer installer,
            boolean factoryTest, boolean onlyCore) {
            ...
            //打印掃描系統(tǒng)階段日志
            EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
                    startTime);
            ...
            //在/system中創(chuàng)建framework目錄
            File frameworkDir = new File(Environment.getRootDirectory(), "framework");
            ...
            //掃描/vendor/overlay目錄下的文件
            scanDirTracedLI(new File(VENDOR_OVERLAY_DIR), mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR
                    | PackageParser.PARSE_TRUSTED_OVERLAY, scanFlags | SCAN_TRUSTED_OVERLAY, 0);
            mParallelPackageParserCallback.findStaticOverlayPackages();
            //掃描/system/framework 目錄下的文件
            scanDirTracedLI(frameworkDir, mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR
                    | PackageParser.PARSE_IS_PRIVILEGED,
                    scanFlags | SCAN_NO_DEX, 0);
            final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
            //掃描 /system/priv-app 目錄下的文件
            scanDirTracedLI(privilegedAppDir, mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR
                    | PackageParser.PARSE_IS_PRIVILEGED, scanFlags, 0);
            final File systemAppDir = new File(Environment.getRootDirectory(), "app");
            //掃描/system/app 目錄下的文件
            scanDirTracedLI(systemAppDir, mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
            File vendorAppDir = new File("/vendor/app");
            try {
                vendorAppDir = vendorAppDir.getCanonicalFile();
            } catch (IOException e) {
                // failed to look up canonical path, continue with original one
            }
            //掃描 /vendor/app 目錄下的文件
            scanDirTracedLI(vendorAppDir, mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);

           //掃描/oem/app 目錄下的文件
            final File oemAppDir = new File(Environment.getOemDirectory(), "app");
            scanDirTracedLI(oemAppDir, mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);

            //這個(gè)列表代表有可能有升級包的系統(tǒng)App
            final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<String>();//1
            if (!mOnlyCore) {
                Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
                while (psit.hasNext()) {
                    PackageSetting ps = psit.next();                 
                    if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
                        continue;
                    }
                    //這里的mPackages的是PMS的成員變量桥爽,代表scanDirTracedLI方法掃描上面那些目錄得到的 
                    final PackageParser.Package scannedPkg = mPackages.get(ps.name);
                    if (scannedPkg != null) {           
                        if (mSettings.isDisabledSystemPackageLPr(ps.name)) {//2
                           ...
                            //將這個(gè)系統(tǒng)App的PackageSetting從PMS的mPackages中移除
                            removePackageLI(scannedPkg, true);
                            //將升級包的路徑添加到mExpectingBetter列表中
                            mExpectingBetter.put(ps.name, ps.codePath);
                        }
                        continue;
                    }
                   
                    if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {
                       ...   
                    } else {
                        final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps.name);
                        //這個(gè)系統(tǒng)App升級包信息在mDisabledSysPackages中,但是沒有發(fā)現(xiàn)這個(gè)升級包存在
                        if (disabledPs.codePath == null || !disabledPs.codePath.exists()) {//5
                            possiblyDeletedUpdatedSystemApps.add(ps.name);//
                        }
                    }
                }
            }
            ...        
}
  • BOOT_PROGRESS_PMS_DATA_SCAN_START:PMS掃描/data目錄下的安裝包

app: 存儲用戶自己安裝的App
data: 存儲所有已安裝的App數(shù)據(jù)的目錄朱灿,每個(gè)App都有自己單獨(dú)的子目錄
app-private: App的私有存儲空間
app-lib: 存儲所有App的Jni庫
system: 存放系統(tǒng)配置文件
anr: 用于存儲ANR發(fā)生時(shí)系統(tǒng)生成的traces.txt文件

掃描Data分區(qū)階段主要做了以下幾件事:

  • 掃描/data/app和/data/app-private目錄下的文件。
  • 遍歷possiblyDeletedUpdatedSystemApps列表钠四,注釋1處如果這個(gè)系統(tǒng)App的包信息不在PMS的變量mPackages中盗扒,說明是殘留的App信息,后續(xù)會刪除它的數(shù)據(jù)缀去。注釋2處如果這個(gè)系統(tǒng)App的包信息在mPackages中侣灶,說明是存在于Data分區(qū),不屬于系統(tǒng)App缕碎,那么移除其系統(tǒng)權(quán)限褥影。
  • 遍歷mExpectingBetter列表,注釋3處根據(jù)系統(tǒng)App所在的目錄設(shè)置掃描的解析參數(shù)咏雌,注釋4處的方法內(nèi)部會將packageName對應(yīng)的包設(shè)置數(shù)據(jù)(PackageSetting)添加到mSettings的mPackages中伪阶。注釋5處掃描系統(tǒng)App的升級包,最后清除mExpectingBetter列表处嫌。
public PackageManagerService(Context context, Installer installer,
            boolean factoryTest, boolean onlyCore) {
    ...        
    mSettings.pruneSharedUsersLPw();
    //如果沒有加密設(shè)備,那么就開始掃描Data分區(qū)斟湃。
    if (!mOnlyCore) {
        //打印掃描Data分區(qū)階段日志
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
                SystemClock.uptimeMillis());
        //掃描/data/app目錄下的文件       
        scanDirTracedLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);
        //掃描/data/app-private目錄下的文件   
        scanDirTracedLI(mDrmAppPrivateInstallDir, mDefParseFlags
                | PackageParser.PARSE_FORWARD_LOCK,
                scanFlags | SCAN_REQUIRE_KNOWN, 0);
        //掃描完Data分區(qū)后熏迹,處理possiblyDeletedUpdatedSystemApps列表
        for (String deletedAppName : possiblyDeletedUpdatedSystemApps) {
            PackageParser.Package deletedPkg = mPackages.get(deletedAppName);
            // 從mSettings.mDisabledSysPackages變量中移除去此應(yīng)用
            mSettings.removeDisabledSystemPackageLPw(deletedAppName);
            String msg;
          //1:如果這個(gè)系統(tǒng)App的包信息不在PMS的變量mPackages中,說明是殘留的App信息凝赛,后續(xù)會刪除它的數(shù)據(jù)注暗。
            if (deletedPkg == null) {
                msg = "Updated system package " + deletedAppName
                        + " no longer exists; it's data will be wiped";
                // Actual deletion of code and data will be handled by later
                // reconciliation step
            } else {
            //2:如果這個(gè)系統(tǒng)App在mPackages中,說明是存在于Data分區(qū)墓猎,不屬于系統(tǒng)App捆昏,那么移除其系統(tǒng)權(quán)限。
                msg = "Updated system app + " + deletedAppName
                        + " no longer present; removing system privileges for "
                        + deletedAppName;
                deletedPkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;
                PackageSetting deletedPs = mSettings.mPackages.get(deletedAppName);
                deletedPs.pkgFlags &= ~ApplicationInfo.FLAG_SYSTEM;
            }
            logCriticalInfo(Log.WARN, msg);
        }
         //遍歷mExpectingBetter列表
        for (int i = 0; i < mExpectingBetter.size(); i++) {
            final String packageName = mExpectingBetter.keyAt(i);
            if (!mPackages.containsKey(packageName)) {
                //得到系統(tǒng)App的升級包路徑
                final File scanFile = mExpectingBetter.valueAt(i);
                logCriticalInfo(Log.WARN, "Expected better " + packageName
                        + " but never showed up; reverting to system");
                int reparseFlags = mDefParseFlags;
                //3:根據(jù)系統(tǒng)App所在的目錄設(shè)置掃描的解析參數(shù)
                if (FileUtils.contains(privilegedAppDir, scanFile)) {
                    reparseFlags = PackageParser.PARSE_IS_SYSTEM
                            | PackageParser.PARSE_IS_SYSTEM_DIR
                            | PackageParser.PARSE_IS_PRIVILEGED;
                } 
                ...
                //將packageName對應(yīng)的包設(shè)置數(shù)據(jù)(PackageSetting)添加到mSettings的mPackages中
                mSettings.enableSystemPackageLPw(packageName);//4
                try {
                    //掃描系統(tǒng)App的升級包
                    scanPackageTracedLI(scanFile, reparseFlags, scanFlags, 0, null);//5
                } catch (PackageManagerException e) {
                    Slog.e(TAG, "Failed to parse original system package: "
                            + e.getMessage());
                }
            }
        }
    }
   //清除mExpectingBetter列表
    mExpectingBetter.clear();
...
}
  • BOOT_PROGRESS_PMS_SCAN_END:PMS掃描結(jié)束

1毙沾、如果當(dāng)前平臺SDK版本和上次啟動時(shí)的SDK版本不同骗卜,重新更新APK的授權(quán)。
2、如果是第一次啟動或者是Android M升級后的第一次啟動寇仓,需要初始化所有用戶定義的默認(rèn)首選App举户。
3、OTA升級后的第一次啟動遍烦,會清除代碼緩存目錄俭嘁。
4、把Settings的內(nèi)容保存到packages.xml中服猪,這樣此后PMS再次創(chuàng)建時(shí)會讀到此前保存的Settings的內(nèi)容供填。

//打印掃描結(jié)束階段日志
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
                  SystemClock.uptimeMillis());
          Slog.i(TAG, "Time to scan packages: "
                  + ((SystemClock.uptimeMillis()-startTime)/1000f)
                  + " seconds");
          int updateFlags = UPDATE_PERMISSIONS_ALL;
          // 如果當(dāng)前平臺SDK版本和上次啟動時(shí)的SDK版本不同,重新更新APK的授權(quán)
          if (ver.sdkVersion != mSdkVersion) {
              Slog.i(TAG, "Platform changed from " + ver.sdkVersion + " to "
                      + mSdkVersion + "; regranting permissions for internal storage");
              updateFlags |= UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL;
          }
          updatePermissionsLPw(null, null, StorageManager.UUID_PRIVATE_INTERNAL, updateFlags);
          ver.sdkVersion = mSdkVersion;
         //如果是第一次啟動或者是Android M升級后的第一次啟動罢猪,需要初始化所有用戶定義的默認(rèn)首選App
          if (!onlyCore && (mPromoteSystemApps || mFirstBoot)) {
              for (UserInfo user : sUserManager.getUsers(true)) {
                  mSettings.applyDefaultPreferredAppsLPw(this, user.id);
                  applyFactoryDefaultBrowserLPw(user.id);
                  primeDomainVerificationsLPw(user.id);
              }
          }
         ...
          //OTA后的第一次啟動近她,會清除代碼緩存目錄。
          if (mIsUpgrade && !onlyCore) {
              Slog.i(TAG, "Build fingerprint changed; clearing code caches");
              for (int i = 0; i < mSettings.mPackages.size(); i++) {
                  final PackageSetting ps = mSettings.mPackages.valueAt(i);
                  if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, ps.volumeUuid)) {
                      clearAppDataLIF(ps.pkg, UserHandle.USER_ALL,
                              StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE
                                      | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
                  }
              }
              ver.fingerprint = Build.FINGERPRINT;
          }
          ...
         // 把Settings的內(nèi)容保存到packages.xml中
          mSettings.writeLPr();
          Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
  • BOOT_PROGRESS_PMS_READY:PMS就緒

注釋1處創(chuàng)建PackageInstallerService坡脐,PackageInstallerService是用于管理安裝會話的服務(wù)泄私,它會為每次安裝過程分配一個(gè)SessionId。
注釋2處進(jìn)行一次垃圾收集备闲。
注釋3處將PackageManagerInternalImpl(PackageManager的本地服務(wù))添加到LocalServices中晌端,
LocalServices用于存儲運(yùn)行在當(dāng)前的進(jìn)程中的本地服務(wù)。

 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
                SystemClock.uptimeMillis());
    ... 
    mInstallerService = new PackageInstallerService(context, this);//1
    ...
    Runtime.getRuntime().gc();//2
    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "loadFallbacks");
    FallbackCategoryProvider.loadFallbacks();
    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    mInstaller.setWarnIfHeld(mPackages);
    LocalServices.addService(PackageManagerInternal.class, new PackageManagerInternalImpl());//3
    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}

PMS構(gòu)造方法大致流程:
1恬砂、先讀取packages.xml文件內(nèi)容咧纠,解析并保存在成員變量mSettings中。
2泻骤、掃描設(shè)備中的幾個(gè)分區(qū)目錄下的應(yīng)用文件漆羔,把掃描結(jié)果保存到PMS的mPackages中。這記錄的是當(dāng)前系統(tǒng)中的應(yīng)用狀態(tài)信息
3狱掂、后面就是對兩次的應(yīng)用狀態(tài)信息進(jìn)行:比對演痒、重新調(diào)整、掃描特定目錄趋惨。
4鸟顺、最后將應(yīng)用信息重新寫回packages.xml文件


帶學(xué)習(xí):
SystemConfig 對 platform.xml 文件的操作


image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市器虾,隨后出現(xiàn)的幾起案子讯嫂,更是在濱河造成了極大的恐慌,老刑警劉巖兆沙,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件欧芽,死亡現(xiàn)場離奇詭異,居然都是意外死亡葛圃,警方通過查閱死者的電腦和手機(jī)千扔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進(jìn)店門憎妙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人昏鹃,你說我怎么就攤上這事尚氛。” “怎么了洞渤?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵阅嘶,是天一觀的道長。 經(jīng)常有香客問我载迄,道長讯柔,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任护昧,我火速辦了婚禮魂迄,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘惋耙。我一直安慰自己捣炬,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布绽榛。 她就那樣靜靜地躺著湿酸,像睡著了一般。 火紅的嫁衣襯著肌膚如雪灭美。 梳的紋絲不亂的頭發(fā)上推溃,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天,我揣著相機(jī)與錄音届腐,去河邊找鬼铁坎。 笑死,一個(gè)胖子當(dāng)著我的面吹牛犁苏,可吹牛的內(nèi)容都是我干的硬萍。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼围详,長吁一口氣:“原來是場噩夢啊……” “哼朴乖!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起短曾,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎赐劣,沒想到半個(gè)月后嫉拐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡魁兼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年婉徘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了漠嵌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,117評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡盖呼,死狀恐怖儒鹿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情几晤,我是刑警寧澤约炎,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站蟹瘾,受9級特大地震影響圾浅,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜憾朴,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一狸捕、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧众雷,春花似錦灸拍、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至纯蛾,卻和暖如春纤房,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背翻诉。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工炮姨, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人碰煌。 一個(gè)月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓舒岸,卻偏偏與公主長得像,于是被迫代替她去往敵國和親芦圾。 傳聞我的和親對象是個(gè)殘疾皇子蛾派,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容