20.0: Network & Sensors permission from GrapheneOS

This revokes the permissions to all user installed apps on update.
Likely an expected quirk of being on 20.0 without the permission.
19.1 upgrades and new 20.0 installs should be fine.

TODO: update 19.1 with the SpecialRuntimePermAppUtils too

Signed-off-by: Tad <tad@spotco.us>
This commit is contained in:
Tad 2022-10-18 17:13:17 -04:00
parent cdca2c032e
commit 0c4db149e1
No known key found for this signature in database
GPG key ID: B286E9F57A07424B
33 changed files with 2211 additions and 65 deletions

View file

@ -1,48 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor <muhomor.dmitry@gmail.com>
Date: Fri, 29 Jul 2022 20:45:30 +0300
Subject: [PATCH] bugfix: reportNetworkConnectivity() wasn't switched to
isInternetCompatEnabled()
---
framework/src/android/net/ConnectivityManager.java | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java
index 8857b7996..0fa34a46b 100644
--- a/framework/src/android/net/ConnectivityManager.java
+++ b/framework/src/android/net/ConnectivityManager.java
@@ -25,7 +25,6 @@ import static android.net.NetworkRequest.Type.TRACK_DEFAULT;
import static android.net.NetworkRequest.Type.TRACK_SYSTEM_DEFAULT;
import static android.net.QosCallback.QosCallbackRegistrationException;
-import android.Manifest;
import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -43,7 +42,7 @@ import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.PackageManager;
+import android.content.pm.SpecialRuntimePermAppUtils;
import android.net.ConnectivityDiagnosticsManager.DataStallReport.DetectionMethod;
import android.net.IpSecManager.UdpEncapsulationSocket;
import android.net.SocketKeepalive.Callback;
@@ -3141,12 +3140,12 @@ public class ConnectivityManager {
*/
public void reportNetworkConnectivity(@Nullable Network network, boolean hasConnectivity) {
printStackTrace();
- if (mContext.checkSelfPermission(Manifest.permission.INTERNET) != PackageManager.PERMISSION_GRANTED) {
- // ConnectivityService enforces this by throwing an unexpected SecurityException,
- // which puts GMS into a crash loop. Also useful for other apps that don't expect that
- // INTERNET permission might get revoked.
+
+ if (SpecialRuntimePermAppUtils.isInternetCompatEnabled()) {
+ // caller doesn't have INTERNET, but expects to always have it
return;
}
+
try {
mService.reportNetworkConnectivity(network, hasConnectivity);
} catch (RemoteException e) {

View file

@ -0,0 +1,28 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor <muhomor.dmitry@gmail.com>
Date: Thu, 18 Aug 2022 10:04:46 +0300
Subject: [PATCH] fix DevicePolicyManager#logoutUser() never succeeding
To succeed, userId to switch to needs to be set with setLogoutUserIdLocked(), but this is not done
in both callers of this method (both of which are "End session" buttons), making them no-ops.
---
.../server/devicepolicy/DevicePolicyManagerService.java | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 4be9c1a1d54a..a33f4fa55b53 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -11155,6 +11155,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Preconditions.checkCallAuthorization(canManageUsers(caller)
|| hasCallingOrSelfPermission(permission.INTERACT_ACROSS_USERS));
+ synchronized (getLockObject()) {
+ if (getLogoutUserIdUnchecked() == UserHandle.USER_NULL) {
+ setLogoutUserIdLocked(UserHandle.USER_SYSTEM);
+ }
+ }
+
int currentUserId = getCurrentForegroundUserId();
if (VERBOSE_LOG) {
Slogf.v(LOG_TAG, "logout() called by uid %d; current user is %d", caller.getUid(),

View file

@ -0,0 +1,137 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: inthewaves <inthewaves@pm.me>
Date: Sat, 12 Sep 2020 22:28:34 +0300
Subject: [PATCH] support new special runtime permissions
Ported from 12: b294a2ce1d0d185dbc438ac3c06c90386d5f5949
---
.../PermissionManagerServiceImpl.java | 39 ++++++++++++++-----
1 file changed, 30 insertions(+), 9 deletions(-)
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
index d34682df3413..1d974b980f6e 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
@@ -1409,7 +1409,8 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
// their permissions as always granted runtime ones since we need
// to keep the review required permission flag per user while an
// install permission's state is shared across all users.
- if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.M && bp.isRuntime()) {
+ if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.M && bp.isRuntime() &&
+ !isSpecialRuntimePermission(permName)) {
return;
}
@@ -1452,7 +1453,8 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
+ " for package " + packageName);
}
- if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.M) {
+ if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.M &&
+ !isSpecialRuntimePermission(permName)) {
Slog.w(TAG, "Cannot grant runtime permission to a legacy app");
return;
}
@@ -1598,7 +1600,8 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
// their permissions as always granted runtime ones since we need
// to keep the review required permission flag per user while an
// install permission's state is shared across all users.
- if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.M && bp.isRuntime()) {
+ if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.M && bp.isRuntime() &&
+ !isSpecialRuntimePermission(permName)) {
return;
}
@@ -1784,7 +1787,8 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
// permission as requiring a review as this is the initial state.
final int uid = mPackageManagerInt.getPackageUid(packageName, 0, userId);
final int targetSdk = mPackageManagerInt.getUidTargetSdkVersion(uid);
- final int flags = (targetSdk < Build.VERSION_CODES.M && isRuntimePermission)
+ final int flags = (targetSdk < Build.VERSION_CODES.M && isRuntimePermission
+ && !isSpecialRuntimePermission(permName))
? FLAG_PERMISSION_REVIEW_REQUIRED | FLAG_PERMISSION_REVOKED_COMPAT
: 0;
@@ -1804,7 +1808,8 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
// If this permission was granted by default or role, make sure it is.
if ((oldFlags & FLAG_PERMISSION_GRANTED_BY_DEFAULT) != 0
- || (oldFlags & FLAG_PERMISSION_GRANTED_BY_ROLE) != 0) {
+ || (oldFlags & FLAG_PERMISSION_GRANTED_BY_ROLE) != 0
+ || isSpecialRuntimePermission(permName)) {
// PermissionPolicyService will handle the app op for runtime permissions later.
grantRuntimePermissionInternal(packageName, permName, false,
Process.SYSTEM_UID, userId, delayingPermCallback);
@@ -2477,6 +2482,10 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
}
}
+ public static boolean isSpecialRuntimePermission(final String permission) {
+ return false;
+ }
+
/**
* Restore the permission state for a package.
*
@@ -2601,6 +2610,8 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
synchronized (mLock) {
for (final int userId : userIds) {
final UserPermissionState userState = mState.getOrCreateUserState(userId);
+ // "replace" parameter is set to true even when the app is first installed
+ final boolean uidStateWasPresent = userState.getUidState(ps.getAppId()) != null;
final UidPermissionState uidState = userState.getOrCreateUidState(ps.getAppId());
if (uidState.isMissing()) {
@@ -2617,7 +2628,7 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT,
FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT);
}
- if (uidTargetSdkVersion < Build.VERSION_CODES.M) {
+ if (uidTargetSdkVersion < Build.VERSION_CODES.M && !isSpecialRuntimePermission(permissionName)) {
uidState.updatePermissionFlags(permission,
PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED
| PackageManager.FLAG_PERMISSION_REVOKED_COMPAT,
@@ -2823,7 +2834,7 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
boolean restrictionApplied = (origState.getPermissionFlags(
bp.getName()) & FLAG_PERMISSION_APPLY_RESTRICTION) != 0;
- if (appSupportsRuntimePermissions) {
+ if (appSupportsRuntimePermissions || isSpecialRuntimePermission(bp.getName())) {
// If hard restricted we don't allow holding it
if (permissionPolicyInitialized && hardRestricted) {
if (!restrictionExempt) {
@@ -2877,6 +2888,16 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
}
}
}
+
+ if (isSpecialRuntimePermission(permName) &&
+ origPermState == null &&
+ // don't grant special runtime permission after update,
+ // unless app comes from the system image
+ (!uidStateWasPresent || ps.isSystem())) {
+ if (uidState.grantPermission(bp)) {
+ wasChanged = true;
+ }
+ }
} else {
if (origPermState == null) {
// New permission
@@ -2911,7 +2932,7 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
if (restrictionApplied) {
flags &= ~FLAG_PERMISSION_APPLY_RESTRICTION;
// Dropping restriction on a legacy app implies a review
- if (!appSupportsRuntimePermissions) {
+ if (!appSupportsRuntimePermissions && !isSpecialRuntimePermission(bp.getName())) {
flags |= FLAG_PERMISSION_REVIEW_REQUIRED;
}
wasChanged = true;
@@ -3642,7 +3663,7 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
if (shouldGrantPermission) {
final int flags = getPermissionFlagsInternal(pkg.getPackageName(), permission,
myUid, userId);
- if (supportsRuntimePermissions) {
+ if (supportsRuntimePermissions || isSpecialRuntimePermission(permission)) {
// Installer cannot change immutable permissions.
if ((flags & immutableFlags) == 0) {
grantRuntimePermissionInternal(pkg.getPackageName(), permission, false,

View file

@ -0,0 +1,25 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor <muhomor.dmitry@gmail.com>
Date: Fri, 7 Oct 2022 20:12:26 +0300
Subject: [PATCH] srt permissions: don't auto-grant denied ones when
permissions are reset
---
.../server/pm/permission/PermissionManagerServiceImpl.java | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
index da832f59671d..2204ad6721c8 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
@@ -1809,7 +1809,9 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
// If this permission was granted by default or role, make sure it is.
if ((oldFlags & FLAG_PERMISSION_GRANTED_BY_DEFAULT) != 0
|| (oldFlags & FLAG_PERMISSION_GRANTED_BY_ROLE) != 0
- || isSpecialRuntimePermission(permName)) {
+ || (isSpecialRuntimePermission(permName)
+ && checkPermission(packageName, permName, userId) == PERMISSION_GRANTED)
+ ) {
// PermissionPolicyService will handle the app op for runtime permissions later.
grantRuntimePermissionInternal(packageName, permName, false,
Process.SYSTEM_UID, userId, delayingPermCallback);

View file

@ -0,0 +1,231 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor <muhomor.dmitry@gmail.com>
Date: Fri, 7 Oct 2022 20:15:14 +0300
Subject: [PATCH] srt permissions: fix auto granting after package install
Previous approach to auto-granting is not compatible with ability to disable auto-grants:
special runtime permissions were auto-granted for all users, including those that didn't have
the package installed.
---
.../server/pm/InstallPackageHelper.java | 10 +++--
.../PermissionManagerServiceImpl.java | 43 +++++++++++++------
.../PermissionManagerServiceInternal.java | 20 ++++++++-
3 files changed, 55 insertions(+), 18 deletions(-)
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 7da5f51bcbc2..f7fa93bce4cb 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -599,6 +599,7 @@ final class InstallPackageHelper {
permissionParamsBuilder.setAllowlistedRestrictedPermissions(
pkgSetting.getPkg().getRequestedPermissions());
}
+ permissionParamsBuilder.setNewlyInstalledInUserId(userId);
mPm.mPermissionManager.onPackageInstalled(pkgSetting.getPkg(),
Process.INVALID_UID /* previousAppId */,
permissionParamsBuilder.build(), userId);
@@ -2118,6 +2119,10 @@ final class InstallPackageHelper {
}
}
+ final PermissionManagerServiceInternal.PackageInstalledParams.Builder
+ permissionParamsBuilder =
+ new PermissionManagerServiceInternal.PackageInstalledParams.Builder();
+
// Set install reason for users that are having the package newly installed.
final int[] allUsersList = mPm.mUserManager.getUserIds();
if (userId == UserHandle.USER_ALL) {
@@ -2125,10 +2130,12 @@ final class InstallPackageHelper {
if (!previousUserIds.contains(currentUserId)
&& ps.getInstalled(currentUserId)) {
ps.setInstallReason(installReason, currentUserId);
+ permissionParamsBuilder.setNewlyInstalledInUserId(currentUserId);
}
}
} else if (!previousUserIds.contains(userId)) {
ps.setInstallReason(installReason, userId);
+ permissionParamsBuilder.setNewlyInstalledInUserId(userId);
}
// TODO(b/169721400): generalize Incremental States and create a Callback object
@@ -2149,9 +2156,6 @@ final class InstallPackageHelper {
mPm.mSettings.writeKernelMappingLPr(ps);
- final PermissionManagerServiceInternal.PackageInstalledParams.Builder
- permissionParamsBuilder =
- new PermissionManagerServiceInternal.PackageInstalledParams.Builder();
final boolean grantPermissions = (installArgs.mInstallFlags
& PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS) != 0;
if (grantPermissions) {
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
index 2204ad6721c8..0fcd067142f5 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
@@ -136,6 +136,7 @@ import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
import com.android.server.pm.pkg.AndroidPackageApi;
import com.android.server.pm.pkg.PackageStateInternal;
+import com.android.server.pm.pkg.PackageUserStateUtils;
import com.android.server.pm.pkg.component.ComponentMutateUtils;
import com.android.server.pm.pkg.component.ParsedPermission;
import com.android.server.pm.pkg.component.ParsedPermissionGroup;
@@ -2611,9 +2612,10 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
synchronized (mLock) {
for (final int userId : userIds) {
+ final boolean isNotInstalledUserApp = !ps.isSystem()
+ && !PackageUserStateUtils.isAvailable(ps.getUserStateOrDefault(userId), 0);
+
final UserPermissionState userState = mState.getOrCreateUserState(userId);
- // "replace" parameter is set to true even when the app is first installed
- final boolean uidStateWasPresent = userState.getUidState(ps.getAppId()) != null;
final UidPermissionState uidState = userState.getOrCreateUidState(ps.getAppId());
if (uidState.isMissing()) {
@@ -2891,13 +2893,23 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
}
}
- if (isSpecialRuntimePermission(permName) &&
- origPermState == null &&
- // don't grant special runtime permission after update,
- // unless app comes from the system image
- (!uidStateWasPresent || ps.isSystem())) {
- if (uidState.grantPermission(bp)) {
- wasChanged = true;
+ if (isSpecialRuntimePermission(permName)) {
+ if (origPermState == null && ps.isSystem()) {
+ // always grant special runtime permissions to system packages
+ if (uidState.grantPermission(bp)) {
+ wasChanged = true;
+ }
+ }
+
+ if (isNotInstalledUserApp) {
+ // Previously, special runtime permissions were granted in users
+ // that didn't have the package installed, which breaks the code
+ // that allows to skip granting these permissions at install time.
+ // (if UidPermissionState is already present at install time, it's
+ // reused as is).
+ if (uidState.revokePermission(bp)) {
+ wasChanged = true;
+ }
}
}
} else {
@@ -3639,7 +3651,7 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
}
private void grantRequestedRuntimePermissionsInternal(@NonNull AndroidPackage pkg,
- @Nullable List<String> permissions, int userId) {
+ @Nullable List<String> permissions, int userId, boolean newlyInstalled) {
final int immutableFlags = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
| PackageManager.FLAG_PERMISSION_POLICY_FIXED;
@@ -3654,6 +3666,9 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
final int myUid = Process.myUid();
for (String permission : pkg.getRequestedPermissions()) {
+ final boolean isPregrantedSpecialRuntimePermission = newlyInstalled &&
+ SpecialRuntimePermUtils.shouldAutoGrant(pkg.getPackageName(), userId, permission);
+
final boolean shouldGrantPermission;
synchronized (mLock) {
final Permission bp = mRegistry.getPermission(permission);
@@ -3662,10 +3677,11 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
&& (supportsRuntimePermissions || !bp.isRuntimeOnly())
&& (permissions == null || permissions.contains(permission));
}
- if (shouldGrantPermission) {
+
+ if (shouldGrantPermission || isPregrantedSpecialRuntimePermission) {
final int flags = getPermissionFlagsInternal(pkg.getPackageName(), permission,
myUid, userId);
- if (supportsRuntimePermissions || isSpecialRuntimePermission(permission)) {
+ if (supportsRuntimePermissions || isPregrantedSpecialRuntimePermission) {
// Installer cannot change immutable permissions.
if ((flags & immutableFlags) == 0) {
grantRuntimePermissionInternal(pkg.getPackageName(), permission, false,
@@ -5016,7 +5032,8 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
addAllowlistedRestrictedPermissionsInternal(pkg,
params.getAllowlistedRestrictedPermissions(),
FLAG_PERMISSION_WHITELIST_INSTALLER, userId);
- grantRequestedRuntimePermissionsInternal(pkg, params.getGrantedPermissions(), userId);
+ grantRequestedRuntimePermissionsInternal(pkg, params.getGrantedPermissions(), userId,
+ params.isNewlyInstalledInUserId(userId));
}
}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
index 95badb31f324..d17c0697ff7a 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
@@ -22,6 +22,7 @@ import android.annotation.UserIdInt;
import android.app.AppOpsManager;
import android.content.pm.PermissionInfo;
import android.permission.PermissionManagerInternal;
+import android.util.SparseBooleanArray;
import com.android.server.pm.parsing.pkg.AndroidPackage;
@@ -322,13 +323,17 @@ public interface PermissionManagerServiceInternal extends PermissionManagerInter
private final List<String> mAllowlistedRestrictedPermissions;
@NonNull
private final int mAutoRevokePermissionsMode;
+ @NonNull
+ private final SparseBooleanArray mNewlyInstalledInUserIds;
private PackageInstalledParams(@NonNull List<String> grantedPermissions,
@NonNull List<String> allowlistedRestrictedPermissions,
- int autoRevokePermissionsMode) {
+ int autoRevokePermissionsMode,
+ SparseBooleanArray newlyInstalledInUserIds) {
mGrantedPermissions = grantedPermissions;
mAllowlistedRestrictedPermissions = allowlistedRestrictedPermissions;
mAutoRevokePermissionsMode = autoRevokePermissionsMode;
+ mNewlyInstalledInUserIds = newlyInstalledInUserIds;
}
/**
@@ -360,6 +365,10 @@ public interface PermissionManagerServiceInternal extends PermissionManagerInter
return mAutoRevokePermissionsMode;
}
+ public boolean isNewlyInstalledInUserId(int userId) {
+ return mNewlyInstalledInUserIds.get(userId, false);
+ }
+
/**
* Builder class for {@link PackageInstalledParams}.
*/
@@ -370,6 +379,8 @@ public interface PermissionManagerServiceInternal extends PermissionManagerInter
private List<String> mAllowlistedRestrictedPermissions = Collections.emptyList();
@NonNull
private int mAutoRevokePermissionsMode = AppOpsManager.MODE_DEFAULT;
+ @NonNull
+ private final SparseBooleanArray mNewlyInstalledInUserIds = new SparseBooleanArray();
/**
* Set the permissions to be granted.
@@ -419,6 +430,10 @@ public interface PermissionManagerServiceInternal extends PermissionManagerInter
mAutoRevokePermissionsMode = autoRevokePermissionsMode;
}
+ public void setNewlyInstalledInUserId(int userId) {
+ mNewlyInstalledInUserIds.put(userId, true);
+ }
+
/**
* Build a new instance of {@link PackageInstalledParams}.
*
@@ -427,7 +442,8 @@ public interface PermissionManagerServiceInternal extends PermissionManagerInter
@NonNull
public PackageInstalledParams build() {
return new PackageInstalledParams(mGrantedPermissions,
- mAllowlistedRestrictedPermissions, mAutoRevokePermissionsMode);
+ mAllowlistedRestrictedPermissions, mAutoRevokePermissionsMode,
+ mNewlyInstalledInUserIds);
}
}
}

View file

@ -0,0 +1,33 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor <muhomor.dmitry@gmail.com>
Date: Sun, 16 Oct 2022 17:13:03 +0300
Subject: [PATCH] srt permissions: don't auto-revoke from "hidden" packages
Special runtime permissions are auto-revoked in users that don't have the package installed, as a
workaround to a bug in previous OS versions that granted these permissions automatically in all
user profiles, including the ones that don't have this package installed, which interfered with
configurable auto-grants.
PackageUserStateUtils.isAvailable() is not the right check for this, it returns false for apps
which are "hidden" with DevicePolicyManager#setApplicationHidden(). This method is used by work
profile managers (in particular, Shelter) to implement "app freezing" functionality.
This led to special runtime permission being auto-revoked from "hidden" packages after OS reboot
and in a few other cases.
---
.../server/pm/permission/PermissionManagerServiceImpl.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
index 0fcd067142f5..d546ee0db05f 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
@@ -2613,7 +2613,7 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
synchronized (mLock) {
for (final int userId : userIds) {
final boolean isNotInstalledUserApp = !ps.isSystem()
- && !PackageUserStateUtils.isAvailable(ps.getUserStateOrDefault(userId), 0);
+ && !ps.getUserStateOrDefault(userId).isInstalled();
final UserPermissionState userState = mState.getOrCreateUserState(userId);
final UidPermissionState uidState = userState.getOrCreateUidState(ps.getAppId());

View file

@ -0,0 +1,144 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor <muhomor.dmitry@gmail.com>
Date: Fri, 7 Oct 2022 20:47:48 +0300
Subject: [PATCH] PackageInstallerUI: an option to skip auto-grant of INTERNET
permission
---
.../res/layout/install_content_view.xml | 25 ++++++++++---
.../PackageInstaller/res/values/strings.xml | 2 ++
.../PackageInstallerActivity.java | 35 +++++++++++++++++++
3 files changed, 58 insertions(+), 4 deletions(-)
diff --git a/packages/PackageInstaller/res/layout/install_content_view.xml b/packages/PackageInstaller/res/layout/install_content_view.xml
index 2ecd2d55ac71..4db24fffd7ea 100644
--- a/packages/PackageInstaller/res/layout/install_content_view.xml
+++ b/packages/PackageInstaller/res/layout/install_content_view.xml
@@ -70,13 +70,30 @@
</LinearLayout>
- <TextView
+ <LinearLayout
android:id="@+id/install_confirm_question"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- style="@android:style/TextAppearance.Material.Subhead"
- android:text="@string/install_confirm_question"
- android:visibility="invisible" />
+ android:orientation="vertical"
+ android:visibility="invisible">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ style="@android:style/TextAppearance.Material.Subhead"
+ android:text="@string/install_confirm_question" />
+
+ <CheckBox
+ android:id="@+id/install_allow_INTERNET_permission"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ style="@android:style/TextAppearance.Material.Subhead"
+ android:text="@string/allow_network_permission_checkbox"
+ android:checked="true"
+ android:visibility="gone" />
+
+ </LinearLayout>
<TextView
android:id="@+id/install_confirm_question_update"
diff --git a/packages/PackageInstaller/res/values/strings.xml b/packages/PackageInstaller/res/values/strings.xml
index 688d11691477..36d3beb03ee0 100644
--- a/packages/PackageInstaller/res/values/strings.xml
+++ b/packages/PackageInstaller/res/values/strings.xml
@@ -235,4 +235,6 @@
<!-- Notification shown in status bar when an application is successfully installed.
[CHAR LIMIT=50] -->
<string name="notification_installation_success_status">Successfully installed \u201c<xliff:g id="appname" example="Package Installer">%1$s</xliff:g>\u201d</string>
+
+ <string name="allow_network_permission_checkbox">Allow Network permission</string>
</resources>
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
index 10eefebadeff..7ecd02e47852 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
@@ -44,16 +44,19 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.Bundle;
import android.os.Process;
+import android.os.RemoteException;
import android.os.UserManager;
import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.widget.Button;
+import android.widget.CheckBox;
import com.android.internal.app.AlertActivity;
import java.io.File;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
/**
@@ -132,6 +135,8 @@ public class PackageInstallerActivity extends AlertActivity {
private boolean mPermissionResultWasSet;
private boolean mAllowNextOnPause;
+ private CheckBox mGrantInternetPermission;
+
private void startInstallConfirm() {
View viewToEnable;
@@ -141,6 +146,14 @@ public class PackageInstallerActivity extends AlertActivity {
} else {
// This is a new application with no permissions.
viewToEnable = requireViewById(R.id.install_confirm_question);
+
+ if (mPkgInfo != null) {
+ String[] perms = mPkgInfo.requestedPermissions;
+ if (perms != null && Arrays.asList(perms).contains(Manifest.permission.INTERNET)) {
+ mGrantInternetPermission = requireViewById(R.id.install_allow_INTERNET_permission);
+ mGrantInternetPermission.setVisibility(View.VISIBLE);
+ }
+ }
}
viewToEnable.setVisibility(View.VISIBLE);
@@ -438,6 +451,8 @@ public class PackageInstallerActivity extends AlertActivity {
mAlert.setButton(DialogInterface.BUTTON_POSITIVE, getString(R.string.install),
(ignored, ignored2) -> {
if (mOk.isEnabled()) {
+ handleSpecialRuntimePermissionAutoGrants();
+
if (mSessionId != -1) {
mInstaller.setPermissionsResult(mSessionId, true);
mPermissionResultWasSet = true;
@@ -894,4 +909,24 @@ public class PackageInstallerActivity extends AlertActivity {
getActivity().finish();
}
}
+
+ void handleSpecialRuntimePermissionAutoGrants() {
+ var skipPermissionAutoGrants = new ArrayList<String>();
+
+ if (mGrantInternetPermission != null) {
+ if (!mGrantInternetPermission.isChecked()) {
+ skipPermissionAutoGrants.add(Manifest.permission.INTERNET);
+ }
+ }
+
+ var pm = AppGlobals.getPackageManager();
+ var pkgName = mPkgInfo.packageName;
+ int userId = getUserId();
+ try {
+ pm.skipSpecialRuntimePermissionAutoGrantsForPackage(pkgName,
+ userId, skipPermissionAutoGrants);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}

View file

@ -0,0 +1,81 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Daniel Micay <danielmicay@gmail.com>
Date: Sun, 17 Mar 2019 17:59:15 +0200
Subject: [PATCH] make INTERNET into a special runtime permission
Ported from 12: a980a4c3d6b6906eb0ee5fb07ca4cf0bae052d00
---
core/api/current.txt | 1 +
core/res/AndroidManifest.xml | 10 +++++++++-
core/res/res/values/strings.xml | 5 +++++
.../pm/permission/PermissionManagerServiceImpl.java | 2 +-
4 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/core/api/current.txt b/core/api/current.txt
index c8a43db2f9c2..f229b6e25126 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -225,6 +225,7 @@ package android {
field public static final String LOCATION = "android.permission-group.LOCATION";
field public static final String MICROPHONE = "android.permission-group.MICROPHONE";
field public static final String NEARBY_DEVICES = "android.permission-group.NEARBY_DEVICES";
+ field public static final String NETWORK = "android.permission-group.NETWORK";
field public static final String NOTIFICATIONS = "android.permission-group.NOTIFICATIONS";
field public static final String PHONE = "android.permission-group.PHONE";
field public static final String READ_MEDIA_AURAL = "android.permission-group.READ_MEDIA_AURAL";
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 6e48de5ba31f..371a036e284a 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1971,13 +1971,21 @@
<!-- ======================================= -->
<eat-comment />
+ <!-- Network access -->
+ <permission-group android:name="android.permission-group.NETWORK"
+ android:icon="@drawable/perm_group_network"
+ android:label="@string/permgrouplab_network"
+ android:description="@string/permgroupdesc_network"
+ android:priority="900" />
+
<!-- Allows applications to open network sockets.
<p>Protection level: normal
-->
<permission android:name="android.permission.INTERNET"
+ android:permissionGroup="android.permission-group.UNDEFINED"
android:description="@string/permdesc_createNetworkSockets"
android:label="@string/permlab_createNetworkSockets"
- android:protectionLevel="normal|instant" />
+ android:protectionLevel="dangerous|instant" />
<!-- Allows applications to access information about networks.
<p>Protection level: normal
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index c6b60f586047..42922a094cd7 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -931,6 +931,11 @@
<!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=NONE]-->
<string name="permgroupdesc_notifications">show notifications</string>
+ <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permgrouplab_network">Network</string>
+ <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permgroupdesc_network">access the network</string>
+
<!-- Title for the capability of an accessibility service to retrieve window content. -->
<string name="capability_title_canRetrieveWindowContent">Retrieve window content</string>
<!-- Description for the capability of an accessibility service to retrieve window content. -->
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
index 1d974b980f6e..7c76d55d7ae4 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
@@ -2483,7 +2483,7 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
}
public static boolean isSpecialRuntimePermission(final String permission) {
- return false;
+ return Manifest.permission.INTERNET.equals(permission);
}
/**

View file

@ -0,0 +1,113 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Daniel Micay <danielmicay@gmail.com>
Date: Sat, 7 Oct 2017 22:54:42 +0300
Subject: [PATCH] add special runtime permission for other sensors
Ported from 12: 9d5a62ed573bc3c7be8b19445b372fed13533d0e
---
core/api/current.txt | 2 ++
core/res/AndroidManifest.xml | 12 ++++++++++++
core/res/res/values/strings.xml | 12 ++++++++++++
.../pm/permission/PermissionManagerServiceImpl.java | 2 +-
.../server/pm/pkg/parsing/ParsingPackageUtils.java | 2 ++
5 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/core/api/current.txt b/core/api/current.txt
index f229b6e25126..773d77422d9f 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -122,6 +122,7 @@ package android {
field public static final String NFC = "android.permission.NFC";
field public static final String NFC_PREFERRED_PAYMENT_INFO = "android.permission.NFC_PREFERRED_PAYMENT_INFO";
field public static final String NFC_TRANSACTION_EVENT = "android.permission.NFC_TRANSACTION_EVENT";
+ field public static final String OTHER_SENSORS = "android.permission.OTHER_SENSORS";
field public static final String OVERRIDE_WIFI_CONFIG = "android.permission.OVERRIDE_WIFI_CONFIG";
field public static final String PACKAGE_USAGE_STATS = "android.permission.PACKAGE_USAGE_STATS";
field @Deprecated public static final String PERSISTENT_ACTIVITY = "android.permission.PERSISTENT_ACTIVITY";
@@ -227,6 +228,7 @@ package android {
field public static final String NEARBY_DEVICES = "android.permission-group.NEARBY_DEVICES";
field public static final String NETWORK = "android.permission-group.NETWORK";
field public static final String NOTIFICATIONS = "android.permission-group.NOTIFICATIONS";
+ field public static final String OTHER_SENSORS = "android.permission-group.OTHER_SENSORS";
field public static final String PHONE = "android.permission-group.PHONE";
field public static final String READ_MEDIA_AURAL = "android.permission-group.READ_MEDIA_AURAL";
field public static final String READ_MEDIA_VISUAL = "android.permission-group.READ_MEDIA_VISUAL";
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 371a036e284a..eb64b68836f4 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1732,6 +1732,18 @@
android:protectionLevel="dangerous|instant" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
+ <permission-group android:name="android.permission-group.OTHER_SENSORS"
+ android:icon="@drawable/perm_group_location"
+ android:label="@string/permgrouplab_otherSensors"
+ android:description="@string/permgroupdesc_otherSensors"
+ android:priority="1000" />
+
+ <permission android:name="android.permission.OTHER_SENSORS"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_otherSensors"
+ android:description="@string/permdesc_otherSensors"
+ android:protectionLevel="dangerous" />
+
<!-- ====================================================================== -->
<!-- REMOVED PERMISSIONS -->
<!-- ====================================================================== -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 42922a094cd7..b153a36f65db 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -931,6 +931,11 @@
<!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=NONE]-->
<string name="permgroupdesc_notifications">show notifications</string>
+ <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permgrouplab_otherSensors">Sensors</string>
+ <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permgroupdesc_otherSensors">access sensor data about orientation, movement, etc.</string>
+
<!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permgrouplab_network">Network</string>
<!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
@@ -1261,6 +1266,13 @@
<!-- Description of the background body sensors permission, listed so the user can decide whether to allow the application to access data from body sensors in the background. [CHAR LIMIT=NONE] -->
<string name="permdesc_bodySensors_background" product="default">Allows the app to access body sensor data, such as heart rate, temperature, and blood oxygen percentage, while the app is in the background.</string>
+ <!-- Title of the sensors permission, listed so the user can decide whether to allow the application to access sensor data. [CHAR LIMIT=80] -->
+ <string name="permlab_otherSensors">access sensors (like the compass)
+ </string>
+ <!-- Description of the sensors permission, listed so the user can decide whether to allow the application to access data from sensors. [CHAR LIMIT=NONE] -->
+ <string name="permdesc_otherSensors" product="default">Allows the app to access data from sensors
+ monitoring orientation, movement, vibration (including low frequency sound) and environmental data</string>
+
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_readCalendar">Read calendar events and details</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
index 7c76d55d7ae4..da832f59671d 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
@@ -2483,7 +2483,7 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
}
public static boolean isSpecialRuntimePermission(final String permission) {
- return Manifest.permission.INTERNET.equals(permission);
+ return Manifest.permission.INTERNET.equals(permission) || Manifest.permission.OTHER_SENSORS.equals(permission);
}
/**
diff --git a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
index 9bfb40fe11f7..ca3b9e5bda95 100644
--- a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
+++ b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
@@ -2203,6 +2203,8 @@ public class ParsingPackageUtils {
pkg.setHasDomainUrls(hasDomainURLs(pkg));
+ pkg.addUsesPermission(new ParsedUsesPermissionImpl(android.Manifest.permission.OTHER_SENSORS, 0));
+
return input.success(pkg);
}

View file

@ -0,0 +1,118 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor <muhomor.dmitry@gmail.com>
Date: Sun, 31 Jul 2022 18:24:34 +0300
Subject: [PATCH] infrastructure for spoofing self permission checks
---
.../app/ApplicationPackageManager.java | 13 ++++++++-
core/java/android/app/ContextImpl.java | 18 ++++++++++--
.../content/pm/AppPermissionUtils.java | 29 +++++++++++++++++++
3 files changed, 57 insertions(+), 3 deletions(-)
create mode 100644 core/java/android/content/pm/AppPermissionUtils.java
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 475e0f4cb05b..73dcd39a2837 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -47,6 +47,7 @@ import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.pm.ActivityInfo;
import android.content.pm.ApkChecksum;
+import android.content.pm.AppPermissionUtils;
import android.content.pm.ApplicationInfo;
import android.content.pm.ChangedPackages;
import android.content.pm.Checksum;
@@ -835,7 +836,17 @@ public class ApplicationPackageManager extends PackageManager {
@Override
public int checkPermission(String permName, String pkgName) {
- return PermissionManager.checkPackageNamePermission(permName, pkgName, getUserId());
+ int res = PermissionManager.checkPackageNamePermission(permName, pkgName, getUserId());
+
+ if (res != PERMISSION_GRANTED) {
+ if (pkgName.equals(ActivityThread.currentPackageName())
+ && AppPermissionUtils.shouldSpoofSelfCheck(permName))
+ {
+ return PERMISSION_GRANTED;
+ }
+ }
+
+ return res;
}
@Override
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 6d982ced385c..b50cd115382d 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -45,6 +45,7 @@ import android.content.ReceiverCallNotAllowedException;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
+import android.content.pm.AppPermissionUtils;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
@@ -2165,12 +2166,25 @@ class ContextImpl extends Context {
if (permission == null) {
throw new IllegalArgumentException("permission is null");
}
+
+ final boolean selfCheck = pid == android.os.Process.myPid() && uid == android.os.Process.myUid();
+
if (mParams.isRenouncedPermission(permission)
- && pid == android.os.Process.myPid() && uid == android.os.Process.myUid()) {
+ && selfCheck) {
Log.v(TAG, "Treating renounced permission " + permission + " as denied");
return PERMISSION_DENIED;
}
- return PermissionManager.checkPermission(permission, pid, uid);
+ int res = PermissionManager.checkPermission(permission, pid, uid);
+
+ if (res != PERMISSION_GRANTED) {
+ if (selfCheck) {
+ if (AppPermissionUtils.shouldSpoofSelfCheck(permission)) {
+ return PERMISSION_GRANTED;
+ }
+ }
+ }
+
+ return res;
}
/** @hide */
diff --git a/core/java/android/content/pm/AppPermissionUtils.java b/core/java/android/content/pm/AppPermissionUtils.java
new file mode 100644
index 000000000000..7dc20eec8485
--- /dev/null
+++ b/core/java/android/content/pm/AppPermissionUtils.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2022 GrapheneOS
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import android.Manifest;
+
+/** @hide */
+public class AppPermissionUtils {
+
+ // android.app.ApplicationPackageManager#checkPermission(String permName, String pkgName)
+ // android.app.ContextImpl#checkPermission(String permission, int pid, int uid)
+ public static boolean shouldSpoofSelfCheck(String permName) {
+ return false;
+ }
+}

View file

@ -0,0 +1,189 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor <muhomor.dmitry@gmail.com>
Date: Sun, 31 Jul 2022 18:10:28 +0300
Subject: [PATCH] app-side infrastructure for special runtime permissions
---
core/api/system-current.txt | 3 ++
.../android/content/pm/IPackageManager.aidl | 2 +
.../pm/SpecialRuntimePermAppUtils.java | 54 +++++++++++++++++++
.../server/pm/PackageManagerService.java | 19 +++++++
.../permission/SpecialRuntimePermUtils.java | 46 ++++++++++++++++
5 files changed, 124 insertions(+)
create mode 100644 core/java/android/content/pm/SpecialRuntimePermAppUtils.java
create mode 100644 services/core/java/com/android/server/pm/permission/SpecialRuntimePermUtils.java
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 0126199add0c..531b03cd7c0c 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -3546,6 +3546,9 @@ package android.content.pm {
field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.ShortcutManager.ShareShortcutInfo> CREATOR;
}
+ public class SpecialRuntimePermAppUtils {
+ }
+
public final class SuspendDialogInfo implements android.os.Parcelable {
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 54d57a1b24d9..0e4ca05f3c1d 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -803,4 +803,6 @@ interface IPackageManager {
void setKeepUninstalledPackages(in List<String> packageList);
boolean canPackageQuery(String sourcePackageName, String targetPackageName, int userId);
+
+ int getSpecialRuntimePermissionFlags(String packageName);
}
diff --git a/core/java/android/content/pm/SpecialRuntimePermAppUtils.java b/core/java/android/content/pm/SpecialRuntimePermAppUtils.java
new file mode 100644
index 000000000000..efd48cb49aa3
--- /dev/null
+++ b/core/java/android/content/pm/SpecialRuntimePermAppUtils.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2022 GrapheneOS
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import android.Manifest;
+import android.annotation.SystemApi;
+import android.app.AppGlobals;
+import android.os.Binder;
+import android.os.Process;
+import android.os.RemoteException;
+import android.permission.PermissionManager;
+
+/** @hide */
+@SystemApi
+public class SpecialRuntimePermAppUtils {
+ private static final int FLAG_INITED = 1;
+
+ private static volatile int cachedFlags;
+
+ private static int getFlags() {
+ int cache = cachedFlags;
+ if (cache != 0) {
+ return cache;
+ }
+
+ IPackageManager pm = AppGlobals.getPackageManager();
+ String pkgName = AppGlobals.getInitialPackage();
+
+ final long token = Binder.clearCallingIdentity(); // in case this method is called in the system_server
+ try {
+ return (cachedFlags = pm.getSpecialRuntimePermissionFlags(pkgName) | FLAG_INITED);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ private SpecialRuntimePermAppUtils() {}
+}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index a638f8cfcb25..dc20b6ccaa3f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -213,6 +213,7 @@ import com.android.server.pm.permission.LegacyPermissionManagerInternal;
import com.android.server.pm.permission.LegacyPermissionManagerService;
import com.android.server.pm.permission.PermissionManagerService;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
+import com.android.server.pm.permission.SpecialRuntimePermUtils;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.PackageUserState;
import com.android.server.pm.pkg.PackageUserStateInternal;
@@ -6048,6 +6049,24 @@ public class PackageManagerService implements PackageSender, TestUtilityService
getPerUidReadTimeouts(snapshot)
).doDump(snapshot, fd, pw, args);
}
+
+ @Override
+ public int getSpecialRuntimePermissionFlags(String packageName) {
+ final int callingUid = Binder.getCallingUid();
+
+ synchronized (mLock) {
+ AndroidPackage pkg = mPackages.get(packageName);
+ if (pkg == null) {
+ throw new IllegalStateException();
+ }
+
+ if (UserHandle.getAppId(callingUid) != pkg.getUid()) { // getUid() confusingly returns appId
+ throw new SecurityException();
+ }
+
+ return SpecialRuntimePermUtils.getFlags(pkg);
+ }
+ }
}
private class PackageManagerLocalImpl implements PackageManagerLocal {
diff --git a/services/core/java/com/android/server/pm/permission/SpecialRuntimePermUtils.java b/services/core/java/com/android/server/pm/permission/SpecialRuntimePermUtils.java
new file mode 100644
index 000000000000..fe946ff5d5ca
--- /dev/null
+++ b/services/core/java/com/android/server/pm/permission/SpecialRuntimePermUtils.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2022 GrapheneOS
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.permission;
+
+import android.Manifest;
+import android.os.Bundle;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.component.ParsedUsesPermission;
+
+import static android.content.pm.SpecialRuntimePermAppUtils.*;
+
+public class SpecialRuntimePermUtils {
+
+ @GuardedBy("PackageManagerService.mLock")
+ public static int getFlags(AndroidPackage pkg) {
+ int flags = 0;
+
+ for (ParsedUsesPermission perm : pkg.getUsesPermissions()) {
+ String name = perm.getName();
+ switch (name) {
+ default:
+ continue;
+ }
+ }
+
+ return flags;
+ }
+
+ private SpecialRuntimePermUtils() {}
+}

View file

@ -0,0 +1,165 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor <muhomor.dmitry@gmail.com>
Date: Sun, 31 Jul 2022 18:00:35 +0300
Subject: [PATCH] improve compatibility of INTERNET special runtime permission
There are apps that refuse to work when they detect that INTERNET is revoked, usually because of
a library check that reminds the app developer to add INTERNET uses-permission element to app's
AndroidManifest.
Always report that INTERNET is granted unless the app has
<meta-data android:name="android.permission.INTERNET.mode" android:value="runtime" />
declaration inside <application> element in its AndroidManifest, or is a system app.
---
core/api/system-current.txt | 5 +++++
core/java/android/app/DownloadManager.java | 13 ++++++++++++
.../content/pm/AppPermissionUtils.java | 7 +++++++
.../pm/SpecialRuntimePermAppUtils.java | 20 +++++++++++++++++++
.../permission/SpecialRuntimePermUtils.java | 17 ++++++++++++++++
5 files changed, 62 insertions(+)
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 531b03cd7c0c..64115f76caf4 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -3547,6 +3547,11 @@ package android.content.pm {
}
public class SpecialRuntimePermAppUtils {
+ method public static boolean awareOfRuntimeInternetPermission();
+ method public static boolean isInternetCompatEnabled();
+ method public static boolean requestsInternetPermission();
+ field public static final int FLAG_AWARE_OF_RUNTIME_INTERNET_PERMISSION = 4; // 0x4
+ field public static final int FLAG_REQUESTS_INTERNET_PERMISSION = 2; // 0x2
}
public final class SuspendDialogInfo implements android.os.Parcelable {
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index c209660f4197..ee412eb50064 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -34,6 +34,7 @@ import android.content.Context;
import android.database.Cursor;
import android.database.CursorWrapper;
import android.database.DatabaseUtils;
+import android.database.MatrixCursor;
import android.net.ConnectivityManager;
import android.net.NetworkPolicyManager;
import android.net.Uri;
@@ -53,6 +54,8 @@ import android.util.LongSparseArray;
import android.util.Pair;
import android.webkit.MimeTypeMap;
+import android.content.pm.SpecialRuntimePermAppUtils;
+
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
@@ -1123,6 +1126,11 @@ public class DownloadManager {
* calls related to this download.
*/
public long enqueue(Request request) {
+ if (SpecialRuntimePermAppUtils.isInternetCompatEnabled()) {
+ // invalid id (DownloadProvider uses SQLite and returns a row id)
+ return -1;
+ }
+
ContentValues values = request.toContentValues(mPackageName);
Uri downloadUri = mResolver.insert(Downloads.Impl.CONTENT_URI, values);
long id = Long.parseLong(downloadUri.getLastPathSegment());
@@ -1170,6 +1178,11 @@ public class DownloadManager {
/** @hide */
public Cursor query(Query query, String[] projection) {
+ if (SpecialRuntimePermAppUtils.isInternetCompatEnabled()) {
+ // underlying provider is protected by the INTERNET permission
+ return new MatrixCursor(projection);
+ }
+
Cursor underlyingCursor = query.runQuery(mResolver, projection, mBaseUri);
if (underlyingCursor == null) {
return null;
diff --git a/core/java/android/content/pm/AppPermissionUtils.java b/core/java/android/content/pm/AppPermissionUtils.java
index 7dc20eec8485..6a96f70dcfcf 100644
--- a/core/java/android/content/pm/AppPermissionUtils.java
+++ b/core/java/android/content/pm/AppPermissionUtils.java
@@ -24,6 +24,13 @@ public class AppPermissionUtils {
// android.app.ApplicationPackageManager#checkPermission(String permName, String pkgName)
// android.app.ContextImpl#checkPermission(String permission, int pid, int uid)
public static boolean shouldSpoofSelfCheck(String permName) {
+ if (Manifest.permission.INTERNET.equals(permName)
+ && SpecialRuntimePermAppUtils.requestsInternetPermission()
+ && !SpecialRuntimePermAppUtils.awareOfRuntimeInternetPermission())
+ {
+ return true;
+ }
+
return false;
}
}
diff --git a/core/java/android/content/pm/SpecialRuntimePermAppUtils.java b/core/java/android/content/pm/SpecialRuntimePermAppUtils.java
index efd48cb49aa3..2f973a585d5c 100644
--- a/core/java/android/content/pm/SpecialRuntimePermAppUtils.java
+++ b/core/java/android/content/pm/SpecialRuntimePermAppUtils.java
@@ -28,9 +28,29 @@ import android.permission.PermissionManager;
@SystemApi
public class SpecialRuntimePermAppUtils {
private static final int FLAG_INITED = 1;
+ public static final int FLAG_REQUESTS_INTERNET_PERMISSION = 1 << 1;
+ public static final int FLAG_AWARE_OF_RUNTIME_INTERNET_PERMISSION = 1 << 2;
private static volatile int cachedFlags;
+ private static boolean hasInternetPermission() {
+ // checkSelfPermission() is spoofed, query the underlying API directly
+ return PermissionManager.checkPermission(Manifest.permission.INTERNET, Process.myPid(), Process.myUid())
+ == PackageManager.PERMISSION_GRANTED;
+ }
+
+ public static boolean requestsInternetPermission() {
+ return (getFlags() & FLAG_REQUESTS_INTERNET_PERMISSION) != 0;
+ }
+
+ public static boolean awareOfRuntimeInternetPermission() {
+ return (getFlags() & FLAG_AWARE_OF_RUNTIME_INTERNET_PERMISSION) != 0;
+ }
+
+ public static boolean isInternetCompatEnabled() {
+ return !hasInternetPermission() && requestsInternetPermission() && !awareOfRuntimeInternetPermission();
+ }
+
private static int getFlags() {
int cache = cachedFlags;
if (cache != 0) {
diff --git a/services/core/java/com/android/server/pm/permission/SpecialRuntimePermUtils.java b/services/core/java/com/android/server/pm/permission/SpecialRuntimePermUtils.java
index fe946ff5d5ca..6f5cabb8a8fc 100644
--- a/services/core/java/com/android/server/pm/permission/SpecialRuntimePermUtils.java
+++ b/services/core/java/com/android/server/pm/permission/SpecialRuntimePermUtils.java
@@ -34,11 +34,28 @@ public class SpecialRuntimePermUtils {
for (ParsedUsesPermission perm : pkg.getUsesPermissions()) {
String name = perm.getName();
switch (name) {
+ case Manifest.permission.INTERNET:
+ flags |= FLAG_REQUESTS_INTERNET_PERMISSION;
+ continue;
default:
continue;
}
}
+ if ((flags & FLAG_REQUESTS_INTERNET_PERMISSION) != 0) {
+ if (pkg.isSystem()) {
+ flags |= FLAG_AWARE_OF_RUNTIME_INTERNET_PERMISSION;
+ } else {
+ Bundle metadata = pkg.getMetaData();
+ if (metadata != null) {
+ String key = Manifest.permission.INTERNET + ".mode";
+ if ("runtime".equals(metadata.getString(key))) {
+ flags |= FLAG_AWARE_OF_RUNTIME_INTERNET_PERMISSION;
+ }
+ }
+ }
+ }
+
return flags;
}

View file

@ -0,0 +1,48 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor <muhomor.dmitry@gmail.com>
Date: Wed, 17 Aug 2022 10:12:42 +0300
Subject: [PATCH] mark UserHandle#get{Uid, UserId} as module SystemApi
Needed by packages_modules_Connectivity ->
"enforce INTERNET permission per-uid instead of per-appId".
---
core/api/module-lib-current.txt | 5 +++++
core/java/android/os/UserHandle.java | 2 ++
2 files changed, 7 insertions(+)
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index b9522163b5d0..5e8bfd4dff61 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -392,6 +392,11 @@ package android.os {
field public static final long TRACE_TAG_NETWORK = 2097152L; // 0x200000L
}
+ public final class UserHandle implements android.os.Parcelable {
+ method public static int getUid(int, int);
+ method public static int getUserId(int);
+ }
+
}
package android.os.storage {
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index 3d5abb3b8a2f..e6326bb0ad8b 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -275,6 +275,7 @@ public final class UserHandle implements Parcelable {
* Returns the user id for a given uid.
* @hide
*/
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@UnsupportedAppUsage
@TestApi
public static @UserIdInt int getUserId(int uid) {
@@ -365,6 +366,7 @@ public final class UserHandle implements Parcelable {
* Returns the uid that is composed from the userId and the appId.
* @hide
*/
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@UnsupportedAppUsage
@TestApi
public static int getUid(@UserIdInt int userId, @AppIdInt int appId) {

View file

@ -0,0 +1,38 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor <muhomor.dmitry@gmail.com>
Date: Tue, 30 Aug 2022 12:37:03 +0300
Subject: [PATCH] improve compatibility with revoked INTERNET in
DownloadManager
---
core/java/android/app/DownloadManager.java | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index ee412eb50064..f1bda3d1a81f 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -1163,6 +1163,11 @@ public class DownloadManager {
* @return the number of downloads actually removed
*/
public int remove(long... ids) {
+ if (SpecialRuntimePermAppUtils.isInternetCompatEnabled()) {
+ // underlying provider is protected by the INTERNET permission
+ return 0;
+ }
+
return markRowDeleted(ids);
}
@@ -1589,6 +1594,11 @@ public class DownloadManager {
throw new IllegalArgumentException(" invalid value for param: totalBytes");
}
+ if (SpecialRuntimePermAppUtils.isInternetCompatEnabled()) {
+ // underlying provider is protected by the INTERNET permission
+ return -1;
+ }
+
// if there is already an entry with the given path name in downloads.db, return its id
Request request;
if (uri != null) {

View file

@ -0,0 +1,36 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor <muhomor.dmitry@gmail.com>
Date: Thu, 15 Sep 2022 13:58:34 +0300
Subject: [PATCH] ignore pid when spoofing permission checks
Permissions are enforced per-uid, checking pid may break spoofing for multi-process apps.
---
core/java/android/app/ContextImpl.java | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index b50cd115382d..58d3702c7356 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -2166,18 +2166,16 @@ class ContextImpl extends Context {
if (permission == null) {
throw new IllegalArgumentException("permission is null");
}
-
- final boolean selfCheck = pid == android.os.Process.myPid() && uid == android.os.Process.myUid();
-
if (mParams.isRenouncedPermission(permission)
- && selfCheck) {
+ && pid == android.os.Process.myPid() && uid == android.os.Process.myUid()) {
Log.v(TAG, "Treating renounced permission " + permission + " as denied");
return PERMISSION_DENIED;
}
+
int res = PermissionManager.checkPermission(permission, pid, uid);
if (res != PERMISSION_GRANTED) {
- if (selfCheck) {
+ if (uid == android.os.Process.myUid()) {
if (AppPermissionUtils.shouldSpoofSelfCheck(permission)) {
return PERMISSION_GRANTED;
}

View file

@ -110,10 +110,10 @@ index c3b149a1e295..a47b82018377 100644
<Button
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index c6b60f586047..9b5916a91280 100644
index b153a36f65db..3f03f5726b23 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -6326,4 +6326,7 @@ ul.</string>
@@ -6343,4 +6343,7 @@ ul.</string>
<!-- Title for preference of the system default locale. [CHAR LIMIT=50]-->
<string name="system_locale_title">System default</string>

View file

@ -0,0 +1,89 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor <muhomor.dmitry@gmail.com>
Date: Thu, 2 Jun 2022 09:18:26 +0300
Subject: [PATCH] make sure PackageInstaller UI returns a result
---
.../PackageInstallerActivity.java | 27 +++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
index 9c6113ce4b47..10eefebadeff 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
@@ -129,6 +129,8 @@ public class PackageInstallerActivity extends AlertActivity {
// Would the mOk button be enabled if this activity would be resumed
private boolean mEnableOk = false;
+ private boolean mPermissionResultWasSet;
+ private boolean mAllowNextOnPause;
private void startInstallConfirm() {
View viewToEnable;
@@ -298,6 +300,7 @@ public class PackageInstallerActivity extends AlertActivity {
protected void onCreate(Bundle icicle) {
if (mLocalLOGV) Log.i(TAG, "creating for user " + getUserId());
getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+ getWindow().setCloseOnTouchOutside(false);
super.onCreate(null);
@@ -390,6 +393,24 @@ public class PackageInstallerActivity extends AlertActivity {
// Don't allow the install button to be clicked as there might be overlays
mOk.setEnabled(false);
}
+ // sometimes this activity becomes hidden after onPause(),
+ // and the user is unable to bring it back
+ if (!mPermissionResultWasSet && mSessionId != -1) {
+ if (mAllowNextOnPause) {
+ mAllowNextOnPause = false;
+ } else {
+ if (!isFinishing()) {
+ finish();
+ }
+ }
+ }
+ }
+
+ // handles startActivity() calls too
+ @Override
+ public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
+ mAllowNextOnPause = true;
+ super.startActivityForResult(intent, requestCode, options);
}
@Override
@@ -405,6 +426,9 @@ public class PackageInstallerActivity extends AlertActivity {
while (!mActiveUnknownSourcesListeners.isEmpty()) {
unregister(mActiveUnknownSourcesListeners.get(0));
}
+ if (!mPermissionResultWasSet) {
+ mInstaller.setPermissionsResult(mSessionId, false);
+ }
}
private void bindUi() {
@@ -416,6 +440,7 @@ public class PackageInstallerActivity extends AlertActivity {
if (mOk.isEnabled()) {
if (mSessionId != -1) {
mInstaller.setPermissionsResult(mSessionId, true);
+ mPermissionResultWasSet = true;
finish();
} else {
startInstall();
@@ -428,6 +453,7 @@ public class PackageInstallerActivity extends AlertActivity {
setResult(RESULT_CANCELED);
if (mSessionId != -1) {
mInstaller.setPermissionsResult(mSessionId, false);
+ mPermissionResultWasSet = true;
}
finish();
}, null);
@@ -599,6 +625,7 @@ public class PackageInstallerActivity extends AlertActivity {
public void onBackPressed() {
if (mSessionId != -1) {
mInstaller.setPermissionsResult(mSessionId, false);
+ mPermissionResultWasSet = true;
}
super.onBackPressed();
}

View file

@ -0,0 +1,54 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor <muhomor.dmitry@gmail.com>
Date: Sun, 24 Jul 2022 13:07:00 +0300
Subject: [PATCH] protect step sensors with OTHER_SENSORS permission for
targetSdk<29 apps
---
services/sensorservice/SensorService.cpp | 24 +++++++++++++++---------
1 file changed, 15 insertions(+), 9 deletions(-)
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 948692bd47..6caee5b220 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -2015,17 +2015,9 @@ bool SensorService::canAccessSensor(const Sensor& sensor, const char* operation,
}
const int32_t opCode = sensor.getRequiredAppOp();
- int targetSdkVersion = getTargetSdkVersion(opPackageName);
bool canAccess = false;
- if (targetSdkVersion > 0 && targetSdkVersion <= __ANDROID_API_P__ &&
- (sensor.getType() == SENSOR_TYPE_STEP_COUNTER ||
- sensor.getType() == SENSOR_TYPE_STEP_DETECTOR)) {
- // Allow access to step sensors if the application targets pre-Q, which is before the
- // requirement to hold the AR permission to access Step Counter and Step Detector events
- // was introduced.
- canAccess = true;
- } else if (hasPermissionForSensor(sensor)) {
+ if (hasPermissionForSensor(sensor)) {
// Ensure that the AppOp is allowed, or that there is no necessary app op for the sensor
if (opCode >= 0) {
const int32_t appOpMode = sAppOpsManager.checkOp(opCode,
@@ -2034,6 +2026,20 @@ bool SensorService::canAccessSensor(const Sensor& sensor, const char* operation,
} else {
canAccess = true;
}
+ } else {
+ int targetSdkVersion = getTargetSdkVersion(opPackageName);
+ if (targetSdkVersion > 0 && targetSdkVersion <= __ANDROID_API_P__ &&
+ (sensor.getType() == SENSOR_TYPE_STEP_COUNTER ||
+ sensor.getType() == SENSOR_TYPE_STEP_DETECTOR)) {
+
+ // upstream allows access to these sensors without the ACTIVITY_RECOGNITION permission
+ // for targetSdk < 29 apps, enforce the OTHER_SENSORS permission instead
+ const String16 requiredPermission("android.permission.OTHER_SENSORS");
+
+ // copied from hasPermissionForSensor() below
+ canAccess = checkPermission(requiredPermission,
+ IPCThreadState::self()->getCallingPid(), IPCThreadState::self()->getCallingUid());
+ }
}
if (!canAccess) {

View file

@ -0,0 +1,22 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Daniel Micay <danielmicay@gmail.com>
Date: Sat, 7 Oct 2017 16:28:57 -0400
Subject: [PATCH] require OTHER_SENSORS permission for sensors
Ported from 10: ff005a6b6a38baef95c4a01d7e1fc75aac651a58
---
libs/sensor/Sensor.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/libs/sensor/Sensor.cpp b/libs/sensor/Sensor.cpp
index ec0ced8663..1cf12e1f43 100644
--- a/libs/sensor/Sensor.cpp
+++ b/libs/sensor/Sensor.cpp
@@ -59,6 +59,7 @@ Sensor::Sensor(struct sensor_t const& hwSensor, const uuid_t& uuid, int halVersi
mMinDelay = hwSensor.minDelay;
mFlags = 0;
mUuid = uuid;
+ mRequiredPermission = "android.permission.OTHER_SENSORS";
// Set fifo event count zero for older devices which do not support batching. Fused
// sensors also have their fifo counts set to zero.

View file

@ -0,0 +1,32 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor <muhomor.dmitry@gmail.com>
Date: Tue, 14 Dec 2021 21:10:51 +0200
Subject: [PATCH] don't throw SecurityException when INTERNET permission is
revoked
---
ojluni/src/main/java/java/net/Inet6AddressImpl.java | 11 +----------
1 file changed, 1 insertion(+), 10 deletions(-)
diff --git a/ojluni/src/main/java/java/net/Inet6AddressImpl.java b/ojluni/src/main/java/java/net/Inet6AddressImpl.java
index 84bcf17edae..fda9674e08e 100644
--- a/ojluni/src/main/java/java/net/Inet6AddressImpl.java
+++ b/ojluni/src/main/java/java/net/Inet6AddressImpl.java
@@ -141,16 +141,7 @@ class Inet6AddressImpl implements InetAddressImpl {
addressCache.put(host, netId, addresses);
return addresses;
} catch (GaiException gaiException) {
- // If the failure appears to have been a lack of INTERNET permission, throw a clear
- // SecurityException to aid in debugging this common mistake.
- // http://code.google.com/p/android/issues/detail?id=15722
- if (gaiException.getCause() instanceof ErrnoException) {
- int errno = ((ErrnoException) gaiException.getCause()).errno;
- if (errno == EACCES || errno == EPERM) {
- throw new SecurityException("Permission denied (missing INTERNET permission?)", gaiException);
- }
- }
- // Otherwise, throw an UnknownHostException.
+ // Throw an UnknownHostException.
String detailMessage = "Unable to resolve host \"" + host + "\": " + Libcore.os.gai_strerror(gaiException.error);
addressCache.putUnknownHost(host, netId, detailMessage);
throw gaiException.rethrowAsUnknownHostException(detailMessage);

View file

@ -0,0 +1,34 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor <muhomor.dmitry@gmail.com>
Date: Tue, 14 Dec 2021 18:17:11 +0200
Subject: [PATCH] skip reportNetworkConnectivity() when permission is revoked
---
framework/src/android/net/ConnectivityManager.java | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java
index f741c2bb3..f5bac0613 100644
--- a/framework/src/android/net/ConnectivityManager.java
+++ b/framework/src/android/net/ConnectivityManager.java
@@ -41,6 +41,7 @@ import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.SpecialRuntimePermAppUtils;
import android.net.ConnectivityDiagnosticsManager.DataStallReport.DetectionMethod;
import android.net.IpSecManager.UdpEncapsulationSocket;
import android.net.SocketKeepalive.Callback;
@@ -3358,6 +3359,12 @@ public class ConnectivityManager {
*/
public void reportNetworkConnectivity(@Nullable Network network, boolean hasConnectivity) {
printStackTrace();
+
+ if (SpecialRuntimePermAppUtils.isInternetCompatEnabled()) {
+ // caller doesn't have INTERNET, but expects to always have it
+ return;
+ }
+
try {
mService.reportNetworkConnectivity(network, hasConnectivity);
} catch (RemoteException e) {

View file

@ -0,0 +1,208 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor <muhomor.dmitry@gmail.com>
Date: Wed, 6 Oct 2021 03:05:49 +0300
Subject: [PATCH] enforce INTERNET permission per-uid instead of per-appId
---
bpf_progs/netd.c | 10 +--
.../connectivity/PermissionMonitor.java | 63 ++++++++++++++-----
2 files changed, 48 insertions(+), 25 deletions(-)
diff --git a/bpf_progs/netd.c b/bpf_progs/netd.c
index 24b3fed58..065f41fd8 100644
--- a/bpf_progs/netd.c
+++ b/bpf_progs/netd.c
@@ -429,14 +429,8 @@ DEFINE_BPF_PROG_EXT("cgroupsock/inet/create", AID_ROOT, AID_ROOT, inet_socket_cr
KVER(4, 14, 0), KVER_INF, false, "fs_bpf_netd_readonly", "")
(struct bpf_sock* sk) {
uint64_t gid_uid = bpf_get_current_uid_gid();
- /*
- * A given app is guaranteed to have the same app ID in all the profiles in
- * which it is installed, and install permission is granted to app for all
- * user at install time so we only check the appId part of a request uid at
- * run time. See UserHandle#isSameApp for detail.
- */
- uint32_t appId = (gid_uid & 0xffffffff) % AID_USER_OFFSET; // == PER_USER_RANGE == 100000
- uint8_t* permissions = bpf_uid_permission_map_lookup_elem(&appId);
+ uint32_t uid = (gid_uid & 0xffffffff);
+ uint8_t* permissions = bpf_uid_permission_map_lookup_elem(&uid);
if (!permissions) {
// UID not in map. Default to just INTERNET permission.
return 1;
diff --git a/service/src/com/android/server/connectivity/PermissionMonitor.java b/service/src/com/android/server/connectivity/PermissionMonitor.java
index 0e265f9ef..4509d9f3f 100755
--- a/service/src/com/android/server/connectivity/PermissionMonitor.java
+++ b/service/src/com/android/server/connectivity/PermissionMonitor.java
@@ -392,6 +392,11 @@ public class PermissionMonitor {
public synchronized void startMonitoring() {
log("Monitoring");
+ mPackageManager.addOnPermissionsChangeListener(uid -> {
+ // traffic permissions are INTERNET and UPDATE_DEVICE_STATS
+ sendPackagePermissionsForUid(uid, getTrafficPermissionForUid(uid));
+ });
+
final Context userAllContext = mContext.createContextAsUser(UserHandle.ALL, 0 /* flags */);
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
@@ -566,7 +571,7 @@ public class PermissionMonitor {
mUsersTrafficPermissions.put(user, addedUserAppIds);
// Generate appIds from all users and send result to netd.
final SparseIntArray appIds = makeAppIdsTrafficPermForAllUsers();
- sendAppIdsTrafficPermission(appIds);
+ sendUidsTrafficPermission(user.getIdentifier(), appIds);
// Log user added
mPermissionUpdateLogs.log("New user(" + user.getIdentifier() + ") added: nPerm uids="
@@ -614,7 +619,7 @@ public class PermissionMonitor {
appIds.put(appId, PERMISSION_UNINSTALLED);
}
}
- sendAppIdsTrafficPermission(appIds);
+ sendUidsTrafficPermission(user.getIdentifier(), appIds);
// Log user removed
mPermissionUpdateLogs.log("User(" + user.getIdentifier() + ") removed: nPerm uids="
@@ -734,16 +739,25 @@ public class PermissionMonitor {
}
}
- private synchronized int getAppIdTrafficPermission(int appId) {
+ private synchronized int getUidTrafficPermission(final int uid) {
+ final int userId = UserHandle.getUserId(uid);
+
int permission = PERMISSION_NONE;
boolean installed = false;
+
for (UserHandle user : mUsersTrafficPermissions.keySet()) {
+ if (user.getIdentifier() != userId) {
+ continue;
+ }
+
final SparseIntArray userApps = mUsersTrafficPermissions.get(user);
+ final int appId = UserHandle.getAppId(uid);
final int appIdx = userApps.indexOfKey(appId);
if (appIdx >= 0) {
permission |= userApps.valueAt(appIdx);
installed = true;
}
+ break;
}
return installed ? permission : PERMISSION_UNINSTALLED;
}
@@ -761,8 +775,8 @@ public class PermissionMonitor {
updateAppIdTrafficPermission(uid);
// Get the appId permission from all users then send the latest permission to netd.
final int appId = UserHandle.getAppId(uid);
- final int appIdTrafficPerm = getAppIdTrafficPermission(appId);
- sendPackagePermissionsForAppId(appId, appIdTrafficPerm);
+ final int uidTrafficPerm = getUidTrafficPermission(uid);
+ sendPackagePermissionsForUid(uid, uidTrafficPerm);
final int currentPermission = mUidToNetworkPerm.get(uid, PERMISSION_NONE);
final int permission = highestPermissionForUid(uid, currentPermission, packageName);
@@ -792,7 +806,7 @@ public class PermissionMonitor {
mPermissionUpdateLogs.log("Package add: name=" + packageName + ", uid=" + uid
+ ", nPerm=(" + permissionToString(permission) + "/"
+ permissionToString(currentPermission) + ")"
- + ", tPerm=" + permissionToString(appIdTrafficPerm));
+ + ", tPerm=" + permissionToString(uidTrafficPerm));
}
private int highestUidNetworkPermission(int uid) {
@@ -824,8 +838,8 @@ public class PermissionMonitor {
updateAppIdTrafficPermission(uid);
// Get the appId permission from all users then send the latest permission to netd.
final int appId = UserHandle.getAppId(uid);
- final int appIdTrafficPerm = getAppIdTrafficPermission(appId);
- sendPackagePermissionsForAppId(appId, appIdTrafficPerm);
+ final int uidTrafficPerm = getUidTrafficPermission(uid);
+ sendPackagePermissionsForUid(uid, uidTrafficPerm);
// If the newly-removed package falls within some VPN's uid range, update Netd with it.
// This needs to happen before the mUidToNetworkPerm update below, since
@@ -845,7 +859,7 @@ public class PermissionMonitor {
mPermissionUpdateLogs.log("Package remove: name=" + packageName + ", uid=" + uid
+ ", nPerm=(" + permissionToString(permission) + "/"
+ permissionToString(currentPermission) + ")"
- + ", tPerm=" + permissionToString(appIdTrafficPerm));
+ + ", tPerm=" + permissionToString(uidTrafficPerm));
if (permission != currentPermission) {
final SparseIntArray apps = new SparseIntArray();
@@ -1097,14 +1111,17 @@ public class PermissionMonitor {
* @hide
*/
@VisibleForTesting
- void sendPackagePermissionsForAppId(int appId, int permissions) {
+ void sendPackagePermissionsForUid(int uid, int permissions) {
+ int userId = UserHandle.getUserId(uid);
+ int appId = UserHandle.getAppId(uid);
+
SparseIntArray netdPermissionsAppIds = new SparseIntArray();
netdPermissionsAppIds.put(appId, permissions);
if (hasSdkSandbox(appId)) {
int sdkSandboxAppId = sProcessShim.toSdkSandboxUid(appId);
netdPermissionsAppIds.put(sdkSandboxAppId, permissions);
}
- sendAppIdsTrafficPermission(netdPermissionsAppIds);
+ sendUidsTrafficPermission(userId, netdPermissionsAppIds);
}
/**
@@ -1116,7 +1133,7 @@ public class PermissionMonitor {
* @hide
*/
@VisibleForTesting
- void sendAppIdsTrafficPermission(SparseIntArray netdPermissionsAppIds) {
+ void sendUidsTrafficPermission(final int userId, SparseIntArray netdPermissionsAppIds) {
final ArrayList<Integer> allPermissionAppIds = new ArrayList<>();
final ArrayList<Integer> internetPermissionAppIds = new ArrayList<>();
final ArrayList<Integer> updateStatsPermissionAppIds = new ArrayList<>();
@@ -1150,29 +1167,41 @@ public class PermissionMonitor {
if (allPermissionAppIds.size() != 0) {
mBpfNetMaps.setNetPermForUids(
PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS,
- toIntArray(allPermissionAppIds));
+ appIdListToUidArray(userId, allPermissionAppIds));
}
if (internetPermissionAppIds.size() != 0) {
mBpfNetMaps.setNetPermForUids(PERMISSION_INTERNET,
- toIntArray(internetPermissionAppIds));
+ appIdListToUidArray(userId, internetPermissionAppIds));
}
if (updateStatsPermissionAppIds.size() != 0) {
mBpfNetMaps.setNetPermForUids(PERMISSION_UPDATE_DEVICE_STATS,
- toIntArray(updateStatsPermissionAppIds));
+ appIdListToUidArray(userId, updateStatsPermissionAppIds));
}
if (noPermissionAppIds.size() != 0) {
mBpfNetMaps.setNetPermForUids(PERMISSION_NONE,
- toIntArray(noPermissionAppIds));
+ appIdListToUidArray(userId, noPermissionAppIds));
}
if (uninstalledAppIds.size() != 0) {
mBpfNetMaps.setNetPermForUids(PERMISSION_UNINSTALLED,
- toIntArray(uninstalledAppIds));
+ appIdListToUidArray(userId, uninstalledAppIds));
}
} catch (RemoteException | ServiceSpecificException e) {
Log.e(TAG, "Pass appId list of special permission failed." + e);
}
}
+ private static int[] appIdListToUidArray(int userId, ArrayList<Integer> appIds) {
+ final int cnt = appIds.size();
+ int[] array = new int[cnt];
+
+ for (int i = 0; i < cnt; ++i) {
+ int appId = appIds.get(i).intValue();
+ array[i] = UserHandle.getUid(userId, appId);
+ }
+
+ return array;
+ }
+
/** Should only be used by unit tests */
@VisibleForTesting
public Set<UidRange> getVpnInterfaceUidRanges(String iface) {

View file

@ -0,0 +1,54 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor <muhomor.dmitry@gmail.com>
Date: Tue, 30 Aug 2022 12:27:52 +0300
Subject: [PATCH] don't crash INTERNET-unaware apps that try to access
NsdManager
---
.../src/android/net/nsd/NsdManager.java | 33 ++++++++++++++++---
1 file changed, 29 insertions(+), 4 deletions(-)
diff --git a/framework-t/src/android/net/nsd/NsdManager.java b/framework-t/src/android/net/nsd/NsdManager.java
index f19bf4a6f..ac0a9f6ab 100644
--- a/framework-t/src/android/net/nsd/NsdManager.java
+++ b/framework-t/src/android/net/nsd/NsdManager.java
@@ -498,10 +498,35 @@ public final class NsdManager {
t.start();
mHandler = new ServiceHandler(t.getLooper());
- try {
- mService = service.connect(new NsdCallbackImpl(mHandler));
- } catch (RemoteException e) {
- throw new RuntimeException("Failed to connect to NsdService");
+ if (android.content.pm.SpecialRuntimePermAppUtils.isInternetCompatEnabled()) {
+ // INsdManager#connect() enforces INTERNET permission
+ mService = new INsdServiceConnector() {
+ final NsdCallbackImpl callback = new NsdCallbackImpl(mHandler);
+
+ @Override public void registerService(int listenerKey, NsdServiceInfo serviceInfo) {
+ callback.onRegisterServiceFailed(listenerKey, FAILURE_INTERNAL_ERROR);
+ }
+ @Override public void unregisterService(int listenerKey) {
+ callback.onUnregisterServiceFailed(listenerKey, FAILURE_INTERNAL_ERROR);
+ }
+ @Override public void discoverServices(int listenerKey, NsdServiceInfo serviceInfo) {
+ callback.onDiscoverServicesFailed(listenerKey, FAILURE_INTERNAL_ERROR);
+ }
+ @Override public void stopDiscovery(int listenerKey) {
+ callback.onStopDiscoveryFailed(listenerKey, FAILURE_INTERNAL_ERROR);
+ }
+ @Override public void resolveService(int listenerKey, NsdServiceInfo serviceInfo) {
+ callback.onResolveServiceFailed(listenerKey, FAILURE_INTERNAL_ERROR);
+ }
+ @Override public void startDaemon() {}
+ @Override public android.os.IBinder asBinder() { return null; }
+ };
+ } else {
+ try {
+ mService = service.connect(new NsdCallbackImpl(mHandler));
+ } catch (RemoteException e) {
+ throw new RuntimeException("Failed to connect to NsdService");
+ }
}
// Only proactively start the daemon if the target SDK < S, otherwise the internal service

View file

@ -0,0 +1,179 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Daniel Micay <danielmicay@gmail.com>
Date: Sun, 23 Jul 2017 04:43:50 +0300
Subject: [PATCH] add special handling for INTERNET/OTHER_SENSORS
---
.../data/HibernationSettingStateLiveData.kt | 3 +-
.../permission/model/AppPermissionGroup.java | 4 +--
.../permission/model/Permission.java | 4 ++-
.../service/AutoRevokePermissions.kt | 2 +-
.../permission/utils/KotlinUtils.kt | 2 ++
.../permission/utils/Utils.java | 34 +++++++++++++++++++
6 files changed, 44 insertions(+), 5 deletions(-)
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/HibernationSettingStateLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/HibernationSettingStateLiveData.kt
index 606562641..b908eadb5 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/HibernationSettingStateLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/HibernationSettingStateLiveData.kt
@@ -34,6 +34,7 @@ import com.android.permissioncontroller.hibernation.isPackageHibernationExemptBy
import com.android.permissioncontroller.hibernation.isPackageHibernationExemptByUser
import com.android.permissioncontroller.permission.data.PackagePermissionsLiveData.Companion.NON_RUNTIME_NORMAL_PERMS
import com.android.permissioncontroller.permission.model.livedatatypes.HibernationSettingState
+import com.android.permissioncontroller.permission.utils.Utils
import kotlinx.coroutines.Job
/**
@@ -117,7 +118,7 @@ class HibernationSettingStateLiveData private constructor(
permState.permFlags and (FLAG_PERMISSION_GRANTED_BY_DEFAULT or
FLAG_PERMISSION_GRANTED_BY_ROLE) != 0
} ?: false
- if (!default) {
+ if (!default && !Utils.isSpecialRuntimePermissionGroup(groupName)) {
revocableGroups.add(groupName)
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/model/AppPermissionGroup.java b/PermissionController/src/com/android/permissioncontroller/permission/model/AppPermissionGroup.java
index c03aef013..6e548e271 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/model/AppPermissionGroup.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/model/AppPermissionGroup.java
@@ -925,7 +925,7 @@ public final class AppPermissionGroup implements Comparable<AppPermissionGroup>
boolean wasGranted = permission.isGrantedIncludingAppOp();
- if (mAppSupportsRuntimePermissions) {
+ if (mAppSupportsRuntimePermissions || Utils.isSpecialRuntimePermission(permission.getName())) {
// Do not touch permissions fixed by the system.
if (permission.isSystemFixed()) {
wasAllGranted = false;
@@ -1113,7 +1113,7 @@ public final class AppPermissionGroup implements Comparable<AppPermissionGroup>
break;
}
- if (mAppSupportsRuntimePermissions) {
+ if (mAppSupportsRuntimePermissions || Utils.isSpecialRuntimePermission(permission.getName())) {
// Revoke the permission if needed.
if (permission.isGranted()) {
permission.setGranted(false);
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/model/Permission.java b/PermissionController/src/com/android/permissioncontroller/permission/model/Permission.java
index 5ddea4605..3eca8235c 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/model/Permission.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/model/Permission.java
@@ -21,6 +21,8 @@ import android.content.pm.PermissionInfo;
import androidx.annotation.NonNull;
+import com.android.permissioncontroller.permission.utils.Utils;
+
import java.util.ArrayList;
import java.util.Objects;
@@ -137,7 +139,7 @@ public final class Permission {
* @return {@code true} if the permission (and the app-op) is granted.
*/
public boolean isGrantedIncludingAppOp() {
- return mGranted && (!affectsAppOp() || isAppOpAllowed()) && !isReviewRequired();
+ return mGranted && (!affectsAppOp() || isAppOpAllowed()) && (!isReviewRequired() || Utils.isSpecialRuntimePermission(mName));
}
public boolean isReviewRequired() {
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/service/AutoRevokePermissions.kt b/PermissionController/src/com/android/permissioncontroller/permission/service/AutoRevokePermissions.kt
index aed275d8a..2cc012479 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/service/AutoRevokePermissions.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/service/AutoRevokePermissions.kt
@@ -108,7 +108,7 @@ suspend fun revokeAppPermissions(
!group.isGrantedByDefault &&
!group.isGrantedByRole &&
!group.isRevokeWhenRequested &&
- group.isUserSensitive) {
+ group.isUserSensitive && !Utils.isSpecialRuntimePermissionGroup(groupName)) {
revocableGroups.add(groupName)
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt b/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt
index 2216802f3..7bca04085 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt
@@ -597,6 +597,7 @@ object KotlinUtils {
val pkgInfo = group.packageInfo
val user = UserHandle.getUserHandleForUid(pkgInfo.uid)
val supportsRuntime = pkgInfo.targetSdkVersion >= Build.VERSION_CODES.M
+ || Utils.isSpecialRuntimePermission(perm.name)
val isGrantingAllowed = (!pkgInfo.isInstantApp || perm.isInstantPerm) &&
(supportsRuntime || !perm.isRuntimeOnly)
// Do not touch permissions fixed by the system, or permissions that cannot be granted
@@ -827,6 +828,7 @@ object KotlinUtils {
var newFlags = perm.flags
var isGranted = perm.isGrantedIncludingAppOp
val supportsRuntime = group.packageInfo.targetSdkVersion >= Build.VERSION_CODES.M
+ || Utils.isSpecialRuntimePermission(perm.name)
var shouldKill = false
val affectsAppOp = permissionToOp(perm.name) != null || perm.isBackgroundPermission
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/Utils.java b/PermissionController/src/com/android/permissioncontroller/permission/utils/Utils.java
index 48793ab51..5109c83e0 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/Utils.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/Utils.java
@@ -24,7 +24,9 @@ import static android.Manifest.permission_group.CONTACTS;
import static android.Manifest.permission_group.LOCATION;
import static android.Manifest.permission_group.MICROPHONE;
import static android.Manifest.permission_group.NEARBY_DEVICES;
+import static android.Manifest.permission_group.NETWORK;
import static android.Manifest.permission_group.NOTIFICATIONS;
+import static android.Manifest.permission_group.OTHER_SENSORS;
import static android.Manifest.permission_group.PHONE;
import static android.Manifest.permission_group.READ_MEDIA_AURAL;
import static android.Manifest.permission_group.READ_MEDIA_VISUAL;
@@ -212,6 +214,9 @@ public final class Utils {
*/
public static final long ONE_TIME_PERMISSIONS_KILLED_DELAY_MILLIS = 5 * 1000;
+ /** Mapping permission -> group for all special runtime permissions */
+ private static final ArrayMap<String, String> SPECIAL_RUNTIME_PERMISSIONS;
+
/** Mapping permission -> group for all dangerous platform permissions */
private static final ArrayMap<String, String> PLATFORM_PERMISSIONS;
@@ -336,6 +341,13 @@ public final class Utils {
PLATFORM_PERMISSIONS.put(Manifest.permission.BODY_SENSORS, SENSORS);
+ PLATFORM_PERMISSIONS.put(Manifest.permission.INTERNET, NETWORK);
+ PLATFORM_PERMISSIONS.put(Manifest.permission.OTHER_SENSORS, OTHER_SENSORS);
+
+ SPECIAL_RUNTIME_PERMISSIONS = new ArrayMap<>();
+ SPECIAL_RUNTIME_PERMISSIONS.put(Manifest.permission.INTERNET, NETWORK);
+ SPECIAL_RUNTIME_PERMISSIONS.put(Manifest.permission.OTHER_SENSORS, OTHER_SENSORS);
+
if (SdkLevel.isAtLeastT()) {
PLATFORM_PERMISSIONS.put(Manifest.permission.POST_NOTIFICATIONS, NOTIFICATIONS);
PLATFORM_PERMISSIONS.put(Manifest.permission.BODY_SENSORS_BACKGROUND, SENSORS);
@@ -807,6 +819,28 @@ public final class Utils {
return PLATFORM_PERMISSIONS.containsKey(permission);
}
+ /**
+ * Is the permission a special runtime permission?
+ * These are treated as a runtime permission even for legacy apps. They
+ * need to be granted by default for all apps to maintain compatibility.
+ *
+ * @return whether the permission is a special runtime permission.
+ */
+ public static boolean isSpecialRuntimePermission(@NonNull String permission) {
+ return SPECIAL_RUNTIME_PERMISSIONS.containsKey(permission);
+ }
+
+ /**
+ * Is the permission group a special runtime permission group?
+ * These are treated as a runtime permission even for legacy apps. They
+ * need to be granted by default for all apps to maintain compatibility.
+ *
+ * @return whether the permission group is a special runtime permission group.
+ */
+ public static boolean isSpecialRuntimePermissionGroup(@NonNull String permissionGroup) {
+ return SPECIAL_RUNTIME_PERMISSIONS.containsValue(permissionGroup);
+ }
+
/**
* Should UI show this permission.
*

View file

@ -0,0 +1,54 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Daniel Micay <danielmicay@gmail.com>
Date: Mon, 18 Oct 2021 10:23:42 +0300
Subject: [PATCH] fix usage UI summary for Network/Sensors
---
PermissionController/res/values/strings.xml | 3 +++
.../v31/PermissionUsageControlPreferenceUtils.kt | 15 +++++++++++----
2 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/PermissionController/res/values/strings.xml b/PermissionController/res/values/strings.xml
index 882fc4181..210f5fb99 100644
--- a/PermissionController/res/values/strings.xml
+++ b/PermissionController/res/values/strings.xml
@@ -1583,4 +1583,7 @@ Allow <xliff:g id="app_name" example="Gmail">%4$s</xliff:g> to upload a bug repo
<string name="media_confirm_dialog_message_q_to_s_visual_allow">This app doesn\u2019t support the latest version of Android. If this app can access photos and videos, it will also be allowed to access music and audio files.</string>
<!-- Message for media confirm dialog (when user denies visual group of q_to_s app) [CHAR LIMIT=NONE] -->
<string name="media_confirm_dialog_message_q_to_s_visual_deny">This app doesn\u2019t support the latest version of Android. If this app can\u2019t access music and audio files, it also won\u2019t be allowed to access photos and videos.</string>
+
+ <!-- Summary text if tracking permission usage is not supported [CHAR LIMIT=60] -->
+ <string name="permission_usage_preference_summary_not_supported">Tracking usage not yet supported</string>
</resources>
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/PermissionUsageControlPreferenceUtils.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/PermissionUsageControlPreferenceUtils.kt
index 302e4432c..429a219b3 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/PermissionUsageControlPreferenceUtils.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/PermissionUsageControlPreferenceUtils.kt
@@ -69,10 +69,17 @@ object PermissionUsageControlPreferenceUtils {
R.string.permission_usage_preference_label, count)
if (count == 0) {
isEnabled = false
- val permissionUsageSummaryNotUsed = if (show7Days) {
- R.string.permission_usage_preference_summary_not_used_7d
+ val permissionUsageSummaryNotUsed = if (
+ groupName == Manifest.permission_group.NETWORK
+ || groupName == Manifest.permission_group.OTHER_SENSORS)
+ {
+ R.string.permission_usage_preference_summary_not_supported
} else {
- R.string.permission_usage_preference_summary_not_used_24h
+ if (show7Days) {
+ R.string.permission_usage_preference_summary_not_used_7d
+ } else {
+ R.string.permission_usage_preference_summary_not_used_24h
+ }
}
setSummary(permissionUsageSummaryNotUsed)
} else if (SENSOR_DATA_PERMISSIONS.contains(groupName)) {
@@ -112,4 +119,4 @@ object PermissionUsageControlPreferenceUtils {
if (act == 0) return
PermissionControllerStatsLog.write(PERMISSION_USAGE_FRAGMENT_INTERACTION, sessionId, act)
}
-}
\ No newline at end of file
+}

View file

@ -0,0 +1,21 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Daniel Micay <danielmicay@gmail.com>
Date: Sun, 6 Aug 2017 08:19:36 -0400
Subject: [PATCH] remove legacy NETWORK permission group reference
---
AndroidManifest.xml | 1 -
1 file changed, 1 deletion(-)
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 336b2505..a6e61a4f 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -29,7 +29,6 @@
<!-- Allows to queue downloads without a notification shown while the download runs. -->
<permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION"
- android:permissionGroup="android.permission-group.NETWORK"
android:label="@string/permlab_downloadWithoutNotification"
android:description="@string/permdesc_downloadWithoutNotification"
android:protectionLevel="normal"/>