Snap for 7306623 from 16f3036c4b to sc-release

Change-Id: Ib9280871b9dc7888d76c97769c089da0cae19209
This commit is contained in:
android-build-team Robot
2021-04-23 01:08:52 +00:00
34 changed files with 741 additions and 282 deletions

View File

@@ -1,23 +0,0 @@
<?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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/black"
android:pathData="M21,3L3,10.53v0.98l6.84,2.65L12.48,21h0.98L21,3z"/>
</vector>

View File

@@ -36,7 +36,7 @@
android:layout_width="56dp" android:layout_width="56dp"
android:layout_height="56dp" android:layout_height="56dp"
android:layout_marginTop="12dp" android:layout_marginTop="12dp"
android:layout_toRightOf="@id/filter_spinner" android:layout_toEndOf="@id/filter_spinner"
android:contentDescription="@string/configure" android:contentDescription="@string/configure"
android:scaleType="center" android:scaleType="center"
android:src="@drawable/ic_apps_filter_settings_24dp" android:src="@drawable/ic_apps_filter_settings_24dp"

View File

@@ -1,68 +0,0 @@
<?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.
-->
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/content_parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:outlineAmbientShadowColor="@android:color/transparent"
android:outlineSpotShadowColor="@android:color/transparent"
android:background="@android:color/transparent"
android:theme="@style/Theme.CollapsingToolbar.Settings">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="@dimen/toolbar_one_line_height"
android:clipToPadding="false"
app:contentScrim="@color/color_surface_header"
app:maxLines="3"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
app:scrimAnimationDuration="50"
app:scrimVisibleHeightTrigger="@dimen/scrim_visible_height_trigger"
app:statusBarScrim="@empty"
app:titleCollapseMode="fade"
app:collapsedTitleTextAppearance="@style/ToolbarText.Collapsed"
app:expandedTitleTextAppearance="@style/ToolbarText.Expanded"
app:expandedTitleMarginStart="@dimen/expanded_title_margin_start"
app:expandedTitleMarginEnd="@dimen/expanded_title_margin_end"
app:toolbarId="@id/action_bar">
<Toolbar
android:id="@+id/action_bar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:theme="?android:attr/actionBarTheme"
app:layout_collapseMode="pin"/>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<FrameLayout
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -446,12 +446,4 @@
<dimen name="chartview_trapezoid_radius">2dp</dimen> <dimen name="chartview_trapezoid_radius">2dp</dimen>
<dimen name="chartview_trapezoid_margin_start">1dp</dimen> <dimen name="chartview_trapezoid_margin_start">1dp</dimen>
<dimen name="chartview_trapezoid_margin_bottom">2dp</dimen> <dimen name="chartview_trapezoid_margin_bottom">2dp</dimen>
<!-- Collapsing toolbar layout dimensions -->
<dimen name="toolbar_one_line_height">226dp</dimen>
<dimen name="toolbar_two_lines_height">270dp</dimen>
<dimen name="toolbar_three_lines_height">314dp</dimen>
<dimen name="scrim_visible_height_trigger">174dp</dimen>
<dimen name="expanded_title_margin_start">24dp</dimen>
<dimen name="expanded_title_margin_end">24dp</dimen>
</resources> </resources>

View File

@@ -4121,7 +4121,7 @@
<!-- Description text for Bluetooth always scanning --> <!-- Description text for Bluetooth always scanning -->
<string name="location_scanning_bluetooth_always_scanning_description">Allow apps and services to scan for nearby devices at any time, even when Bluetooth is off. This can be used, for example, to improve location-based features and services.</string> <string name="location_scanning_bluetooth_always_scanning_description">Allow apps and services to scan for nearby devices at any time, even when Bluetooth is off. This can be used, for example, to improve location-based features and services.</string>
<!-- [CHAR LIMIT=60] Location Services preference title --> <!-- [CHAR LIMIT=60] Location Services preference title -->
<string name="location_services_preference_title">Manage location services</string> <string name="location_services_preference_title">Location services</string>
<!-- [CHAR LIMIT=60] Location Services screen, screen title --> <!-- [CHAR LIMIT=60] Location Services screen, screen title -->
<string name="location_services_screen_title">Location Services</string> <string name="location_services_screen_title">Location Services</string>
<!-- [CHAR LIMIT=50] Location settings screen, sub category for location services for managed profile --> <!-- [CHAR LIMIT=50] Location settings screen, sub category for location services for managed profile -->
@@ -6255,8 +6255,39 @@
<string name ="battery_detail_info_title">Since full charge</string> <string name ="battery_detail_info_title">Since full charge</string>
<!-- Title for the battery management group [CHAR LIMIT=40] --> <!-- Title for the battery management group [CHAR LIMIT=40] -->
<string name ="battery_detail_manage_title">Manage battery usage</string> <string name ="battery_detail_manage_title">Manage battery usage</string>
<!-- Description for battery total and background usage time for an app, i.e. 1 hr 15 min total • 39 min background for past 24 hr. Note: ^1 and ^2 should be used in all translations [CHAR LIMIT=120] --> <!-- Description for battery total and background usage time for an app, i.e. 1 hr 15 min total • 39 min background for past 24 hr. Note: ^1 and ^2 should be used in all translations [CHAR LIMIT=120] -->
<string name="battery_total_and_background_usage"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total • <xliff:g id="time" example="39 min">^2</xliff:g> background for past 24 hr</string> <string name="battery_total_and_background_usage"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total • <xliff:g id="time" example="39 min">^2</xliff:g> background for past 24 hr</string>
<!-- Description for battery total and background usage time in a time period for an app, i.e. 1 hr 15 min total • 39 min background for 12 am-2 am. Note: ^1, ^2 and ^3 should be used in all translations [CHAR LIMIT=120] -->
<string name="battery_total_and_background_usage_with_period"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total • <xliff:g id="time" example="39 min">^2</xliff:g> background for <xliff:g id="time_period" example="12 am-2 am">^3</xliff:g></string>
<!-- Description for battery total usage time is less than a minute for an app [CHAR LIMIT=120] -->
<string name="battery_total_usage_less_minute">Total less than a minute for past 24 hr</string>
<!-- Description for battery total usage time is less than a minute in a time period for an app, i.e. Total less than a minute for 12 am-2 am. Note: ^1 should be used in all translations[CHAR LIMIT=120] -->
<string name="battery_total_usage_less_minute_with_period">Total less than a minute for <xliff:g id="time_period" example="12 am-2 am">^1</xliff:g></string>
<!-- Description for battery background usage time is less than a minute for an app [CHAR LIMIT=120] -->
<string name="battery_background_usage_less_minute">Background less than a minute for past 24 hr</string>
<!-- Description for battery background usage time is less than a minute in a time period for an app, i.e. Background less than a minute for 12 am-2 am. Note: ^1 should be used in all translations[CHAR LIMIT=120] -->
<string name="battery_background_usage_less_minute_with_period">Background less than a minute for <xliff:g id="time_period" example="12 am-2 am">^1</xliff:g></string>
<!-- Description for battery total usage time for an app, i.e. 1 hr 15 min total for past 24 hr. Note: ^1 should be used in all translations [CHAR LIMIT=120] -->
<string name="battery_total_usage"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total for past 24 hr</string>
<!-- Description for battery total usage time in a time period for an app, i.e. 1 hr 15 min total for 12 am-2 am. Note: ^1 and ^2 should be used in all translations [CHAR LIMIT=120] -->
<string name="battery_total_usage_with_period"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total for <xliff:g id="time_period" example="12 am-2 am">^2</xliff:g></string>
<!-- Description for battery background usage time for an app, i.e. 1 hr 15 min background for past 24 hr. Note: ^1 should be used in all translations [CHAR LIMIT=120] -->
<string name="battery_background_usage"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> background for past 24 hr</string>
<!-- Description for battery background usage time in a time period for an app, i.e. 1 hr 15 min background for 12 am-2 am. Note: ^1 and ^2 should be used in all translations [CHAR LIMIT=120] -->
<string name="battery_background_usage_with_period"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> background for <xliff:g id="time_period" example="12 am-2 am">^2</xliff:g></string>
<!-- Description for battery total usage with background usage time less than a minute for an app, i.e. 1 hr 15 min total • background less than a minute for past 24 hr. Note: ^1 should be used in all translations [CHAR LIMIT=120] -->
<string name="battery_total_usage_and_background_less_minute_usage"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total • background less than a minute for past 24 hr</string>
<!-- Description for battery total usage with background usage time less than a minute in a time period for an app, i.e. 1 hr 15 min total • background less than a minute for 12 am-2 am. Note: ^1 and ^2 should be used in all translations [CHAR LIMIT=120] -->
<string name="battery_total_usage_and_background_less_minute_usage_with_period"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total • background less than a minute for <xliff:g id="time_period" example="12 am-2 am">^2</xliff:g></string>
<!-- Description for no any battery usage for past 24 hr [CHAR LIMIT=120] -->
<string name="battery_not_usage">No usage for past 24 hr</string>
<!-- Graph subtext displayed to user when enhanced battery estimate is being used [CHAR LIMIT=120] --> <!-- Graph subtext displayed to user when enhanced battery estimate is being used [CHAR LIMIT=120] -->
<string name="advanced_battery_graph_subtext">Battery left estimate is based on your device usage</string> <string name="advanced_battery_graph_subtext">Battery left estimate is based on your device usage</string>
@@ -13187,4 +13218,13 @@
<!-- Label for button to not allow grant the permission for remote devices. [CHAR_LIMIT=50] --> <!-- Label for button to not allow grant the permission for remote devices. [CHAR_LIMIT=50] -->
<string name="request_manage_bluetooth_permission_dont_allow">Don\u2019t allow</string> <string name="request_manage_bluetooth_permission_dont_allow">Don\u2019t allow</string>
<!-- Title for UWB preference [CHAR_LIMIT=60] -->
<string name="uwb_settings_title">Ultra-WideBand (UWB)</string>
<!-- Summary for UWB preference. [CHAR_LIMIT=NONE]-->
<string name="uwb_settings_summary">Helps identify the relative position of nearby devices that have UWB</string>
<!-- Summary for UWB preference when airplane mode is disabled. [CHAR_LIMIT=NONE]-->
<string name="uwb_settings_summary_airplane_mode">Turn off Airplane mode to use UWB. </string>
</resources> </resources>

