diff --git a/res/layout/preference_bluetooth_profile_category.xml b/res/layout/preference_bluetooth_profile_category.xml new file mode 100644 index 00000000000..8c09bad01bc --- /dev/null +++ b/res/layout/preference_bluetooth_profile_category.xml @@ -0,0 +1,26 @@ + + + + + diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java b/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java index aa1240921a5..dcaeffe07d8 100644 --- a/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java +++ b/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java @@ -28,6 +28,7 @@ import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceScreen; import androidx.preference.SwitchPreference; +import com.android.settings.R; import com.android.settingslib.bluetooth.A2dpProfile; import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.bluetooth.LocalBluetoothManager; @@ -48,6 +49,8 @@ public class BluetoothDetailsProfilesController extends BluetoothDetailsControll implements Preference.OnPreferenceClickListener, LocalBluetoothProfileManager.ServiceListener { private static final String KEY_PROFILES_GROUP = "bluetooth_profiles"; + private static final String KEY_BOTTOM_PREFERENCE = "bottom_preference"; + private static final int ORDINAL = 99; @VisibleForTesting static final String HIGH_QUALITY_AUDIO_PREF_TAG = "A2dpProfileHighQualityAudio"; @@ -55,7 +58,9 @@ public class BluetoothDetailsProfilesController extends BluetoothDetailsControll private LocalBluetoothManager mManager; private LocalBluetoothProfileManager mProfileManager; private CachedBluetoothDevice mCachedDevice; - private PreferenceCategory mProfilesContainer; + + @VisibleForTesting + PreferenceCategory mProfilesContainer; public BluetoothDetailsProfilesController(Context context, PreferenceFragmentCompat fragment, LocalBluetoothManager manager, CachedBluetoothDevice device, Lifecycle lifecycle) { @@ -69,6 +74,7 @@ public class BluetoothDetailsProfilesController extends BluetoothDetailsControll @Override protected void init(PreferenceScreen screen) { mProfilesContainer = (PreferenceCategory)screen.findPreference(getPreferenceKey()); + mProfilesContainer.setLayoutResource(R.layout.preference_bluetooth_profile_category); // Call refresh here even though it will get called later in onResume, to avoid the // list of switches appearing to "pop" into the page. refresh(); @@ -283,6 +289,16 @@ public class BluetoothDetailsProfilesController extends BluetoothDetailsControll mProfilesContainer.removePreference(pref); } } + + Preference preference = mProfilesContainer.findPreference(KEY_BOTTOM_PREFERENCE); + if (preference == null) { + preference = new Preference(mContext); + preference.setLayoutResource(R.layout.preference_bluetooth_profile_category); + preference.setEnabled(false); + preference.setKey(KEY_BOTTOM_PREFERENCE); + preference.setOrder(ORDINAL); + mProfilesContainer.addPreference(preference); + } } @Override diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsProfilesControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsProfilesControllerTest.java index 5fc45a63773..c5b0a6a0630 100644 --- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsProfilesControllerTest.java +++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsProfilesControllerTest.java @@ -29,6 +29,7 @@ import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; import android.content.Context; +import androidx.preference.Preference; import androidx.preference.PreferenceCategory; import androidx.preference.SwitchPreference; @@ -84,6 +85,7 @@ public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsCont mController = new BluetoothDetailsProfilesController(mContext, mFragment, mLocalManager, mCachedDevice, mLifecycle); mProfiles.setKey(mController.getPreferenceKey()); + mController.mProfilesContainer = mProfiles; mScreen.addPreference(mProfiles); } @@ -193,11 +195,14 @@ public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsCont private List getProfileSwitches(boolean expectOnlyMConnectable) { if (expectOnlyMConnectable) { assertThat(mConnectableProfiles).isNotEmpty(); - assertThat(mProfiles.getPreferenceCount()).isEqualTo(mConnectableProfiles.size()); + assertThat(mProfiles.getPreferenceCount() - 1).isEqualTo(mConnectableProfiles.size()); } List result = new ArrayList<>(); for (int i = 0; i < mProfiles.getPreferenceCount(); i++) { - result.add((SwitchPreference)mProfiles.getPreference(i)); + final Preference preference = mProfiles.getPreference(i); + if (preference instanceof SwitchPreference) { + result.add((SwitchPreference) preference); + } } return result; } @@ -236,7 +241,7 @@ public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsCont mController.onDeviceAttributesChanged(); // There should have been no new switches added. - assertThat(mProfiles.getPreferenceCount()).isEqualTo(2); + assertThat(mProfiles.getPreferenceCount()).isEqualTo(3); // Make sure both switches got disabled. assertThat(switches.get(0).isEnabled()).isFalse(); @@ -258,7 +263,7 @@ public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsCont assertThat(mConnectableProfiles.get(0).isEnabled(mDevice)).isFalse(); // Make sure no new preferences were added. - assertThat(mProfiles.getPreferenceCount()).isEqualTo(2); + assertThat(mProfiles.getPreferenceCount()).isEqualTo(3); // Clicking the pref again should make the profile once again preferred. pref.performClick(); @@ -266,7 +271,7 @@ public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsCont assertThat(mConnectableProfiles.get(0).isEnabled(mDevice)).isTrue(); // Make sure we still haven't gotten any new preferences added. - assertThat(mProfiles.getPreferenceCount()).isEqualTo(2); + assertThat(mProfiles.getPreferenceCount()).isEqualTo(3); } @Test @@ -295,7 +300,7 @@ public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsCont assertThat(pref.isChecked()).isTrue(); pref.performClick(); - assertThat(mProfiles.getPreferenceCount()).isEqualTo(1); + assertThat(mProfiles.getPreferenceCount()).isEqualTo(2); assertThat(mDevice.getPhonebookAccessPermission()) .isEqualTo(BluetoothDevice.ACCESS_REJECTED); } @@ -318,7 +323,7 @@ public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsCont assertThat(pref.isChecked()).isFalse(); pref.performClick(); - assertThat(mProfiles.getPreferenceCount()).isEqualTo(1); + assertThat(mProfiles.getPreferenceCount()).isEqualTo(2); assertThat(mDevice.getPhonebookAccessPermission()) .isEqualTo(BluetoothDevice.ACCESS_ALLOWED); } @@ -340,7 +345,7 @@ public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsCont assertThat(pref.isChecked()).isFalse(); pref.performClick(); - assertThat(mProfiles.getPreferenceCount()).isEqualTo(1); + assertThat(mProfiles.getPreferenceCount()).isEqualTo(2); assertThat(mDevice.getMessageAccessPermission()).isEqualTo(BluetoothDevice.ACCESS_ALLOWED); } @@ -386,7 +391,7 @@ public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsCont setupDevice(makeDefaultDeviceConfig()); addMockA2dpProfile(true, false, false); showScreen(mController); - assertThat(mProfiles.getPreferenceCount()).isEqualTo(1); + assertThat(mProfiles.getPreferenceCount()).isEqualTo(2); SwitchPreference pref = (SwitchPreference) mProfiles.getPreference(0); assertThat(pref.getKey()) .isNotEqualTo(BluetoothDetailsProfilesController.HIGH_QUALITY_AUDIO_PREF_TAG); @@ -408,7 +413,7 @@ public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsCont setupDevice(makeDefaultDeviceConfig()); A2dpProfile audioProfile = addMockA2dpProfile(true, true, true); showScreen(mController); - assertThat(mProfiles.getPreferenceCount()).isEqualTo(2); + assertThat(mProfiles.getPreferenceCount()).isEqualTo(3); // Disabling media audio should cause the high quality audio switch to disappear, but not // the regular audio one.