summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp1
-rw-r--r--core/api/current.txt16
-rw-r--r--core/api/module-lib-current.txt6
-rw-r--r--core/api/system-current.txt8
-rw-r--r--core/java/android/app/SystemServiceRegistry.java7
-rw-r--r--core/java/android/app/cloudsearch/OWNERS4
-rw-r--r--core/java/android/bluetooth/BluetoothA2dp.java511
-rwxr-xr-xcore/java/android/bluetooth/BluetoothA2dpSink.java183
-rw-r--r--core/java/android/bluetooth/BluetoothAdapter.java2
-rw-r--r--core/java/android/bluetooth/BluetoothAvrcpController.java135
-rw-r--r--core/java/android/bluetooth/BluetoothCsipSetCoordinator.java260
-rw-r--r--core/java/android/bluetooth/BluetoothDevice.java2
-rw-r--r--core/java/android/bluetooth/BluetoothGatt.java10
-rw-r--r--core/java/android/bluetooth/BluetoothHeadset.java540
-rw-r--r--core/java/android/bluetooth/BluetoothHeadsetClient.java581
-rw-r--r--core/java/android/bluetooth/BluetoothHearingAid.java302
-rw-r--r--core/java/android/bluetooth/BluetoothHidDevice.java264
-rw-r--r--core/java/android/bluetooth/BluetoothHidHost.java291
-rw-r--r--core/java/android/bluetooth/BluetoothLeAudio.java307
-rw-r--r--core/java/android/bluetooth/BluetoothManager.java34
-rw-r--r--core/java/android/bluetooth/BluetoothMap.java185
-rw-r--r--core/java/android/bluetooth/BluetoothMapClient.java251
-rw-r--r--core/java/android/bluetooth/BluetoothPan.java159
-rw-r--r--core/java/android/bluetooth/BluetoothPbap.java135
-rw-r--r--core/java/android/bluetooth/BluetoothPbapClient.java157
-rw-r--r--core/java/android/bluetooth/BluetoothProfileConnector.java32
-rw-r--r--core/java/android/bluetooth/BluetoothSap.java184
-rw-r--r--core/java/android/bluetooth/BluetoothUtils.java41
-rw-r--r--core/java/android/bluetooth/BluetoothVolumeControl.java128
-rw-r--r--core/java/android/bluetooth/le/BluetoothLeScanner.java13
-rw-r--r--core/java/android/content/AttributionSource.java43
-rw-r--r--core/java/android/content/Intent.java12
-rw-r--r--core/java/android/net/NetworkPolicy.java29
-rw-r--r--core/java/android/os/Binder.java7
-rw-r--r--core/java/android/os/SystemVibrator.java2
-rw-r--r--core/java/android/provider/Settings.java8
-rw-r--r--core/java/android/service/cloudsearch/OWNERS4
-rw-r--r--core/java/android/telephony/TelephonyRegistryManager.java119
-rw-r--r--core/java/com/android/internal/net/NetworkUtilsInternal.java31
-rw-r--r--core/java/com/android/internal/telephony/ICarrierPrivilegesListener.aidl22
-rw-r--r--core/java/com/android/internal/telephony/ITelephonyRegistry.aidl7
-rw-r--r--core/jni/OWNERS6
-rw-r--r--core/proto/android/providers/settings/global.proto2
-rw-r--r--core/tests/coretests/src/android/net/NetworkPolicyTest.kt28
-rw-r--r--media/java/android/media/AudioManager.java83
-rw-r--r--media/java/android/media/MediaActionSound.java25
-rw-r--r--media/java/android/media/tv/TvContract.java62
-rw-r--r--packages/ConnectivityT/framework-t/Android.bp18
-rw-r--r--packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java11
-rw-r--r--packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java (renamed from core/java/android/net/EthernetManager.java)0
-rw-r--r--packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkSpecifier.java (renamed from core/java/android/net/EthernetNetworkSpecifier.java)0
-rw-r--r--packages/ConnectivityT/framework-t/src/android/net/IEthernetManager.aidl (renamed from core/java/android/net/IEthernetManager.aidl)0
-rw-r--r--packages/ConnectivityT/framework-t/src/android/net/IEthernetServiceListener.aidl (renamed from core/java/android/net/IEthernetServiceListener.aidl)0
-rw-r--r--packages/ConnectivityT/framework-t/src/android/net/ITetheredInterfaceCallback.aidl (renamed from core/java/android/net/ITetheredInterfaceCallback.aidl)0
-rw-r--r--packages/ConnectivityT/framework-t/src/android/net/IpSecAlgorithm.java9
-rw-r--r--packages/ConnectivityT/framework-t/src/android/net/IpSecManager.java6
-rw-r--r--packages/ConnectivityT/framework-t/src/android/net/IpSecTransform.java20
-rw-r--r--packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java2
-rw-r--r--packages/ConnectivityT/framework-t/src/android/net/NetworkStatsAccess.java14
-rw-r--r--packages/ConnectivityT/framework-t/src/android/net/NetworkStatsCollection.java2
-rw-r--r--packages/ConnectivityT/framework-t/src/android/net/NetworkStatsHistory.java2
-rw-r--r--packages/ConnectivityT/framework-t/src/android/net/NetworkTemplate.java430
-rw-r--r--packages/ConnectivityT/service/Android.bp14
-rw-r--r--packages/ConnectivityT/service/src/com/android/server/IpSecService.java194
-rw-r--r--packages/ConnectivityT/service/src/com/android/server/net/IpConfigStore.java (renamed from services/core/java/com/android/server/net/IpConfigStore.java)32
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java1
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java4
-rw-r--r--packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java1
-rw-r--r--packages/SystemUI/res/layout/internet_connectivity_dialog.xml40
-rw-r--r--packages/SystemUI/res/values/strings.xml2
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AnnotationLinkSpan.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java26
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java9
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java47
-rw-r--r--services/OWNERS2
-rw-r--r--services/cloudsearch/OWNERS4
-rw-r--r--services/core/java/com/android/server/TelephonyRegistry.java129
-rw-r--r--services/core/java/com/android/server/am/OomAdjuster.java23
-rw-r--r--services/core/java/com/android/server/audio/PlaybackActivityMonitor.java2
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java4
-rw-r--r--services/core/java/com/android/server/pm/SELinuxMMAC.java6
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java14
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java3
-rw-r--r--services/core/java/com/android/server/wm/Task.java10
-rw-r--r--services/proguard.flags14
-rw-r--r--telephony/common/com/google/android/mms/util/SqliteWrapper.java49
-rw-r--r--telephony/java/android/service/carrier/CarrierService.java68
-rw-r--r--telephony/java/android/service/carrier/ICarrierService.aidl2
-rw-r--r--telephony/java/android/telephony/CarrierConfigManager.java16
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java124
-rw-r--r--telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java4
-rw-r--r--telephony/java/com/android/internal/telephony/ITelephony.aidl10
92 files changed, 4178 insertions, 2439 deletions
diff --git a/Android.bp b/Android.bp
index ecf6deeeb432..36ed8656cfbc 100644
--- a/Android.bp
+++ b/Android.bp
@@ -350,6 +350,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",
],
diff --git a/core/api/current.txt b/core/api/current.txt
index 6aeed38e0adb..4f96abe2323e 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -9178,10 +9178,10 @@ package android.bluetooth {
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void disconnect();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean discoverServices();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean executeReliableWrite();
- method public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
- method public int getConnectionState(android.bluetooth.BluetoothDevice);
+ method @Deprecated public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
+ method @Deprecated public int getConnectionState(android.bluetooth.BluetoothDevice);
method public android.bluetooth.BluetoothDevice getDevice();
- method public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
+ method @Deprecated public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
method public android.bluetooth.BluetoothGattService getService(java.util.UUID);
method public java.util.List<android.bluetooth.BluetoothGattService> getServices();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean readCharacteristic(android.bluetooth.BluetoothGattCharacteristic);
@@ -10091,6 +10091,7 @@ package android.content {
method @Nullable public String getPackageName();
method public int getUid();
method public boolean isTrusted(@NonNull android.content.Context);
+ method @NonNull public static android.content.AttributionSource myAttributionSource();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.content.AttributionSource> CREATOR;
}
@@ -21541,6 +21542,7 @@ package android.media {
public class MediaActionSound {
ctor public MediaActionSound();
method public void load(int);
+ method public static boolean mustPlayShutterSound();
method public void play(int);
method public void release();
field public static final int FOCUS_COMPLETE = 1; // 0x1
@@ -25723,11 +25725,14 @@ package android.media.tv {
field public static final String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
field public static final String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
field public static final String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
+ field public static final String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
field public static final String COLUMN_LONG_DESCRIPTION = "long_description";
+ field public static final String COLUMN_MULTI_SERIES_ID = "multi_series_id";
field public static final String COLUMN_POSTER_ART_URI = "poster_art_uri";
field public static final String COLUMN_RECORDING_PROHIBITED = "recording_prohibited";
field public static final String COLUMN_REVIEW_RATING = "review_rating";
field public static final String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
+ field public static final String COLUMN_SCRAMBLED = "scrambled";
field public static final String COLUMN_SEARCHABLE = "searchable";
field public static final String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
field @Deprecated public static final String COLUMN_SEASON_NUMBER = "season_number";
@@ -25787,7 +25792,9 @@ package android.media.tv {
field public static final String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
field public static final String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
field public static final String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
+ field public static final String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
field public static final String COLUMN_LONG_DESCRIPTION = "long_description";
+ field public static final String COLUMN_MULTI_SERIES_ID = "multi_series_id";
field public static final String COLUMN_POSTER_ART_URI = "poster_art_uri";
field public static final String COLUMN_RECORDING_DATA_BYTES = "recording_data_bytes";
field public static final String COLUMN_RECORDING_DATA_URI = "recording_data_uri";
@@ -38284,7 +38291,8 @@ package android.service.carrier {
method @Deprecated public final void notifyCarrierNetworkChange(boolean);
method public final void notifyCarrierNetworkChange(int, boolean);
method @CallSuper public android.os.IBinder onBind(android.content.Intent);
- method public abstract android.os.PersistableBundle onLoadConfig(android.service.carrier.CarrierIdentifier);
+ method @Deprecated public abstract android.os.PersistableBundle onLoadConfig(android.service.carrier.CarrierIdentifier);
+ method @Nullable public android.os.PersistableBundle onLoadConfig(int, @Nullable android.service.carrier.CarrierIdentifier);
field public static final String CARRIER_SERVICE_INTERFACE = "android.service.carrier.CarrierService";
}
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index 81b4ee80a1d2..a646a681afc1 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -113,6 +113,8 @@ package android.media {
public class AudioManager {
method public void adjustStreamVolumeForUid(int, int, int, @NonNull String, int, int, int);
method public void adjustSuggestedStreamVolumeForUid(int, int, int, @NonNull String, int, int, int);
+ method @NonNull public java.util.List<android.bluetooth.BluetoothCodecConfig> getHwOffloadFormatsSupportedForA2dp();
+ method @NonNull public java.util.List<android.bluetooth.BluetoothLeAudioCodecConfig> getHwOffloadFormatsSupportedForLeAudio();
method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void handleBluetoothActiveDeviceChanged(@Nullable android.bluetooth.BluetoothDevice, @Nullable android.bluetooth.BluetoothDevice, @NonNull android.media.BtProfileConnectionInfo);
method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void setA2dpSuspended(boolean);
method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void setBluetoothHeadsetProperties(@NonNull String, boolean, boolean);
@@ -202,6 +204,10 @@ package android.net {
field @NonNull public static final android.os.Parcelable.Creator<android.net.EthernetNetworkSpecifier> CREATOR;
}
+ public final class IpSecManager {
+ field public static final int DIRECTION_FWD = 2; // 0x2
+ }
+
public static final class IpSecManager.UdpEncapsulationSocket implements java.lang.AutoCloseable {
method public int getResourceId();
}
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index da9a4c50d3cb..bb454a642ff1 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -12001,6 +12001,7 @@ package android.telephony {
}
public class TelephonyManager {
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void addCarrierPrivilegesListener(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CarrierPrivilegesListener);
method @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) @WorkerThread public void bootstrapAuthenticationRequest(int, @NonNull android.net.Uri, @NonNull android.telephony.gba.UaSecurityProtocolIdentifier, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.BootstrapAuthenticationCallback);
method @Deprecated @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void call(String, String);
method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telephony.PinResult changeIccLockPin(@NonNull String, @NonNull String);
@@ -12025,6 +12026,8 @@ package android.telephony {
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCarrierPrivilegeStatus(int);
method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<java.lang.String> getCarrierPrivilegedPackagesForAllActiveSubscriptions();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.CarrierRestrictionRules getCarrierRestrictionRules();
+ method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getCarrierServicePackageName();
+ method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getCarrierServicePackageNameForLogicalSlot(int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCdmaEnhancedRoamingIndicatorDisplayNumber();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMdn();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMdn(int);
@@ -12093,6 +12096,7 @@ package android.telephony {
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyOtaEmergencyNumberDbInstalled();
method @RequiresPermission(android.Manifest.permission.REBOOT) public int prepareForUnattendedReboot();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean rebootRadio();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void removeCarrierPrivilegesListener(@NonNull android.telephony.TelephonyManager.CarrierPrivilegesListener);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void reportDefaultNetworkStatus(boolean);
method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.MODIFY_PHONE_STATE}) public void requestCellInfoUpdate(@NonNull android.os.WorkSource, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void requestModemActivityInfo(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.telephony.ModemActivityInfo,android.telephony.TelephonyManager.ModemActivityInfoException>);
@@ -12268,6 +12272,10 @@ package android.telephony {
field public static final int RESULT_SUCCESS = 0; // 0x0
}
+ public static interface TelephonyManager.CarrierPrivilegesListener {
+ method public void onCarrierPrivilegesChanged(@NonNull java.util.List<java.lang.String>, @NonNull int[]);
+ }
+
public static class TelephonyManager.ModemActivityInfoException extends java.lang.Exception {
method public int getErrorCode();
field public static final int ERROR_INVALID_INFO_RECEIVED = 2; // 0x2
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 0171f0a5a327..f9739a489453 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -130,6 +130,7 @@ import android.net.EthernetManager;
import android.net.IEthernetManager;
import android.net.IIpSecService;
import android.net.INetworkPolicyManager;
+import android.net.INetworkStatsService;
import android.net.IPacProxyManager;
import android.net.IVpnManager;
import android.net.IpSecManager;
@@ -981,7 +982,11 @@ public final class SystemServiceRegistry {
new CachedServiceFetcher<NetworkStatsManager>() {
@Override
public NetworkStatsManager createService(ContextImpl ctx) throws ServiceNotFoundException {
- return new NetworkStatsManager(ctx.getOuterContext());
+ // TODO: Replace with an initializer in the module, see
+ // {@code ConnectivityFrameworkInitializer}.
+ final INetworkStatsService service = INetworkStatsService.Stub.asInterface(
+ ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE));
+ return new NetworkStatsManager(ctx.getOuterContext(), service);
}});
registerService(Context.PERSISTENT_DATA_BLOCK_SERVICE, PersistentDataBlockManager.class,
diff --git a/core/java/android/app/cloudsearch/OWNERS b/core/java/android/app/cloudsearch/OWNERS
new file mode 100644
index 000000000000..aa4da3b4bee0
--- /dev/null
+++ b/core/java/android/app/cloudsearch/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 758286
+
+huiwu@google.com
+srazdan@google.com
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index d66dc637743d..8b9cec17a196 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<Boolean> 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<Boolean> 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<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
- try {
- final IBluetoothA2dp service = getService();
- if (service != null && isEnabled()) {
+ final IBluetoothA2dp service = getService();
+ final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) log(Log.getStackTraceString(new Throwable()));
+ } else if (isEnabled()) {
+ try {
+ final SynchronousResultReceiver<List<BluetoothDevice>> 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<BluetoothDevice>();
- } catch (RemoteException e) {
- Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
- return new ArrayList<BluetoothDevice>();
}
+ return defaultValue;
}
/**
@@ -408,20 +425,25 @@ public final class BluetoothA2dp implements BluetoothProfile {
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
- try {
- final IBluetoothA2dp service = getService();
- if (service != null && isEnabled()) {
+ final IBluetoothA2dp service = getService();
+ final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) log(Log.getStackTraceString(new Throwable()));
+ } else if (isEnabled()) {
+ try {
+ final SynchronousResultReceiver<List<BluetoothDevice>> 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<BluetoothDevice>();
- } catch (RemoteException e) {
- Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
- return new ArrayList<BluetoothDevice>();
}
+ 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<Integer> 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<Boolean> 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<BluetoothDevice> 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<Boolean> 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<Integer> 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<Boolean> 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<Boolean> 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<BluetoothCodecStatus> 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<Integer> 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<Integer> 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<Integer> 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<BufferConstraints> 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<Boolean> 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 924dc55f31a0..59416818ceb3 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<Boolean> 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<Boolean> 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<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
final IBluetoothA2dpSink service = getService();
- if (service != null && isEnabled()) {
+ final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) log(Log.getStackTraceString(new Throwable()));
+ } else if (isEnabled()) {
try {
+ final SynchronousResultReceiver<List<BluetoothDevice>> 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<BluetoothDevice>();
+ 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<BluetoothDevice>();
+ return defaultValue;
}
/**
@@ -228,18 +246,23 @@ public final class BluetoothA2dpSink implements BluetoothProfile {
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
final IBluetoothA2dpSink service = getService();
- if (service != null && isEnabled()) {
+ final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) log(Log.getStackTraceString(new Throwable()));
+ } else if (isEnabled()) {
try {
+ final SynchronousResultReceiver<List<BluetoothDevice>> 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<BluetoothDevice>();
+ } 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<BluetoothDevice>();
+ 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<Integer> 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<BluetoothAudioConfig> 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<Boolean> 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<Integer> 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<Boolean> 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/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 5612e7cf56ce..9b37457c9907 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -786,7 +786,7 @@ public final class BluetoothAdapter {
@RequiresNoPermission
public static synchronized BluetoothAdapter getDefaultAdapter() {
if (sAdapter == null) {
- sAdapter = createAdapter(BluetoothManager.resolveAttributionSource(null));
+ sAdapter = createAdapter(AttributionSource.myAttributionSource());
}
return sAdapter;
}
diff --git a/core/java/android/bluetooth/BluetoothAvrcpController.java b/core/java/android/bluetooth/BluetoothAvrcpController.java
index 536dfb0a66dd..81fc3e11e9e1 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<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
- final IBluetoothAvrcpController service =
- getService();
- if (service != null && isEnabled()) {
+ final IBluetoothAvrcpController service = getService();
+ final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) log(Log.getStackTraceString(new Throwable()));
+ } else if (isEnabled()) {
try {
+ final SynchronousResultReceiver<List<BluetoothDevice>> 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<BluetoothDevice>();
+ 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<BluetoothDevice>();
+ return defaultValue;
}
/**
@@ -153,20 +161,24 @@ public final class BluetoothAvrcpController implements BluetoothProfile {
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
- final IBluetoothAvrcpController service =
- getService();
- if (service != null && isEnabled()) {
+ final IBluetoothAvrcpController service = getService();
+ final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) log(Log.getStackTraceString(new Throwable()));
+ } else if (isEnabled()) {
try {
+ final SynchronousResultReceiver<List<BluetoothDevice>> 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<BluetoothDevice>();
+ } 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<BluetoothDevice>();
+ 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<Integer> 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<BluetoothAvrcpPlayerSettings> 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<Boolean> 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 f0a8df0fa72f..ba57ec472a6e 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<ParcelUuid> 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<Map> 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<Integer> 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<Integer> 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<List<Integer>> 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<Integer>();
- } catch (RemoteException e) {
- Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
- return new ArrayList<Integer>();
}
+ return defaultValue;
}
/**
@@ -399,22 +403,23 @@ public final class BluetoothCsipSetCoordinator implements BluetoothProfile, Auto
*/
@Override
public @NonNull List<BluetoothDevice> 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<BluetoothDevice>();
- }
- }
+ final List<BluetoothDevice> 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<List<BluetoothDevice>> 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<BluetoothDevice>();
+ return defaultValue;
}
/**
@@ -422,24 +427,24 @@ public final class BluetoothCsipSetCoordinator implements BluetoothProfile, Auto
*/
@Override
public
- @NonNull List<BluetoothDevice> getDevicesMatchingConnectionStates(
- @NonNull int[] states) {
- if (VDBG) {
- log("getDevicesMatchingStates(states=" + Arrays.toString(states) + ")");
- }
+ @NonNull List<BluetoothDevice> 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<BluetoothDevice>();
- }
- }
+ final List<BluetoothDevice> 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<List<BluetoothDevice>> 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<BluetoothDevice>();
+ 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<Integer> 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<Boolean> 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<Integer> 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/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 9ff4dc3bb125..93f026860856 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -1177,7 +1177,7 @@ public final class BluetoothDevice implements Parcelable, Attributable {
mAddress = address;
mAddressType = ADDRESS_TYPE_PUBLIC;
- mAttributionSource = BluetoothManager.resolveAttributionSource(null);
+ mAttributionSource = AttributionSource.myAttributionSource();
}
/** {@hide} */
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index 4e7c01ad2db1..fe8d1ba80e33 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -1806,32 +1806,33 @@ public final class BluetoothGatt implements BluetoothProfile {
}
/**
- * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
+ * @deprecated Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
* with {@link BluetoothProfile#GATT} as argument
- *
* @throws UnsupportedOperationException
*/
@Override
@RequiresNoPermission
+ @Deprecated
public int getConnectionState(BluetoothDevice device) {
throw new UnsupportedOperationException("Use BluetoothManager#getConnectionState instead.");
}
/**
- * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
+ * @deprecated Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
* with {@link BluetoothProfile#GATT} as argument
*
* @throws UnsupportedOperationException
*/
@Override
@RequiresNoPermission
+ @Deprecated
public List<BluetoothDevice> getConnectedDevices() {
throw new UnsupportedOperationException(
"Use BluetoothManager#getConnectedDevices instead.");
}
/**
- * Not supported - please use
+ * @deprecated Not supported - please use
* {@link BluetoothManager#getDevicesMatchingConnectionStates(int, int[])}
* with {@link BluetoothProfile#GATT} as first argument
*
@@ -1839,6 +1840,7 @@ public final class BluetoothGatt implements BluetoothProfile {
*/
@Override
@RequiresNoPermission
+ @Deprecated
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
throw new UnsupportedOperationException(
"Use BluetoothManager#getDevicesMatchingConnectionStates instead.");
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index 3bdfd2859bc2..1b141c9afaca 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<Boolean> 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<Boolean> 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<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
final IBluetoothHeadset service = mService;
- if (service != null && isEnabled()) {
+ final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) log(Log.getStackTraceString(new Throwable()));
+ } else if (isEnabled()) {
try {
+ final SynchronousResultReceiver<List<BluetoothDevice>> 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<BluetoothDevice>();
+ } 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<BluetoothDevice>();
+ return defaultValue;
}
/**
@@ -564,18 +581,23 @@ public final class BluetoothHeadset implements BluetoothProfile {
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
final IBluetoothHeadset service = mService;
- if (service != null && isEnabled()) {
+ final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) log(Log.getStackTraceString(new Throwable()));
+ } else if (isEnabled()) {
try {
+ final SynchronousResultReceiver<List<BluetoothDevice>> 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<BluetoothDevice>();
+ } 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<BluetoothDevice>();
+ 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<Integer> 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;
}
/**
@@ -623,23 +649,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
})
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
- final IBluetoothHeadset service = mService;
- if (service != null && isEnabled() && isValidDevice(device)) {
- if (priority != BluetoothProfile.PRIORITY_OFF
- && priority != BluetoothProfile.PRIORITY_ON) {
- return false;
- }
- try {
- return service.setPriority(
- device, BluetoothAdapter.priorityToConnectionPolicy(priority),
- mAttributionSource);
- } catch (RemoteException e) {
- Log.e(TAG, Log.getStackTraceString(new Throwable()));
- return false;
- }
- }
- if (service == null) Log.w(TAG, "Proxy not attached to service");
- return false;
+ return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
}
/**
@@ -665,20 +675,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<Boolean> 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;
}
/**
@@ -698,18 +710,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));
}
/**
@@ -732,16 +733,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<Integer> 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;
}
/**
@@ -756,15 +761,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<Boolean> 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;
}
/**
@@ -779,15 +789,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<Boolean> 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;
}
/**
@@ -818,15 +833,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<Boolean> 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;
}
/**
@@ -847,15 +867,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<Boolean> 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;
}
/**
@@ -870,15 +895,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<Boolean> 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;
}
/**
@@ -904,17 +934,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<Integer> 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;
}
/**
@@ -932,15 +965,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()));
}
}
@@ -955,17 +990,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<Boolean> 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;
}
/**
@@ -980,15 +1018,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()));
}
}
@@ -1005,16 +1045,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<Boolean> 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;
}
/**
@@ -1039,18 +1083,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<Boolean> 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;
}
/**
@@ -1068,18 +1116,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<Boolean> 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;
}
/**
@@ -1113,17 +1165,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<Boolean> 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;
}
/**
@@ -1148,17 +1203,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<Boolean> 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;
}
/**
@@ -1178,16 +1236,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()));
}
}
@@ -1204,16 +1262,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()));
}
}
@@ -1245,18 +1305,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<Boolean> 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;
}
/**
@@ -1290,17 +1353,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<Boolean> 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;
}
/**
@@ -1316,22 +1382,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<BluetoothDevice> 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;
}
/**
@@ -1346,21 +1415,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<Boolean> 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;
}
/**
@@ -1380,7 +1450,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 2ef37101e23d..7d7a7f798bb9 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<Boolean> 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<Boolean> 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<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
- final IBluetoothHeadsetClient service =
- getService();
- if (service != null && isEnabled()) {
+ final IBluetoothHeadsetClient service = getService();
+ final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) log(Log.getStackTraceString(new Throwable()));
+ } else if (isEnabled()) {
try {
+ final SynchronousResultReceiver<List<BluetoothDevice>> 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<BluetoothDevice>();
+ 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<BluetoothDevice>();
+ return defaultValue;
}
/**
@@ -558,20 +573,24 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
- final IBluetoothHeadsetClient service =
- getService();
- if (service != null && isEnabled()) {
+ final IBluetoothHeadsetClient service = getService();
+ final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) log(Log.getStackTraceString(new Throwable()));
+ } else if (isEnabled()) {
try {
+ final SynchronousResultReceiver<List<BluetoothDevice>> 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<BluetoothDevice>();
+ } 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<BluetoothDevice>();
+ 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<Integer> 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<Boolean> 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<Integer> 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<Boolean> 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<Boolean> 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<Boolean> 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<BluetoothHeadsetClientCall> getCurrentCalls(BluetoothDevice device) {
if (DBG) log("getCurrentCalls()");
- final IBluetoothHeadsetClient service =
- getService();
- if (service != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadsetClient service = getService();
+ final List<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<List<BluetoothHeadsetClientCall>> 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<Bundle> 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<Boolean> 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<Boolean> 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<Boolean> 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<Boolean> 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<Boolean> 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<Boolean> 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<BluetoothHeadsetClientCall> 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<Boolean> 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<Boolean> 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<Integer> 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<Boolean> 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<Boolean> 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<Boolean> 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<Bundle> 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 a00b20d99f96..339a75fe0fbe 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<Boolean> 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<Boolean> 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<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
final IBluetoothHearingAid service = getService();
- try {
- if (service != null && isEnabled()) {
+ final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) log(Log.getStackTraceString(new Throwable()));
+ } else if (isEnabled()) {
+ try {
+ final SynchronousResultReceiver<List<BluetoothDevice>> 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<BluetoothDevice>();
- } catch (RemoteException e) {
- Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
- return new ArrayList<BluetoothDevice>();
}
+ 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<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) log(Log.getStackTraceString(new Throwable()));
+ } else if (isEnabled()) {
+ try {
+ final SynchronousResultReceiver<List<BluetoothDevice>> 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<BluetoothDevice>();
- } catch (RemoteException e) {
- Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
- return new ArrayList<BluetoothDevice>();
}
+ 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<Integer> 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<Boolean> 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<BluetoothDevice> getActiveDevices() {
if (VDBG) log("getActiveDevices()");
final IBluetoothHearingAid service = getService();
- try {
- if (service != null && isEnabled()) {
+ final List<BluetoothDevice> 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<List<BluetoothDevice>> 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<Boolean> 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<Integer> 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<Long> 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<Integer> 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<Integer> 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 f5b444fd17cb..44a355b5f75c 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<BluetoothDevice> getConnectedDevices() {
final IBluetoothHidDevice service = getService();
- if (service != null) {
+ final List<BluetoothDevice> 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<List<BluetoothDevice>> 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<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
final IBluetoothHidDevice service = getService();
- if (service != null) {
+ final List<BluetoothDevice> 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<List<BluetoothDevice>> 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<Integer> 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<Boolean> 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<Boolean> 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<Boolean> 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<Boolean> 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<Boolean> 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<String> 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<Boolean> 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<Boolean> 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<Boolean> 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 121aa1611522..ecbeddf2b853 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<Boolean> 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<Boolean> 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<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
final IBluetoothHidHost service = getService();
- if (service != null && isEnabled()) {
+ final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) log(Log.getStackTraceString(new Throwable()));
+ } else if (isEnabled()) {
try {
+ final SynchronousResultReceiver<List<BluetoothDevice>> 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<BluetoothDevice>();
+ 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<BluetoothDevice>();
+ return defaultValue;
}
/**
@@ -382,18 +400,23 @@ public final class BluetoothHidHost implements BluetoothProfile {
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
final IBluetoothHidHost service = getService();
- if (service != null && isEnabled()) {
+ final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) log(Log.getStackTraceString(new Throwable()));
+ } else if (isEnabled()) {
try {
+ final SynchronousResultReceiver<List<BluetoothDevice>> 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<BluetoothDevice>();
+ } 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<BluetoothDevice>();
+ 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<Integer> 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<Boolean> 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<Integer> 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<Boolean> 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<Boolean> 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<Boolean> 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<Boolean> 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<Boolean> 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<Boolean> 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<Boolean> 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<Boolean> 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 34398eba5d28..15db686b3be4 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<Boolean> 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<Boolean> 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<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
- try {
- final IBluetoothLeAudio service = getService();
- if (service != null && mAdapter.isEnabled()) {
+ final IBluetoothLeAudio service = getService();
+ final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
+ 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<List<BluetoothDevice>> 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<BluetoothDevice>();
- } catch (RemoteException e) {
- Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
- return new ArrayList<BluetoothDevice>();
}
+ return defaultValue;
}
/**
@@ -469,19 +487,24 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable {
public @NonNull List<BluetoothDevice> getDevicesMatchingConnectionStates(
@NonNull int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
- try {
- final IBluetoothLeAudio service = getService();
- if (service != null && mAdapter.isEnabled()) {
+ final IBluetoothLeAudio service = getService();
+ final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
+ 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<List<BluetoothDevice>> 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<BluetoothDevice>();
- } catch (RemoteException e) {
- Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
- return new ArrayList<BluetoothDevice>();
}
+ 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<Integer> 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<Boolean> 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<BluetoothDevice> 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<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
+ 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<List<BluetoothDevice>> 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<Integer> 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<Boolean> 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<Boolean> 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<Boolean> 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<Integer> 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/BluetoothManager.java b/core/java/android/bluetooth/BluetoothManager.java
index c93de41b5b36..fef6f225dd3b 100644
--- a/core/java/android/bluetooth/BluetoothManager.java
+++ b/core/java/android/bluetooth/BluetoothManager.java
@@ -16,14 +16,10 @@
package android.bluetooth;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.annotation.RequiresFeature;
import android.annotation.RequiresNoPermission;
import android.annotation.RequiresPermission;
import android.annotation.SystemService;
-import android.app.ActivityThread;
-import android.app.AppGlobals;
import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
import android.content.AttributionSource;
@@ -68,37 +64,11 @@ public final class BluetoothManager {
* @hide
*/
public BluetoothManager(Context context) {
- mAttributionSource = resolveAttributionSource(context);
+ mAttributionSource = (context != null) ? context.getAttributionSource() :
+ AttributionSource.myAttributionSource();
mAdapter = BluetoothAdapter.createAdapter(mAttributionSource);
}
- /** {@hide} */
- public static @NonNull AttributionSource resolveAttributionSource(@Nullable Context context) {
- AttributionSource res = null;
- if (context != null) {
- res = context.getAttributionSource();
- }
- if (res == null) {
- res = ActivityThread.currentAttributionSource();
- }
- if (res == null) {
- int uid = android.os.Process.myUid();
- if (uid == android.os.Process.ROOT_UID) {
- uid = android.os.Process.SYSTEM_UID;
- }
- try {
- res = new AttributionSource.Builder(uid)
- .setPackageName(AppGlobals.getPackageManager().getPackagesForUid(uid)[0])
- .build();
- } catch (RemoteException ignored) {
- }
- }
- if (res == null) {
- throw new IllegalStateException("Failed to resolve AttributionSource");
- }
- return res;
- }
-
/**
* Get the BLUETOOTH Adapter for this device.
*
diff --git a/core/java/android/bluetooth/BluetoothMap.java b/core/java/android/bluetooth/BluetoothMap.java
index 474e41f4aa19..56e497262421 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<Integer> 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<BluetoothDevice> 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<Boolean> 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<Boolean> 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<BluetoothDevice> getConnectedDevices() {
if (DBG) log("getConnectedDevices()");
final IBluetoothMap service = getService();
- if (service != null && isEnabled()) {
+ final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) log(Log.getStackTraceString(new Throwable()));
+ } else if (isEnabled()) {
try {
+ final SynchronousResultReceiver<List<BluetoothDevice>> 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<BluetoothDevice>();
+ 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<BluetoothDevice>();
+ return defaultValue;
}
/**
@@ -309,18 +334,23 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable {
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (DBG) log("getDevicesMatchingStates()");
final IBluetoothMap service = getService();
- if (service != null && isEnabled()) {
+ final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) log(Log.getStackTraceString(new Throwable()));
+ } else if (isEnabled()) {
try {
+ final SynchronousResultReceiver<List<BluetoothDevice>> 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<BluetoothDevice>();
+ } 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<BluetoothDevice>();
+ 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<Integer> 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<Boolean> 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<Integer> 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 8a3f80164aeb..03536f9aad39 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<Boolean> 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<Boolean> 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<Boolean> 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<BluetoothDevice> getConnectedDevices() {
if (DBG) Log.d(TAG, "getConnectedDevices()");
final IBluetoothMapClient service = getService();
- if (service != null && isEnabled()) {
+ final List<BluetoothDevice> 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<List<BluetoothDevice>> 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<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (DBG) Log.d(TAG, "getDevicesMatchingStates()");
final IBluetoothMapClient service = getService();
- if (service != null && isEnabled()) {
+ final List<BluetoothDevice> 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<List<BluetoothDevice>> 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<Integer> 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<Boolean> 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<Integer> 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<Uri> 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<Boolean> 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<Boolean> 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<Integer> 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<Boolean> 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 ac7a52d8f636..d4ad4ef47acd 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<Boolean> 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<Boolean> 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<Boolean> 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<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
final IBluetoothPan service = getService();
- if (service != null && isEnabled()) {
+ final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) log(Log.getStackTraceString(new Throwable()));
+ } else if (isEnabled()) {
try {
+ final SynchronousResultReceiver<List<BluetoothDevice>> 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<BluetoothDevice>();
+ 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<BluetoothDevice>();
+ return defaultValue;
}
/**
@@ -381,18 +400,23 @@ public final class BluetoothPan implements BluetoothProfile {
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
final IBluetoothPan service = getService();
- if (service != null && isEnabled()) {
+ final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) log(Log.getStackTraceString(new Throwable()));
+ } else if (isEnabled()) {
try {
+ final SynchronousResultReceiver<List<BluetoothDevice>> 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<BluetoothDevice>();
+ } 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<BluetoothDevice>();
+ 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<Integer> 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<Boolean> 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/BluetoothPbap.java b/core/java/android/bluetooth/BluetoothPbap.java
index e13792918103..de2db9c2ca86 100644
--- a/core/java/android/bluetooth/BluetoothPbap.java
+++ b/core/java/android/bluetooth/BluetoothPbap.java
@@ -25,15 +25,10 @@ import android.annotation.SystemApi;
import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.AttributionSource;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.content.pm.PackageManager;
import android.os.Build;
import android.os.IBinder;
import android.os.RemoteException;
-import android.os.UserHandle;
import android.util.Log;
import java.util.ArrayList;
@@ -96,10 +91,6 @@ public class BluetoothPbap implements BluetoothProfile {
public static final String ACTION_CONNECTION_STATE_CHANGED =
"android.bluetooth.pbap.profile.action.CONNECTION_STATE_CHANGED";
- private volatile IBluetoothPbap mService;
- private final Context mContext;
- private ServiceListener mServiceListener;
- private final BluetoothAdapter mAdapter;
private final AttributionSource mAttributionSource;
/** @hide */
@@ -113,87 +104,25 @@ public class BluetoothPbap implements BluetoothProfile {
*/
public static final int RESULT_CANCELED = 2;
- @SuppressLint("AndroidFrameworkBluetoothPermission")
- private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
- new IBluetoothStateChangeCallback.Stub() {
- public void onBluetoothStateChange(boolean up) {
- log("onBluetoothStateChange: up=" + up);
- if (!up) {
- doUnbind();
- } else {
- doBind();
- }
+ private BluetoothAdapter mAdapter;
+ private final BluetoothProfileConnector<IBluetoothPbap> mProfileConnector =
+ new BluetoothProfileConnector(this, BluetoothProfile.PBAP, "BluetoothPbap",
+ IBluetoothPbap.class.getName()) {
+ @Override
+ public IBluetoothPbap getServiceInterface(IBinder service) {
+ return IBluetoothPbap.Stub.asInterface(service);
}
- };
+ };
/**
* Create a BluetoothPbap proxy object.
*
* @hide
*/
- public BluetoothPbap(Context context, ServiceListener l, BluetoothAdapter adapter) {
- mContext = context;
- mServiceListener = l;
+ public BluetoothPbap(Context context, ServiceListener listener, BluetoothAdapter adapter) {
mAdapter = adapter;
mAttributionSource = adapter.getAttributionSource();
-
- // Preserve legacy compatibility where apps were depending on
- // registerStateChangeCallback() performing a permissions check which
- // has been relaxed in modern platform versions
- if (context.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.R
- && context.checkSelfPermission(android.Manifest.permission.BLUETOOTH)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Need BLUETOOTH permission");
- }
-
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException re) {
- Log.e(TAG, "", re);
- }
- }
- doBind();
- }
-
- @SuppressLint("AndroidFrameworkRequiresPermission")
- boolean doBind() {
- synchronized (mConnection) {
- try {
- if (mService == null) {
- log("Binding service...");
- Intent intent = new Intent(IBluetoothPbap.class.getName());
- ComponentName comp = intent.resolveSystemService(
- mContext.getPackageManager(), 0);
- intent.setComponent(comp);
- if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
- UserHandle.CURRENT)) {
- Log.e(TAG, "Could not bind to Bluetooth Pbap Service with " + intent);
- return false;
- }
- }
- } catch (SecurityException se) {
- Log.e(TAG, "", se);
- return false;
- }
- }
- return true;
- }
-
- private void doUnbind() {
- synchronized (mConnection) {
- if (mService != null) {
- log("Unbinding service...");
- try {
- mContext.unbindService(mConnection);
- } catch (IllegalArgumentException ie) {
- Log.e(TAG, "", ie);
- } finally {
- mService = null;
- }
- }
- }
+ mProfileConnector.connect(context, listener);
}
/** @hide */
@@ -214,16 +143,11 @@ public class BluetoothPbap implements BluetoothProfile {
* @hide
*/
public synchronized void close() {
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException re) {
- Log.e(TAG, "", re);
- }
- }
- doUnbind();
- mServiceListener = null;
+ mProfileConnector.disconnect();
+ }
+
+ private IBluetoothPbap getService() {
+ return (IBluetoothPbap) mProfileConnector.getService();
}
/**
@@ -236,7 +160,7 @@ public class BluetoothPbap implements BluetoothProfile {
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
public List<BluetoothDevice> getConnectedDevices() {
log("getConnectedDevices()");
- final IBluetoothPbap service = mService;
+ final IBluetoothPbap service = getService();
if (service == null) {
Log.w(TAG, "Proxy not attached to service");
return new ArrayList<BluetoothDevice>();
@@ -265,7 +189,7 @@ public class BluetoothPbap implements BluetoothProfile {
public @BtProfileState int getConnectionState(@NonNull BluetoothDevice device) {
log("getConnectionState: device=" + device);
try {
- final IBluetoothPbap service = mService;
+ final IBluetoothPbap service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
return service.getConnectionState(device, mAttributionSource);
}
@@ -289,7 +213,7 @@ public class BluetoothPbap implements BluetoothProfile {
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
log("getDevicesMatchingConnectionStates: states=" + Arrays.toString(states));
- final IBluetoothPbap service = mService;
+ final IBluetoothPbap service = getService();
if (service == null) {
Log.w(TAG, "Proxy not attached to service");
return new ArrayList<BluetoothDevice>();
@@ -330,7 +254,7 @@ public class BluetoothPbap implements BluetoothProfile {
@ConnectionPolicy int connectionPolicy) {
if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
try {
- final IBluetoothPbap service = mService;
+ final IBluetoothPbap service = getService();
if (service != null && isEnabled()
&& isValidDevice(device)) {
if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
@@ -359,7 +283,7 @@ public class BluetoothPbap implements BluetoothProfile {
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean disconnect(BluetoothDevice device) {
log("disconnect()");
- final IBluetoothPbap service = mService;
+ final IBluetoothPbap service = getService();
if (service == null) {
Log.w(TAG, "Proxy not attached to service");
return false;
@@ -373,25 +297,6 @@ public class BluetoothPbap implements BluetoothProfile {
return false;
}
- @SuppressLint("AndroidFrameworkBluetoothPermission")
- private final ServiceConnection mConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- log("Proxy object connected");
- mService = IBluetoothPbap.Stub.asInterface(service);
- if (mServiceListener != null) {
- mServiceListener.onServiceConnected(BluetoothProfile.PBAP, BluetoothPbap.this);
- }
- }
-
- public void onServiceDisconnected(ComponentName className) {
- log("Proxy object disconnected");
- doUnbind();
- if (mServiceListener != null) {
- mServiceListener.onServiceDisconnected(BluetoothProfile.PBAP);
- }
- }
- };
-
private boolean isEnabled() {
if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
return false;
diff --git a/core/java/android/bluetooth/BluetoothPbapClient.java b/core/java/android/bluetooth/BluetoothPbapClient.java
index cc91ad258d03..e096de8cb829 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<Boolean> 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<Boolean> 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<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) log(Log.getStackTraceString(new Throwable()));
+ } else if (isEnabled()) {
try {
+ final SynchronousResultReceiver<List<BluetoothDevice>> 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<BluetoothDevice>();
+ 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<BluetoothDevice>();
+ return defaultValue;
}
/**
@@ -212,20 +224,23 @@ public final class BluetoothPbapClient implements BluetoothProfile {
log("getDevicesMatchingStates()");
}
final IBluetoothPbapClient service = getService();
- if (service != null && isEnabled()) {
+ final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) log(Log.getStackTraceString(new Throwable()));
+ } else if (isEnabled()) {
try {
+ final SynchronousResultReceiver<List<BluetoothDevice>> 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<BluetoothDevice>();
+ } 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<BluetoothDevice>();
+ 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<Integer> 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<Boolean> 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<Integer> 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/BluetoothProfileConnector.java b/core/java/android/bluetooth/BluetoothProfileConnector.java
index ecd5e4077de9..79373f1a32ec 100644
--- a/core/java/android/bluetooth/BluetoothProfileConnector.java
+++ b/core/java/android/bluetooth/BluetoothProfileConnector.java
@@ -16,12 +16,16 @@
package android.bluetooth;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.os.Build;
import android.os.IBinder;
import android.os.RemoteException;
@@ -29,6 +33,7 @@ import android.os.UserHandle;
import android.util.CloseGuard;
import android.util.Log;
+import java.util.List;
/**
* Connector for Bluetooth profile proxies to bind manager service and
* profile services
@@ -57,6 +62,29 @@ public abstract class BluetoothProfileConnector<T> {
}
};
+ private @Nullable ComponentName resolveSystemService(@NonNull Intent intent,
+ @NonNull PackageManager pm, @PackageManager.ComponentInfoFlags int flags) {
+ List<ResolveInfo> results = pm.queryIntentServices(intent, flags);
+ if (results == null) {
+ return null;
+ }
+ ComponentName comp = null;
+ for (int i = 0; i < results.size(); i++) {
+ ResolveInfo ri = results.get(i);
+ if ((ri.serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
+ continue;
+ }
+ ComponentName foundComp = new ComponentName(ri.serviceInfo.applicationInfo.packageName,
+ ri.serviceInfo.name);
+ if (comp != null) {
+ throw new IllegalStateException("Multiple system services handle " + intent
+ + ": " + comp + ", " + foundComp);
+ }
+ comp = foundComp;
+ }
+ return comp;
+ }
+
private final ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
logDebug("Proxy object connected");
@@ -99,8 +127,8 @@ public abstract class BluetoothProfileConnector<T> {
mCloseGuard.open("doUnbind");
try {
Intent intent = new Intent(mServiceName);
- ComponentName comp = intent.resolveSystemService(
- mContext.getPackageManager(), 0);
+ ComponentName comp = resolveSystemService(intent, mContext.getPackageManager(),
+ 0);
intent.setComponent(comp);
if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
UserHandle.CURRENT)) {
diff --git a/core/java/android/bluetooth/BluetoothSap.java b/core/java/android/bluetooth/BluetoothSap.java
index ab2b8eaaa36e..808fa3913316 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<Integer> 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<BluetoothDevice> 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<Boolean> 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<Boolean> 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<BluetoothDevice> getConnectedDevices() {
if (DBG) log("getConnectedDevices()");
final IBluetoothSap service = getService();
- if (service != null && isEnabled()) {
+ final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) log(Log.getStackTraceString(new Throwable()));
+ } else if (isEnabled()) {
try {
+ final SynchronousResultReceiver<List<BluetoothDevice>> 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<BluetoothDevice>();
+ 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<BluetoothDevice>();
+ return defaultValue;
}
/**
@@ -291,18 +316,23 @@ public final class BluetoothSap implements BluetoothProfile {
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (DBG) log("getDevicesMatchingStates()");
final IBluetoothSap service = getService();
- if (service != null && isEnabled()) {
+ final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) log(Log.getStackTraceString(new Throwable()));
+ } else if (isEnabled()) {
try {
+ final SynchronousResultReceiver<List<BluetoothDevice>> 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<BluetoothDevice>();
+ } 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<BluetoothDevice>();
+ 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<Integer> 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<Boolean> 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<Integer> 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 000000000000..867469241f84
--- /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 ba83eca423f4..27532aabc3fc 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<BluetoothDevice> getConnectedDevices() {
if (DBG) log("getConnectedDevices()");
final IBluetoothVolumeControl service = getService();
- if (service != null && isEnabled()) {
+ final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) log(Log.getStackTraceString(new Throwable()));
+ } else if (isEnabled()) {
try {
+ final SynchronousResultReceiver<List<BluetoothDevice>> 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<BluetoothDevice>();
+ 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<BluetoothDevice>();
+ return defaultValue;
}
/**
@@ -159,18 +169,23 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (DBG) log("getDevicesMatchingStates()");
final IBluetoothVolumeControl service = getService();
- if (service != null && isEnabled()) {
+ final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) log(Log.getStackTraceString(new Throwable()));
+ } else if (isEnabled()) {
try {
+ final SynchronousResultReceiver<List<BluetoothDevice>> 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<BluetoothDevice>();
+ } 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<BluetoothDevice>();
+ 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<Integer> 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<Boolean> 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<Integer> 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() {
diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java
index f913349e7955..540e5a778c27 100644
--- a/core/java/android/bluetooth/le/BluetoothLeScanner.java
+++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java
@@ -514,16 +514,27 @@ public final class BluetoothLeScanner {
@Override
public void onScanResult(final ScanResult scanResult) {
Attributable.setAttributionSource(scanResult, mAttributionSource);
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "onScanResult() - mScannerId=" + mScannerId);
+ }
if (VDBG) Log.d(TAG, "onScanResult() - " + scanResult.toString());
// Check null in case the scan has been stopped
synchronized (this) {
- if (mScannerId <= 0) return;
+ if (mScannerId <= 0) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Ignoring result as scan stopped.");
+ }
+ return;
+ };
}
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "onScanResult() - handler run");
+ }
mScanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, scanResult);
}
});
diff --git a/core/java/android/content/AttributionSource.java b/core/java/android/content/AttributionSource.java
index 6ae2bb5b642a..157e709a67f0 100644
--- a/core/java/android/content/AttributionSource.java
+++ b/core/java/android/content/AttributionSource.java
@@ -22,6 +22,7 @@ import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.app.ActivityThread;
+import android.app.AppGlobals;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
@@ -191,10 +192,42 @@ public final class AttributionSource implements Parcelable {
return new ScopedParcelState(this);
}
- /** @hide */
- public static AttributionSource myAttributionSource() {
- return new AttributionSource(Process.myUid(), ActivityThread.currentOpPackageName(),
- /*attributionTag*/ null, (String[]) /*renouncedPermissions*/ null, /*next*/ null);
+ /**
+ * Returns a generic {@link AttributionSource} that represents the entire
+ * calling process.
+ *
+ * <p>Callers are <em>strongly</em> encouraged to use a more specific
+ * attribution source whenever possible, such as from
+ * {@link Context#getAttributionSource()}, since that enables developers to
+ * have more detailed and scoped control over attribution within
+ * sub-components of their app.
+ *
+ * @see Context#createAttributionContext(String)
+ * @see Context#getAttributionTag()
+ * @return a generic {@link AttributionSource} representing the entire
+ * calling process
+ * @throws IllegalStateException when no accurate {@link AttributionSource}
+ * can be determined
+ */
+ public static @NonNull AttributionSource myAttributionSource() {
+
+ final AttributionSource globalSource = ActivityThread.currentAttributionSource();
+ if (globalSource != null) {
+ return globalSource;
+ }
+
+ int uid = Process.myUid();
+ if (uid == Process.ROOT_UID) {
+ uid = Process.SYSTEM_UID;
+ }
+ try {
+ return new AttributionSource.Builder(uid)
+ .setPackageName(AppGlobals.getPackageManager().getPackagesForUid(uid)[0])
+ .build();
+ } catch (Exception ignored) {
+ }
+
+ throw new IllegalStateException("Failed to resolve AttributionSource");
}
/**
@@ -247,7 +280,7 @@ public final class AttributionSource implements Parcelable {
* whether the attribution source is one for the calling app to prevent the caller
* to pass you a source from another app without including themselves in the
* attribution chain.
- *f
+ *
* @return if the attribution source cannot be trusted to be from the caller.
*/
public boolean checkCallingUid() {
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 1552dbd00c92..9659df6bf04a 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -5408,7 +5408,9 @@ public class Intent implements Parcelable, Cloneable {
*
* <p>Targets provided in this way will be presented inline with all other targets provided
* by services from other apps. They will be prioritized before other service targets, but
- * after those targets provided by sources that the user has manually pinned to the front.</p>
+ * after those targets provided by sources that the user has manually pinned to the front.
+ * You can provide up to two targets on this extra (the limit of two targets
+ * starts in Android 10).</p>
*
* @see #ACTION_CHOOSER
*/
@@ -5519,9 +5521,11 @@ public class Intent implements Parcelable, Cloneable {
/**
* A Parcelable[] of {@link Intent} or
* {@link android.content.pm.LabeledIntent} objects as set with
- * {@link #putExtra(String, Parcelable[])} of additional activities to place
- * a the front of the list of choices, when shown to the user with a
- * {@link #ACTION_CHOOSER}.
+ * {@link #putExtra(String, Parcelable[])} to place
+ * at the front of the list of choices, when shown to the user with an
+ * {@link #ACTION_CHOOSER}. You can choose up to two additional activities
+ * to show before the app suggestions (the limit of two additional activities starts in
+ * Android 10).
*/
public static final String EXTRA_INITIAL_INTENTS = "android.intent.extra.INITIAL_INTENTS";
diff --git a/core/java/android/net/NetworkPolicy.java b/core/java/android/net/NetworkPolicy.java
index 70fe5d677b4f..123c55c27d1c 100644
--- a/core/java/android/net/NetworkPolicy.java
+++ b/core/java/android/net/NetworkPolicy.java
@@ -18,8 +18,11 @@ package android.net;
import static android.net.NetworkStats.METERED_ALL;
import static android.net.NetworkStats.METERED_YES;
+import static android.net.NetworkTemplate.MATCH_BLUETOOTH;
import static android.net.NetworkTemplate.MATCH_CARRIER;
+import static android.net.NetworkTemplate.MATCH_ETHERNET;
import static android.net.NetworkTemplate.MATCH_MOBILE;
+import static android.net.NetworkTemplate.MATCH_WIFI;
import static android.net.NetworkTemplate.SUBSCRIBER_ID_MATCH_RULE_EXACT;
import android.annotation.NonNull;
@@ -324,7 +327,7 @@ public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
@NonNull
private byte[] getNetworkTemplateBytesForBackup() throws IOException {
- if (!template.isPersistable()) {
+ if (!isTemplatePersistable(this.template)) {
Log.wtf(TAG, "Trying to backup non-persistable template: " + this);
}
@@ -378,4 +381,28 @@ public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
"Restored network template contains unknown match rule " + matchRule, e);
}
}
+
+ /**
+ * Check if the template can be persisted into disk.
+ */
+ public static boolean isTemplatePersistable(@NonNull NetworkTemplate template) {
+ switch (template.getMatchRule()) {
+ case MATCH_BLUETOOTH:
+ case MATCH_ETHERNET:
+ return true;
+ case MATCH_CARRIER:
+ case MATCH_MOBILE:
+ return !template.getSubscriberIds().isEmpty();
+ case MATCH_WIFI:
+ if (Objects.equals(template.getWifiNetworkKey(), null)
+ && template.getSubscriberIds().isEmpty()) {
+ return false;
+ }
+ return true;
+ default:
+ // Don't allow persistable for unknown types or legacy types such as
+ // MATCH_MOBILE_WILDCARD, MATCH_PROXY, etc.
+ return false;
+ }
+ }
}
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index b069fb336d55..59db8f495dd9 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -1235,10 +1235,11 @@ public class Binder implements IBinder {
data.readCallingWorkSourceUid());
observer.callEnded(callSession, data.dataSize(), reply.dataSize(), workSourceUid);
}
+
+ checkParcel(this, code, reply, "Unreasonably large binder reply buffer");
+ reply.recycle();
+ data.recycle();
}
- checkParcel(this, code, reply, "Unreasonably large binder reply buffer");
- reply.recycle();
- data.recycle();
// Just in case -- we are done with the IPC, so there should be no more strict
// mode violations that have gathered for this thread. Either they have been
diff --git a/core/java/android/os/SystemVibrator.java b/core/java/android/os/SystemVibrator.java
index 0c3debb1b54e..26de7112a8b5 100644
--- a/core/java/android/os/SystemVibrator.java
+++ b/core/java/android/os/SystemVibrator.java
@@ -389,7 +389,7 @@ public class SystemVibrator extends Vibrator {
mExecutor.execute(() -> {
boolean anyVibrating;
synchronized (mLock) {
- int allInitializedMask = 1 << mVibratorListeners.size() - 1;
+ int allInitializedMask = (1 << mVibratorListeners.size()) - 1;
int vibratorMask = 1 << vibratorIdx;
if ((mInitializedMask & vibratorMask) == 0) {
// First state report for this vibrator, set vibrating initial value.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 2d70bad39c85..d0ef546a8122 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5756,7 +5756,6 @@ public final class Settings {
MOVED_TO_GLOBAL.add(Settings.Global.CONNECTIVITY_CHANGE_DELAY);
MOVED_TO_GLOBAL.add(Settings.Global.CAPTIVE_PORTAL_DETECTION_ENABLED);
MOVED_TO_GLOBAL.add(Settings.Global.CAPTIVE_PORTAL_SERVER);
- MOVED_TO_GLOBAL.add(Settings.Global.NSD_ON);
MOVED_TO_GLOBAL.add(Settings.Global.SET_INSTALL_LOCATION);
MOVED_TO_GLOBAL.add(Settings.Global.DEFAULT_INSTALL_LOCATION);
MOVED_TO_GLOBAL.add(Settings.Global.INET_CONDITION_DEBOUNCE_UP_DELAY);
@@ -12631,13 +12630,6 @@ public final class Settings {
@Readable
public static final String MIN_DURATION_BETWEEN_RECOVERY_STEPS_IN_MS =
"min_duration_between_recovery_steps";
- /**
- * Whether network service discovery is enabled.
- *
- * @hide
- */
- @Readable
- public static final String NSD_ON = "nsd_on";
/**
* Let user pick default install location.
diff --git a/core/java/android/service/cloudsearch/OWNERS b/core/java/android/service/cloudsearch/OWNERS
new file mode 100644
index 000000000000..aa4da3b4bee0
--- /dev/null
+++ b/core/java/android/service/cloudsearch/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 758286
+
+huiwu@google.com
+srazdan@google.com
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index e7f89204c1ec..9eaaa91532d0 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -36,18 +36,24 @@ import android.telephony.Annotation.PreciseDisconnectCauses;
import android.telephony.Annotation.RadioPowerState;
import android.telephony.Annotation.SimActivationState;
import android.telephony.Annotation.SrvccState;
+import android.telephony.TelephonyManager.CarrierPrivilegesListener;
import android.telephony.emergency.EmergencyNumber;
import android.telephony.ims.ImsReasonInfo;
import android.util.ArraySet;
import android.util.Log;
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.listeners.ListenerExecutor;
+import com.android.internal.telephony.ICarrierPrivilegesListener;
import com.android.internal.telephony.IOnSubscriptionsChangedListener;
import com.android.internal.telephony.ITelephonyRegistry;
+import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.WeakHashMap;
import java.util.concurrent.Executor;
/**
@@ -1214,4 +1220,117 @@ public class TelephonyRegistryManager {
listenFromCallback(false, false, subId,
pkgName, attributionTag, callback, new int[0], notifyNow);
}
+
+ private static class CarrierPrivilegesListenerWrapper extends ICarrierPrivilegesListener.Stub
+ implements ListenerExecutor {
+ private final WeakReference<CarrierPrivilegesListener> mListener;
+ private final Executor mExecutor;
+
+ CarrierPrivilegesListenerWrapper(CarrierPrivilegesListener listener, Executor executor) {
+ mListener = new WeakReference<>(listener);
+ mExecutor = executor;
+ }
+
+ @Override
+ public void onCarrierPrivilegesChanged(
+ List<String> privilegedPackageNames, int[] privilegedUids) {
+ Binder.withCleanCallingIdentity(
+ () ->
+ executeSafely(
+ mExecutor,
+ mListener::get,
+ cpl ->
+ cpl.onCarrierPrivilegesChanged(
+ privilegedPackageNames, privilegedUids)));
+ }
+ }
+
+ @GuardedBy("sCarrierPrivilegeListeners")
+ private static final WeakHashMap<
+ CarrierPrivilegesListener, WeakReference<CarrierPrivilegesListenerWrapper>>
+ sCarrierPrivilegeListeners = new WeakHashMap<>();
+
+ /**
+ * Registers a {@link CarrierPrivilegesListener} on the given {@code logicalSlotIndex} to
+ * receive callbacks when the set of packages with carrier privileges changes. The callback will
+ * immediately be called with the latest state.
+ *
+ * @param logicalSlotIndex The SIM slot to listen on
+ * @param executor The executor where {@code listener} will be invoked
+ * @param listener The callback to register
+ */
+ public void addCarrierPrivilegesListener(
+ int logicalSlotIndex,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull CarrierPrivilegesListener listener) {
+ if (listener == null || executor == null) {
+ throw new IllegalArgumentException("listener and executor must be non-null");
+ }
+ synchronized (sCarrierPrivilegeListeners) {
+ WeakReference<CarrierPrivilegesListenerWrapper> existing =
+ sCarrierPrivilegeListeners.get(listener);
+ if (existing != null && existing.get() != null) {
+ Log.d(TAG, "addCarrierPrivilegesListener: listener already registered");
+ return;
+ }
+ CarrierPrivilegesListenerWrapper wrapper =
+ new CarrierPrivilegesListenerWrapper(listener, executor);
+ sCarrierPrivilegeListeners.put(listener, new WeakReference<>(wrapper));
+ try {
+ sRegistry.addCarrierPrivilegesListener(
+ logicalSlotIndex,
+ wrapper,
+ mContext.getOpPackageName(),
+ mContext.getAttributionTag());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+ /**
+ * Unregisters a {@link CarrierPrivilegesListener}.
+ *
+ * @param listener The callback to unregister
+ */
+ public void removeCarrierPrivilegesListener(@NonNull CarrierPrivilegesListener listener) {
+ if (listener == null) {
+ throw new IllegalArgumentException("listener must be non-null");
+ }
+ synchronized (sCarrierPrivilegeListeners) {
+ WeakReference<CarrierPrivilegesListenerWrapper> ref =
+ sCarrierPrivilegeListeners.remove(listener);
+ if (ref == null) return;
+ CarrierPrivilegesListenerWrapper wrapper = ref.get();
+ if (wrapper == null) return;
+ try {
+ sRegistry.removeCarrierPrivilegesListener(wrapper, mContext.getOpPackageName());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+ /**
+ * Notify listeners that the set of packages with carrier privileges has changed.
+ *
+ * @param logicalSlotIndex The SIM slot the change occurred on
+ * @param privilegedPackageNames The updated set of packages names with carrier privileges
+ * @param privilegedUids The updated set of UIDs with carrier privileges
+ */
+ public void notifyCarrierPrivilegesChanged(
+ int logicalSlotIndex,
+ @NonNull List<String> privilegedPackageNames,
+ @NonNull int[] privilegedUids) {
+ if (privilegedPackageNames == null || privilegedUids == null) {
+ throw new IllegalArgumentException(
+ "privilegedPackageNames and privilegedUids must be non-null");
+ }
+ try {
+ sRegistry.notifyCarrierPrivilegesChanged(
+ logicalSlotIndex, privilegedPackageNames, privilegedUids);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/com/android/internal/net/NetworkUtilsInternal.java b/core/java/com/android/internal/net/NetworkUtilsInternal.java
index 052959abff69..1b6cb29d048d 100644
--- a/core/java/com/android/internal/net/NetworkUtilsInternal.java
+++ b/core/java/com/android/internal/net/NetworkUtilsInternal.java
@@ -74,35 +74,4 @@ public class NetworkUtilsInternal {
return true;
}
-
- /**
- * Safely multiple a value by a rational.
- * <p>
- * Internally it uses integer-based math whenever possible, but switches
- * over to double-based math if values would overflow.
- * @hide
- */
- public static long multiplySafeByRational(long value, long num, long den) {
- if (den == 0) {
- throw new ArithmeticException("Invalid Denominator");
- }
- long x = value;
- long y = num;
-
- // Logic shamelessly borrowed from Math.multiplyExact()
- long r = x * y;
- long ax = Math.abs(x);
- long ay = Math.abs(y);
- if (((ax | ay) >>> 31 != 0)) {
- // Some bits greater than 2^31 that might cause overflow
- // Check the result using the divide operator
- // and check for the special case of Long.MIN_VALUE * -1
- if (((y != 0) && (r / y != x))
- || (x == Long.MIN_VALUE && y == -1)) {
- // Use double math to avoid overflowing
- return (long) (((double) num / den) * value);
- }
- }
- return r / den;
- }
}
diff --git a/core/java/com/android/internal/telephony/ICarrierPrivilegesListener.aidl b/core/java/com/android/internal/telephony/ICarrierPrivilegesListener.aidl
new file mode 100644
index 000000000000..6ca8cecba3c8
--- /dev/null
+++ b/core/java/com/android/internal/telephony/ICarrierPrivilegesListener.aidl
@@ -0,0 +1,22 @@
+/*
+ * 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 com.android.internal.telephony;
+
+oneway interface ICarrierPrivilegesListener {
+ void onCarrierPrivilegesChanged(
+ in List<String> privilegedPackageNames, in int[] privilegedUids);
+}
diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index 15d4246e302a..9712d7e38a4b 100644
--- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -32,6 +32,7 @@ import android.telephony.PreciseDataConnectionState;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.emergency.EmergencyNumber;
+import com.android.internal.telephony.ICarrierPrivilegesListener;
import com.android.internal.telephony.IPhoneStateListener;
import com.android.internal.telephony.IOnSubscriptionsChangedListener;
@@ -100,4 +101,10 @@ interface ITelephonyRegistry {
void notifyAllowedNetworkTypesChanged(in int phoneId, in int subId, in int reason, in long allowedNetworkType);
void notifyLinkCapacityEstimateChanged(in int phoneId, in int subId,
in List<LinkCapacityEstimate> linkCapacityEstimateList);
+
+ void addCarrierPrivilegesListener(
+ int phoneId, ICarrierPrivilegesListener callback, String pkg, String featureId);
+ void removeCarrierPrivilegesListener(ICarrierPrivilegesListener callback, String pkg);
+ void notifyCarrierPrivilegesChanged(
+ int phoneId, in List<String> privilegedPackageNames, in int[] privilegedUids);
}
diff --git a/core/jni/OWNERS b/core/jni/OWNERS
index 790c39e73bff..832c49801bdc 100644
--- a/core/jni/OWNERS
+++ b/core/jni/OWNERS
@@ -55,13 +55,17 @@ per-file android_media_* = file:/media/java/android/media/OWNERS
per-file android_media_midi_* = file:/media/java/android/media/midi/OWNERS
per-file android_opengl_* = file:/opengl/java/android/opengl/OWNERS
per-file android_os_storage_* = file:/core/java/android/os/storage/OWNERS
-per-file android_se_* = file:/core/java/android/se/OWNERS
+per-file android_se_* = file:/omapi/java/android/se/OWNERS
per-file android_security_* = file:/core/java/android/security/OWNERS
per-file android_view_* = file:/core/java/android/view/OWNERS
per-file com_android_internal_net_* = file:/services/core/java/com/android/server/net/OWNERS
### Graphics ###
per-file android_graphics_* = file:/graphics/java/android/graphics/OWNERS
+
+### Text ###
+per-file android_text_* = file:/core/java/android/text/OWNERS
+
# These are highly common-use files
per-file Android.bp = file:/graphics/java/android/graphics/OWNERS
per-file AndroidRuntime.cpp = file:/graphics/java/android/graphics/OWNERS
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index ca9124a78204..e035ab151190 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -716,8 +716,6 @@ message GlobalSettingsProto {
optional SettingProto nr_nsa_tracking_screen_off_mode = 153 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto nsd_on = 83 [ (android.privacy).dest = DEST_AUTOMATIC ];
-
message Ntp {
option (android.msg_privacy).dest = DEST_EXPLICIT;
diff --git a/core/tests/coretests/src/android/net/NetworkPolicyTest.kt b/core/tests/coretests/src/android/net/NetworkPolicyTest.kt
index d936cad15689..121caef87f6f 100644
--- a/core/tests/coretests/src/android/net/NetworkPolicyTest.kt
+++ b/core/tests/coretests/src/android/net/NetworkPolicyTest.kt
@@ -16,6 +16,10 @@
package android.net
+import android.net.NetworkTemplate.MATCH_BLUETOOTH
+import android.net.NetworkTemplate.MATCH_ETHERNET
+import android.net.NetworkTemplate.MATCH_MOBILE
+import android.net.NetworkTemplate.MATCH_WIFI
import android.text.format.Time.TIMEZONE_UTC
import androidx.test.runner.AndroidJUnit4
import org.junit.Test
@@ -24,6 +28,8 @@ import java.io.ByteArrayInputStream
import java.io.DataInputStream
import java.time.ZoneId
import kotlin.test.assertEquals
+import kotlin.test.assertFalse
+import kotlin.test.assertTrue
private const val TEST_IMSI1 = "TESTIMSI1"
private const val TEST_SSID1 = "TESTISSID1"
@@ -53,4 +59,26 @@ class NetworkPolicyTest {
val restored = NetworkPolicy.getNetworkPolicyFromBackup(stream)
assertEquals(policy, restored)
}
+
+ @Test
+ fun testIsTemplatePersistable() {
+ listOf(MATCH_MOBILE, MATCH_WIFI).forEach {
+ // Verify wildcard templates cannot be persistable.
+ assertFalse(NetworkPolicy.isTemplatePersistable(NetworkTemplate.Builder(it).build()))
+
+ // Verify mobile/wifi templates can be persistable if the Subscriber Id is supplied.
+ assertTrue(NetworkPolicy.isTemplatePersistable(NetworkTemplate.Builder(it)
+ .setSubscriberIds(setOf(TEST_IMSI1)).build()))
+ }
+
+ // Verify bluetooth and ethernet templates can be persistable without any other
+ // field is supplied.
+ listOf(MATCH_BLUETOOTH, MATCH_ETHERNET).forEach {
+ assertTrue(NetworkPolicy.isTemplatePersistable(NetworkTemplate.Builder(it).build()))
+ }
+
+ // Verify wifi template can be persistable if the Wifi Network Key is supplied.
+ assertTrue(NetworkPolicy.isTemplatePersistable(NetworkTemplate.Builder(MATCH_WIFI)
+ .setWifiNetworkKey(TEST_SSID1).build()))
+ }
} \ No newline at end of file
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 60f4a5a226db..982cf07da358 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -6791,56 +6791,63 @@ public class AudioManager {
/**
* Returns a list of audio formats that corresponds to encoding formats
- * supported on offload path for A2DP and LE audio playback.
+ * supported on offload path for A2DP playback.
*
- * @param deviceType Indicates the target device type {@link AudioSystem.DeviceType}
* @return a list of {@link BluetoothCodecConfig} objects containing encoding formats
- * supported for offload A2DP playback or a list of {@link BluetoothLeAudioCodecConfig}
- * objects containing encoding formats supported for offload LE Audio playback
+ * supported for offload A2DP playback
* @hide
*/
- public List<?> getHwOffloadFormatsSupportedForBluetoothMedia(
- @AudioSystem.DeviceType int deviceType) {
- ArrayList<Integer> formatsList = new ArrayList<Integer>();
- ArrayList<BluetoothCodecConfig> a2dpCodecConfigList = new ArrayList<BluetoothCodecConfig>();
- ArrayList<BluetoothLeAudioCodecConfig> leAudioCodecConfigList =
- new ArrayList<BluetoothLeAudioCodecConfig>();
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ public @NonNull List<BluetoothCodecConfig> getHwOffloadFormatsSupportedForA2dp() {
+ ArrayList<Integer> formatsList = new ArrayList<>();
+ ArrayList<BluetoothCodecConfig> codecConfigList = new ArrayList<>();
- if (deviceType != AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP
- && deviceType != AudioSystem.DEVICE_OUT_BLE_HEADSET) {
- throw new IllegalArgumentException(
- "Illegal devicetype for the getHwOffloadFormatsSupportedForBluetoothMedia");
+ int status = AudioSystem.getHwOffloadFormatsSupportedForBluetoothMedia(
+ AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, formatsList);
+ if (status != AudioManager.SUCCESS) {
+ Log.e(TAG, "getHwOffloadEncodingFormatsSupportedForA2DP failed:" + status);
+ return codecConfigList;
+ }
+
+ for (Integer format : formatsList) {
+ int btSourceCodec = AudioSystem.audioFormatToBluetoothSourceCodec(format);
+ if (btSourceCodec != BluetoothCodecConfig.SOURCE_CODEC_TYPE_INVALID) {
+ codecConfigList.add(new BluetoothCodecConfig(btSourceCodec));
+ }
}
+ return codecConfigList;
+ }
+
+ /**
+ * Returns a list of audio formats that corresponds to encoding formats
+ * supported on offload path for Le audio playback.
+ *
+ * @return a list of {@link BluetoothLeAudioCodecConfig} objects containing encoding formats
+ * supported for offload Le Audio playback
+ * @hide
+ */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @NonNull
+ public List<BluetoothLeAudioCodecConfig> getHwOffloadFormatsSupportedForLeAudio() {
+ ArrayList<Integer> formatsList = new ArrayList<>();
+ ArrayList<BluetoothLeAudioCodecConfig> leAudioCodecConfigList = new ArrayList<>();
- int status = AudioSystem.getHwOffloadFormatsSupportedForBluetoothMedia(deviceType,
- formatsList);
+ int status = AudioSystem.getHwOffloadFormatsSupportedForBluetoothMedia(
+ AudioSystem.DEVICE_OUT_BLE_HEADSET, formatsList);
if (status != AudioManager.SUCCESS) {
- Log.e(TAG, "getHwOffloadFormatsSupportedForBluetoothMedia for deviceType "
- + deviceType + " failed:" + status);
- return a2dpCodecConfigList;
+ Log.e(TAG, "getHwOffloadEncodingFormatsSupportedForLeAudio failed:" + status);
+ return leAudioCodecConfigList;
}
- if (deviceType == AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) {
- for (Integer format : formatsList) {
- int btSourceCodec = AudioSystem.audioFormatToBluetoothSourceCodec(format);
- if (btSourceCodec != BluetoothCodecConfig.SOURCE_CODEC_TYPE_INVALID) {
- a2dpCodecConfigList.add(new BluetoothCodecConfig(btSourceCodec));
- }
+ for (Integer format : formatsList) {
+ int btLeAudioCodec = AudioSystem.audioFormatToBluetoothLeAudioSourceCodec(format);
+ if (btLeAudioCodec != BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_INVALID) {
+ leAudioCodecConfigList.add(new BluetoothLeAudioCodecConfig.Builder()
+ .setCodecType(btLeAudioCodec)
+ .build());
}
- return a2dpCodecConfigList;
- } else if (deviceType == AudioSystem.DEVICE_OUT_BLE_HEADSET) {
- for (Integer format : formatsList) {
- int btLeAudioCodec = AudioSystem.audioFormatToBluetoothLeAudioSourceCodec(format);
- if (btLeAudioCodec != BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_INVALID) {
- leAudioCodecConfigList.add(new BluetoothLeAudioCodecConfig.Builder()
- .setCodecType(btLeAudioCodec)
- .build());
- }
- }
- return leAudioCodecConfigList;
}
- Log.e(TAG, "Input deviceType " + deviceType + " doesn't support.");
- return a2dpCodecConfigList;
+ return leAudioCodecConfigList;
}
// Since we need to calculate the changes since THE LAST NOTIFICATION, and not since the
diff --git a/media/java/android/media/MediaActionSound.java b/media/java/android/media/MediaActionSound.java
index dcd4dce5f3eb..ec56d614f2b5 100644
--- a/media/java/android/media/MediaActionSound.java
+++ b/media/java/android/media/MediaActionSound.java
@@ -16,8 +16,11 @@
package android.media;
-import android.media.AudioManager;
+import android.content.Context;
import android.media.SoundPool;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
import android.util.Log;
/**
@@ -104,6 +107,26 @@ public class MediaActionSound {
private static final int STATE_LOADING_PLAY_REQUESTED = 2;
private static final int STATE_LOADED = 3;
+ /**
+ * <p>Returns true if the application must play the shutter sound in accordance
+ * to certain regional restrictions. </p>
+ *
+ * <p>If this method returns true, applications are strongly recommended to use
+ * MediaActionSound.play(SHUTTER_CLICK) or START_VIDEO_RECORDING whenever it captures
+ * images or video to storage or sends them over the network.</p>
+ */
+ public static boolean mustPlayShutterSound() {
+ boolean result = false;
+ IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
+ IAudioService audioService = IAudioService.Stub.asInterface(b);
+ try {
+ result = audioService.isCameraSoundForced();
+ } catch (RemoteException e) {
+ Log.e(TAG, "audio service is unavailable for queries, defaulting to false");
+ }
+ return result;
+ }
+
private class SoundState {
public final int name;
public int id;
diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index a0f6fb9577c3..9147c123c6f3 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -2720,6 +2720,42 @@ public final class TvContract {
*/
public static final String COLUMN_GLOBAL_CONTENT_ID = "global_content_id";
+ /**
+ * The flag indicating whether this TV program is scrambled or not.
+ *
+ * <p>Use the same coding for scrambled in the underlying broadcast standard
+ * if {@code free_ca_mode} in EIT is defined there (e.g. ETSI EN 300 468).
+ *
+ * <p>Type: INTEGER (boolean)
+ */
+ public static final String COLUMN_SCRAMBLED = "scrambled";
+
+ /**
+ * The comma-separated series IDs of this TV program for episodic TV shows.
+ *
+ * <p>This is used to indicate the series IDs.
+ * Programs in the same series share a series ID.
+ * Use this instead of {@link #COLUMN_SERIES_ID} if more than one series IDs
+ * are assigned to the TV program.
+ *
+ * <p>Can be empty.
+ *
+ * <p>Type: TEXT
+ */
+ public static final String COLUMN_MULTI_SERIES_ID = "multi_series_id";
+
+ /**
+ * The internal ID used by individual TV input services.
+ *
+ * <p>This is internal to the provider that inserted it, and should not be decoded by other
+ * apps.
+ *
+ * <p>Can be empty.
+ *
+ * <p>Type: TEXT
+ */
+ public static final String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
+
private Programs() {}
/** Canonical genres for TV programs. */
@@ -3052,6 +3088,32 @@ public final class TvContract {
public static final String COLUMN_RECORDING_EXPIRE_TIME_UTC_MILLIS =
"recording_expire_time_utc_millis";
+ /**
+ * The comma-separated series IDs of this TV program for episodic TV shows.
+ *
+ * <p>This is used to indicate the series IDs.
+ * Programs in the same series share a series ID.
+ * Use this instead of {@link #COLUMN_SERIES_ID} if more than one series IDs
+ * are assigned to the TV program.
+ *
+ * <p>Can be empty.
+ *
+ * <p>Type: TEXT
+ */
+ public static final String COLUMN_MULTI_SERIES_ID = "multi_series_id";
+
+ /**
+ * The internal ID used by individual TV input services.
+ *
+ * <p>This is internal to the provider that inserted it, and should not be decoded by other
+ * apps.
+ *
+ * <p>Can be empty.
+ *
+ * <p>Type: TEXT
+ */
+ public static final String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
+
private RecordedPrograms() {}
}
diff --git a/packages/ConnectivityT/framework-t/Android.bp b/packages/ConnectivityT/framework-t/Android.bp
index 931a55b27ddb..0bda923f2389 100644
--- a/packages/ConnectivityT/framework-t/Android.bp
+++ b/packages/ConnectivityT/framework-t/Android.bp
@@ -114,6 +114,23 @@ filegroup {
],
}
+// Ethernet related libraries.
+
+filegroup {
+ name: "framework-connectivity-ethernet-sources",
+ srcs: [
+ "src/android/net/EthernetManager.java",
+ "src/android/net/EthernetNetworkSpecifier.java",
+ "src/android/net/IEthernetManager.aidl",
+ "src/android/net/IEthernetServiceListener.aidl",
+ "src/android/net/ITetheredInterfaceCallback.aidl",
+ ],
+ path: "src",
+ visibility: [
+ "//visibility:private",
+ ],
+}
+
// Connectivity-T common libraries.
filegroup {
@@ -130,6 +147,7 @@ filegroup {
filegroup {
name: "framework-connectivity-tiramisu-sources",
srcs: [
+ ":framework-connectivity-ethernet-sources",
":framework-connectivity-ipsec-sources",
":framework-connectivity-netstats-sources",
":framework-connectivity-nsd-sources",
diff --git a/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java b/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java
index 8a6c85d54896..ca8330921620 100644
--- a/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java
+++ b/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java
@@ -45,8 +45,6 @@ import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.ServiceManager.ServiceNotFoundException;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.DataUnit;
@@ -135,15 +133,6 @@ public class NetworkStatsManager {
private int mFlags;
- /**
- * {@hide}
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public NetworkStatsManager(Context context) throws ServiceNotFoundException {
- this(context, INetworkStatsService.Stub.asInterface(
- ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE)));
- }
-
/** @hide */
@VisibleForTesting
public NetworkStatsManager(Context context, INetworkStatsService service) {
diff --git a/core/java/android/net/EthernetManager.java b/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java
index 7cd63ef9cc5a..7cd63ef9cc5a 100644
--- a/core/java/android/net/EthernetManager.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java
diff --git a/core/java/android/net/EthernetNetworkSpecifier.java b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkSpecifier.java
index 62c576144221..62c576144221 100644
--- a/core/java/android/net/EthernetNetworkSpecifier.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkSpecifier.java
diff --git a/core/java/android/net/IEthernetManager.aidl b/packages/ConnectivityT/framework-t/src/android/net/IEthernetManager.aidl
index e058e5a70c71..e058e5a70c71 100644
--- a/core/java/android/net/IEthernetManager.aidl
+++ b/packages/ConnectivityT/framework-t/src/android/net/IEthernetManager.aidl
diff --git a/core/java/android/net/IEthernetServiceListener.aidl b/packages/ConnectivityT/framework-t/src/android/net/IEthernetServiceListener.aidl
index 782fa19d9df7..782fa19d9df7 100644
--- a/core/java/android/net/IEthernetServiceListener.aidl
+++ b/packages/ConnectivityT/framework-t/src/android/net/IEthernetServiceListener.aidl
diff --git a/core/java/android/net/ITetheredInterfaceCallback.aidl b/packages/ConnectivityT/framework-t/src/android/net/ITetheredInterfaceCallback.aidl
index 14aa0237f24a..14aa0237f24a 100644
--- a/core/java/android/net/ITetheredInterfaceCallback.aidl
+++ b/packages/ConnectivityT/framework-t/src/android/net/ITetheredInterfaceCallback.aidl
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecAlgorithm.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecAlgorithm.java
index 840af28b77e7..a84e7a9c6344 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecAlgorithm.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/IpSecAlgorithm.java
@@ -23,7 +23,6 @@ import android.os.Parcel;
import android.os.Parcelable;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.HexDump;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -469,20 +468,12 @@ public final class IpSecAlgorithm implements Parcelable {
}
}
- // Because encryption keys are sensitive and userdebug builds are used by large user pools
- // such as beta testers, we only allow sensitive info such as keys on eng builds.
- private static boolean isUnsafeBuild() {
- return Build.IS_DEBUGGABLE && Build.IS_ENG;
- }
-
@Override
@NonNull
public String toString() {
return new StringBuilder()
.append("{mName=")
.append(mName)
- .append(", mKey=")
- .append(isUnsafeBuild() ? HexDump.toHexString(mKey) : "<hidden>")
.append(", mTruncLenBits=")
.append(mTruncLenBits)
.append("}")
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecManager.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecManager.java
index 837629911ccd..0d15dffae92d 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecManager.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/IpSecManager.java
@@ -17,8 +17,6 @@ package android.net;
import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
-import static com.android.internal.util.Preconditions.checkNotNull;
-
import android.annotation.NonNull;
import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
@@ -46,6 +44,7 @@ import java.io.IOException;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.Socket;
+import java.util.Objects;
/**
* This class contains methods for managing IPsec sessions. Once configured, the kernel will apply
@@ -86,6 +85,7 @@ public final class IpSecManager {
*
* @hide
*/
+ @SystemApi(client = MODULE_LIBRARIES)
public static final int DIRECTION_FWD = 2;
/**
@@ -988,7 +988,7 @@ public final class IpSecManager {
*/
public IpSecManager(Context ctx, IIpSecService service) {
mContext = ctx;
- mService = checkNotNull(service, "missing service");
+ mService = Objects.requireNonNull(service, "missing service");
}
private static void maybeHandleServiceSpecificException(ServiceSpecificException sse) {
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecTransform.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecTransform.java
index b48c1fdaf1b2..36199a046cfc 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecTransform.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/IpSecTransform.java
@@ -33,7 +33,6 @@ import android.os.ServiceSpecificException;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.Preconditions;
import dalvik.system.CloseGuard;
@@ -41,6 +40,7 @@ import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.net.InetAddress;
+import java.util.Objects;
/**
* This class represents a transform, which roughly corresponds to an IPsec Security Association.
@@ -255,7 +255,7 @@ public final class IpSecTransform implements AutoCloseable {
@NonNull
public IpSecTransform.Builder setEncryption(@NonNull IpSecAlgorithm algo) {
// TODO: throw IllegalArgumentException if algo is not an encryption algorithm.
- Preconditions.checkNotNull(algo);
+ Objects.requireNonNull(algo);
mConfig.setEncryption(algo);
return this;
}
@@ -270,7 +270,7 @@ public final class IpSecTransform implements AutoCloseable {
@NonNull
public IpSecTransform.Builder setAuthentication(@NonNull IpSecAlgorithm algo) {
// TODO: throw IllegalArgumentException if algo is not an authentication algorithm.
- Preconditions.checkNotNull(algo);
+ Objects.requireNonNull(algo);
mConfig.setAuthentication(algo);
return this;
}
@@ -290,7 +290,7 @@ public final class IpSecTransform implements AutoCloseable {
*/
@NonNull
public IpSecTransform.Builder setAuthenticatedEncryption(@NonNull IpSecAlgorithm algo) {
- Preconditions.checkNotNull(algo);
+ Objects.requireNonNull(algo);
mConfig.setAuthenticatedEncryption(algo);
return this;
}
@@ -311,7 +311,7 @@ public final class IpSecTransform implements AutoCloseable {
@NonNull
public IpSecTransform.Builder setIpv4Encapsulation(
@NonNull IpSecManager.UdpEncapsulationSocket localSocket, int remotePort) {
- Preconditions.checkNotNull(localSocket);
+ Objects.requireNonNull(localSocket);
mConfig.setEncapType(ENCAP_ESPINUDP);
if (localSocket.getResourceId() == INVALID_RESOURCE_ID) {
throw new IllegalArgumentException("Invalid UdpEncapsulationSocket");
@@ -348,8 +348,8 @@ public final class IpSecTransform implements AutoCloseable {
@NonNull IpSecManager.SecurityParameterIndex spi)
throws IpSecManager.ResourceUnavailableException,
IpSecManager.SpiUnavailableException, IOException {
- Preconditions.checkNotNull(sourceAddress);
- Preconditions.checkNotNull(spi);
+ Objects.requireNonNull(sourceAddress);
+ Objects.requireNonNull(spi);
if (spi.getResourceId() == INVALID_RESOURCE_ID) {
throw new IllegalArgumentException("Invalid SecurityParameterIndex");
}
@@ -387,8 +387,8 @@ public final class IpSecTransform implements AutoCloseable {
@NonNull IpSecManager.SecurityParameterIndex spi)
throws IpSecManager.ResourceUnavailableException,
IpSecManager.SpiUnavailableException, IOException {
- Preconditions.checkNotNull(sourceAddress);
- Preconditions.checkNotNull(spi);
+ Objects.requireNonNull(sourceAddress);
+ Objects.requireNonNull(spi);
if (spi.getResourceId() == INVALID_RESOURCE_ID) {
throw new IllegalArgumentException("Invalid SecurityParameterIndex");
}
@@ -404,7 +404,7 @@ public final class IpSecTransform implements AutoCloseable {
* @param context current context
*/
public Builder(@NonNull Context context) {
- Preconditions.checkNotNull(context);
+ Objects.requireNonNull(context);
mContext = context;
mConfig = new IpSecConfig();
}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java
index c7ffc1933829..1986b83b12d8 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java
@@ -16,7 +16,7 @@
package android.net;
-import static com.android.internal.net.NetworkUtilsInternal.multiplySafeByRational;
+import static com.android.net.module.util.NetworkStatsUtils.multiplySafeByRational;
import android.annotation.IntDef;
import android.annotation.NonNull;
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsAccess.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsAccess.java
index 3885a9e6d5cb..591605d952e9 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsAccess.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsAccess.java
@@ -24,7 +24,7 @@ import static android.net.TrafficStats.UID_TETHERING;
import android.Manifest;
import android.annotation.IntDef;
import android.app.AppOpsManager;
-import android.app.admin.DevicePolicyManagerInternal;
+import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Binder;
@@ -32,8 +32,6 @@ import android.os.Process;
import android.os.UserHandle;
import android.telephony.TelephonyManager;
-import com.android.server.LocalServices;
-
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -109,8 +107,7 @@ public final class NetworkStatsAccess {
/** Returns the {@link NetworkStatsAccess.Level} for the given caller. */
public static @NetworkStatsAccess.Level int checkAccessLevel(
Context context, int callingUid, String callingPackage) {
- final DevicePolicyManagerInternal dpmi = LocalServices.getService(
- DevicePolicyManagerInternal.class);
+ final DevicePolicyManager mDpm = context.getSystemService(DevicePolicyManager.class);
final TelephonyManager tm = (TelephonyManager)
context.getSystemService(Context.TELEPHONY_SERVICE);
boolean hasCarrierPrivileges;
@@ -123,8 +120,9 @@ public final class NetworkStatsAccess {
Binder.restoreCallingIdentity(token);
}
- final boolean isDeviceOwner = dpmi != null && dpmi.isActiveDeviceOwner(callingUid);
+ final boolean isDeviceOwner = mDpm != null && mDpm.isDeviceOwnerApp(callingPackage);
final int appId = UserHandle.getAppId(callingUid);
+
if (hasCarrierPrivileges || isDeviceOwner
|| appId == Process.SYSTEM_UID || appId == Process.NETWORK_STACK_UID) {
// Carrier-privileged apps and device owners, and the system (including the
@@ -139,8 +137,8 @@ public final class NetworkStatsAccess {
}
//TODO(b/169395065) Figure out if this flow makes sense in Device Owner mode.
- boolean isProfileOwner = dpmi != null && (dpmi.isActiveProfileOwner(callingUid)
- || dpmi.isActiveDeviceOwner(callingUid));
+ boolean isProfileOwner = mDpm != null && (mDpm.isProfileOwnerApp(callingPackage)
+ || mDpm.isDeviceOwnerApp(callingPackage));
if (isProfileOwner) {
// Apps with the AppOps permission, profile owners, and apps with the privileged
// permission can access data usage for all apps in this user/profile.
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsCollection.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsCollection.java
index 0d3b9ed4e3d4..8d1347e25bb6 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsCollection.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsCollection.java
@@ -30,7 +30,7 @@ import static android.net.NetworkStats.UID_ALL;
import static android.net.TrafficStats.UID_REMOVED;
import static android.text.format.DateUtils.WEEK_IN_MILLIS;
-import static com.android.internal.net.NetworkUtilsInternal.multiplySafeByRational;
+import static com.android.net.module.util.NetworkStatsUtils.multiplySafeByRational;
import android.os.Binder;
import android.service.NetworkStatsCollectionKeyProto;
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsHistory.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsHistory.java
index a875e1ad45a3..3eef4ee6f829 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsHistory.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsHistory.java
@@ -28,8 +28,8 @@ import static android.net.NetworkStatsHistory.ParcelUtils.readLongArray;
import static android.net.NetworkStatsHistory.ParcelUtils.writeLongArray;
import static android.text.format.DateUtils.SECOND_IN_MILLIS;
-import static com.android.internal.net.NetworkUtilsInternal.multiplySafeByRational;
import static com.android.internal.util.ArrayUtils.total;
+import static com.android.net.module.util.NetworkStatsUtils.multiplySafeByRational;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkTemplate.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkTemplate.java
index 8b9c14df7dc8..d85291318fa4 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkTemplate.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkTemplate.java
@@ -24,6 +24,8 @@ import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.ConnectivityManager.TYPE_WIFI_P2P;
import static android.net.ConnectivityManager.TYPE_WIMAX;
import static android.net.NetworkIdentity.OEM_NONE;
+import static android.net.NetworkIdentity.OEM_PAID;
+import static android.net.NetworkIdentity.OEM_PRIVATE;
import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
import static android.net.NetworkStats.DEFAULT_NETWORK_YES;
@@ -35,6 +37,7 @@ import static android.net.NetworkStats.ROAMING_NO;
import static android.net.NetworkStats.ROAMING_YES;
import static android.net.wifi.WifiInfo.sanitizeSsid;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
@@ -44,15 +47,21 @@ import android.os.Parcelable;
import android.telephony.Annotation.NetworkType;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
+import android.util.ArraySet;
import com.android.internal.util.ArrayUtils;
import com.android.net.module.util.NetworkIdentityUtils;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
/**
* Predicate used to match {@link NetworkIdentity}, usually when collecting
@@ -60,40 +69,88 @@ import java.util.Objects;
*
* @hide
*/
-public class NetworkTemplate implements Parcelable {
- private static final String TAG = "NetworkTemplate";
-
+// @SystemApi(client = MODULE_LIBRARIES)
+public final class NetworkTemplate implements Parcelable {
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "MATCH_" }, value = {
+ MATCH_MOBILE,
+ MATCH_WIFI,
+ MATCH_ETHERNET,
+ MATCH_BLUETOOTH,
+ MATCH_CARRIER
+ })
+ public @interface TemplateMatchRule{}
+
+ /** Match rule to match cellular networks with given Subscriber Ids. */
public static final int MATCH_MOBILE = 1;
+ /** Match rule to match wifi networks. */
public static final int MATCH_WIFI = 4;
+ /** Match rule to match ethernet networks. */
public static final int MATCH_ETHERNET = 5;
+ /**
+ * Match rule to match all cellular networks.
+ *
+ * @hide
+ */
public static final int MATCH_MOBILE_WILDCARD = 6;
+ /**
+ * Match rule to match all wifi networks.
+ *
+ * @hide
+ */
public static final int MATCH_WIFI_WILDCARD = 7;
+ /** Match rule to match bluetooth networks. */
public static final int MATCH_BLUETOOTH = 8;
+ /**
+ * Match rule to match networks with {@link Connectivity#TYPE_PROXY} as the legacy network type.
+ *
+ * @hide
+ */
public static final int MATCH_PROXY = 9;
+ /**
+ * Match rule to match all networks with subscriberId inside the template. Some carriers
+ * may offer non-cellular networks like WiFi, which will be matched by this rule.
+ */
public static final int MATCH_CARRIER = 10;
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "SUBSCRIBER_ID_MATCH_RULE_" }, value = {
+ SUBSCRIBER_ID_MATCH_RULE_EXACT,
+ SUBSCRIBER_ID_MATCH_RULE_ALL
+ })
+ public @interface SubscriberIdMatchRule{}
/**
* Value of the match rule of the subscriberId to match networks with specific subscriberId.
+ *
+ * @hide
*/
public static final int SUBSCRIBER_ID_MATCH_RULE_EXACT = 0;
/**
* Value of the match rule of the subscriberId to match networks with any subscriberId which
* includes null and non-null.
+ *
+ * @hide
*/
public static final int SUBSCRIBER_ID_MATCH_RULE_ALL = 1;
+ // TODO: Remove this and replace all callers with WIFI_NETWORK_KEY_ALL.
+ /** @hide */
+ public static final String WIFI_NETWORKID_ALL = null;
+
/**
- * Wi-Fi Network ID is never supposed to be null (if it is, it is a bug that
+ * Wi-Fi Network Key is never supposed to be null (if it is, it is a bug that
* should be fixed), so it's not possible to want to match null vs
- * non-null. Therefore it's fine to use null as a sentinel for Network ID.
+ * non-null. Therefore it's fine to use null as a sentinel for Wifi Network Key.
+ *
+ * @hide
*/
- public static final String WIFI_NETWORKID_ALL = null;
+ public static final String WIFI_NETWORK_KEY_ALL = WIFI_NETWORKID_ALL;
/**
* Include all network types when filtering. This is meant to merge in with the
* {@code TelephonyManager.NETWORK_TYPE_*} constants, and thus needs to stay in sync.
- *
- * @hide
*/
public static final int NETWORK_TYPE_ALL = -1;
/**
@@ -106,21 +163,37 @@ public class NetworkTemplate implements Parcelable {
*/
public static final int NETWORK_TYPE_5G_NSA = -2;
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "OEM_MANAGED_" }, value = {
+ OEM_MANAGED_ALL,
+ OEM_MANAGED_NO,
+ OEM_MANAGED_YES,
+ OEM_MANAGED_PAID,
+ OEM_MANAGED_PRIVATE
+ })
+ public @interface OemManaged{}
+
/**
* Value to match both OEM managed and unmanaged networks (all networks).
- * @hide
*/
public static final int OEM_MANAGED_ALL = -1;
/**
* Value to match networks which are not OEM managed.
- * @hide
*/
public static final int OEM_MANAGED_NO = OEM_NONE;
/**
* Value to match any OEM managed network.
- * @hide
*/
public static final int OEM_MANAGED_YES = -2;
+ /**
+ * Network has {@link NetworkCapabilities#NET_CAPABILITY_OEM_PAID}.
+ */
+ public static final int OEM_MANAGED_PAID = OEM_PAID;
+ /**
+ * Network has {@link NetworkCapabilities#NET_CAPABILITY_OEM_PRIVATE}.
+ */
+ public static final int OEM_MANAGED_PRIVATE = OEM_PRIVATE;
private static boolean isKnownMatchRule(final int rule) {
switch (rule) {
@@ -142,6 +215,8 @@ public class NetworkTemplate implements Parcelable {
/**
* Template to match {@link ConnectivityManager#TYPE_MOBILE} networks with
* the given IMSI.
+ *
+ * @hide
*/
@UnsupportedAppUsage
public static NetworkTemplate buildTemplateMobileAll(String subscriberId) {
@@ -152,6 +227,8 @@ public class NetworkTemplate implements Parcelable {
* Template to match cellular networks with the given IMSI, {@code ratType} and
* {@code metered}. Use {@link #NETWORK_TYPE_ALL} to include all network types when
* filtering. See {@code TelephonyManager.NETWORK_TYPE_*}.
+ *
+ * @hide
*/
public static NetworkTemplate buildTemplateMobileWithRatType(@Nullable String subscriberId,
@NetworkType int ratType, int metered) {
@@ -168,6 +245,8 @@ public class NetworkTemplate implements Parcelable {
/**
* Template to match metered {@link ConnectivityManager#TYPE_MOBILE} networks,
* regardless of IMSI.
+ *
+ * @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public static NetworkTemplate buildTemplateMobileWildcard() {
@@ -177,6 +256,8 @@ public class NetworkTemplate implements Parcelable {
/**
* Template to match all metered {@link ConnectivityManager#TYPE_WIFI} networks,
* regardless of SSID.
+ *
+ * @hide
*/
@UnsupportedAppUsage
public static NetworkTemplate buildTemplateWifiWildcard() {
@@ -185,6 +266,7 @@ public class NetworkTemplate implements Parcelable {
return new NetworkTemplate(MATCH_WIFI_WILDCARD, null, null);
}
+ /** @hide */
@Deprecated
@UnsupportedAppUsage
public static NetworkTemplate buildTemplateWifi() {
@@ -194,6 +276,8 @@ public class NetworkTemplate implements Parcelable {
/**
* Template to match {@link ConnectivityManager#TYPE_WIFI} networks with the
* given SSID.
+ *
+ * @hide
*/
public static NetworkTemplate buildTemplateWifi(@NonNull String networkId) {
Objects.requireNonNull(networkId);
@@ -208,7 +292,10 @@ public class NetworkTemplate implements Parcelable {
* Template to match all {@link ConnectivityManager#TYPE_WIFI} networks with the given SSID,
* and IMSI.
*
- * Call with {@link #WIFI_NETWORKID_ALL} for {@code networkId} to get result regardless of SSID.
+ * Call with {@link #WIFI_NETWORK_KEY_ALL} for {@code networkId} to get result regardless
+ * of SSID.
+ *
+ * @hide
*/
public static NetworkTemplate buildTemplateWifi(@Nullable String networkId,
@Nullable String subscriberId) {
@@ -221,6 +308,8 @@ public class NetworkTemplate implements Parcelable {
/**
* Template to combine all {@link ConnectivityManager#TYPE_ETHERNET} style
* networks together.
+ *
+ * @hide
*/
@UnsupportedAppUsage
public static NetworkTemplate buildTemplateEthernet() {
@@ -230,6 +319,8 @@ public class NetworkTemplate implements Parcelable {
/**
* Template to combine all {@link ConnectivityManager#TYPE_BLUETOOTH} style
* networks together.
+ *
+ * @hide
*/
public static NetworkTemplate buildTemplateBluetooth() {
return new NetworkTemplate(MATCH_BLUETOOTH, null, null);
@@ -238,6 +329,8 @@ public class NetworkTemplate implements Parcelable {
/**
* Template to combine all {@link ConnectivityManager#TYPE_PROXY} style
* networks together.
+ *
+ * @hide
*/
public static NetworkTemplate buildTemplateProxy() {
return new NetworkTemplate(MATCH_PROXY, null, null);
@@ -245,6 +338,8 @@ public class NetworkTemplate implements Parcelable {
/**
* Template to match all metered carrier networks with the given IMSI.
+ *
+ * @hide
*/
public static NetworkTemplate buildTemplateCarrierMetered(@NonNull String subscriberId) {
Objects.requireNonNull(subscriberId);
@@ -267,6 +362,7 @@ public class NetworkTemplate implements Parcelable {
*/
private final String[] mMatchSubscriberIds;
+ // TODO: Change variable name to match the Api surface.
private final String mNetworkId;
// Matches for the NetworkStats constants METERED_*, ROAMING_* and DEFAULT_NETWORK_*.
@@ -283,14 +379,14 @@ public class NetworkTemplate implements Parcelable {
// Bitfield containing OEM network properties{@code NetworkIdentity#OEM_*}.
private final int mOemManaged;
- private void checkValidSubscriberIdMatchRule() {
- switch (mMatchRule) {
+ private static void checkValidSubscriberIdMatchRule(int matchRule, int subscriberIdMatchRule) {
+ switch (matchRule) {
case MATCH_MOBILE:
case MATCH_CARRIER:
// MOBILE and CARRIER templates must always specify a subscriber ID.
- if (mSubscriberIdMatchRule == SUBSCRIBER_ID_MATCH_RULE_ALL) {
- throw new IllegalArgumentException("Invalid SubscriberIdMatchRule"
- + "on match rule: " + getMatchRuleName(mMatchRule));
+ if (subscriberIdMatchRule == SUBSCRIBER_ID_MATCH_RULE_ALL) {
+ throw new IllegalArgumentException("Invalid SubscriberIdMatchRule "
+ + "on match rule: " + getMatchRuleName(matchRule));
}
return;
default:
@@ -298,12 +394,14 @@ public class NetworkTemplate implements Parcelable {
}
}
+ /** @hide */
// TODO: Deprecate this constructor, mark it @UnsupportedAppUsage(maxTargetSdk = S)
@UnsupportedAppUsage
public NetworkTemplate(int matchRule, String subscriberId, String networkId) {
this(matchRule, subscriberId, new String[] { subscriberId }, networkId);
}
+ /** @hide */
public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
String networkId) {
// Older versions used to only match MATCH_MOBILE and MATCH_MOBILE_WILDCARD templates
@@ -316,6 +414,7 @@ public class NetworkTemplate implements Parcelable {
OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_EXACT);
}
+ /** @hide */
// TODO: Remove it after updating all of the caller.
public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
String networkId, int metered, int roaming, int defaultNetwork, int subType,
@@ -324,6 +423,7 @@ public class NetworkTemplate implements Parcelable {
defaultNetwork, subType, oemManaged, SUBSCRIBER_ID_MATCH_RULE_EXACT);
}
+ /** @hide */
public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
String networkId, int metered, int roaming, int defaultNetwork, int subType,
int oemManaged, int subscriberIdMatchRule) {
@@ -339,7 +439,7 @@ public class NetworkTemplate implements Parcelable {
mSubType = subType;
mOemManaged = oemManaged;
mSubscriberIdMatchRule = subscriberIdMatchRule;
- checkValidSubscriberIdMatchRule();
+ checkValidSubscriberIdMatchRule(matchRule, subscriberIdMatchRule);
if (!isKnownMatchRule(matchRule)) {
throw new IllegalArgumentException("Unknown network template rule " + matchRule
+ " will not match any identity.");
@@ -360,7 +460,7 @@ public class NetworkTemplate implements Parcelable {
}
@Override
- public void writeToParcel(Parcel dest, int flags) {
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mMatchRule);
dest.writeString(mSubscriberId);
dest.writeStringArray(mMatchSubscriberIds);
@@ -437,7 +537,7 @@ public class NetworkTemplate implements Parcelable {
return false;
}
- private String subscriberIdMatchRuleToString(int rule) {
+ private static String subscriberIdMatchRuleToString(int rule) {
switch (rule) {
case SUBSCRIBER_ID_MATCH_RULE_EXACT:
return "EXACT_MATCH";
@@ -448,6 +548,7 @@ public class NetworkTemplate implements Parcelable {
}
}
+ /** @hide */
public boolean isMatchRuleMobile() {
switch (mMatchRule) {
case MATCH_MOBILE:
@@ -458,48 +559,108 @@ public class NetworkTemplate implements Parcelable {
}
}
- public boolean isPersistable() {
+ /**
+ * Get match rule of the template. See {@code MATCH_*}.
+ */
+ @UnsupportedAppUsage
+ public int getMatchRule() {
+ // Wildcard rules are not exposed. For external callers, convert wildcard rules to
+ // exposed rules before returning.
switch (mMatchRule) {
case MATCH_MOBILE_WILDCARD:
+ return MATCH_MOBILE;
case MATCH_WIFI_WILDCARD:
- return false;
- case MATCH_CARRIER:
- return mSubscriberId != null;
- case MATCH_WIFI:
- if (Objects.equals(mNetworkId, WIFI_NETWORKID_ALL)
- && mSubscriberIdMatchRule == SUBSCRIBER_ID_MATCH_RULE_ALL) {
- return false;
- }
- return true;
+ return MATCH_WIFI;
default:
- return true;
+ return mMatchRule;
}
}
- @UnsupportedAppUsage
- public int getMatchRule() {
- return mMatchRule;
- }
-
+ /**
+ * Get subscriber Id of the template.
+ */
+ @Nullable
@UnsupportedAppUsage
public String getSubscriberId() {
return mSubscriberId;
}
+ /**
+ * Get set of subscriber Ids of the template.
+ */
+ @NonNull
+ public Set<String> getSubscriberIds() {
+ return new ArraySet<>(Arrays.asList(mMatchSubscriberIds));
+ }
+
+ /**
+ * Get Wifi Network Key of the template. See {@link WifiInfo#getCurrentNetworkKey()}.
+ */
+ @Nullable
+ public String getWifiNetworkKey() {
+ return mNetworkId;
+ }
+
+ /** @hide */
+ // TODO: Remove this and replace all callers with {@link #getWifiNetworkKey()}.
+ @Nullable
public String getNetworkId() {
return mNetworkId;
}
+ /**
+ * Get Subscriber Id Match Rule of the template.
+ *
+ * @hide
+ */
public int getSubscriberIdMatchRule() {
return mSubscriberIdMatchRule;
}
+ /**
+ * Get meteredness filter of the template.
+ */
+ @NetworkStats.Meteredness
public int getMeteredness() {
return mMetered;
}
/**
+ * Get roaming filter of the template.
+ */
+ @NetworkStats.Roaming
+ public int getRoaming() {
+ return mRoaming;
+ }
+
+ /**
+ * Get the default network status filter of the template.
+ */
+ @NetworkStats.DefaultNetwork
+ public int getDefaultNetworkStatus() {
+ return mDefaultNetwork;
+ }
+
+ /**
+ * Get the Radio Access Technology(RAT) type filter of the template.
+ */
+ public int getRatType() {
+ return mSubType;
+ }
+
+ /**
+ * Get the OEM managed filter of the template. See {@code OEM_MANAGED_*} or
+ * {@code android.net.NetworkIdentity#OEM_*}.
+ */
+ @OemManaged
+ public int getOemManaged() {
+ return mOemManaged;
+ }
+
+ /**
* Test if given {@link NetworkIdentity} matches this template.
+ *
+ * @hide
*/
public boolean matches(NetworkIdentity ident) {
if (!matchesMetered(ident)) return false;
@@ -565,6 +726,8 @@ public class NetworkTemplate implements Parcelable {
* Check if this template matches {@code subscriberId}. Returns true if this
* template was created with {@code SUBSCRIBER_ID_MATCH_RULE_ALL}, or with a
* {@code mMatchSubscriberIds} array that contains {@code subscriberId}.
+ *
+ * @hide
*/
public boolean matchesSubscriberId(@Nullable String subscriberId) {
return mSubscriberIdMatchRule == SUBSCRIBER_ID_MATCH_RULE_ALL
@@ -573,10 +736,10 @@ public class NetworkTemplate implements Parcelable {
/**
* Check if network with matching SSID. Returns true when the SSID matches, or when
- * {@code mNetworkId} is {@code WIFI_NETWORKID_ALL}.
+ * {@code mNetworkId} is {@code WIFI_NETWORK_KEY_ALL}.
*/
private boolean matchesWifiNetworkId(@Nullable String networkId) {
- return Objects.equals(mNetworkId, WIFI_NETWORKID_ALL)
+ return Objects.equals(mNetworkId, WIFI_NETWORK_KEY_ALL)
|| Objects.equals(sanitizeSsid(mNetworkId), sanitizeSsid(networkId));
}
@@ -599,10 +762,13 @@ public class NetworkTemplate implements Parcelable {
* The mapping is corresponding to {@code TelephonyManager#NETWORK_CLASS_BIT_MASK_*}.
*
* @param ratType An integer defined in {@code TelephonyManager#NETWORK_TYPE_*}.
+ *
+ * @hide
*/
// TODO: 1. Consider move this to TelephonyManager if used by other modules.
// 2. Consider make this configurable.
// 3. Use TelephonyManager APIs when available.
+ // TODO: @SystemApi when ready.
public static int getCollapsedRatType(int ratType) {
switch (ratType) {
case TelephonyManager.NETWORK_TYPE_GPRS:
@@ -639,7 +805,10 @@ public class NetworkTemplate implements Parcelable {
/**
* Return all supported collapsed RAT types that could be returned by
* {@link #getCollapsedRatType(int)}.
+ *
+ * @hide
*/
+ // TODO: @SystemApi when ready.
@NonNull
public static final int[] getAllCollapsedRatTypes() {
final int[] ratTypes = TelephonyManager.getAllNetworkTypes();
@@ -779,6 +948,8 @@ public class NetworkTemplate implements Parcelable {
* active merge set [A,B], we'd return a new template that primarily matches
* A, but also matches B.
* TODO: remove and use {@link #normalize(NetworkTemplate, List)}.
+ *
+ * @hide
*/
@UnsupportedAppUsage
public static NetworkTemplate normalize(NetworkTemplate template, String[] merged) {
@@ -797,7 +968,10 @@ public class NetworkTemplate implements Parcelable {
* For example, given an incoming template matching B, and the currently
* active merge set [A,B], we'd return a new template that primarily matches
* A, but also matches B.
+ *
+ * @hide
*/
+ // TODO: @SystemApi when ready.
public static NetworkTemplate normalize(NetworkTemplate template, List<String[]> mergedList) {
// Now there are several types of network which uses SubscriberId to store network
// information. For instances:
@@ -830,4 +1004,184 @@ public class NetworkTemplate implements Parcelable {
return new NetworkTemplate[size];
}
};
+
+ /**
+ * Builder class for NetworkTemplate.
+ */
+ public static final class Builder {
+ private final int mMatchRule;
+ // Use a SortedSet to provide a deterministic order when fetching the first one.
+ @NonNull
+ private final SortedSet<String> mMatchSubscriberIds = new TreeSet<>();
+ @Nullable
+ private String mWifiNetworkKey;
+
+ // Matches for the NetworkStats constants METERED_*, ROAMING_* and DEFAULT_NETWORK_*.
+ private int mMetered;
+ private int mRoaming;
+ private int mDefaultNetwork;
+ private int mRatType;
+
+ // Bitfield containing OEM network properties {@code NetworkIdentity#OEM_*}.
+ private int mOemManaged;
+
+ /**
+ * Creates a new Builder with given match rule to construct NetworkTemplate objects.
+ *
+ * @param matchRule the match rule of the template, see {@code MATCH_*}.
+ */
+ public Builder(@TemplateMatchRule final int matchRule) {
+ assertRequestableMatchRule(matchRule);
+ // Initialize members with default values.
+ mMatchRule = matchRule;
+ mWifiNetworkKey = WIFI_NETWORK_KEY_ALL;
+ mMetered = METERED_ALL;
+ mRoaming = ROAMING_ALL;
+ mDefaultNetwork = DEFAULT_NETWORK_ALL;
+ mRatType = NETWORK_TYPE_ALL;
+ mOemManaged = OEM_MANAGED_ALL;
+ }
+
+ /**
+ * Set the Subscriber Ids. Calling this function with an empty set represents
+ * the intention of matching any Subscriber Ids.
+ *
+ * @param subscriberIds the list of Subscriber Ids.
+ * @return this builder.
+ */
+ @NonNull
+ public Builder setSubscriberIds(@NonNull Set<String> subscriberIds) {
+ Objects.requireNonNull(subscriberIds);
+ mMatchSubscriberIds.clear();
+ mMatchSubscriberIds.addAll(subscriberIds);
+ return this;
+ }
+
+ /**
+ * Set the Wifi Network Key.
+ *
+ * @param wifiNetworkKey the Wifi Network Key, see {@link WifiInfo#getCurrentNetworkKey()}.
+ * Or null to match all networks.
+ * @return this builder.
+ */
+ @NonNull
+ public Builder setWifiNetworkKey(@Nullable String wifiNetworkKey) {
+ mWifiNetworkKey = wifiNetworkKey;
+ return this;
+ }
+
+ /**
+ * Set the meteredness filter.
+ *
+ * @param metered the meteredness filter.
+ * @return this builder.
+ */
+ @NonNull
+ public Builder setMeteredness(@NetworkStats.Meteredness int metered) {
+ mMetered = metered;
+ return this;
+ }
+
+ /**
+ * Set the roaming filter.
+ *
+ * @param roaming the roaming filter.
+ * @return this builder.
+ */
+ @NonNull
+ public Builder setRoaming(@NetworkStats.Roaming int roaming) {
+ mRoaming = roaming;
+ return this;
+ }
+
+ /**
+ * Set the default network status filter.
+ *
+ * @param defaultNetwork the default network status filter.
+ * @return this builder.
+ */
+ @NonNull
+ public Builder setDefaultNetworkStatus(@NetworkStats.DefaultNetwork int defaultNetwork) {
+ mDefaultNetwork = defaultNetwork;
+ return this;
+ }
+
+ /**
+ * Set the Radio Access Technology(RAT) type filter.
+ *
+ * @param ratType the Radio Access Technology(RAT) type filter. Use
+ * {@link #NETWORK_TYPE_ALL} to include all network types when filtering.
+ * See {@code TelephonyManager.NETWORK_TYPE_*}.
+ * @return this builder.
+ */
+ @NonNull
+ public Builder setRatType(@NetworkType int ratType) {
+ // Input will be validated with the match rule when building the template.
+ mRatType = ratType;
+ return this;
+ }
+
+ /**
+ * Set the OEM managed filter.
+ *
+ * @param oemManaged the match rule to match different type of OEM managed network or
+ * unmanaged networks. See {@code OEM_MANAGED_*}.
+ * @return this builder.
+ */
+ @NonNull
+ public Builder setOemManaged(@OemManaged int oemManaged) {
+ mOemManaged = oemManaged;
+ return this;
+ }
+
+ /**
+ * Check whether the match rule is requestable.
+ *
+ * @param matchRule the target match rule to be checked.
+ */
+ private static void assertRequestableMatchRule(final int matchRule) {
+ if (!isKnownMatchRule(matchRule)
+ || matchRule == MATCH_PROXY
+ || matchRule == MATCH_MOBILE_WILDCARD
+ || matchRule == MATCH_WIFI_WILDCARD) {
+ throw new IllegalArgumentException("Invalid match rule: "
+ + getMatchRuleName(matchRule));
+ }
+ }
+
+ private void assertRequestableParameters() {
+ // TODO: Check all the input are legitimate.
+ }
+
+ /**
+ * For backward compatibility, deduce match rule to a wildcard match rule
+ * if the Subscriber Ids are empty.
+ */
+ private int getWildcardDeducedMatchRule() {
+ if (mMatchRule == MATCH_MOBILE && mMatchSubscriberIds.isEmpty()) {
+ return MATCH_MOBILE_WILDCARD;
+ } else if (mMatchRule == MATCH_WIFI && mMatchSubscriberIds.isEmpty()
+ && mWifiNetworkKey == WIFI_NETWORK_KEY_ALL) {
+ return MATCH_WIFI_WILDCARD;
+ }
+ return mMatchRule;
+ }
+
+ /**
+ * Builds the instance of the NetworkTemplate.
+ *
+ * @return the built instance of NetworkTemplate.
+ */
+ @NonNull
+ public NetworkTemplate build() {
+ assertRequestableParameters();
+ final int subscriberIdMatchRule = mMatchSubscriberIds.isEmpty()
+ ? SUBSCRIBER_ID_MATCH_RULE_ALL : SUBSCRIBER_ID_MATCH_RULE_EXACT;
+ return new NetworkTemplate(getWildcardDeducedMatchRule(),
+ mMatchSubscriberIds.isEmpty() ? null : mMatchSubscriberIds.iterator().next(),
+ mMatchSubscriberIds.toArray(new String[0]),
+ mWifiNetworkKey, mMetered, mRoaming, mDefaultNetwork, mRatType, mOemManaged,
+ subscriberIdMatchRule);
+ }
+ }
}
diff --git a/packages/ConnectivityT/service/Android.bp b/packages/ConnectivityT/service/Android.bp
index 7b8817692b74..97dfb64b33dd 100644
--- a/packages/ConnectivityT/service/Android.bp
+++ b/packages/ConnectivityT/service/Android.bp
@@ -61,11 +61,25 @@ filegroup {
],
}
+// Ethernet related libraries.
+
+filegroup {
+ name: "services.connectivity-ethernet-sources",
+ srcs: [
+ "src/com/android/server/net/IpConfigStore.java",
+ ],
+ path: "src",
+ visibility: [
+ "//frameworks/opt/net/ethernet",
+ ],
+}
+
// Connectivity-T common libraries.
filegroup {
name: "services.connectivity-tiramisu-sources",
srcs: [
+ ":services.connectivity-ethernet-sources",
":services.connectivity-ipsec-sources",
":services.connectivity-netstats-sources",
":services.connectivity-nsd-sources",
diff --git a/packages/ConnectivityT/service/src/com/android/server/IpSecService.java b/packages/ConnectivityT/service/src/com/android/server/IpSecService.java
index f251b86b7a09..d1e432e80f51 100644
--- a/packages/ConnectivityT/service/src/com/android/server/IpSecService.java
+++ b/packages/ConnectivityT/service/src/com/android/server/IpSecService.java
@@ -45,7 +45,6 @@ import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.TrafficStats;
-import android.net.util.NetdService;
import android.os.Binder;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
@@ -96,8 +95,6 @@ import java.util.Objects;
public class IpSecService extends IIpSecService.Stub {
private static final String TAG = "IpSecService";
private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
-
- private static final String NETD_SERVICE_NAME = "netd";
private static final int[] ADDRESS_FAMILIES =
new int[] {OsConstants.AF_INET, OsConstants.AF_INET6};
@@ -106,6 +103,8 @@ public class IpSecService extends IIpSecService.Stub {
@VisibleForTesting static final int MAX_PORT_BIND_ATTEMPTS = 10;
+ private final INetd mNetd;
+
static {
try {
INADDR_ANY = InetAddress.getByAddress(new byte[] {0, 0, 0, 0});
@@ -627,16 +626,14 @@ public class IpSecService extends IIpSecService.Stub {
public void freeUnderlyingResources() {
int spi = mSpi.getSpi();
try {
- mDeps
- .getNetdInstance(mContext)
- .ipSecDeleteSecurityAssociation(
- mUid,
- mConfig.getSourceAddress(),
- mConfig.getDestinationAddress(),
- spi,
- mConfig.getMarkValue(),
- mConfig.getMarkMask(),
- mConfig.getXfrmInterfaceId());
+ mNetd.ipSecDeleteSecurityAssociation(
+ mUid,
+ mConfig.getSourceAddress(),
+ mConfig.getDestinationAddress(),
+ spi,
+ mConfig.getMarkValue(),
+ mConfig.getMarkMask(),
+ mConfig.getXfrmInterfaceId());
} catch (RemoteException | ServiceSpecificException e) {
Log.e(TAG, "Failed to delete SA with ID: " + mResourceId, e);
}
@@ -680,14 +677,12 @@ public class IpSecService extends IIpSecService.Stub {
private final String mSourceAddress;
private final String mDestinationAddress;
private int mSpi;
- private final Context mContext;
private boolean mOwnedByTransform = false;
- SpiRecord(Context context, int resourceId, String sourceAddress,
+ SpiRecord(int resourceId, String sourceAddress,
String destinationAddress, int spi) {
super(resourceId);
- mContext = context;
mSourceAddress = sourceAddress;
mDestinationAddress = destinationAddress;
mSpi = spi;
@@ -698,11 +693,9 @@ public class IpSecService extends IIpSecService.Stub {
public void freeUnderlyingResources() {
try {
if (!mOwnedByTransform) {
- mDeps
- .getNetdInstance(mContext)
- .ipSecDeleteSecurityAssociation(
- mUid, mSourceAddress, mDestinationAddress, mSpi, 0 /* mark */,
- 0 /* mask */, 0 /* if_id */);
+ mNetd.ipSecDeleteSecurityAssociation(
+ mUid, mSourceAddress, mDestinationAddress, mSpi, 0 /* mark */,
+ 0 /* mask */, 0 /* if_id */);
}
} catch (ServiceSpecificException | RemoteException e) {
Log.e(TAG, "Failed to delete SPI reservation with ID: " + mResourceId, e);
@@ -821,10 +814,8 @@ public class IpSecService extends IIpSecService.Stub {
private final int mIfId;
private Network mUnderlyingNetwork;
- private final Context mContext;
TunnelInterfaceRecord(
- Context context,
int resourceId,
String interfaceName,
Network underlyingNetwork,
@@ -835,7 +826,6 @@ public class IpSecService extends IIpSecService.Stub {
int intfId) {
super(resourceId);
- mContext = context;
mInterfaceName = interfaceName;
mUnderlyingNetwork = underlyingNetwork;
mLocalAddress = localAddr;
@@ -852,18 +842,17 @@ public class IpSecService extends IIpSecService.Stub {
// Teardown VTI
// Delete global policies
try {
- final INetd netd = mDeps.getNetdInstance(mContext);
- netd.ipSecRemoveTunnelInterface(mInterfaceName);
+ mNetd.ipSecRemoveTunnelInterface(mInterfaceName);
for (int selAddrFamily : ADDRESS_FAMILIES) {
- netd.ipSecDeleteSecurityPolicy(
+ mNetd.ipSecDeleteSecurityPolicy(
mUid,
selAddrFamily,
IpSecManager.DIRECTION_OUT,
mOkey,
0xffffffff,
mIfId);
- netd.ipSecDeleteSecurityPolicy(
+ mNetd.ipSecDeleteSecurityPolicy(
mUid,
selAddrFamily,
IpSecManager.DIRECTION_IN,
@@ -1026,7 +1015,6 @@ public class IpSecService extends IIpSecService.Stub {
static IpSecService create(Context context)
throws InterruptedException {
final IpSecService service = new IpSecService(context);
- service.connectNativeNetdService();
return service;
}
@@ -1057,8 +1045,13 @@ public class IpSecService extends IIpSecService.Stub {
@VisibleForTesting
public IpSecService(Context context, Dependencies deps, UidFdTagger uidFdTagger) {
mContext = context;
- mDeps = deps;
+ mDeps = Objects.requireNonNull(deps, "Missing dependencies.");
mUidFdTagger = uidFdTagger;
+ try {
+ mNetd = mDeps.getNetdInstance(mContext);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
/** Called by system server when system is ready. */
@@ -1070,25 +1063,12 @@ public class IpSecService extends IIpSecService.Stub {
}
}
- private void connectNativeNetdService() {
- // Avoid blocking the system server to do this
- new Thread() {
- @Override
- public void run() {
- synchronized (IpSecService.this) {
- NetdService.get(NETD_FETCH_TIMEOUT_MS);
- }
- }
- }.start();
- }
-
synchronized boolean isNetdAlive() {
try {
- final INetd netd = mDeps.getNetdInstance(mContext);
- if (netd == null) {
+ if (mNetd == null) {
return false;
}
- return netd.isAlive();
+ return mNetd.isAlive();
} catch (RemoteException re) {
return false;
}
@@ -1149,15 +1129,12 @@ public class IpSecService extends IIpSecService.Stub {
IpSecManager.Status.RESOURCE_UNAVAILABLE, INVALID_RESOURCE_ID, spi);
}
- spi =
- mDeps
- .getNetdInstance(mContext)
- .ipSecAllocateSpi(callingUid, "", destinationAddress, requestedSpi);
+ spi = mNetd.ipSecAllocateSpi(callingUid, "", destinationAddress, requestedSpi);
Log.d(TAG, "Allocated SPI " + spi);
userRecord.mSpiRecords.put(
resourceId,
new RefcountedResource<SpiRecord>(
- new SpiRecord(mContext, resourceId, "",
+ new SpiRecord(resourceId, "",
destinationAddress, spi), binder));
} catch (ServiceSpecificException e) {
if (e.errorCode == OsConstants.ENOENT) {
@@ -1275,8 +1252,7 @@ public class IpSecService extends IIpSecService.Stub {
OsConstants.UDP_ENCAP,
OsConstants.UDP_ENCAP_ESPINUDP);
- mDeps.getNetdInstance(mContext).ipSecSetEncapSocketOwner(
- new ParcelFileDescriptor(sockFd), callingUid);
+ mNetd.ipSecSetEncapSocketOwner(new ParcelFileDescriptor(sockFd), callingUid);
if (port != 0) {
Log.v(TAG, "Binding to port " + port);
Os.bind(sockFd, INADDR_ANY, port);
@@ -1338,16 +1314,15 @@ public class IpSecService extends IIpSecService.Stub {
// Create VTI
// Add inbound/outbound global policies
// (use reqid = 0)
- final INetd netd = mDeps.getNetdInstance(mContext);
- netd.ipSecAddTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey, resourceId);
+ mNetd.ipSecAddTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey, resourceId);
BinderUtils.withCleanCallingIdentity(() -> {
- NetdUtils.setInterfaceUp(netd, intfName);
+ NetdUtils.setInterfaceUp(mNetd, intfName);
});
for (int selAddrFamily : ADDRESS_FAMILIES) {
// Always send down correct local/remote addresses for template.
- netd.ipSecAddSecurityPolicy(
+ mNetd.ipSecAddSecurityPolicy(
callerUid,
selAddrFamily,
IpSecManager.DIRECTION_OUT,
@@ -1357,7 +1332,7 @@ public class IpSecService extends IIpSecService.Stub {
okey,
0xffffffff,
resourceId);
- netd.ipSecAddSecurityPolicy(
+ mNetd.ipSecAddSecurityPolicy(
callerUid,
selAddrFamily,
IpSecManager.DIRECTION_IN,
@@ -1377,7 +1352,7 @@ public class IpSecService extends IIpSecService.Stub {
//
// This is necessary only on the tunnel interface, and not any the interface to
// which traffic will be forwarded to.
- netd.ipSecAddSecurityPolicy(
+ mNetd.ipSecAddSecurityPolicy(
callerUid,
selAddrFamily,
IpSecManager.DIRECTION_FWD,
@@ -1393,7 +1368,6 @@ public class IpSecService extends IIpSecService.Stub {
resourceId,
new RefcountedResource<TunnelInterfaceRecord>(
new TunnelInterfaceRecord(
- mContext,
resourceId,
intfName,
underlyingNetwork,
@@ -1435,12 +1409,10 @@ public class IpSecService extends IIpSecService.Stub {
try {
// We can assume general validity of the IP address, since we get them as a
// LinkAddress, which does some validation.
- mDeps
- .getNetdInstance(mContext)
- .interfaceAddAddress(
- tunnelInterfaceInfo.mInterfaceName,
- localAddr.getAddress().getHostAddress(),
- localAddr.getPrefixLength());
+ mNetd.interfaceAddAddress(
+ tunnelInterfaceInfo.mInterfaceName,
+ localAddr.getAddress().getHostAddress(),
+ localAddr.getPrefixLength());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1464,9 +1436,7 @@ public class IpSecService extends IIpSecService.Stub {
try {
// We can assume general validity of the IP address, since we get them as a
// LinkAddress, which does some validation.
- mDeps
- .getNetdInstance(mContext)
- .interfaceDelAddress(
+ mNetd.interfaceDelAddress(
tunnelInterfaceInfo.mInterfaceName,
localAddr.getAddress().getHostAddress(),
localAddr.getPrefixLength());
@@ -1679,30 +1649,28 @@ public class IpSecService extends IIpSecService.Stub {
cryptName = crypt.getName();
}
- mDeps
- .getNetdInstance(mContext)
- .ipSecAddSecurityAssociation(
- Binder.getCallingUid(),
- c.getMode(),
- c.getSourceAddress(),
- c.getDestinationAddress(),
- (c.getNetwork() != null) ? c.getNetwork().getNetId() : 0,
- spiRecord.getSpi(),
- c.getMarkValue(),
- c.getMarkMask(),
- (auth != null) ? auth.getName() : "",
- (auth != null) ? auth.getKey() : new byte[] {},
- (auth != null) ? auth.getTruncationLengthBits() : 0,
- cryptName,
- (crypt != null) ? crypt.getKey() : new byte[] {},
- (crypt != null) ? crypt.getTruncationLengthBits() : 0,
- (authCrypt != null) ? authCrypt.getName() : "",
- (authCrypt != null) ? authCrypt.getKey() : new byte[] {},
- (authCrypt != null) ? authCrypt.getTruncationLengthBits() : 0,
- encapType,
- encapLocalPort,
- encapRemotePort,
- c.getXfrmInterfaceId());
+ mNetd.ipSecAddSecurityAssociation(
+ Binder.getCallingUid(),
+ c.getMode(),
+ c.getSourceAddress(),
+ c.getDestinationAddress(),
+ (c.getNetwork() != null) ? c.getNetwork().getNetId() : 0,
+ spiRecord.getSpi(),
+ c.getMarkValue(),
+ c.getMarkMask(),
+ (auth != null) ? auth.getName() : "",
+ (auth != null) ? auth.getKey() : new byte[] {},
+ (auth != null) ? auth.getTruncationLengthBits() : 0,
+ cryptName,
+ (crypt != null) ? crypt.getKey() : new byte[] {},
+ (crypt != null) ? crypt.getTruncationLengthBits() : 0,
+ (authCrypt != null) ? authCrypt.getName() : "",
+ (authCrypt != null) ? authCrypt.getKey() : new byte[] {},
+ (authCrypt != null) ? authCrypt.getTruncationLengthBits() : 0,
+ encapType,
+ encapLocalPort,
+ encapRemotePort,
+ c.getXfrmInterfaceId());
}
/**
@@ -1791,15 +1759,13 @@ public class IpSecService extends IIpSecService.Stub {
c.getMode() == IpSecTransform.MODE_TRANSPORT,
"Transform mode was not Transport mode; cannot be applied to a socket");
- mDeps
- .getNetdInstance(mContext)
- .ipSecApplyTransportModeTransform(
- socket,
- callingUid,
- direction,
- c.getSourceAddress(),
- c.getDestinationAddress(),
- info.getSpiRecord().getSpi());
+ mNetd.ipSecApplyTransportModeTransform(
+ socket,
+ callingUid,
+ direction,
+ c.getSourceAddress(),
+ c.getDestinationAddress(),
+ info.getSpiRecord().getSpi());
}
/**
@@ -1811,9 +1777,7 @@ public class IpSecService extends IIpSecService.Stub {
@Override
public synchronized void removeTransportModeTransforms(ParcelFileDescriptor socket)
throws RemoteException {
- mDeps
- .getNetdInstance(mContext)
- .ipSecRemoveTransportModeTransform(socket);
+ mNetd.ipSecRemoveTransportModeTransform(socket);
}
/**
@@ -1888,18 +1852,16 @@ public class IpSecService extends IIpSecService.Stub {
// Always update the policy with the relevant XFRM_IF_ID
for (int selAddrFamily : ADDRESS_FAMILIES) {
- mDeps
- .getNetdInstance(mContext)
- .ipSecUpdateSecurityPolicy(
- callingUid,
- selAddrFamily,
- direction,
- transformInfo.getConfig().getSourceAddress(),
- transformInfo.getConfig().getDestinationAddress(),
- spi, // If outbound, also add SPI to the policy.
- mark, // Must always set policy mark; ikey/okey for VTIs
- 0xffffffff,
- c.getXfrmInterfaceId());
+ mNetd.ipSecUpdateSecurityPolicy(
+ callingUid,
+ selAddrFamily,
+ direction,
+ transformInfo.getConfig().getSourceAddress(),
+ transformInfo.getConfig().getDestinationAddress(),
+ spi, // If outbound, also add SPI to the policy.
+ mark, // Must always set policy mark; ikey/okey for VTIs
+ 0xffffffff,
+ c.getXfrmInterfaceId());
}
// Update SA with tunnel mark (ikey or okey based on direction)
diff --git a/services/core/java/com/android/server/net/IpConfigStore.java b/packages/ConnectivityT/service/src/com/android/server/net/IpConfigStore.java
index d17dbde496ce..3a9a54415537 100644
--- a/services/core/java/com/android/server/net/IpConfigStore.java
+++ b/packages/ConnectivityT/service/src/com/android/server/net/IpConfigStore.java
@@ -44,6 +44,9 @@ import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
+/**
+ * This class provides an API to store and manage L3 network IP configuration.
+ */
public class IpConfigStore {
private static final String TAG = "IpConfigStore";
private static final boolean DBG = false;
@@ -78,6 +81,9 @@ public class IpConfigStore {
return writeConfig(out, configKey, config, IPCONFIG_FILE_VERSION);
}
+ /**
+ * Write the IP configuration with the given parameters to {@link DataOutputStream}.
+ */
@VisibleForTesting
public static boolean writeConfig(DataOutputStream out, String configKey,
IpConfiguration config, int version) throws IOException {
@@ -154,10 +160,10 @@ public class IpConfigStore {
break;
case UNASSIGNED:
/* Ignore */
- break;
- default:
- loge("Ignore invalid proxy settings while writing");
- break;
+ break;
+ default:
+ loge("Ignore invalid proxy settings while writing");
+ break;
}
if (written) {
@@ -177,7 +183,7 @@ public class IpConfigStore {
}
/**
- * @Deprecated use {@link #writeIpConfigurations(String, ArrayMap)} instead.
+ * @deprecated use {@link #writeIpConfigurations(String, ArrayMap)} instead.
* New method uses string as network identifier which could be interface name or MAC address or
* other token.
*/
@@ -186,22 +192,28 @@ public class IpConfigStore {
final SparseArray<IpConfiguration> networks) {
mWriter.write(filePath, out -> {
out.writeInt(IPCONFIG_FILE_VERSION);
- for(int i = 0; i < networks.size(); i++) {
+ for (int i = 0; i < networks.size(); i++) {
writeConfig(out, String.valueOf(networks.keyAt(i)), networks.valueAt(i));
}
});
}
+ /**
+ * Write the IP configuration associated to the target networks to the destination path.
+ */
public void writeIpConfigurations(String filePath,
ArrayMap<String, IpConfiguration> networks) {
mWriter.write(filePath, out -> {
out.writeInt(IPCONFIG_FILE_VERSION);
- for(int i = 0; i < networks.size(); i++) {
+ for (int i = 0; i < networks.size(); i++) {
writeConfig(out, networks.keyAt(i), networks.valueAt(i));
}
});
}
+ /**
+ * Read the IP configuration from the destination path to {@link BufferedInputStream}.
+ */
public static ArrayMap<String, IpConfiguration> readIpConfigurations(String filePath) {
BufferedInputStream bufferedInputStream;
try {
@@ -215,7 +227,7 @@ public class IpConfigStore {
return readIpConfigurations(bufferedInputStream);
}
- /** @Deprecated use {@link #readIpConfigurations(String)} */
+ /** @deprecated use {@link #readIpConfigurations(String)} */
@Deprecated
public static SparseArray<IpConfiguration> readIpAndProxyConfigurations(String filePath) {
BufferedInputStream bufferedInputStream;
@@ -230,7 +242,7 @@ public class IpConfigStore {
return readIpAndProxyConfigurations(bufferedInputStream);
}
- /** @Deprecated use {@link #readIpConfigurations(InputStream)} */
+ /** @deprecated use {@link #readIpConfigurations(InputStream)} */
@Deprecated
public static SparseArray<IpConfiguration> readIpAndProxyConfigurations(
InputStream inputStream) {
@@ -420,7 +432,7 @@ public class IpConfigStore {
if (in != null) {
try {
in.close();
- } catch (Exception e) {}
+ } catch (Exception e) { }
}
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 268603fa8b0d..200e902c6420 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -1348,7 +1348,6 @@ class DatabaseHelper extends SQLiteOpenHelper {
Settings.Global.CONNECTIVITY_CHANGE_DELAY,
Settings.Global.CAPTIVE_PORTAL_DETECTION_ENABLED,
Settings.Global.CAPTIVE_PORTAL_SERVER,
- Settings.Global.NSD_ON,
Settings.Global.SET_INSTALL_LOCATION,
Settings.Global.DEFAULT_INSTALL_LOCATION,
Settings.Global.INET_CONDITION_DEBOUNCE_UP_DELAY,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index f145f508da2e..63c874a08621 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1115,10 +1115,6 @@ class SettingsProtoDumpUtil {
p.end(notificationToken);
dumpSetting(s, p,
- Settings.Global.NSD_ON,
- GlobalSettingsProto.NSD_ON);
-
- dumpSetting(s, p,
Settings.Global.NR_NSA_TRACKING_SCREEN_OFF_MODE,
GlobalSettingsProto.NR_NSA_TRACKING_SCREEN_OFF_MODE);
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 883c4a1cd936..10dafd93c18e 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -394,7 +394,6 @@ public class SettingsBackupTest {
Settings.Global.NOTIFICATION_SNOOZE_OPTIONS,
Settings.Global.NOTIFICATION_FEEDBACK_ENABLED,
Settings.Global.NR_NSA_TRACKING_SCREEN_OFF_MODE,
- Settings.Global.NSD_ON,
Settings.Global.NTP_SERVER,
Settings.Global.NTP_TIMEOUT,
Settings.Global.OTA_DISABLE_AUTOMATIC_UPDATE,
diff --git a/packages/SystemUI/res/layout/internet_connectivity_dialog.xml b/packages/SystemUI/res/layout/internet_connectivity_dialog.xml
index 918635d666fa..c88e95f07f12 100644
--- a/packages/SystemUI/res/layout/internet_connectivity_dialog.xml
+++ b/packages/SystemUI/res/layout/internet_connectivity_dialog.xml
@@ -323,6 +323,46 @@
</FrameLayout>
</LinearLayout>
+ <LinearLayout
+ android:id="@+id/wifi_scan_notify_layout"
+ style="@style/InternetDialog.Network"
+ android:orientation="vertical"
+ android:layout_height="wrap_content"
+ android:paddingBottom="4dp"
+ android:clickable="false"
+ android:focusable="false">
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:minWidth="56dp"
+ android:gravity="start|top"
+ android:orientation="horizontal"
+ android:paddingEnd="12dp"
+ android:paddingTop="16dp"
+ android:paddingBottom="4dp">
+ <ImageView
+ android:src="@drawable/ic_info_outline"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:tint="?android:attr/textColorTertiary"/>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+ <TextView
+ android:id="@+id/wifi_scan_notify_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingTop="16dp"
+ android:paddingBottom="8dp"
+ android:textColor="?android:attr/textColorSecondary"
+ android:clickable="true"/>
+ </LinearLayout>
+ </LinearLayout>
+
<FrameLayout
android:id="@+id/done_layout"
android:layout_width="67dp"
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 7aacb702b75a..4ad4fa9d0854 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -3033,4 +3033,6 @@
<string name="see_all_networks">See all</string>
<!-- Summary for warning to disconnect ethernet first then switch to other networks. [CHAR LIMIT=60] -->
<string name="to_switch_networks_disconnect_ethernet">To switch networks, disconnect ethernet</string>
+ <!-- Message to describe "Wi-Fi scan always available feature" when Wi-Fi is off and Wi-Fi scanning is on. [CHAR LIMIT=NONE] -->
+ <string name="wifi_scan_notify_message">To improve device experience, apps and services can still scan for Wi\u2011Fi networks at any time, even when Wi\u2011Fi is off. You can change this in Wi\u2011Fi scanning settings. <annotation id="link">Change</annotation></string>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AnnotationLinkSpan.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AnnotationLinkSpan.java
index d8e80fe99331..0d7551ff66e9 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AnnotationLinkSpan.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AnnotationLinkSpan.java
@@ -30,7 +30,7 @@ import java.util.Optional;
/**
* A span that turns the text wrapped by annotation tag into the clickable link text.
*/
-class AnnotationLinkSpan extends ClickableSpan {
+public class AnnotationLinkSpan extends ClickableSpan {
private final Optional<View.OnClickListener> mClickListener;
private AnnotationLinkSpan(View.OnClickListener listener) {
@@ -50,7 +50,7 @@ class AnnotationLinkSpan extends ClickableSpan {
* @param linkInfos used to attach the click action into the corresponding span
* @return the text attached with the span
*/
- static CharSequence linkify(CharSequence text, LinkInfo... linkInfos) {
+ public static CharSequence linkify(CharSequence text, LinkInfo... linkInfos) {
final SpannableString msg = new SpannableString(text);
final Annotation[] spans =
msg.getSpans(/* queryStart= */ 0, msg.length(), Annotation.class);
@@ -78,12 +78,12 @@ class AnnotationLinkSpan extends ClickableSpan {
/**
* Data class to store the annotation and the click action.
*/
- static class LinkInfo {
- static final String DEFAULT_ANNOTATION = "link";
+ public static class LinkInfo {
+ public static final String DEFAULT_ANNOTATION = "link";
private final Optional<String> mAnnotation;
private final Optional<View.OnClickListener> mListener;
- LinkInfo(@NonNull String annotation, View.OnClickListener listener) {
+ public LinkInfo(@NonNull String annotation, View.OnClickListener listener) {
mAnnotation = Optional.of(annotation);
mListener = Optional.ofNullable(listener);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
index dc54e1b52f2e..dae357e9e36b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
@@ -36,6 +36,7 @@ import android.telephony.TelephonyDisplayInfo;
import android.telephony.TelephonyManager;
import android.text.Html;
import android.text.TextUtils;
+import android.text.method.LinkMovementMethod;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
@@ -63,6 +64,7 @@ import com.android.internal.logging.UiEvent;
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.Prefs;
import com.android.systemui.R;
+import com.android.systemui.accessibility.floatingmenu.AnnotationLinkSpan;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.phone.SystemUIDialog;
@@ -110,6 +112,8 @@ public class InternetDialog extends SystemUIDialog implements
private LinearLayout mTurnWifiOnLayout;
private LinearLayout mEthernetLayout;
private TextView mWifiToggleTitleText;
+ private LinearLayout mWifiScanNotifyLayout;
+ private TextView mWifiScanNotifyText;
private LinearLayout mSeeAllLayout;
private RecyclerView mWifiRecyclerView;
private ImageView mConnectedWifiIcon;
@@ -220,6 +224,8 @@ public class InternetDialog extends SystemUIDialog implements
mMobileNetworkLayout = mDialogView.requireViewById(R.id.mobile_network_layout);
mTurnWifiOnLayout = mDialogView.requireViewById(R.id.turn_on_wifi_layout);
mWifiToggleTitleText = mDialogView.requireViewById(R.id.wifi_toggle_title);
+ mWifiScanNotifyLayout = mDialogView.requireViewById(R.id.wifi_scan_notify_layout);
+ mWifiScanNotifyText = mDialogView.requireViewById(R.id.wifi_scan_notify_text);
mConnectedWifListLayout = mDialogView.requireViewById(R.id.wifi_connected_layout);
mConnectedWifiIcon = mDialogView.requireViewById(R.id.wifi_connected_icon);
mConnectedWifiTitleText = mDialogView.requireViewById(R.id.wifi_connected_title);
@@ -313,8 +319,10 @@ public class InternetDialog extends SystemUIDialog implements
showProgressBar();
final boolean isDeviceLocked = mInternetDialogController.isDeviceLocked();
final boolean isWifiEnabled = mWifiManager.isWifiEnabled();
+ final boolean isWifiScanEnabled = mWifiManager.isScanAlwaysAvailable();
updateWifiToggle(isWifiEnabled, isDeviceLocked);
updateConnectedWifi(isWifiEnabled, isDeviceLocked);
+ updateWifiScanNotify(isWifiEnabled, isWifiScanEnabled, isDeviceLocked);
final int visibility = (isDeviceLocked || !isWifiEnabled || mWifiEntriesCount <= 0)
? View.GONE : View.VISIBLE;
@@ -411,6 +419,24 @@ public class InternetDialog extends SystemUIDialog implements
mContext.getColor(R.color.connected_network_primary_color));
}
+ @MainThread
+ private void updateWifiScanNotify(boolean isWifiEnabled, boolean isWifiScanEnabled,
+ boolean isDeviceLocked) {
+ if (isWifiEnabled || !isWifiScanEnabled || isDeviceLocked) {
+ mWifiScanNotifyLayout.setVisibility(View.GONE);
+ return;
+ }
+ if (TextUtils.isEmpty(mWifiScanNotifyText.getText())) {
+ final AnnotationLinkSpan.LinkInfo linkInfo = new AnnotationLinkSpan.LinkInfo(
+ AnnotationLinkSpan.LinkInfo.DEFAULT_ANNOTATION,
+ v -> mInternetDialogController.launchWifiScanningSetting());
+ mWifiScanNotifyText.setText(AnnotationLinkSpan.linkify(
+ getContext().getText(R.string.wifi_scan_notify_message), linkInfo));
+ mWifiScanNotifyText.setMovementMethod(LinkMovementMethod.getInstance());
+ }
+ mWifiScanNotifyLayout.setVisibility(View.VISIBLE);
+ }
+
void onClickConnectedWifi() {
if (mConnectedWifiEntry == null) {
return;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
index aaba5efc92f6..276c0be53063 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
@@ -103,6 +103,8 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback,
private static final String TAG = "InternetDialogController";
private static final String ACTION_NETWORK_PROVIDER_SETTINGS =
"android.settings.NETWORK_PROVIDER_SETTINGS";
+ private static final String ACTION_WIFI_SCANNING_SETTINGS =
+ "android.settings.WIFI_SCANNING_SETTINGS";
private static final String EXTRA_CHOSEN_WIFI_ENTRY_KEY = "key_chosen_wifientry_key";
public static final Drawable EMPTY_DRAWABLE = new ColorDrawable(Color.TRANSPARENT);
public static final int NO_CELL_DATA_TYPE_ICON = 0;
@@ -603,6 +605,13 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback,
}
}
+ void launchWifiScanningSetting() {
+ mCallback.dismissDialog();
+ final Intent intent = new Intent(ACTION_WIFI_SCANNING_SETTINGS);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mActivityStarter.postStartActivityDismissingKeyguard(intent, 0);
+ }
+
void connectCarrierNetwork() {
final MergedCarrierEntry mergedCarrierEntry =
mAccessPointController.getMergedCarrierEntry();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
index c42b64a09985..7cea430e146f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
@@ -19,6 +19,7 @@ import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.View;
import android.widget.LinearLayout;
+import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import androidx.test.filters.SmallTest;
@@ -73,6 +74,7 @@ public class InternetDialogTest extends SysuiTestCase {
private LinearLayout mConnectedWifi;
private RecyclerView mWifiList;
private LinearLayout mSeeAll;
+ private LinearLayout mWifiScanNotify;
@Before
public void setUp() {
@@ -104,6 +106,7 @@ public class InternetDialogTest extends SysuiTestCase {
mConnectedWifi = mDialogView.requireViewById(R.id.wifi_connected_layout);
mWifiList = mDialogView.requireViewById(R.id.wifi_list_layout);
mSeeAll = mDialogView.requireViewById(R.id.see_all_layout);
+ mWifiScanNotify = mDialogView.requireViewById(R.id.wifi_scan_notify_layout);
}
@After
@@ -264,6 +267,50 @@ public class InternetDialogTest extends SysuiTestCase {
}
@Test
+ public void updateDialog_wifiOn_hideWifiScanNotify() {
+ // The preconditions WiFi ON and Internet WiFi are already in setUp()
+
+ mInternetDialog.updateDialog();
+
+ assertThat(mWifiScanNotify.getVisibility()).isEqualTo(View.GONE);
+ }
+
+ @Test
+ public void updateDialog_wifiOffAndWifiScanOff_hideWifiScanNotify() {
+ when(mWifiManager.isWifiEnabled()).thenReturn(false);
+ when(mWifiManager.isScanAlwaysAvailable()).thenReturn(false);
+
+ mInternetDialog.updateDialog();
+
+ assertThat(mWifiScanNotify.getVisibility()).isEqualTo(View.GONE);
+ }
+
+ @Test
+ public void updateDialog_wifiOffAndWifiScanOnAndDeviceLocked_hideWifiScanNotify() {
+ when(mWifiManager.isWifiEnabled()).thenReturn(false);
+ when(mWifiManager.isScanAlwaysAvailable()).thenReturn(true);
+ when(mInternetDialogController.isDeviceLocked()).thenReturn(true);
+
+ mInternetDialog.updateDialog();
+
+ assertThat(mWifiScanNotify.getVisibility()).isEqualTo(View.GONE);
+ }
+
+ @Test
+ public void updateDialog_wifiOffAndWifiScanOnAndDeviceUnlocked_showWifiScanNotify() {
+ when(mWifiManager.isWifiEnabled()).thenReturn(false);
+ when(mWifiManager.isScanAlwaysAvailable()).thenReturn(true);
+ when(mInternetDialogController.isDeviceLocked()).thenReturn(false);
+
+ mInternetDialog.updateDialog();
+
+ assertThat(mWifiScanNotify.getVisibility()).isEqualTo(View.VISIBLE);
+ TextView wifiScanNotifyText = mDialogView.requireViewById(R.id.wifi_scan_notify_text);
+ assertThat(wifiScanNotifyText.getText().length()).isNotEqualTo(0);
+ assertThat(wifiScanNotifyText.getMovementMethod()).isNotNull();
+ }
+
+ @Test
public void onClickSeeMoreButton_clickSeeAll_verifyLaunchNetworkSetting() {
mSeeAll.performClick();
diff --git a/services/OWNERS b/services/OWNERS
index b3bf5dcd2292..9b5f0e701fdf 100644
--- a/services/OWNERS
+++ b/services/OWNERS
@@ -5,3 +5,5 @@ per-file art-profile* = calin@google.com, ngeoffray@google.com, vmarko@google.co
per-file java/com/android/server/* = patb@google.com
per-file tests/servicestests/src/com/android/server/systemconfig/* = patb@google.com
+
+per-file proguard.flags = jdduke@google.com
diff --git a/services/cloudsearch/OWNERS b/services/cloudsearch/OWNERS
new file mode 100644
index 000000000000..aa4da3b4bee0
--- /dev/null
+++ b/services/cloudsearch/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 758286
+
+huiwu@google.com
+srazdan@google.com
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index d7c1cfb7d1ed..811f2f5e5283 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -91,6 +91,7 @@ import android.util.Pair;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IBatteryStats;
+import com.android.internal.telephony.ICarrierPrivilegesListener;
import com.android.internal.telephony.IOnSubscriptionsChangedListener;
import com.android.internal.telephony.IPhoneStateListener;
import com.android.internal.telephony.ITelephonyRegistry;
@@ -106,6 +107,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -149,6 +151,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
IPhoneStateListener callback;
IOnSubscriptionsChangedListener onSubscriptionsChangedListenerCallback;
IOnSubscriptionsChangedListener onOpportunisticSubscriptionsChangedListenerCallback;
+ ICarrierPrivilegesListener carrierPrivilegesListener;
int callerUid;
int callerPid;
@@ -173,6 +176,10 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
return (onOpportunisticSubscriptionsChangedListenerCallback != null);
}
+ boolean matchCarrierPrivilegesListener() {
+ return carrierPrivilegesListener != null;
+ }
+
boolean canReadCallLog() {
try {
return TelephonyPermissions.checkReadCallLog(
@@ -189,8 +196,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
+ " onSubscriptionsChangedListenererCallback="
+ onSubscriptionsChangedListenerCallback
+ " onOpportunisticSubscriptionsChangedListenererCallback="
- + onOpportunisticSubscriptionsChangedListenerCallback + " subId=" + subId
- + " phoneId=" + phoneId + " events=" + eventList + "}";
+ + onOpportunisticSubscriptionsChangedListenerCallback
+ + " carrierPrivilegesListener=" + carrierPrivilegesListener
+ + " subId=" + subId + " phoneId=" + phoneId + " events=" + eventList + "}";
}
}
@@ -402,6 +410,10 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
*/
private List<Map<Pair<Integer, ApnSetting>, PreciseDataConnectionState>>
mPreciseDataConnectionStates;
+
+ /** Per-phoneId snapshot of privileged packages (names + UIDs). */
+ private List<Pair<List<String>, int[]>> mCarrierPrivilegeStates;
+
/**
* Support backward compatibility for {@link android.telephony.TelephonyDisplayInfo}.
*/
@@ -689,6 +701,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
cutListToSize(mBarringInfo, mNumPhones);
cutListToSize(mPhysicalChannelConfigs, mNumPhones);
cutListToSize(mLinkCapacityEstimateLists, mNumPhones);
+ cutListToSize(mCarrierPrivilegeStates, mNumPhones);
return;
}
@@ -729,6 +742,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mAllowedNetworkTypeReason[i] = -1;
mAllowedNetworkTypeValue[i] = -1;
mLinkCapacityEstimateLists.add(i, INVALID_LCE_LIST);
+ mCarrierPrivilegeStates.add(i, new Pair<>(Collections.emptyList(), new int[0]));
}
}
@@ -794,6 +808,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mIsDataEnabled = new boolean[numPhones];
mDataEnabledReason = new int[numPhones];
mLinkCapacityEstimateLists = new ArrayList<>();
+ mCarrierPrivilegeStates = new ArrayList<>();
for (int i = 0; i < numPhones; i++) {
mCallState[i] = TelephonyManager.CALL_STATE_IDLE;
@@ -831,6 +846,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mAllowedNetworkTypeReason[i] = -1;
mAllowedNetworkTypeValue[i] = -1;
mLinkCapacityEstimateLists.add(i, INVALID_LCE_LIST);
+ mCarrierPrivilegeStates.add(i, new Pair<>(Collections.emptyList(), new int[0]));
}
mAppOps = mContext.getSystemService(AppOpsManager.class);
@@ -2766,6 +2782,104 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
@Override
+ public void addCarrierPrivilegesListener(
+ int phoneId,
+ ICarrierPrivilegesListener callback,
+ String callingPackage,
+ String callingFeatureId) {
+ int callerUserId = UserHandle.getCallingUserId();
+ mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+ "addCarrierPrivilegesListener");
+ if (VDBG) {
+ log(
+ "listen carrier privs: E pkg=" + pii(callingPackage) + " phoneId=" + phoneId
+ + " uid=" + Binder.getCallingUid()
+ + " myUserId=" + UserHandle.myUserId() + " callerUserId=" + callerUserId
+ + " callback=" + callback
+ + " callback.asBinder=" + callback.asBinder());
+ }
+ if (!validatePhoneId(phoneId)) {
+ throw new IllegalArgumentException("Invalid slot index: " + phoneId);
+ }
+
+ synchronized (mRecords) {
+ Record r = add(
+ callback.asBinder(), Binder.getCallingUid(), Binder.getCallingPid(), false);
+
+ if (r == null) return;
+
+ r.context = mContext;
+ r.carrierPrivilegesListener = callback;
+ r.callingPackage = callingPackage;
+ r.callingFeatureId = callingFeatureId;
+ r.callerUid = Binder.getCallingUid();
+ r.callerPid = Binder.getCallingPid();
+ r.phoneId = phoneId;
+ r.eventList = new ArraySet<>();
+ if (DBG) {
+ log("listen carrier privs: Register r=" + r);
+ }
+
+ Pair<List<String>, int[]> state = mCarrierPrivilegeStates.get(phoneId);
+ try {
+ r.carrierPrivilegesListener.onCarrierPrivilegesChanged(
+ Collections.unmodifiableList(state.first),
+ Arrays.copyOf(state.second, state.second.length));
+ } catch (RemoteException ex) {
+ remove(r.binder);
+ }
+ }
+ }
+
+ @Override
+ public void removeCarrierPrivilegesListener(
+ ICarrierPrivilegesListener callback, String callingPackage) {
+ mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+ "removeCarrierPrivilegesListener");
+ remove(callback.asBinder());
+ }
+
+ @Override
+ public void notifyCarrierPrivilegesChanged(
+ int phoneId, List<String> privilegedPackageNames, int[] privilegedUids) {
+ if (!checkNotifyPermission("notifyCarrierPrivilegesChanged")) {
+ return;
+ }
+ if (!validatePhoneId(phoneId)) return;
+ if (VDBG) {
+ log(
+ "notifyCarrierPrivilegesChanged: phoneId=" + phoneId
+ + ", <packages=" + pii(privilegedPackageNames)
+ + ", uids=" + Arrays.toString(privilegedUids) + ">");
+ }
+ synchronized (mRecords) {
+ mCarrierPrivilegeStates.set(
+ phoneId, new Pair<>(privilegedPackageNames, privilegedUids));
+ for (Record r : mRecords) {
+ // Listeners are per-slot, not per-subscription. This is to provide a stable
+ // view across SIM profile switches.
+ if (!r.matchCarrierPrivilegesListener()
+ || !idMatch(r, SubscriptionManager.INVALID_SUBSCRIPTION_ID, phoneId)) {
+ continue;
+ }
+ try {
+ // Make sure even in-process listeners can't modify the values.
+ r.carrierPrivilegesListener.onCarrierPrivilegesChanged(
+ Collections.unmodifiableList(privilegedPackageNames),
+ Arrays.copyOf(privilegedUids, privilegedUids.length));
+ } catch (RemoteException ex) {
+ mRemoveList.add(r.binder);
+ }
+ }
+ handleRemoveListLocked();
+ }
+ }
+
+ @Override
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
@@ -2814,6 +2928,11 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
pw.println("mAllowedNetworkTypeValue=" + mAllowedNetworkTypeValue[i]);
pw.println("mPhysicalChannelConfigs=" + mPhysicalChannelConfigs.get(i));
pw.println("mLinkCapacityEstimateList=" + mLinkCapacityEstimateLists.get(i));
+ // We need to obfuscate package names, and primitive arrays' native toString is ugly
+ Pair<List<String>, int[]> carrierPrivilegeState = mCarrierPrivilegeStates.get(i);
+ pw.println(
+ "mCarrierPrivilegeState=<packages=" + pii(carrierPrivilegeState.first)
+ + ", uids=" + Arrays.toString(carrierPrivilegeState.second) + ">");
pw.decreaseIndent();
}
@@ -3540,4 +3659,10 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
private static String pii(String packageName) {
return Build.IS_DEBUGGABLE ? packageName : "***";
}
+
+ /** Redacts an entire list of package names if necessary. */
+ private static String pii(List<String> packageNames) {
+ if (packageNames.isEmpty() || Build.IS_DEBUGGABLE) return packageNames.toString();
+ return "[***, size=" + packageNames.size() + "]";
+ }
}
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index ff480d1f614c..794b149bbde1 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -2872,29 +2872,18 @@ public class OomAdjuster {
void setAttachingSchedGroupLSP(ProcessRecord app) {
int initialSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
final ProcessStateRecord state = app.mState;
- // If the process has been marked as foreground via Zygote.START_FLAG_USE_TOP_APP_PRIORITY,
- // then verify that the top priority is actually is applied.
+ // If the process has been marked as foreground, it is starting as the top app (with
+ // Zygote#START_AS_TOP_APP_ARG), so boost the thread priority of its default UI thread.
if (state.hasForegroundActivities()) {
- String fallbackReason = null;
try {
// The priority must be the same as how does {@link #applyOomAdjLSP} set for
// {@link ProcessList.SCHED_GROUP_TOP_APP}. We don't check render thread because it
// is not ready when attaching.
- if (Process.getProcessGroup(app.getPid()) == THREAD_GROUP_TOP_APP) {
- app.getWindowProcessController().onTopProcChanged();
- setThreadPriority(app.getPid(), THREAD_PRIORITY_TOP_APP_BOOST);
- } else {
- fallbackReason = "not expected top priority";
- }
- } catch (Exception e) {
- fallbackReason = e.toString();
- }
- if (fallbackReason == null) {
+ app.getWindowProcessController().onTopProcChanged();
+ setThreadPriority(app.getPid(), THREAD_PRIORITY_TOP_APP_BOOST);
initialSchedGroup = ProcessList.SCHED_GROUP_TOP_APP;
- } else {
- // The real scheduling group will depend on if there is any component of the process
- // did something during attaching.
- Slog.w(TAG, "Fallback pre-set sched group to default: " + fallbackReason);
+ } catch (Exception e) {
+ Slog.w(TAG, "Failed to pre-set top priority to " + app + " " + e);
}
}
diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
index b94cea4d5d40..55d0728d803e 100644
--- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
@@ -783,7 +783,7 @@ public final class PlaybackActivityMonitor
// the same time if we still have a public client.
while (clientIterator.hasNext()) {
PlayMonitorClient pmc = clientIterator.next();
- if (pcdb.equals(pmc.mDispatcherCb)) {
+ if (pcdb.asBinder().equals(pmc.mDispatcherCb.asBinder())) {
pmc.release();
clientIterator.remove();
} else {
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 5de5fd3cc79c..dee69e02b371 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -2456,7 +2456,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
networkId, templateMeteredness, NetworkStats.ROAMING_ALL,
NetworkStats.DEFAULT_NETWORK_ALL, NetworkTemplate.NETWORK_TYPE_ALL,
NetworkTemplate.OEM_MANAGED_ALL, subscriberIdMatchRule);
- if (template.isPersistable()) {
+ if (NetworkPolicy.isTemplatePersistable(template)) {
mNetworkPolicy.put(template, new NetworkPolicy(template, cycleRule,
warningBytes, limitBytes, lastWarningSnooze,
lastLimitSnooze, metered, inferred));
@@ -2663,7 +2663,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
for (int i = 0; i < mNetworkPolicy.size(); i++) {
final NetworkPolicy policy = mNetworkPolicy.valueAt(i);
final NetworkTemplate template = policy.template;
- if (!template.isPersistable()) continue;
+ if (!NetworkPolicy.isTemplatePersistable(template)) continue;
out.startTag(null, TAG_NETWORK_POLICY);
writeIntAttribute(out, ATTR_NETWORK_TEMPLATE, template.getMatchRule());
diff --git a/services/core/java/com/android/server/pm/SELinuxMMAC.java b/services/core/java/com/android/server/pm/SELinuxMMAC.java
index 4a913e4edd71..cecbeed67f68 100644
--- a/services/core/java/com/android/server/pm/SELinuxMMAC.java
+++ b/services/core/java/com/android/server/pm/SELinuxMMAC.java
@@ -124,16 +124,10 @@ public final class SELinuxMMAC {
}
// Vendor mac permissions.
- // The filename has been renamed from nonplat_mac_permissions to
- // vendor_mac_permissions. Either of them should exist.
final File vendorMacPermission = new File(
Environment.getVendorDirectory(), "/etc/selinux/vendor_mac_permissions.xml");
if (vendorMacPermission.exists()) {
sMacPermissions.add(vendorMacPermission);
- } else {
- // For backward compatibility.
- sMacPermissions.add(new File(Environment.getVendorDirectory(),
- "/etc/selinux/nonplat_mac_permissions.xml"));
}
// ODM mac permissions (optional).
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index d0457b08aa34..1108c7752777 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -1498,11 +1498,15 @@ public class DisplayPolicy {
statusBarBottom);
}
- sTmpRect.set(windowFrames.mFrame);
- sTmpRect.intersect(displayFrames.mDisplayCutoutSafe);
- sTmpRect.top = windowFrames.mFrame.top; // Ignore top display cutout inset
- sTmpRect.bottom = statusBarBottom; // Use collapsed status bar size
- contentFrame.set(sTmpRect);
+ final InsetsState state = displayFrames.mInsetsState;
+ sTmpRect.set(displayFrames.mDisplayCutoutSafe);
+ // The status bar content can extend into regular display cutout insets but not
+ // waterfall insets.
+ sTmpRect.top = Math.max(state.getDisplayCutout().getWaterfallInsets().top, 0);
+
+ contentFrame.set(windowFrames.mFrame);
+ contentFrame.intersect(sTmpRect);
+ contentFrame.bottom = statusBarBottom; // Use collapsed status bar size
}
private int layoutNavigationBar(DisplayFrames displayFrames, Rect contentFrame) {
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index bd688a618c63..52da4b80a75d 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -2125,6 +2125,9 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
final Task rootTask;
if (singleActivity) {
rootTask = task;
+
+ // Apply the last recents animation leash transform to the task entering PIP
+ rootTask.maybeApplyLastRecentsAnimationTransaction();
} else {
// In the case of multiple activities, we will create a new task for it and then
// move the PIP activity into the task. Note that we explicitly defer the task
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index cae4f22f913f..dca0bacf1af7 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -2787,7 +2787,15 @@ class Task extends WindowContainer<WindowContainer> {
if (inOutConfig.smallestScreenWidthDp
== Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
- if (WindowConfiguration.isFloating(windowingMode)) {
+ // When entering to or exiting from Pip, the PipTaskOrganizer will set the
+ // windowing mode of the activity in the task to WINDOWING_MODE_FULLSCREEN and
+ // temporarily set the bounds of the task to fullscreen size for transitioning.
+ // It will get the wrong value if the calculation is based on this temporary
+ // fullscreen bounds.
+ // We should just inherit the value from parent for this temporary state.
+ final boolean inPipTransition = windowingMode == WINDOWING_MODE_PINNED
+ && !mTmpFullBounds.isEmpty() && mTmpFullBounds.equals(parentBounds);
+ if (WindowConfiguration.isFloating(windowingMode) && !inPipTransition) {
// For floating tasks, calculate the smallest width from the bounds of the task
inOutConfig.smallestScreenWidthDp = (int) (
Math.min(mTmpFullBounds.width(), mTmpFullBounds.height()) / density);
diff --git a/services/proguard.flags b/services/proguard.flags
index 30dd6cf545b9..5d01d3e7f85c 100644
--- a/services/proguard.flags
+++ b/services/proguard.flags
@@ -1,11 +1,21 @@
# TODO(b/196084106): Refine and optimize this configuration. Note that this
# configuration is only used when `SOONG_CONFIG_ANDROID_SYSTEM_OPTIMIZE_JAVA=true`.
-keep,allowoptimization,allowaccessmodification class ** {
- *;
+ !synthetic *;
}
# Various classes subclassed in ethernet-service (avoid marking final).
-keep public class android.net.** { *; }
# Referenced via CarServiceHelperService in car-frameworks-service (avoid removing).
--keep public class com.android.server.utils.Slogf { *; } \ No newline at end of file
+-keep public class com.android.server.utils.Slogf { *; }
+
+# Allows making private and protected methods/fields public as part of
+# optimization. This enables inlining of trivial getter/setter methods.
+-allowaccessmodification
+
+# Disallow accessmodification for soundtrigger classes. Logging via reflective
+# public member traversal can cause infinite loops. See b/210901706.
+-keep,allowoptimization class com.android.server.soundtrigger_middleware.** {
+ !synthetic *;
+}
diff --git a/telephony/common/com/google/android/mms/util/SqliteWrapper.java b/telephony/common/com/google/android/mms/util/SqliteWrapper.java
index e2d62f868d52..6d9b3210ea70 100644
--- a/telephony/common/com/google/android/mms/util/SqliteWrapper.java
+++ b/telephony/common/com/google/android/mms/util/SqliteWrapper.java
@@ -17,7 +17,6 @@
package com.google.android.mms.util;
-import android.app.ActivityManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.content.ContentValues;
@@ -25,49 +24,15 @@ import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteException;
import android.net.Uri;
-import android.os.Build;
import android.util.Log;
-import android.widget.Toast;
public final class SqliteWrapper {
private static final String TAG = "SqliteWrapper";
- private static final String SQLITE_EXCEPTION_DETAIL_MESSAGE
- = "unable to open database file";
private SqliteWrapper() {
// Forbidden being instantiated.
}
- // FIXME: It looks like outInfo.lowMemory does not work well as we expected.
- // after run command: adb shell fillup -p 100, outInfo.lowMemory is still false.
- private static boolean isLowMemory(Context context) {
- if (null == context) {
- return false;
- }
-
- ActivityManager am = (ActivityManager)
- context.getSystemService(Context.ACTIVITY_SERVICE);
- ActivityManager.MemoryInfo outInfo = new ActivityManager.MemoryInfo();
- am.getMemoryInfo(outInfo);
-
- return outInfo.lowMemory;
- }
-
- // FIXME: need to optimize this method.
- private static boolean isLowMemory(SQLiteException e) {
- return e.getMessage().equals(SQLITE_EXCEPTION_DETAIL_MESSAGE);
- }
-
- @UnsupportedAppUsage
- public static void checkSQLiteException(Context context, SQLiteException e) {
- if (isLowMemory(e)) {
- Toast.makeText(context, com.android.internal.R.string.low_memory,
- Toast.LENGTH_SHORT).show();
- } else {
- throw e;
- }
- }
-
@UnsupportedAppUsage
public static Cursor query(Context context, ContentResolver resolver, Uri uri,
String[] projection, String selection, String[] selectionArgs, String sortOrder) {
@@ -75,21 +40,10 @@ public final class SqliteWrapper {
return resolver.query(uri, projection, selection, selectionArgs, sortOrder);
} catch (SQLiteException e) {
Log.e(TAG, "Catch a SQLiteException when query: ", e);
- checkSQLiteException(context, e);
return null;
}
}
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public static boolean requery(Context context, Cursor cursor) {
- try {
- return cursor.requery();
- } catch (SQLiteException e) {
- Log.e(TAG, "Catch a SQLiteException when requery: ", e);
- checkSQLiteException(context, e);
- return false;
- }
- }
@UnsupportedAppUsage
public static int update(Context context, ContentResolver resolver, Uri uri,
ContentValues values, String where, String[] selectionArgs) {
@@ -97,7 +51,6 @@ public final class SqliteWrapper {
return resolver.update(uri, values, where, selectionArgs);
} catch (SQLiteException e) {
Log.e(TAG, "Catch a SQLiteException when update: ", e);
- checkSQLiteException(context, e);
return -1;
}
}
@@ -109,7 +62,6 @@ public final class SqliteWrapper {
return resolver.delete(uri, where, selectionArgs);
} catch (SQLiteException e) {
Log.e(TAG, "Catch a SQLiteException when delete: ", e);
- checkSQLiteException(context, e);
return -1;
}
}
@@ -121,7 +73,6 @@ public final class SqliteWrapper {
return resolver.insert(uri, values);
} catch (SQLiteException e) {
Log.e(TAG, "Catch a SQLiteException when insert: ", e);
- checkSQLiteException(context, e);
return null;
}
}
diff --git a/telephony/java/android/service/carrier/CarrierService.java b/telephony/java/android/service/carrier/CarrierService.java
index ca27998ec8a8..ae91d4d9b595 100644
--- a/telephony/java/android/service/carrier/CarrierService.java
+++ b/telephony/java/android/service/carrier/CarrierService.java
@@ -15,6 +15,8 @@
package android.service.carrier;
import android.annotation.CallSuper;
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
@@ -22,9 +24,12 @@ import android.os.Bundle;
import android.os.IBinder;
import android.os.PersistableBundle;
import android.os.ResultReceiver;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyRegistryManager;
import android.util.Log;
+import com.android.internal.util.ArrayUtils;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -87,7 +92,7 @@ public abstract class CarrierService extends Service {
* PersistableBundle} may be overridden by the system's default configuration service.
* </p>
*
- * @param id contains details about the current carrier that can be used do decide what
+ * @param id contains details about the current carrier that can be used to decide what
* configuration values to return. Instead of using details like MCCMNC to decide
* current carrier, it also contains subscription carrier id
* {@link android.telephony.TelephonyManager#getSimCarrierId()}, a platform-wide
@@ -95,10 +100,61 @@ public abstract class CarrierService extends Service {
* id as the key to look up the carrier info.
* @return a {@link PersistableBundle} object containing the configuration or null if default
* values should be used.
+ * @deprecated use {@link #onLoadConfig(int, CarrierIdentifier)} instead.
*/
+ @Deprecated
public abstract PersistableBundle onLoadConfig(CarrierIdentifier id);
/**
+ * Override this method to set carrier configuration on the given {@code subscriptionId}.
+ * <p>
+ * This method will be called by telephony services to get carrier-specific configuration
+ * values. The returned config will be saved by the system until,
+ * <ol>
+ * <li>The carrier app package is updated, or</li>
+ * <li>The carrier app requests a reload with
+ * {@link android.telephony.CarrierConfigManager#notifyConfigChangedForSubId
+ * notifyConfigChangedForSubId}.</li>
+ * </ol>
+ * This method can be called after a SIM card loads, which may be before or after boot.
+ * </p>
+ * <p>
+ * This method should not block for a long time. If expensive operations (e.g. network access)
+ * are required, this method can schedule the work and return null. Then, use
+ * {@link android.telephony.CarrierConfigManager#notifyConfigChangedForSubId
+ * notifyConfigChangedForSubId} to trigger a reload when the config is ready.
+ * </p>
+ * <p>
+ * Implementations should use the keys defined in {@link android.telephony.CarrierConfigManager
+ * CarrierConfigManager}. Any configuration values not set in the returned {@link
+ * PersistableBundle} may be overridden by the system's default configuration service.
+ * </p>
+ * <p>
+ * By default, this method just calls {@link #onLoadConfig(CarrierIdentifier)} with specified
+ * CarrierIdentifier {@code id}. Carrier app with target SDK
+ * {@link android.os.Build.VERSION_CODES#TIRAMISU} and above should override this method to
+ * load carrier configuration on the given {@code subscriptionId}.
+ * Note that {@link #onLoadConfig(CarrierIdentifier)} is still called prior to
+ * {@link android.os.Build.VERSION_CODES#TIRAMISU}.
+ * </p>
+ *
+ * @param subscriptionId the subscription on which the carrier app should load configuration
+ * @param id contains details about the current carrier that can be used to decide what
+ * configuration values to return. Instead of using details like MCCMNC to decide
+ * current carrier, it also contains subscription carrier id
+ * {@link android.telephony.TelephonyManager#getSimCarrierId()}, a platform-wide
+ * unique identifier for each carrier, CarrierConfigService can directly use carrier
+ * id as the key to look up the carrier info.
+ * @return a {@link PersistableBundle} object containing the configuration or null if default
+ * values should be used.
+ */
+ @SuppressLint("NullableCollection")
+ @Nullable
+ public PersistableBundle onLoadConfig(int subscriptionId, @Nullable CarrierIdentifier id) {
+ return onLoadConfig(id);
+ }
+
+ /**
* Informs the system of an intentional upcoming carrier network change by
* a carrier app. This call is optional and is only used to allow the
* system to provide alternative UI while telephony is performing an action
@@ -179,10 +235,16 @@ public abstract class CarrierService extends Service {
public static final String KEY_CONFIG_BUNDLE = "config_bundle";
@Override
- public void getCarrierConfig(CarrierIdentifier id, ResultReceiver result) {
+ public void getCarrierConfig(int phoneId, CarrierIdentifier id, ResultReceiver result) {
try {
+ int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ int[] subIds = SubscriptionManager.getSubId(phoneId);
+ if (!ArrayUtils.isEmpty(subIds)) {
+ // There should be at most one active subscription mapping to the phoneId.
+ subId = subIds[0];
+ }
Bundle data = new Bundle();
- data.putParcelable(KEY_CONFIG_BUNDLE, CarrierService.this.onLoadConfig(id));
+ data.putParcelable(KEY_CONFIG_BUNDLE, CarrierService.this.onLoadConfig(subId, id));
result.send(RESULT_OK, data);
} catch (Exception e) {
Log.e(LOG_TAG, "Error in onLoadConfig: " + e.getMessage(), e);
diff --git a/telephony/java/android/service/carrier/ICarrierService.aidl b/telephony/java/android/service/carrier/ICarrierService.aidl
index ac6f9614d8f5..054a280c3fe8 100644
--- a/telephony/java/android/service/carrier/ICarrierService.aidl
+++ b/telephony/java/android/service/carrier/ICarrierService.aidl
@@ -29,5 +29,5 @@ import android.service.carrier.CarrierIdentifier;
interface ICarrierService {
/** @see android.service.carrier.CarrierService#onLoadConfig */
- oneway void getCarrierConfig(in CarrierIdentifier id, in ResultReceiver result);
+ oneway void getCarrierConfig(in int phoneId, in CarrierIdentifier id, in ResultReceiver result);
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 95b9fda34211..5851ee182368 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -964,6 +964,21 @@ public class CarrierConfigManager {
= "carrier_use_ims_first_for_emergency_bool";
/**
+ * When {@code true}, the determination of whether to place a call as an emergency call will be
+ * based on the known {@link android.telephony.emergency.EmergencyNumber}s for the SIM on which
+ * the call is being placed. In a dual SIM scenario, if Sim A has the emergency numbers
+ * 123, 456 and Sim B has the emergency numbers 789, and the user places a call on SIM A to 789,
+ * it will not be treated as an emergency call in this case.
+ * When {@code false}, the determination is based on the emergency numbers from all device SIMs,
+ * regardless of which SIM the call is being placed on. If Sim A has the emergency numbers
+ * 123, 456 and Sim B has the emergency numbers 789, and the user places a call on SIM A to 789,
+ * the call will be dialed as an emergency number, but with an unspecified routing.
+ * @hide
+ */
+ public static final String KEY_USE_ONLY_DIALED_SIM_ECC_LIST_BOOL =
+ "use_only_dialed_sim_ecc_list_bool";
+
+ /**
* When IMS instant lettering is available for a carrier (see
* {@link #KEY_CARRIER_INSTANT_LETTERING_AVAILABLE_BOOL}), determines the list of characters
* which may not be contained in messages. Should be specified as a regular expression suitable
@@ -5339,6 +5354,7 @@ public class CarrierConfigManager {
sDefaults.putBoolean(KEY_CARRIER_IMS_GBA_REQUIRED_BOOL, false);
sDefaults.putBoolean(KEY_CARRIER_INSTANT_LETTERING_AVAILABLE_BOOL, false);
sDefaults.putBoolean(KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL, true);
+ sDefaults.putBoolean(KEY_USE_ONLY_DIALED_SIM_ECC_LIST_BOOL, false);
sDefaults.putString(KEY_CARRIER_NETWORK_SERVICE_WWAN_PACKAGE_OVERRIDE_STRING, "");
sDefaults.putString(KEY_CARRIER_NETWORK_SERVICE_WLAN_PACKAGE_OVERRIDE_STRING, "");
sDefaults.putString(KEY_CARRIER_QUALIFIED_NETWORKS_SERVICE_PACKAGE_OVERRIDE_STRING, "");
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 6286390ba139..30cb8ca64ad3 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -70,6 +70,7 @@ import android.os.SystemProperties;
import android.os.WorkSource;
import android.provider.Settings.SettingNotFoundException;
import android.service.carrier.CarrierIdentifier;
+import android.service.carrier.CarrierService;
import android.sysprop.TelephonyProperties;
import android.telecom.CallScreeningService;
import android.telecom.InCallService;
@@ -9178,6 +9179,57 @@ public class TelephonyManager {
return null;
}
+ /**
+ * Returns the package name that provides the {@link CarrierService} implementation for the
+ * current subscription, or {@code null} if no package with carrier privileges declares one.
+ *
+ * <p>If this object has been created with {@link #createForSubscriptionId}, then the provided
+ * subscription ID is used. Otherwise, the default subscription ID will be used.
+ *
+ * @return The system-selected package that provides the {@link CarrierService} implementation
+ * for the current subscription, or {@code null} if none is resolved
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public @Nullable String getCarrierServicePackageName() {
+ // TODO(b/205736323) plumb this through to CarrierPrivilegesTracker, which will cache the
+ // value instead of re-querying every time.
+ List<String> carrierServicePackages =
+ getCarrierPackageNamesForIntent(
+ new Intent(CarrierService.CARRIER_SERVICE_INTERFACE));
+ if (carrierServicePackages != null && !carrierServicePackages.isEmpty()) {
+ return carrierServicePackages.get(0);
+ }
+ return null;
+ }
+
+ /**
+ * Returns the package name that provides the {@link CarrierService} implementation for the
+ * specified {@code logicalSlotIndex}, or {@code null} if no package with carrier privileges
+ * declares one.
+ *
+ * @param logicalSlotIndex The slot index to fetch the {@link CarrierService} package for
+ * @return The system-selected package that provides the {@link CarrierService} implementation
+ * for the slot, or {@code null} if none is resolved
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public @Nullable String getCarrierServicePackageNameForLogicalSlot(int logicalSlotIndex) {
+ // TODO(b/205736323) plumb this through to CarrierPrivilegesTracker, which will cache the
+ // value instead of re-querying every time.
+ List<String> carrierServicePackages =
+ getCarrierPackageNamesForIntentAndPhone(
+ new Intent(CarrierService.CARRIER_SERVICE_INTERFACE), logicalSlotIndex);
+ if (carrierServicePackages != null && !carrierServicePackages.isEmpty()) {
+ return carrierServicePackages.get(0);
+ }
+ return null;
+ }
+
/** @hide */
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public List<String> getPackagesWithCarrierPrivileges() {
@@ -15976,4 +16028,76 @@ public class TelephonyManager {
}
return null;
}
+
+ /**
+ * Callback to listen for when the set of packages with carrier privileges for a SIM changes.
+ *
+ * @hide
+ */
+ @SystemApi
+ public interface CarrierPrivilegesListener {
+ /**
+ * Called when the set of packages with carrier privileges has changed.
+ *
+ * <p>Of note, this callback will <b>not</b> be fired if a carrier triggers a SIM profile
+ * switch and the same set of packages remains privileged after the switch.
+ *
+ * <p>At registration, the callback will receive the current set of privileged packages.
+ *
+ * @param privilegedPackageNames The updated set of package names that have carrier
+ * privileges
+ * @param privilegedUids The updated set of UIDs that have carrier privileges
+ */
+ void onCarrierPrivilegesChanged(
+ @NonNull List<String> privilegedPackageNames, @NonNull int[] privilegedUids);
+ }
+
+ /**
+ * Registers a {@link CarrierPrivilegesListener} on the given {@code logicalSlotIndex} to
+ * receive callbacks when the set of packages with carrier privileges changes. The callback will
+ * immediately be called with the latest state.
+ *
+ * @param logicalSlotIndex The SIM slot to listen on
+ * @param executor The executor where {@code listener} will be invoked
+ * @param listener The callback to register
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public void addCarrierPrivilegesListener(
+ int logicalSlotIndex,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull CarrierPrivilegesListener listener) {
+ if (mContext == null) {
+ throw new IllegalStateException("Telephony service is null");
+ } else if (executor == null || listener == null) {
+ throw new IllegalArgumentException(
+ "CarrierPrivilegesListener and executor must be non-null");
+ }
+ mTelephonyRegistryMgr = mContext.getSystemService(TelephonyRegistryManager.class);
+ if (mTelephonyRegistryMgr == null) {
+ throw new IllegalStateException("Telephony registry service is null");
+ }
+ mTelephonyRegistryMgr.addCarrierPrivilegesListener(logicalSlotIndex, executor, listener);
+ }
+
+ /**
+ * Unregisters an existing {@link CarrierPrivilegesListener}.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public void removeCarrierPrivilegesListener(@NonNull CarrierPrivilegesListener listener) {
+ if (mContext == null) {
+ throw new IllegalStateException("Telephony service is null");
+ } else if (listener == null) {
+ throw new IllegalArgumentException("CarrierPrivilegesListener must be non-null");
+ }
+ mTelephonyRegistryMgr = mContext.getSystemService(TelephonyRegistryManager.class);
+ if (mTelephonyRegistryMgr == null) {
+ throw new IllegalStateException("Telephony registry service is null");
+ }
+ mTelephonyRegistryMgr.removeCarrierPrivilegesListener(listener);
+ }
}
diff --git a/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java b/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java
index 9293a40d9a33..7a1a2af060d2 100644
--- a/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java
+++ b/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java
@@ -93,8 +93,8 @@ public interface CapabilityExchangeEventListener {
* Notify the framework that the ImsService has refreshed the PUBLISH
* internally, which has resulted in a new PUBLISH result.
* <p>
- * This method must return both SUCCESS (200 OK) and FAILURE (300+) codes in order to
- * keep the AOSP stack up to date.
+ * This method must be called to notify the framework of SUCCESS (200 OK) and FAILURE (300+)
+ * codes in order to keep the AOSP stack up to date.
* @param reasonCode The SIP response code sent from the network.
* @param reasonPhrase The optional reason response from the network. If the
* network provided no reason with the sip code, the string should be empty.
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 03010f6b27b6..55778883edde 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -2526,4 +2526,14 @@ interface ITelephony {
*/
CellIdentity getLastKnownCellIdentity(int subId, String callingPackage,
String callingFeatureId);
+
+ /**
+ * @return true if the modem service is set successfully, false otherwise.
+ */
+ boolean setModemService(in String serviceName);
+
+ /**
+ * @return the service name of the modem service which bind to.
+ */
+ String getModemService();
}