[framework] Migration of hidden APIs to System APIs
Bug: 199827901
Tag: #compatibility
Test: IOP, BCST, GTS
Merged-In: Ib0a205bc575e4cc3cf97eac539cd303acd878134
Change-Id: Ib0a205bc575e4cc3cf97eac539cd303acd878134
diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt
index 10f17d4..1f928c1 100644
--- a/framework/api/system-current.txt
+++ b/framework/api/system-current.txt
@@ -51,6 +51,7 @@
method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void generateLocalOobData(int, @NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothAdapter.OobDataCallback);
method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getActiveDevices(int);
method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public long getDiscoveryEndMillis();
+ method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<java.lang.Integer> getSupportedProfiles();
method public boolean isBleScanAlwaysAvailable();
method public boolean isLeEnabled();
method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean removeActiveDevice(int);
@@ -146,8 +147,10 @@
public final class BluetoothHeadset implements android.bluetooth.BluetoothProfile {
method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean connect(android.bluetooth.BluetoothDevice);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disconnect(android.bluetooth.BluetoothDevice);
+ method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getAudioRouteAllowed();
method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean isInbandRingingEnabled();
+ method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int setAudioRouteAllowed(boolean);
method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean startScoUsingVirtualVoiceCall();
method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean stopScoUsingVirtualVoiceCall();
@@ -253,7 +256,10 @@
}
public final class BluetoothStatusCodes {
+ field public static final int ALLOWED = 400; // 0x190
field public static final int ERROR_ANOTHER_ACTIVE_OOB_REQUEST = 1000; // 0x3e8
+ field public static final int ERROR_TIMEOUT = 15; // 0xf
+ field public static final int NOT_ALLOWED = 401; // 0x191
}
public final class BluetoothUuid {
diff --git a/framework/java/android/bluetooth/BluetoothAdapter.java b/framework/java/android/bluetooth/BluetoothAdapter.java
index 385755a..f420b94 100644
--- a/framework/java/android/bluetooth/BluetoothAdapter.java
+++ b/framework/java/android/bluetooth/BluetoothAdapter.java
@@ -2571,14 +2571,20 @@
* BluetoothProfile}.
* @hide
*/
- @RequiresNoPermission
+ @SystemApi
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
public @NonNull List<Integer> getSupportedProfiles() {
final ArrayList<Integer> supportedProfiles = new ArrayList<Integer>();
try {
synchronized (mManagerCallback) {
if (mService != null) {
- final long supportedProfilesBitMask = mService.getSupportedProfiles();
+ final long supportedProfilesBitMask =
+ mService.getSupportedProfiles(mAttributionSource);
for (int i = 0; i <= BluetoothProfile.MAX_PROFILE_ID; i++) {
if ((supportedProfilesBitMask & (1 << i)) != 0) {
@@ -2594,6 +2600,7 @@
}
} catch (RemoteException e) {
Log.e(TAG, "getSupportedProfiles:", e);
+ e.rethrowFromSystemServer();
}
return supportedProfiles;
}
diff --git a/framework/java/android/bluetooth/BluetoothHeadset.java b/framework/java/android/bluetooth/BluetoothHeadset.java
index 750e3a8..fcab7b7 100644
--- a/framework/java/android/bluetooth/BluetoothHeadset.java
+++ b/framework/java/android/bluetooth/BluetoothHeadset.java
@@ -18,6 +18,7 @@
import static android.bluetooth.BluetoothUtils.getSyncTimeout;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -44,6 +45,8 @@
import com.android.modules.utils.SynchronousResultReceiver;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeoutException;
@@ -940,60 +943,99 @@
return defaultValue;
}
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {
+ BluetoothStatusCodes.SUCCESS,
+ BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED,
+ BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND,
+ BluetoothStatusCodes.ERROR_TIMEOUT,
+ BluetoothStatusCodes.ALLOWED,
+ BluetoothStatusCodes.NOT_ALLOWED,
+ })
+ public @interface AudioRouteAllowedReturnValues {}
+
/**
- * Sets whether audio routing is allowed. When set to {@code false}, the AG will not route any
- * audio to the HF unless explicitly told to.
- * This method should be used in cases where the SCO channel is shared between multiple profiles
- * and must be delegated by a source knowledgeable
- * Note: This is an internal function and shouldn't be exposed
+ * Sets whether audio routing is allowed. When set to {@code false}, the AG
+ * will not route any audio to the HF unless explicitly told to. This method
+ * should be used in cases where the SCO channel is shared between multiple
+ * profiles and must be delegated by a source knowledgeable.
*
- * @param allowed {@code true} if the profile can reroute audio, {@code false} otherwise.
+ * @param allowed {@code true} if the profile can reroute audio,
+ * {@code false} otherwise.
+ * @return {@link BluetoothStatusCodes#SUCCESS} upon successful setting,
+ * otherwise an error code.
+ *
* @hide
*/
+ @SystemApi
@RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public void setAudioRouteAllowed(boolean allowed) {
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
+ public @AudioRouteAllowedReturnValues int setAudioRouteAllowed(boolean allowed) {
if (VDBG) log("setAudioRouteAllowed");
final IBluetoothHeadset service = mService;
if (service == null) {
Log.w(TAG, "Proxy not attached to service");
if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver recv = new SynchronousResultReceiver();
- service.setAudioRouteAllowed(allowed, mAttributionSource, recv);
- recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
+ return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;
+ } else if (!isEnabled()) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
}
+ try {
+ final SynchronousResultReceiver recv = new SynchronousResultReceiver();
+ service.setAudioRouteAllowed(allowed, mAttributionSource, recv);
+ recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
+ return BluetoothStatusCodes.SUCCESS;
+ } catch (TimeoutException e) {
+ Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
+ return BluetoothStatusCodes.ERROR_TIMEOUT;
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
+ e.rethrowFromSystemServer();
+ }
+ return BluetoothStatusCodes.ERROR_UNKNOWN;
}
/**
- * Returns whether audio routing is allowed. see {@link #setAudioRouteAllowed(boolean)}.
- * Note: This is an internal function and shouldn't be exposed
+ * @return {@link BluetoothStatusCodes#ALLOWED} if audio routing is allowed,
+ * {@link BluetoothStatusCodes#NOT_ALLOWED} if audio routing is not allowed, or
+ * an error code if an error occurs.
+ * see {@link #setAudioRouteAllowed(boolean)}.
*
* @hide
*/
+ @SystemApi
@RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean getAudioRouteAllowed() {
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
+ public @AudioRouteAllowedReturnValues int getAudioRouteAllowed() {
if (VDBG) log("getAudioRouteAllowed");
final IBluetoothHeadset service = mService;
- final boolean defaultValue = false;
if (service == null) {
Log.w(TAG, "Proxy not attached to service");
if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.getAudioRouteAllowed(mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
+ return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;
+ } else if (!isEnabled()) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
}
- return defaultValue;
+ try {
+ final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
+ service.getAudioRouteAllowed(mAttributionSource, recv);
+ return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(false)
+ ? BluetoothStatusCodes.ALLOWED : BluetoothStatusCodes.NOT_ALLOWED;
+ } catch (TimeoutException e) {
+ Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
+ return BluetoothStatusCodes.ERROR_TIMEOUT;
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
+ e.rethrowFromSystemServer();
+ }
+ return BluetoothStatusCodes.ERROR_UNKNOWN;
}
/**
diff --git a/framework/java/android/bluetooth/BluetoothStatusCodes.java b/framework/java/android/bluetooth/BluetoothStatusCodes.java
index 9dafa07..c6f6cde 100644
--- a/framework/java/android/bluetooth/BluetoothStatusCodes.java
+++ b/framework/java/android/bluetooth/BluetoothStatusCodes.java
@@ -96,6 +96,14 @@
public static final int ERROR_FEATURE_NOT_SUPPORTED = 10;
/**
+ * Error code indicating that the requested operation timed out.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int ERROR_TIMEOUT = 15;
+
+ /**
* A GATT writeCharacteristic request is not permitted on the remote device.
*/
public static final int ERROR_GATT_WRITE_NOT_ALLOWED = 101;
@@ -106,6 +114,22 @@
public static final int ERROR_GATT_WRITE_REQUEST_BUSY = 102;
/**
+ * Indicates that the operation is allowed.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int ALLOWED = 400;
+
+ /**
+ * Indicates that the operation is not allowed.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int NOT_ALLOWED = 401;
+
+ /**
* If another application has already requested {@link OobData} then another fetch will be
* disallowed until the callback is removed.
*