From c33e2a1cefa3a91c4e798b25c432ecf02914921a Mon Sep 17 00:00:00 2001 From: Rubin Xu Date: Fri, 30 Mar 2018 20:51:24 +0100 Subject: [PATCH 1/5] Switch to new checkPasswordHistory method This is part of the fix that upgrades the hashing of password history to a more secure design. Bug: 32826058 Test: manual Change-Id: Ib022c8db1f7b63f75b69d0177fa5f6be528a83c5 --- .../settings/password/ChooseLockPassword.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/com/android/settings/password/ChooseLockPassword.java b/src/com/android/settings/password/ChooseLockPassword.java index 14f7d6bd6c4..e60b4e6d0e5 100644 --- a/src/com/android/settings/password/ChooseLockPassword.java +++ b/src/com/android/settings/password/ChooseLockPassword.java @@ -193,6 +193,7 @@ public class ChooseLockPassword extends SettingsActivity { private int mPasswordMinLengthToFulfillAllPolicies = 0; protected int mUserId; private boolean mHideDrawer = false; + private byte[] mPasswordHistoryHashFactor; /** * Password requirements that we need to verify. */ @@ -667,7 +668,8 @@ public class ChooseLockPassword extends SettingsActivity { } } // Is the password recently used? - if (mLockPatternUtils.checkPasswordHistory(password, mUserId)) { + if (mLockPatternUtils.checkPasswordHistory(password, getPasswordHistoryHashFactor(), + mUserId)) { errorCode |= RECENTLY_USED; } } @@ -730,6 +732,18 @@ public class ChooseLockPassword extends SettingsActivity { return errorCode; } + /** + * Lazily compute and return the history hash factor of the current user (mUserId), used for + * password history check. + */ + private byte[] getPasswordHistoryHashFactor() { + if (mPasswordHistoryHashFactor == null) { + mPasswordHistoryHashFactor = mLockPatternUtils.getPasswordHistoryHashFactor( + mCurrentPassword, mUserId); + } + return mPasswordHistoryHashFactor; + } + public void handleNext() { if (mSaveAndFinishWorker != null) return; mChosenPassword = mPasswordEntry.getText().toString(); From be6a844a06907f1c6cc2855800d650052dbce156 Mon Sep 17 00:00:00 2001 From: Salvador Martinez Date: Mon, 23 Apr 2018 16:52:25 -0700 Subject: [PATCH 2/5] Check if boxes still available when restoring state Apparently when the device is idle long enough the system will clean up the dialog view for the hotspot band preference. This will cause restore state to fail once it decides to pause the activity. To avoid this we should make sure the boxes are not null. Test: robotest Bug: 78445411 Change-Id: I2a82b01f894f62be6c5209c78faddc4089aa6301 --- .../widget/HotspotApBandSelectionPreference.java | 4 ++-- .../HotspotApBandSelectionPreferenceTest.java | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/com/android/settings/widget/HotspotApBandSelectionPreference.java b/src/com/android/settings/widget/HotspotApBandSelectionPreference.java index 4f127eb9193..0a2405e4136 100644 --- a/src/com/android/settings/widget/HotspotApBandSelectionPreference.java +++ b/src/com/android/settings/widget/HotspotApBandSelectionPreference.java @@ -118,8 +118,8 @@ public class HotspotApBandSelectionPreference extends CustomDialogPreference imp SavedState myState = new SavedState(superState); myState.shouldRestore = getDialog() != null; - myState.enabled2G = mBox2G.isChecked(); - myState.enabled5G = mBox5G.isChecked(); + myState.enabled2G = mBox2G != null && mBox2G.isChecked(); + myState.enabled5G = mBox5G != null && mBox5G.isChecked(); return myState; } diff --git a/tests/robotests/src/com/android/settings/widget/HotspotApBandSelectionPreferenceTest.java b/tests/robotests/src/com/android/settings/widget/HotspotApBandSelectionPreferenceTest.java index 6bfc968a12a..0ffda3baa96 100644 --- a/tests/robotests/src/com/android/settings/widget/HotspotApBandSelectionPreferenceTest.java +++ b/tests/robotests/src/com/android/settings/widget/HotspotApBandSelectionPreferenceTest.java @@ -115,6 +115,21 @@ public class HotspotApBandSelectionPreferenceTest { assertThat(mPreference.mShouldRestore).isFalse(); } + @Test + public void onSaveInstanceState_doesNotCrashWhenViewGone() { + mPreference.setExistingConfigValue(WifiConfiguration.AP_BAND_2GHZ); + mPreference.onBindDialogView(mLayout); + // When the device dozes the view and dialog can become null + mPreference.mBox5G = null; + mPreference.mBox2G = null; + ReflectionHelpers.setField(mPreference, "mFragment", null); + + // make sure it does not crash and state is not restored + Parcelable parcelable = mPreference.onSaveInstanceState(); + mPreference.onRestoreInstanceState(parcelable); + assertThat(mPreference.mShouldRestore).isFalse(); + } + @Test public void onSaveInstanceState_presentWhenDialogPresent() { mPreference.setExistingConfigValue(WifiConfiguration.AP_BAND_2GHZ); From 3b7f08d1ee60c6e4abaea43bef38792c1221d4bd Mon Sep 17 00:00:00 2001 From: HJ ChangLiao Date: Wed, 18 Apr 2018 17:28:21 +0800 Subject: [PATCH 3/5] Add intent receiver in BatterySaverCondition Receive ACTION_POWER_SAVE_MODE_CHANGING to listen state and update immediately. Change-Id: Iff2ebb262d95f43d0c970b32f326e3a3e6981a2a Fixes: 78104542 Test: make RunSettingsRoboTests --- .../conditional/BatterySaverCondition.java | 33 +++++- .../BatterySaverConditionTest.java | 103 ++++++++++++++++++ 2 files changed, 134 insertions(+), 2 deletions(-) create mode 100644 tests/robotests/src/com/android/settings/dashboard/conditional/BatterySaverConditionTest.java diff --git a/src/com/android/settings/dashboard/conditional/BatterySaverCondition.java b/src/com/android/settings/dashboard/conditional/BatterySaverCondition.java index f1962efa9cd..728154d5d6d 100644 --- a/src/com/android/settings/dashboard/conditional/BatterySaverCondition.java +++ b/src/com/android/settings/dashboard/conditional/BatterySaverCondition.java @@ -23,12 +23,20 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.settings.R; import com.android.settings.core.SubSettingLauncher; import com.android.settings.fuelgauge.BatterySaverDrawable; +import com.android.settings.fuelgauge.BatterySaverReceiver; import com.android.settings.fuelgauge.batterysaver.BatterySaverSettings; import com.android.settingslib.fuelgauge.BatterySaverUtils; -public class BatterySaverCondition extends Condition { +public class BatterySaverCondition extends Condition implements + BatterySaverReceiver.BatterySaverListener { + + private final BatterySaverReceiver mReceiver; + public BatterySaverCondition(ConditionManager manager) { super(manager); + + mReceiver = new BatterySaverReceiver(manager.getContext()); + mReceiver.setBatterySaverListener(this); } @Override @@ -54,7 +62,7 @@ public class BatterySaverCondition extends Condition { @Override public CharSequence[] getActions() { - return new CharSequence[] {mManager.getContext().getString(R.string.condition_turn_off)}; + return new CharSequence[]{mManager.getContext().getString(R.string.condition_turn_off)}; } @Override @@ -82,4 +90,25 @@ public class BatterySaverCondition extends Condition { public int getMetricsConstant() { return MetricsEvent.SETTINGS_CONDITION_BATTERY_SAVER; } + + @Override + public void onResume() { + mReceiver.setListening(true); + } + + @Override + public void onPause() { + mReceiver.setListening(false); + } + + @Override + public void onPowerSaveModeChanged() { + ConditionManager.get(mManager.getContext()).getCondition(BatterySaverCondition.class) + .refreshState(); + } + + @Override + public void onBatteryChanged(boolean pluggedIn) { + // do nothing + } } diff --git a/tests/robotests/src/com/android/settings/dashboard/conditional/BatterySaverConditionTest.java b/tests/robotests/src/com/android/settings/dashboard/conditional/BatterySaverConditionTest.java new file mode 100644 index 00000000000..84093c47c85 --- /dev/null +++ b/tests/robotests/src/com/android/settings/dashboard/conditional/BatterySaverConditionTest.java @@ -0,0 +1,103 @@ +/* + * 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.dashboard.conditional; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.content.IntentFilter; +import android.os.PowerManager; + +import com.android.settings.R; +import com.android.settings.fuelgauge.BatterySaverReceiver; +import com.android.settings.testutils.SettingsRobolectricTestRunner; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.Shadows; +import org.robolectric.shadows.ShadowPowerManager; + +@RunWith(SettingsRobolectricTestRunner.class) +public class BatterySaverConditionTest { + @Mock + private ConditionManager mConditionManager; + + private ShadowPowerManager mPowerManager; + private Context mContext; + private BatterySaverCondition mCondition; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = spy(RuntimeEnvironment.application); + mPowerManager = Shadows.shadowOf(mContext.getSystemService(PowerManager.class)); + when(mConditionManager.getContext()).thenReturn(mContext); + mCondition = spy(new BatterySaverCondition(mConditionManager)); + } + + @Test + public void verifyText() { + assertThat(mCondition.getTitle()).isEqualTo( + mContext.getText(R.string.condition_battery_title)); + assertThat(mCondition.getSummary()).isEqualTo( + mContext.getText(R.string.condition_battery_summary)); + assertThat(mCondition.getActions()[0]).isEqualTo( + mContext.getText(R.string.condition_turn_off)); + } + + @Test + public void onResume_shouldRegisterReceiver() { + mCondition.onResume(); + + verify(mContext).registerReceiver(any(BatterySaverReceiver.class), any(IntentFilter.class)); + } + + @Test + public void onPause_shouldUnregisterReceiver() { + mCondition.onResume(); + mCondition.onPause(); + + verify(mContext).unregisterReceiver(any(BatterySaverReceiver.class)); + } + + @Test + public void refreshState_PowerSaverOn_shouldActivate() { + mPowerManager.setIsPowerSaveMode(true); + + mCondition.refreshState(); + + assertThat(mCondition.isActive()).isTrue(); + } + + @Test + public void refreshState_PowerSaverOff_shouldNotActivate() { + mPowerManager.setIsPowerSaveMode(false); + + mCondition.refreshState(); + + assertThat(mCondition.isActive()).isFalse(); + } +} From 1cf0dfd3b24d3bfb2688fdd6c7c0d02cc76eb62d Mon Sep 17 00:00:00 2001 From: Doris Ling Date: Tue, 24 Apr 2018 13:42:19 -0700 Subject: [PATCH 4/5] Fix Data warning title not translated. - change to use the title resource id instead of getting the title from the preference, so that it can react to language change properly. Change-Id: I7f4b3c49ef1622b3d90bf035597742cac6f7af3c Fixes: 78318536 Test: run i18nscreenshots --- src/com/android/settings/datausage/BillingCyclePreference.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/android/settings/datausage/BillingCyclePreference.java b/src/com/android/settings/datausage/BillingCyclePreference.java index 7e302c4818b..6fb0df62123 100644 --- a/src/com/android/settings/datausage/BillingCyclePreference.java +++ b/src/com/android/settings/datausage/BillingCyclePreference.java @@ -88,7 +88,7 @@ public class BillingCyclePreference extends Preference implements TemplatePrefer return new SubSettingLauncher(getContext()) .setDestination(BillingCycleSettings.class.getName()) .setArguments(args) - .setTitle(getTitle()) + .setTitle(R.string.billing_cycle) .setSourceMetricsCategory(MetricsProto.MetricsEvent.VIEW_UNKNOWN) .toIntent(); } From 458fb2319fff7f0b3266fbbfeb7c4f92550f098a Mon Sep 17 00:00:00 2001 From: caxtonchan Date: Mon, 23 Apr 2018 15:04:21 +0800 Subject: [PATCH 5/5] Hide the audio switcher if it is not relevant Bug: 78317337 Test: make RunSettingsRoboTests ROBOTEST_FILTER="AudioOutputSwitchPreferenceControllerTest" -j28 ROBOTEST_FILTER="MediaOutputPreferenceControllerTest" -j28 ROBOTEST_FILTER="HandsFreeProfileOutputPreferenceControllerTest" -j28 Change-Id: I9824941cf410b26ad166aa163d7cccd3bfc31a06 --- .../AudioSwitchPreferenceController.java | 1 + ...FreeProfileOutputPreferenceController.java | 6 ++-- .../MediaOutputPreferenceController.java | 8 +++--- ...oOutputSwitchPreferenceControllerTest.java | 2 +- ...ProfileOutputPreferenceControllerTest.java | 16 +++++------ .../MediaOutputPreferenceControllerTest.java | 28 +++++++++---------- 6 files changed, 31 insertions(+), 30 deletions(-) diff --git a/src/com/android/settings/sound/AudioSwitchPreferenceController.java b/src/com/android/settings/sound/AudioSwitchPreferenceController.java index 28ad3f5f3d3..b2dafcc8df0 100644 --- a/src/com/android/settings/sound/AudioSwitchPreferenceController.java +++ b/src/com/android/settings/sound/AudioSwitchPreferenceController.java @@ -134,6 +134,7 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); mPreference = screen.findPreference(mPreferenceKey); + mPreference.setVisible(false); } @Override diff --git a/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceController.java b/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceController.java index 2f21f1b0023..58ea7b7e1d1 100644 --- a/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceController.java +++ b/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceController.java @@ -47,7 +47,7 @@ public class HandsFreeProfileOutputPreferenceController extends if (!isOngoingCallStatus()) { // Without phone call, disable the switch entry. - preference.setEnabled(false); + mPreference.setVisible(false); preference.setSummary(mContext.getText(R.string.media_output_default_summary)); return; } @@ -67,12 +67,12 @@ public class HandsFreeProfileOutputPreferenceController extends final int numDevices = ArrayUtils.size(mConnectedDevices); if (numDevices == 0) { // No connected devices, disable switch entry. - preference.setEnabled(false); + mPreference.setVisible(false); preference.setSummary(mContext.getText(R.string.media_output_default_summary)); return; } - preference.setEnabled(true); + mPreference.setVisible(true); CharSequence[] mediaOutputs = new CharSequence[numDevices + 1]; CharSequence[] mediaValues = new CharSequence[numDevices + 1]; diff --git a/src/com/android/settings/sound/MediaOutputPreferenceController.java b/src/com/android/settings/sound/MediaOutputPreferenceController.java index df07dc5fa68..dce19f171e2 100644 --- a/src/com/android/settings/sound/MediaOutputPreferenceController.java +++ b/src/com/android/settings/sound/MediaOutputPreferenceController.java @@ -52,14 +52,14 @@ public class MediaOutputPreferenceController extends AudioSwitchPreferenceContro if (isStreamFromOutputDevice(STREAM_MUSIC, DEVICE_OUT_REMOTE_SUBMIX)) { // In cast mode, disable switch entry. - preference.setEnabled(false); + mPreference.setVisible(false); preference.setSummary(mContext.getText(R.string.media_output_summary_unavailable)); return; } if (isOngoingCallStatus()) { // Ongoing call status, switch entry for media will be disabled. - preference.setEnabled(false); + mPreference.setVisible(false); preference.setSummary( mContext.getText(R.string.media_out_summary_ongoing_call_state)); return; @@ -79,12 +79,12 @@ public class MediaOutputPreferenceController extends AudioSwitchPreferenceContro final int numDevices = ArrayUtils.size(mConnectedDevices); if (numDevices == 0) { // Disable switch entry if there is no connected devices. - preference.setEnabled(false); + mPreference.setVisible(false); preference.setSummary(mContext.getText(R.string.media_output_default_summary)); return; } - preference.setEnabled(true); + mPreference.setVisible(true); CharSequence[] mediaOutputs = new CharSequence[numDevices + 1]; CharSequence[] mediaValues = new CharSequence[numDevices + 1]; diff --git a/tests/robotests/src/com/android/settings/sound/AudioOutputSwitchPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/sound/AudioOutputSwitchPreferenceControllerTest.java index 2168a2ad62f..e0877e47217 100644 --- a/tests/robotests/src/com/android/settings/sound/AudioOutputSwitchPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/sound/AudioOutputSwitchPreferenceControllerTest.java @@ -245,7 +245,7 @@ public class AudioOutputSwitchPreferenceControllerTest { @Override public String getPreferenceKey() { - return null; + return TEST_KEY; } } } \ No newline at end of file diff --git a/tests/robotests/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceControllerTest.java index f3f1c835787..0692c9c6ccf 100644 --- a/tests/robotests/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceControllerTest.java @@ -159,7 +159,7 @@ public class HandsFreeProfileOutputPreferenceControllerTest { /** * One Headset Bluetooth device is available and activated - * Preference should be enabled + * Preference should be visible * Preference summary should be activate device name */ @Test @@ -170,13 +170,13 @@ public class HandsFreeProfileOutputPreferenceControllerTest { mController.updateState(mPreference); - assertThat(mPreference.isEnabled()).isTrue(); + assertThat(mPreference.isVisible()).isTrue(); assertThat(mPreference.getSummary()).isEqualTo(mBluetoothDevice.getName()); } /** * More than one Headset Bluetooth devices are available, and second device is active. - * Preference should be enabled + * Preference should be visible * Preference summary should be activate device name */ @Test @@ -196,14 +196,14 @@ public class HandsFreeProfileOutputPreferenceControllerTest { mController.updateState(mPreference); - assertThat(mPreference.isEnabled()).isTrue(); + assertThat(mPreference.isVisible()).isTrue(); assertThat(mPreference.getSummary()).isEqualTo(secondBluetoothDevice.getName()); } /** * Hands Free Profile Bluetooth device(s) are available, but wired headset is plugged in * and activated. - * Preference should be enabled + * Preference should be visible * Preference summary should be "This device" */ @Test @@ -216,14 +216,14 @@ public class HandsFreeProfileOutputPreferenceControllerTest { mController.updateState(mPreference); - assertThat(mPreference.isEnabled()).isTrue(); + assertThat(mPreference.isVisible()).isTrue(); assertThat(mPreference.getSummary()).isEqualTo( mContext.getText(R.string.media_output_default_summary)); } /** * No available Headset BT devices - * Preference should be disabled + * Preference should be invisible * Preference summary should be "This device" */ @Test @@ -234,7 +234,7 @@ public class HandsFreeProfileOutputPreferenceControllerTest { mController.updateState(mPreference); - assertThat(mPreference.isEnabled()).isFalse(); + assertThat(mPreference.isVisible()).isFalse(); assertThat(mPreference.getSummary()).isEqualTo( mContext.getText(R.string.media_output_default_summary)); } diff --git a/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java index 1c7c1c4c7b6..b62e6b388d9 100644 --- a/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java @@ -160,7 +160,7 @@ public class MediaOutputPreferenceControllerTest { /** * On going call state: - * Preference should be disabled + * Preference should be invisible * Default string should be "Unavailable during calls" */ @Test @@ -169,14 +169,14 @@ public class MediaOutputPreferenceControllerTest { mController.updateState(mPreference); - assertThat(mPreference.isEnabled()).isFalse(); + assertThat(mPreference.isVisible()).isFalse(); assertThat(mPreference.getSummary()).isEqualTo( mContext.getText(R.string.media_out_summary_ongoing_call_state)); } /** * No available A2dp BT devices: - * Preference should be disabled + * Preference should be invisible * Preference summary should be "This device" */ @Test @@ -187,14 +187,14 @@ public class MediaOutputPreferenceControllerTest { mController.updateState(mPreference); - assertThat(mPreference.isEnabled()).isFalse(); + assertThat(mPreference.isVisible()).isFalse(); String defaultString = mContext.getString(R.string.media_output_default_summary); assertThat(mPreference.getSummary()).isEqualTo(defaultString); } /** * Media stream is captured by something else (cast device): - * Preference should be disabled + * Preference should be invisible * Preference summary should be "unavailable" */ @Test @@ -203,14 +203,14 @@ public class MediaOutputPreferenceControllerTest { mController.updateState(mPreference); - assertThat(mPreference.isEnabled()).isFalse(); + assertThat(mPreference.isVisible()).isFalse(); String defaultString = mContext.getString(R.string.media_output_summary_unavailable); assertThat(mPreference.getSummary()).isEqualTo(defaultString); } /** * One A2DP Bluetooth device is available and active. - * Preference should be enabled + * Preference should be visible * Preference summary should be activate device name */ @Test @@ -221,13 +221,13 @@ public class MediaOutputPreferenceControllerTest { mController.updateState(mPreference); - assertThat(mPreference.isEnabled()).isTrue(); + assertThat(mPreference.isVisible()).isTrue(); assertThat(mPreference.getSummary()).isEqualTo(mBluetoothDevice.getName()); } /** * More than one A2DP Bluetooth devices are available, and second device is active. - * Preference should be enabled + * Preference should be visible * Preference summary should be activate device name */ @Test @@ -247,13 +247,13 @@ public class MediaOutputPreferenceControllerTest { mController.updateState(mPreference); - assertThat(mPreference.isEnabled()).isTrue(); + assertThat(mPreference.isVisible()).isTrue(); assertThat(mPreference.getSummary()).isEqualTo(secondBluetoothDevice.getName()); } /** * A2DP Bluetooth device(s) are available, but wired headset is plugged in and activated - * Preference should be enabled + * Preference should be visible * Preference summary should be "This device" */ @Test @@ -266,7 +266,7 @@ public class MediaOutputPreferenceControllerTest { mController.updateState(mPreference); - assertThat(mPreference.isEnabled()).isTrue(); + assertThat(mPreference.isVisible()).isTrue(); String defaultString = mContext.getString(R.string.media_output_default_summary); assertThat(mPreference.getSummary()).isEqualTo(defaultString); } @@ -274,7 +274,7 @@ public class MediaOutputPreferenceControllerTest { /** * A2DP Bluetooth device(s) are available, but current device speaker is activated - * Preference should be enabled + * Preference should be visible * Preference summary should be "This device" */ @Test @@ -285,7 +285,7 @@ public class MediaOutputPreferenceControllerTest { mController.updateState(mPreference); - assertThat(mPreference.isEnabled()).isTrue(); + assertThat(mPreference.isVisible()).isTrue(); String defaultString = mContext.getString(R.string.media_output_default_summary); assertThat(mPreference.getSummary()).isEqualTo(defaultString); }