diff --git a/res/values/arrays.xml b/res/values/arrays.xml index 0ccbbf44aa0..e326dbe3caf 100644 --- a/res/values/arrays.xml +++ b/res/values/arrays.xml @@ -313,7 +313,8 @@ - 1 (Default) + Use System Default: %1$d + 1 2 3 4 @@ -321,7 +322,8 @@ - + + 1 2 3 diff --git a/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceController.java b/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceController.java index 5512685a138..79187f52470 100644 --- a/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceController.java +++ b/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceController.java @@ -22,9 +22,7 @@ import android.support.annotation.VisibleForTesting; import android.support.v7.preference.ListPreference; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceScreen; -import android.text.TextUtils; -import com.android.settings.R; import com.android.settings.core.PreferenceControllerMixin; import com.android.settingslib.development.DeveloperOptionsPreferenceController; @@ -32,58 +30,65 @@ public class BluetoothMaxConnectedAudioDevicesPreferenceController extends DeveloperOptionsPreferenceController implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin { - private static final String BLUETOOTH_MAX_CONNECTED_AUDIO_DEVICES_KEY = + private static final String MAX_CONNECTED_AUDIO_DEVICES_PREFERENCE_KEY = "bluetooth_max_connected_audio_devices"; @VisibleForTesting - static final String BLUETOOTH_MAX_CONNECTED_AUDIO_DEVICES_PROPERTY = + static final String MAX_CONNECTED_AUDIO_DEVICES_PROPERTY = "persist.bluetooth.maxconnectedaudiodevices"; - private final String[] mListValues; - private final String[] mListSummaries; + private final int mDefaultMaxConnectedAudioDevices; private ListPreference mPreference; public BluetoothMaxConnectedAudioDevicesPreferenceController(Context context) { super(context); - - mListValues = context.getResources() - .getStringArray(R.array.bluetooth_max_connected_audio_devices_values); - mListSummaries = context.getResources() - .getStringArray(R.array.bluetooth_max_connected_audio_devices); + mDefaultMaxConnectedAudioDevices = mContext.getResources().getInteger( + com.android.internal.R.integer.config_bluetooth_max_connected_audio_devices); } @Override public String getPreferenceKey() { - return BLUETOOTH_MAX_CONNECTED_AUDIO_DEVICES_KEY; + return MAX_CONNECTED_AUDIO_DEVICES_PREFERENCE_KEY; } @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); - mPreference = (ListPreference) screen.findPreference(getPreferenceKey()); + final CharSequence[] entries = mPreference.getEntries(); + entries[0] = String.format(entries[0].toString(), mDefaultMaxConnectedAudioDevices); + mPreference.setEntries(entries); } @Override public boolean onPreferenceChange(Preference preference, Object newValue) { - SystemProperties.set(BLUETOOTH_MAX_CONNECTED_AUDIO_DEVICES_PROPERTY, newValue.toString()); + String newValueString = newValue.toString(); + final ListPreference listPreference = (ListPreference) preference; + if (listPreference.findIndexOfValue(newValueString) <= 0) { + // Reset property value when default is chosen or when value is illegal + newValueString = ""; + } + SystemProperties.set(MAX_CONNECTED_AUDIO_DEVICES_PROPERTY, newValueString); updateState(preference); return true; } @Override public void updateState(Preference preference) { - final String currentValue = SystemProperties.get( - BLUETOOTH_MAX_CONNECTED_AUDIO_DEVICES_PROPERTY); - int index = 0; // Defaults to 1 device - for (int i = 0; i < mListValues.length; i++) { - if (TextUtils.equals(currentValue, mListValues[i])) { - index = i; - break; + final ListPreference listPreference = (ListPreference) preference; + final CharSequence[] entries = listPreference.getEntries(); + final String currentValue = SystemProperties.get(MAX_CONNECTED_AUDIO_DEVICES_PROPERTY); + int index = 0; + if (!currentValue.isEmpty()) { + index = listPreference.findIndexOfValue(currentValue); + if (index < 0) { + // Reset property value when value is illegal + SystemProperties.set(MAX_CONNECTED_AUDIO_DEVICES_PROPERTY, ""); + index = 0; } } - mPreference.setValue(mListValues[index]); - mPreference.setSummary(mListSummaries[index]); + listPreference.setValueIndex(index); + listPreference.setSummary(entries[index]); } @Override @@ -95,9 +100,8 @@ public class BluetoothMaxConnectedAudioDevicesPreferenceController extends @Override protected void onDeveloperOptionsSwitchDisabled() { mPreference.setEnabled(false); - SystemProperties.set(BLUETOOTH_MAX_CONNECTED_AUDIO_DEVICES_PROPERTY, mListValues[0]); - mPreference.setValue(mListValues[0]); - mPreference.setSummary(mListSummaries[0]); + SystemProperties.set(MAX_CONNECTED_AUDIO_DEVICES_PROPERTY, ""); + updateState(mPreference); } } diff --git a/tests/robotests/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceControllerTest.java index cf892f8c255..cd56b788000 100644 --- a/tests/robotests/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceControllerTest.java @@ -17,13 +17,15 @@ package com.android.settings.development; import static com.android.settings.development.BluetoothMaxConnectedAudioDevicesPreferenceController - .BLUETOOTH_MAX_CONNECTED_AUDIO_DEVICES_PROPERTY; + .MAX_CONNECTED_AUDIO_DEVICES_PROPERTY; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.when; import android.content.Context; +import android.content.res.Resources; import android.os.SystemProperties; import android.support.v7.preference.ListPreference; import android.support.v7.preference.PreferenceScreen; @@ -39,6 +41,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.mockito.Spy; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; @@ -47,37 +50,41 @@ import org.robolectric.annotation.Config; sdk = TestConfig.SDK_VERSION, shadows = {SettingsShadowSystemProperties.class}) public class BluetoothMaxConnectedAudioDevicesPreferenceControllerTest { + private static final int TEST_MAX_CONNECTED_AUDIO_DEVICES = 3; @Mock private PreferenceScreen mPreferenceScreen; + @Spy + private Context mSpyContext = RuntimeEnvironment.application; + @Spy + private Resources mSpyResources = RuntimeEnvironment.application.getResources(); - private Context mContext; private ListPreference mPreference; private BluetoothMaxConnectedAudioDevicesPreferenceController mController; - /** - * 0: 1 device maximum (Default) - * 1: 2 devices maximum - * 2: 3 devices maximum - * 3: 4 devices maximum - * 4: 5 devices maximum - */ - private String[] mListValues; - private String[] mListSummaries; + private CharSequence[] mListValues; + private CharSequence[] mListEntries; @Before public void setup() { MockitoAnnotations.initMocks(this); - mContext = RuntimeEnvironment.application; - mPreference = new ListPreference(mContext); - mListValues = mContext.getResources().getStringArray( - R.array.bluetooth_max_connected_audio_devices_values); - mListSummaries = mContext.getResources().getStringArray( - R.array.bluetooth_max_connected_audio_devices); - mController = new BluetoothMaxConnectedAudioDevicesPreferenceController(mContext); + doReturn(mSpyResources).when(mSpyContext).getResources(); + // Get XML values without mock + // Setup test list preference using XML values + mPreference = new ListPreference(mSpyContext); + mPreference.setEntries(R.array.bluetooth_max_connected_audio_devices); + mPreference.setEntryValues(R.array.bluetooth_max_connected_audio_devices_values); + // Stub default max connected audio devices to a test controlled value + doReturn(TEST_MAX_CONNECTED_AUDIO_DEVICES).when(mSpyResources).getInteger( + com.android.internal.R.integer.config_bluetooth_max_connected_audio_devices); + // Init the actual controller + mController = new BluetoothMaxConnectedAudioDevicesPreferenceController(mSpyContext); + // Construct preference in the controller via a mocked preference screen object when(mPreferenceScreen.findPreference(mController.getPreferenceKey())).thenReturn( mPreference); mController.displayPreference(mPreferenceScreen); + mListValues = mPreference.getEntryValues(); + mListEntries = mPreference.getEntries(); } @After @@ -85,40 +92,68 @@ public class BluetoothMaxConnectedAudioDevicesPreferenceControllerTest { SettingsShadowSystemProperties.clear(); } + @Test + public void verifyResourceSizeAndRange() { + // Verify normal list entries and default preference entries have the same size + assertThat(mListEntries.length).isEqualTo(mListValues.length); + // Verify that list entries are formatted correctly + final String defaultEntry = String.format(mListEntries[0].toString(), + TEST_MAX_CONNECTED_AUDIO_DEVICES); + assertThat(mListEntries[0]).isEqualTo(defaultEntry); + // Update the preference + mController.updateState(mPreference); + // Verify default preference value, entry and summary + assertThat(mPreference.getValue()).isEqualTo(mListValues[0]); + assertThat(mPreference.getEntry()).isEqualTo(mListEntries[0]); + assertThat(mPreference.getSummary()).isEqualTo(mListEntries[0]); + // Verify that default system property is empty + assertThat(SystemProperties.get(MAX_CONNECTED_AUDIO_DEVICES_PROPERTY)).isEmpty(); + // Verify default property integer value + assertThat(SystemProperties.getInt(MAX_CONNECTED_AUDIO_DEVICES_PROPERTY, + TEST_MAX_CONNECTED_AUDIO_DEVICES)).isEqualTo(TEST_MAX_CONNECTED_AUDIO_DEVICES); + } + @Test public void onPreferenceChange_setNumberOfDevices() { - for (int numberOfDevices = 0; numberOfDevices < mListValues.length; numberOfDevices++) { - mController.onPreferenceChange(mPreference, mListValues[numberOfDevices]); - - final String currentValue = SystemProperties.get( - BLUETOOTH_MAX_CONNECTED_AUDIO_DEVICES_PROPERTY); - - assertThat(currentValue).isEqualTo(mListValues[numberOfDevices]); - assertThat(mPreference.getValue()).isEqualTo(mListValues[numberOfDevices]); - assertThat(mPreference.getSummary()).isEqualTo(mListSummaries[numberOfDevices]); + for (final CharSequence newValue : mListValues) { + // Change preference using a list value + mController.onPreferenceChange(mPreference, newValue); + // Verify that value is set on the preference + assertThat(mPreference.getValue()).isEqualTo(newValue); + int index = mPreference.findIndexOfValue(newValue.toString()); + assertThat(mPreference.getEntry()).isEqualTo(mListEntries[index]); + // Verify that system property is set correctly after the change + final String currentValue = SystemProperties.get(MAX_CONNECTED_AUDIO_DEVICES_PROPERTY); + assertThat(currentValue).isEqualTo(mListValues[index]); } } @Test public void updateState_NumberOfDevicesUpdated_shouldSetPreference() { - for (int numberOfDevices = 0; numberOfDevices < mListValues.length; numberOfDevices++) { - SystemProperties.set(BLUETOOTH_MAX_CONNECTED_AUDIO_DEVICES_PROPERTY, - mListValues[numberOfDevices]); - + for (int i = 0; i < mListValues.length; ++i) { + final String propertyValue = mListValues[i].toString(); + SystemProperties.set(MAX_CONNECTED_AUDIO_DEVICES_PROPERTY, propertyValue); + // Verify that value is set on the preference mController.updateState(mPreference); - - assertThat(mPreference.getValue()).isEqualTo(mListValues[numberOfDevices]); - assertThat(mPreference.getSummary()).isEqualTo(mListSummaries[numberOfDevices]); + assertThat(mPreference.getValue()).isEqualTo(mListValues[i]); + assertThat(mPreference.getEntry()).isEqualTo(mListEntries[i]); + assertThat(mPreference.getSummary()).isEqualTo(mListEntries[i]); + // Verify that property value remain unchanged + assertThat(SystemProperties.get(MAX_CONNECTED_AUDIO_DEVICES_PROPERTY)) + .isEqualTo(propertyValue); } } @Test public void updateState_noValueSet_shouldSetDefaultTo1device() { - SystemProperties.set(BLUETOOTH_MAX_CONNECTED_AUDIO_DEVICES_PROPERTY, "garbage"); + SystemProperties.set(MAX_CONNECTED_AUDIO_DEVICES_PROPERTY, "garbage"); mController.updateState(mPreference); + // Verify that preference is reset back to default and property is reset to default assertThat(mPreference.getValue()).isEqualTo(mListValues[0]); - assertThat(mPreference.getSummary()).isEqualTo(mListSummaries[0]); + assertThat(mPreference.getEntry()).isEqualTo(mListEntries[0]); + assertThat(mPreference.getSummary()).isEqualTo(mListEntries[0]); + assertThat(SystemProperties.get(MAX_CONNECTED_AUDIO_DEVICES_PROPERTY)).isEmpty(); } @Test @@ -126,26 +161,30 @@ public class BluetoothMaxConnectedAudioDevicesPreferenceControllerTest { mController.onDeveloperOptionsSwitchDisabled(); assertThat(mPreference.isEnabled()).isFalse(); + // Verify that preference is reset back to default and property is reset to default assertThat(mPreference.getValue()).isEqualTo(mListValues[0]); - assertThat(mPreference.getSummary()).isEqualTo(mListSummaries[0]); - final String currentValue = SystemProperties.get( - BLUETOOTH_MAX_CONNECTED_AUDIO_DEVICES_PROPERTY); - assertThat(currentValue).isEqualTo(mListValues[0]); + assertThat(mPreference.getEntry()).isEqualTo(mListEntries[0]); + assertThat(mPreference.getSummary()).isEqualTo(mListEntries[0]); + assertThat(SystemProperties.get(MAX_CONNECTED_AUDIO_DEVICES_PROPERTY)).isEmpty(); } @Test public void onDeveloperOptionsSwitchEnabled_shouldEnablePreference() { - for (int numberOfDevices = 0; numberOfDevices < mListValues.length; numberOfDevices++) { + for (int i = 0; i < mListValues.length; ++i) { + final String initialValue = mListValues[i].toString(); mController.onDeveloperOptionsSwitchDisabled(); assertThat(mPreference.isEnabled()).isFalse(); - SystemProperties.set(BLUETOOTH_MAX_CONNECTED_AUDIO_DEVICES_PROPERTY, - mListValues[numberOfDevices]); + SystemProperties.set(MAX_CONNECTED_AUDIO_DEVICES_PROPERTY, initialValue); mController.onDeveloperOptionsSwitchEnabled(); assertThat(mPreference.isEnabled()).isTrue(); - assertThat(mPreference.getValue()).isEqualTo(mListValues[numberOfDevices]); - assertThat(mPreference.getSummary()).isEqualTo(mListSummaries[numberOfDevices]); + assertThat(mPreference.getValue()).isEqualTo(mListValues[i]); + assertThat(mPreference.getEntry()).isEqualTo(mListEntries[i]); + assertThat(mPreference.getSummary()).isEqualTo(mListEntries[i]); + // Verify that property value remain unchanged + assertThat(SystemProperties.get(MAX_CONNECTED_AUDIO_DEVICES_PROPERTY)) + .isEqualTo(initialValue); } } } diff --git a/tests/unit/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceControllerInstrumentationTest.java b/tests/unit/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceControllerInstrumentationTest.java new file mode 100644 index 00000000000..ce8166787e6 --- /dev/null +++ b/tests/unit/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceControllerInstrumentationTest.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2018 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.settings.development; + +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; + +import com.android.settings.R; + +import org.hamcrest.CoreMatchers; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.Arrays; + +@RunWith(AndroidJUnit4.class) +@SmallTest +public class BluetoothMaxConnectedAudioDevicesPreferenceControllerInstrumentationTest { + + private Context mTargetContext; + private String[] mListValues; + private String[] mListEntries; + private String mDefaultMaxConnectedAudioDevices; + + @Before + public void setUp() throws Exception { + mTargetContext = InstrumentationRegistry.getTargetContext(); + // Get XML values without mock + mListValues = mTargetContext.getResources() + .getStringArray(R.array.bluetooth_max_connected_audio_devices_values); + mListEntries = mTargetContext.getResources() + .getStringArray(R.array.bluetooth_max_connected_audio_devices); + mDefaultMaxConnectedAudioDevices = String.valueOf(mTargetContext.getResources() + .getInteger( + com.android.internal.R.integer + .config_bluetooth_max_connected_audio_devices)); + } + + @Test + public void verifyResource() { + // Verify normal list entries and default preference entries have the same size + Assert.assertEquals(mListEntries.length, mListValues.length); + Assert.assertThat(Arrays.asList(mListValues), + CoreMatchers.hasItem(mDefaultMaxConnectedAudioDevices)); + } +}