[Android][Framework]PackageManagerService处理应用权限流程

  • 2020 年 1 月 21 日
  • 笔记

app种类

1、system app (有ApplicationInfo.FLAG_SYSTEM标记)

2、privileged app (有ApplicationInfo.FLAG_SYSTEM和ApplicationInfo.PRIVATE_FLAG_PRIVILEGE两个标记)

system app

system app 定义很明了,就是在PMS初始化安装app的时候赋予了ApplicationInfo.FLAG_SYSTEM这个标记

1、特定shareUID的app 代码在PMS的构造函数中

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);

2、扫描安装特定目录的app 代码在PMS的构造函数中,扫描安装时给予PackageParser.PARSE_IS_SYSTEM标记的app,例如/vendor/overlay,/system/framework,/system/priv-app,/system/app,/vendor/app,/oem/app等,给予的PackageParser.PARSE_IS_SYSTEM最终会转换为ApplicationInfo.FLAG_SYSTEM,部分代码如下

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);  File customFrameworkDir = new File("/custom/framework");      scanDirLI(customFrameworkDir, PackageParser.PARSE_IS_SYSTEM              | PackageParser.PARSE_IS_SYSTEM_DIR,              scanFlags | SCAN_NO_DEX, 0);  scanDirTracedLI(frameworkDir, mDefParseFlags              | PackageParser.PARSE_IS_SYSTEM              | PackageParser.PARSE_IS_SYSTEM_DIR              | PackageParser.PARSE_IS_PRIVILEGED,              scanFlags | SCAN_NO_DEX, 0);

flag转换的过程大致如下

-> scanDirLI(File dir, final int parseFlags, int scanFlags, long currentTime)  ->  scanPackageTracedLI(PackageParser.Package pkg, final int policyFlags,          int scanFlags, long currentTime, UserHandle user)  -> scanPackageLI(PackageParser.Package pkg, final int policyFlags,              int scanFlags, long currentTime, UserHandle user)  -> scanPackageDirtyLI(PackageParser.Package pkg,              final int policyFlags, final int scanFlags, long currentTime, UserHandle user)  //在scanPackageDirtyLI方法中将flag转换  // Apply policy  if ((policyFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {      pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;      ...  }

privileged app

privileged app在ApplicationInfo.FLAG_SYSTEM基础上还必须有ApplicationInfo.PRIVATE_FLAG_PRIVILEGED标记

1、特定shareUID的app 特定shareUID的app有ApplicationInfo.FLAG_SYSTEM的同时都有ApplicationInfo.PRIVATE_FLAG_PRIVILEGED

2、扫描特定目录app时,给予了PackageParser.PARSE_IS_SYSTEM标记和PackageParser.PARSE_IS_PRIVILEGED标记,目录有三个:system/framework,system/priv-app,vendor/priv-app 例如:

//vender/framework目录下有PackageParser.PARSE_IS_SYSTEM没有PackageParser.PARSE_IS_PRIVILEGED标记  File vendorFrameworkDir = new File(Environment.getVendorDirectory(), "framework");  scanDirTracedLI(vendorFrameworkDir, PackageParser.PARSE_IS_SYSTEM      | PackageParser.PARSE_IS_SYSTEM_DIR,      scanFlags | SCAN_NO_DEX, 0);    //system/framework目录下两个标记都有  scanDirTracedLI(frameworkDir, mDefParseFlags      | PackageParser.PARSE_IS_SYSTEM      | PackageParser.PARSE_IS_SYSTEM_DIR      | PackageParser.PARSE_IS_PRIVILEGED,      scanFlags | SCAN_NO_DEX, 0);

PackageParser.PARSE_IS_PRIVILEGED也是在scanPackageDirtyLI方法中转换的

if ((policyFlags&PackageParser.PARSE_IS_PRIVILEGED) != 0) {              pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;          }

PMS赋予apk的runtime权限

入口

PMS(PackageManagerService)在SystemServer中初始化完成最后调用PMS::systemReady,在systemReady方法中开始授予默认权限

final DefaultPermissionGrantPolicy mDefaultPermissionPolicy;  for (int userId : grantPermissionsUserIds) {              mDefaultPermissionPolicy.grantDefaultPermissions(userId);          }

DefaultPermissionGrantPolicy这个类就是管理默认权限的,最终的实现都是在PMS代码中