View File

@@ -787,7 +787,7 @@
<item name="android:fontFamily">@*android:string/config_headlineFontFamily</item> <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
</style> </style>
<style name="HomepageTitleText" parent="ToolbarText.Expanded"> <style name="HomepageTitleText" parent="CollapsingToolbarTitle.Expanded">
<item name="android:layout_width">wrap_content</item> <item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item> <item name="android:layout_height">wrap_content</item>
<item name="android:layout_marginBottom">@dimen/homepage_title_margin_bottom</item> <item name="android:layout_marginBottom">@dimen/homepage_title_margin_bottom</item>
@@ -879,8 +879,4 @@
<item name="android:textSize">16sp</item> <item name="android:textSize">16sp</item>
<item name="android:textColor">?android:attr/textColorSecondary</item> <item name="android:textColor">?android:attr/textColorSecondary</item>
</style> </style>
<style name="ToolbarText.Collapsed" parent="CollapsingToolbarTitle.Collapsed"/>
<style name="ToolbarText.Expanded" parent="CollapsingToolbarTitle"/>
<style name="ToolbarText.MoreThanTwoLines" parent="CollapsingToolbarTitle.MoreThanTwoLines"/>
</resources> </resources>

View File

@@ -30,7 +30,6 @@
<style name="PreferenceTheme.SetupWizard" parent="@style/SettingsPreferenceTheme"> <style name="PreferenceTheme.SetupWizard" parent="@style/SettingsPreferenceTheme">
<item name="preferenceFragmentCompatStyle">@style/SetupWizardPreferenceFragmentStyle</item> <item name="preferenceFragmentCompatStyle">@style/SetupWizardPreferenceFragmentStyle</item>
<item name="preferenceStyle">@style/Preference.Material</item>
</style> </style>
<style name="ApnPreference" parent="@style/Preference.Material"> <style name="ApnPreference" parent="@style/Preference.Material">

View File

@@ -272,5 +272,7 @@
<style name="Theme.NotificationHistory" parent="@android:style/Theme.DeviceDefault.DayNight"> <style name="Theme.NotificationHistory" parent="@android:style/Theme.DeviceDefault.DayNight">
<item name="android:windowActionBar">false</item> <item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item> <item name="android:windowNoTitle">true</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:statusBarColor">@android:color/transparent</item>
</style> </style>
</resources> </resources>

View File

@@ -26,7 +26,7 @@
<com.android.settings.widget.SettingsMainSwitchPreference <com.android.settings.widget.SettingsMainSwitchPreference
android:key="block" /> android:key="block" />
<com.android.settings.notification.app.NotificationFooterPreference <com.android.settingslib.widget.FooterPreference
android:key="block_desc" /> android:key="block_desc" />
@@ -96,11 +96,11 @@
</PreferenceCategory> </PreferenceCategory>
<com.android.settings.notification.app.NotificationFooterPreference <com.android.settingslib.widget.FooterPreference
android:key="desc" android:key="desc"
android:order="5000" /> android:order="5000" />
<com.android.settings.notification.app.NotificationFooterPreference <com.android.settingslib.widget.FooterPreference
android:key="deleted" android:key="deleted"
android:order="8000" /> android:order="8000" />

View File

@@ -116,11 +116,11 @@
android:title="@string/app_settings_link" android:title="@string/app_settings_link"
settings:allowDividerAbove="true"/> settings:allowDividerAbove="true"/>
<com.android.settings.notification.app.NotificationFooterPreference <com.android.settingslib.widget.FooterPreference
android:key="desc" android:key="desc"
android:order="100"/> android:order="100"/>
<com.android.settings.notification.app.NotificationFooterPreference <com.android.settingslib.widget.FooterPreference
android:key="block_desc" android:key="block_desc"
android:order="110" android:order="110"
settings:allowDividerAbove="false"/> settings:allowDividerAbove="false"/>

View File

@@ -65,6 +65,13 @@
android:icon="@drawable/ic_folder_vd_theme_24" android:icon="@drawable/ic_folder_vd_theme_24"
android:title="@string/bluetooth_show_files_received_via_bluetooth"/> android:title="@string/bluetooth_show_files_received_via_bluetooth"/>
<SwitchPreference
android:key="uwb_settings"
android:title="@string/uwb_settings_title"
android:order="100"
android:summary="@string/summary_placeholder"
settings:controller="com.android.settings.uwb.UwbPreferenceController"/>
<PreferenceCategory <PreferenceCategory
android:key="dashboard_tile_placeholder" android:key="dashboard_tile_placeholder"
android:order="-8"/> android:order="-8"/>

View File

@@ -58,7 +58,7 @@
android:summary="@string/demote_conversation_summary" android:summary="@string/demote_conversation_summary"
settings:allowDividerAbove="true"/> settings:allowDividerAbove="true"/>
<com.android.settings.notification.app.NotificationFooterPreference <com.android.settingslib.widget.FooterPreference
android:key="block_desc" android:key="block_desc"
settings:allowDividerAbove="false"/> settings:allowDividerAbove="false"/>

View File

@@ -65,7 +65,7 @@
<Preference <Preference
android:fragment="com.android.settings.location.LocationServices" android:fragment="com.android.settings.location.LocationServices"
android:key="location_services" android:key="location_services"
android:icon="@drawable/baseline_near_me" android:icon="@drawable/ic_chevron_right_24dp"
android:title="@string/location_services_preference_title" android:title="@string/location_services_preference_title"
settings:controller="com.android.settings.location.LocationServicesPreferenceController"/> settings:controller="com.android.settings.location.LocationServicesPreferenceController"/>

View File

@@ -31,9 +31,9 @@
android:title="@string/app_settings_link" android:title="@string/app_settings_link"
settings:allowDividerAbove="true"/> settings:allowDividerAbove="true"/>
<com.android.settings.notification.NotificationFooterPreference <com.android.settingslib.widget.FooterPreference
android:key="desc" /> android:key="desc" />
<com.android.settings.notification.NotificationFooterPreference <com.android.settingslib.widget.FooterPreference
android:key="block_desc" /> android:key="block_desc" />
</PreferenceScreen> </PreferenceScreen>

View File

