diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 0c33b042b80..b9d62f35879 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -274,10 +274,6 @@ - - - - @@ -315,6 +311,26 @@ android:value="true" /> + + + + + + + + + + @@ -2195,6 +2211,8 @@ + + @@ -2225,6 +2243,7 @@ - + + + + + + diff --git a/res/drawable/ic_color_arrow_right_lt.xml b/res/drawable/ic_color_arrow_right_lt.xml new file mode 100644 index 00000000000..510724386a5 --- /dev/null +++ b/res/drawable/ic_color_arrow_right_lt.xml @@ -0,0 +1,29 @@ + + + + + + + diff --git a/res/drawable/ic_color_page_indicator_focused.xml b/res/drawable/ic_color_page_indicator_focused.xml new file mode 100644 index 00000000000..617335803fb --- /dev/null +++ b/res/drawable/ic_color_page_indicator_focused.xml @@ -0,0 +1,27 @@ + + + + + + diff --git a/res/drawable/ic_color_page_indicator_unfocused.xml b/res/drawable/ic_color_page_indicator_unfocused.xml new file mode 100644 index 00000000000..57a13d82282 --- /dev/null +++ b/res/drawable/ic_color_page_indicator_unfocused.xml @@ -0,0 +1,28 @@ + + + + + + diff --git a/res/drawable/ic_fingerprint_24dp.xml b/res/drawable/ic_fingerprint_24dp.xml index e52f0f5e6bb..12df32de73b 100644 --- a/res/drawable/ic_fingerprint_24dp.xml +++ b/res/drawable/ic_fingerprint_24dp.xml @@ -16,10 +16,11 @@ + android:pathData="M7.3122,4.6691C8.6549,3.9318 10.2631,3.5 11.9979,3.5C13.7326,3.5 15.3409,3.9318 16.6835,4.6691C17.0466,4.8684 17.5026,4.7357 17.7019,4.3727C17.9013,4.0096 17.7686,3.5536 17.4055,3.3543C15.838,2.4935 13.9808,2 11.9979,2C10.0149,2 8.1578,2.4935 6.5902,3.3543C6.2271,3.5536 6.0944,4.0096 6.2938,4.3727C6.4932,4.7357 6.9491,4.8684 7.3122,4.6691ZM6.8614,14.8781C6.862,12.3662 9.0049,10.2292 11.9992,10.2292C14.9939,10.2292 17.137,12.3668 17.137,14.8791V15.0389C17.137,15.735 16.5727,16.2992 15.8767,16.2992C15.3591,16.2992 14.9045,15.9899 14.7153,15.5116L14.7142,15.509L14.0424,13.8294L14.0418,13.828C13.6244,12.7746 12.6064,12.0936 11.4861,12.0936C9.9616,12.0936 8.7258,13.3294 8.7258,14.8539C8.7258,16.4681 9.4592,18.005 10.7237,19.0147L10.7237,19.0147L10.7295,19.0192L11.1164,19.322C11.4426,19.5773 11.914,19.5198 12.1692,19.1936C12.4245,18.8674 12.367,18.396 12.0409,18.1408L11.657,17.8403C10.7531,17.1173 10.2258,16.0141 10.2258,14.8539C10.2258,14.1578 10.79,13.5936 11.4861,13.5936C11.9971,13.5936 12.459,13.9045 12.6475,14.3812L12.6486,14.3838L13.3204,16.0634L13.321,16.0649C13.7377,17.1165 14.7462,17.7992 15.8767,17.7992C17.4012,17.7992 18.637,16.5634 18.637,15.0389V14.8791C18.637,11.4364 15.7165,8.7292 11.9992,8.7292C8.2818,8.7292 5.3614,11.4364 5.3614,14.8791H6.1114C5.3614,14.8791 5.3614,14.8792 5.3614,14.8794L5.3614,14.8797L5.3614,14.8803L5.3614,14.882L5.3614,14.8865L5.3615,14.9002C5.3617,14.9114 5.3619,14.9268 5.3624,14.9459C5.3633,14.9842 5.365,15.0379 5.3684,15.1047C5.3752,15.2382 5.3885,15.4256 5.415,15.6487C5.4674,16.0908 5.5735,16.6934 5.7925,17.3028C5.9326,17.6926 6.3622,17.8951 6.752,17.755C7.1418,17.6149 7.3442,17.1853 7.2041,16.7955C7.0362,16.3283 6.9489,15.8459 6.9046,15.4721C6.8826,15.2873 6.8718,15.134 6.8665,15.0288C6.8638,14.9764 6.8625,14.9362 6.8619,14.9105L6.8615,14.8831L6.8614,14.8791H6.1114C6.8614,14.8791 6.8614,14.879 6.8614,14.8789V14.8781ZM11.9985,6.8631C9.2417,6.8631 6.9467,8.145 5.9123,9.8642C5.6987,10.2192 5.2379,10.3338 4.883,10.1202C4.528,9.9067 4.4134,9.4458 4.627,9.0909C5.9813,6.8401 8.8171,5.3631 11.9985,5.3631C15.18,5.3631 18.0157,6.8401 19.3701,9.0909C19.5836,9.4458 19.469,9.9067 19.1141,10.1202C18.7592,10.3338 18.2983,10.2192 18.0848,9.8642C17.0503,8.145 14.7553,6.8631 11.9985,6.8631ZM8.3064,19.0229C8.0034,18.7404 7.5288,18.7571 7.2463,19.06C6.9639,19.363 6.9805,19.8376 7.2835,20.12C8.5306,21.2828 10.182,22.0037 12.0005,22.0037C13.8189,22.0037 15.4703,21.2828 16.7175,20.12C17.0204,19.8376 17.037,19.363 16.7546,19.06C16.4721,18.7571 15.9975,18.7404 15.6946,19.0229C14.7044,19.9461 13.4119,20.5037 12.0005,20.5037C10.5891,20.5037 9.2965,19.9461 8.3064,19.0229Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> diff --git a/res/layout-land/adb_qrcode_scanner_fragment.xml b/res/layout-land/adb_qrcode_scanner_fragment.xml new file mode 100644 index 00000000000..64515510c44 --- /dev/null +++ b/res/layout-land/adb_qrcode_scanner_fragment.xml @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/layout/adb_qrcode_scanner_fragment.xml b/res/layout/adb_qrcode_scanner_fragment.xml index 5b83cb2f33a..78231554319 100644 --- a/res/layout/adb_qrcode_scanner_fragment.xml +++ b/res/layout/adb_qrcode_scanner_fragment.xml @@ -17,10 +17,11 @@ + android:icon="@drawable/ic_scan_32dp" + app:sudDescriptionText="@string/adb_wireless_qrcode_pairing_description"> - + + + + + - - - - - - - - - - - + android:visibility="invisible"/> @@ -109,4 +92,5 @@ + diff --git a/res/layout/battery_chart_graph.xml b/res/layout/battery_chart_graph.xml index db86693043e..e89c9120c74 100644 --- a/res/layout/battery_chart_graph.xml +++ b/res/layout/battery_chart_graph.xml @@ -40,12 +40,14 @@ android:contentDescription="@string/battery_usage_chart" android:textAppearance="?android:attr/textAppearanceSmall" settings:textColor="?android:attr/textColorSecondary" /> + + android:textColor="?android:attr/textColorSecondary" + android:textSize="14dp" /> diff --git a/res/layout/color_mode_preview.xml b/res/layout/color_mode_preview.xml index 88b8281152f..b8601c927bd 100644 --- a/res/layout/color_mode_preview.xml +++ b/res/layout/color_mode_preview.xml @@ -14,16 +14,55 @@ limitations under the License. --> - - - + android:layout_height="wrap_content"> - + + + + + + + + + + + + + + + + + + diff --git a/res/layout/color_mode_view1.xml b/res/layout/color_mode_view1.xml new file mode 100644 index 00000000000..4bdaec1da0b --- /dev/null +++ b/res/layout/color_mode_view1.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + diff --git a/res/layout/color_mode_view2.xml b/res/layout/color_mode_view2.xml new file mode 100644 index 00000000000..c70fa75c4f2 --- /dev/null +++ b/res/layout/color_mode_view2.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + diff --git a/res/layout/color_mode_view3.xml b/res/layout/color_mode_view3.xml new file mode 100644 index 00000000000..430e3b2fee9 --- /dev/null +++ b/res/layout/color_mode_view3.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + diff --git a/res/layout/notification_history_app_layout.xml b/res/layout/notification_history_app_layout.xml index 8f66628e74b..52c0e421408 100644 --- a/res/layout/notification_history_app_layout.xml +++ b/res/layout/notification_history_app_layout.xml @@ -16,6 +16,7 @@ @@ -78,13 +79,27 @@ android:layout_height="1dp" android:background="?android:attr/listDivider"/> + + + app:layout_constrainedHeight="true" + app:layout_constraintHeight_min="48dp" + app:layout_constraintHeight_max="500dp" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintBottom_toBottomOf="parent"/> + + \ No newline at end of file diff --git a/res/layout/preference_labeled_slider.xml b/res/layout/preference_labeled_slider.xml index 75902cf3949..f120a44adeb 100644 --- a/res/layout/preference_labeled_slider.xml +++ b/res/layout/preference_labeled_slider.xml @@ -37,9 +37,18 @@ android:textAppearance="?android:attr/textAppearanceListItem" android:textColor="?android:attr/textColorPrimary" /> + + Cached (empty) + + + @color/SIM_color_cyan + @color/SIM_color_blue800 + @color/SIM_color_green800 + @color/SIM_color_purple800 + @color/SIM_color_pink800 + @color/SIM_color_orange + + - Teal + Cyan Blue - Indigo + Green Purple Pink - Red + Orange #ffd32f2f + + #ff006D74 + #ff185ABC + #ff137333 + #ff7627bb + #ffb80672 + #ff995400 + - #ff80cbc4 - #ff90caf9 - #ffc5cae9 - #ffe1bee7 - #fff48fb1 - #ffef9a9a + #ff4DD0E1 + #ff8AB4F8 + #ff81C995 + #ffC58AF9 + #ffff8bcb + #fffcad70 @*android:color/surface_header_light diff --git a/res/values/dimens.xml b/res/values/dimens.xml index 1b8179abdaf..7a7588315ef 100755 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -437,7 +437,7 @@ 6dp 1dp 4dp - 3dp + 5dp 1dp 2dp diff --git a/res/values/strings.xml b/res/values/strings.xml index 86c80c3e6d0..f6b0895eca5 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -726,6 +726,7 @@ Screen lock, Find My Device, app security + Face added @@ -879,8 +880,12 @@ Use Face Unlock to unlock your phone + Fingerprint + + + Fingerprint for work Manage fingerprints @@ -1059,10 +1064,16 @@ Follow the fingerprint icon Keep lifting your finger to add the different parts of your fingerprint - - Touch & hold each time the fingerprint icon moves. This helps capture your full fingerprint. - - This helps capture your full fingerprint + + Touch & hold each time the fingerprint icon moves. This helps capture more of your fingerprint. + + Place the tip of your finger on the sensor + + Finally, place the edges of your finger + + Place the side of your fingerprint on the sensor and hold, then switch to the other side + + This helps capture more of your fingerprint Enrolling fingerprint %d percent @@ -5196,7 +5207,7 @@ Create widget and allow access? - After you create the widget, %1$s can access all data it displays. + After you create the widget, the application can access everything displayed.\n\nApplication: %1$s\nWidget: %2$s\n Always allow %1$s to create widgets and access their data @@ -6162,6 +6173,12 @@ Charging temporarily limited To preserve your battery. Learn more. + + Resume charging + + In certain conditions, like high temperatures and long charging periods, charging may be limited to %1$s to help preserve battery health.\n\nWhen those conditions end, your phone will automatically charge normally. + + In certain conditions, like high temperatures and long charging periods, charging may be limited to %1$s to help preserve battery health.\n\nWhen those conditions end, your tablet will automatically charge normally. Because you’ve used your phone more than usual, your battery may run out sooner than it normally would.\n\nApps using most battery: @@ -6624,10 +6641,6 @@ System usage for %s App usage for %s - - am - - pm Total: less than a min @@ -7960,9 +7973,13 @@ 4G Calling - Use LTE services to improve voice and other communications (recommended) + Use LTE services to improve voice calls (recommended) - Use 4G services to improve voice and other communications (recommended) + Use 4G services to improve voice calls (recommended) + + Vo5G + + Use 5G for voice calls volte, advanced calling, 4g calling + + vo5g, vonr, advanced calling, 5g calling + add language, add a language @@ -9335,7 +9355,7 @@ %1$s will be able to read all notifications, including personal information such as contact names and the text of messages you receive. - This app will also be able to dismiss notifications or take action on buttons in notifications, including answering phone calls. + This app will also be able to snooze or dismiss notifications or take action on buttons in notifications, including answering phone calls. \n\nThis will also give the app the ability to turn Do Not Disturb on or off and change related settings. @@ -13230,6 +13250,15 @@ Prevent ringing:\nShortcut available in the volume menu. + + Press & hold duration + + Adjust sensitivity by choosing how long to press & hold the power button + + Short + + Long + Show wallet @@ -13333,8 +13362,6 @@ No SIM Network preferences - - Connect to public networks network connection, internet, wireless, data, wifi, wi-fi, wi fi, cellular, mobile, cell carrier, 4g, 3g, 2g, lte @@ -13367,8 +13394,10 @@ W+ network SIM - + DOWNLOADED SIM + + DOWNLOADED SIMS Active @@ -13552,6 +13581,15 @@ Turn on Game Dashboard shortcut, etc + + Previous + + + Next + + + Color preview + SIM card access request diff --git a/res/xml/adb_wireless_settings.xml b/res/xml/adb_wireless_settings.xml index 8a9cfe6d8cc..7d372070f37 100644 --- a/res/xml/adb_wireless_settings.xml +++ b/res/xml/adb_wireless_settings.xml @@ -42,7 +42,8 @@ + android:layout="@layout/preference_category_no_label" + settings:allowDividerAbove="true"> @@ -59,7 +61,8 @@ + android:title="@string/adb_paired_devices_title" + settings:allowDividerAbove="true"/> + + diff --git a/res/xml/mobile_network_settings.xml b/res/xml/mobile_network_settings.xml index eef22131c4d..7d1ff09ae6d 100644 --- a/res/xml/mobile_network_settings.xml +++ b/res/xml/mobile_network_settings.xml @@ -241,6 +241,19 @@ settings:controller="com.android.settings.network.telephony.CarrierPreferenceController"> + + + - - diff --git a/res/xml/network_provider_settings.xml b/res/xml/network_provider_settings.xml index 9e8befa4cb1..9cab9241534 100644 --- a/res/xml/network_provider_settings.xml +++ b/res/xml/network_provider_settings.xml @@ -70,7 +70,6 @@ diff --git a/res/xml/power_menu_settings.xml b/res/xml/power_menu_settings.xml index caaeb979387..121a2dac472 100644 --- a/res/xml/power_menu_settings.xml +++ b/res/xml/power_menu_settings.xml @@ -22,11 +22,21 @@ android:title="@string/power_menu_long_press_for_assist" android:summary="@string/power_menu_long_press_for_assist_summary" settings:controller="com.android.settings.gestures.LongPressPowerButtonPreferenceController" - /> + /> + + + settings:searchable="false"/> diff --git a/res/xml/security_dashboard_settings.xml b/res/xml/security_dashboard_settings.xml index 23d2b6bf0dd..5b687afc488 100644 --- a/res/xml/security_dashboard_settings.xml +++ b/res/xml/security_dashboard_settings.xml @@ -155,7 +155,7 @@ - diff --git a/src/com/android/settings/AllowBindAppWidgetActivity.java b/src/com/android/settings/AllowBindAppWidgetActivity.java index e7f7a6af203..0272c83702e 100644 --- a/src/com/android/settings/AllowBindAppWidgetActivity.java +++ b/src/com/android/settings/AllowBindAppWidgetActivity.java @@ -19,6 +19,7 @@ package com.android.settings; import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; import android.appwidget.AppWidgetManager; +import android.appwidget.AppWidgetProviderInfo; import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; @@ -122,9 +123,12 @@ public class AllowBindAppWidgetActivity extends AlertActivity implements return; } } + mAppWidgetManager = AppWidgetManager.getInstance(this); + final String widgetLabel = getWidgetLabel(); AlertController.AlertParams ap = mAlertParams; ap.mTitle = getString(R.string.allow_bind_app_widget_activity_allow_bind_title); - ap.mMessage = getString(R.string.allow_bind_app_widget_activity_allow_bind, label); + ap.mMessage = getString(R.string.allow_bind_app_widget_activity_allow_bind, label, + widgetLabel); ap.mPositiveButtonText = getString(R.string.create); ap.mNegativeButtonText = getString(android.R.string.cancel); ap.mPositiveButtonListener = this; @@ -133,18 +137,30 @@ public class AllowBindAppWidgetActivity extends AlertActivity implements (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); ap.mView = inflater.inflate(com.android.internal.R.layout.always_use_checkbox, null); mAlwaysUse = (CheckBox) ap.mView.findViewById(com.android.internal.R.id.alwaysUse); - mAlwaysUse.setText(getString(R.string.allow_bind_app_widget_activity_always_allow_bind, label)); + mAlwaysUse.setText( + getString(R.string.allow_bind_app_widget_activity_always_allow_bind, label)); mAlwaysUse.setPadding(mAlwaysUse.getPaddingLeft(), mAlwaysUse.getPaddingTop(), mAlwaysUse.getPaddingRight(), (int) (mAlwaysUse.getPaddingBottom() + - getResources().getDimension(R.dimen.bind_app_widget_dialog_checkbox_bottom_padding))); + getResources().getDimension( + R.dimen.bind_app_widget_dialog_checkbox_bottom_padding))); - mAppWidgetManager = AppWidgetManager.getInstance(this); mAlwaysUse.setChecked(mAppWidgetManager.hasBindAppWidgetPermission(mCallingPackage, mProfile.getIdentifier())); setupAlert(); } + + private String getWidgetLabel() { + String label = ""; + for (AppWidgetProviderInfo providerInfo : mAppWidgetManager.getInstalledProviders()) { + if (providerInfo.provider.equals(mComponentName)) { + label = providerInfo.loadLabel(getPackageManager()); + break; + } + } + return label; + } } diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java index fdaa7c0a185..cb2cde4a6da 100644 --- a/src/com/android/settings/Settings.java +++ b/src/com/android/settings/Settings.java @@ -90,6 +90,8 @@ public class Settings extends SettingsActivity { public static class WifiSettingsActivity extends SettingsActivity { /* empty */ } public static class WifiSettings2Activity extends SettingsActivity { /* empty */ } public static class NetworkProviderSettingsActivity extends SettingsActivity { /* empty */ } + /** Activity for the Wi-Fi network details settings. */ + public static class WifiDetailsSettingsActivity extends SettingsActivity { /* empty */ } public static class WifiP2pSettingsActivity extends SettingsActivity { /* empty */ } public static class AvailableVirtualKeyboardActivity extends SettingsActivity { /* empty */ } public static class KeyboardLayoutPickerActivity extends SettingsActivity { /* empty */ } diff --git a/src/com/android/settings/TetherSettings.java b/src/com/android/settings/TetherSettings.java index ab1c437271f..1a21b5582a9 100644 --- a/src/com/android/settings/TetherSettings.java +++ b/src/com/android/settings/TetherSettings.java @@ -55,6 +55,7 @@ import com.android.settings.core.FeatureFlags; import com.android.settings.datausage.DataSaverBackend; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.wifi.tether.WifiTetherPreferenceController; +import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedSwitchPreference; import com.android.settingslib.TetherUtil; import com.android.settingslib.search.SearchIndexable; @@ -425,14 +426,16 @@ public class TetherSettings extends RestrictedSettingsFragment private void updateUsbPreference() { boolean usbAvailable = mUsbConnected && !mMassStorageActive; + final RestrictedLockUtils.EnforcedAdmin enforcedAdmin = + checkIfUsbDataSignalingIsDisabled(mContext, UserHandle.myUserId()); - if (usbAvailable) { + if (enforcedAdmin != null) { + mUsbTether.setDisabledByAdmin(enforcedAdmin); + } else if (usbAvailable) { mUsbTether.setEnabled(!mDataSaverEnabled); } else { mUsbTether.setEnabled(false); } - mUsbTether.setDisabledByAdmin( - checkIfUsbDataSignalingIsDisabled(mContext, UserHandle.myUserId())); } @VisibleForTesting diff --git a/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java b/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java index 09bf86a8120..1b270d63b4d 100644 --- a/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java +++ b/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java @@ -226,7 +226,8 @@ public class AppButtonsPreferenceController extends BasePreferenceController imp uninstallDaIntent.putExtra(DeviceAdminAdd.EXTRA_DEVICE_ADMIN_PACKAGE_NAME, packageName); mMetricsFeatureProvider.action(mActivity, - SettingsEnums.ACTION_SETTINGS_UNINSTALL_DEVICE_ADMIN); + SettingsEnums.ACTION_SETTINGS_UNINSTALL_DEVICE_ADMIN, + getPackageNameForMetric()); mFragment.startActivityForResult(uninstallDaIntent, mRequestRemoveDeviceAdmin); return; } @@ -253,7 +254,8 @@ public class AppButtonsPreferenceController extends BasePreferenceController imp mActivity, mAppEntry.info.enabled ? SettingsEnums.ACTION_SETTINGS_DISABLE_APP - : SettingsEnums.ACTION_SETTINGS_ENABLE_APP); + : SettingsEnums.ACTION_SETTINGS_ENABLE_APP, + getPackageNameForMetric()); AsyncTask.execute(new DisableChangerRunnable(mPm, mAppEntry.info.packageName, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT)); } @@ -270,7 +272,9 @@ public class AppButtonsPreferenceController extends BasePreferenceController imp @Override public void onClick(View v) { mMetricsFeatureProvider.action( - mActivity, SettingsEnums.ACTION_APP_INFO_FORCE_STOP); + mActivity, + SettingsEnums.ACTION_APP_INFO_FORCE_STOP, + getPackageNameForMetric()); // force stop if (mPm.isPackageStateProtected(mAppEntry.info.packageName, mUserId)) { RestrictedLockUtils.sendShowAdminSupportDetailsIntent(mActivity, @@ -757,6 +761,14 @@ public class AppButtonsPreferenceController extends BasePreferenceController imp || AppUtils.isMainlineModule(mPm, mAppEntry.info.packageName)); } + private String getPackageNameForMetric() { + final String packageName = + mAppEntry != null && mAppEntry.info != null + ? mAppEntry.info.packageName + : null; + return packageName != null ? packageName : ""; + } + /** * Changes the status of disable/enable for a package */ diff --git a/src/com/android/settings/applications/specialaccess/notificationaccess/NotificationAccessDetails.java b/src/com/android/settings/applications/specialaccess/notificationaccess/NotificationAccessDetails.java index 9e03657883e..da25f17c138 100644 --- a/src/com/android/settings/applications/specialaccess/notificationaccess/NotificationAccessDetails.java +++ b/src/com/android/settings/applications/specialaccess/notificationaccess/NotificationAccessDetails.java @@ -173,7 +173,7 @@ public class NotificationAccessDetails extends DashboardFragment { getActivity(), UserManager.DISALLOW_APPS_CONTROL, mUserId); if (!refreshUi()) { - setIntentAndFinish(true /* appChanged */); + finish(); } Preference apps = getPreferenceScreen().findPreference( use(BridgedAppsLinkPreferenceController.class).getPreferenceKey()); @@ -197,14 +197,6 @@ public class NotificationAccessDetails extends DashboardFragment { } } - protected void setIntentAndFinish(boolean appChanged) { - Log.i(TAG, "appChanged=" + appChanged); - Intent intent = new Intent(); - intent.putExtra(ManageApplications.APP_CHG, appChanged); - SettingsActivity sa = (SettingsActivity) getActivity(); - sa.finishPreferencePanel(Activity.RESULT_OK, intent); - } - protected void retrieveAppEntry() { final Bundle args = getArguments(); mPackageName = (args != null) ? args.getString(ARG_PACKAGE_NAME) : null; @@ -228,7 +220,7 @@ public class NotificationAccessDetails extends DashboardFragment { PackageManager.GET_SIGNING_CERTIFICATES | PackageManager.GET_PERMISSIONS, mUserId); } catch (PackageManager.NameNotFoundException e) { - Log.e(TAG, "Exception when retrieving package:" + mPackageName, e); + // oh well } } diff --git a/src/com/android/settings/applications/specialaccess/zenaccess/ZenAccessDetails.java b/src/com/android/settings/applications/specialaccess/zenaccess/ZenAccessDetails.java index c608b5bf9a0..0a326c6629b 100644 --- a/src/com/android/settings/applications/specialaccess/zenaccess/ZenAccessDetails.java +++ b/src/com/android/settings/applications/specialaccess/zenaccess/ZenAccessDetails.java @@ -53,10 +53,11 @@ public class ZenAccessDetails extends AppInfoWithHeader implements // If this app didn't declare this permission in their manifest, don't bother showing UI. final Set needAccessApps = ZenAccessController.getPackagesRequestingNotificationPolicyAccess(); - if (!needAccessApps.contains(mPackageName)) { - return false; + if (needAccessApps.contains(mPackageName)) { + updatePreference(context, findPreference(SWITCH_PREF_KEY)); + } else { + finish(); } - updatePreference(context, findPreference(SWITCH_PREF_KEY)); return true; } diff --git a/src/com/android/settings/biometrics/ParentalConsentHelper.java b/src/com/android/settings/biometrics/ParentalConsentHelper.java index 6c4004e5c55..e0e082b8fef 100644 --- a/src/com/android/settings/biometrics/ParentalConsentHelper.java +++ b/src/com/android/settings/biometrics/ParentalConsentHelper.java @@ -48,6 +48,10 @@ public class ParentalConsentHelper { private static final String KEY_FINGERPRINT_CONSENT = "fingerprint"; private static final String KEY_IRIS_CONSENT = "iris"; + private static final String KEY_FACE_CONSENT_STRINGS = "face_strings"; + private static final String KEY_FINGERPRINT_CONSENT_STRINGS = "fingerprint_strings"; + private static final String KEY_IRIS_CONSENT_STRINGS = "iris_strings"; + private final boolean mRequireFace; private final boolean mRequireFingerprint; @@ -152,9 +156,14 @@ public class ParentalConsentHelper { public Bundle getConsentResult() { final Bundle result = new Bundle(); result.putBoolean(KEY_FACE_CONSENT, mConsentFace != null ? mConsentFace : false); + result.putIntArray(KEY_FACE_CONSENT_STRINGS, + FaceEnrollParentalConsent.CONSENT_STRING_RESOURCES); result.putBoolean(KEY_FINGERPRINT_CONSENT, mConsentFingerprint != null ? mConsentFingerprint : false); + result.putIntArray(KEY_FINGERPRINT_CONSENT_STRINGS, + FingerprintEnrollParentalConsent.CONSENT_STRING_RESOURCES); result.putBoolean(KEY_IRIS_CONSENT, false); + result.putIntArray(KEY_IRIS_CONSENT_STRINGS, new int[0]); return result; } diff --git a/src/com/android/settings/biometrics/combination/BiometricSettingsAppPreferenceController.java b/src/com/android/settings/biometrics/combination/BiometricSettingsAppPreferenceController.java index 861ff276d7a..2da81641c7d 100644 --- a/src/com/android/settings/biometrics/combination/BiometricSettingsAppPreferenceController.java +++ b/src/com/android/settings/biometrics/combination/BiometricSettingsAppPreferenceController.java @@ -86,4 +86,9 @@ public class BiometricSettingsAppPreferenceController extends TogglePreferenceCo return AVAILABLE_UNSEARCHABLE; } } + + @Override + public final boolean isSliceable() { + return false; + } } diff --git a/src/com/android/settings/biometrics/combination/BiometricSettingsKeyguardPreferenceController.java b/src/com/android/settings/biometrics/combination/BiometricSettingsKeyguardPreferenceController.java index 6fe651f74cc..f6f2d5f2b57 100644 --- a/src/com/android/settings/biometrics/combination/BiometricSettingsKeyguardPreferenceController.java +++ b/src/com/android/settings/biometrics/combination/BiometricSettingsKeyguardPreferenceController.java @@ -68,4 +68,9 @@ public class BiometricSettingsKeyguardPreferenceController extends TogglePrefere } return getRestrictingAdmin() != null ? DISABLED_FOR_USER : AVAILABLE; } + + @Override + public final boolean isSliceable() { + return false; + } } diff --git a/src/com/android/settings/biometrics/face/FaceEnrollParentalConsent.java b/src/com/android/settings/biometrics/face/FaceEnrollParentalConsent.java index 183e05ef29d..54466f90f0a 100644 --- a/src/com/android/settings/biometrics/face/FaceEnrollParentalConsent.java +++ b/src/com/android/settings/biometrics/face/FaceEnrollParentalConsent.java @@ -33,6 +33,21 @@ import com.android.settings.R; */ public class FaceEnrollParentalConsent extends FaceEnrollIntroduction { + /** + * List of string resources to log when recording the result of this activity in gms. + * This must be updated when any strings are added/removed. + */ + public static final int[] CONSENT_STRING_RESOURCES = new int[] { + R.string.security_settings_face_enroll_consent_introduction_title, + R.string.security_settings_face_enroll_introduction_consent_message, + R.string.security_settings_face_enroll_introduction_info_consent_glasses, + R.string.security_settings_face_enroll_introduction_info_consent_looking, + R.string.security_settings_face_enroll_introduction_info_consent_gaze, + R.string.security_settings_face_enroll_introduction_how_consent_message, + R.string.security_settings_face_enroll_introduction_control_consent_title, + R.string.security_settings_face_enroll_introduction_control_consent_message + }; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); diff --git a/src/com/android/settings/biometrics/face/FaceSettings.java b/src/com/android/settings/biometrics/face/FaceSettings.java index 140a3fc469e..62347ac8ced 100644 --- a/src/com/android/settings/biometrics/face/FaceSettings.java +++ b/src/com/android/settings/biometrics/face/FaceSettings.java @@ -44,7 +44,6 @@ import com.android.settings.overlay.FeatureFactory; import com.android.settings.password.ChooseLockSettingsHelper; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settingslib.core.AbstractPreferenceController; -import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.search.SearchIndexable; import java.util.ArrayList; @@ -290,7 +289,7 @@ public class FaceSettings extends DashboardFragment { if (!isFaceHardwareDetected(context)) { return null; } - mControllers = buildPreferenceControllers(context, getSettingsLifecycle()); + mControllers = buildPreferenceControllers(context); // There's no great way of doing this right now :/ for (AbstractPreferenceController controller : mControllers) { if (controller instanceof FaceSettingsAttentionPreferenceController) { @@ -309,8 +308,7 @@ public class FaceSettings extends DashboardFragment { return mControllers; } - private static List buildPreferenceControllers(Context context, - Lifecycle lifecycle) { + private static List buildPreferenceControllers(Context context) { final List controllers = new ArrayList<>(); controllers.add(new FaceSettingsKeyguardPreferenceController(context)); controllers.add(new FaceSettingsAppPreferenceController(context)); @@ -328,7 +326,7 @@ public class FaceSettings extends DashboardFragment { public List createPreferenceControllers( Context context) { if (isFaceHardwareDetected(context)) { - return buildPreferenceControllers(context, null /* lifecycle */); + return buildPreferenceControllers(context); } else { return null; } diff --git a/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java index 0eb823bc4d9..82fa00b864e 100644 --- a/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java +++ b/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java @@ -116,11 +116,6 @@ public class FaceSettingsAttentionPreferenceController extends FaceSettingsPrefe return true; } - @Override - public boolean isSliceable() { - return false; - } - @Override public int getAvailabilityStatus() { return AVAILABLE; diff --git a/src/com/android/settings/biometrics/face/FaceSettingsPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsPreferenceController.java index 3149c353ada..36984a28958 100644 --- a/src/com/android/settings/biometrics/face/FaceSettingsPreferenceController.java +++ b/src/com/android/settings/biometrics/face/FaceSettingsPreferenceController.java @@ -46,4 +46,9 @@ public abstract class FaceSettingsPreferenceController extends TogglePreferenceC return RestrictedLockUtilsInternal.checkIfKeyguardFeaturesDisabled( mContext, DevicePolicyManager.KEYGUARD_DISABLE_FACE, mUserId); } + + @Override + public final boolean isSliceable() { + return false; + } } diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java index 714e210f9f1..748a1dccc0d 100644 --- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java +++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java @@ -46,6 +46,7 @@ import android.view.animation.Interpolator; import android.widget.ProgressBar; import android.widget.TextView; +import androidx.annotation.IntDef; import androidx.appcompat.app.AlertDialog; import com.android.settings.R; @@ -58,6 +59,8 @@ import com.google.android.setupcompat.template.FooterBarMixin; import com.google.android.setupcompat.template.FooterButton; import com.google.android.setupcompat.util.WizardManagerHelper; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.List; /** @@ -69,11 +72,16 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { static final String TAG_SIDECAR = "sidecar"; private static final int PROGRESS_BAR_MAX = 10000; - private static final int FINISH_DELAY = 250; - /** - * Enroll with two center touches before going to guided enrollment. - */ - private static final int NUM_CENTER_TOUCHES = 2; + + private static final int STAGE_UNKNOWN = -1; + private static final int STAGE_CENTER = 0; + private static final int STAGE_GUIDED = 1; + private static final int STAGE_FINGERTIP = 2; + private static final int STAGE_EDGES = 3; + + @IntDef({STAGE_UNKNOWN, STAGE_CENTER, STAGE_GUIDED, STAGE_FINGERTIP, STAGE_EDGES}) + @Retention(RetentionPolicy.SOURCE) + private @interface EnrollStage {} /** * If we don't see progress during this time, we show an error message to remind the users that @@ -100,6 +108,7 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) .build(); + private FingerprintManager mFingerprintManager; private boolean mCanAssumeUdfps; @Nullable private ProgressBar mProgressBar; private ObjectAnimator mProgressAnim; @@ -125,9 +134,9 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - final FingerprintManager fingerprintManager = getSystemService(FingerprintManager.class); + mFingerprintManager = getSystemService(FingerprintManager.class); final List props = - fingerprintManager.getSensorPropertiesInternal(); + mFingerprintManager.getSensorPropertiesInternal(); mCanAssumeUdfps = props.size() == 1 && props.get(0).isAnyUdfpsType(); mAccessibilityManager = getSystemService(AccessibilityManager.class); @@ -149,7 +158,7 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { mIsSetupWizard = WizardManagerHelper.isAnySetupWizard(getIntent()); if (mCanAssumeUdfps) { - updateTitleAndDescription(); + updateTitleAndDescriptionForUdfps(); } else { setHeaderText(R.string.security_settings_fingerprint_enroll_repeat_title); } @@ -273,7 +282,7 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { // UDFPS animations are owned by SystemUI if (progress >= PROGRESS_BAR_MAX) { // Wait for any animations in SysUI to finish, then proceed to next page - getMainThreadHandler().postDelayed(mDelayedFinishRunnable, FINISH_DELAY); + getMainThreadHandler().postDelayed(mDelayedFinishRunnable, getFinishDelay()); } return; } @@ -300,8 +309,55 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { } private void updateTitleAndDescription() { + if (mCanAssumeUdfps) { + updateTitleAndDescriptionForUdfps(); + return; + } + if (mSidecar == null || mSidecar.getEnrollmentSteps() == -1) { - if (mCanAssumeUdfps) { + setDescriptionText(R.string.security_settings_fingerprint_enroll_start_message); + } else { + setDescriptionText(R.string.security_settings_fingerprint_enroll_repeat_message); + } + } + + private void updateTitleAndDescriptionForUdfps() { + switch (getCurrentStage()) { + case STAGE_CENTER: + setHeaderText(R.string.security_settings_fingerprint_enroll_repeat_title); + setDescriptionText(R.string.security_settings_udfps_enroll_start_message); + break; + + case STAGE_GUIDED: + setHeaderText(R.string.security_settings_fingerprint_enroll_repeat_title); + if (mIsAccessibilityEnabled) { + setDescriptionText(R.string.security_settings_udfps_enroll_repeat_a11y_message); + } else { + setDescriptionText(R.string.security_settings_udfps_enroll_repeat_message); + } + break; + + case STAGE_FINGERTIP: + setHeaderText(R.string.security_settings_udfps_enroll_fingertip_title); + if (isStageHalfCompleted()) { + setDescriptionText(R.string.security_settings_fingerprint_enroll_repeat_title); + } else { + setDescriptionText(""); + } + break; + + case STAGE_EDGES: + setHeaderText(R.string.security_settings_udfps_enroll_edge_title); + if (isStageHalfCompleted()) { + setDescriptionText( + R.string.security_settings_fingerprint_enroll_repeat_message); + } else { + setDescriptionText(R.string.security_settings_udfps_enroll_edge_message); + } + break; + + case STAGE_UNKNOWN: + default: // setHeaderText(R.string.security_settings_fingerprint_enroll_udfps_title); // Don't use BiometricEnrollBase#setHeaderText, since that invokes setTitle, // which gets announced for a11y upon entering the page. For UDFPS, we want to @@ -309,41 +365,61 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { getLayout().setHeaderText( R.string.security_settings_fingerprint_enroll_udfps_title); setDescriptionText(R.string.security_settings_udfps_enroll_start_message); - final CharSequence description = getString( R.string.security_settings_udfps_enroll_a11y); getLayout().getHeaderTextView().setContentDescription(description); setTitle(description); - } else { - setDescriptionText(R.string.security_settings_fingerprint_enroll_start_message); - } - } else if (mCanAssumeUdfps && !isCenterEnrollmentComplete()) { - if (mIsSetupWizard) { - setHeaderText(R.string.security_settings_udfps_enroll_title_one_more_time); - } else { - setHeaderText(R.string.security_settings_fingerprint_enroll_repeat_title); - } - setDescriptionText(R.string.security_settings_udfps_enroll_start_message); - } else { - if (mCanAssumeUdfps) { - setHeaderText(R.string.security_settings_fingerprint_enroll_repeat_title); - if (mIsAccessibilityEnabled) { - setDescriptionText(R.string.security_settings_udfps_enroll_repeat_a11y_message); - } else { - setDescriptionText(R.string.security_settings_udfps_enroll_repeat_message); - } - } else { - setDescriptionText(R.string.security_settings_fingerprint_enroll_repeat_message); - } + break; } } - private boolean isCenterEnrollmentComplete() { + @EnrollStage + private int getCurrentStage() { + if (mSidecar == null || mSidecar.getEnrollmentSteps() == -1) { + return STAGE_UNKNOWN; + } + + final int progressSteps = mSidecar.getEnrollmentSteps() - mSidecar.getEnrollmentRemaining(); + if (progressSteps < getStageThresholdSteps(0)) { + return STAGE_CENTER; + } else if (progressSteps < getStageThresholdSteps(1)) { + return STAGE_GUIDED; + } else if (progressSteps < getStageThresholdSteps(2)) { + return STAGE_FINGERTIP; + } else { + return STAGE_EDGES; + } + } + + private boolean isStageHalfCompleted() { + // Prior to first enrollment step. if (mSidecar == null || mSidecar.getEnrollmentSteps() == -1) { return false; } - final int stepsEnrolled = mSidecar.getEnrollmentSteps() - mSidecar.getEnrollmentRemaining(); - return stepsEnrolled >= NUM_CENTER_TOUCHES; + + final int progressSteps = mSidecar.getEnrollmentSteps() - mSidecar.getEnrollmentRemaining(); + int prevThresholdSteps = 0; + for (int i = 0; i < mFingerprintManager.getEnrollStageCount(); i++) { + final int thresholdSteps = getStageThresholdSteps(i); + if (progressSteps >= prevThresholdSteps && progressSteps < thresholdSteps) { + final int adjustedProgress = progressSteps - prevThresholdSteps; + final int adjustedThreshold = thresholdSteps - prevThresholdSteps; + return adjustedProgress >= adjustedThreshold / 2; + } + prevThresholdSteps = thresholdSteps; + } + + // After last enrollment step. + return true; + } + + private int getStageThresholdSteps(int index) { + if (mSidecar == null || mSidecar.getEnrollmentSteps() == -1) { + Log.w(TAG, "getStageThresholdSteps: Enrollment not started yet"); + return 1; + } + return Math.round(mSidecar.getEnrollmentSteps() + * mFingerprintManager.getEnrollStageThreshold(index)); } @Override @@ -489,25 +565,28 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { mOrientationEventListener = null; } - private final Animator.AnimatorListener mProgressAnimationListener - = new Animator.AnimatorListener() { + private final Animator.AnimatorListener mProgressAnimationListener = + new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { } - @Override - public void onAnimationStart(Animator animation) { } + @Override + public void onAnimationRepeat(Animator animation) { } - @Override - public void onAnimationRepeat(Animator animation) { } + @Override + public void onAnimationEnd(Animator animation) { + if (mProgressBar.getProgress() >= PROGRESS_BAR_MAX) { + mProgressBar.postDelayed(mDelayedFinishRunnable, getFinishDelay()); + } + } - @Override - public void onAnimationEnd(Animator animation) { - if (mProgressBar.getProgress() >= PROGRESS_BAR_MAX) { - mProgressBar.postDelayed(mDelayedFinishRunnable, FINISH_DELAY); - } - } + @Override + public void onAnimationCancel(Animator animation) { } + }; - @Override - public void onAnimationCancel(Animator animation) { } - }; + private long getFinishDelay() { + return mCanAssumeUdfps ? 400L : 250L; + } // Give the user a chance to see progress completed before jumping to the next stage. private final Runnable mDelayedFinishRunnable = new Runnable() { diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java index e4de7f1c397..cabe5bfcab1 100644 --- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java +++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java @@ -22,11 +22,9 @@ import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.os.Bundle; import android.view.View; -import android.view.accessibility.AccessibilityManager; import androidx.annotation.Nullable; -import com.airbnb.lottie.LottieAnimationView; import com.android.settings.R; import com.android.settings.Utils; import com.android.settings.biometrics.BiometricEnrollBase; @@ -82,13 +80,6 @@ public class FingerprintEnrollFindSensor extends BiometricEnrollBase implements .setTheme(R.style.SudGlifButton_Primary) .build() ); - - LottieAnimationView lottieAnimationView = findViewById(R.id.illustration_lottie); - AccessibilityManager am = getSystemService(AccessibilityManager.class); - if (am.isEnabled()) { - lottieAnimationView.setAnimation(R.raw.udfps_edu_a11y_lottie); - } - } else { setHeaderText(R.string.security_settings_fingerprint_enroll_find_sensor_title); setDescriptionText(R.string.security_settings_fingerprint_enroll_find_sensor_message); diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollParentalConsent.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollParentalConsent.java index a95a91260d5..22212f27d83 100644 --- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollParentalConsent.java +++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollParentalConsent.java @@ -33,6 +33,20 @@ import com.android.settings.R; */ public class FingerprintEnrollParentalConsent extends FingerprintEnrollIntroduction { + /** + * List of string resources to log when recording the result of this activity in gms. + * This must be updated when any strings are added/removed. + */ + public static final int[] CONSENT_STRING_RESOURCES = new int[] { + R.string.security_settings_fingerprint_enroll_consent_introduction_title, + R.string.security_settings_fingerprint_enroll_introduction_consent_message, + R.string.security_settings_fingerprint_enroll_introduction_footer_title_consent_1, + R.string.security_settings_fingerprint_v2_enroll_introduction_footer_message_consent_2, + R.string.security_settings_fingerprint_v2_enroll_introduction_footer_message_consent_3, + R.string.security_settings_fingerprint_v2_enroll_introduction_footer_message_consent_4, + R.string.security_settings_fingerprint_v2_enroll_introduction_footer_message_consent_5 + }; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); diff --git a/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java b/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java index 5851b506e4e..b60f1b64c38 100644 --- a/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java +++ b/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java @@ -103,8 +103,10 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont new BluetoothAdapter.OnMetadataChangedListener() { @Override public void onMetadataChanged(BluetoothDevice device, int key, byte[] value) { - Log.i(TAG, String.format("Metadata updated in Device %s: %d = %s.", device, key, - value == null ? null : new String(value))); + if (DEBUG) { + Log.d(TAG, String.format("Metadata updated in Device %s: %d = %s.", device, + key, value == null ? null : new String(value))); + } refresh(); } }; diff --git a/src/com/android/settings/connecteddevice/usb/UsbDefaultFragment.java b/src/com/android/settings/connecteddevice/usb/UsbDefaultFragment.java index 97906703069..0abe04259ed 100644 --- a/src/com/android/settings/connecteddevice/usb/UsbDefaultFragment.java +++ b/src/com/android/settings/connecteddevice/usb/UsbDefaultFragment.java @@ -198,8 +198,9 @@ public class UsbDefaultFragment extends RadioButtonPickerFragment { @Override public void onTetheringStarted() { - Log.d(TAG, "onTetheringStarted()"); // Set default usb functions again to make internal data persistent + mCurrentFunctions = mUsbBackend.getCurrentFunctions(); + Log.d(TAG, "onTetheringStarted() : mCurrentFunctions " + mCurrentFunctions); mUsbBackend.setDefaultUsbFunctions(mCurrentFunctions); } diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java index 0ba389ef078..6d7626c8b61 100644 --- a/src/com/android/settings/core/gateway/SettingsGateway.java +++ b/src/com/android/settings/core/gateway/SettingsGateway.java @@ -160,6 +160,7 @@ import com.android.settings.wifi.WifiInfo; import com.android.settings.wifi.WifiSettings; import com.android.settings.wifi.calling.WifiCallingDisclaimerFragment; import com.android.settings.wifi.calling.WifiCallingSettings; +import com.android.settings.wifi.details.WifiNetworkDetailsFragment; import com.android.settings.wifi.p2p.WifiP2pSettings; import com.android.settings.wifi.savedaccesspoints2.SavedAccessPointsWifiSettings2; import com.android.settings.wifi.tether.WifiTetherSettings; @@ -174,6 +175,7 @@ public class SettingsGateway { AdvancedConnectedDeviceDashboardFragment.class.getName(), CreateShortcut.class.getName(), WifiSettings.class.getName(), + WifiNetworkDetailsFragment.class.getName(), ConfigureWifiSettings.class.getName(), SavedAccessPointsWifiSettings2.class.getName(), AllInOneTetherSettings.class.getName(), diff --git a/src/com/android/settings/development/AdbQrCodeActivity.java b/src/com/android/settings/development/AdbQrCodeActivity.java new file mode 100644 index 00000000000..bab20f9754a --- /dev/null +++ b/src/com/android/settings/development/AdbQrCodeActivity.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.development; + +import android.app.settings.SettingsEnums; +import android.content.Intent; +import android.os.Bundle; + +import androidx.fragment.app.FragmentTransaction; + +import com.android.settings.R; +import com.android.settings.wifi.dpp.WifiDppBaseActivity; + +/** + * To scan an ADB QR code to pair a device. + * + * To use intent action {@code ACTION_ADB_QR_CODE_SCANNER}. + */ +public class AdbQrCodeActivity extends WifiDppBaseActivity { + private static final String TAG = "AdbQrCodeActivity"; + + static final String TAG_FRAGMENT_ADB_QR_CODE_SCANNER = "adb_qr_code_scanner_fragment"; + + public static final String ACTION_ADB_QR_CODE_SCANNER = + "android.settings.ADB_QR_CODE_SCANNER"; + + @Override + public int getMetricsCategory() { + return SettingsEnums.SETTINGS_ADB_WIRELESS; + } + + @Override + protected void onCreate(Bundle icicle) { + super.onCreate(icicle); + AdbQrcodeScannerFragment fragment = + (AdbQrcodeScannerFragment) mFragmentManager.findFragmentByTag( + TAG_FRAGMENT_ADB_QR_CODE_SCANNER); + + if (fragment == null) { + fragment = new AdbQrcodeScannerFragment(); + } else { + if (fragment.isVisible()) { + return; + } + + // When the fragment in back stack but not on top of the stack, we can simply pop + // stack because current fragment transactions are arranged in an order + mFragmentManager.popBackStackImmediate(); + return; + } + final FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction(); + + fragmentTransaction.replace(R.id.fragment_container, fragment, + TAG_FRAGMENT_ADB_QR_CODE_SCANNER); + fragmentTransaction.commit(); + } + + @Override + protected void handleIntent(Intent intent) { + } +} diff --git a/src/com/android/settings/development/AdbQrCodePreferenceController.java b/src/com/android/settings/development/AdbQrCodePreferenceController.java index 7c1ae12538d..9085d1ba848 100644 --- a/src/com/android/settings/development/AdbQrCodePreferenceController.java +++ b/src/com/android/settings/development/AdbQrCodePreferenceController.java @@ -16,8 +16,8 @@ package com.android.settings.development; -import android.app.settings.SettingsEnums; import android.content.Context; +import android.content.Intent; import android.debug.IAdbManager; import android.os.RemoteException; import android.os.ServiceManager; @@ -28,7 +28,6 @@ import androidx.fragment.app.Fragment; import androidx.preference.Preference; import com.android.settings.core.BasePreferenceController; -import com.android.settings.core.SubSettingLauncher; /** * Controller for the "Pair device with QR code" preference in the Wireless debugging @@ -68,12 +67,9 @@ public class AdbQrCodePreferenceController extends BasePreferenceController { return false; } - new SubSettingLauncher(preference.getContext()) - .setDestination(AdbQrcodeScannerFragment.class.getName()) - .setSourceMetricsCategory(SettingsEnums.SETTINGS_ADB_WIRELESS) - .setResultListener(mParentFragment, - WirelessDebuggingFragment.PAIRING_DEVICE_REQUEST) - .launch(); + final Intent intent = new Intent(mContext, AdbQrCodeActivity.class); + mParentFragment.startActivityForResult(intent, + WirelessDebuggingFragment.PAIRING_DEVICE_REQUEST); return true; } } diff --git a/src/com/android/settings/development/AdbQrcodeScannerFragment.java b/src/com/android/settings/development/AdbQrcodeScannerFragment.java index 7a30443bca4..1035fbeab33 100644 --- a/src/com/android/settings/development/AdbQrcodeScannerFragment.java +++ b/src/com/android/settings/development/AdbQrcodeScannerFragment.java @@ -44,12 +44,15 @@ import android.widget.TextView; import androidx.annotation.StringRes; import com.android.settings.R; +import com.android.settings.SetupWizardUtils; import com.android.settings.wifi.dpp.AdbQrCode; import com.android.settings.wifi.dpp.WifiDppQrCodeBaseFragment; import com.android.settings.wifi.dpp.WifiNetworkConfig; import com.android.settings.wifi.qrcode.QrCamera; import com.android.settings.wifi.qrcode.QrDecorateView; +import com.google.android.setupdesign.util.ThemeHelper; + /** * Fragment shown when clicking on the "Pair by QR code" preference in * the Wireless Debugging fragment. @@ -144,6 +147,9 @@ public class AdbQrcodeScannerFragment extends WifiDppQrCodeBaseFragment implemen @Override public void onCreate(Bundle savedInstanceState) { + Context context = getContext(); + context.setTheme(SetupWizardUtils.getTheme(context, getActivity().getIntent())); + ThemeHelper.trySetDynamicColor(getContext()); super.onCreate(savedInstanceState); mIntentFilter = new IntentFilter(AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION); @@ -158,6 +164,7 @@ public class AdbQrcodeScannerFragment extends WifiDppQrCodeBaseFragment implemen @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); + mSummary = view.findViewById(R.id.sud_layout_subtitle); mTextureView = (TextureView) view.findViewById(R.id.preview_view); mTextureView.setSurfaceTextureListener(this); @@ -165,8 +172,6 @@ public class AdbQrcodeScannerFragment extends WifiDppQrCodeBaseFragment implemen mDecorateView = view.findViewById(R.id.decorate_view); setProgressBarShown(false); - setHeaderIconImageResource(R.drawable.ic_scan_24dp); - mQrCameraView = view.findViewById(R.id.camera_layout); mVerifyingView = view.findViewById(R.id.verifying_layout); mVerifyingTextView = view.findViewById(R.id.verifying_textview); @@ -181,12 +186,18 @@ public class AdbQrcodeScannerFragment extends WifiDppQrCodeBaseFragment implemen public void onResume() { super.onResume(); + restartCamera(); + mAdbManager = IAdbManager.Stub.asInterface(ServiceManager.getService(Context.ADB_SERVICE)); getActivity().registerReceiver(mReceiver, mIntentFilter); } @Override public void onPause() { + if (mCamera != null) { + mCamera.stop(); + } + super.onPause(); getActivity().unregisterReceiver(mReceiver); @@ -195,8 +206,6 @@ public class AdbQrcodeScannerFragment extends WifiDppQrCodeBaseFragment implemen } catch (RemoteException e) { Log.e(TAG, "Unable to cancel pairing"); } - getActivity().setResult(Activity.RESULT_CANCELED); - getActivity().finish(); } @Override @@ -213,7 +222,6 @@ public class AdbQrcodeScannerFragment extends WifiDppQrCodeBaseFragment implemen public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - getActivity().getActionBar().hide(); // setTitle for TalkBack getActivity().setTitle(R.string.wifi_dpp_scan_qr_code); } diff --git a/src/com/android/settings/display/ColorModePreferenceFragment.java b/src/com/android/settings/display/ColorModePreferenceFragment.java index b8fa0b9a5fd..ce33e673fde 100644 --- a/src/com/android/settings/display/ColorModePreferenceFragment.java +++ b/src/com/android/settings/display/ColorModePreferenceFragment.java @@ -28,12 +28,18 @@ import android.database.ContentObserver; import android.graphics.drawable.Drawable; import android.hardware.display.ColorDisplayManager; import android.net.Uri; +import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.provider.Settings.Secure; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; import androidx.annotation.VisibleForTesting; import androidx.preference.PreferenceScreen; +import androidx.viewpager.widget.PagerAdapter; +import androidx.viewpager.widget.ViewPager; import com.android.settings.R; import com.android.settings.search.BaseSearchIndexProvider; @@ -43,6 +49,7 @@ import com.android.settingslib.widget.CandidateInfo; import com.android.settingslib.widget.LayoutPreference; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; @@ -54,10 +61,25 @@ public class ColorModePreferenceFragment extends RadioButtonPickerFragment { private static final int COLOR_MODE_FALLBACK = COLOR_MODE_NATURAL; + static final String PAGE_VIEWER_SELECTION_INDEX = "page_viewer_selection_index"; + + private static final int DOT_INDICATOR_SIZE = 12; + private static final int DOT_INDICATOR_LEFT_PADDING = 6; + private static final int DOT_INDICATOR_RIGHT_PADDING = 6; + private ContentObserver mContentObserver; private ColorDisplayManager mColorDisplayManager; private Resources mResources; + private View mViewArrowPrevious; + private View mViewArrowNext; + private ViewPager mViewPager; + + private ArrayList mPageList; + + private ImageView[] mDotIndicators; + private View[] mViewPagerImages; + @Override public void onAttach(Context context) { super.onAttach(context); @@ -85,6 +107,16 @@ public class ColorModePreferenceFragment extends RadioButtonPickerFragment { false /* notifyForDescendants */, mContentObserver, mUserId); } + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (savedInstanceState != null) { + final int selectedPosition = savedInstanceState.getInt(PAGE_VIEWER_SELECTION_INDEX); + mViewPager.setCurrentItem(selectedPosition); + updateIndicator(selectedPosition); + } + } + @Override public void onDetach() { if (mContentObserver != null) { @@ -94,6 +126,12 @@ public class ColorModePreferenceFragment extends RadioButtonPickerFragment { super.onDetach(); } + @Override + public void onSaveInstanceState(Bundle outState){ + super.onSaveInstanceState(outState); + outState.putInt(PAGE_VIEWER_SELECTION_INDEX, mViewPager.getCurrentItem()); + } + @Override protected int getPreferenceScreenResId() { return R.xml.color_mode_settings; @@ -105,11 +143,69 @@ public class ColorModePreferenceFragment extends RadioButtonPickerFragment { screen.addPreference(preview); } + @VisibleForTesting + public ArrayList getViewPagerResource() { + return new ArrayList( + Arrays.asList( + R.layout.color_mode_view1, + R.layout.color_mode_view2, + R.layout.color_mode_view3)); + } + + void addViewPager(LayoutPreference preview) { + final ArrayList tmpviewPagerList = getViewPagerResource(); + mViewPager = preview.findViewById(R.id.viewpager); + + mViewPagerImages = new View[3]; + for (int idx = 0; idx < tmpviewPagerList.size(); idx++) { + mViewPagerImages[idx] = + getLayoutInflater().inflate(tmpviewPagerList.get(idx), null /* root */); + } + + mPageList = new ArrayList(); + mPageList.add(mViewPagerImages[0]); + mPageList.add(mViewPagerImages[1]); + mPageList.add(mViewPagerImages[2]); + + mViewPager.setAdapter(new ColorPagerAdapter(mPageList)); + + mViewArrowPrevious = preview.findViewById(R.id.arrow_previous); + mViewArrowPrevious.setOnClickListener(v -> { + final int previousPos = mViewPager.getCurrentItem() - 1; + mViewPager.setCurrentItem(previousPos, true); + }); + + mViewArrowNext = preview.findViewById(R.id.arrow_next); + mViewArrowNext.setOnClickListener(v -> { + final int nextPos = mViewPager.getCurrentItem() + 1; + mViewPager.setCurrentItem(nextPos, true); + }); + + mViewPager.addOnPageChangeListener(createPageListener()); + + final ViewGroup viewGroup = (ViewGroup) preview.findViewById(R.id.viewGroup); + mDotIndicators = new ImageView[mPageList.size()]; + for (int i = 0; i < mPageList.size(); i++) { + final ImageView imageView = new ImageView(getContext()); + final ViewGroup.MarginLayoutParams lp = + new ViewGroup.MarginLayoutParams(DOT_INDICATOR_SIZE, DOT_INDICATOR_SIZE); + lp.setMargins(DOT_INDICATOR_LEFT_PADDING, 0, DOT_INDICATOR_RIGHT_PADDING, 0); + imageView.setLayoutParams(lp); + mDotIndicators[i] = imageView; + + viewGroup.addView(mDotIndicators[i]); + } + + updateIndicator(mViewPager.getCurrentItem()); + } + @Override protected void addStaticPreferences(PreferenceScreen screen) { final LayoutPreference preview = new LayoutPreference(screen.getContext(), R.layout.color_mode_preview); configureAndInstallPreview(preview, screen); + + addViewPager(preview); } @Override @@ -207,6 +303,88 @@ public class ColorModePreferenceFragment extends RadioButtonPickerFragment { } } + private ViewPager.OnPageChangeListener createPageListener() { + return new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled( + int position, float positionOffset, int positionOffsetPixels) { + if (positionOffset != 0) { + for (int idx = 0; idx < mPageList.size(); idx++) { + mViewPagerImages[idx].setVisibility(View.VISIBLE); + } + } else { + mViewPagerImages[position].setContentDescription( + getContext().getString(R.string.colors_viewpager_content_description)); + updateIndicator(position); + } + } + + @Override + public void onPageSelected(int position) {} + + @Override + public void onPageScrollStateChanged(int state) {} + }; + } + + private void updateIndicator(int position) { + for (int i = 0; i < mPageList.size(); i++) { + if (position == i) { + mDotIndicators[i].setBackgroundResource( + R.drawable.ic_color_page_indicator_focused); + + mViewPagerImages[i].setVisibility(View.VISIBLE); + } else { + mDotIndicators[i].setBackgroundResource( + R.drawable.ic_color_page_indicator_unfocused); + + mViewPagerImages[i].setVisibility(View.INVISIBLE); + } + } + + if (position == 0) { + mViewArrowPrevious.setVisibility(View.INVISIBLE); + mViewArrowNext.setVisibility(View.VISIBLE); + } else if (position == (mPageList.size() - 1)) { + mViewArrowPrevious.setVisibility(View.VISIBLE); + mViewArrowNext.setVisibility(View.INVISIBLE); + } else { + mViewArrowPrevious.setVisibility(View.VISIBLE); + mViewArrowNext.setVisibility(View.VISIBLE); + } + } + + static class ColorPagerAdapter extends PagerAdapter { + private final ArrayList mPageViewList; + + ColorPagerAdapter(ArrayList pageViewList) { + mPageViewList = pageViewList; + } + + @Override + public void destroyItem(ViewGroup container, int position, Object object) { + if (mPageViewList.get(position) != null) { + container.removeView(mPageViewList.get(position)); + } + } + + @Override + public Object instantiateItem(ViewGroup container, int position) { + container.addView(mPageViewList.get(position)); + return mPageViewList.get(position); + } + + @Override + public int getCount() { + return mPageViewList.size(); + } + + @Override + public boolean isViewFromObject(View view, Object object) { + return object == view; + } + } + public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = new BaseSearchIndexProvider(R.xml.color_mode_settings) { diff --git a/src/com/android/settings/display/SmartAutoRotatePreferenceController.java b/src/com/android/settings/display/SmartAutoRotatePreferenceController.java index f8d5f96786e..849fbe74cc8 100644 --- a/src/com/android/settings/display/SmartAutoRotatePreferenceController.java +++ b/src/com/android/settings/display/SmartAutoRotatePreferenceController.java @@ -22,6 +22,8 @@ import static android.provider.Settings.Secure.CAMERA_AUTOROTATE; import static com.android.settings.display.SmartAutoRotateController.hasSufficientPermission; import static com.android.settings.display.SmartAutoRotateController.isRotationResolverServiceAvailable; +import android.text.TextUtils; +import android.app.settings.SettingsEnums; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -37,7 +39,9 @@ import androidx.preference.PreferenceScreen; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.view.RotationPolicy; import com.android.settings.R; -import com.android.settings.core.BasePreferenceController; +import com.android.settings.core.TogglePreferenceController; +import com.android.settings.overlay.FeatureFactory; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnStart; import com.android.settingslib.core.lifecycle.events.OnStop; @@ -45,12 +49,10 @@ import com.android.settingslib.core.lifecycle.events.OnStop; /** * SmartAutoRotatePreferenceController provides auto rotate summary in display settings */ -public class SmartAutoRotatePreferenceController extends BasePreferenceController +public class SmartAutoRotatePreferenceController extends TogglePreferenceController implements LifecycleObserver, OnStart, OnStop { - private RotationPolicy.RotationPolicyListener mRotationPolicyListener; - private Preference mPreference; - + private final MetricsFeatureProvider mMetricsFeatureProvider; private final SensorPrivacyManager mPrivacyManager; private final PowerManager mPowerManager; private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @@ -60,12 +62,16 @@ public class SmartAutoRotatePreferenceController extends BasePreferenceControlle } }; + private RotationPolicy.RotationPolicyListener mRotationPolicyListener; + private Preference mPreference; + public SmartAutoRotatePreferenceController(Context context, String preferenceKey) { super(context, preferenceKey); mPrivacyManager = SensorPrivacyManager.getInstance(context); mPrivacyManager .addSensorPrivacyListener(CAMERA, (sensor, enabled) -> refreshSummary(mPreference)); mPowerManager = context.getSystemService(PowerManager.class); + mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider(); } @Override @@ -74,12 +80,28 @@ public class SmartAutoRotatePreferenceController extends BasePreferenceControlle ? AVAILABLE : UNSUPPORTED_ON_DEVICE; } + @Override + public boolean isSliceable() { + return TextUtils.equals(getPreferenceKey(), "auto_rotate"); + } + + @Override + public boolean isPublicSlice() { + return true; + } + @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); mPreference = screen.findPreference(getPreferenceKey()); } + @Override + public void updateState(Preference preference) { + super.updateState(preference); + refreshSummary(mPreference); + } + @Override public void onStart() { mContext.registerReceiver(mReceiver, @@ -89,7 +111,7 @@ public class SmartAutoRotatePreferenceController extends BasePreferenceControlle @Override public void onChange() { if (mPreference != null) { - refreshSummary(mPreference); + updateState(mPreference); } } }; @@ -121,6 +143,20 @@ public class SmartAutoRotatePreferenceController extends BasePreferenceControlle return mPowerManager.isPowerSaveMode(); } + @Override + public boolean isChecked() { + return !RotationPolicy.isRotationLocked(mContext); + } + + @Override + public boolean setChecked(boolean isChecked) { + final boolean isLocked = !isChecked; + mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_ROTATION_LOCK, + isLocked); + RotationPolicy.setRotationLock(mContext, isLocked); + return true; + } + @Override public CharSequence getSummary() { int activeStringId = R.string.auto_rotate_option_off; diff --git a/src/com/android/settings/enterprise/ActionDisabledByAdminDialog.java b/src/com/android/settings/enterprise/ActionDisabledByAdminDialog.java index ce7ad242056..c4bef25b1cc 100644 --- a/src/com/android/settings/enterprise/ActionDisabledByAdminDialog.java +++ b/src/com/android/settings/enterprise/ActionDisabledByAdminDialog.java @@ -58,11 +58,25 @@ public class ActionDisabledByAdminDialog extends Activity return admin; } admin.component = intent.getParcelableExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN); + int userId = intent.getIntExtra(Intent.EXTRA_USER_ID, UserHandle.myUserId()); + + Bundle adminDetails = null; + if (admin.component == null) { + DevicePolicyManager devicePolicyManager = getSystemService(DevicePolicyManager.class); + adminDetails = devicePolicyManager.getEnforcingAdminAndUserDetails(userId, + getRestrictionFromIntent(intent)); + if (adminDetails != null) { + admin.component = adminDetails.getParcelable( + DevicePolicyManager.EXTRA_DEVICE_ADMIN); + } + } if (intent.hasExtra(Intent.EXTRA_USER)) { admin.user = intent.getParcelableExtra(Intent.EXTRA_USER); } else { - int userId = intent.getIntExtra(Intent.EXTRA_USER_ID, UserHandle.myUserId()); + if (adminDetails != null) { + userId = adminDetails.getInt(Intent.EXTRA_USER_ID, UserHandle.myUserId()); + } if (userId == UserHandle.USER_NULL) { admin.user = null; } else { diff --git a/src/com/android/settings/fuelgauge/BatteryChartView.java b/src/com/android/settings/fuelgauge/BatteryChartView.java index a98c644b22a..7bc60b23c38 100644 --- a/src/com/android/settings/fuelgauge/BatteryChartView.java +++ b/src/com/android/settings/fuelgauge/BatteryChartView.java @@ -57,7 +57,8 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick Arrays.asList("SwitchAccessService", "TalkBackService", "JustSpeakService"); private static final int DEFAULT_TRAPEZOID_COUNT = 12; - private static final int DEFAULT_TIMESTAMP_COUNT = 5; + private static final int DEFAULT_TIMESTAMP_COUNT = 4; + private static final int TIMESTAMP_GAPS_COUNT = DEFAULT_TIMESTAMP_COUNT - 1; private static final int DIVIDER_COLOR = Color.parseColor("#CDCCC5"); private static final long UPDATE_STATE_DELAYED_TIME = 500L; @@ -91,7 +92,7 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick new Rect[] {new Rect(), new Rect(), new Rect()}; // For drawing the timestamp information. private final Rect[] mTimestampsBounds = - new Rect[] {new Rect(), new Rect(), new Rect(), new Rect(), new Rect()}; + new Rect[] {new Rect(), new Rect(), new Rect(), new Rect()}; @VisibleForTesting Handler mHandler = new Handler(); @@ -198,13 +199,14 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick if (mTimestamps == null) { mTimestamps = new String[DEFAULT_TIMESTAMP_COUNT]; } - final long timeSlotOffset = DateUtils.HOUR_IN_MILLIS * 6; + final long timeSlotOffset = + DateUtils.HOUR_IN_MILLIS * (/*total 24 hours*/ 24 / TIMESTAMP_GAPS_COUNT); final boolean is24HourFormat = DateFormat.is24HourFormat(getContext()); for (int index = 0; index < DEFAULT_TIMESTAMP_COUNT; index++) { mTimestamps[index] = ConvertUtils.utcToLocalTimeHour( getContext(), - latestTimestamp - (4 - index) * timeSlotOffset, + latestTimestamp - (TIMESTAMP_GAPS_COUNT - index) * timeSlotOffset, is24HourFormat); } requestLayout(); @@ -426,8 +428,9 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick final float[] xOffsets = new float[DEFAULT_TIMESTAMP_COUNT]; final float baselineX = mDividerWidth * .5f; final float offsetX = mDividerWidth + unitWidth; + final int slotBarOffset = (/*total 12 bars*/ 12) / TIMESTAMP_GAPS_COUNT; for (int index = 0; index < DEFAULT_TIMESTAMP_COUNT; index++) { - xOffsets[index] = baselineX + index * offsetX * 3; + xOffsets[index] = baselineX + index * offsetX * slotBarOffset; } drawTimestamp(canvas, xOffsets); } @@ -439,13 +442,15 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick mTimestamps[0], xOffsets[0] - mTimestampsBounds[0].left, getTimestampY(0), mTextPaint); + final int latestIndex = DEFAULT_TIMESTAMP_COUNT - 1; // Draws the last timestamp info. canvas.drawText( - mTimestamps[4], - xOffsets[4] - mTimestampsBounds[4].width() - mTimestampsBounds[4].left, - getTimestampY(4), mTextPaint); + mTimestamps[latestIndex], + xOffsets[latestIndex] - mTimestampsBounds[latestIndex].width() + - mTimestampsBounds[latestIndex].left, + getTimestampY(latestIndex), mTextPaint); // Draws the rest of timestamp info since it is located in the center. - for (int index = 1; index <= 3; index++) { + for (int index = 1; index <= DEFAULT_TIMESTAMP_COUNT - 2; index++) { canvas.drawText( mTimestamps[index], xOffsets[index] - diff --git a/src/com/android/settings/fuelgauge/BatteryInfo.java b/src/com/android/settings/fuelgauge/BatteryInfo.java index 92151c0c58d..d641e7bef3c 100644 --- a/src/com/android/settings/fuelgauge/BatteryInfo.java +++ b/src/com/android/settings/fuelgauge/BatteryInfo.java @@ -25,6 +25,7 @@ import android.os.BatteryStatsManager; import android.os.BatteryUsageStats; import android.os.SystemClock; import android.text.format.Formatter; +import android.util.Log; import android.util.SparseIntArray; import androidx.annotation.NonNull; @@ -42,6 +43,7 @@ import com.android.settingslib.utils.PowerUtil; import com.android.settingslib.utils.StringUtil; public class BatteryInfo { + private static final String TAG = "BatteryInfo"; public CharSequence chargeLabel; public CharSequence remainingLabel; @@ -155,8 +157,15 @@ public class BatteryInfo { if (batteryUsageStats != null) { stats = batteryUsageStats; } else { - stats = context.getSystemService(BatteryStatsManager.class) - .getBatteryUsageStats(); + try { + stats = context.getSystemService(BatteryStatsManager.class) + .getBatteryUsageStats(); + } catch (RuntimeException e) { + Log.e(TAG, "getBatteryInfo() from getBatteryUsageStats()", e); + // Use default BatteryUsageStats. + stats = new BatteryUsageStats.Builder( + new String[0], /* includePowerModels */ false).build(); + } } return getBatteryInfo(context, stats, shortString); } diff --git a/src/com/android/settings/fuelgauge/BatteryOptimizeUtils.java b/src/com/android/settings/fuelgauge/BatteryOptimizeUtils.java index 4a560402667..21d20235f65 100644 --- a/src/com/android/settings/fuelgauge/BatteryOptimizeUtils.java +++ b/src/com/android/settings/fuelgauge/BatteryOptimizeUtils.java @@ -74,6 +74,14 @@ public class BatteryOptimizeUtils { } public void setAppUsageState(AppUsageState state) { + try { + setAppUsageStateInternal(state); + } catch (Exception e) { + Log.e(TAG, "setAppUsageState() is failed for " + mPackageName, e); + } + } + + private void setAppUsageStateInternal(AppUsageState state) { switch (state) { case RESTRICTED: mBatteryUtils.setForceAppStandby(mUid, mPackageName, AppOpsManager.MODE_IGNORED); diff --git a/src/com/android/settings/fuelgauge/BatteryUsageStatsLoader.java b/src/com/android/settings/fuelgauge/BatteryUsageStatsLoader.java index d35ef82b818..2e3200d5835 100644 --- a/src/com/android/settings/fuelgauge/BatteryUsageStatsLoader.java +++ b/src/com/android/settings/fuelgauge/BatteryUsageStatsLoader.java @@ -20,6 +20,7 @@ import android.content.Context; import android.os.BatteryStatsManager; import android.os.BatteryUsageStats; import android.os.BatteryUsageStatsQuery; +import android.util.Log; import com.android.settingslib.utils.AsyncLoaderCompat; @@ -27,6 +28,7 @@ import com.android.settingslib.utils.AsyncLoaderCompat; * Loader to get new {@link BatteryUsageStats} in the background */ public class BatteryUsageStatsLoader extends AsyncLoaderCompat { + private static final String TAG = "BatteryUsageStatsLoader"; private final BatteryStatsManager mBatteryStatsManager; private final boolean mIncludeBatteryHistory; @@ -42,7 +44,14 @@ public class BatteryUsageStatsLoader extends AsyncLoaderCompat> getBatteryHistory(Context context) { return null; diff --git a/src/com/android/settings/fuelgauge/RequestIgnoreBatteryOptimizations.java b/src/com/android/settings/fuelgauge/RequestIgnoreBatteryOptimizations.java index f75fccc0efb..7caad60fa17 100644 --- a/src/com/android/settings/fuelgauge/RequestIgnoreBatteryOptimizations.java +++ b/src/com/android/settings/fuelgauge/RequestIgnoreBatteryOptimizations.java @@ -32,10 +32,11 @@ import com.android.settings.R; public class RequestIgnoreBatteryOptimizations extends AlertActivity implements DialogInterface.OnClickListener { - static final String TAG = "RequestIgnoreBatteryOptimizations"; + private static final String TAG = "RequestIgnoreBatteryOptimizations"; + private static final boolean DEBUG = false; private PowerWhitelistManager mPowerWhitelistManager; - String mPackageName; + private String mPackageName; @Override public void onCreate(Bundle savedInstanceState) { @@ -45,14 +46,14 @@ public class RequestIgnoreBatteryOptimizations extends AlertActivity implements Uri data = getIntent().getData(); if (data == null) { - Log.w(TAG, "No data supplied for IGNORE_BATTERY_OPTIMIZATION_SETTINGS in: " + debugLog("No data supplied for IGNORE_BATTERY_OPTIMIZATION_SETTINGS in: " + getIntent()); finish(); return; } mPackageName = data.getSchemeSpecificPart(); if (mPackageName == null) { - Log.w(TAG, "No data supplied for IGNORE_BATTERY_OPTIMIZATION_SETTINGS in: " + debugLog("No data supplied for IGNORE_BATTERY_OPTIMIZATION_SETTINGS in: " + getIntent()); finish(); return; @@ -60,7 +61,7 @@ public class RequestIgnoreBatteryOptimizations extends AlertActivity implements PowerManager power = getSystemService(PowerManager.class); if (power.isIgnoringBatteryOptimizations(mPackageName)) { - Log.i(TAG, "Not should prompt, already ignoring optimizations: " + mPackageName); + debugLog("Not should prompt, already ignoring optimizations: " + mPackageName); finish(); return; } @@ -69,7 +70,7 @@ public class RequestIgnoreBatteryOptimizations extends AlertActivity implements try { ai = getPackageManager().getApplicationInfo(mPackageName, 0); } catch (PackageManager.NameNotFoundException e) { - Log.w(TAG, "Requested package doesn't exist: " + mPackageName); + debugLog("Requested package doesn't exist: " + mPackageName); finish(); return; } @@ -77,7 +78,7 @@ public class RequestIgnoreBatteryOptimizations extends AlertActivity implements if (getPackageManager().checkPermission( Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, mPackageName) != PackageManager.PERMISSION_GRANTED) { - Log.w(TAG, "Requested package " + mPackageName + " does not hold permission " + debugLog("Requested package " + mPackageName + " does not hold permission " + Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); finish(); return; @@ -105,10 +106,13 @@ public class RequestIgnoreBatteryOptimizations extends AlertActivity implements switch (which) { case BUTTON_POSITIVE: mPowerWhitelistManager.addToWhitelist(mPackageName); - setResult(RESULT_OK); break; case BUTTON_NEGATIVE: break; } } + + private static void debugLog(String debugContent) { + if (DEBUG) Log.w(TAG, debugContent); + } } diff --git a/src/com/android/settings/fuelgauge/batterytip/BatteryTipDialogFragment.java b/src/com/android/settings/fuelgauge/batterytip/BatteryTipDialogFragment.java index 58038cd4bb4..e9e5d68c067 100644 --- a/src/com/android/settings/fuelgauge/batterytip/BatteryTipDialogFragment.java +++ b/src/com/android/settings/fuelgauge/batterytip/BatteryTipDialogFragment.java @@ -20,6 +20,9 @@ import android.app.Dialog; import android.app.settings.SettingsEnums; import android.content.Context; import android.content.DialogInterface; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.BatteryManager; import android.os.Bundle; import android.view.LayoutInflater; @@ -40,6 +43,7 @@ import com.android.settings.fuelgauge.batterytip.tips.HighUsageTip; import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip; import com.android.settings.fuelgauge.batterytip.tips.UnrestrictAppTip; +import java.text.NumberFormat; import java.util.List; /** @@ -50,6 +54,7 @@ public class BatteryTipDialogFragment extends InstrumentedDialogFragment impleme private static final String ARG_BATTERY_TIP = "battery_tip"; private static final String ARG_METRICS_KEY = "metrics_key"; + private static final double CHARGE_LIMIT_LEVEL = 0.8f; @VisibleForTesting BatteryTip mBatteryTip; @@ -138,6 +143,28 @@ public class BatteryTipDialogFragment extends InstrumentedDialogFragment impleme .setPositiveButton(R.string.battery_tip_unrestrict_app_dialog_ok, this) .setNegativeButton(R.string.battery_tip_unrestrict_app_dialog_cancel, null) .create(); + case BatteryTip.TipType.BATTERY_DEFENDER: + mMetricsFeatureProvider.action(context, + SettingsEnums.ACTION_TIP_BATTERY_DEFENDER, mMetricsKey); + final String percentage = + NumberFormat.getPercentInstance().format(CHARGE_LIMIT_LEVEL); + final String message = context.getString( + R.string.battery_tip_limited_temporarily_dialog_msg, percentage); + final boolean isPluggedIn = isPluggedIn(); + final AlertDialog.Builder dialogBuilder = + new AlertDialog.Builder(context) + .setTitle(R.string.battery_tip_limited_temporarily_title) + .setMessage(message); + if (isPluggedIn) { + dialogBuilder + .setPositiveButton( + R.string.battery_tip_limited_temporarily_dialog_resume_charge, + this) + .setNegativeButton(R.string.okay, null); + } else { + dialogBuilder.setPositiveButton(R.string.okay, null); + } + return dialogBuilder.create(); default: throw new IllegalArgumentException("unknown type " + mBatteryTip.getType()); } @@ -163,4 +190,11 @@ public class BatteryTipDialogFragment extends InstrumentedDialogFragment impleme lsn.onBatteryTipHandled(mBatteryTip); } + private boolean isPluggedIn() { + final Intent batteryIntent = getContext().registerReceiver(null /* receiver */, + new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); + return batteryIntent != null && batteryIntent.getIntExtra( + BatteryManager.EXTRA_PLUGGED, 0) != 0; + } + } diff --git a/src/com/android/settings/fuelgauge/batterytip/actions/BatteryDefenderAction.java b/src/com/android/settings/fuelgauge/batterytip/actions/BatteryDefenderAction.java index 24cddcd809e..af16952aa5c 100644 --- a/src/com/android/settings/fuelgauge/batterytip/actions/BatteryDefenderAction.java +++ b/src/com/android/settings/fuelgauge/batterytip/actions/BatteryDefenderAction.java @@ -16,12 +16,11 @@ package com.android.settings.fuelgauge.batterytip.actions; -import android.app.settings.SettingsEnums; import android.content.Intent; -import com.android.settings.R; import com.android.settings.SettingsActivity; -import com.android.settingslib.HelpUtils; +import com.android.settings.overlay.FeatureFactory; +import android.os.AsyncTask; /** * Action to open the Support Center article @@ -34,19 +33,13 @@ public class BatteryDefenderAction extends BatteryTipAction { mSettingsActivity = settingsActivity; } - /** - * Handle the action when user clicks positive button - */ @Override public void handlePositiveAction(int metricsKey) { - mMetricsFeatureProvider.action(mContext, - SettingsEnums.ACTION_TIP_BATTERY_DEFENDER, metricsKey); - final Intent intent = HelpUtils.getHelpIntent( - mContext, - mContext.getString(R.string.help_url_battery_defender), - getClass().getName()); + final Intent intent = FeatureFactory.getFactory(mContext) + .getPowerUsageFeatureProvider(mContext).getResumeChargeIntent(); if (intent != null) { - mSettingsActivity.startActivityForResult(intent, 0); + // Post intent to background thread to avoid UI flaky + AsyncTask.execute(() -> mContext.sendBroadcast(intent)); } } } diff --git a/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryDefenderDetector.java b/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryDefenderDetector.java index dc33026c934..5befa330b0a 100644 --- a/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryDefenderDetector.java +++ b/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryDefenderDetector.java @@ -17,7 +17,6 @@ package com.android.settings.fuelgauge.batterytip.detectors; import com.android.settings.fuelgauge.BatteryInfo; -import com.android.settings.fuelgauge.BatteryUtils; import com.android.settings.fuelgauge.batterytip.tips.BatteryDefenderTip; import com.android.settings.fuelgauge.batterytip.tips.BatteryTip; @@ -34,7 +33,7 @@ public class BatteryDefenderDetector implements BatteryTipDetector { @Override public BatteryTip detect() { final int state = - BatteryUtils.isBatteryDefenderOn(mBatteryInfo) + mBatteryInfo.isOverheated ? BatteryTip.StateType.NEW : BatteryTip.StateType.INVISIBLE; return new BatteryDefenderTip(state); diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/BatteryDefenderTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/BatteryDefenderTip.java index 242be24b44e..a2890ad9b40 100644 --- a/src/com/android/settings/fuelgauge/batterytip/tips/BatteryDefenderTip.java +++ b/src/com/android/settings/fuelgauge/batterytip/tips/BatteryDefenderTip.java @@ -29,7 +29,7 @@ import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; public class BatteryDefenderTip extends BatteryTip { public BatteryDefenderTip(@StateType int state) { - super(TipType.BATTERY_DEFENDER, state, false /* showDialog */); + super(TipType.BATTERY_DEFENDER, state, true /* showDialog */); } private BatteryDefenderTip(Parcel in) { diff --git a/src/com/android/settings/gestures/LongPressPowerButtonPreferenceController.java b/src/com/android/settings/gestures/LongPressPowerButtonPreferenceController.java index 3e9c80fecce..44494eeced2 100644 --- a/src/com/android/settings/gestures/LongPressPowerButtonPreferenceController.java +++ b/src/com/android/settings/gestures/LongPressPowerButtonPreferenceController.java @@ -16,6 +16,11 @@ package com.android.settings.gestures; +import static com.android.settings.gestures.PowerMenuSettingsUtils.LONG_PRESS_POWER_ASSISTANT_VALUE; +import static com.android.settings.gestures.PowerMenuSettingsUtils.LONG_PRESS_POWER_GLOBAL_ACTIONS; +import static com.android.settings.gestures.PowerMenuSettingsUtils.POWER_BUTTON_LONG_PRESS_DEFAULT_VALUE_RESOURCE; +import static com.android.settings.gestures.PowerMenuSettingsUtils.POWER_BUTTON_LONG_PRESS_SETTING; + import android.content.Context; import android.provider.Settings; @@ -33,27 +38,12 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; */ public class LongPressPowerButtonPreferenceController extends TogglePreferenceController { - private static final String POWER_BUTTON_LONG_PRESS_SETTING = - Settings.Global.POWER_BUTTON_LONG_PRESS; private static final String KEY_CHORD_POWER_VOLUME_UP_SETTING = Settings.Global.KEY_CHORD_POWER_VOLUME_UP; private static final String FOOTER_HINT_KEY = "power_menu_power_volume_up_hint"; private static final String ASSIST_SWITCH_KEY = "gesture_power_menu_long_press_for_assist"; - /** - * Values used for long press power button behaviour when Assist setting is enabled. - * - * {@link com.android.server.policy.PhoneWindowManager#LONG_PRESS_POWER_GLOBAL_ACTIONS} for - * source of the value. - */ - @VisibleForTesting - static final int LONG_PRESS_POWER_NO_ACTION = 0; - @VisibleForTesting - static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1; - @VisibleForTesting - static final int LONG_PRESS_POWER_ASSISTANT_VALUE = 5; // Settings.Secure.ASSISTANT - /** * Values used for volume key chord behaviour when Assist setting is enabled. * @@ -67,15 +57,6 @@ public class LongPressPowerButtonPreferenceController extends TogglePreferenceCo @VisibleForTesting static final int KEY_CHORD_POWER_VOLUME_UP_GLOBAL_ACTIONS = 2; - /** - * Value used for long press power button behaviour when the Assist setting is disabled. - * - * If this value matches Assist setting, then it falls back to Global Actions panel or - * power menu, depending on their respective settings. - */ - private static final int POWER_BUTTON_LONG_PRESS_DEFAULT_VALUE_RESOURCE = - com.android.internal.R.integer.config_longPressOnPowerBehavior; - private static final int KEY_CHORD_POWER_VOLUME_UP_DEFAULT_VALUE_RESOURCE = com.android.internal.R.integer.config_keyChordPowerVolumeUp; @@ -101,7 +82,7 @@ public class LongPressPowerButtonPreferenceController extends TogglePreferenceCo @Override public CharSequence getSummary() { - final int powerButtonValue = getPowerButtonValue(); + final int powerButtonValue = PowerMenuSettingsUtils.getPowerButtonSettingValue(mContext); if (powerButtonValue == LONG_PRESS_POWER_ASSISTANT_VALUE) { return mContext.getString(R.string.power_menu_summary_long_press_for_assist_enabled); } else if (powerButtonValue == LONG_PRESS_POWER_GLOBAL_ACTIONS) { @@ -122,7 +103,7 @@ public class LongPressPowerButtonPreferenceController extends TogglePreferenceCo @Override public boolean isChecked() { - return getPowerButtonValue() == LONG_PRESS_POWER_ASSISTANT_VALUE; + return PowerMenuSettingsUtils.isLongPressPowerForAssistEnabled(mContext); } @Override @@ -159,12 +140,6 @@ public class LongPressPowerButtonPreferenceController extends TogglePreferenceCo } } - private int getPowerButtonValue() { - return Settings.Global.getInt(mContext.getContentResolver(), - POWER_BUTTON_LONG_PRESS_SETTING, - mContext.getResources().getInteger(POWER_BUTTON_LONG_PRESS_DEFAULT_VALUE_RESOURCE)); - } - private static boolean isPowerMenuKeyChordEnabled(Context context) { return Settings.Global.getInt(context.getContentResolver(), KEY_CHORD_POWER_VOLUME_UP_SETTING, @@ -179,16 +154,18 @@ public class LongPressPowerButtonPreferenceController extends TogglePreferenceCo POWER_BUTTON_LONG_PRESS_SETTING, LONG_PRESS_POWER_ASSISTANT_VALUE); } - // We need to determine the right disabled value - we set it to device default - // if it's different than Assist, otherwise we fallback to either global actions or power - // menu. + // We need to determine the right disabled value based on the device default + // for long-press power. + + // If the default is to start the assistant, then the fallback is GlobalActions. final int defaultPowerButtonValue = mContext.getResources().getInteger( POWER_BUTTON_LONG_PRESS_DEFAULT_VALUE_RESOURCE); if (defaultPowerButtonValue == LONG_PRESS_POWER_ASSISTANT_VALUE) { return Settings.Global.putInt(mContext.getContentResolver(), - POWER_BUTTON_LONG_PRESS_SETTING, LONG_PRESS_POWER_NO_ACTION); + POWER_BUTTON_LONG_PRESS_SETTING, LONG_PRESS_POWER_GLOBAL_ACTIONS); } + // If the default is something different than Assist, we use that default. return Settings.Global.putInt(mContext.getContentResolver(), POWER_BUTTON_LONG_PRESS_SETTING, defaultPowerButtonValue); } diff --git a/src/com/android/settings/gestures/LongPressPowerSensitivityPreferenceController.java b/src/com/android/settings/gestures/LongPressPowerSensitivityPreferenceController.java new file mode 100644 index 00000000000..a1d681cd475 --- /dev/null +++ b/src/com/android/settings/gestures/LongPressPowerSensitivityPreferenceController.java @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2021 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.gestures; + +import android.content.Context; +import android.database.ContentObserver; +import android.os.Handler; +import android.provider.Settings; + +import androidx.annotation.Nullable; +import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; + +import com.android.settings.core.SliderPreferenceController; +import com.android.settings.widget.LabeledSeekBarPreference; +import com.android.settingslib.core.lifecycle.LifecycleObserver; +import com.android.settingslib.core.lifecycle.events.OnStart; +import com.android.settingslib.core.lifecycle.events.OnStop; + +/** Handles changes to the long press power button sensitivity slider. */ +public class LongPressPowerSensitivityPreferenceController extends + SliderPreferenceController implements + LifecycleObserver, OnStart, OnStop { + + private final ContentObserver mPowerButtonObserver = new ContentObserver(Handler.getMain()) { + @Override + public void onChange(boolean selfChange) { + if (mPreference != null) { + updateState(mPreference); + } + } + }; + + @Nullable + private final int[] mSensitivityValues; + + @Nullable + private LabeledSeekBarPreference mPreference; + + public LongPressPowerSensitivityPreferenceController(Context context, String preferenceKey) { + super(context, preferenceKey); + mSensitivityValues = context.getResources().getIntArray( + com.android.internal.R.array.config_longPressOnPowerDurationSettings); + } + + @Override + public void onStart() { + mContext.getContentResolver().registerContentObserver( + Settings.Global.getUriFor(PowerMenuSettingsUtils.POWER_BUTTON_LONG_PRESS_SETTING), + false, mPowerButtonObserver); + } + + @Override + public void onStop() { + mContext.getContentResolver().unregisterContentObserver(mPowerButtonObserver); + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + mPreference = screen.findPreference(getPreferenceKey()); + if (mPreference != null) { + mPreference.setContinuousUpdates(false); + mPreference.setHapticFeedbackMode( + LabeledSeekBarPreference.HAPTIC_FEEDBACK_MODE_ON_TICKS); + mPreference.setMin(getMin()); + mPreference.setMax(getMax()); + } + } + + @Override + public void updateState(Preference preference) { + super.updateState(preference); + final LabeledSeekBarPreference pref = (LabeledSeekBarPreference) preference; + pref.setEnabled( + isAvailable() && PowerMenuSettingsUtils.isLongPressPowerForAssistEnabled(mContext)); + pref.setProgress(getSliderPosition()); + } + + @Override + public int getAvailabilityStatus() { + if (mSensitivityValues == null || mSensitivityValues.length < 2) { + return UNSUPPORTED_ON_DEVICE; + } + + if (!PowerMenuSettingsUtils.isLongPressPowerForAssistEnabled(mContext)) { + return DISABLED_DEPENDENT_SETTING; + } + + return AVAILABLE; + } + + @Override + public int getSliderPosition() { + return mSensitivityValues == null ? 0 : closestValueIndex(mSensitivityValues, + getCurrentSensitivityValue()); + } + + @Override + public boolean setSliderPosition(int position) { + if (mSensitivityValues == null || position < 0 || position >= mSensitivityValues.length) { + return false; + } + return Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.POWER_BUTTON_LONG_PRESS_DURATION_MS, + mSensitivityValues[position]); + } + + @Override + public int getMax() { + if (mSensitivityValues == null || mSensitivityValues.length == 0) { + return 0; + } + return mSensitivityValues.length - 1; + } + + @Override + public int getMin() { + return 0; + } + + private int getCurrentSensitivityValue() { + return Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.POWER_BUTTON_LONG_PRESS_DURATION_MS, + mContext.getResources().getInteger( + com.android.internal.R.integer.config_longPressOnPowerDurationMs)); + } + + private static int closestValueIndex(int[] values, int needle) { + int minDistance = Integer.MAX_VALUE; + int valueIndex = 0; + for (int i = 0; i < values.length; i++) { + int diff = Math.abs(values[i] - needle); + if (diff < minDistance) { + minDistance = diff; + valueIndex = i; + } + } + return valueIndex; + } +} diff --git a/src/com/android/settings/gestures/OneHandedActionPullDownPrefController.java b/src/com/android/settings/gestures/OneHandedActionPullDownPrefController.java index e17165b1856..26b37630d2b 100644 --- a/src/com/android/settings/gestures/OneHandedActionPullDownPrefController.java +++ b/src/com/android/settings/gestures/OneHandedActionPullDownPrefController.java @@ -93,7 +93,8 @@ public class OneHandedActionPullDownPrefController extends BasePreferenceControl return; } if (uri.equals(OneHandedSettingsUtils.ONE_HANDED_MODE_ENABLED_URI) - || uri.equals(OneHandedSettingsUtils.SHORTCUT_ENABLED_URI)) { + || uri.equals(OneHandedSettingsUtils.SOFTWARE_SHORTCUT_ENABLED_URI) + || uri.equals(OneHandedSettingsUtils.HARDWARE_SHORTCUT_ENABLED_URI)) { mPreference.setEnabled(OneHandedSettingsUtils.canEnableController(mContext)); } else if (uri.equals(OneHandedSettingsUtils.SHOW_NOTIFICATION_ENABLED_URI)) { updateState(mPreference); diff --git a/src/com/android/settings/gestures/OneHandedActionShowNotificationPrefController.java b/src/com/android/settings/gestures/OneHandedActionShowNotificationPrefController.java index 9f56a14afd6..524c135af5e 100644 --- a/src/com/android/settings/gestures/OneHandedActionShowNotificationPrefController.java +++ b/src/com/android/settings/gestures/OneHandedActionShowNotificationPrefController.java @@ -93,7 +93,8 @@ public class OneHandedActionShowNotificationPrefController extends BasePreferenc return; } if (uri.equals(OneHandedSettingsUtils.ONE_HANDED_MODE_ENABLED_URI) - || uri.equals(OneHandedSettingsUtils.SHORTCUT_ENABLED_URI)) { + || uri.equals(OneHandedSettingsUtils.SOFTWARE_SHORTCUT_ENABLED_URI) + || uri.equals(OneHandedSettingsUtils.HARDWARE_SHORTCUT_ENABLED_URI)) { mPreference.setEnabled(OneHandedSettingsUtils.canEnableController(mContext)); } else if (uri.equals(OneHandedSettingsUtils.SHOW_NOTIFICATION_ENABLED_URI)) { updateState(mPreference); diff --git a/src/com/android/settings/gestures/OneHandedSettingsUtils.java b/src/com/android/settings/gestures/OneHandedSettingsUtils.java index f058689912b..04898dc0219 100644 --- a/src/com/android/settings/gestures/OneHandedSettingsUtils.java +++ b/src/com/android/settings/gestures/OneHandedSettingsUtils.java @@ -27,6 +27,7 @@ import android.os.Looper; import android.os.SystemProperties; import android.os.UserHandle; import android.provider.Settings; +import android.text.TextUtils; import androidx.annotation.VisibleForTesting; @@ -45,8 +46,10 @@ public class OneHandedSettingsUtils { Settings.Secure.getUriFor(Settings.Secure.ONE_HANDED_MODE_ENABLED); static final Uri SHOW_NOTIFICATION_ENABLED_URI = Settings.Secure.getUriFor(Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED); - static final Uri SHORTCUT_ENABLED_URI = + static final Uri SOFTWARE_SHORTCUT_ENABLED_URI = Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS); + static final Uri HARDWARE_SHORTCUT_ENABLED_URI = + Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE); public enum OneHandedTimeout { NEVER(0), SHORT(4), MEDIUM(8), LONG(12); @@ -238,9 +241,20 @@ public class OneHandedSettingsUtils { * @return true if user enabled one-handed shortcut in settings, false otherwise. */ public static boolean getShortcutEnabled(Context context) { - final String targets = Settings.Secure.getStringForUser(context.getContentResolver(), + // Checks SOFTWARE_SHORTCUT_KEY + final String targetsSW = Settings.Secure.getStringForUser(context.getContentResolver(), Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, sCurrentUserId); - return targets != null ? targets.contains(ONE_HANDED_MODE_TARGET_NAME) : false; + if (!TextUtils.isEmpty(targetsSW) && targetsSW.contains(ONE_HANDED_MODE_TARGET_NAME)) { + return true; + } + + // Checks HARDWARE_SHORTCUT_KEY + final String targetsHW = Settings.Secure.getStringForUser(context.getContentResolver(), + Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, sCurrentUserId); + if (!TextUtils.isEmpty(targetsHW) && targetsHW.contains(ONE_HANDED_MODE_TARGET_NAME)) { + return true; + } + return false; } /** @@ -285,7 +299,8 @@ public class OneHandedSettingsUtils { final ContentResolver resolver = mContext.getContentResolver(); resolver.registerContentObserver(ONE_HANDED_MODE_ENABLED_URI, true, this); resolver.registerContentObserver(SHOW_NOTIFICATION_ENABLED_URI, true, this); - resolver.registerContentObserver(SHORTCUT_ENABLED_URI, true, this); + resolver.registerContentObserver(SOFTWARE_SHORTCUT_ENABLED_URI, true, this); + resolver.registerContentObserver(HARDWARE_SHORTCUT_ENABLED_URI, true, this); } @Override diff --git a/src/com/android/settings/gestures/PowerMenuPreferenceController.java b/src/com/android/settings/gestures/PowerMenuPreferenceController.java index 0d5f810d884..b4f97aa3ff2 100644 --- a/src/com/android/settings/gestures/PowerMenuPreferenceController.java +++ b/src/com/android/settings/gestures/PowerMenuPreferenceController.java @@ -16,30 +16,23 @@ package com.android.settings.gestures; -import android.content.Context; -import android.provider.Settings; +import static com.android.settings.gestures.PowerMenuSettingsUtils.LONG_PRESS_POWER_ASSISTANT_VALUE; +import static com.android.settings.gestures.PowerMenuSettingsUtils.LONG_PRESS_POWER_GLOBAL_ACTIONS; + +import android.content.Context; -import com.android.internal.annotations.VisibleForTesting; import com.android.settings.R; import com.android.settings.core.BasePreferenceController; public class PowerMenuPreferenceController extends BasePreferenceController { - private static final String POWER_BUTTON_LONG_PRESS_SETTING = - Settings.Global.POWER_BUTTON_LONG_PRESS; - - @VisibleForTesting - static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1; - @VisibleForTesting - static final int LONG_PRESS_POWER_ASSISTANT_VALUE = 5; - public PowerMenuPreferenceController(Context context, String key) { super(context, key); } @Override public CharSequence getSummary() { - final int powerButtonValue = getPowerButtonLongPressValue(mContext); + final int powerButtonValue = PowerMenuSettingsUtils.getPowerButtonSettingValue(mContext); if (powerButtonValue == LONG_PRESS_POWER_ASSISTANT_VALUE) { return mContext.getText(R.string.power_menu_summary_long_press_for_assist_enabled); } else if (powerButtonValue == LONG_PRESS_POWER_GLOBAL_ACTIONS) { @@ -60,11 +53,4 @@ public class PowerMenuPreferenceController extends BasePreferenceController { return mContext.getResources().getBoolean( com.android.internal.R.bool.config_longPressOnPowerForAssistantSettingAvailable); } - - private static int getPowerButtonLongPressValue(Context context) { - return Settings.Global.getInt(context.getContentResolver(), - POWER_BUTTON_LONG_PRESS_SETTING, - context.getResources().getInteger( - com.android.internal.R.integer.config_longPressOnPowerBehavior)); - } } diff --git a/src/com/android/settings/gestures/PowerMenuSettingsUtils.java b/src/com/android/settings/gestures/PowerMenuSettingsUtils.java new file mode 100644 index 00000000000..444b7c1e565 --- /dev/null +++ b/src/com/android/settings/gestures/PowerMenuSettingsUtils.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2021 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.gestures; + +import android.content.Context; +import android.provider.Settings; + +/** Common code for long press power settings shared between controllers. */ +final class PowerMenuSettingsUtils { + + /** + * Setting storing the current behaviour of long press power. + */ + public static final String POWER_BUTTON_LONG_PRESS_SETTING = + Settings.Global.POWER_BUTTON_LONG_PRESS; + + /** + * Value used for long press power button behaviour when the Assist setting is disabled. + * + * If this value matches Assist setting, then it falls back to Global Actions panel or + * power menu, depending on their respective settings. + */ + public static final int POWER_BUTTON_LONG_PRESS_DEFAULT_VALUE_RESOURCE = + com.android.internal.R.integer.config_longPressOnPowerBehavior; + + /** + * Values used for long press power button behaviour when Assist setting is enabled. + * + * {@link com.android.server.policy.PhoneWindowManager#LONG_PRESS_POWER_GLOBAL_ACTIONS} for + * source of the value. + */ + static final int LONG_PRESS_POWER_NO_ACTION = 0; + static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1; + static final int LONG_PRESS_POWER_ASSISTANT_VALUE = 5; // Settings.Secure.ASSISTANT + + /** + * @return current value of power button behaviour. + */ + public static int getPowerButtonSettingValue(Context context) { + return Settings.Global.getInt(context.getContentResolver(), + POWER_BUTTON_LONG_PRESS_SETTING, + context.getResources().getInteger(POWER_BUTTON_LONG_PRESS_DEFAULT_VALUE_RESOURCE)); + } + + /** + * @return true if long press power for assist is currently enabled. + */ + public static boolean isLongPressPowerForAssistEnabled(Context context) { + return getPowerButtonSettingValue(context) == LONG_PRESS_POWER_ASSISTANT_VALUE; + } + + private PowerMenuSettingsUtils() { + } +} diff --git a/src/com/android/settings/network/EraseEuiccDataDialogFragment.java b/src/com/android/settings/network/EraseEuiccDataDialogFragment.java index a141f0c7bab..819d3b1fc6e 100644 --- a/src/com/android/settings/network/EraseEuiccDataDialogFragment.java +++ b/src/com/android/settings/network/EraseEuiccDataDialogFragment.java @@ -32,7 +32,9 @@ import androidx.fragment.app.FragmentManager; import com.android.settings.R; import com.android.settings.core.instrumentation.InstrumentedDialogFragment; +import com.android.settings.network.helper.ConfirmationSimDeletionPredicate; import com.android.settings.system.ResetDashboardFragment; +import com.android.settings.wifi.dpp.WifiDppUtils; public class EraseEuiccDataDialogFragment extends InstrumentedDialogFragment implements DialogInterface.OnClickListener { @@ -73,13 +75,24 @@ public class EraseEuiccDataDialogFragment extends InstrumentedDialogFragment imp } if (which == DialogInterface.BUTTON_POSITIVE) { - AsyncTask.execute(new Runnable() { - @Override - public void run() { - RecoverySystem.wipeEuiccData( - getContext(), PACKAGE_NAME_EUICC_DATA_MANAGEMENT_CALLBACK); - } - }); + if (ConfirmationSimDeletionPredicate.getSingleton().test(getContext())) { + // Create a "verify it's you" verification over keyguard + // when "erase" button been pressed. + // This might protect from erasing by some automation process. + WifiDppUtils.showLockScreen(getContext(), () -> runAsyncWipe()); + } else { + runAsyncWipe(); + } } } + + private void runAsyncWipe() { + AsyncTask.execute(new Runnable() { + @Override + public void run() { + RecoverySystem.wipeEuiccData( + getContext(), PACKAGE_NAME_EUICC_DATA_MANAGEMENT_CALLBACK); + } + }); + } } diff --git a/src/com/android/settings/network/MobileNetworkListFragment.java b/src/com/android/settings/network/MobileNetworkListFragment.java index 1767c1c8039..03e5a010631 100644 --- a/src/com/android/settings/network/MobileNetworkListFragment.java +++ b/src/com/android/settings/network/MobileNetworkListFragment.java @@ -65,14 +65,12 @@ public class MobileNetworkListFragment extends DashboardFragment { if (Utils.isProviderModelEnabled(getContext())) { NetworkProviderSimsCategoryController simCategoryPrefCtrl = - new NetworkProviderSimsCategoryController(context, KEY_PREFERENCE_CATEGORY_SIM); - simCategoryPrefCtrl.init(getSettingsLifecycle()); + new NetworkProviderSimsCategoryController(context, KEY_PREFERENCE_CATEGORY_SIM, + getSettingsLifecycle()); controllers.add(simCategoryPrefCtrl); - NetworkProviderDownloadedSimsCategoryController downloadedSimsCategoryCtrl = new NetworkProviderDownloadedSimsCategoryController(context, - KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM); - downloadedSimsCategoryCtrl.init(getSettingsLifecycle()); + KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM, getSettingsLifecycle()); controllers.add(downloadedSimsCategoryCtrl); } else { controllers.add(new MobileNetworkListController(getContext(), getLifecycle())); diff --git a/src/com/android/settings/network/NetworkProviderCallsSmsController.java b/src/com/android/settings/network/NetworkProviderCallsSmsController.java index f83418ba551..c8b1c49b7bf 100644 --- a/src/com/android/settings/network/NetworkProviderCallsSmsController.java +++ b/src/com/android/settings/network/NetworkProviderCallsSmsController.java @@ -24,6 +24,7 @@ import android.telephony.ServiceState; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; +import android.view.View; import androidx.annotation.VisibleForTesting; import androidx.lifecycle.LifecycleObserver; @@ -44,12 +45,14 @@ public class NetworkProviderCallsSmsController extends AbstractPreferenceControl private static final String TAG = "NetworkProviderCallsSmsController"; private static final String KEY = "calls_and_sms"; + private static final String RTL_MARK = "\u200F"; private UserManager mUserManager; private SubscriptionManager mSubscriptionManager; private SubscriptionsChangeListener mSubscriptionsChangeListener; private TelephonyManager mTelephonyManager; private RestrictedPreference mPreference; + private boolean mIsRtlMode; /** * The summary text and click behavior of the "Calls & SMS" item on the @@ -61,6 +64,8 @@ public class NetworkProviderCallsSmsController extends AbstractPreferenceControl mUserManager = context.getSystemService(UserManager.class); mSubscriptionManager = context.getSystemService(SubscriptionManager.class); mTelephonyManager = mContext.getSystemService(TelephonyManager.class); + mIsRtlMode = context.getResources().getConfiguration().getLayoutDirection() + == View.LAYOUT_DIRECTION_RTL; if (lifecycle != null) { mSubscriptionsChangeListener = new SubscriptionsChangeListener(context, this); lifecycle.addObserver(this); @@ -121,6 +126,10 @@ public class NetworkProviderCallsSmsController extends AbstractPreferenceControl if (subInfo != subs.get(subs.size() - 1)) { summary.append(", "); } + + if (mIsRtlMode) { + summary.insert(0, RTL_MARK).insert(summary.length(), RTL_MARK); + } } return summary; } @@ -152,12 +161,12 @@ public class NetworkProviderCallsSmsController extends AbstractPreferenceControl } @VisibleForTesting - protected int getDefaultVoiceSubscriptionId(){ + protected int getDefaultVoiceSubscriptionId() { return SubscriptionManager.getDefaultVoiceSubscriptionId(); } @VisibleForTesting - protected int getDefaultSmsSubscriptionId(){ + protected int getDefaultSmsSubscriptionId() { return SubscriptionManager.getDefaultSmsSubscriptionId(); } diff --git a/src/com/android/settings/network/NetworkProviderDownloadedSimsCategoryController.java b/src/com/android/settings/network/NetworkProviderDownloadedSimsCategoryController.java index 199740fd202..f5176b030d4 100644 --- a/src/com/android/settings/network/NetworkProviderDownloadedSimsCategoryController.java +++ b/src/com/android/settings/network/NetworkProviderDownloadedSimsCategoryController.java @@ -1,11 +1,13 @@ package com.android.settings.network; import android.content.Context; +import android.util.Log; -import androidx.annotation.VisibleForTesting; +import androidx.preference.Preference; import androidx.preference.PreferenceCategory; import androidx.preference.PreferenceScreen; +import com.android.settings.R; import com.android.settings.widget.PreferenceCategoryController; import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.core.lifecycle.LifecycleObserver; @@ -13,22 +15,17 @@ import com.android.settingslib.core.lifecycle.LifecycleObserver; public class NetworkProviderDownloadedSimsCategoryController extends PreferenceCategoryController implements LifecycleObserver { + private static final String LOG_TAG = "NetworkProviderDownloadedSimsCategoryController"; private static final String KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM = "provider_model_downloaded_sim_category"; + private PreferenceCategory mPreferenceCategory; private NetworkProviderDownloadedSimListController mNetworkProviderDownloadedSimListController; - public NetworkProviderDownloadedSimsCategoryController(Context context, String key) { - super(context, key); - } - - public void init(Lifecycle lifecycle) { - mNetworkProviderDownloadedSimListController = createDownloadedSimListController(lifecycle); - } - - @VisibleForTesting - protected NetworkProviderDownloadedSimListController createDownloadedSimListController( + public NetworkProviderDownloadedSimsCategoryController(Context context, String key, Lifecycle lifecycle) { - return new NetworkProviderDownloadedSimListController(mContext, lifecycle); + super(context, key); + mNetworkProviderDownloadedSimListController = + new NetworkProviderDownloadedSimListController(mContext, lifecycle); } @Override @@ -44,9 +41,27 @@ public class NetworkProviderDownloadedSimsCategoryController extends @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); - PreferenceCategory preferenceCategory = screen.findPreference( - KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM); - preferenceCategory.setVisible(isAvailable()); mNetworkProviderDownloadedSimListController.displayPreference(screen); + mPreferenceCategory = screen.findPreference( + KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM); + if (mPreferenceCategory == null) { + Log.d(LOG_TAG, "displayPreference(), Can not find the category."); + return; + } + mPreferenceCategory.setVisible(isAvailable()); + } + + @Override + public void updateState(Preference preference) { + super.updateState(preference); + if (mPreferenceCategory == null) { + Log.d(LOG_TAG, "updateState(), Can not find the category."); + return; + } + int count = mPreferenceCategory.getPreferenceCount(); + String title = mContext.getString(count > 1 + ? R.string.downloaded_sims_category_title + : R.string.downloaded_sim_category_title); + mPreferenceCategory.setTitle(title); } } diff --git a/src/com/android/settings/network/NetworkProviderSettings.java b/src/com/android/settings/network/NetworkProviderSettings.java index 35a34d471a8..88211ad17ed 100644 --- a/src/com/android/settings/network/NetworkProviderSettings.java +++ b/src/com/android/settings/network/NetworkProviderSettings.java @@ -71,7 +71,7 @@ import com.android.settings.wifi.WifiConnectListener; import com.android.settings.wifi.WifiDialog2; import com.android.settings.wifi.WifiPickerTrackerHelper; import com.android.settings.wifi.WifiUtils; -import com.android.settings.wifi.details2.WifiNetworkDetailsFragment2; +import com.android.settings.wifi.details.WifiNetworkDetailsFragment; import com.android.settings.wifi.dpp.WifiDppUtils; import com.android.settingslib.HelpUtils; import com.android.settingslib.RestrictedLockUtils; @@ -710,6 +710,11 @@ public class NetworkProviderSettings extends RestrictedSettingsFragment Log.i(TAG, "onWifiStateChanged called with wifi state: " + wifiState); } + if (isFinishingOrDestroyed()) { + Log.w(TAG, "onWifiStateChanged shouldn't run when fragment is finishing or destroyed"); + return; + } + switch (wifiState) { case WifiManager.WIFI_STATE_ENABLED: updateWifiEntryPreferences(); @@ -924,11 +929,11 @@ public class NetworkProviderSettings extends RestrictedSettingsFragment : context.getText(R.string.pref_title_network_details); final Bundle bundle = new Bundle(); - bundle.putString(WifiNetworkDetailsFragment2.KEY_CHOSEN_WIFIENTRY_KEY, wifiEntry.getKey()); + bundle.putString(WifiNetworkDetailsFragment.KEY_CHOSEN_WIFIENTRY_KEY, wifiEntry.getKey()); new SubSettingLauncher(context) .setTitleText(title) - .setDestination(WifiNetworkDetailsFragment2.class.getName()) + .setDestination(WifiNetworkDetailsFragment.class.getName()) .setArguments(bundle) .setSourceMetricsCategory(getMetricsCategory()) .launch(); @@ -961,12 +966,10 @@ public class NetworkProviderSettings extends RestrictedSettingsFragment @VisibleForTesting void setAdditionalSettingsSummaries() { - if (!FeatureFlagUtils.isEnabled(getContext(), FeatureFlagUtils.SETTINGS_PROVIDER_MODEL)) { - mConfigureWifiSettingsPreference.setSummary(getString( - isWifiWakeupEnabled() - ? R.string.wifi_configure_settings_preference_summary_wakeup_on - : R.string.wifi_configure_settings_preference_summary_wakeup_off)); - } + mConfigureWifiSettingsPreference.setSummary(getString( + isWifiWakeupEnabled() + ? R.string.wifi_configure_settings_preference_summary_wakeup_on + : R.string.wifi_configure_settings_preference_summary_wakeup_off)); final int numSavedNetworks = mWifiPickerTracker.getNumSavedNetworks(); final int numSavedSubscriptions = mWifiPickerTracker.getNumSavedSubscriptions(); @@ -981,6 +984,11 @@ public class NetworkProviderSettings extends RestrictedSettingsFragment private String getSavedNetworkSettingsSummaryText( int numSavedNetworks, int numSavedSubscriptions) { + if (getResources() == null) { + Log.w(TAG, "getSavedNetworkSettingsSummaryText shouldn't run if resource is not ready"); + return null; + } + if (numSavedSubscriptions == 0) { return getResources().getQuantityString(R.plurals.wifi_saved_access_points_summary, numSavedNetworks, numSavedNetworks); @@ -1174,7 +1182,7 @@ public class NetworkProviderSettings extends RestrictedSettingsFragment private void launchConfigNewNetworkFragment(WifiEntry wifiEntry) { final Bundle bundle = new Bundle(); - bundle.putString(WifiNetworkDetailsFragment2.KEY_CHOSEN_WIFIENTRY_KEY, + bundle.putString(WifiNetworkDetailsFragment.KEY_CHOSEN_WIFIENTRY_KEY, wifiEntry.getKey()); new SubSettingLauncher(getContext()) .setTitleText(wifiEntry.getTitle()) diff --git a/src/com/android/settings/network/NetworkProviderSimListController.java b/src/com/android/settings/network/NetworkProviderSimListController.java index 814a461e988..8fb6cb65d36 100644 --- a/src/com/android/settings/network/NetworkProviderSimListController.java +++ b/src/com/android/settings/network/NetworkProviderSimListController.java @@ -172,7 +172,6 @@ public class NetworkProviderSimListController extends AbstractPreferenceControll for (SubscriptionInfo info : SubscriptionUtil.getAvailableSubscriptions(mContext)) { if (!info.isEmbedded()) { subList.add(info); - break; } } return subList; diff --git a/src/com/android/settings/network/NetworkProviderSimsCategoryController.java b/src/com/android/settings/network/NetworkProviderSimsCategoryController.java index e27575a3b63..06035a91e44 100644 --- a/src/com/android/settings/network/NetworkProviderSimsCategoryController.java +++ b/src/com/android/settings/network/NetworkProviderSimsCategoryController.java @@ -17,33 +17,28 @@ package com.android.settings.network; import android.content.Context; +import android.util.Log; -import androidx.annotation.VisibleForTesting; +import androidx.preference.Preference; import androidx.preference.PreferenceCategory; import androidx.preference.PreferenceScreen; +import com.android.settings.R; import com.android.settings.widget.PreferenceCategoryController; import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.core.lifecycle.LifecycleObserver; public class NetworkProviderSimsCategoryController extends PreferenceCategoryController implements LifecycleObserver { - + private static final String LOG_TAG = "NetworkProviderSimsCategoryController"; private static final String KEY_PREFERENCE_CATEGORY_SIM = "provider_model_sim_category"; private NetworkProviderSimListController mNetworkProviderSimListController; + private PreferenceCategory mPreferenceCategory; - public NetworkProviderSimsCategoryController(Context context, String key) { + public NetworkProviderSimsCategoryController(Context context, String key, Lifecycle lifecycle) { super(context, key); - } - - public void init(Lifecycle lifecycle) { - mNetworkProviderSimListController = createSimListController(lifecycle); - } - - @VisibleForTesting - protected NetworkProviderSimListController createSimListController( - Lifecycle lifecycle) { - return new NetworkProviderSimListController(mContext, lifecycle); + mNetworkProviderSimListController = + new NetworkProviderSimListController(mContext, lifecycle); } @Override @@ -59,8 +54,26 @@ public class NetworkProviderSimsCategoryController extends PreferenceCategoryCon @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); - PreferenceCategory preferenceCategory = screen.findPreference(KEY_PREFERENCE_CATEGORY_SIM); - preferenceCategory.setVisible(isAvailable()); mNetworkProviderSimListController.displayPreference(screen); + mPreferenceCategory = screen.findPreference(KEY_PREFERENCE_CATEGORY_SIM); + if (mPreferenceCategory == null) { + Log.d(LOG_TAG, "displayPreference(), Can not find the category."); + return; + } + mPreferenceCategory.setVisible(isAvailable()); + } + + @Override + public void updateState(Preference preference) { + super.updateState(preference); + if (mPreferenceCategory == null) { + Log.d(LOG_TAG, "updateState(), Can not find the category."); + return; + } + int count = mPreferenceCategory.getPreferenceCount(); + String title = mContext.getString(count > 1 + ? R.string.provider_network_settings_title + : R.string.sim_category_title); + mPreferenceCategory.setTitle(title); } } diff --git a/src/com/android/settings/network/SubscriptionsPreferenceController.java b/src/com/android/settings/network/SubscriptionsPreferenceController.java index 8e9e946820c..36c55e2805e 100644 --- a/src/com/android/settings/network/SubscriptionsPreferenceController.java +++ b/src/com/android/settings/network/SubscriptionsPreferenceController.java @@ -311,7 +311,8 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl numLevels += 1; } - Drawable icon = mSubsPrefCtrlInjector.getIcon(mContext, level, numLevels, false); + Drawable icon = mSubsPrefCtrlInjector.getIcon(mContext, level, numLevels, + !mTelephonyManager.isDataEnabled()); final boolean isActiveCellularNetwork = mSubsPrefCtrlInjector.isActiveCellularNetwork(mContext); if (isActiveCellularNetwork || (mWifiPickerTrackerHelper != null) diff --git a/src/com/android/settings/network/helper/ConfirmationSimDeletionPredicate.java b/src/com/android/settings/network/helper/ConfirmationSimDeletionPredicate.java new file mode 100644 index 00000000000..420f6db6ee1 --- /dev/null +++ b/src/com/android/settings/network/helper/ConfirmationSimDeletionPredicate.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2021 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.network.helper; + +import android.app.KeyguardManager; +import android.content.Context; +import android.provider.Settings; + +import com.android.settings.R; + +import java.util.function.Predicate; + +/** + * {@link Predicate} for detecting the configuration of confirm SIM deletion. + */ +public class ConfirmationSimDeletionPredicate implements Predicate { + + public static final String KEY_CONFIRM_SIM_DELETION = "confirm_sim_deletion"; + + private static final ConfirmationSimDeletionPredicate sSingleton = + new ConfirmationSimDeletionPredicate(); + + // Get singleton of this predicate + public static final ConfirmationSimDeletionPredicate getSingleton() { + return sSingleton; + } + + /** + * Get default configuration of confirm SIM deletion. + * + * @param Context context + * @return the configuration of confirm SIM deletion + */ + private static boolean getDefaultValue(Context context) { + return context.getResources() + .getBoolean(R.bool.config_sim_deletion_confirmation_default_on); + } + + /** + * Get the configuration of confirm SIM deletion. + * + * @param Context context + * @return the configuration of confirm SIM deletion + */ + public boolean test(Context context) { + final KeyguardManager keyguardManager = context.getSystemService(KeyguardManager.class); + if ((keyguardManager != null) && !keyguardManager.isKeyguardSecure()) { + return false; + } + return Settings.Global.getInt(context.getContentResolver(), KEY_CONFIRM_SIM_DELETION, + getDefaultValue(context) ? 1 : 0) == 1; + } +} diff --git a/src/com/android/settings/network/telephony/CallsDefaultSubscriptionController.java b/src/com/android/settings/network/telephony/CallsDefaultSubscriptionController.java index 36b19ba1e60..16ac8f7ab4e 100644 --- a/src/com/android/settings/network/telephony/CallsDefaultSubscriptionController.java +++ b/src/com/android/settings/network/telephony/CallsDefaultSubscriptionController.java @@ -46,7 +46,7 @@ public class CallsDefaultSubscriptionController extends DefaultSubscriptionContr @Override public CharSequence getSummary() { if (Utils.isProviderModelEnabled(mContext)) { - return MobileNetworkUtils.getPreferredStatus(mContext, mManager, true); + return MobileNetworkUtils.getPreferredStatus(isRtlMode(), mContext, mManager, true); } else { return super.getSummary(); } diff --git a/src/com/android/settings/network/telephony/DefaultSubscriptionController.java b/src/com/android/settings/network/telephony/DefaultSubscriptionController.java index 4fb6cff75d0..d21d584a71c 100644 --- a/src/com/android/settings/network/telephony/DefaultSubscriptionController.java +++ b/src/com/android/settings/network/telephony/DefaultSubscriptionController.java @@ -26,6 +26,7 @@ import android.telecom.PhoneAccountHandle; import android.telecom.TelecomManager; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; +import android.view.View; import androidx.lifecycle.Lifecycle; import androidx.lifecycle.LifecycleObserver; @@ -62,11 +63,14 @@ public abstract class DefaultSubscriptionController extends TelephonyBasePrefere private static final ComponentName PSTN_CONNECTION_SERVICE_COMPONENT = new ComponentName("com.android.phone", "com.android.services.telephony.TelephonyConnectionService"); + private boolean mIsRtlMode; public DefaultSubscriptionController(Context context, String preferenceKey) { super(context, preferenceKey); mManager = context.getSystemService(SubscriptionManager.class); mChangeListener = new SubscriptionsChangeListener(context, this); + mIsRtlMode = context.getResources().getConfiguration().getLayoutDirection() + == View.LAYOUT_DIRECTION_RTL; } public void init(Lifecycle lifecycle) { @@ -285,4 +289,8 @@ public abstract class DefaultSubscriptionController extends TelephonyBasePrefere refreshSummary(mPreference); } } + + boolean isRtlMode() { + return mIsRtlMode; + } } diff --git a/src/com/android/settings/network/telephony/MobileNetworkActivity.java b/src/com/android/settings/network/telephony/MobileNetworkActivity.java index c6fe39c2a2b..efb5f8cc08e 100644 --- a/src/com/android/settings/network/telephony/MobileNetworkActivity.java +++ b/src/com/android/settings/network/telephony/MobileNetworkActivity.java @@ -39,7 +39,6 @@ import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentTransaction; import androidx.lifecycle.Lifecycle; -import com.android.internal.util.CollectionUtils; import com.android.settings.R; import com.android.settings.core.SettingsBaseActivity; import com.android.settings.network.ProxySubscriptionManager; @@ -48,6 +47,7 @@ import com.android.settings.network.helper.SelectableSubscriptions; import com.android.settings.network.helper.SubscriptionAnnotation; import java.util.List; +import java.util.function.Function; /** * Activity for displaying MobileNetworkSettings @@ -64,15 +64,14 @@ public class MobileNetworkActivity extends SettingsBaseActivity @VisibleForTesting ProxySubscriptionManager mProxySubscriptionMgr; - private int mCurSubscriptionId; + private int mCurSubscriptionId = SUB_ID_NULL; // This flag forces subscription information fragment to be re-created. // Otherwise, fragment will be kept when subscription id has not been changed. // // Set initial value to true allows subscription information fragment to be re-created when // Activity re-create occur. - private boolean mFragmentForceReload = true; - private boolean mPendingSubscriptionChange = false; + private boolean mPendingSubscriptionChange = true; @Override protected void onNewIntent(Intent intent) { @@ -80,21 +79,25 @@ public class MobileNetworkActivity extends SettingsBaseActivity validate(intent); setIntent(intent); - int updateSubscriptionIndex = SUB_ID_NULL; + int updateSubscriptionIndex = mCurSubscriptionId; if (intent != null) { updateSubscriptionIndex = intent.getIntExtra(Settings.EXTRA_SUB_ID, SUB_ID_NULL); } + SubscriptionInfo info = getSubscriptionOrDefault(updateSubscriptionIndex); + if (info == null) { + Log.d(TAG, "Invalid subId request " + mCurSubscriptionId + + " -> " + updateSubscriptionIndex); + return; + } + int oldSubId = mCurSubscriptionId; - mCurSubscriptionId = updateSubscriptionIndex; - mFragmentForceReload = (mCurSubscriptionId == oldSubId); - final SubscriptionInfo info = getSubscription(); updateSubscriptions(info, null); // If the subscription has changed or the new intent doesnt contain the opt in action, // remove the old discovery dialog. If the activity is being recreated, we will see // onCreate -> onNewIntent, so the dialog will first be recreated for the old subscription // and then removed. - if (updateSubscriptionIndex != oldSubId || !doesIntentContainOptInAction(intent)) { + if (mCurSubscriptionId != oldSubId || !doesIntentContainOptInAction(intent)) { removeContactDiscoveryDialog(oldSubId); } // evaluate showing the new discovery dialog if this intent contains an action to show the @@ -135,7 +138,13 @@ public class MobileNetworkActivity extends SettingsBaseActivity // perform registration after mCurSubscriptionId been configured. registerActiveSubscriptionsListener(); - final SubscriptionInfo subscription = getSubscription(); + SubscriptionInfo subscription = getSubscriptionOrDefault(mCurSubscriptionId); + if (subscription == null) { + Log.d(TAG, "Invalid subId request " + mCurSubscriptionId); + tryToFinishActivity(); + return; + } + maybeShowContactDiscoveryDialog(subscription); updateSubscriptions(subscription, null); @@ -158,39 +167,81 @@ public class MobileNetworkActivity extends SettingsBaseActivity * Implementation of ProxySubscriptionManager.OnActiveSubscriptionChangedListener */ public void onChanged() { + mPendingSubscriptionChange = false; + + if (mCurSubscriptionId == SUB_ID_NULL) { + return; + } + if (!getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)) { mPendingSubscriptionChange = true; return; } - SubscriptionInfo info = getSubscription(); - int oldSubIndex = mCurSubscriptionId; - updateSubscriptions(info, null); - // Remove the dialog if the subscription associated with this activity changes. - if (info == null) { - // Close the activity when subscription removed - if ((oldSubIndex != SUB_ID_NULL) - && (!isFinishing()) && (!isDestroyed())) { - finish(); + SubscriptionInfo subInfo = getSubscription(mCurSubscriptionId, null); + if (subInfo != null) { + if (mCurSubscriptionId != subInfo.getSubscriptionId()) { + // update based on subscription status change + removeContactDiscoveryDialog(mCurSubscriptionId); + updateSubscriptions(subInfo, null); } return; } - int subIndex = info.getSubscriptionId(); - if (subIndex != oldSubIndex) { - removeContactDiscoveryDialog(oldSubIndex); + + Log.w(TAG, "subId missing: " + mCurSubscriptionId); + + // When UI is not the active one, avoid from destroy it immediately + // but wait until onResume() to see if subscription back online again. + // This is to avoid from glitch behavior of subscription which changes + // the UI when UI is considered as in the background or only partly + // visible. + if (!getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED)) { + mPendingSubscriptionChange = true; + return; + } + + // Subscription could be missing + tryToFinishActivity(); + } + + protected void runSubscriptionUpdate(Runnable onUpdateRemaining) { + SubscriptionInfo subInfo = getSubscription(mCurSubscriptionId, null); + if (subInfo == null) { + tryToFinishActivity(); + return; + } + if (mCurSubscriptionId != subInfo.getSubscriptionId()) { + removeContactDiscoveryDialog(mCurSubscriptionId); + updateSubscriptions(subInfo, null); + } + onUpdateRemaining.run(); + } + + protected void tryToFinishActivity() { + if ((!isFinishing()) && (!isDestroyed())) { + finish(); } } @Override protected void onStart() { getProxySubscriptionManager().setLifecycle(getLifecycle()); - super.onStart(); - // updateSubscriptions doesn't need to be called, onChanged will always be called after we - // register a listener. if (mPendingSubscriptionChange) { mPendingSubscriptionChange = false; - onChanged(); + runSubscriptionUpdate(() -> super.onStart()); + return; } + super.onStart(); + } + + @Override + protected void onResume() { + if (mPendingSubscriptionChange) { + mPendingSubscriptionChange = false; + runSubscriptionUpdate(() -> super.onResume()); + return; + } + super.onResume(); } @Override @@ -235,30 +286,49 @@ public class MobileNetworkActivity extends SettingsBaseActivity } mCurSubscriptionId = subscriptionIndex; - mFragmentForceReload = false; + } + + /** + * Select one of the subscription as the default subscription. + * @param subAnnoList a list of {@link SubscriptionAnnotation} + * @return ideally the {@link SubscriptionAnnotation} as expected + */ + protected SubscriptionAnnotation defaultSubscriptionSelection( + List subAnnoList) { + return (subAnnoList == null) ? null : + subAnnoList.stream() + .filter(SubscriptionAnnotation::isDisplayAllowed) + .filter(SubscriptionAnnotation::isActive) + .findFirst().orElse(null); + } + + protected SubscriptionInfo getSubscriptionOrDefault(int subscriptionId) { + return getSubscription(subscriptionId, + (subscriptionId != SUB_ID_NULL) ? null : ( + subAnnoList -> defaultSubscriptionSelection(subAnnoList) + )); } /** * Get the current subscription to display. First check whether intent has {@link - * Settings#EXTRA_SUB_ID} and if so find the subscription with that id. If not, just return the - * first one in the mSubscriptionInfos list since it is already sorted by sim slot. + * Settings#EXTRA_SUB_ID} and if so find the subscription with that id. + * If not, select default one based on {@link Function} provided. + * + * @param preferredSubscriptionId preferred subscription id + * @param selectionOfDefault when true current subscription is absent */ @VisibleForTesting - SubscriptionInfo getSubscription() { + protected SubscriptionInfo getSubscription(int preferredSubscriptionId, + Function, SubscriptionAnnotation> selectionOfDefault) { List subList = (new SelectableSubscriptions(this, true)).call(); - SubscriptionAnnotation currentSubInfo = null; - if (mCurSubscriptionId != SUB_ID_NULL) { - currentSubInfo = subList.stream() - .filter(SubscriptionAnnotation::isDisplayAllowed) - .filter(subAnno -> (subAnno.getSubscriptionId() == mCurSubscriptionId)) - .findFirst().orElse(null); - } - if (currentSubInfo == null) { - currentSubInfo = subList.stream() - .filter(SubscriptionAnnotation::isDisplayAllowed) - .filter(SubscriptionAnnotation::isActive) - .findFirst().orElse(null); + Log.d(TAG, "get subId=" + preferredSubscriptionId + " from " + subList); + SubscriptionAnnotation currentSubInfo = subList.stream() + .filter(SubscriptionAnnotation::isDisplayAllowed) + .filter(subAnno -> (subAnno.getSubscriptionId() == preferredSubscriptionId)) + .findFirst().orElse(null); + if ((currentSubInfo == null) && (selectionOfDefault != null)) { + currentSubInfo = selectionOfDefault.apply(subList); } return (currentSubInfo == null) ? null : currentSubInfo.getSubInfo(); } @@ -285,10 +355,6 @@ public class MobileNetworkActivity extends SettingsBaseActivity final String fragmentTag = buildFragmentTag(subId); if (fragmentManager.findFragmentByTag(fragmentTag) != null) { - if (!mFragmentForceReload) { - Log.d(TAG, "Keep current fragment: " + fragmentTag); - return; - } Log.d(TAG, "Construct fragment: " + fragmentTag); } diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettings.java b/src/com/android/settings/network/telephony/MobileNetworkSettings.java index adf399fb953..ba80a8ce659 100644 --- a/src/com/android/settings/network/telephony/MobileNetworkSettings.java +++ b/src/com/android/settings/network/telephony/MobileNetworkSettings.java @@ -193,6 +193,7 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings { .addListener(videoCallingPreferenceController); use(ContactDiscoveryPreferenceController.class).init(getParentFragmentManager(), mSubId, getLifecycle()); + use(NrAdvancedCallingPreferenceController.class).init(mSubId); } @Override diff --git a/src/com/android/settings/network/telephony/MobileNetworkUtils.java b/src/com/android/settings/network/telephony/MobileNetworkUtils.java index 18984848b2f..ebf77a0acca 100644 --- a/src/com/android/settings/network/telephony/MobileNetworkUtils.java +++ b/src/com/android/settings/network/telephony/MobileNetworkUtils.java @@ -84,6 +84,8 @@ import java.util.Arrays; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; public class MobileNetworkUtils { @@ -99,6 +101,7 @@ public class MobileNetworkUtils { "esim.enable_esim_system_ui_by_default"; private static final String LEGACY_ACTION_CONFIGURE_PHONE_ACCOUNT = "android.telecom.action.CONNECTION_SERVICE_CONFIGURE"; + private static final String RTL_MARK = "\u200F"; // The following constants are used to draw signal icon. public static final int NO_CELL_DATA_TYPE_ICON = 0; @@ -257,9 +260,16 @@ public class MobileNetworkUtils { public static boolean showEuiccSettings(Context context) { long timeForAccess = SystemClock.elapsedRealtime(); try { - return ((Future) ThreadUtils.postOnBackgroundThread(() - -> showEuiccSettingsDetecting(context))).get(); - } catch (ExecutionException | InterruptedException exception) { + Boolean isShow = ((Future) ThreadUtils.postOnBackgroundThread(() -> { + try { + return showEuiccSettingsDetecting(context); + } catch (Exception threadException) { + Log.w(TAG, "Accessing Euicc failure", threadException); + } + return Boolean.FALSE; + })).get(3, TimeUnit.SECONDS); + return ((isShow != null) && isShow.booleanValue()); + } catch (ExecutionException | InterruptedException | TimeoutException exception) { timeForAccess = SystemClock.elapsedRealtime() - timeForAccess; Log.w(TAG, "Accessing Euicc takes too long: +" + timeForAccess + "ms"); } @@ -278,7 +288,7 @@ public class MobileNetworkUtils { final ContentResolver cr = context.getContentResolver(); final boolean esimIgnoredDevice = Arrays.asList(TextUtils.split(SystemProperties.get(KEY_ESIM_CID_IGNORE, ""), ",")) - .contains(SystemProperties.get(KEY_CID, null)); + .contains(SystemProperties.get(KEY_CID)); final boolean enabledEsimUiByDefault = SystemProperties.getBoolean(KEY_ENABLE_ESIM_UI_BY_DEFAULT, true); final boolean euiccProvisioned = @@ -922,7 +932,7 @@ public class MobileNetworkUtils { /** * Returns preferred status of Calls & SMS separately when Provider Model is enabled. */ - public static CharSequence getPreferredStatus(Context context, + public static CharSequence getPreferredStatus(boolean isRtlMode, Context context, SubscriptionManager subscriptionManager, boolean isPreferredCallStatus) { final List subs = SubscriptionUtil.getActiveSubscriptions( subscriptionManager); @@ -956,6 +966,10 @@ public class MobileNetworkUtils { if (subInfo != subs.get(subs.size() - 1)) { summary.append(", "); } + + if (isRtlMode) { + summary.insert(0, RTL_MARK).insert(summary.length(), RTL_MARK); + } } return summary; } else { diff --git a/src/com/android/settings/network/telephony/NrAdvancedCallingPreferenceController.java b/src/com/android/settings/network/telephony/NrAdvancedCallingPreferenceController.java new file mode 100644 index 00000000000..7615fe339bc --- /dev/null +++ b/src/com/android/settings/network/telephony/NrAdvancedCallingPreferenceController.java @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2021 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.network.telephony; + +import android.content.Context; +import android.os.PersistableBundle; +import android.telephony.CarrierConfigManager; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyCallback; +import android.telephony.TelephonyManager; +import android.util.Log; + +import androidx.annotation.VisibleForTesting; +import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; +import androidx.preference.SwitchPreference; + +import com.android.internal.telephony.util.ArrayUtils; +import com.android.settingslib.core.lifecycle.LifecycleObserver; +import com.android.settingslib.core.lifecycle.events.OnStart; +import com.android.settingslib.core.lifecycle.events.OnStop; + +/** + * Preference controller for "Enhanced 4G LTE" + */ +public class NrAdvancedCallingPreferenceController extends TelephonyTogglePreferenceController + implements LifecycleObserver, OnStart, OnStop { + + private static final String TAG = "VoNrSettings"; + + @VisibleForTesting + Preference mPreference; + private TelephonyManager mTelephonyManager; + private PhoneCallStateTelephonyCallback mTelephonyCallback; + private boolean mIsVonrVisibleFromCarrierConfig = false; + private boolean mIsNrEnableFromCarrierConfig = false; + private boolean mHas5gCapability = false; + private Integer mCallState; + + public NrAdvancedCallingPreferenceController(Context context, String key) { + super(context, key); + mTelephonyManager = context.getSystemService(TelephonyManager.class); + } + + /** + * Initial this PreferenceController. + * @param subId The subscription Id. + * @return This PreferenceController. + */ + public NrAdvancedCallingPreferenceController init(int subId) { + Log.d(TAG, "init: "); + if (mTelephonyCallback == null) { + mTelephonyCallback = new PhoneCallStateTelephonyCallback(); + } + + mSubId = subId; + + if (mTelephonyManager == null) { + mTelephonyManager = mContext.getSystemService(TelephonyManager.class); + } + if (SubscriptionManager.isValidSubscriptionId(subId)) { + mTelephonyManager = mTelephonyManager.createForSubscriptionId(subId); + } + long supportedRadioBitmask = mTelephonyManager.getSupportedRadioAccessFamily(); + mHas5gCapability = + (supportedRadioBitmask & TelephonyManager.NETWORK_TYPE_BITMASK_NR) > 0; + + PersistableBundle carrierConfig = getCarrierConfigForSubId(subId); + if (carrierConfig == null) { + return this; + } + mIsVonrVisibleFromCarrierConfig = carrierConfig.getBoolean( + CarrierConfigManager.KEY_VONR_SETTING_VISIBILITY_BOOL); + + int[] nrAvailabilities = carrierConfig.getIntArray( + CarrierConfigManager.KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY); + mIsNrEnableFromCarrierConfig = !ArrayUtils.isEmpty(nrAvailabilities); + + Log.d(TAG, "mHas5gCapability: " + mHas5gCapability + + ",mIsNrEnabledFromCarrierConfig: " + mIsNrEnableFromCarrierConfig + + ",mIsVonrVisibleFromCarrierConfig: " + mIsVonrVisibleFromCarrierConfig); + return this; + } + + @Override + public int getAvailabilityStatus(int subId) { + init(subId); + + if (mHas5gCapability && mIsNrEnableFromCarrierConfig && mIsVonrVisibleFromCarrierConfig) { + return AVAILABLE; + } + return CONDITIONALLY_UNAVAILABLE; + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + mPreference = screen.findPreference(getPreferenceKey()); + } + + @Override + public void onStart() { + if (mTelephonyCallback == null) { + return; + } + mTelephonyCallback.register(mTelephonyManager); + } + + @Override + public void onStop() { + if (mTelephonyCallback == null) { + return; + } + mTelephonyCallback.unregister(); + } + + @Override + public void updateState(Preference preference) { + super.updateState(preference); + if (preference == null) { + return; + } + final SwitchPreference switchPreference = (SwitchPreference) preference; + switchPreference.setEnabled(isUserControlAllowed()); + } + + @Override + public boolean setChecked(boolean isChecked) { + if (!SubscriptionManager.isValidSubscriptionId(mSubId)) { + return false; + } + Log.d(TAG, "setChecked: " + isChecked); + int result = mTelephonyManager.setVoNrEnabled(isChecked); + if (result == TelephonyManager.ENABLE_VONR_SUCCESS) { + return true; + } + Log.d(TAG, "Fail to set VoNR result= " + result + ". subId=" + mSubId); + return false; + } + + @Override + public boolean isChecked() { + return mTelephonyManager.isVoNrEnabled(); + } + + @VisibleForTesting + protected boolean isCallStateIdle() { + return (mCallState != null) && (mCallState == TelephonyManager.CALL_STATE_IDLE); + } + + private boolean isUserControlAllowed() { + return isCallStateIdle(); + } + + private class PhoneCallStateTelephonyCallback extends TelephonyCallback implements + TelephonyCallback.CallStateListener { + + private TelephonyManager mLocalTelephonyManager; + + @Override + public void onCallStateChanged(int state) { + mCallState = state; + updateState(mPreference); + } + + public void register(TelephonyManager telephonyManager) { + mLocalTelephonyManager = telephonyManager; + + // assign current call state so that it helps to show correct preference state even + // before first onCallStateChanged() by initial registration. + mCallState = mLocalTelephonyManager.getCallState(); + mLocalTelephonyManager.registerTelephonyCallback( + mContext.getMainExecutor(), mTelephonyCallback); + } + + public void unregister() { + mCallState = null; + if (mLocalTelephonyManager != null) { + mLocalTelephonyManager.unregisterTelephonyCallback(this); + } + } + } +} diff --git a/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragment.java b/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragment.java index c782b66c677..8e65605eecc 100644 --- a/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragment.java +++ b/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragment.java @@ -52,6 +52,7 @@ import com.android.settingslib.DeviceInfoUtils; import com.google.common.collect.ImmutableMap; +import java.util.Arrays; import java.util.List; import java.util.Map; @@ -108,18 +109,18 @@ public class RenameMobileNetworkDialogFragment extends InstrumentedDialogFragmen mSubId = getArguments().getInt(KEY_SUBSCRIPTION_ID); Resources res = context.getResources(); mLightDarkMap = ImmutableMap.builder() - .put(res.getInteger(R.color.SIM_color_teal), - res.getInteger(R.color.SIM_dark_mode_color_teal)) - .put(res.getInteger(R.color.SIM_color_blue), + .put(res.getInteger(R.color.SIM_color_cyan), + res.getInteger(R.color.SIM_dark_mode_color_cyan)) + .put(res.getInteger(R.color.SIM_color_blue800), res.getInteger(R.color.SIM_dark_mode_color_blue)) - .put(res.getInteger(R.color.SIM_color_indigo), - res.getInteger(R.color.SIM_dark_mode_color_indigo)) - .put(res.getInteger(R.color.SIM_color_purple), + .put(res.getInteger(R.color.SIM_color_green800), + res.getInteger(R.color.SIM_dark_mode_color_green)) + .put(res.getInteger(R.color.SIM_color_purple800), res.getInteger(R.color.SIM_dark_mode_color_purple)) - .put(res.getInteger(R.color.SIM_color_pink), + .put(res.getInteger(R.color.SIM_color_pink800), res.getInteger(R.color.SIM_dark_mode_color_pink)) - .put(res.getInteger(R.color.SIM_color_red), - res.getInteger(R.color.SIM_dark_mode_color_red)) + .put(res.getInteger(R.color.SIM_color_orange), + res.getInteger(R.color.SIM_dark_mode_color_orange)) .build(); } @@ -175,12 +176,7 @@ public class RenameMobileNetworkDialogFragment extends InstrumentedDialogFragmen final ColorAdapter adapter = new ColorAdapter(getContext(), R.layout.dialog_mobile_network_color_picker_item, mColors); mColorSpinner.setAdapter(adapter); - for (int i = 0; i < mColors.length; i++) { - if (mColors[i].getColor() == info.getIconTint()) { - mColorSpinner.setSelection(i); - break; - } - } + mColorSpinner.setSelection(getSimColorIndex(info.getIconTint())); final TextView operatorName = view.findViewById(R.id.operator_name_value); mTelephonyManager = mTelephonyManager.createForSubscriptionId(mSubId); @@ -239,7 +235,7 @@ public class RenameMobileNetworkDialogFragment extends InstrumentedDialogFragmen private Color[] getColors() { final Resources res = getContext().getResources(); - final int[] colorInts = res.getIntArray(com.android.internal.R.array.sim_colors); + final int[] colorInts = res.getIntArray(R.array.sim_color_light); final String[] colorStrings = res.getStringArray(R.array.color_picker); final int iconSize = res.getDimensionPixelSize(R.dimen.color_swatch_size); final int strokeWidth = res.getDimensionPixelSize(R.dimen.color_swatch_stroke_width); @@ -286,4 +282,31 @@ public class RenameMobileNetworkDialogFragment extends InstrumentedDialogFragmen private int getDarkColor(int lightColor) { return mLightDarkMap.getOrDefault(lightColor, lightColor); } + + /* + * Get the color index from previous color that defined in Android OS + * (frameworks/base/core/res/res/values/arrays.xml). If can't find the color, continue to look + * for it in the new color plattee. If not, give it the first index. + */ + + private int getSimColorIndex(int color) { + int index = -1; + final int[] previousSimColorInts = + getContext().getResources().getIntArray(com.android.internal.R.array.sim_colors); + for (int i = 0; i < previousSimColorInts.length; i++) { + if (previousSimColorInts[i] == color) { + index = i; + } + } + + if (index == -1) { + for (int i = 0; i < mColors.length; i++) { + if (mColors[i].getColor() == color) { + index = i; + } + } + } + + return index == -1 ? 0 : index; + } } diff --git a/src/com/android/settings/network/telephony/SmsDefaultSubscriptionController.java b/src/com/android/settings/network/telephony/SmsDefaultSubscriptionController.java index ca8c0f6c5d3..a73c62116a9 100644 --- a/src/com/android/settings/network/telephony/SmsDefaultSubscriptionController.java +++ b/src/com/android/settings/network/telephony/SmsDefaultSubscriptionController.java @@ -62,7 +62,7 @@ public class SmsDefaultSubscriptionController extends DefaultSubscriptionControl @Override public CharSequence getSummary() { if (Utils.isProviderModelEnabled(mContext)) { - return MobileNetworkUtils.getPreferredStatus(mContext, mManager, false); + return MobileNetworkUtils.getPreferredStatus(isRtlMode(), mContext, mManager, false); } else { return super.getSummary(); } diff --git a/src/com/android/settings/nfc/PaymentDefaultDialog.java b/src/com/android/settings/nfc/PaymentDefaultDialog.java index df6d86ffb24..a888167b899 100644 --- a/src/com/android/settings/nfc/PaymentDefaultDialog.java +++ b/src/com/android/settings/nfc/PaymentDefaultDialog.java @@ -32,6 +32,8 @@ import com.android.settings.nfc.PaymentBackend.PaymentInfo; import java.util.List; +import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; + public final class PaymentDefaultDialog extends AlertActivity implements DialogInterface.OnClickListener { @@ -44,6 +46,9 @@ public final class PaymentDefaultDialog extends AlertActivity implements @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + + getWindow().addPrivateFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); + try { mBackend = new PaymentBackend(this); } catch (NullPointerException e) { diff --git a/src/com/android/settings/notification/app/RecentConversationsPreferenceController.java b/src/com/android/settings/notification/app/RecentConversationsPreferenceController.java index 4984fad9400..1ceb45cb316 100644 --- a/src/com/android/settings/notification/app/RecentConversationsPreferenceController.java +++ b/src/com/android/settings/notification/app/RecentConversationsPreferenceController.java @@ -233,8 +233,13 @@ public class RecentConversationsPreferenceController extends AbstractPreferenceC private final Collator sCollator = Collator.getInstance(); @Override public int compare(ConversationChannel o1, ConversationChannel o2) { - int labelComparison = sCollator.compare(o1.getShortcutInfo().getLabel(), - o2.getShortcutInfo().getLabel()); + int labelComparison = 0; + if (o1.getShortcutInfo().getLabel() != null + && o2.getShortcutInfo().getLabel() != null) { + labelComparison = sCollator.compare( + o1.getShortcutInfo().getLabel().toString(), + o2.getShortcutInfo().getLabel().toString()); + } if (labelComparison == 0) { return o1.getNotificationChannel().getId().compareTo( diff --git a/src/com/android/settings/notification/history/NotificationHistoryActivity.java b/src/com/android/settings/notification/history/NotificationHistoryActivity.java index 1d663fc1629..ec09a9fabba 100644 --- a/src/com/android/settings/notification/history/NotificationHistoryActivity.java +++ b/src/com/android/settings/notification/history/NotificationHistoryActivity.java @@ -163,7 +163,7 @@ public class NotificationHistoryActivity extends CollapsingToolbarBaseActivity { View viewForPackage = LayoutInflater.from(this) .inflate(R.layout.notification_history_app_layout, null); - final View container = viewForPackage.findViewById(R.id.notification_list); + final View container = viewForPackage.findViewById(R.id.notification_list_wrapper); container.setVisibility(View.GONE); View header = viewForPackage.findViewById(R.id.app_header); NotificationExpandButton expand = viewForPackage.findViewById( diff --git a/src/com/android/settings/notification/history/NotificationHistoryAdapter.java b/src/com/android/settings/notification/history/NotificationHistoryAdapter.java index 0683ef7612d..96bc14a6fb2 100644 --- a/src/com/android/settings/notification/history/NotificationHistoryAdapter.java +++ b/src/com/android/settings/notification/history/NotificationHistoryAdapter.java @@ -71,6 +71,11 @@ public class NotificationHistoryAdapter extends return new NotificationHistoryViewHolder(view); } + @Override + public long getItemId(int position) { + return mValues.get(position).hashCode(); + } + @Override public void onBindViewHolder(final @NonNull NotificationHistoryViewHolder holder, int position) { @@ -85,7 +90,6 @@ public class NotificationHistoryAdapter extends .putExtra(EXTRA_APP_PACKAGE, hn.getPackage()) .putExtra(EXTRA_CHANNEL_ID, hn.getChannelId()) .putExtra(EXTRA_CONVERSATION_ID, hn.getConversationId()); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); holder.itemView.getContext().startActivityAsUser(intent, UserHandle.of(hn.getUserId())); }; holder.itemView.setOnClickListener(onClick); diff --git a/src/com/android/settings/notification/history/NotificationHistoryRecyclerView.java b/src/com/android/settings/notification/history/NotificationHistoryRecyclerView.java index 06c74bc3432..224c31d1f55 100644 --- a/src/com/android/settings/notification/history/NotificationHistoryRecyclerView.java +++ b/src/com/android/settings/notification/history/NotificationHistoryRecyclerView.java @@ -40,7 +40,6 @@ public class NotificationHistoryRecyclerView extends RecyclerView { ItemTouchHelper touchHelper = new ItemTouchHelper( new DismissTouchHelper(0, ItemTouchHelper.START | ItemTouchHelper.END)); touchHelper.attachToRecyclerView(this); - setNestedScrollingEnabled(false); } public void setOnItemSwipeDeleteListener(OnItemSwipeDeleteListener listener) { diff --git a/src/com/android/settings/notification/history/NotificationSbnAdapter.java b/src/com/android/settings/notification/history/NotificationSbnAdapter.java index e0328542803..7eca3b7f8ab 100644 --- a/src/com/android/settings/notification/history/NotificationSbnAdapter.java +++ b/src/com/android/settings/notification/history/NotificationSbnAdapter.java @@ -133,7 +133,6 @@ public class NotificationSbnAdapter extends .putExtra(EXTRA_APP_PACKAGE, sbn.getPackageName()) .putExtra(EXTRA_CHANNEL_ID, sbn.getNotification().getChannelId()) .putExtra(EXTRA_CONVERSATION_ID, sbn.getNotification().getShortcutId()); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); holder.itemView.getContext().startActivityAsUser(intent, UserHandle.of(userId)); return true; }); diff --git a/src/com/android/settings/panel/InternetConnectivityPanel.java b/src/com/android/settings/panel/InternetConnectivityPanel.java deleted file mode 100644 index ae6f2e0f59e..00000000000 --- a/src/com/android/settings/panel/InternetConnectivityPanel.java +++ /dev/null @@ -1,425 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.settings.panel; - -import static androidx.lifecycle.Lifecycle.Event.ON_PAUSE; -import static androidx.lifecycle.Lifecycle.Event.ON_RESUME; - -import android.app.settings.SettingsEnums; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.net.Uri; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiManager; -import android.os.Handler; -import android.os.HandlerExecutor; -import android.os.Looper; -import android.provider.Settings; -import android.telephony.ServiceState; -import android.telephony.SubscriptionManager; -import android.telephony.TelephonyCallback; -import android.telephony.TelephonyManager; -import android.text.TextUtils; -import android.util.Log; - -import androidx.annotation.VisibleForTesting; -import androidx.lifecycle.LifecycleObserver; -import androidx.lifecycle.OnLifecycleEvent; - -import com.android.settings.R; -import com.android.settings.Utils; -import com.android.settings.network.AirplaneModePreferenceController; -import com.android.settings.network.InternetUpdater; -import com.android.settings.network.ProviderModelSliceHelper; -import com.android.settings.network.SubscriptionsChangeListener; -import com.android.settings.network.telephony.DataConnectivityListener; -import com.android.settings.slices.CustomSliceRegistry; - -import java.util.ArrayList; -import java.util.List; - -/** - * Represents the Internet Connectivity Panel. - */ -public class InternetConnectivityPanel implements PanelContent, LifecycleObserver, - InternetUpdater.InternetChangeListener, DataConnectivityListener.Client, - SubscriptionsChangeListener.SubscriptionsChangeListenerClient { - private static final String TAG = "InternetConnectivityPanel"; - private static final int SUBTITLE_TEXT_NONE = -1; - private static final int SUBTITLE_TEXT_WIFI_IS_OFF = R.string.wifi_is_off; - private static final int SUBTITLE_TEXT_TAP_A_NETWORK_TO_CONNECT = - R.string.tap_a_network_to_connect; - private static final int SUBTITLE_TEXT_SEARCHING_FOR_NETWORKS = - R.string.wifi_empty_list_wifi_on; - private static final int SUBTITLE_TEXT_NON_CARRIER_NETWORK_UNAVAILABLE = - R.string.non_carrier_network_unavailable; - private static final int SUBTITLE_TEXT_ALL_CARRIER_NETWORK_UNAVAILABLE = - R.string.all_network_unavailable; - - private final Context mContext; - private final WifiManager mWifiManager; - private final IntentFilter mWifiStateFilter; - private final NetworkProviderTelephonyCallback mTelephonyCallback; - private final BroadcastReceiver mWifiStateReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (intent == null) { - return; - } - - if (TextUtils.equals(intent.getAction(), WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) { - updateProgressBar(); - updatePanelTitle(); - return; - } - - if (TextUtils.equals(intent.getAction(), WifiManager.NETWORK_STATE_CHANGED_ACTION)) { - updateProgressBar(); - updatePanelTitle(); - } - } - }; - - @VisibleForTesting - boolean mIsProviderModelEnabled; - @VisibleForTesting - InternetUpdater mInternetUpdater; - @VisibleForTesting - ProviderModelSliceHelper mProviderModelSliceHelper; - - private int mSubtitle = SUBTITLE_TEXT_NONE; - private PanelContentCallback mCallback; - private TelephonyManager mTelephonyManager; - private SubscriptionsChangeListener mSubscriptionsListener; - private DataConnectivityListener mConnectivityListener; - private int mDefaultDataSubid = SubscriptionManager.INVALID_SUBSCRIPTION_ID; - - // Wi-Fi scanning progress bar - protected HandlerInjector mHandlerInjector; - protected boolean mIsProgressBarVisible; - protected boolean mIsScanningSubTitleShownOnce; - protected Runnable mHideProgressBarRunnable = () -> { - setProgressBarVisible(false); - }; - protected Runnable mHideScanningSubTitleRunnable = () -> { - mIsScanningSubTitleShownOnce = true; - updatePanelTitle(); - }; - - /** - * Wrapper for testing compatibility. - */ - @VisibleForTesting - static class HandlerInjector { - protected final Handler mHandler; - - HandlerInjector(Context context) { - mHandler = context.getMainThreadHandler(); - } - - public void postDelay(Runnable runnable) { - mHandler.postDelayed(runnable, 2000 /* delay millis */); - } - - public void removeCallbacks(Runnable runnable) { - mHandler.removeCallbacks(runnable); - } - } - - private InternetConnectivityPanel(Context context) { - mContext = context.getApplicationContext(); - mHandlerInjector = new HandlerInjector(context); - mIsProviderModelEnabled = Utils.isProviderModelEnabled(mContext); - mInternetUpdater = new InternetUpdater(context, null /* Lifecycle */, this); - - mSubscriptionsListener = new SubscriptionsChangeListener(context, this); - mConnectivityListener = new DataConnectivityListener(context, this); - mTelephonyCallback = new NetworkProviderTelephonyCallback(); - mDefaultDataSubid = getDefaultDataSubscriptionId(); - mTelephonyManager = mContext.getSystemService(TelephonyManager.class); - - mWifiManager = mContext.getSystemService(WifiManager.class); - mWifiStateFilter = new IntentFilter(WifiManager.NETWORK_STATE_CHANGED_ACTION); - mWifiStateFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); - - mProviderModelSliceHelper = new ProviderModelSliceHelper(mContext, null); - } - - /** create the panel */ - public static InternetConnectivityPanel create(Context context) { - return new InternetConnectivityPanel(context); - } - - /** @OnLifecycleEvent(ON_RESUME) */ - @OnLifecycleEvent(ON_RESUME) - public void onResume() { - if (!mIsProviderModelEnabled) { - return; - } - mInternetUpdater.onResume(); - mSubscriptionsListener.start(); - mConnectivityListener.start(); - mTelephonyManager.registerTelephonyCallback( - new HandlerExecutor(new Handler(Looper.getMainLooper())), mTelephonyCallback); - mContext.registerReceiver(mWifiStateReceiver, mWifiStateFilter); - updateProgressBar(); - updatePanelTitle(); - } - - /** @OnLifecycleEvent(ON_PAUSE) */ - @OnLifecycleEvent(ON_PAUSE) - public void onPause() { - if (!mIsProviderModelEnabled) { - return; - } - mInternetUpdater.onPause(); - mSubscriptionsListener.stop(); - mConnectivityListener.stop(); - mTelephonyManager.unregisterTelephonyCallback(mTelephonyCallback); - mContext.unregisterReceiver(mWifiStateReceiver); - mHandlerInjector.removeCallbacks(mHideProgressBarRunnable); - mHandlerInjector.removeCallbacks(mHideScanningSubTitleRunnable); - } - - /** - * @return a string for the title of the Panel. - */ - @Override - public CharSequence getTitle() { - if (mIsProviderModelEnabled) { - return mContext.getText(mInternetUpdater.isAirplaneModeOn() - ? R.string.airplane_mode : R.string.provider_internet_settings); - } - return mContext.getText(R.string.internet_connectivity_panel_title); - } - - /** - * @return a string for the subtitle of the Panel. - */ - @Override - public CharSequence getSubTitle() { - if (mIsProviderModelEnabled && mSubtitle != SUBTITLE_TEXT_NONE) { - return mContext.getText(mSubtitle); - } - return null; - } - - @Override - public List getSlices() { - final List uris = new ArrayList<>(); - if (mIsProviderModelEnabled) { - uris.add(CustomSliceRegistry.PROVIDER_MODEL_SLICE_URI); - } else { - uris.add(CustomSliceRegistry.WIFI_SLICE_URI); - uris.add(CustomSliceRegistry.MOBILE_DATA_SLICE_URI); - uris.add(AirplaneModePreferenceController.SLICE_URI); - } - return uris; - } - - @Override - public Intent getSeeMoreIntent() { - // Disable the see more button for provider model design. - if (mIsProviderModelEnabled) { - return null; - } - - // Don't remove the see more intent for non-provider model design. This intent will be - // used when isCustomizedButtonUsed() returns false. - return new Intent(Settings.ACTION_WIRELESS_SETTINGS) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - } - - @Override - public boolean isProgressBarVisible() { - return mIsProgressBarVisible; - } - - @Override - public int getMetricsCategory() { - return SettingsEnums.PANEL_INTERNET_CONNECTIVITY; - } - - @Override - public void registerCallback(PanelContentCallback callback) { - mCallback = callback; - } - - /** - * Called when airplane mode state is changed. - */ - @Override - public void onAirplaneModeChanged(boolean isAirplaneModeOn) { - log("onAirplaneModeChanged: isAirplaneModeOn:" + isAirplaneModeOn); - updatePanelTitle(); - } - - /** - * Called when Wi-Fi enabled is changed. - */ - @Override - public void onWifiEnabledChanged(boolean enabled) { - log("onWifiEnabledChanged: enabled:" + enabled); - updatePanelTitle(); - } - - @Override - public void onSubscriptionsChanged() { - final int defaultDataSubId = getDefaultDataSubscriptionId(); - log("onSubscriptionsChanged: defaultDataSubId:" + defaultDataSubId); - if (mDefaultDataSubid == defaultDataSubId) { - return; - } - if (SubscriptionManager.isUsableSubscriptionId(defaultDataSubId)) { - mTelephonyManager.unregisterTelephonyCallback(mTelephonyCallback); - mTelephonyManager.registerTelephonyCallback( - new HandlerExecutor(new Handler(Looper.getMainLooper())), mTelephonyCallback); - } - updatePanelTitle(); - } - - @Override - public void onDataConnectivityChange() { - log("onDataConnectivityChange"); - updatePanelTitle(); - } - - @VisibleForTesting - void updatePanelTitle() { - if (mCallback == null) { - return; - } - updateSubtitleText(); - mCallback.onHeaderChanged(); - } - - @VisibleForTesting - int getDefaultDataSubscriptionId() { - return SubscriptionManager.getDefaultDataSubscriptionId(); - } - - private void updateSubtitleText() { - mSubtitle = SUBTITLE_TEXT_NONE; - if (!mInternetUpdater.isWifiEnabled()) { - if (!mInternetUpdater.isAirplaneModeOn()) { - // When the airplane mode is off and Wi-Fi is disabled. - // Sub-Title: Wi-Fi is off - log("Airplane mode off + Wi-Fi off."); - mSubtitle = SUBTITLE_TEXT_WIFI_IS_OFF; - } - return; - } - - if (mInternetUpdater.isAirplaneModeOn()) { - return; - } - - final List wifiList = mWifiManager.getScanResults(); - if (wifiList != null && wifiList.size() != 0) { - // When the Wi-Fi scan result is not empty - // Sub-Title: Tap a network to connect - mSubtitle = SUBTITLE_TEXT_TAP_A_NETWORK_TO_CONNECT; - return; - } - - if (!mIsScanningSubTitleShownOnce && mIsProgressBarVisible) { - // When the Wi-Fi scan result callback is received - // Sub-Title: Searching for networks... - mSubtitle = SUBTITLE_TEXT_SEARCHING_FOR_NETWORKS; - return; - } - - // Sub-Title: - // show non_carrier_network_unavailable - // - while Wi-Fi on + no Wi-Fi item - // - while Wi-Fi on + no Wi-Fi item + mobile data off - // show all_network_unavailable: - // - while Wi-Fi on + no Wi-Fi item + no carrier item - // - while Wi-Fi on + no Wi-Fi item + service is out of service - // - while Wi-Fi on + no Wi-Fi item + mobile data on + no carrier data. - log("No Wi-Fi item."); - if (!mProviderModelSliceHelper.hasCarrier() - || (!mProviderModelSliceHelper.isVoiceStateInService() - && !mProviderModelSliceHelper.isDataStateInService())) { - log("no carrier or service is out of service."); - mSubtitle = SUBTITLE_TEXT_ALL_CARRIER_NETWORK_UNAVAILABLE; - return; - } - if (!mProviderModelSliceHelper.isMobileDataEnabled()) { - log("mobile data off"); - mSubtitle = SUBTITLE_TEXT_NON_CARRIER_NETWORK_UNAVAILABLE; - return; - } - if (!mProviderModelSliceHelper.isDataSimActive()) { - log("no carrier data."); - mSubtitle = SUBTITLE_TEXT_ALL_CARRIER_NETWORK_UNAVAILABLE; - return; - } - mSubtitle = SUBTITLE_TEXT_NON_CARRIER_NETWORK_UNAVAILABLE; - } - - protected void updateProgressBar() { - if (mWifiManager == null || !mInternetUpdater.isWifiEnabled()) { - setProgressBarVisible(false); - return; - } - - setProgressBarVisible(true); - List wifiScanResults = mWifiManager.getScanResults(); - if (wifiScanResults != null && wifiScanResults.size() > 0) { - mHandlerInjector.postDelay(mHideProgressBarRunnable); - } else if (!mIsScanningSubTitleShownOnce) { - mHandlerInjector.postDelay(mHideScanningSubTitleRunnable); - } - } - - protected void setProgressBarVisible(boolean visible) { - if (mIsProgressBarVisible == visible) { - return; - } - mIsProgressBarVisible = visible; - - if (mCallback == null) { - return; - } - mCallback.onProgressBarVisibleChanged(); - updatePanelTitle(); - } - - private class NetworkProviderTelephonyCallback extends TelephonyCallback implements - TelephonyCallback.DataConnectionStateListener, - TelephonyCallback.ServiceStateListener { - @Override - public void onServiceStateChanged(ServiceState state) { - log("onServiceStateChanged voiceState=" + state.getState() - + " dataState=" + state.getDataRegistrationState()); - updatePanelTitle(); - } - - @Override - public void onDataConnectionStateChanged(int state, int networkType) { - log("onDataConnectionStateChanged: networkType=" + networkType + " state=" + state); - updatePanelTitle(); - } - } - - private static void log(String s) { - Log.d(TAG, s); - } -} diff --git a/src/com/android/settings/panel/PanelFeatureProviderImpl.java b/src/com/android/settings/panel/PanelFeatureProviderImpl.java index ca30952a72d..a73881b4cc1 100644 --- a/src/com/android/settings/panel/PanelFeatureProviderImpl.java +++ b/src/com/android/settings/panel/PanelFeatureProviderImpl.java @@ -17,11 +17,14 @@ package com.android.settings.panel; import android.content.Context; +import android.content.Intent; import android.os.Bundle; import android.provider.Settings; public class PanelFeatureProviderImpl implements PanelFeatureProvider { + private static final String SYSTEMUI_PACKAGE_NAME = "com.android.systemui"; + @Override public PanelContent getPanel(Context context, Bundle bundle) { if (context == null) { @@ -35,7 +38,12 @@ public class PanelFeatureProviderImpl implements PanelFeatureProvider { switch (panelType) { case Settings.Panel.ACTION_INTERNET_CONNECTIVITY: - return InternetConnectivityPanel.create(context); + // Redirect to the internet dialog in SystemUI. + Intent intent = new Intent(Settings.Panel.ACTION_INTERNET_CONNECTIVITY); + intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND) + .setPackage(SYSTEMUI_PACKAGE_NAME); + context.sendBroadcast(intent); + return null; case Settings.Panel.ACTION_NFC: return NfcPanel.create(context); case Settings.Panel.ACTION_WIFI: diff --git a/src/com/android/settings/password/ChooseLockGenericController.java b/src/com/android/settings/password/ChooseLockGenericController.java index 1b951d4f968..cd9eb2fd44d 100644 --- a/src/com/android/settings/password/ChooseLockGenericController.java +++ b/src/com/android/settings/password/ChooseLockGenericController.java @@ -190,7 +190,8 @@ public class ChooseLockGenericController { * requirements. The lock's visibility ({@link #isScreenLockVisible}) is not considered here. */ public boolean isScreenLockEnabled(ScreenLockType type) { - return type.maxQuality >= upgradeQuality(PASSWORD_QUALITY_UNSPECIFIED); + return !mLockPatternUtils.isCredentialsDisabledForUser(mUserId) + && type.maxQuality >= upgradeQuality(PASSWORD_QUALITY_UNSPECIFIED); } /** diff --git a/src/com/android/settings/password/ChooseLockPassword.java b/src/com/android/settings/password/ChooseLockPassword.java index ae178c88883..c03362510d0 100644 --- a/src/com/android/settings/password/ChooseLockPassword.java +++ b/src/com/android/settings/password/ChooseLockPassword.java @@ -499,13 +499,7 @@ public class ChooseLockPassword extends SettingsActivity { mNextButton = mixin.getPrimaryButton(); mMessage = view.findViewById(R.id.sud_layout_description); - if (mForFingerprint) { - mLayout.setIcon(getActivity().getDrawable(R.drawable.ic_fingerprint_header)); - } else if (mForFace) { - mLayout.setIcon(getActivity().getDrawable(R.drawable.ic_face_header)); - } else if (mForBiometrics) { - mLayout.setIcon(getActivity().getDrawable(R.drawable.ic_lock)); - } + mLayout.setIcon(getActivity().getDrawable(R.drawable.ic_lock)); mIsAlphaMode = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == mPasswordType || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == mPasswordType diff --git a/src/com/android/settings/password/ChooseLockPattern.java b/src/com/android/settings/password/ChooseLockPattern.java index e85ce60c6c4..8464a2ffd7c 100644 --- a/src/com/android/settings/password/ChooseLockPattern.java +++ b/src/com/android/settings/password/ChooseLockPattern.java @@ -505,13 +505,7 @@ public class ChooseLockPattern extends SettingsActivity { layout.getMixin(IconMixin.class).setVisibility(View.GONE); } } else { - if (mForFingerprint) { - layout.setIcon(getActivity().getDrawable(R.drawable.ic_fingerprint_header)); - } else if (mForFace) { - layout.setIcon(getActivity().getDrawable(R.drawable.ic_face_header)); - } else if (mForBiometrics) { - layout.setIcon(getActivity().getDrawable(R.drawable.ic_lock)); - } + layout.setIcon(getActivity().getDrawable(R.drawable.ic_lock)); } final FooterBarMixin mixin = layout.getMixin(FooterBarMixin.class); diff --git a/src/com/android/settings/security/ConfirmSimDeletionPreferenceController.java b/src/com/android/settings/security/ConfirmSimDeletionPreferenceController.java index bf807a19715..a7185e3f207 100644 --- a/src/com/android/settings/security/ConfirmSimDeletionPreferenceController.java +++ b/src/com/android/settings/security/ConfirmSimDeletionPreferenceController.java @@ -26,6 +26,7 @@ import androidx.preference.TwoStatePreference; import com.android.settings.R; import com.android.settings.core.BasePreferenceController; +import com.android.settings.network.helper.ConfirmationSimDeletionPredicate; import com.android.settings.network.telephony.MobileNetworkUtils; import com.android.settings.overlay.FeatureFactory; import com.android.settings.wifi.dpp.WifiDppUtils; @@ -34,7 +35,8 @@ import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; /** Enable/disable user confirmation before deleting an eSim */ public class ConfirmSimDeletionPreferenceController extends BasePreferenceController implements Preference.OnPreferenceChangeListener{ - public static final String KEY_CONFIRM_SIM_DELETION = "confirm_sim_deletion"; + public static final String KEY_CONFIRM_SIM_DELETION = + ConfirmationSimDeletionPredicate.KEY_CONFIRM_SIM_DELETION; private boolean mConfirmationDefaultOn; private MetricsFeatureProvider mMetricsFeatureProvider; diff --git a/src/com/android/settings/sim/SimDialogActivity.java b/src/com/android/settings/sim/SimDialogActivity.java index 252b6c06e25..e5457ae3459 100644 --- a/src/com/android/settings/sim/SimDialogActivity.java +++ b/src/com/android/settings/sim/SimDialogActivity.java @@ -24,6 +24,7 @@ import android.telecom.TelecomManager; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.util.Log; +import android.view.WindowManager; import android.widget.Toast; import androidx.fragment.app.Fragment; @@ -59,6 +60,8 @@ public class SimDialogActivity extends FragmentActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + getWindow().addSystemFlags( + WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); showOrUpdateDialog(); } diff --git a/src/com/android/settings/sim/smartForwarding/DisableSmartForwardingTask.java b/src/com/android/settings/sim/smartForwarding/DisableSmartForwardingTask.java index 45333ec7bcb..d483dd12ed2 100644 --- a/src/com/android/settings/sim/smartForwarding/DisableSmartForwardingTask.java +++ b/src/com/android/settings/sim/smartForwarding/DisableSmartForwardingTask.java @@ -19,6 +19,7 @@ package com.android.settings.sim.smartForwarding; import static com.android.settings.sim.smartForwarding.SmartForwardingUtils.TAG; import android.telephony.CallForwardingInfo; +import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.util.Log; @@ -37,17 +38,29 @@ public class DisableSmartForwardingTask implements Runnable { @Override public void run() { for (int i = 0; i < tm.getActiveModemCount(); i++) { - if (callWaitingStatus != null) { + int subId = getSubId(i); + if (callWaitingStatus != null + && subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { Log.d(TAG, "Restore call waiting to " + callWaitingStatus[i]); - tm.setCallWaitingEnabled(callWaitingStatus[i], null, null); + tm.createForSubscriptionId(subId) + .setCallWaitingEnabled(callWaitingStatus[i], null, null); } if (callForwardingInfo != null && callForwardingInfo[i] != null - && callForwardingInfo[i].getTimeoutSeconds() > 0) { - Log.d(TAG, "Restore call waiting to " + callForwardingInfo); - tm.setCallForwarding(callForwardingInfo[i], null, null); + && subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + Log.d(TAG, "Restore call forwarding to " + callForwardingInfo[i]); + tm.createForSubscriptionId(subId) + .setCallForwarding(callForwardingInfo[i], null, null); } } } + + private int getSubId(int slotIndex) { + int[] subId = SubscriptionManager.getSubId(slotIndex); + if (subId != null && subId.length > 0) { + return subId[0]; + } + return SubscriptionManager.INVALID_SUBSCRIPTION_ID; + } } diff --git a/src/com/android/settings/uwb/UwbPreferenceController.java b/src/com/android/settings/uwb/UwbPreferenceController.java index 15979b510cf..877c9f2f2b4 100644 --- a/src/com/android/settings/uwb/UwbPreferenceController.java +++ b/src/com/android/settings/uwb/UwbPreferenceController.java @@ -57,7 +57,9 @@ public class UwbPreferenceController extends TogglePreferenceController implemen public UwbPreferenceController(Context context, String key) { super(context, key); mExecutor = Executors.newSingleThreadExecutor(); - mUwbManager = context.getSystemService(UwbManager.class); + if (isUwbSupportedOnDevice()) { + mUwbManager = context.getSystemService(UwbManager.class); + } mAirplaneModeOn = Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0) == 1; mAirplaneModeChangedReceiver = new BroadcastReceiver() { diff --git a/src/com/android/settings/widget/LabeledSeekBarPreference.java b/src/com/android/settings/widget/LabeledSeekBarPreference.java index 3a9ac18beb0..b34ea1946f9 100644 --- a/src/com/android/settings/widget/LabeledSeekBarPreference.java +++ b/src/com/android/settings/widget/LabeledSeekBarPreference.java @@ -20,9 +20,11 @@ import android.content.Context; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; import android.util.AttributeSet; +import android.view.View; import android.widget.SeekBar; import android.widget.TextView; +import androidx.annotation.Nullable; import androidx.core.content.res.TypedArrayUtils; import androidx.preference.PreferenceViewHolder; @@ -35,6 +37,8 @@ public class LabeledSeekBarPreference extends SeekBarPreference { private final int mTextEndId; private final int mTickMarkId; private OnPreferenceChangeListener mStopListener; + @Nullable + private CharSequence mSummary; public LabeledSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { @@ -52,6 +56,7 @@ public class LabeledSeekBarPreference extends SeekBarPreference { R.string.summary_placeholder); mTickMarkId = styledAttrs.getResourceId( R.styleable.LabeledSeekBarPreference_tickMark, /* defValue= */ 0); + mSummary = styledAttrs.getText(R.styleable.Preference_android_summary); styledAttrs.recycle(); } @@ -76,6 +81,15 @@ public class LabeledSeekBarPreference extends SeekBarPreference { com.android.internal.R.id.seekbar); seekBar.setTickMark(tickMark); } + + final TextView summary = (TextView) holder.findViewById(android.R.id.summary); + if (mSummary != null) { + summary.setText(mSummary); + summary.setVisibility(View.VISIBLE); + } else { + summary.setText(null); + summary.setVisibility(View.GONE); + } } public void setOnPreferenceChangeStopListener(OnPreferenceChangeListener listener) { @@ -90,5 +104,24 @@ public class LabeledSeekBarPreference extends SeekBarPreference { mStopListener.onPreferenceChange(this, seekBar.getProgress()); } } + + @Override + public void setSummary(CharSequence summary) { + super.setSummary(summary); + mSummary = summary; + notifyChanged(); + } + + @Override + public void setSummary(int summaryResId) { + super.setSummary(summaryResId); + mSummary = getContext().getText(summaryResId); + notifyChanged(); + } + + @Override + public CharSequence getSummary() { + return mSummary; + } } diff --git a/src/com/android/settings/wifi/ConfigureWifiEntryFragment.java b/src/com/android/settings/wifi/ConfigureWifiEntryFragment.java index d2f50903698..469ca1dd9e7 100644 --- a/src/com/android/settings/wifi/ConfigureWifiEntryFragment.java +++ b/src/com/android/settings/wifi/ConfigureWifiEntryFragment.java @@ -38,7 +38,7 @@ import androidx.annotation.VisibleForTesting; import com.android.settings.R; import com.android.settings.core.InstrumentedFragment; import com.android.settings.overlay.FeatureFactory; -import com.android.settings.wifi.details2.WifiNetworkDetailsFragment2; +import com.android.settings.wifi.details.WifiNetworkDetailsFragment; import com.android.wifitrackerlib.NetworkDetailsTracker; import com.android.wifitrackerlib.WifiEntry; @@ -238,6 +238,6 @@ public class ConfigureWifiEntryFragment extends InstrumentedFragment implements MAX_SCAN_AGE_MILLIS, SCAN_INTERVAL_MILLIS, getArguments().getString( - WifiNetworkDetailsFragment2.KEY_CHOSEN_WIFIENTRY_KEY)); + WifiNetworkDetailsFragment.KEY_CHOSEN_WIFIENTRY_KEY)); } } diff --git a/src/com/android/settings/wifi/NetworkRequestDialogFragment.java b/src/com/android/settings/wifi/NetworkRequestDialogFragment.java index cbc89ae7720..5fe156c3dbf 100644 --- a/src/com/android/settings/wifi/NetworkRequestDialogFragment.java +++ b/src/com/android/settings/wifi/NetworkRequestDialogFragment.java @@ -330,7 +330,7 @@ public class NetworkRequestDialogFragment extends NetworkRequestDialogBaseFragme final PreferenceImageView imageView = view.findViewById(android.R.id.icon); final int level = wifiEntry.getLevel(); - if (imageView != null) { + if (imageView != null && level != WifiEntry.WIFI_LEVEL_UNREACHABLE) { final Drawable drawable = getContext().getDrawable( Utils.getWifiIconResource(level)); drawable.setTintList( diff --git a/src/com/android/settings/wifi/WifiConfigController2.java b/src/com/android/settings/wifi/WifiConfigController2.java index e8f2384d5cd..011c9709c00 100644 --- a/src/com/android/settings/wifi/WifiConfigController2.java +++ b/src/com/android/settings/wifi/WifiConfigController2.java @@ -484,7 +484,7 @@ public class WifiConfigController2 implements TextWatcher, } boolean isValidSaePassword(String password) { - if (password.length() >= 1 && password.length() <= 63) { + if (password.length() >= 1 && password.length() <= 128) { return true; } return false; diff --git a/src/com/android/settings/wifi/WifiConnectionPreferenceController.java b/src/com/android/settings/wifi/WifiConnectionPreferenceController.java index 3b2669cefda..fc2f8f15415 100644 --- a/src/com/android/settings/wifi/WifiConnectionPreferenceController.java +++ b/src/com/android/settings/wifi/WifiConnectionPreferenceController.java @@ -34,7 +34,7 @@ import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settings.core.SubSettingLauncher; import com.android.settings.overlay.FeatureFactory; -import com.android.settings.wifi.details2.WifiNetworkDetailsFragment2; +import com.android.settings.wifi.details.WifiNetworkDetailsFragment; import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.wifi.WifiEntryPreference; @@ -165,11 +165,11 @@ public class WifiConnectionPreferenceController extends AbstractPreferenceContro mPreference.setOrder(order); mPreference.setOnPreferenceClickListener(pref -> { final Bundle args = new Bundle(); - args.putString(WifiNetworkDetailsFragment2.KEY_CHOSEN_WIFIENTRY_KEY, + args.putString(WifiNetworkDetailsFragment.KEY_CHOSEN_WIFIENTRY_KEY, wifiEntry.getKey()); new SubSettingLauncher(mPrefContext) .setTitleRes(R.string.pref_title_network_details) - .setDestination(WifiNetworkDetailsFragment2.class.getName()) + .setDestination(WifiNetworkDetailsFragment.class.getName()) .setArguments(args) .setSourceMetricsCategory(mMetricsCategory) .launch(); diff --git a/src/com/android/settings/wifi/WifiDialog2.java b/src/com/android/settings/wifi/WifiDialog2.java index dc546f3c231..05dad3f1b96 100644 --- a/src/com/android/settings/wifi/WifiDialog2.java +++ b/src/com/android/settings/wifi/WifiDialog2.java @@ -21,6 +21,8 @@ import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; import android.view.View; +import android.view.Window; +import android.view.WindowManager; import android.widget.Button; import android.widget.ImageButton; import android.widget.TextView; @@ -108,6 +110,8 @@ public class WifiDialog2 extends AlertDialog implements WifiConfigUiBase2, @Override protected void onCreate(Bundle savedInstanceState) { + setWindowsOverlay(); + mView = getLayoutInflater().inflate(R.layout.wifi_dialog, /* root */ null); setView(mView); mController = new WifiConfigController2(this, mView, mWifiEntry, mMode); @@ -126,6 +130,13 @@ public class WifiDialog2 extends AlertDialog implements WifiConfigUiBase2, } } + private void setWindowsOverlay() { + final Window window = getWindow(); + final WindowManager.LayoutParams lp = window.getAttributes(); + window.setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); + window.setAttributes(lp); + } + @Override protected void onStart() { final ImageButton ssidScannerButton = findViewById(R.id.ssid_scanner_button); diff --git a/src/com/android/settings/wifi/WifiDialogActivity.java b/src/com/android/settings/wifi/WifiDialogActivity.java index 4514b0d19f0..877933edafe 100644 --- a/src/com/android/settings/wifi/WifiDialogActivity.java +++ b/src/com/android/settings/wifi/WifiDialogActivity.java @@ -16,12 +16,8 @@ package com.android.settings.wifi; -import static android.Manifest.permission.ACCESS_COARSE_LOCATION; -import static android.Manifest.permission.ACCESS_FINE_LOCATION; - import android.content.DialogInterface; import android.content.Intent; -import android.content.pm.PackageManager; import android.net.NetworkInfo; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiManager; @@ -33,7 +29,6 @@ import android.os.Process; import android.os.SimpleClock; import android.os.SystemClock; import android.text.TextUtils; -import android.util.EventLog; import android.util.Log; import androidx.annotation.VisibleForTesting; @@ -83,12 +78,10 @@ public class WifiDialogActivity extends ObservableActivity implements WifiDialog public static final String KEY_WIFI_CONFIGURATION = "wifi_configuration"; - @VisibleForTesting - static final int RESULT_CONNECTED = RESULT_FIRST_USER; + private static final int RESULT_CONNECTED = RESULT_FIRST_USER; private static final int RESULT_FORGET = RESULT_FIRST_USER + 1; - @VisibleForTesting - static final int REQUEST_CODE_WIFI_DPP_ENROLLEE_QR_CODE_SCANNER = 0; + private static final int REQUEST_CODE_WIFI_DPP_ENROLLEE_QR_CODE_SCANNER = 0; // Max age of tracked WifiEntries. private static final long MAX_SCAN_AGE_MILLIS = 15_000; @@ -265,7 +258,10 @@ public class WifiDialogActivity extends ObservableActivity implements WifiDialog } } - Intent resultData = hasPermissionForResult() ? createResultData(config, null) : null; + final Intent resultData = new Intent(); + if (config != null) { + resultData.putExtra(KEY_WIFI_CONFIGURATION, config); + } setResult(RESULT_CONNECTED, resultData); finish(); } @@ -293,22 +289,17 @@ public class WifiDialogActivity extends ObservableActivity implements WifiDialog } } - Intent resultData = hasPermissionForResult() ? createResultData(config, accessPoint) : null; - setResult(RESULT_CONNECTED, resultData); - finish(); - } - - protected Intent createResultData(WifiConfiguration config, AccessPoint accessPoint) { - Intent result = new Intent(); + Intent resultData = new Intent(); if (accessPoint != null) { Bundle accessPointState = new Bundle(); accessPoint.saveWifiState(accessPointState); - result.putExtra(KEY_ACCESS_POINT_STATE, accessPointState); + resultData.putExtra(KEY_ACCESS_POINT_STATE, accessPointState); } if (config != null) { - result.putExtra(KEY_WIFI_CONFIGURATION, config); + resultData.putExtra(KEY_WIFI_CONFIGURATION, config); } - return result; + setResult(RESULT_CONNECTED, resultData); + finish(); } @Override @@ -344,44 +335,9 @@ public class WifiDialogActivity extends ObservableActivity implements WifiDialog if (resultCode != RESULT_OK) { return; } - if (hasPermissionForResult()) { - setResult(RESULT_CONNECTED, data); - } else { - setResult(RESULT_CONNECTED); - } + + setResult(RESULT_CONNECTED, data); finish(); } } - - protected boolean hasPermissionForResult() { - final String callingPackage = getCallingPackage(); - if (callingPackage == null) { - Log.d(TAG, "Failed to get the calling package, don't return the result."); - EventLog.writeEvent(0x534e4554, "185126813", -1 /* UID */, "no calling package"); - return false; - } - - if (getPackageManager().checkPermission(ACCESS_COARSE_LOCATION, callingPackage) - == PackageManager.PERMISSION_GRANTED) { - Log.d(TAG, "The calling package has ACCESS_COARSE_LOCATION permission for result."); - return true; - } - - if (getPackageManager().checkPermission(ACCESS_FINE_LOCATION, callingPackage) - == PackageManager.PERMISSION_GRANTED) { - Log.d(TAG, "The calling package has ACCESS_FINE_LOCATION permission for result."); - return true; - } - - Log.d(TAG, "The calling package does not have the necessary permissions for result."); - try { - EventLog.writeEvent(0x534e4554, "185126813", - getPackageManager().getPackageUid(callingPackage, 0 /* flags */), - "no permission"); - } catch (PackageManager.NameNotFoundException e) { - EventLog.writeEvent(0x534e4554, "185126813", -1 /* UID */, "no permission"); - Log.w(TAG, "Cannot find the UID, calling package: " + callingPackage, e); - } - return false; - } } diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java index 59f65041c6e..c4b4d5928d1 100644 --- a/src/com/android/settings/wifi/WifiSettings.java +++ b/src/com/android/settings/wifi/WifiSettings.java @@ -67,7 +67,7 @@ import com.android.settings.location.WifiScanningFragment; import com.android.settings.overlay.FeatureFactory; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.widget.MainSwitchBarController; -import com.android.settings.wifi.details2.WifiNetworkDetailsFragment2; +import com.android.settings.wifi.details.WifiNetworkDetailsFragment; import com.android.settings.wifi.dpp.WifiDppUtils; import com.android.settingslib.HelpUtils; import com.android.settingslib.RestrictedLockUtils; @@ -844,11 +844,11 @@ public class WifiSettings extends RestrictedSettingsFragment : context.getText(R.string.pref_title_network_details); final Bundle bundle = new Bundle(); - bundle.putString(WifiNetworkDetailsFragment2.KEY_CHOSEN_WIFIENTRY_KEY, wifiEntry.getKey()); + bundle.putString(WifiNetworkDetailsFragment.KEY_CHOSEN_WIFIENTRY_KEY, wifiEntry.getKey()); new SubSettingLauncher(context) .setTitleText(title) - .setDestination(WifiNetworkDetailsFragment2.class.getName()) + .setDestination(WifiNetworkDetailsFragment.class.getName()) .setArguments(bundle) .setSourceMetricsCategory(getMetricsCategory()) .launch(); @@ -1121,7 +1121,7 @@ public class WifiSettings extends RestrictedSettingsFragment private void launchConfigNewNetworkFragment(WifiEntry wifiEntry) { final Bundle bundle = new Bundle(); - bundle.putString(WifiNetworkDetailsFragment2.KEY_CHOSEN_WIFIENTRY_KEY, + bundle.putString(WifiNetworkDetailsFragment.KEY_CHOSEN_WIFIENTRY_KEY, wifiEntry.getKey()); new SubSettingLauncher(getContext()) .setTitleText(wifiEntry.getTitle()) diff --git a/src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2.java b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java similarity index 93% rename from src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2.java rename to src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java index 6bc510d6b16..dd0c20a4765 100644 --- a/src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2.java +++ b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 The Android Open Source Project + * Copyright (C) 2021 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. @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.settings.wifi.details2; +package com.android.settings.wifi.details; import static com.android.settings.wifi.WifiSettings.WIFI_DIALOG_ID; @@ -45,6 +45,13 @@ import com.android.settings.dashboard.RestrictedDashboardFragment; import com.android.settings.overlay.FeatureFactory; import com.android.settings.wifi.WifiConfigUiBase2; import com.android.settings.wifi.WifiDialog2; +import com.android.settings.wifi.details2.AddDevicePreferenceController2; +import com.android.settings.wifi.details2.WifiAutoConnectPreferenceController2; +import com.android.settings.wifi.details2.WifiDetailPreferenceController2; +import com.android.settings.wifi.details2.WifiMeteredPreferenceController2; +import com.android.settings.wifi.details2.WifiPrivacyPreferenceController2; +import com.android.settings.wifi.details2.WifiSecondSummaryController2; +import com.android.settings.wifi.details2.WifiSubscriptionDetailPreferenceController2; import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; import com.android.settingslib.RestrictedLockUtilsInternal; @@ -63,10 +70,10 @@ import java.util.List; *

