Merge "Update BluetoothDevice#setAlias based on API council feedback: now accepts null input and returns an int (with error codes). Update CompanionDeviceManager#canPairWithoutPrompt to take a UserHandle instead of an int. Adds BluetoothStatusCodes class for all new Bluetooth error / success codes. Moved OOB and hci disconnect constants to the new BluetoothStatusCodes class." into sc-dev am: b8cfbebbec

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/14457502

Change-Id: Ie9981f42551d47dd654d3cf38f4dbfd3f5d44607
This commit is contained in:
Rahul Sabnis
2021-05-19 16:22:47 +00:00
committed by Automerger Merge Worker
6 changed files with 279 additions and 170 deletions

View File

@@ -9039,7 +9039,7 @@ package android.bluetooth {
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public String getName(); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public String getName();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getType(); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getType();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.os.ParcelUuid[] getUuids(); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.os.ParcelUuid[] getUuids();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean setAlias(@NonNull String); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int setAlias(@Nullable String);
method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setPairingConfirmation(boolean); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setPairingConfirmation(boolean);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean setPin(byte[]); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean setPin(byte[]);
method public void writeToParcel(android.os.Parcel, int); method public void writeToParcel(android.os.Parcel, int);
@@ -9487,6 +9487,15 @@ package android.bluetooth {
field public static final int TYPE_SCO = 2; // 0x2 field public static final int TYPE_SCO = 2; // 0x2
} }
public final class BluetoothStatusCodes {
field public static final int ERROR_BLUETOOTH_NOT_ALLOWED = 2; // 0x2
field public static final int ERROR_BLUETOOTH_NOT_ENABLED = 1; // 0x1
field public static final int ERROR_DEVICE_NOT_BONDED = 3; // 0x3
field public static final int ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION = 6; // 0x6
field public static final int ERROR_UNKNOWN = 2147483647; // 0x7fffffff
field public static final int SUCCESS = 0; // 0x0
}
} }
package android.bluetooth.le { package android.bluetooth.le {

View File

@@ -1950,9 +1950,6 @@ package android.bluetooth {
field public static final int ACTIVE_DEVICE_ALL = 2; // 0x2 field public static final int ACTIVE_DEVICE_ALL = 2; // 0x2
field public static final int ACTIVE_DEVICE_AUDIO = 0; // 0x0 field public static final int ACTIVE_DEVICE_AUDIO = 0; // 0x0
field public static final int ACTIVE_DEVICE_PHONE_CALL = 1; // 0x1 field public static final int ACTIVE_DEVICE_PHONE_CALL = 1; // 0x1
field public static final int OOB_ERROR_ADAPTER_DISABLED = 2; // 0x2
field public static final int OOB_ERROR_ANOTHER_ACTIVE_REQUEST = 1; // 0x1
field public static final int OOB_ERROR_UNKNOWN = 0; // 0x0
} }
public static interface BluetoothAdapter.OnMetadataChangedListener { public static interface BluetoothAdapter.OnMetadataChangedListener {
@@ -2090,6 +2087,10 @@ package android.bluetooth {
field @Deprecated public static final int PRIORITY_ON = 100; // 0x64 field @Deprecated public static final int PRIORITY_ON = 100; // 0x64
} }
public final class BluetoothStatusCodes {
field public static final int ERROR_ANOTHER_ACTIVE_OOB_REQUEST = 1000; // 0x3e8
}
public final class BluetoothUuid { public final class BluetoothUuid {
method public static boolean containsAnyUuid(@Nullable android.os.ParcelUuid[], @Nullable android.os.ParcelUuid[]); method public static boolean containsAnyUuid(@Nullable android.os.ParcelUuid[], @Nullable android.os.ParcelUuid[]);
method @NonNull public static android.os.ParcelUuid parseUuidFrom(@Nullable byte[]); method @NonNull public static android.os.ParcelUuid parseUuidFrom(@Nullable byte[]);
@@ -2245,7 +2246,7 @@ package android.companion {
public final class CompanionDeviceManager { public final class CompanionDeviceManager {
method @RequiresPermission(android.Manifest.permission.ASSOCIATE_COMPANION_DEVICES) public void associate(@NonNull String, @NonNull android.net.MacAddress); method @RequiresPermission(android.Manifest.permission.ASSOCIATE_COMPANION_DEVICES) public void associate(@NonNull String, @NonNull android.net.MacAddress);
method @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public boolean canPairWithoutPrompt(@NonNull String, @NonNull String, int); method @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public boolean canPairWithoutPrompt(@NonNull String, @NonNull String, @NonNull android.os.UserHandle);
method @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public boolean isDeviceAssociatedForWifiConnection(@NonNull String, @NonNull android.net.MacAddress, @NonNull android.os.UserHandle); method @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public boolean isDeviceAssociatedForWifiConnection(@NonNull String, @NonNull android.net.MacAddress, @NonNull android.os.UserHandle);
} }

View File

@@ -3258,38 +3258,13 @@ public final class BluetoothAdapter {
/** @hide */ /** @hide */
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = { "OOB_ERROR_" }, value = { @IntDef(value = {
OOB_ERROR_UNKNOWN, BluetoothStatusCodes.ERROR_UNKNOWN,
OOB_ERROR_ANOTHER_ACTIVE_REQUEST, BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED,
OOB_ERROR_ADAPTER_DISABLED BluetoothStatusCodes.ERROR_ANOTHER_ACTIVE_OOB_REQUEST,
}) })
public @interface OobError {} public @interface OobError {}
/**
* An unknown error has occurred in the controller, stack, or callback pipeline.
*
* @hide
*/
@SystemApi
public static final int OOB_ERROR_UNKNOWN = 0;
/**
* If another application has already requested {@link OobData} then another fetch will be
* disallowed until the callback is removed.
*
* @hide
*/
@SystemApi
public static final int OOB_ERROR_ANOTHER_ACTIVE_REQUEST = 1;
/**
* The adapter is currently disabled, please enable it.
*
* @hide
*/
@SystemApi
public static final int OOB_ERROR_ADAPTER_DISABLED = 2;
/** /**
* Provides callback methods for receiving {@link OobData} from the host stack, as well as an * Provides callback methods for receiving {@link OobData} from the host stack, as well as an
* error interface in order to allow the caller to determine next steps based on the {@code * error interface in order to allow the caller to determine next steps based on the {@code
@@ -3310,7 +3285,7 @@ public final class BluetoothAdapter {
/** /**
* Provides feedback when things don't go as expected. * Provides feedback when things don't go as expected.
* *
* @param errorCode - the code descibing the type of error that occurred. * @param errorCode - the code describing the type of error that occurred.
*/ */
void onError(@OobError int errorCode); void onError(@OobError int errorCode);
} }
@@ -3407,7 +3382,7 @@ public final class BluetoothAdapter {
Preconditions.checkNotNull(callback); Preconditions.checkNotNull(callback);
if (!isEnabled()) { if (!isEnabled()) {
Log.w(TAG, "generateLocalOobData(): Adapter isn't enabled!"); Log.w(TAG, "generateLocalOobData(): Adapter isn't enabled!");
callback.onError(OOB_ERROR_ADAPTER_DISABLED); callback.onError(BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED);
} else { } else {
try { try {
mService.generateLocalOobData(transport, new WrappedOobDataCallback(callback, mService.generateLocalOobData(transport, new WrappedOobDataCallback(callback,
@@ -4210,141 +4185,45 @@ public final class BluetoothAdapter {
*/ */
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = { "REASON_" }, value = { @IntDef(prefix = { "REASON_" }, value = {
REASON_UNKNOWN, BluetoothStatusCodes.ERROR_UNKNOWN,
REASON_LOCAL_REQUEST, BluetoothStatusCodes.ERROR_DISCONNECT_REASON_LOCAL_REQUEST,
REASON_REMOTE_REQUEST, BluetoothStatusCodes.ERROR_DISCONNECT_REASON_REMOTE_REQUEST,
REASON_LOCAL_ERROR, BluetoothStatusCodes.ERROR_DISCONNECT_REASON_LOCAL,
REASON_REMOTE_ERROR, BluetoothStatusCodes.ERROR_DISCONNECT_REASON_REMOTE,
REASON_TIMEOUT, BluetoothStatusCodes.ERROR_DISCONNECT_REASON_TIMEOUT,
REASON_SECURITY, BluetoothStatusCodes.ERROR_DISCONNECT_REASON_SECURITY,
REASON_SYSTEM_POLICY, BluetoothStatusCodes.ERROR_DISCONNECT_REASON_SYSTEM_POLICY,
REASON_RESOURCE_LIMIT_REACHED, BluetoothStatusCodes.ERROR_DISCONNECT_REASON_RESOURCE_LIMIT_REACHED,
REASON_CONNECTION_EXISTS, BluetoothStatusCodes.ERROR_DISCONNECT_REASON_CONNECTION_ALREADY_EXISTS,
REASON_BAD_PARAMETERS}) BluetoothStatusCodes.ERROR_DISCONNECT_REASON_BAD_PARAMETERS})
public @interface DisconnectReason {} public @interface DisconnectReason {}
/**
* Indicates that the ACL disconnected due to an unknown reason.
*/
public static final int REASON_UNKNOWN = 0;
/**
* Indicates that the ACL disconnected due to an explicit request from the local device.
* <p>
* Example cause: This is a normal disconnect reason, e.g., user/app initiates
* disconnection.
*/
public static final int REASON_LOCAL_REQUEST = 1;
/**
* Indicates that the ACL disconnected due to an explicit request from the remote device.
* <p>
* Example cause: This is a normal disconnect reason, e.g., user/app initiates
* disconnection.
* <p>
* Example solution: The app can also prompt the user to check their remote device.
*/
public static final int REASON_REMOTE_REQUEST = 2;
/**
* Generic disconnect reason indicating the ACL disconnected due to an error on the local
* device.
* <p>
* Example solution: Prompt the user to check their local device (e.g., phone, car
* headunit).
*/
public static final int REASON_LOCAL_ERROR = 3;
/**
* Generic disconnect reason indicating the ACL disconnected due to an error on the remote
* device.
* <p>
* Example solution: Prompt the user to check their remote device (e.g., headset, car
* headunit, watch).
*/
public static final int REASON_REMOTE_ERROR = 4;
/**
* Indicates that the ACL disconnected due to a timeout.
* <p>
* Example cause: remote device might be out of range.
* <p>
* Example solution: Prompt user to verify their remote device is on or in
* connection/pairing mode.
*/
public static final int REASON_TIMEOUT = 5;
/**
* Indicates that the ACL disconnected due to link key issues.
* <p>
* Example cause: Devices are either unpaired or remote device is refusing our pairing
* request.
* <p>
* Example solution: Prompt user to unpair and pair again.
*/
public static final int REASON_SECURITY = 6;
/**
* Indicates that the ACL disconnected due to the local device's system policy.
* <p>
* Example cause: privacy policy, power management policy, permissions, etc.
* <p>
* Example solution: Prompt the user to check settings, or check with their system
* administrator (e.g. some corp-managed devices do not allow OPP connection).
*/
public static final int REASON_SYSTEM_POLICY = 7;
/**
* Indicates that the ACL disconnected due to resource constraints, either on the local
* device or the remote device.
* <p>
* Example cause: controller is busy, memory limit reached, maximum number of connections
* reached.
* <p>
* Example solution: The app should wait and try again. If still failing, prompt the user
* to disconnect some devices, or toggle Bluetooth on the local and/or the remote device.
*/
public static final int REASON_RESOURCE_LIMIT_REACHED = 8;
/**
* Indicates that the ACL disconnected because another ACL connection already exists.
*/
public static final int REASON_CONNECTION_EXISTS = 9;
/**
* Indicates that the ACL disconnected due to incorrect parameters passed in from the app.
* <p>
* Example solution: Change parameters and try again. If error persists, the app can report
* telemetry and/or log the error in a bugreport.
*/
public static final int REASON_BAD_PARAMETERS = 10;
/** /**
* Returns human-readable strings corresponding to {@link DisconnectReason}. * Returns human-readable strings corresponding to {@link DisconnectReason}.
*/ */
public static String disconnectReasonText(@DisconnectReason int reason) { public static String disconnectReasonText(@DisconnectReason int reason) {
switch (reason) { switch (reason) {
case REASON_UNKNOWN: case BluetoothStatusCodes.ERROR_UNKNOWN:
return "Reason unknown"; return "Reason unknown";
case REASON_LOCAL_REQUEST: case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_LOCAL_REQUEST:
return "Local request"; return "Local request";
case REASON_REMOTE_REQUEST: case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_REMOTE_REQUEST:
return "Remote request"; return "Remote request";
case REASON_LOCAL_ERROR: case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_LOCAL:
return "Local error"; return "Local error";
case REASON_REMOTE_ERROR: case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_REMOTE:
return "Remote error"; return "Remote error";
case REASON_TIMEOUT: case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_TIMEOUT:
return "Timeout"; return "Timeout";
case REASON_SECURITY: case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_SECURITY:
return "Security"; return "Security";
case REASON_SYSTEM_POLICY: case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_SYSTEM_POLICY:
return "System policy"; return "System policy";
case REASON_RESOURCE_LIMIT_REACHED: case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_RESOURCE_LIMIT_REACHED:
return "Resource constrained"; return "Resource constrained";
case REASON_CONNECTION_EXISTS: case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_CONNECTION_ALREADY_EXISTS:
return "Connection already exists"; return "Connection already exists";
case REASON_BAD_PARAMETERS: case BluetoothStatusCodes.ERROR_DISCONNECT_REASON_BAD_PARAMETERS:
return "Bad parameters"; return "Bad parameters";
default: default:
return "Unrecognized disconnect reason: " + reason; return "Unrecognized disconnect reason: " + reason;

View File

@@ -1351,6 +1351,17 @@ public final class BluetoothDevice implements Parcelable {
return null; return null;
} }
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(value = {
BluetoothStatusCodes.SUCCESS,
BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED,
BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED,
BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION,
BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED
})
public @interface SetAliasReturnValues{}
/** /**
* Sets the locally modifiable name (alias) of the remote Bluetooth device. This method * Sets the locally modifiable name (alias) of the remote Bluetooth device. This method
* overwrites the previously stored alias. The new alias is saved in local * overwrites the previously stored alias. The new alias is saved in local
@@ -1358,34 +1369,35 @@ public final class BluetoothDevice implements Parcelable {
* *
* <p>This method requires the calling app to be associated with Companion Device Manager (see * <p>This method requires the calling app to be associated with Companion Device Manager (see
* {@link android.companion.CompanionDeviceManager#associate(AssociationRequest, * {@link android.companion.CompanionDeviceManager#associate(AssociationRequest,
* android.companion.CompanionDeviceManager.Callback, Handler)}) and have the {@link * android.companion.CompanionDeviceManager.Callback, Handler)}) and have the
* android.Manifest.permission#BLUETOOTH} permission. Alternatively, if the caller has the * {@link android.Manifest.permission#BLUETOOTH_CONNECT} permission. Alternatively, if the
* {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED} permission, they can bypass the * caller has the {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED} permission, they can
* Companion Device Manager association requirement. * bypass the Companion Device Manager association requirement as well as other permission
* requirements.
* *
* @param alias is the new locally modifiable name for the remote Bluetooth device which must be * @param alias is the new locally modifiable name for the remote Bluetooth device which must
* non-null and not the empty string. * be the empty string. If null, we clear the alias.
* @return {@code true} if the alias is successfully set, {@code false} on error * @return whether the alias was successfully changed
* @throws IllegalArgumentException if the alias is {@code null} or the empty string * @throws IllegalArgumentException if the alias is the empty string
*/ */
@RequiresLegacyBluetoothPermission @RequiresLegacyBluetoothPermission
@RequiresBluetoothConnectPermission @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean setAlias(@NonNull String alias) { public @SetAliasReturnValues int setAlias(@Nullable String alias) {
if (alias == null || alias.isEmpty()) { if (alias != null && alias.isEmpty()) {
throw new IllegalArgumentException("Cannot set the alias to null or the empty string"); throw new IllegalArgumentException("alias cannot be the empty string");
} }
final IBluetooth service = sService; final IBluetooth service = sService;
if (service == null) { if (service == null) {
Log.e(TAG, "BT not enabled. Cannot set Remote Device name"); Log.e(TAG, "BT not enabled. Cannot set Remote Device name");
return false; return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
} }
try { try {
return service.setRemoteAlias(this, alias, mAttributionSource); return service.setRemoteAlias(this, alias, mAttributionSource);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.e(TAG, "", e); Log.e(TAG, "", e);
throw e.rethrowFromSystemServer();
} }
return false;
} }
/** /**

View File

@@ -0,0 +1,205 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.bluetooth;
import android.annotation.SystemApi;
/**
* A class with constants representing possible return values for Bluetooth APIs. General return
* values occupy the range 0 to 99. Profile-specific return values occupy the range 100-999.
* API-specific return values start at 1000. The exception to this is the "other" error code which
* occupies the max integer value.
*/
public final class BluetoothStatusCodes {
private BluetoothStatusCodes() {}
/**
* Indicates that the API call was successful
*/
public static final int SUCCESS = 0;
/**
* Error code indicating that Bluetooth is not enabled
*/
public static final int ERROR_BLUETOOTH_NOT_ENABLED = 1;
/**
* Error code indicating that the API call was initiated by neither the system nor the active
* Zuser
*/
public static final int ERROR_BLUETOOTH_NOT_ALLOWED = 2;
/**
* Error code indicating that the Bluetooth Device specified is not bonded
*/
public static final int ERROR_DEVICE_NOT_BONDED = 3;
/**
* Error code indicating that the Bluetooth Device specified is not connected, but is bonded
*
* @hide
*/
public static final int ERROR_DEVICE_NOT_CONNECTED = 4;
/**
* Error code indicating that the caller does not have the
* {@link android.Manifest.permission#BLUETOOTH_ADVERTISE} permission
*
* @hide
*/
public static final int ERROR_MISSING_BLUETOOTH_ADVERTISE_PERMISSION = 5;
/**
* Error code indicating that the caller does not have the
* {@link android.Manifest.permission#BLUETOOTH_CONNECT} permission
*/
public static final int ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION = 6;
/**
* Error code indicating that the caller does not have the
* {@link android.Manifest.permission#BLUETOOTH_SCAN} permission
*
* @hide
*/
public static final int ERROR_MISSING_BLUETOOTH_SCAN_PERMISSION = 7;
/**
* If another application has already requested {@link OobData} then another fetch will be
* disallowed until the callback is removed.
*
* @hide
*/
@SystemApi
public static final int ERROR_ANOTHER_ACTIVE_OOB_REQUEST = 1000;
/**
* Indicates that the ACL disconnected due to an explicit request from the local device.
* <p>
* Example cause: This is a normal disconnect reason, e.g., user/app initiates
* disconnection.
*
* @hide
*/
public static final int ERROR_DISCONNECT_REASON_LOCAL_REQUEST = 1100;
/**
* Indicates that the ACL disconnected due to an explicit request from the remote device.
* <p>
* Example cause: This is a normal disconnect reason, e.g., user/app initiates
* disconnection.
* <p>
* Example solution: The app can also prompt the user to check their remote device.
*
* @hide
*/
public static final int ERROR_DISCONNECT_REASON_REMOTE_REQUEST = 1101;
/**
* Generic disconnect reason indicating the ACL disconnected due to an error on the local
* device.
* <p>
* Example solution: Prompt the user to check their local device (e.g., phone, car
* headunit).
*
* @hide
*/
public static final int ERROR_DISCONNECT_REASON_LOCAL = 1102;
/**
* Generic disconnect reason indicating the ACL disconnected due to an error on the remote
* device.
* <p>
* Example solution: Prompt the user to check their remote device (e.g., headset, car
* headunit, watch).
*
* @hide
*/
public static final int ERROR_DISCONNECT_REASON_REMOTE = 1103;
/**
* Indicates that the ACL disconnected due to a timeout.
* <p>
* Example cause: remote device might be out of range.
* <p>
* Example solution: Prompt user to verify their remote device is on or in
* connection/pairing mode.
*
* @hide
*/
public static final int ERROR_DISCONNECT_REASON_TIMEOUT = 1104;
/**
* Indicates that the ACL disconnected due to link key issues.
* <p>
* Example cause: Devices are either unpaired or remote device is refusing our pairing
* request.
* <p>
* Example solution: Prompt user to unpair and pair again.
*
* @hide
*/
public static final int ERROR_DISCONNECT_REASON_SECURITY = 1105;
/**
* Indicates that the ACL disconnected due to the local device's system policy.
* <p>
* Example cause: privacy policy, power management policy, permissions, etc.
* <p>
* Example solution: Prompt the user to check settings, or check with their system
* administrator (e.g. some corp-managed devices do not allow OPP connection).
*
* @hide
*/
public static final int ERROR_DISCONNECT_REASON_SYSTEM_POLICY = 1106;
/**
* Indicates that the ACL disconnected due to resource constraints, either on the local
* device or the remote device.
* <p>
* Example cause: controller is busy, memory limit reached, maximum number of connections
* reached.
* <p>
* Example solution: The app should wait and try again. If still failing, prompt the user
* to disconnect some devices, or toggle Bluetooth on the local and/or the remote device.
*
* @hide
*/
public static final int ERROR_DISCONNECT_REASON_RESOURCE_LIMIT_REACHED = 1107;
/**
* Indicates that the ACL disconnected because another ACL connection already exists.
*
* @hide
*/
public static final int ERROR_DISCONNECT_REASON_CONNECTION_ALREADY_EXISTS = 1108;
/**
* Indicates that the ACL disconnected due to incorrect parameters passed in from the app.
* <p>
* Example solution: Change parameters and try again. If error persists, the app can report
* telemetry and/or log the error in a bugreport.
*
* @hide
*/
public static final int ERROR_DISCONNECT_REASON_BAD_PARAMETERS = 1109;
/**
* Indicates that an unknown error has occurred has occurred.
*/
public static final int ERROR_UNKNOWN = Integer.MAX_VALUE;
}

View File

@@ -338,21 +338,24 @@ public final class CompanionDeviceManager {
* *
* @param packageName the package name of the calling app * @param packageName the package name of the calling app
* @param deviceMacAddress the bluetooth device's mac address * @param deviceMacAddress the bluetooth device's mac address
* @param userId the calling user's identifier * @param user the user handle that currently hosts the package being queried for a companion
* device association
* @return true if it was recently associated and we can bypass the dialog, false otherwise * @return true if it was recently associated and we can bypass the dialog, false otherwise
* @hide * @hide
*/ */
@SystemApi @SystemApi
@RequiresPermission(android.Manifest.permission.MANAGE_COMPANION_DEVICES) @RequiresPermission(android.Manifest.permission.MANAGE_COMPANION_DEVICES)
public boolean canPairWithoutPrompt(@NonNull String packageName, public boolean canPairWithoutPrompt(@NonNull String packageName,
@NonNull String deviceMacAddress, int userId) { @NonNull String deviceMacAddress, @NonNull UserHandle user) {
if (!checkFeaturePresent()) { if (!checkFeaturePresent()) {
return false; return false;
} }
Objects.requireNonNull(packageName, "package name cannot be null"); Objects.requireNonNull(packageName, "package name cannot be null");
Objects.requireNonNull(deviceMacAddress, "device mac address cannot be null"); Objects.requireNonNull(deviceMacAddress, "device mac address cannot be null");
Objects.requireNonNull(user, "user handle cannot be null");
try { try {
return mService.canPairWithoutPrompt(packageName, deviceMacAddress, userId); return mService.canPairWithoutPrompt(packageName, deviceMacAddress,
user.getIdentifier());
} catch (RemoteException e) { } catch (RemoteException e) {
throw e.rethrowFromSystemServer(); throw e.rethrowFromSystemServer();
} }