美文网首页
基于Android9.0的PackageManagerServi

基于Android9.0的PackageManagerServi

作者: android_coder | 来源:发表于2019-05-12 15:54 被阅读0次

PackageManagerService启动流程(下)
我们先看下PMS的启动过程,这部分主要是涉及SystemServer的startOtherServices方法

if (!mOnlyCore) {
        traceBeginAndSlog("UpdatePackagesIfNeeded");
        try {
            mPackageManagerService.updatePackagesIfNeeded();
        } catch (Throwable e) {
            reportWtf("update packages", e);
        }
        traceEnd();
    }

    traceBeginAndSlog("PerformFstrimIfNeeded");
    try {
        mPackageManagerService.performFstrimIfNeeded();
    } catch (Throwable e) {
        reportWtf("performing fstrim", e);
    }
 traceEnd();
......
traceBeginAndSlog("MakePackageManagerServiceReady");
mPackageManagerService.systemReady();
traceEnd();
........
// Wait for all packages to be prepared
mPackageManagerService.waitForAppDataPrepared();
........

上部分我们主要是介绍PMS的初始化过程,这部分我们主要涉及到下面的几个方法

mPackageManagerService.updatePackagesIfNeeded
mPackageManagerService.performFstrimIfNeeded
mPackageManagerService.systemReady
mPackageManagerService.waitForAppDataPrepared

我们接下来按照上面的几个方法介绍

PMS之updatePackagesIfNeeded

public void updatePackagesIfNeeded() {
    //只有system或是root用户才有权限
    enforceSystemOrRoot("Only the system can request package update");

    // We need to re-extract after an OTA.
    boolean causeUpgrade = isUpgrade();//判断是否是ota

    // First boot or factory reset.
    // Note: we also handle devices that are upgrading to N right now as if it is their
    //       first boot, as they do not have profile data.
    boolean causeFirstBoot = isFirstBoot() || mIsPreNUpgrade;//是否是第一次启动或是升级到Android N
    // We need to re-extract after a pruned cache, as AoT-ed files will be out of date.
    //判断是否有清除过dalvik虚拟机的缓存
    boolean causePrunedCache = VMRuntime.didPruneDalvikCache();
    //如果上面的三个都没有,那么就不进行任何操作
    if (!causeUpgrade && !causeFirstBoot && !causePrunedCache) {
        return;
    }
    List<PackageParser.Package> pkgs;
    synchronized (mPackages) {
    //按照package的优先级进行排序,core app >system app > other app
        pkgs = PackageManagerServiceUtils.getPackagesForDexopt(mPackages.values(), this);
    }
    final long startTime = System.nanoTime();//记录开始时间
    final int[] stats = performDexOptUpgrade(pkgs, mIsPreNUpgrade /* showDialog */,
                causeFirstBoot ? REASON_FIRST_BOOT : REASON_BOOT,
                false /* bootComplete */);
    final int elapsedTimeSeconds =
            (int) TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - startTime);
    MetricsLogger.histogram(mContext, "opt_dialog_num_dexopted", stats[0]);
    MetricsLogger.histogram(mContext, "opt_dialog_num_skipped", stats[1]);
    MetricsLogger.histogram(mContext, "opt_dialog_num_failed", stats[2]);
    MetricsLogger.histogram(mContext, "opt_dialog_num_total", getOptimizablePackages().size());
    MetricsLogger.histogram(mContext, "opt_dialog_time_s", elapsedTimeSeconds);
}

PMS之performDexOptUpgrade

