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

Commit a88aa312 authored by Roshan Pius's avatar Roshan Pius
Browse files

UwbManager: Use AttributionSource for runtime permission enforcement

This attribution source is going to be used by Gmscore to proxy
the blame for uwb_ranging runtime permission check (since Gmscore which
is the direct caller of this surface is in most cases proxying the
request from 1p/3p apps).

Note: This CL just adds the skeletal API to start the API reviews. The
actual implementation needs a major refactor of the stack which is WIP.

Bug: 183904955
Test: atest android.uwb
Change-Id: Ia0338b573306f44c493bf1c136e68b4f46877816
parent 9d350e3a
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -14237,7 +14237,7 @@ package android.uwb {
  public final class UwbManager {
    method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public long elapsedRealtimeResolutionNanos();
    method @NonNull @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public android.os.PersistableBundle getSpecificationInfo();
    method @NonNull @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public android.os.CancellationSignal openRangingSession(@NonNull android.os.PersistableBundle, @NonNull java.util.concurrent.Executor, @NonNull android.uwb.RangingSession.Callback);
    method @NonNull @RequiresPermission(allOf={android.Manifest.permission.UWB_PRIVILEGED, android.Manifest.permission.UWB_RANGING}) public android.os.CancellationSignal openRangingSession(@NonNull android.os.PersistableBundle, @NonNull java.util.concurrent.Executor, @NonNull android.uwb.RangingSession.Callback);
    method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public void registerAdapterStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.uwb.UwbManager.AdapterStateCallback);
    method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public void unregisterAdapterStateCallback(@NonNull android.uwb.UwbManager.AdapterStateCallback);
  }
+1 −1
Original line number Diff line number Diff line
@@ -722,7 +722,7 @@ public final class SystemServiceRegistry {
                new CachedServiceFetcher<UwbManager>() {
                    @Override
                    public UwbManager createService(ContextImpl ctx) {
                        return UwbManager.getInstance();
                        return UwbManager.getInstance(ctx);
                    }
                });

+7 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.uwb;