@@ -26,6 +26,7 @@ import android.content.res.TypedArray;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.text.Spannable; import android.text.Spannable;
import android.text.SpannableString; import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.method.LinkMovementMethod; import android.text.method.LinkMovementMethod;
import android.text.style.ImageSpan; import android.text.style.ImageSpan;
@@ -320,8 +321,13 @@ public class AccessibilityEditDialogUtils {
} }
private static CharSequence retrieveSummary(Context context, int lineHeight) { private static CharSequence retrieveSummary(Context context, int lineHeight) {
return AccessibilityUtil.isFloatingMenuEnabled(context) final SpannableStringBuilder sb = new SpannableStringBuilder();
? getSummaryStringWithLink(context) : getSummaryStringWithIcon(context, lineHeight); if (!AccessibilityUtil.isFloatingMenuEnabled(context)) {
sb.append(getSummaryStringWithIcon(context, lineHeight));
sb.append("\n\n");
}
sb.append(getCustomizeAccessibilityButtonLink(context));
return sb;
} }
private static int retrieveSoftwareShortcutImageResId(Context context) { private static int retrieveSoftwareShortcutImageResId(Context context) {
@@ -330,7 +336,7 @@ public class AccessibilityEditDialogUtils {
: R.drawable.accessibility_shortcut_type_software; : R.drawable.accessibility_shortcut_type_software;
} }
private static CharSequence getSummaryStringWithLink(Context context) { private static CharSequence getCustomizeAccessibilityButtonLink(Context context) {
final View.OnClickListener linkListener = v -> new SubSettingLauncher(context) final View.OnClickListener linkListener = v -> new SubSettingLauncher(context)
.setDestination(AccessibilityButtonFragment.class.getName()) .setDestination(AccessibilityButtonFragment.class.getName())
.setSourceMetricsCategory( .setSourceMetricsCategory(

View File

@@ -16,6 +16,9 @@
package com.android.settings.biometrics; package com.android.settings.biometrics;
import static android.provider.Settings.ACTION_BIOMETRIC_ENROLL;
import static android.provider.Settings.EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManager;
import android.app.settings.SettingsEnums; import android.app.settings.SettingsEnums;
@@ -24,6 +27,7 @@ import android.content.pm.PackageManager;
import android.content.res.Resources; import android.content.res.Resources;
import android.hardware.biometrics.BiometricManager; import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricManager.Authenticators; import android.hardware.biometrics.BiometricManager.Authenticators;
import android.hardware.biometrics.BiometricManager.BiometricError;
import android.hardware.face.FaceManager; import android.hardware.face.FaceManager;
import android.hardware.face.FaceSensorPropertiesInternal; import android.hardware.face.FaceSensorPropertiesInternal;
import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintManager;
@@ -31,11 +35,11 @@ import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.os.Bundle; import android.os.Bundle;
import android.os.UserHandle; import android.os.UserHandle;
import android.os.UserManager; import android.os.UserManager;
import android.provider.Settings;
import android.util.Log; import android.util.Log;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockPatternUtils;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.SetupWizardUtils; import com.android.settings.SetupWizardUtils;
@@ -68,12 +72,14 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
public static final String EXTRA_SKIP_INTRO = "skip_intro"; public static final String EXTRA_SKIP_INTRO = "skip_intro";
private static final String SAVED_STATE_CONFIRMING_CREDENTIALS = "confirming_credentials"; private static final String SAVED_STATE_CONFIRMING_CREDENTIALS = "confirming_credentials";
private static final String SAVED_STATE_ENROLL_ACTION_LOGGED = "enroll_action_logged";
private static final String SAVED_STATE_GK_PW_HANDLE = "gk_pw_handle"; private static final String SAVED_STATE_GK_PW_HANDLE = "gk_pw_handle";
public static final class InternalActivity extends BiometricEnrollActivity {} public static final class InternalActivity extends BiometricEnrollActivity {}
private int mUserId = UserHandle.myUserId(); private int mUserId = UserHandle.myUserId();
private boolean mConfirmingCredentials; private boolean mConfirmingCredentials;
private boolean mIsEnrollActionLogged;
private boolean mIsFaceEnrollable; private boolean mIsFaceEnrollable;
private boolean mIsFingerprintEnrollable; private boolean mIsFingerprintEnrollable;
@Nullable private Long mGkPwHandle; @Nullable private Long mGkPwHandle;
@@ -91,15 +97,44 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
} }
if (savedInstanceState != null) { if (savedInstanceState != null) {
mConfirmingCredentials = savedInstanceState mConfirmingCredentials = savedInstanceState.getBoolean(
.getBoolean(SAVED_STATE_CONFIRMING_CREDENTIALS, false); SAVED_STATE_CONFIRMING_CREDENTIALS, false);
mIsEnrollActionLogged = savedInstanceState.getBoolean(
SAVED_STATE_ENROLL_ACTION_LOGGED, false);
if (savedInstanceState.containsKey(SAVED_STATE_GK_PW_HANDLE)) { if (savedInstanceState.containsKey(SAVED_STATE_GK_PW_HANDLE)) {
mGkPwHandle = savedInstanceState.getLong(SAVED_STATE_GK_PW_HANDLE); mGkPwHandle = savedInstanceState.getLong(SAVED_STATE_GK_PW_HANDLE);
} }
} }
// Put the theme in the intent so it gets propagated to other activities in the flow // Log a framework stats event if this activity was launched via intent action.
final Intent intent = getIntent(); final Intent intent = getIntent();
if (!mIsEnrollActionLogged && ACTION_BIOMETRIC_ENROLL.equals(intent.getAction())) {
mIsEnrollActionLogged = true;
// Get the current status for each authenticator type.
@BiometricError final int strongBiometricStatus;
@BiometricError final int weakBiometricStatus;
@BiometricError final int deviceCredentialStatus;
final BiometricManager bm = getSystemService(BiometricManager.class);
if (bm != null) {
strongBiometricStatus = bm.canAuthenticate(Authenticators.BIOMETRIC_STRONG);
weakBiometricStatus = bm.canAuthenticate(Authenticators.BIOMETRIC_WEAK);
deviceCredentialStatus = bm.canAuthenticate(Authenticators.DEVICE_CREDENTIAL);
} else {
strongBiometricStatus = BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE;
weakBiometricStatus = BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE;
deviceCredentialStatus = BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE;
}
FrameworkStatsLog.write(FrameworkStatsLog.AUTH_ENROLL_ACTION_INVOKED,
strongBiometricStatus == BiometricManager.BIOMETRIC_SUCCESS,
weakBiometricStatus == BiometricManager.BIOMETRIC_SUCCESS,
deviceCredentialStatus == BiometricManager.BIOMETRIC_SUCCESS,
intent.hasExtra(EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED),
intent.getIntExtra(EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED, 0));
}
// Put the theme in the intent so it gets propagated to other activities in the flow
if (intent.getStringExtra(WizardManagerHelper.EXTRA_THEME) == null) { if (intent.getStringExtra(WizardManagerHelper.EXTRA_THEME) == null) {
intent.putExtra( intent.putExtra(
WizardManagerHelper.EXTRA_THEME, WizardManagerHelper.EXTRA_THEME,
@@ -108,7 +143,7 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
// Default behavior is to enroll BIOMETRIC_WEAK or above. See ACTION_BIOMETRIC_ENROLL. // Default behavior is to enroll BIOMETRIC_WEAK or above. See ACTION_BIOMETRIC_ENROLL.
final int authenticators = intent.getIntExtra( final int authenticators = intent.getIntExtra(
Settings.EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED, Authenticators.BIOMETRIC_WEAK); EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED, Authenticators.BIOMETRIC_WEAK);
Log.d(TAG, "Authenticators: " + authenticators); Log.d(TAG, "Authenticators: " + authenticators);
@@ -132,7 +167,7 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
} else { } else {
// If the caller is not setup wizard, and the user has something enrolled, finish. // If the caller is not setup wizard, and the user has something enrolled, finish.
final BiometricManager bm = getSystemService(BiometricManager.class); final BiometricManager bm = getSystemService(BiometricManager.class);
final @BiometricManager.BiometricError int result = bm.canAuthenticate(authenticators); final @BiometricError int result = bm.canAuthenticate(authenticators);
if (result != BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED) { if (result != BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED) {
Log.e(TAG, "Unexpected result: " + result); Log.e(TAG, "Unexpected result: " + result);
finish(); finish();
@@ -159,6 +194,7 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
protected void onSaveInstanceState(@NonNull Bundle outState) { protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState); super.onSaveInstanceState(outState);
outState.putBoolean(SAVED_STATE_CONFIRMING_CREDENTIALS, mConfirmingCredentials); outState.putBoolean(SAVED_STATE_CONFIRMING_CREDENTIALS, mConfirmingCredentials);
outState.putBoolean(SAVED_STATE_ENROLL_ACTION_LOGGED, mIsEnrollActionLogged);
if (mGkPwHandle != null) { if (mGkPwHandle != null) {
outState.putLong(SAVED_STATE_GK_PW_HANDLE, mGkPwHandle); outState.putLong(SAVED_STATE_GK_PW_HANDLE, mGkPwHandle);
} }

View File

@@ -49,8 +49,6 @@ import com.android.settingslib.drawer.Tile;
import com.google.android.material.appbar.CollapsingToolbarLayout; import com.google.android.material.appbar.CollapsingToolbarLayout;
import com.google.android.setupcompat.util.WizardManagerHelper; import com.google.android.setupcompat.util.WizardManagerHelper;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -61,7 +59,6 @@ public class SettingsBaseActivity extends FragmentActivity {
protected static final boolean DEBUG_TIMING = false; protected static final boolean DEBUG_TIMING = false;
private static final String TAG = "SettingsBaseActivity"; private static final String TAG = "SettingsBaseActivity";
private static final String DATA_SCHEME_PKG = "package"; private static final String DATA_SCHEME_PKG = "package";
private static final int TOOLBAR_MAX_LINE_NUMBER = 2;
// Serves as a temporary list of tiles to ignore until we heard back from the PM that they // Serves as a temporary list of tiles to ignore until we heard back from the PM that they
// are disabled. // are disabled.
@@ -95,7 +92,7 @@ public class SettingsBaseActivity extends FragmentActivity {
if (FeatureFlagUtils.isEnabled(this, FeatureFlags.SILKY_HOME) if (FeatureFlagUtils.isEnabled(this, FeatureFlags.SILKY_HOME)
&& isToolbarEnabled() && !isAnySetupWizard) { && isToolbarEnabled() && !isAnySetupWizard) {
super.setContentView(R.layout.settings_collapsing_base_layout); super.setContentView(R.layout.collapsing_toolbar_base_layout);
mCollapsingToolbarLayout = findViewById(R.id.collapsing_toolbar); mCollapsingToolbarLayout = findViewById(R.id.collapsing_toolbar);
} else { } else {
super.setContentView(R.layout.settings_base_layout); super.setContentView(R.layout.settings_base_layout);
@@ -108,7 +105,6 @@ public class SettingsBaseActivity extends FragmentActivity {
return; return;
} }
setActionBar(toolbar); setActionBar(toolbar);
initCollapsingToolbar();
if (DEBUG_TIMING) { if (DEBUG_TIMING) {
Log.d(TAG, "onCreate took " + (System.currentTimeMillis() - startTime) + " ms"); Log.d(TAG, "onCreate took " + (System.currentTimeMillis() - startTime) + " ms");
@@ -207,50 +203,6 @@ public class SettingsBaseActivity extends FragmentActivity {
return true; return true;
} }
private void initCollapsingToolbar() {
if (mCollapsingToolbarLayout == null) {
return;
}
mCollapsingToolbarLayout.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom,
int oldLeft, int oldTop, int oldRight, int oldBottom) {
v.removeOnLayoutChangeListener(this);
final int count = getLineCount();
if (count > TOOLBAR_MAX_LINE_NUMBER) {
ViewGroup.LayoutParams lp = mCollapsingToolbarLayout.getLayoutParams();
lp.height = getResources()
.getDimensionPixelSize(R.dimen.toolbar_three_lines_height);
mCollapsingToolbarLayout.setLayoutParams(lp);
} else if (count == TOOLBAR_MAX_LINE_NUMBER) {
ViewGroup.LayoutParams lp = mCollapsingToolbarLayout.getLayoutParams();
lp.height =
getResources().getDimensionPixelSize(R.dimen.toolbar_two_lines_height);
mCollapsingToolbarLayout.setLayoutParams(lp);
}
}
});
}
private int getLineCount() {
try {
final Class<?> toolbarClazz = mCollapsingToolbarLayout.getClass();
final Field textHelperField = toolbarClazz.getDeclaredField("collapsingTextHelper");
textHelperField.setAccessible(true);
final Object textHelperObj = textHelperField.get(mCollapsingToolbarLayout);
final Field layoutField = textHelperObj.getClass().getDeclaredField("textLayout");
layoutField.setAccessible(true);
final Object layoutObj = layoutField.get(textHelperObj);
final Method method = layoutObj.getClass().getDeclaredMethod("getLineCount");
return (int) method.invoke(layoutObj);
} catch (Exception e) {
return 0;
}
}
private void onCategoriesChanged(Set<String> categories) { private void onCategoriesChanged(Set<String> categories) {
final int N = mCategoryListeners.size(); final int N = mCategoryListeners.size();
for (int i = 0; i < N; i++) { for (int i = 0; i < N; i++) {

View File

@@ -371,7 +371,7 @@ public abstract class DevelopmentTiles extends TileService {
mContext = getApplicationContext(); mContext = getApplicationContext();
mSensorPrivacyManager = (SensorPrivacyManager) mContext.getSystemService( mSensorPrivacyManager = (SensorPrivacyManager) mContext.getSystemService(
Context.SENSOR_PRIVACY_SERVICE); Context.SENSOR_PRIVACY_SERVICE);
mIsEnabled = mSensorPrivacyManager.isSensorPrivacyEnabled(); mIsEnabled = mSensorPrivacyManager.isAllSensorPrivacyEnabled();
mMetricsFeatureProvider = FeatureFactory.getFactory( mMetricsFeatureProvider = FeatureFactory.getFactory(
mContext).getMetricsFeatureProvider(); mContext).getMetricsFeatureProvider();
mKeyguardManager = (KeyguardManager) mContext.getSystemService( mKeyguardManager = (KeyguardManager) mContext.getSystemService(
@@ -392,7 +392,7 @@ public abstract class DevelopmentTiles extends TileService {
mMetricsFeatureProvider.action(getApplicationContext(), SettingsEnums.QS_SENSOR_PRIVACY, mMetricsFeatureProvider.action(getApplicationContext(), SettingsEnums.QS_SENSOR_PRIVACY,
isEnabled); isEnabled);
mIsEnabled = isEnabled; mIsEnabled = isEnabled;
mSensorPrivacyManager.setSensorPrivacy(isEnabled); mSensorPrivacyManager.setAllSensorPrivacy(isEnabled);
} }
} }

View File

@@ -43,7 +43,7 @@ public class AdaptiveSleepCameraStatePreferenceController {
mPreference.setPositiveButtonText(R.string.allow); mPreference.setPositiveButtonText(R.string.allow);
mPrivacyManager = SensorPrivacyManager.getInstance(context); mPrivacyManager = SensorPrivacyManager.getInstance(context);
mPrivacyManager.addSensorPrivacyListener(CAMERA, mPrivacyManager.addSensorPrivacyListener(CAMERA,
enabled -> updateVisibility()); (sensor, enabled) -> updateVisibility());
mPreference.setPositiveButtonOnClickListener(p -> { mPreference.setPositiveButtonOnClickListener(p -> {
mPrivacyManager.setSensorPrivacy(CAMERA, false); mPrivacyManager.setSensorPrivacy(CAMERA, false);
}); });

View File

@@ -111,9 +111,7 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements
mPrivacyPreference.setLayoutResource(R.layout.preference_footer); mPrivacyPreference.setLayoutResource(R.layout.preference_footer);
mPrivacyManager = SensorPrivacyManager.getInstance(context); mPrivacyManager = SensorPrivacyManager.getInstance(context);
mPrivacyManager.addSensorPrivacyListener(CAMERA, mPrivacyManager.addSensorPrivacyListener(CAMERA,
enabled -> { (sensor, enabled) -> mAdaptiveSleepController.updatePreference());
mAdaptiveSleepController.updatePreference();
});
} }
@Override @Override

View File

@@ -43,7 +43,7 @@ public class SmartAutoRotateCameraStateController extends BasePreferenceControll
public SmartAutoRotateCameraStateController(Context context, String key) { public SmartAutoRotateCameraStateController(Context context, String key) {
super(context, key); super(context, key);
mPrivacyManager = SensorPrivacyManager.getInstance(context); mPrivacyManager = SensorPrivacyManager.getInstance(context);
mPrivacyManager.addSensorPrivacyListener(CAMERA, enabled -> { mPrivacyManager.addSensorPrivacyListener(CAMERA, (sensor, enabled) -> {
mPreference.setVisible(enabled); mPreference.setVisible(enabled);
updateState(mPreference); updateState(mPreference);
}); });

View File

@@ -52,7 +52,8 @@ public class SmartAutoRotateController extends TogglePreferenceController implem
super(context, preferenceKey); super(context, preferenceKey);
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider(); mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
mPrivacyManager = SensorPrivacyManager.getInstance(context); mPrivacyManager = SensorPrivacyManager.getInstance(context);
mPrivacyManager.addSensorPrivacyListener(CAMERA, enabled -> updateState(mPreference)); mPrivacyManager
.addSensorPrivacyListener(CAMERA, (sensor, enabled) -> updateState(mPreference));
} }
@Override @Override

View File

@@ -27,6 +27,7 @@ import android.os.Bundle;
import android.os.UserHandle; import android.os.UserHandle;
import android.text.Html; import android.text.Html;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
@@ -282,20 +283,8 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
final long foregroundTimeMs = bundle.getLong(EXTRA_FOREGROUND_TIME); final long foregroundTimeMs = bundle.getLong(EXTRA_FOREGROUND_TIME);
final long backgroundTimeMs = bundle.getLong(EXTRA_BACKGROUND_TIME); final long backgroundTimeMs = bundle.getLong(EXTRA_BACKGROUND_TIME);
final long totalTimeMs = foregroundTimeMs + backgroundTimeMs; //TODO(b/178197718) Update layout to support multiple lines
//TODO(b/178197718) Refine the layout controller.setSummary(getAppActiveTime(foregroundTimeMs, backgroundTimeMs));
controller.setSummary(TextUtils.expandTemplate(
getText(R.string.battery_total_and_background_usage),
StringUtil.formatElapsedTime(
getContext(),
totalTimeMs,
/* withSeconds */ false,
/* collapseTimeUnit */ false),
StringUtil.formatElapsedTime(
getContext(),
backgroundTimeMs,
/* withSeconds */ false,
/* collapseTimeUnit */ false)));
controller.done(context, true /* rebindActions */); controller.done(context, true /* rebindActions */);
} }
@@ -388,4 +377,53 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
private void updatePreferenceState(RadioButtonPreference preference, String selectedKey) { private void updatePreferenceState(RadioButtonPreference preference, String selectedKey) {
preference.setChecked(selectedKey.equals(preference.getKey())); preference.setChecked(selectedKey.equals(preference.getKey()));
} }
//TODO(b/178197718) Update method to support time period
private CharSequence getAppActiveTime(long foregroundTimeMs, long backgroundTimeMs) {
final long totalTimeMs = foregroundTimeMs + backgroundTimeMs;
final CharSequence usageTimeSummary;
if (totalTimeMs == 0) {
usageTimeSummary = getText(R.string.battery_not_usage);
// Shows background summary only if we don't have foreground usage time.
} else if (foregroundTimeMs == 0 && backgroundTimeMs != 0) {
usageTimeSummary = backgroundTimeMs < DateUtils.MINUTE_IN_MILLIS ?
getText(R.string.battery_background_usage_less_minute) :
TextUtils.expandTemplate(getText(R.string.battery_background_usage),
StringUtil.formatElapsedTime(
getContext(),
backgroundTimeMs,
/* withSeconds */ false,
/* collapseTimeUnit */ false));
// Shows total usage summary only if total usage time is small.
} else if (totalTimeMs < DateUtils.MINUTE_IN_MILLIS) {
usageTimeSummary = getText(R.string.battery_total_usage_less_minute);
// Shows different total usage summary when background usage time is small.
} else if (backgroundTimeMs < DateUtils.MINUTE_IN_MILLIS) {
usageTimeSummary = TextUtils.expandTemplate(
getText(backgroundTimeMs == 0 ?
R.string.battery_total_usage :
R.string.battery_total_usage_and_background_less_minute_usage),
StringUtil.formatElapsedTime(
getContext(),
totalTimeMs,
/* withSeconds */ false,
/* collapseTimeUnit */ false));
// Shows default summary.
} else {
usageTimeSummary = TextUtils.expandTemplate(
getText(R.string.battery_total_and_background_usage),
StringUtil.formatElapsedTime(
getContext(),
totalTimeMs,
/* withSeconds */ false,
/* collapseTimeUnit */ false),
StringUtil.formatElapsedTime(
getContext(),
backgroundTimeMs,
/* withSeconds */ false,
/* collapseTimeUnit */ false));
}
return usageTimeSummary;
}
} }

View File

@@ -12,7 +12,6 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
* *
*
*/ */
package com.android.settings.fuelgauge; package com.android.settings.fuelgauge;
@@ -51,7 +50,7 @@ import java.util.Map;
/** Controls the update for chart graph and the list items. */ /** Controls the update for chart graph and the list items. */
public class BatteryChartPreferenceController extends AbstractPreferenceController public class BatteryChartPreferenceController extends AbstractPreferenceController
implements PreferenceControllerMixin, LifecycleObserver, OnPause, OnDestroy, implements PreferenceControllerMixin, LifecycleObserver, OnPause, OnDestroy,
BatteryChartView.OnSelectListener { BatteryChartView.OnSelectListener, ExpandDividerPreference.OnExpandListener {
private static final String TAG = "BatteryChartPreferenceController"; private static final String TAG = "BatteryChartPreferenceController";
private static final int CHART_KEY_ARRAY_SIZE = 25; private static final int CHART_KEY_ARRAY_SIZE = 25;
private static final int CHART_LEVEL_ARRAY_SIZE = 13; private static final int CHART_LEVEL_ARRAY_SIZE = 13;
@@ -65,6 +64,7 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
@VisibleForTesting BatteryUtils mBatteryUtils; @VisibleForTesting BatteryUtils mBatteryUtils;
@VisibleForTesting PreferenceGroup mAppListPrefGroup; @VisibleForTesting PreferenceGroup mAppListPrefGroup;
@VisibleForTesting BatteryChartView mBatteryChartView; @VisibleForTesting BatteryChartView mBatteryChartView;
@VisibleForTesting ExpandDividerPreference mExpandDividerPreference;
@VisibleForTesting int[] mBatteryHistoryLevels; @VisibleForTesting int[] mBatteryHistoryLevels;
@VisibleForTesting long[] mBatteryHistoryKeys; @VisibleForTesting long[] mBatteryHistoryKeys;
@@ -76,9 +76,13 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
private final Handler mHandler = new Handler(Looper.getMainLooper()); private final Handler mHandler = new Handler(Looper.getMainLooper());
private final CharSequence[] mNotAllowShowSummaryPackages; private final CharSequence[] mNotAllowShowSummaryPackages;
private boolean mIsExpanded = false;
// Preference cache to avoid create new instance each time. // Preference cache to avoid create new instance each time.
@VisibleForTesting @VisibleForTesting
final Map<String, Preference> mPreferenceCache = new HashMap<>(); final Map<String, Preference> mPreferenceCache = new HashMap<>();
@VisibleForTesting
final List<BatteryDiffEntry> mSystemEntries = new ArrayList<>();
public BatteryChartPreferenceController( public BatteryChartPreferenceController(
Context context, String preferenceKey, Context context, String preferenceKey,
@@ -163,6 +167,12 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
refreshUi(trapezoidIndex, /*isForce=*/ false); refreshUi(trapezoidIndex, /*isForce=*/ false);
} }
@Override
public void onExpand(boolean isExpanded) {
mIsExpanded = isExpanded;
refreshExpandUi();
}
void setBatteryHistoryMap( void setBatteryHistoryMap(
final Map<Long, List<BatteryHistEntry>> batteryHistoryMap) { final Map<Long, List<BatteryHistEntry>> batteryHistoryMap) {
mHandler.post(() -> setBatteryHistoryMapInner(batteryHistoryMap)); mHandler.post(() -> setBatteryHistoryMapInner(batteryHistoryMap));
@@ -266,10 +276,10 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
} }
// Separates data into two groups and sort them individually. // Separates data into two groups and sort them individually.
final List<BatteryDiffEntry> appEntries = new ArrayList<>(); final List<BatteryDiffEntry> appEntries = new ArrayList<>();
final List<BatteryDiffEntry> systemEntries = new ArrayList<>(); mSystemEntries.clear();
entries.forEach(entry -> { entries.forEach(entry -> {
if (entry.isSystemEntry()) { if (entry.isSystemEntry()) {
systemEntries.add(entry); mSystemEntries.add(entry);
} else { } else {
appEntries.add(entry); appEntries.add(entry);
} }
@@ -279,11 +289,25 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
} }
}); });
Collections.sort(appEntries, BatteryDiffEntry.COMPARATOR); Collections.sort(appEntries, BatteryDiffEntry.COMPARATOR);
Collections.sort(systemEntries, BatteryDiffEntry.COMPARATOR); Collections.sort(mSystemEntries, BatteryDiffEntry.COMPARATOR);
Log.d(TAG, String.format("addAllPreferences() app=%d system=%d", Log.d(TAG, String.format("addAllPreferences() app=%d system=%d",
appEntries.size(), systemEntries.size())); appEntries.size(), mSystemEntries.size()));
addPreferenceToScreen(appEntries);
addPreferenceToScreen(systemEntries); // Adds app entries to the list if it is not empty.
if (!appEntries.isEmpty()) {
addPreferenceToScreen(appEntries);
}
// Adds the expabable divider if we have two sections data.
if (!appEntries.isEmpty() && !mSystemEntries.isEmpty()) {
if (mExpandDividerPreference == null) {
mExpandDividerPreference = new ExpandDividerPreference(mPrefContext);
mExpandDividerPreference.setOnExpandListener(this);
}
mExpandDividerPreference.setOrder(
mAppListPrefGroup.getPreferenceCount());
mAppListPrefGroup.addPreference(mExpandDividerPreference);
}
refreshExpandUi();
} }
@VisibleForTesting @VisibleForTesting
@@ -337,6 +361,22 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
mAppListPrefGroup.removeAll(); mAppListPrefGroup.removeAll();
} }
private void refreshExpandUi() {
if (mIsExpanded) {
addPreferenceToScreen(mSystemEntries);
} else {
// Removes and recycles all system entries to hide all of them.
for (BatteryDiffEntry entry : mSystemEntries) {
final String prefKey = entry.mBatteryHistEntry.getKey();
final Preference pref = mAppListPrefGroup.findPreference(prefKey);
if (pref != null) {
mAppListPrefGroup.removePreference(pref);
mPreferenceCache.put(pref.getKey(), pref);
}
}
}
}
@VisibleForTesting @VisibleForTesting
void setPreferenceSummary( void setPreferenceSummary(
PowerGaugePreference preference, BatteryDiffEntry entry) { PowerGaugePreference preference, BatteryDiffEntry entry) {

View File

@@ -72,7 +72,7 @@ public class Enable2gPreferenceController extends TelephonyTogglePreferenceContr
public int getAvailabilityStatus(int subId) { public int getAvailabilityStatus(int subId) {
final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(subId); final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(subId);
boolean visible = boolean visible =
subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID SubscriptionManager.isUsableSubscriptionId(subId)
&& carrierConfig != null && carrierConfig != null
&& !carrierConfig.getBoolean(CarrierConfigManager.KEY_HIDE_ENABLE_2G) && !carrierConfig.getBoolean(CarrierConfigManager.KEY_HIDE_ENABLE_2G)
&& mTelephonyManager.isRadioInterfaceCapabilitySupported( && mTelephonyManager.isRadioInterfaceCapabilitySupported(
@@ -89,6 +89,9 @@ public class Enable2gPreferenceController extends TelephonyTogglePreferenceContr
@Override @Override
public boolean setChecked(boolean isChecked) { public boolean setChecked(boolean isChecked) {
if (!SubscriptionManager.isUsableSubscriptionId(mSubId)) {
return false;
}
long currentlyAllowedNetworkTypes = mTelephonyManager.getAllowedNetworkTypesForReason( long currentlyAllowedNetworkTypes = mTelephonyManager.getAllowedNetworkTypesForReason(
mTelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G); mTelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G);
boolean enabled = (currentlyAllowedNetworkTypes & BITMASK_2G) != 0; boolean enabled = (currentlyAllowedNetworkTypes & BITMASK_2G) != 0;

View File

@@ -77,11 +77,7 @@ public class NotificationAssistantPreferenceController extends TogglePreferenceC
protected void setNotificationAssistantGranted(ComponentName cn) { protected void setNotificationAssistantGranted(ComponentName cn) {
if (Settings.Secure.getIntForUser(mContext.getContentResolver(), if (Settings.Secure.getIntForUser(mContext.getContentResolver(),
Settings.Secure.NAS_SETTINGS_UPDATED, 0, mUserId) == 0) { Settings.Secure.NAS_SETTINGS_UPDATED, 0, mUserId) == 0) {
for (int profileId : mUserManager.getProfileIds(mUserId, false)) { mNotificationBackend.setNASMigrationDoneAndResetDefault(mUserId, cn != null);
Settings.Secure.putIntForUser(mContext.getContentResolver(),
Settings.Secure.NAS_SETTINGS_UPDATED, 1, profileId);
}
mNotificationBackend.resetDefaultNotificationAssistant(cn != null);
} }
mNotificationBackend.setNotificationAssistantGranted(cn); mNotificationBackend.setNotificationAssistantGranted(cn);
} }

View File

@@ -570,9 +570,9 @@ public class NotificationBackend {
} }
} }
public void resetDefaultNotificationAssistant(boolean loadFromConfig) { public void setNASMigrationDoneAndResetDefault(int userId, boolean loadFromConfig) {
try { try {
sINM.resetDefaultNotificationAssistant(loadFromConfig); sINM.setNASMigrationDoneAndResetDefault(userId, loadFromConfig);
} catch (Exception e) { } catch (Exception e) {
Log.w(TAG, "Error calling NoMan", e); Log.w(TAG, "Error calling NoMan", e);
} }

View File

@@ -1,58 +0,0 @@
/*
* Copyright (C) 2017 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.notification.app;
import android.content.Context;
import android.text.method.LinkMovementMethod;
import android.util.AttributeSet;
import android.widget.TextView;
import androidx.core.content.res.TypedArrayUtils;
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
import com.android.settingslib.R;
/**
* FooterPreference that can have any key or ordering.
*/
public class NotificationFooterPreference extends Preference {
public NotificationFooterPreference(Context context, AttributeSet attrs) {
super(context, attrs, TypedArrayUtils.getAttr(
context, R.attr.footerPreferenceStyle, android.R.attr.preferenceStyle));
init();
}
public NotificationFooterPreference(Context context) {
this(context, null);
}
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
TextView title = holder.itemView.findViewById(android.R.id.title);
title.setMovementMethod(new LinkMovementMethod());
title.setClickable(false);
title.setLongClickable(false);
}
private void init() {
setIcon(R.drawable.ic_info_outline_24dp);
setSelectable(false);
}
}

View File

@@ -0,0 +1,168 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.uwb;
import static androidx.lifecycle.Lifecycle.Event.ON_START;
import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.provider.Settings;
import android.uwb.UwbManager;
import android.uwb.UwbManager.AdapterStateCallback;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
/** Controller for "UWB" toggle. */
public class UwbPreferenceController extends TogglePreferenceController implements
AdapterStateCallback, LifecycleObserver {
@VisibleForTesting
static final String KEY_UWB_SETTINGS = "uwb_settings";
@VisibleForTesting
UwbManager mUwbManager;
@VisibleForTesting
boolean mAirplaneModeOn;
@VisibleForTesting
private final BroadcastReceiver mAirplaneModeChangedReceiver;
private final Executor mExecutor;
private boolean mIsChecked = true;
boolean mRegisteredAdapterStateCallback = false;
private Preference mPreference;
public UwbPreferenceController(Context context, String key) {
super(context, key);
mExecutor = Executors.newSingleThreadExecutor();
mUwbManager = context.getSystemService(UwbManager.class);
mAirplaneModeOn = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.AIRPLANE_MODE_ON, 0) == 1;
mAirplaneModeChangedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updateState(mPreference);
}
};
}
@VisibleForTesting
boolean isUwbSupportedOnDevice() {
return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_UWB);
}
@Override
public int getAvailabilityStatus() {
if (!isUwbSupportedOnDevice()) {
return UNSUPPORTED_ON_DEVICE;
} else if (mAirplaneModeOn) {
return DISABLED_DEPENDENT_SETTING;
} else {
return AVAILABLE;
}
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreference = screen.findPreference(getPreferenceKey());
}
@Override
public boolean isChecked() {
//TODO(b/186075119): Update toggle state by assigning to the real value by default.
return mIsChecked;
}
@Override
public boolean setChecked(boolean isChecked) {
mIsChecked = isChecked;
mUwbManager.setUwbEnabled(isChecked);
return true;
}
@Override
public void onStateChanged(int state, int reason) {
// Only update toggle state from service the first time. Otherwise toggle state is
// changed from controller. For example, UWB is disabled if airplane mode is on but we do
// not want to change the preference for the user in this case.
if (!mRegisteredAdapterStateCallback) {
mIsChecked = state == STATE_ENABLED_ACTIVE || state == STATE_ENABLED_INACTIVE;
mRegisteredAdapterStateCallback = true;
}
}
/** Called when activity starts being displayed to user. */
@OnLifecycleEvent(ON_START)
public void onStart() {
if (isUwbSupportedOnDevice()) {
mUwbManager.registerAdapterStateCallback(mExecutor, this);
}
if (mAirplaneModeChangedReceiver != null) {
mContext.registerReceiver(mAirplaneModeChangedReceiver,
new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));
}
refreshSummary(mPreference);
}
/** Called when activity stops being displayed to user. */
@OnLifecycleEvent(ON_STOP)
public void onStop() {
if (isUwbSupportedOnDevice()) {
mUwbManager.unregisterAdapterStateCallback(this);
}
if (mAirplaneModeChangedReceiver != null) {
mContext.unregisterReceiver(mAirplaneModeChangedReceiver);
}
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
mAirplaneModeOn = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.AIRPLANE_MODE_ON, 0) == 1;
preference.setEnabled(!mAirplaneModeOn);
if (isUwbSupportedOnDevice()) {
if (mAirplaneModeOn) {
mUwbManager.setUwbEnabled(false);
} else {
mUwbManager.setUwbEnabled(mIsChecked);
}
}
refreshSummary(preference);
}
@Override
public CharSequence getSummary() {
if (mAirplaneModeOn) {
return mContext.getResources().getString(R.string.uwb_settings_summary_airplane_mode);
} else {
return mContext.getResources().getString(R.string.uwb_settings_summary);
}
}
}

View File

@@ -249,14 +249,122 @@ public class AdvancedPowerUsageDetailTest {
} }
@Test @Test
public void testInitHeader_hasCorrectSummary() { public void testInitHeader_noUsageTime_hasCorrectSummary() {
mFragment.mAppEntry = null; Bundle bundle = new Bundle(2);
bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, /* value */ 0);
bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, /* value */ 0);
when(mFragment.getArguments()).thenReturn(bundle);
mFragment.initHeader(); mFragment.initHeader();
ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class); ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
verify(mEntityHeaderController).setSummary(captor.capture()); verify(mEntityHeaderController).setSummary(captor.capture());
assertThat(captor.getValue().toString()) assertThat(captor.getValue().toString())
.isEqualTo("0 min total • 0 min background for past 24 hr"); .isEqualTo("No usage for past 24 hr");
}
@Test
public void testInitHeader_backgroundTwoMinutesForegroundZero_hasCorrectSummary() {
final long backgroundTimeTwoMinutes = 120000;
final long foregroundTimeZero = 0;
Bundle bundle = new Bundle(2);
bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeTwoMinutes);
bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeZero);
when(mFragment.getArguments()).thenReturn(bundle);
mFragment.initHeader();
ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
verify(mEntityHeaderController).setSummary(captor.capture());
assertThat(captor.getValue().toString())
.isEqualTo("2 min background for past 24 hr");
}
@Test
public void testInitHeader_backgroundLessThanAMinutesForegroundZero_hasCorrectSummary() {
final long backgroundTimeLessThanAMinute = 59999;
final long foregroundTimeZero = 0;
Bundle bundle = new Bundle(2);
bundle.putLong(
AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeLessThanAMinute);
bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeZero);
when(mFragment.getArguments()).thenReturn(bundle);
mFragment.initHeader();
ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
verify(mEntityHeaderController).setSummary(captor.capture());
assertThat(captor.getValue().toString())
.isEqualTo("Background less than a minute for past 24 hr");
}
@Test
public void testInitHeader_totalUsageLessThanAMinutes_hasCorrectSummary() {
final long backgroundTimeLessThanHalfMinute = 20000;
final long foregroundTimeLessThanHalfMinute = 20000;
Bundle bundle = new Bundle(2);
bundle.putLong(
AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeLessThanHalfMinute);
bundle.putLong(
AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeLessThanHalfMinute);
when(mFragment.getArguments()).thenReturn(bundle);
mFragment.initHeader();
ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
verify(mEntityHeaderController).setSummary(captor.capture());
assertThat(captor.getValue().toString())
.isEqualTo("Total less than a minute for past 24 hr");
}
@Test
public void testInitHeader_TotalAMinutesBackgroundLessThanAMinutes_hasCorrectSummary() {
final long backgroundTimeZero = 59999;
final long foregroundTimeTwoMinutes = 1;
Bundle bundle = new Bundle(2);
bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeZero);
bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeTwoMinutes);
when(mFragment.getArguments()).thenReturn(bundle);
mFragment.initHeader();
ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
verify(mEntityHeaderController).setSummary(captor.capture());
assertThat(captor.getValue().toString())
.isEqualTo("1 min total • background less than a minute for past 24 hr");
}
@Test
public void testInitHeader_TotalAMinutesBackgroundZero_hasCorrectSummary() {
final long backgroundTimeZero = 0;
final long foregroundTimeAMinutes = 60000;
Bundle bundle = new Bundle(2);
bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeZero);
bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeAMinutes);
when(mFragment.getArguments()).thenReturn(bundle);
mFragment.initHeader();
ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
verify(mEntityHeaderController).setSummary(captor.capture());
assertThat(captor.getValue().toString())
.isEqualTo("1 min total for past 24 hr");
}
@Test
public void testInitHeader_foregroundTwoMinutesBackgroundFourMinutes_hasCorrectSummary() {
final long backgroundTimeFourMinute = 240000;
final long foregroundTimeTwoMinutes = 120000;
Bundle bundle = new Bundle(2);
bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeFourMinute);
bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeTwoMinutes);
when(mFragment.getArguments()).thenReturn(bundle);
mFragment.initHeader();
ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
verify(mEntityHeaderController).setSummary(captor.capture());
assertThat(captor.getValue().toString())
.isEqualTo("6 min total • 4 min background for past 24 hr");
} }
@Test @Test

