Loading services/core/java/com/android/server/pm/permission/PermissionManagerService.java +68 −5 Original line number Original line Diff line number Diff line Loading @@ -172,6 +172,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Iterator; import java.util.List; import java.util.List; import java.util.Map; import java.util.Map; import java.util.NoSuchElementException; import java.util.Objects; import java.util.Objects; import java.util.Set; import java.util.Set; import java.util.WeakHashMap; import java.util.WeakHashMap; Loading @@ -180,6 +181,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BiFunction; import java.util.function.BiFunction; Loading Loading @@ -219,6 +221,10 @@ public class PermissionManagerService extends IPermissionManager.Stub { /** If the permission of the value is granted, so is the key */ /** If the permission of the value is granted, so is the key */ private static final Map<String, String> FULLER_PERMISSION_MAP = new HashMap<>(); private static final Map<String, String> FULLER_PERMISSION_MAP = new HashMap<>(); /** Map of IBinder -> Running AttributionSource */ private static final ConcurrentHashMap<IBinder, RegisteredAttribution> sRunningAttributionSources = new ConcurrentHashMap<>(); static { static { FULLER_PERMISSION_MAP.put(Manifest.permission.ACCESS_COARSE_LOCATION, FULLER_PERMISSION_MAP.put(Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION); Manifest.permission.ACCESS_FINE_LOCATION); Loading Loading @@ -5555,8 +5561,15 @@ public class PermissionManagerService extends IPermissionManager.Stub { @Override @Override public void finishDataDelivery(int op, public void finishDataDelivery(int op, @NonNull AttributionSourceState attributionSourceState, boolean fromDataSource) { finishDataDelivery(mContext, op, attributionSourceState, fromDataSource); } private static void finishDataDelivery(Context context, int op, @NonNull AttributionSourceState attributionSourceState, boolean fromDatasource) { @NonNull AttributionSourceState attributionSourceState, boolean fromDatasource) { Objects.requireNonNull(attributionSourceState); Objects.requireNonNull(attributionSourceState); AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class); if (op == AppOpsManager.OP_NONE) { if (op == AppOpsManager.OP_NONE) { return; return; Loading @@ -5573,7 +5586,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { // If the call is from a datasource we need to vet only the chain before it. This // 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. // way we can avoid the datasource creating an attribution context for every call. if (!(fromDatasource && current.asState() == attributionSourceState) if (!(fromDatasource && current.asState() == attributionSourceState) && next != null && !current.isTrusted(mContext)) { && next != null && !current.isTrusted(context)) { return; return; } } Loading @@ -5589,20 +5602,20 @@ public class PermissionManagerService extends IPermissionManager.Stub { ? current : next; ? current : next; if (selfAccess) { if (selfAccess) { final String resolvedPackageName = resolvePackageName(mContext, accessorSource); final String resolvedPackageName = resolvePackageName(context, accessorSource); if (resolvedPackageName == null) { if (resolvedPackageName == null) { return; return; } } mAppOpsManager.finishOp(accessorSource.getToken(), op, appOpsManager.finishOp(accessorSource.getToken(), op, accessorSource.getUid(), resolvedPackageName, accessorSource.getUid(), resolvedPackageName, accessorSource.getAttributionTag()); accessorSource.getAttributionTag()); } else { } else { final AttributionSource resolvedAttributionSource = final AttributionSource resolvedAttributionSource = resolveAttributionSource(mContext, accessorSource); resolveAttributionSource(context, accessorSource); if (resolvedAttributionSource.getPackageName() == null) { if (resolvedAttributionSource.getPackageName() == null) { return; return; } } mAppOpsManager.finishProxyOp(AppOpsManager.opToPublicName(op), appOpsManager.finishProxyOp(AppOpsManager.opToPublicName(op), resolvedAttributionSource, skipCurrentFinish); resolvedAttributionSource, skipCurrentFinish); } } Loading @@ -5610,6 +5623,11 @@ public class PermissionManagerService extends IPermissionManager.Stub { return; return; } } RegisteredAttribution registered = sRunningAttributionSources.remove(current.getToken()); if (registered != null) { registered.unregister(); } current = next; current = next; } } } } Loading Loading @@ -5827,6 +5845,12 @@ public class PermissionManagerService extends IPermissionManager.Stub { } } } } if (startDataDelivery) { RegisteredAttribution registered = new RegisteredAttribution(context, op, current, fromDatasource); sRunningAttributionSources.put(current.getToken(), registered); } if (next == null || next.getNext() == null) { if (next == null || next.getNext() == null) { return PermissionChecker.PERMISSION_GRANTED; return PermissionChecker.PERMISSION_GRANTED; } } Loading Loading @@ -6153,4 +6177,43 @@ public class PermissionManagerService extends IPermissionManager.Stub { attributionSource)); attributionSource)); } } } } private static final class RegisteredAttribution { private final DeathRecipient mDeathRecipient; private final IBinder mToken; private final AtomicBoolean mFinished; RegisteredAttribution(Context context, int op, AttributionSource source, boolean fromDatasource) { mFinished = new AtomicBoolean(false); mDeathRecipient = () -> { if (unregister()) { PermissionCheckerService .finishDataDelivery(context, op, source.asState(), fromDatasource); } }; mToken = source.getToken(); if (mToken != null) { try { mToken.linkToDeath(mDeathRecipient, 0); } catch (RemoteException e) { mDeathRecipient.binderDied(); } } } public boolean unregister() { if (mFinished.compareAndSet(false, true)) { try { if (mToken != null) { mToken.unlinkToDeath(mDeathRecipient, 0); } } catch (NoSuchElementException e) { // do nothing } return true; } return false; } } } } Loading
services/core/java/com/android/server/pm/permission/PermissionManagerService.java +68 −5 Original line number Original line Diff line number Diff line Loading @@ -172,6 +172,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Iterator; import java.util.List; import java.util.List; import java.util.Map; import java.util.Map; import java.util.NoSuchElementException; import java.util.Objects; import java.util.Objects; import java.util.Set; import java.util.Set; import java.util.WeakHashMap; import java.util.WeakHashMap; Loading @@ -180,6 +181,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BiFunction; import java.util.function.BiFunction; Loading Loading @@ -219,6 +221,10 @@ public class PermissionManagerService extends IPermissionManager.Stub { /** If the permission of the value is granted, so is the key */ /** If the permission of the value is granted, so is the key */ private static final Map<String, String> FULLER_PERMISSION_MAP = new HashMap<>(); private static final Map<String, String> FULLER_PERMISSION_MAP = new HashMap<>(); /** Map of IBinder -> Running AttributionSource */ private static final ConcurrentHashMap<IBinder, RegisteredAttribution> sRunningAttributionSources = new ConcurrentHashMap<>(); static { static { FULLER_PERMISSION_MAP.put(Manifest.permission.ACCESS_COARSE_LOCATION, FULLER_PERMISSION_MAP.put(Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION); Manifest.permission.ACCESS_FINE_LOCATION); Loading Loading @@ -5555,8 +5561,15 @@ public class PermissionManagerService extends IPermissionManager.Stub { @Override @Override public void finishDataDelivery(int op, public void finishDataDelivery(int op, @NonNull AttributionSourceState attributionSourceState, boolean fromDataSource) { finishDataDelivery(mContext, op, attributionSourceState, fromDataSource); } private static void finishDataDelivery(Context context, int op, @NonNull AttributionSourceState attributionSourceState, boolean fromDatasource) { @NonNull AttributionSourceState attributionSourceState, boolean fromDatasource) { Objects.requireNonNull(attributionSourceState); Objects.requireNonNull(attributionSourceState); AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class); if (op == AppOpsManager.OP_NONE) { if (op == AppOpsManager.OP_NONE) { return; return; Loading @@ -5573,7 +5586,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { // If the call is from a datasource we need to vet only the chain before it. This // 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. // way we can avoid the datasource creating an attribution context for every call. if (!(fromDatasource && current.asState() == attributionSourceState) if (!(fromDatasource && current.asState() == attributionSourceState) && next != null && !current.isTrusted(mContext)) { && next != null && !current.isTrusted(context)) { return; return; } } Loading @@ -5589,20 +5602,20 @@ public class PermissionManagerService extends IPermissionManager.Stub { ? current : next; ? current : next; if (selfAccess) { if (selfAccess) { final String resolvedPackageName = resolvePackageName(mContext, accessorSource); final String resolvedPackageName = resolvePackageName(context, accessorSource); if (resolvedPackageName == null) { if (resolvedPackageName == null) { return; return; } } mAppOpsManager.finishOp(accessorSource.getToken(), op, appOpsManager.finishOp(accessorSource.getToken(), op, accessorSource.getUid(), resolvedPackageName, accessorSource.getUid(), resolvedPackageName, accessorSource.getAttributionTag()); accessorSource.getAttributionTag()); } else { } else { final AttributionSource resolvedAttributionSource = final AttributionSource resolvedAttributionSource = resolveAttributionSource(mContext, accessorSource); resolveAttributionSource(context, accessorSource); if (resolvedAttributionSource.getPackageName() == null) { if (resolvedAttributionSource.getPackageName() == null) { return; return; } } mAppOpsManager.finishProxyOp(AppOpsManager.opToPublicName(op), appOpsManager.finishProxyOp(AppOpsManager.opToPublicName(op), resolvedAttributionSource, skipCurrentFinish); resolvedAttributionSource, skipCurrentFinish); } } Loading @@ -5610,6 +5623,11 @@ public class PermissionManagerService extends IPermissionManager.Stub { return; return; } } RegisteredAttribution registered = sRunningAttributionSources.remove(current.getToken()); if (registered != null) { registered.unregister(); } current = next; current = next; } } } } Loading Loading @@ -5827,6 +5845,12 @@ public class PermissionManagerService extends IPermissionManager.Stub { } } } } if (startDataDelivery) { RegisteredAttribution registered = new RegisteredAttribution(context, op, current, fromDatasource); sRunningAttributionSources.put(current.getToken(), registered); } if (next == null || next.getNext() == null) { if (next == null || next.getNext() == null) { return PermissionChecker.PERMISSION_GRANTED; return PermissionChecker.PERMISSION_GRANTED; } } Loading Loading @@ -6153,4 +6177,43 @@ public class PermissionManagerService extends IPermissionManager.Stub { attributionSource)); attributionSource)); } } } } private static final class RegisteredAttribution { private final DeathRecipient mDeathRecipient; private final IBinder mToken; private final AtomicBoolean mFinished; RegisteredAttribution(Context context, int op, AttributionSource source, boolean fromDatasource) { mFinished = new AtomicBoolean(false); mDeathRecipient = () -> { if (unregister()) { PermissionCheckerService .finishDataDelivery(context, op, source.asState(), fromDatasource); } }; mToken = source.getToken(); if (mToken != null) { try { mToken.linkToDeath(mDeathRecipient, 0); } catch (RemoteException e) { mDeathRecipient.binderDied(); } } } public boolean unregister() { if (mFinished.compareAndSet(false, true)) { try { if (mToken != null) { mToken.unlinkToDeath(mDeathRecipient, 0); } } catch (NoSuchElementException e) { // do nothing } return true; } return false; } } } }