Merge "Remove restricted icon in SettingsMainSwitchBar" into udc-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index dd09997..6fe6832 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -4575,7 +4575,7 @@
android:launchMode="singleInstance"
android:excludeFromRecents="true"
android:exported="true"
- android:configChanges="orientation|keyboardHidden|screenSize">
+ android:configChanges="orientation|keyboard|keyboardHidden|screenSize|smallestScreenSize|screenLayout">
<intent-filter>
<action android:name="android.settings.WIFI_ADD_NETWORKS" />
<category android:name="android.intent.category.DEFAULT" />
@@ -4875,7 +4875,7 @@
android:excludeFromRecents="true"
android:resizeableActivity="false"
android:theme="@android:style/Theme.NoDisplay"
- android:label="@string/note_task_button_label"
+ android:label="@string/note_task_shortcut_label"
android:icon="@drawable/ic_note_task_shortcut_widget">
<intent-filter>
diff --git a/res/drawable/ic_note_task_shortcut_widget.xml b/res/drawable/ic_note_task_shortcut_widget.xml
index e37c22a..ce1f51a 100644
--- a/res/drawable/ic_note_task_shortcut_widget.xml
+++ b/res/drawable/ic_note_task_shortcut_widget.xml
@@ -14,18 +14,20 @@
~ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportHeight="24"
- android:viewportWidth="24">
- <path
- android:fillAlpha="1"
- android:fillColor="#636C6F"
- android:fillType="nonZero"
- android:pathData="M17.6258,4.96L19.0358,6.37L7.4058,18.01L5.9958,16.6L17.6258,4.96ZM16.1358,3.62L4.1258,15.63L3.0158,19.83C2.9058,20.45 3.3858,21 3.9958,21C4.0558,21 4.1058,21 4.1658,20.99L8.3658,19.88L20.3758,7.86C20.7758,7.46 20.9958,6.93 20.9958,6.37C20.9958,5.81 20.7758,5.28 20.3758,4.88L19.1058,3.61C18.7158,3.22 18.1858,3 17.6258,3C17.0658,3 16.5358,3.22 16.1358,3.62Z" />
- <path
- android:fillAlpha="1"
- android:fillColor="#636C6F"
- android:fillType="nonZero"
- android:pathData="M20.1936,15.3369C20.3748,16.3837 19.9151,17.5414 18.8846,18.7597C19.1546,18.872 19.4576,18.9452 19.7724,18.9867C20.0839,19.0278 20.3683,19.0325 20.5749,19.0266C20.6772,19.0236 20.7578,19.0181 20.8101,19.0138C20.8362,19.0116 20.855,19.0097 20.8657,19.0085L20.8754,19.0074L20.875,19.0075C21.4217,18.9385 21.9214,19.325 21.9918,19.8718C22.0624,20.4195 21.6756,20.9208 21.1279,20.9914L21,19.9996C21.1279,20.9914 21.1265,20.9916 21.1265,20.9916L21.1249,20.9918L21.1211,20.9923L21.1107,20.9935L21.0795,20.997C21.0542,20.9998 21.0199,21.0032 20.9775,21.0067C20.8929,21.0138 20.7753,21.0216 20.6323,21.0257C20.3481,21.0339 19.9533,21.0279 19.5109,20.9695C18.873,20.8854 18.0393,20.6793 17.3106,20.1662C16.9605,20.3559 16.5876,20.4952 16.2299,20.6003C15.5742,20.7927 14.8754,20.8968 14.2534,20.9534C13.6801,21.0055 13.4553,21.0037 13.1015,21.0008C13.0689,21.0005 13.0352,21.0002 13,21H12.8594C12.8214,21.0002 12.785,21.0006 12.7504,21.0009C12.6524,21.0019 12.5683,21.0027 12.5,21H12.0562C12.0277,21.0003 12.0054,21.0006 11.9926,21.001L11.9751,21H9L11,19H11.9795C11.9929,18.9997 12.0064,18.9997 12.0199,19H12.4117C12.4534,18.9996 12.4864,18.9995 12.5,19H12.9675C12.977,18.9999 12.9878,18.9999 13,19C13.0446,19.0003 13.0859,19.0007 13.1249,19.0011C13.4259,19.0038 13.591,19.0054 14.0723,18.9616C14.6201,18.9118 15.1795,18.8242 15.6665,18.6813C15.753,18.6559 15.8346,18.6295 15.9114,18.6022C15.0315,17.2981 14.7125,16.1044 15.015,15.0829C15.4095,13.7511 16.6784,13.2418 17.7026,13.2864C18.7262,13.3309 19.954,13.9529 20.1936,15.3369ZM16.9327,15.6508C16.873,15.8523 16.8651,16.3878 17.4697,17.334C18.2007,16.4284 18.2585,15.8839 18.2229,15.6781C18.1939,15.5108 18.0297,15.3025 17.6157,15.2845C17.2025,15.2665 16.9885,15.4626 16.9327,15.6508Z" />
-</vector>
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48"
+ android:viewportHeight="48">
+
+ <group>
+ <path
+ android:fillColor="#0B57D0"
+ android:pathData="M48 24C48 10.7452 37.2548 0 24 0C10.7452 0 0 10.7452 0 24C0 37.2548 10.7452 48 24 48C37.2548 48 48 37.2548 48 24Z" />
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M37.692 16.8L36 15.108C35.556 14.652 34.944 14.4 34.308 14.4C33.672 14.4 33.06 14.652 32.616 15.108L23.268 24.456L20.508 27.216L19.248 32.28C19.212 32.352 19.2 32.448 19.2 32.532C19.2 33.12 19.68 33.6 20.268 33.6C20.352 33.6 20.448 33.588 20.532 33.564L25.596 32.304L28.356 29.544L37.704 20.196C38.148 19.74 38.4 19.128 38.4 18.492C38.4 17.856 38.148 17.244 37.692 16.8ZM26.652 27.852L25.452 29.052L23.76 27.36L24.96 26.16L34.308 16.8L36 18.492L26.652 27.852Z" />
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M17.825 33.6C12.257 33.6 10.2 31.9581 10.2 28.7351C10.2 25.8284 12.727 24.4472 16.656 23.8703C17.95 23.6802 18.6125 23.137 18.6125 22.5654C18.6125 20.9818 15.415 21.0788 14.4 21.0324V18.6C14.4 18.6 17.95 18.6 19.65 19.8923C20.5181 20.5521 21 21.4125 21 22.7149C21 24.5027 19.7375 25.9099 16.656 26.1633C14.6206 26.3307 12.6 26.9351 12.6 28.7351C12.6 30.3527 14.616 31.1676 18.6 31.1676L17.825 33.6Z" />
+ </group>
+</vector>
\ No newline at end of file
diff --git a/res/layout/notification_channel_panel.xml b/res/layout/notification_channel_panel.xml
index 14e10cc..7e944ac 100644
--- a/res/layout/notification_channel_panel.xml
+++ b/res/layout/notification_channel_panel.xml
@@ -19,6 +19,7 @@
android:layout_height="@dimen/notif_channel_panel_max_height"
android:maxHeight="@dimen/notif_channel_panel_max_height"
android:background="@drawable/settings_panel_background"
+ android:fitsSystemWindows="true"
android:orientation="vertical"
android:layout_width="match_parent">
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 00a05af..b38552f 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -7097,8 +7097,8 @@
<!-- List of synonyms for the font size, used to match in settings search [CHAR LIMIT=NONE] -->
<string name="keywords_font_size">text size, large print, large font, large text, low vision, make text bigger, font enlarger, font enlargement</string>
- <!-- List of synonyms for the always show time and info [CHAR LIMIT=NONE] -->
- <string name="keywords_always_show_time_info">always on display, AOD</string>
+ <!-- List of synonyms for the always show time and info, used to match in settings search [CHAR LIMIT=NONE] -->
+ <string name="keywords_always_show_time_info">always on ambient display, AOD</string>
<!-- List of synonyms for the nfc tag apps control [CHAR LIMIT=NONE] -->
<string name="keywords_change_nfc_tag_apps_state">nfc, tag, reader</string>
@@ -12060,5 +12060,5 @@
<string name="dock_multi_instances_not_supported_text">"This app can only be opened in 1 window"</string>
<!-- [CHAR LIMIT=30] Label used to open Note Task -->
- <string name="note_task_button_label">Notetaking</string>
+ <string name="note_task_shortcut_label">Note shortcut</string>
</resources>
diff --git a/res/xml/security_settings_fingerprint.xml b/res/xml/security_settings_fingerprint.xml
index a4ce545..0156ef9 100644
--- a/res/xml/security_settings_fingerprint.xml
+++ b/res/xml/security_settings_fingerprint.xml
@@ -20,9 +20,20 @@
android:title="@string/security_settings_fingerprint_preference_title">
<PreferenceCategory
+ android:key="security_settings_fingerprints_enrolled"
+ settings:controller="com.android.settings.biometrics.fingerprint.FingerprintsEnrolledCategoryPreferenceController">
+ </PreferenceCategory>
+
+ <androidx.preference.Preference
+ android:key="key_fingerprint_add"
+ android:title="@string/fingerprint_add_title"
+ android:icon="@drawable/ic_add_24dp"/>
+
+ <PreferenceCategory
android:key="security_settings_fingerprint_unlock_category"
android:title="@string/security_settings_fingerprint_settings_preferences_category"
- settings:controller="com.android.settings.biometrics.fingerprint.FingerprintUnlockCategoryPreferenceController">
+ settings:controller="com.android.settings.biometrics.fingerprint.FingerprintUnlockCategoryController"
+ settings:isPreferenceVisible="false">
<com.android.settingslib.RestrictedSwitchPreference
android:key="security_settings_require_screen_on_to_auth"
@@ -32,4 +43,8 @@
settings:controller="com.android.settings.biometrics.fingerprint.FingerprintSettingsRequireScreenOnToAuthPreferenceController" />
</PreferenceCategory>
+ <PreferenceCategory
+ android:key="security_settings_fingerprint_footer">
+ </PreferenceCategory>
+
</PreferenceScreen>
diff --git a/src/com/android/settings/accessibility/PaletteListPreference.java b/src/com/android/settings/accessibility/PaletteListPreference.java
index 4e10b93..eec8b5a 100644
--- a/src/com/android/settings/accessibility/PaletteListPreference.java
+++ b/src/com/android/settings/accessibility/PaletteListPreference.java
@@ -34,6 +34,7 @@
import androidx.annotation.ColorInt;
import androidx.annotation.IntDef;
+import androidx.core.text.TextUtilsCompat;
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
@@ -49,6 +50,7 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
+import java.util.Locale;
import java.util.stream.Collectors;
/** Preference that easier preview by matching name to color. */
@@ -156,10 +158,11 @@
mGradientColors.set(Position.END, color);
final GradientDrawable gradientDrawable = new GradientDrawable();
+ final Locale locale = Locale.getDefault();
final Orientation orientation =
- rootView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL
- ? Orientation.RIGHT_LEFT
- : Orientation.LEFT_RIGHT;
+ TextUtilsCompat.getLayoutDirectionFromLocale(locale) == View.LAYOUT_DIRECTION_RTL
+ ? Orientation.RIGHT_LEFT
+ : Orientation.LEFT_RIGHT;
gradientDrawable.setOrientation(orientation);
gradientDrawable.setColors(Ints.toArray(mGradientColors), Floats.toArray(mGradientOffsets));
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java b/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
index 40a719a..a5e5f57 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
@@ -171,8 +171,12 @@
private static final String KEY_IS_ENROLLING = "is_enrolled";
private static final String KEY_REQUIRE_SCREEN_ON_TO_AUTH =
"security_settings_require_screen_on_to_auth";
+ private static final String KEY_FINGERPRINTS_ENROLLED_CATEGORY =
+ "security_settings_fingerprints_enrolled";
private static final String KEY_FINGERPRINT_UNLOCK_CATEGORY =
"security_settings_fingerprint_unlock_category";
+ private static final String KEY_FINGERPRINT_UNLOCK_FOOTER =
+ "security_settings_fingerprint_footer";
private static final int MSG_REFRESH_FINGERPRINT_TEMPLATES = 1000;
private static final int MSG_FINGER_AUTH_SUCCESS = 1001;
@@ -189,10 +193,15 @@
protected static final boolean DEBUG = false;
private List<AbstractPreferenceController> mControllers;
+ private FingerprintUnlockCategoryController
+ mFingerprintUnlockCategoryPreferenceController;
private FingerprintSettingsRequireScreenOnToAuthPreferenceController
mRequireScreenOnToAuthPreferenceController;
+ private Preference mAddFingerprintPreference;
private RestrictedSwitchPreference mRequireScreenOnToAuthPreference;
+ private PreferenceCategory mFingerprintsEnrolledCategory;
private PreferenceCategory mFingerprintUnlockCategory;
+ private PreferenceCategory mFingerprintUnlockFooter;
private FingerprintManager mFingerprintManager;
private FingerprintUpdater mFingerprintUpdater;
@@ -259,9 +268,6 @@
}
private void updateDialog() {
- if (isSfps()) {
- setRequireScreenOnToAuthVisibility();
- }
RenameDialog renameDialog = (RenameDialog) getFragmentManager().
findFragmentByTag(RenameDialog.class.getName());
if (renameDialog != null) {
@@ -277,7 +283,8 @@
case MSG_REFRESH_FINGERPRINT_TEMPLATES:
removeFingerprintPreference(msg.arg1);
updateAddPreference();
- retryFingerprint();
+ updateFingerprintUnlockCategoryVisibility();
+ updatePreferences();
break;
case MSG_FINGER_AUTH_SUCCESS:
highlightFingerprintItem(msg.arg1);
@@ -423,6 +430,9 @@
addFirstFingerprint(null);
}
}
+ final PreferenceScreen root = getPreferenceScreen();
+ root.removeAll();
+ addPreferencesFromResource(getPreferenceScreenResId());
updateFooterColumns(activity);
}
@@ -512,48 +522,33 @@
*/
private PreferenceScreen createPreferenceHierarchy() {
PreferenceScreen root = getPreferenceScreen();
- if (root != null) {
- root.removeAll();
- }
- final String fpPrefKey = addFingerprintItemPreferences(root);
- if (isSfps()) {
- scrollToPreference(fpPrefKey);
- }
- addPreferencesFromResource(getPreferenceScreenResId());
- mRequireScreenOnToAuthPreference = findPreference(KEY_REQUIRE_SCREEN_ON_TO_AUTH);
- mFingerprintUnlockCategory = findPreference(KEY_FINGERPRINT_UNLOCK_CATEGORY);
- for (AbstractPreferenceController controller : mControllers) {
- ((FingerprintSettingsPreferenceController) controller).setUserId(mUserId);
- }
- mRequireScreenOnToAuthPreference.setChecked(
- mRequireScreenOnToAuthPreferenceController.isChecked());
- mRequireScreenOnToAuthPreference.setOnPreferenceChangeListener(
- (preference, newValue) -> {
- boolean isChecked = ((SwitchPreference) preference).isChecked();
- mRequireScreenOnToAuthPreferenceController.setChecked(!isChecked);
- return true;
- });
- mFingerprintUnlockCategory.setVisible(false);
- if (isSfps()) {
- setRequireScreenOnToAuthVisibility();
- }
+ addFingerprintPreferences(root);
setPreferenceScreen(root);
return root;
}
- private void setRequireScreenOnToAuthVisibility() {
- int fingerprintsEnrolled = mFingerprintManager.getEnrolledFingerprints(mUserId).size();
- final boolean removalInProgress = mRemovalSidecar.inProgress();
- // Removing last remaining fingerprint
- if (fingerprintsEnrolled == 0 && removalInProgress) {
- mFingerprintUnlockCategory.setVisible(false);
- } else {
- mFingerprintUnlockCategory.setVisible(true);
+ private void addFingerprintPreferences(PreferenceGroup root) {
+ final String fpPrefKey = addFingerprintItemPreferences(root);
+ if (isSfps()) {
+ scrollToPreference(fpPrefKey);
+ addFingerprintUnlockCategory();
}
+ for (AbstractPreferenceController controller : mControllers) {
+ if (controller instanceof FingerprintSettingsPreferenceController) {
+ ((FingerprintSettingsPreferenceController) controller).setUserId(mUserId);
+ } else if (controller instanceof FingerprintUnlockCategoryController) {
+ ((FingerprintUnlockCategoryController) controller).setUserId(mUserId);
+ }
+ }
+ createFooterPreference(root);
}
private String addFingerprintItemPreferences(PreferenceGroup root) {
- root.removeAll();
+ mFingerprintsEnrolledCategory = findPreference(KEY_FINGERPRINTS_ENROLLED_CATEGORY);
+ if (mFingerprintsEnrolledCategory != null) {
+ mFingerprintsEnrolledCategory.removeAll();
+ }
+
String keyToReturn = KEY_FINGERPRINT_ADD;
final List<Fingerprint> items = mFingerprintManager.getEnrolledFingerprints(mUserId);
final int fingerprintCount = items.size();
@@ -576,22 +571,46 @@
if (mFingerprintsRenaming.containsKey(item.getBiometricId())) {
pref.setTitle(mFingerprintsRenaming.get(item.getBiometricId()));
}
- root.addPreference(pref);
+ mFingerprintsEnrolledCategory.addPreference(pref);
pref.setOnPreferenceChangeListener(this);
}
-
- Preference addPreference = new Preference(root.getContext());
- addPreference.setKey(KEY_FINGERPRINT_ADD);
- addPreference.setTitle(R.string.fingerprint_add_title);
- addPreference.setIcon(R.drawable.ic_add_24dp);
- root.addPreference(addPreference);
- addPreference.setOnPreferenceChangeListener(this);
- updateAddPreference();
- createFooterPreference(root);
-
+ mAddFingerprintPreference = findPreference(KEY_FINGERPRINT_ADD);
+ setupAddFingerprintPreference();
return keyToReturn;
}
+ private void setupAddFingerprintPreference() {
+ mAddFingerprintPreference.setOnPreferenceChangeListener(this);
+ updateAddPreference();
+ }
+
+ private void addFingerprintUnlockCategory() {
+ mFingerprintUnlockCategory = findPreference(KEY_FINGERPRINT_UNLOCK_CATEGORY);
+ setupFingerprintUnlockCategoryPreferences();
+ updateFingerprintUnlockCategoryVisibility();
+ }
+
+ private void updateFingerprintUnlockCategoryVisibility() {
+ final boolean mFingerprintUnlockCategoryAvailable =
+ mFingerprintUnlockCategoryPreferenceController.isAvailable();
+ if (mFingerprintUnlockCategory.isVisible() != mFingerprintUnlockCategoryAvailable) {
+ mFingerprintUnlockCategory.setVisible(
+ mFingerprintUnlockCategoryAvailable);
+ }
+ }
+
+ private void setupFingerprintUnlockCategoryPreferences() {
+ mRequireScreenOnToAuthPreference = findPreference(KEY_REQUIRE_SCREEN_ON_TO_AUTH);
+ mRequireScreenOnToAuthPreference.setChecked(
+ mRequireScreenOnToAuthPreferenceController.isChecked());
+ mRequireScreenOnToAuthPreference.setOnPreferenceChangeListener(
+ (preference, newValue) -> {
+ final boolean isChecked = ((SwitchPreference) preference).isChecked();
+ mRequireScreenOnToAuthPreferenceController.setChecked(!isChecked);
+ return true;
+ });
+ }
+
private void updateAddPreference() {
if (getActivity() == null) {
return; // Activity went away
@@ -612,8 +631,8 @@
final boolean removalInProgress = mRemovalSidecar.inProgress();
CharSequence maxSummary = tooMany ?
getContext().getString(R.string.fingerprint_add_max, max) : "";
- addPreference.setSummary(maxSummary);
- addPreference.setEnabled(!tooMany && !removalInProgress && mToken != null);
+ mAddFingerprintPreference.setSummary(maxSummary);
+ mAddFingerprintPreference.setEnabled(!tooMany && !removalInProgress && mToken != null);
}
private void createFooterPreference(PreferenceGroup root) {
@@ -621,6 +640,10 @@
if (context == null) {
return;
}
+ mFingerprintUnlockFooter = findPreference(KEY_FINGERPRINT_UNLOCK_FOOTER);
+ if (mFingerprintUnlockFooter != null) {
+ mFingerprintUnlockFooter.removeAll();
+ }
for (int i = 0; i < mFooterColumns.size(); ++i) {
final FooterColumn column = mFooterColumns.get(i);
final FooterPreference footer = new FooterPreference.Builder(context)
@@ -634,7 +657,7 @@
footer.setLearnMoreText(column.mLearnMoreOverrideText);
}
}
- root.addPreference(footer);
+ mFingerprintUnlockFooter.addPreference(footer);
}
}
@@ -815,11 +838,17 @@
private List<AbstractPreferenceController> buildPreferenceControllers(Context context) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
+ mFingerprintUnlockCategoryPreferenceController =
+ new FingerprintUnlockCategoryController(
+ context,
+ KEY_FINGERPRINT_UNLOCK_CATEGORY
+ );
mRequireScreenOnToAuthPreferenceController =
new FingerprintSettingsRequireScreenOnToAuthPreferenceController(
context,
KEY_REQUIRE_SCREEN_ON_TO_AUTH
);
+ controllers.add(mFingerprintUnlockCategoryPreferenceController);
controllers.add(mRequireScreenOnToAuthPreferenceController);
return controllers;
}
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsRequireScreenOnToAuthPreferenceController.java b/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsRequireScreenOnToAuthPreferenceController.java
index 52e6d13..87396dd 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsRequireScreenOnToAuthPreferenceController.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsRequireScreenOnToAuthPreferenceController.java
@@ -94,7 +94,7 @@
&& mFingerprintManager.isHardwareDetected()
&& mFingerprintManager.isPowerbuttonFps()) {
return mFingerprintManager.hasEnrolledTemplates(getUserId())
- ? AVAILABLE : DISABLED_DEPENDENT_SETTING;
+ ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
} else {
return UNSUPPORTED_ON_DEVICE;
}
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintUnlockCategoryController.java b/src/com/android/settings/biometrics/fingerprint/FingerprintUnlockCategoryController.java
new file mode 100644
index 0000000..674a0df
--- /dev/null
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintUnlockCategoryController.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2023 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.fingerprint;
+
+import android.content.Context;
+import android.hardware.fingerprint.FingerprintManager;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settings.Utils;
+import com.android.settings.core.BasePreferenceController;
+
+/**
+ * Preference controller that controls the fingerprint unlock features to be shown / be hidden.
+ */
+public class FingerprintUnlockCategoryController extends BasePreferenceController {
+ private static final String TAG = "FingerprintUnlockCategoryPreferenceController";
+
+ private int mUserId;
+ @VisibleForTesting
+ protected FingerprintManager mFingerprintManager;
+
+ public FingerprintUnlockCategoryController(Context context, String key) {
+ super(context, key);
+ mFingerprintManager = Utils.getFingerprintManagerOrNull(context);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ if (mFingerprintManager != null
+ && mFingerprintManager.isHardwareDetected()
+ && mFingerprintManager.isPowerbuttonFps()) {
+ return mFingerprintManager.hasEnrolledTemplates(getUserId())
+ ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
+ } else {
+ return UNSUPPORTED_ON_DEVICE;
+ }
+ }
+
+ public void setUserId(int userId) {
+ mUserId = userId;
+ }
+
+ protected int getUserId() {
+ return mUserId;
+ }
+}
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintsEnrolledCategoryPreferenceController.java b/src/com/android/settings/biometrics/fingerprint/FingerprintsEnrolledCategoryPreferenceController.java
new file mode 100644
index 0000000..53d5379
--- /dev/null
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintsEnrolledCategoryPreferenceController.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2023 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.fingerprint;
+
+import android.content.Context;
+import android.hardware.fingerprint.FingerprintManager;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settings.Utils;
+import com.android.settings.core.BasePreferenceController;
+
+/**
+ * Preference controller that controls the enrolled fingerprints to be shown / be hidden.
+ */
+public class FingerprintsEnrolledCategoryPreferenceController extends BasePreferenceController {
+ private static final String TAG = "FingerprintsEnrolledCategoryPreferenceController";
+
+ private int mUserId;
+ @VisibleForTesting
+ protected FingerprintManager mFingerprintManager;
+
+ public FingerprintsEnrolledCategoryPreferenceController(Context context, String key) {
+ super(context, key);
+ mFingerprintManager = Utils.getFingerprintManagerOrNull(context);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ if (mFingerprintManager != null
+ && mFingerprintManager.isHardwareDetected()) {
+ return mFingerprintManager.hasEnrolledTemplates(getUserId())
+ ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
+ } else {
+ return UNSUPPORTED_ON_DEVICE;
+ }
+ }
+
+ public void setUserId(int userId) {
+ mUserId = userId;
+ }
+
+ protected int getUserId() {
+ return mUserId;
+ }
+}
diff --git a/src/com/android/settings/display/AlwaysOnDisplaySlice.java b/src/com/android/settings/display/AlwaysOnDisplaySlice.java
index c66f4ed..003c603 100644
--- a/src/com/android/settings/display/AlwaysOnDisplaySlice.java
+++ b/src/com/android/settings/display/AlwaysOnDisplaySlice.java
@@ -28,6 +28,7 @@
import android.net.Uri;
import android.os.UserHandle;
import android.provider.Settings;
+import android.text.TextUtils;
import androidx.slice.Slice;
import androidx.slice.builders.ListBuilder;
@@ -40,6 +41,10 @@
import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.CustomSliceable;
+import java.util.Arrays;
+import java.util.Set;
+import java.util.stream.Collectors;
+
/**
* Custom {@link Slice} for Always on Display.
* <p>
@@ -75,6 +80,7 @@
return new ListBuilder(mContext, CustomSliceRegistry.ALWAYS_ON_SLICE_URI,
ListBuilder.INFINITY)
.setAccentColor(color)
+ .setKeywords(getKeywords())
.addRow(new ListBuilder.RowBuilder()
.setTitle(mContext.getText(R.string.doze_always_on_title))
.setSubtitle(mContext.getText(R.string.doze_always_on_summary))
@@ -84,6 +90,13 @@
.build();
}
+ private Set<String> getKeywords() {
+ final String keywords = mContext.getString(R.string.keywords_always_show_time_info);
+ return Arrays.stream(TextUtils.split(keywords, ","))
+ .map(String::trim)
+ .collect(Collectors.toSet());
+ }
+
@Override
public Uri getUri() {
return CustomSliceRegistry.ALWAYS_ON_SLICE_URI;
diff --git a/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceController.java b/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceController.java
index e0e25df..5d95ddb 100644
--- a/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceController.java
+++ b/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceController.java
@@ -22,7 +22,6 @@
import android.os.SystemProperties;
import android.os.UserHandle;
import android.provider.Settings;
-import android.text.TextUtils;
import androidx.preference.Preference;
@@ -59,7 +58,7 @@
@Override
public boolean isSliceable() {
- return TextUtils.equals(getPreferenceKey(), "ambient_display_always_on");
+ return true;
}
@Override
diff --git a/src/com/android/settings/notetask/shortcut/CreateNoteTaskShortcutActivity.kt b/src/com/android/settings/notetask/shortcut/CreateNoteTaskShortcutActivity.kt
index b984622..d3d7510 100644
--- a/src/com/android/settings/notetask/shortcut/CreateNoteTaskShortcutActivity.kt
+++ b/src/com/android/settings/notetask/shortcut/CreateNoteTaskShortcutActivity.kt
@@ -37,6 +37,11 @@
* shortcut will appear in the widget picker. If the shortcut is selected, the Activity here will be
* launched, creating a new shortcut for [CreateNoteTaskShortcutActivity], and will finish.
*
+ * IMPORTANT! The shortcut package name and class should be synchronized with SystemUI controller:
+ * [com.android.systemui.notetask.NoteTaskController#SETTINGS_CREATE_NOTE_TASK_SHORTCUT_COMPONENT].
+ *
+ * Changing the package name or class is a breaking change.
+ *
* @see <a
* href="https://developer.android.com/develop/ui/views/launch/shortcuts/creating-shortcuts#custom-pinned">Creating
* a custom shortcut activity</a>
@@ -81,9 +86,16 @@
setPackage(systemUiComponent.packageName)
}
- return ShortcutInfo.Builder(context, SHORTCUT_ID)
+ // Creates a System UI context. That will let the ownership with SystemUI and allows it
+ // to perform updates such as enabling or updating the badge override package.
+ val systemUiContext = context.createPackageContext(
+ systemUiComponent.packageName,
+ /* flags */ 0,
+ )
+
+ return ShortcutInfo.Builder(systemUiContext, SHORTCUT_ID)
.setIntent(intent)
- .setShortLabel(context.getString(R.string.note_task_button_label))
+ .setShortLabel(context.getString(R.string.note_task_shortcut_label))
.setLongLived(true)
.setIcon(icon)
.setExtras(extras)
diff --git a/src/com/android/settings/notification/app/ChannelPanelActivity.java b/src/com/android/settings/notification/app/ChannelPanelActivity.java
index 9889183..dda1c65 100644
--- a/src/com/android/settings/notification/app/ChannelPanelActivity.java
+++ b/src/com/android/settings/notification/app/ChannelPanelActivity.java
@@ -28,10 +28,13 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.core.view.ViewCompat;
+import androidx.core.view.WindowInsetsControllerCompat;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import com.android.settings.R;
+import com.android.settings.Utils;
import com.android.settings.core.SubSettingLauncher;
import com.android.settingslib.core.lifecycle.HideNonSystemOverlayMixin;
@@ -99,7 +102,7 @@
findViewById(R.id.done).setOnClickListener(v -> finish());
findViewById(R.id.see_more).setOnClickListener(v -> launchFullSettings());
-
+ setupNavigationBar();
mPanelFragment = callingIntent.hasExtra(Settings.EXTRA_CONVERSATION_ID)
? new ConversationNotificationSettings()
: new ChannelNotificationSettings();
@@ -107,4 +110,27 @@
fragmentManager.beginTransaction().replace(
android.R.id.list_container, mPanelFragment).commit();
}
+
+ /**
+ * Adjust bottom edge and color.
+ */
+ private void setupNavigationBar() {
+ // Extend the panel all the way to the bottom of the screen, as opposed to sitting on top of
+ // the navigation bar.
+ ViewCompat.setOnApplyWindowInsetsListener(getWindow().getDecorView(),
+ (v, windowInsets) -> {
+ v.setPadding(v.getPaddingLeft(), v.getPaddingTop(), v.getPaddingRight(), 0);
+ return windowInsets; // propagate down to panel layout root element
+ });
+
+ // When using 3-button navigation in light mode, the system picks white navigation buttons
+ // which are not sufficiently contrasted from the panel background.
+ WindowInsetsControllerCompat windowInsetsController =
+ ViewCompat.getWindowInsetsController(getWindow().getDecorView());
+
+ if (windowInsetsController != null) {
+ boolean forceNavigationButtonsDark = !Utils.isNightMode(this);
+ windowInsetsController.setAppearanceLightNavigationBars(forceNavigationButtonsDark);
+ }
+ }
}
diff --git a/src/com/android/settings/wifi/factory/WifiFeatureProvider.java b/src/com/android/settings/wifi/factory/WifiFeatureProvider.java
index 6612476..c61cf51 100644
--- a/src/com/android/settings/wifi/factory/WifiFeatureProvider.java
+++ b/src/com/android/settings/wifi/factory/WifiFeatureProvider.java
@@ -18,6 +18,7 @@
import android.annotation.Nullable;
import android.content.Context;
+import android.net.TetheringManager;
import android.net.wifi.WifiManager;
import android.util.Log;
@@ -40,6 +41,7 @@
private final Context mAppContext;
private WifiManager mWifiManager;
+ private TetheringManager mTetheringManager;
private WifiVerboseLogging mWifiVerboseLogging;
private WifiHotspotRepository mWifiHotspotRepository;
@@ -48,7 +50,7 @@
}
/**
- * Get WifiManager
+ * Gets WifiManager
*/
public WifiManager getWifiManager() {
if (mWifiManager == null) {
@@ -58,7 +60,18 @@
}
/**
- * Get WifiVerboseLogging
+ * Gets TetheringManager
+ */
+ public TetheringManager getTetheringManager() {
+ if (mTetheringManager == null) {
+ mTetheringManager = mAppContext.getSystemService(TetheringManager.class);
+ verboseLog(TAG, "getTetheringManager():" + mTetheringManager);
+ }
+ return mTetheringManager;
+ }
+
+ /**
+ * Gets WifiVerboseLogging
*/
public WifiVerboseLogging getWifiVerboseLogging() {
if (mWifiVerboseLogging == null) {
@@ -68,25 +81,26 @@
}
/**
- * Get WifiHotspotRepository
+ * Gets WifiHotspotRepository
*/
public WifiHotspotRepository getWifiHotspotRepository() {
if (mWifiHotspotRepository == null) {
- mWifiHotspotRepository = new WifiHotspotRepository(mAppContext, getWifiManager());
+ mWifiHotspotRepository = new WifiHotspotRepository(mAppContext, getWifiManager(),
+ getTetheringManager());
verboseLog(TAG, "getWifiHotspotRepository():" + mWifiHotspotRepository);
}
return mWifiHotspotRepository;
}
/**
- * Get WifiTetherViewModel
+ * Gets WifiTetherViewModel
*/
public WifiTetherViewModel getWifiTetherViewModel(@NotNull ViewModelStoreOwner owner) {
return new ViewModelProvider(owner).get(WifiTetherViewModel.class);
}
/**
- * Get WifiHotspotSecurityViewModel
+ * Gets WifiHotspotSecurityViewModel
*/
public WifiHotspotSecurityViewModel getWifiHotspotSecurityViewModel(
@NotNull ViewModelStoreOwner owner) {
@@ -97,7 +111,7 @@
}
/**
- * Get WifiHotspotSpeedViewModel
+ * Gets WifiHotspotSpeedViewModel
*/
public WifiHotspotSpeedViewModel getWifiHotspotSpeedViewModel(
@NotNull ViewModelStoreOwner owner) {
diff --git a/src/com/android/settings/wifi/repository/WifiHotspotRepository.java b/src/com/android/settings/wifi/repository/WifiHotspotRepository.java
index c96896f..c46fb2b 100644
--- a/src/com/android/settings/wifi/repository/WifiHotspotRepository.java
+++ b/src/com/android/settings/wifi/repository/WifiHotspotRepository.java
@@ -16,14 +16,18 @@
package com.android.settings.wifi.repository;
+import static android.net.TetheringManager.TETHERING_WIFI;
import static android.net.wifi.SoftApConfiguration.BAND_2GHZ;
import static android.net.wifi.SoftApConfiguration.BAND_5GHZ;
import static android.net.wifi.SoftApConfiguration.BAND_6GHZ;
import static android.net.wifi.SoftApConfiguration.SECURITY_TYPE_OPEN;
import static android.net.wifi.SoftApConfiguration.SECURITY_TYPE_WPA3_SAE;
import static android.net.wifi.WifiAvailableChannel.OP_MODE_SAP;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
import android.content.Context;
+import android.net.TetheringManager;
import android.net.wifi.SoftApConfiguration;
import android.net.wifi.WifiAvailableChannel;
import android.net.wifi.WifiManager;
@@ -51,6 +55,8 @@
public class WifiHotspotRepository {
private static final String TAG = "WifiHotspotRepository";
+ private static final int RESTART_INTERVAL_MS = 100;
+
/** Wi-Fi hotspot band unknown. */
public static final int BAND_UNKNOWN = 0;
/** Wi-Fi hotspot band 2.4GHz and 5GHz. */
@@ -79,8 +85,9 @@
sSpeedMap.put(BAND_2GHZ_5GHZ, SPEED_2GHZ_5GHZ);
}
- protected final Context mAppContext;
- protected final WifiManager mWifiManager;
+ private final Context mAppContext;
+ private final WifiManager mWifiManager;
+ private final TetheringManager mTetheringManager;
protected String mLastPassword;
protected LastPasswordListener mLastPasswordListener = new LastPasswordListener();
@@ -102,9 +109,24 @@
Boolean mIsConfigShowSpeed;
private Boolean mIsSpeedFeatureAvailable;
- public WifiHotspotRepository(@NonNull Context appContext, @NonNull WifiManager wifiManager) {
+ @VisibleForTesting
+ SoftApCallback mSoftApCallback = new SoftApCallback();
+ @VisibleForTesting
+ StartTetheringCallback mStartTetheringCallback;
+ @VisibleForTesting
+ int mWifiApState = WIFI_AP_STATE_DISABLED;
+
+ @VisibleForTesting
+ boolean mIsRestarting;
+ @VisibleForTesting
+ MutableLiveData<Boolean> mRestarting;
+
+ public WifiHotspotRepository(@NonNull Context appContext, @NonNull WifiManager wifiManager,
+ @NonNull TetheringManager tetheringManager) {
mAppContext = appContext;
mWifiManager = wifiManager;
+ mTetheringManager = tetheringManager;
+ mWifiManager.registerSoftApCallback(mAppContext.getMainExecutor(), mSoftApCallback);
}
/**
@@ -126,6 +148,15 @@
return !TextUtils.isEmpty(mLastPassword) ? mLastPassword : generateRandomPassword();
}
+ @VisibleForTesting
+ String generatePassword(SoftApConfiguration config) {
+ String password = config.getPassphrase();
+ if (TextUtils.isEmpty(password)) {
+ password = generatePassword();
+ }
+ return password;
+ }
+
private class LastPasswordListener implements Consumer<String> {
@Override
public void accept(String password) {
@@ -140,13 +171,27 @@
}
/**
+ * Gets the Wi-Fi tethered AP Configuration.
+ *
+ * @return AP details in {@link SoftApConfiguration}
+ */
+ public SoftApConfiguration getSoftApConfiguration() {
+ return mWifiManager.getSoftApConfiguration();
+ }
+
+ /**
* Sets the tethered Wi-Fi AP Configuration.
*
* @param config A valid SoftApConfiguration specifying the configuration of the SAP.
*/
public void setSoftApConfiguration(@NonNull SoftApConfiguration config) {
+ if (mIsRestarting) {
+ Log.e(TAG, "Skip setSoftApConfiguration because hotspot is restarting.");
+ return;
+ }
mWifiManager.setSoftApConfiguration(config);
refresh();
+ restartTetheringIfNeeded();
}
/**
@@ -217,13 +262,7 @@
return;
}
SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder(config);
- String passphrase = null;
- if (securityType != SECURITY_TYPE_OPEN) {
- passphrase = config.getPassphrase();
- if (TextUtils.isEmpty(passphrase)) {
- passphrase = generatePassword();
- }
- }
+ String passphrase = (securityType == SECURITY_TYPE_OPEN) ? null : generatePassword(config);
configBuilder.setPassphrase(passphrase, securityType);
setSoftApConfiguration(configBuilder.build());
@@ -302,7 +341,7 @@
configBuilder.setBand(BAND_2GHZ_5GHZ_6GHZ);
if (config.getSecurityType() != SECURITY_TYPE_WPA3_SAE) {
log("setSpeedType(), setPassphrase(SECURITY_TYPE_WPA3_SAE)");
- configBuilder.setPassphrase(generatePassword(), SECURITY_TYPE_WPA3_SAE);
+ configBuilder.setPassphrase(generatePassword(config), SECURITY_TYPE_WPA3_SAE);
}
} else if (speedType == SPEED_5GHZ) {
log("setSpeedType(), setBand(BAND_2GHZ_5GHZ)");
@@ -543,6 +582,84 @@
}
}
+ /**
+ * Gets Restarting LiveData
+ */
+ public LiveData<Boolean> getRestarting() {
+ if (mRestarting == null) {
+ mRestarting = new MutableLiveData<>();
+ mRestarting.setValue(mIsRestarting);
+ }
+ return mRestarting;
+ }
+
+ private void setRestarting(boolean isRestarting) {
+ log("setRestarting(), isRestarting:" + isRestarting);
+ mIsRestarting = isRestarting;
+ if (mRestarting != null) {
+ mRestarting.setValue(mIsRestarting);
+ }
+ }
+
+ @VisibleForTesting
+ void restartTetheringIfNeeded() {
+ if (mWifiApState != WIFI_AP_STATE_ENABLED) {
+ return;
+ }
+ log("restartTetheringIfNeeded()");
+ mAppContext.getMainThreadHandler().postDelayed(() -> {
+ setRestarting(true);
+ stopTethering();
+ }, RESTART_INTERVAL_MS);
+ }
+
+ private void startTethering() {
+ if (mStartTetheringCallback == null) {
+ mStartTetheringCallback = new StartTetheringCallback();
+ }
+ log("startTethering()");
+ mTetheringManager.startTethering(TETHERING_WIFI, mAppContext.getMainExecutor(),
+ mStartTetheringCallback);
+ }
+
+ private void stopTethering() {
+ log("startTethering()");
+ mTetheringManager.stopTethering(TETHERING_WIFI);
+ }
+
+ @VisibleForTesting
+ class SoftApCallback implements WifiManager.SoftApCallback {
+ @Override
+ public void onStateChanged(int state, int failureReason) {
+ log("onStateChanged(), state:" + state + ", failureReason:" + failureReason);
+ mWifiApState = state;
+ if (!mIsRestarting) {
+ return;
+ }
+ if (state == WIFI_AP_STATE_DISABLED) {
+ mAppContext.getMainThreadHandler().postDelayed(() -> startTethering(),
+ RESTART_INTERVAL_MS);
+ return;
+ }
+ if (state == WIFI_AP_STATE_ENABLED) {
+ refresh();
+ setRestarting(false);
+ }
+ }
+ }
+
+ private class StartTetheringCallback implements TetheringManager.StartTetheringCallback {
+ @Override
+ public void onTetheringStarted() {
+ log("onTetheringStarted()");
+ }
+
+ @Override
+ public void onTetheringFailed(int error) {
+ log("onTetheringFailed(), error:" + error);
+ }
+ }
+
private void log(String msg) {
FeatureFactory.getFactory(mAppContext).getWifiFeatureProvider().verboseLog(TAG, msg);
}
diff --git a/src/com/android/settings/wifi/tether/WifiHotspotSecuritySettings.java b/src/com/android/settings/wifi/tether/WifiHotspotSecuritySettings.java
index 8ff2689..0dc1605 100644
--- a/src/com/android/settings/wifi/tether/WifiHotspotSecuritySettings.java
+++ b/src/com/android/settings/wifi/tether/WifiHotspotSecuritySettings.java
@@ -19,6 +19,7 @@
import android.app.settings.SettingsEnums;
import android.os.Bundle;
+import androidx.annotation.VisibleForTesting;
import androidx.lifecycle.LiveData;
import com.android.settings.R;
@@ -72,6 +73,7 @@
SelectorWithWidgetPreference preference = findPreference(viewItem.mKey);
preference.setOnClickListener(this);
}
+ mWifiHotspotSecurityViewModel.getRestarting().observe(this, this::onRestartingChanged);
}
protected void onViewItemListDataChanged(
@@ -96,6 +98,12 @@
}
}
+ @VisibleForTesting
+ void onRestartingChanged(Boolean restarting) {
+ log("onRestartingChanged(), restarting:" + restarting);
+ setLoading(restarting, false);
+ }
+
@Override
public void onRadioButtonClicked(SelectorWithWidgetPreference emiter) {
String key = emiter.getKey();
diff --git a/src/com/android/settings/wifi/tether/WifiHotspotSecurityViewModel.java b/src/com/android/settings/wifi/tether/WifiHotspotSecurityViewModel.java
index 422e40b..7c8554c 100644
--- a/src/com/android/settings/wifi/tether/WifiHotspotSecurityViewModel.java
+++ b/src/com/android/settings/wifi/tether/WifiHotspotSecurityViewModel.java
@@ -130,6 +130,13 @@
}
/**
+ * Gets Restarting LiveData
+ */
+ public LiveData<Boolean> getRestarting() {
+ return mWifiHotspotRepository.getRestarting();
+ }
+
+ /**
* Wi-Fi Hotspot View Item
*/
public static final class ViewItem {
diff --git a/src/com/android/settings/wifi/tether/WifiHotspotSpeedSettings.java b/src/com/android/settings/wifi/tether/WifiHotspotSpeedSettings.java
index 467d394..f5066bd 100644
--- a/src/com/android/settings/wifi/tether/WifiHotspotSpeedSettings.java
+++ b/src/com/android/settings/wifi/tether/WifiHotspotSpeedSettings.java
@@ -24,6 +24,8 @@
import android.app.settings.SettingsEnums;
import android.os.Bundle;
+import androidx.annotation.VisibleForTesting;
+
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.overlay.FeatureFactory;
@@ -80,6 +82,7 @@
onSpeedInfoMapDataChanged(mWifiHotspotSpeedViewModel.getSpeedInfoMapData().getValue());
mWifiHotspotSpeedViewModel.getSpeedInfoMapData()
.observe(this, this::onSpeedInfoMapDataChanged);
+ mWifiHotspotSpeedViewModel.getRestarting().observe(this, this::onRestartingChanged);
}
protected void loadPreferences() {
@@ -117,6 +120,12 @@
}
}
+ @VisibleForTesting
+ void onRestartingChanged(Boolean restarting) {
+ log("onRestartingChanged(), restarting:" + restarting);
+ setLoading(restarting, false);
+ }
+
@Override
public void onRadioButtonClicked(SelectorWithWidgetPreference emiter) {
String key = emiter.getKey();
diff --git a/src/com/android/settings/wifi/tether/WifiHotspotSpeedViewModel.java b/src/com/android/settings/wifi/tether/WifiHotspotSpeedViewModel.java
index c30174e..f04669a 100644
--- a/src/com/android/settings/wifi/tether/WifiHotspotSpeedViewModel.java
+++ b/src/com/android/settings/wifi/tether/WifiHotspotSpeedViewModel.java
@@ -131,6 +131,13 @@
}
/**
+ * Gets Restarting LiveData
+ */
+ public LiveData<Boolean> getRestarting() {
+ return mWifiHotspotRepository.getRestarting();
+ }
+
+ /**
* Wi-Fi Hotspot Speed Information
*/
public static final class SpeedInfo {
diff --git a/src/com/android/settings/wifi/tether/WifiTetherSettings.java b/src/com/android/settings/wifi/tether/WifiTetherSettings.java
index 174ccb0..2774be6 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherSettings.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherSettings.java
@@ -17,6 +17,8 @@
package com.android.settings.wifi.tether;
import static android.net.wifi.WifiManager.WIFI_AP_STATE_CHANGED_ACTION;
+import static android.view.View.INVISIBLE;
+import static android.view.View.VISIBLE;
import static com.android.settings.wifi.WifiUtils.canShowWifiHotspot;
@@ -26,7 +28,6 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.SoftApConfiguration;
-import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.UserManager;
import android.util.FeatureFlagUtils;
@@ -76,6 +77,8 @@
@VisibleForTesting
static final String KEY_WIFI_HOTSPOT_SPEED = "wifi_hotspot_speed";
+ @VisibleForTesting
+ SettingsMainSwitchBar mMainSwitchBar;
private WifiTetherSwitchBarController mSwitchBarController;
private WifiTetherSSIDPreferenceController mSSIDPreferenceController;
private WifiTetherPasswordPreferenceController mPasswordPreferenceController;
@@ -83,8 +86,6 @@
private WifiTetherMaximizeCompatibilityPreferenceController mMaxCompatibilityPrefController;
private WifiTetherAutoOffPreferenceController mWifiTetherAutoOffPreferenceController;
- private WifiManager mWifiManager;
- private boolean mRestartWifiApAfterConfigChange;
private boolean mUnavailable;
private WifiRestriction mWifiRestriction;
@VisibleForTesting
@@ -138,6 +139,7 @@
.getWifiTetherViewModel(this);
if (mWifiTetherViewModel != null) {
setupSpeedFeature(mWifiTetherViewModel.isSpeedFeatureAvailable());
+ mWifiTetherViewModel.getRestarting().observe(this, this::onRestartingChanged);
}
}
@@ -159,7 +161,6 @@
@Override
public void onAttach(Context context) {
super.onAttach(context);
- mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
mTetherChangeReceiver = new TetherChangeReceiver();
mSSIDPreferenceController = use(WifiTetherSSIDPreferenceController.class);
@@ -179,11 +180,11 @@
// Assume we are in a SettingsActivity. This is only safe because we currently use
// SettingsActivity as base for all preference fragments.
final SettingsActivity activity = (SettingsActivity) getActivity();
- final SettingsMainSwitchBar switchBar = activity.getSwitchBar();
- switchBar.setTitle(getContext().getString(R.string.use_wifi_hotsopt_main_switch_title));
- mSwitchBarController = new WifiTetherSwitchBarController(activity, switchBar);
+ mMainSwitchBar = activity.getSwitchBar();
+ mMainSwitchBar.setTitle(getString(R.string.use_wifi_hotsopt_main_switch_title));
+ mSwitchBarController = new WifiTetherSwitchBarController(activity, mMainSwitchBar);
getSettingsLifecycle().addObserver(mSwitchBarController);
- switchBar.show();
+ mMainSwitchBar.show();
}
@Override
@@ -259,40 +260,34 @@
final SoftApConfiguration config = buildNewConfig();
mPasswordPreferenceController.setSecurityType(config.getSecurityType());
- /**
- * if soft AP is stopped, bring up
- * else restart with new config
- * TODO: update config on a running access point when framework support is added
- */
- if (mWifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_ENABLED) {
- Log.d("TetheringSettings",
- "Wifi AP config changed while enabled, stop and restart");
- mRestartWifiApAfterConfigChange = true;
- mSwitchBarController.stopTether();
- }
mWifiTetherViewModel.setSoftApConfiguration(config);
}
+ @VisibleForTesting
+ void onRestartingChanged(Boolean restarting) {
+ mMainSwitchBar.setVisibility((restarting) ? INVISIBLE : VISIBLE);
+ setLoading(restarting, false);
+ }
+
private SoftApConfiguration buildNewConfig() {
- final SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder();
- final int securityType = mSecurityPreferenceController.getSecurityType();
+ SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder();
+ int securityType = (mWifiTetherViewModel.isSpeedFeatureAvailable())
+ ? mWifiTetherViewModel.getSoftApConfiguration().getSecurityType()
+ : mSecurityPreferenceController.getSecurityType();
configBuilder.setSsid(mSSIDPreferenceController.getSSID());
if (securityType != SoftApConfiguration.SECURITY_TYPE_OPEN) {
configBuilder.setPassphrase(
mPasswordPreferenceController.getPasswordValidated(securityType),
securityType);
}
- mMaxCompatibilityPrefController.setupMaximizeCompatibility(configBuilder);
+ if (!mWifiTetherViewModel.isSpeedFeatureAvailable()) {
+ mMaxCompatibilityPrefController.setupMaximizeCompatibility(configBuilder);
+ }
configBuilder.setAutoShutdownEnabled(
mWifiTetherAutoOffPreferenceController.isEnabled());
return configBuilder.build();
}
- private void startTether() {
- mRestartWifiApAfterConfigChange = false;
- mSwitchBarController.startTether();
- }
-
private void updateDisplayWithNewConfig() {
use(WifiTetherSSIDPreferenceController.class).updateDisplay();
use(WifiTetherSecurityPreferenceController.class).updateDisplay();
@@ -369,13 +364,6 @@
String action = intent.getAction();
Log.d(TAG, "updating display config due to receiving broadcast action " + action);
updateDisplayWithNewConfig();
- if (action.equals(WIFI_AP_STATE_CHANGED_ACTION)) {
- int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_AP_STATE, 0);
- if (state == WifiManager.WIFI_AP_STATE_DISABLED
- && mRestartWifiApAfterConfigChange) {
- startTether();
- }
- }
}
}
}
diff --git a/src/com/android/settings/wifi/tether/WifiTetherViewModel.java b/src/com/android/settings/wifi/tether/WifiTetherViewModel.java
index dd4ca28..fb2160f 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherViewModel.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherViewModel.java
@@ -101,6 +101,15 @@
}
/**
+ * Gets the Wi-Fi tethered AP Configuration.
+ *
+ * @return AP details in {@link SoftApConfiguration}
+ */
+ public SoftApConfiguration getSoftApConfiguration() {
+ return mWifiHotspotRepository.getSoftApConfiguration();
+ }
+
+ /**
* Sets the tethered Wi-Fi AP Configuration.
*
* @param config A valid SoftApConfiguration specifying the configuration of the SAP.
@@ -153,4 +162,11 @@
}
mSpeedSummary.setValue(resId);
}
+
+ /**
+ * Gets Restarting LiveData
+ */
+ public LiveData<Boolean> getRestarting() {
+ return mWifiHotspotRepository.getRestarting();
+ }
}
diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsRequireScreenOnToAuthPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsRequireScreenOnToAuthPreferenceControllerTest.java
index b6df62e..ebfa6d5 100644
--- a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsRequireScreenOnToAuthPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsRequireScreenOnToAuthPreferenceControllerTest.java
@@ -17,7 +17,7 @@
package com.android.settings.biometrics.fingerprint;
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
-import static com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING;
+import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
import static com.google.common.truth.Truth.assertThat;
@@ -103,15 +103,15 @@
}
@Test
- public void isAvailable_isDisabled_whenSfpsHardwareDetected_AndNoEnrolledFingerprints() {
+ public void isUnavailable_isDisabled_whenSfpsHardwareDetected_AndNoEnrolledFingerprints() {
assertThat(mController.isAvailable()).isEqualTo(false);
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
configure_hardwareDetected_isSfps_hasEnrolledTemplates(
true /* isHardwareDetected */,
true /* isPowerbuttonFps */,
false /* hasEnrolledTemplates */);
- assertThat(mController.isAvailable()).isEqualTo(true);
- assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_DEPENDENT_SETTING);
+ assertThat(mController.isAvailable()).isEqualTo(false);
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
}
@Test
@@ -122,7 +122,7 @@
false /* isHardwareDetected */,
true /* isPowerbuttonFps */,
true /* hasEnrolledTemplates */);
- assertThat(mController.isAvailable()).isFalse();
+ assertThat(mController.isAvailable()).isEqualTo(false);
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
}
diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsUnlockCategoryControllerTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsUnlockCategoryControllerTest.java
new file mode 100644
index 0000000..7b6a70e
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsUnlockCategoryControllerTest.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2023 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.fingerprint;
+
+import static com.android.settings.core.BasePreferenceController.AVAILABLE;
+import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
+import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.hardware.fingerprint.FingerprintManager;
+
+import com.android.settings.testutils.shadow.ShadowUtils;
+import com.android.settingslib.RestrictedSwitchPreference;
+
+import org.junit.After;
+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;
+import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowUtils.class})
+public class FingerprintSettingsUnlockCategoryControllerTest {
+
+ @Mock
+ private FingerprintManager mFingerprintManager;
+ @Mock
+ private PackageManager mPackageManager;
+ @Mock
+ private RestrictedSwitchPreference mPreference;
+
+ private Context mContext;
+ private FingerprintSettingsRequireScreenOnToAuthPreferenceController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+ when(mContext.getSystemService(eq(Context.FINGERPRINT_SERVICE))).thenReturn(
+ mFingerprintManager);
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+
+ mController = spy(new FingerprintSettingsRequireScreenOnToAuthPreferenceController(mContext,
+ "test_key"));
+ ReflectionHelpers.setField(mController, "mFingerprintManager", mFingerprintManager);
+ }
+
+ @After
+ public void tearDown() {
+ ShadowUtils.reset();
+ }
+
+ @Test
+ public void isAvailable_isEnabled_whenSfpsHardwareDetected_AndHasEnrolledFingerprints() {
+ assertThat(mController.isAvailable()).isEqualTo(false);
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
+ configure_hardwareDetected_isSfps_hasEnrolledTemplates(
+ true /* isHardwareDetected */,
+ true /* isPowerbuttonFps */,
+ true /* hasEnrolledTemplates */);
+ assertThat(mController.isAvailable()).isEqualTo(true);
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+ }
+
+ @Test
+ public void isUnavailable_isDisabled_whenSfpsHardwareDetected_AndNoEnrolledFingerprints() {
+ assertThat(mController.isAvailable()).isEqualTo(false);
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
+ configure_hardwareDetected_isSfps_hasEnrolledTemplates(
+ true /* isHardwareDetected */,
+ true /* isPowerbuttonFps */,
+ false /* hasEnrolledTemplates */);
+ assertThat(mController.isAvailable()).isEqualTo(false);
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
+ }
+
+ @Test
+ public void isUnavailable_whenHardwareNotDetected() {
+ assertThat(mController.isAvailable()).isFalse();
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
+ configure_hardwareDetected_isSfps_hasEnrolledTemplates(
+ false /* isHardwareDetected */,
+ true /* isPowerbuttonFps */,
+ true /* hasEnrolledTemplates */);
+ assertThat(mController.isAvailable()).isEqualTo(false);
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
+ }
+
+ @Test
+ public void isUnavailable_onNonSfpsDevice() {
+ assertThat(mController.isAvailable()).isFalse();
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
+ configure_hardwareDetected_isSfps_hasEnrolledTemplates(
+ true /* isHardwareDetected */,
+ false /* isPowerbuttonFps */,
+ true /* hasEnrolledTemplates */);
+ assertThat(mController.isAvailable()).isFalse();
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
+ }
+
+ private void configure_hardwareDetected_isSfps_hasEnrolledTemplates(
+ boolean isHardwareDetected, boolean isPowerbuttonFps, boolean hasEnrolledTemplates) {
+ when(mFingerprintManager.isHardwareDetected()).thenReturn(isHardwareDetected);
+ when(mFingerprintManager.isPowerbuttonFps()).thenReturn(isPowerbuttonFps);
+ when(mFingerprintManager.hasEnrolledTemplates(anyInt())).thenReturn(hasEnrolledTemplates);
+ }
+
+}
diff --git a/tests/robotests/src/com/android/settings/wifi/tether/WifiHotspotSpeedSettingsTest.java b/tests/robotests/src/com/android/settings/wifi/tether/WifiHotspotSpeedSettingsTest.java
index ec8cfe8..969f992 100644
--- a/tests/robotests/src/com/android/settings/wifi/tether/WifiHotspotSpeedSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/tether/WifiHotspotSpeedSettingsTest.java
@@ -25,6 +25,9 @@
import static com.android.settings.wifi.tether.WifiHotspotSpeedSettings.KEY_SPEED_5GHZ;
import static com.android.settings.wifi.tether.WifiHotspotSpeedSettings.KEY_SPEED_6GHZ;
+import static org.mockito.Mockito.anyBoolean;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -80,7 +83,7 @@
WifiFeatureProvider provider = FakeFeatureFactory.setupForTest().getWifiFeatureProvider();
when(provider.getWifiHotspotSpeedViewModel(mViewModelStoreOwner)).thenReturn(mViewModel);
- mSettings = new WifiHotspotSpeedSettings();
+ mSettings = spy(new WifiHotspotSpeedSettings());
mSettings.mWifiHotspotSpeedViewModel = mViewModel;
}
@@ -181,6 +184,24 @@
}
@Test
+ public void onRestartingChanged_restartingTrue_setLoadingTrue() {
+ doNothing().when(mSettings).setLoading(anyBoolean(), anyBoolean());
+
+ mSettings.onRestartingChanged(true);
+
+ verify(mSettings).setLoading(true, false);
+ }
+
+ @Test
+ public void onRestartingChanged_restartingFalse_setLoadingFalse() {
+ doNothing().when(mSettings).setLoading(anyBoolean(), anyBoolean());
+
+ mSettings.onRestartingChanged(false);
+
+ verify(mSettings).setLoading(false, false);
+ }
+
+ @Test
public void onRadioButtonClicked_toSpeed2g_setSpeedType2g() {
when(mRadioButton.getKey()).thenReturn(KEY_SPEED_2GHZ);
diff --git a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSettingsTest.java b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSettingsTest.java
index e264177..0a54c88 100644
--- a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSettingsTest.java
@@ -16,6 +16,9 @@
package com.android.settings.wifi.tether;
+import static android.view.View.INVISIBLE;
+import static android.view.View.VISIBLE;
+
import static com.android.settings.wifi.WifiUtils.setCanShowWifiHotspotCached;
import static com.android.settings.wifi.tether.WifiTetherSettings.KEY_WIFI_HOTSPOT_SECURITY;
import static com.android.settings.wifi.tether.WifiTetherSettings.KEY_WIFI_HOTSPOT_SPEED;
@@ -25,6 +28,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@@ -55,6 +59,7 @@
import com.android.settings.dashboard.RestrictedDashboardFragment;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.shadow.ShadowFragment;
+import com.android.settings.widget.SettingsMainSwitchBar;
import com.android.settings.wifi.factory.WifiFeatureProvider;
import com.android.settings.wifi.repository.WifiHotspotRepository;
@@ -110,6 +115,8 @@
private Preference mWifiHotspotSpeed;
@Mock
private LiveData<Integer> mSpeedSummary;
+ @Mock
+ private SettingsMainSwitchBar mMainSwitchBar;
private WifiTetherSettings mSettings;
@@ -135,6 +142,7 @@
when(mWifiTetherViewModel.getSpeedSummary()).thenReturn(mSpeedSummary);
mSettings = spy(new WifiTetherSettings(mWifiRestriction));
+ mSettings.mMainSwitchBar = mMainSwitchBar;
mSettings.mWifiTetherViewModel = mWifiTetherViewModel;
when(mSettings.findPreference(KEY_WIFI_HOTSPOT_SECURITY)).thenReturn(mWifiHotspotSecurity);
when(mSettings.findPreference(KEY_WIFI_HOTSPOT_SPEED)).thenReturn(mWifiHotspotSpeed);
@@ -308,6 +316,26 @@
verify(mSpeedSummary, never()).observe(any(), any());
}
+ @Test
+ public void onRestartingChanged_restartingTrue_setLoadingTrue() {
+ doNothing().when(mSettings).setLoading(anyBoolean(), anyBoolean());
+
+ mSettings.onRestartingChanged(true);
+
+ verify(mMainSwitchBar).setVisibility(INVISIBLE);
+ verify(mSettings).setLoading(true, false);
+ }
+
+ @Test
+ public void onRestartingChanged_restartingFalse_setLoadingFalse() {
+ doNothing().when(mSettings).setLoading(anyBoolean(), anyBoolean());
+
+ mSettings.onRestartingChanged(false);
+
+ verify(mMainSwitchBar).setVisibility(VISIBLE);
+ verify(mSettings).setLoading(false, false);
+ }
+
private void spyWifiTetherSettings() {
mSettings = spy(new WifiTetherSettings(mWifiRestriction));
final FragmentActivity activity = mock(FragmentActivity.class);
diff --git a/tests/unit/src/com/android/settings/wifi/repository/WifiHotspotRepositoryTest.java b/tests/unit/src/com/android/settings/wifi/repository/WifiHotspotRepositoryTest.java
index 6559c12..7110a1b 100644
--- a/tests/unit/src/com/android/settings/wifi/repository/WifiHotspotRepositoryTest.java
+++ b/tests/unit/src/com/android/settings/wifi/repository/WifiHotspotRepositoryTest.java
@@ -16,12 +16,15 @@
package com.android.settings.wifi.repository;
+import static android.net.TetheringManager.TETHERING_WIFI;
import static android.net.wifi.SoftApConfiguration.BAND_2GHZ;
import static android.net.wifi.SoftApConfiguration.SECURITY_TYPE_OPEN;
import static android.net.wifi.SoftApConfiguration.SECURITY_TYPE_WPA2_PSK;
import static android.net.wifi.SoftApConfiguration.SECURITY_TYPE_WPA3_SAE;
import static android.net.wifi.SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION;
import static android.net.wifi.WifiAvailableChannel.OP_MODE_SAP;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
import static com.android.settings.wifi.repository.WifiHotspotRepository.BAND_2GHZ_5GHZ;
import static com.android.settings.wifi.repository.WifiHotspotRepository.BAND_2GHZ_5GHZ_6GHZ;
@@ -42,12 +45,17 @@
import static org.mockito.Mockito.when;
import android.content.Context;
+import android.net.TetheringManager;
import android.net.wifi.SoftApConfiguration;
import android.net.wifi.WifiAvailableChannel;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiScanner;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
import android.util.SparseIntArray;
+import androidx.annotation.NonNull;
import androidx.lifecycle.MutableLiveData;
import androidx.test.annotation.UiThreadTest;
import androidx.test.core.app.ApplicationProvider;
@@ -81,30 +89,33 @@
@Rule
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@Spy
- Context mContext = ApplicationProvider.getApplicationContext();
+ private Context mContext = ApplicationProvider.getApplicationContext();
@Mock
- WifiManager mWifiManager;
+ private WifiManager mWifiManager;
@Mock
- MutableLiveData<Integer> mSecurityType;
+ private TetheringManager mTetheringManager;
@Mock
- MutableLiveData<Integer> mSpeedType;
+ private MutableLiveData<Integer> mSecurityType;
+ @Mock
+ private MutableLiveData<Integer> mSpeedType;
- WifiHotspotRepository mWifiHotspotRepository;
- SoftApConfiguration mSoftApConfiguration;
- ArgumentCaptor<SoftApConfiguration> mSoftApConfigCaptor =
+ private WifiHotspotRepository mRepository;
+ private SoftApConfiguration mSoftApConfiguration = new SoftApConfiguration.Builder().build();
+ private ArgumentCaptor<SoftApConfiguration> mSoftApConfigCaptor =
ArgumentCaptor.forClass(SoftApConfiguration.class);
@Before
public void setUp() {
+ doReturn(new TestHandler()).when(mContext).getMainThreadHandler();
doReturn(SPEED_6GHZ).when(mSpeedType).getValue();
- mWifiHotspotRepository = new WifiHotspotRepository(mContext, mWifiManager);
- mWifiHotspotRepository.mSecurityType = mSecurityType;
- mWifiHotspotRepository.mSpeedType = mSpeedType;
- mWifiHotspotRepository.mCurrentCountryCode = WIFI_CURRENT_COUNTRY_CODE;
- mWifiHotspotRepository.mIsDualBand = true;
- mWifiHotspotRepository.mIs5gAvailable = true;
- mWifiHotspotRepository.mIs6gAvailable = true;
+ mRepository = new WifiHotspotRepository(mContext, mWifiManager, mTetheringManager);
+ mRepository.mSecurityType = mSecurityType;
+ mRepository.mSpeedType = mSpeedType;
+ mRepository.mCurrentCountryCode = WIFI_CURRENT_COUNTRY_CODE;
+ mRepository.mIsDualBand = true;
+ mRepository.mIs5gAvailable = true;
+ mRepository.mIs6gAvailable = true;
}
@Test
@@ -115,7 +126,7 @@
.build();
when(mWifiManager.getSoftApConfiguration()).thenReturn(mSoftApConfiguration);
- mWifiHotspotRepository.queryLastPasswordIfNeeded();
+ mRepository.queryLastPasswordIfNeeded();
verify(mWifiManager).queryLastConfiguredTetheredApPassphraseSinceBoot(any(), any());
}
@@ -128,7 +139,7 @@
.build();
when(mWifiManager.getSoftApConfiguration()).thenReturn(mSoftApConfiguration);
- mWifiHotspotRepository.queryLastPasswordIfNeeded();
+ mRepository.queryLastPasswordIfNeeded();
verify(mWifiManager, never())
.queryLastConfiguredTetheredApPassphraseSinceBoot(any(), any());
@@ -136,46 +147,74 @@
@Test
public void generatePassword_haveLastPassword_returnLastPassword() {
- mWifiHotspotRepository.mLastPassword = WIFI_PASSWORD;
+ mRepository.mLastPassword = WIFI_PASSWORD;
- assertThat(mWifiHotspotRepository.generatePassword()).isEqualTo(WIFI_PASSWORD);
+ assertThat(mRepository.generatePassword()).isEqualTo(WIFI_PASSWORD);
}
@Test
public void generatePassword_noLastPassword_returnRandomPassword() {
- mWifiHotspotRepository.mLastPassword = "";
+ mRepository.mLastPassword = "";
- String password = mWifiHotspotRepository.generatePassword();
-
- assertThat(password).isNotEqualTo(WIFI_PASSWORD);
- assertThat(password.length()).isNotEqualTo(0);
+ assertThat(mRepository.generatePassword().length()).isNotEqualTo(0);
}
@Test
- public void setSoftApConfiguration_setConfigByWifiManager() {
- SoftApConfiguration config = new SoftApConfiguration.Builder().build();
+ public void generatePassword_configPasswordIsNotEmpty_returnConfigPassword() {
+ mSoftApConfiguration = new SoftApConfiguration.Builder()
+ .setPassphrase(WIFI_PASSWORD, SECURITY_TYPE_WPA2_PSK)
+ .build();
- mWifiHotspotRepository.setSoftApConfiguration(config);
+ assertThat(mRepository.generatePassword(mSoftApConfiguration)).isEqualTo(WIFI_PASSWORD);
+ }
- verify(mWifiManager).setSoftApConfiguration(config);
+ @Test
+ public void generatePassword_configPasswordIsEmpty_returnConfigPassword() {
+ mSoftApConfiguration = new SoftApConfiguration.Builder().build();
+ mRepository.mLastPassword = WIFI_PASSWORD;
+
+ assertThat(mRepository.generatePassword(mSoftApConfiguration)).isEqualTo(WIFI_PASSWORD);
+ }
+
+ @Test
+ public void getSoftApConfiguration_getConfigFromWifiManager() {
+ mRepository.getSoftApConfiguration();
+
+ verify(mWifiManager).getSoftApConfiguration();
+ }
+
+ @Test
+ public void setSoftApConfiguration_setConfigToWifiManager() {
+ mRepository.setSoftApConfiguration(mSoftApConfiguration);
+
+ verify(mWifiManager).setSoftApConfiguration(mSoftApConfiguration);
+ }
+
+ @Test
+ public void setSoftApConfiguration_isRestarting_doNotSetConfig() {
+ mRepository.mIsRestarting = true;
+
+ mRepository.setSoftApConfiguration(mSoftApConfiguration);
+
+ verify(mWifiManager, never()).setSoftApConfiguration(mSoftApConfiguration);
}
@Test
public void refresh_liveDataNotUsed_doNothing() {
// If LiveData is not used then it's null.
- mWifiHotspotRepository.mSecurityType = null;
- mWifiHotspotRepository.mSpeedType = null;
+ mRepository.mSecurityType = null;
+ mRepository.mSpeedType = null;
- mWifiHotspotRepository.refresh();
+ mRepository.refresh();
verify(mWifiManager, never()).getSoftApConfiguration();
}
@Test
public void refresh_liveDataIsUsed_getConfigAndUpdateLiveData() {
- mWifiHotspotRepository.getSpeedType();
+ mRepository.getSpeedType();
- mWifiHotspotRepository.refresh();
+ mRepository.refresh();
verify(mWifiManager, atLeast(1)).getSoftApConfiguration();
verify(mSpeedType).setValue(anyInt());
@@ -183,18 +222,18 @@
@Test
public void setAutoRefresh_setEnabled_registerCallback() {
- mWifiHotspotRepository.mActiveCountryCodeChangedCallback = null;
+ mRepository.mActiveCountryCodeChangedCallback = null;
- mWifiHotspotRepository.setAutoRefresh(true);
+ mRepository.setAutoRefresh(true);
verify(mWifiManager).registerActiveCountryCodeChangedCallback(any(), any());
}
@Test
public void setAutoRefresh_setDisabled_registerCallback() {
- mWifiHotspotRepository.setAutoRefresh(true);
+ mRepository.setAutoRefresh(true);
- mWifiHotspotRepository.setAutoRefresh(false);
+ mRepository.setAutoRefresh(false);
verify(mWifiManager).unregisterActiveCountryCodeChangedCallback(any());
}
@@ -203,17 +242,17 @@
@UiThreadTest
public void getSecurityType_shouldNotReturnNull() {
// If LiveData is not used then it's null.
- mWifiHotspotRepository.mSecurityType = null;
+ mRepository.mSecurityType = null;
mockConfigSecurityType(SECURITY_TYPE_OPEN);
- assertThat(mWifiHotspotRepository.getSecurityType()).isNotNull();
+ assertThat(mRepository.getSecurityType()).isNotNull();
}
@Test
public void updateSecurityType_securityTypeOpen_setValueCorrectly() {
mockConfigSecurityType(SECURITY_TYPE_OPEN);
- mWifiHotspotRepository.updateSecurityType();
+ mRepository.updateSecurityType();
verify(mSecurityType).setValue(SECURITY_TYPE_OPEN);
}
@@ -222,7 +261,7 @@
public void updateSecurityType_securityTypeWpa2_setValueCorrectly() {
mockConfigSecurityType(SECURITY_TYPE_WPA2_PSK);
- mWifiHotspotRepository.updateSecurityType();
+ mRepository.updateSecurityType();
verify(mSecurityType).setValue(SECURITY_TYPE_WPA2_PSK);
}
@@ -231,7 +270,7 @@
public void updateSecurityType_securityTypeWpa2Wpa3_setValueCorrectly() {
mockConfigSecurityType(SECURITY_TYPE_WPA3_SAE_TRANSITION);
- mWifiHotspotRepository.updateSecurityType();
+ mRepository.updateSecurityType();
verify(mSecurityType).setValue(SECURITY_TYPE_WPA3_SAE_TRANSITION);
}
@@ -240,7 +279,7 @@
public void updateSecurityType_securityTypeWpa3_setValueCorrectly() {
mockConfigSecurityType(SECURITY_TYPE_WPA3_SAE);
- mWifiHotspotRepository.updateSecurityType();
+ mRepository.updateSecurityType();
verify(mSecurityType).setValue(SECURITY_TYPE_WPA3_SAE);
}
@@ -249,7 +288,7 @@
public void setSecurityType_sameValue_doNotSetConfig() {
mockConfigSecurityType(SECURITY_TYPE_WPA3_SAE);
- mWifiHotspotRepository.setSecurityType(SECURITY_TYPE_WPA3_SAE);
+ mRepository.setSecurityType(SECURITY_TYPE_WPA3_SAE);
verify(mWifiManager, never()).setSoftApConfiguration(any());
}
@@ -258,7 +297,7 @@
public void setSecurityType_wpa3ToWpa2Wpa3_setConfigCorrectly() {
mockConfigSecurityType(SECURITY_TYPE_WPA3_SAE);
- mWifiHotspotRepository.setSecurityType(SECURITY_TYPE_WPA3_SAE_TRANSITION);
+ mRepository.setSecurityType(SECURITY_TYPE_WPA3_SAE_TRANSITION);
verify(mWifiManager).setSoftApConfiguration(mSoftApConfigCaptor.capture());
assertThat(mSoftApConfigCaptor.getValue().getSecurityType())
@@ -269,7 +308,7 @@
public void setSecurityType_Wpa2Wpa3ToWpa2_setConfigCorrectly() {
mockConfigSecurityType(SECURITY_TYPE_WPA3_SAE_TRANSITION);
- mWifiHotspotRepository.setSecurityType(SECURITY_TYPE_WPA2_PSK);
+ mRepository.setSecurityType(SECURITY_TYPE_WPA2_PSK);
verify(mWifiManager).setSoftApConfiguration(mSoftApConfigCaptor.capture());
assertThat(mSoftApConfigCaptor.getValue().getSecurityType())
@@ -280,7 +319,7 @@
public void setSecurityType_Wpa2ToOpen_setConfigCorrectly() {
mockConfigSecurityType(SECURITY_TYPE_WPA2_PSK);
- mWifiHotspotRepository.setSecurityType(SECURITY_TYPE_OPEN);
+ mRepository.setSecurityType(SECURITY_TYPE_OPEN);
verify(mWifiManager).setSoftApConfiguration(mSoftApConfigCaptor.capture());
assertThat(mSoftApConfigCaptor.getValue().getSecurityType())
@@ -291,7 +330,7 @@
public void setSecurityType_OpenToWpa3_setConfigCorrectly() {
mockConfigSecurityType(SECURITY_TYPE_OPEN);
- mWifiHotspotRepository.setSecurityType(SECURITY_TYPE_WPA3_SAE);
+ mRepository.setSecurityType(SECURITY_TYPE_WPA3_SAE);
verify(mWifiManager).setSoftApConfiguration(mSoftApConfigCaptor.capture());
assertThat(mSoftApConfigCaptor.getValue().getSecurityType())
@@ -302,109 +341,109 @@
@UiThreadTest
public void getSpeedType_shouldNotReturnNull() {
// If LiveData is not used then it's null.
- mWifiHotspotRepository.mSpeedType = null;
+ mRepository.mSpeedType = null;
SoftApConfiguration config = new SoftApConfiguration.Builder().setBand(BAND_2GHZ).build();
when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
- assertThat(mWifiHotspotRepository.getSpeedType()).isNotNull();
+ assertThat(mRepository.getSpeedType()).isNotNull();
}
@Test
public void updateSpeedType_singleBand2g_get2gSpeedType() {
- mWifiHotspotRepository.mIsDualBand = false;
+ mRepository.mIsDualBand = false;
SoftApConfiguration config = new SoftApConfiguration.Builder().setBand(BAND_2GHZ).build();
when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
- mWifiHotspotRepository.updateSpeedType();
+ mRepository.updateSpeedType();
verify(mSpeedType).setValue(SPEED_2GHZ);
}
@Test
public void updateSpeedType_singleBand5gPreferred_get5gSpeedType() {
- mWifiHotspotRepository.mIsDualBand = false;
+ mRepository.mIsDualBand = false;
SoftApConfiguration config = new SoftApConfiguration.Builder()
.setBand(WIFI_5GHZ_BAND_PREFERRED).build();
when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
- mWifiHotspotRepository.updateSpeedType();
+ mRepository.updateSpeedType();
verify(mSpeedType).setValue(SPEED_5GHZ);
}
@Test
public void updateSpeedType_singleBand5gPreferredBut5gUnavailable_get2gSpeedType() {
- mWifiHotspotRepository.mIsDualBand = false;
- mWifiHotspotRepository.mIs5gAvailable = false;
+ mRepository.mIsDualBand = false;
+ mRepository.mIs5gAvailable = false;
SoftApConfiguration config = new SoftApConfiguration.Builder()
.setBand(WIFI_5GHZ_BAND_PREFERRED).build();
when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
- mWifiHotspotRepository.updateSpeedType();
+ mRepository.updateSpeedType();
verify(mSpeedType).setValue(SPEED_2GHZ);
}
@Test
public void updateSpeedType_singleBand6gPreferred_get6gSpeedType() {
- mWifiHotspotRepository.mIsDualBand = false;
+ mRepository.mIsDualBand = false;
SoftApConfiguration config = new SoftApConfiguration.Builder()
.setBand(WIFI_6GHZ_BAND_PREFERRED).build();
when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
- mWifiHotspotRepository.updateSpeedType();
+ mRepository.updateSpeedType();
verify(mSpeedType).setValue(SPEED_6GHZ);
}
@Test
public void updateSpeedType_singleBand6gPreferredBut6gUnavailable_get5gSpeedType() {
- mWifiHotspotRepository.mIsDualBand = false;
- mWifiHotspotRepository.mIs6gAvailable = false;
+ mRepository.mIsDualBand = false;
+ mRepository.mIs6gAvailable = false;
SoftApConfiguration config = new SoftApConfiguration.Builder()
.setBand(WIFI_6GHZ_BAND_PREFERRED).build();
when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
- mWifiHotspotRepository.updateSpeedType();
+ mRepository.updateSpeedType();
verify(mSpeedType).setValue(SPEED_5GHZ);
}
@Test
public void updateSpeedType_singleBand6gPreferredBut5gAnd6gUnavailable_get2gSpeedType() {
- mWifiHotspotRepository.mIsDualBand = false;
- mWifiHotspotRepository.mIs5gAvailable = false;
- mWifiHotspotRepository.mIs6gAvailable = false;
+ mRepository.mIsDualBand = false;
+ mRepository.mIs5gAvailable = false;
+ mRepository.mIs6gAvailable = false;
SoftApConfiguration config = new SoftApConfiguration.Builder()
.setBand(WIFI_6GHZ_BAND_PREFERRED).build();
when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
- mWifiHotspotRepository.updateSpeedType();
+ mRepository.updateSpeedType();
verify(mSpeedType).setValue(SPEED_2GHZ);
}
@Test
public void updateSpeedType_dualBand2gAnd5g_get2gAnd5gSpeedType() {
- mWifiHotspotRepository.mIsDualBand = true;
+ mRepository.mIsDualBand = true;
SoftApConfiguration config = new SoftApConfiguration.Builder()
.setBand(WIFI_5GHZ_BAND_PREFERRED).build();
when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
- mWifiHotspotRepository.updateSpeedType();
+ mRepository.updateSpeedType();
verify(mSpeedType).setValue(SPEED_2GHZ_5GHZ);
}
@Test
public void updateSpeedType_dualBand2gAnd5gBut5gUnavailable_get2gSpeedType() {
- mWifiHotspotRepository.mIsDualBand = true;
- mWifiHotspotRepository.mIs5gAvailable = false;
+ mRepository.mIsDualBand = true;
+ mRepository.mIs5gAvailable = false;
SoftApConfiguration config = new SoftApConfiguration.Builder()
.setBand(WIFI_5GHZ_BAND_PREFERRED).build();
when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
- mWifiHotspotRepository.updateSpeedType();
+ mRepository.updateSpeedType();
verify(mSpeedType).setValue(SPEED_2GHZ);
}
@@ -413,7 +452,7 @@
public void setSpeedType_sameValue_doNotSetConfig() {
doReturn(SPEED_6GHZ).when(mSpeedType).getValue();
- mWifiHotspotRepository.setSpeedType(SPEED_6GHZ);
+ mRepository.setSpeedType(SPEED_6GHZ);
verify(mWifiManager, never()).setSoftApConfiguration(any());
}
@@ -422,7 +461,7 @@
public void setSpeedType_2g5ghzTo6ghz_setConfigBandTo6ghzPreferred() {
mockConfigSpeedType(SPEED_2GHZ_5GHZ);
- mWifiHotspotRepository.setSpeedType(SPEED_6GHZ);
+ mRepository.setSpeedType(SPEED_6GHZ);
verify(mWifiManager).setSoftApConfiguration(mSoftApConfigCaptor.capture());
assertThat(mSoftApConfigCaptor.getValue().getBand()).isEqualTo(BAND_2GHZ_5GHZ_6GHZ);
@@ -432,7 +471,7 @@
public void setSpeedType_2g5ghzTo6ghz_setConfigSecurityToWpa3() {
mockConfig(SPEED_2GHZ_5GHZ, SECURITY_TYPE_WPA3_SAE_TRANSITION);
- mWifiHotspotRepository.setSpeedType(SPEED_6GHZ);
+ mRepository.setSpeedType(SPEED_6GHZ);
verify(mWifiManager).setSoftApConfiguration(mSoftApConfigCaptor.capture());
assertThat(mSoftApConfigCaptor.getValue().getSecurityType())
@@ -442,9 +481,9 @@
@Test
public void setSpeedType_6ghzTo2g5ghz_setConfigBandsTo2g5ghz() {
mockConfigSpeedType(SPEED_6GHZ);
- mWifiHotspotRepository.mIsDualBand = true;
+ mRepository.mIsDualBand = true;
- mWifiHotspotRepository.setSpeedType(SPEED_2GHZ_5GHZ);
+ mRepository.setSpeedType(SPEED_2GHZ_5GHZ);
verify(mWifiManager).setSoftApConfiguration(mSoftApConfigCaptor.capture());
SparseIntArray channels = mSoftApConfigCaptor.getValue().getChannels();
@@ -456,7 +495,7 @@
public void setSpeedType_2ghzTo5ghz_setConfigBandTo5ghzPreferred() {
mockConfigSpeedType(SPEED_2GHZ);
- mWifiHotspotRepository.setSpeedType(SPEED_5GHZ);
+ mRepository.setSpeedType(SPEED_5GHZ);
verify(mWifiManager).setSoftApConfiguration(mSoftApConfigCaptor.capture());
assertThat(mSoftApConfigCaptor.getValue().getBand()).isEqualTo(WIFI_5GHZ_BAND_PREFERRED);
@@ -466,7 +505,7 @@
public void setSpeedType_5ghzTo6ghz_setConfigBandTo6ghzPreferred() {
mockConfigSpeedType(SPEED_5GHZ);
- mWifiHotspotRepository.setSpeedType(SPEED_6GHZ);
+ mRepository.setSpeedType(SPEED_6GHZ);
verify(mWifiManager).setSoftApConfiguration(mSoftApConfigCaptor.capture());
assertThat(mSoftApConfigCaptor.getValue().getBand()).isEqualTo(WIFI_6GHZ_BAND_PREFERRED);
@@ -476,7 +515,7 @@
public void setSpeedType_6ghzTo2ghz_setConfigBandTo2ghz() {
mockConfigSpeedType(SPEED_6GHZ);
- mWifiHotspotRepository.setSpeedType(SPEED_2GHZ);
+ mRepository.setSpeedType(SPEED_2GHZ);
verify(mWifiManager).setSoftApConfiguration(mSoftApConfigCaptor.capture());
assertThat(mSoftApConfigCaptor.getValue().getBand()).isEqualTo(BAND_2GHZ);
@@ -485,171 +524,227 @@
@Test
public void isDualBand_resultSameAsWifiManager() {
// Reset mIsDualBand to trigger an update
- mWifiHotspotRepository.mIsDualBand = null;
+ mRepository.mIsDualBand = null;
when(mWifiManager.isBridgedApConcurrencySupported()).thenReturn(true);
- assertThat(mWifiHotspotRepository.isDualBand()).isTrue();
+ assertThat(mRepository.isDualBand()).isTrue();
// Reset mIsDualBand to trigger an update
- mWifiHotspotRepository.mIsDualBand = null;
+ mRepository.mIsDualBand = null;
when(mWifiManager.isBridgedApConcurrencySupported()).thenReturn(false);
- assertThat(mWifiHotspotRepository.isDualBand()).isFalse();
+ assertThat(mRepository.isDualBand()).isFalse();
}
@Test
public void is5GHzBandSupported_resultSameAsWifiManager() {
// Reset mIs5gBandSupported to trigger an update
- mWifiHotspotRepository.mIs5gBandSupported = null;
+ mRepository.mIs5gBandSupported = null;
when(mWifiManager.is5GHzBandSupported()).thenReturn(true);
- assertThat(mWifiHotspotRepository.is5GHzBandSupported()).isTrue();
+ assertThat(mRepository.is5GHzBandSupported()).isTrue();
// Reset mIs5gBandSupported to trigger an update
- mWifiHotspotRepository.mIs5gBandSupported = null;
+ mRepository.mIs5gBandSupported = null;
when(mWifiManager.is5GHzBandSupported()).thenReturn(false);
- assertThat(mWifiHotspotRepository.is5GHzBandSupported()).isFalse();
+ assertThat(mRepository.is5GHzBandSupported()).isFalse();
}
@Test
public void is5gAvailable_hasUsableChannels_returnTrue() {
- mWifiHotspotRepository.mIs5gBandSupported = true;
+ mRepository.mIs5gBandSupported = true;
// Reset mIs5gAvailable to trigger an update
- mWifiHotspotRepository.mIs5gAvailable = null;
+ mRepository.mIs5gAvailable = null;
List<WifiAvailableChannel> channels =
Arrays.asList(new WifiAvailableChannel(FREQ_5GHZ, OP_MODE_SAP));
when(mWifiManager.getUsableChannels(WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS, OP_MODE_SAP))
.thenReturn(channels);
- assertThat(mWifiHotspotRepository.is5gAvailable()).isTrue();
+ assertThat(mRepository.is5gAvailable()).isTrue();
}
@Test
public void is5gAvailable_noUsableChannels_returnFalse() {
- mWifiHotspotRepository.mIs5gBandSupported = true;
+ mRepository.mIs5gBandSupported = true;
// Reset mIs5gAvailable to trigger an update
- mWifiHotspotRepository.mIs5gAvailable = null;
+ mRepository.mIs5gAvailable = null;
when(mWifiManager.getUsableChannels(WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS, OP_MODE_SAP))
.thenReturn(null);
- assertThat(mWifiHotspotRepository.is5gAvailable()).isFalse();
+ assertThat(mRepository.is5gAvailable()).isFalse();
}
@Test
@UiThreadTest
public void get5gAvailable_shouldNotReturnNull() {
// Reset m5gAvailable to trigger an update
- mWifiHotspotRepository.m5gAvailable = null;
+ mRepository.m5gAvailable = null;
- assertThat(mWifiHotspotRepository.get5gAvailable()).isNotNull();
+ assertThat(mRepository.get5gAvailable()).isNotNull();
}
@Test
public void is6GHzBandSupported_resultSameAsWifiManager() {
// Reset mIs6gBandSupported to trigger an update
- mWifiHotspotRepository.mIs6gBandSupported = null;
+ mRepository.mIs6gBandSupported = null;
when(mWifiManager.is6GHzBandSupported()).thenReturn(true);
- assertThat(mWifiHotspotRepository.is6GHzBandSupported()).isTrue();
+ assertThat(mRepository.is6GHzBandSupported()).isTrue();
// Reset mIs6gBandSupported to trigger an update
- mWifiHotspotRepository.mIs6gBandSupported = null;
+ mRepository.mIs6gBandSupported = null;
when(mWifiManager.is6GHzBandSupported()).thenReturn(false);
- assertThat(mWifiHotspotRepository.is6GHzBandSupported()).isFalse();
+ assertThat(mRepository.is6GHzBandSupported()).isFalse();
}
@Test
public void is6gAvailable_hasUsableChannels_returnTrue() {
- mWifiHotspotRepository.mIs6gBandSupported = true;
+ mRepository.mIs6gBandSupported = true;
// Reset mIs6gAvailable to trigger an update
- mWifiHotspotRepository.mIs6gAvailable = null;
+ mRepository.mIs6gAvailable = null;
List<WifiAvailableChannel> channels =
Arrays.asList(new WifiAvailableChannel(FREQ_6GHZ, OP_MODE_SAP));
when(mWifiManager.getUsableChannels(WifiScanner.WIFI_BAND_6_GHZ, OP_MODE_SAP))
.thenReturn(channels);
- assertThat(mWifiHotspotRepository.is6gAvailable()).isTrue();
+ assertThat(mRepository.is6gAvailable()).isTrue();
}
@Test
public void is6gAvailable_noUsableChannels_returnFalse() {
- mWifiHotspotRepository.mIs6gBandSupported = true;
+ mRepository.mIs6gBandSupported = true;
// Reset mIs6gAvailable to trigger an update
- mWifiHotspotRepository.mIs6gAvailable = null;
+ mRepository.mIs6gAvailable = null;
when(mWifiManager.getUsableChannels(WifiScanner.WIFI_BAND_6_GHZ, OP_MODE_SAP))
.thenReturn(null);
- assertThat(mWifiHotspotRepository.is6gAvailable()).isFalse();
+ assertThat(mRepository.is6gAvailable()).isFalse();
}
@Test
@UiThreadTest
public void get6gAvailable_shouldNotReturnNull() {
// Reset m6gAvailable to trigger an update
- mWifiHotspotRepository.m6gAvailable = null;
+ mRepository.m6gAvailable = null;
- assertThat(mWifiHotspotRepository.get6gAvailable()).isNotNull();
+ assertThat(mRepository.get6gAvailable()).isNotNull();
}
@Test
public void isSpeedFeatureAvailable_configNotShow_returnFalse() {
- mWifiHotspotRepository.mIsConfigShowSpeed = false;
+ mRepository.mIsConfigShowSpeed = false;
- assertThat(mWifiHotspotRepository.isSpeedFeatureAvailable()).isFalse();
+ assertThat(mRepository.isSpeedFeatureAvailable()).isFalse();
}
@Test
public void isSpeedFeatureAvailable_5gBandNotSupported_returnFalse() {
- mWifiHotspotRepository.mIsConfigShowSpeed = true;
- mWifiHotspotRepository.mIs5gBandSupported = false;
+ mRepository.mIsConfigShowSpeed = true;
+ mRepository.mIs5gBandSupported = false;
- assertThat(mWifiHotspotRepository.isSpeedFeatureAvailable()).isFalse();
+ assertThat(mRepository.isSpeedFeatureAvailable()).isFalse();
}
@Test
public void isSpeedFeatureAvailable_throwExceptionWhenGet5gSapChannel_returnFalse() {
- mWifiHotspotRepository.mIsConfigShowSpeed = true;
- mWifiHotspotRepository.mIs5gBandSupported = true;
+ mRepository.mIsConfigShowSpeed = true;
+ mRepository.mIs5gBandSupported = true;
doThrow(IllegalArgumentException.class).when(mWifiManager)
.getUsableChannels(WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS, OP_MODE_SAP);
- assertThat(mWifiHotspotRepository.isSpeedFeatureAvailable()).isFalse();
+ assertThat(mRepository.isSpeedFeatureAvailable()).isFalse();
doThrow(UnsupportedOperationException.class).when(mWifiManager)
.getUsableChannels(WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS, OP_MODE_SAP);
- assertThat(mWifiHotspotRepository.isSpeedFeatureAvailable()).isFalse();
+ assertThat(mRepository.isSpeedFeatureAvailable()).isFalse();
}
@Test
public void isSpeedFeatureAvailable_throwExceptionWhenGet6gSapChannel_returnFalse() {
- mWifiHotspotRepository.mIsConfigShowSpeed = true;
- mWifiHotspotRepository.mIs5gBandSupported = true;
+ mRepository.mIsConfigShowSpeed = true;
+ mRepository.mIs5gBandSupported = true;
doReturn(Arrays.asList(new WifiAvailableChannel(FREQ_5GHZ, OP_MODE_SAP))).when(mWifiManager)
.getUsableChannels(WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS, OP_MODE_SAP);
doThrow(IllegalArgumentException.class).when(mWifiManager)
.getUsableChannels(WifiScanner.WIFI_BAND_6_GHZ, OP_MODE_SAP);
- assertThat(mWifiHotspotRepository.isSpeedFeatureAvailable()).isFalse();
+ assertThat(mRepository.isSpeedFeatureAvailable()).isFalse();
doThrow(UnsupportedOperationException.class).when(mWifiManager)
.getUsableChannels(WifiScanner.WIFI_BAND_6_GHZ, OP_MODE_SAP);
- assertThat(mWifiHotspotRepository.isSpeedFeatureAvailable()).isFalse();
+ assertThat(mRepository.isSpeedFeatureAvailable()).isFalse();
}
@Test
public void isSpeedFeatureAvailable_conditionsAreReady_returnTrue() {
- mWifiHotspotRepository.mIsConfigShowSpeed = true;
- mWifiHotspotRepository.mIs5gBandSupported = true;
+ mRepository.mIsConfigShowSpeed = true;
+ mRepository.mIs5gBandSupported = true;
doReturn(Arrays.asList(new WifiAvailableChannel(FREQ_5GHZ, OP_MODE_SAP))).when(mWifiManager)
.getUsableChannels(WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS, OP_MODE_SAP);
doReturn(Arrays.asList(new WifiAvailableChannel(FREQ_6GHZ, OP_MODE_SAP))).when(mWifiManager)
.getUsableChannels(WifiScanner.WIFI_BAND_6_GHZ, OP_MODE_SAP);
- assertThat(mWifiHotspotRepository.isSpeedFeatureAvailable()).isTrue();
+ assertThat(mRepository.isSpeedFeatureAvailable()).isTrue();
+ }
+
+ @Test
+ @UiThreadTest
+ public void getRestarting_shouldNotReturnNull() {
+ // Reset mIsRestarting to trigger an update
+ mRepository.mRestarting = null;
+
+ assertThat(mRepository.getRestarting()).isNotNull();
+ }
+
+ @Test
+ public void restartTetheringIfNeeded_stateDisabled_doNotStopTethering() {
+ mRepository.mWifiApState = WIFI_AP_STATE_DISABLED;
+
+ mRepository.restartTetheringIfNeeded();
+
+ verify(mTetheringManager, never()).stopTethering(TETHERING_WIFI);
+ }
+
+ @Test
+ public void restartTetheringIfNeeded_stateEnabled_stopTethering() {
+ mRepository.mWifiApState = WIFI_AP_STATE_ENABLED;
+
+ mRepository.restartTetheringIfNeeded();
+
+ verify(mTetheringManager).stopTethering(TETHERING_WIFI);
+ }
+
+ @Test
+ public void onStateChanged_stateDisabledAndRestartingFalse_doNotStartTethering() {
+ mRepository.mIsRestarting = false;
+
+ mRepository.mSoftApCallback.onStateChanged(WIFI_AP_STATE_DISABLED, 0);
+
+ verify(mTetheringManager, never()).startTethering(TETHERING_WIFI,
+ mContext.getMainExecutor(), mRepository.mStartTetheringCallback);
+ }
+
+ @Test
+ public void onStateChanged_stateDisabledAndRestartingTrue_startTethering() {
+ mRepository.mIsRestarting = true;
+
+ mRepository.mSoftApCallback.onStateChanged(WIFI_AP_STATE_DISABLED, 0);
+
+ verify(mTetheringManager).startTethering(TETHERING_WIFI, mContext.getMainExecutor(),
+ mRepository.mStartTetheringCallback);
+ }
+
+ @Test
+ public void onStateChanged_stateEnabledAndRestartingTrue_setRestartingFalse() {
+ mRepository.mIsRestarting = true;
+
+ mRepository.mSoftApCallback.onStateChanged(WIFI_AP_STATE_ENABLED, 0);
+
+ assertThat(mRepository.mIsRestarting).isFalse();
}
private void mockConfigSecurityType(int securityType) {
@@ -669,12 +764,12 @@
// Speed Type
doReturn(speedType).when(mSpeedType).getValue();
- mWifiHotspotRepository.mIsDualBand = true;
+ mRepository.mIsDualBand = true;
if (speedType == SPEED_2GHZ) {
- mWifiHotspotRepository.mIsDualBand = false;
+ mRepository.mIsDualBand = false;
configBuilder.setBand(BAND_2GHZ);
} else if (speedType == SPEED_5GHZ) {
- mWifiHotspotRepository.mIsDualBand = false;
+ mRepository.mIsDualBand = false;
configBuilder.setBand(BAND_2GHZ_5GHZ);
} else if (speedType == SPEED_2GHZ_5GHZ) {
int[] bands = {BAND_2GHZ, BAND_2GHZ_5GHZ};
@@ -684,4 +779,17 @@
}
when(mWifiManager.getSoftApConfiguration()).thenReturn(configBuilder.build());
}
+
+ private static class TestHandler extends Handler {
+
+ TestHandler() {
+ super(Looper.getMainLooper());
+ }
+
+ @Override
+ public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
+ msg.getCallback().run();
+ return true;
+ }
+ }
}
diff --git a/tests/unit/src/com/android/settings/wifi/tether/WifiHotspotSecuritySettingsTest.java b/tests/unit/src/com/android/settings/wifi/tether/WifiHotspotSecuritySettingsTest.java
index 511240e..9743253 100644
--- a/tests/unit/src/com/android/settings/wifi/tether/WifiHotspotSecuritySettingsTest.java
+++ b/tests/unit/src/com/android/settings/wifi/tether/WifiHotspotSecuritySettingsTest.java
@@ -26,6 +26,8 @@
import static com.android.settings.wifi.tether.WifiHotspotSecurityViewModel.KEY_SECURITY_WPA2_WPA3;
import static com.android.settings.wifi.tether.WifiHotspotSecurityViewModel.KEY_SECURITY_WPA3;
+import static org.mockito.Mockito.anyBoolean;
+import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -144,6 +146,24 @@
}
@Test
+ public void onRestartingChanged_restartingTrue_setLoadingTrue() {
+ doNothing().when(mSettings).setLoading(anyBoolean(), anyBoolean());
+
+ mSettings.onRestartingChanged(true);
+
+ verify(mSettings).setLoading(true, false);
+ }
+
+ @Test
+ public void onRestartingChanged_restartingFalse_setLoadingFalse() {
+ doNothing().when(mSettings).setLoading(anyBoolean(), anyBoolean());
+
+ mSettings.onRestartingChanged(false);
+
+ verify(mSettings).setLoading(false, false);
+ }
+
+ @Test
public void onRadioButtonClicked_clickedWpa3_setSecurityTypeCorrectly() {
mSettings.onRadioButtonClicked(mRadioButtonWpa3);
diff --git a/tests/unit/src/com/android/settings/wifi/tether/WifiHotspotSecurityViewModelTest.java b/tests/unit/src/com/android/settings/wifi/tether/WifiHotspotSecurityViewModelTest.java
index db768c7..401678c 100644
--- a/tests/unit/src/com/android/settings/wifi/tether/WifiHotspotSecurityViewModelTest.java
+++ b/tests/unit/src/com/android/settings/wifi/tether/WifiHotspotSecurityViewModelTest.java
@@ -65,6 +65,8 @@
MutableLiveData<Integer> mSecurityType;
@Mock
MutableLiveData<Integer> mSpeedType;
+ @Mock
+ private MutableLiveData<Boolean> mRestarting;
WifiHotspotSecurityViewModel mViewModel;
@@ -75,6 +77,7 @@
.thenReturn(mWifiHotspotRepository);
when(mWifiHotspotRepository.getSecurityType()).thenReturn(mSecurityType);
when(mWifiHotspotRepository.getSpeedType()).thenReturn(mSpeedType);
+ when(mWifiHotspotRepository.getRestarting()).thenReturn(mRestarting);
mViewModel = new WifiHotspotSecurityViewModel((Application) mContext);
}
@@ -185,6 +188,11 @@
assertThat(mViewModel.getViewItemListData()).isNotNull();
}
+ @Test
+ public void getRestarting_shouldNotReturnNull() {
+ assertThat(mViewModel.getRestarting()).isNotNull();
+ }
+
private void assertItemChecked(boolean checkedWpa3, boolean checkedWpa2Wpa3,
boolean checkedWpa2, boolean checkedNone) {
assertThat(mViewModel.mViewItemMap.get(SECURITY_TYPE_WPA3_SAE).mIsChecked)
diff --git a/tests/unit/src/com/android/settings/wifi/tether/WifiHotspotSpeedViewModelTest.java b/tests/unit/src/com/android/settings/wifi/tether/WifiHotspotSpeedViewModelTest.java
index 7308161..3a1a927 100644
--- a/tests/unit/src/com/android/settings/wifi/tether/WifiHotspotSpeedViewModelTest.java
+++ b/tests/unit/src/com/android/settings/wifi/tether/WifiHotspotSpeedViewModelTest.java
@@ -64,6 +64,8 @@
MutableLiveData<Boolean> m6gAvailable;
@Mock
MutableLiveData<Map<Integer, WifiHotspotSpeedViewModel.SpeedInfo>> mSpeedInfoMapData;
+ @Mock
+ private MutableLiveData<Boolean> mRestarting;
WifiHotspotSpeedViewModel mViewModel;
@@ -77,6 +79,7 @@
when(mWifiHotspotRepository.get5gAvailable()).thenReturn(m5gAvailable);
when(mWifiHotspotRepository.is6GHzBandSupported()).thenReturn(true);
when(mWifiHotspotRepository.get6gAvailable()).thenReturn(m6gAvailable);
+ when(mWifiHotspotRepository.getRestarting()).thenReturn(mRestarting);
mViewModel = new WifiHotspotSpeedViewModel((Application) mContext);
mViewModel.mSpeedInfoMapData = mSpeedInfoMapData;
@@ -284,4 +287,9 @@
assertThat(mViewModel.getSpeedInfoMapData()).isNotNull();
}
+
+ @Test
+ public void getRestarting_shouldNotReturnNull() {
+ assertThat(mViewModel.getRestarting()).isNotNull();
+ }
}
diff --git a/tests/unit/src/com/android/settings/wifi/tether/WifiTetherViewModelTest.java b/tests/unit/src/com/android/settings/wifi/tether/WifiTetherViewModelTest.java
index 36da390..af1f62b 100644
--- a/tests/unit/src/com/android/settings/wifi/tether/WifiTetherViewModelTest.java
+++ b/tests/unit/src/com/android/settings/wifi/tether/WifiTetherViewModelTest.java
@@ -55,6 +55,8 @@
MutableLiveData<Integer> mSecurityType;
@Mock
MutableLiveData<Integer> mSpeedType;
+ @Mock
+ private MutableLiveData<Boolean> mRestarting;
WifiTetherViewModel mViewModel;
@@ -67,6 +69,7 @@
.thenReturn(mWifiHotspotRepository);
when(mWifiHotspotRepository.getSecurityType()).thenReturn(mSecurityType);
when(mWifiHotspotRepository.getSpeedType()).thenReturn(mSpeedType);
+ when(mWifiHotspotRepository.getRestarting()).thenReturn(mRestarting);
mViewModel = new WifiTetherViewModel(mApplication);
}
@@ -83,6 +86,13 @@
}
@Test
+ public void getSoftApConfiguration_getConfigFromRepository() {
+ mViewModel.getSoftApConfiguration();
+
+ verify(mWifiHotspotRepository).getSoftApConfiguration();
+ }
+
+ @Test
public void setSoftApConfiguration_setConfigByRepository() {
SoftApConfiguration config = new SoftApConfiguration.Builder().build();
@@ -126,4 +136,9 @@
verify(mWifiHotspotRepository).isSpeedFeatureAvailable();
}
+
+ @Test
+ public void getRestarting_shouldNotReturnNull() {
+ assertThat(mViewModel.getRestarting()).isNotNull();
+ }
}