diff --git a/Android.bp b/Android.bp index 23fd580cf6527d26f8d9283cd403922464db9eee..acd3b34d4e7b6d8a81f6b57001d205b5637dea80 100644 --- a/Android.bp +++ b/Android.bp @@ -388,6 +388,7 @@ java_defaults { "tv_tuner_resource_manager_aidl_interface-java", "soundtrigger_middleware-aidl-java", "modules-utils-preconditions", + "modules-utils-synchronous-result-receiver", "modules-utils-os", "framework-permission-aidl-java", "spatializer-aidl-java", diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java index d66dc637743dd1f8c431a2dada3060e445b64741..8b9cec17a1963c150f15a8b7074588774eb9bd00 100644 --- a/core/java/android/bluetooth/BluetoothA2dp.java +++ b/core/java/android/bluetooth/BluetoothA2dp.java @@ -16,6 +16,8 @@ package android.bluetooth; +import static android.bluetooth.BluetoothUtils.getSyncTimeout; + import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -30,17 +32,19 @@ import android.bluetooth.annotations.RequiresLegacyBluetoothPermission; import android.compat.annotation.UnsupportedAppUsage; import android.content.AttributionSource; import android.content.Context; -import android.os.Binder; import android.os.Build; import android.os.IBinder; import android.os.ParcelUuid; import android.os.RemoteException; 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; /** @@ -271,7 +275,7 @@ public final class BluetoothA2dp implements BluetoothProfile { IBluetoothA2dp.class.getName()) { @Override public IBluetoothA2dp getServiceInterface(IBinder service) { - return IBluetoothA2dp.Stub.asInterface(Binder.allowBlocking(service)); + return IBluetoothA2dp.Stub.asInterface(service); } }; @@ -322,17 +326,21 @@ public final class BluetoothA2dp implements BluetoothProfile { @UnsupportedAppUsage public boolean connect(BluetoothDevice device) { if (DBG) log("connect(" + device + ")"); - try { - final IBluetoothA2dp service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { - return service.connect(device); + final IBluetoothA2dp service = getService(); + 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() && isValidDevice(device)) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.connectWithAttribution(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; } + return defaultValue; } /** @@ -364,17 +372,21 @@ public final class BluetoothA2dp implements BluetoothProfile { @UnsupportedAppUsage public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); - try { - final IBluetoothA2dp service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { - return service.disconnect(device); + final IBluetoothA2dp service = getService(); + 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() && isValidDevice(device)) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.disconnectWithAttribution(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; } + return defaultValue; } /** @@ -385,19 +397,24 @@ public final class BluetoothA2dp implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public List getConnectedDevices() { if (VDBG) log("getConnectedDevices()"); - try { - final IBluetoothA2dp service = getService(); - if (service != null && isEnabled()) { + final IBluetoothA2dp service = getService(); + final List defaultValue = new ArrayList(); + 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.getConnectedDevicesWithAttribution(mAttributionSource, recv); return Attributable.setAttributionSource( - service.getConnectedDevicesWithAttribution(mAttributionSource), + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), mAttributionSource); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList(); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return new ArrayList(); } + return defaultValue; } /** @@ -408,20 +425,25 @@ public final class BluetoothA2dp implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public List getDevicesMatchingConnectionStates(int[] states) { if (VDBG) log("getDevicesMatchingStates()"); - try { - final IBluetoothA2dp service = getService(); - if (service != null && isEnabled()) { + final IBluetoothA2dp service = getService(); + final List defaultValue = new ArrayList(); + 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.getDevicesMatchingConnectionStatesWithAttribution(states, + mAttributionSource, recv); return Attributable.setAttributionSource( - service.getDevicesMatchingConnectionStatesWithAttribution(states, - mAttributionSource), + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), mAttributionSource); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList(); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return new ArrayList(); } + return defaultValue; } /** @@ -432,18 +454,21 @@ public final class BluetoothA2dp implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public @BtProfileState int getConnectionState(BluetoothDevice device) { if (VDBG) log("getState(" + device + ")"); - try { - final IBluetoothA2dp service = getService(); - if (service != null && isEnabled() - && isValidDevice(device)) { - return service.getConnectionState(device); + final IBluetoothA2dp service = getService(); + final int defaultValue = BluetoothProfile.STATE_DISCONNECTED; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getConnectionStateWithAttribution(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return BluetoothProfile.STATE_DISCONNECTED; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return BluetoothProfile.STATE_DISCONNECTED; } + return defaultValue; } /** @@ -471,18 +496,21 @@ public final class BluetoothA2dp implements BluetoothProfile { @UnsupportedAppUsage(trackingBug = 171933273) public boolean setActiveDevice(@Nullable BluetoothDevice device) { if (DBG) log("setActiveDevice(" + device + ")"); - try { - final IBluetoothA2dp service = getService(); - if (service != null && isEnabled() - && ((device == null) || isValidDevice(device))) { - return service.setActiveDevice(device, mAttributionSource); + final IBluetoothA2dp service = getService(); + 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() && ((device == null) || isValidDevice(device))) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.setActiveDevice(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; } + return defaultValue; } /** @@ -499,18 +527,24 @@ public final class BluetoothA2dp implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public BluetoothDevice getActiveDevice() { if (VDBG) log("getActiveDevice()"); - try { - final IBluetoothA2dp service = getService(); - if (service != null && isEnabled()) { + final IBluetoothA2dp service = getService(); + final BluetoothDevice defaultValue = null; + 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.getActiveDevice(mAttributionSource, recv); return Attributable.setAttributionSource( - service.getActiveDevice(mAttributionSource), mAttributionSource); + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), + mAttributionSource); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return null; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return null; } + return defaultValue; } /** @@ -555,22 +589,23 @@ public final class BluetoothA2dp implements BluetoothProfile { public boolean setConnectionPolicy(@NonNull BluetoothDevice device, @ConnectionPolicy int connectionPolicy) { if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")"); - try { - final IBluetoothA2dp service = getService(); - if (service != null && isEnabled() - && isValidDevice(device)) { - if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN - && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) { - return false; - } - return service.setConnectionPolicy(device, connectionPolicy, mAttributionSource); + final IBluetoothA2dp service = getService(); + 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() && isValidDevice(device) + && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN + || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; } + return defaultValue; } /** @@ -589,19 +624,7 @@ public final class BluetoothA2dp implements BluetoothProfile { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) public int getPriority(BluetoothDevice device) { if (VDBG) log("getPriority(" + device + ")"); - try { - final IBluetoothA2dp service = getService(); - if (service != null && isEnabled() - && isValidDevice(device)) { - return BluetoothAdapter.connectionPolicyToPriority( - service.getPriority(device, mAttributionSource)); - } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return BluetoothProfile.PRIORITY_OFF; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return BluetoothProfile.PRIORITY_OFF; - } + return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device)); } /** @@ -623,18 +646,21 @@ public final class BluetoothA2dp implements BluetoothProfile { }) public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) { if (VDBG) log("getConnectionPolicy(" + device + ")"); - try { - final IBluetoothA2dp service = getService(); - if (service != null && isEnabled() - && isValidDevice(device)) { - return service.getConnectionPolicy(device, mAttributionSource); + final IBluetoothA2dp service = getService(); + final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getConnectionPolicy(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; } + return defaultValue; } /** @@ -646,17 +672,21 @@ public final class BluetoothA2dp implements BluetoothProfile { @RequiresNoPermission public boolean isAvrcpAbsoluteVolumeSupported() { if (DBG) Log.d(TAG, "isAvrcpAbsoluteVolumeSupported"); - try { - final IBluetoothA2dp service = getService(); - if (service != null && isEnabled()) { - return service.isAvrcpAbsoluteVolumeSupported(); + final IBluetoothA2dp service = getService(); + 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 recv = new SynchronousResultReceiver(); + service.isAvrcpAbsoluteVolumeSupported(recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; - } catch (RemoteException e) { - Log.e(TAG, "Error talking to BT service in isAvrcpAbsoluteVolumeSupported()", e); - return false; } + return defaultValue; } /** @@ -669,14 +699,16 @@ public final class BluetoothA2dp implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void setAvrcpAbsoluteVolume(int volume) { if (DBG) Log.d(TAG, "setAvrcpAbsoluteVolume"); - try { - final IBluetoothA2dp service = getService(); - if (service != null && isEnabled()) { + final IBluetoothA2dp service = getService(); + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled()) { + try { service.setAvrcpAbsoluteVolume(volume, mAttributionSource); + } catch (RemoteException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - } catch (RemoteException e) { - Log.e(TAG, "Error talking to BT service in setAvrcpAbsoluteVolume()", e); } } @@ -689,18 +721,22 @@ public final class BluetoothA2dp implements BluetoothProfile { @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean isA2dpPlaying(BluetoothDevice device) { - try { - final IBluetoothA2dp service = getService(); - if (service != null && isEnabled() - && isValidDevice(device)) { - return service.isA2dpPlaying(device, mAttributionSource); + if (DBG) log("isA2dpPlaying(" + device + ")"); + final IBluetoothA2dp service = getService(); + 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() && isValidDevice(device)) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.isA2dpPlaying(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; } + return defaultValue; } /** @@ -729,8 +765,7 @@ public final class BluetoothA2dp implements BluetoothProfile { /** * Gets the current codec status (configuration and capability). * - * @param device the remote Bluetooth device. If null, use the current - * active A2DP Bluetooth device. + * @param device the remote Bluetooth device. * @return the current codec status * @hide */ @@ -742,26 +777,28 @@ public final class BluetoothA2dp implements BluetoothProfile { public BluetoothCodecStatus getCodecStatus(@NonNull BluetoothDevice device) { if (DBG) Log.d(TAG, "getCodecStatus(" + device + ")"); verifyDeviceNotNull(device, "getCodecStatus"); - try { - final IBluetoothA2dp service = getService(); - if (service != null && isEnabled()) { - return service.getCodecStatus(device, mAttributionSource); - } - if (service == null) { - Log.w(TAG, "Proxy not attached to service"); + final IBluetoothA2dp service = getService(); + final BluetoothCodecStatus defaultValue = null; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { + try { + final SynchronousResultReceiver recv = + new SynchronousResultReceiver(); + service.getCodecStatus(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - return null; - } catch (RemoteException e) { - Log.e(TAG, "Error talking to BT service in getCodecStatus()", e); - return null; } + return defaultValue; } /** * Sets the codec configuration preference. * - * @param device the remote Bluetooth device. If null, use the current - * active A2DP Bluetooth device. + * @param device the remote Bluetooth device. * @param codecConfig the codec configuration preference * @hide */ @@ -777,24 +814,23 @@ public final class BluetoothA2dp implements BluetoothProfile { Log.e(TAG, "setCodecConfigPreference: Codec config can't be null"); throw new IllegalArgumentException("codecConfig cannot be null"); } - try { - final IBluetoothA2dp service = getService(); - if (service != null && isEnabled()) { + final IBluetoothA2dp service = getService(); + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled()) { + try { service.setCodecConfigPreference(device, codecConfig, mAttributionSource); + } catch (RemoteException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return; - } catch (RemoteException e) { - Log.e(TAG, "Error talking to BT service in setCodecConfigPreference()", e); - return; } } /** * Enables the optional codecs. * - * @param device the remote Bluetooth device. If null, use the currect - * active A2DP Bluetooth device. + * @param device the remote Bluetooth device. * @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) @@ -810,8 +846,7 @@ public final class BluetoothA2dp implements BluetoothProfile { /** * Disables the optional codecs. * - * @param device the remote Bluetooth device. If null, use the currect - * active A2DP Bluetooth device. + * @param device the remote Bluetooth device. * @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) @@ -827,26 +862,25 @@ public final class BluetoothA2dp implements BluetoothProfile { /** * Enables or disables the optional codecs. * - * @param device the remote Bluetooth device. If null, use the currect - * active A2DP Bluetooth device. + * @param device the remote Bluetooth device. * @param enable if true, enable the optional codecs, other disable them */ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) private void enableDisableOptionalCodecs(BluetoothDevice device, boolean enable) { - try { - final IBluetoothA2dp service = getService(); - if (service != null && isEnabled()) { + final IBluetoothA2dp service = getService(); + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { + try { if (enable) { service.enableOptionalCodecs(device, mAttributionSource); } else { service.disableOptionalCodecs(device, mAttributionSource); } + } catch (RemoteException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return; - } catch (RemoteException e) { - Log.e(TAG, "Error talking to BT service in enableDisableOptionalCodecs()", e); - return; } } @@ -864,18 +898,23 @@ public final class BluetoothA2dp implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) @OptionalCodecsSupportStatus public int isOptionalCodecsSupported(@NonNull BluetoothDevice device) { + if (DBG) log("isOptionalCodecsSupported(" + device + ")"); verifyDeviceNotNull(device, "isOptionalCodecsSupported"); - try { - final IBluetoothA2dp service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { - return service.supportsOptionalCodecs(device, mAttributionSource); + final IBluetoothA2dp service = getService(); + final int defaultValue = OPTIONAL_CODECS_SUPPORT_UNKNOWN; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.supportsOptionalCodecs(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return OPTIONAL_CODECS_SUPPORT_UNKNOWN; - } catch (RemoteException e) { - Log.e(TAG, "Error talking to BT service in supportsOptionalCodecs()", e); - return OPTIONAL_CODECS_SUPPORT_UNKNOWN; } + return defaultValue; } /** @@ -892,18 +931,23 @@ public final class BluetoothA2dp implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) @OptionalCodecsPreferenceStatus public int isOptionalCodecsEnabled(@NonNull BluetoothDevice device) { + if (DBG) log("isOptionalCodecsEnabled(" + device + ")"); verifyDeviceNotNull(device, "isOptionalCodecsEnabled"); - try { - final IBluetoothA2dp service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { - return service.getOptionalCodecsEnabled(device, mAttributionSource); + final IBluetoothA2dp service = getService(); + final int defaultValue = OPTIONAL_CODECS_PREF_UNKNOWN; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getOptionalCodecsEnabled(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return OPTIONAL_CODECS_PREF_UNKNOWN; - } catch (RemoteException e) { - Log.e(TAG, "Error talking to BT service in getOptionalCodecsEnabled()", e); - return OPTIONAL_CODECS_PREF_UNKNOWN; } + return defaultValue; } /** @@ -921,24 +965,24 @@ public final class BluetoothA2dp implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void setOptionalCodecsEnabled(@NonNull BluetoothDevice device, @OptionalCodecsPreferenceStatus int value) { + if (DBG) log("setOptionalCodecsEnabled(" + device + ")"); verifyDeviceNotNull(device, "setOptionalCodecsEnabled"); - try { - if (value != BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN - && value != BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED - && value != BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED) { - Log.e(TAG, "Invalid value passed to setOptionalCodecsEnabled: " + value); - return; - } - final IBluetoothA2dp service = getService(); - if (service != null && isEnabled() - && isValidDevice(device)) { + if (value != BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN + && value != BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED + && value != BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED) { + Log.e(TAG, "Invalid value passed to setOptionalCodecsEnabled: " + value); + return; + } + final IBluetoothA2dp service = getService(); + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { + try { service.setOptionalCodecsEnabled(device, value, mAttributionSource); + } catch (RemoteException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return; } } @@ -961,17 +1005,21 @@ public final class BluetoothA2dp implements BluetoothProfile { }) public @Type int getDynamicBufferSupport() { if (VDBG) log("getDynamicBufferSupport()"); - try { - final IBluetoothA2dp service = getService(); - if (service != null && isEnabled()) { - return service.getDynamicBufferSupport(mAttributionSource); + final IBluetoothA2dp service = getService(); + final int defaultValue = DYNAMIC_BUFFER_SUPPORT_NONE; + 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.getDynamicBufferSupport(mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return DYNAMIC_BUFFER_SUPPORT_NONE; - } catch (RemoteException e) { - Log.e(TAG, "failed to get getDynamicBufferSupport, error: ", e); - return DYNAMIC_BUFFER_SUPPORT_NONE; } + return defaultValue; } /** @@ -992,17 +1040,22 @@ public final class BluetoothA2dp implements BluetoothProfile { }) public @Nullable BufferConstraints getBufferConstraints() { if (VDBG) log("getBufferConstraints()"); - try { - final IBluetoothA2dp service = getService(); - if (service != null && isEnabled()) { - return service.getBufferConstraints(mAttributionSource); + final IBluetoothA2dp service = getService(); + final BufferConstraints defaultValue = null; + 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.getBufferConstraints(mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return null; - } catch (RemoteException e) { - Log.e(TAG, "", e); - return null; } + return defaultValue; } /** @@ -1027,17 +1080,21 @@ public final class BluetoothA2dp implements BluetoothProfile { Log.e(TAG, "Trying to set audio buffer length to a negative value: " + value); return false; } - try { - final IBluetoothA2dp service = getService(); - if (service != null && isEnabled()) { - return service.setBufferLengthMillis(codec, value, mAttributionSource); + final IBluetoothA2dp service = getService(); + 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 recv = new SynchronousResultReceiver(); + service.setBufferLengthMillis(codec, value, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; - } catch (RemoteException e) { - Log.e(TAG, "", e); - return false; } + return defaultValue; } /** diff --git a/core/java/android/bluetooth/BluetoothA2dpSink.java b/core/java/android/bluetooth/BluetoothA2dpSink.java index 924dc55f31a0214771ac931f1a040ac13c2c807b..59416818ceb3b295c5a934fb74e9b8dc8969af81 100755 --- a/core/java/android/bluetooth/BluetoothA2dpSink.java +++ b/core/java/android/bluetooth/BluetoothA2dpSink.java @@ -16,6 +16,8 @@ package android.bluetooth; +import static android.bluetooth.BluetoothUtils.getSyncTimeout; + import android.Manifest; import android.annotation.NonNull; import android.annotation.RequiresPermission; @@ -29,14 +31,16 @@ import android.bluetooth.annotations.RequiresLegacyBluetoothPermission; import android.compat.annotation.UnsupportedAppUsage; import android.content.AttributionSource; import android.content.Context; -import android.os.Binder; import android.os.Build; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; +import com.android.modules.utils.SynchronousResultReceiver; + import java.util.ArrayList; import java.util.List; +import java.util.concurrent.TimeoutException; /** * This class provides the public APIs to control the Bluetooth A2DP Sink @@ -86,7 +90,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile { "BluetoothA2dpSink", IBluetoothA2dpSink.class.getName()) { @Override public IBluetoothA2dpSink getServiceInterface(IBinder service) { - return IBluetoothA2dpSink.Stub.asInterface(Binder.allowBlocking(service)); + return IBluetoothA2dpSink.Stub.asInterface(service); } }; @@ -140,16 +144,20 @@ public final class BluetoothA2dpSink implements BluetoothProfile { public boolean connect(BluetoothDevice device) { if (DBG) log("connect(" + device + ")"); final IBluetoothA2dpSink service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + 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() && isValidDevice(device)) { try { - return service.connect(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.connect(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -181,16 +189,20 @@ public final class BluetoothA2dpSink implements BluetoothProfile { public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); final IBluetoothA2dpSink service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + 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() && isValidDevice(device)) { try { - return service.disconnect(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.disconnect(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -204,17 +216,23 @@ public final class BluetoothA2dpSink implements BluetoothProfile { public List getConnectedDevices() { if (VDBG) log("getConnectedDevices()"); final IBluetoothA2dpSink service = getService(); - if (service != null && isEnabled()) { + final List defaultValue = new ArrayList(); + 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.getConnectedDevices(mAttributionSource, recv); return Attributable.setAttributionSource( - service.getConnectedDevices(mAttributionSource), mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return new ArrayList(); + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), + mAttributionSource); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList(); + return defaultValue; } /** @@ -228,18 +246,23 @@ public final class BluetoothA2dpSink implements BluetoothProfile { public List getDevicesMatchingConnectionStates(int[] states) { if (VDBG) log("getDevicesMatchingStates()"); final IBluetoothA2dpSink service = getService(); - if (service != null && isEnabled()) { + final List defaultValue = new ArrayList(); + 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.getDevicesMatchingConnectionStates(states, mAttributionSource, recv); return Attributable.setAttributionSource( - service.getDevicesMatchingConnectionStates(states, mAttributionSource), + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return new ArrayList(); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList(); + return defaultValue; } /** @@ -251,18 +274,22 @@ public final class BluetoothA2dpSink implements BluetoothProfile { @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(BluetoothDevice device) { - if (VDBG) log("getState(" + device + ")"); + if (VDBG) log("getConnectionState(" + device + ")"); final IBluetoothA2dpSink service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final int defaultValue = BluetoothProfile.STATE_DISCONNECTED; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { try { - return service.getConnectionState(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return BluetoothProfile.STATE_DISCONNECTED; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getConnectionState(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return BluetoothProfile.STATE_DISCONNECTED; + return defaultValue; } /** @@ -282,16 +309,21 @@ public final class BluetoothA2dpSink implements BluetoothProfile { public BluetoothAudioConfig getAudioConfig(BluetoothDevice device) { if (VDBG) log("getAudioConfig(" + device + ")"); final IBluetoothA2dpSink service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final BluetoothAudioConfig defaultValue = null; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { try { - return service.getAudioConfig(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return null; + final SynchronousResultReceiver recv = + new SynchronousResultReceiver(); + service.getAudioConfig(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return null; + return defaultValue; } /** @@ -337,20 +369,22 @@ public final class BluetoothA2dpSink implements BluetoothProfile { @ConnectionPolicy int connectionPolicy) { if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")"); final IBluetoothA2dpSink service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { - if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN - && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) { - return false; - } + 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() && isValidDevice(device) + && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN + || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) { try { - return service.setConnectionPolicy(device, connectionPolicy, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -393,16 +427,20 @@ public final class BluetoothA2dpSink implements BluetoothProfile { public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) { if (VDBG) log("getConnectionPolicy(" + device + ")"); final IBluetoothA2dpSink service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { try { - return service.getConnectionPolicy(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getConnectionPolicy(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; + return defaultValue; } /** @@ -420,17 +458,22 @@ public final class BluetoothA2dpSink implements BluetoothProfile { android.Manifest.permission.BLUETOOTH_PRIVILEGED, }) public boolean isAudioPlaying(@NonNull BluetoothDevice device) { + if (VDBG) log("isAudioPlaying(" + device + ")"); final IBluetoothA2dpSink service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + 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() && isValidDevice(device)) { try { - return service.isA2dpPlaying(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.isA2dpPlaying(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** diff --git a/core/java/android/bluetooth/BluetoothAvrcpController.java b/core/java/android/bluetooth/BluetoothAvrcpController.java index 536dfb0a66ddfda53e456ae33d93226d110b6221..81fc3e11e9e123c985cc2eefcfe13baf0b414d9c 100644 --- a/core/java/android/bluetooth/BluetoothAvrcpController.java +++ b/core/java/android/bluetooth/BluetoothAvrcpController.java @@ -16,6 +16,8 @@ package android.bluetooth; +import static android.bluetooth.BluetoothUtils.getSyncTimeout; + import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; @@ -23,13 +25,15 @@ import android.bluetooth.annotations.RequiresBluetoothConnectPermission; import android.bluetooth.annotations.RequiresLegacyBluetoothPermission; import android.content.AttributionSource; import android.content.Context; -import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; +import com.android.modules.utils.SynchronousResultReceiver; + import java.util.ArrayList; import java.util.List; +import java.util.concurrent.TimeoutException; /** * This class provides the public APIs to control the Bluetooth AVRCP Controller. It currently @@ -93,8 +97,7 @@ public final class BluetoothAvrcpController implements BluetoothProfile { "BluetoothAvrcpController", IBluetoothAvrcpController.class.getName()) { @Override public IBluetoothAvrcpController getServiceInterface(IBinder service) { - return IBluetoothAvrcpController.Stub.asInterface( - Binder.allowBlocking(service)); + return IBluetoothAvrcpController.Stub.asInterface(service); } }; @@ -130,19 +133,24 @@ public final class BluetoothAvrcpController implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public List getConnectedDevices() { if (VDBG) log("getConnectedDevices()"); - final IBluetoothAvrcpController service = - getService(); - if (service != null && isEnabled()) { + final IBluetoothAvrcpController service = getService(); + final List defaultValue = new ArrayList(); + 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.getConnectedDevices(mAttributionSource, recv); return Attributable.setAttributionSource( - service.getConnectedDevices(mAttributionSource), mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return new ArrayList(); + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), + mAttributionSource); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList(); + return defaultValue; } /** @@ -153,20 +161,24 @@ public final class BluetoothAvrcpController implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public List getDevicesMatchingConnectionStates(int[] states) { if (VDBG) log("getDevicesMatchingStates()"); - final IBluetoothAvrcpController service = - getService(); - if (service != null && isEnabled()) { + final IBluetoothAvrcpController service = getService(); + final List defaultValue = new ArrayList(); + 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.getDevicesMatchingConnectionStates(states, mAttributionSource, recv); return Attributable.setAttributionSource( - service.getDevicesMatchingConnectionStates(states, mAttributionSource), + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return new ArrayList(); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList(); + return defaultValue; } /** @@ -177,18 +189,21 @@ public final class BluetoothAvrcpController implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(BluetoothDevice device) { if (VDBG) log("getState(" + device + ")"); - final IBluetoothAvrcpController service = - getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final IBluetoothAvrcpController service = getService(); + final int defaultValue = BluetoothProfile.STATE_DISCONNECTED; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { try { - return service.getConnectionState(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return BluetoothProfile.STATE_DISCONNECTED; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getConnectionState(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return BluetoothProfile.STATE_DISCONNECTED; + return defaultValue; } /** @@ -201,17 +216,22 @@ public final class BluetoothAvrcpController implements BluetoothProfile { public BluetoothAvrcpPlayerSettings getPlayerSettings(BluetoothDevice device) { if (DBG) Log.d(TAG, "getPlayerSettings"); BluetoothAvrcpPlayerSettings settings = null; - final IBluetoothAvrcpController service = - getService(); - if (service != null && isEnabled()) { + final IBluetoothAvrcpController service = getService(); + final BluetoothAvrcpPlayerSettings defaultValue = null; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled()) { try { - settings = service.getPlayerSettings(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Error talking to BT service in getMetadata() " + e); - return null; + final SynchronousResultReceiver recv = + new SynchronousResultReceiver(); + service.getPlayerSettings(device, mAttributionSource, recv); + settings = recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - return settings; + return defaultValue; } /** @@ -222,18 +242,21 @@ public final class BluetoothAvrcpController implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean setPlayerApplicationSetting(BluetoothAvrcpPlayerSettings plAppSetting) { if (DBG) Log.d(TAG, "setPlayerApplicationSetting"); - final IBluetoothAvrcpController service = - getService(); - if (service != null && isEnabled()) { + final IBluetoothAvrcpController service = getService(); + 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 { - return service.setPlayerApplicationSetting(plAppSetting, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Error talking to BT service in setPlayerApplicationSetting() " + e); - return false; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.setPlayerApplicationSetting(plAppSetting, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -245,18 +268,20 @@ public final class BluetoothAvrcpController implements BluetoothProfile { public void sendGroupNavigationCmd(BluetoothDevice device, int keyCode, int keyState) { Log.d(TAG, "sendGroupNavigationCmd dev = " + device + " key " + keyCode + " State = " + keyState); - final IBluetoothAvrcpController service = - getService(); - if (service != null && isEnabled()) { + final IBluetoothAvrcpController service = getService(); + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled()) { try { - service.sendGroupNavigationCmd(device, keyCode, keyState, mAttributionSource); - return; - } catch (RemoteException e) { - Log.e(TAG, "Error talking to BT service in sendGroupNavigationCmd()", e); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.sendGroupNavigationCmd(device, keyCode, keyState, mAttributionSource, recv); + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null); return; + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); } private boolean isEnabled() { diff --git a/core/java/android/bluetooth/BluetoothCsipSetCoordinator.java b/core/java/android/bluetooth/BluetoothCsipSetCoordinator.java index f0a8df0fa72f016a9b7c9fed2c7336c4ccc85205..ba57ec472a6e58398c66f994742ef2ccc12dc0a3 100644 --- a/core/java/android/bluetooth/BluetoothCsipSetCoordinator.java +++ b/core/java/android/bluetooth/BluetoothCsipSetCoordinator.java @@ -17,6 +17,8 @@ package android.bluetooth; +import static android.bluetooth.BluetoothUtils.getSyncTimeout; + import android.Manifest; import android.annotation.CallbackExecutor; import android.annotation.NonNull; @@ -27,13 +29,14 @@ import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemApi; import android.content.AttributionSource; import android.content.Context; -import android.os.Binder; import android.os.IBinder; import android.os.ParcelUuid; import android.os.RemoteException; import android.util.CloseGuard; import android.util.Log; +import com.android.modules.utils.SynchronousResultReceiver; + import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -41,6 +44,7 @@ import java.util.List; import java.util.Map; import java.util.UUID; import java.util.concurrent.Executor; +import java.util.concurrent.TimeoutException; /** * This class provides the public APIs to control the Bluetooth CSIP set coordinator. @@ -229,8 +233,7 @@ public final class BluetoothCsipSetCoordinator implements BluetoothProfile, Auto IBluetoothCsipSetCoordinator.class.getName()) { @Override public IBluetoothCsipSetCoordinator getServiceInterface(IBinder service) { - return IBluetoothCsipSetCoordinator.Stub.asInterface( - Binder.allowBlocking(service)); + return IBluetoothCsipSetCoordinator.Stub.asInterface(service); } }; @@ -283,26 +286,27 @@ public final class BluetoothCsipSetCoordinator implements BluetoothProfile, Auto public @Nullable UUID groupLock(int groupId, @Nullable @CallbackExecutor Executor executor, @Nullable ClientLockCallback cb) { - if (VDBG) { - log("groupLockSet()"); - } + if (VDBG) log("groupLockSet()"); final IBluetoothCsipSetCoordinator service = getService(); - try { - if (service != null && isEnabled()) { - IBluetoothCsipSetCoordinatorLockCallback delegate = null; - if ((executor != null) && (cb != null)) { - delegate = new BluetoothCsipSetCoordinatorLockCallbackDelegate(executor, cb); - } - return service.groupLock(groupId, delegate, mAttributionSource).getUuid(); + final UUID defaultValue = null; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled()) { + IBluetoothCsipSetCoordinatorLockCallback delegate = null; + if ((executor != null) && (cb != null)) { + delegate = new BluetoothCsipSetCoordinatorLockCallbackDelegate(executor, cb); } - if (service == null) { - Log.w(TAG, "Proxy not attached to service"); + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.groupLock(groupId, delegate, mAttributionSource, recv); + final ParcelUuid ret = recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null); + return ret == null ? defaultValue : ret.getUuid(); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - return null; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return null; } + return defaultValue; } /** @@ -315,27 +319,26 @@ public final class BluetoothCsipSetCoordinator implements BluetoothProfile, Auto @SystemApi @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean groupUnlock(@NonNull UUID lockUuid) { - if (VDBG) { - log("groupLockSet()"); - } + if (VDBG) log("groupLockSet()"); if (lockUuid == null) { return false; } - final IBluetoothCsipSetCoordinator service = getService(); - try { - if (service != null && isEnabled()) { - service.groupUnlock(new ParcelUuid(lockUuid), mAttributionSource); + 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 recv = new SynchronousResultReceiver(); + service.groupUnlock(new ParcelUuid(lockUuid), mAttributionSource, recv); + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null); return true; + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) { - Log.w(TAG, "Proxy not attached to service"); - } - return false; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; } + return defaultValue; } /** @@ -348,22 +351,22 @@ public final class BluetoothCsipSetCoordinator implements BluetoothProfile, Auto @SystemApi @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) public @NonNull Map getGroupUuidMapByDevice(@Nullable BluetoothDevice device) { - if (VDBG) { - log("getGroupUuidMapByDevice()"); - } + if (VDBG) log("getGroupUuidMapByDevice()"); final IBluetoothCsipSetCoordinator service = getService(); - try { - if (service != null && isEnabled()) { - return service.getGroupUuidMapByDevice(device, mAttributionSource); - } - if (service == null) { - Log.w(TAG, "Proxy not attached to service"); + final Map defaultValue = new HashMap<>(); + 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.getGroupUuidMapByDevice(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - return new HashMap<>(); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return new HashMap<>(); } + return defaultValue; } /** @@ -376,22 +379,23 @@ public final class BluetoothCsipSetCoordinator implements BluetoothProfile, Auto @SystemApi @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) public @NonNull List getAllGroupIds(@Nullable ParcelUuid uuid) { - if (VDBG) { - log("getAllGroupIds()"); - } + if (VDBG) log("getAllGroupIds()"); final IBluetoothCsipSetCoordinator service = getService(); - try { - if (service != null && isEnabled()) { - return service.getAllGroupIds(uuid, mAttributionSource); - } - if (service == null) { - Log.w(TAG, "Proxy not attached to service"); + final List defaultValue = new ArrayList<>(); + 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.getAllGroupIds(uuid, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - return new ArrayList(); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return new ArrayList(); } + return defaultValue; } /** @@ -399,22 +403,23 @@ public final class BluetoothCsipSetCoordinator implements BluetoothProfile, Auto */ @Override public @NonNull List getConnectedDevices() { - if (VDBG) { - log("getConnectedDevices()"); - } + if (VDBG) log("getConnectedDevices()"); final IBluetoothCsipSetCoordinator service = getService(); - if (service != null && isEnabled()) { - try { - return service.getConnectedDevices(mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return new ArrayList(); - } - } + final List defaultValue = new ArrayList<>(); 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.getConnectedDevices(mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } } - return new ArrayList(); + return defaultValue; } /** @@ -422,24 +427,24 @@ public final class BluetoothCsipSetCoordinator implements BluetoothProfile, Auto */ @Override public - @NonNull List getDevicesMatchingConnectionStates( - @NonNull int[] states) { - if (VDBG) { - log("getDevicesMatchingStates(states=" + Arrays.toString(states) + ")"); - } + @NonNull List getDevicesMatchingConnectionStates(@NonNull int[] states) { + if (VDBG) log("getDevicesMatchingStates(states=" + Arrays.toString(states) + ")"); final IBluetoothCsipSetCoordinator service = getService(); - if (service != null && isEnabled()) { - try { - return service.getDevicesMatchingConnectionStates(states, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return new ArrayList(); - } - } + final List defaultValue = new ArrayList<>(); 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.getDevicesMatchingConnectionStates(states, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } } - return new ArrayList(); + return defaultValue; } /** @@ -447,24 +452,23 @@ public final class BluetoothCsipSetCoordinator implements BluetoothProfile, Auto */ @Override public - @BluetoothProfile.BtProfileState int getConnectionState( - @Nullable BluetoothDevice device) { - if (VDBG) { - log("getState(" + device + ")"); - } + @BluetoothProfile.BtProfileState int getConnectionState(@Nullable BluetoothDevice device) { + if (VDBG) log("getState(" + device + ")"); final IBluetoothCsipSetCoordinator service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { - try { - return service.getConnectionState(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return BluetoothProfile.STATE_DISCONNECTED; - } - } + final int defaultValue = BluetoothProfile.STATE_DISCONNECTED; 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.getConnectionState(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } } - return BluetoothProfile.STATE_DISCONNECTED; + return defaultValue; } /** @@ -484,26 +488,24 @@ public final class BluetoothCsipSetCoordinator implements BluetoothProfile, Auto @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setConnectionPolicy( @Nullable BluetoothDevice device, @ConnectionPolicy int connectionPolicy) { - if (DBG) { - log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")"); - } + if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")"); final IBluetoothCsipSetCoordinator service = getService(); - try { - if (service != null && isEnabled() && isValidDevice(device)) { - if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN - && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) { - return false; - } - return service.setConnectionPolicy(device, connectionPolicy, mAttributionSource); - } - if (service == null) { - Log.w(TAG, "Proxy not attached to service"); + 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() && isValidDevice(device) + && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN + || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - return false; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; } + return defaultValue; } /** @@ -521,22 +523,22 @@ public final class BluetoothCsipSetCoordinator implements BluetoothProfile, Auto @SystemApi @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) public @ConnectionPolicy int getConnectionPolicy(@Nullable BluetoothDevice device) { - if (VDBG) { - log("getConnectionPolicy(" + device + ")"); - } + if (VDBG) log("getConnectionPolicy(" + device + ")"); final IBluetoothCsipSetCoordinator service = getService(); - try { - if (service != null && isEnabled() && isValidDevice(device)) { - return service.getConnectionPolicy(device, mAttributionSource); - } - if (service == null) { - Log.w(TAG, "Proxy not attached to service"); + final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getConnectionPolicy(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; } + return defaultValue; } private boolean isEnabled() { diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java index 17c02cdbf8d581df2d4e4e1c696e5eea3c2357f6..f2a6276ce8fe1ace205f5273ae948df5ce675f41 100644 --- a/core/java/android/bluetooth/BluetoothHeadset.java +++ b/core/java/android/bluetooth/BluetoothHeadset.java @@ -16,6 +16,8 @@ package android.bluetooth; +import static android.bluetooth.BluetoothUtils.getSyncTimeout; + import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; @@ -31,7 +33,6 @@ import android.content.AttributionSource; import android.content.ComponentName; import android.content.Context; import android.content.pm.PackageManager; -import android.os.Binder; import android.os.Build; import android.os.Handler; import android.os.IBinder; @@ -41,8 +42,11 @@ import android.os.RemoteException; import android.util.CloseGuard; import android.util.Log; +import com.android.modules.utils.SynchronousResultReceiver; + import java.util.ArrayList; import java.util.List; +import java.util.concurrent.TimeoutException; /** * Public API for controlling the Bluetooth Headset Service. This includes both @@ -479,16 +483,20 @@ public final class BluetoothHeadset implements BluetoothProfile { public boolean connect(BluetoothDevice device) { if (DBG) log("connect(" + device + ")"); final IBluetoothHeadset service = mService; - if (service != null && isEnabled() && isValidDevice(device)) { + 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() && isValidDevice(device)) { try { - return service.connect(device); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return false; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.connectWithAttribution(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -520,16 +528,20 @@ public final class BluetoothHeadset implements BluetoothProfile { public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); final IBluetoothHeadset service = mService; - if (service != null && isEnabled() && isValidDevice(device)) { + 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() && isValidDevice(device)) { try { - return service.disconnect(device); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return false; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.disconnectWithAttribution(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -541,18 +553,23 @@ public final class BluetoothHeadset implements BluetoothProfile { public List getConnectedDevices() { if (VDBG) log("getConnectedDevices()"); final IBluetoothHeadset service = mService; - if (service != null && isEnabled()) { + final List defaultValue = new ArrayList(); + 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.getConnectedDevicesWithAttribution(mAttributionSource, recv); return Attributable.setAttributionSource( - service.getConnectedDevicesWithAttribution(mAttributionSource), + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return new ArrayList(); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList(); + return defaultValue; } /** @@ -564,18 +581,23 @@ public final class BluetoothHeadset implements BluetoothProfile { public List getDevicesMatchingConnectionStates(int[] states) { if (VDBG) log("getDevicesMatchingStates()"); final IBluetoothHeadset service = mService; - if (service != null && isEnabled()) { + final List defaultValue = new ArrayList(); + 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.getDevicesMatchingConnectionStates(states, mAttributionSource, recv); return Attributable.setAttributionSource( - service.getDevicesMatchingConnectionStates(states, mAttributionSource), + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return new ArrayList(); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList(); + return defaultValue; } /** @@ -587,16 +609,20 @@ public final class BluetoothHeadset implements BluetoothProfile { public int getConnectionState(BluetoothDevice device) { if (VDBG) log("getConnectionState(" + device + ")"); final IBluetoothHeadset service = mService; - if (service != null && isEnabled() && isValidDevice(device)) { + final int defaultValue = BluetoothProfile.STATE_DISCONNECTED; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { try { - return service.getConnectionState(device); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return BluetoothProfile.STATE_DISCONNECTED; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getConnectionStateWithAttribution(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return BluetoothProfile.STATE_DISCONNECTED; + return defaultValue; } /** @@ -622,20 +648,22 @@ public final class BluetoothHeadset implements BluetoothProfile { @ConnectionPolicy int connectionPolicy) { if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")"); final IBluetoothHeadset service = mService; - if (service != null && isEnabled() && isValidDevice(device)) { - if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN - && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) { - return false; - } + 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() && isValidDevice(device) + && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN + || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) { try { - return service.setConnectionPolicy(device, connectionPolicy, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return false; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -655,18 +683,7 @@ public final class BluetoothHeadset implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getPriority(BluetoothDevice device) { if (VDBG) log("getPriority(" + device + ")"); - final IBluetoothHeadset service = mService; - if (service != null && isEnabled() && isValidDevice(device)) { - try { - return BluetoothAdapter.connectionPolicyToPriority( - service.getPriority(device, mAttributionSource)); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return BluetoothProfile.PRIORITY_OFF; - } - } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return BluetoothProfile.PRIORITY_OFF; + return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device)); } /** @@ -689,16 +706,20 @@ public final class BluetoothHeadset implements BluetoothProfile { public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) { if (VDBG) log("getConnectionPolicy(" + device + ")"); final IBluetoothHeadset service = mService; - if (service != null && isEnabled() && isValidDevice(device)) { + final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { try { - return service.getConnectionPolicy(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getConnectionPolicy(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; + return defaultValue; } /** @@ -713,15 +734,20 @@ public final class BluetoothHeadset implements BluetoothProfile { public boolean isNoiseReductionSupported(@NonNull BluetoothDevice device) { if (DBG) log("isNoiseReductionSupported()"); final IBluetoothHeadset service = mService; - if (service != null && isEnabled() && isValidDevice(device)) { + 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() && isValidDevice(device)) { try { - return service.isNoiseReductionSupported(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.isNoiseReductionSupported(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -736,15 +762,20 @@ public final class BluetoothHeadset implements BluetoothProfile { public boolean isVoiceRecognitionSupported(@NonNull BluetoothDevice device) { if (DBG) log("isVoiceRecognitionSupported()"); final IBluetoothHeadset service = mService; - if (service != null && isEnabled() && isValidDevice(device)) { + 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() && isValidDevice(device)) { try { - return service.isVoiceRecognitionSupported(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.isVoiceRecognitionSupported(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -775,15 +806,20 @@ public final class BluetoothHeadset implements BluetoothProfile { public boolean startVoiceRecognition(BluetoothDevice device) { if (DBG) log("startVoiceRecognition()"); final IBluetoothHeadset service = mService; - if (service != null && isEnabled() && isValidDevice(device)) { + 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() && isValidDevice(device)) { try { - return service.startVoiceRecognition(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.startVoiceRecognition(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -804,15 +840,20 @@ public final class BluetoothHeadset implements BluetoothProfile { public boolean stopVoiceRecognition(BluetoothDevice device) { if (DBG) log("stopVoiceRecognition()"); final IBluetoothHeadset service = mService; - if (service != null && isEnabled() && isValidDevice(device)) { + 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() && isValidDevice(device)) { try { - return service.stopVoiceRecognition(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.stopVoiceRecognition(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -827,15 +868,20 @@ public final class BluetoothHeadset implements BluetoothProfile { public boolean isAudioConnected(BluetoothDevice device) { if (VDBG) log("isAudioConnected()"); final IBluetoothHeadset service = mService; - if (service != null && isEnabled() && isValidDevice(device)) { + 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() && isValidDevice(device)) { try { - return service.isAudioConnected(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.isAudioConnected(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -861,17 +907,20 @@ public final class BluetoothHeadset implements BluetoothProfile { public int getAudioState(BluetoothDevice device) { if (VDBG) log("getAudioState"); final IBluetoothHeadset service = mService; - if (service != null && !isDisabled()) { + final int defaultValue = BluetoothHeadset.STATE_AUDIO_DISCONNECTED; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (!isDisabled()) { try { - return service.getAudioState(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getAudioState(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - } else { - Log.w(TAG, "Proxy not attached to service"); - if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); } - return BluetoothHeadset.STATE_AUDIO_DISCONNECTED; + return defaultValue; } /** @@ -889,15 +938,17 @@ public final class BluetoothHeadset implements BluetoothProfile { public void setAudioRouteAllowed(boolean allowed) { if (VDBG) log("setAudioRouteAllowed"); final IBluetoothHeadset service = mService; - if (service != null && isEnabled()) { + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled()) { try { - service.setAudioRouteAllowed(allowed, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); + 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())); } - } else { - Log.w(TAG, "Proxy not attached to service"); - if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); } } @@ -912,17 +963,20 @@ public final class BluetoothHeadset implements BluetoothProfile { public boolean getAudioRouteAllowed() { if (VDBG) log("getAudioRouteAllowed"); final IBluetoothHeadset service = mService; - if (service != null && isEnabled()) { + 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 { - return service.getAudioRouteAllowed(mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); + final SynchronousResultReceiver 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())); } - } else { - Log.w(TAG, "Proxy not attached to service"); - if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); } - return false; + return defaultValue; } /** @@ -937,15 +991,17 @@ public final class BluetoothHeadset implements BluetoothProfile { public void setForceScoAudio(boolean forced) { if (VDBG) log("setForceScoAudio " + String.valueOf(forced)); final IBluetoothHeadset service = mService; - if (service != null && isEnabled()) { + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled()) { try { - service.setForceScoAudio(forced, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.setForceScoAudio(forced, mAttributionSource, recv); + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - } else { - Log.w(TAG, "Proxy not attached to service"); - if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); } } @@ -962,16 +1018,20 @@ public final class BluetoothHeadset implements BluetoothProfile { public boolean isAudioOn() { if (VDBG) log("isAudioOn()"); final IBluetoothHeadset service = mService; - if (service != null && isEnabled()) { + 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 { - return service.isAudioOn(mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.isAudioOn(mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; - + return defaultValue; } /** @@ -996,18 +1056,22 @@ public final class BluetoothHeadset implements BluetoothProfile { @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean connectAudio() { + if (VDBG) log("connectAudio()"); final IBluetoothHeadset service = mService; - if (service != null && isEnabled()) { + 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 { - return service.connectAudio(mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.connectAudio(mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - } else { - Log.w(TAG, "Proxy not attached to service"); - if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); } - return false; + return defaultValue; } /** @@ -1025,18 +1089,22 @@ public final class BluetoothHeadset implements BluetoothProfile { @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disconnectAudio() { + if (VDBG) log("disconnectAudio()"); final IBluetoothHeadset service = mService; - if (service != null && isEnabled()) { + 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 { - return service.disconnectAudio(mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.disconnectAudio(mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - } else { - Log.w(TAG, "Proxy not attached to service"); - if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); } - return false; + return defaultValue; } /** @@ -1070,17 +1138,20 @@ public final class BluetoothHeadset implements BluetoothProfile { public boolean startScoUsingVirtualVoiceCall() { if (DBG) log("startScoUsingVirtualVoiceCall()"); final IBluetoothHeadset service = mService; - if (service != null && isEnabled()) { + 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 { - return service.startScoUsingVirtualVoiceCall(mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.startScoUsingVirtualVoiceCall(mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - } else { - Log.w(TAG, "Proxy not attached to service"); - if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); } - return false; + return defaultValue; } /** @@ -1105,17 +1176,20 @@ public final class BluetoothHeadset implements BluetoothProfile { public boolean stopScoUsingVirtualVoiceCall() { if (DBG) log("stopScoUsingVirtualVoiceCall()"); final IBluetoothHeadset service = mService; - if (service != null && isEnabled()) { + 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 { - return service.stopScoUsingVirtualVoiceCall(mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.stopScoUsingVirtualVoiceCall(mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - } else { - Log.w(TAG, "Proxy not attached to service"); - if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); } - return false; + return defaultValue; } /** @@ -1135,16 +1209,16 @@ public final class BluetoothHeadset implements BluetoothProfile { public void phoneStateChanged(int numActive, int numHeld, int callState, String number, int type, String name) { final IBluetoothHeadset service = mService; - if (service != null && isEnabled()) { + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled()) { try { service.phoneStateChanged(numActive, numHeld, callState, number, type, name, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); + } catch (RemoteException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - } else { - Log.w(TAG, "Proxy not attached to service"); - if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); } } @@ -1161,16 +1235,18 @@ public final class BluetoothHeadset implements BluetoothProfile { public void clccResponse(int index, int direction, int status, int mode, boolean mpty, String number, int type) { final IBluetoothHeadset service = mService; - if (service != null && isEnabled()) { + 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.clccResponse(index, direction, status, mode, mpty, number, type, - mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); + mAttributionSource, recv); + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - } else { - Log.w(TAG, "Proxy not attached to service"); - if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); } } @@ -1202,18 +1278,21 @@ public final class BluetoothHeadset implements BluetoothProfile { throw new IllegalArgumentException("command is null"); } final IBluetoothHeadset service = mService; - if (service != null && isEnabled() && isValidDevice(device)) { - try { - return service.sendVendorSpecificResultCode(device, command, arg, - mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - } - } + 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() && isValidDevice(device)) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.sendVendorSpecificResultCode(device, command, arg, + mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } } - return false; + return defaultValue; } /** @@ -1247,17 +1326,20 @@ public final class BluetoothHeadset implements BluetoothProfile { Log.d(TAG, "setActiveDevice: " + device); } final IBluetoothHeadset service = mService; - if (service != null && isEnabled() && (device == null || isValidDevice(device))) { - try { - return service.setActiveDevice(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - } - } + 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() && (device == null || isValidDevice(device))) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.setActiveDevice(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } } - return false; + return defaultValue; } /** @@ -1273,22 +1355,25 @@ public final class BluetoothHeadset implements BluetoothProfile { @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public BluetoothDevice getActiveDevice() { - if (VDBG) { - Log.d(TAG, "getActiveDevice"); - } + if (VDBG) Log.d(TAG, "getActiveDevice"); final IBluetoothHeadset service = mService; - if (service != null && isEnabled()) { + final BluetoothDevice defaultValue = null; + 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.getActiveDevice(mAttributionSource, recv); return Attributable.setAttributionSource( - service.getActiveDevice(mAttributionSource), mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), + mAttributionSource); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) { - Log.w(TAG, "Proxy not attached to service"); - } - return null; + return defaultValue; } /** @@ -1303,21 +1388,22 @@ public final class BluetoothHeadset implements BluetoothProfile { @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean isInbandRingingEnabled() { - if (DBG) { - log("isInbandRingingEnabled()"); - } + if (DBG) log("isInbandRingingEnabled()"); final IBluetoothHeadset service = mService; - if (service != null && isEnabled()) { - try { - return service.isInbandRingingEnabled(mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - } - } + 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 recv = new SynchronousResultReceiver(); + service.isInbandRingingEnabled(mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } } - return false; + return defaultValue; } /** @@ -1337,7 +1423,7 @@ public final class BluetoothHeadset implements BluetoothProfile { @Override public void onServiceConnected(ComponentName className, IBinder service) { if (DBG) Log.d(TAG, "Proxy object connected"); - mService = IBluetoothHeadset.Stub.asInterface(Binder.allowBlocking(service)); + mService = IBluetoothHeadset.Stub.asInterface(service); mHandler.sendMessage(mHandler.obtainMessage( MESSAGE_HEADSET_SERVICE_CONNECTED)); } diff --git a/core/java/android/bluetooth/BluetoothHeadsetClient.java b/core/java/android/bluetooth/BluetoothHeadsetClient.java index 2ef37101e23de3cc22c5909529c148fcee0892dc..7d7a7f798bb9e7a8b9e4adab7cb045e52f271495 100644 --- a/core/java/android/bluetooth/BluetoothHeadsetClient.java +++ b/core/java/android/bluetooth/BluetoothHeadsetClient.java @@ -16,6 +16,8 @@ package android.bluetooth; +import static android.bluetooth.BluetoothUtils.getSyncTimeout; + import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; @@ -25,15 +27,17 @@ import android.bluetooth.annotations.RequiresLegacyBluetoothPermission; import android.compat.annotation.UnsupportedAppUsage; import android.content.AttributionSource; import android.content.Context; -import android.os.Binder; import android.os.Build; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; +import com.android.modules.utils.SynchronousResultReceiver; + import java.util.ArrayList; import java.util.List; +import java.util.concurrent.TimeoutException; /** * Public API to control Hands Free Profile (HFP role only). @@ -432,7 +436,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { "BluetoothHeadsetClient", IBluetoothHeadsetClient.class.getName()) { @Override public IBluetoothHeadsetClient getServiceInterface(IBinder service) { - return IBluetoothHeadsetClient.Stub.asInterface(Binder.allowBlocking(service)); + return IBluetoothHeadsetClient.Stub.asInterface(service); } }; @@ -479,18 +483,21 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean connect(BluetoothDevice device) { if (DBG) log("connect(" + device + ")"); - final IBluetoothHeadsetClient service = - getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadsetClient service = getService(); + 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() && isValidDevice(device)) { try { - return service.connect(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return false; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.connect(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -507,18 +514,21 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); - final IBluetoothHeadsetClient service = - getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadsetClient service = getService(); + 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() && isValidDevice(device)) { try { - return service.disconnect(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return false; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.disconnect(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -531,19 +541,24 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public List getConnectedDevices() { if (VDBG) log("getConnectedDevices()"); - final IBluetoothHeadsetClient service = - getService(); - if (service != null && isEnabled()) { + final IBluetoothHeadsetClient service = getService(); + final List defaultValue = new ArrayList(); + 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.getConnectedDevices(mAttributionSource, recv); return Attributable.setAttributionSource( - service.getConnectedDevices(mAttributionSource), mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return new ArrayList(); + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), + mAttributionSource); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList(); + return defaultValue; } /** @@ -558,20 +573,24 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public List getDevicesMatchingConnectionStates(int[] states) { if (VDBG) log("getDevicesMatchingStates()"); - final IBluetoothHeadsetClient service = - getService(); - if (service != null && isEnabled()) { + final IBluetoothHeadsetClient service = getService(); + final List defaultValue = new ArrayList(); + 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.getDevicesMatchingConnectionStates(states, mAttributionSource, recv); return Attributable.setAttributionSource( - service.getDevicesMatchingConnectionStates(states, mAttributionSource), + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return new ArrayList(); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList(); + return defaultValue; } /** @@ -585,18 +604,21 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(BluetoothDevice device) { if (VDBG) log("getConnectionState(" + device + ")"); - final IBluetoothHeadsetClient service = - getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadsetClient service = getService(); + final int defaultValue = BluetoothProfile.STATE_DISCONNECTED; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { try { - return service.getConnectionState(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return BluetoothProfile.STATE_DISCONNECTED; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getConnectionState(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return BluetoothProfile.STATE_DISCONNECTED; + return defaultValue; } /** @@ -634,22 +656,23 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { public boolean setConnectionPolicy(@NonNull BluetoothDevice device, @ConnectionPolicy int connectionPolicy) { if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")"); - final IBluetoothHeadsetClient service = - getService(); - if (service != null && isEnabled() && isValidDevice(device)) { - if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN - && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) { - return false; - } + final IBluetoothHeadsetClient service = getService(); + 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() && isValidDevice(device) + && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN + || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) { try { - return service.setConnectionPolicy(device, connectionPolicy, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return false; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -686,18 +709,21 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) { if (VDBG) log("getConnectionPolicy(" + device + ")"); - final IBluetoothHeadsetClient service = - getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadsetClient service = getService(); + final @ConnectionPolicy int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { try { - return service.getConnectionPolicy(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getConnectionPolicy(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; + return defaultValue; } /** @@ -715,17 +741,21 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean startVoiceRecognition(BluetoothDevice device) { if (DBG) log("startVoiceRecognition()"); - final IBluetoothHeadsetClient service = - getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadsetClient service = getService(); + 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() && isValidDevice(device)) { try { - return service.startVoiceRecognition(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.startVoiceRecognition(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -739,20 +769,23 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { */ @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) - public boolean sendVendorAtCommand(BluetoothDevice device, int vendorId, - String atCommand) { + public boolean sendVendorAtCommand(BluetoothDevice device, int vendorId, String atCommand) { if (DBG) log("sendVendorSpecificCommand()"); - final IBluetoothHeadsetClient service = - getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadsetClient service = getService(); + 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() && isValidDevice(device)) { try { - return service.sendVendorAtCommand(device, vendorId, atCommand, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.sendVendorAtCommand(device, vendorId, atCommand, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -770,17 +803,21 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean stopVoiceRecognition(BluetoothDevice device) { if (DBG) log("stopVoiceRecognition()"); - final IBluetoothHeadsetClient service = - getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadsetClient service = getService(); + 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() && isValidDevice(device)) { try { - return service.stopVoiceRecognition(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.stopVoiceRecognition(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -793,18 +830,24 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public List getCurrentCalls(BluetoothDevice device) { if (DBG) log("getCurrentCalls()"); - final IBluetoothHeadsetClient service = - getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadsetClient service = getService(); + final List defaultValue = null; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { try { + final SynchronousResultReceiver> recv = + new SynchronousResultReceiver(); + service.getCurrentCalls(device, mAttributionSource, recv); return Attributable.setAttributionSource( - service.getCurrentCalls(device, mAttributionSource), mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), + mAttributionSource); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return null; + return defaultValue; } /** @@ -817,17 +860,21 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public Bundle getCurrentAgEvents(BluetoothDevice device) { if (DBG) log("getCurrentAgEvents()"); - final IBluetoothHeadsetClient service = - getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadsetClient service = getService(); + final Bundle defaultValue = null; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { try { - return service.getCurrentAgEvents(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getCurrentAgEvents(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return null; + return defaultValue; } /** @@ -844,17 +891,21 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean acceptCall(BluetoothDevice device, int flag) { if (DBG) log("acceptCall()"); - final IBluetoothHeadsetClient service = - getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadsetClient service = getService(); + 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() && isValidDevice(device)) { try { - return service.acceptCall(device, flag, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.acceptCall(device, flag, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -868,17 +919,21 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean holdCall(BluetoothDevice device) { if (DBG) log("holdCall()"); - final IBluetoothHeadsetClient service = - getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadsetClient service = getService(); + 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() && isValidDevice(device)) { try { - return service.holdCall(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.holdCall(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -897,17 +952,21 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean rejectCall(BluetoothDevice device) { if (DBG) log("rejectCall()"); - final IBluetoothHeadsetClient service = - getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadsetClient service = getService(); + 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() && isValidDevice(device)) { try { - return service.rejectCall(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.rejectCall(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -930,17 +989,21 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean terminateCall(BluetoothDevice device, BluetoothHeadsetClientCall call) { if (DBG) log("terminateCall()"); - final IBluetoothHeadsetClient service = - getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadsetClient service = getService(); + 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() && isValidDevice(device)) { try { - return service.terminateCall(device, call, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.terminateCall(device, call, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -961,17 +1024,21 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean enterPrivateMode(BluetoothDevice device, int index) { if (DBG) log("enterPrivateMode()"); - final IBluetoothHeadsetClient service = - getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadsetClient service = getService(); + 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() && isValidDevice(device)) { try { - return service.enterPrivateMode(device, index, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.enterPrivateMode(device, index, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -991,17 +1058,21 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean explicitCallTransfer(BluetoothDevice device) { if (DBG) log("explicitCallTransfer()"); - final IBluetoothHeadsetClient service = - getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadsetClient service = getService(); + 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() && isValidDevice(device)) { try { - return service.explicitCallTransfer(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.explicitCallTransfer(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -1017,18 +1088,24 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public BluetoothHeadsetClientCall dial(BluetoothDevice device, String number) { if (DBG) log("dial()"); - final IBluetoothHeadsetClient service = - getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadsetClient service = getService(); + final BluetoothHeadsetClientCall defaultValue = null; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { try { + final SynchronousResultReceiver recv = + new SynchronousResultReceiver(); + service.dial(device, number, mAttributionSource, recv); return Attributable.setAttributionSource( - service.dial(device, number, mAttributionSource), mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), + mAttributionSource); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return null; + return defaultValue; } /** @@ -1045,17 +1122,21 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean sendDTMF(BluetoothDevice device, byte code) { if (DBG) log("sendDTMF()"); - final IBluetoothHeadsetClient service = - getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadsetClient service = getService(); + 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() && isValidDevice(device)) { try { - return service.sendDTMF(device, code, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.sendDTMF(device, code, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -1074,17 +1155,21 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean getLastVoiceTagNumber(BluetoothDevice device) { if (DBG) log("getLastVoiceTagNumber()"); - final IBluetoothHeadsetClient service = - getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadsetClient service = getService(); + 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() && isValidDevice(device)) { try { - return service.getLastVoiceTagNumber(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getLastVoiceTagNumber(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -1097,17 +1182,21 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getAudioState(BluetoothDevice device) { if (VDBG) log("getAudioState"); - final IBluetoothHeadsetClient service = - getService(); - if (service != null && isEnabled()) { + final IBluetoothHeadsetClient service = getService(); + final int defaultValue = BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled()) { try { - return service.getAudioState(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getAudioState(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } else { - Log.w(TAG, "Proxy not attached to service"); - if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + return defaultValue; } return BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED; } @@ -1123,17 +1212,18 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void setAudioRouteAllowed(BluetoothDevice device, boolean allowed) { if (VDBG) log("setAudioRouteAllowed"); - final IBluetoothHeadsetClient service = - getService(); - if (service != null && isEnabled()) { + final IBluetoothHeadsetClient service = getService(); + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled()) { try { - service.setAudioRouteAllowed(device, allowed, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.setAudioRouteAllowed(device, allowed, mAttributionSource, recv); + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - } else { - Log.w(TAG, "Proxy not attached to service"); - if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); } } @@ -1148,19 +1238,21 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean getAudioRouteAllowed(BluetoothDevice device) { if (VDBG) log("getAudioRouteAllowed"); - final IBluetoothHeadsetClient service = - getService(); - if (service != null && isEnabled()) { + final IBluetoothHeadsetClient service = getService(); + 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 { - return service.getAudioRouteAllowed(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getAudioRouteAllowed(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - } else { - Log.w(TAG, "Proxy not attached to service"); - if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); } - return false; + return defaultValue; } /** @@ -1175,19 +1267,22 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean connectAudio(BluetoothDevice device) { - final IBluetoothHeadsetClient service = - getService(); - if (service != null && isEnabled()) { + if (VDBG) log("connectAudio"); + final IBluetoothHeadsetClient service = getService(); + 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 { - return service.connectAudio(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.connectAudio(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - } else { - Log.w(TAG, "Proxy not attached to service"); - if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); } - return false; + return defaultValue; } /** @@ -1202,19 +1297,22 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disconnectAudio(BluetoothDevice device) { - final IBluetoothHeadsetClient service = - getService(); - if (service != null && isEnabled()) { + if (VDBG) log("disconnectAudio"); + final IBluetoothHeadsetClient service = getService(); + 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 { - return service.disconnectAudio(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.disconnectAudio(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - } else { - Log.w(TAG, "Proxy not attached to service"); - if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); } - return false; + return defaultValue; } /** @@ -1226,19 +1324,22 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public Bundle getCurrentAgFeatures(BluetoothDevice device) { - final IBluetoothHeadsetClient service = - getService(); - if (service != null && isEnabled()) { + if (VDBG) log("getCurrentAgFeatures"); + final IBluetoothHeadsetClient service = getService(); + final Bundle defaultValue = null; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled()) { try { - return service.getCurrentAgFeatures(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getCurrentAgFeatures(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - } else { - Log.w(TAG, "Proxy not attached to service"); - if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); } - return null; + return defaultValue; } private boolean isEnabled() { diff --git a/core/java/android/bluetooth/BluetoothHearingAid.java b/core/java/android/bluetooth/BluetoothHearingAid.java index a00b20d99f964bb9a858358b65b39b3a743ecadc..339a75fe0fbe4d21eccbac01ecc9c6527d5bc994 100644 --- a/core/java/android/bluetooth/BluetoothHearingAid.java +++ b/core/java/android/bluetooth/BluetoothHearingAid.java @@ -16,6 +16,8 @@ package android.bluetooth; +import static android.bluetooth.BluetoothUtils.getSyncTimeout; + import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; @@ -28,14 +30,16 @@ import android.bluetooth.annotations.RequiresLegacyBluetoothPermission; import android.compat.annotation.UnsupportedAppUsage; import android.content.AttributionSource; import android.content.Context; -import android.os.Binder; import android.os.Build; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; +import com.android.modules.utils.SynchronousResultReceiver; + import java.util.ArrayList; import java.util.List; +import java.util.concurrent.TimeoutException; /** * This class provides the public APIs to control the Hearing Aid profile. @@ -136,7 +140,7 @@ public final class BluetoothHearingAid implements BluetoothProfile { "BluetoothHearingAid", IBluetoothHearingAid.class.getName()) { @Override public IBluetoothHearingAid getServiceInterface(IBinder service) { - return IBluetoothHearingAid.Stub.asInterface(Binder.allowBlocking(service)); + return IBluetoothHearingAid.Stub.asInterface(service); } }; @@ -181,16 +185,20 @@ public final class BluetoothHearingAid implements BluetoothProfile { public boolean connect(BluetoothDevice device) { if (DBG) log("connect(" + device + ")"); final IBluetoothHearingAid service = getService(); - try { - if (service != null && isEnabled() && isValidDevice(device)) { - return service.connect(device, mAttributionSource); + 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() && isValidDevice(device)) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.connect(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; } + return defaultValue; } /** @@ -223,16 +231,20 @@ public final class BluetoothHearingAid implements BluetoothProfile { public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); final IBluetoothHearingAid service = getService(); - try { - if (service != null && isEnabled() && isValidDevice(device)) { - return service.disconnect(device, mAttributionSource); + 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() && isValidDevice(device)) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.disconnect(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; } + return defaultValue; } /** @@ -244,17 +256,23 @@ public final class BluetoothHearingAid implements BluetoothProfile { public @NonNull List getConnectedDevices() { if (VDBG) log("getConnectedDevices()"); final IBluetoothHearingAid service = getService(); - try { - if (service != null && isEnabled()) { + final List defaultValue = new ArrayList(); + 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.getConnectedDevices(mAttributionSource, recv); return Attributable.setAttributionSource( - service.getConnectedDevices(mAttributionSource), mAttributionSource); + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), + mAttributionSource); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList(); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return new ArrayList(); } + return defaultValue; } /** @@ -267,18 +285,23 @@ public final class BluetoothHearingAid implements BluetoothProfile { @NonNull int[] states) { if (VDBG) log("getDevicesMatchingStates()"); final IBluetoothHearingAid service = getService(); - try { - if (service != null && isEnabled()) { + final List defaultValue = new ArrayList(); + 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.getDevicesMatchingConnectionStates(states, mAttributionSource, recv); return Attributable.setAttributionSource( - service.getDevicesMatchingConnectionStates(states, mAttributionSource), + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), mAttributionSource); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList(); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return new ArrayList(); } + return defaultValue; } /** @@ -291,17 +314,20 @@ public final class BluetoothHearingAid implements BluetoothProfile { @NonNull BluetoothDevice device) { if (VDBG) log("getState(" + device + ")"); final IBluetoothHearingAid service = getService(); - try { - if (service != null && isEnabled() - && isValidDevice(device)) { - return service.getConnectionState(device, mAttributionSource); + final int defaultValue = BluetoothProfile.STATE_DISCONNECTED; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getConnectionState(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return BluetoothProfile.STATE_DISCONNECTED; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return BluetoothProfile.STATE_DISCONNECTED; } + return defaultValue; } /** @@ -330,18 +356,20 @@ public final class BluetoothHearingAid implements BluetoothProfile { public boolean setActiveDevice(@Nullable BluetoothDevice device) { if (DBG) log("setActiveDevice(" + device + ")"); final IBluetoothHearingAid service = getService(); - try { - if (service != null && isEnabled() - && ((device == null) || isValidDevice(device))) { - service.setActiveDevice(device, mAttributionSource); - return true; + 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() && ((device == null) || isValidDevice(device))) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.setActiveDevice(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; } + return defaultValue; } /** @@ -359,17 +387,23 @@ public final class BluetoothHearingAid implements BluetoothProfile { public @NonNull List getActiveDevices() { if (VDBG) log("getActiveDevices()"); final IBluetoothHearingAid service = getService(); - try { - if (service != null && isEnabled()) { + final List defaultValue = new ArrayList<>(); + 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.getActiveDevices(mAttributionSource, recv); return Attributable.setAttributionSource( - service.getActiveDevices(mAttributionSource), mAttributionSource); + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), + mAttributionSource); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList<>(); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return new ArrayList<>(); } + return defaultValue; } /** @@ -416,21 +450,22 @@ public final class BluetoothHearingAid implements BluetoothProfile { if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")"); verifyDeviceNotNull(device, "setConnectionPolicy"); final IBluetoothHearingAid service = getService(); - try { - if (service != null && isEnabled() - && isValidDevice(device)) { - if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN - && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) { - return false; - } - return service.setConnectionPolicy(device, connectionPolicy, mAttributionSource); + 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() && isValidDevice(device) + && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN + || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; } + return defaultValue; } /** @@ -474,17 +509,20 @@ public final class BluetoothHearingAid implements BluetoothProfile { if (VDBG) log("getConnectionPolicy(" + device + ")"); verifyDeviceNotNull(device, "getConnectionPolicy"); final IBluetoothHearingAid service = getService(); - try { - if (service != null && isEnabled() - && isValidDevice(device)) { - return service.getConnectionPolicy(device, mAttributionSource); + final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getConnectionPolicy(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; } + return defaultValue; } /** @@ -519,19 +557,18 @@ public final class BluetoothHearingAid implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void setVolume(int volume) { if (DBG) Log.d(TAG, "setVolume(" + volume + ")"); - final IBluetoothHearingAid service = getService(); - try { - if (service == null) { - Log.w(TAG, "Proxy not attached to service"); - return; + 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.setVolume(volume, mAttributionSource, recv); + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - - if (!isEnabled()) return; - - service.setVolume(volume, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); } } @@ -552,24 +589,23 @@ public final class BluetoothHearingAid implements BluetoothProfile { android.Manifest.permission.BLUETOOTH_PRIVILEGED, }) public long getHiSyncId(@NonNull BluetoothDevice device) { - if (VDBG) { - log("getHiSyncId(" + device + ")"); - } + if (VDBG) log("getHiSyncId(" + device + ")"); verifyDeviceNotNull(device, "getConnectionPolicy"); final IBluetoothHearingAid service = getService(); - try { - if (service == null) { - Log.w(TAG, "Proxy not attached to service"); - return HI_SYNC_ID_INVALID; + final long defaultValue = HI_SYNC_ID_INVALID; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getHiSyncId(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - - if (!isEnabled() || !isValidDevice(device)) return HI_SYNC_ID_INVALID; - - return service.getHiSyncId(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return HI_SYNC_ID_INVALID; } + return defaultValue; } /** @@ -583,21 +619,22 @@ public final class BluetoothHearingAid implements BluetoothProfile { @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getDeviceSide(BluetoothDevice device) { - if (VDBG) { - log("getDeviceSide(" + device + ")"); - } + if (VDBG) log("getDeviceSide(" + device + ")"); final IBluetoothHearingAid service = getService(); - try { - if (service != null && isEnabled() - && isValidDevice(device)) { - return service.getDeviceSide(device, mAttributionSource); + final int defaultValue = SIDE_LEFT; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getDeviceSide(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return SIDE_LEFT; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return SIDE_LEFT; } + return defaultValue; } /** @@ -611,21 +648,22 @@ public final class BluetoothHearingAid implements BluetoothProfile { @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getDeviceMode(BluetoothDevice device) { - if (VDBG) { - log("getDeviceMode(" + device + ")"); - } + if (VDBG) log("getDeviceMode(" + device + ")"); final IBluetoothHearingAid service = getService(); - try { - if (service != null && isEnabled() - && isValidDevice(device)) { - return service.getDeviceMode(device, mAttributionSource); + final int defaultValue = MODE_MONAURAL; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getDeviceMode(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return MODE_MONAURAL; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return MODE_MONAURAL; } + return defaultValue; } private boolean isEnabled() { diff --git a/core/java/android/bluetooth/BluetoothHidDevice.java b/core/java/android/bluetooth/BluetoothHidDevice.java index f5b444fd17cb55248d0a93b9ca1e4f7f8d36e05a..44a355b5f75c2b1514e9ace95b98e795bb45bf97 100644 --- a/core/java/android/bluetooth/BluetoothHidDevice.java +++ b/core/java/android/bluetooth/BluetoothHidDevice.java @@ -16,6 +16,8 @@ package android.bluetooth; +import static android.bluetooth.BluetoothUtils.getSyncTimeout; + import android.Manifest; import android.annotation.NonNull; import android.annotation.RequiresPermission; @@ -26,14 +28,16 @@ import android.bluetooth.annotations.RequiresBluetoothConnectPermission; import android.bluetooth.annotations.RequiresLegacyBluetoothPermission; import android.content.AttributionSource; import android.content.Context; -import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; +import com.android.modules.utils.SynchronousResultReceiver; + import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executor; +import java.util.concurrent.TimeoutException; /** * Provides the public APIs to control the Bluetooth HID Device profile. @@ -431,7 +435,7 @@ public final class BluetoothHidDevice implements BluetoothProfile { "BluetoothHidDevice", IBluetoothHidDevice.class.getName()) { @Override public IBluetoothHidDevice getServiceInterface(IBinder service) { - return IBluetoothHidDevice.Stub.asInterface(Binder.allowBlocking(service)); + return IBluetoothHidDevice.Stub.asInterface(service); } }; @@ -455,18 +459,23 @@ public final class BluetoothHidDevice implements BluetoothProfile { @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT) public List getConnectedDevices() { final IBluetoothHidDevice service = getService(); - if (service != null) { + final List defaultValue = new ArrayList<>(); + 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.getConnectedDevices(mAttributionSource, recv); return Attributable.setAttributionSource( - service.getConnectedDevices(mAttributionSource), mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), + mAttributionSource); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - } else { - Log.w(TAG, "Proxy not attached to service"); } - - return new ArrayList<>(); + return defaultValue; } /** {@inheritDoc} */ @@ -475,19 +484,23 @@ public final class BluetoothHidDevice implements BluetoothProfile { @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT) public List getDevicesMatchingConnectionStates(int[] states) { final IBluetoothHidDevice service = getService(); - if (service != null) { + final List defaultValue = new ArrayList<>(); + 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.getDevicesMatchingConnectionStates(states, mAttributionSource, recv); return Attributable.setAttributionSource( - service.getDevicesMatchingConnectionStates(states, mAttributionSource), + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - } else { - Log.w(TAG, "Proxy not attached to service"); } - - return new ArrayList<>(); + return defaultValue; } /** {@inheritDoc} */ @@ -496,17 +509,20 @@ public final class BluetoothHidDevice implements BluetoothProfile { @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(BluetoothDevice device) { final IBluetoothHidDevice service = getService(); - if (service != null) { + final int defaultValue = STATE_DISCONNECTED; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled()) { try { - return service.getConnectionState(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getConnectionState(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - } else { - Log.w(TAG, "Proxy not attached to service"); } - - return STATE_DISCONNECTED; + return defaultValue; } /** @@ -555,18 +571,21 @@ public final class BluetoothHidDevice implements BluetoothProfile { } final IBluetoothHidDevice service = getService(); - if (service != null) { + final boolean defaultValue = result; + 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(); CallbackWrapper cbw = new CallbackWrapper(executor, callback, mAttributionSource); - result = service.registerApp(sdp, inQos, outQos, cbw, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); + service.registerApp(sdp, inQos, outQos, cbw, mAttributionSource, recv); + result = recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - } else { - Log.w(TAG, "Proxy not attached to service"); } - - return result; + return defaultValue; } /** @@ -582,20 +601,21 @@ public final class BluetoothHidDevice implements BluetoothProfile { @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean unregisterApp() { - boolean result = false; - final IBluetoothHidDevice service = getService(); - if (service != null) { + 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 { - result = service.unregisterApp(mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.unregisterApp(mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - } else { - Log.w(TAG, "Proxy not attached to service"); } - - return result; + return defaultValue; } /** @@ -609,20 +629,21 @@ public final class BluetoothHidDevice implements BluetoothProfile { @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean sendReport(BluetoothDevice device, int id, byte[] data) { - boolean result = false; - final IBluetoothHidDevice service = getService(); - if (service != null) { + 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 { - result = service.sendReport(device, id, data, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.sendReport(device, id, data, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - } else { - Log.w(TAG, "Proxy not attached to service"); } - - return result; + return defaultValue; } /** @@ -637,20 +658,21 @@ public final class BluetoothHidDevice implements BluetoothProfile { @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean replyReport(BluetoothDevice device, byte type, byte id, byte[] data) { - boolean result = false; - final IBluetoothHidDevice service = getService(); - if (service != null) { + 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 { - result = service.replyReport(device, type, id, data, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.replyReport(device, type, id, data, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - } else { - Log.w(TAG, "Proxy not attached to service"); } - - return result; + return defaultValue; } /** @@ -663,20 +685,21 @@ public final class BluetoothHidDevice implements BluetoothProfile { @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean reportError(BluetoothDevice device, byte error) { - boolean result = false; - final IBluetoothHidDevice service = getService(); - if (service != null) { + 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 { - result = service.reportError(device, error, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.reportError(device, error, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - } else { - Log.w(TAG, "Proxy not attached to service"); } - - return result; + return defaultValue; } /** @@ -689,18 +712,20 @@ public final class BluetoothHidDevice implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public String getUserAppName() { final IBluetoothHidDevice service = getService(); - - if (service != null) { + final String defaultValue = ""; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled()) { try { - return service.getUserAppName(mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getUserAppName(mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - } else { - Log.w(TAG, "Proxy not attached to service"); } - - return ""; + return defaultValue; } /** @@ -714,20 +739,21 @@ public final class BluetoothHidDevice implements BluetoothProfile { @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean connect(BluetoothDevice device) { - boolean result = false; - final IBluetoothHidDevice service = getService(); - if (service != null) { + 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() && isValidDevice(device)) { try { - result = service.connect(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.connect(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - } else { - Log.w(TAG, "Proxy not attached to service"); } - - return result; + return defaultValue; } /** @@ -740,20 +766,21 @@ public final class BluetoothHidDevice implements BluetoothProfile { @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disconnect(BluetoothDevice device) { - boolean result = false; - final IBluetoothHidDevice service = getService(); - if (service != null) { + 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 { - result = service.disconnect(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.disconnect(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - } else { - Log.w(TAG, "Proxy not attached to service"); } - - return result; + return defaultValue; } /** @@ -781,23 +808,24 @@ public final class BluetoothHidDevice implements BluetoothProfile { }) public boolean setConnectionPolicy(@NonNull BluetoothDevice device, @ConnectionPolicy int connectionPolicy) { - log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")"); - try { - final IBluetoothHidDevice service = getService(); - if (service != null && isEnabled() - && isValidDevice(device)) { - if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN - && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) { - return false; - } - return service.setConnectionPolicy(device, connectionPolicy, mAttributionSource); + if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")"); + final IBluetoothHidDevice service = getService(); + 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() && isValidDevice(device) + && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN + || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; } + return defaultValue; } private boolean isEnabled() { diff --git a/core/java/android/bluetooth/BluetoothHidHost.java b/core/java/android/bluetooth/BluetoothHidHost.java index 121aa16115228ac9363be77551d5cbe1ffe858d6..ecbeddf2b85321fb8641c071f9578b111d8e96de 100644 --- a/core/java/android/bluetooth/BluetoothHidHost.java +++ b/core/java/android/bluetooth/BluetoothHidHost.java @@ -16,6 +16,8 @@ package android.bluetooth; +import static android.bluetooth.BluetoothUtils.getSyncTimeout; + import android.Manifest; import android.annotation.NonNull; import android.annotation.RequiresPermission; @@ -28,13 +30,15 @@ import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission; import android.bluetooth.annotations.RequiresLegacyBluetoothPermission; import android.content.AttributionSource; import android.content.Context; -import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; +import com.android.modules.utils.SynchronousResultReceiver; + import java.util.ArrayList; import java.util.List; +import java.util.concurrent.TimeoutException; /** @@ -244,7 +248,7 @@ public final class BluetoothHidHost implements BluetoothProfile { "BluetoothHidHost", IBluetoothHidHost.class.getName()) { @Override public IBluetoothHidHost getServiceInterface(IBinder service) { - return IBluetoothHidHost.Stub.asInterface(Binder.allowBlocking(service)); + return IBluetoothHidHost.Stub.asInterface(service); } }; @@ -292,16 +296,20 @@ public final class BluetoothHidHost implements BluetoothProfile { public boolean connect(BluetoothDevice device) { if (DBG) log("connect(" + device + ")"); final IBluetoothHidHost service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + 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() && isValidDevice(device)) { try { - return service.connect(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.connect(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -334,16 +342,20 @@ public final class BluetoothHidHost implements BluetoothProfile { public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); final IBluetoothHidHost service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + 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() && isValidDevice(device)) { try { - return service.disconnect(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.disconnect(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -358,17 +370,23 @@ public final class BluetoothHidHost implements BluetoothProfile { public @NonNull List getConnectedDevices() { if (VDBG) log("getConnectedDevices()"); final IBluetoothHidHost service = getService(); - if (service != null && isEnabled()) { + final List defaultValue = new ArrayList(); + 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.getConnectedDevices(mAttributionSource, recv); return Attributable.setAttributionSource( - service.getConnectedDevices(mAttributionSource), mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return new ArrayList(); + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), + mAttributionSource); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList(); + return defaultValue; } /** @@ -382,18 +400,23 @@ public final class BluetoothHidHost implements BluetoothProfile { public List getDevicesMatchingConnectionStates(int[] states) { if (VDBG) log("getDevicesMatchingStates()"); final IBluetoothHidHost service = getService(); - if (service != null && isEnabled()) { + final List defaultValue = new ArrayList(); + 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.getDevicesMatchingConnectionStates(states, mAttributionSource, recv); return Attributable.setAttributionSource( - service.getDevicesMatchingConnectionStates(states, mAttributionSource), + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return new ArrayList(); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList(); + return defaultValue; } /** @@ -411,16 +434,20 @@ public final class BluetoothHidHost implements BluetoothProfile { throw new IllegalArgumentException("device must not be null"); } final IBluetoothHidHost service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final int defaultValue = BluetoothProfile.STATE_DISCONNECTED; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { try { - return service.getConnectionState(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return BluetoothProfile.STATE_DISCONNECTED; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getConnectionState(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return BluetoothProfile.STATE_DISCONNECTED; + return defaultValue; } /** @@ -469,20 +496,22 @@ public final class BluetoothHidHost implements BluetoothProfile { throw new IllegalArgumentException("device must not be null"); } final IBluetoothHidHost service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { - if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN - && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) { - return false; - } + 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() && isValidDevice(device) + && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN + || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) { try { - return service.setConnectionPolicy(device, connectionPolicy, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -528,16 +557,20 @@ public final class BluetoothHidHost implements BluetoothProfile { throw new IllegalArgumentException("device must not be null"); } final IBluetoothHidHost service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { try { - return service.getConnectionPolicy(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getConnectionPolicy(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; + return defaultValue; } private boolean isEnabled() { @@ -561,18 +594,20 @@ public final class BluetoothHidHost implements BluetoothProfile { public boolean virtualUnplug(BluetoothDevice device) { if (DBG) log("virtualUnplug(" + device + ")"); final IBluetoothHidHost service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + 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() && isValidDevice(device)) { try { - return service.virtualUnplug(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.virtualUnplug(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; - + return defaultValue; } /** @@ -588,16 +623,20 @@ public final class BluetoothHidHost implements BluetoothProfile { public boolean getProtocolMode(BluetoothDevice device) { if (VDBG) log("getProtocolMode(" + device + ")"); final IBluetoothHidHost service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + 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() && isValidDevice(device)) { try { - return service.getProtocolMode(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getProtocolMode(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -613,16 +652,20 @@ public final class BluetoothHidHost implements BluetoothProfile { public boolean setProtocolMode(BluetoothDevice device, int protocolMode) { if (DBG) log("setProtocolMode(" + device + ")"); final IBluetoothHidHost service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + 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() && isValidDevice(device)) { try { - return service.setProtocolMode(device, protocolMode, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.setProtocolMode(device, protocolMode, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -645,17 +688,21 @@ public final class BluetoothHidHost implements BluetoothProfile { + "bufferSize=" + bufferSize); } final IBluetoothHidHost service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + 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() && isValidDevice(device)) { try { - return service.getReport(device, reportType, reportId, bufferSize, - mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getReport(device, reportType, reportId, bufferSize, mAttributionSource, + recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -673,16 +720,20 @@ public final class BluetoothHidHost implements BluetoothProfile { public boolean setReport(BluetoothDevice device, byte reportType, String report) { if (VDBG) log("setReport(" + device + "), reportType=" + reportType + " report=" + report); final IBluetoothHidHost service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + 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() && isValidDevice(device)) { try { - return service.setReport(device, reportType, report, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.setReport(device, reportType, report, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -699,16 +750,20 @@ public final class BluetoothHidHost implements BluetoothProfile { public boolean sendData(BluetoothDevice device, String report) { if (DBG) log("sendData(" + device + "), report=" + report); final IBluetoothHidHost service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + 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() && isValidDevice(device)) { try { - return service.sendData(device, report, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.sendData(device, report, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -724,16 +779,20 @@ public final class BluetoothHidHost implements BluetoothProfile { public boolean getIdleTime(BluetoothDevice device) { if (DBG) log("getIdletime(" + device + ")"); final IBluetoothHidHost service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + 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() && isValidDevice(device)) { try { - return service.getIdleTime(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getIdleTime(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -750,16 +809,20 @@ public final class BluetoothHidHost implements BluetoothProfile { public boolean setIdleTime(BluetoothDevice device, byte idleTime) { if (DBG) log("setIdletime(" + device + "), idleTime=" + idleTime); final IBluetoothHidHost service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + 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() && isValidDevice(device)) { try { - return service.setIdleTime(device, idleTime, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.setIdleTime(device, idleTime, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } private static void log(String msg) { diff --git a/core/java/android/bluetooth/BluetoothLeAudio.java b/core/java/android/bluetooth/BluetoothLeAudio.java index 34398eba5d288ed242c8026c624fe052b3adfa1c..15db686b3be4d62dada60156ec6db0908fcb2c69 100644 --- a/core/java/android/bluetooth/BluetoothLeAudio.java +++ b/core/java/android/bluetooth/BluetoothLeAudio.java @@ -17,6 +17,8 @@ package android.bluetooth; +import static android.bluetooth.BluetoothUtils.getSyncTimeout; + import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; @@ -27,14 +29,16 @@ import android.bluetooth.annotations.RequiresBluetoothConnectPermission; import android.bluetooth.annotations.RequiresLegacyBluetoothPermission; import android.content.AttributionSource; import android.content.Context; -import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; import android.util.CloseGuard; import android.util.Log; +import com.android.modules.utils.SynchronousResultReceiver; + import java.util.ArrayList; import java.util.List; +import java.util.concurrent.TimeoutException; /** * This class provides the public APIs to control the LeAudio profile. @@ -331,7 +335,7 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { IBluetoothLeAudio.class.getName()) { @Override public IBluetoothLeAudio getServiceInterface(IBinder service) { - return IBluetoothLeAudio.Stub.asInterface(Binder.allowBlocking(service)); + return IBluetoothLeAudio.Stub.asInterface(service); } }; @@ -385,17 +389,21 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean connect(@Nullable BluetoothDevice device) { if (DBG) log("connect(" + device + ")"); - try { - final IBluetoothLeAudio service = getService(); - if (service != null && mAdapter.isEnabled() && isValidDevice(device)) { - return service.connect(device, mAttributionSource); + final IBluetoothLeAudio service = getService(); + final boolean defaultValue = false; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (mAdapter.isEnabled() && isValidDevice(device)) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.connect(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; } + return defaultValue; } /** @@ -425,17 +433,21 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disconnect(@Nullable BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); - try { - final IBluetoothLeAudio service = getService(); - if (service != null && mAdapter.isEnabled() && isValidDevice(device)) { - return service.disconnect(device, mAttributionSource); + final IBluetoothLeAudio service = getService(); + final boolean defaultValue = false; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (mAdapter.isEnabled() && isValidDevice(device)) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.disconnect(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; } + return defaultValue; } /** @@ -446,18 +458,24 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public @NonNull List getConnectedDevices() { if (VDBG) log("getConnectedDevices()"); - try { - final IBluetoothLeAudio service = getService(); - if (service != null && mAdapter.isEnabled()) { + final IBluetoothLeAudio service = getService(); + final List defaultValue = new ArrayList(); + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (mAdapter.isEnabled()) { + try { + final SynchronousResultReceiver> recv = + new SynchronousResultReceiver(); + service.getConnectedDevices(mAttributionSource, recv); return Attributable.setAttributionSource( - service.getConnectedDevices(mAttributionSource), mAttributionSource); + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), + mAttributionSource); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList(); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return new ArrayList(); } + return defaultValue; } /** @@ -469,19 +487,24 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { public @NonNull List getDevicesMatchingConnectionStates( @NonNull int[] states) { if (VDBG) log("getDevicesMatchingStates()"); - try { - final IBluetoothLeAudio service = getService(); - if (service != null && mAdapter.isEnabled()) { + final IBluetoothLeAudio service = getService(); + final List defaultValue = new ArrayList(); + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (mAdapter.isEnabled()) { + try { + final SynchronousResultReceiver> recv = + new SynchronousResultReceiver(); + service.getDevicesMatchingConnectionStates(states, mAttributionSource, recv); return Attributable.setAttributionSource( - service.getDevicesMatchingConnectionStates(states, mAttributionSource), + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), mAttributionSource); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList(); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return new ArrayList(); } + return defaultValue; } /** @@ -493,18 +516,21 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public @BtProfileState int getConnectionState(@NonNull BluetoothDevice device) { if (VDBG) log("getState(" + device + ")"); - try { - final IBluetoothLeAudio service = getService(); - if (service != null && mAdapter.isEnabled() - && isValidDevice(device)) { - return service.getConnectionState(device, mAttributionSource); + final IBluetoothLeAudio service = getService(); + final int defaultValue = BluetoothProfile.STATE_DISCONNECTED; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (mAdapter.isEnabled() && isValidDevice(device)) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getConnectionState(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return BluetoothProfile.STATE_DISCONNECTED; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return BluetoothProfile.STATE_DISCONNECTED; } + return defaultValue; } /** @@ -531,19 +557,21 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean setActiveDevice(@Nullable BluetoothDevice device) { if (DBG) log("setActiveDevice(" + device + ")"); - try { - final IBluetoothLeAudio service = getService(); - if (service != null && mAdapter.isEnabled() - && ((device == null) || isValidDevice(device))) { - service.setActiveDevice(device, mAttributionSource); - return true; + final IBluetoothLeAudio service = getService(); + final boolean defaultValue = false; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (mAdapter.isEnabled() && ((device == null) || isValidDevice(device))) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.setActiveDevice(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; } + return defaultValue; } /** @@ -557,19 +585,25 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public List getActiveDevices() { - if (VDBG) log("getActiveDevices()"); - try { - final IBluetoothLeAudio service = getService(); - if (service != null && mAdapter.isEnabled()) { + if (VDBG) log("getActiveDevice()"); + final IBluetoothLeAudio service = getService(); + final List defaultValue = new ArrayList(); + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (mAdapter.isEnabled()) { + try { + final SynchronousResultReceiver> recv = + new SynchronousResultReceiver(); + service.getActiveDevices(mAttributionSource, recv); return Attributable.setAttributionSource( - service.getActiveDevices(mAttributionSource), mAttributionSource); + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), + mAttributionSource); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList<>(); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return new ArrayList<>(); } + return defaultValue; } /** @@ -583,17 +617,21 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getGroupId(@NonNull BluetoothDevice device) { if (VDBG) log("getGroupId()"); - try { - final IBluetoothLeAudio service = getService(); - if (service != null && mAdapter.isEnabled()) { - return service.getGroupId(device, mAttributionSource); + final IBluetoothLeAudio service = getService(); + final int defaultValue = GROUP_ID_INVALID; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (mAdapter.isEnabled()) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getGroupId(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return GROUP_ID_INVALID; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return GROUP_ID_INVALID; } + return defaultValue; } /** @@ -606,17 +644,18 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void setVolume(int volume) { if (VDBG) log("setVolume(vol: " + volume + " )"); - try { - final IBluetoothLeAudio service = getService(); - if (service != null && mAdapter.isEnabled()) { - service.setVolume(volume, mAttributionSource); - return; + final IBluetoothLeAudio service = getService(); + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (mAdapter.isEnabled()) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.setVolume(volume, mAttributionSource, recv); + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return; } } @@ -635,16 +674,20 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { public boolean groupAddNode(int group_id, @NonNull BluetoothDevice device) { if (VDBG) log("groupAddNode()"); final IBluetoothLeAudio service = getService(); - try { - if (service != null && mAdapter.isEnabled()) { - return service.groupAddNode(group_id, device, mAttributionSource); + final boolean defaultValue = false; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (mAdapter.isEnabled()) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.groupAddNode(group_id, device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; } + return defaultValue; } /** @@ -663,16 +706,20 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { public boolean groupRemoveNode(int group_id, @NonNull BluetoothDevice device) { if (VDBG) log("groupRemoveNode()"); final IBluetoothLeAudio service = getService(); - try { - if (service != null && mAdapter.isEnabled()) { - return service.groupRemoveNode(group_id, device, mAttributionSource); + final boolean defaultValue = false; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (mAdapter.isEnabled()) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.groupRemoveNode(group_id, device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; } + return defaultValue; } /** @@ -695,22 +742,23 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { public boolean setConnectionPolicy(@NonNull BluetoothDevice device, @ConnectionPolicy int connectionPolicy) { if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")"); - try { - final IBluetoothLeAudio service = getService(); - if (service != null && mAdapter.isEnabled() - && isValidDevice(device)) { - if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN - && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) { - return false; - } - return service.setConnectionPolicy(device, connectionPolicy, mAttributionSource); + final IBluetoothLeAudio service = getService(); + final boolean defaultValue = false; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (mAdapter.isEnabled() && isValidDevice(device) + && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN + || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; } + return defaultValue; } /** @@ -728,18 +776,21 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public @ConnectionPolicy int getConnectionPolicy(@Nullable BluetoothDevice device) { if (VDBG) log("getConnectionPolicy(" + device + ")"); - try { - final IBluetoothLeAudio service = getService(); - if (service != null && mAdapter.isEnabled() - && isValidDevice(device)) { - return service.getConnectionPolicy(device, mAttributionSource); + final IBluetoothLeAudio service = getService(); + final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (mAdapter.isEnabled() && isValidDevice(device)) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getConnectionPolicy(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; } + return defaultValue; } diff --git a/core/java/android/bluetooth/BluetoothMap.java b/core/java/android/bluetooth/BluetoothMap.java index 474e41f4aa197939b8aa13086ed6822ebb06679c..56e4972624210383660b647fef1f79385a1af648 100644 --- a/core/java/android/bluetooth/BluetoothMap.java +++ b/core/java/android/bluetooth/BluetoothMap.java @@ -16,6 +16,8 @@ package android.bluetooth; +import static android.bluetooth.BluetoothUtils.getSyncTimeout; + import android.Manifest; import android.annotation.NonNull; import android.annotation.RequiresNoPermission; @@ -28,15 +30,17 @@ import android.bluetooth.annotations.RequiresBluetoothConnectPermission; import android.compat.annotation.UnsupportedAppUsage; import android.content.AttributionSource; import android.content.Context; -import android.os.Binder; import android.os.Build; import android.os.IBinder; import android.os.RemoteException; import android.util.CloseGuard; import android.util.Log; +import com.android.modules.utils.SynchronousResultReceiver; + import java.util.ArrayList; import java.util.List; +import java.util.concurrent.TimeoutException; /** * This class provides the APIs to control the Bluetooth MAP @@ -87,7 +91,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { "BluetoothMap", IBluetoothMap.class.getName()) { @Override public IBluetoothMap getServiceInterface(IBinder service) { - return IBluetoothMap.Stub.asInterface(Binder.allowBlocking(service)); + return IBluetoothMap.Stub.asInterface(service); } }; @@ -142,17 +146,20 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { public int getState() { if (VDBG) log("getState()"); final IBluetoothMap service = getService(); - if (service != null) { - try { - return service.getState(mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); - } - } else { + final int defaultValue = BluetoothMap.STATE_ERROR; + 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.getState(mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } } - return BluetoothMap.STATE_ERROR; + return defaultValue; } /** @@ -168,18 +175,23 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { public BluetoothDevice getClient() { if (VDBG) log("getClient()"); final IBluetoothMap service = getService(); - if (service != null) { + final BluetoothDevice defaultValue = null; + 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.getClient(mAttributionSource, recv); return Attributable.setAttributionSource( - service.getClient(mAttributionSource), mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), + mAttributionSource); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - } else { - Log.w(TAG, "Proxy not attached to service"); - if (DBG) log(Log.getStackTraceString(new Throwable())); } - return null; + return defaultValue; } /** @@ -194,17 +206,20 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { public boolean isConnected(BluetoothDevice device) { if (VDBG) log("isConnected(" + device + ")"); final IBluetoothMap service = getService(); - if (service != null) { - try { - return service.isConnected(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); - } - } else { + 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() && isValidDevice(device)) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.isConnected(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } } - return false; + return defaultValue; } /** @@ -233,16 +248,20 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); final IBluetoothMap service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + 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() && isValidDevice(device)) { try { - return service.disconnect(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return false; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.disconnect(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -284,17 +303,23 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { public @NonNull List getConnectedDevices() { if (DBG) log("getConnectedDevices()"); final IBluetoothMap service = getService(); - if (service != null && isEnabled()) { + final List defaultValue = new ArrayList(); + 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.getConnectedDevices(mAttributionSource, recv); return Attributable.setAttributionSource( - service.getConnectedDevices(mAttributionSource), mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return new ArrayList(); + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), + mAttributionSource); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList(); + return defaultValue; } /** @@ -309,18 +334,23 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { public List getDevicesMatchingConnectionStates(int[] states) { if (DBG) log("getDevicesMatchingStates()"); final IBluetoothMap service = getService(); - if (service != null && isEnabled()) { + final List defaultValue = new ArrayList(); + 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.getDevicesMatchingConnectionStates(states, mAttributionSource, recv); return Attributable.setAttributionSource( - service.getDevicesMatchingConnectionStates(states, mAttributionSource), + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return new ArrayList(); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList(); + return defaultValue; } /** @@ -335,16 +365,21 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { public int getConnectionState(BluetoothDevice device) { if (DBG) log("getConnectionState(" + device + ")"); final IBluetoothMap service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final int defaultValue = BluetoothProfile.STATE_DISCONNECTED; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { try { - return service.getConnectionState(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return BluetoothProfile.STATE_DISCONNECTED; + final SynchronousResultReceiver recv = + new SynchronousResultReceiver(); + service.getConnectionState(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return BluetoothProfile.STATE_DISCONNECTED; + return defaultValue; } /** @@ -390,20 +425,22 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { @ConnectionPolicy int connectionPolicy) { if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")"); final IBluetoothMap service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { - if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN - && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) { - return false; - } + 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() && isValidDevice(device) + && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN + || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) { try { - return service.setConnectionPolicy(device, connectionPolicy, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return false; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -446,16 +483,20 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) { if (VDBG) log("getConnectionPolicy(" + device + ")"); final IBluetoothMap service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { try { - return service.getConnectionPolicy(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getConnectionPolicy(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; + return defaultValue; } private static void log(String msg) { diff --git a/core/java/android/bluetooth/BluetoothMapClient.java b/core/java/android/bluetooth/BluetoothMapClient.java index 8a3f80164aebef277836cf2495a91a93960162ea..03536f9aad39d5bbb1b8758031968f5b0bf10554 100644 --- a/core/java/android/bluetooth/BluetoothMapClient.java +++ b/core/java/android/bluetooth/BluetoothMapClient.java @@ -16,6 +16,8 @@ package android.bluetooth; +import static android.bluetooth.BluetoothUtils.getSyncTimeout; + import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; @@ -29,15 +31,17 @@ import android.compat.annotation.UnsupportedAppUsage; import android.content.AttributionSource; import android.content.Context; import android.net.Uri; -import android.os.Binder; import android.os.Build; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; +import com.android.modules.utils.SynchronousResultReceiver; + import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.concurrent.TimeoutException; /** * This class provides the APIs to control the Bluetooth MAP MCE Profile. @@ -180,7 +184,7 @@ public final class BluetoothMapClient implements BluetoothProfile { "BluetoothMapClient", IBluetoothMapClient.class.getName()) { @Override public IBluetoothMapClient getServiceInterface(IBinder service) { - return IBluetoothMapClient.Stub.asInterface(Binder.allowBlocking(service)); + return IBluetoothMapClient.Stub.asInterface(service); } }; @@ -221,17 +225,20 @@ public final class BluetoothMapClient implements BluetoothProfile { public boolean isConnected(BluetoothDevice device) { if (VDBG) Log.d(TAG, "isConnected(" + device + ")"); final IBluetoothMapClient service = getService(); - if (service != null) { - try { - return service.isConnected(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); - } - } else { + final boolean defaultValue = false; + if (service == null) { Log.w(TAG, "Proxy not attached to service"); if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } else if (isEnabled()) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.isConnected(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } } - return false; + return defaultValue; } /** @@ -248,17 +255,20 @@ public final class BluetoothMapClient implements BluetoothProfile { public boolean connect(BluetoothDevice device) { if (DBG) Log.d(TAG, "connect(" + device + ")" + "for MAPS MCE"); final IBluetoothMapClient service = getService(); - if (service != null) { - try { - return service.connect(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); - } - } else { + final boolean defaultValue = false; + if (service == null) { Log.w(TAG, "Proxy not attached to service"); if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.connect(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } } - return false; + return defaultValue; } /** @@ -277,15 +287,20 @@ public final class BluetoothMapClient implements BluetoothProfile { public boolean disconnect(BluetoothDevice device) { if (DBG) Log.d(TAG, "disconnect(" + device + ")"); final IBluetoothMapClient service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final boolean defaultValue = false; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { try { - return service.disconnect(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.disconnect(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -300,17 +315,23 @@ public final class BluetoothMapClient implements BluetoothProfile { public List getConnectedDevices() { if (DBG) Log.d(TAG, "getConnectedDevices()"); final IBluetoothMapClient service = getService(); - if (service != null && isEnabled()) { + final List defaultValue = new ArrayList<>(); + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } else if (isEnabled()) { try { + final SynchronousResultReceiver> recv = + new SynchronousResultReceiver(); + service.getConnectedDevices(mAttributionSource, recv); return Attributable.setAttributionSource( - service.getConnectedDevices(mAttributionSource), mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return new ArrayList<>(); + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), + mAttributionSource); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList<>(); + return defaultValue; } /** @@ -325,18 +346,23 @@ public final class BluetoothMapClient implements BluetoothProfile { public List getDevicesMatchingConnectionStates(int[] states) { if (DBG) Log.d(TAG, "getDevicesMatchingStates()"); final IBluetoothMapClient service = getService(); - if (service != null && isEnabled()) { + final List defaultValue = new ArrayList<>(); + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } else if (isEnabled()) { try { + final SynchronousResultReceiver> recv = + new SynchronousResultReceiver(); + service.getDevicesMatchingConnectionStates(states, mAttributionSource, recv); return Attributable.setAttributionSource( - service.getDevicesMatchingConnectionStates(states, mAttributionSource), + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return new ArrayList<>(); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList<>(); + return defaultValue; } /** @@ -351,16 +377,20 @@ public final class BluetoothMapClient implements BluetoothProfile { public int getConnectionState(BluetoothDevice device) { if (DBG) Log.d(TAG, "getConnectionState(" + device + ")"); final IBluetoothMapClient service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final int defaultValue = BluetoothProfile.STATE_DISCONNECTED; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { try { - return service.getConnectionState(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return BluetoothProfile.STATE_DISCONNECTED; + final SynchronousResultReceiver recv = new SynchronousResultReceiver<>(); + service.getConnectionState(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return BluetoothProfile.STATE_DISCONNECTED; + return defaultValue; } /** @@ -405,20 +435,22 @@ public final class BluetoothMapClient implements BluetoothProfile { @ConnectionPolicy int connectionPolicy) { if (DBG) Log.d(TAG, "setConnectionPolicy(" + device + ", " + connectionPolicy + ")"); final IBluetoothMapClient service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { - if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN - && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) { - return false; - } + final boolean defaultValue = false; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device) + && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN + || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) { try { - return service.setConnectionPolicy(device, connectionPolicy, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return false; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -460,16 +492,20 @@ public final class BluetoothMapClient implements BluetoothProfile { public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) { if (VDBG) Log.d(TAG, "getConnectionPolicy(" + device + ")"); final IBluetoothMapClient service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { try { - return service.getConnectionPolicy(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getConnectionPolicy(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; + return defaultValue; } /** @@ -494,18 +530,8 @@ public final class BluetoothMapClient implements BluetoothProfile { public boolean sendMessage(@NonNull BluetoothDevice device, @NonNull Collection contacts, @NonNull String message, @Nullable PendingIntent sentIntent, @Nullable PendingIntent deliveredIntent) { - if (DBG) Log.d(TAG, "sendMessage(" + device + ", " + contacts + ", " + message); - final IBluetoothMapClient service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { - try { - return service.sendMessage(device, contacts.toArray(new Uri[contacts.size()]), - message, sentIntent, deliveredIntent, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return false; - } - } - return false; + return sendMessage(device, contacts.toArray(new Uri[contacts.size()]), message, sentIntent, + deliveredIntent); } /** @@ -531,16 +557,21 @@ public final class BluetoothMapClient implements BluetoothProfile { PendingIntent sentIntent, PendingIntent deliveredIntent) { if (DBG) Log.d(TAG, "sendMessage(" + device + ", " + contacts + ", " + message); final IBluetoothMapClient service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final boolean defaultValue = false; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { try { - return service.sendMessage(device, contacts, message, sentIntent, deliveredIntent, - mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return false; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.sendMessage(device, contacts, message, sentIntent, deliveredIntent, + mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - return false; + return defaultValue; } /** @@ -558,15 +589,20 @@ public final class BluetoothMapClient implements BluetoothProfile { public boolean getUnreadMessages(BluetoothDevice device) { if (DBG) Log.d(TAG, "getUnreadMessages(" + device + ")"); final IBluetoothMapClient service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final boolean defaultValue = false; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { try { - return service.getUnreadMessages(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return false; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getUnreadMessages(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - return false; + return defaultValue; } /** @@ -580,13 +616,21 @@ public final class BluetoothMapClient implements BluetoothProfile { @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean isUploadingSupported(BluetoothDevice device) { + if (DBG) Log.d(TAG, "isUploadingSupported(" + device + ")"); final IBluetoothMapClient service = getService(); - try { - return (service != null && isEnabled() && isValidDevice(device)) - && ((service.getSupportedFeatures(device, mAttributionSource) - & UPLOADING_FEATURE_BITMASK) > 0); - } catch (RemoteException e) { - Log.e(TAG, e.getMessage()); + final int defaultValue = 0; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getSupportedFeatures(device, mAttributionSource, recv); + return (recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue) + & UPLOADING_FEATURE_BITMASK) > 0; + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } } return false; } @@ -615,16 +659,21 @@ public final class BluetoothMapClient implements BluetoothProfile { public boolean setMessageStatus(BluetoothDevice device, String handle, int status) { if (DBG) Log.d(TAG, "setMessageStatus(" + device + ", " + handle + ", " + status + ")"); final IBluetoothMapClient service = getService(); - if (service != null && isEnabled() && isValidDevice(device) && handle != null && - (status == READ || status == UNREAD || status == UNDELETED || status == DELETED)) { + final boolean defaultValue = false; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device) && handle != null && (status == READ + || status == UNREAD || status == UNDELETED || status == DELETED)) { try { - return service.setMessageStatus(device, handle, status, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return false; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.setMessageStatus(device, handle, status, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - return false; + return defaultValue; } private boolean isEnabled() { diff --git a/core/java/android/bluetooth/BluetoothPan.java b/core/java/android/bluetooth/BluetoothPan.java index ac7a52d8f636717f92df33a897cc0846ae90dd85..d4ad4ef47acd7626d1ac24c38df7d4f614d71a18 100644 --- a/core/java/android/bluetooth/BluetoothPan.java +++ b/core/java/android/bluetooth/BluetoothPan.java @@ -16,6 +16,8 @@ package android.bluetooth; +import static android.bluetooth.BluetoothUtils.getSyncTimeout; + import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.RequiresPermission; @@ -28,16 +30,18 @@ import android.bluetooth.annotations.RequiresLegacyBluetoothPermission; import android.compat.annotation.UnsupportedAppUsage; import android.content.AttributionSource; import android.content.Context; -import android.os.Binder; import android.os.Build; import android.os.IBinder; import android.os.RemoteException; 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; /** * This class provides the APIs to control the Bluetooth Pan @@ -188,7 +192,7 @@ public final class BluetoothPan implements BluetoothProfile { "BluetoothPan", IBluetoothPan.class.getName()) { @Override public IBluetoothPan getServiceInterface(IBinder service) { - return IBluetoothPan.Stub.asInterface(Binder.allowBlocking(service)); + return IBluetoothPan.Stub.asInterface(service); } }; @@ -249,16 +253,20 @@ public final class BluetoothPan implements BluetoothProfile { public boolean connect(BluetoothDevice device) { if (DBG) log("connect(" + device + ")"); final IBluetoothPan service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + 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() && isValidDevice(device)) { try { - return service.connect(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.connect(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -289,16 +297,20 @@ public final class BluetoothPan implements BluetoothProfile { public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); final IBluetoothPan service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + 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() && isValidDevice(device)) { try { - return service.disconnect(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.disconnect(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -322,22 +334,23 @@ public final class BluetoothPan implements BluetoothProfile { public boolean setConnectionPolicy(@NonNull BluetoothDevice device, @ConnectionPolicy int connectionPolicy) { if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")"); - try { - final IBluetoothPan service = getService(); - if (service != null && isEnabled() - && isValidDevice(device)) { - if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN - && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) { - return false; - } - return service.setConnectionPolicy(device, connectionPolicy, mAttributionSource); + final IBluetoothPan service = getService(); + 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() && isValidDevice(device) + && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN + || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; } + return defaultValue; } /** @@ -354,17 +367,23 @@ public final class BluetoothPan implements BluetoothProfile { public @NonNull List getConnectedDevices() { if (VDBG) log("getConnectedDevices()"); final IBluetoothPan service = getService(); - if (service != null && isEnabled()) { + final List defaultValue = new ArrayList(); + 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.getConnectedDevices(mAttributionSource, recv); return Attributable.setAttributionSource( - service.getConnectedDevices(mAttributionSource), mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return new ArrayList(); + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), + mAttributionSource); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList(); + return defaultValue; } /** @@ -381,18 +400,23 @@ public final class BluetoothPan implements BluetoothProfile { public List getDevicesMatchingConnectionStates(int[] states) { if (VDBG) log("getDevicesMatchingStates()"); final IBluetoothPan service = getService(); - if (service != null && isEnabled()) { + final List defaultValue = new ArrayList(); + 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.getDevicesMatchingConnectionStates(states, mAttributionSource, recv); return Attributable.setAttributionSource( - service.getDevicesMatchingConnectionStates(states, mAttributionSource), + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return new ArrayList(); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList(); + return defaultValue; } /** @@ -409,16 +433,20 @@ public final class BluetoothPan implements BluetoothProfile { public int getConnectionState(@NonNull BluetoothDevice device) { if (VDBG) log("getState(" + device + ")"); final IBluetoothPan service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final int defaultValue = BluetoothProfile.STATE_DISCONNECTED; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { try { - return service.getConnectionState(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return BluetoothProfile.STATE_DISCONNECTED; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getConnectionState(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return BluetoothProfile.STATE_DISCONNECTED; + return defaultValue; } /** @@ -438,11 +466,16 @@ public final class BluetoothPan implements BluetoothProfile { String pkgName = mContext.getOpPackageName(); if (DBG) log("setBluetoothTethering(" + value + "), calling package:" + pkgName); final IBluetoothPan service = getService(); - if (service != null && isEnabled()) { + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled()) { try { - service.setBluetoothTethering(value, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.setBluetoothTethering(value, mAttributionSource, recv); + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } } @@ -459,14 +492,20 @@ public final class BluetoothPan implements BluetoothProfile { public boolean isTetheringOn() { if (VDBG) log("isTetheringOn()"); final IBluetoothPan service = getService(); - if (service != null && isEnabled()) { + 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 { - return service.isTetheringOn(mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.isTetheringOn(mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - return false; + return defaultValue; } @UnsupportedAppUsage diff --git a/core/java/android/bluetooth/BluetoothPbapClient.java b/core/java/android/bluetooth/BluetoothPbapClient.java index cc91ad258d037f0edab2021b96753a4676acfa2e..e096de8cb829bf149809917ad84ba3320282a9e9 100644 --- a/core/java/android/bluetooth/BluetoothPbapClient.java +++ b/core/java/android/bluetooth/BluetoothPbapClient.java @@ -16,6 +16,8 @@ package android.bluetooth; +import static android.bluetooth.BluetoothUtils.getSyncTimeout; + import android.Manifest; import android.annotation.NonNull; import android.annotation.RequiresPermission; @@ -24,13 +26,15 @@ import android.annotation.SdkConstant.SdkConstantType; import android.bluetooth.annotations.RequiresBluetoothConnectPermission; import android.content.AttributionSource; import android.content.Context; -import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; +import com.android.modules.utils.SynchronousResultReceiver; + import java.util.ArrayList; import java.util.List; +import java.util.concurrent.TimeoutException; /** * This class provides the APIs to control the Bluetooth PBAP Client Profile. @@ -64,7 +68,7 @@ public final class BluetoothPbapClient implements BluetoothProfile { "BluetoothPbapClient", IBluetoothPbapClient.class.getName()) { @Override public IBluetoothPbapClient getServiceInterface(IBinder service) { - return IBluetoothPbapClient.Stub.asInterface(Binder.allowBlocking(service)); + return IBluetoothPbapClient.Stub.asInterface(service); } }; @@ -123,18 +127,20 @@ public final class BluetoothPbapClient implements BluetoothProfile { log("connect(" + device + ") for PBAP Client."); } final IBluetoothPbapClient service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { - try { - return service.connect(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return false; - } - } + 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() && isValidDevice(device)) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.connect(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } } - return false; + return defaultValue; } /** @@ -155,19 +161,21 @@ public final class BluetoothPbapClient implements BluetoothProfile { log("disconnect(" + device + ")" + new Exception()); } final IBluetoothPbapClient service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final boolean defaultValue = true; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { try { - service.disconnect(device, mAttributionSource); + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.disconnect(device, mAttributionSource, recv); + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); return true; - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return false; + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) { - Log.w(TAG, "Proxy not attached to service"); - } - return false; + return defaultValue; } /** @@ -184,19 +192,23 @@ public final class BluetoothPbapClient implements BluetoothProfile { log("getConnectedDevices()"); } final IBluetoothPbapClient service = getService(); - if (service != null && isEnabled()) { + final List defaultValue = new ArrayList(); + 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.getConnectedDevices(mAttributionSource, recv); return Attributable.setAttributionSource( - service.getConnectedDevices(mAttributionSource), mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return new ArrayList(); + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), + mAttributionSource); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) { - Log.w(TAG, "Proxy not attached to service"); - } - return new ArrayList(); + return defaultValue; } /** @@ -212,20 +224,23 @@ public final class BluetoothPbapClient implements BluetoothProfile { log("getDevicesMatchingStates()"); } final IBluetoothPbapClient service = getService(); - if (service != null && isEnabled()) { + final List defaultValue = new ArrayList(); + 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.getDevicesMatchingConnectionStates(states, mAttributionSource, recv); return Attributable.setAttributionSource( - service.getDevicesMatchingConnectionStates(states, mAttributionSource), + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return new ArrayList(); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) { - Log.w(TAG, "Proxy not attached to service"); - } - return new ArrayList(); + return defaultValue; } /** @@ -241,18 +256,20 @@ public final class BluetoothPbapClient implements BluetoothProfile { log("getConnectionState(" + device + ")"); } final IBluetoothPbapClient service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { - try { - return service.getConnectionState(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return BluetoothProfile.STATE_DISCONNECTED; - } - } + final int defaultValue = BluetoothProfile.STATE_DISCONNECTED; if (service == null) { Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getConnectionState(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } } - return BluetoothProfile.STATE_DISCONNECTED; + return defaultValue; } private static void log(String msg) { @@ -311,22 +328,22 @@ public final class BluetoothPbapClient implements BluetoothProfile { log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")"); } final IBluetoothPbapClient service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { - if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN - && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) { - return false; - } - try { - return service.setConnectionPolicy(device, connectionPolicy, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return false; - } - } + 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() && isValidDevice(device) + && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN + || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } } - return false; + return defaultValue; } /** @@ -370,17 +387,19 @@ public final class BluetoothPbapClient implements BluetoothProfile { log("getConnectionPolicy(" + device + ")"); } final IBluetoothPbapClient service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { - try { - return service.getConnectionPolicy(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; - } - } + final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; if (service == null) { Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getConnectionPolicy(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } } - return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; + return defaultValue; } } diff --git a/core/java/android/bluetooth/BluetoothSap.java b/core/java/android/bluetooth/BluetoothSap.java index ab2b8eaaa36e7c9ead50c1b8c4adf32e72c42f79..808fa3913316527efa62c076c442b930ff971cb3 100644 --- a/core/java/android/bluetooth/BluetoothSap.java +++ b/core/java/android/bluetooth/BluetoothSap.java @@ -16,6 +16,8 @@ package android.bluetooth; +import static android.bluetooth.BluetoothUtils.getSyncTimeout; + import android.Manifest; import android.annotation.RequiresNoPermission; import android.annotation.RequiresPermission; @@ -26,14 +28,16 @@ import android.bluetooth.annotations.RequiresLegacyBluetoothPermission; import android.compat.annotation.UnsupportedAppUsage; import android.content.AttributionSource; import android.content.Context; -import android.os.Binder; import android.os.Build; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; +import com.android.modules.utils.SynchronousResultReceiver; + import java.util.ArrayList; import java.util.List; +import java.util.concurrent.TimeoutException; /** * This class provides the APIs to control the Bluetooth SIM @@ -104,7 +108,7 @@ public final class BluetoothSap implements BluetoothProfile { "BluetoothSap", IBluetoothSap.class.getName()) { @Override public IBluetoothSap getServiceInterface(IBinder service) { - return IBluetoothSap.Stub.asInterface(Binder.allowBlocking(service)); + return IBluetoothSap.Stub.asInterface(service); } }; @@ -155,17 +159,20 @@ public final class BluetoothSap implements BluetoothProfile { public int getState() { if (VDBG) log("getState()"); final IBluetoothSap service = getService(); - if (service != null) { - try { - return service.getState(mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); - } - } else { + final int defaultValue = BluetoothSap.STATE_ERROR; + 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.getState(mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } } - return BluetoothSap.STATE_ERROR; + return defaultValue; } /** @@ -180,18 +187,23 @@ public final class BluetoothSap implements BluetoothProfile { public BluetoothDevice getClient() { if (VDBG) log("getClient()"); final IBluetoothSap service = getService(); - if (service != null) { + final BluetoothDevice defaultValue = null; + 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.getClient(mAttributionSource, recv); return Attributable.setAttributionSource( - service.getClient(mAttributionSource), mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), + mAttributionSource); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - } else { - Log.w(TAG, "Proxy not attached to service"); - if (DBG) log(Log.getStackTraceString(new Throwable())); } - return null; + return defaultValue; } /** @@ -206,17 +218,20 @@ public final class BluetoothSap implements BluetoothProfile { public boolean isConnected(BluetoothDevice device) { if (VDBG) log("isConnected(" + device + ")"); final IBluetoothSap service = getService(); - if (service != null) { - try { - return service.isConnected(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); - } - } else { + 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 recv = new SynchronousResultReceiver(); + service.isConnected(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } } - return false; + return defaultValue; } /** @@ -244,16 +259,20 @@ public final class BluetoothSap implements BluetoothProfile { public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); final IBluetoothSap service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + 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() && isValidDevice(device)) { try { - return service.disconnect(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return false; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.disconnect(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -267,17 +286,23 @@ public final class BluetoothSap implements BluetoothProfile { public List getConnectedDevices() { if (DBG) log("getConnectedDevices()"); final IBluetoothSap service = getService(); - if (service != null && isEnabled()) { + final List defaultValue = new ArrayList(); + 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.getConnectedDevices(mAttributionSource, recv); return Attributable.setAttributionSource( - service.getConnectedDevices(mAttributionSource), mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return new ArrayList(); + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), + mAttributionSource); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList(); + return defaultValue; } /** @@ -291,18 +316,23 @@ public final class BluetoothSap implements BluetoothProfile { public List getDevicesMatchingConnectionStates(int[] states) { if (DBG) log("getDevicesMatchingStates()"); final IBluetoothSap service = getService(); - if (service != null && isEnabled()) { + final List defaultValue = new ArrayList(); + 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.getDevicesMatchingConnectionStates(states, mAttributionSource, recv); return Attributable.setAttributionSource( - service.getDevicesMatchingConnectionStates(states, mAttributionSource), + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return new ArrayList(); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList(); + return defaultValue; } /** @@ -316,16 +346,20 @@ public final class BluetoothSap implements BluetoothProfile { public int getConnectionState(BluetoothDevice device) { if (DBG) log("getConnectionState(" + device + ")"); final IBluetoothSap service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final int defaultValue = BluetoothProfile.STATE_DISCONNECTED; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { try { - return service.getConnectionState(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return BluetoothProfile.STATE_DISCONNECTED; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getConnectionState(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return BluetoothProfile.STATE_DISCONNECTED; + return defaultValue; } /** @@ -370,20 +404,22 @@ public final class BluetoothSap implements BluetoothProfile { @ConnectionPolicy int connectionPolicy) { if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")"); final IBluetoothSap service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { - if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN - && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) { - return false; - } + 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() && isValidDevice(device) + && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN + || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) { try { - return service.setConnectionPolicy(device, connectionPolicy, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return false; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -425,16 +461,20 @@ public final class BluetoothSap implements BluetoothProfile { public @ConnectionPolicy int getConnectionPolicy(BluetoothDevice device) { if (VDBG) log("getConnectionPolicy(" + device + ")"); final IBluetoothSap service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { try { - return service.getConnectionPolicy(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getConnectionPolicy(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; + return defaultValue; } private static void log(String msg) { diff --git a/core/java/android/bluetooth/BluetoothUtils.java b/core/java/android/bluetooth/BluetoothUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..867469241f84c778e66bc000817b2fdea18919f6 --- /dev/null +++ b/core/java/android/bluetooth/BluetoothUtils.java @@ -0,0 +1,41 @@ +/* + * 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 java.time.Duration; + +/** + * {@hide} + */ +public final class BluetoothUtils { + /** + * This utility class cannot be instantiated + */ + private BluetoothUtils() {} + + /** + * Timeout value for synchronous binder call + */ + private static final Duration SYNC_CALLS_TIMEOUT = Duration.ofSeconds(5); + + /** + * @return timeout value for synchronous binder call + */ + static Duration getSyncTimeout() { + return SYNC_CALLS_TIMEOUT; + } +} diff --git a/core/java/android/bluetooth/BluetoothVolumeControl.java b/core/java/android/bluetooth/BluetoothVolumeControl.java index ba83eca423f47200e5b36411bdf4a288979adad0..27532aabc3fcd79f819a73c6a304d26fb6391c5e 100644 --- a/core/java/android/bluetooth/BluetoothVolumeControl.java +++ b/core/java/android/bluetooth/BluetoothVolumeControl.java @@ -17,6 +17,8 @@ package android.bluetooth; +import static android.bluetooth.BluetoothUtils.getSyncTimeout; + import android.Manifest; import android.annotation.IntRange; import android.annotation.NonNull; @@ -29,14 +31,16 @@ import android.annotation.SystemApi; import android.bluetooth.annotations.RequiresBluetoothConnectPermission; import android.content.AttributionSource; import android.content.Context; -import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; import android.util.CloseGuard; import android.util.Log; +import com.android.modules.utils.SynchronousResultReceiver; + import java.util.ArrayList; import java.util.List; +import java.util.concurrent.TimeoutException; /** * This class provides the public APIs to control the Bluetooth Volume Control service. @@ -86,7 +90,7 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose IBluetoothVolumeControl.class.getName()) { @Override public IBluetoothVolumeControl getServiceInterface(IBinder service) { - return IBluetoothVolumeControl.Stub.asInterface(Binder.allowBlocking(service)); + return IBluetoothVolumeControl.Stub.asInterface(service); } }; @@ -134,17 +138,23 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose public @NonNull List getConnectedDevices() { if (DBG) log("getConnectedDevices()"); final IBluetoothVolumeControl service = getService(); - if (service != null && isEnabled()) { + final List defaultValue = new ArrayList(); + 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.getConnectedDevices(mAttributionSource, recv); return Attributable.setAttributionSource( - service.getConnectedDevices(mAttributionSource), mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return new ArrayList(); + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), + mAttributionSource); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList(); + return defaultValue; } /** @@ -159,18 +169,23 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose public List getDevicesMatchingConnectionStates(int[] states) { if (DBG) log("getDevicesMatchingStates()"); final IBluetoothVolumeControl service = getService(); - if (service != null && isEnabled()) { + final List defaultValue = new ArrayList(); + 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.getDevicesMatchingConnectionStates(states, mAttributionSource, recv); return Attributable.setAttributionSource( - service.getDevicesMatchingConnectionStates(states, mAttributionSource), + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return new ArrayList(); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList(); + return defaultValue; } /** @@ -185,16 +200,20 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose public int getConnectionState(BluetoothDevice device) { if (DBG) log("getConnectionState(" + device + ")"); final IBluetoothVolumeControl service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final int defaultValue = BluetoothProfile.STATE_DISCONNECTED; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { try { - return service.getConnectionState(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return BluetoothProfile.STATE_DISCONNECTED; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getConnectionState(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return BluetoothProfile.STATE_DISCONNECTED; + return defaultValue; } /** @@ -212,18 +231,19 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose }) public void setVolume(@Nullable BluetoothDevice device, @IntRange(from = 0, to = 255) int volume) { - if (DBG) - log("setVolume(" + volume + ")"); + if (DBG) log("setVolume(" + volume + ")"); final IBluetoothVolumeControl service = getService(); - try { - if (service != null && isEnabled()) { - service.setVolume(device, volume, mAttributionSource); - return; + 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.setVolume(device, volume, mAttributionSource, recv); + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - if (service == null) - Log.w(TAG, "Proxy not attached to service"); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); } } @@ -249,20 +269,22 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose @ConnectionPolicy int connectionPolicy) { if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")"); final IBluetoothVolumeControl service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { - if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN - && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) { - return false; - } + 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() && isValidDevice(device) + && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN + || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) { try { - return service.setConnectionPolicy(device, connectionPolicy, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return false; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -285,16 +307,20 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) { if (VDBG) log("getConnectionPolicy(" + device + ")"); final IBluetoothVolumeControl service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { try { - return service.getConnectionPolicy(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getConnectionPolicy(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; + return defaultValue; } private boolean isEnabled() {