View File

@@ -43,6 +43,7 @@ import com.android.settings.testutils.FakeFeatureFactory;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
@@ -416,23 +417,56 @@ public final class BatteryChartPreferenceControllerTest {
@Test @Test
public void testValidateSlotTimestamp_returnExpectedResult() { public void testValidateSlotTimestamp_returnExpectedResult() {
final List<Long> slotTimestampList = final ArrayList<Long> slotTimestampList = new ArrayList<Long>(
Arrays.asList( Arrays.asList(
Long.valueOf(0), Long.valueOf(0),
Long.valueOf(DateUtils.HOUR_IN_MILLIS), Long.valueOf(DateUtils.HOUR_IN_MILLIS),
Long.valueOf(DateUtils.HOUR_IN_MILLIS * 2 + DateUtils.MINUTE_IN_MILLIS), Long.valueOf(DateUtils.HOUR_IN_MILLIS * 2 + DateUtils.MINUTE_IN_MILLIS),
Long.valueOf(DateUtils.HOUR_IN_MILLIS * 3 + DateUtils.MINUTE_IN_MILLIS * 2)); Long.valueOf(DateUtils.HOUR_IN_MILLIS * 3 + DateUtils.MINUTE_IN_MILLIS * 2)));
// Verifies the testing data is correct before we added invalid data into it. // Verifies the testing data is correct before we added invalid data into it.
assertThat(BatteryChartPreferenceController.validateSlotTimestamp(slotTimestampList)) assertThat(BatteryChartPreferenceController.validateSlotTimestamp(slotTimestampList))
.isTrue(); .isTrue();
// Insert invalid timestamp into the list. // Insert invalid timestamp into the list.
slotTimestampList.add( slotTimestampList.add(
Long.valueOf(DateUtils.HOUR_IN_MILLIS * 4 + DateUtils.MINUTE_IN_MILLIS * 3)); Long.valueOf(DateUtils.HOUR_IN_MILLIS * 4 + DateUtils.MINUTE_IN_MILLIS * 6));
assertThat(BatteryChartPreferenceController.validateSlotTimestamp(slotTimestampList)) assertThat(BatteryChartPreferenceController.validateSlotTimestamp(slotTimestampList))
.isFalse(); .isFalse();
} }
@Test
public void testOnExpand_expandedIsTrue_addSystemEntriesToPreferenceGroup() {
final String prefKey = "preference_key";
doReturn(1).when(mAppListGroup).getPreferenceCount();
mBatteryChartPreferenceController.mSystemEntries.add(mBatteryDiffEntry);
doReturn("label").when(mBatteryDiffEntry).getAppLabel();
doReturn(mDrawable).when(mBatteryDiffEntry).getAppIcon();
doReturn(prefKey).when(mBatteryHistEntry).getKey();
mBatteryChartPreferenceController.onExpand(/*isExpanded=*/ true);
final ArgumentCaptor<Preference> captor = ArgumentCaptor.forClass(Preference.class);
verify(mAppListGroup).addPreference(captor.capture());
// Verifies the added preference.
assertThat(captor.getValue().getKey()).isEqualTo(prefKey);
}
@Test
public void testOnExpand_expandedIsFalse_removeSystemEntriesFromPreferenceGroup() {
final String prefKey = "preference_key";
doReturn(prefKey).when(mBatteryHistEntry).getKey();
doReturn(mPowerGaugePreference).when(mAppListGroup).findPreference(prefKey);
mBatteryChartPreferenceController.mSystemEntries.add(mBatteryDiffEntry);
// Verifies the cache is empty first.
assertThat(mBatteryChartPreferenceController.mPreferenceCache).isEmpty();
mBatteryChartPreferenceController.onExpand(/*isExpanded=*/ false);
verify(mAppListGroup).findPreference(prefKey);
verify(mAppListGroup).removePreference(mPowerGaugePreference);
assertThat(mBatteryChartPreferenceController.mPreferenceCache).hasSize(1);
}
private static Map<Long, List<BatteryHistEntry>> createBatteryHistoryMap(int size) { private static Map<Long, List<BatteryHistEntry>> createBatteryHistoryMap(int size) {
final Map<Long, List<BatteryHistEntry>> batteryHistoryMap = new HashMap<>(); final Map<Long, List<BatteryHistEntry>> batteryHistoryMap = new HashMap<>();
for (int index = 0; index < size; index++) { for (int index = 0; index < size; index++) {

View File

@@ -122,13 +122,13 @@ public class NotificationAssistantPreferenceControllerTest {
assertEquals(1, Settings.Secure.getIntForUser(mContext.getContentResolver(), assertEquals(1, Settings.Secure.getIntForUser(mContext.getContentResolver(),
Settings.Secure.NAS_SETTINGS_UPDATED, 0, 10)); Settings.Secure.NAS_SETTINGS_UPDATED, 0, 10));
verify(mBackend, times(1)) verify(mBackend, times(1))
.resetDefaultNotificationAssistant(eq(true)); .setNASMigrationDoneAndResetDefault(eq(0), eq(true));
//Test user enable again, migration should not happen //Test user enable again, migration should not happen
mPreferenceController.setNotificationAssistantGranted(mNASComponent); mPreferenceController.setNotificationAssistantGranted(mNASComponent);
//Number of invocations should not increase //Number of invocations should not increase
verify(mBackend, times(1)) verify(mBackend, times(1))
.resetDefaultNotificationAssistant(eq(true)); .setNASMigrationDoneAndResetDefault(eq(0), eq(true));
} }
@Test @Test
@@ -146,13 +146,13 @@ public class NotificationAssistantPreferenceControllerTest {
assertEquals(0, Settings.Secure.getIntForUser(mContext.getContentResolver(), assertEquals(0, Settings.Secure.getIntForUser(mContext.getContentResolver(),
Settings.Secure.NAS_SETTINGS_UPDATED, 0, 20)); Settings.Secure.NAS_SETTINGS_UPDATED, 0, 20));
verify(mBackend, times(1)) verify(mBackend, times(1))
.resetDefaultNotificationAssistant(eq(true)); .setNASMigrationDoneAndResetDefault(eq(0), eq(true));
//Test user enable again, migration should not happen //Test user enable again, migration should not happen
mPreferenceController.setNotificationAssistantGranted(mNASComponent); mPreferenceController.setNotificationAssistantGranted(mNASComponent);
//Number of invocations should not increase //Number of invocations should not increase
verify(mBackend, times(1)) verify(mBackend, times(1))
.resetDefaultNotificationAssistant(eq(true)); .setNASMigrationDoneAndResetDefault(eq(0), eq(true));
} }
@Test @Test
@@ -170,13 +170,13 @@ public class NotificationAssistantPreferenceControllerTest {
assertEquals(1, Settings.Secure.getIntForUser(mContext.getContentResolver(), assertEquals(1, Settings.Secure.getIntForUser(mContext.getContentResolver(),
Settings.Secure.NAS_SETTINGS_UPDATED, 0, 10)); Settings.Secure.NAS_SETTINGS_UPDATED, 0, 10));
verify(mBackend, times(1)) verify(mBackend, times(1))
.resetDefaultNotificationAssistant(eq(false)); .setNASMigrationDoneAndResetDefault(eq(0), eq(false));
//Test user disable again, migration should not happen //Test user disable again, migration should not happen
mPreferenceController.setChecked(false); mPreferenceController.setChecked(false);
//Number of invocations should not increase //Number of invocations should not increase
verify(mBackend, times(1)) verify(mBackend, times(1))
.resetDefaultNotificationAssistant(eq(false)); .setNASMigrationDoneAndResetDefault(eq(0), eq(false));
} }
} }