//odex优化操作
private int[] performDexOptUpgrade(List<PackageParser.Package> pkgs, boolean showDialog,
        final int compilationReason, boolean bootComplete) {
    int numberOfPackagesVisited = 0;
    int numberOfPackagesOptimized = 0;
    int numberOfPackagesSkipped = 0;
    int numberOfPackagesFailed = 0;
    final int numberOfPackagesToDexopt = pkgs.size();
    for (PackageParser.Package pkg : pkgs) {
        numberOfPackagesVisited++;
        boolean useProfileForDexopt = false;
        //第一次启动或是ota升级之后并且是系统应用才会进行odex
        if ((isFirstBoot() || isUpgrade()) && isSystemApp(pkg)) {
            // Copy over initial preopt profiles since we won't get any JIT samples for methods
            // that are already compiled.
            File profileFile = new File(getPrebuildProfilePath(pkg));
            // Copy profile if it exists.
            //判断profile文件是否存在
            if (profileFile.exists()) {
                try {
                    // We could also do this lazily before calling dexopt in
                    // PackageDexOptimizer to prevent this happening on first boot. The issue
                    // is that we don't have a good way to say "do this only once".
                    if (!mInstaller.copySystemProfile(profileFile.getAbsolutePath(),
                            pkg.applicationInfo.uid, pkg.packageName,
                            ArtManager.getProfileName(null))) {
                        Log.e(TAG, "Installer failed to copy system profile!");
                    } else {
                        // Disabled as this causes speed-profile compilation during first boot
                        // even if things are already compiled.
                        // useProfileForDexopt = true;
                    }
                } catch (Exception e) {
                    Log.e(TAG, "Failed to copy profile " + profileFile.getAbsolutePath() + " ",
                            e);
                }
            } else {
                PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(pkg.packageName);
                // Handle compressed APKs in this path. Only do this for stubs with profiles to
                // minimize the number off apps being speed-profile compiled during first boot.
                // The other paths will not change the filter.
                if (disabledPs != null && disabledPs.pkg.isStub) {
                    // The package is the stub one, remove the stub suffix to get the normal
                    // package and APK names.
                    String systemProfilePath =
                            getPrebuildProfilePath(disabledPs.pkg).replace(STUB_SUFFIX, "");
                    profileFile = new File(systemProfilePath);
                    // If we have a profile for a compressed APK, copy it to the reference
                    // location.
                    // Note that copying the profile here will cause it to override the
                    // reference profile every OTA even though the existing reference profile
                    // may have more data. We can't copy during decompression since the
                    // directories are not set up at that point.
                    if (profileFile.exists()) {
                        try {
                            // We could also do this lazily before calling dexopt in
                            // PackageDexOptimizer to prevent this happening on first boot. The
                            // issue is that we don't have a good way to say "do this only
                            // once".
                            if (!mInstaller.copySystemProfile(profileFile.getAbsolutePath(),
                                    pkg.applicationInfo.uid, pkg.packageName,
                                    ArtManager.getProfileName(null))) {
                                Log.e(TAG, "Failed to copy system profile for stub package!");
                            } else {
                                useProfileForDexopt = true;
                            }
                        } catch (Exception e) {
                            Log.e(TAG, "Failed to copy profile " +
                                    profileFile.getAbsolutePath() + " ", e);
                        }
                    }
                }
            }
        }
        if (!PackageDexOptimizer.canOptimizePackage(pkg)) {
            if (DEBUG_DEXOPT) {
                Log.i(TAG, "Skipping update of of non-optimizable app " + pkg.packageName);
            }
            numberOfPackagesSkipped++;
            continue;
        }
        if (DEBUG_DEXOPT) {
            Log.i(TAG, "Updating app " + numberOfPackagesVisited + " of " +
                    numberOfPackagesToDexopt + ": " + pkg.packageName);
        }
        if (showDialog) {
            try {
                ActivityManager.getService().showBootMessage(
                        mContext.getResources().getString(R.string.android_upgrading_apk,
                                numberOfPackagesVisited, numberOfPackagesToDexopt), true);
            } catch (RemoteException e) {
            }
            synchronized (mPackages) {
                mDexOptDialogShown = true;
            }
        }
        int pkgCompilationReason = compilationReason;
        if (useProfileForDexopt) {
            // Use background dexopt mode to try and use the profile. Note that this does not
            // guarantee usage of the profile.
            pkgCompilationReason = PackageManagerService.REASON_BACKGROUND_DEXOPT;
        }
        // checkProfiles is false to avoid merging profiles during boot which
        // might interfere with background compilation (b/28612421).
        // Unfortunately this will also means that "pm.dexopt.boot=speed-profile" will
        // behave differently than "pm.dexopt.bg-dexopt=speed-profile" but that's a
        // trade-off worth doing to save boot time work.
        int dexoptFlags = bootComplete ? DexoptOptions.DEXOPT_BOOT_COMPLETE : 0;
        if (compilationReason == REASON_FIRST_BOOT) {
            // TODO: This doesn't cover the upgrade case, we should check for this too.
            dexoptFlags |= DexoptOptions.DEXOPT_INSTALL_WITH_DEX_METADATA_FILE;
        }
        //最终是调用mInstaller.dexopt完成优化的,installd守护进程,installer安装器和Installd通信
        int primaryDexOptStaus = performDexOptTraced(new DexoptOptions(
                pkg.packageName,
                pkgCompilationReason,
                dexoptFlags));
        switch (primaryDexOptStaus) {
            case PackageDexOptimizer.DEX_OPT_PERFORMED:
                numberOfPackagesOptimized++;//odex优化完成的应用
                break;
            case PackageDexOptimizer.DEX_OPT_SKIPPED:
                numberOfPackagesSkipped++;//跳过的应用
                break;
            case PackageDexOptimizer.DEX_OPT_FAILED:
                numberOfPackagesFailed++;//失败的应用
                break;
            default:
                Log.e(TAG, "Unexpected dexopt return code " + primaryDexOptStaus);
                break;
        }
    }
    return new int[] { numberOfPackagesOptimized, numberOfPackagesSkipped,
            numberOfPackagesFailed };
}
上面的方法主要是判断是否需要对package进行更新,如果需要更新那么按照优先级完成dex优化