import android.annotation.NonNull;
import android.content.AttributionSource;
import android.os.CancellationSignal;
import android.os.PersistableBundle;
import android.os.RemoteException;
@@ -42,6 +43,9 @@ public class RangingManager extends android.uwb.IUwbRangingCallbacks.Stub {
    /**
     * Open a new ranging session
     *
     * @param attributionSource Attribution source to use for the enforcement of
     *                          {@link android.Manifest.permission#ULTRAWIDEBAND_RANGING} runtime
     *                          permission.
     * @param params the parameters that define the ranging session
     * @param executor {@link Executor} to run callbacks
     * @param callbacks {@link RangingSession.Callback} to associate with the {@link RangingSession}
@@ -49,7 +53,8 @@ public class RangingManager extends android.uwb.IUwbRangingCallbacks.Stub {
     * @return a {@link CancellationSignal} that may be used to cancel the opening of the
     *         {@link RangingSession}.
     */
    public CancellationSignal openSession(@NonNull PersistableBundle params,
    public CancellationSignal openSession(@NonNull AttributionSource attributionSource,
            @NonNull PersistableBundle params,
            @NonNull Executor executor,
            @NonNull RangingSession.Callback callbacks) {
        synchronized (this) {
@@ -58,6 +63,7 @@ public class RangingManager extends android.uwb.IUwbRangingCallbacks.Stub {
                    new RangingSession(executor, callbacks, mAdapter, sessionHandle);
            mRangingSessionTable.put(sessionHandle, session);
            try {
                // TODO: Pass in the attributionSource to the service.
                mAdapter.openRanging(sessionHandle, this, params);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
+20 −11
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@

package android.uwb;

import android.Manifest;
import android.Manifest.permission;
import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -24,7 +24,9 @@ import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.AttributionSource;
import android.content.Context;
import android.content.ContextParams;
import android.os.CancellationSignal;
import android.os.IBinder;
import android.os.PersistableBundle;
@@ -47,9 +49,10 @@ import java.util.concurrent.Executor;
@SystemApi
@SystemService(Context.UWB_SERVICE)
public final class UwbManager {
    private IUwbAdapter mUwbAdapter;
    private static final String SERVICE_NAME = "uwb";

    private final Context mContext;
    private final IUwbAdapter mUwbAdapter;
    private final AdapterStateListener mAdapterStateListener;
    private final RangingManager mRangingManager;

@@ -116,9 +119,11 @@ public final class UwbManager {
    /**
     * Use <code>Context.getSystemService(UwbManager.class)</code> to get an instance.
     *
     * @param ctx Context of the client.
     * @param adapter an instance of an {@link android.uwb.IUwbAdapter}
     */
    private UwbManager(IUwbAdapter adapter) {
    private UwbManager(@NonNull Context ctx, @NonNull IUwbAdapter adapter) {
        mContext = ctx;
        mUwbAdapter = adapter;
        mAdapterStateListener = new AdapterStateListener(adapter);
        mRangingManager = new RangingManager(adapter);
@@ -127,7 +132,7 @@ public final class UwbManager {
    /**
     * @hide
     */
    public static UwbManager getInstance() {
    public static UwbManager getInstance(@NonNull Context ctx) {
        IBinder b = ServiceManager.getService(SERVICE_NAME);
        if (b == null) {
            return null;
@@ -138,7 +143,7 @@ public final class UwbManager {
            return null;
        }

        return new UwbManager(adapter);
        return new UwbManager(ctx, adapter);
    }

    /**
@@ -153,7 +158,7 @@ public final class UwbManager {
     * @param executor an {@link Executor} to execute given callback
     * @param callback user implementation of the {@link AdapterStateCallback}
     */
    @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
    @RequiresPermission(permission.UWB_PRIVILEGED)
    public void registerAdapterStateCallback(@NonNull @CallbackExecutor Executor executor,
            @NonNull AdapterStateCallback callback) {
        mAdapterStateListener.register(executor, callback);
@@ -168,7 +173,7 @@ public final class UwbManager {
     *
     * @param callback user implementation of the {@link AdapterStateCallback}
     */
    @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
    @RequiresPermission(permission.UWB_PRIVILEGED)
    public void unregisterAdapterStateCallback(@NonNull AdapterStateCallback callback) {
        mAdapterStateListener.unregister(callback);
    }
@@ -182,7 +187,7 @@ public final class UwbManager {
     * @return {@link PersistableBundle} of the device's supported UWB protocols and parameters
     */
    @NonNull
    @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
    @RequiresPermission(permission.UWB_PRIVILEGED)
    public PersistableBundle getSpecificationInfo() {
        try {
            return mUwbAdapter.getSpecificationInfo();
@@ -199,7 +204,7 @@ public final class UwbManager {
     * @return the timestamp resolution in nanoseconds
     */
    @SuppressLint("MethodNameUnits")
    @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
    @RequiresPermission(permission.UWB_PRIVILEGED)
    public long elapsedRealtimeResolutionNanos() {
        try {
            return mUwbAdapter.getTimestampResolutionNanos();
@@ -235,10 +240,14 @@ public final class UwbManager {
     *         {@link RangingSession.Callback#onOpened(RangingSession)}.
     */
    @NonNull
    @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
    @RequiresPermission(allOf = {
            permission.UWB_PRIVILEGED,
            permission.UWB_RANGING
    })
    public CancellationSignal openRangingSession(@NonNull PersistableBundle parameters,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull RangingSession.Callback callbacks) {
        return mRangingManager.openSession(parameters, executor, callbacks);
        return mRangingManager.openSession(
                mContext.getAttributionSource(), parameters, executor, callbacks);
    }
}
+15 −10
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import android.content.AttributionSource;
import android.os.PersistableBundle;
import android.os.RemoteException;

@@ -45,13 +46,17 @@ public class RangingManagerTest {
    private static final Executor EXECUTOR = UwbTestUtils.getExecutor();
    private static final PersistableBundle PARAMS = new PersistableBundle();
    private static final @RangingChangeReason int REASON = RangingChangeReason.UNKNOWN;
    private static final int UID = 343453;
    private static final String PACKAGE_NAME = "com.uwb.test";
    private static final AttributionSource ATTRIBUTION_SOURCE =
            new AttributionSource.Builder(UID).setPackageName(PACKAGE_NAME).build();

    @Test
    public void testOpenSession_OpenRangingInvoked() throws RemoteException {
        IUwbAdapter adapter = mock(IUwbAdapter.class);
        RangingManager rangingManager = new RangingManager(adapter);
        RangingSession.Callback callback = mock(RangingSession.Callback.class);
        rangingManager.openSession(PARAMS, EXECUTOR, callback);
        rangingManager.openSession(ATTRIBUTION_SOURCE, PARAMS, EXECUTOR, callback);
        verify(adapter, times(1)).openRanging(any(), eq(rangingManager), eq(PARAMS));
    }

@@ -74,11 +79,11 @@ public class RangingManagerTest {
                ArgumentCaptor.forClass(SessionHandle.class);

        RangingManager rangingManager = new RangingManager(adapter);
        rangingManager.openSession(PARAMS, EXECUTOR, callback1);
        rangingManager.openSession(ATTRIBUTION_SOURCE, PARAMS, EXECUTOR, callback1);
        verify(adapter, times(1)).openRanging(sessionHandleCaptor.capture(), any(), any());
        SessionHandle sessionHandle1 = sessionHandleCaptor.getValue();

        rangingManager.openSession(PARAMS, EXECUTOR, callback2);
        rangingManager.openSession(ATTRIBUTION_SOURCE, PARAMS, EXECUTOR, callback2);
        verify(adapter, times(2)).openRanging(sessionHandleCaptor.capture(), any(), any());
        SessionHandle sessionHandle2 = sessionHandleCaptor.getValue();

@@ -100,7 +105,7 @@ public class RangingManagerTest {
        ArgumentCaptor<SessionHandle> sessionHandleCaptor =
                ArgumentCaptor.forClass(SessionHandle.class);

        rangingManager.openSession(PARAMS, EXECUTOR, callback);
        rangingManager.openSession(ATTRIBUTION_SOURCE, PARAMS, EXECUTOR, callback);
        verify(adapter, times(1)).openRanging(sessionHandleCaptor.capture(), any(), any());
        SessionHandle handle = sessionHandleCaptor.getValue();

@@ -145,11 +150,11 @@ public class RangingManagerTest {
        ArgumentCaptor<SessionHandle> sessionHandleCaptor =
                ArgumentCaptor.forClass(SessionHandle.class);

        rangingManager.openSession(PARAMS, EXECUTOR, callback1);
        rangingManager.openSession(ATTRIBUTION_SOURCE, PARAMS, EXECUTOR, callback1);
        verify(adapter, times(1)).openRanging(sessionHandleCaptor.capture(), any(), any());
        SessionHandle sessionHandle1 = sessionHandleCaptor.getValue();

        rangingManager.openSession(PARAMS, EXECUTOR, callback2);
        rangingManager.openSession(ATTRIBUTION_SOURCE, PARAMS, EXECUTOR, callback2);
        verify(adapter, times(2)).openRanging(sessionHandleCaptor.capture(), any(), any());
        SessionHandle sessionHandle2 = sessionHandleCaptor.getValue();

@@ -172,12 +177,12 @@ public class RangingManagerTest {
                ArgumentCaptor.forClass(SessionHandle.class);

        RangingManager rangingManager = new RangingManager(adapter);
        rangingManager.openSession(PARAMS, EXECUTOR, callback1);
        rangingManager.openSession(ATTRIBUTION_SOURCE, PARAMS, EXECUTOR, callback1);
        verify(adapter, times(1)).openRanging(sessionHandleCaptor.capture(), any(), any());
        SessionHandle sessionHandle1 = sessionHandleCaptor.getValue();

        rangingManager.onRangingStarted(sessionHandle1, PARAMS);
        rangingManager.openSession(PARAMS, EXECUTOR, callback2);
        rangingManager.openSession(ATTRIBUTION_SOURCE, PARAMS, EXECUTOR, callback2);
        verify(adapter, times(2)).openRanging(sessionHandleCaptor.capture(), any(), any());
        SessionHandle sessionHandle2 = sessionHandleCaptor.getValue();
        rangingManager.onRangingStarted(sessionHandle2, PARAMS);
@@ -224,7 +229,7 @@ public class RangingManagerTest {
        ArgumentCaptor<SessionHandle> sessionHandleCaptor =
                ArgumentCaptor.forClass(SessionHandle.class);

        rangingManager.openSession(PARAMS, EXECUTOR, callback);
        rangingManager.openSession(ATTRIBUTION_SOURCE, PARAMS, EXECUTOR, callback);
        verify(adapter, times(1)).openRanging(sessionHandleCaptor.capture(), any(), any());
        SessionHandle handle = sessionHandleCaptor.getValue();

@@ -232,7 +237,7 @@ public class RangingManagerTest {
        verify(callback, times(1)).onOpenFailed(eq(reasonOut), eq(PARAMS));

        // Open a new session
        rangingManager.openSession(PARAMS, EXECUTOR, callback);
        rangingManager.openSession(ATTRIBUTION_SOURCE, PARAMS, EXECUTOR, callback);
        verify(adapter, times(2)).openRanging(sessionHandleCaptor.capture(), any(), any());
        handle = sessionHandleCaptor.getValue();
        rangingManager.onRangingOpened(handle);