diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java index c861499073232..01e2db2e39395 100644 --- a/core/java/android/util/FeatureFlagUtils.java +++ b/core/java/android/util/FeatureFlagUtils.java @@ -33,6 +33,8 @@ public class FeatureFlagUtils { public static final String FFLAG_PREFIX = "sys.fflag."; public static final String FFLAG_OVERRIDE_PREFIX = FFLAG_PREFIX + "override."; + public static final String PERSIST_PREFIX = "persist." + FFLAG_OVERRIDE_PREFIX; + public static final String HEARING_AID_SETTINGS = "settings_bluetooth_hearing_aid"; private static final Map DEFAULT_FLAGS; static { @@ -44,6 +46,7 @@ public class FeatureFlagUtils { DEFAULT_FLAGS.put("settings_data_usage_v2", "true"); DEFAULT_FLAGS.put("settings_audio_switcher", "true"); DEFAULT_FLAGS.put("settings_systemui_theme", "true"); + DEFAULT_FLAGS.put(HEARING_AID_SETTINGS, "true"); } /** diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java index bb8fbe2da9c99..0370f204f0867 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java @@ -1189,7 +1189,8 @@ public class CachedBluetoothDevice implements Comparable * @return {@code true} if {@code cachedBluetoothDevice} is a2dp device */ public boolean isA2dpDevice() { - return mProfileManager.getA2dpProfile().getConnectionStatus(mDevice) == + A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile(); + return a2dpProfile != null && a2dpProfile.getConnectionStatus(mDevice) == BluetoothProfile.STATE_CONNECTED; } @@ -1197,7 +1198,17 @@ public class CachedBluetoothDevice implements Comparable * @return {@code true} if {@code cachedBluetoothDevice} is HFP device */ public boolean isHfpDevice() { - return mProfileManager.getHeadsetProfile().getConnectionStatus(mDevice) == + HeadsetProfile headsetProfile = mProfileManager.getHeadsetProfile(); + return headsetProfile != null && headsetProfile.getConnectionStatus(mDevice) == + BluetoothProfile.STATE_CONNECTED; + } + + /** + * @return {@code true} if {@code cachedBluetoothDevice} is Hearing Aid device + */ + public boolean isConnectedHearingAidDevice() { + HearingAidProfile hearingAidProfile = mProfileManager.getHearingAidProfile(); + return hearingAidProfile != null && hearingAidProfile.getConnectionStatus(mDevice) == BluetoothProfile.STATE_CONNECTED; } } diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java index 62f8724870e3c..29f21908f20df 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java @@ -123,6 +123,14 @@ public class LocalBluetoothProfileManager { ParcelUuid[] uuids = adapter.getUuids(); + List supportedList = mLocalAdapter.getSupportedProfiles(); + if (supportedList.contains(BluetoothProfile.HEARING_AID)) { + mHearingAidProfile = new HearingAidProfile(mContext, mLocalAdapter, mDeviceManager, + this); + addProfile(mHearingAidProfile, HearingAidProfile.NAME, + BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED); + } + // uuids may be null if Bluetooth is turned off if (uuids != null) { updateLocalProfiles(uuids); @@ -159,13 +167,6 @@ public class LocalBluetoothProfileManager { addProfile(mPbapProfile, PbapServerProfile.NAME, BluetoothPbap.ACTION_CONNECTION_STATE_CHANGED); - List supportedList = mLocalAdapter.getSupportedProfiles(); - if (supportedList.contains(BluetoothProfile.HEARING_AID)) { - mHearingAidProfile = new HearingAidProfile(mContext, mLocalAdapter, mDeviceManager, - this); - addProfile(mHearingAidProfile, HearingAidProfile.NAME, - BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED); - } if (DEBUG) Log.d(TAG, "LocalBluetoothProfileManager construction complete"); } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java index 927a94f6b0179..c39fb85428fa3 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java @@ -572,4 +572,43 @@ public class CachedBluetoothDeviceTest { assertThat(mCachedDevice.isHfpDevice()).isFalse(); } + + @Test + public void isConnectedHearingAidDevice_connected_returnTrue() { + when(mProfileManager.getHearingAidProfile()).thenReturn(mHearingAidProfile); + when(mHearingAidProfile.getConnectionStatus(mDevice)). + thenReturn(BluetoothProfile.STATE_CONNECTED); + + assertThat(mCachedDevice.isConnectedHearingAidDevice()).isTrue(); + } + + @Test + public void isConnectedHearingAidDevice_disconnected_returnFalse() { + when(mProfileManager.getHearingAidProfile()).thenReturn(mHearingAidProfile); + when(mHearingAidProfile.getConnectionStatus(mDevice)). + thenReturn(BluetoothProfile.STATE_DISCONNECTED); + + assertThat(mCachedDevice.isConnectedHearingAidDevice()).isFalse(); + } + + @Test + public void isConnectedHfpDevice_profileIsNull_returnFalse() { + when(mProfileManager.getHeadsetProfile()).thenReturn(null); + + assertThat(mCachedDevice.isHfpDevice()).isFalse(); + } + + @Test + public void isConnectedA2dpDevice_profileIsNull_returnFalse() { + when(mProfileManager.getA2dpProfile()).thenReturn(null); + + assertThat(mCachedDevice.isA2dpDevice()).isFalse(); + } + + @Test + public void isConnectedHearingAidDevice_profileIsNull_returnFalse() { + when(mProfileManager.getHearingAidProfile()).thenReturn(null); + + assertThat(mCachedDevice.isConnectedHearingAidDevice()).isFalse(); + } } diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java index aa426d3cd31f5..78b738500a97f 100644 --- a/services/core/java/com/android/server/BluetoothManagerService.java +++ b/services/core/java/com/android/server/BluetoothManagerService.java @@ -53,12 +53,16 @@ import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.SystemClock; +import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.os.UserManagerInternal; import android.os.UserManagerInternal.UserRestrictionsListener; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; +import android.text.TextUtils; +import android.util.FeatureFlagUtils; +import android.util.Log; import android.util.Slog; import android.util.StatsLog; @@ -386,6 +390,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mCallbacks = new RemoteCallbackList(); mStateChangeCallbacks = new RemoteCallbackList(); + // TODO: We need a more generic way to initialize the persist keys of FeatureFlagUtils + boolean isHearingAidEnabled; + String value = SystemProperties.get(FeatureFlagUtils.PERSIST_PREFIX + FeatureFlagUtils.HEARING_AID_SETTINGS); + if (!TextUtils.isEmpty(value)) { + isHearingAidEnabled = Boolean.parseBoolean(value); + Log.v(TAG, "set feature flag HEARING_AID_SETTINGS to " + isHearingAidEnabled); + FeatureFlagUtils.setEnabled(context, FeatureFlagUtils.HEARING_AID_SETTINGS, isHearingAidEnabled); + } + IntentFilter filter = new IntentFilter(); filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); filter.addAction(BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED);