Merge "Optimize DataUsagePreferenceController" into main
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 31f4768..9e33467 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -3198,6 +3198,7 @@
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="com.google.android.setupwizard.SETUP_WIZARD_FINISHED"/>
<action android:name="com.android.settings.battery.action.PERIODIC_JOB_RECHECK"/>
+ <action android:name="android.intent.action.TIME_SET"/>
</intent-filter>
</receiver>
diff --git a/res/layout/fingerprint_v2_enroll_introduction.xml b/res/layout/fingerprint_v2_enroll_introduction.xml
index e9dd08a..2fd1f9c 100644
--- a/res/layout/fingerprint_v2_enroll_introduction.xml
+++ b/res/layout/fingerprint_v2_enroll_introduction.xml
@@ -16,199 +16,210 @@
-->
<com.google.android.setupdesign.GlifLayout
-xmlns:android="http://schemas.android.com/apk/res/android"
-xmlns:app="http://schemas.android.com/apk/res-auto"
-style="?attr/fingerprint_layout_theme"
-android:id="@+id/setup_wizard_layout"
-android:layout_width="match_parent"
-android:layout_height="match_parent">
-
-<LinearLayout
- style="@style/SudContentFrame"
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/setup_wizard_layout"
+ style="?attr/fingerprint_layout_theme"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:orientation="vertical">
+ android:layout_height="match_parent">
- <com.google.android.setupdesign.view.RichTextView
- android:id="@+id/error_text"
- style="@style/SudDescription.Glif"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
-
- <FrameLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
-
- <ImageView
- style="@style/SudContentIllustration"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:contentDescription="@null"
- android:src="@drawable/fingerprint_enroll_introduction" />
-
- </FrameLayout>
-
- <!-- Contains the extra information text at the bottom -->
<LinearLayout
+ style="@style/SudContentFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:clipChildren="false"
+ android:clipToPadding="false"
android:orientation="vertical">
- <!-- How it works -->
- <TextView
+ <com.google.android.setupdesign.view.RichTextView
+ android:id="@+id/error_text"
+ style="@style/SudDescription.Glif"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- style="@style/BiometricEnrollIntroTitle"
- android:text="@string/security_settings_fingerprint_v2_enroll_introduction_footer_title_2" />
+ android:layout_height="wrap_content" />
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <ImageView
+ style="@style/SudContentIllustration"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:contentDescription="@null"
+ android:src="@drawable/fingerprint_enroll_introduction" />
+
+ </FrameLayout>
+
+ <!-- Contains the extra information text at the bottom -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="horizontal">
+ android:orientation="vertical">
- <ImageView
- android:id="@+id/icon_fingerprint"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:contentDescription="@null"
- android:src="@drawable/ic_fingerprint_24dp"/>
- <Space
- android:layout_width="16dp"
- android:layout_height="wrap_content"/>
+ <!-- How it works -->
<TextView
- android:id="@+id/footer_message_2"
+ style="@style/BiometricEnrollIntroTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- style="@style/BiometricEnrollIntroMessage" />
- </LinearLayout>
+ android:text="@string/security_settings_fingerprint_v2_enroll_introduction_footer_title_2" />
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal">
-
- <ImageView
- android:id="@+id/icon_device_locked"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:contentDescription="@null"
- android:src="@drawable/ic_lock_24dp"/>
- <Space
- android:layout_width="16dp"
- android:layout_height="wrap_content"/>
- <TextView
- android:id="@+id/footer_message_3"
+ <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- style="@style/BiometricEnrollIntroMessage" />
- </LinearLayout>
+ android:orientation="horizontal">
- <!-- You're in control -->
- <TextView
- android:id="@+id/footer_title_1"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- style="@style/BiometricEnrollIntroTitle" />
+ <ImageView
+ android:id="@+id/icon_fingerprint"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:contentDescription="@null"
+ android:src="@drawable/ic_fingerprint_24dp" />
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal">
+ <Space
+ android:layout_width="16dp"
+ android:layout_height="wrap_content" />
- <ImageView
- android:id="@+id/icon_trash_can"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:contentDescription="@null"
- android:src="@drawable/ic_trash_can"/>
- <Space
- android:layout_width="16dp"
- android:layout_height="wrap_content"/>
- <TextView
- android:id="@+id/footer_message_4"
+ <TextView
+ android:id="@+id/footer_message_2"
+ style="@style/BiometricEnrollIntroMessage"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+ </LinearLayout>
+
+ <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- style="@style/BiometricEnrollIntroMessage" />
- </LinearLayout>
+ android:orientation="horizontal">
- <!-- Keep in mind -->
- <TextView
- android:id="@+id/footer_title_2"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- style="@style/BiometricEnrollIntroTitle"
- android:text="@string/security_settings_face_enroll_introduction_info_title"/>
+ <ImageView
+ android:id="@+id/icon_device_locked"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:contentDescription="@null"
+ android:src="@drawable/ic_lock_24dp" />
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal">
+ <Space
+ android:layout_width="16dp"
+ android:layout_height="wrap_content" />
- <ImageView
- android:id="@+id/icon_info"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:contentDescription="@null"
- android:src="@drawable/ic_info_outline_24dp"/>
- <Space
- android:layout_width="16dp"
- android:layout_height="wrap_content"/>
+ <TextView
+ android:id="@+id/footer_message_3"
+ style="@style/BiometricEnrollIntroMessage"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+ </LinearLayout>
+
+ <!-- You're in control -->
<TextView
- android:id="@+id/footer_message_5"
+ android:id="@+id/footer_title_1"
+ style="@style/BiometricEnrollIntroTitle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+
+ <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- style="@style/BiometricEnrollIntroMessage" />
- </LinearLayout>
+ android:orientation="horizontal">
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal">
+ <ImageView
+ android:id="@+id/icon_trash_can"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:contentDescription="@null"
+ android:src="@drawable/ic_trash_can" />
- <ImageView
- android:id="@+id/icon_shield"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:contentDescription="@null"
- android:src="@drawable/ic_guarantee"/>
- <Space
- android:layout_width="16dp"
- android:layout_height="wrap_content"/>
+ <Space
+ android:layout_width="16dp"
+ android:layout_height="wrap_content" />
+
+ <TextView
+ android:id="@+id/footer_message_4"
+ style="@style/BiometricEnrollIntroMessage"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+ </LinearLayout>
+
+ <!-- Keep in mind -->
<TextView
- android:id="@+id/footer_message_6"
+ android:id="@+id/footer_title_2"
+ style="@style/BiometricEnrollIntroTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- style="@style/BiometricEnrollIntroMessage" />
- </LinearLayout>
+ android:text="@string/security_settings_face_enroll_introduction_info_title" />
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal">
-
- <ImageView
- android:id="@+id/icon_link"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:contentDescription="@null"
- android:src="@drawable/ic_link_24dp"/>
- <Space
- android:layout_width="16dp"
- android:layout_height="wrap_content"/>
- <TextView
- android:id="@+id/footer_learn_more"
- android:linksClickable="true"
+ <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- style="@style/BiometricEnrollIntroMessage"
- android:paddingBottom="0dp"
- android:text="@string/security_settings_fingerprint_v2_enroll_introduction_message_learn_more" />
+ android:orientation="horizontal">
+
+ <ImageView
+ android:id="@+id/icon_info"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:contentDescription="@null"
+ android:src="@drawable/ic_info_outline_24dp" />
+
+ <Space
+ android:layout_width="16dp"
+ android:layout_height="wrap_content" />
+
+ <TextView
+ android:id="@+id/footer_message_5"
+ style="@style/BiometricEnrollIntroMessage"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+
+ <ImageView
+ android:id="@+id/icon_shield"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:contentDescription="@null"
+ android:src="@drawable/ic_guarantee" />
+
+ <Space
+ android:layout_width="16dp"
+ android:layout_height="wrap_content" />
+
+ <TextView
+ android:id="@+id/footer_message_6"
+ style="@style/BiometricEnrollIntroMessage"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+
+ <ImageView
+ android:id="@+id/icon_link"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:contentDescription="@null"
+ android:src="@drawable/ic_link_24dp" />
+
+ <Space
+ android:layout_width="16dp"
+ android:layout_height="wrap_content" />
+
+ <TextView
+ android:id="@+id/footer_learn_more"
+ style="@style/BiometricEnrollIntroMessage"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:linksClickable="true"
+ android:paddingBottom="0dp"
+ android:text="@string/security_settings_fingerprint_v2_enroll_introduction_message_learn_more" />
+ </LinearLayout>
+
</LinearLayout>
</LinearLayout>
-</LinearLayout>
-
</com.google.android.setupdesign.GlifLayout>
\ No newline at end of file
diff --git a/res/layout/preference_icon_credman.xml b/res/layout/preference_icon_credman.xml
new file mode 100644
index 0000000..3db0c3b
--- /dev/null
+++ b/res/layout/preference_icon_credman.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<!-- Based off preference_material_settings.xml except that ripple on only on the left side. -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="?android:attr/listPreferredItemHeightSmall"
+ android:gravity="center_vertical"
+ android:background="@android:color/transparent"
+ android:clipToPadding="false">
+
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:background="?android:attr/selectableItemBackground"
+ android:gravity="start|center_vertical"
+ android:clipToPadding="false"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
+
+ <LinearLayout
+ android:id="@+id/icon_frame"
+ android:layout_width="48dp"
+ android:layout_height="40dp"
+ android:gravity="start|center_vertical"
+ android:minWidth="56dp"
+ android:orientation="horizontal"
+ android:clipToPadding="false"
+ android:paddingTop="4dp"
+ android:paddingBottom="4dp">
+ <androidx.preference.internal.PreferenceImageView
+ android:id="@android:id/icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ settings:maxWidth="32dp"
+ settings:maxHeight="32dp" />
+ </LinearLayout>
+
+ <RelativeLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:paddingTop="16dp"
+ android:paddingBottom="16dp">
+
+ <TextView
+ android:id="@android:id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:textAppearance="?android:attr/textAppearanceListItem"
+ android:ellipsize="marquee" />
+
+ <TextView
+ android:id="@android:id/summary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@android:id/title"
+ android:layout_alignStart="@android:id/title"
+ android:textAppearance="?android:attr/textAppearanceListItemSecondary"
+ android:textColor="?android:attr/textColorSecondary"
+ android:maxLines="10" />
+
+ </RelativeLayout>
+
+ </LinearLayout>
+
+ <include layout="@layout/preference_two_target_divider" />
+
+ <!-- Preference should place its actual preference widget here. -->
+ <LinearLayout
+ android:id="@android:id/widget_frame"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:paddingEnd="16dp"
+ android:minWidth="61dp"
+ android:gravity="center"
+ android:orientation="vertical" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 4946be5..1bbecc0 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -6184,6 +6184,8 @@
<string name="account_settings_menu_auto_sync_personal">Auto-sync personal data</string>
<!-- Title for menu option to enable global auto-sync of work account data [CHAR LIMIT=30] -->
<string name="account_settings_menu_auto_sync_work">Auto-sync work data</string>
+ <!-- Title for menu option to enable global auto-sync of private account data [CHAR LIMIT=30] -->
+ <string name="account_settings_menu_auto_sync_private">Auto-sync private data</string>
<!-- Title for option to change data usage cycle day. [CHAR LIMIT=32] -->
<string name="data_usage_change_cycle">Change cycle\u2026</string>
diff --git a/res/xml/accounts_private_dashboard_settings.xml b/res/xml/accounts_private_dashboard_settings.xml
new file mode 100644
index 0000000..79bcce9
--- /dev/null
+++ b/res/xml/accounts_private_dashboard_settings.xml
@@ -0,0 +1,66 @@
+<?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:key="user_and_account_settings_screen"
+ android:title="@string/account_dashboard_title"
+ settings:keywords="@string/keywords_accounts">
+
+ <PreferenceCategory
+ android:key="passwords_category"
+ android:order="10"
+ android:persistent="false"
+ android:title="@string/autofill_passwords"
+ settings:controller="com.android.settings.applications.autofill.PasswordsPreferenceController"
+ settings:keywords="@string/autofill_keywords" />
+
+ <PreferenceCategory
+ android:key="default_service_category"
+ android:order="20"
+ android:title="@string/autofill_app">
+
+ <com.android.settings.widget.GearPreference
+ android:fragment="com.android.settings.applications.defaultapps.DefaultAutofillPicker"
+ android:key="default_autofill_private"
+ android:title="@string/autofill_app"
+ settings:keywords="@string/autofill_keywords">
+ <extra
+ android:name="for_work"
+ android:value="false" />
+ </com.android.settings.widget.GearPreference>
+ </PreferenceCategory>
+
+ <PreferenceCategory
+ android:key="dashboard_tile_placeholder"
+ android:order="130"/>
+
+ <SwitchPreference
+ android:key="auto_sync_account_data"
+ android:title="@string/auto_sync_account_title"
+ android:summary="@string/auto_sync_account_summary"
+ android:order="200"
+ settings:allowDividerAbove="true"/>
+
+ <SwitchPreference
+ android:key="auto_sync_private_account_data"
+ android:title="@string/account_settings_menu_auto_sync_private"
+ android:summary="@string/auto_sync_account_summary"
+ android:order="210"/>
+
+</PreferenceScreen>
diff --git a/res/xml/accounts_private_dashboard_settings_credman.xml b/res/xml/accounts_private_dashboard_settings_credman.xml
new file mode 100644
index 0000000..88b2736
--- /dev/null
+++ b/res/xml/accounts_private_dashboard_settings_credman.xml
@@ -0,0 +1,67 @@
+<?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:key="user_and_account_settings_screen"
+ android:title="@string/account_dashboard_title"
+ settings:keywords="@string/keywords_accounts">
+
+ <PreferenceCategory
+ android:key="default_service_category"
+ android:order="10"
+ android:title="@string/credman_chosen_app_title">
+
+ <com.android.settings.widget.GearPreference
+ android:fragment="com.android.settings.applications.credentials.DefaultCombinedPickerPrivate"
+ android:key="default_credman_autofill_private"
+ android:title="@string/credman_chosen_app_title"
+ settings:searchable="false">
+ settings:keywords="@string/credman_autofill_keywords">
+ <extra
+ android:name="for_work"
+ android:value="false" />
+ </com.android.settings.widget.GearPreference>
+ </PreferenceCategory>
+
+ <PreferenceCategory
+ android:key="credman_category"
+ android:order="20"
+ android:persistent="false"
+ android:title="@string/credman_credentials"
+ settings:controller="com.android.settings.applications.credentials.CredentialManagerPreferenceController"
+ settings:keywords="@string/credman_keywords" />
+
+ <PreferenceCategory
+ android:key="dashboard_tile_placeholder"
+ android:order="130"/>
+
+ <SwitchPreference
+ android:key="auto_sync_account_data"
+ android:title="@string/auto_sync_account_title"
+ android:summary="@string/auto_sync_account_summary"
+ android:order="200"
+ settings:allowDividerAbove="true"/>
+
+ <SwitchPreference
+ android:key="auto_sync_private_account_data"
+ android:title="@string/account_settings_menu_auto_sync_private"
+ android:summary="@string/auto_sync_account_summary"
+ android:order="210"/>
+
+</PreferenceScreen>
\ No newline at end of file
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index b41650c..29eabdb 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -18,6 +18,9 @@
import static android.content.Intent.EXTRA_USER;
import static android.content.Intent.EXTRA_USER_ID;
+import static android.os.UserManager.USER_TYPE_FULL_SYSTEM;
+import static android.os.UserManager.USER_TYPE_PROFILE_MANAGED;
+import static android.os.UserManager.USER_TYPE_PROFILE_PRIVATE;
import static android.text.format.DateUtils.FORMAT_ABBREV_MONTH;
import static android.text.format.DateUtils.FORMAT_SHOW_DATE;
@@ -63,6 +66,7 @@
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
+import android.os.Flags;
import android.os.IBinder;
import android.os.INetworkManagementService;
import android.os.RemoteException;
@@ -111,6 +115,7 @@
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.dashboard.profileselector.ProfileFragmentBridge;
import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
+import com.android.settings.dashboard.profileselector.ProfileSelectFragment.ProfileType;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settingslib.widget.ActionBarShadowController;
import com.android.settingslib.widget.AdaptiveIcon;
@@ -118,6 +123,7 @@
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
+import java.util.Objects;
import java.util.Set;
public final class Utils extends com.android.settingslib.Utils {
@@ -441,6 +447,38 @@
}
/**
+ * Returns the profile of userType of the current user or {@code null} if none is found or a
+ * profile exists, but it is disabled.
+ */
+ @Nullable
+ public static UserHandle getProfileOfType(
+ @NonNull UserManager userManager, @ProfileType int userType) {
+ final List<UserHandle> userProfiles = userManager.getUserProfiles();
+ String umUserType = getUmUserType(userType);
+ for (UserHandle profile : userProfiles) {
+ if (profile.getIdentifier() == UserHandle.myUserId()) {
+ continue;
+ }
+ final UserInfo userInfo = userManager.getUserInfo(profile.getIdentifier());
+ if (Objects.equals(umUserType, userInfo.userType)) {
+ return profile;
+ }
+ }
+ return null;
+ }
+
+ private static String getUmUserType(@ProfileType int userType) throws IllegalArgumentException {
+ if (userType == ProfileType.WORK) {
+ return USER_TYPE_PROFILE_MANAGED;
+ } else if (userType == ProfileType.PRIVATE) {
+ return USER_TYPE_PROFILE_PRIVATE;
+ } else if (userType == ProfileType.PERSONAL) {
+ return USER_TYPE_FULL_SYSTEM;
+ }
+ throw new IllegalArgumentException("Cannot get user type for ALL types");
+ }
+
+ /**
* Returns the managed profile of the current user or {@code null} if none is found. Unlike
* {@link #getManagedProfile} this method returns enabled and disabled managed profiles.
*/
@@ -479,15 +517,20 @@
return UserHandle.USER_NULL;
}
- /** Returns user ID of current user, throws IllegalStateException if it's not available. */
- public static int getCurrentUserId(UserManager userManager, boolean isWorkProfile)
- throws IllegalStateException {
- if (isWorkProfile) {
- final UserHandle managedUserHandle = getManagedProfile(userManager);
- if (managedUserHandle == null) {
- throw new IllegalStateException("Work profile user ID is not available.");
+ /**
+ * Returns user ID of the user of specified type under the current context, throws
+ * IllegalStateException if it's not available.
+ */
+ public static int getCurrentUserIdOfType(
+ @NonNull UserManager userManager,
+ @ProfileType int userType) throws IllegalStateException {
+ if (userType != ProfileType.PERSONAL) {
+ final UserHandle userHandle = getProfileOfType(userManager, userType);
+ if (userHandle == null) {
+ throw new IllegalStateException("User ID of requested profile type is not "
+ + "available.");
}
- return managedUserHandle.getIdentifier();
+ return userHandle.getIdentifier();
}
return UserHandle.myUserId();
}
@@ -1223,8 +1266,10 @@
List<UserHandle> profiles = userManager.getUserProfiles();
for (UserHandle userHandle : profiles) {
UserProperties userProperties = userManager.getUserProperties(userHandle);
- if (userProperties.getShowInSettings()
- == UserProperties.SHOW_IN_SETTINGS_SEPARATE) {
+ if (userProperties.getShowInSettings() == UserProperties.SHOW_IN_SETTINGS_SEPARATE) {
+ if (Flags.allowPrivateProfile() && userProperties.getHideInSettingsInQuietMode()) {
+ return !userManager.isQuietModeEnabled(userHandle);
+ }
return true;
}
}
diff --git a/src/com/android/settings/accounts/AccountDashboardFragment.java b/src/com/android/settings/accounts/AccountDashboardFragment.java
index 7816fd7..81aefd9 100644
--- a/src/com/android/settings/accounts/AccountDashboardFragment.java
+++ b/src/com/android/settings/accounts/AccountDashboardFragment.java
@@ -31,14 +31,17 @@
import com.android.settings.applications.autofill.PasswordsPreferenceController;
import com.android.settings.applications.credentials.CredentialManagerPreferenceController;
import com.android.settings.applications.credentials.DefaultCombinedPreferenceController;
+import com.android.settings.applications.credentials.DefaultPrivateCombinedPreferenceController;
import com.android.settings.applications.credentials.DefaultWorkCombinedPreferenceController;
import com.android.settings.applications.defaultapps.DefaultAutofillPreferenceController;
+import com.android.settings.applications.defaultapps.DefaultPrivateAutofillPreferenceController;
import com.android.settings.applications.defaultapps.DefaultWorkAutofillPreferenceController;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.users.AutoSyncDataPreferenceController;
import com.android.settings.users.AutoSyncPersonalDataPreferenceController;
+import com.android.settings.users.AutoSyncPrivateDataPreferenceController;
import com.android.settings.users.AutoSyncWorkDataPreferenceController;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.search.SearchIndexable;
@@ -111,9 +114,11 @@
if (CredentialManager.isServiceEnabled(context)) {
controllers.add(new DefaultCombinedPreferenceController(context));
controllers.add(new DefaultWorkCombinedPreferenceController(context));
+ controllers.add(new DefaultPrivateCombinedPreferenceController(context));
} else {
controllers.add(new DefaultAutofillPreferenceController(context));
controllers.add(new DefaultWorkAutofillPreferenceController(context));
+ controllers.add(new DefaultPrivateAutofillPreferenceController(context));
}
}
@@ -132,6 +137,7 @@
controllers.add(new AutoSyncDataPreferenceController(context, parent));
controllers.add(new AutoSyncPersonalDataPreferenceController(context, parent));
controllers.add(new AutoSyncWorkDataPreferenceController(context, parent));
+ controllers.add(new AutoSyncPrivateDataPreferenceController(context, parent));
}
private static int getPreferenceLayoutResId(Context context) {
diff --git a/src/com/android/settings/accounts/AccountPreferenceController.java b/src/com/android/settings/accounts/AccountPreferenceController.java
index db6a4ae..33b3888 100644
--- a/src/com/android/settings/accounts/AccountPreferenceController.java
+++ b/src/com/android/settings/accounts/AccountPreferenceController.java
@@ -296,14 +296,15 @@
updateProfileUi(userInfo);
} else {
List<UserInfo> profiles = mUm.getProfiles(UserHandle.myUserId());
- final int profilesCount = profiles.size();
- for (int i = 0; i < profilesCount; i++) {
- if (profiles.get(i).isManagedProfile()
- && (mType & ProfileSelectFragment.ProfileType.WORK) != 0) {
- updateProfileUi(profiles.get(i));
- } else if (!profiles.get(i).isManagedProfile()
- && (mType & ProfileSelectFragment.ProfileType.PERSONAL) != 0) {
- updateProfileUi(profiles.get(i));
+ for (UserInfo profile : profiles) {
+ if ((profile.isManagedProfile()
+ && (mType & ProfileSelectFragment.ProfileType.WORK) != 0)
+ || (profile.isPrivateProfile()
+ && (mType & ProfileSelectFragment.ProfileType.PRIVATE) != 0)
+ || (!profile.isManagedProfile()
+ && !profile.isPrivateProfile()
+ && (mType & ProfileSelectFragment.ProfileType.PERSONAL) != 0)) {
+ updateProfileUi(profile);
}
}
}
diff --git a/src/com/android/settings/accounts/AccountPrivateDashboardFragment.java b/src/com/android/settings/accounts/AccountPrivateDashboardFragment.java
new file mode 100644
index 0000000..9794b4a
--- /dev/null
+++ b/src/com/android/settings/accounts/AccountPrivateDashboardFragment.java
@@ -0,0 +1,109 @@
+/*
+ * 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.accounts;
+
+import static android.provider.Settings.EXTRA_AUTHORITIES;
+
+import static com.android.settings.accounts.AccountDashboardFragment.buildAutofillPreferenceControllers;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.credentials.CredentialManager;
+
+import com.android.settings.R;
+import com.android.settings.applications.autofill.PasswordsPreferenceController;
+import com.android.settings.applications.credentials.CredentialManagerPreferenceController;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
+import com.android.settings.users.AutoSyncDataPreferenceController;
+import com.android.settings.users.AutoSyncPrivateDataPreferenceController;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class AccountPrivateDashboardFragment extends DashboardFragment {
+ private static final String TAG = "AccountPrivateFrag";
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.ACCOUNT_PRIVATE;
+ }
+
+ @Override
+ protected String getLogTag() {
+ return TAG;
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ if (this.getContext() != null && CredentialManager.isServiceEnabled(this.getContext())) {
+ return R.xml.accounts_private_dashboard_settings_credman;
+ }
+ return R.xml.accounts_private_dashboard_settings;
+ }
+
+ @Override
+ public int getHelpResource() {
+ return R.string.help_url_user_and_account_dashboard;
+ }
+
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ if (CredentialManager.isServiceEnabled(context)) {
+ CredentialManagerPreferenceController cmpp =
+ use(CredentialManagerPreferenceController.class);
+ CredentialManagerPreferenceController.Delegate delegate =
+ new CredentialManagerPreferenceController.Delegate() {
+ public void setActivityResult(int resultCode) {
+ getActivity().setResult(resultCode);
+ }
+ public void forceDelegateRefresh() {
+ forceUpdatePreferences();
+ }
+ };
+ cmpp.init(this, getFragmentManager(), getIntent(), delegate, /*isWorkProfile=*/false);
+ } else {
+ getSettingsLifecycle().addObserver(use(PasswordsPreferenceController.class));
+ }
+ }
+
+ @Override
+ protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
+ final List<AbstractPreferenceController> controllers = new ArrayList<>();
+ buildAutofillPreferenceControllers(context, controllers);
+ final String[] authorities = getIntent().getStringArrayExtra(EXTRA_AUTHORITIES);
+ buildAccountPreferenceControllers(context, authorities, controllers);
+ return controllers;
+ }
+
+ private void buildAccountPreferenceControllers(
+ Context context,
+ String[] authorities,
+ List<AbstractPreferenceController> controllers) {
+ final AccountPreferenceController accountPrefController =
+ new AccountPreferenceController(
+ context,
+ this,
+ authorities,
+ ProfileSelectFragment.ProfileType.PRIVATE);
+ controllers.add(accountPrefController);
+ controllers.add(new AutoSyncDataPreferenceController(context, this));
+ controllers.add(new AutoSyncPrivateDataPreferenceController(context, this));
+ }
+}
diff --git a/src/com/android/settings/applications/autofill/PasswordsPreferenceController.java b/src/com/android/settings/applications/autofill/PasswordsPreferenceController.java
index 03a551f..73fef1b 100644
--- a/src/com/android/settings/applications/autofill/PasswordsPreferenceController.java
+++ b/src/com/android/settings/applications/autofill/PasswordsPreferenceController.java
@@ -17,6 +17,7 @@
package com.android.settings.applications.autofill;
import static android.app.admin.DevicePolicyResources.Strings.Settings.AUTO_SYNC_PERSONAL_DATA;
+import static android.app.admin.DevicePolicyResources.Strings.Settings.AUTO_SYNC_PRIVATE_DATA;
import static android.app.admin.DevicePolicyResources.Strings.Settings.AUTO_SYNC_WORK_DATA;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.service.autofill.AutofillService.EXTRA_RESULT;
@@ -122,6 +123,8 @@
AUTO_SYNC_PERSONAL_DATA, R.string.account_settings_menu_auto_sync_personal);
replaceEnterpriseStringTitle(screen, "auto_sync_work_account_data",
AUTO_SYNC_WORK_DATA, R.string.account_settings_menu_auto_sync_work);
+ replaceEnterpriseStringTitle(screen, "auto_sync_private_account_data",
+ AUTO_SYNC_PRIVATE_DATA, R.string.account_settings_menu_auto_sync_private);
}
private void addPasswordPreferences(
diff --git a/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java b/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java
index 98d56cc..b08bc61 100644
--- a/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java
+++ b/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java
@@ -45,7 +45,6 @@
import android.provider.Settings;
import android.service.autofill.AutofillServiceInfo;
import android.text.TextUtils;
-import android.util.IconDrawableFactory;
import android.util.Log;
import android.view.View;
import android.widget.Switch;
@@ -98,7 +97,6 @@
private static final int MAX_SELECTABLE_PROVIDERS = 5;
private final PackageManager mPm;
- private final IconDrawableFactory mIconFactory;
private final List<CredentialProviderInfo> mServices;
private final Set<String> mEnabledPackageNames;
private final @Nullable CredentialManager mCredentialManager;
@@ -119,7 +117,6 @@
public CredentialManagerPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
mPm = context.getPackageManager();
- mIconFactory = IconDrawableFactory.newInstance(mContext);
mServices = new ArrayList<>();
mEnabledPackageNames = new HashSet<>();
mExecutor = ContextCompat.getMainExecutor(mContext);
@@ -575,9 +572,11 @@
pref.setTitle(title);
if (icon != null) {
- pref.setIcon(Utils.getSafeIcon(icon));
+ pref.setIcon(icon);
}
+ pref.setLayoutResource(R.layout.preference_icon_credman);
+
if (subtitle != null) {
pref.setSummary(subtitle);
}
diff --git a/src/com/android/settings/applications/credentials/DefaultCombinedPickerPrivate.java b/src/com/android/settings/applications/credentials/DefaultCombinedPickerPrivate.java
new file mode 100644
index 0000000..722cb1a
--- /dev/null
+++ b/src/com/android/settings/applications/credentials/DefaultCombinedPickerPrivate.java
@@ -0,0 +1,30 @@
+/*
+ * 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.applications.credentials;
+
+import android.os.UserManager;
+
+import com.android.settings.Utils;
+import com.android.settings.dashboard.profileselector.ProfileSelectFragment.ProfileType;
+
+public class DefaultCombinedPickerPrivate extends DefaultCombinedPicker {
+ @Override
+ protected int getUser() {
+ UserManager userManager = getContext().getSystemService(UserManager.class);
+ return Utils.getCurrentUserIdOfType(userManager, ProfileType.PRIVATE);
+ }
+}
diff --git a/src/com/android/settings/applications/credentials/DefaultPrivateCombinedPreferenceController.kt b/src/com/android/settings/applications/credentials/DefaultPrivateCombinedPreferenceController.kt
new file mode 100644
index 0000000..d606f3c
--- /dev/null
+++ b/src/com/android/settings/applications/credentials/DefaultPrivateCombinedPreferenceController.kt
@@ -0,0 +1,57 @@
+/*
+ * 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.applications.credentials
+
+import android.content.Context
+import android.content.Intent
+import android.os.UserHandle
+import com.android.settings.Utils
+import com.android.settings.dashboard.profileselector.ProfileSelectFragment
+import com.android.settingslib.applications.DefaultAppInfo
+
+class DefaultPrivateCombinedPreferenceController(context: Context?) : DefaultCombinedPreferenceController(context) {
+ private val userHandle: UserHandle? =
+ Utils.getProfileOfType(mUserManager, ProfileSelectFragment.ProfileType.PRIVATE)
+
+ override fun isAvailable(): Boolean {
+ return if (userHandle == null) {
+ false
+ } else super.isAvailable()
+ }
+
+ override fun getPreferenceKey(): String {
+ return "default_credman_autofill_private"
+ }
+
+ override fun getSettingIntent(info: DefaultAppInfo ?): Intent ? {
+ if (info == null) {
+ return null
+ }
+ return userHandle?.let { handle ->
+ AutofillSettingIntentProvider(mContext, handle.identifier, info.key).intent
+ } ?: null
+ }
+
+ override fun startActivity(intent: Intent) {
+ userHandle?.let { handle ->
+ mContext.startActivityAsUser(intent, handle)
+ }
+ }
+
+ override fun getUser(): Int {
+ return userHandle?.identifier ?: UserHandle.myUserId()
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/applications/defaultapps/DefaultPrivateAutofillPreferenceController.kt b/src/com/android/settings/applications/defaultapps/DefaultPrivateAutofillPreferenceController.kt
new file mode 100644
index 0000000..67211b4
--- /dev/null
+++ b/src/com/android/settings/applications/defaultapps/DefaultPrivateAutofillPreferenceController.kt
@@ -0,0 +1,66 @@
+/*
+ * 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.applications.defaultapps
+
+import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import android.os.UserHandle
+import android.provider.Settings
+import android.text.TextUtils
+import com.android.settings.Utils
+import com.android.settings.dashboard.profileselector.ProfileSelectFragment
+import com.android.settingslib.applications.DefaultAppInfo
+
+class DefaultPrivateAutofillPreferenceController(context: Context?) : DefaultAutofillPreferenceController(context) {
+ private val userHandle: UserHandle? = Utils
+ .getProfileOfType(mUserManager, ProfileSelectFragment.ProfileType.PRIVATE)
+
+ override fun isAvailable(): Boolean {
+ return if (userHandle == null) {
+ false
+ } else super.isAvailable()
+ }
+
+ override fun getPreferenceKey(): String {
+ return "default_autofill_private"
+ }
+
+ override fun getDefaultAppInfo(): DefaultAppInfo ? {
+ val flattenComponent = userHandle?.let { handle ->
+ Settings.Secure.getStringForUser(
+ mContext.contentResolver,
+ DefaultAutofillPicker.SETTING,
+ handle.identifier
+ )
+ }
+ return if (!flattenComponent.isNullOrEmpty()) {
+ userHandle?.let {
+ DefaultAppInfo(
+ mContext,
+ mPackageManager,
+ it.identifier,
+ ComponentName.unflattenFromString(flattenComponent))
+ }
+ } else null
+ }
+
+ override fun startActivity(intent: Intent) {
+ if (userHandle == null) {
+ mContext.startActivityAsUser(intent, UserHandle.CURRENT)
+ } else mContext.startActivityAsUser(intent, userHandle)
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/activity/FingerprintEnrollmentV2Activity.kt b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/activity/FingerprintEnrollmentV2Activity.kt
index bbd67b5..58fcea6 100644
--- a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/activity/FingerprintEnrollmentV2Activity.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/activity/FingerprintEnrollmentV2Activity.kt
@@ -42,6 +42,7 @@
import com.android.settings.biometrics.BiometricEnrollBase.RESULT_FINISHED
import com.android.settings.biometrics.GatekeeperPasswordProvider
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintManagerInteractorImpl
+import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintViewModel
import com.android.settings.biometrics.fingerprint2.ui.enrollment.fragment.FingerprintEnrollConfirmationV2Fragment
import com.android.settings.biometrics.fingerprint2.ui.enrollment.fragment.FingerprintEnrollEnrollingV2Fragment
import com.android.settings.biometrics.fingerprint2.ui.enrollment.fragment.FingerprintEnrollFindSensorV2Fragment
@@ -82,6 +83,7 @@
private lateinit var accessibilityViewModel: AccessibilityViewModel
private lateinit var foldStateViewModel: FoldStateViewModel
private lateinit var orientationStateViewModel: OrientationStateViewModel
+ private lateinit var fingerprintScrollViewModel: FingerprintScrollViewModel
private val coroutineDispatcher = Dispatchers.Default
/** Result listener for ChooseLock activity flow. */
@@ -210,8 +212,9 @@
)[FingerprintEnrollViewModel::class.java]
// Initialize scroll view model
- ViewModelProvider(this, FingerprintScrollViewModel.FingerprintScrollViewModelFactory())[
- FingerprintScrollViewModel::class.java]
+ fingerprintScrollViewModel =
+ ViewModelProvider(this, FingerprintScrollViewModel.FingerprintScrollViewModelFactory())[
+ FingerprintScrollViewModel::class.java]
// Initialize AccessibilityViewModel
accessibilityViewModel =
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/fragment/FingerprintEnrollIntroV2Fragment.kt b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/fragment/FingerprintEnrollIntroV2Fragment.kt
index dbf6d12..898b158 100644
--- a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/fragment/FingerprintEnrollIntroV2Fragment.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/fragment/FingerprintEnrollIntroV2Fragment.kt
@@ -25,10 +25,13 @@
import android.text.Html
import android.text.method.LinkMovementMethod
import android.util.Log
+import android.view.LayoutInflater
import android.view.View
+import android.view.ViewGroup
import android.widget.ImageView
import android.widget.ScrollView
import android.widget.TextView
+import androidx.annotation.VisibleForTesting
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
@@ -72,48 +75,69 @@
* 2. How the data will be stored
* 3. How the user can access and remove their data
*/
-class FingerprintEnrollIntroV2Fragment : Fragment(R.layout.fingerprint_v2_enroll_introduction) {
- private lateinit var footerBarMixin: FooterBarMixin
- private lateinit var textModel: TextModel
- private lateinit var navigationViewModel: FingerprintEnrollNavigationViewModel
- private lateinit var fingerprintEnrollViewModel: FingerprintEnrollViewModel
- private lateinit var fingerprintScrollViewModel: FingerprintScrollViewModel
- private lateinit var gateKeeperViewModel: FingerprintGatekeeperViewModel
+class FingerprintEnrollIntroV2Fragment() : Fragment(R.layout.fingerprint_v2_enroll_introduction) {
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- navigationViewModel =
- ViewModelProvider(requireActivity())[FingerprintEnrollNavigationViewModel::class.java]
- fingerprintEnrollViewModel =
- ViewModelProvider(requireActivity())[FingerprintEnrollViewModel::class.java]
- fingerprintScrollViewModel =
- ViewModelProvider(requireActivity())[FingerprintScrollViewModel::class.java]
- gateKeeperViewModel =
- ViewModelProvider(requireActivity())[FingerprintGatekeeperViewModel::class.java]
+ /** Used for testing purposes */
+ private var factory: ViewModelProvider.Factory? = null
+
+ @VisibleForTesting
+ constructor(theFactory: ViewModelProvider.Factory) : this() {
+ factory = theFactory
}
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- super.onViewCreated(view, savedInstanceState)
+ private val viewModelProvider: ViewModelProvider by lazy {
+ if (factory != null) {
+ ViewModelProvider(requireActivity(), factory!!)
+ } else {
+ ViewModelProvider(requireActivity())
+ }
+ }
- lifecycleScope.launch {
- combine(
- navigationViewModel.enrollType,
- fingerprintEnrollViewModel.sensorType,
- ) { enrollType, sensorType ->
- Pair(enrollType, sensorType)
- }
- .collect { (enrollType, sensorType) ->
- textModel =
- when (enrollType) {
- Unicorn -> getUnicornTextModel()
- else -> getNormalTextModel()
- }
+ private lateinit var footerBarMixin: FooterBarMixin
+ private lateinit var textModel: TextModel
- setupFooterBarAndScrollView(view)
+ // Note that the ViewModels cannot be requested before the onCreate call
+ private val navigationViewModel: FingerprintEnrollNavigationViewModel by lazy {
+ viewModelProvider[FingerprintEnrollNavigationViewModel::class.java]
+ }
+ private val fingerprintViewModel: FingerprintEnrollViewModel by lazy {
+ viewModelProvider[FingerprintEnrollViewModel::class.java]
+ }
+ private val fingerprintScrollViewModel: FingerprintScrollViewModel by lazy {
+ viewModelProvider[FingerprintScrollViewModel::class.java]
+ }
+ private val gateKeeperViewModel: FingerprintGatekeeperViewModel by lazy {
+ viewModelProvider[FingerprintGatekeeperViewModel::class.java]
+ }
- if (savedInstanceState == null) {
- getLayout()?.setHeaderText(textModel.headerText)
- getLayout()?.setDescriptionText(textModel.descriptionText)
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? =
+ super.onCreateView(inflater, container, savedInstanceState).also { theView ->
+ val view = theView!!
+
+ viewLifecycleOwner.lifecycleScope.launch {
+ combine(
+ navigationViewModel.enrollType,
+ fingerprintViewModel.sensorType,
+ ) { enrollType, sensorType ->
+ Pair(enrollType, sensorType)
+ }
+ .collect { (enrollType, sensorType) ->
+ textModel =
+ when (enrollType) {
+ Unicorn -> getUnicornTextModel()
+ else -> getNormalTextModel()
+ }
+
+ setupFooterBarAndScrollView(view)
+
+ val layout = view as GlifLayout
+
+ layout.setHeaderText(textModel.headerText)
+ layout.setDescriptionText(textModel.descriptionText)
// Set color filter for the following icons.
val colorFilter = getIconColorFilter()
@@ -158,9 +182,9 @@
view.requireViewById<TextView?>(R.id.footer_title_1).setText(textModel.footerTitleOne)
view.requireViewById<TextView?>(R.id.footer_title_2).setText(textModel.footerTitleOne)
}
- }
+ }
+ return view
}
- }
private fun setFooterLink(view: View) {
val footerLink: TextView = view.requireViewById(R.id.footer_learn_more)
@@ -185,17 +209,18 @@
navigationViewModel.nextStep()
}
- val layout: GlifLayout = requireActivity().requireViewById(R.id.setup_wizard_layout)
+ val layout: GlifLayout = view.findViewById(R.id.setup_wizard_layout)!!
footerBarMixin = layout.getMixin(FooterBarMixin::class.java)
footerBarMixin.primaryButton =
- FooterButton.Builder(requireActivity())
+ FooterButton.Builder(requireContext())
.setText(R.string.security_settings_face_enroll_introduction_more)
.setListener(onNextButtonClick)
.setButtonType(FooterButton.ButtonType.OPT_IN)
.setTheme(com.google.android.setupdesign.R.style.SudGlifButton_Primary)
.build()
+
footerBarMixin.setSecondaryButton(
- FooterButton.Builder(requireActivity())
+ FooterButton.Builder(requireContext())
.setText(textModel.negativeButton)
.setListener({ Log.d(TAG, "prevClicked") })
.setButtonType(FooterButton.ButtonType.NEXT)
@@ -211,8 +236,8 @@
val requireScrollMixin = layout.getMixin(RequireScrollMixin::class.java)
requireScrollMixin.requireScrollWithButton(
- requireActivity(),
- footerBarMixin.primaryButton,
+ requireContext(),
+ primaryButton,
R.string.security_settings_face_enroll_introduction_more,
onNextButtonClick
)
@@ -224,7 +249,7 @@
}
}
- lifecycleScope.launch {
+ viewLifecycleOwner.lifecycleScope.launch {
fingerprintScrollViewModel.hasReadConsentScreen.collect { consented ->
if (consented) {
primaryButton.setText(
@@ -244,7 +269,7 @@
// the flow. For instance if someone launches the activity with an invalid challenge, it
// either 1) Fails or 2) Launched confirmDeviceCredential
primaryButton.isEnabled = false
- lifecycleScope.launch {
+ viewLifecycleOwner.lifecycleScope.launch {
gateKeeperViewModel.hasValidGatekeeperInfo.collect { primaryButton.isEnabled = it }
}
}
@@ -284,8 +309,4 @@
PorterDuff.Mode.SRC_IN
)
}
-
- private fun getLayout(): GlifLayout? {
- return requireView().findViewById(R.id.setup_wizard_layout) as GlifLayout?
- }
}
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintEnrolllNavigationViewModel.kt b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintEnrolllNavigationViewModel.kt
index d2bb321..97c8271 100644
--- a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintEnrolllNavigationViewModel.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintEnrolllNavigationViewModel.kt
@@ -31,11 +31,6 @@
private const val TAG = "FingerprintEnrollNavigationViewModel"
-/** Interface to validate a gatekeeper hat */
-interface Validator {
- fun validateGateKeeper(challenge: Long?): Boolean
-}
-
/**
* The [EnrollType] for fingerprint enrollment indicates information on how the flow should behave.
*/
@@ -56,7 +51,6 @@
*/
class FingerprintEnrollNavigationViewModel(
private val dispatcher: CoroutineDispatcher,
- private val validator: Validator,
private val fingerprintManagerInteractor: FingerprintManagerInteractor,
private val gatekeeperViewModel: FingerprintGatekeeperViewModel,
private val canSkipConfirm: Boolean
@@ -145,11 +139,6 @@
return FingerprintEnrollNavigationViewModel(
backgroundDispatcher,
- object : Validator {
- override fun validateGateKeeper(challenge: Long?): Boolean {
- return challenge != null
- }
- },
fingerprintManagerInteractor,
fingerprintGatekeeperViewModel,
canSkipConfirm,
diff --git a/src/com/android/settings/dashboard/profileselector/ProfileSelectAccountFragment.java b/src/com/android/settings/dashboard/profileselector/ProfileSelectAccountFragment.java
index cf91031..77dc3a7 100644
--- a/src/com/android/settings/dashboard/profileselector/ProfileSelectAccountFragment.java
+++ b/src/com/android/settings/dashboard/profileselector/ProfileSelectAccountFragment.java
@@ -15,10 +15,12 @@
*/
package com.android.settings.dashboard.profileselector;
+
import androidx.fragment.app.Fragment;
import com.android.settings.R;
import com.android.settings.accounts.AccountPersonalDashboardFragment;
+import com.android.settings.accounts.AccountPrivateDashboardFragment;
import com.android.settings.accounts.AccountWorkProfileDashboardFragment;
/**
@@ -28,10 +30,12 @@
@Override
public Fragment[] getFragments() {
- return new Fragment[] {
- new AccountPersonalDashboardFragment(),
- new AccountWorkProfileDashboardFragment()
- };
+ return ProfileSelectFragment.getFragments(
+ getContext(),
+ null /* bundle */,
+ AccountPersonalDashboardFragment::new,
+ AccountWorkProfileDashboardFragment::new,
+ AccountPrivateDashboardFragment::new);
}
@Override
diff --git a/src/com/android/settings/dashboard/profileselector/ProfileSelectFragment.java b/src/com/android/settings/dashboard/profileselector/ProfileSelectFragment.java
index 5c0580d..657cdbf 100644
--- a/src/com/android/settings/dashboard/profileselector/ProfileSelectFragment.java
+++ b/src/com/android/settings/dashboard/profileselector/ProfileSelectFragment.java
@@ -17,21 +17,28 @@
package com.android.settings.dashboard.profileselector;
import static android.app.admin.DevicePolicyResources.Strings.Settings.PERSONAL_CATEGORY_HEADER;
+import static android.app.admin.DevicePolicyResources.Strings.Settings.PRIVATE_CATEGORY_HEADER;
import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_CATEGORY_HEADER;
import static android.content.Intent.EXTRA_USER_ID;
import android.annotation.IntDef;
import android.app.Activity;
import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.pm.UserInfo;
import android.os.Bundle;
+import android.os.Flags;
import android.os.UserHandle;
import android.os.UserManager;
+import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.RecyclerView;
@@ -42,12 +49,14 @@
import com.android.settings.SettingsActivity;
import com.android.settings.Utils;
import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.privatespace.PrivateSpaceMaintainer;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
/**
* Base fragment class for profile settings.
@@ -77,9 +86,14 @@
int WORK = 1 << 1;
/**
- * It is personal and work profile
+ * It is private profile
*/
- int ALL = PERSONAL | WORK;
+ int PRIVATE = 1 << 2;
+
+ /**
+ * It is personal, work, and private profile
+ */
+ int ALL = PERSONAL | WORK | PRIVATE;
}
/**
@@ -97,6 +111,11 @@
*/
public static final int WORK_TAB = 1;
+ /**
+ * Used in fragment argument with Extra key {@link SettingsActivity.EXTRA_SHOW_FRAGMENT_TAB}
+ */
+ public static final int PRIVATE_TAB = 2;
+
private ViewGroup mContentView;
private ViewPager2 mViewPager;
@@ -215,12 +234,20 @@
if (isWorkProfile) {
return WORK_TAB;
}
+ UserInfo userInfo = UserManager.get(activity).getUserInfo(userId);
+ if (Flags.allowPrivateProfile() && userInfo != null && userInfo.isPrivateProfile()) {
+ return PRIVATE_TAB;
+ }
}
// Start intent from a specific user eg: adb shell --user 10
final int intentUser = activity.getIntent().getContentUserHint();
if (UserManager.get(activity).isManagedProfile(intentUser)) {
return WORK_TAB;
}
+ UserInfo userInfo = UserManager.get(activity).getUserInfo(intentUser);
+ if (Flags.allowPrivateProfile() && userInfo != null && userInfo.isPrivateProfile()) {
+ return PRIVATE_TAB;
+ }
return PERSONAL_TAB;
}
@@ -229,13 +256,114 @@
final DevicePolicyManager devicePolicyManager =
getContext().getSystemService(DevicePolicyManager.class);
- if (position == WORK_TAB) {
+ if (Flags.allowPrivateProfile()) {
+ int tabForPosition =
+ ((ViewPagerAdapter) mViewPager.getAdapter()).getTabForPosition(position);
+
+ if (tabForPosition == WORK_TAB) {
+ return devicePolicyManager.getResources().getString(WORK_CATEGORY_HEADER,
+ () -> getContext().getString(
+ com.android.settingslib.R.string.category_work));
+ }
+
+ if (tabForPosition == PRIVATE_TAB) {
+ return devicePolicyManager.getResources().getString(PRIVATE_CATEGORY_HEADER,
+ () -> getContext()
+ .getString(com.android.settingslib.R.string.category_private));
+ }
+
+ } else if (position == WORK_TAB) {
return devicePolicyManager.getResources().getString(WORK_CATEGORY_HEADER,
() -> getContext().getString(com.android.settingslib.R.string.category_work));
+
+ }
+ return devicePolicyManager.getResources().getString(PERSONAL_CATEGORY_HEADER,
+ () -> getContext().getString(
+ com.android.settingslib.R.string.category_personal));
+ }
+
+ /** Creates fragments of passed types, and returns them in an array. */
+ @NonNull static Fragment[] getFragments(
+ Context context,
+ @Nullable Bundle bundle,
+ FragmentConstructor personalFragmentConstructor,
+ FragmentConstructor workFragmentConstructor,
+ FragmentConstructor privateFragmentConstructor) {
+ return getFragments(
+ context,
+ bundle,
+ personalFragmentConstructor,
+ workFragmentConstructor,
+ privateFragmentConstructor,
+ new PrivateSpaceInfoProvider() {},
+ new ManagedProfileInfoProvider() {});
+ }
+
+ /**
+ * Creates fragments of passed types, and returns them in an array. This overload exists only
+ * for helping with testing.
+ */
+ @NonNull static Fragment[] getFragments(
+ Context context,
+ @Nullable Bundle bundle,
+ FragmentConstructor personalFragmentConstructor,
+ FragmentConstructor workFragmentConstructor,
+ FragmentConstructor privateFragmentConstructor,
+ PrivateSpaceInfoProvider privateSpaceInfoProvider,
+ ManagedProfileInfoProvider managedProfileInfoProvider) {
+ Fragment[] result = new Fragment[0];
+ ArrayList<Fragment> fragments = new ArrayList<>();
+
+ try {
+ final Bundle personalOnly = bundle != null ? bundle : new Bundle();
+ personalOnly.putInt(EXTRA_PROFILE, ProfileType.PERSONAL);
+ final Fragment personalFragment =
+ personalFragmentConstructor.constructAndGetFragment();
+ personalFragment.setArguments(personalOnly);
+ fragments.add(personalFragment);
+
+ if (managedProfileInfoProvider.getManagedProfile(context) != null) {
+ final Bundle workOnly = bundle != null ? bundle : new Bundle();
+ workOnly.putInt(EXTRA_PROFILE, ProfileType.WORK);
+ final Fragment workFragment =
+ workFragmentConstructor.constructAndGetFragment();
+ workFragment.setArguments(workOnly);
+ fragments.add(workFragment);
+ }
+
+ if (Flags.allowPrivateProfile()
+ && !privateSpaceInfoProvider.isPrivateSpaceLocked(context)) {
+ final Bundle privateOnly = bundle != null ? bundle : new Bundle();
+ privateOnly.putInt(EXTRA_PROFILE, ProfileType.PRIVATE);
+ final Fragment privateFragment =
+ privateFragmentConstructor.constructAndGetFragment();
+ privateFragment.setArguments(privateOnly);
+ fragments.add(privateFragment);
+ }
+
+ result = new Fragment[fragments.size()];
+ fragments.toArray(result);
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to create fragment");
}
- return devicePolicyManager.getResources().getString(PERSONAL_CATEGORY_HEADER,
- () -> getContext().getString(com.android.settingslib.R.string.category_personal));
+ return result;
+ }
+
+ interface FragmentConstructor {
+ Fragment constructAndGetFragment();
+ }
+
+ interface PrivateSpaceInfoProvider {
+ default boolean isPrivateSpaceLocked(Context context) {
+ return PrivateSpaceMaintainer.getInstance(context).isPrivateSpaceLocked();
+ }
+ }
+
+ interface ManagedProfileInfoProvider {
+ default UserHandle getManagedProfile(Context context) {
+ return Utils.getManagedProfile(context.getSystemService(UserManager.class));
+ }
}
static class ViewPagerAdapter extends FragmentStateAdapter {
@@ -256,5 +384,22 @@
public int getItemCount() {
return mChildFragments.length;
}
+
+ private int getTabForPosition(int position) {
+ if (position >= mChildFragments.length) {
+ Log.e(TAG, "tab requested for out of bound position " + position);
+ return PERSONAL_TAB;
+ }
+ @ProfileType
+ int profileType = mChildFragments[position].getArguments().getInt(EXTRA_PROFILE);
+
+ if (profileType == ProfileType.WORK) {
+ return WORK_TAB;
+ }
+ if (profileType == ProfileType.PRIVATE) {
+ return PRIVATE_TAB;
+ }
+ return PERSONAL_TAB;
+ }
}
}
diff --git a/src/com/android/settings/dashboard/profileselector/ProfileSelectKeyboardFragment.java b/src/com/android/settings/dashboard/profileselector/ProfileSelectKeyboardFragment.java
index c4386e6..d35692c 100644
--- a/src/com/android/settings/dashboard/profileselector/ProfileSelectKeyboardFragment.java
+++ b/src/com/android/settings/dashboard/profileselector/ProfileSelectKeyboardFragment.java
@@ -16,8 +16,6 @@
package com.android.settings.dashboard.profileselector;
-import android.os.Bundle;
-
import androidx.fragment.app.Fragment;
import com.android.settings.R;
@@ -39,19 +37,11 @@
@Override
public Fragment[] getFragments() {
- final Bundle personalOnly = new Bundle();
- personalOnly.putInt(EXTRA_PROFILE, ProfileType.PERSONAL);
- final Fragment personalFragment = new AvailableVirtualKeyboardFragment();
- personalFragment.setArguments(personalOnly);
-
- final Bundle workOnly = new Bundle();
- workOnly.putInt(EXTRA_PROFILE, ProfileType.WORK);
- final Fragment workFragment = new AvailableVirtualKeyboardFragment();
- workFragment.setArguments(workOnly);
-
- return new Fragment[]{
- personalFragment,
- workFragment
- };
+ return ProfileSelectFragment.getFragments(
+ getContext(),
+ null /* bundle */,
+ AvailableVirtualKeyboardFragment::new,
+ AvailableVirtualKeyboardFragment::new,
+ AvailableVirtualKeyboardFragment::new);
}
}
diff --git a/src/com/android/settings/dashboard/profileselector/ProfileSelectLocationFragment.java b/src/com/android/settings/dashboard/profileselector/ProfileSelectLocationFragment.java
index 28fb97b..feaec74 100644
--- a/src/com/android/settings/dashboard/profileselector/ProfileSelectLocationFragment.java
+++ b/src/com/android/settings/dashboard/profileselector/ProfileSelectLocationFragment.java
@@ -45,20 +45,12 @@
@Override
public Fragment[] getFragments() {
-
- final Bundle workOnly = new Bundle();
- workOnly.putInt(EXTRA_PROFILE, ProfileSelectFragment.ProfileType.WORK);
- final Fragment workFragment = new LocationWorkProfileSettings();
- workFragment.setArguments(workOnly);
-
- final Bundle personalOnly = new Bundle();
- personalOnly.putInt(EXTRA_PROFILE, ProfileSelectFragment.ProfileType.PERSONAL);
- final Fragment personalFragment = new LocationPersonalSettings();
- personalFragment.setArguments(personalOnly);
- return new Fragment[]{
- personalFragment,
- workFragment
- };
+ return ProfileSelectFragment.getFragments(
+ getContext(),
+ null /* bundle */,
+ LocationPersonalSettings::new,
+ LocationWorkProfileSettings::new,
+ LocationPersonalSettings::new);
}
@Override
diff --git a/src/com/android/settings/dashboard/profileselector/ProfileSelectLocationServicesFragment.java b/src/com/android/settings/dashboard/profileselector/ProfileSelectLocationServicesFragment.java
index 111e4ce..8e48c7b 100644
--- a/src/com/android/settings/dashboard/profileselector/ProfileSelectLocationServicesFragment.java
+++ b/src/com/android/settings/dashboard/profileselector/ProfileSelectLocationServicesFragment.java
@@ -16,8 +16,6 @@
package com.android.settings.dashboard.profileselector;
-import android.os.Bundle;
-
import androidx.fragment.app.Fragment;
import com.android.settings.R;
@@ -31,19 +29,12 @@
@Override
public Fragment[] getFragments() {
- final Bundle workOnly = new Bundle();
- workOnly.putInt(EXTRA_PROFILE, ProfileType.WORK);
- final Fragment workFragment = new LocationServicesForWork();
- workFragment.setArguments(workOnly);
-
- final Bundle personalOnly = new Bundle();
- personalOnly.putInt(EXTRA_PROFILE, ProfileType.PERSONAL);
- final Fragment personalFragment = new LocationServices();
- personalFragment.setArguments(personalOnly);
- return new Fragment[]{
- personalFragment, // 0
- workFragment
- };
+ return ProfileSelectFragment.getFragments(
+ getContext(),
+ null /* bundle */,
+ LocationServices::new,
+ LocationServicesForWork::new,
+ LocationServices::new);
}
@Override
diff --git a/src/com/android/settings/dashboard/profileselector/ProfileSelectManageApplications.java b/src/com/android/settings/dashboard/profileselector/ProfileSelectManageApplications.java
index 36aa9c5..4c82f6c 100644
--- a/src/com/android/settings/dashboard/profileselector/ProfileSelectManageApplications.java
+++ b/src/com/android/settings/dashboard/profileselector/ProfileSelectManageApplications.java
@@ -31,19 +31,12 @@
@Override
public Fragment[] getFragments() {
- final Bundle workOnly = getArguments() != null ? getArguments().deepCopy() : new Bundle();
- workOnly.putInt(EXTRA_PROFILE, ProfileSelectFragment.ProfileType.WORK);
- final Fragment workFragment = new ManageApplications();
- workFragment.setArguments(workOnly);
-
- final Bundle personalOnly = getArguments() != null ? getArguments() : new Bundle();
- personalOnly.putInt(EXTRA_PROFILE, ProfileSelectFragment.ProfileType.PERSONAL);
- final Fragment personalFragment = new ManageApplications();
- personalFragment.setArguments(personalOnly);
- return new Fragment[]{
- personalFragment, //0
- workFragment
- };
+ return ProfileSelectFragment.getFragments(
+ getContext(),
+ getArguments(),
+ ManageApplications::new,
+ ManageApplications::new,
+ ManageApplications::new);
}
@Override
diff --git a/src/com/android/settings/dashboard/profileselector/ProfileSelectPhysicalKeyboardFragment.java b/src/com/android/settings/dashboard/profileselector/ProfileSelectPhysicalKeyboardFragment.java
index 3c1546e..239d609 100644
--- a/src/com/android/settings/dashboard/profileselector/ProfileSelectPhysicalKeyboardFragment.java
+++ b/src/com/android/settings/dashboard/profileselector/ProfileSelectPhysicalKeyboardFragment.java
@@ -51,22 +51,11 @@
@Override
public Fragment[] getFragments() {
- final Bundle personalOnly = new Bundle();
- personalOnly.putInt(EXTRA_PROFILE, ProfileType.PERSONAL);
- final Fragment personalFragment = new NewKeyboardLayoutEnabledLocalesFragment();
- personalOnly.putParcelable(
- Settings.EXTRA_INPUT_DEVICE_IDENTIFIER, mInputDeviceIdentifier);
- personalFragment.setArguments(personalOnly);
-
- final Bundle workOnly = new Bundle();
- workOnly.putInt(EXTRA_PROFILE, ProfileType.WORK);
- final Fragment workFragment = new NewKeyboardLayoutEnabledLocalesFragment();
- workOnly.putParcelable(Settings.EXTRA_INPUT_DEVICE_IDENTIFIER, mInputDeviceIdentifier);
- workFragment.setArguments(workOnly);
-
- return new Fragment[]{
- personalFragment,
- workFragment
- };
+ return ProfileSelectFragment.getFragments(
+ getContext(),
+ null /* bundle */,
+ NewKeyboardLayoutEnabledLocalesFragment::new,
+ NewKeyboardLayoutEnabledLocalesFragment::new,
+ NewKeyboardLayoutEnabledLocalesFragment::new);
}
}
diff --git a/src/com/android/settings/dashboard/profileselector/ProfileSelectStorageFragment.java b/src/com/android/settings/dashboard/profileselector/ProfileSelectStorageFragment.java
index 5babf30..b523e7e 100644
--- a/src/com/android/settings/dashboard/profileselector/ProfileSelectStorageFragment.java
+++ b/src/com/android/settings/dashboard/profileselector/ProfileSelectStorageFragment.java
@@ -193,20 +193,12 @@
return mFragments;
}
- final Bundle workBundle = new Bundle();
- workBundle.putInt(EXTRA_PROFILE, ProfileType.WORK);
- final Fragment workFragment = new StorageCategoryFragment();
- workFragment.setArguments(workBundle);
-
- final Bundle personalBundle = new Bundle();
- personalBundle.putInt(EXTRA_PROFILE, ProfileType.PERSONAL);
- final Fragment personalFragment = new StorageCategoryFragment();
- personalFragment.setArguments(personalBundle);
-
- mFragments = new Fragment[] {
- personalFragment,
- workFragment
- };
+ mFragments = ProfileSelectFragment.getFragments(
+ getContext(),
+ null /* bundle */,
+ StorageCategoryFragment::new,
+ StorageCategoryFragment::new,
+ StorageCategoryFragment::new);
return mFragments;
}
diff --git a/src/com/android/settings/deviceinfo/StorageCategoryFragment.java b/src/com/android/settings/deviceinfo/StorageCategoryFragment.java
index 52f453d..1280057 100644
--- a/src/com/android/settings/deviceinfo/StorageCategoryFragment.java
+++ b/src/com/android/settings/deviceinfo/StorageCategoryFragment.java
@@ -37,6 +37,7 @@
import com.android.settings.Utils;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
+import com.android.settings.dashboard.profileselector.ProfileSelectFragment.ProfileType;
import com.android.settings.deviceinfo.storage.ManageStoragePreferenceController;
import com.android.settings.deviceinfo.storage.NonCurrentUserController;
import com.android.settings.deviceinfo.storage.StorageAsyncLoader;
@@ -85,7 +86,7 @@
private StorageItemPreferenceController mPreferenceController;
private List<NonCurrentUserController> mNonCurrentUsers;
- private boolean mIsWorkProfile;
+ private @ProfileType int mProfileType;
private int mUserId;
private boolean mIsLoadedFromCache;
private StorageCacheHelper mStorageCacheHelper;
@@ -163,9 +164,9 @@
// These member variables are initialized befoer super.onAttach for
// createPreferenceControllers to work correctly.
mUserManager = context.getSystemService(UserManager.class);
- mIsWorkProfile = getArguments().getInt(ProfileSelectFragment.EXTRA_PROFILE)
- == ProfileSelectFragment.ProfileType.WORK;
- mUserId = Utils.getCurrentUserId(mUserManager, mIsWorkProfile);
+ mProfileType = getArguments().getInt(ProfileSelectFragment.EXTRA_PROFILE);
+ mUserId = Utils.getCurrentUserIdOfType(mUserManager, mProfileType);
+
mStorageCacheHelper = new StorageCacheHelper(getContext(), mUserId);
super.onAttach(context);
@@ -229,8 +230,12 @@
@Override
public int getMetricsCategory() {
- return mIsWorkProfile ? SettingsEnums.SETTINGS_STORAGE_CATEGORY_WORK :
- SettingsEnums.SETTINGS_STORAGE_CATEGORY;
+ if (mProfileType == ProfileSelectFragment.ProfileType.WORK) {
+ return SettingsEnums.SETTINGS_STORAGE_CATEGORY_WORK;
+ } else if (mProfileType == ProfileSelectFragment.ProfileType.PRIVATE) {
+ return SettingsEnums.SETTINGS_STORAGE_CATEGORY_PRIVATE;
+ }
+ return SettingsEnums.SETTINGS_STORAGE_CATEGORY;
}
@Override
@@ -248,11 +253,12 @@
final List<AbstractPreferenceController> controllers = new ArrayList<>();
final StorageManager sm = context.getSystemService(StorageManager.class);
mPreferenceController = new StorageItemPreferenceController(context, this,
- null /* volume */, new StorageManagerVolumeProvider(sm), mIsWorkProfile);
+ null /* volume */, new StorageManagerVolumeProvider(sm), mProfileType);
controllers.add(mPreferenceController);
- mNonCurrentUsers = mIsWorkProfile ? EMPTY_LIST :
- NonCurrentUserController.getNonCurrentUserControllers(context, mUserManager);
+ mNonCurrentUsers = mProfileType == ProfileSelectFragment.ProfileType.PERSONAL
+ ? NonCurrentUserController.getNonCurrentUserControllers(context, mUserManager)
+ : EMPTY_LIST;
controllers.addAll(mNonCurrentUsers);
return controllers;
}
diff --git a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
index f31f2be..0da3667 100644
--- a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
+++ b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
@@ -308,7 +308,6 @@
// These member variables are initialized befoer super.onAttach for
// createPreferenceControllers to work correctly.
mUserManager = context.getSystemService(UserManager.class);
- mIsWorkProfile = false;
mUserId = UserHandle.myUserId();
mStorageCacheHelper = new StorageCacheHelper(getContext(), mUserId);
@@ -423,7 +422,7 @@
final List<AbstractPreferenceController> controllers = new ArrayList<>();
final StorageManager sm = context.getSystemService(StorageManager.class);
mPreferenceController = new StorageItemPreferenceController(context, this,
- null /* volume */, new StorageManagerVolumeProvider(sm), mIsWorkProfile);
+ null /* volume */, new StorageManagerVolumeProvider(sm));
controllers.add(mPreferenceController);
mNonCurrentUsers = NonCurrentUserController.getNonCurrentUserControllers(context,
@@ -467,8 +466,7 @@
final UserManager userManager = context.getSystemService(UserManager.class);
final List<AbstractPreferenceController> controllers = new ArrayList<>();
controllers.add(new StorageItemPreferenceController(context, null /* host */,
- null /* volume */, new StorageManagerVolumeProvider(sm),
- false /* isWorkProfile */));
+ null /* volume */, new StorageManagerVolumeProvider(sm)));
controllers.addAll(NonCurrentUserController.getNonCurrentUserControllers(
context, userManager));
return controllers;
diff --git a/src/com/android/settings/deviceinfo/TopLevelStoragePreferenceController.java b/src/com/android/settings/deviceinfo/TopLevelStoragePreferenceController.java
index ccae7e9..1955f36 100644
--- a/src/com/android/settings/deviceinfo/TopLevelStoragePreferenceController.java
+++ b/src/com/android/settings/deviceinfo/TopLevelStoragePreferenceController.java
@@ -27,6 +27,7 @@
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.core.BasePreferenceController;
+import com.android.settings.dashboard.profileselector.ProfileSelectFragment.ProfileType;
import com.android.settings.deviceinfo.storage.StorageCacheHelper;
import com.android.settingslib.deviceinfo.PrivateStorageInfo;
import com.android.settingslib.deviceinfo.StorageManagerVolumeProvider;
@@ -62,8 +63,8 @@
@VisibleForTesting
protected Future refreshSummaryThread(Preference preference) {
- int userId = Utils.getCurrentUserId(mContext.getSystemService(UserManager.class),
- /* isWorkProfile */ false);
+ int userId = Utils.getCurrentUserIdOfType(
+ mContext.getSystemService(UserManager.class), ProfileType.PERSONAL);
final StorageCacheHelper storageCacheHelper = new StorageCacheHelper(mContext, userId);
long cachedUsedSize = storageCacheHelper.retrieveUsedSize();
long cachedTotalSize = storageCacheHelper.retrieveCachedSize().totalSize;
diff --git a/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java b/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
index a57cd5b..fd42417 100644
--- a/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
@@ -17,11 +17,13 @@
package com.android.settings.deviceinfo.storage;
import static com.android.settings.dashboard.profileselector.ProfileSelectFragment.PERSONAL_TAB;
+import static com.android.settings.dashboard.profileselector.ProfileSelectFragment.PRIVATE_TAB;
import static com.android.settings.dashboard.profileselector.ProfileSelectFragment.WORK_TAB;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.net.Uri;
@@ -47,6 +49,7 @@
import com.android.settings.applications.manageapplications.ManageApplications;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.core.SubSettingLauncher;
+import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
import com.android.settings.deviceinfo.StorageItemPreference;
import com.android.settings.deviceinfo.storage.StorageUtils.SystemInfoFragment;
import com.android.settings.overlay.FeatureFactory;
@@ -108,33 +111,33 @@
private final Fragment mFragment;
private final MetricsFeatureProvider mMetricsFeatureProvider;
private final StorageVolumeProvider mSvp;
- private VolumeInfo mVolume;
+ @Nullable private VolumeInfo mVolume;
private int mUserId;
private long mUsedBytes;
private long mTotalSize;
- private List<StorageItemPreference> mPrivateStorageItemPreferences;
- private PreferenceScreen mScreen;
+ @Nullable private List<StorageItemPreference> mPrivateStorageItemPreferences;
+ @Nullable private PreferenceScreen mScreen;
@VisibleForTesting
- Preference mPublicStoragePreference;
+ @Nullable Preference mPublicStoragePreference;
@VisibleForTesting
- StorageItemPreference mImagesPreference;
+ @Nullable StorageItemPreference mImagesPreference;
@VisibleForTesting
- StorageItemPreference mVideosPreference;
+ @Nullable StorageItemPreference mVideosPreference;
@VisibleForTesting
- StorageItemPreference mAudioPreference;
+ @Nullable StorageItemPreference mAudioPreference;
@VisibleForTesting
- StorageItemPreference mAppsPreference;
+ @Nullable StorageItemPreference mAppsPreference;
@VisibleForTesting
- StorageItemPreference mGamesPreference;
+ @Nullable StorageItemPreference mGamesPreference;
@VisibleForTesting
- StorageItemPreference mDocumentsAndOtherPreference;
+ @Nullable StorageItemPreference mDocumentsAndOtherPreference;
@VisibleForTesting
- StorageItemPreference mSystemPreference;
+ @Nullable StorageItemPreference mSystemPreference;
@VisibleForTesting
- StorageItemPreference mTrashPreference;
+ @Nullable StorageItemPreference mTrashPreference;
- private boolean mIsWorkProfile;
+ private final int mProfileType;
private StorageCacheHelper mStorageCacheHelper;
// The mIsDocumentsPrefShown being used here is to prevent a flicker problem from displaying
@@ -142,15 +145,24 @@
private boolean mIsDocumentsPrefShown;
private boolean mIsPreferenceOrderedBySize;
- public StorageItemPreferenceController(Context context, Fragment hostFragment,
- VolumeInfo volume, StorageVolumeProvider svp, boolean isWorkProfile) {
+ public StorageItemPreferenceController(
+ Context context, Fragment hostFragment, VolumeInfo volume, StorageVolumeProvider svp) {
+ this(context, hostFragment, volume, svp, ProfileSelectFragment.ProfileType.PERSONAL);
+ }
+
+ public StorageItemPreferenceController(
+ Context context,
+ Fragment hostFragment,
+ @Nullable VolumeInfo volume,
+ StorageVolumeProvider svp,
+ @ProfileSelectFragment.ProfileType int profileType) {
super(context);
mPackageManager = context.getPackageManager();
mUserManager = context.getSystemService(UserManager.class);
mFragment = hostFragment;
mVolume = volume;
mSvp = svp;
- mIsWorkProfile = isWorkProfile;
+ mProfileType = profileType;
mMetricsFeatureProvider = FeatureFactory.getFeatureFactory().getMetricsFeatureProvider();
mUserId = getCurrentUserId();
mIsDocumentsPrefShown = isDocumentsPrefShown();
@@ -168,7 +180,7 @@
@VisibleForTesting
int getCurrentUserId() {
- return Utils.getCurrentUserId(mUserManager, mIsWorkProfile);
+ return Utils.getCurrentUserIdOfType(mUserManager, mProfileType);
}
@Override
@@ -229,7 +241,9 @@
mVolume = volume;
if (mPublicStoragePreference != null) {
- mPublicStoragePreference.setVisible(isValidPublicVolume() && !mIsWorkProfile);
+ mPublicStoragePreference.setVisible(
+ isValidPublicVolume()
+ && mProfileType == ProfileSelectFragment.ProfileType.PERSONAL);
}
// If isValidPrivateVolume() is true, these preferences will become visible at
@@ -327,9 +341,16 @@
* Sets the user id for which this preference controller is handling.
*/
public void setUserId(UserHandle userHandle) {
- if (mIsWorkProfile && !mUserManager.isManagedProfile(userHandle.getIdentifier())) {
+ if (mProfileType == ProfileSelectFragment.ProfileType.WORK
+ && !mUserManager.isManagedProfile(userHandle.getIdentifier())) {
throw new IllegalArgumentException("Only accept work profile userHandle");
}
+
+ UserInfo userInfo = mUserManager.getUserInfo(userHandle.getIdentifier());
+ if (mProfileType == ProfileSelectFragment.ProfileType.PRIVATE
+ && (userInfo == null || userInfo.isPrivateProfile())) {
+ throw new IllegalArgumentException("Only accept private profile userHandle");
+ }
mUserId = userHandle.getIdentifier();
tintPreference(mPublicStoragePreference);
@@ -498,8 +519,13 @@
private Bundle getWorkAnnotatedBundle(int additionalCapacity) {
final Bundle args = new Bundle(1 + additionalCapacity);
- args.putInt(SettingsActivity.EXTRA_SHOW_FRAGMENT_TAB,
- mIsWorkProfile ? WORK_TAB : PERSONAL_TAB);
+ if (mProfileType == ProfileSelectFragment.ProfileType.WORK) {
+ args.putInt(SettingsActivity.EXTRA_SHOW_FRAGMENT_TAB, WORK_TAB);
+ } else if (mProfileType == ProfileSelectFragment.ProfileType.PRIVATE) {
+ args.putInt(SettingsActivity.EXTRA_SHOW_FRAGMENT_TAB, PRIVATE_TAB);
+ } else {
+ args.putInt(SettingsActivity.EXTRA_SHOW_FRAGMENT_TAB, PERSONAL_TAB);
+ }
return args;
}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/ConvertUtils.java b/src/com/android/settings/fuelgauge/batteryusage/ConvertUtils.java
index a1987c9..4eef3a0 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/ConvertUtils.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/ConvertUtils.java
@@ -111,8 +111,8 @@
values.put(BatteryHistEntry.KEY_UID, Long.valueOf(entry.getUid()));
values.put(BatteryHistEntry.KEY_USER_ID,
Long.valueOf(UserHandle.getUserId(entry.getUid())));
- values.put(BatteryHistEntry.KEY_PACKAGE_NAME,
- entry.getDefaultPackageName());
+ final String packageName = entry.getDefaultPackageName();
+ values.put(BatteryHistEntry.KEY_PACKAGE_NAME, packageName != null ? packageName : "");
values.put(BatteryHistEntry.KEY_CONSUMER_TYPE,
Integer.valueOf(entry.getConsumerType()));
} else {
diff --git a/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java b/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java
index 6efbc6d..7e27529 100644
--- a/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java
+++ b/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java
@@ -84,6 +84,16 @@
newUserAwareContext = context.createContextAsUser(UserHandle.of(newUserId), 0);
break;
}
+ case ProfileSelectFragment.ProfileType.PRIVATE: {
+ // If the user is a private profile user, use currentUserId directly. Or get the
+ // private profile userId instead.
+ newUserId = userManager.isPrivateProfile()
+ ? currentUserId
+ : Utils.getCurrentUserIdOfType(
+ userManager, ProfileSelectFragment.ProfileType.PRIVATE);
+ newUserAwareContext = context.createContextAsUser(UserHandle.of(newUserId), 0);
+ break;
+ }
case ProfileSelectFragment.ProfileType.PERSONAL: {
// Use the parent user of the current user if the current user is profile.
final UserHandle currentUser = UserHandle.of(currentUserId);
diff --git a/src/com/android/settings/inputmethod/NewKeyboardLayoutEnabledLocalesFragment.java b/src/com/android/settings/inputmethod/NewKeyboardLayoutEnabledLocalesFragment.java
index f007bc8..abe640b 100644
--- a/src/com/android/settings/inputmethod/NewKeyboardLayoutEnabledLocalesFragment.java
+++ b/src/com/android/settings/inputmethod/NewKeyboardLayoutEnabledLocalesFragment.java
@@ -77,6 +77,15 @@
? currentUserId : Utils.getManagedProfileId(userManager, currentUserId);
break;
}
+ case ProfileSelectFragment.ProfileType.PRIVATE: {
+ // If the user is a private profile user, use currentUserId directly. Or get the
+ // private profile userId instead.
+ newUserId = userManager.isPrivateProfile()
+ ? currentUserId
+ : Utils.getCurrentUserIdOfType(
+ userManager, ProfileSelectFragment.ProfileType.PRIVATE);
+ break;
+ }
case ProfileSelectFragment.ProfileType.PERSONAL: {
final UserHandle primaryUser = userManager.getPrimaryUser().getUserHandle();
newUserId = primaryUser.getIdentifier();
diff --git a/src/com/android/settings/privatespace/PrivateSpaceMaintainer.java b/src/com/android/settings/privatespace/PrivateSpaceMaintainer.java
index 709814d..0abf8f7 100644
--- a/src/com/android/settings/privatespace/PrivateSpaceMaintainer.java
+++ b/src/com/android/settings/privatespace/PrivateSpaceMaintainer.java
@@ -131,7 +131,17 @@
return false;
}
- static synchronized PrivateSpaceMaintainer getInstance(Context context) {
+ /** Returns true when the PS is locked or when PS doesn't exist, false otherwise. */
+ public synchronized boolean isPrivateSpaceLocked() {
+ if (!doesPrivateSpaceExist()) {
+ return true;
+ }
+
+ return mUserManager.isQuietModeEnabled(mUserHandle);
+ }
+
+ /** Returns the instance of {@link PrivateSpaceMaintainer} */
+ public static synchronized PrivateSpaceMaintainer getInstance(Context context) {
if (sPrivateSpaceMaintainer == null) {
sPrivateSpaceMaintainer = new PrivateSpaceMaintainer(context);
}
diff --git a/src/com/android/settings/users/AutoSyncPrivateDataPreferenceController.kt b/src/com/android/settings/users/AutoSyncPrivateDataPreferenceController.kt
new file mode 100644
index 0000000..3eabafe
--- /dev/null
+++ b/src/com/android/settings/users/AutoSyncPrivateDataPreferenceController.kt
@@ -0,0 +1,43 @@
+/*
+ * 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.users
+
+import android.content.Context
+import androidx.preference.PreferenceFragmentCompat
+import com.android.settings.Utils
+import com.android.settings.dashboard.profileselector.ProfileSelectFragment
+
+class AutoSyncPrivateDataPreferenceController(
+ context: Context?, parent: PreferenceFragmentCompat?)
+ : AutoSyncDataPreferenceController(context, parent) {
+ init {
+ mUserHandle = Utils
+ .getProfileOfType(mUserManager, ProfileSelectFragment.ProfileType.PRIVATE)
+ }
+
+ override fun getPreferenceKey(): String {
+ return KEY_AUTO_SYNC_PRIVATE_ACCOUNT
+ }
+
+ override fun isAvailable(): Boolean {
+ return (mUserHandle != null
+ && mUserManager.getUserInfo(mUserHandle.identifier).isPrivateProfile)
+ }
+
+ companion object {
+ private const val KEY_AUTO_SYNC_PRIVATE_ACCOUNT = "auto_sync_private_account_data"
+ }
+}
\ No newline at end of file
diff --git a/tests/anomaly-tester/Android.bp b/tests/anomaly-tester/Android.bp
index f17f4b2..0b05e04 100644
--- a/tests/anomaly-tester/Android.bp
+++ b/tests/anomaly-tester/Android.bp
@@ -18,7 +18,7 @@
"androidx.test.rules",
"mockito-target",
"androidx.test.uiautomator_uiautomator",
- "truth-prebuilt",
+ "truth",
],
srcs: ["**/*.java"],
diff --git a/tests/componenttests/Android.bp b/tests/componenttests/Android.bp
index 5c03aa9..300a338 100644
--- a/tests/componenttests/Android.bp
+++ b/tests/componenttests/Android.bp
@@ -19,7 +19,7 @@
],
static_libs: [
- "truth-prebuilt",
+ "truth",
"androidx.test.core",
"androidx.test.espresso.core",
"androidx.test.espresso.intents-nodeps",
diff --git a/tests/robotests/Android.bp b/tests/robotests/Android.bp
index 6b56d93..68793a1 100644
--- a/tests/robotests/Android.bp
+++ b/tests/robotests/Android.bp
@@ -25,6 +25,8 @@
"androidx.fragment_fragment-testing",
"frameworks-base-testutils",
"androidx.fragment_fragment",
+ "androidx.lifecycle_lifecycle-runtime-testing",
+ "kotlinx_coroutines_test",
],
aaptflags: ["--extra-packages com.android.settings"],
@@ -59,6 +61,7 @@
"androidx.test.rules",
"androidx.test.runner",
"flag-junit",
+ "flag-junit-base",
"aconfig_settings_flags_lib",
"platform-test-annotations",
"Settings-testutils2",
@@ -69,7 +72,10 @@
"ims-common",
],
- java_resource_dirs: ["config", "resources"],
+ java_resource_dirs: [
+ "config",
+ "resources",
+ ],
instrumentation_for: "SettingsRoboTestStub",
@@ -94,6 +100,6 @@
"Robolectric_all-target_upstream",
"Settings-core",
"mockito-robolectric-prebuilt",
- "truth-prebuilt",
+ "truth",
],
}
diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint2/fragment/FingerprintEnrollIntroFragmentTest.kt b/tests/robotests/src/com/android/settings/biometrics/fingerprint2/fragment/FingerprintEnrollIntroFragmentTest.kt
new file mode 100644
index 0000000..cea6676
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint2/fragment/FingerprintEnrollIntroFragmentTest.kt
@@ -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.biometrics.fingerprint2.fragment
+
+import android.content.Context
+import android.os.Bundle
+import androidx.fragment.app.testing.FragmentScenario
+import androidx.fragment.app.testing.launchFragmentInContainer
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.espresso.Espresso.onView
+import androidx.test.espresso.assertion.ViewAssertions.doesNotExist
+import androidx.test.espresso.assertion.ViewAssertions.matches
+import androidx.test.espresso.matcher.ViewMatchers.Visibility
+import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
+import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility
+import androidx.test.espresso.matcher.ViewMatchers.withId
+import androidx.test.espresso.matcher.ViewMatchers.withText
+import androidx.test.runner.AndroidJUnit4
+import com.android.settings.R
+import com.android.settings.biometrics.fingerprint2.ui.enrollment.fragment.FingerprintEnrollIntroV2Fragment
+import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollNavigationViewModel
+import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollViewModel
+import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintGatekeeperViewModel
+import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintScrollViewModel
+import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.GatekeeperInfo
+import com.android.settings.testutils2.FakeFingerprintManagerInteractor
+import com.google.android.setupdesign.GlifLayout
+import com.google.android.setupdesign.template.RequireScrollMixin
+import kotlinx.coroutines.test.StandardTestDispatcher
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class FingerprintEnrollIntroFragmentTest {
+ private var context: Context = ApplicationProvider.getApplicationContext()
+ private var interactor = FakeFingerprintManagerInteractor()
+
+ private val gatekeeperViewModel =
+ FingerprintGatekeeperViewModel(
+ GatekeeperInfo.GatekeeperPasswordInfo(byteArrayOf(1, 2, 3), 100L),
+ interactor
+ )
+ private val backgroundDispatcher = StandardTestDispatcher()
+ private lateinit var fragmentScenario: FragmentScenario<FingerprintEnrollIntroV2Fragment>
+
+ private val navigationViewModel =
+ FingerprintEnrollNavigationViewModel(
+ backgroundDispatcher,
+ interactor,
+ gatekeeperViewModel,
+ canSkipConfirm = true,
+ )
+ private var fingerprintViewModel = FingerprintEnrollViewModel(interactor, backgroundDispatcher)
+ private var fingerprintScrollViewModel = FingerprintScrollViewModel()
+
+ @Before
+ fun setup() {
+ val factory =
+ object : ViewModelProvider.Factory {
+ @Suppress("UNCHECKED_CAST")
+ override fun <T : ViewModel> create(
+ modelClass: Class<T>,
+ ): T {
+ return when (modelClass) {
+ FingerprintEnrollViewModel::class.java -> fingerprintViewModel
+ FingerprintScrollViewModel::class.java -> fingerprintScrollViewModel
+ FingerprintEnrollNavigationViewModel::class.java -> navigationViewModel
+ FingerprintGatekeeperViewModel::class.java -> gatekeeperViewModel
+ else -> null
+ }
+ as T
+ }
+ }
+
+ fragmentScenario =
+ launchFragmentInContainer(Bundle(), R.style.SudThemeGlif) {
+ FingerprintEnrollIntroV2Fragment(factory)
+ }
+ }
+
+ @Test
+ fun testScrollToBottomButtonChangesText() {
+ fragmentScenario.onFragment { fragment ->
+ onView(withText("I agree")).check(doesNotExist())
+ val someView = (fragment.requireView().findViewById<GlifLayout>(R.id.setup_wizard_layout))!!
+ val scrollMixin = someView.getMixin(RequireScrollMixin::class.java)!!
+ val listener = scrollMixin.onRequireScrollStateChangedListener
+ // This actually changes the button text
+ listener.onRequireScrollStateChanged(false)
+
+ onView(withText("I agree")).check(matches(isDisplayed()))
+ }
+ }
+
+ @Test
+ fun testBasicTitle() {
+ onView(withText(R.string.security_settings_fingerprint_enroll_introduction_title))
+ .check(matches(withEffectiveVisibility(Visibility.VISIBLE)))
+ }
+
+ @Test
+ fun testFooterMessageTwo() {
+ onView(withId(R.id.footer_message_2))
+ .check(
+ matches(
+ withText(
+ context.getString(
+ (R.string.security_settings_fingerprint_v2_enroll_introduction_footer_message_2)
+ )
+ )
+ )
+ )
+ }
+
+ @Test
+ fun testFooterMessageThree() {
+ onView(withId(R.id.footer_message_3))
+ .check(
+ matches(
+ withText(
+ context.getString(
+ (R.string.security_settings_fingerprint_v2_enroll_introduction_footer_message_3)
+ )
+ )
+ )
+ )
+ }
+
+ @Test
+ fun testFooterMessageFour() {
+ onView(withId(R.id.footer_message_4))
+ .check(
+ matches(
+ withText(
+ context.getString(
+ (R.string.security_settings_fingerprint_v2_enroll_introduction_footer_message_4)
+ )
+ )
+ )
+ )
+ }
+
+ @Test
+ fun testFooterMessageFive() {
+ onView(withId(R.id.footer_message_5))
+ .check(
+ matches(
+ withText(
+ context.getString(
+ (R.string.security_settings_fingerprint_v2_enroll_introduction_footer_message_5)
+ )
+ )
+ )
+ )
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/dashboard/profileselector/ProfileSelectFragmentTest.java b/tests/robotests/src/com/android/settings/dashboard/profileselector/ProfileSelectFragmentTest.java
index b595d06..056935c 100644
--- a/tests/robotests/src/com/android/settings/dashboard/profileselector/ProfileSelectFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/profileselector/ProfileSelectFragmentTest.java
@@ -19,6 +19,7 @@
import static android.content.Intent.EXTRA_USER_ID;
import static com.android.settings.dashboard.profileselector.ProfileSelectFragment.PERSONAL_TAB;
+import static com.android.settings.dashboard.profileselector.ProfileSelectFragment.PRIVATE_TAB;
import static com.android.settings.dashboard.profileselector.ProfileSelectFragment.WORK_TAB;
import static com.google.common.truth.Truth.assertThat;
@@ -29,6 +30,9 @@
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
+import android.os.Flags;
+import android.os.UserHandle;
+import android.platform.test.flag.junit.SetFlagsRule;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
@@ -38,6 +42,7 @@
import com.android.settings.testutils.shadow.ShadowUserManager;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
@@ -60,6 +65,7 @@
private TestProfileSelectFragment mFragment;
private FragmentActivity mActivity;
private ShadowUserManager mUserManager;
+ @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@Before
public void setUp() {
@@ -86,6 +92,14 @@
}
@Test
+ public void getTabId_setArgumentPrivate_setCorrectTab() {
+ final Bundle bundle = new Bundle();
+ bundle.putInt(SettingsActivity.EXTRA_SHOW_FRAGMENT_TAB, PRIVATE_TAB);
+
+ assertThat(mFragment.getTabId(mActivity, bundle)).isEqualTo(PRIVATE_TAB);
+ }
+
+ @Test
public void getTabId_setArgumentPersonal_setCorrectTab() {
final Bundle bundle = new Bundle();
bundle.putInt(SettingsActivity.EXTRA_SHOW_FRAGMENT_TAB, PERSONAL_TAB);
@@ -105,6 +119,16 @@
}
@Test
+ public void getTabId_setPrivateId_getCorrectTab() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+ final Bundle bundle = new Bundle();
+ bundle.putInt(EXTRA_USER_ID, 11);
+ mUserManager.setPrivateProfile(11, "private", 0);
+
+ assertThat(mFragment.getTabId(mActivity, bundle)).isEqualTo(PRIVATE_TAB);
+ }
+
+ @Test
public void getTabId_setPersonalId_getCorrectTab() {
final Bundle bundle = new Bundle();
bundle.putInt(EXTRA_USER_ID, 0);
@@ -124,12 +148,120 @@
assertThat(mFragment.getTabId(mActivity, null)).isEqualTo(WORK_TAB);
}
+ @Test
+ public void testGetFragments_whenOnlyPersonal_returnsOneFragment() {
+ mSetFlagsRule.disableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+ Fragment[] fragments = ProfileSelectFragment.getFragments(
+ mContext,
+ null /* bundle */,
+ TestProfileSelectFragment::new,
+ TestProfileSelectFragment::new,
+ TestProfileSelectFragment::new);
+ assertThat(fragments).hasLength(1);
+ }
+
+ @Test
+ public void testGetFragments_whenPrivateDisabled_returnsOneFragment() {
+ Fragment[] fragments = ProfileSelectFragment.getFragments(
+ mContext,
+ null /* bundle */,
+ TestProfileSelectFragment::new,
+ TestProfileSelectFragment::new,
+ TestProfileSelectFragment::new,
+ new ProfileSelectFragment.PrivateSpaceInfoProvider() {
+ @Override
+ public boolean isPrivateSpaceLocked(Context context) {
+ return true;
+ }
+ },
+ new ProfileSelectFragment.ManagedProfileInfoProvider() {
+ @Override
+ public UserHandle getManagedProfile(Context context) {
+ return null;
+ }
+ });
+ assertThat(fragments).hasLength(1);
+ }
+
+ @Test
+ public void testGetFragments_whenPrivateEnabled_returnsTwoFragments() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+ Fragment[] fragments = ProfileSelectFragment.getFragments(
+ mContext,
+ null /* bundle */,
+ TestProfileSelectFragment::new,
+ TestProfileSelectFragment::new,
+ TestProfileSelectFragment::new,
+ new ProfileSelectFragment.PrivateSpaceInfoProvider() {
+ @Override
+ public boolean isPrivateSpaceLocked(Context context) {
+ return false;
+ }
+ },
+ new ProfileSelectFragment.ManagedProfileInfoProvider() {
+ @Override
+ public UserHandle getManagedProfile(Context context) {
+ return null;
+ }
+ });
+ assertThat(fragments).hasLength(2);
+ }
+
+ @Test
+ public void testGetFragments_whenManagedProfile_returnsTwoFragments() {
+ mSetFlagsRule.disableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+ Fragment[] fragments = ProfileSelectFragment.getFragments(
+ mContext,
+ null /* bundle */,
+ TestProfileSelectFragment::new,
+ TestProfileSelectFragment::new,
+ TestProfileSelectFragment::new,
+ new ProfileSelectFragment.PrivateSpaceInfoProvider() {
+ @Override
+ public boolean isPrivateSpaceLocked(Context context) {
+ return false;
+ }
+ },
+ new ProfileSelectFragment.ManagedProfileInfoProvider() {
+ @Override
+ public UserHandle getManagedProfile(Context context) {
+ return new UserHandle(123);
+ }
+ });
+ assertThat(fragments).hasLength(2);
+ }
+
+ @Test
+ public void testGetFragments_whenAllProfiles_returnsThreeFragments() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+ Fragment[] fragments = ProfileSelectFragment.getFragments(
+ mContext,
+ null /* bundle */,
+ TestProfileSelectFragment::new,
+ TestProfileSelectFragment::new,
+ TestProfileSelectFragment::new,
+ new ProfileSelectFragment.PrivateSpaceInfoProvider() {
+ @Override
+ public boolean isPrivateSpaceLocked(Context context) {
+ return false;
+ }
+ },
+ new ProfileSelectFragment.ManagedProfileInfoProvider() {
+ @Override
+ public UserHandle getManagedProfile(Context context) {
+ return new UserHandle(123);
+ }
+ });
+ assertThat(fragments).hasLength(3);
+ }
+
public static class TestProfileSelectFragment extends ProfileSelectFragment {
@Override
public Fragment[] getFragments() {
return new Fragment[]{
new SettingsPreferenceFragmentTest.TestFragment(), //0
+ new SettingsPreferenceFragmentTest.TestFragment(),
new SettingsPreferenceFragmentTest.TestFragment()
};
}
diff --git a/tests/robotests/src/com/android/settings/dashboard/profileselector/ProfileSelectLocationFragmentTest.java b/tests/robotests/src/com/android/settings/dashboard/profileselector/ProfileSelectLocationFragmentTest.java
index f463bec..fa2782f 100644
--- a/tests/robotests/src/com/android/settings/dashboard/profileselector/ProfileSelectLocationFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/profileselector/ProfileSelectLocationFragmentTest.java
@@ -39,10 +39,12 @@
@Test
public void getFragments_containsCorrectBundle() {
- assertThat(mProfileSelectLocationFragment.getFragments().length).isEqualTo(2);
+ assertThat(mProfileSelectLocationFragment.getFragments().length).isEqualTo(3);
assertThat(mProfileSelectLocationFragment.getFragments()[0].getArguments().getInt(
EXTRA_PROFILE, -1)).isEqualTo(ProfileSelectFragment.ProfileType.PERSONAL);
assertThat(mProfileSelectLocationFragment.getFragments()[1].getArguments().getInt(
EXTRA_PROFILE, -1)).isEqualTo(ProfileSelectFragment.ProfileType.WORK);
+ assertThat(mProfileSelectLocationFragment.getFragments()[1].getArguments().getInt(
+ EXTRA_PROFILE, -1)).isEqualTo(ProfileSelectFragment.ProfileType.PRIVATE);
}
}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java
index 5db0243..b61f5ab 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java
@@ -52,6 +52,7 @@
import com.android.settings.SubSettings;
import com.android.settings.applications.manageapplications.ManageApplications;
import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
+import com.android.settings.dashboard.profileselector.ProfileSelectFragment.ProfileType;
import com.android.settings.deviceinfo.StorageItemPreference;
import com.android.settings.testutils.shadow.ShadowUserManager;
import com.android.settingslib.deviceinfo.StorageVolumeProvider;
@@ -99,7 +100,7 @@
// Note: null is passed as the Lifecycle because we are handling it outside of the normal
// Settings fragment lifecycle for test purposes.
mController = new StorageItemPreferenceController(mContext, mFragment, mVolume, mSvp,
- false /* isWorkProfile */);
+ ProfileSelectFragment.ProfileType.PERSONAL);
mPreference = new StorageItemPreference(mContext);
// Inflate the preference and the widget.
@@ -175,7 +176,7 @@
mPreference.setKey(StorageItemPreferenceController.IMAGES_KEY);
final Context mockContext = getMockContext();
mController = new StorageItemPreferenceController(mockContext, mFragment, mVolume,
- mSvp, false /* isWorkProfile */);
+ mSvp, ProfileSelectFragment.ProfileType.PERSONAL);
mController.handlePreferenceTreeClick(mPreference);
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -192,7 +193,7 @@
mPreference.setKey(StorageItemPreferenceController.AUDIO_KEY);
final Context mockContext = getMockContext();
mController = new StorageItemPreferenceController(mockContext, mFragment, mVolume,
- mSvp, false /* isWorkProfile */);
+ mSvp, ProfileSelectFragment.ProfileType.PERSONAL);
mController.handlePreferenceTreeClick(mPreference);
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -242,7 +243,7 @@
@Test
public void launchAppsIntent_forWork_settingsIntent() {
mController = new FakeStorageItemPreferenceController(mContext, mFragment, mVolume, mSvp,
- true /* isWorkProfile */);
+ ProfileType.WORK);
mPreference.setKey(StorageItemPreferenceController.APPS_KEY);
mController.handlePreferenceTreeClick(mPreference);
@@ -272,7 +273,7 @@
mPreference.setKey(StorageItemPreferenceController.DOCUMENTS_AND_OTHER_KEY);
final Context mockContext = getMockContext();
mController = new StorageItemPreferenceController(mockContext, mFragment, mVolume,
- mSvp, false /* isWorkProfile */);
+ mSvp, ProfileSelectFragment.ProfileType.PERSONAL);
mController.handlePreferenceTreeClick(mPreference);
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -307,7 +308,7 @@
mPreference.setKey(StorageItemPreferenceController.VIDEOS_KEY);
final Context mockContext = getMockContext();
mController = new StorageItemPreferenceController(mockContext, mFragment, mVolume,
- mSvp, false /* isWorkProfile */);
+ mSvp, ProfileSelectFragment.ProfileType.PERSONAL);
mController.handlePreferenceTreeClick(mPreference);
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -457,8 +458,8 @@
private static final int CURRENT_USER_ID = 10;
FakeStorageItemPreferenceController(Context context, Fragment hostFragment,
- VolumeInfo volume, StorageVolumeProvider svp, boolean isWorkProfile) {
- super(context, hostFragment, volume, svp, isWorkProfile);
+ VolumeInfo volume, StorageVolumeProvider svp, @ProfileType int profileType) {
+ super(context, hostFragment, volume, svp, profileType);
}
@Override
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/ConvertUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/ConvertUtilsTest.java
index cd594d3..c648cde 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/ConvertUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/ConvertUtilsTest.java
@@ -32,6 +32,7 @@
import android.content.Context;
import android.content.pm.PackageManager;
import android.database.MatrixCursor;
+import android.os.BatteryConsumer;
import android.os.BatteryManager;
import android.os.BatteryUsageStats;
import android.os.LocaleList;
@@ -80,8 +81,7 @@
}
@Test
- public void convertBatteryEntryToContentValues_returnsExpectedContentValues() {
- final int expectedType = 3;
+ public void convertBatteryEntryToContentValues_appEntry_returnsExpectedContentValues() {
when(mMockBatteryEntry.getUid()).thenReturn(1001);
when(mMockBatteryEntry.getLabel()).thenReturn("Settings");
when(mMockBatteryEntry.getDefaultPackageName())
@@ -96,9 +96,9 @@
mMockBatteryEntry.mPercent = 0.3;
when(mMockBatteryEntry.getTimeInForegroundMs()).thenReturn(1234L);
when(mMockBatteryEntry.getTimeInBackgroundMs()).thenReturn(5689L);
- when(mMockBatteryEntry.getPowerComponentId()).thenReturn(expectedType);
+ when(mMockBatteryEntry.getPowerComponentId()).thenReturn(-1);
when(mMockBatteryEntry.getConsumerType())
- .thenReturn(ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY);
+ .thenReturn(ConvertUtils.CONSUMER_TYPE_UID_BATTERY);
final ContentValues values =
ConvertUtils.convertBatteryEntryToContentValues(
@@ -122,7 +122,7 @@
.isEqualTo("com.google.android.settings.battery");
assertThat(values.getAsLong(BatteryHistEntry.KEY_TIMESTAMP)).isEqualTo(10001L);
assertThat(values.getAsInteger(BatteryHistEntry.KEY_CONSUMER_TYPE))
- .isEqualTo(ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY);
+ .isEqualTo(ConvertUtils.CONSUMER_TYPE_UID_BATTERY);
assertThat(values.getAsBoolean(BatteryHistEntry.KEY_IS_FULL_CHARGE_CYCLE_START)).isTrue();
assertThat(batteryInformation.getAppLabel()).isEqualTo("Settings");
assertThat(batteryInformation.getIsHidden()).isTrue();
@@ -137,7 +137,71 @@
assertThat(batteryInformation.getPercentOfTotal()).isEqualTo(0.3);
assertThat(batteryInformation.getForegroundUsageTimeInMs()).isEqualTo(1234L);
assertThat(batteryInformation.getBackgroundUsageTimeInMs()).isEqualTo(5689L);
- assertThat(batteryInformation.getDrainType()).isEqualTo(expectedType);
+ assertThat(batteryInformation.getDrainType()).isEqualTo(-1);
+ assertThat(deviceBatteryState.getBatteryLevel()).isEqualTo(12);
+ assertThat(deviceBatteryState.getBatteryStatus())
+ .isEqualTo(BatteryManager.BATTERY_STATUS_FULL);
+ assertThat(deviceBatteryState.getBatteryHealth())
+ .isEqualTo(BatteryManager.BATTERY_HEALTH_COLD);
+ }
+
+ @Test
+ public void convertBatteryEntryToContentValues_systemEntry_returnsExpectedContentValues() {
+ when(mMockBatteryEntry.getUid()).thenReturn(-1);
+ when(mMockBatteryEntry.getLabel()).thenReturn("CPU");
+ when(mMockBatteryEntry.getDefaultPackageName()).thenReturn(null);
+ when(mMockBatteryEntry.getPowerComponentId()).thenReturn(
+ BatteryConsumer.POWER_COMPONENT_CPU);
+ when(mBatteryUsageStats.getConsumedPower()).thenReturn(5.1);
+ when(mMockBatteryEntry.getConsumedPower()).thenReturn(1.1);
+ when(mMockBatteryEntry.getConsumedPowerInForeground()).thenReturn(1.2);
+ when(mMockBatteryEntry.getConsumedPowerInForegroundService()).thenReturn(1.3);
+ when(mMockBatteryEntry.getConsumedPowerInBackground()).thenReturn(1.4);
+ when(mMockBatteryEntry.getConsumedPowerInCached()).thenReturn(1.5);
+ mMockBatteryEntry.mPercent = 0.3;
+ when(mMockBatteryEntry.getTimeInForegroundMs()).thenReturn(1234L);
+ when(mMockBatteryEntry.getTimeInBackgroundMs()).thenReturn(5689L);
+ when(mMockBatteryEntry.getConsumerType())
+ .thenReturn(ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY);
+
+ final ContentValues values =
+ ConvertUtils.convertBatteryEntryToContentValues(
+ mMockBatteryEntry,
+ mBatteryUsageStats,
+ /*batteryLevel=*/ 12,
+ /*batteryStatus=*/ BatteryManager.BATTERY_STATUS_FULL,
+ /*batteryHealth=*/ BatteryManager.BATTERY_HEALTH_COLD,
+ /*bootTimestamp=*/ 101L,
+ /*timestamp=*/ 10001L,
+ /*isFullChargeStart=*/ true);
+ final BatteryInformation batteryInformation =
+ ConvertUtils.getBatteryInformation(
+ values, BatteryHistEntry.KEY_BATTERY_INFORMATION);
+ final DeviceBatteryState deviceBatteryState = batteryInformation.getDeviceBatteryState();
+
+ assertThat(values.getAsLong(BatteryHistEntry.KEY_UID)).isEqualTo(-1);
+ assertThat(values.getAsLong(BatteryHistEntry.KEY_USER_ID))
+ .isEqualTo(UserHandle.getUserId(1001));
+ assertThat(values.getAsString(BatteryHistEntry.KEY_PACKAGE_NAME)).isEqualTo("");
+ assertThat(values.getAsLong(BatteryHistEntry.KEY_TIMESTAMP)).isEqualTo(10001L);
+ assertThat(values.getAsInteger(BatteryHistEntry.KEY_CONSUMER_TYPE))
+ .isEqualTo(ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY);
+ assertThat(values.getAsBoolean(BatteryHistEntry.KEY_IS_FULL_CHARGE_CYCLE_START)).isTrue();
+ assertThat(batteryInformation.getAppLabel()).isEqualTo("CPU");
+ assertThat(batteryInformation.getIsHidden()).isFalse();
+ assertThat(batteryInformation.getBootTimestamp()).isEqualTo(101L);
+ assertThat(batteryInformation.getZoneId()).isEqualTo(TimeZone.getDefault().getID());
+ assertThat(batteryInformation.getTotalPower()).isEqualTo(5.1);
+ assertThat(batteryInformation.getConsumePower()).isEqualTo(1.1);
+ assertThat(batteryInformation.getForegroundUsageConsumePower()).isEqualTo(1.2);
+ assertThat(batteryInformation.getForegroundServiceUsageConsumePower()).isEqualTo(1.3);
+ assertThat(batteryInformation.getBackgroundUsageConsumePower()).isEqualTo(1.4);
+ assertThat(batteryInformation.getCachedUsageConsumePower()).isEqualTo(1.5);
+ assertThat(batteryInformation.getPercentOfTotal()).isEqualTo(0.3);
+ assertThat(batteryInformation.getForegroundUsageTimeInMs()).isEqualTo(1234L);
+ assertThat(batteryInformation.getBackgroundUsageTimeInMs()).isEqualTo(5689L);
+ assertThat(batteryInformation.getDrainType()).isEqualTo(
+ BatteryConsumer.POWER_COMPONENT_CPU);
assertThat(deviceBatteryState.getBatteryLevel()).isEqualTo(12);
assertThat(deviceBatteryState.getBatteryStatus())
.isEqualTo(BatteryManager.BATTERY_STATUS_FULL);
diff --git a/tests/robotests/testutils/com/android/settings/testutils/shadow/ShadowUserManager.java b/tests/robotests/testutils/com/android/settings/testutils/shadow/ShadowUserManager.java
index c8d2866..ce6dc6a 100644
--- a/tests/robotests/testutils/com/android/settings/testutils/shadow/ShadowUserManager.java
+++ b/tests/robotests/testutils/com/android/settings/testutils/shadow/ShadowUserManager.java
@@ -17,6 +17,7 @@
package com.android.settings.testutils.shadow;
import static android.os.Build.VERSION_CODES.LOLLIPOP;
+import static android.os.UserManager.USER_TYPE_PROFILE_PRIVATE;
import android.annotation.UserIdInt;
import android.content.pm.UserInfo;
@@ -223,6 +224,10 @@
mManagedProfiles.addAll(profileIds);
}
+ public void setPrivateProfile(int id, String name, int flags) {
+ mUserProfileInfos.add(new UserInfo(id, name, null, flags, USER_TYPE_PROFILE_PRIVATE));
+ }
+
public void setUserSwitcherEnabled(boolean userSwitchEnabled) {
mUserSwitchEnabled = userSwitchEnabled;
}
diff --git a/tests/uitests/Android.bp b/tests/uitests/Android.bp
index 407b5ec..f149519 100644
--- a/tests/uitests/Android.bp
+++ b/tests/uitests/Android.bp
@@ -47,7 +47,7 @@
"settings-helper",
"sysui-helper",
"timeresult-helper-lib",
- "truth-prebuilt",
+ "truth",
],
//sdk_version: "current",
diff --git a/tests/unit/Android.bp b/tests/unit/Android.bp
index 1b14a73..0f045a8 100644
--- a/tests/unit/Android.bp
+++ b/tests/unit/Android.bp
@@ -27,7 +27,7 @@
"mockito-target-minus-junit4",
"platform-test-annotations",
"platform-test-rules",
- "truth-prebuilt",
+ "truth",
"kotlinx_coroutines_test",
"flag-junit",
"Settings-testutils2",
@@ -36,7 +36,7 @@
],
errorprone: {
- javacflags: ["-Xep:CheckReturnValue:WARN"]
+ javacflags: ["-Xep:CheckReturnValue:WARN"],
},
// Include all test java/kotlin files.
srcs: [