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.大多数人开始学编程时…...

企业电子招投标采购系统——功能模块功能描述
功能模块: 待办消息,招标公告,中标公告,信息发布 描述: 全过程数字化采购管理,打造从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理。通供应商门户具备内外协同的能力,为外…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...

CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...

中医有效性探讨
文章目录 西医是如何发展到以生物化学为药理基础的现代医学?传统医学奠基期(远古 - 17 世纪)近代医学转型期(17 世纪 - 19 世纪末)现代医学成熟期(20世纪至今) 中医的源远流长和一脉相承远古至…...

华为OD机考-机房布局
import java.util.*;public class DemoTest5 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseSystem.out.println(solve(in.nextLine()));}}priv…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...