Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a4d18e76 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Track active AttributionSources, and finish chains on death" into sc-dev

parents 144dab97 7008c4d5
Loading
Loading
Loading
Loading
+68 −5
Original line number Original line Diff line number Diff line
@@ -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;
@@ -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;


@@ -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);
@@ -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;
@@ -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;
                }
                }


@@ -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);
                }
                }


@@ -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;
            }
            }
        }
        }
@@ -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;
                }
                }
@@ -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;
        }
    }
}
}