The key of {@link WifiEntry} should be saved to the intent Extras when launching this class * in order to properly render this page. */ -public class WifiNetworkDetailsFragment2 extends RestrictedDashboardFragment implements +public class WifiNetworkDetailsFragment extends RestrictedDashboardFragment implements WifiDialog2.WifiDialog2Listener { - private static final String TAG = "WifiNetworkDetailsFrg2"; + private static final String TAG = "WifiNetworkDetailsFrg"; // Key of a Bundle to save/restore the selected WifiEntry public static final String KEY_CHOSEN_WIFIENTRY_KEY = "key_chosen_wifientry_key"; @@ -86,7 +93,7 @@ public class WifiNetworkDetailsFragment2 extends RestrictedDashboardFragment imp @VisibleForTesting List mControllers; - public WifiNetworkDetailsFragment2() { + public WifiNetworkDetailsFragment() { super(UserManager.DISALLOW_CONFIG_WIFI); } diff --git a/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java b/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java index 7bf680da103..f9d0db07b25 100644 --- a/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java +++ b/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java @@ -76,6 +76,7 @@ import com.android.settings.widget.EntityHeaderController; import com.android.settings.wifi.WifiDialog2; import com.android.settings.wifi.WifiDialog2.WifiDialog2Listener; import com.android.settings.wifi.WifiUtils; +import com.android.settings.wifi.details.WifiNetworkDetailsFragment; import com.android.settings.wifi.dpp.WifiDppUtils; import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; @@ -1099,7 +1100,7 @@ public class WifiDetailPreferenceController2 extends AbstractPreferenceControlle refreshPage(); // Refresh the Preferences in fragment. - ((WifiNetworkDetailsFragment2) mFragment).refreshPreferences(); + ((WifiNetworkDetailsFragment) mFragment).refreshPreferences(); } /** diff --git a/src/com/android/settings/wifi/dpp/WifiDppBaseActivity.java b/src/com/android/settings/wifi/dpp/WifiDppBaseActivity.java index 499f66cb3c8..f55960be5e0 100644 --- a/src/com/android/settings/wifi/dpp/WifiDppBaseActivity.java +++ b/src/com/android/settings/wifi/dpp/WifiDppBaseActivity.java @@ -26,7 +26,7 @@ import com.android.settings.R; import com.android.settings.SetupWizardUtils; import com.android.settings.core.InstrumentedActivity; -abstract class WifiDppBaseActivity extends InstrumentedActivity { +public abstract class WifiDppBaseActivity extends InstrumentedActivity { protected FragmentManager mFragmentManager; protected abstract void handleIntent(Intent intent); diff --git a/src/com/android/settings/wifi/savedaccesspoints2/SavedAccessPointsWifiSettings2.java b/src/com/android/settings/wifi/savedaccesspoints2/SavedAccessPointsWifiSettings2.java index e579ad73dbb..1443e3247cf 100644 --- a/src/com/android/settings/wifi/savedaccesspoints2/SavedAccessPointsWifiSettings2.java +++ b/src/com/android/settings/wifi/savedaccesspoints2/SavedAccessPointsWifiSettings2.java @@ -39,7 +39,7 @@ import com.android.settings.R; import com.android.settings.core.SubSettingLauncher; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.wifi.WifiSettings; -import com.android.settings.wifi.details2.WifiNetworkDetailsFragment2; +import com.android.settings.wifi.details.WifiNetworkDetailsFragment; import com.android.wifitrackerlib.SavedNetworkTracker; import java.time.Clock; @@ -126,7 +126,7 @@ public class SavedAccessPointsWifiSettings2 extends DashboardFragment } /** - * Shows {@link WifiNetworkDetailsFragment2} for assigned key of {@link WifiEntry}. + * Shows {@link WifiNetworkDetailsFragment} for assigned key of {@link WifiEntry}. */ public void showWifiPage(@NonNull String key, CharSequence title) { removeDialog(WifiSettings.WIFI_DIALOG_ID); @@ -137,11 +137,11 @@ public class SavedAccessPointsWifiSettings2 extends DashboardFragment } final Bundle bundle = new Bundle(); - bundle.putString(WifiNetworkDetailsFragment2.KEY_CHOSEN_WIFIENTRY_KEY, key); + bundle.putString(WifiNetworkDetailsFragment.KEY_CHOSEN_WIFIENTRY_KEY, key); new SubSettingLauncher(getContext()) .setTitleText(title) - .setDestination(WifiNetworkDetailsFragment2.class.getName()) + .setDestination(WifiNetworkDetailsFragment.class.getName()) .setArguments(bundle) .setSourceMetricsCategory(getMetricsCategory()) .launch(); diff --git a/src/com/android/settings/wifi/slice/WifiSlice.java b/src/com/android/settings/wifi/slice/WifiSlice.java index 75d2c669954..f6604dd6f6e 100644 --- a/src/com/android/settings/wifi/slice/WifiSlice.java +++ b/src/com/android/settings/wifi/slice/WifiSlice.java @@ -50,7 +50,7 @@ import com.android.settings.slices.SliceBuilderUtils; import com.android.settings.wifi.WifiDialogActivity; import com.android.settings.wifi.WifiSettings; import com.android.settings.wifi.WifiUtils; -import com.android.settings.wifi.details2.WifiNetworkDetailsFragment2; +import com.android.settings.wifi.details.WifiNetworkDetailsFragment; import com.android.wifitrackerlib.WifiEntry; import java.util.Arrays; @@ -200,11 +200,11 @@ public class WifiSlice implements CustomSliceable { if (wifiSliceItem.getConnectedState() != WifiEntry.CONNECTED_STATE_DISCONNECTED) { final Bundle bundle = new Bundle(); - bundle.putString(WifiNetworkDetailsFragment2.KEY_CHOSEN_WIFIENTRY_KEY, + bundle.putString(WifiNetworkDetailsFragment.KEY_CHOSEN_WIFIENTRY_KEY, wifiSliceItem.getKey()); final Intent intent = new SubSettingLauncher(mContext) .setTitleRes(R.string.pref_title_network_details) - .setDestination(WifiNetworkDetailsFragment2.class.getName()) + .setDestination(WifiNetworkDetailsFragment.class.getName()) .setArguments(bundle) .setSourceMetricsCategory(SettingsEnums.WIFI) .toIntent(); diff --git a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDefaultFragmentTest.java b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDefaultFragmentTest.java index eee63980753..2317c97513b 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDefaultFragmentTest.java +++ b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDefaultFragmentTest.java @@ -183,7 +183,7 @@ public class UsbDefaultFragmentTest { @Test public void onTetheringStarted_currentFunctionsIsRndis_setsRndisAsDefaultUsbFunctions() { - mFragment.mCurrentFunctions = UsbManager.FUNCTION_RNDIS; + when(mUsbBackend.getCurrentFunctions()).thenReturn(UsbManager.FUNCTION_RNDIS); mFragment.mOnStartTetheringCallback.onTetheringStarted(); @@ -192,7 +192,7 @@ public class UsbDefaultFragmentTest { @Test public void onTetheringStarted_currentFunctionsIsNcm_setsNcmAsDefaultUsbFunctions() { - mFragment.mCurrentFunctions = UsbManager.FUNCTION_NCM; + when(mUsbBackend.getCurrentFunctions()).thenReturn(UsbManager.FUNCTION_NCM); mFragment.mOnStartTetheringCallback.onTetheringStarted(); diff --git a/tests/robotests/src/com/android/settings/display/BrightnessLevelPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/BrightnessLevelPreferenceControllerTest.java index 49489865049..c2de51050e8 100644 --- a/tests/robotests/src/com/android/settings/display/BrightnessLevelPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/display/BrightnessLevelPreferenceControllerTest.java @@ -152,7 +152,8 @@ public class BrightnessLevelPreferenceControllerTest { System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC); when(mDisplay.getBrightnessInfo()).thenReturn( - new BrightnessInfo(0.1f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF)); + new BrightnessInfo(0.1f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF, + 0.5f)); mController.updateState(mPreference); @@ -166,7 +167,8 @@ public class BrightnessLevelPreferenceControllerTest { System.SCREEN_BRIGHTNESS_MODE_MANUAL); when(mDisplay.getBrightnessInfo()).thenReturn( - new BrightnessInfo(0.5f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF)); + new BrightnessInfo(0.5f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF, + 0.5f)); mController.updateState(mPreference); diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java index fd4e82d4b23..43fbe81a3a1 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java @@ -50,7 +50,6 @@ import com.android.settings.testutils.FakeFeatureFactory; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; @@ -65,7 +64,6 @@ import java.util.HashMap; import java.util.Locale; import java.util.List; import java.util.Map; -import java.util.TimeZone; @RunWith(RobolectricTestRunner.class) public final class BatteryChartPreferenceControllerTest { @@ -125,37 +123,6 @@ public final class BatteryChartPreferenceControllerTest { createBatteryHistoryMap()); } - @Ignore - @Test - public void testOnResume_uiModeIsChanged_clearBatteryDiffEntryCache() { - doReturn(mResources).when(mContext).getResources(); - doReturn(mConfiguration).when(mResources).getConfiguration(); - mConfiguration.uiMode = Configuration.UI_MODE_NIGHT_UNDEFINED; - // Ensures the testing environment is correct. - assertThat(BatteryDiffEntry.sResourceCache).hasSize(1); - mBatteryChartPreferenceController.onResume(); - // Changes the uiMode in the configuration. - mConfiguration.uiMode = Configuration.UI_MODE_NIGHT_YES; - - mBatteryChartPreferenceController.onResume(); - assertThat(BatteryDiffEntry.sResourceCache).isEmpty(); - } - - @Ignore - @Test - public void testOnResume_uiModeIsNotChanged_notClearBatteryDiffEntryCache() { - doReturn(mResources).when(mContext).getResources(); - doReturn(mConfiguration).when(mResources).getConfiguration(); - mConfiguration.uiMode = Configuration.UI_MODE_NIGHT_UNDEFINED; - // Ensures the testing environment is correct. - assertThat(BatteryDiffEntry.sResourceCache).hasSize(1); - - mBatteryChartPreferenceController.onResume(); - assertThat(BatteryDiffEntry.sResourceCache).isNotEmpty(); - verify(mMetricsFeatureProvider) - .action(mContext, SettingsEnums.OPEN_BATTERY_USAGE); - } - @Test public void testOnDestroy_activityIsChanging_clearBatteryEntryCache() { doReturn(true).when(mSettingsActivity).isChangingConfigurations(); @@ -579,12 +546,12 @@ public final class BatteryChartPreferenceControllerTest { // Verifies the title in the preference group. verify(mBatteryChartPreferenceController.mAppListPrefGroup) .setTitle(captor.capture()); - assertThat(captor.getValue()).isEqualTo("App usage for 4 - 7"); + assertThat(captor.getValue()).isNotEqualTo("App usage for past 24 hr"); // Verifies the title in the expandable divider. captor = ArgumentCaptor.forClass(String.class); verify(mBatteryChartPreferenceController.mExpandDividerPreference) .setTitle(captor.capture()); - assertThat(captor.getValue()).isEqualTo("System usage for 4 - 7"); + assertThat(captor.getValue()).isNotEqualTo("System usage for past 24 hr"); } @Test @@ -722,9 +689,6 @@ public final class BatteryChartPreferenceControllerTest { new long[] {1619196786769L, 0L, 1619247636826L}; ConvertUtils.utcToLocalTimeHour( mContext, /*timestamp=*/ 0, /*is24HourFormat=*/ false); - // Simulates the locale in GMT. - ConvertUtils.sSimpleDateFormatForHour - .setTimeZone(TimeZone.getTimeZone("GMT")); } private BatteryChartPreferenceController createController() { diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartViewTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartViewTest.java index d19a012812e..0b75e798423 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartViewTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartViewTest.java @@ -33,7 +33,6 @@ import android.view.accessibility.AccessibilityManager; import com.android.settings.testutils.FakeFeatureFactory; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @@ -44,7 +43,6 @@ import org.robolectric.RuntimeEnvironment; import java.util.Arrays; import java.util.ArrayList; import java.util.Locale; -import java.util.TimeZone; @RunWith(RobolectricTestRunner.class) public final class BatteryChartViewTest { @@ -233,21 +231,4 @@ public final class BatteryChartViewTest { verify(mBatteryChartView.mHandler) .postDelayed(mBatteryChartView.mUpdateClickableStateRun, 500L); } - - @Ignore - @Test - public void testSetLatestTimestamp_generateExpectedTimestamps() { - final long timestamp = 1619196786769L; - ConvertUtils.sSimpleDateFormatForHour = null; - // Invokes the method first to create the SimpleDateFormat. - ConvertUtils.utcToLocalTimeHour( - mContext, /*timestamp=*/ 0, /*is24HourFormat=*/ false); - ConvertUtils.sSimpleDateFormatForHour - .setTimeZone(TimeZone.getTimeZone("America/Los_Angeles")); - final String[] expectedTimestamps = new String[] {"00", "06", "12", "18", "00"}; - - mBatteryChartView.setLatestTimestamp(timestamp); - - assertThat(mBatteryChartView.mTimestamps).isEqualTo(expectedTimestamps); - } } diff --git a/tests/robotests/src/com/android/settings/fuelgauge/ConvertUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/ConvertUtilsTest.java index 1b9e05b63b6..b04f053624a 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/ConvertUtilsTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/ConvertUtilsTest.java @@ -30,7 +30,6 @@ import android.os.UserHandle; import com.android.settings.testutils.FakeFeatureFactory; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @@ -320,71 +319,6 @@ public final class ConvertUtilsTest { .isEqualTo(entry.mConsumePower * ratio); } - @Ignore - @Test - public void testUtcToLocalTime_returnExpectedResult() { - ConvertUtils.sZoneId = null; - ConvertUtils.sLocale = null; - final long timestamp = 1619196786769L; - final String expectedZoneId = "America/Los_Angeles"; - ConvertUtils.sSimpleDateFormat = null; - // Invokes the method first to create the SimpleDateFormat. - ConvertUtils.utcToLocalTime(mContext, /*timestamp=*/ 0); - ConvertUtils.sSimpleDateFormat - .setTimeZone(TimeZone.getTimeZone(expectedZoneId)); - mContext.getResources().getConfiguration().setLocales( - new LocaleList(new Locale("en_US"))); - - assertThat(ConvertUtils.utcToLocalTime(mContext, timestamp)) - .isEqualTo("Apr 24,2021 00:53:06"); - assertThat(ConvertUtils.sZoneId).isNotEqualTo(expectedZoneId); - assertThat(ConvertUtils.sLocale).isEqualTo(new Locale("en_US")); - } - - @Ignore - @Test - public void testUtcToLocalTimeHour_12HourFormat_returnExpectedResult() { - ConvertUtils.sZoneIdForHour = null; - ConvertUtils.sLocaleForHour = null; - final long timestamp = 1619000086769L; - final String expectedZoneId = "America/Los_Angeles"; - ConvertUtils.sSimpleDateFormatForHour = null; - // Invokes the method first to create the SimpleDateFormat. - ConvertUtils.utcToLocalTimeHour( - mContext, /*timestamp=*/ 0, /*is24HourFormat=*/ false); - ConvertUtils.sSimpleDateFormatForHour - .setTimeZone(TimeZone.getTimeZone(expectedZoneId)); - mContext.getResources().getConfiguration().setLocales( - new LocaleList(new Locale("en_US"))); - - assertThat(ConvertUtils.utcToLocalTimeHour( - mContext, timestamp, /*is24HourFormat=*/ false)).isEqualTo("6"); - assertThat(ConvertUtils.sZoneIdForHour).isNotEqualTo(expectedZoneId); - assertThat(ConvertUtils.sLocaleForHour).isEqualTo(new Locale("en_US")); - } - - @Ignore - @Test - public void testUtcToLocalTimeHour_24HourFormat_returnExpectedResult() { - ConvertUtils.sZoneIdForHour = null; - ConvertUtils.sLocaleForHour = null; - final long timestamp = 1619000086769L; - final String expectedZoneId = "America/Los_Angeles"; - ConvertUtils.sSimpleDateFormatForHour = null; - // Invokes the method first to create the SimpleDateFormat. - ConvertUtils.utcToLocalTimeHour( - mContext, /*timestamp=*/ 0, /*is24HourFormat=*/ false); - ConvertUtils.sSimpleDateFormatForHour - .setTimeZone(TimeZone.getTimeZone(expectedZoneId)); - mContext.getResources().getConfiguration().setLocales( - new LocaleList(new Locale("en_US"))); - - assertThat(ConvertUtils.utcToLocalTimeHour( - mContext, timestamp, /*is24HourFormat=*/ true)).isEqualTo("18"); - assertThat(ConvertUtils.sZoneIdForHour).isNotEqualTo(expectedZoneId); - assertThat(ConvertUtils.sLocaleForHour).isEqualTo(new Locale("en_US")); - } - @Test public void testGetIndexedUsageMap_hideBackgroundUsageTime_returnsExpectedResult() { final long[] batteryHistoryKeys = new long[] {101L, 102L, 103L}; diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java index e8a9c5cb05a..c0b566a5f4b 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java @@ -155,4 +155,9 @@ public class PowerUsageFeatureProviderImplTest { assertThat(mPowerFeatureProvider.isSmartBatterySupported()).isFalse(); } + + @Test + public void testGetResumeChargeIntent_returnNull() { + assertThat(mPowerFeatureProvider.getResumeChargeIntent()).isNull(); + } } diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipDialogFragmentTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipDialogFragmentTest.java index 331fb343d43..99fbaf3c812 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipDialogFragmentTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipDialogFragmentTest.java @@ -31,6 +31,7 @@ import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.FragmentActivity; import com.android.settings.R; +import com.android.settings.fuelgauge.batterytip.tips.BatteryDefenderTip; import com.android.settings.fuelgauge.batterytip.tips.BatteryTip; import com.android.settings.fuelgauge.batterytip.tips.HighUsageTip; import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip; @@ -74,6 +75,7 @@ public class BatteryTipDialogFragmentTest { private RestrictAppTip mRestrictTwoAppsTip; private UnrestrictAppTip mUnrestrictAppTip; private SummaryTip mSummaryTip; + private BatteryDefenderTip mDefenderTip; private AppInfo mAppInfo; private ShadowPackageManager mPackageManager; @@ -116,6 +118,7 @@ public class BatteryTipDialogFragmentTest { mUnrestrictAppTip = new UnrestrictAppTip(BatteryTip.StateType.NEW, mAppInfo); mSummaryTip = spy(new SummaryTip(BatteryTip.StateType.NEW, EstimateKt.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN)); + mDefenderTip = new BatteryDefenderTip(BatteryTip.StateType.NEW); } @After @@ -243,4 +246,20 @@ public class BatteryTipDialogFragmentTest { + "your phone will suggest actions you can take.\n\nYou can always turn" + " on Battery Saver if you’re running low on battery."); } + + @Test + public void testOnCreateDialog_defenderTip_fireDialog() { + mDialogFragment = BatteryTipDialogFragment.newInstance(mDefenderTip, METRICS_KEY); + + FragmentController.setupFragment(mDialogFragment, FragmentActivity.class, + 0 /* containerViewId */, null /* bundle */); + + final AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog(); + ShadowAlertDialogCompat shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog); + + assertThat(shadowDialog.getTitle()).isEqualTo( + mContext.getString(R.string.battery_tip_limited_temporarily_title)); + assertThat(shadowDialog.getMessage()).isEqualTo( + mContext.getString(R.string.battery_tip_limited_temporarily_dialog_msg, "80%")); + } } diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/actions/BatteryDefenderActionTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/actions/BatteryDefenderActionTest.java deleted file mode 100644 index ad5dc54ca9b..00000000000 --- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/actions/BatteryDefenderActionTest.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2021 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.fuelgauge.batterytip.actions; - - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; - -import android.app.settings.SettingsEnums; -import android.content.Context; - -import com.android.settings.R; -import com.android.settings.SettingsActivity; -import com.android.settings.testutils.FakeFeatureFactory; -import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.RuntimeEnvironment; - -@RunWith(RobolectricTestRunner.class) -public final class BatteryDefenderActionTest { - - private Context mContext; - private FakeFeatureFactory mFeatureFactory; - private BatteryDefenderAction mBatteryDefenderAction; - private MetricsFeatureProvider mMetricsFeatureProvider; - - @Mock private SettingsActivity mSettingsActivity; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - - mFeatureFactory = FakeFeatureFactory.setupForTest(); - mMetricsFeatureProvider = mFeatureFactory.metricsFeatureProvider; - mContext = spy(RuntimeEnvironment.application); - doReturn(mContext).when(mSettingsActivity).getApplicationContext(); - mBatteryDefenderAction = new BatteryDefenderAction(mSettingsActivity); - } - - @Test - public void testHandlePositiveAction_logMetric() { - final int metricKey = 10; - mBatteryDefenderAction.handlePositiveAction(metricKey); - - verify(mMetricsFeatureProvider).action(mContext, - SettingsEnums.ACTION_TIP_BATTERY_DEFENDER, metricKey); - } -} diff --git a/tests/robotests/src/com/android/settings/gestures/LabeledSeekBarPreferenceTest.java b/tests/robotests/src/com/android/settings/gestures/LabeledSeekBarPreferenceTest.java index 4fb94f8cad5..3d83d58141b 100644 --- a/tests/robotests/src/com/android/settings/gestures/LabeledSeekBarPreferenceTest.java +++ b/tests/robotests/src/com/android/settings/gestures/LabeledSeekBarPreferenceTest.java @@ -16,6 +16,8 @@ package com.android.settings.gestures; +import static com.google.common.truth.Truth.assertThat; + import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -24,9 +26,12 @@ import android.view.LayoutInflater; import android.view.View; import android.widget.LinearLayout; import android.widget.SeekBar; +import android.widget.TextView; import androidx.preference.Preference; +import androidx.preference.PreferenceViewHolder; +import com.android.internal.R; import com.android.settings.widget.LabeledSeekBarPreference; import org.junit.Before; @@ -41,7 +46,9 @@ import org.robolectric.RuntimeEnvironment; public class LabeledSeekBarPreferenceTest { private Context mContext; + private PreferenceViewHolder mViewHolder; private SeekBar mSeekBar; + private TextView mSummary; private LabeledSeekBarPreference mSeekBarPreference; @Mock @@ -57,7 +64,9 @@ public class LabeledSeekBarPreferenceTest { final View view = inflater.inflate(mSeekBarPreference.getLayoutResource(), new LinearLayout(mContext), false); - mSeekBar = view.findViewById(com.android.internal.R.id.seekbar); + mViewHolder = PreferenceViewHolder.createInstanceForTests(view); + mSeekBar = (SeekBar) mViewHolder.findViewById(R.id.seekbar); + mSummary = (TextView) mViewHolder.findViewById(R.id.summary); } @Test @@ -69,4 +78,23 @@ public class LabeledSeekBarPreferenceTest { verify(mListener, times(1)).onPreferenceChange(mSeekBarPreference, 2); } + + @Test + public void seekBarPreferenceSummarySet_returnsValue() { + final String summary = "this is a summary"; + mSeekBarPreference.setSummary(summary); + mSeekBarPreference.onBindViewHolder(mViewHolder); + + assertThat(mSeekBarPreference.getSummary()).isEqualTo(summary); + assertThat(mSummary.getText()).isEqualTo(summary); + } + + @Test + public void seekBarPreferenceSummaryNull_hidesView() { + mSeekBarPreference.setSummary(null); + mSeekBarPreference.onBindViewHolder(mViewHolder); + + assertThat(mSummary.getText()).isEqualTo(""); + assertThat(mSummary.getVisibility()).isEqualTo(View.GONE); + } } diff --git a/tests/robotests/src/com/android/settings/gestures/LongPressPowerButtonPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/LongPressPowerButtonPreferenceControllerTest.java index 053fa5a12d7..fa97754491c 100644 --- a/tests/robotests/src/com/android/settings/gestures/LongPressPowerButtonPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/gestures/LongPressPowerButtonPreferenceControllerTest.java @@ -137,7 +137,7 @@ public class LongPressPowerButtonPreferenceControllerTest { when(mResources.getInteger( com.android.internal.R.integer.config_keyChordPowerVolumeUp)) .thenReturn( - LongPressPowerButtonPreferenceController.KEY_CHORD_POWER_VOLUME_UP_NO_ACTION); + LongPressPowerButtonPreferenceController.KEY_CHORD_POWER_VOLUME_UP_NO_ACTION); verify(mController.mFooterHint).setVisible(false); } @@ -148,7 +148,7 @@ public class LongPressPowerButtonPreferenceControllerTest { assertThat(Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.POWER_BUTTON_LONG_PRESS, -1)).isEqualTo( - LongPressPowerButtonPreferenceController.LONG_PRESS_POWER_ASSISTANT_VALUE); + PowerMenuSettingsUtils.LONG_PRESS_POWER_ASSISTANT_VALUE); assertThat(Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.KEY_CHORD_POWER_VOLUME_UP, -1)).isEqualTo( LongPressPowerButtonPreferenceController.KEY_CHORD_POWER_VOLUME_UP_GLOBAL_ACTIONS); @@ -162,19 +162,19 @@ public class LongPressPowerButtonPreferenceControllerTest { when(mResources.getInteger( com.android.internal.R.integer.config_longPressOnPowerBehavior)) .thenReturn( - LongPressPowerButtonPreferenceController.LONG_PRESS_POWER_GLOBAL_ACTIONS); + PowerMenuSettingsUtils.LONG_PRESS_POWER_GLOBAL_ACTIONS); mController.onPreferenceChange(null, false); assertThat(Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.POWER_BUTTON_LONG_PRESS, -1)).isEqualTo( - LongPressPowerButtonPreferenceController.LONG_PRESS_POWER_GLOBAL_ACTIONS); + PowerMenuSettingsUtils.LONG_PRESS_POWER_GLOBAL_ACTIONS); assertThat(Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.KEY_CHORD_POWER_VOLUME_UP, -1)).isEqualTo( LongPressPowerButtonPreferenceController.KEY_CHORD_POWER_VOLUME_UP_NO_ACTION); verify(mController.mAssistSwitch).setSummary( getString( - R.string.power_menu_summary_long_press_for_assist_disabled_with_power_menu)); + R.string.power_menu_summary_long_press_for_assist_disabled_with_power_menu)); } @Test @@ -199,23 +199,22 @@ public class LongPressPowerButtonPreferenceControllerTest { @Test public void preferenceUnchecked_assistDefault_setNoAction() { - // Value out of range chosen deliberately. + // Ensure that the Assistant is the default behavior for LPP. when(mResources.getInteger( com.android.internal.R.integer.config_longPressOnPowerBehavior)) .thenReturn( - LongPressPowerButtonPreferenceController.LONG_PRESS_POWER_ASSISTANT_VALUE); + PowerMenuSettingsUtils.LONG_PRESS_POWER_ASSISTANT_VALUE); mController.onPreferenceChange(null, false); assertThat(Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.POWER_BUTTON_LONG_PRESS, -1)).isEqualTo( - LongPressPowerButtonPreferenceController.LONG_PRESS_POWER_NO_ACTION); + PowerMenuSettingsUtils.LONG_PRESS_POWER_GLOBAL_ACTIONS); assertThat(Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.KEY_CHORD_POWER_VOLUME_UP, -1)).isEqualTo( LongPressPowerButtonPreferenceController.KEY_CHORD_POWER_VOLUME_UP_NO_ACTION); - verify(mController.mAssistSwitch).setSummary( - getString( - R.string.power_menu_summary_long_press_for_assist_disabled_no_action)); + verify(mController.mAssistSwitch).setSummary(getString( + R.string.power_menu_summary_long_press_for_assist_disabled_with_power_menu)); } private String getString(@StringRes int id) { diff --git a/tests/robotests/src/com/android/settings/gestures/LongPressPowerSensitivityPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/LongPressPowerSensitivityPreferenceControllerTest.java new file mode 100644 index 00000000000..9c99092849d --- /dev/null +++ b/tests/robotests/src/com/android/settings/gestures/LongPressPowerSensitivityPreferenceControllerTest.java @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2021 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.gestures; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import android.app.Application; +import android.content.res.Resources; +import android.provider.Settings; + +import androidx.test.core.app.ApplicationProvider; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; + +@RunWith(RobolectricTestRunner.class) +public class LongPressPowerSensitivityPreferenceControllerTest { + + private static final String KEY_LONG_PRESS_SENSITIVITY = + "gesture_power_menu_long_press_for_assist_sensitivity"; + + private static final int[] SENSITIVITY_VALUES = {250, 350, 500, 750, 850}; + + private Application mContext; + private Resources mResources; + private LongPressPowerSensitivityPreferenceController mController; + + @Before + public void setUp() { + mContext = spy(ApplicationProvider.getApplicationContext()); + mResources = mock(Resources.class); + when(mContext.getResources()).thenReturn(mResources); + + when(mResources.getIntArray( + com.android.internal.R.array.config_longPressOnPowerDurationSettings)) + .thenReturn(SENSITIVITY_VALUES); + + mController = new LongPressPowerSensitivityPreferenceController(mContext, + KEY_LONG_PRESS_SENSITIVITY); + } + + @Test + public void getSliderPosition_returnsDefaultValue() { + when(mResources.getInteger( + com.android.internal.R.integer.config_longPressOnPowerDurationMs)) + .thenReturn(750); + assertThat(mController.getSliderPosition()).isEqualTo(3); + } + + @Test + public void getSliderPosition_returnsSetValue() { + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.POWER_BUTTON_LONG_PRESS_DURATION_MS, 350); + assertThat(mController.getSliderPosition()).isEqualTo(1); + } + + @Test + public void setSliderPosition_setsValue() { + mController.setSliderPosition(4); + assertThat(Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.POWER_BUTTON_LONG_PRESS_DURATION_MS, 0)).isEqualTo(850); + } + + @Test + public void setSliderPositionOutOfBounds_returnsFalse() { + assertThat(mController.setSliderPosition(-1)).isFalse(); + assertThat(mController.setSliderPosition(10)).isFalse(); + } + + @Test + public void getMin_isZero() { + assertThat(mController.getMin()).isEqualTo(0); + } + + @Test + public void getMax_isEqualToLastValueIndex() { + assertThat(mController.getMax()).isEqualTo(4); + } + + @Test + public void longPressForAssistEnabled_isAvailable() { + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.POWER_BUTTON_LONG_PRESS, + PowerMenuSettingsUtils.LONG_PRESS_POWER_ASSISTANT_VALUE); + + assertThat(mController.getAvailabilityStatus()).isEqualTo( + LongPressPowerSensitivityPreferenceController.AVAILABLE); + } + + @Test + public void longPressForAssistDisabled_isNotAvailableDueToDependentSetting() { + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.POWER_BUTTON_LONG_PRESS, + PowerMenuSettingsUtils.LONG_PRESS_POWER_NO_ACTION); + + assertThat(mController.getAvailabilityStatus()).isEqualTo( + LongPressPowerSensitivityPreferenceController.DISABLED_DEPENDENT_SETTING); + } + + @Test + public void sensitivityValuesAreNull_notAvailable() { + when(mResources.getIntArray( + com.android.internal.R.array.config_longPressOnPowerDurationSettings)) + .thenReturn(null); + mController = new LongPressPowerSensitivityPreferenceController(mContext, + KEY_LONG_PRESS_SENSITIVITY); + + assertThat(mController.getAvailabilityStatus()).isEqualTo( + LongPressPowerSensitivityPreferenceController.UNSUPPORTED_ON_DEVICE); + } + + @Test + public void sensitivityValuesArrayTooShort_notAvailable() { + when(mResources.getIntArray( + com.android.internal.R.array.config_longPressOnPowerDurationSettings)) + .thenReturn(new int[]{200}); + mController = new LongPressPowerSensitivityPreferenceController(mContext, + KEY_LONG_PRESS_SENSITIVITY); + + assertThat(mController.getAvailabilityStatus()).isEqualTo( + LongPressPowerSensitivityPreferenceController.UNSUPPORTED_ON_DEVICE); + } +} diff --git a/tests/robotests/src/com/android/settings/gestures/PowerMenuSettingsUtilsTest.java b/tests/robotests/src/com/android/settings/gestures/PowerMenuSettingsUtilsTest.java new file mode 100644 index 00000000000..25f03207284 --- /dev/null +++ b/tests/robotests/src/com/android/settings/gestures/PowerMenuSettingsUtilsTest.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2021 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.gestures; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.content.res.Resources; +import android.provider.Settings; + +import androidx.test.core.app.ApplicationProvider; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; + +@RunWith(RobolectricTestRunner.class) +public class PowerMenuSettingsUtilsTest { + + private Context mContext; + private Resources mResources; + + @Before + public void setUp() { + mContext = spy(ApplicationProvider.getApplicationContext()); + mResources = mock(Resources.class); + when(mContext.getResources()).thenReturn(mResources); + } + + @Test + public void longPressBehaviourValuePresent_returnsValue() { + when(mResources.getInteger( + com.android.internal.R.integer.config_longPressOnPowerBehavior)) + .thenReturn(0); + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.POWER_BUTTON_LONG_PRESS, 1); + + assertThat(PowerMenuSettingsUtils.getPowerButtonSettingValue(mContext)).isEqualTo(1); + } + + @Test + public void longPressBehaviourValueNotPresent_returnsDefault() { + when(mResources.getInteger( + com.android.internal.R.integer.config_longPressOnPowerBehavior)) + .thenReturn(2); + + assertThat(PowerMenuSettingsUtils.getPowerButtonSettingValue(mContext)).isEqualTo(2); + } + + @Test + public void longPressBehaviourValueSetToAssistant_isAssistEnabledReturnsTrue() { + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.POWER_BUTTON_LONG_PRESS, 5); + assertThat(PowerMenuSettingsUtils.isLongPressPowerForAssistEnabled(mContext)).isTrue(); + } + + @Test + public void longPressBehaviourValueNotSetToAssistant_isAssistEnabledReturnsFalse() { + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.POWER_BUTTON_LONG_PRESS, 3); + assertThat(PowerMenuSettingsUtils.isLongPressPowerForAssistEnabled(mContext)).isFalse(); + } + + @Test + public void longPressBehaviourDefaultSetToAssistant_isAssistEnabledReturnsFalse() { + when(mResources.getInteger( + com.android.internal.R.integer.config_longPressOnPowerBehavior)) + .thenReturn(3); + + assertThat(PowerMenuSettingsUtils.isLongPressPowerForAssistEnabled(mContext)).isFalse(); + } +} diff --git a/tests/robotests/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragmentTest.java b/tests/robotests/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragmentTest.java index d0df92ec8a7..70b05981370 100644 --- a/tests/robotests/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragmentTest.java +++ b/tests/robotests/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragmentTest.java @@ -159,7 +159,7 @@ public class RenameMobileNetworkDialogFragmentTest { eq(SubscriptionManager.NAME_SOURCE_USER_INPUT)); assertThat(captor.getValue()).isEqualTo("test2"); verify(mSubscriptionMgr) - .setIconTint(eq(Color.parseColor("#ff00796b" /* teal */)), eq(mSubscriptionId)); + .setIconTint(eq(Color.parseColor("#ff006D74" /* cyan */)), eq(mSubscriptionId)); } @Test @@ -174,6 +174,34 @@ public class RenameMobileNetworkDialogFragmentTest { assertThat(view.findViewById(R.id.number_label).getVisibility()).isEqualTo(View.GONE); } + @Test + public void populateView_getPreviousSimColor_setCorrectSelection() { + final View view = LayoutInflater.from(mActivity).inflate( + R.layout.dialog_mobile_network_rename, null); + when(mSubscriptionInfo.getIconTint()) + .thenReturn(Color.parseColor("#ff3367d6"/* blue700 */)); + + startDialog(); + mFragment.populateView(view); + + final Spinner colorSpinnerView = mFragment.getColorSpinnerView(); + assertThat(colorSpinnerView.getSelectedItemPosition()).isEqualTo(1); + } + + @Test + public void populateView_getUpdatedSimColor_setCorrectSelection() { + final View view = LayoutInflater.from(mActivity).inflate( + R.layout.dialog_mobile_network_rename, null); + when(mSubscriptionInfo.getIconTint()) + .thenReturn(Color.parseColor("#ff137333"/* Green800 */)); + + startDialog(); + mFragment.populateView(view); + + final Spinner colorSpinnerView = mFragment.getColorSpinnerView(); + assertThat(colorSpinnerView.getSelectedItemPosition()).isEqualTo(2); + } + /** * Helper method to start the dialog */ diff --git a/tests/robotests/src/com/android/settings/notification/app/RecentConversationsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/app/RecentConversationsPreferenceControllerTest.java index f0ae7ab376d..1688d63ec52 100644 --- a/tests/robotests/src/com/android/settings/notification/app/RecentConversationsPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/app/RecentConversationsPreferenceControllerTest.java @@ -36,6 +36,7 @@ import android.content.pm.ShortcutInfo; import android.os.Bundle; import android.os.UserHandle; import android.provider.Settings; +import android.text.SpannedString; import android.view.LayoutInflater; import android.view.View; import android.widget.LinearLayout; @@ -338,4 +339,36 @@ public class RecentConversationsPreferenceControllerTest { // one for the preference, none for 'clear all' verify(outerContainer, times(1)).addPreference(any()); } + + @Test + public void testSpans() { + ShortcutInfo si = mock(ShortcutInfo.class); + when(si.getLabel()).thenReturn(new SpannedString("hello")); + ConversationChannel ccw = new ConversationChannel(si, 6, + new NotificationChannel("hi", "hi", 4), + null, 7, + true /* hasactivenotifs */); + ShortcutInfo si2 = mock(ShortcutInfo.class); + when(si2.getLabel()).thenReturn("hello"); + ConversationChannel ccw2 = new ConversationChannel(si2, 6, + new NotificationChannel("hi2", "hi2", 4), + null, 7, + true /* hasactivenotifs */); + // no crash + mController.mConversationComparator.compare(ccw, ccw2); + } + + @Test + public void testNullSpans() { + ConversationChannel ccw = new ConversationChannel(mock(ShortcutInfo.class), 6, + new NotificationChannel("hi", "hi", 4), + null, 7, + true /* hasactivenotifs */); + ConversationChannel ccw2 = new ConversationChannel(mock(ShortcutInfo.class), 6, + new NotificationChannel("hi2", "hi2", 4), + null, 7, + true /* hasactivenotifs */); + // no crash + mController.mConversationComparator.compare(ccw, ccw2); + } } diff --git a/tests/robotests/src/com/android/settings/password/ChooseLockGenericControllerTest.java b/tests/robotests/src/com/android/settings/password/ChooseLockGenericControllerTest.java index 049a34969c1..996d5722693 100644 --- a/tests/robotests/src/com/android/settings/password/ChooseLockGenericControllerTest.java +++ b/tests/robotests/src/com/android/settings/password/ChooseLockGenericControllerTest.java @@ -22,6 +22,7 @@ import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_MEDIUM; import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE; import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC; import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX; +import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_MANAGED; import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC; import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX; import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING; @@ -189,6 +190,16 @@ public class ChooseLockGenericControllerTest { assertThat(mController.isScreenLockEnabled(ScreenLockType.PASSWORD)).isTrue(); } + @Test + public void isScreenLockEnabled_QualityManaged() { + setDevicePolicyPasswordQuality(PASSWORD_QUALITY_MANAGED); + assertThat(mController.isScreenLockEnabled(ScreenLockType.NONE)).isFalse(); + assertThat(mController.isScreenLockEnabled(ScreenLockType.SWIPE)).isFalse(); + assertThat(mController.isScreenLockEnabled(ScreenLockType.PATTERN)).isFalse(); + assertThat(mController.isScreenLockEnabled(ScreenLockType.PIN)).isFalse(); + assertThat(mController.isScreenLockEnabled(ScreenLockType.PASSWORD)).isFalse(); + } + @Test public void isScreenLockEnabled_NoneComplexity() { when(mLockPatternUtils.getRequestedPasswordComplexity(anyInt(), anyBoolean())) @@ -353,6 +364,9 @@ public class ChooseLockGenericControllerTest { when(mLockPatternUtils.getRequestedPasswordMetrics(anyInt(), anyBoolean())) .thenReturn(policy.getMinMetrics()); + + when(mLockPatternUtils.isCredentialsDisabledForUser(anyInt())) + .thenReturn(quality == PASSWORD_QUALITY_MANAGED); } private ChooseLockGenericController.Builder createBuilder() { diff --git a/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java b/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java index 7da9c505b8e..e789b61f188 100644 --- a/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java +++ b/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java @@ -404,18 +404,6 @@ public class ChooseLockPasswordTest { "Must be fewer than 17 characters"); } - @Test - public void assertThat_chooseLockIconChanged_WhenFingerprintExtraSet() { - ShadowDrawable drawable = setActivityAndGetIconDrawable(true); - assertThat(drawable.getCreatedFromResId()).isEqualTo(R.drawable.ic_fingerprint_header); - } - - @Test - public void assertThat_chooseLockIconNotChanged_WhenFingerprintExtraSet() { - ShadowDrawable drawable = setActivityAndGetIconDrawable(false); - assertThat(drawable.getCreatedFromResId()).isNotEqualTo(R.drawable.ic_fingerprint_header); - } - @Test public void validateComplexityMergedFromDpmOnCreate() { ShadowLockPatternUtils.setRequiredPasswordComplexity(PASSWORD_COMPLEXITY_LOW); diff --git a/tests/robotests/src/com/android/settings/password/ChooseLockPatternTest.java b/tests/robotests/src/com/android/settings/password/ChooseLockPatternTest.java index 1cb946b786f..f5cc39435ad 100644 --- a/tests/robotests/src/com/android/settings/password/ChooseLockPatternTest.java +++ b/tests/robotests/src/com/android/settings/password/ChooseLockPatternTest.java @@ -31,9 +31,6 @@ import com.android.settings.R; import com.android.settings.password.ChooseLockPattern.ChooseLockPatternFragment; import com.android.settings.password.ChooseLockPattern.IntentBuilder; import com.android.settings.testutils.shadow.ShadowUtils; -import com.android.settingslib.testutils.DrawableTestHelper; - -import com.google.android.setupdesign.GlifLayout; import org.junit.Test; import org.junit.runner.RunWith; @@ -99,16 +96,6 @@ public class ChooseLockPatternTest { .isNotNull(); } - @Config(qualifiers = "sw400dp") - @Test - public void fingerprintExtraSet_shouldDisplayFingerprintIcon() { - ChooseLockPattern activity = createActivity(true); - ChooseLockPatternFragment fragment = (ChooseLockPatternFragment) - activity.getSupportFragmentManager().findFragmentById(R.id.main_content); - DrawableTestHelper.assertDrawableResId(((GlifLayout) fragment.getView()).getIcon(), - R.drawable.ic_fingerprint_header); - } - @Config(qualifiers = "sw300dp") @Test public void smallScreens_shouldHideIcon() { diff --git a/tests/robotests/src/com/android/settings/wifi/WifiDialogActivityTest.java b/tests/robotests/src/com/android/settings/wifi/WifiDialogActivityTest.java index 685819e7839..f601e36229c 100644 --- a/tests/robotests/src/com/android/settings/wifi/WifiDialogActivityTest.java +++ b/tests/robotests/src/com/android/settings/wifi/WifiDialogActivityTest.java @@ -16,25 +16,12 @@ package com.android.settings.wifi; -import static android.Manifest.permission.ACCESS_COARSE_LOCATION; -import static android.Manifest.permission.ACCESS_FINE_LOCATION; - -import static com.android.settings.wifi.WifiDialogActivity.REQUEST_CODE_WIFI_DPP_ENROLLEE_QR_CODE_SCANNER; -import static com.android.settings.wifi.WifiDialogActivity.RESULT_CONNECTED; -import static com.android.settings.wifi.WifiDialogActivity.RESULT_OK; - import static com.google.common.truth.Truth.assertThat; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; import android.content.Intent; -import android.content.pm.PackageManager; import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiManager; import androidx.lifecycle.Lifecycle.State; import androidx.test.core.app.ActivityScenario; @@ -44,7 +31,6 @@ import com.android.settings.testutils.shadow.ShadowAlertDialogCompat; import com.android.settings.testutils.shadow.ShadowConnectivityManager; import com.android.settings.testutils.shadow.ShadowNetworkDetailsTracker; import com.android.settings.testutils.shadow.ShadowWifiManager; -import com.android.settingslib.wifi.AccessPoint; import com.google.android.setupcompat.util.WizardManagerHelper; @@ -69,25 +55,7 @@ import org.robolectric.util.ReflectionHelpers; }) public class WifiDialogActivityTest { - private static final String CALLING_PACKAGE = "calling_package"; private static final String AP1_SSID = "\"ap1\""; - - @Mock - PackageManager mPackageManager; - @Mock - WifiManager mWifiManager; - @Mock - WifiDialog mWifiDialog; - @Mock - WifiConfiguration mWifiConfiguration; - @Mock - AccessPoint mAccessPoint; - @Mock - WifiDialog2 mWifiDialog2; - @Mock - WifiConfigController2 mWifiConfiguration2; - @Mock - Intent mResultData; @Mock private WifiConfigController mController; @Mock @@ -98,10 +66,6 @@ public class WifiDialogActivityTest { @Before public void setUp() { MockitoAnnotations.initMocks(this); - when(mWifiDialog.getController()).thenReturn(mController); - when(mController.getConfig()).thenReturn(mWifiConfiguration); - when(mController.getAccessPoint()).thenReturn(mAccessPoint); - when(mWifiDialog2.getController()).thenReturn(mWifiConfiguration2); WifiConfiguration wifiConfig = new WifiConfiguration(); wifiConfig.SSID = AP1_SSID; @@ -133,52 +97,6 @@ public class WifiDialogActivityTest { assertThat(ShadowWifiManager.get().savedWifiConfig.SSID).isEqualTo(AP1_SSID); } - @Test - public void onSubmit_noPermissionForResult_setResultWithoutData() { - WifiDialogActivity activity = spy(Robolectric.setupActivity(WifiDialogActivity.class)); - when(activity.hasPermissionForResult()).thenReturn(false); - when(activity.getSystemService(WifiManager.class)).thenReturn(mWifiManager); - - activity.onSubmit(mWifiDialog); - - verify(activity).setResult(RESULT_CONNECTED, null); - } - - @Test - public void onSubmit_hasPermissionForResult_setResultWithData() { - WifiDialogActivity activity = spy(Robolectric.setupActivity(WifiDialogActivity.class)); - when(activity.hasPermissionForResult()).thenReturn(true); - when(activity.createResultData(any(), any())).thenReturn(mResultData); - when(activity.getSystemService(WifiManager.class)).thenReturn(mWifiManager); - - activity.onSubmit(mWifiDialog); - - verify(activity).setResult(RESULT_CONNECTED, mResultData); - } - - @Test - public void onSubmit2_noPermissionForResult_setResultWithoutData() { - WifiDialogActivity activity = spy(Robolectric.setupActivity(WifiDialogActivity.class)); - when(activity.hasPermissionForResult()).thenReturn(false); - when(activity.getSystemService(WifiManager.class)).thenReturn(mWifiManager); - - activity.onSubmit(mWifiDialog2); - - verify(activity).setResult(RESULT_CONNECTED, null); - } - - @Test - public void onSubmit2_hasPermissionForResult_setResultWithData() { - WifiDialogActivity activity = spy(Robolectric.setupActivity(WifiDialogActivity.class)); - when(activity.hasPermissionForResult()).thenReturn(true); - when(activity.createResultData(any(), any())).thenReturn(mResultData); - when(activity.getSystemService(WifiManager.class)).thenReturn(mWifiManager); - - activity.onSubmit(mWifiDialog2); - - verify(activity).setResult(RESULT_CONNECTED, mResultData); - } - @Test @Ignore public void onSubmit2_whenConnectForCallerIsTrue_shouldConnectToNetwork() { @@ -260,97 +178,4 @@ public class WifiDialogActivityTest { assertThat(dialog.getContext().getThemeResId()) .isEqualTo(R.style.SuwAlertDialogThemeCompat_Light); } - - @Test - public void onActivityResult_noPermissionForResult_setResultWithoutData() { - WifiDialogActivity activity = spy(Robolectric.setupActivity(WifiDialogActivity.class)); - when(activity.hasPermissionForResult()).thenReturn(false); - final Intent data = new Intent(); - - activity.onActivityResult(REQUEST_CODE_WIFI_DPP_ENROLLEE_QR_CODE_SCANNER, RESULT_OK, - data); - - verify(activity).setResult(RESULT_CONNECTED); - } - - @Test - public void onActivityResult_hasPermissionForResult_setResultWithData() { - WifiDialogActivity activity = spy(Robolectric.setupActivity(WifiDialogActivity.class)); - when(activity.hasPermissionForResult()).thenReturn(true); - final Intent data = new Intent(); - - activity.onActivityResult(REQUEST_CODE_WIFI_DPP_ENROLLEE_QR_CODE_SCANNER, RESULT_OK, - data); - - verify(activity).setResult(RESULT_CONNECTED, data); - } - - @Test - public void hasPermissionForResult_noCallingPackage_returnFalse() { - WifiDialogActivity activity = spy(Robolectric.setupActivity(WifiDialogActivity.class)); - when(activity.getCallingPackage()).thenReturn(null); - - final boolean result = activity.hasPermissionForResult(); - - assertThat(result).isFalse(); - } - - @Test - public void hasPermissionForResult_noPermission_returnFalse() { - WifiDialogActivity activity = spy(Robolectric.setupActivity(WifiDialogActivity.class)); - when(activity.getCallingPackage()).thenReturn(null); - when(mPackageManager.checkPermission(ACCESS_COARSE_LOCATION, CALLING_PACKAGE)) - .thenReturn(PackageManager.PERMISSION_DENIED); - when(mPackageManager.checkPermission(ACCESS_FINE_LOCATION, CALLING_PACKAGE)) - .thenReturn(PackageManager.PERMISSION_DENIED); - - final boolean result = activity.hasPermissionForResult(); - - assertThat(result).isFalse(); - } - - @Test - public void hasPermissionForResult_hasCoarseLocationPermission_returnTrue() { - WifiDialogActivity activity = spy(Robolectric.setupActivity(WifiDialogActivity.class)); - when(activity.getCallingPackage()).thenReturn(CALLING_PACKAGE); - when(activity.getPackageManager()).thenReturn(mPackageManager); - when(mPackageManager.checkPermission(ACCESS_COARSE_LOCATION, CALLING_PACKAGE)) - .thenReturn(PackageManager.PERMISSION_GRANTED); - when(mPackageManager.checkPermission(ACCESS_FINE_LOCATION, CALLING_PACKAGE)) - .thenReturn(PackageManager.PERMISSION_DENIED); - - final boolean result = activity.hasPermissionForResult(); - - assertThat(result).isTrue(); - } - - @Test - public void hasPermissionForResult_hasFineLocationPermission_returnTrue() { - WifiDialogActivity activity = spy(Robolectric.setupActivity(WifiDialogActivity.class)); - when(activity.getCallingPackage()).thenReturn(CALLING_PACKAGE); - when(activity.getPackageManager()).thenReturn(mPackageManager); - when(mPackageManager.checkPermission(ACCESS_COARSE_LOCATION, CALLING_PACKAGE)) - .thenReturn(PackageManager.PERMISSION_DENIED); - when(mPackageManager.checkPermission(ACCESS_FINE_LOCATION, CALLING_PACKAGE)) - .thenReturn(PackageManager.PERMISSION_GRANTED); - - final boolean result = activity.hasPermissionForResult(); - - assertThat(result).isTrue(); - } - - @Test - public void hasPermissionForResult_haveBothLocationPermissions_returnTrue() { - WifiDialogActivity activity = spy(Robolectric.setupActivity(WifiDialogActivity.class)); - when(activity.getCallingPackage()).thenReturn(CALLING_PACKAGE); - when(activity.getPackageManager()).thenReturn(mPackageManager); - when(mPackageManager.checkPermission(ACCESS_COARSE_LOCATION, CALLING_PACKAGE)) - .thenReturn(PackageManager.PERMISSION_GRANTED); - when(mPackageManager.checkPermission(ACCESS_FINE_LOCATION, CALLING_PACKAGE)) - .thenReturn(PackageManager.PERMISSION_GRANTED); - - final boolean result = activity.hasPermissionForResult(); - - assertThat(result).isTrue(); - } } diff --git a/tests/robotests/src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2Test.java b/tests/robotests/src/com/android/settings/wifi/details/WifiNetworkDetailsFragmentTest.java similarity index 91% rename from tests/robotests/src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2Test.java rename to tests/robotests/src/com/android/settings/wifi/details/WifiNetworkDetailsFragmentTest.java index fdd6295ab65..4f742549f24 100644 --- a/tests/robotests/src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2Test.java +++ b/tests/robotests/src/com/android/settings/wifi/details/WifiNetworkDetailsFragmentTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 The Android Open Source Project + * Copyright (C) 2021 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. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.settings.wifi.details2; +package com.android.settings.wifi.details; import static com.android.settings.wifi.WifiSettings.WIFI_DIALOG_ID; @@ -54,9 +54,9 @@ import org.robolectric.RuntimeEnvironment; import java.util.ArrayList; @RunWith(RobolectricTestRunner.class) -public class WifiNetworkDetailsFragment2Test { +public class WifiNetworkDetailsFragmentTest { - final String TEST_PREFERENCE_KEY = "TEST_PREFERENCE_KEY"; + private static final String TEST_PREFERENCE_KEY = "TEST_PREFERENCE_KEY"; @Mock WifiEntry mWifiEntry; @@ -64,7 +64,7 @@ public class WifiNetworkDetailsFragment2Test { NetworkDetailsTracker mNetworkDetailsTracker; @Mock Menu mMenu; - private WifiNetworkDetailsFragment2 mFragment; + private WifiNetworkDetailsFragment mFragment; @Before public void setUp() { @@ -72,7 +72,7 @@ public class WifiNetworkDetailsFragment2Test { doReturn(mWifiEntry).when(mNetworkDetailsTracker).getWifiEntry(); doReturn(true).when(mWifiEntry).isSaved(); - mFragment = new WifiNetworkDetailsFragment2(); + mFragment = new WifiNetworkDetailsFragment(); mFragment.mNetworkDetailsTracker = mNetworkDetailsTracker; } @@ -165,8 +165,8 @@ public class WifiNetworkDetailsFragment2Test { verify(controller).displayPreference(screen); } - // Fake WifiNetworkDetailsFragment2 to override the protected method as public. - public class FakeFragment extends WifiNetworkDetailsFragment2 { + // Fake WifiNetworkDetailsFragment to override the protected method as public. + public static class FakeFragment extends WifiNetworkDetailsFragment { @Override public void addPreferenceController(AbstractPreferenceController controller) { @@ -179,7 +179,7 @@ public class WifiNetworkDetailsFragment2Test { } } - public class TestController extends BasePreferenceController { + public static class TestController extends BasePreferenceController { public TestController() { super(RuntimeEnvironment.application, TEST_PREFERENCE_KEY); diff --git a/tests/robotests/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2Test.java b/tests/robotests/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2Test.java index 7354d85bc7a..6a098bc9ead 100644 --- a/tests/robotests/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2Test.java +++ b/tests/robotests/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2Test.java @@ -76,6 +76,7 @@ import com.android.settings.Utils; import com.android.settings.testutils.shadow.ShadowDevicePolicyManager; import com.android.settings.testutils.shadow.ShadowEntityHeaderController; import com.android.settings.widget.EntityHeaderController; +import com.android.settings.wifi.details.WifiNetworkDetailsFragment; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.utils.StringUtil; @@ -145,7 +146,7 @@ public class WifiDetailPreferenceController2Test { @Mock private WifiInfo mMockWifiInfo; @Mock - private WifiNetworkDetailsFragment2 mMockFragment; + private WifiNetworkDetailsFragment mMockFragment; @Mock private WifiManager mMockWifiManager; @Mock diff --git a/tests/unit/src/com/android/settings/biometrics/combination/BiometricSettingsAppPreferenceControllerTest.java b/tests/unit/src/com/android/settings/biometrics/combination/BiometricSettingsAppPreferenceControllerTest.java new file mode 100644 index 00000000000..f66e65f6c5b --- /dev/null +++ b/tests/unit/src/com/android/settings/biometrics/combination/BiometricSettingsAppPreferenceControllerTest.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2021 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.biometrics.combination; + +import static com.google.common.truth.Truth.assertThat; + +import android.content.Context; + +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +public class BiometricSettingsAppPreferenceControllerTest { + + private Context mContext; + private BiometricSettingsAppPreferenceController mController; + + @Before + public void setUp() { + mContext = ApplicationProvider.getApplicationContext(); + mController = new BiometricSettingsAppPreferenceController(mContext, "key"); + } + + @Test + public void isSliceable_returnFalse() { + assertThat(mController.isSliceable()).isFalse(); + } +} diff --git a/tests/unit/src/com/android/settings/biometrics/combination/BiometricSettingsKeyguardPreferenceControllerTest.java b/tests/unit/src/com/android/settings/biometrics/combination/BiometricSettingsKeyguardPreferenceControllerTest.java new file mode 100644 index 00000000000..400b4fe70e9 --- /dev/null +++ b/tests/unit/src/com/android/settings/biometrics/combination/BiometricSettingsKeyguardPreferenceControllerTest.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2021 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.biometrics.combination; + +import static com.google.common.truth.Truth.assertThat; + +import android.content.Context; + +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +public class BiometricSettingsKeyguardPreferenceControllerTest { + + private Context mContext; + private BiometricSettingsKeyguardPreferenceController mController; + + @Before + public void setUp() { + mContext = ApplicationProvider.getApplicationContext(); + mController = new BiometricSettingsKeyguardPreferenceController(mContext, "key"); + } + + @Test + public void isSliceable_returnFalse() { + assertThat(mController.isSliceable()).isFalse(); + } +} diff --git a/tests/unit/src/com/android/settings/biometrics/face/FaceSettingsAppPreferenceControllerTest.java b/tests/unit/src/com/android/settings/biometrics/face/FaceSettingsAppPreferenceControllerTest.java new file mode 100644 index 00000000000..af45a68d7d1 --- /dev/null +++ b/tests/unit/src/com/android/settings/biometrics/face/FaceSettingsAppPreferenceControllerTest.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2021 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.biometrics.face; + +import static com.google.common.truth.Truth.assertThat; + +import android.content.Context; + +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +public class FaceSettingsAppPreferenceControllerTest { + + private Context mContext; + private FaceSettingsAppPreferenceController mController; + + @Before + public void setUp() { + mContext = ApplicationProvider.getApplicationContext(); + mController = new FaceSettingsAppPreferenceController(mContext); + } + + @Test + public void isSliceable_returnFalse() { + assertThat(mController.isSliceable()).isFalse(); + } +} diff --git a/tests/unit/src/com/android/settings/biometrics/face/FaceSettingsConfirmPreferenceControllerTest.java b/tests/unit/src/com/android/settings/biometrics/face/FaceSettingsConfirmPreferenceControllerTest.java new file mode 100644 index 00000000000..678295943e7 --- /dev/null +++ b/tests/unit/src/com/android/settings/biometrics/face/FaceSettingsConfirmPreferenceControllerTest.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2021 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.biometrics.face; + +import static com.google.common.truth.Truth.assertThat; + +import android.content.Context; + +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +public class FaceSettingsConfirmPreferenceControllerTest { + + private Context mContext; + private FaceSettingsConfirmPreferenceController mController; + + @Before + public void setUp() { + mContext = ApplicationProvider.getApplicationContext(); + mController = new FaceSettingsConfirmPreferenceController(mContext); + } + + @Test + public void isSliceable_returnFalse() { + assertThat(mController.isSliceable()).isFalse(); + } +} diff --git a/tests/unit/src/com/android/settings/biometrics/face/FaceSettingsKeyguardPreferenceControllerTest.java b/tests/unit/src/com/android/settings/biometrics/face/FaceSettingsKeyguardPreferenceControllerTest.java new file mode 100644 index 00000000000..ee62ed7ba34 --- /dev/null +++ b/tests/unit/src/com/android/settings/biometrics/face/FaceSettingsKeyguardPreferenceControllerTest.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2021 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.biometrics.face; + +import static com.google.common.truth.Truth.assertThat; + +import android.content.Context; + +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +public class FaceSettingsKeyguardPreferenceControllerTest { + private Context mContext; + private FaceSettingsKeyguardPreferenceController mController; + + @Before + public void setUp() { + mContext = ApplicationProvider.getApplicationContext(); + mController = new FaceSettingsKeyguardPreferenceController(mContext); + } + + @Test + public void isSliceable_returnFalse() { + assertThat(mController.isSliceable()).isFalse(); + } +} diff --git a/tests/unit/src/com/android/settings/display/ColorModePreferenceFragmentTest.java b/tests/unit/src/com/android/settings/display/ColorModePreferenceFragmentTest.java index cfdedc78e0c..450525c9339 100644 --- a/tests/unit/src/com/android/settings/display/ColorModePreferenceFragmentTest.java +++ b/tests/unit/src/com/android/settings/display/ColorModePreferenceFragmentTest.java @@ -39,6 +39,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.ArrayList; import java.util.List; @RunWith(AndroidJUnit4.class) @@ -232,4 +233,15 @@ public class ColorModePreferenceFragmentTest { verify(mFragment).setColorMode(ColorDisplayManager.COLOR_MODE_AUTOMATIC); } + + @Test + @UiThreadTest + public void checkViewPagerTotalCount() throws Throwable { + final ArrayList viewPagerResList = mFragment.getViewPagerResource(); + + assertThat(viewPagerResList.size()).isEqualTo(3); + for (int idx = 0; idx < viewPagerResList.size(); idx++) { + assertThat(viewPagerResList.get(idx) > 0).isTrue(); + } + } } diff --git a/tests/unit/src/com/android/settings/network/NetworkProviderDownloadedSimsCategoryControllerTest.java b/tests/unit/src/com/android/settings/network/NetworkProviderDownloadedSimsCategoryControllerTest.java index e34b489844e..90455022eda 100644 --- a/tests/unit/src/com/android/settings/network/NetworkProviderDownloadedSimsCategoryControllerTest.java +++ b/tests/unit/src/com/android/settings/network/NetworkProviderDownloadedSimsCategoryControllerTest.java @@ -26,9 +26,12 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.os.Looper; +import android.telephony.SubscriptionInfo; +import com.android.settings.testutils.ResourcesUtils; import com.android.settingslib.core.lifecycle.Lifecycle; +import androidx.preference.Preference; import androidx.preference.PreferenceCategory; import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; @@ -41,38 +44,39 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.util.ArrayList; +import java.util.Arrays; + @RunWith(AndroidJUnit4.class) public class NetworkProviderDownloadedSimsCategoryControllerTest { private static final String KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM = "provider_model_downloaded_sim_category"; + private static final String KEY_ADD_MORE = "add_more"; + private static final String SUB_1 = "SUB_1"; + private static final String SUB_2 = "SUB_2"; + private static final int SUB_ID_1 = 1; + private static final int SUB_ID_2 = 2; - @Mock - private NetworkProviderDownloadedSimListController mNetworkProviderDownloadedSimListController; - @Mock - private PreferenceCategory mPreferenceCategory; @Mock private Lifecycle mLifecycle; + @Mock + private SubscriptionInfo mSubscriptionInfo1; + @Mock + private SubscriptionInfo mSubscriptionInfo2; private Context mContext; private NetworkProviderDownloadedSimsCategoryController mCategoryController; - + private PreferenceCategory mPreferenceCategory; private PreferenceManager mPreferenceManager; private PreferenceScreen mPreferenceScreen; + private Preference mAddMorePreference; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mContext = spy(ApplicationProvider.getApplicationContext()); - mCategoryController = new NetworkProviderDownloadedSimsCategoryController( - mContext, KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM) { - @Override - protected NetworkProviderDownloadedSimListController createDownloadedSimListController( - Lifecycle lifecycle) { - return mNetworkProviderDownloadedSimListController; - } - }; if (Looper.myLooper() == null) { Looper.prepare(); @@ -80,14 +84,21 @@ public class NetworkProviderDownloadedSimsCategoryControllerTest { mPreferenceManager = new PreferenceManager(mContext); mPreferenceScreen = mPreferenceManager.createPreferenceScreen(mContext); - when(mPreferenceCategory.getKey()).thenReturn(KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM); - when(mPreferenceCategory.getPreferenceCount()).thenReturn(1); + mPreferenceCategory = new PreferenceCategory(mContext); + mPreferenceCategory.setKey(KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM); + mAddMorePreference = new Preference(mContext); + mAddMorePreference.setKey(KEY_ADD_MORE); + mAddMorePreference.setVisible(true); mPreferenceScreen.addPreference(mPreferenceCategory); + mPreferenceScreen.addPreference(mAddMorePreference); + + mCategoryController = new NetworkProviderDownloadedSimsCategoryController(mContext, + KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM, mLifecycle); } @Test public void getAvailabilityStatus_returnUnavailable() { - mNetworkProviderDownloadedSimListController = null; + SubscriptionUtil.setAvailableSubscriptionsForTesting(new ArrayList<>()); assertThat(mCategoryController.getAvailabilityStatus()).isEqualTo( CONDITIONALLY_UNAVAILABLE); @@ -95,10 +106,46 @@ public class NetworkProviderDownloadedSimsCategoryControllerTest { @Test public void displayPreference_isVisible() { - when(mNetworkProviderDownloadedSimListController.isAvailable()).thenReturn(true); - mCategoryController.init(mLifecycle); + setUpSubscriptionInfoForDownloadedSim(SUB_ID_1, SUB_1, mSubscriptionInfo1); + SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(mSubscriptionInfo1)); mCategoryController.displayPreference(mPreferenceScreen); assertEquals(mPreferenceCategory.isVisible(), true); } + + + @Test + public void updateState_setTitle_withTwoDownloadedSims_returnDownloadedSims() { + setUpSubscriptionInfoForDownloadedSim(SUB_ID_1, SUB_1, mSubscriptionInfo1); + setUpSubscriptionInfoForDownloadedSim(SUB_ID_2, SUB_2, mSubscriptionInfo2); + SubscriptionUtil.setAvailableSubscriptionsForTesting( + Arrays.asList(mSubscriptionInfo1, mSubscriptionInfo2)); + + mCategoryController.displayPreference(mPreferenceScreen); + mCategoryController.updateState(mPreferenceCategory); + + assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(2); + assertThat(mPreferenceCategory.getTitle()).isEqualTo( + ResourcesUtils.getResourcesString(mContext, "downloaded_sims_category_title")); + } + + @Test + public void updateState_setTitle_withOneDownloadedSim_returnDownloadedSim() { + setUpSubscriptionInfoForDownloadedSim(SUB_ID_1, SUB_1, mSubscriptionInfo1); + SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(mSubscriptionInfo1)); + + mCategoryController.displayPreference(mPreferenceScreen); + mCategoryController.updateState(mPreferenceCategory); + + assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(1); + assertThat(mPreferenceCategory.getTitle()).isEqualTo( + ResourcesUtils.getResourcesString(mContext, "downloaded_sim_category_title")); + } + + private void setUpSubscriptionInfoForDownloadedSim(int subId, String displayName, + SubscriptionInfo subscriptionInfo) { + when(subscriptionInfo.isEmbedded()).thenReturn(true); + when(subscriptionInfo.getSubscriptionId()).thenReturn(subId); + when(subscriptionInfo.getDisplayName()).thenReturn(displayName); + } } diff --git a/tests/unit/src/com/android/settings/network/NetworkProviderSimListControllerTest.java b/tests/unit/src/com/android/settings/network/NetworkProviderSimListControllerTest.java index 3b0a40ab702..066cf6b5f69 100644 --- a/tests/unit/src/com/android/settings/network/NetworkProviderSimListControllerTest.java +++ b/tests/unit/src/com/android/settings/network/NetworkProviderSimListControllerTest.java @@ -16,10 +16,14 @@ package com.android.settings.network; +import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE; +import static com.google.common.truth.Truth.assertThat; + import static androidx.lifecycle.Lifecycle.Event; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; @@ -170,7 +174,6 @@ public class NetworkProviderSimListControllerTest { assertTrue(TextUtils.equals(mController.getSummary(SUB_ID_1, DISPLAY_NAME_1), summary)); } - @Test @UiThreadTest public void getSummary_inactivePSim() { @@ -227,4 +230,18 @@ public class NetworkProviderSimListControllerTest { assertTrue(TextUtils.equals(mController.getSummary(SUB_ID_1, DISPLAY_NAME_1), summary)); } + @Test + @UiThreadTest + public void getAvailablePhysicalSubscription_withTwoPhysicalSims_returnTwo() { + final SubscriptionInfo info1 = mock(SubscriptionInfo.class); + when(info1.isEmbedded()).thenReturn(false); + final SubscriptionInfo info2 = mock(SubscriptionInfo.class); + when(info2.isEmbedded()).thenReturn(false); + when(mSubscriptionManager.getAvailableSubscriptionInfoList()).thenReturn( + Arrays.asList(info1, info2)); + displayPreferenceWithLifecycle(); + + assertThat(mController.getAvailablePhysicalSubscription().size()).isEqualTo(2); + } + } diff --git a/tests/unit/src/com/android/settings/network/NetworkProviderSimsCategoryControllerTest.java b/tests/unit/src/com/android/settings/network/NetworkProviderSimsCategoryControllerTest.java index cfa376bd183..c8d750ce437 100644 --- a/tests/unit/src/com/android/settings/network/NetworkProviderSimsCategoryControllerTest.java +++ b/tests/unit/src/com/android/settings/network/NetworkProviderSimsCategoryControllerTest.java @@ -17,6 +17,7 @@ package com.android.settings.network; import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE; + import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; @@ -25,7 +26,10 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.os.Looper; +import android.telephony.SubscriptionInfo; +import android.telephony.SubscriptionManager; +import com.android.settings.testutils.ResourcesUtils; import com.android.settingslib.core.lifecycle.Lifecycle; import androidx.preference.PreferenceCategory; @@ -40,37 +44,35 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.util.ArrayList; +import java.util.Arrays; + @RunWith(AndroidJUnit4.class) public class NetworkProviderSimsCategoryControllerTest { private static final String KEY_PREFERENCE_CATEGORY_SIM = "provider_model_sim_category"; + private static final String SUB_1 = "SUB_1"; + private static final String SUB_2 = "SUB_2"; + private static final int SUB_ID_1 = 1; + private static final int SUB_ID_2 = 2; - @Mock - private NetworkProviderSimListController mNetworkProviderSimListController; - @Mock - private PreferenceCategory mPreferenceCategory; @Mock private Lifecycle mLifecycle; + @Mock + private SubscriptionInfo mSubscriptionInfo1; + @Mock + private SubscriptionInfo mSubscriptionInfo2; private Context mContext; private NetworkProviderSimsCategoryController mCategoryController; - private PreferenceManager mPreferenceManager; private PreferenceScreen mPreferenceScreen; + private PreferenceCategory mPreferenceCategory; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); - mContext = spy(ApplicationProvider.getApplicationContext()); - mCategoryController = new NetworkProviderSimsCategoryController( - mContext, KEY_PREFERENCE_CATEGORY_SIM) { - @Override - protected NetworkProviderSimListController createSimListController( - Lifecycle lifecycle) { - return mNetworkProviderSimListController; - } - }; if (Looper.myLooper() == null) { Looper.prepare(); @@ -78,14 +80,17 @@ public class NetworkProviderSimsCategoryControllerTest { mPreferenceManager = new PreferenceManager(mContext); mPreferenceScreen = mPreferenceManager.createPreferenceScreen(mContext); - when(mPreferenceCategory.getKey()).thenReturn(KEY_PREFERENCE_CATEGORY_SIM); - when(mPreferenceCategory.getPreferenceCount()).thenReturn(1); + mPreferenceCategory = new PreferenceCategory(mContext); + mPreferenceCategory.setKey(KEY_PREFERENCE_CATEGORY_SIM); mPreferenceScreen.addPreference(mPreferenceCategory); + + mCategoryController = new NetworkProviderSimsCategoryController( + mContext, KEY_PREFERENCE_CATEGORY_SIM, mLifecycle); } @Test public void getAvailabilityStatus_returnUnavailable() { - mNetworkProviderSimListController = null; + SubscriptionUtil.setAvailableSubscriptionsForTesting(new ArrayList<>()); assertThat(mCategoryController.getAvailabilityStatus()).isEqualTo( CONDITIONALLY_UNAVAILABLE); @@ -93,10 +98,46 @@ public class NetworkProviderSimsCategoryControllerTest { @Test public void displayPreference_isVisible() { - when(mNetworkProviderSimListController.isAvailable()).thenReturn(true); - mCategoryController.init(mLifecycle); + setUpSubscriptionInfoForPhysicalSim(SUB_ID_1, SUB_1, mSubscriptionInfo1); + SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(mSubscriptionInfo1)); mCategoryController.displayPreference(mPreferenceScreen); assertEquals(mPreferenceCategory.isVisible(), true); } + + @Test + public void updateState_setTitle_withTwoPhysicalSims_returnSims() { + setUpSubscriptionInfoForPhysicalSim(SUB_ID_1, SUB_1, mSubscriptionInfo1); + setUpSubscriptionInfoForPhysicalSim(SUB_ID_2, SUB_2, mSubscriptionInfo2); + SubscriptionUtil.setAvailableSubscriptionsForTesting( + Arrays.asList(mSubscriptionInfo1, mSubscriptionInfo2)); + + mCategoryController.displayPreference(mPreferenceScreen); + mCategoryController.updateState(mPreferenceCategory); + + assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(2); + assertThat(mPreferenceCategory.getTitle()).isEqualTo( + ResourcesUtils.getResourcesString(mContext, "provider_network_settings_title")); + } + + @Test + public void updateState_setTitle_withOnePhysicalSim_returnSim() { + setUpSubscriptionInfoForPhysicalSim(SUB_ID_1, SUB_1, mSubscriptionInfo1); + SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(mSubscriptionInfo1)); + + mCategoryController.displayPreference(mPreferenceScreen); + mCategoryController.updateState(mPreferenceCategory); + + assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(1); + assertThat(mPreferenceCategory.getTitle()).isEqualTo( + ResourcesUtils.getResourcesString(mContext, "sim_category_title")); + } + + private void setUpSubscriptionInfoForPhysicalSim(int subId, String displayName, + SubscriptionInfo subscriptionInfo) { + when(subscriptionInfo.isEmbedded()).thenReturn(false); + when(subscriptionInfo.getSubscriptionId()).thenReturn(subId); + when(subscriptionInfo.getDisplayName()).thenReturn(displayName); + } + } diff --git a/tests/unit/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java index cb78d19714c..7cffb76f983 100644 --- a/tests/unit/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java +++ b/tests/unit/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java @@ -665,6 +665,7 @@ public class SubscriptionsPreferenceControllerTest { doReturn(true).when(sInjector).isProviderModelEnabled(mContext); doReturn(sub.get(0)).when(mSubscriptionManager).getDefaultDataSubscriptionInfo(); Drawable icon = mock(Drawable.class); + when(mTelephonyManager.isDataEnabled()).thenReturn(true); doReturn(icon).when(sInjector).getIcon(any(), anyInt(), anyInt(), eq(false)); setupGetIconConditions(sub.get(0).getSubscriptionId(), true, true, true, ServiceState.STATE_IN_SERVICE); @@ -683,6 +684,7 @@ public class SubscriptionsPreferenceControllerTest { doReturn(true).when(sInjector).isProviderModelEnabled(mContext); doReturn(subs.get(0)).when(mSubscriptionManager).getDefaultDataSubscriptionInfo(); Drawable icon = mock(Drawable.class); + when(mTelephonyManager.isDataEnabled()).thenReturn(true); doReturn(icon).when(sInjector).getIcon(any(), anyInt(), anyInt(), eq(false)); setupGetIconConditions(subId, false, true, true, ServiceState.STATE_IN_SERVICE); @@ -701,7 +703,8 @@ public class SubscriptionsPreferenceControllerTest { doReturn(true).when(sInjector).isProviderModelEnabled(mContext); doReturn(subs.get(0)).when(mSubscriptionManager).getDefaultDataSubscriptionInfo(); Drawable icon = mock(Drawable.class); - doReturn(icon).when(sInjector).getIcon(any(), anyInt(), anyInt(), eq(false)); + when(mTelephonyManager.isDataEnabled()).thenReturn(false); + doReturn(icon).when(sInjector).getIcon(any(), anyInt(), anyInt(), eq(true)); setupGetIconConditions(subId, false, false, false, ServiceState.STATE_IN_SERVICE); diff --git a/tests/unit/src/com/android/settings/network/telephony/NrAdvancedCallingPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/NrAdvancedCallingPreferenceControllerTest.java new file mode 100644 index 00000000000..9eb67df96ca --- /dev/null +++ b/tests/unit/src/com/android/settings/network/telephony/NrAdvancedCallingPreferenceControllerTest.java @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2021 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.network.telephony; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.os.PersistableBundle; +import android.telephony.CarrierConfigManager; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; + +import androidx.preference.SwitchPreference; +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import com.android.settings.core.BasePreferenceController; +import com.android.settingslib.RestrictedSwitchPreference; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@RunWith(AndroidJUnit4.class) +public class NrAdvancedCallingPreferenceControllerTest { + private static final int SUB_ID = 2; + + @Mock + private TelephonyManager mTelephonyManager; + @Mock + private TelephonyManager mInvalidTelephonyManager; + @Mock + private SubscriptionManager mSubscriptionManager; + @Mock + private CarrierConfigManager mCarrierConfigManager; + + private NrAdvancedCallingPreferenceController mController; + private SwitchPreference mPreference; + private PersistableBundle mCarrierConfig; + private Context mContext; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mContext = spy(ApplicationProvider.getApplicationContext()); + when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager); + when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager); + when(mContext.getSystemService(CarrierConfigManager.class)) + .thenReturn(mCarrierConfigManager); + + doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID); + doReturn(mInvalidTelephonyManager).when(mTelephonyManager).createForSubscriptionId( + SubscriptionManager.INVALID_SUBSCRIPTION_ID); + doReturn(TelephonyManager.NETWORK_TYPE_BITMASK_NR).when( + mTelephonyManager).getSupportedRadioAccessFamily(); + doReturn(false).when(mTelephonyManager).isVoNrEnabled(); + doReturn(TelephonyManager.ENABLE_VONR_REQUEST_NOT_SUPPORTED).when( + mTelephonyManager).setVoNrEnabled(anyBoolean()); + mCarrierConfig = new PersistableBundle(); + doReturn(mCarrierConfig).when(mCarrierConfigManager).getConfigForSubId(SUB_ID); + mCarrierConfig.putBoolean(CarrierConfigManager.KEY_VONR_SETTING_VISIBILITY_BOOL, false); + mCarrierConfig.putIntArray(CarrierConfigManager.KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY, + new int[]{1, 2}); + + mPreference = new RestrictedSwitchPreference(mContext); + mController = spy(new NrAdvancedCallingPreferenceController(mContext, "VoNr")); + mController.init(SUB_ID); + doReturn(true).when(mController).isCallStateIdle(); + mPreference.setKey(mController.getPreferenceKey()); + } + + @Test + public void getAvailabilityStatus_vonrDisabled_returnUnavailable() { + mCarrierConfig.putBoolean(CarrierConfigManager.KEY_VONR_SETTING_VISIBILITY_BOOL, false); + + mController.init(SUB_ID); + + assertThat(mController.getAvailabilityStatus()).isEqualTo( + BasePreferenceController.CONDITIONALLY_UNAVAILABLE); + } + + @Test + public void getAvailabilityStatus_vonrEnabled_returnAvailable() { + mCarrierConfig.putBoolean(CarrierConfigManager.KEY_VONR_SETTING_VISIBILITY_BOOL, true); + + mController.init(SUB_ID); + + assertThat(mController.getAvailabilityStatus()).isEqualTo( + BasePreferenceController.AVAILABLE); + } + + @Test + public void getAvailabilityStatus_deviceNoNr_returnUnavailable() { + doReturn(TelephonyManager.NETWORK_TYPE_BITMASK_LTE).when( + mTelephonyManager).getSupportedRadioAccessFamily(); + + mController.init(SUB_ID); + + assertThat(mController.getAvailabilityStatus()).isEqualTo( + BasePreferenceController.CONDITIONALLY_UNAVAILABLE); + } + + @Test + public void getAvailabilityStatus_carrierNoNr_returnUnavailable() { + mCarrierConfig.putIntArray(CarrierConfigManager.KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY, + new int[0]); + + mController.init(SUB_ID); + + assertThat(mController.getAvailabilityStatus()).isEqualTo( + BasePreferenceController.CONDITIONALLY_UNAVAILABLE); + } + + @Test + public void getAvailabilityStatus_carrierConfigNrIsNull_returnUnavailable() { + mCarrierConfig.putIntArray(CarrierConfigManager.KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY, + null); + + mController.init(SUB_ID); + + assertThat(mController.getAvailabilityStatus()).isEqualTo( + BasePreferenceController.CONDITIONALLY_UNAVAILABLE); + } + + @Test + public void updateState_callStateNotIdle_prefDisabled() { + doReturn(false).when(mController).isCallStateIdle(); + mPreference.setEnabled(true); + + mController.updateState(mPreference); + + assertThat(mPreference.isEnabled()).isFalse(); + } + + @Test + public void updateState_configOn_prefChecked() { + doReturn(TelephonyManager.ENABLE_VONR_SUCCESS).when( + mTelephonyManager).setVoNrEnabled(anyBoolean()); + doReturn(true).when(mTelephonyManager).isVoNrEnabled(); + mPreference.setChecked(false); + + mController.updateState(mPreference); + + assertThat(mPreference.isChecked()).isTrue(); + } +} diff --git a/tests/unit/src/com/android/settings/panel/InternetConnectivityPanelTest.java b/tests/unit/src/com/android/settings/panel/InternetConnectivityPanelTest.java deleted file mode 100644 index 30a272950f5..00000000000 --- a/tests/unit/src/com/android/settings/panel/InternetConnectivityPanelTest.java +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Copyright (C) 2021 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.panel; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.Mockito.clearInvocations; -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; - -import android.content.Context; -import android.net.Uri; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiManager; -import android.os.Handler; - -import androidx.test.core.app.ApplicationProvider; -import androidx.test.ext.junit.runners.AndroidJUnit4; - -import com.android.settings.network.AirplaneModePreferenceController; -import com.android.settings.network.InternetUpdater; -import com.android.settings.network.ProviderModelSliceHelper; -import com.android.settings.slices.CustomSliceRegistry; -import com.android.settings.testutils.ResourcesUtils; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; - -import java.util.ArrayList; -import java.util.List; - -@RunWith(AndroidJUnit4.class) -public class InternetConnectivityPanelTest { - - public static final String TITLE_INTERNET = ResourcesUtils.getResourcesString( - ApplicationProvider.getApplicationContext(), "provider_internet_settings"); - public static final String TITLE_APM = ResourcesUtils.getResourcesString( - ApplicationProvider.getApplicationContext(), "airplane_mode"); - public static final String SUBTITLE_TEXT_WIFI_IS_OFF = - ResourcesUtils.getResourcesString(ApplicationProvider.getApplicationContext(), - "wifi_is_off"); - public static final String SUBTITLE_TEXT_TAP_A_NETWORK_TO_CONNECT = - ResourcesUtils.getResourcesString(ApplicationProvider.getApplicationContext(), - "tap_a_network_to_connect"); - public static final String SUBTITLE_NON_CARRIER_NETWORK_UNAVAILABLE = - ResourcesUtils.getResourcesString(ApplicationProvider.getApplicationContext(), - "non_carrier_network_unavailable"); - public static final String SUBTITLE_ALL_NETWORK_UNAVAILABLE = - ResourcesUtils.getResourcesString(ApplicationProvider.getApplicationContext(), - "all_network_unavailable"); - public static final String BUTTON_TURN_ON_WIFI = ResourcesUtils.getResourcesString( - ApplicationProvider.getApplicationContext(), "turn_on_wifi"); - public static final String BUTTON_TURN_OFF_WIFI = ResourcesUtils.getResourcesString( - ApplicationProvider.getApplicationContext(), "turn_off_wifi"); - - @Rule - public final MockitoRule mMocks = MockitoJUnit.rule(); - @Mock - Handler mMainThreadHandler; - @Mock - PanelContentCallback mPanelContentCallback; - @Mock - InternetUpdater mInternetUpdater; - @Mock - private WifiManager mWifiManager; - @Mock - private ProviderModelSliceHelper mProviderModelSliceHelper; - - private Context mContext; - private FakeHandlerInjector mFakeHandlerInjector; - private InternetConnectivityPanel mPanel; - - private class FakeHandlerInjector extends InternetConnectivityPanel.HandlerInjector { - - private Runnable mRunnable; - - FakeHandlerInjector(Context context) { - super(context); - } - - @Override - public void postDelay(Runnable runnable) { - mRunnable = runnable; - } - - public Runnable getRunnable() { - return mRunnable; - } - } - - @Before - public void setUp() { - mContext = spy(ApplicationProvider.getApplicationContext()); - mFakeHandlerInjector = new FakeHandlerInjector(mContext); - when(mContext.getApplicationContext()).thenReturn(mContext); - when(mContext.getMainThreadHandler()).thenReturn(mMainThreadHandler); - when(mContext.getSystemService(WifiManager.class)).thenReturn(mWifiManager); - - mPanel = InternetConnectivityPanel.create(mContext); - mPanel.registerCallback(mPanelContentCallback); - mPanel.mIsProviderModelEnabled = true; - mPanel.mInternetUpdater = mInternetUpdater; - mPanel.mProviderModelSliceHelper = mProviderModelSliceHelper; - mPanel.mHandlerInjector = mFakeHandlerInjector; - } - - @Test - public void getTitle_apmOff_shouldBeInternet() { - doReturn(false).when(mInternetUpdater).isAirplaneModeOn(); - - assertThat(mPanel.getTitle()).isEqualTo(TITLE_INTERNET); - } - - @Test - public void getTitle_apmOn_shouldBeApm() { - doReturn(true).when(mInternetUpdater).isAirplaneModeOn(); - - assertThat(mPanel.getTitle()).isEqualTo(TITLE_APM); - } - - @Test - public void getSubTitle_apmOnWifiOff_shouldBeNull() { - doReturn(true).when(mInternetUpdater).isAirplaneModeOn(); - doReturn(false).when(mInternetUpdater).isWifiEnabled(); - - assertThat(mPanel.getSubTitle()).isNull(); - } - - @Test - public void getSubTitle_apmOnWifiOn_shouldBeNull() { - doReturn(true).when(mInternetUpdater).isAirplaneModeOn(); - doReturn(true).when(mInternetUpdater).isWifiEnabled(); - - assertThat(mPanel.getSubTitle()).isNull(); - } - - @Test - public void getSubTitle_apmOffWifiOff_wifiIsOn() { - doReturn(false).when(mInternetUpdater).isAirplaneModeOn(); - doReturn(false).when(mInternetUpdater).isWifiEnabled(); - - mPanel.updatePanelTitle(); - - assertThat(mPanel.getSubTitle()).isEqualTo(SUBTITLE_TEXT_WIFI_IS_OFF); - } - - @Test - public void getSubTitle_apmOffWifiOnNoWifiListHasCarrierData_NonCarrierNetworkUnavailable() { - List wifiList = new ArrayList(); - mockCondition(false, true, true, true, true, true, wifiList); - - mPanel.updatePanelTitle(); - - assertThat(mPanel.getSubTitle()).isEqualTo(SUBTITLE_NON_CARRIER_NETWORK_UNAVAILABLE); - } - - @Test - public void getSubTitle_apmOffWifiOnNoWifiListNoCarrierItem_AllNetworkUnavailable() { - List wifiList = new ArrayList(); - mockCondition(false, false, false, false, false, true, wifiList); - - mPanel.updatePanelTitle(); - - assertThat(mPanel.getSubTitle()).isEqualTo(SUBTITLE_ALL_NETWORK_UNAVAILABLE); - } - - @Test - public void getSubTitle_apmOffWifiOnNoWifiListNoDataSimActive_AllNetworkUnavailable() { - List wifiList = new ArrayList(); - mockCondition(false, true, false, true, true, true, wifiList); - - mPanel.updatePanelTitle(); - - assertThat(mPanel.getSubTitle()).isEqualTo(SUBTITLE_ALL_NETWORK_UNAVAILABLE); - } - - @Test - public void getSubTitle_apmOffWifiOnNoWifiListNoService_AllNetworkUnavailable() { - List wifiList = new ArrayList(); - mockCondition(false, true, false, true, false, true, wifiList); - - mPanel.updatePanelTitle(); - - assertThat(mPanel.getSubTitle()).isEqualTo(SUBTITLE_ALL_NETWORK_UNAVAILABLE); - } - - @Test - public void getSubTitle_apmOffWifiOnTwoWifiItemsNoCarrierData_tapANetworkToConnect() { - List wifiList = new ArrayList(); - wifiList.add(new ScanResult()); - wifiList.add(new ScanResult()); - mockCondition(false, true, false, true, true, true, wifiList); - - mPanel.updatePanelTitle(); - - assertThat(mPanel.getSubTitle()).isEqualTo(SUBTITLE_TEXT_TAP_A_NETWORK_TO_CONNECT); - } - - @Test - public void getSlices_providerModelDisabled_containsNecessarySlices() { - mPanel.mIsProviderModelEnabled = false; - List uris = mPanel.getSlices(); - - assertThat(uris).containsExactly( - AirplaneModePreferenceController.SLICE_URI, - CustomSliceRegistry.MOBILE_DATA_SLICE_URI, - CustomSliceRegistry.WIFI_SLICE_URI); - } - - @Test - public void getSlices_providerModelEnabled_containsNecessarySlices() { - List uris = mPanel.getSlices(); - - assertThat(uris).containsExactly(CustomSliceRegistry.PROVIDER_MODEL_SLICE_URI); - } - - @Test - public void getSeeMoreIntent_providerModelDisabled_shouldNotNull() { - mPanel.mIsProviderModelEnabled = false; - - assertThat(mPanel.getSeeMoreIntent()).isNotNull(); - } - - @Test - public void getSeeMoreIntent_providerModelEnabled_shouldBeNull() { - mPanel.mIsProviderModelEnabled = true; - - assertThat(mPanel.getSeeMoreIntent()).isNull(); - } - - @Test - public void updatePanelTitle_onHeaderChanged() { - clearInvocations(mPanelContentCallback); - - mPanel.updatePanelTitle(); - - verify(mPanelContentCallback).onHeaderChanged(); - } - - @Test - public void updateProgressBar_wifiDisabled_hideProgress() { - mPanel.mIsProgressBarVisible = true; - doReturn(false).when(mInternetUpdater).isWifiEnabled(); - clearInvocations(mPanelContentCallback); - - mPanel.updateProgressBar(); - - assertThat(mPanel.isProgressBarVisible()).isFalse(); - verify(mPanelContentCallback).onProgressBarVisibleChanged(); - } - - @Test - public void updateProgressBar_noWifiScanResults_showProgressForever() { - mPanel.mIsScanningSubTitleShownOnce = false; - mPanel.mIsProgressBarVisible = false; - doReturn(true).when(mInternetUpdater).isWifiEnabled(); - List noWifiScanResults = new ArrayList<>(); - doReturn(noWifiScanResults).when(mWifiManager).getScanResults(); - clearInvocations(mPanelContentCallback); - - mPanel.updateProgressBar(); - - assertThat(mPanel.mIsProgressBarVisible).isTrue(); - verify(mPanelContentCallback).onProgressBarVisibleChanged(); - verify(mPanelContentCallback).onHeaderChanged(); - - assertThat(mFakeHandlerInjector.getRunnable()) - .isEqualTo(mPanel.mHideScanningSubTitleRunnable); - mFakeHandlerInjector.getRunnable().run(); - assertThat(mPanel.mIsScanningSubTitleShownOnce).isTrue(); - assertThat(mPanel.mIsProgressBarVisible).isTrue(); - } - - @Test - public void updateProgressBar_hasWifiScanResults_showProgressDelayedHide() { - mPanel.mIsProgressBarVisible = false; - doReturn(true).when(mInternetUpdater).isWifiEnabled(); - List hasWifiScanResults = mock(ArrayList.class); - doReturn(1).when(hasWifiScanResults).size(); - doReturn(hasWifiScanResults).when(mWifiManager).getScanResults(); - clearInvocations(mPanelContentCallback); - - mPanel.updateProgressBar(); - - assertThat(mPanel.isProgressBarVisible()).isTrue(); - verify(mPanelContentCallback).onProgressBarVisibleChanged(); - - assertThat(mFakeHandlerInjector.getRunnable()) - .isEqualTo(mPanel.mHideProgressBarRunnable); - mFakeHandlerInjector.getRunnable().run(); - assertThat(mPanel.mIsProgressBarVisible).isFalse(); - } - - @Test - public void setProgressBarVisible_onProgressBarVisibleChanged() { - mPanel.mIsProgressBarVisible = false; - doReturn(true).when(mInternetUpdater).isWifiEnabled(); - clearInvocations(mPanelContentCallback); - - mPanel.setProgressBarVisible(true); - - assertThat(mPanel.mIsProgressBarVisible).isTrue(); - verify(mPanelContentCallback).onProgressBarVisibleChanged(); - verify(mPanelContentCallback).onHeaderChanged(); - } - - private void mockCondition(boolean airplaneMode, boolean hasCarrier, - boolean isDataSimActive, boolean isMobileDataEnabled, boolean isServiceInService, - boolean isWifiEnabled, List wifiItems) { - doReturn(airplaneMode).when(mInternetUpdater).isAirplaneModeOn(); - when(mProviderModelSliceHelper.hasCarrier()).thenReturn(hasCarrier); - when(mProviderModelSliceHelper.isDataSimActive()).thenReturn(isDataSimActive); - when(mProviderModelSliceHelper.isMobileDataEnabled()).thenReturn(isMobileDataEnabled); - when(mProviderModelSliceHelper.isDataStateInService()).thenReturn(isServiceInService); - when(mProviderModelSliceHelper.isVoiceStateInService()).thenReturn(isServiceInService); - doReturn(isWifiEnabled).when(mInternetUpdater).isWifiEnabled(); - doReturn(wifiItems).when(mWifiManager).getScanResults(); - } -} diff --git a/tests/unit/src/com/android/settings/panel/PanelFeatureProviderImplTest.java b/tests/unit/src/com/android/settings/panel/PanelFeatureProviderImplTest.java index 3b61a734af1..a02c054237f 100644 --- a/tests/unit/src/com/android/settings/panel/PanelFeatureProviderImplTest.java +++ b/tests/unit/src/com/android/settings/panel/PanelFeatureProviderImplTest.java @@ -20,7 +20,12 @@ import static com.android.settings.panel.SettingsPanelActivity.KEY_PANEL_TYPE_AR import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; + import android.content.Context; +import android.content.Intent; import android.os.Bundle; import android.provider.Settings; @@ -36,25 +41,28 @@ public class PanelFeatureProviderImplTest { private static final String TEST_PACKAGENAME = "com.test.packagename"; + private static final String SYSTEMUI_PACKAGE_NAME = "com.android.systemui"; private Context mContext; private PanelFeatureProviderImpl mProvider; private Bundle mBundle; @Before public void setUp() { - mContext = ApplicationProvider.getApplicationContext(); + mContext = spy(ApplicationProvider.getApplicationContext()); mProvider = new PanelFeatureProviderImpl(); mBundle = new Bundle(); mBundle.putString(KEY_MEDIA_PACKAGE_NAME, TEST_PACKAGENAME); } @Test - public void getPanel_internetConnectivityKey_returnsCorrectPanel() { + public void getPanel_internetConnectivityKey_sendsCorrectBroadcast() { mBundle.putString(KEY_PANEL_TYPE_ARGUMENT, Settings.Panel.ACTION_INTERNET_CONNECTIVITY); + mProvider.getPanel(mContext, mBundle); + Intent intent = new Intent(Settings.Panel.ACTION_INTERNET_CONNECTIVITY); + intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND) + .setPackage(SYSTEMUI_PACKAGE_NAME); - final PanelContent panel = mProvider.getPanel(mContext, mBundle); - - assertThat(panel).isInstanceOf(InternetConnectivityPanel.class); + verify(mContext, never()).sendBroadcast(intent); } @Test