PMS之performFstrimIfNeeded

public void performFstrimIfNeeded() {
    enforceSystemOrRoot("Only the system can request fstrim");
    // Before everything else, see whether we need to fstrim.
    try {
        //获取mountSerice服务
        IStorageManager sm = PackageHelper.getStorageManager();
        if (sm != null) {
            boolean doTrim = false;
            //获取执行FTRIM间隔,默认是3天,可以通过setting provider更改这个时间
            final long interval = android.provider.Settings.Global.getLong(
                    mContext.getContentResolver(),
                    android.provider.Settings.Global.FSTRIM_MANDATORY_INTERVAL,
                    DEFAULT_MANDATORY_FSTRIM_INTERVAL);
            if (interval > 0) {
                final long timeSinceLast = System.currentTimeMillis() - sm.lastMaintenance();
                if (timeSinceLast > interval) {
                    doTrim = true;//如果超过了三天就进行磁盘清理
                    Slog.w(TAG, "No disk maintenance in " + timeSinceLast
                            + "; running immediately");
                }
            }
            if (doTrim) {
                final boolean dexOptDialogShown;
                synchronized (mPackages) {
                    dexOptDialogShown = mDexOptDialogShown;
                }
                if (!isFirstBoot() && dexOptDialogShown) {
                    //如果不是第一次启动,显示一个提示框
                    try {
                        ActivityManager.getService().showBootMessage(
                                mContext.getResources().getString(
                                        R.string.android_upgrading_fstrim), true);
                    } catch (RemoteException e) {
                    }
                }
                // 发送消息H_FSTRIM给handler,然后再向vold发送fstrim命令
                sm.runMaintenance();
            }
        } else {
            Slog.e(TAG, "storageManager service unavailable!");
        }
    } catch (RemoteException e) {
        // Can't happen; StorageManagerService is local
    }
}

上面主要是执行磁盘清理工作,释放磁盘空间。

PMS之SystemReady

