PackageManagerService启动分析

作者: Yink_Liu | 来源:发表于2017-09-15 10:21 被阅读0次

    PMS系列:
    1、PackageManagerService服务框架详解
    2、本文PackageManagerService启动分析
    3、PackageManagerService之app数据类(Settings)分析
    4、PackageManagerService扫描安装apk详解
    5、PackageManagerService根据权限等级管理权限(默认赋予apk权限)

    PackageManagerService初始化过程

    简述Android启动

    简单说一下Android的启动过程:
    Android基于Linux,前面和Linux大致相同
    按下电源 -> BIOS自检 -> 引导程序 -> 启动kernel -> 启动Init进程(system\core\init\init.c) -> 开启虚拟机(Zygotes)
    然后
    Zygote会startSystemServer,而Systemserver就开始启动framework层的各种公共服务,AMS、WMS、PMS等...

    Systemserver启动PMS

    从Systemserver.run开始,这里开始启动各种服务

    private void run() {
        ...
        // 初始化system Context
        createSystemContext();
    
        // 创建system manager
        mSystemServiceManager = new SystemServiceManager(mSystemContext);
        LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
        ...
        // Start services.
        try {
            Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartServices");
            // 开始引导Services,Installer创建user/data等目录,
            // 以及MessageMonitorService,AMS,PowerManagerService,LightsService,DisplayManagerService,UserManagerService等
            startBootstrapServices();
            // 核心Services,BatteryService,UsageStatsService,WebViewUpdateService
            startCoreServices();
            // 其他Services,这里启动的服务最多,TelecomLoaderService,CameraService,AccountManagerService等等一系列Service
            startOtherServices();
        } 
        ...
        // Loop forever.
        Looper.loop();
        ...
    }
    

    其他服务的启动这里就不展开了,这里开始看PMS的启动

    private void startBootstrapServices() {
        ...
        // 创建PMS
        mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
            mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
        ...
        
        // 权限检查,启动其他服务需要授予权限,在这之前需要AMS先做权限检查
        mPackageManagerService.onAmsAddedtoServiceMgr();
        ...
    }
        
    private void startOtherServices() {
        ...
        //检查system app是否需要更新,需要则更新
        mPackageManagerService.updatePackagesIfNeeded();
        ...
    
        //检查system app是否需要fs裁剪
        mPackageManagerService.performFstrimIfNeeded();
        ...
    
        //最后system Ready通知其他服务ready设置相关信息
        mPackageManagerService.systemReady();
        ...
    }
    

    详细过程分析

    1、创建

    PackageManagerService的main中主要进行new PackageManagerService操作,那么从PackageManagerService构建函数开始,这里进行大量的操作

    public PackageManagerService(Context context, Installer installer,
                boolean factoryTest, boolean onlyCore) {
            ...
            mContext = context;
            mFactoryTest = factoryTest;
        //是否需要dex化
            mOnlyCore = onlyCore;
        //DisplayMetrics 屏幕信息
            mMetrics = new DisplayMetrics();
        //这个Settings类保存了apk的各种信息
            mSettings = new Settings(mPackages);
        //分配UID,方便权限管理
            mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
                    ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
            mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID,
                    ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
            mSettings.addSharedUserLPw("android.uid.log", LOG_UID,
                    ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
            mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID,
                    ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
            mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID,
                    ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
            mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID,
                    ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        ...
            mInstaller = installer;
        //PackageDexOptimizer初始化,dex优化相关
            mPackageDexOptimizer = new PackageDexOptimizer(installer, mInstallLock, context,
                    "*dexopt*");
        //移动app的监听
            mMoveCallbacks = new MoveCallbacks(FgThread.get().getLooper());
        //Permission监听
            mOnPermissionChangeListeners = new OnPermissionChangeListeners(
                    FgThread.get().getLooper());
        //获得屏幕信息
            getDefaultDisplayMetrics(context, mMetrics);
            ...
            // writer
            synchronized (mPackages) {
            //消息处理线程
                mHandlerThread = new ServiceThread(TAG,
                        Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
                mHandlerThread.start();
                mHandler = new PackageHandler(mHandlerThread.getLooper());
                mProcessLoggingHandler = new ProcessLoggingHandler();
                Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);
    
            //在手机的data目录下创建app、app-lib、app-ephemeral、app-asec、app-private
                File dataDir = Environment.getDataDirectory();
                mAppInstallDir = new File(dataDir, "app");
                mAppLib32InstallDir = new File(dataDir, "app-lib");
                mEphemeralInstallDir = new File(dataDir, "app-ephemeral");
                mAsecInternalPath = new File(dataDir, "app-asec").getPath();
                mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
            
                sUserManager = new UserManagerService(context, this, mPackages);
    
                //package manager权限配置
                ArrayMap<String, SystemConfig.PermissionEntry> permConfig
                        = systemConfig.getPermissions();
                for (int i=0; i<permConfig.size(); i++) {
                    SystemConfig.PermissionEntry perm = permConfig.valueAt(i);
                    BasePermission bp = mSettings.mPermissions.get(perm.name);
                    if (bp == null) {
                        bp = new BasePermission(perm.name, "android", BasePermission.TYPE_BUILTIN);
                        mSettings.mPermissions.put(perm.name, bp);
                    }
                    if (perm.gids != null) {
                        bp.setGids(perm.gids, perm.perUser);
                    }
                }
    
               ...
           //保存lib路径
                if (mSharedLibraries.size() > 0) {
                    ...
                    for (String dexCodeInstructionSet : dexCodeInstructionSets) {
                        for (SharedLibraryEntry libEntry : mSharedLibraries.values()) {
                            final String lib = libEntry.path;
                            if (lib == null) {
                                continue;
                            }
    
                            try {
                                // Shared libraries do not have profiles so we perform a full
                                // AOT compilation (if needed).
                                int dexoptNeeded = DexFile.getDexOptNeeded(
                                        lib, dexCodeInstructionSet,
                                        getCompilerFilterForReason(REASON_SHARED_APK),
                                        false /* newProfile */);
                    //判断是否需要dex优化
                                if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
                                    mInstaller.dexopt(lib, Process.SYSTEM_UID, dexCodeInstructionSet,
                                            dexoptNeeded, DEXOPT_PUBLIC /*dexFlags*/,
                                            getCompilerFilterForReason(REASON_SHARED_APK),
                                            StorageManager.UUID_PRIVATE_INTERNAL,
                                            SKIP_SHARED_LIBRARY_CHECK);
                                }
                            } catch (FileNotFoundException e) {
                                Slog.w(TAG, "Library not found: " + lib);
                            } catch (IOException | InstallerException e) {
                                Slog.w(TAG, "Cannot dexopt " + lib + "; is it an APK or JAR? "
                                        + e.getMessage());
                            }
                        }
                    }
                }
    
            //创建system/framework
                File frameworkDir = new File(Environment.getRootDirectory(), "framework");
            ...
                //从M开始,默认不给权限
                if (mPromoteSystemApps) {
                    Iterator<PackageSetting> pkgSettingIter = mSettings.mPackages.values().iterator();
                    while (pkgSettingIter.hasNext()) {
                        PackageSetting ps = pkgSettingIter.next();
                        if (isSystemApp(ps)) {
                            mExistingSystemPackages.add(ps.name);
                        }
                    }
                }
    
                //手机overlay资源覆盖包
                File vendorOverlayDir = new File(VENDOR_OVERLAY_DIR);
                scanDirTracedLI(vendorOverlayDir, mDefParseFlags
                        | PackageParser.PARSE_IS_SYSTEM
                        | PackageParser.PARSE_IS_SYSTEM_DIR
                        | PackageParser.PARSE_TRUSTED_OVERLAY, scanFlags | SCAN_TRUSTED_OVERLAY, 0);
            ...
            //接下来扫描安装apk
                //扫描安装/custom/framework下apk
                File customFrameworkDir = new File("/custom/framework");
                scanDirLI(customFrameworkDir, PackageParser.PARSE_IS_SYSTEM
                        | PackageParser.PARSE_IS_SYSTEM_DIR,
                        scanFlags | SCAN_NO_DEX, 0);
                ...
            //此处省略代码为扫描安装各种路径下的apk,和上面代码类似,e.g:system/priv-app、vender/app/等
            ...
    
                //扫描安装apk,移除已经不在手机里的apk的信息,
                final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<String>();
                if (!mOnlyCore) {
                    Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
                    while (psit.hasNext()) {
                        PackageSetting ps = psit.next();
                ...
                        if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
                            /// M: [Operator] Operator apps are belong to system domain, therefore, need prune.
                            /// M: [Operator] We should also consider OTA from old version without mtkFlag
                            if (!isVendorApp(ps) && !locationIsOperator(ps.codePath)) {
                                continue;
                            }
                        }
                ...
                        final PackageParser.Package scannedPkg = mPackages.get(ps.name);
                        if (scannedPkg != null) {
                            ...
                            if (mSettings.isDisabledSystemPackageLPr(ps.name)) {
                                logCriticalInfo(Log.WARN, "Expecting better updated system app for "
                                        + ps.name + "; removing system app.  Last known codePath="
                                        + ps.codePathString + ", installStatus=" + ps.installStatus
                                        + ", versionCode=" + ps.versionCode + "; scanned versionCode="
                                        + scannedPkg.mVersionCode);
                                removePackageLI(scannedPkg, true);
                                mExpectingBetter.put(ps.name, ps.codePath);
                            }
    
                            continue;
                        }
    
                        if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {
                            psit.remove();
                            logCriticalInfo(Log.WARN, "System package " + ps.name
                                    + " no longer exists; it's data will be wiped");
                            // Actual deletion of code and data will be handled by later
                            // reconciliation step
                        } else {
                            final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps.name);
                            if (disabledPs.codePath == null || !disabledPs.codePath.exists()) {
                                possiblyDeletedUpdatedSystemApps.add(ps.name);
                            }
                        }
                    }
                }
    
                //查找未完成安装的apk
                ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
                for (int i = 0; i < deletePkgsList.size(); i++) {
                    ...
                    final String packageName = deletePkgsList.get(i).name;
                    logCriticalInfo(Log.WARN, "Cleaning up incompletely installed app: " + packageName);
                    synchronized (mPackages) {
                        mSettings.removePackageLPw(packageName);
                    }
                }
    
                //删除temp文件
                deleteTempPackageFiles();
    
                // 删除没有相关软件包的共享用户ID
                mSettings.pruneSharedUsersLPw();
    
                if (!mOnlyCore) {
                    EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
                            SystemClock.uptimeMillis());
            //扫描安装/data/app/目录下的apk文件
                    scanDirTracedLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);
            //扫描安装/data/app/app-private/目录下的apk文件
                    scanDirTracedLI(mDrmAppPrivateInstallDir, mDefParseFlags
                            | PackageParser.PARSE_FORWARD_LOCK,
                            scanFlags | SCAN_REQUIRE_KNOWN, 0);
            //扫描安装/data/app-ephemeral/目录
                    scanDirLI(mEphemeralInstallDir, mDefParseFlags
                            | PackageParser.PARSE_IS_EPHEMERAL,
                            scanFlags | SCAN_REQUIRE_KNOWN, 0);
    
                    /**
                     * Remove disable package settings for any updated system
                     * apps that were removed via an OTA. If they're not a
                     * previously-updated app, remove them completely.
                     * Otherwise, just revoke their system-level permissions.
                     */
                    for (String deletedAppName : possiblyDeletedUpdatedSystemApps) {
                        PackageParser.Package deletedPkg = mPackages.get(deletedAppName);
                        mSettings.removeDisabledSystemPackageLPw(deletedAppName);
    
                        String msg;
                        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 {
                            msg = "Updated system app + " + deletedAppName
                                    + " no longer present; removing system privileges for "
                                    + deletedAppName;
    
                            deletedPkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;
    
                            /// M: [Operator] Revoke operator permissions for the original operator package
                            /// under operator folder was gone due to OTA
                            deletedPkg.applicationInfo.flagsEx &= ~ApplicationInfo.FLAG_EX_OPERATOR;
    
                            PackageSetting deletedPs = mSettings.mPackages.get(deletedAppName);
                            deletedPs.pkgFlags &= ~ApplicationInfo.FLAG_SYSTEM;
    
                            /// M: [Operator] Revoke vendor permissions
                            deletedPs.pkgFlagsEx &= ~ApplicationInfo.FLAG_EX_OPERATOR;
                        }
                        logCriticalInfo(Log.WARN, msg);
                    }
    
                    /**
                     * Make sure all system apps that we expected to appear on
                     * the userdata partition actually showed up. If they never
                     * appeared, crawl back and revive the system version.
                     */
                    for (int i = 0; i < mExpectingBetter.size(); i++) {
                        final String packageName = mExpectingBetter.keyAt(i);
                        if (!mPackages.containsKey(packageName)) {
                            final File scanFile = mExpectingBetter.valueAt(i);
    
                            logCriticalInfo(Log.WARN, "Expected better " + packageName
                                    + " but never showed up; reverting to system");
    
                            int reparseFlags = mDefParseFlags;
                            if (FileUtils.contains(privilegedAppDir, scanFile)) {
                                reparseFlags = PackageParser.PARSE_IS_SYSTEM
                                        | PackageParser.PARSE_IS_SYSTEM_DIR
                                        | PackageParser.PARSE_IS_PRIVILEGED;
                            } else if (FileUtils.contains(systemAppDir, scanFile)) {
                                reparseFlags = PackageParser.PARSE_IS_SYSTEM
                                        | PackageParser.PARSE_IS_SYSTEM_DIR;
                            } else if (FileUtils.contains(vendorAppDir, scanFile)) {
                                reparseFlags = PackageParser.PARSE_IS_SYSTEM
                                        | PackageParser.PARSE_IS_SYSTEM_DIR;
                            } else if (FileUtils.contains(oemAppDir, scanFile)) {
                                reparseFlags = PackageParser.PARSE_IS_SYSTEM
                                        | PackageParser.PARSE_IS_SYSTEM_DIR;
                            } else {
                                Slog.e(TAG, "Ignoring unexpected fallback path " + scanFile);
                                continue;
                            }
    
                            mSettings.enableSystemPackageLPw(packageName);
    
                            try {
                                scanPackageTracedLI(scanFile, reparseFlags, scanFlags, 0, null);
                            } catch (PackageManagerException e) {
                                Slog.e(TAG, "Failed to parse original system package: "
                                        + e.getMessage());
                            }
                        }
                    }
                }
                mExpectingBetter.clear();
    
                //获得开机向导
                mSetupWizardPackage = getSetupWizardPackageName();
                if (mProtectedFilters.size() > 0) {
                    ...
                    for (ActivityIntentInfo filter : mProtectedFilters) {
                        ...
                        filter.setPriority(0);//设置优先级
                    }
                }
                ...
                // 为package更新正确的库文件路径
                updateAllSharedLibrariesLPw();
            ....
                // 更新packages最后使用的时间
                mPackageUsage.readLP();
            ...
                //white/back list
                mForcePermReviewPkgs = new HashSet<String>(
                        Arrays.asList(mContext.getResources().getStringArray(
                                com.mediatek.internal.R.array.force_review_pkgs)));
                ...
                mBlockPermReviewPkgs = new HashSet<String>(
                        Arrays.asList(mContext.getResources().getStringArray(
                                com.mediatek.internal.R.array.block_review_pkgs)));
                ...
                //如果SDK改变,更新权限
                int updateFlags = UPDATE_PERMISSIONS_ALL;
                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;
            ...
                if (!onlyCore && (mPromoteSystemApps || !mRestoredSettings)) {
                    for (UserInfo user : sUserManager.getUsers(true)) {
                        mSettings.applyDefaultPreferredAppsLPw(this, user.id);
                        applyFactoryDefaultBrowserLPw(user.id);
                        primeDomainVerificationsLPw(user.id);
                    }
                }
                //为启动系统核心应用准备storage
                final int storageFlags;
                if (StorageManager.isFileEncryptedNativeOrEmulated()) {
                    storageFlags = StorageManager.FLAG_STORAGE_DE;
                } else {
                    storageFlags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
                }
                reconcileAppsDataLI(StorageManager.UUID_PRIVATE_INTERNAL, UserHandle.USER_SYSTEM,
                        storageFlags);
    
                //以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)) {
                            // No apps are running this early, so no need to freeze
                            clearAppDataLIF(ps.pkg, UserHandle.USER_ALL,
                                    StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE
                                            | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
                        }
                    }
                    ver.fingerprint = Build.FINGERPRINT;
                }
            
            //检查默认浏览器
                checkDefaultBrowser();
            ...
            
            mSettings.writeLPr();
            //第一次开机,升级,执行dexopt
                if ((isFirstBoot() || isUpgrade() || VMRuntime.didPruneDalvikCache()) && !onlyCore) {
                    long start = System.nanoTime();
                    List<PackageParser.Package> coreApps = new ArrayList<>();
                    for (PackageParser.Package pkg : mPackages.values()) {
                        if (pkg.coreApp) {
                            coreApps.add(pkg);
                        }
                    }
    
                    int[] stats = performDexOpt(coreApps, false,
                            getCompilerFilterForReason(REASON_CORE_APP));
    
                    final int elapsedTimeSeconds =
                            (int) TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - start);
                    MetricsLogger.histogram(mContext, "opt_coreapps_time_s", elapsedTimeSeconds);
            ...
                }
            ...
            //初始化PackageInstallerService
                mInstallerService = new PackageInstallerService(context, this);
    
            //为系统组件公开私有服务
            LocalServices.addService(PackageManagerInternal.class, new PackageManagerInternalImpl());
    
            //permission记录控制
            if (CtaUtils.isCtaSupported()) {
                mPermRecordController = new PermissionRecordController(mContext);
            }
        }
    

    创建过程总结:
    1、准备:创建Settings保存apk信息,分配UID,PackageDexOptimizer初始化,移动app的监听,Permission监听,启动消息线程
    2、目录创建:data目录创建,保存lib路径,创建system/framework
    3、扫描并安装:overlay资源覆盖包,扫描各种路径下的apk信息,安装,删除temp文件
    4、更新:获得开机向导,跟新库文件路径,更新package使用时间,更新权限
    5、准备完毕:准备storage,检查默认浏览器,执行dexopt,初始化PackageInstallerService,公开私有服务

    小结

    PMS启动分析到此结束,主要过程就是PMS的创建,这里只是对整个初始化过程进行一个整体的小结。把握PMS的整体流程,后续文章再对PMS进行细节分析。

    相关文章

      网友评论

        本文标题:PackageManagerService启动分析

        本文链接:https://www.haomeiwen.com/subject/vdkssxtx.html