View File

@@ -0,0 +1,176 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.uwb;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.content.Context;
import android.content.pm.PackageManager;
import android.uwb.UwbManager;
import com.android.settings.core.BasePreferenceController;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
/** Unit tests for UWB preference toggle. */
@RunWith(RobolectricTestRunner.class)
public class UwbPreferenceControllerTest {
@Rule
public MockitoRule rule = MockitoJUnit.rule();
private Context mContext;
private PackageManager mPackageManager;
private UwbPreferenceController mController;
@Mock
private UwbManager mUwbManager;
@Before
public void setUp() {
mContext = spy(RuntimeEnvironment.application);
mPackageManager = spy(mContext.getPackageManager());
mController = new UwbPreferenceController(mContext, "uwb_settings");
mController.mUwbManager = mUwbManager;
}
@Test
public void getAvailabilityStatus_uwbDisabled_shouldReturnDisabled() {
doReturn(mPackageManager).when(mContext).getPackageManager();
doReturn(true).when(mPackageManager)
.hasSystemFeature(PackageManager.FEATURE_UWB);
mController.mAirplaneModeOn = true;
assertThat(mController.getAvailabilityStatus())
.isEqualTo(BasePreferenceController.DISABLED_DEPENDENT_SETTING);
}
@Test
public void getAvailabilityStatus_uwbShown_shouldReturnAvailable() {
doReturn(mPackageManager).when(mContext).getPackageManager();
doReturn(true).when(mPackageManager)
.hasSystemFeature(PackageManager.FEATURE_UWB);
mController.mAirplaneModeOn = false;
assertThat(mController.getAvailabilityStatus())
.isEqualTo(BasePreferenceController.AVAILABLE);
}
@Test
public void getAvailabilityStatus_uwbNotShown_shouldReturnUnsupported() {
doReturn(mPackageManager).when(mContext).getPackageManager();
doReturn(false).when(mPackageManager)
.hasSystemFeature(PackageManager.FEATURE_UWB);
assertThat(mController.getAvailabilityStatus())
.isEqualTo(BasePreferenceController.UNSUPPORTED_ON_DEVICE);
}
@Test
public void onStateChanged_stateNotRegistered_shouldUpdate() {
mController.mRegisteredAdapterStateCallback = false;
mController.onStateChanged(UwbManager.AdapterStateCallback.STATE_DISABLED,
UwbManager.AdapterStateCallback.STATE_CHANGED_REASON_SYSTEM_POLICY);
assertThat(mController.isChecked()).isFalse();
}
@Test
public void onStateChanged_stateRegistered_shouldNotUpdate() {
mController.mRegisteredAdapterStateCallback = true;
mController.onStateChanged(UwbManager.AdapterStateCallback.STATE_ENABLED_INACTIVE,
UwbManager.AdapterStateCallback.STATE_CHANGED_REASON_SYSTEM_POLICY);
assertThat(mController.isChecked()).isTrue();
}
@Test
public void isChecked_uwbEnabledInactive_shouldReturnTrue() {
doReturn(mPackageManager).when(mContext).getPackageManager();
doReturn(true).when(mPackageManager)
.hasSystemFeature(PackageManager.FEATURE_UWB);
mController.mRegisteredAdapterStateCallback = false;
mController.onStateChanged(UwbManager.AdapterStateCallback.STATE_ENABLED_INACTIVE,
UwbManager.AdapterStateCallback.STATE_CHANGED_REASON_SYSTEM_POLICY);
assertThat(mController.isChecked()).isTrue();
}
@Test
public void isChecked_uwbEnabledActive_shouldReturnTrue() {
doReturn(mPackageManager).when(mContext).getPackageManager();
doReturn(true).when(mPackageManager)
.hasSystemFeature(PackageManager.FEATURE_UWB);
mController.mRegisteredAdapterStateCallback = false;
mController.onStateChanged(UwbManager.AdapterStateCallback.STATE_ENABLED_ACTIVE,
UwbManager.AdapterStateCallback.STATE_CHANGED_REASON_SYSTEM_POLICY);
assertThat(mController.isChecked()).isTrue();
}
@Test
public void isChecked_uwbDisabled_shouldReturnFalse() {
doReturn(mPackageManager).when(mContext).getPackageManager();
doReturn(true).when(mPackageManager)
.hasSystemFeature(PackageManager.FEATURE_UWB);
mController.mRegisteredAdapterStateCallback = false;
mController.onStateChanged(UwbManager.AdapterStateCallback.STATE_DISABLED,
UwbManager.AdapterStateCallback.STATE_CHANGED_REASON_SYSTEM_POLICY);
assertThat(mController.isChecked()).isFalse();
}
@Test
public void setChecked_uwbDisabled_shouldEnableUwb() {
clearInvocations(mUwbManager);
doReturn(mPackageManager).when(mContext).getPackageManager();
doReturn(true).when(mPackageManager)
.hasSystemFeature(PackageManager.FEATURE_UWB);
mController.setChecked(true);
verify(mUwbManager).setUwbEnabled(true);
verify(mUwbManager, never()).setUwbEnabled(false);
}
@Test
public void setChecked_uwbEnabled_shouldDisableUwb() {
clearInvocations(mUwbManager);
doReturn(mPackageManager).when(mContext).getPackageManager();
doReturn(true).when(mPackageManager)
.hasSystemFeature(PackageManager.FEATURE_UWB);
mController.setChecked(false);
verify(mUwbManager).setUwbEnabled(false);
verify(mUwbManager, never()).setUwbEnabled(true);
}
}