traceBeginAndSlog("MakePackageManagerServiceReady");
mPackageManagerService.systemReady();
traceEnd();
...............................................................................
public void systemReady() {
    enforceSystemOrRoot("Only the system can claim the system is ready");
    mSystemReady = true;
    final ContentResolver resolver = mContext.getContentResolver();
    ContentObserver co = new ContentObserver(mHandler) {
        @Override
        public void onChange(boolean selfChange) {
            mWebInstantAppsDisabled =
                    (Global.getInt(resolver, Global.ENABLE_EPHEMERAL_FEATURE, 1) == 0) ||
                            (Secure.getInt(resolver, Secure.INSTANT_APPS_ENABLED, 1) == 0);
        }
    };//小程序
   mContext.getContentResolver().registerContentObserver(android.provider.Settings.Global
                    .getUriFor(Global.ENABLE_EPHEMERAL_FEATURE),
            false, co, UserHandle.USER_SYSTEM);
  mContext.getContentResolver().registerContentObserver(android.provider.Settings.Secure
                    .getUriFor(Secure.INSTANT_APPS_ENABLED), false, co, UserHandle.USER_SYSTEM);
    co.onChange(true);//注册一个监听
    // Disable any carrier apps. We do this very early in boot to prevent the apps from being
    // disabled after already being started.
    CarrierAppUtils.disableCarrierAppsUntilPrivileged(mContext.getOpPackageName(), this,
            mContext.getContentResolver(), UserHandle.USER_SYSTEM);
    // Read the compatibilty setting when the system is ready.
    boolean compatibilityModeEnabled = android.provider.Settings.Global.getInt(
            mContext.getContentResolver(),
            android.provider.Settings.Global.COMPATIBILITY_MODE, 1) == 1;
    PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
    if (DEBUG_SETTINGS) {
        Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
    }
    int[] grantPermissionsUserIds = EMPTY_INT_ARRAY;
    synchronized (mPackages) {
        // Verify that all of the preferred activity components actually
        // exist.  It is possible for applications to be updated and at
        // that point remove a previously declared activity component that
        // had been set as a preferred activity.  We try to clean this up
        // the next time we encounter that preferred activity, but it is
        // possible for the user flow to never be able to return to that
        // situation so here we do a sanity check to make sure we haven't
        // left any junk around.
        ArrayList<PreferredActivity> removed = new ArrayList<PreferredActivity>();
        for (int i=0; i<mSettings.mPreferredActivities.size(); i++) {
            PreferredIntentResolver pir = mSettings.mPreferredActivities.valueAt(i);
            removed.clear();
            for (PreferredActivity pa : pir.filterSet()) {
                if (mActivities.mActivities.get(pa.mPref.mComponent) == null) {
                    removed.add(pa);
                }
            }//移除不存在的先前用户设置保存的优先选择的activity组件
            if (removed.size() > 0) {
                for (int r=0; r<removed.size(); r++) {
                    PreferredActivity pa = removed.get(r);
                    Slog.w(TAG, "Removing dangling preferred activity: "
                            + pa.mPref.mComponent);
                    pir.removeFilter(pa);
                }
                mSettings.writePackageRestrictionsLPr(
                        mSettings.mPreferredActivities.keyAt(i));//写入到文件中
            }
        }
        for (int userId : UserManagerService.getInstance().getUserIds()) {
            if (!mSettings.areDefaultRuntimePermissionsGrantedLPr(userId)) {
                grantPermissionsUserIds = ArrayUtils.appendInt(
                        grantPermissionsUserIds, userId);
            }
        }
    }
    sUserManager.systemReady();//多用户服务的systemReady方法
    // If we upgraded grant all default permissions before kicking off.
    for (int userId : grantPermissionsUserIds) {
        mDefaultPermissionPolicy.grantDefaultPermissions(userId);//默认授权操作
    }
    if (grantPermissionsUserIds == EMPTY_INT_ARRAY) {
        // If we did not grant default permissions, we preload from this the
        // default permission exceptions lazily to ensure we don't hit the
        // disk on a new user creation.
        mDefaultPermissionPolicy.scheduleReadDefaultPermissionExceptions();
    }
    // Now that we've scanned all packages, and granted any default
    // permissions, ensure permissions are updated. Beware of dragons if you
    // try optimizing this.
    synchronized (mPackages) {
        mPermissionManager.updateAllPermissions(
                StorageManager.UUID_PRIVATE_INTERNAL, false, mPackages.values(),
                mPermissionCallback);//更新权限信息
    }
    // Kick off any messages waiting for system ready
    if (mPostSystemReadyMessages != null) {
        for (Message msg : mPostSystemReadyMessages) {
            msg.sendToTarget();
        }
        mPostSystemReadyMessages = null;
    }
    // Watch for external volumes that come and go over time
    final StorageManager storage = mContext.getSystemService(StorageManager.class);
    storage.registerListener(mStorageListener);
    mInstallerService.systemReady();
    mDexManager.systemReady();
    mPackageDexOptimizer.systemReady();
    StorageManagerInternal StorageManagerInternal = LocalServices.getService(
            StorageManagerInternal.class);
    StorageManagerInternal.addExternalStoragePolicy(
            new StorageManagerInternal.ExternalStorageMountPolicy() {
        @Override
        public int getMountMode(int uid, String packageName) {
            if (Process.isIsolated(uid)) {
                return Zygote.MOUNT_EXTERNAL_NONE;
            }
            if (checkUidPermission(READ_EXTERNAL_STORAGE, uid) == PERMISSION_DENIED) {
                return Zygote.MOUNT_EXTERNAL_DEFAULT;
            }
            if (checkUidPermission(WRITE_EXTERNAL_STORAGE, uid) == PERMISSION_DENIED) {
                return Zygote.MOUNT_EXTERNAL_READ;
            }
            return Zygote.MOUNT_EXTERNAL_WRITE;
        }
        @Override
        public boolean hasExternalStorage(int uid, String packageName) {
            return true;
        }
    });
    //清除过期的userid和app
    // Now that we're mostly running, clean up stale users and apps
    sUserManager.reconcileUsers(StorageManager.UUID_PRIVATE_INTERNAL);
    reconcileApps(StorageManager.UUID_PRIVATE_INTERNAL);
    mPermissionManager.systemReady();
    if (mInstantAppResolverConnection != null) {
        mContext.registerReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                mInstantAppResolverConnection.optimisticBind();
                mContext.unregisterReceiver(this);
            }
        }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
    }
}