public void grantDefaultPermissions(int userId) {      // 系统组件赋予Dangerous权限          grantPermissionsToSysComponentsAndPrivApps(userId);      // 指定app的指定权限          grantDefaultSystemHandlerPermissions(userId);      }

系统组件赋予Dangerous权限

private void grantPermissionsToSysComponentsAndPrivApps(int userId) {          Log.i(TAG, "Granting permissions to platform components for user " + userId);            synchronized (mService.mPackages) {              for (PackageParser.Package pkg : mService.mPackages.values()) {              // 过滤掉privileged app , FLAG_PERSISTENT标记app ,系统签名相同的app                  if (!isSysComponentOrPersistentPlatformSignedPrivAppLPr(pkg)              // 判断targetSdkVersion > 22                          || !doesPackageSupportRuntimePermissions(pkg)              // 请求权限列表为空                          || pkg.requestedPermissions.isEmpty()) {                      continue;                  }                  Set<String> permissions = new ArraySet<>();                  final int permissionCount = pkg.requestedPermissions.size();                  for (int i = 0; i < permissionCount; i++) {                      String permission = pkg.requestedPermissions.get(i);                      BasePermission bp = mService.mSettings.mPermissions.get(permission);              // 权限为Dangerous权限                      if (bp != null && bp.isRuntime()) {                          permissions.add(permission);                      }                  }                  if (!permissions.isEmpty()) {              // 添加权限                      grantRuntimePermissionsLPw(pkg, permissions, true, userId);                  }              }          }      }

接下来看下isSysComponentOrPersistentPlatformSignedPrivAppLPr和isRuntime的内容

private boolean isSysComponentOrPersistentPlatformSignedPrivAppLPr(PackageParser.Package pkg) {      // UserID 小于10000          if (UserHandle.getAppId(pkg.applicationInfo.uid) < FIRST_APPLICATION_UID) {              return true;          }      // privileged app过滤          if (!pkg.isPrivilegedApp()) {              return false;          }      // 这两个判断过滤掉FLAG_PERSISTENT          PackageSetting sysPkg = mService.mSettings.getDisabledSystemPkgLPr(pkg.packageName);          if (sysPkg != null && sysPkg.pkg != null) {              if ((sysPkg.pkg.applicationInfo.flags & ApplicationInfo.FLAG_PERSISTENT) == 0) {                  return false;              }          } else if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_PERSISTENT) == 0) {              return false;          }      // 过滤掉系统签名相同的apk          return PackageManagerService.compareSignatures(mService.mPlatformPackage.mSignatures,                  pkg.mSignatures) == PackageManager.SIGNATURE_MATCH;      }  public boolean isRuntime() {      // protectionLevel & PermissionInfo.PROTECTION_MASK_BASE 表示当前等级          return (protectionLevel & PermissionInfo.PROTECTION_MASK_BASE)                  == PermissionInfo.PROTECTION_DANGEROUS;      }

指定app的指定权限

这里是给指定某个app,给予它指定的几个权限,这里的代码十分类似,截取片段如下

private void grantDefaultSystemHandlerPermissions(int userId) {      ...      // Dialer              if (dialerAppPackageNames == null) {                  Intent dialerIntent = new Intent(Intent.ACTION_DIAL);                  PackageParser.Package dialerPackage = getDefaultSystemHandlerActivityPackageLPr(                          dialerIntent, userId);                  if (dialerPackage != null) {                      grantDefaultPermissionsToDefaultSystemDialerAppLPr(dialerPackage, userId);                  }              } else {                  for (String dialerAppPackageName : dialerAppPackageNames) {                      PackageParser.Package dialerPackage = getSystemPackageLPr(dialerAppPackageName);                      if (dialerPackage != null) {                          grantDefaultPermissionsToDefaultSystemDialerAppLPr(dialerPackage, userId);                      }                  }              }                // SMS              if (smsAppPackageNames == null) {                  Intent smsIntent = new Intent(Intent.ACTION_MAIN);                  smsIntent.addCategory(Intent.CATEGORY_APP_MESSAGING);                  PackageParser.Package smsPackage = getDefaultSystemHandlerActivityPackageLPr(                          smsIntent, userId);                  if (smsPackage != null) {                     grantDefaultPermissionsToDefaultSystemSmsAppLPr(smsPackage, userId);                  }              } else {                  for (String smsPackageName : smsAppPackageNames) {                      PackageParser.Package smsPackage = getSystemPackageLPr(smsPackageName);                      if (smsPackage != null) {                          grantDefaultPermissionsToDefaultSystemSmsAppLPr(smsPackage, userId);                      }                  }              }      ...  }  private void grantDefaultPermissionsToDefaultSystemDialerAppLPr(              PackageParser.Package dialerPackage, int userId) {          if (doesPackageSupportRuntimePermissions(dialerPackage)) {              boolean isPhonePermFixed =                      mService.hasSystemFeature(PackageManager.FEATURE_WATCH, 0);              grantRuntimePermissionsLPw(                      dialerPackage, PHONE_PERMISSIONS, isPhonePermFixed, userId);              grantRuntimePermissionsLPw(dialerPackage, CONTACTS_PERMISSIONS, userId);              grantRuntimePermissionsLPw(dialerPackage, SMS_PERMISSIONS, userId);              grantRuntimePermissionsLPw(dialerPackage, MICROPHONE_PERMISSIONS, userId);          }      }

两种添加最后都走到了grantRuntimePermissionsLPw,我们接着分析grantRuntimePermissionsLPw函数

添加权限grantRuntimePermissionsLPw

grantRuntimePermissionsLPw赋予权限的代码,最终是交给PMS来处理,经过一些列判断后调用关键方法mService.grantRuntimePermission和mService.updatePermissionFlags,代码片段如下

private final PackageManagerService mService;  private void grantRuntimePermissionsLPw(PackageParser.Package pkg, Set<String> permissions,      boolean systemFixed, boolean isDefaultPhoneOrSms, int userId) {      ...      mService.grantRuntimePermission(pkg.packageName, permission, userId);      ...      mService.updatePermissionFlags(permission, pkg.packageName,      newFlags, newFlags, userId);      ...  }

接着看PMS的grantRuntimePermission如何添加权限

    public void grantRuntimePermission(String packageName, String name, final int userId) {          ...      // 要添加权限,也需要“添加”权限          mContext.enforceCallingOrSelfPermission(                  android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,                  "grantRuntimePermission");      enforceCrossUserPermission(Binder.getCallingUid(), userId,                  true /* requireFullPermission */, true /* checkShell */,                  "grantRuntimePermission");          ...      // 添加权限      final int result = permissionsState.grantRuntimePermission(bp, userId);      switch (result) {      case PermissionsState.PERMISSION_OPERATION_FAILURE: {          return;      }        case PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED: {          final int appId = UserHandle.getAppId(pkg.applicationInfo.uid);          mHandler.post(new Runnable() {          @Override          public void run() {              killUid(appId, userId, KILL_APP_REASON_GIDS_CHANGED);          }          });      }      break;      }      // PermissionsChanged监听      mOnPermissionChangeListeners.onPermissionsChanged(uid);        // 把数据更新到runtime-permissions.xml中      mSettings.writeRuntimePermissionsForUserLPr(userId, false);  }

最后grantRuntimePermission就是把permission存到mPermissions数据map中,再把数据跟新到/data/system/users/0/runtime-permissions.xml中,片段如下

<pkg name="com.google.android.apps.messaging">    <item name="android.permission.READ_SMS" granted="true" flags="20" />    <item name="android.permission.RECEIVE_WAP_PUSH" granted="true" flags="20" />    <item name="android.permission.RECEIVE_MMS" granted="true" flags="20" />    <item name="android.permission.RECEIVE_SMS" granted="true" flags="20" />    <item name="android.permission.READ_PHONE_STATE" granted="true" flags="20" />    <item name="android.permission.SEND_SMS" granted="true" flags="20" />    <item name="android.permission.CALL_PHONE" granted="true" flags="20" />    <item name="android.permission.WRITE_CONTACTS" granted="true" flags="20" />    <item name="android.permission.READ_CONTACTS" granted="true" flags="20" />  </pkg>  <pkg name="com.google.android.setupwizard">    <item name="android.permission.ACCESS_COARSE_LOCATION" granted="true" flags="20" />    <item name="android.permission.CALL_PHONE" granted="true" flags="20" />    <item name="android.permission.WRITE_CONTACTS" granted="true" flags="20" />    <item name="android.permission.CAMERA" granted="true" flags="20" />    <item name="android.permission.PROCESS_OUTGOING_CALLS" granted="true" flags="20" />    <item name="android.permission.READ_CONTACTS" granted="true" flags="20" />  </pkg>

PMS赋予apk安装权限

过程精简如下:

-> scanDirLI(File dir, final int parseFlags, int scanFlags, long currentTime)  ->  scanPackageTracedLI(PackageParser.Package pkg, final int policyFlags,          int scanFlags, long currentTime, UserHandle user)  -> scanPackageLI(PackageParser.Package pkg, final int policyFlags,              int scanFlags, long currentTime, UserHandle user)  -> scanPackageDirtyLI(PackageParser.Package pkg,              final int policyFlags, final int scanFlags, long currentTime, UserHandle user)  -> updateSettingsLI(PackageParser.Package newPackage, String installerPackageName,              int[] allUsers, PackageInstalledInfo res, UserHandle user)  -> updateSettingsInternalLI(PackageParser.Package newPackage,              String installerPackageName, int[] allUsers, int[] installedForUsers,              PackageInstalledInfo res, UserHandle user)  -> updatePermissionsLPw(String changingPkg, PackageParser.Package pkgInfo,              int flags)  -> updatePermissionsLPw(String changingPkg,              PackageParser.Package pkgInfo, String replaceVolumeUuid, int flags)  -> grantPermissionsLPw(PackageParser.Package pkg, boolean replace,              String packageOfInterest)

在grantPermissionsLPw函数中做最后权限赋予操作,代码片段如下:

private void grantPermissionsLPw(PackageParser.Package pkg, boolean replace,          String packageOfInterest) {   for (int i=0; i<N; i++) {          final String name = pkg.requestedPermissions.get(i); // 权限名字          final BasePermission bp = mSettings.mPermissions.get(name); // 权限信息      ...            final int level = bp.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE; // 权限级别ProtectionLevel          final boolean appSupportsRuntimePermissions = pkg.applicationInfo.targetSdkVersion                  >= Build.VERSION_CODES.M;      // 根据权限级别定义grant          switch (level) {              case PermissionInfo.PROTECTION_NORMAL: {                  // For all apps normal permissions are install time ones.                  grant = GRANT_INSTALL;              } break;                case PermissionInfo.PROTECTION_DANGEROUS: {                  if (!appSupportsRuntimePermissions && !Build.isPermissionReviewRequired()) {                      // For legacy apps dangerous permissions are install time ones.                      grant = GRANT_INSTALL;                  } else if (origPermissions.hasInstallPermission(bp.name)) {                      // For legacy apps that became modern, install becomes runtime.                      grant = GRANT_UPGRADE;                  } else if (mPromoteSystemApps                      && isSystemApp(ps)                      && mExistingSystemPackages.contains(ps.name)) {                      // For legacy system apps, install becomes runtime.                      // We cannot check hasInstallPermission() for system apps since those                      // permissions were granted implicitly and not persisted pre-M.                      grant = GRANT_UPGRADE;                  } else {                      // For modern apps keep runtime permissions unchanged.                      grant = GRANT_RUNTIME;                  }              } break;                case PermissionInfo.PROTECTION_SIGNATURE: {                  // For all apps signature permissions are install time ones.                  allowedSig = grantSignaturePermission(perm, pkg, bp, origPermissions);                  if (allowedSig) {                      grant = GRANT_INSTALL;                  }              } break;          }      ...          if (grant != GRANT_DENIED) {              if (!isSystemApp(ps) && ps.installPermissionsFixed) {                  // If this is an existing, non-system package, then                  // we can't add any new permissions to it.                  if (!allowedSig && !origPermissions.hasInstallPermission(perm)) {                      // Except...  if this is a permission that was added                      // to the platform (note: need to only do this when                      // updating the platform).                      if (!isNewPlatformPermissionForPackage(perm, pkg)) {                          grant = GRANT_DENIED;                      }                  }              }      // 根据grant 选择权限给予方式              switch (grant) {                  case GRANT_INSTALL: {                      for (int userId : UserManagerService.getInstance().getUserIds()) {                          if (origPermissions.getRuntimePermissionState(                                  bp.name, userId) != null) {                              // Revoke the runtime permission and clear the flags.                              origPermissions.revokeRuntimePermission(bp, userId);                              origPermissions.updatePermissionFlags(bp, userId,                                    PackageManager.MASK_PERMISSION_FLAGS, 0);                              // If we revoked a permission permission, we have to write.                              changedRuntimePermissionUserIds = ArrayUtils.appendInt(                                      changedRuntimePermissionUserIds, userId);                          }                      }                      // install权限                      if (permissionsState.grantInstallPermission(bp) !=                              PermissionsState.PERMISSION_OPERATION_FAILURE) {                          changedInstallPermission = true;                      }                  } break;                    case GRANT_RUNTIME: {                      // Grant previously granted runtime permissions.                      for (int userId : UserManagerService.getInstance().getUserIds()) {                          PermissionState permissionState = origPermissions                                  .getRuntimePermissionState(bp.name, userId);                          int flags = permissionState != null                                  ? permissionState.getFlags() : 0;                          if (origPermissions.hasRuntimePermission(bp.name, userId)) {                              if (permissionsState.grantRuntimePermission(bp, userId) ==                                      PermissionsState.PERMISSION_OPERATION_FAILURE) {                                  // If we cannot put the permission as it was, we have to write.                                  changedRuntimePermissionUserIds = ArrayUtils.appendInt(                                          changedRuntimePermissionUserIds, userId);                              }                              // If the app supports runtime permissions no need for a review.                              /// M: CTA requirement - permission control                              if (Build.isPermissionReviewRequired()                                      && appSupportsRuntimePermissions                                      && (flags & PackageManager                                              .FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {                                  flags &= ~PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;                                  // Since we changed the flags, we have to write.                                  changedRuntimePermissionUserIds = ArrayUtils.appendInt(                                          changedRuntimePermissionUserIds, userId);                              }                          /// M: CTA requirement - permission control                          } else if (Build.isPermissionReviewRequired()                                  && !appSupportsRuntimePermissions) {                              if (CtaUtils.isPlatformPermission(bp.sourcePackage, bp.name)                                      && pkgReviewRequired) {                                  if ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) == 0) {                                      /// M: CTA requirement - review UI for all apps  @{                                      Slog.d(TAG, "add review UI for legacy pkg = " +                                              pkg.packageName + ", permission = " +                                              bp.name + ", userId = " + userId +                                              ", uid = " + pkg.mSharedUserId);                                      ///@}                                      flags |= FLAG_PERMISSION_REVIEW_REQUIRED;                                      // We changed the flags, hence have to write.                                      changedRuntimePermissionUserIds = ArrayUtils.appendInt(                                              changedRuntimePermissionUserIds, userId);                                  }                              }              // runtime权限                              if (permissionsState.grantRuntimePermission(bp, userId)                                      != PermissionsState.PERMISSION_OPERATION_FAILURE) {                                  // We changed the permission, hence have to write.                                  changedRuntimePermissionUserIds = ArrayUtils.appendInt(                                          changedRuntimePermissionUserIds, userId);                              }                          /// M: CTA requirement - review UI for all apps  @{                          } else if (appSupportsRuntimePermissions &&                                  pkgReviewRequired) {                              if (CtaUtils.isPlatformPermission(bp.sourcePackage, bp.name)) {                                  if ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) == 0 &&                                          (flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED)                                          == 0) {                                      Slog.d(TAG, "add review UI for non-legacy pkg = " +                                              pkg.packageName + ", permission = " +                                              bp.name + ", userId = " + userId +                                              ", uid = " + pkg.mSharedUserId);                                      flags |= FLAG_PERMISSION_REVIEW_REQUIRED;                                      // We changed the flags, hence have to write.                                      changedRuntimePermissionUserIds = ArrayUtils.appendInt(                                              changedRuntimePermissionUserIds, userId);                                  }                              }                          }                          ///@}                          // Propagate the permission flags.                          permissionsState.updatePermissionFlags(bp, userId, flags, flags);                      }                  } break;                    case GRANT_UPGRADE: {                      // Grant runtime permissions for a previously held install permission.                      PermissionState permissionState = origPermissions                              .getInstallPermissionState(bp.name);                      final int flags = permissionState != null ? permissionState.getFlags() : 0;                        if (origPermissions.revokeInstallPermission(bp)                              != PermissionsState.PERMISSION_OPERATION_FAILURE) {                          // 跟新应用的权限                          origPermissions.updatePermissionFlags(bp, UserHandle.USER_ALL,                                  PackageManager.MASK_PERMISSION_FLAGS, 0);                          changedInstallPermission = true;                      }                        // If the permission runtime-permissions.xmlis not to be promoted to runtime we ignore it and                      // also its other flags as they are not applicable to install permissions.                      if ((flags & PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE) == 0) {                          for (int userId : currentUserIds) {                              if (permissionsState.grantRuntimePermission(bp, userId) !=                                      PermissionsState.PERMISSION_OPERATION_FAILURE) {                                  // Transfer the permission flags.                                  permissionsState.updatePermissionFlags(bp, userId,                                          flags, flags);                                  // If we granted the permission, we have to write.                                  changedRuntimePermissionUserIds = ArrayUtils.appendInt(                                          changedRuntimePermissionUserIds, userId);                              }                          }                      }                  } break;                    default: {                      if (packageOfInterest == null                              || packageOfInterest.equals(pkg.packageName)) {                          Slog.w(TAG, "Not granting permission " + perm                                  + " to package " + pkg.packageName                                  + " because it was previously installed without");                      }                  } break;              }          } else {              if (permissionsState.revokeInstallPermission(bp) !=                      PermissionsState.PERMISSION_OPERATION_FAILURE) {                  // Also drop the permission flags.                  permissionsState.updatePermissionFlags(bp, UserHandle.USER_ALL,                          PackageManager.MASK_PERMISSION_FLAGS, 0);                  changedInstallPermission = true;                  Slog.i(TAG, "Un-granting permission " + perm                          + " from package " + pkg.packageName                          + " (protectionLevel=" + bp.protectionLevel                          + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)                          + ")");              } else if ((bp.protectionLevel&PermissionInfo.PROTECTION_FLAG_APPOP) == 0) {                  // Don't print warning for app op permissions, since it is fine for them                  // not to be granted, there is a UI for the user to decide.                  if (packageOfInterest == null || packageOfInterest.equals(pkg.packageName)) {                      Slog.w(TAG, "Not granting permission " + perm                              + " to package " + pkg.packageName                              + " (protectionLevel=" + bp.protectionLevel                              + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)                              + ")");                  }              }          }      }        if ((changedInstallPermission || replace) && !ps.installPermissionsFixed &&              !isSystemApp(ps) || isUpdatedSystemApp(ps)){          // This is the first that we have heard about this package, so the          // permissions we have now selected are fixed until explicitly          // changed.          ps.installPermissionsFixed = true;      }        // 把runtime权限跟新到runtime-permissions.xml中      for (int userId : changedRuntimePermissionUserIds) {          mSettings.writeRuntimePermissionsForUserLPr(userId, runtimePermissionsRevoked);      }        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);  }

grantPermissionsLPw函数根据权限等级,来赋予权限。注意:这里的安装时赋予的runtime权限是之前已经赋予过此apk的权限才会执行到GRANT_RUNTIME 回到上面的精简过程: updateSettingsInternalLI方法中调用updatePermissionsLPw后,最后会调用mSettings.writeLPr(); 这些权限信息就被写到data/system/packages.xml中了,举例片段代码:

...  <package name="com.android.settings" codePath="/system/priv-app/Settings" nativeLibraryPath="/system/priv-app/Settings/lib" primaryCpuAbi="arm64-v8a" publicFlags="944258629" privateFlags="8" ft="15f7a5ec8a8" it="15f7a5ec8a8" ut="15f7a5ec8a8" version="25" sharedUserId="1000" isOrphaned="true">          <sigs count="1">              <cert index="1" />          </sigs>          <perms>              <item name="android.permission.BIND_INCALL_SERVICE" granted="true" flags="0" />              <item name="android.permission.WRITE_SETTINGS" granted="true" flags="0" />              <item name="com.google.android.gm.permission.WRITE_GMAIL" granted="true" flags="0" />              <item name="android.permission.CONFIGURE_WIFI_DISPLAY" granted="true" flags="0" />              <item name="android.permission.CONFIGURE_DISPLAY_COLOR_MODE" granted="true" flags="0" />              <item name="android.permission.ACCESS_WIMAX_STATE" granted="true" flags="0" />              <item name="com.qualcomm.permission.READPROC" granted="true" flags="0" />              <item name="android.permission.RESTART_PACKAGES" granted="true" flags="0" />              <item name="android.permission.USE_CREDENTIALS" granted="true" flags="0" />              <item name="android.permission.MODIFY_AUDIO_SETTINGS" granted="true" flags="0" />              <item name="android.permission.ACCESS_CHECKIN_PROPERTIES" granted="true" flags="0" />              <item name="android.permission.MODIFY_AUDIO_ROUTING" granted="true" flags="0" />      ...

小结

1、PMS扫描安装时赋予安装权限

2、PMS在systemReady函数中调用mDefaultPermissionPolicy.grantDefaultPermissions来赋予运行权限即dangerous权限