aboutsummaryrefslogtreecommitdiff
path: root/framework/java/android/bluetooth/BluetoothAdapter.java
diff options
context:
space:
mode:
Diffstat (limited to 'framework/java/android/bluetooth/BluetoothAdapter.java')
-rw-r--r--framework/java/android/bluetooth/BluetoothAdapter.java220
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();