Merge "Fix settings crashed" into udc-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 100a071..6aad2af 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -2955,13 +2955,6 @@
</intent-filter>
</activity>
- <activity android:name=".bluetooth.RequestPermissionHelperActivity"
- android:label="@string/bluetooth_pairing_request"
- android:excludeFromRecents="true"
- android:permission="android.permission.BLUETOOTH_CONNECT"
- android:theme="@*android:style/Theme.DeviceDefault.Dialog.Alert.DayNight">
- </activity>
-
<service android:name=".bluetooth.BluetoothPairingService" />
<receiver android:name=".bluetooth.BluetoothPairingRequest"
diff --git a/res-product/values/strings.xml b/res-product/values/strings.xml
index 2f01c47..2a58f45 100644
--- a/res-product/values/strings.xml
+++ b/res-product/values/strings.xml
@@ -96,6 +96,12 @@
<!-- Introduction detail message shown in face enrollment dialog when asking for parental consent [CHAR LIMIT=NONE]-->
<string name="security_settings_face_enroll_introduction_consent_message_0" product="device">Allow your child to use their face to unlock their device</string>
<!-- Introduction detail message shown in face enrollment dialog when asking for parental consent [CHAR LIMIT=NONE]-->
+ <string name="security_settings_face_enroll_introduction_consent_message_0_class3" product="default">Allow your child to use their face to unlock their phone or verify it\u2019s them. This happens when they sign in to apps, approve a purchase, and more.</string>
+ <!-- Introduction detail message shown in face enrollment dialog when asking for parental consent [CHAR LIMIT=NONE]-->
+ <string name="security_settings_face_enroll_introduction_consent_message_0_class3" product="tablet">Allow your child to use their face to unlock their tablet or verify it\u2019s them. This happens when they sign in to apps, approve a purchase, and more.</string>
+ <!-- Introduction detail message shown in face enrollment dialog when asking for parental consent [CHAR LIMIT=NONE]-->
+ <string name="security_settings_face_enroll_introduction_consent_message_0_class3" product="device">Allow your child to use their face to unlock their device or verify it\u2019s them. This happens when they sign in to apps, approve a purchase, and more.</string>
+ <!-- Introduction detail message shown in face enrollment dialog when asking for parental consent [CHAR LIMIT=NONE]-->
<string name="security_settings_face_enroll_introduction_consent_message" product="default">Using your child\u2019s face to unlock their phone may be less secure than a strong pattern or PIN.</string>
<!-- Introduction detail message shown in face enrollment dialog when asking for parental consent [CHAR LIMIT=NONE]-->
<string name="security_settings_face_enroll_introduction_consent_message" product="tablet">Using your child\u2019s face to unlock their tablet may be less secure than a strong pattern or PIN.</string>
diff --git a/res/drawable/ic_check_24dp.xml b/res/drawable/ic_check_24dp.xml
index 9ac8021..0ed6b32 100644
--- a/res/drawable/ic_check_24dp.xml
+++ b/res/drawable/ic_check_24dp.xml
@@ -18,8 +18,8 @@
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
- android:tint="?androidprv:attr/materialColorPrimaryContainer">
+ android:tint="?androidprv:attr/colorAccent">
<path
android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"
android:fillColor="@android:color/white"/>
-</vector>
\ No newline at end of file
+</vector>
diff --git a/res/layout/modifier_key_picker_dialog.xml b/res/layout/modifier_key_picker_dialog.xml
index 6de3294..fd4d75e 100644
--- a/res/layout/modifier_key_picker_dialog.xml
+++ b/res/layout/modifier_key_picker_dialog.xml
@@ -14,94 +14,102 @@
limitations under the License.
-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
- android:id="@+id/modifier_key_fragment_container"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
+<ScrollView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:id="@+id/modifier_key_fragment_scroll_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
- <LinearLayout android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:divider="?android:dividerHorizontal"
- android:showDividers="end" >
- <TextView
- android:id="@+id/modifier_key_picker_title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="24dip"
- android:layout_marginBottom="8dip"
- android:layout_gravity="center_horizontal"
- android:singleLine="true"
- android:textAppearance="?android:attr/textAppearanceLarge"
- android:textColor="?android:attr/textColorPrimary"
- android:text="@string/modifier_keys_picker_title"/>
+ <LinearLayout
+ android:id="@+id/modifier_key_fragment_container"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
- <TextView
- android:id="@+id/modifier_key_picker_summary"
- android:layout_width="wrap_content"
+ <LinearLayout android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:divider="?android:dividerHorizontal"
+ android:showDividers="end" >
+ <TextView
+ android:id="@+id/modifier_key_picker_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="24dp"
+ android:layout_marginBottom="8dp"
+ android:layout_marginStart="16dp"
+ android:layout_marginEnd="16dp"
+ android:layout_gravity="center_horizontal"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:textColor="?android:attr/textColorPrimary"
+ android:text="@string/modifier_keys_picker_title"/>
+
+ <TextView
+ android:id="@+id/modifier_key_picker_summary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:layout_marginBottom="16dp"
+ android:layout_marginStart="16dp"
+ android:layout_marginEnd="16dp"
+ android:layout_gravity="center_horizontal"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="?android:attr/textColorSecondary"/>
+ </LinearLayout>
+
+ <LinearLayout android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:divider="?android:dividerHorizontal"
+ android:showDividers="end">
+ <ListView
+ android:id="@+id/modifier_key_picker"
+ android:layout_width="wrap_content"
+ android:layout_height="352dp"
+ android:divider="@null"
+ android:dividerHeight="8dp"
+ android:padding="16dp"
+ android:listSelector="@drawable/modifier_key_lisetview_background"
+ />
+ </LinearLayout>
+
+ <RelativeLayout
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="8dip"
- android:layout_marginBottom="16dip"
- android:layout_gravity="center_horizontal"
- android:singleLine="true"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorSecondary"/>
+ android:layout_marginStart="8dp"
+ android:layout_marginEnd="8dp"
+ android:layout_marginTop="6dp"
+ android:layout_marginBottom="6dp">
+
+ <Button
+ android:id="@+id/modifier_key_cancel_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="6dp"
+ android:layout_marginBottom="6dp"
+ android:layout_marginStart="8dp"
+ android:layout_alignParentStart="true"
+ android:paddingVertical="14dp"
+ android:drawablePadding="9dp"
+ style="@style/ModifierKeyButtonCancel"
+ android:textColor="?android:attr/textColorPrimary"
+ android:text="@string/modifier_keys_cancel"/>
+
+ <Button
+ android:id="@+id/modifier_key_done_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="6dp"
+ android:layout_marginBottom="6dp"
+ android:layout_marginEnd="8dp"
+ android:layout_alignParentEnd="true"
+ android:paddingVertical="14dp"
+ android:drawablePadding="9dp"
+ style="@style/ModifierKeyButtonDone"
+ android:textColor="?androidprv:attr/materialColorOnPrimary"
+ android:text="@string/modifier_keys_done"/>
+
+ </RelativeLayout>
</LinearLayout>
-
- <LinearLayout android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:divider="?android:dividerHorizontal"
- android:showDividers="end">
- <ListView
- android:id="@+id/modifier_key_picker"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:divider="@null"
- android:dividerHeight="8dp"
- android:padding="16dip"
- android:listSelector="@drawable/modifier_key_lisetview_background"
- />
- </LinearLayout>
-
- <RelativeLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginStart="8dip"
- android:layout_marginEnd="8dip"
- android:layout_marginTop="6dip"
- android:layout_marginBottom="6dip"
- android:layout_weight="1">
-
- <Button
- android:id="@+id/modifier_key_cancel_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="6dip"
- android:layout_marginBottom="6dip"
- android:layout_marginStart="8dip"
- android:layout_alignParentStart="true"
- android:paddingVertical="14dp"
- android:drawablePadding="9dp"
- style="@style/ModifierKeyButtonCancel"
- android:textColor="?android:attr/textColorPrimary"
- android:text="@string/modifier_keys_cancel"/>
-
- <Button
- android:id="@+id/modifier_key_done_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="6dip"
- android:layout_marginBottom="6dip"
- android:layout_marginEnd="8dip"
- android:layout_alignParentEnd="true"
- android:paddingVertical="14dp"
- android:drawablePadding="9dp"
- style="@style/ModifierKeyButtonDone"
- android:textColor="?androidprv:attr/materialColorOnPrimary"
- android:text="@string/modifier_keys_done"/>
-
- </RelativeLayout>
-</LinearLayout>
\ No newline at end of file
+</ScrollView>
\ No newline at end of file
diff --git a/res/layout/modifier_key_reset_dialog.xml b/res/layout/modifier_key_reset_dialog.xml
index 11712bf..784b608 100644
--- a/res/layout/modifier_key_reset_dialog.xml
+++ b/res/layout/modifier_key_reset_dialog.xml
@@ -26,7 +26,6 @@
android:layout_marginTop="24dip"
android:layout_marginBottom="8dip"
android:layout_gravity="center_horizontal"
- android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="?android:attr/textColorPrimary"
android:text="@string/modifier_keys_reset_title" />
@@ -39,7 +38,6 @@
android:layout_marginBottom="16dip"
android:layout_marginStart="32dip"
android:layout_marginEnd="32dip"
- android:gravity="center"
android:layout_gravity="center_horizontal"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorSecondary"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 505aac0..f31f105 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -2067,6 +2067,10 @@
<string name="wifi_hotspot_speed_summary_unavailable">Not available in your country or region</string>
<!-- The footer message for switch screen resolution [CHAR LIMIT=NONE] -->
<string name="wifi_hotspot_speed_footer">If your preferred frequency isn\u0027t available, your hotspot may use a different one. Hotspot security settings may change if you change the frequency.</string>
+ <!-- Summary for the Wi-Fi hotspot security unavailable [CHAR LIMIT=NONE] -->
+ <string name="wifi_hotspot_security_summary_unavailable">Not available with 6 GHz</string>
+ <!-- The footer message for Wi-Fi hotspot security settings [CHAR LIMIT=NONE] -->
+ <string name="wifi_hotspot_security_footer">Security settings may change if you change the hotspot’s frequency</string>
<!-- Summary text when turning hotspot on -->
<string name="wifi_tether_starting">Turning hotspot on\u2026</string>
@@ -11904,6 +11908,12 @@
<!-- Developer settings: Summary for disabling phantom process monitoring. [CHAR LIMIT=NONE]-->
<string name="disable_phantom_process_monitor_summary">Disable restrictions on the system resource usage of the app child processes</string>
+ <!-- Developer settings: Title for force enabling Notes role. [CHAR LIMIT=50]-->
+ <string name="enable_notes_role_title">Force enable Notes role</string>
+ <!-- Developer settings: Summary for disabling phantom process monitoring. [CHAR LIMIT=NONE]-->
+ <string name="enable_notes_role_summary">Enable note-taking system integrations via the Notes role. If the Notes role is already enabled, does nothing.</string>
+
+
<!-- BT LE Audio Device: Media Broadcast -->
<!-- The title of the Media Broadcast Dialog [CHAR LIMIT=none] -->
<string name="bluetooth_broadcast_dialog_title">Broadcast</string>
diff --git a/res/xml/development_settings.xml b/res/xml/development_settings.xml
index 9e1dbad..e7aac3e 100644
--- a/res/xml/development_settings.xml
+++ b/res/xml/development_settings.xml
@@ -713,6 +713,11 @@
android:title="@string/disable_phantom_process_monitor_title"
android:summary="@string/disable_phantom_process_monitor_summary" />
+ <SwitchPreference
+ android:key="force_enable_notes_role"
+ android:title="@string/enable_notes_role_title"
+ android:summary="@string/enable_notes_role_summary" />
+
</PreferenceCategory>
<PreferenceCategory
diff --git a/res/xml/wifi_hotspot_security.xml b/res/xml/wifi_hotspot_security.xml
new file mode 100644
index 0000000..3993d47
--- /dev/null
+++ b/res/xml/wifi_hotspot_security.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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.
+ -->
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
+ android:title="@string/wifi_security"
+ settings:searchable="false">
+
+ <com.android.settingslib.widget.SelectorWithWidgetPreference
+ android:key="wifi_hotspot_security_wpa3"
+ android:title="@string/wifi_security_sae"/>
+
+ <com.android.settingslib.widget.SelectorWithWidgetPreference
+ android:key="wifi_hotspot_security_wpa2_wpa3"
+ android:title="@string/wifi_security_psk_sae"/>
+
+ <com.android.settingslib.widget.SelectorWithWidgetPreference
+ android:key="wifi_hotspot_security_wpa2"
+ android:title="@string/wifi_security_wpa2"/>
+
+ <com.android.settingslib.widget.SelectorWithWidgetPreference
+ android:key="wifi_hotspot_security_none"
+ android:title="@string/wifi_security_none"/>
+
+ <com.android.settingslib.widget.FooterPreference
+ android:title="@string/wifi_hotspot_security_footer"/>
+
+</PreferenceScreen>
diff --git a/res/xml/wifi_tether_settings.xml b/res/xml/wifi_tether_settings.xml
index 3023a6e..a85d9ea 100644
--- a/res/xml/wifi_tether_settings.xml
+++ b/res/xml/wifi_tether_settings.xml
@@ -32,6 +32,13 @@
android:entries="@array/wifi_tether_security"
android:entryValues="@array/wifi_tether_security_values"/>
+ <Preference
+ android:key="wifi_hotspot_security"
+ android:title="@string/wifi_security"
+ android:summary="@string/summary_placeholder"
+ android:fragment="com.android.settings.wifi.tether.WifiHotspotSecuritySettings"
+ settings:isPreferenceVisible="@bool/config_show_wifi_hotspot_speed"/>
+
<com.android.settings.widget.ValidatedEditTextPreference
android:key="wifi_tether_network_password"
android:persistent="false"
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index 388a510..68b1a48 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -134,6 +134,8 @@
public static final String SETTINGS_PACKAGE_NAME = "com.android.settings";
+ public static final String SYSTEMUI_PACKAGE_NAME = "com.android.systemui";
+
public static final String OS_PKG = "os";
/**
diff --git a/src/com/android/settings/applications/AppStateOverlayBridge.java b/src/com/android/settings/applications/AppStateOverlayBridge.java
index 64a6ea1..2276b19 100644
--- a/src/com/android/settings/applications/AppStateOverlayBridge.java
+++ b/src/com/android/settings/applications/AppStateOverlayBridge.java
@@ -19,6 +19,7 @@
import android.app.AppOpsManager;
import android.content.Context;
+import com.android.settings.Utils;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.ApplicationsState.AppEntry;
import com.android.settingslib.applications.ApplicationsState.AppFilter;
@@ -59,7 +60,7 @@
private static final List<String> DISABLE_PACKAGE_LIST = new ArrayList<>();
static {
- DISABLE_PACKAGE_LIST.add("com.android.systemui");
+ DISABLE_PACKAGE_LIST.add(Utils.SYSTEMUI_PACKAGE_NAME);
}
public OverlayState(PermissionState permissionState) {
diff --git a/src/com/android/settings/applications/RecentAppStatsMixin.java b/src/com/android/settings/applications/RecentAppStatsMixin.java
index 6705b25..4e8f795 100644
--- a/src/com/android/settings/applications/RecentAppStatsMixin.java
+++ b/src/com/android/settings/applications/RecentAppStatsMixin.java
@@ -17,6 +17,7 @@
package com.android.settings.applications;
import static com.android.settings.Utils.SETTINGS_PACKAGE_NAME;
+import static com.android.settings.Utils.SYSTEMUI_PACKAGE_NAME;
import android.app.Application;
import android.app.usage.UsageStats;
@@ -76,7 +77,7 @@
"android",
"com.android.phone",
SETTINGS_PACKAGE_NAME,
- "com.android.systemui",
+ SYSTEMUI_PACKAGE_NAME,
"com.android.providers.calendar",
"com.android.providers.media"
));
diff --git a/src/com/android/settings/applications/specialaccess/pictureinpicture/PictureInPictureSettings.java b/src/com/android/settings/applications/specialaccess/pictureinpicture/PictureInPictureSettings.java
index d794de6..3c90bf3 100644
--- a/src/com/android/settings/applications/specialaccess/pictureinpicture/PictureInPictureSettings.java
+++ b/src/com/android/settings/applications/specialaccess/pictureinpicture/PictureInPictureSettings.java
@@ -38,6 +38,7 @@
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
+import com.android.settings.Utils;
import com.android.settings.applications.AppInfoBase;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.widget.EmptyTextSettings;
@@ -57,7 +58,7 @@
static final List<String> IGNORE_PACKAGE_LIST = new ArrayList<>();
static {
- IGNORE_PACKAGE_LIST.add("com.android.systemui");
+ IGNORE_PACKAGE_LIST.add(Utils.SYSTEMUI_PACKAGE_NAME);
}
/**
diff --git a/src/com/android/settings/applications/specialaccess/turnscreenon/TurnScreenOnSettings.java b/src/com/android/settings/applications/specialaccess/turnscreenon/TurnScreenOnSettings.java
index 014971a..742831e 100644
--- a/src/com/android/settings/applications/specialaccess/turnscreenon/TurnScreenOnSettings.java
+++ b/src/com/android/settings/applications/specialaccess/turnscreenon/TurnScreenOnSettings.java
@@ -37,6 +37,7 @@
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
+import com.android.settings.Utils;
import com.android.settings.applications.AppInfoBase;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.widget.EmptyTextSettings;
@@ -58,7 +59,7 @@
static final List<String> IGNORE_PACKAGE_LIST = new ArrayList<>();
static {
- IGNORE_PACKAGE_LIST.add("com.android.systemui");
+ IGNORE_PACKAGE_LIST.add(Utils.SYSTEMUI_PACKAGE_NAME);
}
/**
diff --git a/src/com/android/settings/biometrics/combination/CombinedBiometricStatusUtils.java b/src/com/android/settings/biometrics/combination/CombinedBiometricStatusUtils.java
index d3e8fa7..8cc6bc4 100644
--- a/src/com/android/settings/biometrics/combination/CombinedBiometricStatusUtils.java
+++ b/src/com/android/settings/biometrics/combination/CombinedBiometricStatusUtils.java
@@ -133,6 +133,19 @@
}
/**
+ * Returns the class name of the Settings page corresponding to combined biometric settings
+ * based on the current user.
+ */
+ public String getSettingsClassNameBasedOnUser() {
+ UserManager userManager = mContext.getSystemService(UserManager.class);
+ if (userManager != null && userManager.isProfile()) {
+ return getProfileSettingsClassName();
+ } else {
+ return getSettingsClassName();
+ }
+ }
+
+ /**
* Returns the class name of the Settings page corresponding to combined biometric settings.
*/
public String getSettingsClassName() {
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
index 3e8c458..efd9753 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
@@ -592,6 +592,10 @@
return data;
}
+ protected boolean isFaceStrong() {
+ return mIsFaceStrong;
+ }
+
private void onFaceStrengthChanged() {
// Set up and show the "less secure" info section if necessary.
if (!mIsFaceStrong && getResources().getBoolean(
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollParentalConsent.java b/src/com/android/settings/biometrics/face/FaceEnrollParentalConsent.java
index a3a745d..aabbf6f 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollParentalConsent.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollParentalConsent.java
@@ -47,13 +47,14 @@
R.string.security_settings_face_enroll_introduction_control_consent_title,
R.string.security_settings_face_enroll_introduction_control_consent_message,
R.string.security_settings_face_enroll_introduction_consent_message_0,
+ R.string.security_settings_face_enroll_introduction_consent_message_0_class3,
R.string.security_settings_face_enroll_introduction_info_consent_less_secure
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setDescriptionText(R.string.security_settings_face_enroll_introduction_consent_message_0);
+ updateDescriptionText();
}
@Override
@@ -144,4 +145,16 @@
public int getMetricsCategory() {
return SettingsEnums.FACE_PARENTAL_CONSENT;
}
+
+ @Override
+ protected void updateDescriptionText() {
+ super.updateDescriptionText();
+ if (isFaceStrong()) {
+ setDescriptionText(getString(
+ R.string.security_settings_face_enroll_introduction_consent_message_0_class3));
+ } else {
+ setDescriptionText(
+ R.string.security_settings_face_enroll_introduction_consent_message_0);
+ }
+ }
}
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollParentalConsent.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollParentalConsent.java
index c33ae17..7f4142d 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollParentalConsent.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollParentalConsent.java
@@ -131,4 +131,12 @@
public int getMetricsCategory() {
return SettingsEnums.FINGERPRINT_PARENTAL_CONSENT;
}
+
+
+ @Override
+ protected void updateDescriptionText() {
+ super.updateDescriptionText();
+ setDescriptionText(
+ R.string.security_settings_fingerprint_enroll_introduction_consent_message);
+ }
}
diff --git a/src/com/android/settings/bluetooth/RequestPermissionActivity.java b/src/com/android/settings/bluetooth/RequestPermissionActivity.java
index 588bc73..620cfb0 100644
--- a/src/com/android/settings/bluetooth/RequestPermissionActivity.java
+++ b/src/com/android/settings/bluetooth/RequestPermissionActivity.java
@@ -42,6 +42,8 @@
import com.android.settings.R;
import com.android.settingslib.bluetooth.BluetoothDiscoverableTimeoutReceiver;
+import kotlin.Unit;
+
import java.time.Duration;
/**
@@ -100,12 +102,15 @@
case BluetoothAdapter.STATE_ON:
case BluetoothAdapter.STATE_TURNING_ON: {
- Intent intent = new Intent(this, RequestPermissionHelperActivity.class);
- intent.putExtra(RequestPermissionHelperActivity.EXTRA_APP_LABEL, mAppLabel);
- intent.setAction(RequestPermissionHelperActivity
- .ACTION_INTERNAL_REQUEST_BT_OFF);
-
- startActivityForResult(intent, 0);
+ RequestPermissionHelper.INSTANCE.requestDisable(this, mAppLabel,
+ () -> {
+ onDisableConfirmed();
+ return Unit.INSTANCE;
+ },
+ () -> {
+ cancelAndFinish();
+ return Unit.INSTANCE;
+ });
} break;
default: {
@@ -126,18 +131,17 @@
* case via the broadcast receiver.
*/
- /*
- * Start the helper activity to:
- * 1) ask the user about enabling bt AND discovery
- * 2) enable BT upon confirmation
- */
- Intent intent = new Intent(this, RequestPermissionHelperActivity.class);
- intent.setAction(RequestPermissionHelperActivity.ACTION_INTERNAL_REQUEST_BT_ON);
- intent.putExtra(RequestPermissionHelperActivity.EXTRA_APP_LABEL, mAppLabel);
- if (mRequest == REQUEST_ENABLE_DISCOVERABLE) {
- intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, mTimeout);
- }
- startActivityForResult(intent, 0);
+ // Start the helper activity to ask the user about enabling bt AND discovery
+ RequestPermissionHelper.INSTANCE.requestEnable(this, mAppLabel,
+ mRequest == REQUEST_ENABLE_DISCOVERABLE ? mTimeout : -1,
+ () -> {
+ onEnableConfirmed();
+ return Unit.INSTANCE;
+ },
+ () -> {
+ cancelAndFinish();
+ return Unit.INSTANCE;
+ });
} break;
case BluetoothAdapter.STATE_ON: {
@@ -202,42 +206,27 @@
mDialog.show();
}
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (resultCode != Activity.RESULT_OK) {
- cancelAndFinish();
- return;
+ private void onEnableConfirmed() {
+ mBluetoothAdapter.enable();
+ if (mBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) {
+ proceedAndFinish();
+ } else {
+ // If BT is not up yet, show "Turning on Bluetooth..."
+ mReceiver = new StateChangeReceiver();
+ registerReceiver(mReceiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
+ createDialog();
}
+ }
- switch (mRequest) {
- case REQUEST_ENABLE:
- case REQUEST_ENABLE_DISCOVERABLE: {
- if (mBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) {
- proceedAndFinish();
- } else {
- // If BT is not up yet, show "Turning on Bluetooth..."
- mReceiver = new StateChangeReceiver();
- registerReceiver(mReceiver, new IntentFilter(
- BluetoothAdapter.ACTION_STATE_CHANGED));
- createDialog();
- }
- } break;
-
- case REQUEST_DISABLE: {
- if (mBluetoothAdapter.getState() == BluetoothAdapter.STATE_OFF) {
- proceedAndFinish();
- } else {
- // If BT is not up yet, show "Turning off Bluetooth..."
- mReceiver = new StateChangeReceiver();
- registerReceiver(mReceiver, new IntentFilter(
- BluetoothAdapter.ACTION_STATE_CHANGED));
- createDialog();
- }
- } break;
-
- default: {
- cancelAndFinish();
- } break;
+ private void onDisableConfirmed() {
+ mBluetoothAdapter.disable();
+ if (mBluetoothAdapter.getState() == BluetoothAdapter.STATE_OFF) {
+ proceedAndFinish();
+ } else {
+ // If BT is not up yet, show "Turning off Bluetooth..."
+ mReceiver = new StateChangeReceiver();
+ registerReceiver(mReceiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
+ createDialog();
}
}
diff --git a/src/com/android/settings/bluetooth/RequestPermissionHelper.kt b/src/com/android/settings/bluetooth/RequestPermissionHelper.kt
new file mode 100644
index 0000000..000a7d1
--- /dev/null
+++ b/src/com/android/settings/bluetooth/RequestPermissionHelper.kt
@@ -0,0 +1,98 @@
+/*
+ * 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.bluetooth
+
+import android.content.Context
+import android.os.UserManager
+import androidx.appcompat.app.AlertDialog
+import com.android.settings.R
+import com.android.settingslib.spaprivileged.framework.common.devicePolicyManager
+import com.android.settingslib.spaprivileged.framework.common.userManager
+
+object RequestPermissionHelper {
+ fun requestEnable(
+ context: Context,
+ appLabel: CharSequence?,
+ timeout: Int,
+ onAllow: () -> Unit,
+ onDeny: () -> Unit,
+ ) {
+ if (context.resources.getBoolean(R.bool.auto_confirm_bluetooth_activation_dialog)) {
+ // Don't even show the dialog if configured this way
+ onAllow()
+ return
+ }
+ AlertDialog.Builder(context).apply {
+ setMessage(context.getEnableMessage(timeout, appLabel))
+ setPositiveButton(R.string.allow) { _, _ ->
+ if (context.isDisallowBluetooth()) onDeny() else onAllow()
+ }
+ setNegativeButton(R.string.deny) { _, _ -> onDeny() }
+ setOnCancelListener { onDeny() }
+ }.show()
+ }
+
+ fun requestDisable(
+ context: Context,
+ appLabel: CharSequence?,
+ onAllow: () -> Unit,
+ onDeny: () -> Unit,
+ ) {
+ if (context.resources.getBoolean(R.bool.auto_confirm_bluetooth_activation_dialog)) {
+ // Don't even show the dialog if configured this way
+ onAllow()
+ return
+ }
+ AlertDialog.Builder(context).apply {
+ setMessage(context.getDisableMessage(appLabel))
+ setPositiveButton(R.string.allow) { _, _ -> onAllow() }
+ setNegativeButton(R.string.deny) { _, _ -> onDeny() }
+ setOnCancelListener { onDeny() }
+ }.show()
+ }
+}
+
+// If Bluetooth is disallowed, don't try to enable it, show policy transparency message instead.
+private fun Context.isDisallowBluetooth() =
+ if (userManager.hasUserRestriction(UserManager.DISALLOW_BLUETOOTH)) {
+ devicePolicyManager.createAdminSupportIntent(UserManager.DISALLOW_BLUETOOTH)
+ ?.let { startActivity(it) }
+ true
+ } else false
+
+private fun Context.getEnableMessage(timeout: Int, name: CharSequence?): String = when {
+ timeout < 0 -> when (name) {
+ null -> getString(R.string.bluetooth_ask_enablement_no_name)
+ else -> getString(R.string.bluetooth_ask_enablement, name)
+ }
+
+ timeout == BluetoothDiscoverableEnabler.DISCOVERABLE_TIMEOUT_NEVER -> when (name) {
+ null -> getString(R.string.bluetooth_ask_enablement_and_lasting_discovery_no_name)
+ else -> getString(R.string.bluetooth_ask_enablement_and_lasting_discovery, name)
+ }
+
+ else -> when (name) {
+ null -> getString(R.string.bluetooth_ask_enablement_and_discovery_no_name, timeout)
+ else -> getString(R.string.bluetooth_ask_enablement_and_discovery, name, timeout)
+ }
+}
+
+private fun Context.getDisableMessage(name: CharSequence?): String =
+ when (name) {
+ null -> getString(R.string.bluetooth_ask_disablement_no_name)
+ else -> getString(R.string.bluetooth_ask_disablement, name)
+ }
diff --git a/src/com/android/settings/bluetooth/RequestPermissionHelperActivity.java b/src/com/android/settings/bluetooth/RequestPermissionHelperActivity.java
deleted file mode 100644
index 99ac928..0000000
--- a/src/com/android/settings/bluetooth/RequestPermissionHelperActivity.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (C) 2009 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.bluetooth;
-
-import android.app.Activity;
-import android.app.admin.DevicePolicyManager;
-import android.bluetooth.BluetoothAdapter;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.UserManager;
-import android.util.Log;
-
-import com.android.internal.app.AlertActivity;
-import com.android.internal.app.AlertController;
-import com.android.settings.R;
-
-/**
- * RequestPermissionHelperActivity asks the user whether to toggle Bluetooth.
- *
- * TODO: This activity isn't needed - this should be folded in RequestPermissionActivity
- */
-public class RequestPermissionHelperActivity extends AlertActivity implements
- DialogInterface.OnClickListener {
- private static final String TAG = "RequestPermissionHelperActivity";
-
- public static final String ACTION_INTERNAL_REQUEST_BT_ON =
- "com.android.settings.bluetooth.ACTION_INTERNAL_REQUEST_BT_ON";
-
- public static final String ACTION_INTERNAL_REQUEST_BT_OFF =
- "com.android.settings.bluetooth.ACTION_INTERNAL_REQUEST_BT_OFF";
-
- public static final String EXTRA_APP_LABEL =
- "com.android.settings.bluetooth.extra.APP_LABEL";
-
- private BluetoothAdapter mBluetoothAdapter;
-
- private CharSequence mAppLabel;
-
- private int mTimeout = -1;
-
- private int mRequest;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setResult(RESULT_CANCELED);
-
- // Note: initializes mBluetoothAdapter and returns true on error
- if (!parseIntent()) {
- finish();
- return;
- }
-
- if (getResources().getBoolean(R.bool.auto_confirm_bluetooth_activation_dialog)) {
- // Don't even show the dialog if configured this way
- onClick(null, BUTTON_POSITIVE);
- dismiss();
- }
-
- createDialog();
- }
-
- void createDialog() {
- final AlertController.AlertParams p = mAlertParams;
-
- switch (mRequest) {
- case RequestPermissionActivity.REQUEST_ENABLE: {
- if (mTimeout < 0) {
- p.mMessage = mAppLabel != null
- ? getString(R.string.bluetooth_ask_enablement, mAppLabel)
- : getString(R.string.bluetooth_ask_enablement_no_name);
- } else if (mTimeout == BluetoothDiscoverableEnabler.DISCOVERABLE_TIMEOUT_NEVER) {
- p.mMessage = mAppLabel != null
- ? getString(
- R.string.bluetooth_ask_enablement_and_lasting_discovery,
- mAppLabel)
- : getString(
- R.string.bluetooth_ask_enablement_and_lasting_discovery_no_name);
- } else {
- p.mMessage = mAppLabel != null
- ? getString(R.string.bluetooth_ask_enablement_and_discovery,
- mAppLabel, mTimeout)
- : getString(R.string.bluetooth_ask_enablement_and_discovery_no_name,
- mTimeout);
- }
- } break;
-
- case RequestPermissionActivity.REQUEST_DISABLE: {
- p.mMessage = mAppLabel != null
- ? getString(R.string.bluetooth_ask_disablement, mAppLabel)
- : getString(R.string.bluetooth_ask_disablement_no_name);
- } break;
- }
-
- p.mPositiveButtonText = getString(R.string.allow);
- p.mPositiveButtonListener = this;
- p.mNegativeButtonText = getString(R.string.deny);
-
- setupAlert();
- }
-
- public void onClick(DialogInterface dialog, int which) {
- switch (mRequest) {
- case RequestPermissionActivity.REQUEST_ENABLE:
- case RequestPermissionActivity.REQUEST_ENABLE_DISCOVERABLE: {
- UserManager userManager = getSystemService(UserManager.class);
- if (userManager.hasUserRestriction(UserManager.DISALLOW_BLUETOOTH)) {
- // If Bluetooth is disallowed, don't try to enable it, show policy transparency
- // message instead.
- DevicePolicyManager dpm = getSystemService(DevicePolicyManager.class);
- Intent intent = dpm.createAdminSupportIntent(UserManager.DISALLOW_BLUETOOTH);
- if (intent != null) {
- startActivity(intent);
- }
- } else {
- mBluetoothAdapter.enable();
- setResult(Activity.RESULT_OK);
- }
- } break;
-
- case RequestPermissionActivity.REQUEST_DISABLE: {
- mBluetoothAdapter.disable();
- setResult(Activity.RESULT_OK);
- } break;
- }
- }
-
- /**
- * Parse the received Intent and initialize mBluetoothAdapter.
- * @return true if an error occurred; false otherwise
- */
- private boolean parseIntent() {
- Intent intent = getIntent();
- if (intent == null) {
- return false;
- }
-
- String action = intent.getAction();
- if (ACTION_INTERNAL_REQUEST_BT_ON.equals(action)) {
- mRequest = RequestPermissionActivity.REQUEST_ENABLE;
- if (intent.hasExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION)) {
- // Value used for display purposes. Not range checking.
- mTimeout = intent.getIntExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,
- BluetoothDiscoverableEnabler.DEFAULT_DISCOVERABLE_TIMEOUT);
- }
- } else if (ACTION_INTERNAL_REQUEST_BT_OFF.equals(action)) {
- mRequest = RequestPermissionActivity.REQUEST_DISABLE;
- } else {
- return false;
- }
-
- mAppLabel = getIntent().getCharSequenceExtra(EXTRA_APP_LABEL);
-
- mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
- if (mBluetoothAdapter == null) {
- Log.e(TAG, "Error: there's a problem starting Bluetooth");
- return false;
- }
-
- return true;
- }
-}
diff --git a/src/com/android/settings/connecteddevice/BluetoothDashboardFragment.java b/src/com/android/settings/connecteddevice/BluetoothDashboardFragment.java
index b30aee4..66f2f1b 100644
--- a/src/com/android/settings/connecteddevice/BluetoothDashboardFragment.java
+++ b/src/com/android/settings/connecteddevice/BluetoothDashboardFragment.java
@@ -25,6 +25,7 @@
import com.android.settings.R;
import com.android.settings.SettingsActivity;
+import com.android.settings.Utils;
import com.android.settings.bluetooth.BluetoothDeviceRenamePreferenceController;
import com.android.settings.bluetooth.BluetoothSwitchPreferenceController;
import com.android.settings.dashboard.DashboardFragment;
@@ -45,8 +46,6 @@
private static final String TAG = "BluetoothDashboardFrag";
private static final String KEY_BLUETOOTH_SCREEN_FOOTER = "bluetooth_screen_footer";
- private static final String SETTINGS_PACKAGE_NAME = "com.android.settings";
- private static final String SYSTEMUI_PACKAGE_NAME = "com.android.systemui";
private static final String SLICE_ACTION = "com.android.settings.SEARCH_RESULT_TRAMPOLINE";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -112,8 +111,8 @@
@VisibleForTesting
boolean isAlwaysDiscoverable(String callingAppPackageName, String action) {
return TextUtils.equals(SLICE_ACTION, action) ? false
- : TextUtils.equals(SETTINGS_PACKAGE_NAME, callingAppPackageName)
- || TextUtils.equals(SYSTEMUI_PACKAGE_NAME, callingAppPackageName);
+ : TextUtils.equals(Utils.SETTINGS_PACKAGE_NAME, callingAppPackageName)
+ || TextUtils.equals(Utils.SYSTEMUI_PACKAGE_NAME, callingAppPackageName);
}
/**
diff --git a/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java b/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java
index 3c6077e..9286b81 100644
--- a/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java
+++ b/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java
@@ -28,6 +28,7 @@
import com.android.settings.R;
import com.android.settings.SettingsActivity;
+import com.android.settings.Utils;
import com.android.settings.core.SettingsUIDeviceConfig;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
@@ -38,7 +39,6 @@
public class ConnectedDeviceDashboardFragment extends DashboardFragment {
private static final String TAG = "ConnectedDeviceFrag";
- private static final String SYSTEMUI_PACKAGE_NAME = "com.android.systemui";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static final String SLICE_ACTION = "com.android.settings.SEARCH_RESULT_TRAMPOLINE";
@@ -92,8 +92,8 @@
@VisibleForTesting
boolean isAlwaysDiscoverable(String callingAppPackageName, String action) {
return TextUtils.equals(SLICE_ACTION, action) ? false
- : TextUtils.equals(SETTINGS_PACKAGE_NAME, callingAppPackageName)
- || TextUtils.equals(SYSTEMUI_PACKAGE_NAME, callingAppPackageName);
+ : TextUtils.equals(Utils.SETTINGS_PACKAGE_NAME, callingAppPackageName)
+ || TextUtils.equals(Utils.SYSTEMUI_PACKAGE_NAME, callingAppPackageName);
}
/**
diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
index acc0e7c..65d3be0 100644
--- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
+++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
@@ -733,6 +733,7 @@
controllers.add(new PhantomProcessPreferenceController(context));
controllers.add(new ContrastPreferenceController(
context, context.getSystemService(UiModeManager.class)));
+ controllers.add(new ForceEnableNotesRolePreferenceController(context));
return controllers;
}
diff --git a/src/com/android/settings/development/ForceEnableNotesRolePreferenceController.java b/src/com/android/settings/development/ForceEnableNotesRolePreferenceController.java
new file mode 100644
index 0000000..7821bec
--- /dev/null
+++ b/src/com/android/settings/development/ForceEnableNotesRolePreferenceController.java
@@ -0,0 +1,103 @@
+/*
+ * 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.
+ */
+/*
+ * 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.development;
+
+import static android.os.UserHandle.USER_CURRENT;
+
+import android.content.Context;
+import android.content.om.IOverlayManager;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+
+import androidx.preference.Preference;
+import androidx.preference.SwitchPreference;
+
+import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.development.DeveloperOptionsPreferenceController;
+
+public class ForceEnableNotesRolePreferenceController
+ extends DeveloperOptionsPreferenceController
+ implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin {
+
+ private static final String NOTES_ROLE_ENABLED_KEY =
+ "force_enable_notes_role";
+
+ private static final String OVERLAY_PACKAGE_NAME =
+ "com.android.role.notes.enabled";
+
+ private final IOverlayManager mOverlayManager;
+
+ public ForceEnableNotesRolePreferenceController(Context context) {
+ super(context);
+ mOverlayManager = IOverlayManager.Stub.asInterface(
+ ServiceManager.getService(Context.OVERLAY_SERVICE));
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return NOTES_ROLE_ENABLED_KEY;
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ setEnabled((boolean) newValue);
+ return true;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ ((SwitchPreference) mPreference).setChecked(isEnabled());
+ }
+
+ @Override
+ protected void onDeveloperOptionsSwitchDisabled() {
+ super.onDeveloperOptionsSwitchDisabled();
+ ((SwitchPreference) mPreference).setChecked(false);
+ setEnabled(false);
+ }
+
+ @VisibleForTesting
+ protected boolean isEnabled() {
+ return mContext.getResources().getBoolean(R.bool.config_enableDefaultNotes);
+ }
+
+ @VisibleForTesting
+ protected void setEnabled(boolean enabled) {
+ try {
+ mOverlayManager.setEnabled(OVERLAY_PACKAGE_NAME, enabled, USER_CURRENT);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+}
diff --git a/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceController.java b/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceController.java
index bf81727..e0e25df 100644
--- a/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceController.java
+++ b/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceController.java
@@ -121,7 +121,7 @@
final PowerManager powerManager = context.getSystemService(PowerManager.class);
final PackageManager packageManager = context.getPackageManager();
final String packageName = context.getString(
- com.android.internal.R.string.config_defaultWellbeingPackage);
+ com.android.internal.R.string.config_systemWellbeing);
try {
uid = packageManager.getApplicationInfo(packageName, /* flags= */ 0).uid;
} catch (PackageManager.NameNotFoundException e) {
diff --git a/src/com/android/settings/display/darkmode/BedtimeSettings.java b/src/com/android/settings/display/darkmode/BedtimeSettings.java
index 28121b2..5b9b4d2 100644
--- a/src/com/android/settings/display/darkmode/BedtimeSettings.java
+++ b/src/com/android/settings/display/darkmode/BedtimeSettings.java
@@ -37,7 +37,7 @@
mContext = context;
mPackageManager = context.getPackageManager();
mWellbeingPackage = mContext.getResources().getString(
- com.android.internal.R.string.config_defaultWellbeingPackage);
+ com.android.internal.R.string.config_systemWellbeing);
}
/**
diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
index ac72ced..496cfab 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
@@ -16,6 +16,8 @@
package com.android.settings.fuelgauge;
+import static com.android.settings.Utils.SYSTEMUI_PACKAGE_NAME;
+
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -35,9 +37,8 @@
private static final String PACKAGE_CALENDAR_PROVIDER = "com.android.providers.calendar";
private static final String PACKAGE_MEDIA_PROVIDER = "com.android.providers.media";
- private static final String PACKAGE_SYSTEMUI = "com.android.systemui";
private static final String[] PACKAGES_SYSTEM = {PACKAGE_MEDIA_PROVIDER,
- PACKAGE_CALENDAR_PROVIDER, PACKAGE_SYSTEMUI};
+ PACKAGE_CALENDAR_PROVIDER, SYSTEMUI_PACKAGE_NAME};
protected PackageManager mPackageManager;
protected Context mContext;
diff --git a/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java b/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java
index e622f4c..8e9d485 100644
--- a/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java
+++ b/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java
@@ -72,7 +72,7 @@
.detect());
tips.add(new BatteryDefenderDetector(batteryInfo, context).detect());
tips.add(new DockDefenderDetector(batteryInfo, context).detect());
- tips.add(new IncompatibleChargerDetector(context, batteryInfo).detect());
+ tips.add(new IncompatibleChargerDetector(context).detect());
Collections.sort(tips);
return tips;
}
diff --git a/src/com/android/settings/fuelgauge/batterytip/detectors/IncompatibleChargerDetector.java b/src/com/android/settings/fuelgauge/batterytip/detectors/IncompatibleChargerDetector.java
index 483e37d..cfd9a2c 100644
--- a/src/com/android/settings/fuelgauge/batterytip/detectors/IncompatibleChargerDetector.java
+++ b/src/com/android/settings/fuelgauge/batterytip/detectors/IncompatibleChargerDetector.java
@@ -18,7 +18,6 @@
import android.content.Context;
import android.util.Log;
-import com.android.settings.fuelgauge.BatteryInfo;
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
import com.android.settings.fuelgauge.batterytip.tips.IncompatibleChargerTip;
import com.android.settingslib.Utils;
@@ -28,25 +27,17 @@
private static final String TAG = "IncompatibleChargerDetector";
private final Context mContext;
- private final BatteryInfo mBatteryInfo;
- public IncompatibleChargerDetector(Context context, BatteryInfo batteryInfo) {
+ public IncompatibleChargerDetector(Context context) {
mContext = context;
- mBatteryInfo = batteryInfo;
}
@Override
public BatteryTip detect() {
- int state = BatteryTip.StateType.INVISIBLE;
- boolean isIncompatibleCharging = false;
-
- // Check incompatible charging state if the device is plugged.
- if (mBatteryInfo.pluggedStatus != 0) {
- isIncompatibleCharging = Utils.containsIncompatibleChargers(mContext, TAG);
- if (isIncompatibleCharging) {
- state = BatteryTip.StateType.NEW;
- }
- }
+ final boolean isIncompatibleCharging =
+ Utils.containsIncompatibleChargers(mContext, TAG);
+ final int state = isIncompatibleCharging
+ ? BatteryTip.StateType.NEW : BatteryTip.StateType.INVISIBLE;
Log.d(TAG, "detect() state= " + state + " isIncompatibleCharging: "
+ isIncompatibleCharging);
return new IncompatibleChargerTip(state);
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
index d192e1a..e9d10f2 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
@@ -296,6 +296,10 @@
});
mHourlyChartView = hourlyChartView;
mHourlyChartView.setOnSelectListener(trapezoidIndex -> {
+ if (mDailyChartIndex == BatteryChartViewModel.SELECTED_INDEX_ALL) {
+ // This will happen when a daily slot and an hour slot are clicked together.
+ return;
+ }
if (mHourlyChartIndex == trapezoidIndex) {
return;
}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownController.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownController.java
index 2121c60..cd1bdef 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownController.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownController.java
@@ -313,11 +313,8 @@
@VisibleForTesting
void removeAndCacheAllUnusedPreferences() {
List<BatteryDiffEntry> entries = getBatteryDiffEntries();
- Set<String> entryKeySet = new ArraySet<>();
- for (BatteryDiffEntry entry : entries) {
- entryKeySet.add(entry.getKey());
- }
-
+ Set<String> entryKeySet = new ArraySet<>(entries.size());
+ entries.forEach(entry -> entryKeySet.add(entry.getKey()));
final int prefsCount = mAppListPreferenceGroup.getPreferenceCount();
for (int index = prefsCount - 1; index >= 0; index--) {
final Preference pref = mAppListPreferenceGroup.getPreference(index);
diff --git a/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java b/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java
index 8818431..24571cd 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java
@@ -725,9 +725,9 @@
@VisibleForTesting
@Nullable
static Map<Long, Map<String, List<AppUsagePeriod>>> buildAppUsagePeriodList(
- final List<AppUsageEvent> allAppUsageEvents, final List<BatteryEvent> batteryEventList,
+ final List<AppUsageEvent> appUsageEvents, final List<BatteryEvent> batteryEventList,
final long startTime, final long endTime) {
- if (allAppUsageEvents.isEmpty()) {
+ if (appUsageEvents.isEmpty()) {
return null;
}
@@ -735,7 +735,7 @@
// use.
final List<AppUsageEvent> deviceEvents = new ArrayList<>();
final ArrayMap<Integer, List<AppUsageEvent>> usageEventsByInstanceId = new ArrayMap<>();
- for (final AppUsageEvent event : allAppUsageEvents) {
+ for (final AppUsageEvent event : appUsageEvents) {
final AppUsageEventType eventType = event.getType();
if (eventType == AppUsageEventType.ACTIVITY_RESUMED
|| eventType == AppUsageEventType.ACTIVITY_STOPPED) {
diff --git a/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtils.java b/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtils.java
index 84a39bb..0435e45 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtils.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtils.java
@@ -110,13 +110,7 @@
// For testing only.
@VisibleForTesting
- static Supplier<Cursor> sFakeBatteryStateSupplier;
- @VisibleForTesting
- static Supplier<Cursor> sFakeAppUsageEventSupplier;
- @VisibleForTesting
- static Supplier<Cursor> sFakeAppUsageLatestTimestampSupplier;
- @VisibleForTesting
- static Supplier<Cursor> sFakeBatteryEventSupplier;
+ static Supplier<Cursor> sFakeSupplier;
private DatabaseUtils() {
}
@@ -340,7 +334,7 @@
resolver.insert(BATTERY_EVENT_URI, contentValues);
Log.d(TAG, "insert() battery event data into database: " + batteryEvent.toString());
} catch (Exception e) {
- Log.e(TAG, "insert() battery event data into database error:\n" + e);
+ Log.e(TAG, "insert() battery event data into database error:", e);
}
Log.d(TAG, String.format("sendBatteryEventData() in %d/ms",
(System.currentTimeMillis() - startTime)));
@@ -487,8 +481,8 @@
Context context, final Uri appUsageLatestTimestampUri) {
// We have already make sure the context here is with profile parent's user identity. Don't
// need to check whether current user is work profile.
- try (Cursor cursor = sFakeAppUsageLatestTimestampSupplier != null
- ? sFakeAppUsageLatestTimestampSupplier.get()
+ try (Cursor cursor = sFakeSupplier != null
+ ? sFakeSupplier.get()
: context.getContentResolver().query(
appUsageLatestTimestampUri, null, null, null)) {
if (cursor == null || cursor.getCount() == 0) {
@@ -514,8 +508,8 @@
if (context == null) {
return appUsageEventList;
}
- try (Cursor cursor = sFakeAppUsageEventSupplier != null
- ? sFakeAppUsageEventSupplier.get()
+ try (Cursor cursor = sFakeSupplier != null
+ ? sFakeSupplier.get()
: context.getContentResolver().query(appUsageEventUri, null, null, null)) {
if (cursor == null || cursor.getCount() == 0) {
return appUsageEventList;
@@ -540,8 +534,8 @@
if (context == null) {
return batteryEventList;
}
- try (Cursor cursor = sFakeBatteryEventSupplier != null
- ? sFakeBatteryEventSupplier.get()
+ try (Cursor cursor = sFakeSupplier != null
+ ? sFakeSupplier.get()
: context.getContentResolver().query(batteryEventUri, null, null, null)) {
if (cursor == null || cursor.getCount() == 0) {
return batteryEventList;
@@ -566,7 +560,7 @@
return null;
}
final Map<Long, Map<String, BatteryHistEntry>> resultMap = new HashMap();
- try (Cursor cursor = sFakeBatteryStateSupplier != null ? sFakeBatteryStateSupplier.get() :
+ try (Cursor cursor = sFakeSupplier != null ? sFakeSupplier.get() :
context.getContentResolver().query(batteryStateUri, null, null, null)) {
if (cursor == null || cursor.getCount() == 0) {
return resultMap;
diff --git a/src/com/android/settings/network/SubscriptionUtil.java b/src/com/android/settings/network/SubscriptionUtil.java
index 9c4ac03..9d953bf 100644
--- a/src/com/android/settings/network/SubscriptionUtil.java
+++ b/src/com/android/settings/network/SubscriptionUtil.java
@@ -438,6 +438,7 @@
}
}
+ Log.d(TAG, "getSelectableSubscriptionInfoList: " + selectableList);
return selectableList;
}
}
diff --git a/src/com/android/settings/panel/PanelFeatureProviderImpl.java b/src/com/android/settings/panel/PanelFeatureProviderImpl.java
index 57a1ab0..71711f9 100644
--- a/src/com/android/settings/panel/PanelFeatureProviderImpl.java
+++ b/src/com/android/settings/panel/PanelFeatureProviderImpl.java
@@ -22,9 +22,9 @@
import android.provider.Settings;
import android.util.FeatureFlagUtils;
-public class PanelFeatureProviderImpl implements PanelFeatureProvider {
+import com.android.settings.Utils;
- private static final String SYSTEMUI_PACKAGE_NAME = "com.android.systemui";
+public class PanelFeatureProviderImpl implements PanelFeatureProvider {
@Override
public PanelContent getPanel(Context context, Bundle bundle) {
@@ -42,7 +42,7 @@
// Redirect to the internet dialog in SystemUI.
Intent intent = new Intent(Settings.Panel.ACTION_INTERNET_CONNECTIVITY);
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
- .setPackage(SYSTEMUI_PACKAGE_NAME);
+ .setPackage(Utils.SYSTEMUI_PACKAGE_NAME);
context.sendBroadcast(intent);
return null;
case Settings.Panel.ACTION_NFC:
@@ -55,7 +55,7 @@
// Redirect to the volume panel in SystemUI.
Intent volumeIntent = new Intent(Settings.Panel.ACTION_VOLUME);
volumeIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND).setPackage(
- SYSTEMUI_PACKAGE_NAME);
+ Utils.SYSTEMUI_PACKAGE_NAME);
context.sendBroadcast(volumeIntent);
return null;
} else {
diff --git a/src/com/android/settings/safetycenter/BiometricsSafetySource.java b/src/com/android/settings/safetycenter/BiometricsSafetySource.java
index 1fe366d..74964ce 100644
--- a/src/com/android/settings/safetycenter/BiometricsSafetySource.java
+++ b/src/com/android/settings/safetycenter/BiometricsSafetySource.java
@@ -85,7 +85,7 @@
combinedBiometricStatusUtils.getSummary(),
createPendingIntent(context,
biometricNavigationUtils.getBiometricSettingsIntent(context,
- combinedBiometricStatusUtils.getSettingsClassName(),
+ combinedBiometricStatusUtils.getSettingsClassNameBasedOnUser(),
disablingAdmin, Bundle.EMPTY),
REQUEST_CODE_COMBINED_BIOMETRIC_SETTING),
disablingAdmin == null /* enabled */,
diff --git a/src/com/android/settings/sim/receivers/SimSlotChangeHandler.java b/src/com/android/settings/sim/receivers/SimSlotChangeHandler.java
index f6c9cc4..dabb088 100644
--- a/src/com/android/settings/sim/receivers/SimSlotChangeHandler.java
+++ b/src/com/android/settings/sim/receivers/SimSlotChangeHandler.java
@@ -43,7 +43,6 @@
import com.google.common.collect.ImmutableList;
-import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@@ -100,6 +99,9 @@
int lastRemovableSlotState = getLastRemovableSimSlotState(mContext);
int currentRemovableSlotState = removableSlotInfo.getCardStateInfo();
+ Log.i(TAG,
+ "lastRemovableSlotState: " + lastRemovableSlotState + ",currentRemovableSlotState: "
+ + currentRemovableSlotState);
boolean isRemovableSimInserted =
lastRemovableSlotState == UiccSlotInfo.CARD_STATE_INFO_ABSENT
&& currentRemovableSlotState == UiccSlotInfo.CARD_STATE_INFO_PRESENT;
@@ -259,7 +261,7 @@
}
List<SubscriptionInfo> subscriptionInfos = getAvailableRemovableSubscription();
- if (subscriptionInfos == null || subscriptionInfos.get(0) == null) {
+ if (subscriptionInfos.isEmpty()) {
Log.e(TAG, "Unable to find the removable subscriptionInfo. Do nothing.");
return;
}
@@ -275,6 +277,7 @@
private void setRemovableSimSlotState(Context context, int state) {
final SharedPreferences prefs = context.getSharedPreferences(EUICC_PREFS, MODE_PRIVATE);
prefs.edit().putInt(KEY_REMOVABLE_SLOT_STATE, state).apply();
+ Log.d(TAG, "setRemovableSimSlotState: " + state);
}
private int getSuwRemovableSlotAction(Context context) {
@@ -332,13 +335,14 @@
}
protected List<SubscriptionInfo> getAvailableRemovableSubscription() {
- List<SubscriptionInfo> subList = new ArrayList<>();
- for (SubscriptionInfo info : SubscriptionUtil.getAvailableSubscriptions(mContext)) {
- if (!info.isEmbedded()) {
- subList.add(info);
- }
- }
- return subList;
+ List<SubscriptionInfo> removableSubscriptions =
+ SubscriptionUtil.getAvailableSubscriptions(mContext);
+ return ImmutableList.copyOf(
+ removableSubscriptions.stream()
+ // ToDo: This condition is for psim only. If device supports removable
+ // esim, it needs an new condition.
+ .filter(sub -> !sub.isEmbedded())
+ .collect(Collectors.toList()));
}
private void startChooseSimActivity(boolean psimInserted) {
diff --git a/src/com/android/settings/spa/SettingsSpaEnvironment.kt b/src/com/android/settings/spa/SettingsSpaEnvironment.kt
index c2716b6..455fe9f 100644
--- a/src/com/android/settings/spa/SettingsSpaEnvironment.kt
+++ b/src/com/android/settings/spa/SettingsSpaEnvironment.kt
@@ -17,6 +17,7 @@
package com.android.settings.spa
import android.content.Context
+import android.util.FeatureFlagUtils
import com.android.settings.spa.app.AllAppListPageProvider
import com.android.settings.spa.app.AppsMainPageProvider
import com.android.settings.spa.app.appinfo.AppInfoSettingsProvider
@@ -43,6 +44,7 @@
import com.android.settings.spa.system.SystemMainPageProvider
import com.android.settingslib.spa.framework.common.SettingsPageProviderRepository
import com.android.settingslib.spa.framework.common.SpaEnvironment
+import com.android.settingslib.spa.framework.common.SpaLogger
import com.android.settingslib.spa.framework.common.createSettingsPage
import com.android.settingslib.spaprivileged.template.app.TogglePermissionAppListProvider
import com.android.settingslib.spaprivileged.template.app.TogglePermissionAppListTemplate
@@ -88,5 +90,8 @@
),
)
}
- override val logger = SpaLogProvider
+ override val logger =
+ if (FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.SETTINGS_ENABLE_SPA_METRICS))
+ SpaLogProvider
+ else object: SpaLogger {}
}
diff --git a/src/com/android/settings/spa/system/AppLanguagesListModel.kt b/src/com/android/settings/spa/system/AppLanguagesListModel.kt
index 3141d68..942bcc4 100644
--- a/src/com/android/settings/spa/system/AppLanguagesListModel.kt
+++ b/src/com/android/settings/spa/system/AppLanguagesListModel.kt
@@ -33,8 +33,10 @@
import com.android.settings.applications.appinfo.AppLocaleDetails
import com.android.settings.localepicker.AppLocalePickerActivity
import com.android.settingslib.spa.framework.util.filterItem
+import com.android.settingslib.spaprivileged.framework.common.asUser
import com.android.settingslib.spaprivileged.model.app.AppListModel
import com.android.settingslib.spaprivileged.model.app.AppRecord
+import com.android.settingslib.spaprivileged.model.app.userHandle
import com.android.settingslib.spaprivileged.template.app.AppListItem
import com.android.settingslib.spaprivileged.template.app.AppListItemModel
import kotlinx.coroutines.Dispatchers
@@ -54,17 +56,18 @@
override fun transform(userIdFlow: Flow<Int>, appListFlow: Flow<List<ApplicationInfo>>) =
userIdFlow.map { userId ->
- packageManager.queryIntentActivitiesAsUser(
+ userId to packageManager.queryIntentActivitiesAsUser(
AppLocaleUtil.LAUNCHER_ENTRY_INTENT,
PackageManager.ResolveInfoFlags.of(PackageManager.GET_META_DATA.toLong()),
userId,
)
- }.combine(appListFlow) { resolveInfos, appList ->
+ }.combine(appListFlow) { (userId, resolveInfos), appList ->
+ val userContext = context.asUser(UserHandle.of(userId))
appList.map { app ->
AppLanguagesRecord(
app = app,
isAppLocaleSupported = AppLocaleUtil.canDisplayLocaleUi(
- context, app, resolveInfos
+ userContext, app, resolveInfos
),
)
}
@@ -86,9 +89,7 @@
}.collectAsStateWithLifecycle(initialValue = stringResource(R.string.summary_placeholder))
private fun getSummary(app: ApplicationInfo): String =
- AppLocaleDetails.getAppDefaultLocale(context, app.packageName)?.let {
- AppLocaleDetails.getSummary(context, app).toString()
- } ?: context.getString(R.string.preference_of_system_locale_summary)
+ AppLocaleDetails.getSummary(context, app).toString()
@Composable
override fun AppListItemModel<AppLanguagesRecord>.AppItem() {
@@ -96,8 +97,7 @@
val intent = Intent(context, AppLocalePickerActivity::class.java).apply {
data = Uri.parse("package:${record.app.packageName}")
}
- val userHandle : UserHandle = UserHandle.getUserHandleForUid(record.app.uid)
- context.startActivityAsUser(intent, userHandle)
+ context.startActivityAsUser(intent, record.app.userHandle)
}
}
}
diff --git a/src/com/android/settings/wifi/factory/WifiFeatureProvider.java b/src/com/android/settings/wifi/factory/WifiFeatureProvider.java
index ea15c43..6612476 100644
--- a/src/com/android/settings/wifi/factory/WifiFeatureProvider.java
+++ b/src/com/android/settings/wifi/factory/WifiFeatureProvider.java
@@ -26,6 +26,7 @@
import androidx.lifecycle.ViewModelStoreOwner;
import com.android.settings.wifi.repository.WifiHotspotRepository;
+import com.android.settings.wifi.tether.WifiHotspotSecurityViewModel;
import com.android.settings.wifi.tether.WifiHotspotSpeedViewModel;
import com.android.settings.wifi.tether.WifiTetherViewModel;
@@ -85,6 +86,17 @@
}
/**
+ * Get WifiHotspotSecurityViewModel
+ */
+ public WifiHotspotSecurityViewModel getWifiHotspotSecurityViewModel(
+ @NotNull ViewModelStoreOwner owner) {
+ WifiHotspotSecurityViewModel viewModel =
+ new ViewModelProvider(owner).get(WifiHotspotSecurityViewModel.class);
+ verboseLog(TAG, "getWifiHotspotSecurityViewModel():" + viewModel);
+ return viewModel;
+ }
+
+ /**
* Get WifiHotspotSpeedViewModel
*/
public WifiHotspotSpeedViewModel getWifiHotspotSpeedViewModel(
diff --git a/src/com/android/settings/wifi/repository/WifiHotspotRepository.java b/src/com/android/settings/wifi/repository/WifiHotspotRepository.java
index ff6d883..91de482 100644
--- a/src/com/android/settings/wifi/repository/WifiHotspotRepository.java
+++ b/src/com/android/settings/wifi/repository/WifiHotspotRepository.java
@@ -19,6 +19,8 @@
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 android.content.Context;
@@ -81,6 +83,7 @@
protected String mLastPassword;
protected LastPasswordListener mLastPasswordListener = new LastPasswordListener();
+ protected MutableLiveData<Integer> mSecurityType;
protected MutableLiveData<Integer> mSpeedType;
protected Boolean mIsDualBand;
@@ -144,6 +147,7 @@
* Refresh data from the SoftApConfiguration.
*/
public void refresh() {
+ updateSecurityType();
update6gAvailable();
update5gAvailable();
updateSpeedType();
@@ -163,10 +167,70 @@
}
/**
+ * Gets SecurityType LiveData
+ */
+ public LiveData<Integer> getSecurityType() {
+ if (mSecurityType == null) {
+ startAutoRefresh();
+ mSecurityType = new MutableLiveData<>();
+ updateSecurityType();
+ log("getSecurityType():" + mSecurityType.getValue());
+ }
+ return mSecurityType;
+ }
+
+ protected void updateSecurityType() {
+ if (mSecurityType == null) {
+ return;
+ }
+ SoftApConfiguration config = mWifiManager.getSoftApConfiguration();
+ int securityType = (config != null) ? config.getSecurityType() : SECURITY_TYPE_OPEN;
+ log("updateSecurityType(), securityType:" + securityType);
+ mSecurityType.setValue(securityType);
+ }
+
+ /**
+ * Sets SecurityType
+ *
+ * @param securityType the Wi-Fi hotspot security type.
+ */
+ public void setSecurityType(int securityType) {
+ log("setSecurityType():" + securityType);
+ if (mSecurityType == null) {
+ getSecurityType();
+ }
+ if (securityType == mSecurityType.getValue()) {
+ Log.w(TAG, "setSecurityType() is no changed! mSecurityType:"
+ + mSecurityType.getValue());
+ return;
+ }
+ SoftApConfiguration config = mWifiManager.getSoftApConfiguration();
+ if (config == null) {
+ mSecurityType.setValue(SECURITY_TYPE_OPEN);
+ Log.e(TAG, "setSecurityType(), WifiManager#getSoftApConfiguration() return null!");
+ 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();
+ }
+ }
+ configBuilder.setPassphrase(passphrase, securityType);
+ setSoftApConfiguration(configBuilder.build());
+
+ mWifiManager.queryLastConfiguredTetheredApPassphraseSinceBoot(
+ mAppContext.getMainExecutor(), mLastPasswordListener);
+ }
+
+ /**
* Gets SpeedType LiveData
*/
public LiveData<Integer> getSpeedType() {
if (mSpeedType == null) {
+ startAutoRefresh();
mSpeedType = new MutableLiveData<>();
updateSpeedType();
log("getSpeedType():" + mSpeedType.getValue());
@@ -230,6 +294,10 @@
if (speedType == SPEED_6GHZ) {
log("setSpeedType(), setBand(BAND_2GHZ_5GHZ_6GHZ)");
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);
+ }
} else if (speedType == SPEED_5GHZ) {
log("setSpeedType(), setBand(BAND_2GHZ_5GHZ)");
configBuilder.setBand(BAND_2GHZ_5GHZ);
diff --git a/src/com/android/settings/wifi/tether/WifiHotspotSecuritySettings.java b/src/com/android/settings/wifi/tether/WifiHotspotSecuritySettings.java
new file mode 100644
index 0000000..8ff2689
--- /dev/null
+++ b/src/com/android/settings/wifi/tether/WifiHotspotSecuritySettings.java
@@ -0,0 +1,112 @@
+/*
+ * 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.wifi.tether;
+
+import android.app.settings.SettingsEnums;
+import android.os.Bundle;
+
+import androidx.lifecycle.LiveData;
+
+import com.android.settings.R;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.widget.SelectorWithWidgetPreference;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Wi-Fi Hotspot Security Settings
+ */
+public class WifiHotspotSecuritySettings extends DashboardFragment implements
+ SelectorWithWidgetPreference.OnClickListener {
+ private static final String TAG = "WifiHotspotSecuritySettings";
+
+ protected WifiHotspotSecurityViewModel mWifiHotspotSecurityViewModel;
+ protected Map<Integer, SelectorWithWidgetPreference> mPreferenceMap = new HashMap<>();
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.WIFI_TETHER_SETTINGS;
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.wifi_hotspot_security;
+ }
+
+ @Override
+ protected String getLogTag() {
+ return TAG;
+ }
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ loadViewModel();
+ }
+
+ protected void loadViewModel() {
+ mWifiHotspotSecurityViewModel = FeatureFactory.getFactory(getContext())
+ .getWifiFeatureProvider().getWifiHotspotSecurityViewModel(this);
+ LiveData<List<WifiHotspotSecurityViewModel.ViewItem>> viewItemListData =
+ mWifiHotspotSecurityViewModel.getViewItemListData();
+ viewItemListData.observe(this, this::onViewItemListDataChanged);
+ // set the onRadioButtonClicked callback to related preference
+ for (WifiHotspotSecurityViewModel.ViewItem viewItem : viewItemListData.getValue()) {
+ SelectorWithWidgetPreference preference = findPreference(viewItem.mKey);
+ preference.setOnClickListener(this);
+ }
+ }
+
+ protected void onViewItemListDataChanged(
+ List<WifiHotspotSecurityViewModel.ViewItem> viewItems) {
+ log("onViewItemListDataChanged(), viewItems:" + viewItems);
+ for (WifiHotspotSecurityViewModel.ViewItem viewItem : viewItems) {
+ SelectorWithWidgetPreference preference = findPreference(viewItem.mKey);
+ if (preference == null) {
+ continue;
+ }
+ if (preference.isChecked() != viewItem.mIsChecked) {
+ preference.setChecked(viewItem.mIsChecked);
+ }
+ if (preference.isEnabled() != viewItem.mIsEnabled) {
+ preference.setEnabled(viewItem.mIsEnabled);
+ if (viewItem.mIsEnabled) {
+ preference.setSummary(null);
+ } else {
+ preference.setSummary(R.string.wifi_hotspot_security_summary_unavailable);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void onRadioButtonClicked(SelectorWithWidgetPreference emiter) {
+ String key = emiter.getKey();
+ log("onRadioButtonClicked(), key:" + key);
+ if (key.isEmpty()) {
+ return;
+ }
+ mWifiHotspotSecurityViewModel.handleRadioButtonClicked(key);
+ }
+
+ private void log(String msg) {
+ FeatureFactory.getFactory(getContext()).getWifiFeatureProvider().verboseLog(TAG, msg);
+ }
+}
diff --git a/src/com/android/settings/wifi/tether/WifiHotspotSecurityViewModel.java b/src/com/android/settings/wifi/tether/WifiHotspotSecurityViewModel.java
new file mode 100644
index 0000000..422e40b
--- /dev/null
+++ b/src/com/android/settings/wifi/tether/WifiHotspotSecurityViewModel.java
@@ -0,0 +1,157 @@
+/*
+ * 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.wifi.tether;
+
+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 com.android.settings.wifi.repository.WifiHotspotRepository.SPEED_6GHZ;
+
+import android.app.Application;
+
+import androidx.lifecycle.AndroidViewModel;
+import androidx.lifecycle.LiveData;
+import androidx.lifecycle.MutableLiveData;
+import androidx.lifecycle.Observer;
+
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.wifi.repository.WifiHotspotRepository;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Wi-Fi Hotspot Security View Model for {@link WifiHotspotSecuritySettings}
+ */
+public class WifiHotspotSecurityViewModel extends AndroidViewModel {
+ private static final String TAG = "WifiHotspotSecurityViewModel";
+
+ public static final String KEY_SECURITY_WPA3 = "wifi_hotspot_security_wpa3";
+ public static final String KEY_SECURITY_WPA2_WPA3 = "wifi_hotspot_security_wpa2_wpa3";
+ public static final String KEY_SECURITY_WPA2 = "wifi_hotspot_security_wpa2";
+ public static final String KEY_SECURITY_NONE = "wifi_hotspot_security_none";
+
+ protected Map<Integer, ViewItem> mViewItemMap = new HashMap<>();
+ protected MutableLiveData<List<ViewItem>> mViewInfoListData;
+
+ protected final WifiHotspotRepository mWifiHotspotRepository;
+ protected final Observer<Integer> mSecurityTypeObserver = st -> onSecurityTypeChanged(st);
+ protected final Observer<Integer> mSpeedTypeObserver = st -> onSpeedTypeChanged(st);
+
+ public WifiHotspotSecurityViewModel(
+ @NotNull Application application) {
+ super(application);
+ mViewItemMap.put(SECURITY_TYPE_WPA3_SAE, new ViewItem(KEY_SECURITY_WPA3));
+ mViewItemMap.put(SECURITY_TYPE_WPA3_SAE_TRANSITION, new ViewItem(KEY_SECURITY_WPA2_WPA3));
+ mViewItemMap.put(SECURITY_TYPE_WPA2_PSK, new ViewItem(KEY_SECURITY_WPA2));
+ mViewItemMap.put(SECURITY_TYPE_OPEN, new ViewItem(KEY_SECURITY_NONE));
+
+ mWifiHotspotRepository = FeatureFactory.getFactory(application).getWifiFeatureProvider()
+ .getWifiHotspotRepository();
+ mWifiHotspotRepository.getSecurityType().observeForever(mSecurityTypeObserver);
+ mWifiHotspotRepository.getSpeedType().observeForever(mSpeedTypeObserver);
+ }
+
+ @Override
+ protected void onCleared() {
+ mWifiHotspotRepository.getSecurityType().removeObserver(mSecurityTypeObserver);
+ mWifiHotspotRepository.getSpeedType().removeObserver(mSpeedTypeObserver);
+ }
+
+ protected void onSecurityTypeChanged(int securityType) {
+ log("onSecurityTypeChanged(), securityType:" + securityType);
+ for (Map.Entry<Integer, ViewItem> entry : mViewItemMap.entrySet()) {
+ entry.getValue().mIsChecked = entry.getKey().equals(securityType);
+ }
+ updateViewItemListData();
+ }
+
+ protected void onSpeedTypeChanged(Integer speedType) {
+ log("onSpeedTypeChanged(), speedType:" + speedType);
+ boolean isWpa3Only = (speedType == SPEED_6GHZ);
+ for (Map.Entry<Integer, ViewItem> entry : mViewItemMap.entrySet()) {
+ if (entry.getKey() != SECURITY_TYPE_WPA3_SAE) {
+ entry.getValue().mIsEnabled = !isWpa3Only;
+ }
+ }
+ updateViewItemListData();
+ }
+
+ /**
+ * Handle RadioButton Clicked
+ */
+ public void handleRadioButtonClicked(String key) {
+ log("handleRadioButtonClicked(), key:" + key);
+ for (Map.Entry<Integer, ViewItem> entry : mViewItemMap.entrySet()) {
+ ViewItem viewItem = entry.getValue();
+ if (viewItem.mKey.equals(key)) {
+ mWifiHotspotRepository.setSecurityType(entry.getKey());
+ return;
+ }
+ }
+ }
+
+ /**
+ * Gets ViewItemList LiveData
+ */
+ public LiveData<List<ViewItem>> getViewItemListData() {
+ if (mViewInfoListData == null) {
+ mViewInfoListData = new MutableLiveData<>();
+ updateViewItemListData();
+ log("getViewItemListData(), mViewInfoListData:" + mViewInfoListData.getValue());
+ }
+ return mViewInfoListData;
+ }
+
+ protected void updateViewItemListData() {
+ if (mViewInfoListData == null) {
+ return;
+ }
+ mViewInfoListData.setValue(mViewItemMap.values().stream().toList());
+ }
+
+ /**
+ * Wi-Fi Hotspot View Item
+ */
+ public static final class ViewItem {
+ String mKey;
+ boolean mIsChecked;
+ boolean mIsEnabled = true;
+
+ public ViewItem(String key) {
+ mKey = key;
+ }
+
+ @Override
+ public String toString() {
+ return new StringBuilder("ViewItem:{")
+ .append("Key:").append(mKey)
+ .append(",IsChecked:").append(mIsChecked)
+ .append(",IsEnabled:").append(mIsEnabled)
+ .append('}').toString();
+ }
+ }
+
+ private void log(String msg) {
+ FeatureFactory.getFactory(getApplication()).getWifiFeatureProvider().verboseLog(TAG, msg);
+ }
+}
diff --git a/src/com/android/settings/wifi/tether/WifiTetherSettings.java b/src/com/android/settings/wifi/tether/WifiTetherSettings.java
index 3a3691a..bdb1a2e 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherSettings.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherSettings.java
@@ -72,6 +72,8 @@
static final String KEY_WIFI_TETHER_MAXIMIZE_COMPATIBILITY =
WifiTetherMaximizeCompatibilityPreferenceController.PREF_KEY;
@VisibleForTesting
+ static final String KEY_WIFI_HOTSPOT_SECURITY = "wifi_hotspot_security";
+ @VisibleForTesting
static final String KEY_WIFI_HOTSPOT_SPEED = "wifi_hotspot_speed";
private WifiTetherSwitchBarController mSwitchBarController;
@@ -91,6 +93,8 @@
@VisibleForTesting
WifiTetherViewModel mWifiTetherViewModel;
@VisibleForTesting
+ Preference mWifiHotspotSecurity;
+ @VisibleForTesting
Preference mWifiHotspotSpeed;
static {
@@ -132,6 +136,10 @@
mWifiTetherViewModel = FeatureFactory.getFactory(getContext()).getWifiFeatureProvider()
.getWifiTetherViewModel(this);
+ mWifiHotspotSecurity = findPreference(KEY_WIFI_HOTSPOT_SECURITY);
+ if (mWifiHotspotSecurity != null && mWifiHotspotSecurity.isVisible()) {
+ mWifiTetherViewModel.getSecuritySummary().observe(this, this::onSecuritySummaryChanged);
+ }
mWifiHotspotSpeed = findPreference(KEY_WIFI_HOTSPOT_SPEED);
if (mWifiHotspotSpeed != null && mWifiHotspotSpeed.isVisible()) {
mWifiTetherViewModel.getSpeedSummary().observe(this, this::onSpeedSummaryChanged);
@@ -206,6 +214,10 @@
}
}
+ protected void onSecuritySummaryChanged(Integer securityResId) {
+ mWifiHotspotSecurity.setSummary(securityResId);
+ }
+
protected void onSpeedSummaryChanged(Integer summaryResId) {
mWifiHotspotSpeed.setSummary(summaryResId);
}
diff --git a/src/com/android/settings/wifi/tether/WifiTetherViewModel.java b/src/com/android/settings/wifi/tether/WifiTetherViewModel.java
index 8cb74c3..6bb2cd5 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherViewModel.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherViewModel.java
@@ -16,11 +16,15 @@
package com.android.settings.wifi.tether;
+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 com.android.settings.wifi.repository.WifiHotspotRepository.SPEED_2GHZ;
import static com.android.settings.wifi.repository.WifiHotspotRepository.SPEED_2GHZ_5GHZ;
import static com.android.settings.wifi.repository.WifiHotspotRepository.SPEED_5GHZ;
import static com.android.settings.wifi.repository.WifiHotspotRepository.SPEED_6GHZ;
-import static com.android.settings.wifi.repository.WifiHotspotRepository.SPEED_UNKNOWN;
import android.app.Application;
import android.net.wifi.SoftApConfiguration;
@@ -28,7 +32,7 @@
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
-import androidx.lifecycle.Transformations;
+import androidx.lifecycle.Observer;
import com.android.settings.R;
import com.android.settings.overlay.FeatureFactory;
@@ -45,9 +49,19 @@
public class WifiTetherViewModel extends AndroidViewModel {
private static final String TAG = "WifiTetherViewModel";
- protected static Map<Integer, Integer> sSpeedSummaryResMap = new HashMap<>();
+ static Map<Integer, Integer> sSecuritySummaryResMap = new HashMap<>();
+
static {
- sSpeedSummaryResMap.put(SPEED_UNKNOWN, R.string.summary_placeholder);
+ sSecuritySummaryResMap.put(SECURITY_TYPE_WPA3_SAE, R.string.wifi_security_sae);
+ sSecuritySummaryResMap.put(SECURITY_TYPE_WPA3_SAE_TRANSITION,
+ R.string.wifi_security_psk_sae);
+ sSecuritySummaryResMap.put(SECURITY_TYPE_WPA2_PSK, R.string.wifi_security_wpa2);
+ sSecuritySummaryResMap.put(SECURITY_TYPE_OPEN, R.string.wifi_security_none);
+ }
+
+ static Map<Integer, Integer> sSpeedSummaryResMap = new HashMap<>();
+
+ static {
sSpeedSummaryResMap.put(SPEED_2GHZ, R.string.wifi_hotspot_speed_summary_2g);
sSpeedSummaryResMap.put(SPEED_5GHZ, R.string.wifi_hotspot_speed_summary_5g);
sSpeedSummaryResMap.put(SPEED_6GHZ, R.string.wifi_hotspot_speed_summary_6g);
@@ -55,18 +69,22 @@
}
protected final WifiHotspotRepository mWifiHotspotRepository;
+ protected MutableLiveData<Integer> mSecuritySummary;
protected MutableLiveData<Integer> mSpeedSummary;
+ protected final Observer<Integer> mSecurityTypeObserver = st -> onSecurityTypeChanged(st);
+ protected final Observer<Integer> mSpeedTypeObserver = st -> onSpeedTypeChanged(st);
+
public WifiTetherViewModel(@NotNull Application application) {
super(application);
mWifiHotspotRepository = FeatureFactory.getFactory(application).getWifiFeatureProvider()
.getWifiHotspotRepository();
- mWifiHotspotRepository.setAutoRefresh(true);
}
@Override
protected void onCleared() {
- mWifiHotspotRepository.setAutoRefresh(false);
+ mWifiHotspotRepository.getSecurityType().removeObserver(mSecurityTypeObserver);
+ mWifiHotspotRepository.getSpeedType().removeObserver(mSpeedTypeObserver);
}
/**
@@ -86,17 +104,40 @@
}
/**
+ * Gets SecuritySummary LiveData
+ */
+ public LiveData<Integer> getSecuritySummary() {
+ if (mSecuritySummary == null) {
+ mSecuritySummary = new MutableLiveData<>();
+ mWifiHotspotRepository.getSecurityType().observeForever(mSecurityTypeObserver);
+ }
+ return mSecuritySummary;
+ }
+
+ protected void onSecurityTypeChanged(int securityType) {
+ int resId = R.string.summary_placeholder;
+ if (sSecuritySummaryResMap.containsKey(securityType)) {
+ resId = sSecuritySummaryResMap.get(securityType);
+ }
+ mSecuritySummary.setValue(resId);
+ }
+
+ /**
* Gets SpeedSummary LiveData
*/
public LiveData<Integer> getSpeedSummary() {
if (mSpeedSummary == null) {
mSpeedSummary = new MutableLiveData<>();
- mWifiHotspotRepository.getSpeedType().observeForever(this::onSpeedTypeChanged);
+ mWifiHotspotRepository.getSpeedType().observeForever(mSpeedTypeObserver);
}
- return Transformations.distinctUntilChanged(mSpeedSummary);
+ return mSpeedSummary;
}
protected void onSpeedTypeChanged(Integer speedType) {
- mSpeedSummary.setValue(sSpeedSummaryResMap.get(speedType));
+ int resId = R.string.summary_placeholder;
+ if (sSpeedSummaryResMap.containsKey(speedType)) {
+ resId = sSpeedSummaryResMap.get(speedType);
+ }
+ mSpeedSummary.setValue(resId);
}
}
diff --git a/tests/robotests/src/com/android/settings/bluetooth/RequestPermissionHelperTest.kt b/tests/robotests/src/com/android/settings/bluetooth/RequestPermissionHelperTest.kt
new file mode 100644
index 0000000..ce0792c
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/bluetooth/RequestPermissionHelperTest.kt
@@ -0,0 +1,247 @@
+/*
+ * 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.bluetooth
+
+import androidx.activity.ComponentActivity
+import com.android.settings.R
+import com.android.settings.testutils.shadow.ShadowAlertDialogCompat
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.spy
+import org.robolectric.RobolectricTestRunner
+import org.robolectric.android.controller.ActivityController
+import org.robolectric.annotation.Config
+import org.mockito.Mockito.`when` as whenever
+
+@RunWith(RobolectricTestRunner::class)
+@Config(shadows = [ShadowAlertDialogCompat::class])
+class RequestPermissionHelperTest {
+ private lateinit var activityController: ActivityController<ComponentActivity>
+
+ @Before
+ fun setUp() {
+ activityController =
+ ActivityController.of(ComponentActivity()).create().start().postCreate(null).resume()
+ }
+
+ @After
+ fun tearDown() {
+ activityController.pause().stop().destroy()
+ }
+
+ @Test
+ fun requestEnable_withAppLabelAndNoTimeout_hasCorrectMessage() {
+ val activity = activityController.get()
+ RequestPermissionHelper.requestEnable(
+ context = activity,
+ appLabel = "App Label",
+ timeout = -1,
+ onAllow = {},
+ onDeny = {},
+ )
+
+ assertLatestMessageIs("App Label wants to turn on Bluetooth")
+ }
+
+ @Test
+ fun requestEnable_withAppLabelAndZeroTimeout_hasCorrectMessage() {
+ val activity = activityController.get()
+ RequestPermissionHelper.requestEnable(
+ context = activity,
+ appLabel = "App Label",
+ timeout = 0,
+ onAllow = {},
+ onDeny = {},
+ )
+
+ assertLatestMessageIs(
+ "App Label wants to turn on Bluetooth and make your phone visible to other devices. " +
+ "You can change this later in Bluetooth settings."
+ )
+ }
+
+ @Test
+ fun requestEnable_withAppLabelAndNormalTimeout_hasCorrectMessage() {
+ val activity = activityController.get()
+ RequestPermissionHelper.requestEnable(
+ context = activity,
+ appLabel = "App Label",
+ timeout = 120,
+ onAllow = {},
+ onDeny = {},
+ )
+
+ assertLatestMessageIs(
+ "App Label wants to turn on Bluetooth and make your phone visible to other devices " +
+ "for 120 seconds."
+ )
+ }
+
+ @Test
+ fun requestEnable_withNoAppLabelAndNoTimeout_hasCorrectMessage() {
+ val activity = activityController.get()
+ RequestPermissionHelper.requestEnable(
+ context = activity,
+ appLabel = null,
+ timeout = -1,
+ onAllow = {},
+ onDeny = {},
+ )
+
+ assertLatestMessageIs("An app wants to turn on Bluetooth")
+ }
+
+ @Test
+ fun requestEnable_withNoAppLabelAndZeroTimeout_hasCorrectMessage() {
+ val activity = activityController.get()
+ RequestPermissionHelper.requestEnable(
+ context = activity,
+ appLabel = null,
+ timeout = 0,
+ onAllow = {},
+ onDeny = {},
+ )
+
+ assertLatestMessageIs(
+ "An app wants to turn on Bluetooth and make your phone visible to other devices. " +
+ "You can change this later in Bluetooth settings."
+ )
+ }
+
+ @Test
+ fun requestEnable_withNoAppLabelAndNormalTimeout_hasCorrectMessage() {
+ val activity = activityController.get()
+ RequestPermissionHelper.requestEnable(
+ context = activity,
+ appLabel = null,
+ timeout = 120,
+ onAllow = {},
+ onDeny = {},
+ )
+
+ assertLatestMessageIs(
+ "An app wants to turn on Bluetooth and make your phone visible to other devices for " +
+ "120 seconds."
+ )
+ }
+
+ @Test
+ fun requestEnable_whenAutoConfirm_onAllowIsCalled() {
+ val activity = getActivityWith(autoConfirm = true)
+ var onAllowCalled = false
+
+ RequestPermissionHelper.requestEnable(
+ context = activity,
+ appLabel = null,
+ timeout = -1,
+ onAllow = { onAllowCalled = true },
+ onDeny = {},
+ )
+
+ assertThat(onAllowCalled).isTrue()
+ }
+
+ @Test
+ fun requestEnable_whenNotAutoConfirm_onAllowIsNotCalledWhenRequest() {
+ val activity = getActivityWith(autoConfirm = false)
+ var onAllowCalled = false
+
+ RequestPermissionHelper.requestEnable(
+ context = activity,
+ appLabel = null,
+ timeout = -1,
+ onAllow = { onAllowCalled = true },
+ onDeny = {},
+ )
+
+ assertThat(onAllowCalled).isFalse()
+ }
+
+ @Test
+ fun requestDisable_withAppLabel_hasCorrectMessage() {
+ val activity = activityController.get()
+ RequestPermissionHelper.requestDisable(
+ context = activity,
+ appLabel = "App Label",
+ onAllow = {},
+ onDeny = {},
+ )
+
+ assertLatestMessageIs("App Label wants to turn off Bluetooth")
+ }
+
+ @Test
+ fun requestDisable_withNoAppLabel_hasCorrectMessage() {
+ val activity = activityController.get()
+ RequestPermissionHelper.requestDisable(
+ context = activity,
+ appLabel = null,
+ onAllow = {},
+ onDeny = {},
+ )
+
+ assertLatestMessageIs("An app wants to turn off Bluetooth")
+ }
+
+ @Test
+ fun requestDisable_whenAutoConfirm_onAllowIsCalled() {
+ val activity = getActivityWith(autoConfirm = true)
+ var onAllowCalled = false
+
+ RequestPermissionHelper.requestDisable(
+ context = activity,
+ appLabel = null,
+ onAllow = { onAllowCalled = true },
+ onDeny = {},
+ )
+
+ assertThat(onAllowCalled).isTrue()
+ }
+
+ @Test
+ fun requestDisable_whenNotAutoConfirm_onAllowIsNotCalledWhenRequest() {
+ val activity = getActivityWith(autoConfirm = false)
+ var onAllowCalled = false
+
+ RequestPermissionHelper.requestDisable(
+ context = activity,
+ appLabel = null,
+ onAllow = { onAllowCalled = true },
+ onDeny = {},
+ )
+
+ assertThat(onAllowCalled).isFalse()
+ }
+
+ private fun getActivityWith(autoConfirm: Boolean): ComponentActivity {
+ val activity = spy(activityController.get())
+ val spyResources = spy(activity.resources)
+ whenever(activity.resources).thenReturn(spyResources)
+ whenever(spyResources.getBoolean(R.bool.auto_confirm_bluetooth_activation_dialog))
+ .thenReturn(autoConfirm)
+ return activity
+ }
+
+ private fun assertLatestMessageIs(message: String) {
+ val dialog = ShadowAlertDialogCompat.getLatestAlertDialog()
+ val shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog)
+ assertThat(shadowDialog.message.toString()).isEqualTo(message)
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/development/ForceEnableNotesRolePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/ForceEnableNotesRolePreferenceControllerTest.java
new file mode 100644
index 0000000..32a28fe
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/ForceEnableNotesRolePreferenceControllerTest.java
@@ -0,0 +1,102 @@
+/*
+ * 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.development;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class ForceEnableNotesRolePreferenceControllerTest {
+
+ @Mock
+ private PreferenceScreen mScreen;
+ @Mock
+ private SwitchPreference mPreference;
+
+ private ForceEnableNotesRolePreferenceController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mController = new ForceEnableNotesRolePreferenceController(
+ RuntimeEnvironment.application) {
+ private boolean mEnabled;
+
+ protected boolean isEnabled() {
+ return mEnabled;
+ }
+
+ protected void setEnabled(boolean enabled) {
+ mEnabled = enabled;
+ }
+ };
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
+ mController.displayPreference(mScreen);
+ }
+
+ @Test
+ public void updateState_enabled_preferenceShouldBeChecked() {
+ mController.setEnabled(true);
+ mController.updateState(mPreference);
+
+ verify(mPreference).setChecked(true);
+ }
+
+ @Test
+ public void updateState_disabled_preferenceShouldBeUnchecked() {
+ mController.setEnabled(false);
+ mController.updateState(mPreference);
+
+ verify(mPreference).setChecked(false);
+ }
+
+ @Test
+ public void onPreferenceChange_checked_shouldBeEnabled() {
+ mController.onPreferenceChange(mPreference, true);
+
+ assertTrue(mController.isEnabled());
+ }
+
+ @Test
+ public void onPreferenceChange_unchecked_shouldNotBeEnabled() {
+ mController.onPreferenceChange(mPreference, false);
+
+ assertFalse(mController.isEnabled());
+ }
+
+ @Test
+ public void onDeveloperOptionsSwitchDisabled_preferenceShouldNotBeEnabled() {
+ mController.onDeveloperOptionsSwitchDisabled();
+
+ assertFalse(mController.isEnabled());
+ verify(mPreference).setEnabled(false);
+ verify(mPreference).setChecked(false);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceControllerTest.java
index 405ea12..3ad14e5 100644
--- a/tests/robotests/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceControllerTest.java
@@ -74,7 +74,7 @@
mController.setConfig(mConfig);
mApplicationInfo.uid = 1;
- when(mContext.getString(R.string.config_defaultWellbeingPackage)).thenReturn(TEST_PACKAGE);
+ when(mContext.getString(R.string.config_systemWellbeing)).thenReturn(TEST_PACKAGE);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
doReturn(mApplicationInfo).when(mPackageManager).getApplicationInfo(
diff --git a/tests/robotests/src/com/android/settings/display/darkmode/DarkModeCustomBedtimePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/darkmode/DarkModeCustomBedtimePreferenceControllerTest.java
index 7f50568..85d6fab 100644
--- a/tests/robotests/src/com/android/settings/display/darkmode/DarkModeCustomBedtimePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/display/darkmode/DarkModeCustomBedtimePreferenceControllerTest.java
@@ -77,7 +77,7 @@
when(mContext.getSystemService(UiModeManager.class)).thenReturn(mService);
when(mContext.getResources()).thenReturn(mResources);
- when(mResources.getString(com.android.internal.R.string.config_defaultWellbeingPackage))
+ when(mResources.getString(com.android.internal.R.string.config_systemWellbeing))
.thenReturn("wellbeing");
when(mScreen.findPreference(anyString())).thenReturn(mFooterPreference);
diff --git a/tests/robotests/src/com/android/settings/display/darkmode/DarkModeScheduleSelectorControllerTest.java b/tests/robotests/src/com/android/settings/display/darkmode/DarkModeScheduleSelectorControllerTest.java
index d776e5e..d95635e 100644
--- a/tests/robotests/src/com/android/settings/display/darkmode/DarkModeScheduleSelectorControllerTest.java
+++ b/tests/robotests/src/com/android/settings/display/darkmode/DarkModeScheduleSelectorControllerTest.java
@@ -84,7 +84,7 @@
when(mContext.getSystemService(LocationManager.class)).thenReturn(mLocationManager);
when(mContext.getResources()).thenReturn(mResources);
when(mResources.getConfiguration()).thenReturn(mConfigNightNo);
- when(mResources.getString(com.android.internal.R.string.config_defaultWellbeingPackage))
+ when(mResources.getString(com.android.internal.R.string.config_systemWellbeing))
.thenReturn("wellbeing");
when(mContext.getString(R.string.dark_ui_auto_mode_never)).thenReturn("never");
diff --git a/tests/robotests/src/com/android/settings/dream/WhenToDreamPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/dream/WhenToDreamPreferenceControllerTest.java
index 6e687bb..e173add 100644
--- a/tests/robotests/src/com/android/settings/dream/WhenToDreamPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/dream/WhenToDreamPreferenceControllerTest.java
@@ -72,7 +72,7 @@
mApplicationInfo.uid = 1;
when(mContext.getString(
- com.android.internal.R.string.config_defaultWellbeingPackage)).thenReturn(
+ com.android.internal.R.string.config_systemWellbeing)).thenReturn(
TEST_PACKAGE);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/IncompatibleChargerDetectorTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/IncompatibleChargerDetectorTest.java
index 1dfe6e2..9ababe7 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/IncompatibleChargerDetectorTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/IncompatibleChargerDetectorTest.java
@@ -25,7 +25,6 @@
import android.hardware.usb.UsbPort;
import android.hardware.usb.UsbPortStatus;
-import com.android.settings.fuelgauge.BatteryInfo;
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
import org.junit.Before;
@@ -42,7 +41,6 @@
@RunWith(RobolectricTestRunner.class)
public final class IncompatibleChargerDetectorTest {
- @Mock private BatteryInfo mBatteryInfo;
@Mock private UsbPort mUsbPort;
@Mock private UsbManager mUsbManager;
@Mock private UsbPortStatus mUsbPortStatus;
@@ -55,14 +53,11 @@
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
when(mContext.getSystemService(UsbManager.class)).thenReturn(mUsbManager);
- mIncompatibleChargerDetector =
- new IncompatibleChargerDetector(mContext, mBatteryInfo);
+ mIncompatibleChargerDetector = new IncompatibleChargerDetector(mContext);
}
@Test
- public void detect_unplugDevice_shouldNotShowTip() {
- mBatteryInfo.pluggedStatus = 0;
-
+ public void detect_withoutIncompatibleCharger_shouldNotShowTip() {
BatteryTip batteryTip = mIncompatibleChargerDetector.detect();
assertThat(batteryTip.isVisible()).isFalse();
@@ -70,18 +65,7 @@
}
@Test
- public void detect_plugDeviceWithoutIncompatibleCharger_shouldNotShowTip() {
- mBatteryInfo.pluggedStatus = 1;
-
- BatteryTip batteryTip = mIncompatibleChargerDetector.detect();
-
- assertThat(batteryTip.isVisible()).isFalse();
- assertThat(batteryTip.getState()).isEqualTo(BatteryTip.StateType.INVISIBLE);
- }
-
- @Test
- public void detect_plugDeviceWithIncompatibleCharger_showTip() {
- mBatteryInfo.pluggedStatus = 1;
+ public void detect_withIncompatibleCharger_showTip() {
setupIncompatibleCharging();
BatteryTip batteryTip = mIncompatibleChargerDetector.detect();
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownControllerTest.java
index 16fec09..8d0a839 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownControllerTest.java
@@ -176,7 +176,7 @@
}
@Test
- public void removeAndCacheAllUnusedPreferences_removePerf_buildCacheAndRemoveAllPreference() {
+ public void removeAndCacheAllUnusedPreferences_removePref_buildCacheAndRemoveAllPreference() {
doReturn(1).when(mAppListPreferenceGroup).getPreferenceCount();
doReturn(mPowerGaugePreference).when(mAppListPreferenceGroup).getPreference(0);
doReturn(PREF_KEY2).when(mBatteryHistEntry).getKey();
@@ -193,7 +193,7 @@
}
@Test
- public void removeAndCacheAllUnusedPreferences_keepPerf_KeepAllPreference() {
+ public void removeAndCacheAllUnusedPreferences_keepPref_KeepAllPreference() {
doReturn(1).when(mAppListPreferenceGroup).getPreferenceCount();
doReturn(mPowerGaugePreference).when(mAppListPreferenceGroup).getPreference(0);
doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessManagerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessManagerTest.java
index 753a7f7..2a00116 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessManagerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessManagerTest.java
@@ -102,7 +102,7 @@
AppUsageEventEntity.KEY_UID,
AppUsageEventEntity.KEY_PACKAGE_NAME,
AppUsageEventEntity.KEY_TIMESTAMP});
- DatabaseUtils.sFakeAppUsageEventSupplier = () -> cursor;
+ DatabaseUtils.sFakeSupplier = () -> cursor;
doReturn(true).when(mUserManager).isUserUnlocked(anyInt());
mDataProcessManager.start();
@@ -171,7 +171,7 @@
cursor.addRow(new Object[] {
AppUsageEventType.ACTIVITY_STOPPED.getNumber(), /*timestamp=*/ 6, /*userId=*/ 1,
/*instanceId=*/ 2, packageName});
- DatabaseUtils.sFakeAppUsageEventSupplier = () -> cursor;
+ DatabaseUtils.sFakeSupplier = () -> cursor;
final DataProcessManager dataProcessManager = new DataProcessManager(
mContext, /*handler=*/ null, /*rawStartTimestamp=*/ 2L, /*callbackFunction=*/ null,
@@ -240,7 +240,7 @@
AppUsageEventEntity.KEY_TIMESTAMP});
// Adds fake data into the cursor.
cursor.addRow(new Object[] {101L, "app name1", 1001L});
- DatabaseUtils.sFakeAppUsageEventSupplier = () -> cursor;
+ DatabaseUtils.sFakeSupplier = () -> cursor;
mDataProcessManager.start();
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtilsTest.java
index 20799d4..efce44e 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtilsTest.java
@@ -261,7 +261,7 @@
public void getAppUsageStartTimestampOfUser_emptyCursorContent_returnEarliestTimestamp() {
final MatrixCursor cursor =
new MatrixCursor(new String[] {AppUsageEventEntity.KEY_TIMESTAMP});
- DatabaseUtils.sFakeAppUsageLatestTimestampSupplier = () -> cursor;
+ DatabaseUtils.sFakeSupplier = () -> cursor;
final long earliestTimestamp = 10001L;
assertThat(DatabaseUtils.getAppUsageStartTimestampOfUser(
@@ -270,7 +270,7 @@
@Test
public void getAppUsageStartTimestampOfUser_nullCursor_returnEarliestTimestamp() {
- DatabaseUtils.sFakeAppUsageLatestTimestampSupplier = () -> null;
+ DatabaseUtils.sFakeSupplier = () -> null;
final long earliestTimestamp = 10001L;
assertThat(DatabaseUtils.getAppUsageStartTimestampOfUser(
mContext, /*userId=*/ 0, earliestTimestamp)).isEqualTo(earliestTimestamp);
@@ -283,7 +283,7 @@
new MatrixCursor(new String[] {AppUsageEventEntity.KEY_TIMESTAMP});
// Adds fake data into the cursor.
cursor.addRow(new Object[] {returnedTimestamp});
- DatabaseUtils.sFakeAppUsageLatestTimestampSupplier = () -> cursor;
+ DatabaseUtils.sFakeSupplier = () -> cursor;
final long earliestTimestamp1 = 1001L;
assertThat(DatabaseUtils.getAppUsageStartTimestampOfUser(
@@ -302,7 +302,7 @@
AppUsageEventEntity.KEY_PACKAGE_NAME,
AppUsageEventEntity.KEY_TIMESTAMP,
AppUsageEventEntity.KEY_APP_USAGE_EVENT_TYPE});
- DatabaseUtils.sFakeAppUsageEventSupplier = () -> cursor;
+ DatabaseUtils.sFakeSupplier = () -> cursor;
assertThat(DatabaseUtils.getAppUsageEventForUsers(
mContext,
@@ -313,7 +313,7 @@
@Test
public void getAppUsageEventForUsers_nullCursor_returnEmptyMap() {
- DatabaseUtils.sFakeAppUsageEventSupplier = () -> null;
+ DatabaseUtils.sFakeSupplier = () -> null;
assertThat(DatabaseUtils.getAppUsageEventForUsers(
mContext,
/*calendar=*/ null,
@@ -335,7 +335,7 @@
cursor.addRow(new Object[] {101L, "app name2", timestamp2});
cursor.addRow(new Object[] {101L, "app name3", timestamp2});
cursor.addRow(new Object[] {101L, "app name4", timestamp2});
- DatabaseUtils.sFakeAppUsageEventSupplier = () -> cursor;
+ DatabaseUtils.sFakeSupplier = () -> cursor;
final List<AppUsageEvent> appUsageEventList = DatabaseUtils.getAppUsageEventForUsers(
mContext,
@@ -356,7 +356,7 @@
BatteryHistEntry.KEY_UID,
BatteryHistEntry.KEY_USER_ID,
BatteryHistEntry.KEY_TIMESTAMP});
- DatabaseUtils.sFakeBatteryStateSupplier = () -> cursor;
+ DatabaseUtils.sFakeSupplier = () -> cursor;
assertThat(DatabaseUtils.getHistoryMapSinceLastFullCharge(
mContext, /*calendar=*/ null)).isEmpty();
@@ -364,7 +364,7 @@
@Test
public void getHistoryMapSinceLastFullCharge_nullCursor_returnEmptyMap() {
- DatabaseUtils.sFakeBatteryStateSupplier = () -> null;
+ DatabaseUtils.sFakeSupplier = () -> null;
assertThat(DatabaseUtils.getHistoryMapSinceLastFullCharge(
mContext, /*calendar=*/ null)).isEmpty();
}
@@ -383,7 +383,7 @@
"app name3", timestamp2, 3, ConvertUtils.CONSUMER_TYPE_UID_BATTERY});
cursor.addRow(new Object[] {
"app name4", timestamp2, 4, ConvertUtils.CONSUMER_TYPE_UID_BATTERY});
- DatabaseUtils.sFakeBatteryStateSupplier = () -> cursor;
+ DatabaseUtils.sFakeSupplier = () -> cursor;
final Map<Long, Map<String, BatteryHistEntry>> batteryHistMap =
DatabaseUtils.getHistoryMapSinceLastFullCharge(
@@ -413,7 +413,7 @@
doReturn(true).when(mUserManager).isManagedProfile();
doReturn(UserHandle.SYSTEM).when(mUserManager).getProfileParent(UserHandle.CURRENT);
- DatabaseUtils.sFakeBatteryStateSupplier = () -> getMatrixCursor();
+ DatabaseUtils.sFakeSupplier = () -> getMatrixCursor();
final Map<Long, Map<String, BatteryHistEntry>> batteryHistMap =
DatabaseUtils.getHistoryMapSinceLastFullCharge(
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 0c2bbf5..fb64023 100644
--- a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSettingsTest.java
@@ -156,6 +156,16 @@
}
@Test
+ public void onSecuritySummaryChanged_canNotShowWifiHotspot_returnFalse() {
+ int stringResId = R.string.wifi_security_sae;
+ mWifiTetherSettings.mWifiHotspotSecurity = mock(Preference.class);
+
+ mWifiTetherSettings.onSecuritySummaryChanged(stringResId);
+
+ verify(mWifiTetherSettings.mWifiHotspotSecurity).setSummary(stringResId);
+ }
+
+ @Test
public void onSpeedSummaryChanged_canNotShowWifiHotspot_returnFalse() {
int stringResId = R.string.wifi_hotspot_speed_summary_6g;
mWifiTetherSettings.mWifiHotspotSpeed = mock(Preference.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 b75f9fc..dbbdfec 100644
--- a/tests/unit/src/com/android/settings/wifi/repository/WifiHotspotRepositoryTest.java
+++ b/tests/unit/src/com/android/settings/wifi/repository/WifiHotspotRepositoryTest.java
@@ -18,7 +18,9 @@
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 com.android.settings.wifi.repository.WifiHotspotRepository.BAND_2GHZ_5GHZ;
@@ -32,6 +34,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
@@ -81,6 +84,8 @@
@Mock
WifiManager mWifiManager;
@Mock
+ MutableLiveData<Integer> mSecurityType;
+ @Mock
MutableLiveData<Integer> mSpeedType;
WifiHotspotRepository mWifiHotspotRepository;
@@ -93,6 +98,7 @@
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;
@@ -156,6 +162,7 @@
@Test
public void refresh_liveDataNotUsed_doNothing() {
// If LiveData is not used then it's null.
+ mWifiHotspotRepository.mSecurityType = null;
mWifiHotspotRepository.mSpeedType = null;
mWifiHotspotRepository.refresh();
@@ -169,7 +176,7 @@
mWifiHotspotRepository.refresh();
- verify(mWifiManager).getSoftApConfiguration();
+ verify(mWifiManager, atLeast(1)).getSoftApConfiguration();
verify(mSpeedType).setValue(anyInt());
}
@@ -193,6 +200,105 @@
@Test
@UiThreadTest
+ public void getSecurityType_shouldNotReturnNull() {
+ // If LiveData is not used then it's null.
+ mWifiHotspotRepository.mSecurityType = null;
+ mockConfigSecurityType(SECURITY_TYPE_OPEN);
+
+ assertThat(mWifiHotspotRepository.getSecurityType()).isNotNull();
+ }
+
+ @Test
+ public void updateSecurityType_securityTypeOpen_setValueCorrectly() {
+ mockConfigSecurityType(SECURITY_TYPE_OPEN);
+
+ mWifiHotspotRepository.updateSecurityType();
+
+ verify(mSecurityType).setValue(SECURITY_TYPE_OPEN);
+ }
+
+ @Test
+ public void updateSecurityType_securityTypeWpa2_setValueCorrectly() {
+ mockConfigSecurityType(SECURITY_TYPE_WPA2_PSK);
+
+ mWifiHotspotRepository.updateSecurityType();
+
+ verify(mSecurityType).setValue(SECURITY_TYPE_WPA2_PSK);
+ }
+
+ @Test
+ public void updateSecurityType_securityTypeWpa2Wpa3_setValueCorrectly() {
+ mockConfigSecurityType(SECURITY_TYPE_WPA3_SAE_TRANSITION);
+
+ mWifiHotspotRepository.updateSecurityType();
+
+ verify(mSecurityType).setValue(SECURITY_TYPE_WPA3_SAE_TRANSITION);
+ }
+
+ @Test
+ public void updateSecurityType_securityTypeWpa3_setValueCorrectly() {
+ mockConfigSecurityType(SECURITY_TYPE_WPA3_SAE);
+
+ mWifiHotspotRepository.updateSecurityType();
+
+ verify(mSecurityType).setValue(SECURITY_TYPE_WPA3_SAE);
+ }
+
+ @Test
+ public void setSecurityType_sameValue_doNotSetConfig() {
+ mockConfigSecurityType(SECURITY_TYPE_WPA3_SAE);
+
+ mWifiHotspotRepository.setSecurityType(SECURITY_TYPE_WPA3_SAE);
+
+ verify(mWifiManager, never()).setSoftApConfiguration(any());
+ }
+
+ @Test
+ public void setSecurityType_wpa3ToWpa2Wpa3_setConfigCorrectly() {
+ mockConfigSecurityType(SECURITY_TYPE_WPA3_SAE);
+
+ mWifiHotspotRepository.setSecurityType(SECURITY_TYPE_WPA3_SAE_TRANSITION);
+
+ verify(mWifiManager).setSoftApConfiguration(mSoftApConfigCaptor.capture());
+ assertThat(mSoftApConfigCaptor.getValue().getSecurityType())
+ .isEqualTo(SECURITY_TYPE_WPA3_SAE_TRANSITION);
+ }
+
+ @Test
+ public void setSecurityType_Wpa2Wpa3ToWpa2_setConfigCorrectly() {
+ mockConfigSecurityType(SECURITY_TYPE_WPA3_SAE_TRANSITION);
+
+ mWifiHotspotRepository.setSecurityType(SECURITY_TYPE_WPA2_PSK);
+
+ verify(mWifiManager).setSoftApConfiguration(mSoftApConfigCaptor.capture());
+ assertThat(mSoftApConfigCaptor.getValue().getSecurityType())
+ .isEqualTo(SECURITY_TYPE_WPA2_PSK);
+ }
+
+ @Test
+ public void setSecurityType_Wpa2ToOpen_setConfigCorrectly() {
+ mockConfigSecurityType(SECURITY_TYPE_WPA2_PSK);
+
+ mWifiHotspotRepository.setSecurityType(SECURITY_TYPE_OPEN);
+
+ verify(mWifiManager).setSoftApConfiguration(mSoftApConfigCaptor.capture());
+ assertThat(mSoftApConfigCaptor.getValue().getSecurityType())
+ .isEqualTo(SECURITY_TYPE_OPEN);
+ }
+
+ @Test
+ public void setSecurityType_OpenToWpa3_setConfigCorrectly() {
+ mockConfigSecurityType(SECURITY_TYPE_OPEN);
+
+ mWifiHotspotRepository.setSecurityType(SECURITY_TYPE_WPA3_SAE);
+
+ verify(mWifiManager).setSoftApConfiguration(mSoftApConfigCaptor.capture());
+ assertThat(mSoftApConfigCaptor.getValue().getSecurityType())
+ .isEqualTo(SECURITY_TYPE_WPA3_SAE);
+ }
+
+ @Test
+ @UiThreadTest
public void getSpeedType_shouldNotReturnNull() {
// If LiveData is not used then it's null.
mWifiHotspotRepository.mSpeedType = null;
@@ -312,8 +418,8 @@
}
@Test
- public void setSpeedType_from2g5ghz_setConfigBandTo6ghzPreferred() {
- mockGetSoftApConfiguration(SPEED_2GHZ_5GHZ);
+ public void setSpeedType_2g5ghzTo6ghz_setConfigBandTo6ghzPreferred() {
+ mockConfigSpeedType(SPEED_2GHZ_5GHZ);
mWifiHotspotRepository.setSpeedType(SPEED_6GHZ);
@@ -322,8 +428,19 @@
}
@Test
- public void setSpeedType_from6ghz_setConfigBandsTo2g5ghz() {
- mockGetSoftApConfiguration(SPEED_6GHZ);
+ public void setSpeedType_2g5ghzTo6ghz_setConfigSecurityToWpa3() {
+ mockConfig(SPEED_2GHZ_5GHZ, SECURITY_TYPE_WPA3_SAE_TRANSITION);
+
+ mWifiHotspotRepository.setSpeedType(SPEED_6GHZ);
+
+ verify(mWifiManager).setSoftApConfiguration(mSoftApConfigCaptor.capture());
+ assertThat(mSoftApConfigCaptor.getValue().getSecurityType())
+ .isEqualTo(SECURITY_TYPE_WPA3_SAE);
+ }
+
+ @Test
+ public void setSpeedType_6ghzTo2g5ghz_setConfigBandsTo2g5ghz() {
+ mockConfigSpeedType(SPEED_6GHZ);
mWifiHotspotRepository.mIsDualBand = true;
mWifiHotspotRepository.setSpeedType(SPEED_2GHZ_5GHZ);
@@ -335,8 +452,8 @@
}
@Test
- public void setSpeedType_from2ghz_setConfigBandTo5ghzPreferred() {
- mockGetSoftApConfiguration(SPEED_2GHZ);
+ public void setSpeedType_2ghzTo5ghz_setConfigBandTo5ghzPreferred() {
+ mockConfigSpeedType(SPEED_2GHZ);
mWifiHotspotRepository.setSpeedType(SPEED_5GHZ);
@@ -345,8 +462,8 @@
}
@Test
- public void setSpeedType_from5ghz_setConfigBandTo6ghzPreferred() {
- mockGetSoftApConfiguration(SPEED_5GHZ);
+ public void setSpeedType_5ghzTo6ghz_setConfigBandTo6ghzPreferred() {
+ mockConfigSpeedType(SPEED_5GHZ);
mWifiHotspotRepository.setSpeedType(SPEED_6GHZ);
@@ -355,8 +472,8 @@
}
@Test
- public void setSpeedType_from5gTo6ghz_setConfigBandTo2ghz() {
- mockGetSoftApConfiguration(SPEED_6GHZ);
+ public void setSpeedType_6ghzTo2ghz_setConfigBandTo2ghz() {
+ mockConfigSpeedType(SPEED_6GHZ);
mWifiHotspotRepository.setSpeedType(SPEED_2GHZ);
@@ -475,10 +592,24 @@
assertThat(mWifiHotspotRepository.get6gAvailable()).isNotNull();
}
- private void mockGetSoftApConfiguration(int speedType) {
+ private void mockConfigSecurityType(int securityType) {
+ mockConfig(securityType, SPEED_2GHZ);
+ }
+
+ private void mockConfigSpeedType(int speedType) {
+ mockConfig(SECURITY_TYPE_WPA3_SAE, speedType);
+ }
+
+ private void mockConfig(int securityType, int speedType) {
+ SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder();
+ // Security Type
+ doReturn(securityType).when(mSecurityType).getValue();
+ String passphrase = (securityType == SECURITY_TYPE_OPEN) ? null : WIFI_PASSWORD;
+ configBuilder.setPassphrase(passphrase, securityType).build();
+
+ // Speed Type
doReturn(speedType).when(mSpeedType).getValue();
mWifiHotspotRepository.mIsDualBand = true;
- SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder();
if (speedType == SPEED_2GHZ) {
mWifiHotspotRepository.mIsDualBand = false;
configBuilder.setBand(BAND_2GHZ);
diff --git a/tests/unit/src/com/android/settings/wifi/tether/WifiHotspotSecuritySettingsTest.java b/tests/unit/src/com/android/settings/wifi/tether/WifiHotspotSecuritySettingsTest.java
new file mode 100644
index 0000000..511240e
--- /dev/null
+++ b/tests/unit/src/com/android/settings/wifi/tether/WifiHotspotSecuritySettingsTest.java
@@ -0,0 +1,173 @@
+/*
+ * 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.wifi.tether;
+
+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 com.android.settings.wifi.tether.WifiHotspotSecurityViewModel.KEY_SECURITY_NONE;
+import static com.android.settings.wifi.tether.WifiHotspotSecurityViewModel.KEY_SECURITY_WPA2;
+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.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.settingslib.widget.SelectorWithWidgetPreference;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class WifiHotspotSecuritySettingsTest {
+ @Rule
+ public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+ @Mock
+ WifiHotspotSecurityViewModel mViewModel;
+ @Mock
+ SelectorWithWidgetPreference mRadioButtonWpa3;
+ @Mock
+ SelectorWithWidgetPreference mRadioButtonWpa2Wpa3;
+ @Mock
+ SelectorWithWidgetPreference mRadioButtonWpa2;
+ @Mock
+ SelectorWithWidgetPreference mRadioButtonNone;
+
+ Map<Integer, WifiHotspotSecurityViewModel.ViewItem> mViewItemMap = new HashMap<>();
+ WifiHotspotSecurityViewModel.ViewItem mViewItemWpa3 =
+ new WifiHotspotSecurityViewModel.ViewItem(KEY_SECURITY_WPA3);
+ WifiHotspotSecurityViewModel.ViewItem mViewItemWpa2Wpa3 =
+ new WifiHotspotSecurityViewModel.ViewItem(KEY_SECURITY_WPA2_WPA3);
+ WifiHotspotSecurityViewModel.ViewItem mViewItemWpa2 =
+ new WifiHotspotSecurityViewModel.ViewItem(KEY_SECURITY_WPA2);
+ WifiHotspotSecurityViewModel.ViewItem mViewItemNone =
+ new WifiHotspotSecurityViewModel.ViewItem(KEY_SECURITY_NONE);
+
+ WifiHotspotSecuritySettings mSettings;
+
+ @Before
+ public void setUp() {
+ mViewItemMap.put(SECURITY_TYPE_WPA3_SAE, mViewItemWpa3);
+ mViewItemMap.put(SECURITY_TYPE_WPA3_SAE_TRANSITION, mViewItemWpa2Wpa3);
+ mViewItemMap.put(SECURITY_TYPE_WPA2_PSK, mViewItemWpa2);
+ mViewItemMap.put(SECURITY_TYPE_OPEN, mViewItemNone);
+
+ when(mRadioButtonWpa3.getKey()).thenReturn(KEY_SECURITY_WPA3);
+ when(mRadioButtonWpa2Wpa3.getKey()).thenReturn(KEY_SECURITY_WPA2_WPA3);
+ when(mRadioButtonWpa2.getKey()).thenReturn(KEY_SECURITY_WPA2);
+ when(mRadioButtonNone.getKey()).thenReturn(KEY_SECURITY_NONE);
+
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(
+ () -> mSettings = spy(new WifiHotspotSecuritySettings()));
+ mSettings.mWifiHotspotSecurityViewModel = mViewModel;
+ when(mSettings.findPreference(KEY_SECURITY_WPA3)).thenReturn(mRadioButtonWpa3);
+ when(mSettings.findPreference(KEY_SECURITY_WPA2_WPA3)).thenReturn(mRadioButtonWpa2Wpa3);
+ when(mSettings.findPreference(KEY_SECURITY_WPA2)).thenReturn(mRadioButtonWpa2);
+ when(mSettings.findPreference(KEY_SECURITY_NONE)).thenReturn(mRadioButtonNone);
+ }
+
+ @Test
+ public void onViewItemListDataChanged_checkedWpa3_setViewItemCorrectly() {
+ mViewItemWpa3.mIsChecked = true;
+
+ mSettings.onViewItemListDataChanged(mViewItemMap.values().stream().toList());
+
+ verify(mRadioButtonWpa3).setChecked(true);
+ }
+
+ @Test
+ public void onViewItemListDataChanged_checkedWpa2Wpa3_setViewItemCorrectly() {
+ mViewItemWpa2Wpa3.mIsChecked = true;
+
+ mSettings.onViewItemListDataChanged(mViewItemMap.values().stream().toList());
+
+ verify(mRadioButtonWpa2Wpa3).setChecked(true);
+ }
+
+ @Test
+ public void onViewItemListDataChanged_checkedWpa2_setViewItemCorrectly() {
+ mViewItemWpa2.mIsChecked = true;
+
+ mSettings.onViewItemListDataChanged(mViewItemMap.values().stream().toList());
+
+ verify(mRadioButtonWpa2).setChecked(true);
+ }
+
+ @Test
+ public void onViewItemListDataChanged_checkedNone_setViewItemCorrectly() {
+ mViewItemNone.mIsChecked = true;
+
+ mSettings.onViewItemListDataChanged(mViewItemMap.values().stream().toList());
+
+ verify(mRadioButtonNone).setChecked(true);
+ }
+
+ @Test
+ public void onViewItemListDataChanged_enabledWpa3Only_setViewItemCorrectly() {
+ when(mRadioButtonWpa2Wpa3.isEnabled()).thenReturn(true);
+ when(mRadioButtonWpa2.isEnabled()).thenReturn(true);
+ when(mRadioButtonNone.isEnabled()).thenReturn(true);
+ mViewItemWpa2Wpa3.mIsEnabled = false;
+ mViewItemWpa2.mIsEnabled = false;
+ mViewItemNone.mIsEnabled = false;
+
+ mSettings.onViewItemListDataChanged(mViewItemMap.values().stream().toList());
+
+ verify(mRadioButtonWpa2Wpa3).setEnabled(false);
+ verify(mRadioButtonWpa2).setEnabled(false);
+ verify(mRadioButtonNone).setEnabled(false);
+ }
+
+ @Test
+ public void onRadioButtonClicked_clickedWpa3_setSecurityTypeCorrectly() {
+ mSettings.onRadioButtonClicked(mRadioButtonWpa3);
+
+ verify(mViewModel).handleRadioButtonClicked(KEY_SECURITY_WPA3);
+ }
+
+ @Test
+ public void onRadioButtonClicked_clickedWpa2Wpa3_setSecurityTypeCorrectly() {
+ mSettings.onRadioButtonClicked(mRadioButtonWpa2Wpa3);
+
+ verify(mViewModel).handleRadioButtonClicked(KEY_SECURITY_WPA2_WPA3);
+ }
+
+ @Test
+ public void onRadioButtonClicked_clickedWpa2_setSecurityTypeCorrectly() {
+ mSettings.onRadioButtonClicked(mRadioButtonWpa2);
+
+ verify(mViewModel).handleRadioButtonClicked(KEY_SECURITY_WPA2);
+ }
+
+ @Test
+ public void onRadioButtonClicked_clickedNone_setSecurityTypeCorrectly() {
+ mSettings.onRadioButtonClicked(mRadioButtonNone);
+
+ verify(mViewModel).handleRadioButtonClicked(KEY_SECURITY_NONE);
+ }
+}
diff --git a/tests/unit/src/com/android/settings/wifi/tether/WifiHotspotSecurityViewModelTest.java b/tests/unit/src/com/android/settings/wifi/tether/WifiHotspotSecurityViewModelTest.java
new file mode 100644
index 0000000..db768c7
--- /dev/null
+++ b/tests/unit/src/com/android/settings/wifi/tether/WifiHotspotSecurityViewModelTest.java
@@ -0,0 +1,211 @@
+/*
+ * 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.wifi.tether;
+
+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 com.android.settings.wifi.repository.WifiHotspotRepository.SPEED_2GHZ;
+import static com.android.settings.wifi.repository.WifiHotspotRepository.SPEED_2GHZ_5GHZ;
+import static com.android.settings.wifi.repository.WifiHotspotRepository.SPEED_5GHZ;
+import static com.android.settings.wifi.repository.WifiHotspotRepository.SPEED_6GHZ;
+import static com.android.settings.wifi.tether.WifiHotspotSecurityViewModel.KEY_SECURITY_NONE;
+import static com.android.settings.wifi.tether.WifiHotspotSecurityViewModel.KEY_SECURITY_WPA2;
+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 com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.Application;
+import android.content.Context;
+
+import androidx.lifecycle.MutableLiveData;
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.wifi.repository.WifiHotspotRepository;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+@UiThreadTest
+public class WifiHotspotSecurityViewModelTest {
+ @Rule
+ public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+ @Spy
+ Context mContext = ApplicationProvider.getApplicationContext();
+ @Mock
+ WifiHotspotRepository mWifiHotspotRepository;
+ @Mock
+ MutableLiveData<Integer> mSecurityType;
+ @Mock
+ MutableLiveData<Integer> mSpeedType;
+
+ WifiHotspotSecurityViewModel mViewModel;
+
+ @Before
+ public void setUp() {
+ FakeFeatureFactory featureFactory = FakeFeatureFactory.setupForTest();
+ when(featureFactory.getWifiFeatureProvider().getWifiHotspotRepository())
+ .thenReturn(mWifiHotspotRepository);
+ when(mWifiHotspotRepository.getSecurityType()).thenReturn(mSecurityType);
+ when(mWifiHotspotRepository.getSpeedType()).thenReturn(mSpeedType);
+
+ mViewModel = new WifiHotspotSecurityViewModel((Application) mContext);
+ }
+
+ @Test
+ public void constructor_observeDataAndSetAutoRefresh() {
+ verify(mSecurityType).observeForever(mViewModel.mSecurityTypeObserver);
+ verify(mSpeedType).observeForever(mViewModel.mSpeedTypeObserver);
+ }
+
+ @Test
+ public void onCleared_removeObserverData() {
+ mViewModel.onCleared();
+
+ verify(mSecurityType).removeObserver(mViewModel.mSecurityTypeObserver);
+ verify(mSpeedType).removeObserver(mViewModel.mSpeedTypeObserver);
+ }
+
+ @Test
+ public void onSecurityTypeChanged_securityTypeWpa3_setCheckedCorrectly() {
+ mViewModel.onSecurityTypeChanged(SECURITY_TYPE_WPA3_SAE);
+
+ assertItemChecked(true, false, false, false);
+ }
+
+ @Test
+ public void onSecurityTypeChanged_securityTypeWpa2Wpa3_setCheckedCorrectly() {
+ mViewModel.onSecurityTypeChanged(SECURITY_TYPE_WPA3_SAE_TRANSITION);
+
+ assertItemChecked(false, true, false, false);
+ }
+
+ @Test
+ public void onSecurityTypeChanged_securityTypeWpa2_setCheckedCorrectly() {
+ mViewModel.onSecurityTypeChanged(SECURITY_TYPE_WPA2_PSK);
+
+ assertItemChecked(false, false, true, false);
+ }
+
+ @Test
+ public void onSecurityTypeChanged_securityTypeNone_setCheckedCorrectly() {
+ mViewModel.onSecurityTypeChanged(SECURITY_TYPE_OPEN);
+
+ assertItemChecked(false, false, false, true);
+ }
+
+ @Test
+ public void onSpeedTypeChanged_speed6g_setEnabledCorrectly() {
+ mViewModel.onSpeedTypeChanged(SPEED_6GHZ);
+
+ assertItemEnabled(true, false, false, false);
+ }
+
+ @Test
+ public void onSpeedTypeChanged_speed2g5g_setEnabledCorrectly() {
+ mViewModel.onSpeedTypeChanged(SPEED_2GHZ_5GHZ);
+
+ assertItemEnabled(true, true, true, true);
+ }
+
+ @Test
+ public void onSpeedTypeChanged_speed5g_setEnabledCorrectly() {
+ mViewModel.onSpeedTypeChanged(SPEED_5GHZ);
+
+ assertItemEnabled(true, true, true, true);
+ }
+
+ @Test
+ public void onSpeedTypeChanged_speed2g_setEnabledCorrectly() {
+ mViewModel.onSpeedTypeChanged(SPEED_2GHZ);
+
+ assertItemEnabled(true, true, true, true);
+ }
+
+ @Test
+ public void handleRadioButtonClicked_keyWpa3_setSecurityTypeCorrectly() {
+ mViewModel.handleRadioButtonClicked(KEY_SECURITY_WPA3);
+
+ verify(mWifiHotspotRepository).setSecurityType(SECURITY_TYPE_WPA3_SAE);
+ }
+
+ @Test
+ public void handleRadioButtonClicked_keyWpa2Wpa3_setSecurityTypeCorrectly() {
+ mViewModel.handleRadioButtonClicked(KEY_SECURITY_WPA2_WPA3);
+
+ verify(mWifiHotspotRepository).setSecurityType(SECURITY_TYPE_WPA3_SAE_TRANSITION);
+ }
+
+ @Test
+ public void handleRadioButtonClicked_keyWpa2_setSecurityTypeCorrectly() {
+ mViewModel.handleRadioButtonClicked(KEY_SECURITY_WPA2);
+
+ verify(mWifiHotspotRepository).setSecurityType(SECURITY_TYPE_WPA2_PSK);
+ }
+
+ @Test
+ public void handleRadioButtonClicked_keyNone_setSecurityTypeCorrectly() {
+ mViewModel.handleRadioButtonClicked(KEY_SECURITY_NONE);
+
+ verify(mWifiHotspotRepository).setSecurityType(SECURITY_TYPE_OPEN);
+ }
+
+ @Test
+ public void getViewItemListData_shouldNotReturnNull() {
+ // Reset mViewInfoListData to trigger an update
+ mViewModel.mViewInfoListData = null;
+
+ assertThat(mViewModel.getViewItemListData()).isNotNull();
+ }
+
+ private void assertItemChecked(boolean checkedWpa3, boolean checkedWpa2Wpa3,
+ boolean checkedWpa2, boolean checkedNone) {
+ assertThat(mViewModel.mViewItemMap.get(SECURITY_TYPE_WPA3_SAE).mIsChecked)
+ .isEqualTo(checkedWpa3);
+ assertThat(mViewModel.mViewItemMap.get(SECURITY_TYPE_WPA3_SAE_TRANSITION).mIsChecked)
+ .isEqualTo(checkedWpa2Wpa3);
+ assertThat(mViewModel.mViewItemMap.get(SECURITY_TYPE_WPA2_PSK).mIsChecked)
+ .isEqualTo(checkedWpa2);
+ assertThat(mViewModel.mViewItemMap.get(SECURITY_TYPE_OPEN).mIsChecked)
+ .isEqualTo(checkedNone);
+ }
+
+ private void assertItemEnabled(boolean enabledWpa3, boolean enabledWpa2Wpa3,
+ boolean enabledWpa2, boolean enabledNone) {
+ assertThat(mViewModel.mViewItemMap.get(SECURITY_TYPE_WPA3_SAE).mIsEnabled)
+ .isEqualTo(enabledWpa3);
+ assertThat(mViewModel.mViewItemMap.get(SECURITY_TYPE_WPA3_SAE_TRANSITION).mIsEnabled)
+ .isEqualTo(enabledWpa2Wpa3);
+ assertThat(mViewModel.mViewItemMap.get(SECURITY_TYPE_WPA2_PSK).mIsEnabled)
+ .isEqualTo(enabledWpa2);
+ assertThat(mViewModel.mViewItemMap.get(SECURITY_TYPE_OPEN).mIsEnabled)
+ .isEqualTo(enabledNone);
+ }
+}
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 6724dd5..4c8ce5b 100644
--- a/tests/unit/src/com/android/settings/wifi/tether/WifiTetherViewModelTest.java
+++ b/tests/unit/src/com/android/settings/wifi/tether/WifiTetherViewModelTest.java
@@ -52,6 +52,8 @@
@Mock
WifiHotspotRepository mWifiHotspotRepository;
@Mock
+ MutableLiveData<Integer> mSecurityType;
+ @Mock
MutableLiveData<Integer> mSpeedType;
WifiTetherViewModel mViewModel;
@@ -63,21 +65,18 @@
FakeFeatureFactory featureFactory = FakeFeatureFactory.setupForTest();
when(featureFactory.getWifiFeatureProvider().getWifiHotspotRepository())
.thenReturn(mWifiHotspotRepository);
+ when(mWifiHotspotRepository.getSecurityType()).thenReturn(mSecurityType);
when(mWifiHotspotRepository.getSpeedType()).thenReturn(mSpeedType);
mViewModel = new WifiTetherViewModel(mApplication);
}
@Test
- public void constructor_setAutoRefreshTrue() {
- verify(mWifiHotspotRepository).setAutoRefresh(true);
- }
-
- @Test
public void onCleared_setAutoRefreshFalse() {
mViewModel.onCleared();
- verify(mWifiHotspotRepository).setAutoRefresh(false);
+ verify(mSecurityType).removeObserver(mViewModel.mSecurityTypeObserver);
+ verify(mSpeedType).removeObserver(mViewModel.mSpeedTypeObserver);
}
@Test
@@ -98,11 +97,23 @@
@Test
@UiThreadTest
+ public void getSecuritySummary_returnNotNull() {
+ mViewModel.mSecuritySummary = null;
+
+ mViewModel.getSecuritySummary();
+
+ assertThat(mViewModel.mSecuritySummary).isNotNull();
+ verify(mSecurityType).observeForever(mViewModel.mSecurityTypeObserver);
+ }
+
+ @Test
+ @UiThreadTest
public void getSpeedSummary_returnNotNull() {
mViewModel.mSpeedSummary = null;
mViewModel.getSpeedSummary();
assertThat(mViewModel.mSpeedSummary).isNotNull();
+ verify(mSpeedType).observeForever(mViewModel.mSpeedTypeObserver);
}
}