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等等的特殊处理。基于这个流程,我们有两种思路:
- 所有app申请的权限都作为install 权限赋予给app
- 不改变原有流程,模拟用户操作或跳过某些判断
下面我们以跳过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 方案二
-
跳过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;
-
赋予第三方apk signature权限
跳过判断是否alloweddiff --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申请运行时权限,以及signature级别 install 权限不允许赋予给第三方apk,虽然这是…...
面试总结1
这里写目录标题什么是ORM?为什么mybatis是半自动的ORM框架?动态sqlJDBC步骤:jdbc的缺点:JDBC,MyBatis的区别:MyBatis相比JDBC的优势缓存一级缓存一级缓存在下面情况会被清除二级缓存最近在面试,发现了许多自…...

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

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

《商用密码应用与安全性评估》第一章密码基础知识1.2密码评估基本原理
商用密码应用安全性评估(简称“密评”)的定义:在采用商用密码技术、产品和服务集成建设的网络与信息系统中,对其密码应用的合规性、正确性、有效性等进行评估 信息安全管理过程 相关标准 国际:ISO/IEC TR 13335 中国:GB/T …...

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

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

图解LeetCode——剑指 Offer 12. 矩阵中的路径
一、题目 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相…...
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?RelativeLayout的常见用法:什么是RelativeLayout? 相对布局(RelativeLayout)是一种根据父容器和兄弟控件作为参照来确定控件位置的布局方式。 根据父容器定位 在相…...

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

用 Real-ESRGAN 拯救座机画质,自制高清版动漫资源
内容一览:Real-ESRGAN 是 ESRGAN 升级之作,主要有三点创新:提出高阶退化过程模拟实际图像退化,使用光谱归一化 U-Net 鉴别器增加鉴别器的能力,以及使用纯合成数据进行训练。 关键词:Real-ESRGAN 超分辨率 视…...
数据结构预备知识(模板)
模板 功能上类比C的重载函数,可以使用一种通用的形式,去代替诸多数据类型,使得使用同一种函数的时候,可以实现对于不同数据类型的相同操作。增强类和函数的可重用性。 使用模板函数为函数或类声明一个一般的模式,使得…...

SWM181按键控制双通道PWM固定占空比输出
SWM181按键控制双通道PWM固定占空比输出📌SDK固件包:https://www.synwit.cn/kuhanshu_amp_licheng/ 🌼开发板如下图: ✨注意新手谨慎选择作为入门单片机学习。目前只有一个简易的数据手册和SDK包,又没有参考手册&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…...

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

Vue表单提交与数据存储
学习内容来源:视频p5 书接目录对页面重新命名选择组件后端对接测试接口设置接口前端调用对页面重新命名 将之前的 Page1 Page2 进行重新命名,使其具有实际意义 Page1 → BookManage ; 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 底层使用…...

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

企业电子招投标采购系统——功能模块功能描述
功能模块: 待办消息,招标公告,中标公告,信息发布 描述: 全过程数字化采购管理,打造从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理。通供应商门户具备内外协同的能力,为外…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...

【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南
1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发,使用DevEco Studio作为开发工具,采用Java语言实现,包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...

Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...
08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险
C#入门系列【类的基本概念】:开启编程世界的奇妙冒险 嘿,各位编程小白探险家!欢迎来到 C# 的奇幻大陆!今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类!别害怕,跟着我,保准让你轻松搞…...
深度剖析 DeepSeek 开源模型部署与应用:策略、权衡与未来走向
在人工智能技术呈指数级发展的当下,大模型已然成为推动各行业变革的核心驱动力。DeepSeek 开源模型以其卓越的性能和灵活的开源特性,吸引了众多企业与开发者的目光。如何高效且合理地部署与运用 DeepSeek 模型,成为释放其巨大潜力的关键所在&…...
华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)
题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...