PMS之grantDefaultPermissions

public void grantDefaultPermissions(int userId) {
    grantPermissionsToSysComponentsAndPrivApps(userId);
    grantDefaultSystemHandlerPermissions(userId);
    grantDefaultPermissionExceptions(userId);
}
...........................................
private void grantPermissionsToSysComponentsAndPrivApps(int userId) {
    Log.i(TAG, "Granting permissions to platform components for user " + userId);
    final PackageList packageList = mServiceInternal.getPackageList();
    for (String packageName : packageList.getPackageNames()) {
        final PackageParser.Package pkg = mServiceInternal.getPackage(packageName);
        if (pkg == null) {
            continue;
        }
        if (!isSysComponentOrPersistentPlatformSignedPrivApp(pkg)//不是系统组件或是常驻的priv-app
                || !doesPackageSupportRuntimePermissions(pkg)//不支持dangerous权限
                || pkg.requestedPermissions.isEmpty()) {//没有请求权限
            continue;
        }
        grantRuntimePermissionsForPackage(userId, pkg);
    }
}
.................................................
private void grantRuntimePermissionsForPackage(int userId, PackageParser.Package pkg) {
    Set<String> permissions = new ArraySet<>();
    for (String permission :  pkg.requestedPermissions) {
        final BasePermission bp = mPermissionManager.getPermission(permission);
        if (bp == null) {
            continue;
        }
        if (bp.isRuntime()) {//如果是dangerous权限
            permissions.add(permission);
        }
    }
    if (!permissions.isEmpty()) {
        grantRuntimePermissions(pkg, permissions, true, userId);
    }
}
..................................................
private void grantRuntimePermissions(PackageParser.Package pkg, Set<String> permissions,
        boolean systemFixed, boolean ignoreSystemPackage, int userId) {
    if (pkg.requestedPermissions.isEmpty()) {
        return;
    }
    List<String> requestedPermissions = pkg.requestedPermissions;
    Set<String> grantablePermissions = null;

    // In some cases, like for the Phone or SMS app, we grant permissions regardless
    // of if the version on the system image declares the permission as used since
    // selecting the app as the default for that function the user makes a deliberate
    // choice to grant this app the permissions needed to function. For all other
    // apps, (default grants on first boot and user creation) we don't grant default
    // permissions if the version on the system image does not declare them.
    if (!ignoreSystemPackage && pkg.isUpdatedSystemApp()) {//系统应用升级
        final PackageParser.Package disabledPkg =
                mServiceInternal.getDisabledPackage(pkg.packageName);
        if (disabledPkg != null) {//被disable掉的应用
            if (disabledPkg.requestedPermissions.isEmpty()) {
                return;
            }
            if (!requestedPermissions.equals(disabledPkg.requestedPermissions)) {
                grantablePermissions = new ArraySet<>(requestedPermissions);
                requestedPermissions = disabledPkg.requestedPermissions;
            }
        }
    }
    final int grantablePermissionCount = requestedPermissions.size();
    for (int i = 0; i < grantablePermissionCount; i++) {
        String permission = requestedPermissions.get(i);

        // If there is a disabled system app it may request a permission the updated
        // version ot the data partition doesn't, In this case skip the permission.
        if (grantablePermissions != null && !grantablePermissions.contains(permission)) {
            continue;//如果系统应用升级了 但是最新的版本不存在该权限
        }
        if (permissions.contains(permission)) {
            final int flags = mServiceInternal.getPermissionFlagsTEMP(
                    permission, pkg.packageName, userId);

            // If any flags are set to the permission, then it is either set in
            // its current state by the system or device/profile owner or the user.
            // In all these cases we do not want to clobber the current state.
            // Unless the caller wants to override user choices. The override is
            // to make sure we can grant the needed permission to the default
            // sms and phone apps after the user chooses this in the UI.
            if (flags == 0 || ignoreSystemPackage) {
                // Never clobber policy fixed permissions.
                // We must allow the grant of a system-fixed permission because
                // system-fixed is sticky, but the permission itself may be revoked.
                if ((flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
                    continue;
                }

                mServiceInternal.grantRuntimePermission(
                        pkg.packageName, permission, userId, false);
                if (DEBUG) {
                    Log.i(TAG, "Granted " + (systemFixed ? "fixed " : "not fixed ")
                            + permission + " to default handler " + pkg.packageName);
                }
                int newFlags = PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
                if (systemFixed) {
                    newFlags |= PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
                }
                //最终是通过updatePermissionFlag来完成的
                mServiceInternal.updatePermissionFlagsTEMP(permission, pkg.packageName,
                        newFlags, newFlags, userId);
            }
            // If a component gets a permission for being the default handler A
            // and also default handler B, we grant the weaker grant form.
            if ((flags & PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT) != 0
                    && (flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0
                    && !systemFixed) {
                if (DEBUG) {
                    Log.i(TAG, "Granted not fixed " + permission + " to default handler "
                            + pkg.packageName);
                }
                mServiceInternal.updatePermissionFlagsTEMP(permission, pkg.packageName,
                        PackageManager.FLAG_PERMISSION_SYSTEM_FIXED, 0, userId);
            }
        }
    }
}
.....................................................................
private void updatePermissionFlags(String permName, String packageName, int flagMask,
        int flagValues, int callingUid, int userId, PermissionCallback callback) {
    if (!mUserManagerInt.exists(userId)) {
        return;
    }
    enforceGrantRevokeRuntimePermissionPermissions("updatePermissionFlags");
    enforceCrossUserPermission(callingUid, userId,
            true,  // requireFullPermission
            true,  // checkShell
            false, // requirePermissionWhenSameUser
            "updatePermissionFlags");
    // Only the system can change these flags and nothing else.
    if (callingUid != Process.SYSTEM_UID) {
        flagMask &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
        flagValues &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
        flagMask &= ~PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
        flagValues &= ~PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
        flagValues &= ~PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
    }
    final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
    if (pkg == null || pkg.mExtras == null) {
        throw new IllegalArgumentException("Unknown package: " + packageName);
    }
    if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
        throw new IllegalArgumentException("Unknown package: " + packageName);
    }
    final BasePermission bp;
    synchronized (mLock) {
        bp = mSettings.getPermissionLocked(permName);
    }
    if (bp == null) {
        throw new IllegalArgumentException("Unknown permission: " + permName);
    }
    final PackageSetting ps = (PackageSetting) pkg.mExtras;
    final PermissionsState permissionsState = ps.getPermissionsState();
    final boolean hadState =
            permissionsState.getRuntimePermissionState(permName, userId) != null;
    final boolean permissionUpdated =
            permissionsState.updatePermissionFlags(bp, userId, flagMask, flagValues);
    if (permissionUpdated && callback != null) {
        // Install and runtime permissions are stored in different places,
        // so figure out what permission changed and persist the change.
        if (permissionsState.getInstallPermissionState(permName) != null) {
            callback.onInstallPermissionUpdated();
        } else if (permissionsState.getRuntimePermissionState(permName, userId) != null
                || hadState) {
            callback.onPermissionUpdated(new int[] { userId }, false);
        }
    }
}

onPermissionUpdated的实现

//把runtime权限跟新到runtime-permissions.xml中

  @Override
  public void onPermissionUpdated(int[] updatedUserIds, boolean sync) {
        synchronized (mPackages) {
            for (int userId : updatedUserIds) {
                mSettings.writeRuntimePermissionsForUserLPr(userId, sync);
            }
        }
  }

systemReady主要完成的是默认授权和更新package的信息,通知在等待pms的一些组件

PMS之waitForAppDataPrepared

public void waitForAppDataPrepared() {
    if (mPrepareAppDataFuture == null) {
        return;
    }
    ConcurrentUtils.waitForFutureNoInterrupt(mPrepareAppDataFuture, "wait for prepareAppData");
    mPrepareAppDataFuture = null;
}
....................................................
public static <T> T waitForFutureNoInterrupt(Future<T> future, String description) {
    try {
        return future.get();
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        throw new IllegalStateException(description + " interrupted");
    } catch (ExecutionException e) {
        throw new RuntimeException(description + " failed", e);
    }
}

获取特定的feature
至此pms启动流程的下半部分就分析完成

相关文章

网友评论

      本文标题:基于Android9.0的PackageManagerServi

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