diff options
Diffstat (limited to 'framework/java/android/bluetooth/BluetoothAdapter.java')
| -rw-r--r-- | framework/java/android/bluetooth/BluetoothAdapter.java | 220 |
1 files changed, 104 insertions, 116 deletions
diff --git a/framework/java/android/bluetooth/BluetoothAdapter.java b/framework/java/android/bluetooth/BluetoothAdapter.java index 46893fcc25..1700254ba7 100644 --- a/framework/java/android/bluetooth/BluetoothAdapter.java +++ b/framework/java/android/bluetooth/BluetoothAdapter.java @@ -30,6 +30,7 @@ import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SuppressLint; import android.annotation.SystemApi; //import android.app.PropertyInvalidatedCache; import android.bluetooth.BluetoothDevice.Transport; +import android.bluetooth.BluetoothFrameworkInitializer; import android.bluetooth.BluetoothProfile.ConnectionPolicy; import android.bluetooth.annotations.RequiresBluetoothAdvertisePermission; import android.bluetooth.annotations.RequiresBluetoothConnectPermission; @@ -64,6 +65,7 @@ import com.android.internal.annotations.GuardedBy; import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -396,6 +398,16 @@ public final class BluetoothAdapter { @Retention(RetentionPolicy.SOURCE) public @interface ScanMode {} + /** @hide */ + @IntDef(value = { + BluetoothStatusCodes.SUCCESS, + BluetoothStatusCodes.ERROR_UNKNOWN, + BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED, + BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_SCAN_PERMISSION + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ScanModeStatusCode {} + /** * Indicates that both inquiry scan and page scan are disabled on the local * Bluetooth adapter. Therefore this device is neither discoverable @@ -793,14 +805,16 @@ public final class BluetoothAdapter { /** {@hide} */ public static BluetoothAdapter createAdapter(AttributionSource attributionSource) { - IBinder binder = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE); - if (binder != null) { - return new BluetoothAdapter(IBluetoothManager.Stub.asInterface(binder), - attributionSource); - } else { - Log.e(TAG, "Bluetooth binder is null"); - return null; - } + IBluetoothManager service = IBluetoothManager.Stub.asInterface( + BluetoothFrameworkInitializer.getBluetoothServiceManager() + .getBluetoothManagerServiceRegisterer() + .get()); + if (service != null) { + return new BluetoothAdapter(service, attributionSource); + } else { + Log.e(TAG, "Bluetooth service is null"); + return null; + } } /** @@ -1052,7 +1066,7 @@ public final class BluetoothAdapter { 8, BLUETOOTH_GET_STATE_CACHE_PROPERTY) { @Override @SuppressLint("AndroidFrameworkRequiresPermission") - protected Integer recompute(Void query) { + public Integer recompute(Void query) { try { return mService.getState(); } catch (RemoteException e) { @@ -1615,7 +1629,7 @@ public final class BluetoothAdapter { return mService.getScanMode(mAttributionSource); } } catch (RemoteException e) { - Log.e(TAG, "", e); + throw e.rethrowFromSystemServer(); } finally { mServiceLock.readLock().unlock(); } @@ -1623,143 +1637,110 @@ public final class BluetoothAdapter { } /** - * Set the Bluetooth scan mode of the local Bluetooth adapter. - * <p>The Bluetooth scan mode determines if the local adapter is - * connectable and/or discoverable from remote Bluetooth devices. - * <p>For privacy reasons, discoverable mode is automatically turned off - * after <code>durationMillis</code> milliseconds. For example, 120000 milliseconds should be - * enough for a remote device to initiate and complete its discovery process. - * <p>Valid scan mode values are: - * {@link #SCAN_MODE_NONE}, - * {@link #SCAN_MODE_CONNECTABLE}, - * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}. - * <p>If Bluetooth state is not {@link #STATE_ON}, this API - * will return false. After turning on Bluetooth, - * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON} - * to get the updated value. + * Set the local Bluetooth adapter connectablility and discoverability. + * <p>If the scan mode is set to {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}, + * it will change to {@link #SCAN_MODE_CONNECTABLE} after the discoverable timeout. + * The discoverable timeout can be set with {@link #setDiscoverableTimeout} and + * checked with {@link #getDiscoverableTimeout}. By default, the timeout is usually + * 120 seconds on phones which is enough for a remote device to initiate and complete + * its discovery process. * <p>Applications cannot set the scan mode. They should use - * <code>startActivityForResult( - * BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE}) - * </code>instead. - * - * @param mode valid scan mode - * @param durationMillis time in milliseconds to apply scan mode, only used for {@link - * #SCAN_MODE_CONNECTABLE_DISCOVERABLE} - * @return true if the scan mode was set, false otherwise + * {@link #ACTION_REQUEST_DISCOVERABLE} instead. + * + * @param mode represents the desired state of the local device scan mode + * + * @return status code indicating whether the scan mode was successfully set * @hide */ - @UnsupportedAppUsage(publicAlternatives = "Use {@link #ACTION_REQUEST_DISCOVERABLE}, which " - + "shows UI that confirms the user wants to go into discoverable mode.") - @RequiresLegacyBluetoothPermission + @SystemApi @RequiresBluetoothScanPermission - @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) - public boolean setScanMode(@ScanMode int mode, long durationMillis) { + @RequiresPermission(allOf = { + android.Manifest.permission.BLUETOOTH_SCAN, + android.Manifest.permission.BLUETOOTH_PRIVILEGED, + }) + @ScanModeStatusCode + public int setScanMode(@ScanMode int mode) { if (getState() != STATE_ON) { - return false; + return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; } try { mServiceLock.readLock().lock(); if (mService != null) { - int durationSeconds = Math.toIntExact(durationMillis / 1000); - return mService.setScanMode(mode, durationSeconds, mAttributionSource); + return mService.setScanMode(mode, mAttributionSource); } } catch (RemoteException e) { - Log.e(TAG, "", e); - } catch (ArithmeticException ex) { - Log.e(TAG, "setScanMode: Duration in seconds outside of the bounds of an int"); - throw new IllegalArgumentException("Duration not in bounds. In seconds, the " - + "durationMillis must be in the range of an int"); + throw e.rethrowFromSystemServer(); } finally { mServiceLock.readLock().unlock(); } - return false; + return BluetoothStatusCodes.ERROR_UNKNOWN; } /** - * Set the Bluetooth scan mode of the local Bluetooth adapter. - * <p>The Bluetooth scan mode determines if the local adapter is - * connectable and/or discoverable from remote Bluetooth devices. - * <p>For privacy reasons, discoverable mode is automatically turned off - * after <code>duration</code> seconds. For example, 120 seconds should be - * enough for a remote device to initiate and complete its discovery - * process. - * <p>Valid scan mode values are: - * {@link #SCAN_MODE_NONE}, - * {@link #SCAN_MODE_CONNECTABLE}, - * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}. - * <p>If Bluetooth state is not {@link #STATE_ON}, this API - * will return false. After turning on Bluetooth, - * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON} - * to get the updated value. - * <p>Applications cannot set the scan mode. They should use - * <code>startActivityForResult( - * BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE}) - * </code>instead. + * Get the timeout duration of the {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}. * - * @param mode valid scan mode - * @return true if the scan mode was set, false otherwise - * @hide + * @return the duration of the discoverable timeout or null if an error has occurred */ - @UnsupportedAppUsage - @RequiresLegacyBluetoothPermission @RequiresBluetoothScanPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) - public boolean setScanMode(@ScanMode int mode) { + public @Nullable Duration getDiscoverableTimeout() { if (getState() != STATE_ON) { - return false; + return null; } try { mServiceLock.readLock().lock(); if (mService != null) { - return mService.setScanMode(mode, getDiscoverableTimeout(), mAttributionSource); + long timeout = mService.getDiscoverableTimeout(mAttributionSource); + return (timeout == -1) ? null : Duration.ofSeconds(timeout); } } catch (RemoteException e) { - Log.e(TAG, "", e); + throw e.rethrowFromSystemServer(); } finally { mServiceLock.readLock().unlock(); } - return false; + return null; } - /** @hide */ - @UnsupportedAppUsage + /** + * Set the total time the Bluetooth local adapter will stay discoverable when + * {@link #setScanMode} is called with {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE} mode. + * After this timeout, the scan mode will fallback to {@link #SCAN_MODE_CONNECTABLE}. + * <p>If <code>timeout</code> is set to 0, no timeout will occur and the scan mode will + * be persisted until a subsequent call to {@link #setScanMode}. + * + * @param timeout represents the total duration the local Bluetooth adapter will remain + * discoverable, or no timeout if set to 0 + * @return whether the timeout was successfully set + * @throws IllegalArgumentException if <code>timeout</code> duration in seconds is more + * than {@link Integer#MAX_VALUE} + * @hide + */ + @SystemApi @RequiresBluetoothScanPermission - @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) - public int getDiscoverableTimeout() { + @RequiresPermission(allOf = { + android.Manifest.permission.BLUETOOTH_SCAN, + android.Manifest.permission.BLUETOOTH_PRIVILEGED, + }) + @ScanModeStatusCode + public int setDiscoverableTimeout(@NonNull Duration timeout) { if (getState() != STATE_ON) { - return -1; - } - try { - mServiceLock.readLock().lock(); - if (mService != null) { - return mService.getDiscoverableTimeout(mAttributionSource); - } - } catch (RemoteException e) { - Log.e(TAG, "", e); - } finally { - mServiceLock.readLock().unlock(); + return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; } - return -1; - } - - /** @hide */ - @UnsupportedAppUsage - @RequiresBluetoothScanPermission - @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) - public void setDiscoverableTimeout(int timeout) { - if (getState() != STATE_ON) { - return; + if (timeout.toSeconds() > Integer.MAX_VALUE) { + throw new IllegalArgumentException("Timeout in seconds must be less or equal to " + + Integer.MAX_VALUE); } try { mServiceLock.readLock().lock(); if (mService != null) { - mService.setDiscoverableTimeout(timeout, mAttributionSource); + return mService.setDiscoverableTimeout(timeout.toSeconds(), mAttributionSource); } } catch (RemoteException e) { - Log.e(TAG, "", e); + throw e.rethrowFromSystemServer(); } finally { mServiceLock.readLock().unlock(); } + return BluetoothStatusCodes.ERROR_UNKNOWN; } /** @@ -2112,7 +2093,7 @@ public final class BluetoothAdapter { 8, BLUETOOTH_FILTERING_CACHE_PROPERTY) { @Override @SuppressLint("AndroidFrameworkRequiresPermission") - protected Boolean recompute(Void query) { + public Boolean recompute(Void query) { try { mServiceLock.readLock().lock(); if (mService != null) { @@ -2292,17 +2273,17 @@ public final class BluetoothAdapter { /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(value = { - BluetoothStatusCodes.SUCCESS, + BluetoothStatusCodes.FEATURE_SUPPORTED, BluetoothStatusCodes.ERROR_UNKNOWN, BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED, - BluetoothStatusCodes.ERROR_FEATURE_NOT_SUPPORTED, + BluetoothStatusCodes.FEATURE_NOT_SUPPORTED, }) public @interface LeFeatureReturnValues {} /** - * Returns {@link BluetoothStatusCodes#SUCCESS} if the LE audio feature is - * supported, returns {@link BluetoothStatusCodes#ERROR_FEATURE_NOT_SUPPORTED} if - * the feature is not supported or an error code. + * Returns {@link BluetoothStatusCodes#FEATURE_SUPPORTED} if the LE audio feature is + * supported, {@link BluetoothStatusCodes#FEATURE_NOT_SUPPORTED} if the feature is not + * supported, or an error code. * * @return whether the LE audio is supported */ @@ -2325,9 +2306,9 @@ public final class BluetoothAdapter { } /** - * Returns {@link BluetoothStatusCodes#SUCCESS} if the LE audio broadcast source - * feature is supported, {@link BluetoothStatusCodes#ERROR_FEATURE_NOT_SUPPORTED} if the - * feature is not supported, or an error code. + * Returns {@link BluetoothStatusCodes#FEATURE_SUPPORTED} if the LE audio broadcast source + * feature is supported, {@link BluetoothStatusCodes#FEATURE_NOT_SUPPORTED} if the feature + * is not supported, or an error code. * * @return whether the LE audio broadcast source is supported */ @@ -2351,9 +2332,9 @@ public final class BluetoothAdapter { } /** - * Returns {@link BluetoothStatusCodes#SUCCESS} if the LE audio broadcast assistant - * feature is supported, {@link BluetoothStatusCodes#ERROR_FEATURE_NOT_SUPPORTED} if the - * feature is not supported, or an error code. + * Returns {@link BluetoothStatusCodes#FEATURE_SUPPORTED} if the LE audio broadcast assistant + * feature is supported, {@link BluetoothStatusCodes#FEATURE_NOT_SUPPORTED} if the feature is + * not supported, or an error code. * * @return whether the LE audio broadcast assistent is supported */ @@ -2607,7 +2588,7 @@ public final class BluetoothAdapter { 8, BLUETOOTH_GET_ADAPTER_CONNECTION_STATE_CACHE_PROPERTY) { @Override @SuppressLint("AndroidFrameworkRequiresPermission") - protected Integer recompute(Void query) { + public Integer recompute(Void query) { try { return mService.getAdapterConnectionState(); } catch (RemoteException e) { @@ -2675,7 +2656,7 @@ public final class BluetoothAdapter { 8, BLUETOOTH_PROFILE_CACHE_PROPERTY) { @Override @SuppressLint("AndroidFrameworkRequiresPermission") - protected Integer recompute(Integer query) { + public Integer recompute(Integer query) { try { mServiceLock.readLock().lock(); if (mService != null) { @@ -3140,6 +3121,9 @@ public final class BluetoothAdapter { return true; } return false; + } else if (profile == BluetoothProfile.LE_AUDIO) { + BluetoothLeAudio leAudio = new BluetoothLeAudio(context, listener, this); + return true; } else if (profile == BluetoothProfile.VOLUME_CONTROL) { BluetoothVolumeControl vcs = new BluetoothVolumeControl(context, listener, this); return true; @@ -3239,6 +3223,10 @@ public final class BluetoothAdapter { BluetoothHearingAid hearingAid = (BluetoothHearingAid) proxy; hearingAid.close(); break; + case BluetoothProfile.LE_AUDIO: + BluetoothLeAudio leAudio = (BluetoothLeAudio) proxy; + leAudio.close(); + break; case BluetoothProfile.VOLUME_CONTROL: BluetoothVolumeControl vcs = (BluetoothVolumeControl) proxy; vcs.close(); |
