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.大多数人开始学编程时…...
企业电子招投标采购系统——功能模块功能描述
功能模块: 待办消息,招标公告,中标公告,信息发布 描述: 全过程数字化采购管理,打造从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理。通供应商门户具备内外协同的能力,为外…...
stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
Cesium1.95中高性能加载1500个点
一、基本方式: 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...
高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...
HBuilderX安装(uni-app和小程序开发)
下载HBuilderX 访问官方网站:https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本: Windows版(推荐下载标准版) Windows系统安装步骤 运行安装程序: 双击下载的.exe安装文件 如果出现安全提示&…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...
ubuntu22.04有线网络无法连接,图标也没了
今天突然无法有线网络无法连接任何设备,并且图标都没了 错误案例 往上一顿搜索,试了很多博客都不行,比如 Ubuntu22.04右上角网络图标消失 最后解决的办法 下载网卡驱动,重新安装 操作步骤 查看自己网卡的型号 lspci | gre…...
数据库正常,但后端收不到数据原因及解决
从代码和日志来看,后端SQL查询确实返回了数据,但最终user对象却为null。这表明查询结果没有正确映射到User对象上。 在前后端分离,并且ai辅助开发的时候,很容易出现前后端变量名不一致情况,还不报错,只是单…...
渗透实战PortSwigger Labs指南:自定义标签XSS和SVG XSS利用
阻止除自定义标签之外的所有标签 先输入一些标签测试,说是全部标签都被禁了 除了自定义的 自定义<my-tag onmouseoveralert(xss)> <my-tag idx onfocusalert(document.cookie) tabindex1> onfocus 当元素获得焦点时(如通过点击或键盘导航&…...
