diff options
-rw-r--r-- | framework/api/system-current.txt | 6 | ||||
-rw-r--r-- | framework/java/android/bluetooth/BluetoothAdapter.java | 11 | ||||
-rw-r--r-- | framework/java/android/bluetooth/BluetoothHeadset.java | 102 | ||||
-rw-r--r-- | framework/java/android/bluetooth/BluetoothStatusCodes.java | 24 |
4 files changed, 111 insertions, 32 deletions
diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index 10f17d46a3..1f928c1f55 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -51,6 +51,7 @@ package android.bluetooth { 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 @@ package android.bluetooth { 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 @@ package android.bluetooth { } 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 385755a5e9..f420b94db7 100644 --- a/framework/java/android/bluetooth/BluetoothAdapter.java +++ b/framework/java/android/bluetooth/BluetoothAdapter.java @@ -2571,14 +2571,20 @@ public final class BluetoothAdapter { * 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 @@ public final class BluetoothAdapter { } } 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 750e3a8323..fcab7b7a7a 100644 --- a/framework/java/android/bluetooth/BluetoothHeadset.java +++ b/framework/java/android/bluetooth/BluetoothHeadset.java @@ -18,6 +18,7 @@ package android.bluetooth; 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 android.util.Log; 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 @@ public final class BluetoothHeadset implements BluetoothProfile { 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. + * @return {@link BluetoothStatusCodes#SUCCESS} upon successful setting, + * otherwise an error code. * - * @param allowed {@code true} if the profile can reroute audio, {@code false} otherwise. * @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 9dafa073ab..c6f6cde44e 100644 --- a/framework/java/android/bluetooth/BluetoothStatusCodes.java +++ b/framework/java/android/bluetooth/BluetoothStatusCodes.java @@ -96,6 +96,14 @@ public final class BluetoothStatusCodes { 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 final class BluetoothStatusCodes { 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. * |