View File

@@ -48,6 +48,8 @@ public final class Enable2gPreferenceControllerTest {
@Mock @Mock
private TelephonyManager mTelephonyManager; private TelephonyManager mTelephonyManager;
@Mock @Mock
private TelephonyManager mInvalidTelephonyManager;
@Mock
private CarrierConfigManager mCarrierConfigManager; private CarrierConfigManager mCarrierConfigManager;
private PersistableBundle mPersistableBundle; private PersistableBundle mPersistableBundle;
@@ -65,6 +67,8 @@ public final class Enable2gPreferenceControllerTest {
.thenReturn(mCarrierConfigManager); .thenReturn(mCarrierConfigManager);
doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID); doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID);
doReturn(mInvalidTelephonyManager).when(mTelephonyManager).createForSubscriptionId(
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
mPersistableBundle = new PersistableBundle(); mPersistableBundle = new PersistableBundle();
doReturn(mPersistableBundle).when(mCarrierConfigManager).getConfigForSubId(SUB_ID); doReturn(mPersistableBundle).when(mCarrierConfigManager).getConfigForSubId(SUB_ID);
@@ -120,6 +124,18 @@ public final class Enable2gPreferenceControllerTest {
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
} }
@Test
public void setChecked_invalidSubIdAndIsCheckedTrue_returnFalse() {
mController.init(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
assertThat(mController.setChecked(true)).isFalse();
}
@Test
public void setChecked_invalidSubIdAndIsCheckedFalse_returnFalse() {
mController.init(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
assertThat(mController.setChecked(false)).isFalse();
}
@Test @Test
public void onPreferenceChange_update() { public void onPreferenceChange_update() {
// Set "Enable 2G" flag to "on" // Set "Enable 2G" flag to "on"