diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 091b8e5d6e9ac..a81411b8a0910 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -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); } diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 31b0d413c395f..47a9fbb5fe4a8 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -722,7 +722,7 @@ public final class SystemServiceRegistry { new CachedServiceFetcher() { @Override public UwbManager createService(ContextImpl ctx) { - return UwbManager.getInstance(); + return UwbManager.getInstance(ctx); } }); diff --git a/core/java/android/uwb/RangingManager.java b/core/java/android/uwb/RangingManager.java index 85f2c1ccc1801..5c7f0f5cb1e03 100644 --- a/core/java/android/uwb/RangingManager.java +++ b/core/java/android/uwb/RangingManager.java @@ -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(); diff --git a/core/java/android/uwb/UwbManager.java b/core/java/android/uwb/UwbManager.java index 844bbbe7970bb..bed77e6643372 100644 --- a/core/java/android/uwb/UwbManager.java +++ b/core/java/android/uwb/UwbManager.java @@ -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 Context.getSystemService(UwbManager.class) 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); } } diff --git a/core/tests/uwbtests/src/android/uwb/RangingManagerTest.java b/core/tests/uwbtests/src/android/uwb/RangingManagerTest.java index e41805dd3a59b..8271bed940e22 100644 --- a/core/tests/uwbtests/src/android/uwb/RangingManagerTest.java +++ b/core/tests/uwbtests/src/android/uwb/RangingManagerTest.java @@ -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 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 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 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);