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.大多数人开始学编程时…...
企业电子招投标采购系统——功能模块功能描述
功能模块: 待办消息,招标公告,中标公告,信息发布 描述: 全过程数字化采购管理,打造从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理。通供应商门户具备内外协同的能力,为外…...
Presto 在美图的实践
导读:本文的主题是Presto高性能引擎在美图的实践,首先将介绍美图在处理ad-hoc场景下为何选择Presto,其次我们如何通过外部组件对Presto高可用与稳定性的增强。然后介绍在美图业务中如何做到合理与高效的利用集群资源,最后如何利用…...
Molecule:使用Jetpack Compose构建StateFlow流
Molecule:使用Jetpack Compose构建StateFlow流 看下面的jetpack compose片段: Composable fun MessageCard(message: Message) {Column {Text(text message.author)Text(text message.body)} }这段代码最有趣的部分是它实际上是reactive。其反应性为 通过Composa…...
计算机组成原理(2.2)--系统总线
目录 一、总线结构 1.单总线结构 1.1单总线结构框图 编辑1.2单总线性能下降的原因 2.多总线结构 2.1双总线结构 2.2三总线结构 2.3四总线结构 编辑 二、总线结构举例 1. 传统微型机总线结构 2. VL-BUS局部总线结构 3. PCI 总线结构 4. 多层 PCI 总线结构 …...
如何使用dlinject将一个代码库实时注入到Linux进程中
关于dlinject dlinject是一款针对Linux进程安全的注入测试工具,在该工具的帮助下,广大研究人员可以在不使用ptrace的情况下,轻松向正在运行的Linux进程中注入一个共享代码库(比如说任意代码)。之所以开发该工具&#…...
Docker安装Cassandra数据库,在SpringBoot中连接Cassandra
简介 Apache Cassandra是一个高度可扩展的高性能分布式数据库,旨在处理许多商用服务器上的大量数据,提供高可用性而没有单点故障。它是NoSQL数据库的一种。首先让我们了解一下NoSQL数据库的作用。 NoSQL 数据库 NoSQL数据库(有时称为“Not …...
Linux常用命令总结(建议收藏)
Linux常用命令总结(建议收藏) 这里收集了一些常用命令以便需要时查看,欢迎作补充。(这里的提到操作都默认以CentOS系统为基础) 文件管理 目录操作 切换目录 cd 查看目录 ls -l 列出文件详细信息 或者直接ll-a 列出当前目录下所有文件及…...
【Java】P1 基础知识与碎碎念
Java 基础知识 碎碎念安装 Intellij IDEAJDK 与 JREJava 运行过程Java 系统配置Java 运行过程Java的三大分类前言 本节内容主要围绕Java基础内容,从Java的安装到helloworld,什么是JDK与什么是JRE,系统环境配置,不深入Java代码知识…...
Jackson CVE-2017-7525 反序列化漏洞
0x00 前言 Jackson 相对应fastjson来说利用方面要求更加苛刻,默认情况下无法进行利用。 同样本次的调用链也可以参考fastjson内容:Java代码审计——Fastjson TemplatesImpl调用链 相关原理,可以参考:Jackson 反序列化漏洞原理 …...
【2023】DevOps、SRE、运维开发面试宝典之Kubernetes相关面试题
文章目录 1、Kubernetes集群的特点?2、Kubernetes集群各节点的组件有那些?分别有什么作用?3、简述Kubernetes集群的工作原理4、什么是Pod资源5、Label标签的作用?6、Deployment控制器与Statfulset控制器的区别?7、Pod拉取镜像的三种策略?8、简述Pod的生命周期9、Pod的生命…...
【算法】PatchMatch立体匹配算法_原理解析
目录 前言 原理解析 1.倾斜支持窗口(Slanted Support Windows) 什么是视差平面? 为什么视差和像素坐标点之间的关系可以解释为平面方程? 视差平面的通用参数方程和点加法向量方程 什么是倾斜支持窗口? 2.基于倾…...
哪个网站可以做魔方图片大全/必应搜索引擎网站
select * from 表名 where datalength(列名)0 or datalength(列名) is null转载于:https://www.cnblogs.com/flyrain/p/SQL_Ntext.html...
网站开发用php还是.net好/网络推广app是干什么的
ldd : 列出一个可执行文件在运行时需要的共享库信息 ar : 创建静态库,插入,删除,列出和提取成员 strings : 列出文件中的所有可打印字符串strip : 从目标文件中删除符号表信息nm : 列出目标文件中符号表中定义的符号size : 列出目标文件中…...
网站多少图片怎么做超链接/个人接广告的平台
本文作者是法国里尔大学Inria SequeL团队的博士生,Yannis Flet-Berliac,他在本文中对分层强化学习(HRL)的研究进行了总结,文章首先回顾了强化学习(RL)的基本原理,并阐述了其目前所面…...
郑州网站建设时一定需要注意的六点/网站出售
涉及到链表的面试题: 如果有链表编号的参数,先明确链表的编号是从0开始还是从1开始如果输入有编号、个数这样的参数时,使用unsigned int ,这样最多只需要判断其不等于0即可两个指针可以做很多事,例如先把他们间隔固定,最后一个到结尾时,第一个指针就指向倒数第n个结点了…...
电力建设监理招聘网站/青岛seo网络推广
实现思路:1、 v-model 一个收集所有input(除全选框外)数组checkModel ,vue会动态将其checked为true的input的value值存入数组checkModel里2 、watch函数来监听checkModel 属性,当其长度input元素时 全选按钮选中 否则取消3 、全选按钮v-model…...
国有林场网站建设/seo整站优化外包
质数概念质数 ,又称 素数 ,指在一个大于1的 自然数 中,除了1和此整数自身外,无法被其他自然数 整除 的数(也可定义为只有 1 和本身两个 因数 的数)。最小的素数是2,也是素数中唯一的偶数;其他素数都是奇数。…...