From a8bf29e2e7f661dfe57471364c20c7d23ddd1cb6 Mon Sep 17 00:00:00 2001 From: cnchen Date: Thu, 21 Mar 2019 18:58:17 +0800 Subject: [PATCH 01/20] Pass back number of fingerprint enrolled from settings to SUW Bug: 115251237 Test: RunSettingsRoboTests, manual test intent data has been received by SUW Change-Id: I951106163deb0cf0c0cf226cc629a9caddd55436 --- .../SetupFingerprintEnrollIntroduction.java | 33 +++++++++++++++++-- ...etupFingerprintEnrollIntroductionTest.java | 11 ++++--- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollIntroduction.java b/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollIntroduction.java index 7ccb47ce207..c720b5d3a2b 100644 --- a/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollIntroduction.java +++ b/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollIntroduction.java @@ -21,6 +21,7 @@ import android.app.KeyguardManager; import android.app.admin.DevicePolicyManager; import android.app.settings.SettingsEnums; import android.content.Intent; +import android.hardware.fingerprint.FingerprintManager; import android.os.Bundle; import android.os.UserHandle; import android.os.storage.StorageManager; @@ -30,6 +31,7 @@ import android.widget.TextView; import com.android.internal.widget.LockPatternUtils; import com.android.settings.R; import com.android.settings.SetupWizardUtils; +import com.android.settings.Utils; import com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment; import com.android.settings.password.SetupChooseLockGeneric; import com.android.settings.password.SetupSkipDialog; @@ -37,6 +39,11 @@ import com.android.settings.password.SetupSkipDialog; import com.google.android.setupcompat.template.FooterButton; public class SetupFingerprintEnrollIntroduction extends FingerprintEnrollIntroduction { + /** + * Returns the number of fingerprint enrolled. + */ + private static final String EXTRA_FINGERPRINT_ENROLLED_COUNT = "fingerprint_enrolled_count"; + private static final String KEY_LOCK_SCREEN_PRESENT = "wasLockScreenPresent"; private boolean mAlreadyHadLockScreenSetup = false; @@ -99,10 +106,17 @@ public class SetupFingerprintEnrollIntroduction extends FingerprintEnrollIntrodu protected void onActivityResult(int requestCode, int resultCode, Intent data) { // if lock was already present, do not return intent data since it must have been // reported in previous attempts - if (requestCode == BIOMETRIC_FIND_SENSOR_REQUEST && isKeyguardSecure() - && !mAlreadyHadLockScreenSetup) { - data = getMetricIntent(data); + if (requestCode == BIOMETRIC_FIND_SENSOR_REQUEST && isKeyguardSecure()) { + if(!mAlreadyHadLockScreenSetup) { + data = getMetricIntent(data); + } + + // Report fingerprint count if user adding a new fingerprint + if(resultCode == RESULT_FINISHED) { + data = setFingerprintCount(data); + } } + super.onActivityResult(requestCode, resultCode, data); } @@ -114,6 +128,19 @@ public class SetupFingerprintEnrollIntroduction extends FingerprintEnrollIntrodu data.putExtra(SetupChooseLockGeneric. SetupChooseLockGenericFragment.EXTRA_PASSWORD_QUALITY, lockPatternUtils.getKeyguardStoredPasswordQuality(UserHandle.myUserId())); + + return data; + } + + private Intent setFingerprintCount(Intent data) { + if (data == null) { + data = new Intent(); + } + final FingerprintManager fpm = Utils.getFingerprintManagerOrNull(this); + if (fpm != null) { + int enrolled = fpm.getEnrolledFingerprints(mUserId).size(); + data.putExtra(EXTRA_FINGERPRINT_ENROLLED_COUNT, enrolled); + } return data; } diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollIntroductionTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollIntroductionTest.java index c8177491745..3fa0ed44ade 100644 --- a/tests/robotests/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollIntroductionTest.java +++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollIntroductionTest.java @@ -172,8 +172,7 @@ public class SetupFingerprintEnrollIntroductionTest { layout.getMixin(FooterBarMixin.class).getSecondaryButtonView(); skipButton.performClick(); - ShadowActivity shadowActivity = Shadows.shadowOf(activity); - assertThat(shadowActivity.getResultIntent()).isNull(); + assertThat(Shadows.shadowOf(activity).getResultIntent()).isNull(); } @Test @@ -182,7 +181,10 @@ public class SetupFingerprintEnrollIntroductionTest { SetupFingerprintEnrollIntroduction activity = mController.create().resume().get(); activity.onActivityResult(BiometricEnrollIntroduction.BIOMETRIC_FIND_SENSOR_REQUEST, BiometricEnrollBase.RESULT_FINISHED, null); - assertThat(Shadows.shadowOf(activity).getResultIntent()).isNull(); + ShadowActivity shadowActivity = Shadows.shadowOf(activity); + assertThat(shadowActivity.getResultIntent()).isNotNull(); + assertThat(shadowActivity.getResultIntent().hasExtra( + SetupChooseLockGenericFragment.EXTRA_PASSWORD_QUALITY)).isFalse(); } @Test @@ -201,7 +203,8 @@ public class SetupFingerprintEnrollIntroductionTest { SetupFingerprintEnrollIntroduction activity = mController.create().resume().get(); activity.onActivityResult(BiometricEnrollIntroduction.BIOMETRIC_FIND_SENSOR_REQUEST, BiometricEnrollBase.RESULT_FINISHED, null); - assertThat(Shadows.shadowOf(activity).getResultIntent()).isNull(); + ShadowActivity shadowActivity = Shadows.shadowOf(activity); + assertThat(shadowActivity.getResultIntent()).isNull(); } @Test From a79ed2b1331bcd523a8e7a5026425814642d4269 Mon Sep 17 00:00:00 2001 From: Arc Wang Date: Mon, 1 Apr 2019 18:00:07 +0800 Subject: [PATCH 02/20] Update Wi-Fi QR code scan icon and share icon Replace with new material design version Bug: 128706512 Test: manual Change-Id: If7f474f91d36a9997464c8a68fc41b8d7ced0307 --- res/drawable/ic_qrcode_24dp.xml | 32 +------------------------------- res/drawable/ic_scan_24dp.xml | 26 +------------------------- 2 files changed, 2 insertions(+), 56 deletions(-) diff --git a/res/drawable/ic_qrcode_24dp.xml b/res/drawable/ic_qrcode_24dp.xml index 6928cb97105..57aec5776cf 100644 --- a/res/drawable/ic_qrcode_24dp.xml +++ b/res/drawable/ic_qrcode_24dp.xml @@ -6,35 +6,5 @@ android:tint="?android:attr/colorAccent"> - - - - - - - - - - + android:pathData="M3,9h6V3H3V9zM5,5h2v2H5V5zM15,3v6h6V3H15zM19,7h-2V5h2V7zM3,21h6v-6H3V21zM5,17h2v2H5V17zM13,15v2h-2v-2v-2v-2h2v2h2v-2h2v2v2H13zM17,19h4v2h-4h-2v-2v-2h2V19zM19,11h2v6h-2V11zM7,11h2v2H7V11zM11,19h2v2h-2V19zM5,13H3v-2h2V13zM13,9h-2V3h2V9z"/> diff --git a/res/drawable/ic_scan_24dp.xml b/res/drawable/ic_scan_24dp.xml index c7b82d1f7e2..692bfe8569a 100644 --- a/res/drawable/ic_scan_24dp.xml +++ b/res/drawable/ic_scan_24dp.xml @@ -6,29 +6,5 @@ android:tint="?android:attr/colorAccent"> - - - - - - - - + android:pathData="M3,9h6V3H3V9zM5,5h2v2H5V5zM15,3v6h6V3H15zM19,7h-2V5h2V7zM3,21h6v-6H3V21zM5,17h2v2H5V17zM17,15h4v2h-4v4h-2v-4h-4v-2h4v-4h2V15zM7,11h2v2H7V11zM5,13H3v-2h2V13zM13,9h-2V3h2V9z"/> From b1b07e2030a1a1010fbba70699c8d265a6af9fd6 Mon Sep 17 00:00:00 2001 From: Fan Zhang Date: Fri, 29 Mar 2019 15:43:46 -0700 Subject: [PATCH 03/20] Convert xml based API allowDynamicSummaryInSlice to java - Add boolean useDynamicSliceSummary() in Sliceable interface. This is the switch equivalent to android:allowDynamicSummaryInSlice in xml. It moves the setter closer to regular Sliceable APIs, thus less easily to miss. - Coverted all android:allowDynamicSummaryInSlice to use the java API. - Except 2 prefs in my_device_info. They incorrectly set this to true previously (controller is not sliceable, no point setting dynamicSliceSummary to true. They just won't do anything) Fixes: 128446156 Test: robolectric Change-Id: Ic57acd590dec3e87dcf4592df137321d14b854d9 --- res/values/attrs.xml | 2 - res/xml/firmware_version.xml | 2 - res/xml/hardware_info.xml | 3 -- res/xml/my_device_info.xml | 4 -- res/xml/sound_settings.xml | 5 -- .../core/PreferenceXmlParserUtils.java | 25 +-------- .../PhoneNumberPreferenceController.java | 5 ++ ...wareVersionDetailPreferenceController.java | 5 ++ ...SimpleBuildNumberPreferenceController.java | 5 ++ .../DeviceModelPreferenceController.java | 5 ++ .../HardwareRevisionPreferenceController.java | 5 ++ .../SerialNumberPreferenceController.java | 5 ++ .../imei/ImeiInfoPreferenceController.java | 5 ++ ...tVolumeRestrictedPreferenceController.java | 3 +- .../AlarmVolumePreferenceController.java | 8 ++- .../CallVolumePreferenceController.java | 5 ++ .../MediaVolumePreferenceController.java | 8 ++- .../RemoteVolumePreferenceController.java | 8 ++- .../RingVolumePreferenceController.java | 5 ++ .../SettingsSearchIndexablesProvider.java | 2 +- .../settings/slices/SliceBuilderUtils.java | 4 +- .../android/settings/slices/SliceData.java | 14 ----- .../settings/slices/SliceDataConverter.java | 5 -- .../android/settings/slices/Sliceable.java | 7 +++ .../slices/SlicesDatabaseAccessor.java | 4 -- .../settings/slices/SlicesDatabaseHelper.java | 10 +--- .../settings/slices/SlicesIndexer.java | 2 - .../res/xml-mcc998/location_settings.xml | 6 +-- .../res/xml-mcc999/location_settings.xml | 1 - .../core/BadPreferenceController.java | 5 ++ .../core/PreferenceXmlParserUtilsTest.java | 25 --------- .../slices/FakePreferenceController.java | 5 ++ .../slices/SliceBuilderUtilsTest.java | 54 +++++-------------- .../slices/SliceDataConverterTest.java | 1 - .../settings/slices/SliceDataTest.java | 31 +---------- .../slices/SlicesDatabaseAccessorTest.java | 36 ++----------- .../slices/SlicesDatabaseHelperTest.java | 1 - .../settings/slices/SlicesIndexerTest.java | 6 --- 38 files changed, 108 insertions(+), 224 deletions(-) diff --git a/res/values/attrs.xml b/res/values/attrs.xml index e099cf04ea5..a9797a3508c 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -72,8 +72,6 @@ - - diff --git a/res/xml/firmware_version.xml b/res/xml/firmware_version.xml index 75336ce86b0..f55ee11a1c0 100644 --- a/res/xml/firmware_version.xml +++ b/res/xml/firmware_version.xml @@ -28,7 +28,6 @@ android:title="@string/firmware_version" android:summary="@string/summary_placeholder" settings:enableCopying="true" - settings:allowDynamicSummaryInSlice="true" settings:controller="com.android.settings.deviceinfo.firmwareversion.FirmwareVersionDetailPreferenceController"/> @@ -68,7 +67,6 @@ android:title="@string/build_number" android:summary="@string/summary_placeholder" settings:enableCopying="true" - settings:allowDynamicSummaryInSlice="true" settings:controller="com.android.settings.deviceinfo.firmwareversion.SimpleBuildNumberPreferenceController"/> \ No newline at end of file diff --git a/res/xml/hardware_info.xml b/res/xml/hardware_info.xml index 2e35101aca6..2fd58ff9aea 100644 --- a/res/xml/hardware_info.xml +++ b/res/xml/hardware_info.xml @@ -27,7 +27,6 @@ android:key="hardware_info_device_model" android:title="@string/model_info" android:summary="@string/summary_placeholder" - settings:allowDynamicSummaryInSlice="true" settings:controller="com.android.settings.deviceinfo.hardwareinfo.DeviceModelPreferenceController" settings:enableCopying="true"/> @@ -36,7 +35,6 @@ android:key="hardware_info_device_serial" android:title="@string/status_serial_number" android:summary="@string/summary_placeholder" - settings:allowDynamicSummaryInSlice="true" settings:controller="com.android.settings.deviceinfo.hardwareinfo.SerialNumberPreferenceController" settings:enableCopying="true"/> @@ -45,7 +43,6 @@ android:key="hardware_info_device_revision" android:title="@string/hardware_revision" android:summary="@string/summary_placeholder" - settings:allowDynamicSummaryInSlice="true" settings:controller="com.android.settings.deviceinfo.hardwareinfo.HardwareRevisionPreferenceController" settings:enableCopying="true"/> diff --git a/res/xml/my_device_info.xml b/res/xml/my_device_info.xml index bc498d2205f..b2cc23621e9 100644 --- a/res/xml/my_device_info.xml +++ b/res/xml/my_device_info.xml @@ -52,7 +52,6 @@ android:title="@string/status_number" android:summary="@string/summary_placeholder" android:selectable="false" - settings:allowDynamicSummaryInSlice="true" settings:controller="com.android.settings.deviceinfo.PhoneNumberPreferenceController" settings:enableCopying="true"/> @@ -104,7 +103,6 @@ android:title="@string/hardware_info" settings:keywords="@string/keywords_model_and_hardware" android:summary="@string/summary_placeholder" - settings:allowDynamicSummaryInSlice="true" android:fragment="com.android.settings.deviceinfo.hardwareinfo.HardwareInfoFragment" settings:controller="com.android.settings.deviceinfo.HardwareInfoPreferenceController"/> @@ -115,7 +113,6 @@ android:title="@string/status_imei" settings:keywords="@string/keywords_imei_info" android:summary="@string/summary_placeholder" - settings:allowDynamicSummaryInSlice="true" settings:controller="com.android.settings.deviceinfo.imei.ImeiInfoPreferenceController"/> @@ -124,7 +121,6 @@ android:order="32" android:title="@string/firmware_version" android:summary="@string/summary_placeholder" - settings:allowDynamicSummaryInSlice="true" android:fragment="com.android.settings.deviceinfo.firmwareversion.FirmwareVersionSettings" settings:controller="com.android.settings.deviceinfo.firmwareversion.FirmwareVersionPreferenceController"/> diff --git a/res/xml/sound_settings.xml b/res/xml/sound_settings.xml index c3161d54938..90b7528c175 100644 --- a/res/xml/sound_settings.xml +++ b/res/xml/sound_settings.xml @@ -28,7 +28,6 @@ android:icon="@drawable/ic_volume_remote" android:title="@string/remote_media_volume_option_title" android:order="-185" - settings:allowDynamicSummaryInSlice="true" settings:controller="com.android.settings.notification.RemoteVolumePreferenceController"/> @@ -37,7 +36,6 @@ android:icon="@drawable/ic_media_stream" android:title="@string/media_volume_option_title" android:order="-180" - settings:allowDynamicSummaryInSlice="true" settings:controller="com.android.settings.notification.MediaVolumePreferenceController"/> @@ -54,7 +52,6 @@ android:icon="@drawable/ic_local_phone_24_lib" android:title="@string/call_volume_option_title" android:order="-170" - settings:allowDynamicSummaryInSlice="true" settings:controller="com.android.settings.notification.CallVolumePreferenceController"/> @@ -71,7 +68,6 @@ android:icon="@drawable/ic_notifications" android:title="@string/ring_volume_option_title" android:order="-160" - settings:allowDynamicSummaryInSlice="true" settings:controller="com.android.settings.notification.RingVolumePreferenceController"/> @@ -81,7 +77,6 @@ android:icon="@*android:drawable/ic_audio_alarm" android:title="@string/alarm_volume_option_title" android:order="-150" - settings:allowDynamicSummaryInSlice="true" settings:controller="com.android.settings.notification.AlarmVolumePreferenceController"/> diff --git a/src/com/android/settings/core/PreferenceXmlParserUtils.java b/src/com/android/settings/core/PreferenceXmlParserUtils.java index db6cd41f9bc..5eebee4ab77 100644 --- a/src/com/android/settings/core/PreferenceXmlParserUtils.java +++ b/src/com/android/settings/core/PreferenceXmlParserUtils.java @@ -72,7 +72,6 @@ public class PreferenceXmlParserUtils { MetadataFlag.FLAG_NEED_PREF_SUMMARY, MetadataFlag.FLAG_NEED_PREF_ICON, MetadataFlag.FLAG_NEED_SEARCHABLE, - MetadataFlag.FLAG_ALLOW_DYNAMIC_SUMMARY_IN_SLICE, MetadataFlag.FLAG_UNAVAILABLE_SLICE_SUBTITLE}) @Retention(RetentionPolicy.SOURCE) public @interface MetadataFlag { @@ -87,9 +86,8 @@ public class PreferenceXmlParserUtils { int FLAG_NEED_PLATFORM_SLICE_FLAG = 1 << 7; int FLAG_NEED_KEYWORDS = 1 << 8; int FLAG_NEED_SEARCHABLE = 1 << 9; - int FLAG_ALLOW_DYNAMIC_SUMMARY_IN_SLICE = 1 << 10; - int FLAG_NEED_PREF_APPEND = 1 << 11; - int FLAG_UNAVAILABLE_SLICE_SUBTITLE = 1 << 12; + int FLAG_NEED_PREF_APPEND = 1 << 10; + int FLAG_UNAVAILABLE_SLICE_SUBTITLE = 1 << 11; } public static final String METADATA_PREF_TYPE = "type"; @@ -101,8 +99,6 @@ public class PreferenceXmlParserUtils { public static final String METADATA_PLATFORM_SLICE_FLAG = "platform_slice"; public static final String METADATA_KEYWORDS = "keywords"; public static final String METADATA_SEARCHABLE = "searchable"; - public static final String METADATA_ALLOW_DYNAMIC_SUMMARY_IN_SLICE = - "allow_dynamic_summary_in_slice"; public static final String METADATA_APPEND = "staticPreferenceLocation"; public static final String METADATA_UNAVAILABLE_SLICE_SUBTITLE = "unavailable_slice_subtitle"; @@ -246,10 +242,6 @@ public class PreferenceXmlParserUtils { preferenceMetadata.putBoolean(METADATA_SEARCHABLE, isSearchable(preferenceAttributes)); } - if (hasFlag(flags, MetadataFlag.FLAG_ALLOW_DYNAMIC_SUMMARY_IN_SLICE)) { - preferenceMetadata.putBoolean(METADATA_ALLOW_DYNAMIC_SUMMARY_IN_SLICE, - isDynamicSummaryAllowed(preferenceAttributes)); - } if (hasFlag(flags, MetadataFlag.FLAG_NEED_PREF_APPEND) && hasPrefScreenFlag) { preferenceMetadata.putBoolean(METADATA_APPEND, isAppended(preferenceScreenAttributes)); @@ -267,14 +259,6 @@ public class PreferenceXmlParserUtils { return metadata; } - /** - * Returns the fragment name if this preference launches a child fragment. - */ - public static String getDataChildFragment(Context context, AttributeSet attrs) { - return getStringData(context, attrs, R.styleable.Preference, - R.styleable.Preference_android_fragment); - } - /** * Call {@link #extractMetadata(Context, int, int)} with a {@link MetadataFlag} instead. */ @@ -342,11 +326,6 @@ public class PreferenceXmlParserUtils { return styledAttributes.getBoolean(R.styleable.Preference_searchable, true /* default */); } - private static boolean isDynamicSummaryAllowed(TypedArray styledAttributes) { - return styledAttributes.getBoolean(R.styleable.Preference_allowDynamicSummaryInSlice, - false /* default */); - } - private static String getKeywords(TypedArray styledAttributes) { return styledAttributes.getString(R.styleable.Preference_keywords); } diff --git a/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java b/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java index 3767860add0..ddc3ad6643e 100644 --- a/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java +++ b/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java @@ -101,6 +101,11 @@ public class PhoneNumberPreferenceController extends BasePreferenceController { return true; } + @Override + public boolean useDynamicSliceSummary() { + return true; + } + @Override public void copy() { final ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService( diff --git a/src/com/android/settings/deviceinfo/firmwareversion/FirmwareVersionDetailPreferenceController.java b/src/com/android/settings/deviceinfo/firmwareversion/FirmwareVersionDetailPreferenceController.java index 9f3d6e5ed3b..daa10d26965 100644 --- a/src/com/android/settings/deviceinfo/firmwareversion/FirmwareVersionDetailPreferenceController.java +++ b/src/com/android/settings/deviceinfo/firmwareversion/FirmwareVersionDetailPreferenceController.java @@ -58,6 +58,11 @@ public class FirmwareVersionDetailPreferenceController extends BasePreferenceCon return AVAILABLE; } + @Override + public boolean useDynamicSliceSummary() { + return true; + } + @Override public boolean isSliceable() { return true; diff --git a/src/com/android/settings/deviceinfo/firmwareversion/SimpleBuildNumberPreferenceController.java b/src/com/android/settings/deviceinfo/firmwareversion/SimpleBuildNumberPreferenceController.java index 36f1a43f220..c568f073c7e 100644 --- a/src/com/android/settings/deviceinfo/firmwareversion/SimpleBuildNumberPreferenceController.java +++ b/src/com/android/settings/deviceinfo/firmwareversion/SimpleBuildNumberPreferenceController.java @@ -55,6 +55,11 @@ public class SimpleBuildNumberPreferenceController extends BasePreferenceControl return true; } + @Override + public boolean useDynamicSliceSummary() { + return true; + } + @Override public void copy() { final ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService( diff --git a/src/com/android/settings/deviceinfo/hardwareinfo/DeviceModelPreferenceController.java b/src/com/android/settings/deviceinfo/hardwareinfo/DeviceModelPreferenceController.java index fbd1e9e2515..93dd826dbc7 100644 --- a/src/com/android/settings/deviceinfo/hardwareinfo/DeviceModelPreferenceController.java +++ b/src/com/android/settings/deviceinfo/hardwareinfo/DeviceModelPreferenceController.java @@ -44,4 +44,9 @@ public class DeviceModelPreferenceController extends HardwareInfoPreferenceContr public CharSequence getSummary() { return HardwareInfoPreferenceController.getDeviceModel(); } + + @Override + public boolean useDynamicSliceSummary() { + return true; + } } diff --git a/src/com/android/settings/deviceinfo/hardwareinfo/HardwareRevisionPreferenceController.java b/src/com/android/settings/deviceinfo/hardwareinfo/HardwareRevisionPreferenceController.java index ec0cdb2a362..f88239061bf 100644 --- a/src/com/android/settings/deviceinfo/hardwareinfo/HardwareRevisionPreferenceController.java +++ b/src/com/android/settings/deviceinfo/hardwareinfo/HardwareRevisionPreferenceController.java @@ -34,6 +34,11 @@ public class HardwareRevisionPreferenceController extends BasePreferenceControll ? AVAILABLE : UNSUPPORTED_ON_DEVICE; } + @Override + public boolean useDynamicSliceSummary() { + return true; + } + @Override public boolean isSliceable() { return true; diff --git a/src/com/android/settings/deviceinfo/hardwareinfo/SerialNumberPreferenceController.java b/src/com/android/settings/deviceinfo/hardwareinfo/SerialNumberPreferenceController.java index 01cd5f3b9e4..7ef1313ef41 100644 --- a/src/com/android/settings/deviceinfo/hardwareinfo/SerialNumberPreferenceController.java +++ b/src/com/android/settings/deviceinfo/hardwareinfo/SerialNumberPreferenceController.java @@ -45,6 +45,11 @@ public class SerialNumberPreferenceController extends BasePreferenceController { return true; } + @Override + public boolean useDynamicSliceSummary() { + return true; + } + @Override public void copy() { Sliceable.setCopyContent(mContext, getSummary(), diff --git a/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceController.java b/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceController.java index 77d975ed1eb..68c95883419 100644 --- a/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceController.java +++ b/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceController.java @@ -110,6 +110,11 @@ public class ImeiInfoPreferenceController extends BasePreferenceController { return true; } + @Override + public boolean useDynamicSliceSummary() { + return true; + } + @Override public void copy() { Sliceable.setCopyContent(mContext, getSummary(), mContext.getText(R.string.status_imei)); diff --git a/src/com/android/settings/notification/AdjustVolumeRestrictedPreferenceController.java b/src/com/android/settings/notification/AdjustVolumeRestrictedPreferenceController.java index df2cd450605..bed25cde005 100644 --- a/src/com/android/settings/notification/AdjustVolumeRestrictedPreferenceController.java +++ b/src/com/android/settings/notification/AdjustVolumeRestrictedPreferenceController.java @@ -26,7 +26,6 @@ import androidx.annotation.VisibleForTesting; import androidx.preference.Preference; import com.android.settings.accounts.AccountRestrictionHelper; -import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.core.SliderPreferenceController; import com.android.settingslib.RestrictedPreference; @@ -35,7 +34,7 @@ import com.android.settingslib.RestrictedPreference; * restriction */ public abstract class AdjustVolumeRestrictedPreferenceController extends - SliderPreferenceController implements PreferenceControllerMixin { + SliderPreferenceController { private AccountRestrictionHelper mHelper; diff --git a/src/com/android/settings/notification/AlarmVolumePreferenceController.java b/src/com/android/settings/notification/AlarmVolumePreferenceController.java index 92a1e907766..d6a4110dcdd 100644 --- a/src/com/android/settings/notification/AlarmVolumePreferenceController.java +++ b/src/com/android/settings/notification/AlarmVolumePreferenceController.java @@ -22,8 +22,7 @@ import android.text.TextUtils; import com.android.settings.R; -public class AlarmVolumePreferenceController extends - VolumeSeekBarPreferenceController { +public class AlarmVolumePreferenceController extends VolumeSeekBarPreferenceController { private static final String KEY_ALARM_VOLUME = "alarm_volume"; @@ -42,6 +41,11 @@ public class AlarmVolumePreferenceController extends return TextUtils.equals(getPreferenceKey(), "alarm_volume"); } + @Override + public boolean useDynamicSliceSummary() { + return true; + } + @Override public String getPreferenceKey() { return KEY_ALARM_VOLUME; diff --git a/src/com/android/settings/notification/CallVolumePreferenceController.java b/src/com/android/settings/notification/CallVolumePreferenceController.java index a3eb87f8981..ded57b326b3 100644 --- a/src/com/android/settings/notification/CallVolumePreferenceController.java +++ b/src/com/android/settings/notification/CallVolumePreferenceController.java @@ -43,6 +43,11 @@ public class CallVolumePreferenceController extends VolumeSeekBarPreferenceContr return TextUtils.equals(getPreferenceKey(), "call_volume"); } + @Override + public boolean useDynamicSliceSummary() { + return true; + } + @Override public int getAudioStream() { if (mAudioManager.isBluetoothScoOn()) { diff --git a/src/com/android/settings/notification/MediaVolumePreferenceController.java b/src/com/android/settings/notification/MediaVolumePreferenceController.java index 74ce7695f35..ae3146cbe5a 100644 --- a/src/com/android/settings/notification/MediaVolumePreferenceController.java +++ b/src/com/android/settings/notification/MediaVolumePreferenceController.java @@ -22,8 +22,7 @@ import android.text.TextUtils; import com.android.settings.R; -public class MediaVolumePreferenceController extends - VolumeSeekBarPreferenceController { +public class MediaVolumePreferenceController extends VolumeSeekBarPreferenceController { private static final String KEY_MEDIA_VOLUME = "media_volume"; @@ -43,6 +42,11 @@ public class MediaVolumePreferenceController extends return TextUtils.equals(getPreferenceKey(), KEY_MEDIA_VOLUME); } + @Override + public boolean useDynamicSliceSummary() { + return true; + } + @Override public String getPreferenceKey() { return KEY_MEDIA_VOLUME; diff --git a/src/com/android/settings/notification/RemoteVolumePreferenceController.java b/src/com/android/settings/notification/RemoteVolumePreferenceController.java index 37a493e3954..b4554651cac 100644 --- a/src/com/android/settings/notification/RemoteVolumePreferenceController.java +++ b/src/com/android/settings/notification/RemoteVolumePreferenceController.java @@ -37,8 +37,7 @@ import java.io.IOException; import java.util.List; import java.util.Objects; -public class RemoteVolumePreferenceController extends - VolumeSeekBarPreferenceController { +public class RemoteVolumePreferenceController extends VolumeSeekBarPreferenceController { private static final String KEY_REMOTE_VOLUME = "remote_volume"; @VisibleForTesting @@ -167,6 +166,11 @@ public class RemoteVolumePreferenceController extends return TextUtils.equals(getPreferenceKey(), KEY_REMOTE_VOLUME); } + @Override + public boolean useDynamicSliceSummary() { + return true; + } + @Override public String getPreferenceKey() { return KEY_REMOTE_VOLUME; diff --git a/src/com/android/settings/notification/RingVolumePreferenceController.java b/src/com/android/settings/notification/RingVolumePreferenceController.java index 75ad4a701df..08efc931a0c 100644 --- a/src/com/android/settings/notification/RingVolumePreferenceController.java +++ b/src/com/android/settings/notification/RingVolumePreferenceController.java @@ -95,6 +95,11 @@ public class RingVolumePreferenceController extends VolumeSeekBarPreferenceContr return TextUtils.equals(getPreferenceKey(), KEY_RING_VOLUME); } + @Override + public boolean useDynamicSliceSummary() { + return true; + } + @Override public int getAudioStream() { return AudioManager.STREAM_RING; diff --git a/src/com/android/settings/search/SettingsSearchIndexablesProvider.java b/src/com/android/settings/search/SettingsSearchIndexablesProvider.java index 0a846de317f..d3c4b5aacdd 100644 --- a/src/com/android/settings/search/SettingsSearchIndexablesProvider.java +++ b/src/com/android/settings/search/SettingsSearchIndexablesProvider.java @@ -207,7 +207,7 @@ public class SettingsSearchIndexablesProvider extends SearchIndexablesProvider { if (System.getProperty(SYSPROP_CRASH_ON_ERROR) != null) { throw new RuntimeException(e); } - Log.e(TAG, "Error trying to get non-indexable keys from: " + clazz.getName() , e); + Log.e(TAG, "Error trying to get non-indexable keys from: " + clazz.getName(), e); continue; } diff --git a/src/com/android/settings/slices/SliceBuilderUtils.java b/src/com/android/settings/slices/SliceBuilderUtils.java index c3869a6d5d6..00a82d231fa 100644 --- a/src/com/android/settings/slices/SliceBuilderUtils.java +++ b/src/com/android/settings/slices/SliceBuilderUtils.java @@ -188,8 +188,8 @@ public class SliceBuilderUtils { * @return the summary text for a {@link Slice} built for {@param sliceData}. */ public static CharSequence getSubtitleText(Context context, - AbstractPreferenceController controller, SliceData sliceData) { - final boolean isDynamicSummaryAllowed = sliceData.isDynamicSummaryAllowed(); + BasePreferenceController controller, SliceData sliceData) { + final boolean isDynamicSummaryAllowed = controller.useDynamicSliceSummary(); CharSequence summaryText = controller.getSummary(); // Priority 1 : User prefers showing the dynamic summary in slice view rather than static diff --git a/src/com/android/settings/slices/SliceData.java b/src/com/android/settings/slices/SliceData.java index 9d52d56a8ae..f8185390af0 100644 --- a/src/com/android/settings/slices/SliceData.java +++ b/src/com/android/settings/slices/SliceData.java @@ -73,8 +73,6 @@ public class SliceData { private final boolean mIsPlatformDefined; - private final boolean mIsDynamicSummaryAllowed; - private final String mUnavailableSliceSubtitle; public String getKey() { @@ -121,10 +119,6 @@ public class SliceData { return mIsPlatformDefined; } - public boolean isDynamicSummaryAllowed() { - return mIsDynamicSummaryAllowed; - } - public String getUnavailableSliceSubtitle() { return mUnavailableSliceSubtitle; } @@ -141,7 +135,6 @@ public class SliceData { mPreferenceController = builder.mPrefControllerClassName; mSliceType = builder.mSliceType; mIsPlatformDefined = builder.mIsPlatformDefined; - mIsDynamicSummaryAllowed = builder.mIsDynamicSummaryAllowed; mUnavailableSliceSubtitle = builder.mUnavailableSliceSubtitle; } @@ -182,8 +175,6 @@ public class SliceData { private boolean mIsPlatformDefined; - private boolean mIsDynamicSummaryAllowed; - private String mUnavailableSliceSubtitle; public Builder setKey(String key) { @@ -241,11 +232,6 @@ public class SliceData { return this; } - public Builder setDynamicSummaryAllowed(boolean isDynamicSummaryAllowed) { - mIsDynamicSummaryAllowed = isDynamicSummaryAllowed; - return this; - } - public Builder setUnavailableSliceSubtitle( String unavailableSliceSubtitle) { mUnavailableSliceSubtitle = unavailableSliceSubtitle; diff --git a/src/com/android/settings/slices/SliceDataConverter.java b/src/com/android/settings/slices/SliceDataConverter.java index 69492734908..db46c26d627 100644 --- a/src/com/android/settings/slices/SliceDataConverter.java +++ b/src/com/android/settings/slices/SliceDataConverter.java @@ -16,7 +16,6 @@ package com.android.settings.slices; -import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_ALLOW_DYNAMIC_SUMMARY_IN_SLICE; import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_CONTROLLER; import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_ICON; import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_KEY; @@ -189,7 +188,6 @@ class SliceDataConverter { | MetadataFlag.FLAG_NEED_PREF_ICON | MetadataFlag.FLAG_NEED_PREF_SUMMARY | MetadataFlag.FLAG_NEED_PLATFORM_SLICE_FLAG - | MetadataFlag.FLAG_ALLOW_DYNAMIC_SUMMARY_IN_SLICE | MetadataFlag.FLAG_UNAVAILABLE_SLICE_SUBTITLE); for (Bundle bundle : metadata) { @@ -207,8 +205,6 @@ class SliceDataConverter { final int sliceType = SliceBuilderUtils.getSliceType(mContext, controllerClassName, key); final boolean isPlatformSlice = bundle.getBoolean(METADATA_PLATFORM_SLICE_FLAG); - final boolean isDynamicSummaryAllowed = bundle.getBoolean( - METADATA_ALLOW_DYNAMIC_SUMMARY_IN_SLICE); final String unavailableSliceSubtitle = bundle.getString( METADATA_UNAVAILABLE_SLICE_SUBTITLE); @@ -222,7 +218,6 @@ class SliceDataConverter { .setFragmentName(fragmentName) .setSliceType(sliceType) .setPlatformDefined(isPlatformSlice) - .setDynamicSummaryAllowed(isDynamicSummaryAllowed) .setUnavailableSliceSubtitle(unavailableSliceSubtitle) .build(); diff --git a/src/com/android/settings/slices/Sliceable.java b/src/com/android/settings/slices/Sliceable.java index c1661f8392a..04a3b503637 100644 --- a/src/com/android/settings/slices/Sliceable.java +++ b/src/com/android/settings/slices/Sliceable.java @@ -78,6 +78,13 @@ public interface Sliceable { return false; } + /** + * Whether or not summary comes from something dynamic (ie, not hardcoded in xml) + */ + default boolean useDynamicSliceSummary() { + return false; + } + /** * Set the copy content to the clipboard and show the toast. */ diff --git a/src/com/android/settings/slices/SlicesDatabaseAccessor.java b/src/com/android/settings/slices/SlicesDatabaseAccessor.java index fcc42e47500..2553a217712 100644 --- a/src/com/android/settings/slices/SlicesDatabaseAccessor.java +++ b/src/com/android/settings/slices/SlicesDatabaseAccessor.java @@ -49,7 +49,6 @@ public class SlicesDatabaseAccessor { IndexColumns.CONTROLLER, IndexColumns.PLATFORM_SLICE, IndexColumns.SLICE_TYPE, - IndexColumns.ALLOW_DYNAMIC_SUMMARY_IN_SLICE, IndexColumns.UNAVAILABLE_SLICE_SUBTITLE, }; @@ -166,8 +165,6 @@ public class SlicesDatabaseAccessor { cursor.getColumnIndex(IndexColumns.CONTROLLER)); final boolean isPlatformDefined = cursor.getInt( cursor.getColumnIndex(IndexColumns.PLATFORM_SLICE)) == TRUE; - final boolean isDynamicSummaryAllowed = cursor.getInt( - cursor.getColumnIndex(IndexColumns.ALLOW_DYNAMIC_SUMMARY_IN_SLICE)) == TRUE; int sliceType = cursor.getInt( cursor.getColumnIndex(IndexColumns.SLICE_TYPE)); final String unavailableSliceSubtitle = cursor.getString( @@ -189,7 +186,6 @@ public class SlicesDatabaseAccessor { .setUri(uri) .setPlatformDefined(isPlatformDefined) .setSliceType(sliceType) - .setDynamicSummaryAllowed(isDynamicSummaryAllowed) .setUnavailableSliceSubtitle(unavailableSliceSubtitle) .build(); } diff --git a/src/com/android/settings/slices/SlicesDatabaseHelper.java b/src/com/android/settings/slices/SlicesDatabaseHelper.java index 8dc86fb7996..1f9b05e9333 100644 --- a/src/com/android/settings/slices/SlicesDatabaseHelper.java +++ b/src/com/android/settings/slices/SlicesDatabaseHelper.java @@ -36,7 +36,7 @@ public class SlicesDatabaseHelper extends SQLiteOpenHelper { private static final String DATABASE_NAME = "slices_index.db"; private static final String SHARED_PREFS_TAG = "slices_shared_prefs"; - private static final int DATABASE_VERSION = 4; + private static final int DATABASE_VERSION = 5; public interface Tables { String TABLE_SLICES_INDEX = "slices_index"; @@ -94,12 +94,6 @@ public class SlicesDatabaseHelper extends SQLiteOpenHelper { */ String SLICE_TYPE = "slice_type"; - /** - * Boolean flag, {@code true} when the slice object prefers using the dynamic summary from - * preference controller. - */ - String ALLOW_DYNAMIC_SUMMARY_IN_SLICE = "allow_dynamic_summary_in_slice"; - /** * Customized subtitle if it's a unavailable slice */ @@ -129,8 +123,6 @@ public class SlicesDatabaseHelper extends SQLiteOpenHelper { ", " + IndexColumns.SLICE_TYPE + ", " + - IndexColumns.ALLOW_DYNAMIC_SUMMARY_IN_SLICE + - ", " + IndexColumns.UNAVAILABLE_SLICE_SUBTITLE + ");"; diff --git a/src/com/android/settings/slices/SlicesIndexer.java b/src/com/android/settings/slices/SlicesIndexer.java index 5f800471ba3..495eb0000b8 100644 --- a/src/com/android/settings/slices/SlicesIndexer.java +++ b/src/com/android/settings/slices/SlicesIndexer.java @@ -110,8 +110,6 @@ class SlicesIndexer implements Runnable { values.put(IndexColumns.CONTROLLER, dataRow.getPreferenceController()); values.put(IndexColumns.PLATFORM_SLICE, dataRow.isPlatformDefined()); values.put(IndexColumns.SLICE_TYPE, dataRow.getSliceType()); - values.put(IndexColumns.ALLOW_DYNAMIC_SUMMARY_IN_SLICE, - dataRow.isDynamicSummaryAllowed()); values.put(IndexColumns.UNAVAILABLE_SLICE_SUBTITLE, dataRow.getUnavailableSliceSubtitle()); diff --git a/tests/robotests/res/xml-mcc998/location_settings.xml b/tests/robotests/res/xml-mcc998/location_settings.xml index 16f0d82e1d4..f61ca63d68a 100644 --- a/tests/robotests/res/xml-mcc998/location_settings.xml +++ b/tests/robotests/res/xml-mcc998/location_settings.xml @@ -25,15 +25,13 @@ android:title="title" android:icon="@drawable/ic_android" android:summary="summary1" - settings:controller="com.android.settings.core.BadPreferenceController" - settings:allowDynamicSummaryInSlice="true"/> + settings:controller="com.android.settings.core.BadPreferenceController"/> + settings:controller="com.android.settings.slices.FakePreferenceController"/> \ No newline at end of file diff --git a/tests/robotests/res/xml-mcc999/location_settings.xml b/tests/robotests/res/xml-mcc999/location_settings.xml index a25f36d0437..4e5733fd38f 100644 --- a/tests/robotests/res/xml-mcc999/location_settings.xml +++ b/tests/robotests/res/xml-mcc999/location_settings.xml @@ -27,7 +27,6 @@ settings:controller="com.android.settings.slices.FakePreferenceController" settings:keywords="a, b, c" settings:platform_slice="true" - settings:allowDynamicSummaryInSlice="true" settings:unavailableSliceSubtitle="subtitleOfUnavailableSlice"/> \ No newline at end of file diff --git a/tests/robotests/src/com/android/settings/core/BadPreferenceController.java b/tests/robotests/src/com/android/settings/core/BadPreferenceController.java index e6367233499..32677cdb639 100644 --- a/tests/robotests/src/com/android/settings/core/BadPreferenceController.java +++ b/tests/robotests/src/com/android/settings/core/BadPreferenceController.java @@ -29,4 +29,9 @@ public class BadPreferenceController extends BasePreferenceController { public int getAvailabilityStatus() { return AVAILABLE; } + + @Override + public boolean useDynamicSliceSummary() { + return true; + } } diff --git a/tests/robotests/src/com/android/settings/core/PreferenceXmlParserUtilsTest.java b/tests/robotests/src/com/android/settings/core/PreferenceXmlParserUtilsTest.java index b8051a19e2d..9ad6a7b9af0 100644 --- a/tests/robotests/src/com/android/settings/core/PreferenceXmlParserUtilsTest.java +++ b/tests/robotests/src/com/android/settings/core/PreferenceXmlParserUtilsTest.java @@ -16,7 +16,6 @@ package com.android.settings.core; -import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_ALLOW_DYNAMIC_SUMMARY_IN_SLICE; import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_APPEND; import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_KEY; import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_KEYWORDS; @@ -293,30 +292,6 @@ public class PreferenceXmlParserUtilsTest { assertThat(foundKey).isTrue(); } - @Test - @Config(qualifiers = "mcc999") - public void extractMetadata_requestIsDynamicSummaryAllowed_shouldDefaultToFalse() - throws Exception { - final List metadata = PreferenceXmlParserUtils.extractMetadata(mContext, - R.xml.display_settings, MetadataFlag.FLAG_ALLOW_DYNAMIC_SUMMARY_IN_SLICE); - - for (Bundle bundle : metadata) { - assertThat(bundle.getBoolean(METADATA_ALLOW_DYNAMIC_SUMMARY_IN_SLICE)).isFalse(); - } - } - - @Test - @Config(qualifiers = "mcc998") - public void extractMetadata_requestIsDynamicSummaryAllowed_shouldReturnAttributeValue() - throws Exception { - final List metadata = PreferenceXmlParserUtils.extractMetadata(mContext, - R.xml.location_settings, MetadataFlag.FLAG_ALLOW_DYNAMIC_SUMMARY_IN_SLICE); - - for (Bundle bundle : metadata) { - assertThat(bundle.getBoolean(METADATA_ALLOW_DYNAMIC_SUMMARY_IN_SLICE)).isTrue(); - } - } - @Test @Config(qualifiers = "mcc999") public void extractMetadata_requestAppendProperty_shouldDefaultToFalse() diff --git a/tests/robotests/src/com/android/settings/slices/FakePreferenceController.java b/tests/robotests/src/com/android/settings/slices/FakePreferenceController.java index d0e33f0ec2b..3e4da200a26 100644 --- a/tests/robotests/src/com/android/settings/slices/FakePreferenceController.java +++ b/tests/robotests/src/com/android/settings/slices/FakePreferenceController.java @@ -40,4 +40,9 @@ public class FakePreferenceController extends BasePreferenceController { public boolean isSliceable() { return true; } + + @Override + public boolean useDynamicSliceSummary() { + return true; + } } diff --git a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java index 0a42f42b608..2e47930b73c 100644 --- a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java +++ b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java @@ -69,7 +69,6 @@ public class SliceBuilderUtilsTest { private final Class SLIDER_CONTROLLER = FakeSliderController.class; private final Class COPYABLE_CONTROLLER = FakeCopyableController.class; private final Class CONTEXT_CONTROLLER = FakeContextOnlyPreferenceController.class; - private final boolean IS_DYNAMIC_SUMMARY_ALLOWED = false; private final String INTENT_PATH = SettingsSlicesContract.PATH_SETTING_INTENT + "/" + KEY; private final String ACTION_PATH = SettingsSlicesContract.PATH_SETTING_ACTION + "/" + KEY; @@ -206,7 +205,7 @@ public class SliceBuilderUtilsTest { @Test public void getDynamicSummary_allowDynamicSummary_returnsControllerSummary() { - final SliceData data = getDummyData(true /*isDynamicSummaryAllowed*/); + final SliceData data = getDummyData(); final FakePreferenceController controller = spy( new FakePreferenceController(mContext, KEY)); final String controllerSummary = "new_Summary"; @@ -219,27 +218,17 @@ public class SliceBuilderUtilsTest { @Test public void getDynamicSummary_allowDynamicSummary_nullSummary_returnsNull() { - final SliceData data = getDummyData(true /*isDynamicSummaryAllowed*/); + final SliceData data = getDummyData(); final FakePreferenceController controller = spy( new FakePreferenceController(mContext, KEY)); - final String controllerSummary = null; - doReturn(controllerSummary).when(controller).getSummary(); + + doReturn(null).when(controller).getSummary(); final CharSequence summary = SliceBuilderUtils.getSubtitleText(mContext, controller, data); assertThat(summary).isNull(); } - @Test - public void getDynamicSummary_returnsScreenTitle() { - final SliceData data = getDummyData(); - final FakePreferenceController controller = new FakePreferenceController(mContext, KEY); - - final CharSequence summary = SliceBuilderUtils.getSubtitleText(mContext, controller, data); - - assertThat(summary).isEqualTo(data.getScreenTitle()); - } - @Test public void getDynamicSummary_noScreenTitle_returnsPrefControllerSummary() { final SliceData data = getDummyData("", ""); @@ -272,17 +261,7 @@ public class SliceBuilderUtilsTest { final FakePreferenceController controller = new FakePreferenceController(mContext, KEY); final CharSequence summary = SliceBuilderUtils.getSubtitleText(mContext, controller, data); - assertThat(summary).isEqualTo(""); - } - - @Test - public void - getDynamicSummary_emptyScreenTitle_placeHolderControllerSummary_returnsEmptyString() { - final SliceData data = getDummyData(mContext.getString(R.string.summary_placeholder), null); - final FakePreferenceController controller = new FakePreferenceController(mContext, KEY); - final CharSequence summary = SliceBuilderUtils.getSubtitleText(mContext, controller, data); - - assertThat(summary).isEqualTo(""); + assertThat(summary).isNull(); } @Test @@ -295,7 +274,7 @@ public class SliceBuilderUtilsTest { CharSequence summary = SliceBuilderUtils.getSubtitleText(mContext, controller, data); - assertThat(summary).isEqualTo(""); + assertThat(summary).isEqualTo(summaryPlaceholder); } @Test @@ -449,7 +428,7 @@ public class SliceBuilderUtilsTest { R.drawable.ic_settings_accent).toIcon().getResId(); final SliceData data = getDummyData(FakeUnavailablePreferenceController.class, SUMMARY, SliceData.SliceType.SWITCH, SCREEN_TITLE, 0 /* icon */, - IS_DYNAMIC_SUMMARY_ALLOWED, null /* unavailableSliceSubtitle */); + null /* unavailableSliceSubtitle */); Settings.Global.putInt(mContext.getContentResolver(), FakeUnavailablePreferenceController.AVAILABILITY_KEY, BasePreferenceController.DISABLED_DEPENDENT_SETTING); @@ -523,7 +502,7 @@ public class SliceBuilderUtilsTest { final String subtitleOfUnavailableSlice = "subtitleOfUnavailableSlice"; final SliceData data = getDummyData(FakeUnavailablePreferenceController.class, SUMMARY, SliceData.SliceType.SWITCH, SCREEN_TITLE, 0 /* icon */, - IS_DYNAMIC_SUMMARY_ALLOWED, subtitleOfUnavailableSlice); + subtitleOfUnavailableSlice); Settings.Global.putInt(mContext.getContentResolver(), FakeUnavailablePreferenceController.AVAILABILITY_KEY, BasePreferenceController.DISABLED_DEPENDENT_SETTING); @@ -551,32 +530,26 @@ public class SliceBuilderUtilsTest { private SliceData getDummyData() { return getDummyData(TOGGLE_CONTROLLER, SUMMARY, SliceData.SliceType.SWITCH, SCREEN_TITLE, - ICON, IS_DYNAMIC_SUMMARY_ALLOWED, null /* unavailableSliceSubtitle */); - } - - private SliceData getDummyData(boolean isDynamicSummaryAllowed) { - return getDummyData(TOGGLE_CONTROLLER, SUMMARY, SliceData.SliceType.SWITCH, SCREEN_TITLE, - ICON, isDynamicSummaryAllowed, null /* unavailableSliceSubtitle */); + ICON, null /* unavailableSliceSubtitle */); } private SliceData getDummyData(Class prefController, int sliceType, int icon) { return getDummyData(prefController, SUMMARY, sliceType, SCREEN_TITLE, - icon, IS_DYNAMIC_SUMMARY_ALLOWED, null /* unavailableSliceSubtitle */); + icon, null /* unavailableSliceSubtitle */); } private SliceData getDummyData(String summary, String screenTitle) { return getDummyData(TOGGLE_CONTROLLER, summary, SliceData.SliceType.SWITCH, screenTitle, - ICON, IS_DYNAMIC_SUMMARY_ALLOWED, null /* unavailableSliceSubtitle */); + ICON, null /* unavailableSliceSubtitle */); } private SliceData getDummyData(Class prefController, int sliceType) { return getDummyData(prefController, SUMMARY, sliceType, SCREEN_TITLE, ICON, - IS_DYNAMIC_SUMMARY_ALLOWED, null /* unavailableSliceSubtitle */); + null /* unavailableSliceSubtitle */); } private SliceData getDummyData(Class prefController, String summary, int sliceType, - String screenTitle, int icon, boolean isDynamicSummaryAllowed, - String unavailableSliceSubtitle) { + String screenTitle, int icon, String unavailableSliceSubtitle) { return new SliceData.Builder() .setKey(KEY) .setTitle(TITLE) @@ -588,7 +561,6 @@ public class SliceBuilderUtilsTest { .setUri(URI) .setPreferenceControllerClassName(prefController.getName()) .setSliceType(sliceType) - .setDynamicSummaryAllowed(isDynamicSummaryAllowed) .setUnavailableSliceSubtitle(unavailableSliceSubtitle) .build(); } diff --git a/tests/robotests/src/com/android/settings/slices/SliceDataConverterTest.java b/tests/robotests/src/com/android/settings/slices/SliceDataConverterTest.java index 7c1319c0bb0..ea7bac5cd8b 100644 --- a/tests/robotests/src/com/android/settings/slices/SliceDataConverterTest.java +++ b/tests/robotests/src/com/android/settings/slices/SliceDataConverterTest.java @@ -124,7 +124,6 @@ public class SliceDataConverterTest { assertThat(fakeSlice.getPreferenceController()).isEqualTo(FAKE_CONTROLLER_NAME); assertThat(fakeSlice.getSliceType()).isEqualTo(SliceData.SliceType.SLIDER); assertThat(fakeSlice.isPlatformDefined()).isTrue(); // from XML - assertThat(fakeSlice.isDynamicSummaryAllowed()).isTrue(); // from XML assertThat(fakeSlice.getUnavailableSliceSubtitle()).isEqualTo( "subtitleOfUnavailableSlice"); // from XML } diff --git a/tests/robotests/src/com/android/settings/slices/SliceDataTest.java b/tests/robotests/src/com/android/settings/slices/SliceDataTest.java index b6c7af5499a..6775e059d74 100644 --- a/tests/robotests/src/com/android/settings/slices/SliceDataTest.java +++ b/tests/robotests/src/com/android/settings/slices/SliceDataTest.java @@ -38,7 +38,6 @@ public class SliceDataTest { private final String PREF_CONTROLLER = "com.android.settings.slices.tester"; private final int SLICE_TYPE = SliceData.SliceType.SWITCH; private final boolean IS_PLATFORM_DEFINED = true; - private final boolean IS_DYNAMIC_SUMMARY_ALLOWED = true; private final String UNAVAILABLE_SLICE_SUBTITLE = "subtitleOfUnavailableSlice"; @Test @@ -55,7 +54,6 @@ public class SliceDataTest { .setPreferenceControllerClassName(PREF_CONTROLLER) .setSliceType(SLICE_TYPE) .setPlatformDefined(IS_PLATFORM_DEFINED) - .setDynamicSummaryAllowed(IS_DYNAMIC_SUMMARY_ALLOWED) .setUnavailableSliceSubtitle(UNAVAILABLE_SLICE_SUBTITLE); SliceData data = builder.build(); @@ -71,7 +69,6 @@ public class SliceDataTest { assertThat(data.getPreferenceController()).isEqualTo(PREF_CONTROLLER); assertThat(data.getSliceType()).isEqualTo(SLICE_TYPE); assertThat(data.isPlatformDefined()).isEqualTo(IS_PLATFORM_DEFINED); - assertThat(data.isDynamicSummaryAllowed()).isEqualTo(IS_DYNAMIC_SUMMARY_ALLOWED); assertThat(data.getUnavailableSliceSubtitle()).isEqualTo(UNAVAILABLE_SLICE_SUBTITLE); } @@ -220,31 +217,6 @@ public class SliceDataTest { assertThat(data.getPreferenceController()).isEqualTo(PREF_CONTROLLER); } - @Test - public void testBuilder_noDynamicSummaryAllowed_buildsMatchingObject() { - SliceData.Builder builder = new SliceData.Builder() - .setKey(KEY) - .setTitle(TITLE) - .setSummary(SUMMARY) - .setScreenTitle(SCREEN_TITLE) - .setIcon(ICON) - .setFragmentName(FRAGMENT_NAME) - .setUri(URI) - .setPreferenceControllerClassName(PREF_CONTROLLER); - - SliceData data = builder.build(); - - assertThat(data.getKey()).isEqualTo(KEY); - assertThat(data.getTitle()).isEqualTo(TITLE); - assertThat(data.getSummary()).isEqualTo(SUMMARY); - assertThat(data.getScreenTitle()).isEqualTo(SCREEN_TITLE); - assertThat(data.getIconResource()).isEqualTo(ICON); - assertThat(data.getFragmentClassName()).isEqualTo(FRAGMENT_NAME); - assertThat(data.getUri()).isEqualTo(URI); - assertThat(data.getPreferenceController()).isEqualTo(PREF_CONTROLLER); - assertThat(data.isDynamicSummaryAllowed()).isFalse(); - } - @Test public void testEquality_identicalObjects() { SliceData.Builder builder = new SliceData.Builder() @@ -255,8 +227,7 @@ public class SliceDataTest { .setIcon(ICON) .setFragmentName(FRAGMENT_NAME) .setUri(URI) - .setPreferenceControllerClassName(PREF_CONTROLLER) - .setDynamicSummaryAllowed(IS_DYNAMIC_SUMMARY_ALLOWED); + .setPreferenceControllerClassName(PREF_CONTROLLER); SliceData dataOne = builder.build(); SliceData dataTwo = builder.build(); diff --git a/tests/robotests/src/com/android/settings/slices/SlicesDatabaseAccessorTest.java b/tests/robotests/src/com/android/settings/slices/SlicesDatabaseAccessorTest.java index a657ede7b92..de2c51fc4bf 100644 --- a/tests/robotests/src/com/android/settings/slices/SlicesDatabaseAccessorTest.java +++ b/tests/robotests/src/com/android/settings/slices/SlicesDatabaseAccessorTest.java @@ -108,14 +108,13 @@ public class SlicesDatabaseAccessorTest { assertThat(data.getFragmentClassName()).isEqualTo(FAKE_FRAGMENT_NAME); assertThat(data.getUri()).isNull(); assertThat(data.getPreferenceController()).isEqualTo(FAKE_CONTROLLER_NAME); - assertThat(data.isDynamicSummaryAllowed()).isFalse(); /* default value */ assertThat(data.getUnavailableSliceSubtitle()).isNull(); } @Test public void testGetSliceDataFromKey_allowDynamicSummary_validSliceReturned() { String key = "key"; - insertSpecialCase(key, true /* isPlatformSlice */, true /* isDynamicSummaryAllowed */, + insertSpecialCase(key, true /* isPlatformSlice */, null /* customizedUnavailableSliceSubtitle */); SliceData data = mAccessor.getSliceDataFromKey(key); @@ -129,27 +128,6 @@ public class SlicesDatabaseAccessorTest { assertThat(data.getFragmentClassName()).isEqualTo(FAKE_FRAGMENT_NAME); assertThat(data.getUri()).isNull(); assertThat(data.getPreferenceController()).isEqualTo(FAKE_CONTROLLER_NAME); - assertThat(data.isDynamicSummaryAllowed()).isTrue(); - } - - @Test - public void testGetSliceDataFromKey_doNotAllowDynamicSummary_validSliceReturned() { - String key = "key"; - insertSpecialCase(key, true /* isPlatformSlice */, false /* isDynamicSummaryAllowed */, - null /* customizedUnavailableSliceSubtitle */); - - SliceData data = mAccessor.getSliceDataFromKey(key); - - assertThat(data.getKey()).isEqualTo(key); - assertThat(data.getTitle()).isEqualTo(FAKE_TITLE); - assertThat(data.getSummary()).isEqualTo(FAKE_SUMMARY); - assertThat(data.getScreenTitle()).isEqualTo(FAKE_SCREEN_TITLE); - assertThat(data.getKeywords()).isEqualTo(FAKE_KEYWORDS); - assertThat(data.getIconResource()).isEqualTo(FAKE_ICON); - assertThat(data.getFragmentClassName()).isEqualTo(FAKE_FRAGMENT_NAME); - assertThat(data.getUri()).isNull(); - assertThat(data.getPreferenceController()).isEqualTo(FAKE_CONTROLLER_NAME); - assertThat(data.isDynamicSummaryAllowed()).isFalse(); } @Test(expected = IllegalStateException.class) @@ -249,7 +227,7 @@ public class SlicesDatabaseAccessorTest { @Test public void testGetSliceDataFromKey_defaultUnavailableSlice_validSliceReturned() { String key = "key"; - insertSpecialCase(key, true /* isPlatformSlice */, true /* isDynamicSummaryAllowed */, + insertSpecialCase(key, true /* isPlatformSlice */, null /* customizedUnavailableSliceSubtitle */); SliceData data = mAccessor.getSliceDataFromKey(key); @@ -270,8 +248,7 @@ public class SlicesDatabaseAccessorTest { public void testGetSliceDataFromKey_customizeSubtitleOfUnavailableSlice_validSliceReturned() { String key = "key"; String subtitle = "subtitle"; - insertSpecialCase(key, true /* isPlatformSlice */, true /* isDynamicSummaryAllowed */, - subtitle); + insertSpecialCase(key, true /* isPlatformSlice */, subtitle); SliceData data = mAccessor.getSliceDataFromKey(key); @@ -292,12 +269,11 @@ public class SlicesDatabaseAccessorTest { } private void insertSpecialCase(String key, boolean isPlatformSlice) { - insertSpecialCase(key, isPlatformSlice, false /* isDynamicSummaryAllowed */, - null /*customizedUnavailableSliceSubtitle*/); + insertSpecialCase(key, isPlatformSlice, null /*customizedUnavailableSliceSubtitle*/); } private void insertSpecialCase(String key, boolean isPlatformSlice, - boolean isDynamicSummaryAllowed, String customizedUnavailableSliceSubtitle) { + String customizedUnavailableSliceSubtitle) { ContentValues values = new ContentValues(); values.put(SlicesDatabaseHelper.IndexColumns.KEY, key); values.put(SlicesDatabaseHelper.IndexColumns.TITLE, FAKE_TITLE); @@ -308,8 +284,6 @@ public class SlicesDatabaseAccessorTest { values.put(SlicesDatabaseHelper.IndexColumns.FRAGMENT, FAKE_FRAGMENT_NAME); values.put(SlicesDatabaseHelper.IndexColumns.CONTROLLER, FAKE_CONTROLLER_NAME); values.put(SlicesDatabaseHelper.IndexColumns.PLATFORM_SLICE, isPlatformSlice); - values.put(SlicesDatabaseHelper.IndexColumns.ALLOW_DYNAMIC_SUMMARY_IN_SLICE, - isDynamicSummaryAllowed); values.put(SlicesDatabaseHelper.IndexColumns.SLICE_TYPE, SliceData.SliceType.INTENT); values.put(SlicesDatabaseHelper.IndexColumns.UNAVAILABLE_SLICE_SUBTITLE, customizedUnavailableSliceSubtitle); diff --git a/tests/robotests/src/com/android/settings/slices/SlicesDatabaseHelperTest.java b/tests/robotests/src/com/android/settings/slices/SlicesDatabaseHelperTest.java index 96bca0728a8..585c75d93a1 100644 --- a/tests/robotests/src/com/android/settings/slices/SlicesDatabaseHelperTest.java +++ b/tests/robotests/src/com/android/settings/slices/SlicesDatabaseHelperTest.java @@ -74,7 +74,6 @@ public class SlicesDatabaseHelperTest { IndexColumns.CONTROLLER, IndexColumns.PLATFORM_SLICE, IndexColumns.SLICE_TYPE, - IndexColumns.ALLOW_DYNAMIC_SUMMARY_IN_SLICE, IndexColumns.UNAVAILABLE_SLICE_SUBTITLE, }; diff --git a/tests/robotests/src/com/android/settings/slices/SlicesIndexerTest.java b/tests/robotests/src/com/android/settings/slices/SlicesIndexerTest.java index b63dfd923c2..8fd58c45b82 100644 --- a/tests/robotests/src/com/android/settings/slices/SlicesIndexerTest.java +++ b/tests/robotests/src/com/android/settings/slices/SlicesIndexerTest.java @@ -53,7 +53,6 @@ public class SlicesIndexerTest { private final Uri URI = Uri.parse("content://com.android.settings.slices/test"); private final String PREF_CONTROLLER = "com.android.settings.slices.tester"; private final boolean PLATFORM_DEFINED = true; - private final boolean IS_DYNAMIC_SUMMARY_ALLOWED = true; private final int SLICE_TYPE = SliceData.SliceType.SLIDER; private final String UNAVAILABLE_SLICE_SUBTITLE = "subtitleOfUnavailableSlice"; @@ -142,10 +141,6 @@ public class SlicesIndexerTest { .isEqualTo(1 /* true */); assertThat(cursor.getInt(cursor.getColumnIndex(IndexColumns.SLICE_TYPE))) .isEqualTo(SLICE_TYPE); - assertThat(cursor.getInt( - cursor.getColumnIndex( - IndexColumns.ALLOW_DYNAMIC_SUMMARY_IN_SLICE))) - .isEqualTo(1 /* true */); assertThat(cursor.getString( cursor.getColumnIndex(IndexColumns.UNAVAILABLE_SLICE_SUBTITLE))) .isEqualTo(UNAVAILABLE_SLICE_SUBTITLE); @@ -183,7 +178,6 @@ public class SlicesIndexerTest { .setPreferenceControllerClassName(PREF_CONTROLLER) .setPlatformDefined(PLATFORM_DEFINED) .setSliceType(SLICE_TYPE) - .setDynamicSummaryAllowed(IS_DYNAMIC_SUMMARY_ALLOWED) .setUnavailableSliceSubtitle(UNAVAILABLE_SLICE_SUBTITLE); for (int i = 0; i < KEYS.length; i++) { From 8a61657c6d9aa4f9dfd5e39f897469d5a81d5ad5 Mon Sep 17 00:00:00 2001 From: jackqdyulei Date: Fri, 29 Mar 2019 11:37:47 -0700 Subject: [PATCH 04/20] Disable "Battery dialog" for default apps If it is default active app(i.e. Phone, SMS), disable battery optimzation dialog so user can't optimize it. Fixes: 118910079 Test: RunSettingsLibRoboTests Change-Id: I7223913c1e6ef68d84adfc2c54d133661a529202 --- .../applications/manageapplications/ManageApplications.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java index 4faa158ddc1..ee66b12d83a 100644 --- a/src/com/android/settings/applications/manageapplications/ManageApplications.java +++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java @@ -927,6 +927,7 @@ public class ManageApplications extends InstrumentedFragment private boolean mHasReceivedBridgeCallback; private FileViewHolderController mExtraViewController; private SearchFilter mSearchFilter; + private PowerWhitelistBackend mBackend; // This is to remember and restore the last scroll position when this // fragment is paused. We need this special handling because app entries are added gradually @@ -1361,8 +1362,9 @@ public class ManageApplications extends InstrumentedFragment return true; } ApplicationsState.AppEntry entry = mEntries.get(position); - return !PowerWhitelistBackend.getInstance(mContext) - .isSysWhitelisted(entry.info.packageName); + + return !mBackend.isSysWhitelisted(entry.info.packageName) + && !mBackend.isDefaultActiveApp(entry.info.packageName); } @Override From e560ad09f650de8fe1d556642ee2771c09a68cd1 Mon Sep 17 00:00:00 2001 From: Po-Chien Hsueh Date: Tue, 2 Apr 2019 13:53:21 +0800 Subject: [PATCH 05/20] Make feature flag settings_dynamic_system persistent Bug: 119647479 Test: turn on/off feature flag and use DynamicSystem Change-Id: Icc26e649caea2c6dfc6e09d8f2c9f0f37568d445 --- src/com/android/settings/core/FeatureFlags.java | 1 + .../settings/development/featureflags/FeatureFlagPersistent.java | 1 + 2 files changed, 2 insertions(+) diff --git a/src/com/android/settings/core/FeatureFlags.java b/src/com/android/settings/core/FeatureFlags.java index fbb2ae30f6b..b07635f7c11 100644 --- a/src/com/android/settings/core/FeatureFlags.java +++ b/src/com/android/settings/core/FeatureFlags.java @@ -21,6 +21,7 @@ package com.android.settings.core; */ public class FeatureFlags { public static final String AUDIO_SWITCHER_SETTINGS = "settings_audio_switcher"; + public static final String DYNAMIC_SYSTEM = "settings_dynamic_system"; public static final String HEARING_AID_SETTINGS = "settings_bluetooth_hearing_aid"; public static final String MOBILE_NETWORK_V2 = "settings_mobile_network_v2"; public static final String NETWORK_INTERNET_V2 = "settings_network_and_internet_v2"; diff --git a/src/com/android/settings/development/featureflags/FeatureFlagPersistent.java b/src/com/android/settings/development/featureflags/FeatureFlagPersistent.java index 941c94cfbe4..59318c471dc 100644 --- a/src/com/android/settings/development/featureflags/FeatureFlagPersistent.java +++ b/src/com/android/settings/development/featureflags/FeatureFlagPersistent.java @@ -36,6 +36,7 @@ public class FeatureFlagPersistent { PERSISTENT_FLAGS = new HashSet<>(); PERSISTENT_FLAGS.add(FeatureFlags.HEARING_AID_SETTINGS); PERSISTENT_FLAGS.add(FeatureFlags.NETWORK_INTERNET_V2); + PERSISTENT_FLAGS.add(FeatureFlags.DYNAMIC_SYSTEM); } public static boolean isEnabled(Context context, String feature) { From 5c2637d6d0f34868fb3275078c4c0796841516ce Mon Sep 17 00:00:00 2001 From: clownshen Date: Mon, 1 Apr 2019 16:01:06 +0800 Subject: [PATCH 06/20] Only show Sign In button for connected network The Sign In button may appeared in details page for disconnected network if current network is Captive Portal network. Should hide the button for disconnected network. Bug: 129514576 Test: make RunSettingsRoboTests -j32 ROBOTEST_FILTER=com.android.settings.wifi.details.WifiDetailPreferenceControllerTest Test: manual test Change-Id: I8b4f79e7ba731ce83c49576fffd3e78a27598be3 --- .../WifiDetailPreferenceController.java | 2 +- .../WifiDetailPreferenceControllerTest.java | 22 ++++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java index c0921fc9e40..13905c8abbe 100644 --- a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java +++ b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java @@ -838,7 +838,7 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController * Returns whether the user can sign into the network represented by this preference. */ private boolean canSignIntoNetwork() { - return WifiUtils.canSignIntoNetwork(mNetworkCapabilities); + return mAccessPoint.isActive() && WifiUtils.canSignIntoNetwork(mNetworkCapabilities); } /** diff --git a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java index 307712e686b..2166e979131 100644 --- a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java @@ -1404,6 +1404,27 @@ public class WifiDetailPreferenceControllerTest { .action(mockActivity, MetricsProto.MetricsEvent.ACTION_WIFI_SIGNIN); } + @Test + public void testSignInButton_shouldHideSignInButtonForDisconnectedNetwork() { + setUpForDisconnectedNetwork(); + NetworkCapabilities nc = makeNetworkCapabilities(); + nc.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL); + when(mockConnectivityManager.getNetworkCapabilities(mockNetwork)) + .thenReturn(new NetworkCapabilities(nc)); + + // verify onResume + displayAndResume(); + + verify(mockButtonsPref, never()).setButton2Visible(true); + verify(mockButtonsPref).setButton2Visible(false); + + // verify onCapabilitiesChanged + updateNetworkCapabilities(nc); + + verify(mockButtonsPref, never()).setButton2Visible(true); + verify(mockButtonsPref).setButton2Visible(false); + } + @Test public void testRefreshRssiViews_shouldNotUpdateIfLevelIsSame() { displayAndResume(); @@ -1437,7 +1458,6 @@ public class WifiDetailPreferenceControllerTest { verify(mockSignalStrengthPref, times(2)).setVisible(false); } - private ActionButtonsPreference createMock() { final ActionButtonsPreference pref = mock(ActionButtonsPreference.class); when(pref.setButton1Text(anyInt())).thenReturn(pref); From 0833c5a133f44994e10f9d719c50f88602755717 Mon Sep 17 00:00:00 2001 From: Alan Stokes Date: Tue, 2 Apr 2019 15:37:54 +0100 Subject: [PATCH 07/20] Take default for background activity starts from DeviceConfig. We've modified the implementation to use the value set by DeviceConfig if the user has not touched the developer options setting (change fb227077b8652b817a094d37a5215ad7466ee603). We want the Settings screen to reflect this default until the user explicitly sets it. Additionally if the user disables developer settings we want to go back to using whatever DeviceConfig sets. Bug: 129533810 Test: croot && make RunSettingsRoboTests \ ROBOTEST_FILTER=AllowBackgroundActivityStartsPreferenceControllerTest Change-Id: I73901a22da928f9a6924b30882b26494cdcd94bc --- ...undActivityStartsPreferenceController.java | 41 +++++++--- ...ctivityStartsPreferenceControllerTest.java | 74 ++++++++++++++++--- 2 files changed, 96 insertions(+), 19 deletions(-) diff --git a/src/com/android/settings/development/AllowBackgroundActivityStartsPreferenceController.java b/src/com/android/settings/development/AllowBackgroundActivityStartsPreferenceController.java index d26517a0283..4aaa4906335 100644 --- a/src/com/android/settings/development/AllowBackgroundActivityStartsPreferenceController.java +++ b/src/com/android/settings/development/AllowBackgroundActivityStartsPreferenceController.java @@ -17,11 +17,13 @@ package com.android.settings.development; import android.content.Context; +import android.provider.DeviceConfig; import android.provider.Settings; import androidx.preference.Preference; import androidx.preference.SwitchPreference; +import com.android.internal.annotations.VisibleForTesting; import com.android.settings.core.PreferenceControllerMixin; import com.android.settingslib.development.DeveloperOptionsPreferenceController; @@ -32,6 +34,11 @@ public class AllowBackgroundActivityStartsPreferenceController private static final String BACKGROUND_ACTIVITY_STARTS_ENABLED_KEY = "allow_background_activity_starts"; + /** Key in DeviceConfig that stores the default for the preference (as a boolean). */ + @VisibleForTesting + static final String KEY_DEFAULT_BACKGROUND_ACTIVITY_STARTS_ENABLED = + "default_background_activity_starts_enabled"; + public AllowBackgroundActivityStartsPreferenceController(Context context) { super(context); } @@ -47,22 +54,38 @@ public class AllowBackgroundActivityStartsPreferenceController return true; } - private void writeSetting(boolean isEnabled) { - Settings.Global.putInt(mContext.getContentResolver(), - Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED, isEnabled ? 1 : 0); - } - @Override public void updateState(Preference preference) { final int mode = Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED, 1); - ((SwitchPreference) mPreference).setChecked(mode != 0); + Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED, -1); + + boolean isEnabled = mode < 0 ? isDefaultEnabled() : mode != 0; + ((SwitchPreference) mPreference).setChecked(isEnabled); } @Override protected void onDeveloperOptionsSwitchDisabled() { super.onDeveloperOptionsSwitchDisabled(); - writeSetting(true); - ((SwitchPreference) mPreference).setChecked(true); + clearSetting(); + updateState(mPreference); + } + + private void writeSetting(boolean isEnabled) { + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED, isEnabled ? 1 : 0); + } + + private void clearSetting() { + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED, -1); + } + + private boolean isDefaultEnabled() { + // The default in the absence of user preference is settable via DeviceConfig. + // Note that the default default is enabled. + return DeviceConfig.getBoolean( + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, + KEY_DEFAULT_BACKGROUND_ACTIVITY_STARTS_ENABLED, + /*defaultValue*/ true); } } diff --git a/tests/robotests/src/com/android/settings/development/AllowBackgroundActivityStartsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/AllowBackgroundActivityStartsPreferenceControllerTest.java index 8e95aa109c6..afe08489503 100644 --- a/tests/robotests/src/com/android/settings/development/AllowBackgroundActivityStartsPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/development/AllowBackgroundActivityStartsPreferenceControllerTest.java @@ -16,17 +16,22 @@ package com.android.settings.development; +import static com.android.settings.development.AllowBackgroundActivityStartsPreferenceController.KEY_DEFAULT_BACKGROUND_ACTIVITY_STARTS_ENABLED; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.Context; +import android.provider.DeviceConfig; import android.provider.Settings; import androidx.preference.PreferenceScreen; import androidx.preference.SwitchPreference; +import com.android.settings.testutils.shadow.ShadowDeviceConfig; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -34,8 +39,10 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; @RunWith(RobolectricTestRunner.class) +@Config(shadows = {ShadowDeviceConfig.class}) public class AllowBackgroundActivityStartsPreferenceControllerTest { @Mock @@ -60,20 +67,14 @@ public class AllowBackgroundActivityStartsPreferenceControllerTest { public void onPreferenceChange_settingEnabled_allowBackgroundActivityStartsShouldBeOn() { mController.onPreferenceChange(mPreference, true /* new value */); - final int mode = Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED, 1 /* default */); - - assertThat(mode).isEqualTo(1); + assertThat(getModeFroMSettings()).isEqualTo(1); } @Test public void onPreferenceChange_settingDisabled_allowBackgroundActivityStartsShouldBeOff() { mController.onPreferenceChange(mPreference, false /* new value */); - final int mode = Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED, 1 /* default */); - - assertThat(mode).isEqualTo(0); + assertThat(getModeFroMSettings()).isEqualTo(0); } @Test @@ -83,7 +84,7 @@ public class AllowBackgroundActivityStartsPreferenceControllerTest { mController.updateState(mPreference); verify(mPreference).setChecked(false); - } + } @Test public void updateState_settingEnabled_preferenceShouldBeChecked() { @@ -95,11 +96,64 @@ public class AllowBackgroundActivityStartsPreferenceControllerTest { } @Test - public void onDeveloperOptionsSwitchDisabled_shouldDisablePreference() { + public void updateState_settingReset_defaultDisabled_preferenceShouldNotBeChecked() { + setDefault(false); + mController.updateState(mPreference); + + verify(mPreference).setChecked(false); + } + + @Test + public void updateState_settingReset_defaultEnabled_preferenceShouldBeChecked() { + setDefault(true); + mController.updateState(mPreference); + + verify(mPreference).setChecked(true); + } + + @Test + public void onDeveloperOptionsSwitchDisabled_noDefault_shouldResetPreference() { mController.onDeveloperOptionsSwitchDisabled(); verify(mPreference).setChecked(true); verify(mPreference).setEnabled(false); + + assertThat(getModeFroMSettings()).isEqualTo(-1); + } + + @Test + public void onDeveloperOptionsSwitchDisabled_defaultDisabled_shouldResetPreference() { + setDefault(false); + mController.onDeveloperOptionsSwitchDisabled(); + + verify(mPreference).setChecked(false); + verify(mPreference).setEnabled(false); + + assertThat(getModeFroMSettings()).isEqualTo(-1); + } + + @Test + public void onDeveloperOptionsSwitchDisabled_defaultEnabled_shouldResetPreference() { + setDefault(true); + mController.onDeveloperOptionsSwitchDisabled(); + + verify(mPreference).setChecked(true); + verify(mPreference).setEnabled(false); + + assertThat(getModeFroMSettings()).isEqualTo(-1); + } + + private int getModeFroMSettings() { + return Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED, 999 /* default */); + } + + private void setDefault(boolean defaultEnabled) { + DeviceConfig.setProperty( + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, + KEY_DEFAULT_BACKGROUND_ACTIVITY_STARTS_ENABLED, + Boolean.toString(defaultEnabled), + false /* makeDefault */); } } From 2e7af2f0232428b2e5de68210e374a94ae66cbae Mon Sep 17 00:00:00 2001 From: lindatseng Date: Tue, 2 Apr 2019 11:27:25 -0700 Subject: [PATCH 08/20] Fix tinting on injected pref icon We used to tint the injected pref icon when refreshing Tile. However, when we are going to render the icon, we used Tile.getIcon which uses the icon resource id to get the original version of icon directly. Do a little refactor here to move the tinting logic inside Tile.getIcon. Test: Manual/Visual inspection Fixes: 129010399 Change-Id: I6f187b12cb6d91b54dcfe43e0ff34add55fd7b07 --- .../dashboard/DashboardFeatureProviderImpl.java | 4 +++- .../settings/dashboard/DashboardFragment.java | 12 ------------ 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java b/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java index 2cac4c2a87a..64086cb9a33 100644 --- a/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java +++ b/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java @@ -192,7 +192,9 @@ public class DashboardFeatureProviderImpl implements DashboardFeatureProvider { @VisibleForTesting void bindIcon(Preference preference, Tile tile, boolean forceRoundedIcon) { - final Icon tileIcon = tile.getIcon(mContext); + // Use preference context instead here when get icon from Tile, as we are using the context + // to get the style to tint the icon. Using mContext here won't get the correct style. + final Icon tileIcon = tile.getIcon(preference.getContext()); if (tileIcon != null) { Drawable iconDrawable = tileIcon.loadDrawable(preference.getContext()); if (forceRoundedIcon diff --git a/src/com/android/settings/dashboard/DashboardFragment.java b/src/com/android/settings/dashboard/DashboardFragment.java index dde98ce0a4d..16303116432 100644 --- a/src/com/android/settings/dashboard/DashboardFragment.java +++ b/src/com/android/settings/dashboard/DashboardFragment.java @@ -18,8 +18,6 @@ package com.android.settings.dashboard; import android.app.Activity; import android.app.settings.SettingsEnums; import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.drawable.Icon; import android.os.Bundle; import android.text.TextUtils; import android.util.ArrayMap; @@ -410,10 +408,6 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment final Context context = getContext(); mSummaryLoader = new SummaryLoader(getActivity(), getCategoryKey()); mSummaryLoader.setSummaryConsumer(this); - final TypedArray a = context.obtainStyledAttributes(new int[]{ - android.R.attr.colorControlNormal}); - final int tintColor = a.getColor(0, context.getColor(android.R.color.white)); - a.recycle(); // Install dashboard tiles. final boolean forceRoundedIcons = shouldForceRoundedIcon(); for (Tile tile : tiles) { @@ -425,12 +419,6 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment if (!displayTile(tile)) { continue; } - if (tile.isIconTintable(context)) { - final Icon icon = tile.getIcon(context); - if (icon != null) { - icon.setTint(tintColor); - } - } if (mDashboardTilePrefKeys.contains(key)) { // Have the key already, will rebind. final Preference preference = screen.findPreference(key); From 47788dfb03bca6b5e7dc5011249f503668b1fbd2 Mon Sep 17 00:00:00 2001 From: Fan Zhang Date: Tue, 2 Apr 2019 15:45:51 -0700 Subject: [PATCH 09/20] Allow NEW type battery early warning to show in homepage Fixes: 129492004 Test: robotest Change-Id: I443866a832e4e02c128117dacd766d4fbbd8fc2e --- .../slices/BatteryFixSlice.java | 51 ++++++++++++------- .../slices/BatteryFixSliceTest.java | 25 ++------- 2 files changed, 37 insertions(+), 39 deletions(-) diff --git a/src/com/android/settings/homepage/contextualcards/slices/BatteryFixSlice.java b/src/com/android/settings/homepage/contextualcards/slices/BatteryFixSlice.java index 9b912a8555b..a75f99a54fb 100644 --- a/src/com/android/settings/homepage/contextualcards/slices/BatteryFixSlice.java +++ b/src/com/android/settings/homepage/contextualcards/slices/BatteryFixSlice.java @@ -26,6 +26,7 @@ import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.net.Uri; +import android.util.ArrayMap; import androidx.annotation.VisibleForTesting; import androidx.annotation.WorkerThread; @@ -50,6 +51,7 @@ import com.android.settingslib.utils.ThreadUtils; import java.util.Arrays; import java.util.List; +import java.util.Map; public class BatteryFixSlice implements CustomSliceable { @@ -57,11 +59,18 @@ public class BatteryFixSlice implements CustomSliceable { static final String PREFS = "battery_fix_prefs"; @VisibleForTesting static final String KEY_CURRENT_TIPS_TYPE = "current_tip_type"; + static final String KEY_CURRENT_TIPS_STATE = "current_tip_state"; - private static final List UNIMPORTANT_BATTERY_TIPS = Arrays.asList( - BatteryTip.TipType.SUMMARY, - BatteryTip.TipType.BATTERY_SAVER - ); + // A map tracking which BatteryTip and which state of that tip is not important. + private static final Map> UNIMPORTANT_BATTERY_TIPS; + + static { + UNIMPORTANT_BATTERY_TIPS = new ArrayMap<>(); + UNIMPORTANT_BATTERY_TIPS.put(BatteryTip.TipType.SUMMARY, + Arrays.asList(BatteryTip.StateType.NEW, BatteryTip.StateType.HANDLED)); + UNIMPORTANT_BATTERY_TIPS.put(BatteryTip.TipType.BATTERY_SAVER, + Arrays.asList(BatteryTip.StateType.HANDLED)); + } private static final String TAG = "BatteryFixSlice"; @@ -82,9 +91,8 @@ public class BatteryFixSlice implements CustomSliceable { new ListBuilder(mContext, BATTERY_FIX_SLICE_URI, ListBuilder.INFINITY) .setAccentColor(COLOR_NOT_TINTED); - // TipType.SUMMARY is battery good - if (UNIMPORTANT_BATTERY_TIPS.contains(readBatteryTipAvailabilityCache(mContext))) { - return buildBatteryGoodSlice(sliceBuilder, true); + if (!isBatteryTipAvailableFromCache(mContext)) { + return buildBatteryGoodSlice(sliceBuilder, true /* isError */); } final SliceBackgroundWorker worker = SliceBackgroundWorker.getInstance(getUri()); @@ -92,7 +100,7 @@ public class BatteryFixSlice implements CustomSliceable { if (batteryTips == null) { // Because we need wait slice background worker return data - return buildBatteryGoodSlice(sliceBuilder, false); + return buildBatteryGoodSlice(sliceBuilder, false /* isError */); } for (BatteryTip batteryTip : batteryTips) { @@ -161,15 +169,23 @@ public class BatteryFixSlice implements CustomSliceable { // TODO(b/114807643): we should find a better way to get current battery tip type quickly // Now we save battery tip type to shared preference when battery level changes public static void updateBatteryTipAvailabilityCache(Context context) { - ThreadUtils.postOnBackgroundThread(() -> { - refreshBatteryTips(context); - }); + ThreadUtils.postOnBackgroundThread(() -> refreshBatteryTips(context)); } + @VisibleForTesting - static int readBatteryTipAvailabilityCache(Context context) { + static boolean isBatteryTipAvailableFromCache(Context context) { final SharedPreferences prefs = context.getSharedPreferences(PREFS, MODE_PRIVATE); - return prefs.getInt(KEY_CURRENT_TIPS_TYPE, BatteryTip.TipType.SUMMARY); + + final int type = prefs.getInt(KEY_CURRENT_TIPS_TYPE, BatteryTip.TipType.SUMMARY); + final int state = prefs.getInt(KEY_CURRENT_TIPS_STATE, BatteryTip.StateType.INVISIBLE); + if (state == BatteryTip.StateType.INVISIBLE) { + // State is INVISIBLE, We should not show anything. + return false; + } + final boolean unimportant = UNIMPORTANT_BATTERY_TIPS.containsKey(type) + && UNIMPORTANT_BATTERY_TIPS.get(type).contains(state); + return !unimportant; } @WorkerThread @@ -180,10 +196,11 @@ public class BatteryFixSlice implements CustomSliceable { final List batteryTips = loader.loadInBackground(); for (BatteryTip batteryTip : batteryTips) { if (batteryTip.getState() != BatteryTip.StateType.INVISIBLE) { - SharedPreferences.Editor editor = context.getSharedPreferences(PREFS, - MODE_PRIVATE).edit(); - editor.putInt(KEY_CURRENT_TIPS_TYPE, batteryTip.getType()); - editor.apply(); + context.getSharedPreferences(PREFS, MODE_PRIVATE) + .edit() + .putInt(KEY_CURRENT_TIPS_TYPE, batteryTip.getType()) + .putInt(KEY_CURRENT_TIPS_STATE, batteryTip.getState()) + .apply(); break; } } diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/BatteryFixSliceTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/BatteryFixSliceTest.java index 1c299cb6c40..1027cf1d0c5 100644 --- a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/BatteryFixSliceTest.java +++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/BatteryFixSliceTest.java @@ -16,15 +16,9 @@ package com.android.settings.homepage.contextualcards.slices; -import static android.content.Context.MODE_PRIVATE; - -import static com.android.settings.homepage.contextualcards.slices.BatteryFixSlice.KEY_CURRENT_TIPS_TYPE; -import static com.android.settings.homepage.contextualcards.slices.BatteryFixSlice.PREFS; - import static com.google.common.truth.Truth.assertThat; import android.content.Context; -import android.content.SharedPreferences; import androidx.slice.Slice; import androidx.slice.SliceMetadata; @@ -74,24 +68,12 @@ public class BatteryFixSliceTest { ShadowBatteryTipLoader.reset(); } - @Test - public void readBatteryTipFromPref_readCorrectValue() { - int target = 111; - final SharedPreferences.Editor editor = mContext.getSharedPreferences(PREFS, - MODE_PRIVATE).edit(); - editor.putInt(KEY_CURRENT_TIPS_TYPE, target); - - editor.commit(); - - assertThat(BatteryFixSlice.readBatteryTipAvailabilityCache(mContext)).isEqualTo(target); - } - @Test @Config(shadows = { ShadowBatteryStatsHelperLoader.class, ShadowBatteryTipLoader.class }) - public void updateBatteryTipAvailabilityCache_writeCorrectValue() { + public void updateBatteryTipAvailabilityCache_hasImportantTip_shouldReturnTrue() { final List tips = new ArrayList<>(); tips.add(new LowBatteryTip(BatteryTip.StateType.INVISIBLE, false, "")); tips.add(new EarlyWarningTip(BatteryTip.StateType.NEW, false)); @@ -99,8 +81,7 @@ public class BatteryFixSliceTest { BatteryFixSlice.updateBatteryTipAvailabilityCache(mContext); - assertThat(BatteryFixSlice.readBatteryTipAvailabilityCache(mContext)).isEqualTo( - BatteryTip.TipType.BATTERY_SAVER); + assertThat(BatteryFixSlice.isBatteryTipAvailableFromCache(mContext)).isTrue(); } @Test @@ -111,7 +92,7 @@ public class BatteryFixSliceTest { public void getSlice_unimportantSlice_shouldSkip() { final List tips = new ArrayList<>(); tips.add(new LowBatteryTip(BatteryTip.StateType.INVISIBLE, false, "")); - tips.add(new EarlyWarningTip(BatteryTip.StateType.NEW, false)); + tips.add(new EarlyWarningTip(BatteryTip.StateType.HANDLED, false)); ShadowBatteryTipLoader.setBatteryTips(tips); BatteryFixSlice.updateBatteryTipAvailabilityCache(mContext); From ae5d71938267d4e53581b79a1e05a9f3adef6467 Mon Sep 17 00:00:00 2001 From: Malcolm Chen Date: Fri, 22 Mar 2019 17:59:00 -0700 Subject: [PATCH 10/20] Clean up a few names of Telephony intent extra. Bug: 128645056 Test: build Change-Id: I5d47b132abb722282bd10b9fbb362fb1f1d32f11 Merged-In: I5d47b132abb722282bd10b9fbb362fb1f1d32f11 --- src/com/android/settings/sim/SimSelectNotification.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/com/android/settings/sim/SimSelectNotification.java b/src/com/android/settings/sim/SimSelectNotification.java index 891d1719e66..4f3b9bc3f79 100644 --- a/src/com/android/settings/sim/SimSelectNotification.java +++ b/src/com/android/settings/sim/SimSelectNotification.java @@ -16,11 +16,11 @@ package com.android.settings.sim; -import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_ID; -import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELECT_FOR_ALL_TYPES; import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE; +import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_ALL; import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DATA; import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_NONE; +import static android.telephony.TelephonyManager.EXTRA_SUBSCRIPTION_ID; import android.app.NotificationChannel; import android.app.NotificationManager; @@ -52,8 +52,8 @@ public class SimSelectNotification extends BroadcastReceiver { int dialogType = intent.getIntExtra(EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE, EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_NONE); - if (dialogType == EXTRA_DEFAULT_SUBSCRIPTION_SELECT_FOR_ALL_TYPES) { - int subId = intent.getIntExtra(EXTRA_DEFAULT_SUBSCRIPTION_ID, + if (dialogType == EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_ALL) { + int subId = intent.getIntExtra(EXTRA_SUBSCRIPTION_ID, SubscriptionManager.DEFAULT_SUBSCRIPTION_ID); int slotIndex = SubscriptionManager.getSlotIndex(subId); // If there is only one subscription, ask if user wants to use if for everything From cb1c9fceb8b1d7224ef7cb4289d0a1a0016bd018 Mon Sep 17 00:00:00 2001 From: Arc Wang Date: Tue, 2 Apr 2019 14:31:33 +0800 Subject: [PATCH 11/20] Play vibration when Wi-Fi QR code scanner recognize a valid QR code Bug: 127377350 Test: manual Change-Id: I9bfcb6f4d1d4dee45d2cacdedfc07d2f4eccd758 --- .../dpp/WifiDppQrCodeScannerFragment.java | 24 +++++++++++-------- .../settings/wifi/dpp/WifiDppUtils.java | 16 +++++++++++++ 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java index 0fb56fae334..21920d2d5dc 100644 --- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java +++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java @@ -140,6 +140,11 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl break; case MESSAGE_SCAN_WIFI_DPP_SUCCESS: + if (mCamera != null) { + mCamera.stop(); + } + + mDecorateView.setFocused(true); mErrorMessage.setVisibility(View.INVISIBLE); if (mScanWifiDppSuccessListener == null) { @@ -154,15 +159,24 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl mSummary.sendAccessibilityEvent( AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); } + + WifiDppUtils.triggerVibrationForQrCodeRecognition(getContext()); break; case MESSAGE_SCAN_ZXING_WIFI_FORMAT_SUCCESS: + if (mCamera != null) { + mCamera.stop(); + } + + mDecorateView.setFocused(true); mErrorMessage.setVisibility(View.INVISIBLE); final WifiNetworkConfig wifiNetworkConfig = (WifiNetworkConfig)msg.obj; mWifiConfiguration = wifiNetworkConfig.getWifiConfigurationOrNull(); wifiNetworkConfig.connect(getContext(), /* listener */ WifiDppQrCodeScannerFragment.this); + + WifiDppUtils.triggerVibrationForQrCodeRecognition(getContext()); break; default: @@ -409,11 +423,6 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl } private void handleWifiDpp() { - if (mCamera != null) { - mCamera.stop(); - } - mDecorateView.setFocused(true); - Message message = mHandler.obtainMessage(MESSAGE_SCAN_WIFI_DPP_SUCCESS); message.obj = new WifiQrCode(mWifiQrCode.getQrCode()); @@ -421,11 +430,6 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl } private void handleZxingWifiFormat() { - if (mCamera != null) { - mCamera.stop(); - } - mDecorateView.setFocused(true); - Message message = mHandler.obtainMessage(MESSAGE_SCAN_ZXING_WIFI_FORMAT_SUCCESS); message.obj = new WifiQrCode(mWifiQrCode.getQrCode()).getWifiNetworkConfig(); diff --git a/src/com/android/settings/wifi/dpp/WifiDppUtils.java b/src/com/android/settings/wifi/dpp/WifiDppUtils.java index 42e88a57b02..2ec3137c27c 100644 --- a/src/com/android/settings/wifi/dpp/WifiDppUtils.java +++ b/src/com/android/settings/wifi/dpp/WifiDppUtils.java @@ -26,6 +26,8 @@ import android.net.wifi.WifiManager; import android.os.CancellationSignal; import android.os.Handler; import android.os.Looper; +import android.os.VibrationEffect; +import android.os.Vibrator; import android.text.TextUtils; import android.util.FeatureFlagUtils; @@ -35,6 +37,8 @@ import com.android.settingslib.wifi.AccessPoint; import java.util.List; +import java.time.Duration; + /** * Here are the items shared by both WifiDppConfiguratorActivity & WifiDppEnrolleeActivity * @@ -94,6 +98,8 @@ public class WifiDppUtils { */ public static final int EASY_CONNECT_EVENT_SUCCESS = 1; + private static final Duration VIBRATE_DURATION_QR_CODE_RECOGNITION = Duration.ofMillis(3); + /** * Returns whether the device support WiFi DPP. */ @@ -386,4 +392,14 @@ public class WifiDppUtils { } return false; } + + static void triggerVibrationForQrCodeRecognition(Context context) { + Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); + if (vibrator == null) { + return; + } + vibrator.vibrate(VibrationEffect.createOneShot( + VIBRATE_DURATION_QR_CODE_RECOGNITION.toMillis(), + VibrationEffect.DEFAULT_AMPLITUDE)); + } } From b335e96d2aae65a403040f6a6960958433e6c8ec Mon Sep 17 00:00:00 2001 From: Jason Chiu Date: Wed, 3 Apr 2019 13:49:26 +0800 Subject: [PATCH 12/20] Micro cleanup and refactoring - remove unused dimen resources - remove unused and refactor codes Test: make RunSettingsRoboTests -j Change-Id: Ic2a5b16323667741d048e20e3db8da3fb4dc348a --- res/values/dimens.xml | 16 ---------------- .../homepage/SettingsHomepageActivity.java | 2 +- .../slices/SliceFullCardRendererHelper.java | 7 ------- 3 files changed, 1 insertion(+), 24 deletions(-) diff --git a/res/values/dimens.xml b/res/values/dimens.xml index 7d5ca662e1d..f1265253c4f 100755 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -319,14 +319,6 @@ 64dp 64dp - - 10dp - 5dp - 36dp - - - 2dp - 8dp 12dp @@ -334,12 +326,6 @@ 18sp 14sp - - 90dp - 56dp - 34dp - 68dp - 24dp 8dp @@ -369,8 +355,6 @@ 6dp - 4dp - 8dp .75dp diff --git a/src/com/android/settings/homepage/SettingsHomepageActivity.java b/src/com/android/settings/homepage/SettingsHomepageActivity.java index 9b83f88e832..6d16d7f56cb 100644 --- a/src/com/android/settings/homepage/SettingsHomepageActivity.java +++ b/src/com/android/settings/homepage/SettingsHomepageActivity.java @@ -84,7 +84,7 @@ public class SettingsHomepageActivity extends SettingsBaseActivity { View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN ); - getWindow().setStatusBarColor(getResources().getColor(R.color.homepage_status_bar_color)); + getWindow().setStatusBarColor(getColor(R.color.homepage_status_bar_color)); } @VisibleForTesting diff --git a/src/com/android/settings/homepage/contextualcards/slices/SliceFullCardRendererHelper.java b/src/com/android/settings/homepage/contextualcards/slices/SliceFullCardRendererHelper.java index 1e1bde4981d..35845783c73 100644 --- a/src/com/android/settings/homepage/contextualcards/slices/SliceFullCardRendererHelper.java +++ b/src/com/android/settings/homepage/contextualcards/slices/SliceFullCardRendererHelper.java @@ -17,14 +17,10 @@ package com.android.settings.homepage.contextualcards.slices; import android.content.Context; -import android.util.Log; import android.view.View; -import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import androidx.slice.Slice; -import androidx.slice.SliceItem; -import androidx.slice.widget.EventInfo; import androidx.slice.widget.SliceView; import com.android.settings.R; @@ -32,13 +28,10 @@ import com.android.settings.homepage.contextualcards.ContextualCard; import com.android.settings.homepage.contextualcards.ContextualCardFeatureProvider; import com.android.settings.overlay.FeatureFactory; -import java.util.Set; - /** * Card renderer helper for {@link ContextualCard} built as slice full card. */ class SliceFullCardRendererHelper { - private static final String TAG = "SliceFCRendererHelper"; private final Context mContext; From 1a9a748cdbeff19f86f75edd1d7a09f6291e9f83 Mon Sep 17 00:00:00 2001 From: Yanting Yang Date: Wed, 3 Apr 2019 17:29:24 +0800 Subject: [PATCH 13/20] Remove unused method from NotificationChannelSlice Fixes:129835504 Test: robotests Change-Id: Id0bcad694bba39ce67c77388b9bde7018aae1560 --- .../contextualcards/slices/NotificationChannelSlice.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/com/android/settings/homepage/contextualcards/slices/NotificationChannelSlice.java b/src/com/android/settings/homepage/contextualcards/slices/NotificationChannelSlice.java index 0278f90776d..0550e7b30eb 100644 --- a/src/com/android/settings/homepage/contextualcards/slices/NotificationChannelSlice.java +++ b/src/com/android/settings/homepage/contextualcards/slices/NotificationChannelSlice.java @@ -437,15 +437,6 @@ public class NotificationChannelSlice implements CustomSliceable { .setData(getUri()); } - private PackageInfo getPackageInfo(String packageName) { - try { - return mContext.getPackageManager().getPackageInfo(packageName, 0); - } catch (PackageManager.NameNotFoundException e) { - Log.w(TAG, "No such package to get package info."); - return null; - } - } - private boolean isChannelEnabled(NotificationChannelGroup group, NotificationChannel channel, NotificationBackend.AppRow appRow) { final RestrictedLockUtils.EnforcedAdmin suspendedAppsAdmin = From e6f11ad0f2a8043804869dcfc03c735dd78ebf00 Mon Sep 17 00:00:00 2001 From: Yi-Ling Chuang Date: Tue, 22 Jan 2019 12:12:08 +0800 Subject: [PATCH 14/20] Add tests for ContextualCardManager. Bug: 114307549 Test: robotests Change-Id: Iac9450ed21011cb6e8186fbe686ff4d03547ba5e --- .../ContextualCardManager.java | 21 ++-- .../ContextualCardManagerTest.java | 107 ++++++++++++++++-- 2 files changed, 113 insertions(+), 15 deletions(-) diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java b/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java index 92108f0f535..d8361a9c495 100644 --- a/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java +++ b/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java @@ -72,26 +72,29 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo static final long CARD_CONTENT_LOADER_TIMEOUT_MS = DateUtils.SECOND_IN_MILLIS; @VisibleForTesting static final String KEY_GLOBAL_CARD_LOADER_TIMEOUT = "global_card_loader_timeout_key"; + @VisibleForTesting + static final String KEY_CONTEXTUAL_CARDS = "key_contextual_cards"; - private static final String KEY_CONTEXTUAL_CARDS = "key_contextual_cards"; private static final String TAG = "ContextualCardManager"; //The list for Settings Custom Card private static final int[] SETTINGS_CARDS = {ContextualCard.CardType.CONDITIONAL, ContextualCard.CardType.LEGACY_SUGGESTION}; - @VisibleForTesting - final List mContextualCards; private final Context mContext; private final ControllerRendererPool mControllerRendererPool; private final Lifecycle mLifecycle; private final List mLifecycleObservers; + private ContextualCardUpdateListener mListener; + + @VisibleForTesting + final List mContextualCards; @VisibleForTesting long mStartTime; + @VisibleForTesting boolean mIsFirstLaunch; @VisibleForTesting List mSavedCards; - private ContextualCardUpdateListener mListener; public ContextualCardManager(Context context, Lifecycle lifecycle, Bundle savedInstanceState) { mContext = context; @@ -128,7 +131,8 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo } } - private void setupController(@ContextualCard.CardType int cardType) { + @VisibleForTesting + void setupController(@ContextualCard.CardType int cardType) { final ContextualCardController controller = mControllerRendererPool.getController(mContext, cardType); if (controller == null) { @@ -211,7 +215,7 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo final MetricsFeatureProvider metricsFeatureProvider = FeatureFactory.getFactory(mContext).getMetricsFeatureProvider(); - final long timeoutLimit = getCardLoaderTimeout(mContext); + final long timeoutLimit = getCardLoaderTimeout(); if (loadTime <= timeoutLimit) { onContextualCardUpdated(cards.stream() .collect(groupingBy(ContextualCard::getCardType))); @@ -275,7 +279,7 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo } @VisibleForTesting - long getCardLoaderTimeout(Context context) { + long getCardLoaderTimeout() { // Return the timeout limit if Settings.Global has the KEY_GLOBAL_CARD_LOADER_TIMEOUT key, // else return default timeout. return Settings.Global.getLong(mContext.getContentResolver(), @@ -317,7 +321,8 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo return result; } - private List getCardsToKeep(List cards) { + @VisibleForTesting + List getCardsToKeep(List cards) { if (mSavedCards != null) { //screen rotate final List cardsToKeep = cards.stream() diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardManagerTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardManagerTest.java index 8087716c9e1..9759f982da8 100644 --- a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardManagerTest.java +++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardManagerTest.java @@ -16,21 +16,25 @@ package com.android.settings.homepage.contextualcards; +import static com.android.settings.homepage.contextualcards.ContextualCardManager.KEY_CONTEXTUAL_CARDS; import static com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer.VIEW_TYPE_DEFERRED_SETUP; import static com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer.VIEW_TYPE_FULL_WIDTH; import static com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer.VIEW_TYPE_HALF_WIDTH; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyMap; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import android.content.Context; import android.net.Uri; +import android.os.Bundle; import android.provider.Settings; import android.util.ArrayMap; @@ -39,6 +43,8 @@ import com.android.settings.homepage.contextualcards.conditional.ConditionHeader import com.android.settings.homepage.contextualcards.conditional.ConditionalContextualCard; import com.android.settings.intelligence.ContextualCardProto; import com.android.settings.slices.CustomSliceRegistry; +import com.android.settingslib.core.lifecycle.Lifecycle; +import com.android.settingslib.core.lifecycle.LifecycleObserver; import org.junit.Before; import org.junit.Test; @@ -62,6 +68,8 @@ public class ContextualCardManagerTest { @Mock ContextualCardUpdateListener mListener; + @Mock + Lifecycle mLifecycle; private Context mContext; private ContextualCardManager mManager; @@ -70,9 +78,71 @@ public class ContextualCardManagerTest { public void setUp() { MockitoAnnotations.initMocks(this); mContext = RuntimeEnvironment.application; - final ContextualCardsFragment fragment = new ContextualCardsFragment(); - mManager = new ContextualCardManager(mContext, fragment.getSettingsLifecycle(), - null /* bundle */); + mManager = new ContextualCardManager(mContext, mLifecycle, null /* bundle */); + } + + @Test + public void constructor_noSavedInstanceState_shouldSetFirstLaunch() { + assertThat(mManager.mIsFirstLaunch).isTrue(); + } + + @Test + public void constructor_noSavedInstanceState_shouldNotHaveSavedCards() { + assertThat(mManager.mSavedCards).isNull(); + } + + @Test + public void constructor_hasSavedInstanceState_shouldContainExpectedSavedCards() { + final Bundle outState = new Bundle(); + final ArrayList cards = getContextualCardList().stream() + .map(ContextualCard::getName) + .collect(Collectors.toCollection(ArrayList::new)); + outState.putStringArrayList(KEY_CONTEXTUAL_CARDS, cards); + + mManager = new ContextualCardManager(mContext, mLifecycle, outState); + + final List actualCards = mManager.mSavedCards.stream().collect(Collectors.toList()); + final List expectedCards = Arrays.asList("test_wifi", "test_flashlight", + "test_connected", "test_gesture", "test_battery"); + assertThat(actualCards).containsExactlyElementsIn(expectedCards); + } + + @Test + public void constructor_hasSettingsCustomCards_shouldSetUpCustomControllers() { + final ControllerRendererPool pool = mManager.getControllerRendererPool(); + + final List actual = pool.getControllers().stream() + .map(ContextualCardController::getCardType) + .collect(Collectors.toList()); + final List expected = Arrays.asList(ContextualCard.CardType.CONDITIONAL, + ContextualCard.CardType.LEGACY_SUGGESTION); + assertThat(actual).containsExactlyElementsIn(expected); + } + + @Test + public void setupController_notLifecycleObserverInstance_shouldNotAttachToLifecycle() { + // 3 invocations in constructor(ContextualCardManager, Conditional and LegacySuggestion) + verify(mLifecycle, times(3)).addObserver(any(LifecycleObserver.class)); + + mManager.setupController(ContextualCard.CardType.SLICE); + + // After 3 times call in the constructor, addObserver() shouldn't be called again. + verify(mLifecycle, times(3)).addObserver(any(LifecycleObserver.class)); + } + + @Test + public void sortCards_shouldBeDescendingOrder() { + final List cards = new ArrayList<>(); + final ContextualCard card1 = + buildContextualCard(TEST_SLICE_URI).mutate().setRankingScore(99.0).build(); + final ContextualCard card2 = + buildContextualCard("context://test/test2").mutate().setRankingScore(88.0).build(); + cards.add(card1); + cards.add(card2); + + final List sortedCards = mManager.sortCards(cards); + + assertThat(sortedCards.get(0).getSliceUri()).isEqualTo(Uri.parse(TEST_SLICE_URI)); } @Test @@ -128,7 +198,7 @@ public class ContextualCardManagerTest { @Test public void getCardLoaderTimeout_noConfiguredTimeout_shouldReturnDefaultTimeout() { - final long timeout = mManager.getCardLoaderTimeout(mContext); + final long timeout = mManager.getCardLoaderTimeout(); assertThat(timeout).isEqualTo(ContextualCardManager.CARD_CONTENT_LOADER_TIMEOUT_MS); } @@ -139,7 +209,7 @@ public class ContextualCardManagerTest { Settings.Global.putLong(mContext.getContentResolver(), ContextualCardManager.KEY_GLOBAL_CARD_LOADER_TIMEOUT, configuredTimeout); - final long timeout = mManager.getCardLoaderTimeout(mContext); + final long timeout = mManager.getCardLoaderTimeout(); assertThat(timeout).isEqualTo(configuredTimeout); } @@ -151,6 +221,7 @@ public class ContextualCardManagerTest { doNothing().when(manager).onContextualCardUpdated(anyMap()); manager.onFinishCardLoading(new ArrayList<>()); + verify(manager).onContextualCardUpdated(nullable(Map.class)); } @@ -161,6 +232,7 @@ public class ContextualCardManagerTest { doNothing().when(manager).onContextualCardUpdated(anyMap()); manager.onFinishCardLoading(new ArrayList<>()); + verify(manager, never()).onContextualCardUpdated(anyMap()); } @@ -177,8 +249,18 @@ public class ContextualCardManagerTest { assertThat(mManager.mContextualCards).hasSize(2); } + @Test + public void onFinishCardLoading_newLaunch_shouldSetIsFirstLaunchBackToFalse() { + assertThat(mManager.mIsFirstLaunch).isTrue(); + + mManager.onFinishCardLoading(new ArrayList<>()); + + assertThat(mManager.mIsFirstLaunch).isFalse(); + } + @Test public void onFinishCardLoading_hasSavedCard_shouldOnlyShowSavedCard() { + // test screen rotation mManager.setListener(mListener); final List savedCardNames = new ArrayList<>(); savedCardNames.add(TEST_SLICE_NAME); @@ -204,7 +286,8 @@ public class ContextualCardManagerTest { } @Test - public void onFinishCardLoading_reloadData_shouldOnlyShowOldCard() { + public void onFinishCardLoading_reloadData_hasNewCard_shouldOnlyShowOldCard() { + // test card dismissal cases mManager.setListener(mListener); mManager.mIsFirstLaunch = false; //old card @@ -228,7 +311,6 @@ public class ContextualCardManagerTest { assertThat(actualCards).containsExactlyElementsIn(expectedCards); } - @Test public void getCardsWithViewType_noSuggestionCards_shouldNotHaveHalfCards() { final List categories = Arrays.asList( @@ -411,6 +493,17 @@ public class ContextualCardManagerTest { } } + @Test + public void getCardsToKeep_hasSavedCard_shouldResetSavedCards() { + final List savedCardNames = new ArrayList<>(); + savedCardNames.add(TEST_SLICE_NAME); + mManager.mSavedCards = savedCardNames; + + mManager.getCardsToKeep(getContextualCardList()); + + assertThat(mManager.mSavedCards).isNull(); + } + private ContextualCard buildContextualCard(String sliceUri) { return new ContextualCard.Builder() .setName(TEST_SLICE_NAME) From dbc2bb9ba5d0572636de5819670ee9786901d2c9 Mon Sep 17 00:00:00 2001 From: Yi-Ling Chuang Date: Wed, 3 Apr 2019 17:28:50 +0800 Subject: [PATCH 15/20] Add tests for ContextualCardsAdapter. Fixes: 114307549 Test: robotests Change-Id: I6ce023bf97c9f7b3c709bda2aa991a349c7aa825 --- .../ContextualCardsAdapter.java | 7 +- .../ContextualCardsAdapterTest.java | 187 ++++++++++++++++++ 2 files changed, 192 insertions(+), 2 deletions(-) create mode 100644 tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardsAdapterTest.java diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardsAdapter.java b/src/com/android/settings/homepage/contextualcards/ContextualCardsAdapter.java index 7be0e8e72a5..bca55666149 100644 --- a/src/com/android/settings/homepage/contextualcards/ContextualCardsAdapter.java +++ b/src/com/android/settings/homepage/contextualcards/ContextualCardsAdapter.java @@ -22,14 +22,15 @@ import android.view.View; import android.view.ViewGroup; import androidx.annotation.LayoutRes; +import androidx.annotation.VisibleForTesting; import androidx.lifecycle.LifecycleOwner; import androidx.recyclerview.widget.DiffUtil; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.android.settings.homepage.contextualcards.conditional.ConditionContextualCardRenderer; -import com.android.settings.homepage.contextualcards.slices.SwipeDismissalDelegate; import com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer; +import com.android.settings.homepage.contextualcards.slices.SwipeDismissalDelegate; import java.util.ArrayList; import java.util.List; @@ -43,9 +44,11 @@ public class ContextualCardsAdapter extends RecyclerView.Adapter mContextualCards; + private final Context mContext; private final ControllerRendererPool mControllerRendererPool; - private final List mContextualCards; private final LifecycleOwner mLifecycleOwner; private RecyclerView mRecyclerView; diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardsAdapterTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardsAdapterTest.java new file mode 100644 index 00000000000..26d6498eaa5 --- /dev/null +++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardsAdapterTest.java @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2019 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.homepage.contextualcards; + +import static com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer.VIEW_TYPE_DEFERRED_SETUP; +import static com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer.VIEW_TYPE_FULL_WIDTH; + +import static com.google.common.truth.Truth.assertThat; + +import android.app.Activity; +import android.net.Uri; +import android.util.ArrayMap; +import android.view.LayoutInflater; +import android.view.View; + +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.android.settings.R; +import com.android.settings.homepage.contextualcards.conditional.ConditionContextualCardRenderer; +import com.android.settings.homepage.contextualcards.conditional.ConditionContextualCardRenderer.ConditionalCardHolder; +import com.android.settings.homepage.contextualcards.conditional.ConditionalContextualCard; +import com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.MockitoAnnotations; +import org.robolectric.Robolectric; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.android.controller.ActivityController; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@RunWith(RobolectricTestRunner.class) +public class ContextualCardsAdapterTest { + + private static final Uri TEST_SLICE_URI = Uri.parse("content://test/test"); + private static final String TEST_SLICE_NAME = "test_name"; + + private Activity mActivity; + private ContextualCardManager mManager; + private ContextualCardsAdapter mAdapter; + + @Before + public void setUp() { + final ActivityController activityController = Robolectric.buildActivity( + Activity.class); + mActivity = activityController.get(); + mActivity.setTheme(R.style.Theme_Settings_Home); + activityController.create(); + final ContextualCardsFragment fragment = new ContextualCardsFragment(); + mManager = new ContextualCardManager(mActivity, fragment.getSettingsLifecycle(), + null /* bundle */); + mAdapter = new ContextualCardsAdapter(mActivity, fragment, mManager); + } + + @Test + public void getItemViewType_sliceFullWidth_shouldReturnSliceFullWidthViewType() { + mAdapter.mContextualCards.addAll(getContextualCardList()); + + final int viewType = mAdapter.getItemViewType(1); + + assertThat(viewType).isEqualTo(SliceContextualCardRenderer.VIEW_TYPE_FULL_WIDTH); + } + + @Test + public void getItemCount_cardList_shouldReturnListSize() { + final List cards = getContextualCardList(); + mAdapter.mContextualCards.addAll(cards); + + final int count = mAdapter.getItemCount(); + + assertThat(count).isEqualTo(cards.size()); + } + + @Test + public void onCreateViewHolder_conditionalCard_shouldReturnConditionalCardHolder() { + final RecyclerView recyclerView = new RecyclerView(mActivity); + recyclerView.setLayoutManager(new LinearLayoutManager(mActivity)); + + final RecyclerView.ViewHolder holder = mAdapter.onCreateViewHolder(recyclerView, + ConditionContextualCardRenderer.VIEW_TYPE_FULL_WIDTH); + + assertThat(holder).isInstanceOf(ConditionalCardHolder.class); + } + + @Test + public void onBindViewHolder_conditionalCard_shouldSetTestTitle() { + mAdapter.mContextualCards.add(buildConditionContextualCard()); + final RecyclerView recyclerView = new RecyclerView(mActivity); + recyclerView.setLayoutManager(new LinearLayoutManager(mActivity)); + final View view = LayoutInflater.from(mActivity) + .inflate(ConditionContextualCardRenderer.VIEW_TYPE_FULL_WIDTH, recyclerView, false); + final ConditionalCardHolder holder = new ConditionalCardHolder(view); + + mAdapter.onBindViewHolder(holder, 0); + + assertThat(holder.title.getText()).isEqualTo("test_title"); + } + + @Test + public void onContextualCardUpdated_emptyList_shouldClearCardList() { + mAdapter.mContextualCards.addAll(getContextualCardList()); + final Map> cardsToUpdate = new ArrayMap<>(); + final List newCardList = new ArrayList<>(); + cardsToUpdate.put(ContextualCard.CardType.DEFAULT, newCardList); + + mAdapter.onContextualCardUpdated(cardsToUpdate); + + assertThat(mAdapter.mContextualCards).isEmpty(); + } + + @Test + public void onContextualCardUpdated_newCardList_shouldUpdateCardList() { + mAdapter.mContextualCards.addAll(getContextualCardList()); + final Map> cardsToUpdate = new ArrayMap<>(); + final List newCardList = new ArrayList<>(); + newCardList.add(buildContextualCard(TEST_SLICE_URI)); + cardsToUpdate.put(ContextualCard.CardType.DEFAULT, newCardList); + + mAdapter.onContextualCardUpdated(cardsToUpdate); + + assertThat(mAdapter.mContextualCards).isEqualTo(newCardList); + } + + @Test + public void onSwiped_shouldSetIsPendingDismissToTrue() { + mAdapter.mContextualCards.addAll(getContextualCardList()); + assertThat(mAdapter.mContextualCards.get(0).isPendingDismiss()).isFalse(); + + mAdapter.onSwiped(0); + + assertThat(mAdapter.mContextualCards.get(0).isPendingDismiss()).isTrue(); + } + + private List getContextualCardList() { + final List cards = new ArrayList<>(); + cards.add(new ContextualCard.Builder() + .setName("test_name") + .setCardType(ContextualCard.CardType.SLICE) + .setSliceUri(TEST_SLICE_URI) + .setViewType(VIEW_TYPE_DEFERRED_SETUP) + .build()); + cards.add(new ContextualCard.Builder() + .setName("test_name_1") + .setCardType(ContextualCard.CardType.SLICE) + .setSliceUri(TEST_SLICE_URI) + .setViewType(SliceContextualCardRenderer.VIEW_TYPE_FULL_WIDTH) + .build()); + return cards; + } + + private ContextualCard buildContextualCard(Uri sliceUri) { + return new ContextualCard.Builder() + .setName(TEST_SLICE_NAME) + .setCardType(ContextualCard.CardType.SLICE) + .setSliceUri(sliceUri) + .setViewType(VIEW_TYPE_FULL_WIDTH) + .build(); + } + + private ContextualCard buildConditionContextualCard() { + return new ConditionalContextualCard.Builder() + .setConditionId(123) + .setName("test_name") + .setTitleText("test_title") + .setViewType(ConditionContextualCardRenderer.VIEW_TYPE_FULL_WIDTH) + .build(); + } +} From fafdfea72cd8f1b7b4f509869d9c89a1a159b81d Mon Sep 17 00:00:00 2001 From: clownshen Date: Mon, 1 Apr 2019 21:27:14 +0800 Subject: [PATCH 16/20] Add Wi-Fi data usage field Add Wi-Fi data usage field at Wi-Fi Setting to show out the total Wi-Fi data usage for user. Bug: 129474341 Test: atest WifiSettingsTest Test: manual test Change-Id: Iad5bee47bd83ed143a2730f042d77907344f4017 --- res/xml/data_usage_wifi.xml | 4 +- res/xml/wifi_settings.xml | 4 ++ .../android/settings/wifi/WifiSettings.java | 12 +++++ .../settings/wifi/WifiSettingsTest.java | 46 +++++++++++++++++++ 4 files changed, 65 insertions(+), 1 deletion(-) diff --git a/res/xml/data_usage_wifi.xml b/res/xml/data_usage_wifi.xml index 693a9315d61..4b7620d379b 100644 --- a/res/xml/data_usage_wifi.xml +++ b/res/xml/data_usage_wifi.xml @@ -16,6 +16,7 @@ + android:title="@string/wifi_data_usage" + settings:searchable="false"/> diff --git a/res/xml/wifi_settings.xml b/res/xml/wifi_settings.xml index 516ac0a9e03..d7c299e6a87 100644 --- a/res/xml/wifi_settings.xml +++ b/res/xml/wifi_settings.xml @@ -41,4 +41,8 @@ android:key="saved_networks" android:title="@string/wifi_saved_access_points_label" android:fragment="com.android.settings.wifi.savedaccesspoints.SavedAccessPointsWifiSettings"/> + + diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java index 7e1a36d9b34..da101485c91 100644 --- a/src/com/android/settings/wifi/WifiSettings.java +++ b/src/com/android/settings/wifi/WifiSettings.java @@ -33,6 +33,7 @@ import android.net.Network; import android.net.NetworkInfo; import android.net.NetworkInfo.State; import android.net.NetworkRequest; +import android.net.NetworkTemplate; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiManager; import android.os.Bundle; @@ -60,6 +61,8 @@ import com.android.settings.SettingsActivity; import com.android.settings.core.FeatureFlags; import com.android.settings.core.SubSettingLauncher; import com.android.settings.dashboard.SummaryLoader; +import com.android.settings.datausage.DataUsageUtils; +import com.android.settings.datausage.DataUsagePreference; import com.android.settings.location.ScanningSettings; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.search.Indexable; @@ -115,6 +118,8 @@ public class WifiSettings extends RestrictedSettingsFragment private static final String PREF_KEY_CONFIGURE_WIFI_SETTINGS = "configure_settings"; private static final String PREF_KEY_SAVED_NETWORKS = "saved_networks"; private static final String PREF_KEY_STATUS_MESSAGE = "wifi_status_message"; + @VisibleForTesting + static final String PREF_KEY_DATA_USAGE = "wifi_data_usage"; private static final int REQUEST_CODE_WIFI_DPP_ENROLLEE_QR_CODE_SCANNER = 0; @@ -181,6 +186,8 @@ public class WifiSettings extends RestrictedSettingsFragment Preference mConfigureWifiSettingsPreference; @VisibleForTesting Preference mSavedNetworksPreference; + @VisibleForTesting + DataUsagePreference mDataUsagePreference; private LinkablePreference mStatusMessagePreference; // For Search @@ -237,6 +244,11 @@ public class WifiSettings extends RestrictedSettingsFragment mAddWifiNetworkPreference = new AddWifiNetworkPreference(getPrefContext()); mStatusMessagePreference = (LinkablePreference) findPreference(PREF_KEY_STATUS_MESSAGE); mUserBadgeCache = new AccessPointPreference.UserBadgeCache(getPackageManager()); + mDataUsagePreference = findPreference(PREF_KEY_DATA_USAGE); + mDataUsagePreference.setVisible(DataUsageUtils.hasWifiRadio(getContext())); + mDataUsagePreference.setTemplate(NetworkTemplate.buildTemplateWifiWildcard(), + 0 /*subId*/, + null /*service*/); } @Override diff --git a/tests/robotests/src/com/android/settings/wifi/WifiSettingsTest.java b/tests/robotests/src/com/android/settings/wifi/WifiSettingsTest.java index c811b0caf99..82e6717bf51 100644 --- a/tests/robotests/src/com/android/settings/wifi/WifiSettingsTest.java +++ b/tests/robotests/src/com/android/settings/wifi/WifiSettingsTest.java @@ -19,8 +19,10 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -29,13 +31,19 @@ import android.app.Activity; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; +import android.content.res.Resources; +import android.os.Bundle; import android.os.PowerManager; +import android.os.UserManager; import android.provider.Settings; +import androidx.fragment.app.FragmentActivity; import androidx.preference.Preference; import com.android.settings.R; +import com.android.settings.datausage.DataUsagePreference; import com.android.settings.search.SearchIndexableRaw; +import com.android.settings.testutils.shadow.ShadowDataUsageUtils; import com.android.settingslib.wifi.WifiTracker; import org.junit.Before; @@ -58,6 +66,8 @@ public class WifiSettingsTest { private WifiTracker mWifiTracker; @Mock private PowerManager mPowerManager; + @Mock + private DataUsagePreference mDataUsagePreference; private Context mContext; private WifiSettings mWifiSettings; @@ -159,4 +169,40 @@ public class WifiSettingsTest { assertThat(mWifiSettings.mAddWifiNetworkPreference.getTitle()).isEqualTo( mContext.getString(R.string.wifi_add_network)); } + + private void setUpForOnCreate() { + final FragmentActivity activity = mock(FragmentActivity.class); + when(mWifiSettings.getActivity()).thenReturn(activity); + final Resources.Theme theme = mContext.getTheme(); + when(activity.getTheme()).thenReturn(theme); + UserManager userManager = mock(UserManager.class); + when(activity.getSystemService(Context.USER_SERVICE)) + .thenReturn(userManager); + + when(mWifiSettings.findPreference(WifiSettings.PREF_KEY_DATA_USAGE)) + .thenReturn(mDataUsagePreference); + } + + @Test + @Config(shadows = {ShadowDataUsageUtils.class}) + public void checkDataUsagePreference_perferenceInvisibleIfWifiNotSupported() { + setUpForOnCreate(); + ShadowDataUsageUtils.IS_WIFI_SUPPORTED = false; + + mWifiSettings.onCreate(Bundle.EMPTY); + + verify(mDataUsagePreference).setVisible(false); + } + + @Test + @Config(shadows = {ShadowDataUsageUtils.class}) + public void checkDataUsagePreference_perferenceVisibleIfWifiSupported() { + setUpForOnCreate(); + ShadowDataUsageUtils.IS_WIFI_SUPPORTED = true; + + mWifiSettings.onCreate(Bundle.EMPTY); + + verify(mDataUsagePreference).setVisible(true); + verify(mDataUsagePreference).setTemplate(any(), eq(0) /*subId*/, eq(null) /*service*/); + } } From 4f379d290bf3d4fe156ae71a826cadb3bb1430f8 Mon Sep 17 00:00:00 2001 From: chen xu Date: Wed, 3 Apr 2019 10:31:19 -0700 Subject: [PATCH 17/20] SDK API doesSwitchModemConfigTriggerReboot Bug: 129424775 Change-Id: I95045f8e2c572a9ee7e8f402568e72ac02a2d1be --- src/com/android/settings/RadioInfo.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/com/android/settings/RadioInfo.java b/src/com/android/settings/RadioInfo.java index 6f6e6c4cfd9..0b7d1bea241 100644 --- a/src/com/android/settings/RadioInfo.java +++ b/src/com/android/settings/RadioInfo.java @@ -41,7 +41,6 @@ import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.provider.Settings; -import android.provider.Telephony; import android.telephony.CarrierConfigManager; import android.telephony.CellIdentityCdma; import android.telephony.CellIdentityGsm; @@ -89,7 +88,6 @@ import com.android.ims.ImsConfig; import com.android.ims.ImsException; import com.android.ims.ImsManager; import com.android.internal.telephony.Phone; -import com.android.internal.telephony.PhoneConfigurationManager; import com.android.internal.telephony.PhoneFactory; import java.io.IOException; @@ -471,7 +469,7 @@ public class RadioInfo extends Activity { if (isDsdsSupported()) { dsdsSwitch.setVisibility(View.VISIBLE); dsdsSwitch.setOnClickListener(v -> { - if (mTelephonyManager.isRebootRequiredForModemConfigChange()) { + if (mTelephonyManager.doesSwitchMultiSimConfigTriggerReboot()) { // Undo the click action until user clicks the confirm dialog. dsdsSwitch.toggle(); showDsdsChangeDialog(); From 03dd39c92aab1594f11ba95f4568e8408d11d94d Mon Sep 17 00:00:00 2001 From: Fan Zhang Date: Tue, 2 Apr 2019 16:41:01 -0700 Subject: [PATCH 18/20] Add a flashlight handler activity to support indexability. Fixes: 128465925 Fixes: 123711093 Test: reindex Change-Id: Ie082e65ee070f6143c4c65db3f70615b16af0e52 --- AndroidManifest.xml | 10 ++- res/values/strings.xml | 3 + .../backup/UserBackupSettingsActivity.java | 2 +- .../flashlight/FlashlightHandleActivity.java | 78 +++++++++++++++++++ 4 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 src/com/android/settings/flashlight/FlashlightHandleActivity.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml index c13068fb29c..d0dcede3c3a 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1032,7 +1032,8 @@ + android:theme="@android:style/Theme.NoDisplay" + android:permission="android.permission.MODIFY_PHONE_STATE"> @@ -2672,6 +2673,13 @@ + + diff --git a/res/values/strings.xml b/res/values/strings.xml index b27e9d0e24d..2448d680c30 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -7156,6 +7156,9 @@ timezone Chat head + + + Flashlight, Light, Torch wifi, wi-fi, toggle, control text message, texting, messages, messaging, default cellular, mobile, cell carrier, wireless, data, 4g,3g, 2g, lte diff --git a/src/com/android/settings/backup/UserBackupSettingsActivity.java b/src/com/android/settings/backup/UserBackupSettingsActivity.java index 4a0b80c67e8..9baa9a3acee 100644 --- a/src/com/android/settings/backup/UserBackupSettingsActivity.java +++ b/src/com/android/settings/backup/UserBackupSettingsActivity.java @@ -112,7 +112,7 @@ public class UserBackupSettingsActivity extends FragmentActivity implements Inde data.screenTitle = context.getString(R.string.settings_label); data.keywords = context.getString(R.string.keywords_backup); data.intentTargetPackage = context.getPackageName(); - data.intentTargetClass = com.android.settings.backup.UserBackupSettingsActivity.class.getName(); + data.intentTargetClass = UserBackupSettingsActivity.class.getName(); data.intentAction = Intent.ACTION_MAIN; data.key = BACKUP_SEARCH_INDEX_KEY; result.add(data); diff --git a/src/com/android/settings/flashlight/FlashlightHandleActivity.java b/src/com/android/settings/flashlight/FlashlightHandleActivity.java new file mode 100644 index 00000000000..0c50f91c896 --- /dev/null +++ b/src/com/android/settings/flashlight/FlashlightHandleActivity.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2019 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.flashlight; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.provider.Settings; + +import com.android.settings.R; +import com.android.settings.search.BaseSearchIndexProvider; +import com.android.settings.search.Indexable; +import com.android.settings.search.SearchIndexableRaw; +import com.android.settingslib.search.SearchIndexable; + +import java.util.ArrayList; +import java.util.List; + +/** + * Headless activity that toggles flashlight state when launched. + */ +@SearchIndexable(forTarget = SearchIndexable.MOBILE) +public class FlashlightHandleActivity extends Activity implements Indexable { + + public static final String EXTRA_FALLBACK_TO_HOMEPAGE = "fallback_to_homepage"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + // Do nothing meaningful in this activity. + // The sole purpose of this activity is to provide a place to index flashlight + // into Settings search. + + // Caller's choice: fallback to homepage, or just exit? + if (getIntent().getBooleanExtra(EXTRA_FALLBACK_TO_HOMEPAGE, false)) { + startActivity(new Intent(Settings.ACTION_SETTINGS)); + } + finish(); + } + + public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new BaseSearchIndexProvider() { + + @Override + public List getRawDataToIndex(Context context, + boolean enabled) { + + final List result = new ArrayList<>(); + + SearchIndexableRaw data = new SearchIndexableRaw(context); + data.title = context.getString(R.string.power_flashlight); + data.screenTitle = context.getString(R.string.power_flashlight); + data.keywords = context.getString(R.string.keywords_flashlight); + data.intentTargetPackage = context.getPackageName(); + data.intentTargetClass = FlashlightHandleActivity.class.getName(); + data.intentAction = Intent.ACTION_MAIN; + data.key = "flashlight"; + result.add(data); + + return result; + } + }; +} From 856b34dabc5d5ab0422afee117a595ef1bff30f3 Mon Sep 17 00:00:00 2001 From: Kevin Chyn Date: Tue, 2 Apr 2019 20:01:05 -0700 Subject: [PATCH 19/20] Set/Get features with new interface Bug: 127382095 Test: Builds Change-Id: Ideb252989a49eec88b8ee7f3ce6ea4f9d85bb3bc --- ...SettingsAttentionPreferenceController.java | 38 ++++++++++++++++++- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java index da7e9b5354f..77e1532aa01 100644 --- a/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java +++ b/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java @@ -18,6 +18,8 @@ package com.android.settings.biometrics.face; import android.content.Context; import android.hardware.face.FaceManager; +import android.hardware.face.FaceManager.GetFeatureCallback; +import android.hardware.face.FaceManager.SetFeatureCallback; import androidx.preference.PreferenceScreen; import androidx.preference.SwitchPreference; @@ -37,6 +39,28 @@ public class FaceSettingsAttentionPreferenceController extends TogglePreferenceC private FaceManager mFaceManager; private SwitchPreference mPreference; + private final SetFeatureCallback mSetFeatureCallback = new SetFeatureCallback() { + @Override + public void onCompleted(boolean success, int feature) { + if (feature == FaceManager.FEATURE_REQUIRE_ATTENTION) { + mPreference.setEnabled(true); + if (!success) { + mPreference.setChecked(!mPreference.isChecked()); + } + } + } + }; + + private final GetFeatureCallback mGetFeatureCallback = new GetFeatureCallback() { + @Override + public void onCompleted(boolean success, int feature, boolean value) { + if (feature == FaceManager.FEATURE_REQUIRE_ATTENTION && success) { + mPreference.setEnabled(true); + mPreference.setChecked(value); + } + } + }; + public FaceSettingsAttentionPreferenceController(Context context, String preferenceKey) { super(context, preferenceKey); mFaceManager = Utils.getFaceManagerOrNull(context); @@ -64,12 +88,22 @@ public class FaceSettingsAttentionPreferenceController extends TogglePreferenceC if (!FaceSettings.isAvailable(mContext)) { return true; } - return mFaceManager.getFeature(FaceManager.FEATURE_REQUIRE_ATTENTION); + // Set to disabled until we know the true value. + mPreference.setEnabled(false); + mFaceManager.getFeature(FaceManager.FEATURE_REQUIRE_ATTENTION, mGetFeatureCallback); + + // Ideally returns a cached value. + return true; } @Override public boolean setChecked(boolean isChecked) { - mFaceManager.setFeature(FaceManager.FEATURE_REQUIRE_ATTENTION, isChecked, mToken); + // Optimistically update state and set to disabled until we know it succeeded. + mPreference.setEnabled(false); + mPreference.setChecked(isChecked); + + mFaceManager.setFeature(FaceManager.FEATURE_REQUIRE_ATTENTION, isChecked, mToken, + mSetFeatureCallback); return true; } From 6db1440a0a1a7aec34cb6c0ea12d864bb5d89138 Mon Sep 17 00:00:00 2001 From: jackqdyulei Date: Tue, 2 Apr 2019 17:27:41 -0700 Subject: [PATCH 20/20] Move telephony method to worker thread Get bug complaining it blocks UI even though it works fine some devices. This CL moves methods to worker thread and keep progressbar shown at least for 1 second, to avoid janky UI. Fixes: 129329645 Test: RunSettingsRoboTests Change-Id: Iee51949b7f6dfe2ede0fc4e6cd0f7b96d7199081 --- .../telephony/NetworkSelectSettings.java | 7 +- .../gsm/AutoSelectPreferenceController.java | 68 +++++++++++++++++-- .../AutoSelectPreferenceControllerTest.java | 28 +++++--- 3 files changed, 82 insertions(+), 21 deletions(-) diff --git a/src/com/android/settings/network/telephony/NetworkSelectSettings.java b/src/com/android/settings/network/telephony/NetworkSelectSettings.java index 47db8756998..d27a0c8a3f8 100644 --- a/src/com/android/settings/network/telephony/NetworkSelectSettings.java +++ b/src/com/android/settings/network/telephony/NetworkSelectSettings.java @@ -96,11 +96,10 @@ public class NetworkSelectSettings extends DashboardFragment { com.android.internal.R.bool.config_enableNewAutoSelectNetworkUI); mSubId = getArguments().getInt(Settings.EXTRA_SUB_ID); - mConnectedPreferenceCategory = - (PreferenceCategory) findPreference(PREF_KEY_CONNECTED_NETWORK_OPERATOR); - mPreferenceCategory = - (PreferenceCategory) findPreference(PREF_KEY_NETWORK_OPERATORS); + mConnectedPreferenceCategory = findPreference(PREF_KEY_CONNECTED_NETWORK_OPERATOR); + mPreferenceCategory = findPreference(PREF_KEY_NETWORK_OPERATORS); mStatusMessagePreference = new Preference(getContext()); + mStatusMessagePreference.setSelectable(false); mSelectedPreference = null; mTelephonyManager = TelephonyManager.from(getContext()).createForSubscriptionId(mSubId); mNetworkScanHelper = new NetworkScanHelper( diff --git a/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.java b/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.java index 7db9df0bfca..adfb1d8ad2d 100644 --- a/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.java +++ b/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.java @@ -16,41 +16,57 @@ package com.android.settings.network.telephony.gsm; +import android.app.ProgressDialog; import android.app.settings.SettingsEnums; import android.content.Context; import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; import android.os.PersistableBundle; +import android.os.SystemClock; import android.provider.Settings; import android.telephony.CarrierConfigManager; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; +import androidx.annotation.VisibleForTesting; import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; +import androidx.preference.SwitchPreference; import com.android.settings.R; import com.android.settings.core.SubSettingLauncher; import com.android.settings.network.telephony.MobileNetworkUtils; import com.android.settings.network.telephony.NetworkSelectSettings; import com.android.settings.network.telephony.TelephonyTogglePreferenceController; +import com.android.settingslib.utils.ThreadUtils; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.TimeUnit; /** * Preference controller for "Auto Select Network" */ public class AutoSelectPreferenceController extends TelephonyTogglePreferenceController { + private static final long MINIMUM_DIALOG_TIME_MILLIS = TimeUnit.SECONDS.toMillis(1); + private final Handler mUiHandler; private int mSubId; private TelephonyManager mTelephonyManager; private boolean mOnlyAutoSelectInHome; private List mListeners; + @VisibleForTesting + ProgressDialog mProgressDialog; + @VisibleForTesting + SwitchPreference mSwitchPreference; public AutoSelectPreferenceController(Context context, String key) { super(context, key); mTelephonyManager = context.getSystemService(TelephonyManager.class); mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; mListeners = new ArrayList<>(); + mUiHandler = new Handler(Looper.getMainLooper()); } @Override @@ -60,6 +76,12 @@ public class AutoSelectPreferenceController extends TelephonyTogglePreferenceCon : CONDITIONALLY_UNAVAILABLE; } + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + mSwitchPreference = screen.findPreference(getPreferenceKey()); + } + @Override public boolean isChecked() { return mTelephonyManager.getNetworkSelectionMode() @@ -86,14 +108,28 @@ public class AutoSelectPreferenceController extends TelephonyTogglePreferenceCon @Override public boolean setChecked(boolean isChecked) { if (isChecked) { - mTelephonyManager.setNetworkSelectionModeAutomatic(); + final long startMillis = SystemClock.elapsedRealtime(); + showAutoSelectProgressBar(); + mSwitchPreference.setEnabled(false); + ThreadUtils.postOnBackgroundThread(() -> { + // set network selection mode in background + mTelephonyManager.setNetworkSelectionModeAutomatic(); + final int mode = mTelephonyManager.getNetworkSelectionMode(); - for (OnNetworkSelectModeListener lsn : mListeners) { - lsn.onNetworkSelectModeChanged(); - } - // Manually check whether it is successfully - return mTelephonyManager.getNetworkSelectionMode() - == TelephonyManager.NETWORK_SELECTION_MODE_AUTO; + //Update UI in UI thread + final long durationMillis = SystemClock.elapsedRealtime() - startMillis; + mUiHandler.postDelayed(() -> { + mSwitchPreference.setEnabled(true); + mSwitchPreference.setChecked( + mode == TelephonyManager.NETWORK_SELECTION_MODE_AUTO); + for (OnNetworkSelectModeListener lsn : mListeners) { + lsn.onNetworkSelectModeChanged(); + } + dismissProgressBar(); + }, + Math.max(MINIMUM_DIALOG_TIME_MILLIS - durationMillis, 0)); + }); + return false; } else { final Bundle bundle = new Bundle(); bundle.putInt(Settings.EXTRA_SUB_ID, mSubId); @@ -126,6 +162,24 @@ public class AutoSelectPreferenceController extends TelephonyTogglePreferenceCon return this; } + private void showAutoSelectProgressBar() { + if (mProgressDialog == null) { + mProgressDialog = new ProgressDialog(mContext); + mProgressDialog.setMessage( + mContext.getResources().getString(R.string.register_automatically)); + mProgressDialog.setCanceledOnTouchOutside(false); + mProgressDialog.setCancelable(false); + mProgressDialog.setIndeterminate(true); + } + mProgressDialog.show(); + } + + private void dismissProgressBar() { + if (mProgressDialog != null && mProgressDialog.isShowing()) { + mProgressDialog.dismiss(); + } + } + /** * Callback when network select mode is changed * diff --git a/tests/robotests/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceControllerTest.java index e9cd731a629..0ae2dc6ec6e 100644 --- a/tests/robotests/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceControllerTest.java @@ -23,13 +23,14 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.app.ProgressDialog; import android.content.Context; import android.os.PersistableBundle; import android.telephony.CarrierConfigManager; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; -import androidx.preference.Preference; +import androidx.preference.SwitchPreference; import com.android.settings.R; @@ -39,6 +40,7 @@ import org.junit.runner.RunWith; import org.mockito.Answers; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; @@ -53,10 +55,12 @@ public class AutoSelectPreferenceControllerTest { private SubscriptionManager mSubscriptionManager; @Mock private CarrierConfigManager mCarrierConfigManager; + @Mock + private ProgressDialog mProgressDialog; private PersistableBundle mCarrierConfig; private AutoSelectPreferenceController mController; - private Preference mPreference; + private SwitchPreference mSwitchPreference; private Context mContext; @Before @@ -75,18 +79,22 @@ public class AutoSelectPreferenceControllerTest { true); when(mCarrierConfigManager.getConfigForSubId(SUB_ID)).thenReturn(mCarrierConfig); - mPreference = new Preference(mContext); + mSwitchPreference = new SwitchPreference(mContext); mController = new AutoSelectPreferenceController(mContext, "auto_select"); + mController.mProgressDialog = mProgressDialog; + mController.mSwitchPreference = mSwitchPreference; mController.init(SUB_ID); } @Test - public void setChecked_isChecked_updateValue() { + public void setChecked_isChecked_showProgressDialog() { when(mTelephonyManager.getNetworkSelectionMode()).thenReturn( TelephonyManager.NETWORK_SELECTION_MODE_AUTO); - assertThat(mController.setChecked(true)).isTrue(); + assertThat(mController.setChecked(true)).isFalse(); + Robolectric.flushBackgroundThreadScheduler(); + verify(mProgressDialog).show(); verify(mTelephonyManager).setNetworkSelectionModeAutomatic(); } @@ -94,9 +102,9 @@ public class AutoSelectPreferenceControllerTest { public void updateState_isRoaming_enabled() { when(mTelephonyManager.getServiceState().getRoaming()).thenReturn(true); - mController.updateState(mPreference); + mController.updateState(mSwitchPreference); - assertThat(mPreference.isEnabled()).isTrue(); + assertThat(mSwitchPreference.isEnabled()).isTrue(); } @Test @@ -104,10 +112,10 @@ public class AutoSelectPreferenceControllerTest { when(mTelephonyManager.getServiceState().getRoaming()).thenReturn(false); doReturn(OPERATOR_NAME).when(mTelephonyManager).getSimOperatorName(); - mController.updateState(mPreference); + mController.updateState(mSwitchPreference); - assertThat(mPreference.isEnabled()).isFalse(); - assertThat(mPreference.getSummary()).isEqualTo( + assertThat(mSwitchPreference.isEnabled()).isFalse(); + assertThat(mSwitchPreference.getSummary()).isEqualTo( mContext.getString(R.string.manual_mode_disallowed_summary, mTelephonyManager.getSimOperatorName())); }