当前位置: 首页 > news >正文

Android system实战 — Android R(11) 第三方apk权限

Android system实战 — 第三方apk权限问题

  • 0. 前言
  • 1. 源码实现
    • 1.1 主要函数
    • 1.2 修改思路和实现
      • 1.2.1 修改思路
      • 1.2.2 方案一
      • 1.2.3 方案二

0. 前言

  最近在调试时遇到了第三方apk申请运行时权限,以及signature级别 install 权限不允许赋予给第三方apk,虽然这是Android系统安全性的一种体现,但在某些情况下,确实是有需求去放开权限,使app能使用更方便,毕竟让用户允许权限在一定程度上来说并不是一件容易的事情。

1. 源码实现

涉及路径:在Android R上权限赋予主要由frameworks\base\services\core\java\com\android\server\pm\permission\PermissionManagerService.java管理

1.1 主要函数

PermissionManagerService中主要负责检查权限及赋予权限的函数为restorePermissionState

    /*** Restore the permission state for a package.** <ul>*     <li>During boot the state gets restored from the disk</li>*     <li>During app update the state gets restored from the last version of the app</li>* </ul>** <p>This restores the permission state for all users.** @param pkg the package the permissions belong to* @param replace if the package is getting replaced (this might change the requested*                permissions of this package)* @param packageOfInterest If this is the name of {@code pkg} add extra logging* @param callback Result call back*/private void restorePermissionState(@NonNull AndroidPackage pkg, boolean replace,@Nullable String packageOfInterest, @Nullable PermissionCallback callback) {// IMPORTANT: There are two types of permissions: install and runtime.// Install time permissions are granted when the app is installed to// all device users and users added in the future. Runtime permissions// are granted at runtime explicitly to specific users. Normal and signature// protected permissions are install time permissions. Dangerous permissions// are install permissions if the app's target SDK is Lollipop MR1 or older,// otherwise they are runtime permissions. This function does not manage// runtime permissions except for the case an app targeting Lollipop MR1// being upgraded to target a newer SDK, in which case dangerous permissions// are transformed from install time to runtime ones.final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting(pkg.getPackageName());if (ps == null) {return;}final PermissionsState permissionsState = ps.getPermissionsState();final int[] userIds = getAllUserIds();boolean runtimePermissionsRevoked = false;int[] updatedUserIds = EMPTY_INT_ARRAY;for (int userId : userIds) {if (permissionsState.isMissing(userId)) {Collection<String> requestedPermissions;int targetSdkVersion;if (!ps.isSharedUser()) {requestedPermissions = pkg.getRequestedPermissions();targetSdkVersion = pkg.getTargetSdkVersion();} else {requestedPermissions = new ArraySet<>();targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;List<AndroidPackage> packages = ps.getSharedUser().getPackages();int packagesSize = packages.size();for (int i = 0; i < packagesSize; i++) {AndroidPackage sharedUserPackage = packages.get(i);requestedPermissions.addAll(sharedUserPackage.getRequestedPermissions());targetSdkVersion = Math.min(targetSdkVersion,sharedUserPackage.getTargetSdkVersion());}}for (String permissionName : requestedPermissions) {BasePermission permission = mSettings.getPermission(permissionName);if (permission == null) {continue;}if (Objects.equals(permission.getSourcePackageName(), PLATFORM_PACKAGE_NAME)&& permission.isRuntime() && !permission.isRemoved()) {if (permission.isHardOrSoftRestricted()|| permission.isImmutablyRestricted()) {permissionsState.updatePermissionFlags(permission, userId,FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT,FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT);}if (targetSdkVersion < Build.VERSION_CODES.M) {permissionsState.updatePermissionFlags(permission, userId,PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED| PackageManager.FLAG_PERMISSION_REVOKED_COMPAT,PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED| PackageManager.FLAG_PERMISSION_REVOKED_COMPAT);permissionsState.grantRuntimePermission(permission, userId);}}}permissionsState.setMissing(false, userId);updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);}}PermissionsState origPermissions = permissionsState;boolean changedInstallPermission = false;if (replace) {ps.setInstallPermissionsFixed(false);if (!ps.isSharedUser()) {origPermissions = new PermissionsState(permissionsState);permissionsState.reset();} else {// We need to know only about runtime permission changes since the// calling code always writes the install permissions state but// the runtime ones are written only if changed. The only cases of// changed runtime permissions here are promotion of an install to// runtime and revocation of a runtime from a shared user.synchronized (mLock) {updatedUserIds = revokeUnusedSharedUserPermissionsLocked(ps.getSharedUser(), userIds);if (!ArrayUtils.isEmpty(updatedUserIds)) {runtimePermissionsRevoked = true;}}}}permissionsState.setGlobalGids(mGlobalGids);synchronized (mLock) {ArraySet<String> newImplicitPermissions = new ArraySet<>();final int N = pkg.getRequestedPermissions().size();for (int i = 0; i < N; i++) {final String permName = pkg.getRequestedPermissions().get(i);final String friendlyName = pkg.getPackageName() + "(" + pkg.getUid() + ")";final BasePermission bp = mSettings.getPermissionLocked(permName);final boolean appSupportsRuntimePermissions =pkg.getTargetSdkVersion() >= Build.VERSION_CODES.M;String upgradedActivityRecognitionPermission = null;if (DEBUG_INSTALL && bp != null) {Log.i(TAG, "Package " + friendlyName+ " checking " + permName + ": " + bp);}if (bp == null || getSourcePackageSetting(bp) == null) {if (packageOfInterest == null || packageOfInterest.equals(pkg.getPackageName())) {if (DEBUG_PERMISSIONS) {Slog.i(TAG, "Unknown permission " + permName+ " in package " + friendlyName);}}continue;}// Cache newImplicitPermissions before modifing permissionsState as for the shared// uids the original and new state are the same objectif (!origPermissions.hasRequestedPermission(permName)&& (pkg.getImplicitPermissions().contains(permName)|| (permName.equals(Manifest.permission.ACTIVITY_RECOGNITION)))) {if (pkg.getImplicitPermissions().contains(permName)) {// If permName is an implicit permission, try to auto-grantnewImplicitPermissions.add(permName);if (DEBUG_PERMISSIONS) {Slog.i(TAG, permName + " is newly added for " + friendlyName);}} else {// Special case for Activity Recognition permission. Even if AR permission// is not an implicit permission we want to add it to the list (try to// auto-grant it) if the app was installed on a device before AR permission// was split, regardless of if the app now requests the new AR permission// or has updated its target SDK and AR is no longer implicit to it.// This is a compatibility workaround for apps when AR permission was// split in Q.final List<SplitPermissionInfoParcelable> permissionList =getSplitPermissions();int numSplitPerms = permissionList.size();for (int splitPermNum = 0; splitPermNum < numSplitPerms; splitPermNum++) {SplitPermissionInfoParcelable sp = permissionList.get(splitPermNum);String splitPermName = sp.getSplitPermission();if (sp.getNewPermissions().contains(permName)&& origPermissions.hasInstallPermission(splitPermName)) {upgradedActivityRecognitionPermission = splitPermName;newImplicitPermissions.add(permName);if (DEBUG_PERMISSIONS) {Slog.i(TAG, permName + " is newly added for " + friendlyName);}break;}}}}// TODO(b/140256621): The package instant app method has been removed//  as part of work in b/135203078, so this has been commented out in the meantime// Limit ephemeral apps to ephemeral allowed permissions.
//                if (/*pkg.isInstantApp()*/ false && !bp.isInstant()) {
//                    if (DEBUG_PERMISSIONS) {
//                        Log.i(TAG, "Denying non-ephemeral permission " + bp.getName()
//                                + " for package " + friendlyName);
//                    }
//                    continue;
//                }if (bp.isRuntimeOnly() && !appSupportsRuntimePermissions) {if (DEBUG_PERMISSIONS) {Log.i(TAG, "Denying runtime-only permission " + bp.getName()+ " for package " + friendlyName);}continue;}final String perm = bp.getName();boolean allowedSig = false;int grant = GRANT_DENIED;// 检查permission是否特殊,针对不同级别permission赋予不同的grant// Keep track of app op permissions.if (bp.isAppOp()) {mSettings.addAppOpPackage(perm, pkg.getPackageName());}if (bp.isNormal()) {// For all apps normal permissions are install time ones.grant = GRANT_INSTALL;} else if (bp.isRuntime()) {if (origPermissions.hasInstallPermission(bp.getName())|| upgradedActivityRecognitionPermission != null) {// Before Q we represented some runtime permissions as install permissions,// in Q we cannot do this anymore. Hence upgrade them all.grant = GRANT_UPGRADE;} else {// For modern apps keep runtime permissions unchanged.grant = GRANT_RUNTIME;}} else if (bp.isSignature()) {// For all apps signature permissions are install time ones.allowedSig = grantSignaturePermission(perm, pkg, ps, bp, origPermissions);if (allowedSig) {grant = GRANT_INSTALL;}}if (DEBUG_PERMISSIONS) {Slog.i(TAG, "Considering granting permission " + perm + " to package "+ friendlyName + "grant " + grant);}if (grant != GRANT_DENIED) {if (!ps.isSystem() && ps.areInstallPermissionsFixed() && !bp.isRuntime()) {// If this is an existing, non-system package, then// we can't add any new permissions to it. Runtime// permissions can be added any time - they ad dynamic.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;}}}switch (grant) {case GRANT_INSTALL: {// Revoke this as runtime permission to handle the case of// a runtime permission being downgraded to an install one.// Also in permission review mode we keep dangerous permissions// for legacy appsfor (int userId : userIds) {if (origPermissions.getRuntimePermissionState(perm, userId) != null) {// Revoke the runtime permission and clear the flags.origPermissions.revokeRuntimePermission(bp, userId);origPermissions.updatePermissionFlags(bp, userId,PackageManager.MASK_PERMISSION_FLAGS_ALL, 0);// If we revoked a permission permission, we have to write.updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);}}// Grant an install permission.if (permissionsState.grantInstallPermission(bp) !=PERMISSION_OPERATION_FAILURE) {changedInstallPermission = true;}} break;case GRANT_RUNTIME: {boolean hardRestricted = bp.isHardRestricted();boolean softRestricted = bp.isSoftRestricted();for (int userId : userIds) {// If permission policy is not ready we don't deal with restricted// permissions as the policy may whitelist some permissions. Once// the policy is initialized we would re-evaluate permissions.final boolean permissionPolicyInitialized =mPermissionPolicyInternal != null&& mPermissionPolicyInternal.isInitialized(userId);PermissionState permState = origPermissions.getRuntimePermissionState(perm, userId);int flags = permState != null ? permState.getFlags() : 0;boolean wasChanged = false;boolean restrictionExempt =(origPermissions.getPermissionFlags(bp.name, userId)& FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) != 0;boolean restrictionApplied = (origPermissions.getPermissionFlags(bp.name, userId) & FLAG_PERMISSION_APPLY_RESTRICTION) != 0;if (appSupportsRuntimePermissions) {// If hard restricted we don't allow holding itif (permissionPolicyInitialized && hardRestricted) {if (!restrictionExempt) {if (permState != null && permState.isGranted()&& permissionsState.revokeRuntimePermission(bp, userId) != PERMISSION_OPERATION_FAILURE) {wasChanged = true;}if (!restrictionApplied) {flags |= FLAG_PERMISSION_APPLY_RESTRICTION;wasChanged = true;}}// If soft restricted we allow holding in a restricted form} else if (permissionPolicyInitialized && softRestricted) {// Regardless if granted set the restriction flag as it// may affect app treatment based on this permission.if (!restrictionExempt && !restrictionApplied) {flags |= FLAG_PERMISSION_APPLY_RESTRICTION;wasChanged = true;}}// Remove review flag as it is not necessary anymoreif ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {flags &= ~FLAG_PERMISSION_REVIEW_REQUIRED;wasChanged = true;}if ((flags & FLAG_PERMISSION_REVOKED_COMPAT) != 0) {flags &= ~FLAG_PERMISSION_REVOKED_COMPAT;wasChanged = true;// Hard restricted permissions cannot be held.} else if (!permissionPolicyInitialized|| (!hardRestricted || restrictionExempt)) {if (permState != null && permState.isGranted()) {if (permissionsState.grantRuntimePermission(bp, userId)== PERMISSION_OPERATION_FAILURE) {wasChanged = true;}}}} else {if (permState == null) {// New permissionif (PLATFORM_PACKAGE_NAME.equals(bp.getSourcePackageName())) {if (!bp.isRemoved()) {flags |= FLAG_PERMISSION_REVIEW_REQUIRED| FLAG_PERMISSION_REVOKED_COMPAT;wasChanged = true;}}}if (!permissionsState.hasRuntimePermission(bp.name, userId)&& permissionsState.grantRuntimePermission(bp, userId)!= PERMISSION_OPERATION_FAILURE) {wasChanged = true;}// If legacy app always grant the permission but if restricted// and not exempt take a note a restriction should be applied.if (permissionPolicyInitialized&& (hardRestricted || softRestricted)&& !restrictionExempt && !restrictionApplied) {flags |= FLAG_PERMISSION_APPLY_RESTRICTION;wasChanged = true;}}// If unrestricted or restriction exempt, don't apply restriction.if (permissionPolicyInitialized) {if (!(hardRestricted || softRestricted) || restrictionExempt) {if (restrictionApplied) {flags &= ~FLAG_PERMISSION_APPLY_RESTRICTION;// Dropping restriction on a legacy app implies a reviewif (!appSupportsRuntimePermissions) {flags |= FLAG_PERMISSION_REVIEW_REQUIRED;}wasChanged = true;}}}if (wasChanged) {updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);}permissionsState.updatePermissionFlags(bp, userId,MASK_PERMISSION_FLAGS_ALL, flags);}} break;case GRANT_UPGRADE: {// Upgrade from Pre-Q to Q permission model. Make all permissions// runtimePermissionState permState = origPermissions.getInstallPermissionState(perm);int flags = (permState != null) ? permState.getFlags() : 0;BasePermission bpToRevoke =upgradedActivityRecognitionPermission == null? bp : mSettings.getPermissionLocked(upgradedActivityRecognitionPermission);// Remove install permissionif (origPermissions.revokeInstallPermission(bpToRevoke)!= PERMISSION_OPERATION_FAILURE) {origPermissions.updatePermissionFlags(bpToRevoke,UserHandle.USER_ALL,(MASK_PERMISSION_FLAGS_ALL& ~FLAG_PERMISSION_APPLY_RESTRICTION), 0);changedInstallPermission = true;}boolean hardRestricted = bp.isHardRestricted();boolean softRestricted = bp.isSoftRestricted();for (int userId : userIds) {// If permission policy is not ready we don't deal with restricted// permissions as the policy may whitelist some permissions. Once// the policy is initialized we would re-evaluate permissions.final boolean permissionPolicyInitialized =mPermissionPolicyInternal != null&& mPermissionPolicyInternal.isInitialized(userId);boolean wasChanged = false;boolean restrictionExempt =(origPermissions.getPermissionFlags(bp.name, userId)& FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) != 0;boolean restrictionApplied = (origPermissions.getPermissionFlags(bp.name, userId) & FLAG_PERMISSION_APPLY_RESTRICTION) != 0;if (appSupportsRuntimePermissions) {// If hard restricted we don't allow holding itif (permissionPolicyInitialized && hardRestricted) {if (!restrictionExempt) {if (permState != null && permState.isGranted()&& permissionsState.revokeRuntimePermission(bp, userId) != PERMISSION_OPERATION_FAILURE) {wasChanged = true;}if (!restrictionApplied) {flags |= FLAG_PERMISSION_APPLY_RESTRICTION;wasChanged = true;}}// If soft restricted we allow holding in a restricted form} else if (permissionPolicyInitialized && softRestricted) {// Regardless if granted set the  restriction flag as it// may affect app treatment based on this permission.if (!restrictionExempt && !restrictionApplied) {flags |= FLAG_PERMISSION_APPLY_RESTRICTION;wasChanged = true;}}// Remove review flag as it is not necessary anymoreif ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {flags &= ~FLAG_PERMISSION_REVIEW_REQUIRED;wasChanged = true;}if ((flags & FLAG_PERMISSION_REVOKED_COMPAT) != 0) {flags &= ~FLAG_PERMISSION_REVOKED_COMPAT;wasChanged = true;// Hard restricted permissions cannot be held.} else if (!permissionPolicyInitialized ||(!hardRestricted || restrictionExempt)) {if (permissionsState.grantRuntimePermission(bp, userId) !=PERMISSION_OPERATION_FAILURE) {wasChanged = true;}}} else {if (!permissionsState.hasRuntimePermission(bp.name, userId)&& permissionsState.grantRuntimePermission(bp,userId) != PERMISSION_OPERATION_FAILURE) {flags |= FLAG_PERMISSION_REVIEW_REQUIRED;wasChanged = true;}// If legacy app always grant the permission but if restricted// and not exempt take a note a restriction should be applied.if (permissionPolicyInitialized&& (hardRestricted || softRestricted)&& !restrictionExempt && !restrictionApplied) {flags |= FLAG_PERMISSION_APPLY_RESTRICTION;wasChanged = true;}}// If unrestricted or restriction exempt, don't apply restriction.if (permissionPolicyInitialized) {if (!(hardRestricted || softRestricted) || restrictionExempt) {if (restrictionApplied) {flags &= ~FLAG_PERMISSION_APPLY_RESTRICTION;// Dropping restriction on a legacy app implies a reviewif (!appSupportsRuntimePermissions) {flags |= FLAG_PERMISSION_REVIEW_REQUIRED;}wasChanged = true;}}}if (wasChanged) {updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);}permissionsState.updatePermissionFlags(bp, userId,MASK_PERMISSION_FLAGS_ALL, flags);}} break;default: {if (packageOfInterest == null|| packageOfInterest.equals(pkg.getPackageName())) {if (DEBUG_PERMISSIONS) {Slog.i(TAG, "Not granting permission " + perm+ " to package " + friendlyName+ " because it was previously installed without");}}} break;}} else {if (permissionsState.revokeInstallPermission(bp) !=PERMISSION_OPERATION_FAILURE) {// Also drop the permission flags.permissionsState.updatePermissionFlags(bp, UserHandle.USER_ALL,MASK_PERMISSION_FLAGS_ALL, 0);changedInstallPermission = true;if (DEBUG_PERMISSIONS) {Slog.i(TAG, "Un-granting permission " + perm+ " from package " + friendlyName+ " (protectionLevel=" + bp.getProtectionLevel()+ " flags=0x"+ Integer.toHexString(PackageInfoUtils.appInfoFlags(pkg, ps))+ ")");}} else if (bp.isAppOp()) {// 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 (DEBUG_PERMISSIONS&& (packageOfInterest == null|| packageOfInterest.equals(pkg.getPackageName()))) {Slog.i(TAG, "Not granting permission " + perm+ " to package " + friendlyName+ " (protectionLevel=" + bp.getProtectionLevel()+ " flags=0x"+ Integer.toHexString(PackageInfoUtils.appInfoFlags(pkg, ps))+ ")");}}}}if ((changedInstallPermission || replace) && !ps.areInstallPermissionsFixed() &&!ps.isSystem() || ps.getPkgState().isUpdatedSystemApp()) {// This is the first that we have heard about this package, so the// permissions we have now selected are fixed until explicitly// changed.ps.setInstallPermissionsFixed(true);}updatedUserIds = revokePermissionsNoLongerImplicitLocked(permissionsState, pkg,updatedUserIds);updatedUserIds = setInitialGrantForNewImplicitPermissionsLocked(origPermissions,permissionsState, pkg, newImplicitPermissions, updatedUserIds);updatedUserIds = checkIfLegacyStorageOpsNeedToBeUpdated(pkg, replace, updatedUserIds);}// Persist the runtime permissions state for users with changes. If permissions// were revoked because no app in the shared user declares them we have to// write synchronously to avoid losing runtime permissions state.if (callback != null) {callback.onPermissionUpdated(updatedUserIds, runtimePermissionsRevoked);}for (int userId : updatedUserIds) {notifyRuntimePermissionStateChanged(pkg.getPackageName(), userId);}}

1.2 修改思路和实现

1.2.1 修改思路

  其实我们阅读一下代码可以理解到,Android 会对app申请的权限进行对应分级,比如说signature级权限、dangerous权限仅能赋予系统apk等等的特殊处理。基于这个流程,我们有两种思路:

  1. 所有app申请的权限都作为install 权限赋予给app
  2. 不改变原有流程,模拟用户操作或跳过某些判断

下面我们以跳过runtime permission请求和赋予第三方apksignature级权限为例

1.2.2 方案一

这种方法比较简单粗暴,但是改变了原有流程,目前发现造成某些依赖的so无法找到导致crash的问题,目前暂时未查出原因,但是大部分情况下应该是可以hold住的

diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index a0cae5c..c21ce8f 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -121,6 +121,7 @@import android.util.Slog;import android.util.SparseArray;import android.util.SparseBooleanArray;
+import android.os.SystemProperties;import com.android.internal.annotations.GuardedBy;import com.android.internal.annotations.VisibleForTesting;
@@ -2846,7 +2847,11 @@+ friendlyName + "grant " + grant);}-                if (grant != GRANT_DENIED) {
+                 String proj_type = SystemProperties.get("sys.proj.type", null);
+                 if ("mobile".equals(proj_type) || "telecom".equals(proj_type) || "unicom".equals(proj_type)) {
+                    grant = GRANT_INSTALL;
+                  }
+                 if (grant != GRANT_DENIED) {if (!ps.isSystem() && ps.areInstallPermissionsFixed() && !bp.isRuntime()) {// If this is an existing, non-system package, then// we can't add any new permissions to it. Runtime

1.2.3 方案二

  1. 跳过runtime permission
    这次的改法就是模拟用户已经允许了runtime permission,修改了flags为USER_SET,并grant 运行权限

    diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
    index c21ce8f..c2edbf4 100644
    --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
    +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
    @@ -2847,10 +2847,6 @@+ friendlyName + "grant " + grant);}-                 String proj_type = SystemProperties.get("sys.proj.type", null);
    -                 if ("mobile".equals(proj_type) || "telecom".equals(proj_type) || "unicom".equals(proj_type)) {
    -                    grant = GRANT_INSTALL;
    -                  }if (grant != GRANT_DENIED) {if (!ps.isSystem() && ps.areInstallPermissionsFixed() && !bp.isRuntime()) {// If this is an existing, non-system package, then
    @@ -3001,12 +2997,17 @@}}+                                flags |= FLAG_PERMISSION_USER_SET;if (wasChanged) {updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);}permissionsState.updatePermissionFlags(bp, userId,MASK_PERMISSION_FLAGS_ALL, flags);
    +								String proj_type = SystemProperties.get("sys.proj.type", null);
    +                                if ("mobile".equals(proj_type) || "telecom".equals(proj_type) || "unicom".equals(proj_type)) {
    +                                permissionsState.grantRuntimePermission(bp, userId);
    +                                }		}} break;
  2. 赋予第三方apk signature权限
    跳过判断是否allowed

    diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
    index 8d2363b..a0cae5c 100644
    --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
    +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
    @@ -103,6 +103,7 @@import android.os.UserManagerInternal;import android.os.storage.StorageManager;import android.os.storage.StorageManagerInternal;
    +import android.os.SystemProperties;import android.permission.IOnPermissionsChangeListener;import android.permission.IPermissionManager;import android.permission.PermissionControllerManager;
    @@ -2835,14 +2836,14 @@} else if (bp.isSignature()) {// For all apps signature permissions are install time ones.allowedSig = grantSignaturePermission(perm, pkg, ps, bp, origPermissions);
    -                    if (allowedSig) {
    +                    if (allowedSig || "mobile".equals(SystemProperties.get("sys.proj.type", null))) {grant = GRANT_INSTALL;}}if (DEBUG_PERMISSIONS) {Slog.i(TAG, "Considering granting permission " + perm + " to package "
    -                            + friendlyName);
    +                            + friendlyName + "grant " + grant);}if (grant != GRANT_DENIED) {

相关文章:

Android system实战 — Android R(11) 第三方apk权限

Android system实战 — 第三方apk权限问题0. 前言1. 源码实现1.1 主要函数1.2 修改思路和实现1.2.1 修改思路1.2.2 方案一1.2.3 方案二0. 前言 最近在调试时遇到了第三方apk申请运行时权限&#xff0c;以及signature级别 install 权限不允许赋予给第三方apk&#xff0c;虽然这是…...

面试总结1

这里写目录标题什么是ORM&#xff1f;为什么mybatis是半自动的ORM框架&#xff1f;动态sqlJDBC步骤&#xff1a;jdbc的缺点&#xff1a;JDBC,MyBatis的区别&#xff1a;MyBatis相比JDBC的优势缓存一级缓存一级缓存在下面情况会被清除二级缓存最近在面试&#xff0c;发现了许多自…...

【Hello Linux】程序地址空间

作者&#xff1a;小萌新 专栏&#xff1a;Linux 作者简介&#xff1a;大二学生 希望能和大家一起进步&#xff01; 本篇博客简介&#xff1a;简单介绍下进程地址空间 程序地址空间程序地址空间语言中的程序地址空间矛盾系统中的程序地址空间为什么要有进程地址空间思维导图总结…...

电脑崩溃蓝屏问题如何重装系统

电脑是我们日常生活和工作中必不可少的工具&#xff0c;但在使用过程中&#xff0c;难免会遇到各种问题&#xff0c;例如系统崩溃、蓝屏、病毒感染等&#xff0c;这些问题会严重影响我们的使用体验和工作效率。而小白一键重装系统可以帮助我们快速解决这些问题&#xff0c;本文…...

《商用密码应用与安全性评估》第一章密码基础知识1.2密码评估基本原理

商用密码应用安全性评估&#xff08;简称“密评”&#xff09;的定义&#xff1a;在采用商用密码技术、产品和服务集成建设的网络与信息系统中&#xff0c;对其密码应用的合规性、正确性、有效性等进行评估 信息安全管理过程 相关标准 国际:ISO/IEC TR 13335 中国:GB/T …...

【编程基础之Python】7、Python基本数据类型

【编程基础之Python】7、Python基本数据类型Python基本数据类型整数&#xff08;int&#xff09;基本的四则运算位运算比较运算运算优先级浮点数&#xff08;float&#xff09;布尔值&#xff08;bool&#xff09;字符串&#xff08;str&#xff09;Python数据类型变换隐式类型…...

Kakfa详解(一)

kafka使用场景 canal同步mysqlelk日志系统业务系统Topic kafka基础概念 Producer: 消息生产者&#xff0c;向kafka发送消息Consumer: 从kafka中拉取消息消费的客户端Consumer Group: 消费者组&#xff0c;消费者组是多个消费者的集合。消费者组之间互不影响&#xff0c;所有…...

图解LeetCode——剑指 Offer 12. 矩阵中的路径

一、题目 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 单词必须按照字母顺序&#xff0c;通过相邻的单元格内的字母构成&#xff0c;其中“相邻”单元格是那些水平相…...

particles在vue3中的基本使用

第三方库地址 particles.vue3 - npm 1.安装插件 npm i particles.vue3 npm i tsparticles2.在main.js中引入 import Particles from particles.vue3 app.use(Particles) // 配置相关的文件常用 api particles.number.value>粒子的数量particles.number.density粒子的稀密…...

04 Android基础--RelativeLayout

04 Android基础--RelativeLayout什么是RelativeLayout&#xff1f;RelativeLayout的常见用法&#xff1a;什么是RelativeLayout&#xff1f; 相对布局&#xff08;RelativeLayout&#xff09;是一种根据父容器和兄弟控件作为参照来确定控件位置的布局方式。 根据父容器定位 在相…...

python基础命令

1.现在包的安装路径 #pip show 包名 2.pip讲解 相信对于大多数熟悉Python的人来说&#xff0c;一定都听说并且使用过pip这个工具&#xff0c;但是对它的了解可能还不一定是非常的透彻&#xff0c;今天小编就来为大家介绍10个使用pip的小技巧&#xff0c;相信对大家以后管理和…...

用 Real-ESRGAN 拯救座机画质,自制高清版动漫资源

内容一览&#xff1a;Real-ESRGAN 是 ESRGAN 升级之作&#xff0c;主要有三点创新&#xff1a;提出高阶退化过程模拟实际图像退化&#xff0c;使用光谱归一化 U-Net 鉴别器增加鉴别器的能力&#xff0c;以及使用纯合成数据进行训练。 关键词&#xff1a;Real-ESRGAN 超分辨率 视…...

数据结构预备知识(模板)

模板 功能上类比C的重载函数&#xff0c;可以使用一种通用的形式&#xff0c;去代替诸多数据类型&#xff0c;使得使用同一种函数的时候&#xff0c;可以实现对于不同数据类型的相同操作。增强类和函数的可重用性。 使用模板函数为函数或类声明一个一般的模式&#xff0c;使得…...

SWM181按键控制双通道PWM固定占空比输出

SWM181按键控制双通道PWM固定占空比输出&#x1f4cc;SDK固件包&#xff1a;https://www.synwit.cn/kuhanshu_amp_licheng/ &#x1f33c;开发板如下图&#xff1a; ✨注意新手谨慎选择作为入门单片机学习。目前只有一个简易的数据手册和SDK包&#xff0c;又没有参考手册&am…...

pygame函数命令

pygame.mixer.music.load() —— 载入一个音乐文件用于播放 pygame.mixer.music.play() —— 开始播放音乐流 pygame.mixer.music.rewind() —— 重新开始播放音乐 pygame.mixer.music.stop() —— 结束音乐播放 pygame.mixer.music.pause() —— 暂停音乐播放 pygame.mixer.mu…...

异步循环

业务 &#xff1a; 批量处理照片 &#xff0c; 批量拆建 &#xff0c; 裁剪一张照片需要异步执行等待 &#xff0c; 并且是批量 所以需要用到异步循环 裁剪图片异步代码 &#xff1a; 异步循环 循环可以是 普通 for 、 for of 、 for in 不能使用forEach ,这里推荐 for…...

Vue表单提交与数据存储

学习内容来源&#xff1a;视频p5 书接目录对页面重新命名选择组件后端对接测试接口设置接口前端调用对页面重新命名 将之前的 Page1 Page2 进行重新命名&#xff0c;使其具有实际意义 Page1 → BookManage &#xff1b; Page2 → AddBook 并且 /router/index.js 中配置页面信息…...

API网关(接入层之上业务层之上)以及业务网关(后端服务网关)设计思路(二)

文章目录 流量网关业务网关常见网关对比1. OpenResty2. KongKong解决了什么问题Kong的优点以及性能Kong架构3. Zuul1.0过滤器IncomingEndpointOutgoing过滤器类型Zuul 1.0 请求生命周期4. Zuul2.0Zuul 与 Zuul 2 性能对比5. Spring Cloud GatewaySpring Cloud Gateway 底层使用…...

有些笑话,外行人根本看不懂,只有程序员看了会狂笑不止

我一直都觉得我们写代码的程序员与众不同&#xff0c;就连笑话都跟别人不一样。 如果让外行人来看我们一些我们觉得好笑的东西&#xff0c;他们根本不知道笑点在哪里。 不信你来瞧瞧&#xff0c;但凡有看不懂的地方&#xff0c;说明你的道行还不够深。 1.大多数人开始学编程时…...

企业电子招投标采购系统——功能模块功能描述

​ 功能模块&#xff1a; 待办消息&#xff0c;招标公告&#xff0c;中标公告&#xff0c;信息发布 描述&#xff1a; 全过程数字化采购管理&#xff0c;打造从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理。通供应商门户具备内外协同的能力&#xff0c;为外…...

云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?

大家好&#xff0c;欢迎来到《云原生核心技术》系列的第七篇&#xff01; 在上一篇&#xff0c;我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在&#xff0c;我们就像一个拥有了一块崭新数字土地的农场主&#xff0c;是时…...

R语言AI模型部署方案:精准离线运行详解

R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...

系统设计 --- MongoDB亿级数据查询优化策略

系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log&#xff0c;共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题&#xff0c;不能使用ELK只能使用…...

测试markdown--肇兴

day1&#xff1a; 1、去程&#xff1a;7:04 --11:32高铁 高铁右转上售票大厅2楼&#xff0c;穿过候车厅下一楼&#xff0c;上大巴车 &#xffe5;10/人 **2、到达&#xff1a;**12点多到达寨子&#xff0c;买门票&#xff0c;美团/抖音&#xff1a;&#xffe5;78人 3、中饭&a…...

Cinnamon修改面板小工具图标

Cinnamon开始菜单-CSDN博客 设置模块都是做好的&#xff0c;比GNOME简单得多&#xff01; 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

DBAPI如何优雅的获取单条数据

API如何优雅的获取单条数据 案例一 对于查询类API&#xff0c;查询的是单条数据&#xff0c;比如根据主键ID查询用户信息&#xff0c;sql如下&#xff1a; select id, name, age from user where id #{id}API默认返回的数据格式是多条的&#xff0c;如下&#xff1a; {&qu…...

Python如何给视频添加音频和字幕

在Python中&#xff0c;给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加&#xff0c;包括必要的代码示例和详细解释。 环境准备 在开始之前&#xff0c;需要安装以下Python库&#xff1a;…...

使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度

文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...

Golang——9、反射和文件操作

反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一&#xff1a;使用Read()读取文件2.3、方式二&#xff1a;bufio读取文件2.4、方式三&#xff1a;os.ReadFile读取2.5、写…...

Web后端基础(基础知识)

BS架构&#xff1a;Browser/Server&#xff0c;浏览器/服务器架构模式。客户端只需要浏览器&#xff0c;应用程序的逻辑和数据都存储在服务端。 优点&#xff1a;维护方便缺点&#xff1a;体验一般 CS架构&#xff1a;Client/Server&#xff0c;客户端/服务器架构模式。需要单独…...