diff options
9 files changed, 229 insertions, 23 deletions
diff --git a/framework/java/android/bluetooth/BluetoothDevice.java b/framework/java/android/bluetooth/BluetoothDevice.java index 7ff37d2932..a206b53b53 100644 --- a/framework/java/android/bluetooth/BluetoothDevice.java +++ b/framework/java/android/bluetooth/BluetoothDevice.java @@ -203,6 +203,34 @@ public final class BluetoothDevice implements Parcelable { "android.bluetooth.device.action.BOND_STATE_CHANGED"; /** + * Broadcast Action: Indicates the battery level of a remote device has + * been retrieved for the first time, or changed since the last retrieval + * <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link + * #EXTRA_BATTERY_LEVEL}. + * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. + * @hide + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_BATTERY_LEVEL_CHANGED = + "android.bluetooth.device.action.BATTERY_LEVEL_CHANGED"; + + /** + * Used as an Integer extra field in {@link #ACTION_BATTERY_LEVEL_CHANGED} + * intent. It contains the most recently retrieved battery level information + * ranging from 0% to 100% for a remote device, {@link #BATTERY_LEVEL_UNKNOWN} + * when the valid is unknown or there is an error + * @hide + */ + public static final String EXTRA_BATTERY_LEVEL = + "android.bluetooth.device.extra.BATTERY_LEVEL"; + + /** + * Used as the unknown value for {@link #EXTRA_BATTERY_LEVEL} and {@link #getBatteryLevel()} + * @hide + */ + public static final int BATTERY_LEVEL_UNKNOWN = -1; + + /** * Used as a Parcelable {@link BluetoothDevice} extra field in every intent * broadcast by this class. It contains the {@link BluetoothDevice} that * the intent applies to. @@ -861,6 +889,27 @@ public final class BluetoothDevice implements Parcelable { } /** + * Get the most recent identified battery level of this Bluetooth device + * <p>Requires {@link android.Manifest.permission#BLUETOOTH} + * + * @return Battery level in percents from 0 to 100, or {@link #BATTERY_LEVEL_UNKNOWN} if + * Bluetooth is disabled, or device is disconnected, or does not have any battery + * reporting service, or return value is invalid + * @hide + */ + @RequiresPermission(Manifest.permission.BLUETOOTH) + public int getBatteryLevel() { + if (sService == null) { + Log.e(TAG, "Bluetooth disabled. Cannot get remote device battery level"); + return BATTERY_LEVEL_UNKNOWN; + } + try { + return sService.getBatteryLevel(this); + } catch (RemoteException e) {Log.e(TAG, "", e);} + return BATTERY_LEVEL_UNKNOWN; + } + + /** * Start the bonding (pairing) process with the remote device. * <p>This is an asynchronous call, it will return immediately. Register * for {@link #ACTION_BOND_STATE_CHANGED} intents to be notified when @@ -1709,6 +1758,38 @@ public final class BluetoothDevice implements Parcelable { public BluetoothGatt connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback, int transport, int phy, Handler handler) { + return connectGatt(context, autoConnect, callback, transport, false, phy, handler); + } + + /** + * Connect to GATT Server hosted by this device. Caller acts as GATT client. + * The callback is used to deliver results to Caller, such as connection status as well + * as any further GATT client operations. + * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct + * GATT client operations. + * @param callback GATT callback handler that will receive asynchronous callbacks. + * @param autoConnect Whether to directly connect to the remote device (false) + * or to automatically connect as soon as the remote + * device becomes available (true). + * @param transport preferred transport for GATT connections to remote dual-mode devices + * {@link BluetoothDevice#TRANSPORT_AUTO} or + * {@link BluetoothDevice#TRANSPORT_BREDR} or {@link BluetoothDevice#TRANSPORT_LE} + * @param opportunistic Whether this GATT client is opportunistic. An opportunistic GATT client + * does not hold a GATT connection. It automatically disconnects when no + * other GATT connections are active for the remote device. + * @param phy preferred PHY for connections to remote LE device. Bitwise OR of any of + * {@link BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, + * an d{@link BluetoothDevice#PHY_LE_CODED_MASK}. This option does not take effect + * if {@code autoConnect} is set to true. + * @param handler The handler to use for the callback. If {@code null}, callbacks will happen + * on an un-specified background thread. + * @return A BluetoothGatt instance. You can use BluetoothGatt to conduct GATT client + * operations. + * @hide + */ + public BluetoothGatt connectGatt(Context context, boolean autoConnect, + BluetoothGattCallback callback, int transport, + boolean opportunistic, int phy, Handler handler) { if (callback == null) throw new NullPointerException("callback is null"); @@ -1722,7 +1803,7 @@ public final class BluetoothDevice implements Parcelable { // BLE is not supported return null; } - BluetoothGatt gatt = new BluetoothGatt(iGatt, this, transport, phy); + BluetoothGatt gatt = new BluetoothGatt(iGatt, this, transport, opportunistic, phy); gatt.connect(autoConnect, callback, handler); return gatt; } catch (RemoteException e) {Log.e(TAG, "", e);} diff --git a/framework/java/android/bluetooth/BluetoothGatt.java b/framework/java/android/bluetooth/BluetoothGatt.java index a3d6e9f1e4..678159b712 100644 --- a/framework/java/android/bluetooth/BluetoothGatt.java +++ b/framework/java/android/bluetooth/BluetoothGatt.java @@ -53,6 +53,7 @@ public final class BluetoothGatt implements BluetoothProfile { private Boolean mDeviceBusy = false; private int mTransport; private int mPhy; + private boolean mOpportunistic; private static final int AUTH_RETRY_STATE_IDLE = 0; private static final int AUTH_RETRY_STATE_NO_MITM = 1; @@ -172,7 +173,7 @@ public final class BluetoothGatt implements BluetoothProfile { } try { mService.clientConnect(mClientIf, mDevice.getAddress(), - !mAutoConnect, mTransport, mPhy); // autoConnect is inverse of "isDirect" + !mAutoConnect, mTransport, mOpportunistic, mPhy); // autoConnect is inverse of "isDirect" } catch (RemoteException e) { Log.e(TAG,"",e); } @@ -628,11 +629,12 @@ public final class BluetoothGatt implements BluetoothProfile { }; /*package*/ BluetoothGatt(IBluetoothGatt iGatt, BluetoothDevice device, - int transport, int phy) { + int transport, boolean opportunistic, int phy) { mService = iGatt; mDevice = device; mTransport = transport; mPhy = phy; + mOpportunistic = opportunistic; mServices = new ArrayList<BluetoothGattService>(); mConnState = CONN_STATE_IDLE; @@ -839,8 +841,8 @@ public final class BluetoothGatt implements BluetoothProfile { */ public boolean connect() { try { - mService.clientConnect(mClientIf, mDevice.getAddress(), - false, mTransport, mPhy); // autoConnect is inverse of "isDirect" + mService.clientConnect(mClientIf, mDevice.getAddress(), false, mTransport, + mOpportunistic, mPhy); // autoConnect is inverse of "isDirect" return true; } catch (RemoteException e) { Log.e(TAG,"",e); diff --git a/framework/java/android/bluetooth/BluetoothHeadset.java b/framework/java/android/bluetooth/BluetoothHeadset.java index 8519dbaada..c84643fc46 100644 --- a/framework/java/android/bluetooth/BluetoothHeadset.java +++ b/framework/java/android/bluetooth/BluetoothHeadset.java @@ -200,6 +200,37 @@ public final class BluetoothHeadset implements BluetoothProfile { public static final String VENDOR_RESULT_CODE_COMMAND_ANDROID = "+ANDROID"; /** + * A vendor-specific AT command + * @hide + */ + public static final String VENDOR_SPECIFIC_HEADSET_EVENT_XAPL = "+XAPL"; + + /** + * A vendor-specific AT command + * @hide + */ + public static final String VENDOR_SPECIFIC_HEADSET_EVENT_IPHONEACCEV = "+IPHONEACCEV"; + + /** + * Battery level indicator associated with + * {@link #VENDOR_SPECIFIC_HEADSET_EVENT_IPHONEACCEV} + * @hide + */ + public static final int VENDOR_SPECIFIC_HEADSET_EVENT_IPHONEACCEV_BATTERY_LEVEL = 1; + + /** + * A vendor-specific AT command + * @hide + */ + public static final String VENDOR_SPECIFIC_HEADSET_EVENT_XEVENT = "+XEVENT"; + + /** + * Battery level indicator associated with {@link #VENDOR_SPECIFIC_HEADSET_EVENT_XEVENT} + * @hide + */ + public static final String VENDOR_SPECIFIC_HEADSET_EVENT_XEVENT_BATTERY_LEVEL = "BATTERY"; + + /** * Headset state when SCO audio is not connected. * This state can be one of * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of @@ -227,34 +258,33 @@ public final class BluetoothHeadset implements BluetoothProfile { * * <p>This intent will have 3 extras: * <ul> - * <li> {@link #EXTRA_IND_ID} - The Assigned number of headset Indicator which is supported by - the headset ( as indicated by AT+BIND - command in the SLC sequence).or whose value - is changed (indicated by AT+BIEV command)</li> - * <li> {@link #EXTRA_IND_VALUE}- The updated value of headset indicator. </li> - * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> + * <li> {@link #EXTRA_HF_INDICATORS_IND_ID} - The Assigned number of headset Indicator which + * is supported by the headset ( as indicated by AT+BIND command in the SLC + * sequence) or whose value is changed (indicated by AT+BIEV command) </li> + * <li> {@link #EXTRA_HF_INDICATORS_IND_VALUE} - Updated value of headset indicator. </li> + * <li> {@link BluetoothDevice#EXTRA_DEVICE} - Remote device. </li> * </ul> - * <p>{@link #EXTRA_IND_ID} is defined by Bluetooth SIG and each of the indicators are - * given an assigned number. Below shows the assigned number of Indicator added so far - * - Enhanced Safety - 1 - * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to - * receive. + * <p>{@link #EXTRA_HF_INDICATORS_IND_ID} is defined by Bluetooth SIG and each of the indicators + * are given an assigned number. Below shows the assigned number of Indicator added so far + * - Enhanced Safety - 1, Valid Values: 0 - Disabled, 1 - Enabled + * - Battery Level - 2, Valid Values: 0~100 - Remaining level of Battery + * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to receive. * @hide */ public static final String ACTION_HF_INDICATORS_VALUE_CHANGED = "android.bluetooth.headset.action.HF_INDICATORS_VALUE_CHANGED"; /** - * A String extra field in {@link #ACTION_HF_INDICATORS_VALUE_CHANGED} - * intents that contains the UUID of the headset indicator (as defined by Bluetooth SIG) - * that is being sent. + * A int extra field in {@link #ACTION_HF_INDICATORS_VALUE_CHANGED} + * intents that contains the assigned number of the headset indicator as defined by + * Bluetooth SIG that is being sent. Value range is 0-65535 as defined in HFP 1.7 * @hide */ public static final String EXTRA_HF_INDICATORS_IND_ID = "android.bluetooth.headset.extra.HF_INDICATORS_IND_ID"; /** - * A int extra field in {@link #ACTION_HF_INDICATORS_VALUE_CHANGED} + * A int extra field in {@link #ACTION_HF_INDICATORS_VALUE_CHANGED} * intents that contains the value of the Headset indicator that is being sent. * @hide */ @@ -768,6 +798,28 @@ public final class BluetoothHeadset implements BluetoothProfile { } /** + * Force SCO audio to be opened regardless any other restrictions + * + * @param forced Whether or not SCO audio connection should be forced: + * True to force SCO audio + * False to use SCO audio in normal manner + * @hide + */ + public void setForceScoAudio(boolean forced) { + if (VDBG) log("setForceScoAudio " + String.valueOf(forced)); + if (mService != null && isEnabled()) { + try { + mService.setForceScoAudio(forced); + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } + } else { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } + } + + /** * Check if Bluetooth SCO audio is connected. * * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. diff --git a/framework/java/android/bluetooth/BluetoothInputDevice.java b/framework/java/android/bluetooth/BluetoothInputDevice.java index e3288f3c7c..a5a02435e3 100644 --- a/framework/java/android/bluetooth/BluetoothInputDevice.java +++ b/framework/java/android/bluetooth/BluetoothInputDevice.java @@ -97,6 +97,12 @@ public final class BluetoothInputDevice implements BluetoothProfile { public static final String ACTION_VIRTUAL_UNPLUG_STATUS = "android.bluetooth.input.profile.action.VIRTUAL_UNPLUG_STATUS"; + /** + * @hide + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_IDLE_TIME_CHANGED = + "android.bluetooth.input.profile.action.IDLE_TIME_CHANGED"; /** * Return codes for the connect and disconnect Bluez / Dbus calls. @@ -200,6 +206,11 @@ public final class BluetoothInputDevice implements BluetoothProfile { */ public static final String EXTRA_VIRTUAL_UNPLUG_STATUS = "android.bluetooth.BluetoothInputDevice.extra.VIRTUAL_UNPLUG_STATUS"; + /** + * @hide + */ + public static final String EXTRA_IDLE_TIME = "android.bluetooth.BluetoothInputDevice.extra.IDLE_TIME"; + private Context mContext; private ServiceListener mServiceListener; private BluetoothAdapter mAdapter; @@ -659,6 +670,56 @@ public final class BluetoothInputDevice implements BluetoothProfile { if (mService == null) Log.w(TAG, "Proxy not attached to service"); return false; } + + /** + * Send Get_Idle_Time command to the connected HID input device. + * + * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. + * + * @param device Remote Bluetooth Device + * @return false on immediate error, + * true otherwise + * @hide + */ + public boolean getIdleTime(BluetoothDevice device) { + if (DBG) log("getIdletime(" + device + ")"); + if (mService != null && isEnabled() && isValidDevice(device)) { + try { + return mService.getIdleTime(device); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return false; + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * Send Set_Idle_Time command to the connected HID input device. + * + * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. + * + * @param device Remote Bluetooth Device + * @param idleTime Idle time to be set on HID Device + * @return false on immediate error, + * true otherwise + * @hide + */ + public boolean setIdleTime(BluetoothDevice device, byte idleTime) { + if (DBG) log("setIdletime(" + device + "), idleTime=" + idleTime); + if (mService != null && isEnabled() && isValidDevice(device)) { + try { + return mService.setIdleTime(device, idleTime); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return false; + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + private static void log(String msg) { Log.d(TAG, msg); } diff --git a/framework/java/android/bluetooth/IBluetooth.aidl b/framework/java/android/bluetooth/IBluetooth.aidl index 43c5ae4407..1d7cfc900e 100644 --- a/framework/java/android/bluetooth/IBluetooth.aidl +++ b/framework/java/android/bluetooth/IBluetooth.aidl @@ -75,6 +75,7 @@ interface IBluetooth ParcelUuid[] getRemoteUuids(in BluetoothDevice device); boolean fetchRemoteUuids(in BluetoothDevice device); boolean sdpSearch(in BluetoothDevice device, in ParcelUuid uuid); + int getBatteryLevel(in BluetoothDevice device); boolean setPin(in BluetoothDevice device, boolean accept, int len, in byte[] pinCode); boolean setPasskey(in BluetoothDevice device, boolean accept, int len, in byte[] diff --git a/framework/java/android/bluetooth/IBluetoothGatt.aidl b/framework/java/android/bluetooth/IBluetoothGatt.aidl index 167f5e9e10..e87f070072 100644 --- a/framework/java/android/bluetooth/IBluetoothGatt.aidl +++ b/framework/java/android/bluetooth/IBluetoothGatt.aidl @@ -74,7 +74,7 @@ interface IBluetoothGatt { void registerClient(in ParcelUuid appId, in IBluetoothGattCallback callback); void unregisterClient(in int clientIf); - void clientConnect(in int clientIf, in String address, in boolean isDirect, in int transport, in int phy); + void clientConnect(in int clientIf, in String address, in boolean isDirect, in int transport, in boolean opportunistic, in int phy); void clientDisconnect(in int clientIf, in String address); void clientSetPreferredPhy(in int clientIf, in String address, in int txPhy, in int rxPhy, in int phyOptions); void clientReadPhy(in int clientIf, in String address); diff --git a/framework/java/android/bluetooth/IBluetoothHeadset.aidl b/framework/java/android/bluetooth/IBluetoothHeadset.aidl index dde0ac67bb..92ab8da754 100755 --- a/framework/java/android/bluetooth/IBluetoothHeadset.aidl +++ b/framework/java/android/bluetooth/IBluetoothHeadset.aidl @@ -52,6 +52,7 @@ interface IBluetoothHeadset { boolean disconnectAudio(); void setAudioRouteAllowed(boolean allowed); boolean getAudioRouteAllowed(); + void setForceScoAudio(boolean forced); boolean startScoUsingVirtualVoiceCall(in BluetoothDevice device); boolean stopScoUsingVirtualVoiceCall(in BluetoothDevice device); oneway void phoneStateChanged(int numActive, int numHeld, int callState, String number, int type); diff --git a/framework/java/android/bluetooth/IBluetoothInputDevice.aidl b/framework/java/android/bluetooth/IBluetoothInputDevice.aidl index 1ebb9ca6eb..5bd3f78193 100644 --- a/framework/java/android/bluetooth/IBluetoothInputDevice.aidl +++ b/framework/java/android/bluetooth/IBluetoothInputDevice.aidl @@ -56,4 +56,12 @@ interface IBluetoothInputDevice { * @hide */ boolean sendData(in BluetoothDevice device, String report); + /** + * @hide + */ + boolean getIdleTime(in BluetoothDevice device); + /** + * @hide + */ + boolean setIdleTime(in BluetoothDevice device, byte idleTime); } diff --git a/framework/java/android/bluetooth/le/PeriodicAdvertisingParameters.java b/framework/java/android/bluetooth/le/PeriodicAdvertisingParameters.java index 8891d2e842..cf8f08fddd 100644 --- a/framework/java/android/bluetooth/le/PeriodicAdvertisingParameters.java +++ b/framework/java/android/bluetooth/le/PeriodicAdvertisingParameters.java @@ -26,8 +26,8 @@ import android.os.Parcelable; */ public final class PeriodicAdvertisingParameters implements Parcelable { - private static final int INTERVAL_MAX = 80; - private static final int INTERVAL_MIN = 65519; + private static final int INTERVAL_MIN = 80; + private static final int INTERVAL_MAX = 65519; private final boolean includeTxPower; private final int interval; |
