summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/content/AttributionSource.java2
-rw-r--r--core/java/android/permission/IPermissionManager.aidl2
-rw-r--r--core/java/android/permission/PermissionManager.java14
-rw-r--r--core/java/android/permission/flags.aconfig7
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java29
5 files changed, 43 insertions, 11 deletions
diff --git a/core/java/android/content/AttributionSource.java b/core/java/android/content/AttributionSource.java
index a1357c91b2cf..bde562dbf95b 100644
--- a/core/java/android/content/AttributionSource.java
+++ b/core/java/android/content/AttributionSource.java
@@ -231,7 +231,7 @@ public final class AttributionSource implements Parcelable {
}
/** @hide */
- public AttributionSource withToken(@NonNull Binder token) {
+ public AttributionSource withToken(@NonNull IBinder token) {
return new AttributionSource(getUid(), getPid(), getPackageName(), getAttributionTag(),
token, mAttributionSourceState.renouncedPermissions, getDeviceId(), getNext());
}
diff --git a/core/java/android/permission/IPermissionManager.aidl b/core/java/android/permission/IPermissionManager.aidl
index 7cecfdca851a..471f95bb21f3 100644
--- a/core/java/android/permission/IPermissionManager.aidl
+++ b/core/java/android/permission/IPermissionManager.aidl
@@ -92,7 +92,7 @@ interface IPermissionManager {
boolean isAutoRevokeExempted(String packageName, int userId);
- void registerAttributionSource(in AttributionSourceState source);
+ IBinder registerAttributionSource(in AttributionSourceState source);
boolean isRegisteredAttributionSource(in AttributionSourceState source);
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index 91adc37cb654..4af6e3a9f8d4 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -23,6 +23,7 @@ import static android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET;
import static android.os.Build.VERSION_CODES.S;
+import static android.permission.flags.Flags.serverSideAttributionRegistration;
import android.Manifest;
import android.annotation.CheckResult;
@@ -59,6 +60,7 @@ import android.media.AudioManager;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
+import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
@@ -1464,13 +1466,19 @@ public final class PermissionManager {
// We use a shared static token for sources that are not registered since the token's
// only used for process death detection. If we are about to use the source for security
// enforcement we need to replace the binder with a unique one.
- final AttributionSource registeredSource = source.withToken(new Binder());
try {
- mPermissionManager.registerAttributionSource(registeredSource.asState());
+ if (serverSideAttributionRegistration()) {
+ IBinder newToken = mPermissionManager.registerAttributionSource(source.asState());
+ return source.withToken(newToken);
+ } else {
+ AttributionSource registeredSource = source.withToken(new Binder());
+ mPermissionManager.registerAttributionSource(registeredSource.asState());
+ return registeredSource;
+ }
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
- return registeredSource;
+ return source;
}
/**
diff --git a/core/java/android/permission/flags.aconfig b/core/java/android/permission/flags.aconfig
index 60143cc79d2d..bced21730a34 100644
--- a/core/java/android/permission/flags.aconfig
+++ b/core/java/android/permission/flags.aconfig
@@ -73,6 +73,13 @@ flag {
}
flag {
+ name: "server_side_attribution_registration"
+ namespace: "permissions"
+ description: "controls whether the binder representing an AttributionSource is created in the system server, or client process"
+ bug: "310953959"
+}
+
+flag {
name: "wallet_role_enabled"
namespace: "wallet_integration"
description: "This flag is used to enabled the Wallet Role for all users on the device"
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 5d710d272fc9..ee40e18b7d9f 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -29,6 +29,7 @@ import static android.app.AppOpsManager.MODE_IGNORED;
import static android.app.AppOpsManager.OP_BLUETOOTH_CONNECT;
import static android.content.pm.ApplicationInfo.AUTO_REVOKE_DISALLOWED;
import static android.content.pm.ApplicationInfo.AUTO_REVOKE_DISCOURAGED;
+import static android.permission.flags.Flags.serverSideAttributionRegistration;
import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
@@ -439,10 +440,27 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
}
+ /**
+ * Reference propagation over binder is affected by the ownership of the object. So if
+ * the token is owned by client, references to the token on client side won't be
+ * propagated to the server and the token may still be garbage collected on server side.
+ * But if the token is owned by server, references to the token on client side will now
+ * be propagated to the server since it's a foreign object to the client, and that will
+ * keep the token referenced on the server side as long as the client is alive and
+ * holding it.
+ */
@Override
- public void registerAttributionSource(@NonNull AttributionSourceState source) {
- mAttributionSourceRegistry
- .registerAttributionSource(new AttributionSource(source));
+ public IBinder registerAttributionSource(@NonNull AttributionSourceState source) {
+ if (serverSideAttributionRegistration()) {
+ Binder token = new Binder();
+ mAttributionSourceRegistry
+ .registerAttributionSource(new AttributionSource(source).withToken(token));
+ return token;
+ } else {
+ mAttributionSourceRegistry
+ .registerAttributionSource(new AttributionSource(source));
+ return source.token;
+ }
}
@Override
@@ -1218,7 +1236,6 @@ public class PermissionManagerService extends IPermissionManager.Stub {
@Nullable String message, boolean forDataDelivery, boolean startDataDelivery,
boolean fromDatasource, int attributedOp) {
PermissionInfo permissionInfo = sPlatformPermissions.get(permission);
-
if (permissionInfo == null) {
try {
permissionInfo = context.getPackageManager().getPermissionInfo(permission, 0);
@@ -1346,8 +1363,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
// If the call is from a datasource we need to vet only the chain before it. This
// way we can avoid the datasource creating an attribution context for every call.
- if (!(fromDatasource && current.equals(attributionSource))
- && next != null && !current.isTrusted(context)) {
+ boolean isDatasource = fromDatasource && current.equals(attributionSource);
+ if (!isDatasource && next != null && !current.isTrusted(context)) {
return PermissionChecker.PERMISSION_HARD_DENIED;
}