diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 3027c064641..a8fa7cc0a0a 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1032,7 +1032,8 @@ + android:theme="@android:style/Theme.NoDisplay" + android:permission="android.permission.MODIFY_PHONE_STATE"> @@ -2674,6 +2675,13 @@ + + 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"/> 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/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/res/values/strings.xml b/res/values/strings.xml index d8c85d70c7d..b6ff1a83eef 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -7152,6 +7152,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/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/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/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/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(); 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 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/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; } 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/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/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/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); 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/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) { 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/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; + } + }; +} 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/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/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/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/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 = 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; 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/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/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/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/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/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)); + } } 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/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 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/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 */); } } 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) 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(); + } +} 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); 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())); } 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++) { 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*/); + } } 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);