Snap for 7357013 from c19ad05b02 to sc-release
Change-Id: I9407c736eddf35cc0415c615a1d6a756ccad524f
This commit is contained in:
25
res/drawable/ic_info.xml
Normal file
25
res/drawable/ic_info.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?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">
|
||||
<path
|
||||
android:fillColor="?android:attr/colorAccent"
|
||||
android:pathData="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/>
|
||||
</vector>
|
||||
20
res/drawable/ic_info_selector.xml
Normal file
20
res/drawable/ic_info_selector.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?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.
|
||||
-->
|
||||
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_enabled="true" android:drawable="@drawable/ic_info"/>
|
||||
<item android:state_enabled="false" android:drawable="@drawable/ic_info_outline_24"/>
|
||||
</selector>
|
||||
@@ -24,6 +24,7 @@
|
||||
<TextView
|
||||
android:text="@string/condition_airplane_title"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginVertical="16dp"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
settings:textColor="?android:attr/textColorSecondary"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:text="@string/battery_usage_chart_graph_hint" />
|
||||
|
||||
<com.android.settings.fuelgauge.BatteryChartView
|
||||
@@ -37,6 +37,7 @@
|
||||
android:layout_height="165dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:visibility="invisible"
|
||||
android:contentDescription="@string/battery_usage_chart"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
settings:textColor="?android:attr/textColorSecondary" />
|
||||
<TextView
|
||||
|
||||
@@ -155,6 +155,55 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Keep in mind -->
|
||||
<com.google.android.setupdesign.view.RichTextView
|
||||
style="@style/SudDescription.Glif"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAlignment="viewStart"
|
||||
android:paddingTop="12dp"
|
||||
android:text="@string/security_settings_fingerprint_enroll_introduction_footer_title_2" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingTop="12dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_info_outline_24dp"/>
|
||||
<Space
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="wrap_content"/>
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/security_settings_fingerprint_v2_enroll_introduction_footer_message_5" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingTop="12dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_link_24dp"/>
|
||||
<Space
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="wrap_content"/>
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/security_settings_fingerprint_v2_enroll_introduction_message_learn_more" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.google.android.setupdesign.GlifLayout>
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
android:padding="@*android:dimen/preference_fragment_padding_side"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center_vertical"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:visibility="gone" />
|
||||
|
||||
<LinearLayout
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
<ImageView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/settings_button"
|
||||
android:id="@+id/info_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
@@ -24,5 +24,4 @@
|
||||
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:scaleType="center"
|
||||
android:src="@drawable/ic_info_outline_24"
|
||||
android:contentDescription="@string/settings_button" />
|
||||
android:src="@drawable/ic_info_selector" />
|
||||
@@ -1512,12 +1512,19 @@
|
||||
<item>@string/enhanced_4g_lte_mode_summary_4g_calling</item>
|
||||
</string-array>
|
||||
|
||||
<!-- An allowlist which packages won't show summary in battery usage screen. [CHAR LIMIT=NONE] -->
|
||||
<!-- An allowlist which packages won't show summary in battery usage screen.
|
||||
[CHAR LIMIT=NONE] -->
|
||||
<string-array name="allowlist_hide_summary_in_battery_usage" translatable="false">
|
||||
<!-- Google -->
|
||||
<item>"com.google.android.googlequicksearchbox"</item>
|
||||
</string-array>
|
||||
|
||||
<!-- An allowlist which packages won't show entry in battery usage screen.
|
||||
[CHAR LIMIT=NONE] -->
|
||||
<string-array name="allowlist_hide_entry_in_battery_usage" translatable="false">
|
||||
<item>"com.google.android.gms.persistent"</item>
|
||||
</string-array>
|
||||
|
||||
<!-- Array of titles palette list for accessibility. -->
|
||||
<string-array name="setting_palette_data" translatable="false" >
|
||||
<item>@string/color_red</item>
|
||||
|
||||
@@ -943,6 +943,8 @@
|
||||
<string name="security_settings_fingerprint_v2_enroll_introduction_footer_message_3">The phone will also use images from your interactions with Fingerprint Unlock to update your fingerprint model. Images used to create your fingerprint model are never stored, but the fingerprint model is stored securely on your phone and never leaves the phone. All processing occurs securely on your phone.</string>
|
||||
<!-- Introduction description message shown in fingerprint enrollment introduction screen in setup wizard. [CHAR LIMIT=NONE]-->
|
||||
<string name="security_settings_fingerprint_v2_enroll_introduction_footer_message_4">You can delete your fingerprint model, or turn off Fingerprint Unlock at any time in Settings. Fingerprint models are stored on the phone until you delete them.</string>
|
||||
<!-- Introduction description message shown in fingerprint enrollment introduction screen in setup wizard. [CHAR LIMIT=NONE] -->
|
||||
<string name="security_settings_fingerprint_v2_enroll_introduction_footer_message_5">Your phone can be unlocked when you don\u2019t intend to, like if someone holds it up to your finger.</string>
|
||||
<!-- Introduction detail message shown in fingerprint enrollment introduction to learn more about fingerprint [CHAR LIMIT=NONE]-->
|
||||
<string name="security_settings_fingerprint_v2_enroll_introduction_message_learn_more"></string>
|
||||
|
||||
@@ -5249,6 +5251,8 @@
|
||||
<string name="accessibility_shortcut_edit_dialog_summary_software_gesture_talkback">Swipe up from the bottom of the screen with 3 fingers.\n\nTo switch between features, swipe up with 3 fingers and hold.</string>
|
||||
<!-- Summary for software shortcut in accessibility edit shortcut dialog when user had enabled the accessibility floating button mode (Floating over other apps). [CHAR LIMIT=NONE] -->
|
||||
<string name="accessibility_shortcut_edit_dialog_summary_software_floating"><annotation id="link">Customize accessibility button</annotation></string>
|
||||
<!-- Summary for footer to show help link. [CHAR LIMIT=NONE] -->
|
||||
<string name="footer_learn_more"><annotation id="link">Learn more</annotation></string>
|
||||
<!-- Title for hardware shortcut in accessibility edit shortcut dialog. [CHAR LIMIT=NONE] -->
|
||||
<string name="accessibility_shortcut_edit_dialog_title_hardware">Hold volume keys</string>
|
||||
<!-- Part of list to compose user's accessibility shortcut list. [CHAR LIMIT=NONE] -->
|
||||
@@ -5998,7 +6002,7 @@
|
||||
<!-- Summary for the early hedas up tip [CHAR LIMIT=NONE] -->
|
||||
<string name="battery_tip_early_heads_up_summary">Battery may run out earlier than usual</string>
|
||||
<!-- Title when early heads up is solved [CHAR LIMIT=NONE] -->
|
||||
<string name="battery_tip_early_heads_up_done_title">Battery Saver is on</string>
|
||||
<string name="battery_tip_early_heads_up_done_title">Battery Saver on</string>
|
||||
<!-- Summary when early heads up is solved [CHAR LIMIT=NONE] -->
|
||||
<string name="battery_tip_early_heads_up_done_summary">Some features may be limited</string>
|
||||
<!-- Title for the battery high usage tip [CHAR LIMIT=NONE] -->
|
||||
@@ -6324,9 +6328,9 @@
|
||||
<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] -->
|
||||
<string name="battery_total_and_bg_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_bg_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\nfor 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_bg_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>
|
||||
<string name="battery_total_and_bg_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\nfor <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>
|
||||
@@ -6349,9 +6353,9 @@
|
||||
<string name="battery_bg_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_bg_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>
|
||||
<string name="battery_total_usage_and_bg_less_minute_usage"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total • background less than a minute\nfor 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_bg_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>
|
||||
<string name="battery_total_usage_and_bg_less_minute_usage_with_period"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total • background less than a minute\nfor <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>
|
||||
@@ -6469,6 +6473,8 @@
|
||||
<string name="battery_usage_for_background_time">Background: <xliff:g id="time">%s</xliff:g></string>
|
||||
<!-- [CHAR_LIMIT=NONE] Battery usage main screen footer contentt -->
|
||||
<string name="battery_usage_screen_footer">Battery usage data is approximate and doesn\'t measure usage when phone is charging</string>
|
||||
<!-- [CHAR_LIMIT=NONE] Accessibility content description for battery chart view. -->
|
||||
<string name="battery_usage_chart">Battery usage chart</string>
|
||||
<!-- Process Stats strings -->
|
||||
<skip />
|
||||
|
||||
@@ -11358,6 +11364,9 @@
|
||||
<!-- [CHAR LIMIT=60] Summary string on dark theme explaining why the toggle is disabled while the setting is still on-->
|
||||
<string name="dark_ui_mode_disabled_summary_dark_theme_on">Temporarily disabled due to Battery Saver</string>
|
||||
|
||||
<!-- [CHAR LIMIT=60] Summary string for screen attention explaining why the toggle is disabled by battery saver-->
|
||||
<string name="ambient_camera_summary_battery_saver_on">Temporarily disabled due to Battery Saver</string>
|
||||
|
||||
<!-- [CHAR LIMIT=60] Summary string on dark theme explaining why the toggle is disabled while the setting is off-->
|
||||
<string name="dark_ui_mode_disabled_summary_dark_theme_off">Temporarily turned on due to Battery Saver</string>
|
||||
|
||||
|
||||
@@ -216,16 +216,17 @@
|
||||
<style name="vpn_label">
|
||||
<item name="android:layout_width">match_parent</item>
|
||||
<item name="android:layout_height">wrap_content</item>
|
||||
<item name="android:textAppearance">@android:style/TextAppearance.DeviceDefault.Small</item>
|
||||
<item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
|
||||
</style>
|
||||
|
||||
<style name="vpn_value">
|
||||
<item name="android:layout_width">match_parent</item>
|
||||
<item name="android:layout_height">wrap_content</item>
|
||||
<item name="android:textAppearance">@android:style/TextAppearance.DeviceDefault.Medium</item>
|
||||
<item name="android:textAppearance">?android:attr/textAppearanceMedium</item>
|
||||
<item name="android:singleLine">true</item>
|
||||
<item name="android:textAlignment">viewStart</item>
|
||||
<item name="android:minHeight">@dimen/min_tap_target_size</item>
|
||||
<item name="android:textColorHint">?android:attr/textColorSecondary</item>
|
||||
</style>
|
||||
|
||||
<style name="vpn_warning">
|
||||
|
||||
@@ -32,6 +32,11 @@
|
||||
android:summary="@string/auto_rotate_camera_lock_summary"
|
||||
settings:controller="com.android.settings.display.SmartAutoRotateCameraStateController" />
|
||||
|
||||
<com.android.settingslib.widget.BannerMessagePreference
|
||||
android:key="camera_battery_saver_state"
|
||||
android:title="@string/ambient_camera_summary_battery_saver_on"
|
||||
settings:controller="com.android.settings.display.SmartAutoRotateBatterySaverController" />
|
||||
|
||||
<SwitchPreference
|
||||
android:key="face_based_rotate"
|
||||
android:title="@string/auto_rotate_switch_face_based"
|
||||
|
||||
@@ -21,12 +21,6 @@
|
||||
android:persistent="false"
|
||||
android:title="@string/accessibility_captioning_title">
|
||||
|
||||
<com.android.settings.widget.SettingsMainSwitchPreference
|
||||
android:key="captioning_preference_switch"
|
||||
android:persistent="false"
|
||||
android:summary="@string/accessibility_caption_primary_switch_summary"
|
||||
android:title="@string/accessibility_caption_primary_switch_title" />
|
||||
|
||||
<com.android.settingslib.widget.LayoutPreference
|
||||
android:key="captions_preview"
|
||||
android:layout="@layout/accessibility_captions_preview"
|
||||
@@ -35,6 +29,12 @@
|
||||
android:title="@string/summary_placeholder"
|
||||
settings:searchable="false" />
|
||||
|
||||
<com.android.settings.widget.SettingsMainSwitchPreference
|
||||
android:key="captioning_preference_switch"
|
||||
android:persistent="false"
|
||||
android:summary="@string/accessibility_caption_primary_switch_summary"
|
||||
android:title="@string/accessibility_caption_primary_switch_title" />
|
||||
|
||||
<Preference
|
||||
android:fragment="com.android.settings.accessibility.CaptionAppearanceFragment"
|
||||
android:key="captioning_caption_appearance"
|
||||
|
||||
@@ -22,15 +22,13 @@
|
||||
<com.android.settingslib.widget.LayoutPreference
|
||||
android:key="header_view"
|
||||
android:layout="@layout/settings_entity_header"
|
||||
android:selectable="false"
|
||||
settings:allowDividerBelow="true"/>
|
||||
android:selectable="false"/>
|
||||
|
||||
<com.android.settingslib.widget.ActionButtonsPreference
|
||||
android:key="action_buttons"/>
|
||||
|
||||
<PreferenceCategory
|
||||
android:title="@string/battery_detail_manage_title"
|
||||
settings:allowDividerAbove="true">
|
||||
android:title="@string/battery_detail_manage_title">
|
||||
|
||||
<com.android.settingslib.widget.RadioButtonPreference
|
||||
android:key="unrestricted_pref"
|
||||
|
||||
@@ -23,16 +23,14 @@
|
||||
android:key="header_view"
|
||||
android:layout="@layout/settings_entity_header"
|
||||
android:selectable="false"
|
||||
android:order="-10000"
|
||||
settings:allowDividerBelow="true"/>
|
||||
android:order="-10000"/>
|
||||
|
||||
<com.android.settingslib.widget.ActionButtonsPreference
|
||||
android:key="action_buttons"
|
||||
android:order="-9999"/>
|
||||
|
||||
<PreferenceCategory
|
||||
android:title="@string/battery_detail_manage_title"
|
||||
settings:allowDividerAbove="true">
|
||||
android:title="@string/battery_detail_manage_title">
|
||||
|
||||
<com.android.settingslib.RestrictedPreference
|
||||
android:key="background_activity"
|
||||
|
||||
@@ -469,6 +469,19 @@ public final class Utils extends com.android.settingslib.Utils {
|
||||
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.");
|
||||
}
|
||||
return managedUserHandle.getIdentifier();
|
||||
}
|
||||
return UserHandle.myUserId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the target user for a Settings activity.
|
||||
* <p>
|
||||
|
||||
@@ -34,4 +34,9 @@ public class AccessibilityControlTimeoutFooterPreferenceController extends
|
||||
protected String getLabelName() {
|
||||
return mContext.getString(R.string.accessibility_setting_item_control_timeout_title);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getHelpResource() {
|
||||
return R.string.help_url_timeout;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.settings.accessibility;
|
||||
|
||||
import static com.android.internal.accessibility.AccessibilityShortcutController.ACCESSIBILITY_BUTTON_COMPONENT_NAME;
|
||||
import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_COMPONENT_NAME;
|
||||
|
||||
import android.accessibilityservice.AccessibilityServiceInfo;
|
||||
@@ -101,6 +102,12 @@ public class AccessibilityDetailsSettingsFragment extends InstrumentedFragment {
|
||||
arguments, getContext());
|
||||
return new LaunchFragmentArguments(destination, arguments);
|
||||
}
|
||||
|
||||
if (ACCESSIBILITY_BUTTON_COMPONENT_NAME.equals(componentName)) {
|
||||
final String destination = AccessibilityButtonFragment.class.getName();
|
||||
return new LaunchFragmentArguments(destination, /* arguments= */ null);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -70,45 +70,32 @@ public class AccessibilityEditDialogUtils {
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({
|
||||
DialogType.EDIT_SHORTCUT_GENERIC,
|
||||
DialogType.EDIT_SHORTCUT_GENERIC_SUW,
|
||||
DialogType.EDIT_SHORTCUT_MAGNIFICATION,
|
||||
DialogType.EDIT_SHORTCUT_MAGNIFICATION_SUW,
|
||||
DialogType.EDIT_MAGNIFICATION_SWITCH_SHORTCUT,
|
||||
})
|
||||
|
||||
private @interface DialogType {
|
||||
public @interface DialogType {
|
||||
int EDIT_SHORTCUT_GENERIC = 0;
|
||||
int EDIT_SHORTCUT_MAGNIFICATION = 1;
|
||||
int EDIT_MAGNIFICATION_SWITCH_SHORTCUT = 2;
|
||||
int EDIT_SHORTCUT_GENERIC_SUW = 1;
|
||||
int EDIT_SHORTCUT_MAGNIFICATION = 2;
|
||||
int EDIT_SHORTCUT_MAGNIFICATION_SUW = 3;
|
||||
int EDIT_MAGNIFICATION_SWITCH_SHORTCUT = 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to show the edit shortcut dialog.
|
||||
*
|
||||
* @param context A valid context
|
||||
* @param dialogType The type of edit shortcut dialog
|
||||
* @param dialogTitle The title of edit shortcut dialog
|
||||
* @param listener The listener to determine the action of edit shortcut dialog
|
||||
* @return A edit shortcut dialog for showing
|
||||
*/
|
||||
public static AlertDialog showEditShortcutDialog(Context context, CharSequence dialogTitle,
|
||||
DialogInterface.OnClickListener listener) {
|
||||
final AlertDialog alertDialog = createDialog(context, DialogType.EDIT_SHORTCUT_GENERIC,
|
||||
dialogTitle, listener);
|
||||
alertDialog.show();
|
||||
setScrollIndicators(alertDialog);
|
||||
return alertDialog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to show the edit shortcut dialog in Magnification.
|
||||
*
|
||||
* @param context A valid context
|
||||
* @param dialogTitle The title of edit shortcut dialog
|
||||
* @param listener The listener to determine the action of edit shortcut dialog
|
||||
* @return A edit shortcut dialog for showing in Magnification
|
||||
*/
|
||||
public static AlertDialog showMagnificationEditShortcutDialog(Context context,
|
||||
public static AlertDialog showEditShortcutDialog(Context context, int dialogType,
|
||||
CharSequence dialogTitle, DialogInterface.OnClickListener listener) {
|
||||
final AlertDialog alertDialog = createDialog(context,
|
||||
DialogType.EDIT_SHORTCUT_MAGNIFICATION, dialogTitle, listener);
|
||||
final AlertDialog alertDialog = createDialog(context, dialogType, dialogTitle, listener);
|
||||
alertDialog.show();
|
||||
setScrollIndicators(alertDialog);
|
||||
return alertDialog;
|
||||
@@ -241,6 +228,12 @@ public class AccessibilityEditDialogUtils {
|
||||
initSoftwareShortcut(context, contentView);
|
||||
initHardwareShortcut(context, contentView);
|
||||
break;
|
||||
case DialogType.EDIT_SHORTCUT_GENERIC_SUW:
|
||||
contentView = inflater.inflate(
|
||||
R.layout.accessibility_edit_shortcut, null);
|
||||
initSoftwareShortcutForSUW(context, contentView);
|
||||
initHardwareShortcut(context, contentView);
|
||||
break;
|
||||
case DialogType.EDIT_SHORTCUT_MAGNIFICATION:
|
||||
contentView = inflater.inflate(
|
||||
R.layout.accessibility_edit_shortcut_magnification, null);
|
||||
@@ -249,6 +242,14 @@ public class AccessibilityEditDialogUtils {
|
||||
initMagnifyShortcut(context, contentView);
|
||||
initAdvancedWidget(contentView);
|
||||
break;
|
||||
case DialogType.EDIT_SHORTCUT_MAGNIFICATION_SUW:
|
||||
contentView = inflater.inflate(
|
||||
R.layout.accessibility_edit_shortcut_magnification, null);
|
||||
initSoftwareShortcutForSUW(context, contentView);
|
||||
initHardwareShortcut(context, contentView);
|
||||
initMagnifyShortcut(context, contentView);
|
||||
initAdvancedWidget(contentView);
|
||||
break;
|
||||
case DialogType.EDIT_MAGNIFICATION_SWITCH_SHORTCUT:
|
||||
contentView = inflater.inflate(
|
||||
R.layout.accessibility_edit_magnification_shortcut, null);
|
||||
@@ -278,6 +279,18 @@ public class AccessibilityEditDialogUtils {
|
||||
image.setImageResource(imageResId);
|
||||
}
|
||||
|
||||
private static void initSoftwareShortcutForSUW(Context context, View view) {
|
||||
final View dialogView = view.findViewById(R.id.software_shortcut);
|
||||
final CharSequence title = context.getText(
|
||||
R.string.accessibility_shortcut_edit_dialog_title_software);
|
||||
final TextView summary = dialogView.findViewById(R.id.summary);
|
||||
final int lineHeight = summary.getLineHeight();
|
||||
|
||||
setupShortcutWidget(dialogView, title,
|
||||
retrieveSoftwareShortcutSummaryForSUW(context, lineHeight),
|
||||
retrieveSoftwareShortcutImageResId(context));
|
||||
}
|
||||
|
||||
private static void initSoftwareShortcut(Context context, View view) {
|
||||
final View dialogView = view.findViewById(R.id.software_shortcut);
|
||||
final CharSequence title = context.getText(
|
||||
@@ -285,7 +298,8 @@ public class AccessibilityEditDialogUtils {
|
||||
final TextView summary = dialogView.findViewById(R.id.summary);
|
||||
final int lineHeight = summary.getLineHeight();
|
||||
|
||||
setupShortcutWidget(dialogView, title, retrieveSummary(context, lineHeight),
|
||||
setupShortcutWidget(dialogView, title,
|
||||
retrieveSoftwareShortcutSummary(context, lineHeight),
|
||||
retrieveSoftwareShortcutImageResId(context));
|
||||
}
|
||||
|
||||
@@ -320,7 +334,16 @@ public class AccessibilityEditDialogUtils {
|
||||
});
|
||||
}
|
||||
|
||||
private static CharSequence retrieveSummary(Context context, int lineHeight) {
|
||||
private static CharSequence retrieveSoftwareShortcutSummaryForSUW(Context context,
|
||||
int lineHeight) {
|
||||
final SpannableStringBuilder sb = new SpannableStringBuilder();
|
||||
if (!AccessibilityUtil.isFloatingMenuEnabled(context)) {
|
||||
sb.append(getSummaryStringWithIcon(context, lineHeight));
|
||||
}
|
||||
return sb;
|
||||
}
|
||||
|
||||
private static CharSequence retrieveSoftwareShortcutSummary(Context context, int lineHeight) {
|
||||
final SpannableStringBuilder sb = new SpannableStringBuilder();
|
||||
if (!AccessibilityUtil.isFloatingMenuEnabled(context)) {
|
||||
sb.append(getSummaryStringWithIcon(context, lineHeight));
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
package com.android.settings.accessibility;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.TextUtils;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.util.AttributeSet;
|
||||
@@ -25,7 +27,9 @@ import android.widget.TextView;
|
||||
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
|
||||
import com.android.settingslib.R;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.utils.AnnotationSpan;
|
||||
import com.android.settingslib.HelpUtils;
|
||||
import com.android.settingslib.widget.FooterPreference;
|
||||
|
||||
/**
|
||||
@@ -106,4 +110,23 @@ public final class AccessibilityFooterPreference extends FooterPreference {
|
||||
public boolean isLinkEnabled() {
|
||||
return mLinkEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends {@link AnnotationSpan} with learn more link apart from the other text.
|
||||
*
|
||||
* @param helpLinkRes The Help Uri Resource key
|
||||
*/
|
||||
public void appendHelpLink(int helpLinkRes) {
|
||||
final SpannableStringBuilder sb = new SpannableStringBuilder();
|
||||
sb.append(getTitle()).append("\n\n").append(getLearnMoreLink(getContext(), helpLinkRes));
|
||||
setTitle(sb);
|
||||
}
|
||||
|
||||
private CharSequence getLearnMoreLink(Context context, int helpLinkRes) {
|
||||
final Intent helpIntent = HelpUtils.getHelpIntent(
|
||||
context, context.getString(helpLinkRes), context.getClass().getName());
|
||||
final AnnotationSpan.LinkInfo linkInfo = new AnnotationSpan.LinkInfo(
|
||||
context, AnnotationSpan.LinkInfo.DEFAULT_ANNOTATION, helpIntent);
|
||||
return AnnotationSpan.linkify(context.getText(R.string.footer_learn_more), linkInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,14 @@ public abstract class AccessibilityFooterPreferenceController extends BasePrefer
|
||||
updateFooterPreferences(footerPreference);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this if showing a help item in the footer bar, by returning the resource id.
|
||||
*
|
||||
* @return the resource id for the help url
|
||||
*/
|
||||
protected int getHelpResource() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Returns the accessibility feature name. */
|
||||
protected abstract String getLabelName();
|
||||
@@ -54,5 +62,10 @@ public abstract class AccessibilityFooterPreferenceController extends BasePrefer
|
||||
final String iconContentDescription = mContext.getString(
|
||||
R.string.accessibility_introduction_title, getLabelName());
|
||||
footerPreference.setIconContentDescription(iconContentDescription);
|
||||
|
||||
if (getHelpResource() != 0) {
|
||||
footerPreference.appendHelpLink(getHelpResource());
|
||||
footerPreference.setLinkEnabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,4 +33,9 @@ public class CaptionFooterPreferenceController extends AccessibilityFooterPrefer
|
||||
protected String getLabelName() {
|
||||
return mContext.getString(R.string.accessibility_captioning_title);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getHelpResource() {
|
||||
return R.string.help_url_caption;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,4 +34,9 @@ public class ToggleAutoclickFooterPreferenceController extends
|
||||
protected String getLabelName() {
|
||||
return mContext.getString(R.string.accessibility_autoclick_preference_title);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getHelpResource() {
|
||||
return R.string.help_url_autoclick;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,8 +103,8 @@ public final class ToggleDaltonizerPreferenceFragment extends ToggleFeaturePrefe
|
||||
/** Customizes the order by preference key. */
|
||||
protected List<String> getPreferenceOrderList() {
|
||||
final List<String> lists = new ArrayList<>();
|
||||
lists.add(KEY_USE_SERVICE_PREFERENCE);
|
||||
lists.add(KEY_PREVIEW);
|
||||
lists.add(KEY_USE_SERVICE_PREFERENCE);
|
||||
lists.add(KEY_CATEGORY_MODE);
|
||||
lists.add(KEY_GENERAL_CATEGORY);
|
||||
lists.add(KEY_HTML_DESCRIPTION_PREFERENCE);
|
||||
|
||||
@@ -50,12 +50,15 @@ import androidx.preference.PreferenceScreen;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
import com.android.settings.accessibility.AccessibilityEditDialogUtils.DialogType;
|
||||
import com.android.settings.accessibility.AccessibilityUtil.UserShortcutType;
|
||||
import com.android.settings.widget.SettingsMainSwitchBar;
|
||||
import com.android.settings.widget.SettingsMainSwitchPreference;
|
||||
import com.android.settingslib.accessibility.AccessibilityUtils;
|
||||
import com.android.settingslib.widget.OnMainSwitchChangeListener;
|
||||
|
||||
import com.google.android.setupcompat.util.WizardManagerHelper;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
@@ -221,8 +224,11 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference
|
||||
case DialogEnums.EDIT_SHORTCUT:
|
||||
final CharSequence dialogTitle = getPrefContext().getString(
|
||||
R.string.accessibility_shortcut_title, mPackageName);
|
||||
final int dialogType = WizardManagerHelper.isAnySetupWizard(getIntent())
|
||||
? DialogType.EDIT_SHORTCUT_GENERIC_SUW : DialogType.EDIT_SHORTCUT_GENERIC;
|
||||
dialog = AccessibilityEditDialogUtils.showEditShortcutDialog(
|
||||
getPrefContext(), dialogTitle, this::callOnAlertDialogCheckboxClicked);
|
||||
getPrefContext(), dialogType, dialogTitle,
|
||||
this::callOnAlertDialogCheckboxClicked);
|
||||
setupEditShortcutDialog(dialog);
|
||||
return dialog;
|
||||
case DialogEnums.LAUNCH_ACCESSIBILITY_TUTORIAL:
|
||||
@@ -303,6 +309,11 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference
|
||||
return SettingsEnums.ACCESSIBILITY_SERVICE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHelpResource() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
@@ -379,8 +390,8 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference
|
||||
/** Customizes the order by preference key. */
|
||||
protected List<String> getPreferenceOrderList() {
|
||||
final List<String> lists = new ArrayList<>();
|
||||
lists.add(KEY_USE_SERVICE_PREFERENCE);
|
||||
lists.add(KEY_ANIMATED_IMAGE);
|
||||
lists.add(KEY_USE_SERVICE_PREFERENCE);
|
||||
lists.add(KEY_GENERAL_CATEGORY);
|
||||
lists.add(KEY_HTML_DESCRIPTION_PREFERENCE);
|
||||
return lists;
|
||||
@@ -508,7 +519,13 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference
|
||||
new AccessibilityFooterPreference(screen.getContext());
|
||||
htmlFooterPreference.setKey(KEY_HTML_DESCRIPTION_PREFERENCE);
|
||||
htmlFooterPreference.setSummary(htmlDescription);
|
||||
htmlFooterPreference.setLinkEnabled(false);
|
||||
// Only framework tools support help link
|
||||
if (getHelpResource() != 0) {
|
||||
htmlFooterPreference.appendHelpLink(getHelpResource());
|
||||
htmlFooterPreference.setLinkEnabled(true);
|
||||
} else {
|
||||
htmlFooterPreference.setLinkEnabled(false);
|
||||
}
|
||||
htmlFooterPreference.setIconContentDescription(iconContentDescription);
|
||||
screen.addPreference(htmlFooterPreference);
|
||||
}
|
||||
@@ -542,6 +559,10 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference
|
||||
new AccessibilityFooterPreference(screen.getContext());
|
||||
footerPreference.setSummary(summary);
|
||||
footerPreference.setIconContentDescription(iconContentDescription);
|
||||
if (getHelpResource() != 0) {
|
||||
footerPreference.appendHelpLink(getHelpResource());
|
||||
footerPreference.setLinkEnabled(true);
|
||||
}
|
||||
screen.addPreference(footerPreference);
|
||||
}
|
||||
|
||||
|
||||
@@ -44,8 +44,11 @@ import androidx.preference.PreferenceCategory;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.settings.DialogCreatable;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.accessibility.AccessibilityEditDialogUtils.DialogType;
|
||||
import com.android.settings.accessibility.AccessibilityUtil.UserShortcutType;
|
||||
|
||||
import com.google.android.setupcompat.util.WizardManagerHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@@ -127,9 +130,11 @@ public class ToggleScreenMagnificationPreferenceFragment extends
|
||||
case DialogEnums.MAGNIFICATION_EDIT_SHORTCUT:
|
||||
final CharSequence dialogTitle = getPrefContext().getString(
|
||||
R.string.accessibility_shortcut_title, mPackageName);
|
||||
dialog = AccessibilityEditDialogUtils.showMagnificationEditShortcutDialog(
|
||||
getPrefContext(), dialogTitle,
|
||||
this::callOnAlertDialogCheckboxClicked);
|
||||
final int dialogType = WizardManagerHelper.isAnySetupWizard(getIntent())
|
||||
? DialogType.EDIT_SHORTCUT_MAGNIFICATION_SUW
|
||||
: DialogType.EDIT_SHORTCUT_MAGNIFICATION;
|
||||
dialog = AccessibilityEditDialogUtils.showEditShortcutDialog(getPrefContext(),
|
||||
dialogType, dialogTitle, this::callOnAlertDialogCheckboxClicked);
|
||||
setupMagnificationEditShortcutDialog(dialog);
|
||||
return dialog;
|
||||
default:
|
||||
@@ -139,7 +144,6 @@ public class ToggleScreenMagnificationPreferenceFragment extends
|
||||
|
||||
@Override
|
||||
protected void initSettingsPreference() {
|
||||
|
||||
// If the device doesn't support magnification area, it should hide the settings preference.
|
||||
if (!getContext().getResources().getBoolean(
|
||||
com.android.internal.R.bool.config_magnification_area)) {
|
||||
@@ -296,6 +300,11 @@ public class ToggleScreenMagnificationPreferenceFragment extends
|
||||
getShortcutTypeSummary(getPrefContext()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHelpResource() {
|
||||
return R.string.help_url_magnification;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
// TODO: Distinguish between magnification modes
|
||||
|
||||
@@ -16,26 +16,35 @@
|
||||
|
||||
package com.android.settings.applications;
|
||||
|
||||
import static android.app.usage.UsageStatsManager.INTERVAL_MONTHLY;
|
||||
import static android.provider.DeviceConfig.NAMESPACE_APP_HIBERNATION;
|
||||
|
||||
import static com.android.settings.Utils.PROPERTY_APP_HIBERNATION_ENABLED;
|
||||
|
||||
import android.app.usage.UsageStats;
|
||||
import android.app.usage.UsageStatsManager;
|
||||
import android.apphibernation.AppHibernationManager;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.util.ArrayMap;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* A preference controller handling the logic for updating summary of hibernated apps.
|
||||
*/
|
||||
public final class HibernatedAppsPreferenceController extends BasePreferenceController {
|
||||
private static final String TAG = "HibernatedAppsPrefController";
|
||||
private static final String PROPERTY_HIBERNATION_UNUSED_THRESHOLD_MILLIS =
|
||||
"auto_revoke_unused_threshold_millis2";
|
||||
private static final long DEFAULT_UNUSED_THRESHOLD_MS = TimeUnit.DAYS.toMillis(90);
|
||||
|
||||
public HibernatedAppsPreferenceController(Context context, String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
@@ -55,17 +64,36 @@ public final class HibernatedAppsPreferenceController extends BasePreferenceCont
|
||||
}
|
||||
|
||||
private int getNumHibernated() {
|
||||
// TODO(b/187465752): Find a way to export this logic from PermissionController module
|
||||
final PackageManager pm = mContext.getPackageManager();
|
||||
final AppHibernationManager ahm = mContext.getSystemService(AppHibernationManager.class);
|
||||
final List<String> hibernatedPackages = ahm.getHibernatingPackagesForUser();
|
||||
int numHibernated = hibernatedPackages.size();
|
||||
|
||||
// Also need to count packages that are auto revoked but not hibernated.
|
||||
final UsageStatsManager usm = mContext.getSystemService(UsageStatsManager.class);
|
||||
final long now = System.currentTimeMillis();
|
||||
final long unusedThreshold = DeviceConfig.getLong(DeviceConfig.NAMESPACE_PERMISSIONS,
|
||||
PROPERTY_HIBERNATION_UNUSED_THRESHOLD_MILLIS, DEFAULT_UNUSED_THRESHOLD_MS);
|
||||
final List<UsageStats> usageStatsList = usm.queryUsageStats(INTERVAL_MONTHLY,
|
||||
now - unusedThreshold, now);
|
||||
final Map<String, UsageStats> recentlyUsedPackages = new ArrayMap<>();
|
||||
for (UsageStats us : usageStatsList) {
|
||||
recentlyUsedPackages.put(us.mPackageName, us);
|
||||
}
|
||||
final List<PackageInfo> packages = pm.getInstalledPackages(
|
||||
PackageManager.MATCH_DISABLED_COMPONENTS | PackageManager.GET_PERMISSIONS);
|
||||
for (PackageInfo pi : packages) {
|
||||
final String packageName = pi.packageName;
|
||||
if (!hibernatedPackages.contains(packageName) && pi.requestedPermissions != null) {
|
||||
final UsageStats usageStats = recentlyUsedPackages.get(packageName);
|
||||
// Only count packages that have not been used recently as auto-revoked permissions may
|
||||
// stay revoked even after use if the user has not regranted them.
|
||||
final boolean usedRecently = (usageStats != null
|
||||
&& (now - usageStats.getLastTimeAnyComponentUsed() < unusedThreshold
|
||||
|| now - usageStats.getLastTimeVisible() < unusedThreshold));
|
||||
if (!hibernatedPackages.contains(packageName)
|
||||
&& pi.requestedPermissions != null
|
||||
&& !usedRecently) {
|
||||
for (String perm : pi.requestedPermissions) {
|
||||
if ((pm.getPermissionFlags(perm, packageName, mContext.getUser())
|
||||
& PackageManager.FLAG_PERMISSION_AUTO_REVOKED) != 0) {
|
||||
|
||||
@@ -126,7 +126,7 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
|
||||
public abstract void onClick(LinkSpan span);
|
||||
|
||||
protected interface GenerateChallengeCallback {
|
||||
void onChallengeGenerated(int sensorId, long challenge);
|
||||
void onChallengeGenerated(int sensorId, int userId, long challenge);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -261,7 +261,7 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
|
||||
updatePasswordQuality();
|
||||
overridePendingTransition(R.anim.sud_slide_next_in, R.anim.sud_slide_next_out);
|
||||
getNextButton().setEnabled(false);
|
||||
getChallenge(((sensorId, challenge) -> {
|
||||
getChallenge(((sensorId, userId, challenge) -> {
|
||||
mSensorId = sensorId;
|
||||
mChallenge = challenge;
|
||||
mToken = BiometricUtils.requestGatekeeperHat(this, data, mUserId, challenge);
|
||||
@@ -277,7 +277,7 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
|
||||
if (resultCode == RESULT_OK && data != null) {
|
||||
overridePendingTransition(R.anim.sud_slide_next_in, R.anim.sud_slide_next_out);
|
||||
getNextButton().setEnabled(false);
|
||||
getChallenge(((sensorId, challenge) -> {
|
||||
getChallenge(((sensorId, userId, challenge) -> {
|
||||
mSensorId = sensorId;
|
||||
mChallenge = challenge;
|
||||
mToken = BiometricUtils.requestGatekeeperHat(this, data, mUserId, challenge);
|
||||
|
||||
@@ -67,7 +67,7 @@ public class MultiBiometricEnrollHelper {
|
||||
|
||||
private void launchFaceEnroll() {
|
||||
final FaceManager faceManager = mActivity.getSystemService(FaceManager.class);
|
||||
faceManager.generateChallenge((sensorId, challenge) -> {
|
||||
faceManager.generateChallenge(mUserId, (sensorId, userId, challenge) -> {
|
||||
final byte[] hardwareAuthToken = BiometricUtils.requestGatekeeperHat(mActivity,
|
||||
mGkPwHandle, mUserId, challenge);
|
||||
final Intent faceIntent = BiometricUtils.getFaceIntroIntent(mActivity,
|
||||
@@ -96,7 +96,7 @@ public class MultiBiometricEnrollHelper {
|
||||
private void launchFingerprintEnroll() {
|
||||
final FingerprintManager fingerprintManager = mActivity
|
||||
.getSystemService(FingerprintManager.class);
|
||||
fingerprintManager.generateChallenge(mUserId, ((sensorId, challenge) -> {
|
||||
fingerprintManager.generateChallenge(mUserId, ((sensorId, userId, challenge) -> {
|
||||
final byte[] hardwareAuthToken = BiometricUtils.requestGatekeeperHat(mActivity,
|
||||
mGkPwHandle, mUserId, challenge);
|
||||
final Intent intent = BiometricUtils.getFingerprintIntroIntent(mActivity,
|
||||
|
||||
@@ -115,7 +115,7 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
|
||||
// since FingerprintSettings and FaceSettings revoke the challenge when finishing.
|
||||
if (getFacePreferenceKey().equals(key)) {
|
||||
mDoNotFinishActivity = true;
|
||||
mFaceManager.generateChallenge((sensorId, challenge) -> {
|
||||
mFaceManager.generateChallenge(mUserId, (sensorId, userId, challenge) -> {
|
||||
final byte[] token = BiometricUtils.requestGatekeeperHat(getActivity(), mGkPwHandle,
|
||||
mUserId, challenge);
|
||||
final Bundle extras = preference.getExtras();
|
||||
@@ -125,7 +125,7 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
|
||||
});
|
||||
} else if (getFingerprintPreferenceKey().equals(key)) {
|
||||
mDoNotFinishActivity = true;
|
||||
mFingerprintManager.generateChallenge(mUserId, (sensorId, challenge) -> {
|
||||
mFingerprintManager.generateChallenge(mUserId, (sensorId, userId, challenge) -> {
|
||||
final byte[] token = BiometricUtils.requestGatekeeperHat(getActivity(), mGkPwHandle,
|
||||
mUserId, challenge);
|
||||
final Bundle extras = preference.getExtras();
|
||||
|
||||
@@ -110,7 +110,7 @@ public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
|
||||
mFooterBarMixin.getPrimaryButton().setEnabled(false);
|
||||
// We either block on generateChallenge, or need to gray out the "next" button until
|
||||
// the challenge is ready. Let's just do this for now.
|
||||
mFaceManager.generateChallenge((sensorId, challenge) -> {
|
||||
mFaceManager.generateChallenge(mUserId, (sensorId, userId, challenge) -> {
|
||||
mToken = BiometricUtils.requestGatekeeperHat(this, getIntent(), mUserId, challenge);
|
||||
mSensorId = sensorId;
|
||||
mChallenge = challenge;
|
||||
@@ -196,10 +196,10 @@ public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
|
||||
protected void getChallenge(GenerateChallengeCallback callback) {
|
||||
mFaceManager = Utils.getFaceManagerOrNull(this);
|
||||
if (mFaceManager == null) {
|
||||
callback.onChallengeGenerated(0, 0L);
|
||||
callback.onChallengeGenerated(0, 0, 0L);
|
||||
return;
|
||||
}
|
||||
mFaceManager.generateChallenge(callback::onChallengeGenerated);
|
||||
mFaceManager.generateChallenge(mUserId, callback::onChallengeGenerated);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -249,7 +249,7 @@ public class FaceSettings extends DashboardFragment {
|
||||
if (requestCode == CONFIRM_REQUEST) {
|
||||
if (resultCode == RESULT_FINISHED || resultCode == RESULT_OK) {
|
||||
// The pin/pattern/password was set.
|
||||
mFaceManager.generateChallenge((sensorId, challenge) -> {
|
||||
mFaceManager.generateChallenge(mUserId, (sensorId, userId, challenge) -> {
|
||||
mToken = BiometricUtils.requestGatekeeperHat(getPrefContext(), data, mUserId,
|
||||
challenge);
|
||||
mSensorId = sensorId;
|
||||
|
||||
@@ -81,7 +81,7 @@ public class FingerprintEnrollFindSensor extends BiometricEnrollBase implements
|
||||
// adb shell am start -a android.app.action.SET_NEW_PASSWORD
|
||||
if (mToken == null && BiometricUtils.containsGatekeeperPasswordHandle(getIntent())) {
|
||||
final FingerprintManager fpm = getSystemService(FingerprintManager.class);
|
||||
fpm.generateChallenge(mUserId, (sensorId, challenge) -> {
|
||||
fpm.generateChallenge(mUserId, (sensorId, userId, challenge) -> {
|
||||
mChallenge = challenge;
|
||||
mSensorId = sensorId;
|
||||
mToken = BiometricUtils.requestGatekeeperHat(this, getIntent(), mUserId, challenge);
|
||||
|
||||
@@ -157,7 +157,7 @@ public class FingerprintEnrollIntroduction extends BiometricEnrollIntroduction {
|
||||
protected void getChallenge(GenerateChallengeCallback callback) {
|
||||
mFingerprintManager = Utils.getFingerprintManagerOrNull(this);
|
||||
if (mFingerprintManager == null) {
|
||||
callback.onChallengeGenerated(0, 0L);
|
||||
callback.onChallengeGenerated(0, 0, 0L);
|
||||
return;
|
||||
}
|
||||
mFingerprintManager.generateChallenge(mUserId, callback::onChallengeGenerated);
|
||||
|
||||
@@ -601,12 +601,15 @@ public class FingerprintSettings extends SubSettings {
|
||||
mLaunchedConfirm = false;
|
||||
if (resultCode == RESULT_FINISHED || resultCode == RESULT_OK) {
|
||||
if (data != null && BiometricUtils.containsGatekeeperPasswordHandle(data)) {
|
||||
mFingerprintManager.generateChallenge(mUserId, (sensorId, challenge) -> {
|
||||
mToken = BiometricUtils.requestGatekeeperHat(getActivity(), data,
|
||||
mUserId, challenge);
|
||||
mChallenge = challenge;
|
||||
BiometricUtils.removeGatekeeperPasswordHandle(getActivity(), data);
|
||||
updateAddPreference();
|
||||
mFingerprintManager.generateChallenge(mUserId,
|
||||
(sensorId, userId, challenge) -> {
|
||||
mToken = BiometricUtils.requestGatekeeperHat(getActivity(),
|
||||
data,
|
||||
mUserId, challenge);
|
||||
mChallenge = challenge;
|
||||
BiometricUtils.removeGatekeeperPasswordHandle(getActivity(),
|
||||
data);
|
||||
updateAddPreference();
|
||||
});
|
||||
} else {
|
||||
Log.d(TAG, "Data null or GK PW missing");
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.settings.bluetooth;
|
||||
|
||||
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
@@ -31,6 +33,7 @@ public final class DevicePickerActivity extends FragmentActivity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
|
||||
setContentView(R.layout.bluetooth_device_picker);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.util.ArrayMap;
|
||||
|
||||
import com.android.settings.accounts.AccountDashboardFragment;
|
||||
import com.android.settings.applications.manageapplications.ManageApplications;
|
||||
import com.android.settings.deviceinfo.StorageDashboardFragment;
|
||||
import com.android.settings.location.LocationServices;
|
||||
import com.android.settings.location.RecentLocationAccessSeeAllFragment;
|
||||
|
||||
@@ -46,5 +47,7 @@ public class ProfileFragmentBridge {
|
||||
ProfileSelectRecentLocationAccessFragment.class.getName());
|
||||
FRAGMENT_MAP.put(LocationServices.class.getName(),
|
||||
ProfileSelectLocationServicesFragment.class.getName());
|
||||
FRAGMENT_MAP.put(StorageDashboardFragment.class.getName(),
|
||||
ProfileSelectStorageFragment.class.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.dashboard.profileselector;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.android.settings.deviceinfo.StorageDashboardFragment;
|
||||
|
||||
/**
|
||||
* Storage Settings page for personal/managed profile.
|
||||
*/
|
||||
public class ProfileSelectStorageFragment extends ProfileSelectFragment {
|
||||
|
||||
@Override
|
||||
public Fragment[] getFragments() {
|
||||
final Bundle workBundle = new Bundle();
|
||||
workBundle.putInt(EXTRA_PROFILE, ProfileType.WORK);
|
||||
final Fragment workFragment = new StorageDashboardFragment();
|
||||
workFragment.setArguments(workBundle);
|
||||
|
||||
final Bundle personalBundle = new Bundle();
|
||||
personalBundle.putInt(EXTRA_PROFILE, ProfileType.PERSONAL);
|
||||
final Fragment personalFragment = new StorageDashboardFragment();
|
||||
personalFragment.setArguments(personalBundle);
|
||||
|
||||
return new Fragment[] {
|
||||
personalFragment,
|
||||
workFragment
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -85,6 +85,7 @@ public class StorageDashboardFragment extends DashboardFragment
|
||||
private static final int VOLUME_SIZE_JOB_ID = 2;
|
||||
|
||||
private StorageManager mStorageManager;
|
||||
private UserManager mUserManager;
|
||||
private final List<StorageEntry> mStorageEntries = new ArrayList<>();
|
||||
private StorageEntry mSelectedStorageEntry;
|
||||
private PrivateStorageInfo mStorageInfo;
|
||||
@@ -96,7 +97,8 @@ public class StorageDashboardFragment extends DashboardFragment
|
||||
private StorageSelectionPreferenceController mStorageSelectionController;
|
||||
private StorageUsageProgressBarPreferenceController mStorageUsageProgressBarController;
|
||||
private List<AbstractPreferenceController> mSecondaryUsers;
|
||||
private boolean mPersonalOnly;
|
||||
private boolean mIsWorkProfile;
|
||||
private int mUserId;
|
||||
private Preference mFreeUpSpacePreference;
|
||||
|
||||
private final StorageEventListener mStorageEventListener = new StorageEventListener() {
|
||||
@@ -270,8 +272,6 @@ public class StorageDashboardFragment extends DashboardFragment
|
||||
|
||||
final Activity activity = getActivity();
|
||||
mStorageManager = activity.getSystemService(StorageManager.class);
|
||||
mPersonalOnly = getArguments().getInt(ProfileSelectFragment.EXTRA_PROFILE)
|
||||
== ProfileSelectFragment.ProfileType.PERSONAL;
|
||||
|
||||
if (icicle == null) {
|
||||
final VolumeInfo specifiedVolumeInfo =
|
||||
@@ -288,18 +288,19 @@ public class StorageDashboardFragment extends DashboardFragment
|
||||
}
|
||||
|
||||
private void initializePreference() {
|
||||
if (mPersonalOnly) {
|
||||
final Preference summary = getPreferenceScreen().findPreference(SUMMARY_PREF_KEY);
|
||||
if (summary != null) {
|
||||
summary.setVisible(false);
|
||||
}
|
||||
}
|
||||
mFreeUpSpacePreference = getPreferenceScreen().findPreference(FREE_UP_SPACE_PREF_KEY);
|
||||
mFreeUpSpacePreference.setOnPreferenceClickListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
// 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);
|
||||
|
||||
super.onAttach(context);
|
||||
use(AutomaticStorageManagementSwitchPreferenceController.class).setFragmentManager(
|
||||
getFragmentManager());
|
||||
@@ -396,7 +397,7 @@ public class StorageDashboardFragment extends DashboardFragment
|
||||
}
|
||||
|
||||
if (mAppsResult != null) {
|
||||
mPreferenceController.onLoadFinished(mAppsResult, UserHandle.myUserId());
|
||||
mPreferenceController.onLoadFinished(mAppsResult, mUserId);
|
||||
updateSecondaryUserControllers(mSecondaryUsers, mAppsResult);
|
||||
stopLoading = true;
|
||||
}
|
||||
@@ -427,14 +428,13 @@ public class StorageDashboardFragment extends DashboardFragment
|
||||
@Override
|
||||
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
|
||||
final List<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||
|
||||
StorageManager sm = context.getSystemService(StorageManager.class);
|
||||
mPreferenceController = new StorageItemPreferenceController(context, this,
|
||||
null /* volume */, new StorageManagerVolumeProvider(sm));
|
||||
null /* volume */, new StorageManagerVolumeProvider(sm), mIsWorkProfile);
|
||||
controllers.add(mPreferenceController);
|
||||
|
||||
final UserManager userManager = context.getSystemService(UserManager.class);
|
||||
mSecondaryUsers = SecondaryUserController.getSecondaryUserControllers(context, userManager);
|
||||
mSecondaryUsers = SecondaryUserController.getSecondaryUserControllers(context,
|
||||
mUserManager, mIsWorkProfile /* isWorkProfileOnly */);
|
||||
controllers.addAll(mSecondaryUsers);
|
||||
|
||||
return controllers;
|
||||
@@ -480,9 +480,10 @@ public class StorageDashboardFragment extends DashboardFragment
|
||||
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)));
|
||||
null /* volume */, new StorageManagerVolumeProvider(sm),
|
||||
false /* isWorkProfile */));
|
||||
controllers.addAll(SecondaryUserController.getSecondaryUserControllers(
|
||||
context, userManager));
|
||||
context, userManager, false /* isWorkProfileOnly */));
|
||||
return controllers;
|
||||
}
|
||||
|
||||
@@ -492,7 +493,7 @@ public class StorageDashboardFragment extends DashboardFragment
|
||||
public Loader<SparseArray<StorageAsyncLoader.AppsStorageResult>> onCreateLoader(int id,
|
||||
Bundle args) {
|
||||
final Context context = getContext();
|
||||
return new StorageAsyncLoader(context, context.getSystemService(UserManager.class),
|
||||
return new StorageAsyncLoader(context, mUserManager,
|
||||
mSelectedStorageEntry.getFsUuid(),
|
||||
new StorageStatsSource(context),
|
||||
context.getPackageManager());
|
||||
@@ -519,7 +520,7 @@ public class StorageDashboardFragment extends DashboardFragment
|
||||
metricsFeatureProvider.logClickedPreference(preference, getMetricsCategory());
|
||||
metricsFeatureProvider.action(context, SettingsEnums.STORAGE_FREE_UP_SPACE_NOW);
|
||||
final Intent intent = new Intent(StorageManager.ACTION_MANAGE_STORAGE);
|
||||
context.startActivity(intent);
|
||||
context.startActivityAsUser(intent, new UserHandle(mUserId));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -574,16 +575,14 @@ public class StorageDashboardFragment extends DashboardFragment
|
||||
}
|
||||
|
||||
private void initializeCacheProvider() {
|
||||
mCachedStorageValuesHelper =
|
||||
new CachedStorageValuesHelper(getContext(), UserHandle.myUserId());
|
||||
mCachedStorageValuesHelper = new CachedStorageValuesHelper(getContext(), mUserId);
|
||||
initializeCachedValues();
|
||||
onReceivedSizes();
|
||||
}
|
||||
|
||||
private void maybeCacheFreshValues() {
|
||||
if (mStorageInfo != null && mAppsResult != null) {
|
||||
mCachedStorageValuesHelper.cacheResult(
|
||||
mStorageInfo, mAppsResult.get(UserHandle.myUserId()));
|
||||
mCachedStorageValuesHelper.cacheResult(mStorageInfo, mAppsResult.get(mUserId));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,138 +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.deviceinfo;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.os.storage.StorageManager;
|
||||
import android.os.storage.VolumeInfo;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.loader.app.LoaderManager;
|
||||
import androidx.loader.content.Loader;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.deviceinfo.storage.StorageAsyncLoader;
|
||||
import com.android.settings.deviceinfo.storage.StorageAsyncLoader.AppsStorageResult;
|
||||
import com.android.settings.deviceinfo.storage.StorageItemPreferenceController;
|
||||
import com.android.settingslib.applications.StorageStatsSource;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.deviceinfo.StorageManagerVolumeProvider;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* StorageProfileFragment is a fragment which shows the storage results for a profile of the
|
||||
* primary user.
|
||||
*/
|
||||
public class StorageProfileFragment extends DashboardFragment
|
||||
implements LoaderManager.LoaderCallbacks<SparseArray<AppsStorageResult>> {
|
||||
private static final String TAG = "StorageProfileFragment";
|
||||
public static final String USER_ID_EXTRA = "userId";
|
||||
private static final int APPS_JOB_ID = 0;
|
||||
|
||||
private VolumeInfo mVolume;
|
||||
private int mUserId;
|
||||
private StorageItemPreferenceController mPreferenceController;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
final Bundle args = getArguments();
|
||||
|
||||
// Initialize the storage sizes that we can quickly calc.
|
||||
final Context context = getActivity();
|
||||
final StorageManager sm = context.getSystemService(StorageManager.class);
|
||||
mVolume = Utils.maybeInitializeVolume(sm, args);
|
||||
if (mVolume == null) {
|
||||
getActivity().finish();
|
||||
return;
|
||||
}
|
||||
|
||||
mPreferenceController.setVolume(mVolume);
|
||||
mUserId = args.getInt(USER_ID_EXTRA, UserHandle.myUserId());
|
||||
mPreferenceController.setUserId(UserHandle.of(mUserId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
getLoaderManager().initLoader(APPS_JOB_ID, Bundle.EMPTY, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return SettingsEnums.SETTINGS_STORAGE_PROFILE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getLogTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getPreferenceScreenResId() {
|
||||
return R.xml.storage_profile_fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
|
||||
final List<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||
final StorageManager sm = context.getSystemService(StorageManager.class);
|
||||
mPreferenceController =
|
||||
new StorageItemPreferenceController(
|
||||
context,
|
||||
this,
|
||||
mVolume,
|
||||
new StorageManagerVolumeProvider(sm),
|
||||
/* isWorkProfile */ true);
|
||||
controllers.add(mPreferenceController);
|
||||
return controllers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Loader<SparseArray<AppsStorageResult>> onCreateLoader(int id, Bundle args) {
|
||||
final Context context = getContext();
|
||||
return new StorageAsyncLoader(context,
|
||||
context.getSystemService(UserManager.class),
|
||||
mVolume.fsUuid,
|
||||
new StorageStatsSource(context),
|
||||
context.getPackageManager());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(Loader<SparseArray<AppsStorageResult>> loader,
|
||||
SparseArray<AppsStorageResult> result) {
|
||||
mPreferenceController.onLoadFinished(result, mUserId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(Loader<SparseArray<AppsStorageResult>> loader) {
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void setPreferenceController(StorageItemPreferenceController controller) {
|
||||
mPreferenceController = controller;
|
||||
}
|
||||
}
|
||||
@@ -63,9 +63,11 @@ public class SecondaryUserController extends AbstractPreferenceController implem
|
||||
*
|
||||
* @param context Context for initializing the preference controllers.
|
||||
* @param userManager UserManagerWrapper for figuring out which controllers to add.
|
||||
* @param isWorkProfileOnly only shows secondary users of work profile.
|
||||
* (e.g., it should be true in work profile tab)
|
||||
*/
|
||||
public static List<AbstractPreferenceController> getSecondaryUserControllers(
|
||||
Context context, UserManager userManager) {
|
||||
Context context, UserManager userManager, boolean isWorkProfileOnly) {
|
||||
|
||||
List<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||
UserInfo primaryUser = userManager.getPrimaryUser();
|
||||
@@ -77,7 +79,11 @@ public class SecondaryUserController extends AbstractPreferenceController implem
|
||||
continue;
|
||||
}
|
||||
|
||||
if (info == null || Utils.isProfileOf(primaryUser, info)) {
|
||||
if (Utils.isProfileOf(primaryUser, info)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isWorkProfileOnly && !info.isManagedProfile()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ public class StorageAsyncLoader
|
||||
}
|
||||
});
|
||||
for (int i = 0, userCount = infos.size(); i < userCount; i++) {
|
||||
UserInfo info = infos.get(i);
|
||||
final UserInfo info = infos.get(i);
|
||||
result.put(info.id, getStorageResultForUser(info.id));
|
||||
}
|
||||
return result;
|
||||
@@ -109,7 +109,7 @@ public class StorageAsyncLoader
|
||||
final long dataSize = stats.getDataBytes();
|
||||
final long cacheQuota = mStatsManager.getCacheQuotaBytes(mUuid, app.uid);
|
||||
final long cacheBytes = stats.getCacheBytes();
|
||||
long blamedSize = dataSize;
|
||||
long blamedSize = dataSize + stats.getCodeBytes();
|
||||
// Technically, we could overages as freeable on the storage settings screen.
|
||||
// If the app is using more cache than its quota, we would accidentally subtract the
|
||||
// overage from the system size (because it shows up as unused) during our attribution.
|
||||
@@ -118,12 +118,11 @@ public class StorageAsyncLoader
|
||||
blamedSize = blamedSize - cacheBytes + cacheQuota;
|
||||
}
|
||||
|
||||
// This isn't quite right because it slams the first user by user id with the whole code
|
||||
// size, but this ensures that we count all apps seen once.
|
||||
boolean isAddCodeBytesForFirstUserId = false;
|
||||
if (!mSeenPackages.contains(app.packageName)) {
|
||||
isAddCodeBytesForFirstUserId = true;
|
||||
blamedSize += stats.getCodeBytes();
|
||||
// Code bytes may share between different profiles. To know all the duplicate code size
|
||||
// and we can get a reasonable system size in StorageItemPreferenceController.
|
||||
if (mSeenPackages.contains(app.packageName)) {
|
||||
result.duplicateCodeSize += stats.getCodeBytes();
|
||||
} else {
|
||||
mSeenPackages.add(app.packageName);
|
||||
}
|
||||
|
||||
@@ -135,9 +134,7 @@ public class StorageAsyncLoader
|
||||
// TODO(b/170918505): Should revamp audio size calculation with the data
|
||||
// from media provider.
|
||||
result.musicAppsSize += blamedSize;
|
||||
if (isAddCodeBytesForFirstUserId) {
|
||||
result.musicAppsSize -= stats.getCodeBytes();
|
||||
}
|
||||
result.musicAppsSize -= stats.getCodeBytes();
|
||||
|
||||
result.otherAppsSize += blamedSize;
|
||||
break;
|
||||
@@ -145,9 +142,7 @@ public class StorageAsyncLoader
|
||||
// TODO(b/170918505): Should revamp video size calculation with the data
|
||||
// from media provider.
|
||||
result.videoAppsSize += blamedSize;
|
||||
if (isAddCodeBytesForFirstUserId) {
|
||||
result.videoAppsSize -= stats.getCodeBytes();
|
||||
}
|
||||
result.videoAppsSize -= stats.getCodeBytes();
|
||||
|
||||
result.otherAppsSize += blamedSize;
|
||||
break;
|
||||
@@ -155,9 +150,7 @@ public class StorageAsyncLoader
|
||||
// TODO(b/170918505): Should revamp image size calculation with the data
|
||||
// from media provider.
|
||||
result.photosAppsSize += blamedSize;
|
||||
if (isAddCodeBytesForFirstUserId) {
|
||||
result.photosAppsSize -= stats.getCodeBytes();
|
||||
}
|
||||
result.photosAppsSize -= stats.getCodeBytes();
|
||||
|
||||
result.otherAppsSize += blamedSize;
|
||||
break;
|
||||
@@ -194,6 +187,7 @@ public class StorageAsyncLoader
|
||||
public long videoAppsSize;
|
||||
public long otherAppsSize;
|
||||
public long cacheSize;
|
||||
public long duplicateCodeSize;
|
||||
public StorageStatsSource.ExternalStorageStats externalStats;
|
||||
}
|
||||
|
||||
|
||||
@@ -101,6 +101,7 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
|
||||
private static final int LAST_STORAGE_CATEGORY_PREFERENCE_ORDER = 200;
|
||||
|
||||
private PackageManager mPackageManager;
|
||||
private UserManager mUserManager;
|
||||
private final Fragment mFragment;
|
||||
private final MetricsFeatureProvider mMetricsFeatureProvider;
|
||||
private final StorageVolumeProvider mSvp;
|
||||
@@ -134,15 +135,17 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
|
||||
|
||||
private static final String AUTHORITY_MEDIA = "com.android.providers.media.documents";
|
||||
|
||||
public StorageItemPreferenceController(
|
||||
Context context, Fragment hostFragment, VolumeInfo volume, StorageVolumeProvider svp) {
|
||||
public StorageItemPreferenceController(Context context, Fragment hostFragment,
|
||||
VolumeInfo volume, StorageVolumeProvider svp, boolean isWorkProfile) {
|
||||
super(context);
|
||||
mPackageManager = context.getPackageManager();
|
||||
mUserManager = context.getSystemService(UserManager.class);
|
||||
mFragment = hostFragment;
|
||||
mVolume = volume;
|
||||
mSvp = svp;
|
||||
mIsWorkProfile = isWorkProfile;
|
||||
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
|
||||
mUserId = UserHandle.myUserId();
|
||||
mUserId = getCurrentUserId();
|
||||
|
||||
mImagesUri = Uri.parse(context.getResources()
|
||||
.getString(R.string.config_images_storage_category_uri));
|
||||
@@ -154,14 +157,9 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
|
||||
.getString(R.string.config_documents_and_other_storage_category_uri));
|
||||
}
|
||||
|
||||
public StorageItemPreferenceController(
|
||||
Context context,
|
||||
Fragment hostFragment,
|
||||
VolumeInfo volume,
|
||||
StorageVolumeProvider svp,
|
||||
boolean isWorkProfile) {
|
||||
this(context, hostFragment, volume, svp);
|
||||
mIsWorkProfile = isWorkProfile;
|
||||
@VisibleForTesting
|
||||
int getCurrentUserId() {
|
||||
return Utils.getCurrentUserId(mUserManager, mIsWorkProfile);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -311,6 +309,9 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
|
||||
* Sets the user id for which this preference controller is handling.
|
||||
*/
|
||||
public void setUserId(UserHandle userHandle) {
|
||||
if (mIsWorkProfile && !mUserManager.isManagedProfile(userHandle.getIdentifier())) {
|
||||
throw new IllegalArgumentException("Only accept work profile userHandle");
|
||||
}
|
||||
mUserId = userHandle.getIdentifier();
|
||||
|
||||
tintPreference(mPublicStoragePreference);
|
||||
@@ -359,21 +360,21 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
|
||||
public void onLoadFinished(SparseArray<StorageAsyncLoader.AppsStorageResult> result,
|
||||
int userId) {
|
||||
final StorageAsyncLoader.AppsStorageResult data = result.get(userId);
|
||||
final StorageAsyncLoader.AppsStorageResult profileData = result.get(
|
||||
Utils.getManagedProfileId(mContext.getSystemService(UserManager.class), userId));
|
||||
|
||||
mImagesPreference.setStorageSize(getImagesSize(data, profileData), mTotalSize);
|
||||
mVideosPreference.setStorageSize(getVideosSize(data, profileData), mTotalSize);
|
||||
mAudiosPreference.setStorageSize(getAudiosSize(data, profileData), mTotalSize);
|
||||
mAppsPreference.setStorageSize(getAppsSize(data, profileData), mTotalSize);
|
||||
mGamesPreference.setStorageSize(getGamesSize(data, profileData), mTotalSize);
|
||||
mDocumentsAndOtherPreference.setStorageSize(getDocumentsAndOtherSize(data, profileData),
|
||||
mImagesPreference.setStorageSize(getImagesSize(data), mTotalSize);
|
||||
mVideosPreference.setStorageSize(getVideosSize(data), mTotalSize);
|
||||
mAudiosPreference.setStorageSize(getAudiosSize(data), mTotalSize);
|
||||
mAppsPreference.setStorageSize(getAppsSize(data), mTotalSize);
|
||||
mGamesPreference.setStorageSize(getGamesSize(data), mTotalSize);
|
||||
mDocumentsAndOtherPreference.setStorageSize(getDocumentsAndOtherSize(data),
|
||||
mTotalSize);
|
||||
mTrashPreference.setStorageSize(getTrashSize(data, profileData), mTotalSize);
|
||||
mTrashPreference.setStorageSize(getTrashSize(data), mTotalSize);
|
||||
|
||||
if (mSystemPreference != null) {
|
||||
// Everything else that hasn't already been attributed is tracked as
|
||||
// belonging to system.
|
||||
// TODO(b/170918505): Should revamp system size calculation with the data
|
||||
// from media provider.
|
||||
long attributedSize = 0;
|
||||
for (int i = 0; i < result.size(); i++) {
|
||||
final StorageAsyncLoader.AppsStorageResult otherData = result.valueAt(i);
|
||||
@@ -385,6 +386,7 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
|
||||
+ otherData.otherAppsSize;
|
||||
attributedSize += otherData.externalStats.totalBytes
|
||||
- otherData.externalStats.appBytes;
|
||||
attributedSize -= otherData.duplicateCodeSize;
|
||||
}
|
||||
|
||||
final long systemSize = Math.max(TrafficStats.GB_IN_BYTES, mUsedBytes - attributedSize);
|
||||
@@ -404,47 +406,28 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
|
||||
|
||||
private void launchPublicStorageIntent() {
|
||||
final Intent intent = mVolume.buildBrowseIntent();
|
||||
if (intent != null) {
|
||||
mContext.startActivity(intent);
|
||||
if (intent == null) {
|
||||
return;
|
||||
}
|
||||
mContext.startActivityAsUser(intent, new UserHandle(mUserId));
|
||||
}
|
||||
|
||||
private void launchActivityWithUri(Uri dataUri) {
|
||||
final Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setData(dataUri);
|
||||
mContext.startActivity(intent);
|
||||
mContext.startActivityAsUser(intent, new UserHandle(mUserId));
|
||||
}
|
||||
|
||||
private long getImagesSize(StorageAsyncLoader.AppsStorageResult data,
|
||||
StorageAsyncLoader.AppsStorageResult profileData) {
|
||||
if (profileData != null) {
|
||||
return data.photosAppsSize + data.externalStats.imageBytes
|
||||
+ data.externalStats.videoBytes
|
||||
+ profileData.photosAppsSize + profileData.externalStats.imageBytes
|
||||
+ profileData.externalStats.videoBytes;
|
||||
} else {
|
||||
return data.photosAppsSize + data.externalStats.imageBytes
|
||||
+ data.externalStats.videoBytes;
|
||||
}
|
||||
private long getImagesSize(StorageAsyncLoader.AppsStorageResult data) {
|
||||
return data.photosAppsSize + data.externalStats.imageBytes + data.externalStats.videoBytes;
|
||||
}
|
||||
|
||||
private long getVideosSize(StorageAsyncLoader.AppsStorageResult data,
|
||||
StorageAsyncLoader.AppsStorageResult profileData) {
|
||||
if (profileData != null) {
|
||||
return data.videoAppsSize + profileData.videoAppsSize;
|
||||
} else {
|
||||
return data.videoAppsSize;
|
||||
}
|
||||
private long getVideosSize(StorageAsyncLoader.AppsStorageResult data) {
|
||||
return data.videoAppsSize;
|
||||
}
|
||||
|
||||
private long getAudiosSize(StorageAsyncLoader.AppsStorageResult data,
|
||||
StorageAsyncLoader.AppsStorageResult profileData) {
|
||||
if (profileData != null) {
|
||||
return data.musicAppsSize + data.externalStats.audioBytes
|
||||
+ profileData.musicAppsSize + profileData.externalStats.audioBytes;
|
||||
} else {
|
||||
return data.musicAppsSize + data.externalStats.audioBytes;
|
||||
}
|
||||
private long getAudiosSize(StorageAsyncLoader.AppsStorageResult data) {
|
||||
return data.musicAppsSize + data.externalStats.audioBytes;
|
||||
}
|
||||
|
||||
private void launchAppsIntent() {
|
||||
@@ -463,13 +446,8 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
|
||||
Utils.launchIntent(mFragment, intent);
|
||||
}
|
||||
|
||||
private long getAppsSize(StorageAsyncLoader.AppsStorageResult data,
|
||||
StorageAsyncLoader.AppsStorageResult profileData) {
|
||||
if (profileData != null) {
|
||||
return data.otherAppsSize + profileData.otherAppsSize;
|
||||
} else {
|
||||
return data.otherAppsSize;
|
||||
}
|
||||
private long getAppsSize(StorageAsyncLoader.AppsStorageResult data) {
|
||||
return data.otherAppsSize;
|
||||
}
|
||||
|
||||
private void launchGamesIntent() {
|
||||
@@ -486,13 +464,8 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
|
||||
Utils.launchIntent(mFragment, intent);
|
||||
}
|
||||
|
||||
private long getGamesSize(StorageAsyncLoader.AppsStorageResult data,
|
||||
StorageAsyncLoader.AppsStorageResult profileData) {
|
||||
if (profileData != null) {
|
||||
return data.gamesSize + profileData.gamesSize;
|
||||
} else {
|
||||
return data.gamesSize;
|
||||
}
|
||||
private long getGamesSize(StorageAsyncLoader.AppsStorageResult data) {
|
||||
return data.gamesSize;
|
||||
}
|
||||
|
||||
private Bundle getWorkAnnotatedBundle(int additionalCapacity) {
|
||||
@@ -502,26 +475,12 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
|
||||
return args;
|
||||
}
|
||||
|
||||
private long getDocumentsAndOtherSize(StorageAsyncLoader.AppsStorageResult data,
|
||||
StorageAsyncLoader.AppsStorageResult profileData) {
|
||||
if (profileData != null) {
|
||||
return data.externalStats.totalBytes
|
||||
- data.externalStats.audioBytes
|
||||
- data.externalStats.videoBytes
|
||||
- data.externalStats.imageBytes
|
||||
- data.externalStats.appBytes
|
||||
+ profileData.externalStats.totalBytes
|
||||
- profileData.externalStats.audioBytes
|
||||
- profileData.externalStats.videoBytes
|
||||
- profileData.externalStats.imageBytes
|
||||
- profileData.externalStats.appBytes;
|
||||
} else {
|
||||
return data.externalStats.totalBytes
|
||||
- data.externalStats.audioBytes
|
||||
- data.externalStats.videoBytes
|
||||
- data.externalStats.imageBytes
|
||||
- data.externalStats.appBytes;
|
||||
}
|
||||
private long getDocumentsAndOtherSize(StorageAsyncLoader.AppsStorageResult data) {
|
||||
return data.externalStats.totalBytes
|
||||
- data.externalStats.audioBytes
|
||||
- data.externalStats.videoBytes
|
||||
- data.externalStats.imageBytes
|
||||
- data.externalStats.appBytes;
|
||||
}
|
||||
|
||||
private void launchTrashIntent() {
|
||||
@@ -530,12 +489,11 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
|
||||
if (intent.resolveActivity(mPackageManager) == null) {
|
||||
EmptyTrashFragment.show(mFragment);
|
||||
} else {
|
||||
mContext.startActivity(intent);
|
||||
mContext.startActivityAsUser(intent, new UserHandle(mUserId));
|
||||
}
|
||||
}
|
||||
|
||||
private long getTrashSize(StorageAsyncLoader.AppsStorageResult data,
|
||||
StorageAsyncLoader.AppsStorageResult profileData) {
|
||||
private long getTrashSize(StorageAsyncLoader.AppsStorageResult data) {
|
||||
// TODO(170918505): Implement it.
|
||||
return 0L;
|
||||
}
|
||||
|
||||
@@ -73,6 +73,10 @@ public class StorageSelectionPreferenceController extends BasePreferenceControll
|
||||
Collections.sort(mStorageEntries);
|
||||
mStorageEntries.addAll(storageEntries);
|
||||
mStorageAdapter.addAll(storageEntries);
|
||||
|
||||
if (mSpinnerPreference != null) {
|
||||
mSpinnerPreference.setClickable(mStorageAdapter.getCount() > 1);
|
||||
}
|
||||
}
|
||||
|
||||
/** set selected storage in the spinner. */
|
||||
@@ -93,6 +97,7 @@ public class StorageSelectionPreferenceController extends BasePreferenceControll
|
||||
mSpinnerPreference = screen.findPreference(getPreferenceKey());
|
||||
mSpinnerPreference.setAdapter(mStorageAdapter);
|
||||
mSpinnerPreference.setOnItemSelectedListener(this);
|
||||
mSpinnerPreference.setClickable(mStorageAdapter.getCount() > 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -100,7 +105,8 @@ public class StorageSelectionPreferenceController extends BasePreferenceControll
|
||||
if (mOnItemSelectedListener == null) {
|
||||
return;
|
||||
}
|
||||
mOnItemSelectedListener.onItemSelected(mStorageAdapter.getItem(position));
|
||||
mOnItemSelectedListener.onItemSelected(
|
||||
(StorageEntry) mSpinnerPreference.getSelectedItem());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,138 +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.deviceinfo.storage;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.storage.VolumeInfo;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.core.SubSettingLauncher;
|
||||
import com.android.settings.deviceinfo.StorageItemPreference;
|
||||
import com.android.settings.deviceinfo.StorageProfileFragment;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
/**
|
||||
* Defines a {@link AbstractPreferenceController} which handles a single profile of the primary
|
||||
* user.
|
||||
*/
|
||||
public class UserProfileController extends AbstractPreferenceController implements
|
||||
PreferenceControllerMixin, StorageAsyncLoader.ResultHandler,
|
||||
UserIconLoader.UserIconHandler {
|
||||
private static final String PREFERENCE_KEY_BASE = "pref_profile_";
|
||||
private StorageItemPreference mStoragePreference;
|
||||
private UserInfo mUser;
|
||||
private long mTotalSizeBytes;
|
||||
private final int mPreferenceOrder;
|
||||
|
||||
public UserProfileController(Context context, UserInfo info, int preferenceOrder) {
|
||||
super(context);
|
||||
mUser = Preconditions.checkNotNull(info);
|
||||
mPreferenceOrder = preferenceOrder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return PREFERENCE_KEY_BASE + mUser.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
mStoragePreference = new StorageItemPreference(screen.getContext());
|
||||
mStoragePreference.setOrder(mPreferenceOrder);
|
||||
mStoragePreference.setKey(PREFERENCE_KEY_BASE + mUser.id);
|
||||
mStoragePreference.setTitle(mUser.name);
|
||||
screen.addPreference(mStoragePreference);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handlePreferenceTreeClick(Preference preference) {
|
||||
if (preference != null && mStoragePreference == preference) {
|
||||
final Bundle args = new Bundle();
|
||||
args.putInt(StorageProfileFragment.USER_ID_EXTRA, mUser.id);
|
||||
args.putString(VolumeInfo.EXTRA_VOLUME_ID, VolumeInfo.ID_PRIVATE_INTERNAL);
|
||||
|
||||
new SubSettingLauncher(mContext)
|
||||
.setDestination(StorageProfileFragment.class.getName())
|
||||
.setArguments(args)
|
||||
.setTitleText(mUser.name)
|
||||
.setSourceMetricsCategory(SettingsEnums.DEVICEINFO_STORAGE)
|
||||
.launch();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleResult(SparseArray<StorageAsyncLoader.AppsStorageResult> stats) {
|
||||
Preconditions.checkNotNull(stats);
|
||||
|
||||
int userId = mUser.id;
|
||||
StorageAsyncLoader.AppsStorageResult result = stats.get(userId);
|
||||
if (result != null) {
|
||||
setSize(result.externalStats.totalBytes
|
||||
+ result.otherAppsSize
|
||||
+ result.videoAppsSize
|
||||
+ result.musicAppsSize
|
||||
+ result.gamesSize,
|
||||
mTotalSizeBytes);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the size for the preference using a byte count.
|
||||
*/
|
||||
public void setSize(long size, long totalSize) {
|
||||
if (mStoragePreference != null) {
|
||||
mStoragePreference.setStorageSize(size, totalSize);
|
||||
}
|
||||
}
|
||||
|
||||
public void setTotalSize(long totalSize) {
|
||||
mTotalSizeBytes = totalSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleUserIcons(SparseArray<Drawable> fetchedIcons) {
|
||||
Drawable userIcon = fetchedIcons.get(mUser.id);
|
||||
if (userIcon != null) {
|
||||
mStoragePreference.setIcon(applyTint(mContext, userIcon));
|
||||
}
|
||||
}
|
||||
|
||||
private static Drawable applyTint(Context context, Drawable icon) {
|
||||
icon = icon.mutate();
|
||||
icon.setTintList(Utils.getColorAttr(context, android.R.attr.colorControlNormal));
|
||||
return icon;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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.display;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.PowerManager;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settingslib.widget.BannerMessagePreference;
|
||||
|
||||
/**
|
||||
* The controller of Screen attention's battery saver warning preference.
|
||||
* The preference appears when Screen Attention feature is disabled by battery saver mode.
|
||||
*/
|
||||
public class AdaptiveSleepBatterySaverPreferenceController {
|
||||
|
||||
@VisibleForTesting
|
||||
final BannerMessagePreference mPreference;
|
||||
private final PowerManager mPowerManager;
|
||||
|
||||
public AdaptiveSleepBatterySaverPreferenceController(Context context) {
|
||||
mPreference = new BannerMessagePreference(context);
|
||||
mPreference.setTitle(R.string.ambient_camera_summary_battery_saver_on);
|
||||
mPreference.setPositiveButtonText(R.string.disable_text);
|
||||
mPowerManager = context.getSystemService(PowerManager.class);
|
||||
mPreference.setPositiveButtonOnClickListener(p -> {
|
||||
mPowerManager.setPowerSaveModeEnabled(false);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the controlled preference to the provided preference screen.
|
||||
*/
|
||||
public void addToScreen(PreferenceScreen screen) {
|
||||
screen.addPreference(mPreference);
|
||||
updateVisibility();
|
||||
}
|
||||
|
||||
/**
|
||||
* Need this because all controller tests use RoboElectric. No easy way to mock this service,
|
||||
* so we mock the call we need
|
||||
*/
|
||||
@VisibleForTesting
|
||||
boolean isPowerSaveMode() {
|
||||
return mPowerManager.isPowerSaveMode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the visibility of the preference.
|
||||
*/
|
||||
public void updateVisibility() {
|
||||
mPreference.setVisible(isPowerSaveMode());
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.hardware.SensorPrivacyManager;
|
||||
import android.os.PowerManager;
|
||||
import android.os.UserManager;
|
||||
import android.provider.Settings;
|
||||
import android.service.attention.AttentionService;
|
||||
@@ -53,6 +54,7 @@ public class AdaptiveSleepPreferenceController {
|
||||
private final PackageManager mPackageManager;
|
||||
private final Context mContext;
|
||||
private final MetricsFeatureProvider mMetricsFeatureProvider;
|
||||
private final PowerManager mPowerManager;
|
||||
|
||||
@VisibleForTesting
|
||||
RestrictedSwitchPreference mPreference;
|
||||
@@ -62,6 +64,20 @@ public class AdaptiveSleepPreferenceController {
|
||||
mRestrictionUtils = restrictionUtils;
|
||||
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
|
||||
mPrivacyManager = SensorPrivacyManager.getInstance(context);
|
||||
mPowerManager = context.getSystemService(PowerManager.class);
|
||||
mPreference = new RestrictedSwitchPreference(context);
|
||||
mPreference.setTitle(R.string.adaptive_sleep_title);
|
||||
mPreference.setSummary(R.string.adaptive_sleep_description);
|
||||
mPreference.setChecked(isChecked());
|
||||
mPreference.setKey(PREFERENCE_KEY);
|
||||
mPreference.setOnPreferenceClickListener(preference -> {
|
||||
final boolean isChecked = ((RestrictedSwitchPreference) preference).isChecked();
|
||||
mMetricsFeatureProvider.action(context, SettingsEnums.ACTION_SCREEN_ATTENTION_CHANGED,
|
||||
isChecked);
|
||||
Settings.Secure.putInt(context.getContentResolver(),
|
||||
Settings.Secure.ADAPTIVE_SLEEP, isChecked ? 1 : DEFAULT_VALUE);
|
||||
return true;
|
||||
});
|
||||
mPackageManager = context.getPackageManager();
|
||||
}
|
||||
|
||||
@@ -87,7 +103,8 @@ public class AdaptiveSleepPreferenceController {
|
||||
if (enforcedAdmin != null) {
|
||||
mPreference.setDisabledByAdmin(enforcedAdmin);
|
||||
} else {
|
||||
mPreference.setEnabled(hasSufficientPermission(mPackageManager) && !isCameraLocked());
|
||||
mPreference.setEnabled(hasSufficientPermission(mPackageManager) && !isCameraLocked()
|
||||
&& !isPowerSaveMode());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,7 +131,7 @@ public class AdaptiveSleepPreferenceController {
|
||||
@VisibleForTesting
|
||||
boolean isChecked() {
|
||||
return hasSufficientPermission(mContext.getPackageManager()) && !isCameraLocked()
|
||||
&& Settings.Secure.getInt(mContext.getContentResolver(),
|
||||
&& !isPowerSaveMode() && Settings.Secure.getInt(mContext.getContentResolver(),
|
||||
Settings.Secure.ADAPTIVE_SLEEP, DEFAULT_VALUE)
|
||||
!= DEFAULT_VALUE;
|
||||
}
|
||||
@@ -128,6 +145,11 @@ public class AdaptiveSleepPreferenceController {
|
||||
return mPrivacyManager.isSensorPrivacyEnabled(CAMERA);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
boolean isPowerSaveMode() {
|
||||
return mPowerManager.isPowerSaveMode();
|
||||
}
|
||||
|
||||
public static int isControllerAvailable(Context context) {
|
||||
return context.getResources().getBoolean(
|
||||
com.android.internal.R.bool.config_adaptive_sleep_available)
|
||||
|
||||
@@ -21,10 +21,14 @@ import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
|
||||
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.hardware.SensorPrivacyManager;
|
||||
import android.os.PowerManager;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.text.SpannableString;
|
||||
@@ -73,6 +77,12 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements
|
||||
private FooterPreference mPrivacyPreference;
|
||||
private final MetricsFeatureProvider mMetricsFeatureProvider;
|
||||
private SensorPrivacyManager mPrivacyManager;
|
||||
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
mAdaptiveSleepBatterySaverPreferenceController.updateVisibility();
|
||||
}
|
||||
};
|
||||
|
||||
@VisibleForTesting
|
||||
Context mContext;
|
||||
@@ -92,6 +102,9 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements
|
||||
@VisibleForTesting
|
||||
AdaptiveSleepPreferenceController mAdaptiveSleepController;
|
||||
|
||||
@VisibleForTesting
|
||||
AdaptiveSleepBatterySaverPreferenceController mAdaptiveSleepBatterySaverPreferenceController;
|
||||
|
||||
public ScreenTimeoutSettings() {
|
||||
super();
|
||||
mMetricsFeatureProvider = FeatureFactory.getFactory(getContext())
|
||||
@@ -109,6 +122,13 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements
|
||||
context);
|
||||
mAdaptiveSleepCameraStatePreferenceController =
|
||||
new AdaptiveSleepCameraStatePreferenceController(context);
|
||||
mAdaptiveSleepBatterySaverPreferenceController =
|
||||
new AdaptiveSleepBatterySaverPreferenceController(context);
|
||||
mPrivacyPreference = new FooterPreference(context);
|
||||
mPrivacyPreference.setIcon(R.drawable.ic_privacy_shield_24dp);
|
||||
mPrivacyPreference.setTitle(R.string.adaptive_sleep_privacy);
|
||||
mPrivacyPreference.setSelectable(false);
|
||||
mPrivacyPreference.setLayoutResource(R.layout.preference_footer);
|
||||
mPrivacyManager = SensorPrivacyManager.getInstance(context);
|
||||
mPrivacyManager.addSensorPrivacyListener(CAMERA,
|
||||
(sensor, enabled) -> mAdaptiveSleepController.updatePreference());
|
||||
@@ -136,7 +156,16 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements
|
||||
super.onStart();
|
||||
mAdaptiveSleepPermissionController.updateVisibility();
|
||||
mAdaptiveSleepCameraStatePreferenceController.updateVisibility();
|
||||
mAdaptiveSleepBatterySaverPreferenceController.updateVisibility();
|
||||
mAdaptiveSleepController.updatePreference();
|
||||
mContext.registerReceiver(mReceiver,
|
||||
new IntentFilter(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
mContext.unregisterReceiver(mReceiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -176,6 +205,7 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements
|
||||
if (isScreenAttentionAvailable(getContext())) {
|
||||
mAdaptiveSleepPermissionController.addToScreen(screen);
|
||||
mAdaptiveSleepCameraStatePreferenceController.addToScreen(screen);
|
||||
mAdaptiveSleepBatterySaverPreferenceController.addToScreen(screen);
|
||||
mAdaptiveSleepController.addToScreen(screen);
|
||||
screen.addPreference(mPrivacyPreference);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.display;
|
||||
|
||||
import static com.android.settings.display.SmartAutoRotateController.isRotationResolverServiceAvailable;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.PowerManager;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.lifecycle.LifecycleObserver;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settingslib.core.lifecycle.events.OnStart;
|
||||
import com.android.settingslib.core.lifecycle.events.OnStop;
|
||||
import com.android.settingslib.widget.BannerMessagePreference;
|
||||
|
||||
/**
|
||||
* The controller of camera based rotate battery saver warning preference. The preference appears
|
||||
* when battery saver mode is enabled.
|
||||
*/
|
||||
public class SmartAutoRotateBatterySaverController extends BasePreferenceController implements
|
||||
LifecycleObserver, OnStart, OnStop {
|
||||
|
||||
private Preference mPreference;
|
||||
private final PowerManager mPowerManager;
|
||||
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (mPreference == null) {
|
||||
return;
|
||||
}
|
||||
mPreference.setVisible(isPowerSaveMode());
|
||||
updateState(mPreference);
|
||||
}
|
||||
};
|
||||
|
||||
public SmartAutoRotateBatterySaverController(Context context, String key) {
|
||||
super(context, key);
|
||||
mPowerManager = context.getSystemService(PowerManager.class);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
boolean isPowerSaveMode() {
|
||||
return mPowerManager.isPowerSaveMode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
mPreference = screen.findPreference(getPreferenceKey());
|
||||
((BannerMessagePreference) mPreference)
|
||||
.setPositiveButtonText(R.string.disable_text)
|
||||
.setPositiveButtonOnClickListener(v -> {
|
||||
mPowerManager.setPowerSaveModeEnabled(false);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
mContext.registerReceiver(mReceiver,
|
||||
new IntentFilter(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
mContext.unregisterReceiver(mReceiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
@AvailabilityStatus
|
||||
public int getAvailabilityStatus() {
|
||||
return isRotationResolverServiceAvailable(mContext)
|
||||
&& isPowerSaveMode() ? AVAILABLE_UNSEARCHABLE : UNSUPPORTED_ON_DEVICE;
|
||||
}
|
||||
}
|
||||
@@ -20,15 +20,19 @@ import static android.provider.Settings.Secure.CAMERA_AUTOROTATE;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.hardware.SensorPrivacyManager;
|
||||
import android.os.PowerManager;
|
||||
import android.provider.Settings;
|
||||
import android.service.rotationresolver.RotationResolverService;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.lifecycle.LifecycleObserver;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
@@ -37,15 +41,24 @@ import com.android.internal.view.RotationPolicy;
|
||||
import com.android.settings.core.TogglePreferenceController;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settingslib.core.lifecycle.events.OnStart;
|
||||
import com.android.settingslib.core.lifecycle.events.OnStop;
|
||||
|
||||
/**
|
||||
* SmartAutoRotateController controls whether auto rotation is enabled
|
||||
*/
|
||||
public class SmartAutoRotateController extends TogglePreferenceController implements
|
||||
Preference.OnPreferenceChangeListener {
|
||||
Preference.OnPreferenceChangeListener, LifecycleObserver, OnStart, OnStop {
|
||||
|
||||
private final MetricsFeatureProvider mMetricsFeatureProvider;
|
||||
private final SensorPrivacyManager mPrivacyManager;
|
||||
private final PowerManager mPowerManager;
|
||||
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
updateState(mPreference);
|
||||
}
|
||||
};
|
||||
private Preference mPreference;
|
||||
|
||||
public SmartAutoRotateController(Context context, String preferenceKey) {
|
||||
@@ -54,6 +67,7 @@ public class SmartAutoRotateController extends TogglePreferenceController implem
|
||||
mPrivacyManager = SensorPrivacyManager.getInstance(context);
|
||||
mPrivacyManager
|
||||
.addSensorPrivacyListener(CAMERA, (sensor, enabled) -> updateState(mPreference));
|
||||
mPowerManager = context.getSystemService(PowerManager.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -62,7 +76,7 @@ public class SmartAutoRotateController extends TogglePreferenceController implem
|
||||
return UNSUPPORTED_ON_DEVICE;
|
||||
}
|
||||
return !RotationPolicy.isRotationLocked(mContext) && hasSufficientPermission(mContext)
|
||||
&& !isCameraLocked() ? AVAILABLE : DISABLED_DEPENDENT_SETTING;
|
||||
&& !isCameraLocked() && !isPowerSaveMode() ? AVAILABLE : DISABLED_DEPENDENT_SETTING;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -82,11 +96,27 @@ public class SmartAutoRotateController extends TogglePreferenceController implem
|
||||
return mPrivacyManager.isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
boolean isPowerSaveMode() {
|
||||
return mPowerManager.isPowerSaveMode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
mContext.registerReceiver(mReceiver,
|
||||
new IntentFilter(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
mContext.unregisterReceiver(mReceiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChecked() {
|
||||
return hasSufficientPermission(mContext) && !isCameraLocked() && Settings.Secure.getInt(
|
||||
mContext.getContentResolver(),
|
||||
CAMERA_AUTOROTATE, 0) == 1;
|
||||
return hasSufficientPermission(mContext) && !isCameraLocked() && !isPowerSaveMode()
|
||||
&& Settings.Secure.getInt(mContext.getContentResolver(),
|
||||
CAMERA_AUTOROTATE, 0) == 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -21,6 +21,7 @@ import static com.android.settings.display.SmartAutoRotateController.isRotationR
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.hardware.SensorPrivacyManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.PowerManager;
|
||||
import android.text.Html;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
@@ -50,6 +51,7 @@ public class SmartAutoRotatePreferenceFragment extends DashboardFragment {
|
||||
private RotationPolicy.RotationPolicyListener mRotationPolicyListener;
|
||||
private SensorPrivacyManager mPrivacyManager;
|
||||
private AutoRotateSwitchBarController mSwitchBarController;
|
||||
private PowerManager mPowerManager;
|
||||
private static final String FACE_SWITCH_PREFERENCE_ID = "face_based_rotate";
|
||||
|
||||
@Override
|
||||
@@ -69,6 +71,7 @@ public class SmartAutoRotatePreferenceFragment extends DashboardFragment {
|
||||
mSwitchBarController = new AutoRotateSwitchBarController(activity, switchBar,
|
||||
getSettingsLifecycle());
|
||||
mPrivacyManager = SensorPrivacyManager.getInstance(activity);
|
||||
mPowerManager = getSystemService(PowerManager.class);
|
||||
final Preference footerPreference = findPreference(FooterPreference.KEY_FOOTER);
|
||||
if (footerPreference != null) {
|
||||
footerPreference.setTitle(Html.fromHtml(getString(R.string.smart_rotate_text_headline),
|
||||
@@ -89,9 +92,10 @@ public class SmartAutoRotatePreferenceFragment extends DashboardFragment {
|
||||
final boolean isLocked = RotationPolicy.isRotationLocked(getContext());
|
||||
final boolean isCameraLocked = mPrivacyManager.isSensorPrivacyEnabled(
|
||||
SensorPrivacyManager.Sensors.CAMERA);
|
||||
final boolean isBatterySaver = mPowerManager.isPowerSaveMode();
|
||||
final Preference preference = findPreference(FACE_SWITCH_PREFERENCE_ID);
|
||||
if (preference != null && hasSufficientPermission(getContext())) {
|
||||
preference.setEnabled(!isLocked && !isCameraLocked);
|
||||
preference.setEnabled(!isLocked && !isCameraLocked && !isBatterySaver);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -17,7 +17,9 @@
|
||||
package com.android.settings.fuelgauge;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.text.TextUtils;
|
||||
@@ -36,8 +38,10 @@ import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnCreate;
|
||||
import com.android.settingslib.core.lifecycle.events.OnDestroy;
|
||||
import com.android.settingslib.core.lifecycle.events.OnPause;
|
||||
import com.android.settingslib.core.lifecycle.events.OnResume;
|
||||
import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState;
|
||||
import com.android.settingslib.utils.StringUtil;
|
||||
|
||||
import java.time.Clock;
|
||||
@@ -50,8 +54,9 @@ import java.util.Map;
|
||||
|
||||
/** Controls the update for chart graph and the list items. */
|
||||
public class BatteryChartPreferenceController extends AbstractPreferenceController
|
||||
implements PreferenceControllerMixin, LifecycleObserver, OnPause, OnDestroy,
|
||||
BatteryChartView.OnSelectListener, ExpandDividerPreference.OnExpandListener {
|
||||
implements PreferenceControllerMixin, LifecycleObserver, OnCreate, OnDestroy,
|
||||
OnSaveInstanceState, BatteryChartView.OnSelectListener, OnResume,
|
||||
ExpandDividerPreference.OnExpandListener {
|
||||
private static final String TAG = "BatteryChartPreferenceController";
|
||||
/** Desired battery history size for timestamp slots. */
|
||||
public static final int DESIRED_HISTORY_SIZE = 25;
|
||||
@@ -60,6 +65,12 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
|
||||
private static final long VALID_USAGE_TIME_DURATION = DateUtils.HOUR_IN_MILLIS * 2;
|
||||
private static final long VALID_DIFF_DURATION = DateUtils.MINUTE_IN_MILLIS * 3;
|
||||
|
||||
// Keys for bundle instance to restore configurations.
|
||||
private static final String KEY_EXPAND_SYSTEM_INFO = "expand_system_info";
|
||||
private static final String KEY_CURRENT_TIME_SLOT = "current_time_slot";
|
||||
|
||||
private static int sUiMode = Configuration.UI_MODE_NIGHT_UNDEFINED;
|
||||
|
||||
@VisibleForTesting
|
||||
Map<Integer, List<BatteryDiffEntry>> mBatteryIndexedMap;
|
||||
|
||||
@@ -69,6 +80,7 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
|
||||
@VisibleForTesting BatteryChartView mBatteryChartView;
|
||||
@VisibleForTesting ExpandDividerPreference mExpandDividerPreference;
|
||||
|
||||
@VisibleForTesting boolean mIsExpanded = false;
|
||||
@VisibleForTesting int[] mBatteryHistoryLevels;
|
||||
@VisibleForTesting long[] mBatteryHistoryKeys;
|
||||
@VisibleForTesting int mTrapezoidIndex = BatteryChartView.SELECTED_INDEX_INVALID;
|
||||
@@ -78,8 +90,7 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
|
||||
private final InstrumentedPreferenceFragment mFragment;
|
||||
private final Handler mHandler = new Handler(Looper.getMainLooper());
|
||||
private final CharSequence[] mNotAllowShowSummaryPackages;
|
||||
|
||||
private boolean mIsExpanded = false;
|
||||
private final CharSequence[] mNotAllowShowEntryPackages;
|
||||
|
||||
// Preference cache to avoid create new instance each time.
|
||||
@VisibleForTesting
|
||||
@@ -97,13 +108,47 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
|
||||
mPreferenceKey = preferenceKey;
|
||||
mNotAllowShowSummaryPackages = context.getResources()
|
||||
.getTextArray(R.array.allowlist_hide_summary_in_battery_usage);
|
||||
mNotAllowShowEntryPackages = context.getResources()
|
||||
.getTextArray(R.array.allowlist_hide_entry_in_battery_usage);
|
||||
if (lifecycle != null) {
|
||||
lifecycle.addObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
if (savedInstanceState == null) {
|
||||
return;
|
||||
}
|
||||
mTrapezoidIndex =
|
||||
savedInstanceState.getInt(KEY_CURRENT_TIME_SLOT, mTrapezoidIndex);
|
||||
mIsExpanded =
|
||||
savedInstanceState.getBoolean(KEY_EXPAND_SYSTEM_INFO, mIsExpanded);
|
||||
Log.d(TAG, String.format("onCreate() slotIndex=%d isExpanded=%b",
|
||||
mTrapezoidIndex, mIsExpanded));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
final int currentUiMode =
|
||||
mContext.getResources().getConfiguration().uiMode
|
||||
& Configuration.UI_MODE_NIGHT_MASK;
|
||||
if (sUiMode != currentUiMode) {
|
||||
sUiMode = currentUiMode;
|
||||
BatteryDiffEntry.clearCache();
|
||||
Log.d(TAG, "clear icon and label cache since uiMode is changed");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle savedInstance) {
|
||||
if (savedInstance == null) {
|
||||
return;
|
||||
}
|
||||
savedInstance.putInt(KEY_CURRENT_TIME_SLOT, mTrapezoidIndex);
|
||||
savedInstance.putBoolean(KEY_EXPAND_SYSTEM_INFO, mIsExpanded);
|
||||
Log.d(TAG, String.format("onSaveInstanceState() slotIndex=%d isExpanded=%b",
|
||||
mTrapezoidIndex, mIsExpanded));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -154,8 +199,8 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
|
||||
isValidPackage = mBatteryUtils.getPackageUid(packageName)
|
||||
!= BatteryUtils.UID_NULL;
|
||||
}
|
||||
Log.d(TAG, String.format("handleClick() label=%s key=%s isValid:%b %s",
|
||||
diffEntry.getAppLabel(), histEntry.getKey(), isValidPackage, packageName));
|
||||
Log.d(TAG, String.format("handleClick() label=%s key=%s isValid:%b\n%s",
|
||||
diffEntry.getAppLabel(), histEntry.getKey(), isValidPackage, histEntry));
|
||||
if (isValidPackage) {
|
||||
AdvancedPowerUsageDetail.startBatteryDetailPage(
|
||||
mActivity, mFragment, diffEntry, powerPref.getPercent(),
|
||||
@@ -234,7 +279,9 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
|
||||
}
|
||||
|
||||
void setBatteryChartView(final BatteryChartView batteryChartView) {
|
||||
mHandler.post(() -> setBatteryChartViewInner(batteryChartView));
|
||||
if (mBatteryChartView != batteryChartView) {
|
||||
mHandler.post(() -> setBatteryChartViewInner(batteryChartView));
|
||||
}
|
||||
}
|
||||
|
||||
private void setBatteryChartViewInner(final BatteryChartView batteryChartView) {
|
||||
@@ -250,6 +297,7 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
|
||||
: mTrapezoidIndex;
|
||||
if (mBatteryChartView != null) {
|
||||
mBatteryChartView.setLevels(mBatteryHistoryLevels);
|
||||
mBatteryChartView.setSelectedIndex(refreshIndex);
|
||||
setTimestampLabel();
|
||||
}
|
||||
refreshUi(refreshIndex, /*isForce=*/ true);
|
||||
@@ -286,6 +334,11 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
|
||||
final List<BatteryDiffEntry> appEntries = new ArrayList<>();
|
||||
mSystemEntries.clear();
|
||||
entries.forEach(entry -> {
|
||||
final String packageName = entry.getPackageName();
|
||||
if (!isValidToShowEntry(packageName)) {
|
||||
Log.w(TAG, "ignore showing item:" + packageName);
|
||||
return;
|
||||
}
|
||||
if (entry.isSystemEntry()) {
|
||||
mSystemEntries.add(entry);
|
||||
} else {
|
||||
@@ -310,6 +363,7 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
|
||||
if (mExpandDividerPreference == null) {
|
||||
mExpandDividerPreference = new ExpandDividerPreference(mPrefContext);
|
||||
mExpandDividerPreference.setOnExpandListener(this);
|
||||
mExpandDividerPreference.setIsExpanded(mIsExpanded);
|
||||
}
|
||||
mExpandDividerPreference.setOrder(
|
||||
mAppListPrefGroup.getPreferenceCount());
|
||||
@@ -480,15 +534,14 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
|
||||
return mPrefContext.getString(resourceId, timeSequence);
|
||||
}
|
||||
|
||||
private boolean isValidToShowSummary(String packageName) {
|
||||
if (mNotAllowShowSummaryPackages != null) {
|
||||
for (CharSequence notAllowPackageName : mNotAllowShowSummaryPackages) {
|
||||
if (TextUtils.equals(packageName, notAllowPackageName)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@VisibleForTesting
|
||||
boolean isValidToShowSummary(String packageName) {
|
||||
return !contains(packageName, mNotAllowShowSummaryPackages);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
boolean isValidToShowEntry(String packageName) {
|
||||
return !contains(packageName, mNotAllowShowEntryPackages);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -522,6 +575,17 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private static boolean contains(String target, CharSequence[] packageNames) {
|
||||
if (target != null && packageNames != null) {
|
||||
for (CharSequence packageName : packageNames) {
|
||||
if (TextUtils.equals(target, packageName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static boolean validateUsageTime(BatteryDiffEntry entry) {
|
||||
final long foregroundUsageTimeInMs = entry.mForegroundUsageTimeInMs;
|
||||
|
||||
@@ -111,8 +111,9 @@ public class BatteryHeaderPreferenceController extends BasePreferenceController
|
||||
private CharSequence generateLabel(BatteryInfo info) {
|
||||
if (BatteryUtils.isBatteryDefenderOn(info)) {
|
||||
return null;
|
||||
} else if (info.remainingLabel == null) {
|
||||
// Present status independently if no remaining time
|
||||
} else if (info.remainingLabel == null
|
||||
|| info.batteryStatus == BatteryManager.BATTERY_STATUS_NOT_CHARGING) {
|
||||
// Present status only if no remaining time or status anomalous
|
||||
return info.statusLabel;
|
||||
} else if (info.statusLabel != null && !info.discharging) {
|
||||
// Charging state
|
||||
|
||||
@@ -46,6 +46,7 @@ public class BatteryInfo {
|
||||
public CharSequence chargeLabel;
|
||||
public CharSequence remainingLabel;
|
||||
public int batteryLevel;
|
||||
public int batteryStatus;
|
||||
public boolean discharging = true;
|
||||
public boolean isOverheated;
|
||||
public long remainingTimeUs = 0;
|
||||
@@ -238,6 +239,8 @@ public class BatteryInfo {
|
||||
== BatteryManager.BATTERY_HEALTH_OVERHEAT;
|
||||
|
||||
info.statusLabel = Utils.getBatteryStatus(context, batteryBroadcast);
|
||||
info.batteryStatus = batteryBroadcast.getIntExtra(
|
||||
BatteryManager.EXTRA_STATUS, BatteryManager.BATTERY_STATUS_UNKNOWN);
|
||||
if (!info.mCharging) {
|
||||
updateBatteryInfoDischarging(context, shortString, estimate, info);
|
||||
} else {
|
||||
|
||||
@@ -400,7 +400,7 @@ public class BatteryUtils {
|
||||
// couldn't get estimate from cache or provider, use fallback
|
||||
if (estimate == null) {
|
||||
estimate = new Estimate(
|
||||
PowerUtil.convertUsToMs(batteryUsageStats.getBatteryTimeRemainingMs()),
|
||||
batteryUsageStats.getBatteryTimeRemainingMs(),
|
||||
false /* isBasedOnUsage */,
|
||||
EstimateKt.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN);
|
||||
}
|
||||
|
||||
@@ -370,7 +370,6 @@ public class NetworkProviderSettings extends RestrictedSettingsFragment
|
||||
}
|
||||
}
|
||||
};
|
||||
registerForContextMenu(getListView());
|
||||
setHasOptionsMenu(true);
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
|
||||
@@ -43,6 +43,7 @@ import com.android.settings.network.telephony.NetworkProviderWorker;
|
||||
import com.android.settings.slices.CustomSliceable;
|
||||
import com.android.settings.slices.SliceBackgroundWorker;
|
||||
import com.android.settings.slices.SliceBuilderUtils;
|
||||
import com.android.settings.wifi.WifiUtils;
|
||||
import com.android.settings.wifi.slice.WifiSlice;
|
||||
import com.android.settings.wifi.slice.WifiSliceItem;
|
||||
import com.android.wifitrackerlib.WifiEntry;
|
||||
@@ -255,7 +256,8 @@ public class ProviderModelSlice extends WifiSlice {
|
||||
final @ColorInt int tint = Utils.getColorAttrDefaultColor(mContext,
|
||||
android.R.attr.colorControlNormal);
|
||||
final Drawable drawable = mContext.getDrawable(
|
||||
Utils.getWifiIconResource(wifiSliceItem.getLevel()));
|
||||
WifiUtils.getInternetIconResource(
|
||||
wifiSliceItem.getLevel(), wifiSliceItem.shouldShowXLevelIcon()));
|
||||
drawable.setTint(tint);
|
||||
return Utils.createIconWithDrawable(drawable);
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ import android.os.UserManager;
|
||||
import android.service.notification.NotifyingApp;
|
||||
import android.text.TextUtils;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
import android.util.IconDrawableFactory;
|
||||
import android.util.Slog;
|
||||
|
||||
@@ -56,8 +55,6 @@ import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* This controller displays a list of recently used apps and a "See all" button. If there is
|
||||
@@ -149,9 +146,12 @@ public class RecentNotifyingAppsPreferenceController extends AbstractPreferenceC
|
||||
|
||||
@VisibleForTesting
|
||||
void refreshUi(Context prefContext) {
|
||||
((PrimarySwitchPreference) mCategory.findPreference(KEY_PLACEHOLDER + 1)).setChecked(true);
|
||||
((PrimarySwitchPreference) mCategory.findPreference(KEY_PLACEHOLDER + 2)).setChecked(true);
|
||||
((PrimarySwitchPreference) mCategory.findPreference(KEY_PLACEHOLDER + 3)).setChecked(true);
|
||||
for (int i = 1; i <= SHOW_RECENT_APP_COUNT; i++) {
|
||||
PrimarySwitchPreference app = mCategory.findPreference(KEY_PLACEHOLDER + i);
|
||||
if (app != null) {
|
||||
app.setChecked(true);
|
||||
}
|
||||
}
|
||||
ThreadUtils.postOnBackgroundThread(() -> {
|
||||
reloadData();
|
||||
final List<NotifyingApp> recentApps = getDisplayableRecentAppList();
|
||||
|
||||
@@ -24,8 +24,11 @@ import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageItemInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.util.ArraySet;
|
||||
import android.view.View;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
@@ -92,6 +95,11 @@ public class ZenAccessSettings extends EmptyTextSettings implements
|
||||
}
|
||||
|
||||
private void reloadList() {
|
||||
if (mContext.getSystemService(UserManager.class)
|
||||
.isManagedProfile(UserHandle.myUserId())) {
|
||||
Log.w(TAG, "DND access cannot be enabled in a work profile");
|
||||
return;
|
||||
}
|
||||
final PreferenceScreen screen = getPreferenceScreen();
|
||||
screen.removeAll();
|
||||
final ArrayList<ApplicationInfo> apps = new ArrayList<>();
|
||||
|
||||
@@ -322,11 +322,13 @@ public class InternetConnectivityPanel implements PanelContent, LifecycleObserve
|
||||
|
||||
final List<ScanResult> wifiList = mWifiManager.getScanResults();
|
||||
if (wifiList != null && wifiList.size() != 0) {
|
||||
if (mIsProgressBarVisible) {
|
||||
// When the Wi-Fi scan result callback is received
|
||||
// Sub-Title: Searching for networks...
|
||||
mSubtitle = SUBTITLE_TEXT_SEARCHING_FOR_NETWORKS;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (mIsProgressBarVisible) {
|
||||
// When the Wi-Fi scan result callback is received
|
||||
// Sub-Title: Searching for networks...
|
||||
mSubtitle = SUBTITLE_TEXT_SEARCHING_FOR_NETWORKS;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import android.text.TextUtils;
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.SubSettingLauncher;
|
||||
import com.android.settings.password.ChooseLockGeneric;
|
||||
@@ -36,7 +37,7 @@ public class ChangeProfileScreenLockPreferenceController extends
|
||||
private static final String KEY_UNLOCK_SET_OR_CHANGE_PROFILE = "unlock_set_or_change_profile";
|
||||
|
||||
public ChangeProfileScreenLockPreferenceController(Context context,
|
||||
SecuritySettings host) {
|
||||
SettingsPreferenceFragment host) {
|
||||
super(context, host);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,9 +29,9 @@ import com.android.settings.core.BasePreferenceController;
|
||||
public class EncryptionStatusPreferenceController extends BasePreferenceController {
|
||||
|
||||
|
||||
static final String PREF_KEY_ENCRYPTION_DETAIL_PAGE =
|
||||
public static final String PREF_KEY_ENCRYPTION_DETAIL_PAGE =
|
||||
"encryption_and_credentials_encryption_status";
|
||||
static final String PREF_KEY_ENCRYPTION_SECURITY_PAGE = "encryption_and_credential";
|
||||
public static final String PREF_KEY_ENCRYPTION_SECURITY_PAGE = "encryption_and_credential";
|
||||
|
||||
private final UserManager mUserManager;
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ import androidx.preference.PreferenceScreen;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.internal.widget.LockscreenCredential;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.core.SubSettingLauncher;
|
||||
@@ -67,7 +68,7 @@ public class LockUnificationPreferenceController extends AbstractPreferenceContr
|
||||
private final DevicePolicyManager mDpm;
|
||||
private final LockPatternUtils mLockPatternUtils;
|
||||
private final int mProfileUserId;
|
||||
private final SecuritySettings mHost;
|
||||
private final SettingsPreferenceFragment mHost;
|
||||
|
||||
private RestrictedSwitchPreference mUnifyProfile;
|
||||
|
||||
@@ -82,7 +83,7 @@ public class LockUnificationPreferenceController extends AbstractPreferenceContr
|
||||
mUnifyProfile = screen.findPreference(KEY_UNIFICATION);
|
||||
}
|
||||
|
||||
public LockUnificationPreferenceController(Context context, SecuritySettings host) {
|
||||
public LockUnificationPreferenceController(Context context, SettingsPreferenceFragment host) {
|
||||
super(context);
|
||||
mHost = host;
|
||||
mUm = context.getSystemService(UserManager.class);
|
||||
@@ -175,7 +176,10 @@ public class LockUnificationPreferenceController extends AbstractPreferenceContr
|
||||
.launch();
|
||||
}
|
||||
|
||||
void startUnification() {
|
||||
/**
|
||||
* Unify primary and profile locks.
|
||||
*/
|
||||
public void startUnification() {
|
||||
// Confirm profile lock
|
||||
final String title = mContext.getString(
|
||||
R.string.unlock_set_unlock_launch_picker_title_profile);
|
||||
|
||||
@@ -31,11 +31,11 @@ import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settings.password.ChooseLockSettingsHelper;
|
||||
import com.android.settings.security.SecurityFeatureProvider;
|
||||
import com.android.settings.security.SecuritySettings;
|
||||
import com.android.settingslib.RestrictedPreference;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
@@ -61,7 +61,7 @@ public class TrustAgentListPreferenceController extends AbstractPreferenceContro
|
||||
|
||||
private final LockPatternUtils mLockPatternUtils;
|
||||
private final TrustAgentManager mTrustAgentManager;
|
||||
private final SecuritySettings mHost;
|
||||
private final SettingsPreferenceFragment mHost;
|
||||
|
||||
private Intent mTrustAgentClickIntent;
|
||||
private PreferenceCategory mSecurityCategory;
|
||||
@@ -69,7 +69,7 @@ public class TrustAgentListPreferenceController extends AbstractPreferenceContro
|
||||
@VisibleForTesting
|
||||
final List<String> mTrustAgentsKeyList;
|
||||
|
||||
public TrustAgentListPreferenceController(Context context, SecuritySettings host,
|
||||
public TrustAgentListPreferenceController(Context context, SettingsPreferenceFragment host,
|
||||
Lifecycle lifecycle) {
|
||||
super(context);
|
||||
final SecurityFeatureProvider provider = FeatureFactory.getFactory(context)
|
||||
|
||||
@@ -829,13 +829,14 @@ public class UserSettings extends SettingsPreferenceFragment
|
||||
/**
|
||||
* Erase the current user (guest) and switch to another user.
|
||||
*/
|
||||
private void exitGuest() {
|
||||
@VisibleForTesting
|
||||
void exitGuest() {
|
||||
// Just to be safe
|
||||
mMetricsFeatureProvider.action(getActivity(),
|
||||
SettingsEnums.ACTION_USER_GUEST_EXIT_CONFIRMED);
|
||||
if (!isCurrentUserGuest()) {
|
||||
return;
|
||||
}
|
||||
mMetricsFeatureProvider.action(getActivity(),
|
||||
SettingsEnums.ACTION_USER_GUEST_EXIT_CONFIRMED);
|
||||
removeThisUser();
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,8 @@ import com.android.wifitrackerlib.WifiEntry;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class WifiUtils {
|
||||
/** A utility class for Wi-Fi functions. */
|
||||
public class WifiUtils extends com.android.settingslib.wifi.WifiUtils {
|
||||
|
||||
private static final int SSID_ASCII_MIN_LENGTH = 1;
|
||||
private static final int SSID_ASCII_MAX_LENGTH = 32;
|
||||
|
||||
@@ -49,6 +49,7 @@ import com.android.settings.slices.SliceBackgroundWorker;
|
||||
import com.android.settings.slices.SliceBuilderUtils;
|
||||
import com.android.settings.wifi.WifiDialogActivity;
|
||||
import com.android.settings.wifi.WifiSettings;
|
||||
import com.android.settings.wifi.WifiUtils;
|
||||
import com.android.settings.wifi.details2.WifiNetworkDetailsFragment2;
|
||||
import com.android.wifitrackerlib.WifiEntry;
|
||||
|
||||
@@ -176,7 +177,8 @@ public class WifiSlice implements CustomSliceable {
|
||||
}
|
||||
|
||||
final Drawable drawable = mContext.getDrawable(
|
||||
com.android.settingslib.Utils.getWifiIconResource(wifiSliceItem.getLevel()));
|
||||
WifiUtils.getInternetIconResource(wifiSliceItem.getLevel(),
|
||||
wifiSliceItem.shouldShowXLevelIcon()));
|
||||
drawable.setTint(tint);
|
||||
return Utils.createIconWithDrawable(drawable);
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ public class WifiSliceItem {
|
||||
private final int mSecurity;
|
||||
private final int mConnectedState;
|
||||
private final int mLevel;
|
||||
private final boolean mShouldShowXLevelIcon;
|
||||
private final boolean mShouldEditBeforeConnect;
|
||||
private final String mSummary;
|
||||
|
||||
@@ -53,6 +54,7 @@ public class WifiSliceItem {
|
||||
mSecurity = wifiEntry.getSecurity();
|
||||
mConnectedState = wifiEntry.getConnectedState();
|
||||
mLevel = wifiEntry.getLevel();
|
||||
mShouldShowXLevelIcon = wifiEntry.shouldShowXLevelIcon();
|
||||
mShouldEditBeforeConnect = wifiEntry.shouldEditBeforeConnect();
|
||||
mSummary = wifiEntry.getSummary(false /* concise */);
|
||||
}
|
||||
@@ -73,6 +75,9 @@ public class WifiSliceItem {
|
||||
if (getLevel() != otherItem.getLevel()) {
|
||||
return false;
|
||||
}
|
||||
if (shouldShowXLevelIcon() != otherItem.shouldShowXLevelIcon()) {
|
||||
return false;
|
||||
}
|
||||
if (!TextUtils.equals(getSummary(), otherItem.getSummary())) {
|
||||
return false;
|
||||
}
|
||||
@@ -99,6 +104,13 @@ public class WifiSliceItem {
|
||||
return mLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the level icon for this network should show an X or not.
|
||||
*/
|
||||
public boolean shouldShowXLevelIcon() {
|
||||
return mShouldShowXLevelIcon;
|
||||
}
|
||||
|
||||
/**
|
||||
* In Wi-Fi picker, when users click a saved network, it will connect to the Wi-Fi network.
|
||||
* However, for some special cases, Wi-Fi picker should show Wi-Fi editor UI for users to edit
|
||||
|
||||
@@ -36,9 +36,7 @@ com.android.settings.datausage.DataUsageList
|
||||
com.android.settings.datausage.DataUsageSummary
|
||||
com.android.settings.datetime.timezone.TimeZoneSettings
|
||||
com.android.settings.development.compat.PlatformCompatDashboard
|
||||
com.android.settings.deviceinfo.PrivateVolumeSettings
|
||||
com.android.settings.deviceinfo.PublicVolumeSettings
|
||||
com.android.settings.deviceinfo.StorageProfileFragment
|
||||
com.android.settings.deviceinfo.legal.ModuleLicensesDashboard
|
||||
com.android.settings.enterprise.ApplicationListFragment$AdminGrantedPermissionCamera
|
||||
com.android.settings.enterprise.ApplicationListFragment$AdminGrantedPermissionLocation
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.settings.accessibility;
|
||||
|
||||
import static com.android.internal.accessibility.AccessibilityShortcutController.ACCESSIBILITY_BUTTON_COMPONENT_NAME;
|
||||
import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_COMPONENT_NAME;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
@@ -85,7 +86,18 @@ public class AccessibilityDetailsSettingsFragmentTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_hasValidExtraComponentName_launchExpectedFragmentAndFinish() {
|
||||
public void onCreate_afterSuccessfullyLaunch_shouldBeFinished() {
|
||||
final Intent intent = new Intent();
|
||||
intent.putExtra(Intent.EXTRA_COMPONENT_NAME, COMPONENT_NAME);
|
||||
doReturn(intent).when(mActivity).getIntent();
|
||||
|
||||
mFragment.onCreate(Bundle.EMPTY);
|
||||
|
||||
verify(mActivity).finish();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_hasValidExtraComponentName_launchExpectedFragment() {
|
||||
final Intent intent = new Intent();
|
||||
intent.putExtra(Intent.EXTRA_COMPONENT_NAME, COMPONENT_NAME);
|
||||
doReturn(intent).when(mActivity).getIntent();
|
||||
@@ -94,11 +106,10 @@ public class AccessibilityDetailsSettingsFragmentTest {
|
||||
|
||||
assertStartActivityWithExpectedFragment(mActivity,
|
||||
ToggleAccessibilityServicePreferenceFragment.class.getName());
|
||||
verify(mActivity).finish();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_hasInvalidExtraComponentName_launchAccessibilitySettingsAndFinish() {
|
||||
public void onCreate_hasInvalidExtraComponentName_launchAccessibilitySettings() {
|
||||
final Intent intent = new Intent();
|
||||
intent.putExtra(Intent.EXTRA_COMPONENT_NAME, PACKAGE_NAME + "/.service");
|
||||
doReturn(intent).when(mActivity).getIntent();
|
||||
@@ -106,22 +117,20 @@ public class AccessibilityDetailsSettingsFragmentTest {
|
||||
mFragment.onCreate(Bundle.EMPTY);
|
||||
|
||||
assertStartActivityWithExpectedFragment(mActivity, AccessibilitySettings.class.getName());
|
||||
verify(mActivity).finish();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_hasNoExtraComponentName_launchAccessibilitySettingsAndFinish() {
|
||||
public void onCreate_hasNoExtraComponentName_launchAccessibilitySettings() {
|
||||
final Intent intent = new Intent();
|
||||
doReturn(intent).when(mActivity).getIntent();
|
||||
|
||||
mFragment.onCreate(Bundle.EMPTY);
|
||||
|
||||
assertStartActivityWithExpectedFragment(mActivity, AccessibilitySettings.class.getName());
|
||||
verify(mActivity).finish();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_extraComponentNameIsDisallowed_launchAccessibilitySettingsAndFinish() {
|
||||
public void onCreate_extraComponentNameIsDisallowed_launchAccessibilitySettings() {
|
||||
final Intent intent = new Intent();
|
||||
intent.putExtra(Intent.EXTRA_COMPONENT_NAME, COMPONENT_NAME);
|
||||
doReturn(intent).when(mActivity).getIntent();
|
||||
@@ -130,11 +139,10 @@ public class AccessibilityDetailsSettingsFragmentTest {
|
||||
mFragment.onCreate(Bundle.EMPTY);
|
||||
|
||||
assertStartActivityWithExpectedFragment(mActivity, AccessibilitySettings.class.getName());
|
||||
verify(mActivity).finish();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_magnificationComponentName_launchMagnificationFragmentAndFinish() {
|
||||
public void onCreate_magnificationComponentName_launchMagnificationFragment() {
|
||||
final Intent intent = new Intent();
|
||||
intent.putExtra(Intent.EXTRA_COMPONENT_NAME,
|
||||
MAGNIFICATION_COMPONENT_NAME.flattenToString());
|
||||
@@ -145,7 +153,19 @@ public class AccessibilityDetailsSettingsFragmentTest {
|
||||
|
||||
assertStartActivityWithExpectedFragment(mActivity,
|
||||
ToggleScreenMagnificationPreferenceFragment.class.getName());
|
||||
verify(mActivity).finish();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_accessibilityButton_launchAccessibilityButtonFragment() {
|
||||
final Intent intent = new Intent();
|
||||
intent.putExtra(Intent.EXTRA_COMPONENT_NAME,
|
||||
ACCESSIBILITY_BUTTON_COMPONENT_NAME.flattenToString());
|
||||
doReturn(intent).when(mActivity).getIntent();
|
||||
|
||||
mFragment.onCreate(Bundle.EMPTY);
|
||||
|
||||
assertStartActivityWithExpectedFragment(mActivity,
|
||||
AccessibilityButtonFragment.class.getName());
|
||||
}
|
||||
|
||||
private AccessibilityServiceInfo getMockAccessibilityServiceInfo() {
|
||||
|
||||
@@ -25,8 +25,9 @@ import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settingslib.R;
|
||||
import com.android.settings.R;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -41,6 +42,7 @@ public final class AccessibilityFooterPreferenceTest {
|
||||
private static final String DEFAULT_SUMMARY = "default summary";
|
||||
private static final String DEFAULT_DESCRIPTION = "default description";
|
||||
|
||||
private Context mContext = ApplicationProvider.getApplicationContext();
|
||||
private AccessibilityFooterPreference mAccessibilityFooterPreference;
|
||||
private PreferenceViewHolder mPreferenceViewHolder;
|
||||
|
||||
@@ -83,4 +85,14 @@ public final class AccessibilityFooterPreferenceTest {
|
||||
assertThat(infoFrame.getContentDescription()).isEqualTo(DEFAULT_DESCRIPTION);
|
||||
assertThat(infoFrame.isFocusable()).isEqualTo(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void appendHelpLink_timeoutHelpUri_updateSummary() {
|
||||
mAccessibilityFooterPreference.setSummary(DEFAULT_SUMMARY);
|
||||
|
||||
mAccessibilityFooterPreference.appendHelpLink(R.string.help_url_timeout);
|
||||
|
||||
final String title = mAccessibilityFooterPreference.getTitle().toString();
|
||||
assertThat(title.contains(mContext.getString(R.string.footer_learn_more))).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ import androidx.preference.PreferenceScreen;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.accessibility.AccessibilityEditDialogUtils.DialogType;
|
||||
import com.android.settings.accessibility.AccessibilityUtil.UserShortcutType;
|
||||
import com.android.settings.testutils.shadow.ShadowFragment;
|
||||
|
||||
@@ -145,7 +146,8 @@ public class ToggleFeaturePreferenceFragmentTest {
|
||||
public void setupEditShortcutDialog_shortcutPreferenceOff_checkboxIsEmptyValue() {
|
||||
mContext.setTheme(R.style.Theme_AppCompat);
|
||||
final AlertDialog dialog = AccessibilityEditDialogUtils.showEditShortcutDialog(
|
||||
mContext, PLACEHOLDER_DIALOG_TITLE, this::callEmptyOnClicked);
|
||||
mContext, DialogType.EDIT_SHORTCUT_GENERIC, PLACEHOLDER_DIALOG_TITLE,
|
||||
this::callEmptyOnClicked);
|
||||
final ShortcutPreference shortcutPreference = new ShortcutPreference(mContext, /* attrs= */
|
||||
null);
|
||||
mFragment.mComponentName = PLACEHOLDER_COMPONENT_NAME;
|
||||
@@ -162,7 +164,8 @@ public class ToggleFeaturePreferenceFragmentTest {
|
||||
public void setupEditShortcutDialog_shortcutPreferenceOn_checkboxIsSavedValue() {
|
||||
mContext.setTheme(R.style.Theme_AppCompat);
|
||||
final AlertDialog dialog = AccessibilityEditDialogUtils.showEditShortcutDialog(
|
||||
mContext, PLACEHOLDER_DIALOG_TITLE, this::callEmptyOnClicked);
|
||||
mContext, DialogType.EDIT_SHORTCUT_GENERIC, PLACEHOLDER_DIALOG_TITLE,
|
||||
this::callEmptyOnClicked);
|
||||
final ShortcutPreference shortcutPreference = new ShortcutPreference(mContext, /* attrs= */
|
||||
null);
|
||||
final PreferredShortcut hardwareShortcut = new PreferredShortcut(
|
||||
@@ -183,7 +186,8 @@ public class ToggleFeaturePreferenceFragmentTest {
|
||||
public void restoreValueFromSavedInstanceState_assignToVariable() {
|
||||
mContext.setTheme(R.style.Theme_AppCompat);
|
||||
final AlertDialog dialog = AccessibilityEditDialogUtils.showEditShortcutDialog(
|
||||
mContext, PLACEHOLDER_DIALOG_TITLE, this::callEmptyOnClicked);
|
||||
mContext, DialogType.EDIT_SHORTCUT_GENERIC, PLACEHOLDER_DIALOG_TITLE,
|
||||
this::callEmptyOnClicked);
|
||||
final Bundle savedInstanceState = new Bundle();
|
||||
final ShortcutPreference shortcutPreference = new ShortcutPreference(mContext, /* attrs= */
|
||||
null);
|
||||
|
||||
@@ -53,6 +53,7 @@ import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.DialogCreatable;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.accessibility.AccessibilityEditDialogUtils.DialogType;
|
||||
import com.android.settings.testutils.shadow.ShadowFragment;
|
||||
import com.android.settings.testutils.shadow.ShadowSettingsPreferenceFragment;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
@@ -208,8 +209,9 @@ public class ToggleScreenMagnificationPreferenceFragmentTest {
|
||||
@Test
|
||||
public void setupMagnificationEditShortcutDialog_shortcutPreferenceOff_checkboxIsEmptyValue() {
|
||||
mContext.setTheme(R.style.Theme_AppCompat);
|
||||
final AlertDialog dialog = AccessibilityEditDialogUtils.showMagnificationEditShortcutDialog(
|
||||
mContext, PLACEHOLDER_DIALOG_TITLE, this::callEmptyOnClicked);
|
||||
final AlertDialog dialog = AccessibilityEditDialogUtils.showEditShortcutDialog(
|
||||
mContext, DialogType.EDIT_SHORTCUT_MAGNIFICATION, PLACEHOLDER_DIALOG_TITLE,
|
||||
this::callEmptyOnClicked);
|
||||
final ShortcutPreference shortcutPreference = new ShortcutPreference(mContext, /* attrs= */
|
||||
null);
|
||||
mFragment.mShortcutPreference = shortcutPreference;
|
||||
@@ -224,8 +226,9 @@ public class ToggleScreenMagnificationPreferenceFragmentTest {
|
||||
@Test
|
||||
public void setupMagnificationEditShortcutDialog_shortcutPreferenceOn_checkboxIsSavedValue() {
|
||||
mContext.setTheme(R.style.Theme_AppCompat);
|
||||
final AlertDialog dialog = AccessibilityEditDialogUtils.showMagnificationEditShortcutDialog(
|
||||
mContext, PLACEHOLDER_DIALOG_TITLE, this::callEmptyOnClicked);
|
||||
final AlertDialog dialog = AccessibilityEditDialogUtils.showEditShortcutDialog(
|
||||
mContext, DialogType.EDIT_SHORTCUT_MAGNIFICATION, PLACEHOLDER_DIALOG_TITLE,
|
||||
this::callEmptyOnClicked);
|
||||
final ShortcutPreference shortcutPreference = new ShortcutPreference(mContext, /* attrs= */
|
||||
null);
|
||||
final PreferredShortcut tripletapShortcut = new PreferredShortcut(
|
||||
@@ -244,8 +247,9 @@ public class ToggleScreenMagnificationPreferenceFragmentTest {
|
||||
@Config(shadows = ShadowFragment.class)
|
||||
public void restoreValueFromSavedInstanceState_assignToVariable() {
|
||||
mContext.setTheme(R.style.Theme_AppCompat);
|
||||
final AlertDialog dialog = AccessibilityEditDialogUtils.showMagnificationEditShortcutDialog(
|
||||
mContext, PLACEHOLDER_DIALOG_TITLE, this::callEmptyOnClicked);
|
||||
final AlertDialog dialog = AccessibilityEditDialogUtils.showEditShortcutDialog(
|
||||
mContext, DialogType.EDIT_SHORTCUT_MAGNIFICATION, PLACEHOLDER_DIALOG_TITLE,
|
||||
this::callEmptyOnClicked);
|
||||
final Bundle savedInstanceState = new Bundle();
|
||||
mFragment.mShortcutPreference = new ShortcutPreference(mContext, /* attrs= */ null);
|
||||
|
||||
|
||||
@@ -1,72 +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.deviceinfo;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.util.SparseArray;
|
||||
|
||||
import com.android.settings.deviceinfo.storage.StorageAsyncLoader;
|
||||
import com.android.settings.deviceinfo.storage.StorageItemPreferenceController;
|
||||
import com.android.settingslib.applications.StorageStatsSource;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class StorageProfileFragmentTest {
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<SparseArray<StorageAsyncLoader.AppsStorageResult>> mCaptor;
|
||||
|
||||
@Test
|
||||
public void verifyAppSizesAreNotZeroedOut() {
|
||||
StorageItemPreferenceController controller = mock(StorageItemPreferenceController.class);
|
||||
StorageProfileFragment fragment = new StorageProfileFragment();
|
||||
StorageAsyncLoader.AppsStorageResult result = new StorageAsyncLoader.AppsStorageResult();
|
||||
result.musicAppsSize = 100;
|
||||
result.otherAppsSize = 200;
|
||||
result.gamesSize = 300;
|
||||
result.videoAppsSize = 400;
|
||||
result.externalStats = new StorageStatsSource.ExternalStorageStats(6, 1, 2, 3, 0);
|
||||
SparseArray<StorageAsyncLoader.AppsStorageResult> resultsArray = new SparseArray<>();
|
||||
resultsArray.put(0, result);
|
||||
fragment.setPreferenceController(controller);
|
||||
|
||||
fragment.onLoadFinished(null, resultsArray);
|
||||
|
||||
MockitoAnnotations.initMocks(this);
|
||||
verify(controller).onLoadFinished(mCaptor.capture(), anyInt());
|
||||
|
||||
StorageAsyncLoader.AppsStorageResult extractedResult = mCaptor.getValue().get(0);
|
||||
assertThat(extractedResult.musicAppsSize).isEqualTo(100);
|
||||
assertThat(extractedResult.videoAppsSize).isEqualTo(400);
|
||||
assertThat(extractedResult.otherAppsSize).isEqualTo(200);
|
||||
assertThat(extractedResult.gamesSize).isEqualTo(300);
|
||||
assertThat(extractedResult.externalStats.audioBytes).isEqualTo(1);
|
||||
assertThat(extractedResult.externalStats.videoBytes).isEqualTo(2);
|
||||
assertThat(extractedResult.externalStats.imageBytes).isEqualTo(3);
|
||||
assertThat(extractedResult.externalStats.totalBytes).isEqualTo(6);
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@@ -112,7 +113,8 @@ public class SecondaryUserControllerTest {
|
||||
when(mUserManager.getPrimaryUser()).thenReturn(mPrimaryUser);
|
||||
when(mUserManager.getUsers()).thenReturn(userInfos);
|
||||
final List<AbstractPreferenceController> controllers =
|
||||
SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager);
|
||||
SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager,
|
||||
false /* isWorkProfileOnly */);
|
||||
|
||||
assertThat(controllers).hasSize(1);
|
||||
// We should have the NoSecondaryUserController.
|
||||
@@ -122,15 +124,17 @@ public class SecondaryUserControllerTest {
|
||||
@Test
|
||||
public void getSecondaryUserControllers_notWorkProfile_addSecondaryUserController() {
|
||||
final ArrayList<UserInfo> userInfos = new ArrayList<>();
|
||||
final UserInfo secondaryUser = new UserInfo();
|
||||
final UserInfo secondaryUser = spy(new UserInfo());
|
||||
secondaryUser.id = 10;
|
||||
secondaryUser.profileGroupId = 101010; // this just has to be something not 0
|
||||
when(secondaryUser.isManagedProfile()).thenReturn(false);
|
||||
userInfos.add(mPrimaryUser);
|
||||
userInfos.add(secondaryUser);
|
||||
when(mUserManager.getPrimaryUser()).thenReturn(mPrimaryUser);
|
||||
when(mUserManager.getUsers()).thenReturn(userInfos);
|
||||
final List<AbstractPreferenceController> controllers =
|
||||
SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager);
|
||||
SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager,
|
||||
false /* isWorkProfileOnly */);
|
||||
|
||||
assertThat(controllers).hasSize(1);
|
||||
assertThat(controllers.get(0) instanceof SecondaryUserController).isTrue();
|
||||
@@ -139,20 +143,41 @@ public class SecondaryUserControllerTest {
|
||||
@Test
|
||||
public void getSecondaryUserControllers_workProfile_addNoSecondaryUserController() {
|
||||
final ArrayList<UserInfo> userInfos = new ArrayList<>();
|
||||
final UserInfo secondaryUser = new UserInfo();
|
||||
final UserInfo secondaryUser = spy(new UserInfo());
|
||||
secondaryUser.id = 10;
|
||||
secondaryUser.profileGroupId = 101010; // this just has to be something not 0
|
||||
when(secondaryUser.isManagedProfile()).thenReturn(true);
|
||||
userInfos.add(mPrimaryUser);
|
||||
userInfos.add(secondaryUser);
|
||||
when(mUserManager.getPrimaryUser()).thenReturn(mPrimaryUser);
|
||||
when(mUserManager.getUsers()).thenReturn(userInfos);
|
||||
final List<AbstractPreferenceController> controllers =
|
||||
SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager);
|
||||
SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager,
|
||||
false /* isWorkProfileOnly */);
|
||||
|
||||
assertThat(controllers).hasSize(1);
|
||||
assertThat(controllers.get(0) instanceof SecondaryUserController).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSecondaryUserControllers_notWorkProfileWorkProfileOnly_addNoSecondController() {
|
||||
final ArrayList<UserInfo> userInfos = new ArrayList<>();
|
||||
final UserInfo secondaryUser = spy(new UserInfo());
|
||||
secondaryUser.id = 10;
|
||||
secondaryUser.profileGroupId = 101010; // this just has to be something not 0
|
||||
when(secondaryUser.isManagedProfile()).thenReturn(false);
|
||||
userInfos.add(mPrimaryUser);
|
||||
userInfos.add(secondaryUser);
|
||||
when(mUserManager.getPrimaryUser()).thenReturn(mPrimaryUser);
|
||||
when(mUserManager.getUsers()).thenReturn(userInfos);
|
||||
final List<AbstractPreferenceController> controllers =
|
||||
SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager,
|
||||
true /* isWorkProfileOnly */);
|
||||
|
||||
assertThat(controllers).hasSize(1);
|
||||
assertThat(controllers.get(0) instanceof SecondaryUserController).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void profilesOfPrimaryUserAreIgnored() {
|
||||
final ArrayList<UserInfo> userInfos = new ArrayList<>();
|
||||
@@ -164,7 +189,8 @@ public class SecondaryUserControllerTest {
|
||||
when(mUserManager.getUsers()).thenReturn(userInfos);
|
||||
|
||||
final List<AbstractPreferenceController> controllers =
|
||||
SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager);
|
||||
SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager,
|
||||
false /* isWorkProfileOnly */);
|
||||
|
||||
assertThat(controllers).hasSize(1);
|
||||
assertThat(controllers.get(0) instanceof SecondaryUserController).isFalse();
|
||||
@@ -206,7 +232,8 @@ public class SecondaryUserControllerTest {
|
||||
when(mUserManager.getPrimaryUser()).thenReturn(mPrimaryUser);
|
||||
when(mUserManager.getUsers()).thenReturn(userInfos);
|
||||
final List<AbstractPreferenceController> controllers =
|
||||
SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager);
|
||||
SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager,
|
||||
false /* isWorkProfileOnly */);
|
||||
|
||||
assertThat(controllers).hasSize(1);
|
||||
// We should have the NoSecondaryUserController.
|
||||
|
||||
@@ -94,7 +94,8 @@ public class StorageItemPreferenceControllerTest {
|
||||
mVolume = spy(new VolumeInfo("id", 0, null, "id"));
|
||||
// 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);
|
||||
mController = new StorageItemPreferenceController(mContext, mFragment, mVolume, mSvp,
|
||||
false /* isWorkProfile */);
|
||||
mPreference = new StorageItemPreference(mContext);
|
||||
|
||||
// Inflate the preference and the widget.
|
||||
@@ -165,7 +166,7 @@ public class StorageItemPreferenceControllerTest {
|
||||
mController.handlePreferenceTreeClick(mPreference);
|
||||
|
||||
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
|
||||
verify(mContext).startActivity(argumentCaptor.capture());
|
||||
verify(mContext).startActivityAsUser(argumentCaptor.capture(), nullable(UserHandle.class));
|
||||
|
||||
final Intent intent = argumentCaptor.getValue();
|
||||
assertThat(intent.getAction()).isEqualTo(fakeBrowseAction);
|
||||
@@ -176,11 +177,12 @@ public class StorageItemPreferenceControllerTest {
|
||||
mPreference.setKey(StorageItemPreferenceController.IMAGES_KEY);
|
||||
final Context mockContext = getMockContext();
|
||||
mController = new StorageItemPreferenceController(mockContext, mFragment, mVolume,
|
||||
mSvp);
|
||||
mSvp, false /* isWorkProfile */);
|
||||
mController.handlePreferenceTreeClick(mPreference);
|
||||
|
||||
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
|
||||
verify(mockContext).startActivity(argumentCaptor.capture());
|
||||
verify(mockContext).startActivityAsUser(argumentCaptor.capture(),
|
||||
nullable(UserHandle.class));
|
||||
|
||||
final Intent intent = argumentCaptor.getValue();
|
||||
assertThat(intent.getAction()).isEqualTo(Intent.ACTION_VIEW);
|
||||
@@ -192,11 +194,12 @@ public class StorageItemPreferenceControllerTest {
|
||||
mPreference.setKey(StorageItemPreferenceController.AUDIOS_KEY);
|
||||
final Context mockContext = getMockContext();
|
||||
mController = new StorageItemPreferenceController(mockContext, mFragment, mVolume,
|
||||
mSvp);
|
||||
mSvp, false /* isWorkProfile */);
|
||||
mController.handlePreferenceTreeClick(mPreference);
|
||||
|
||||
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
|
||||
verify(mockContext).startActivity(argumentCaptor.capture());
|
||||
verify(mockContext).startActivityAsUser(argumentCaptor.capture(),
|
||||
nullable(UserHandle.class));
|
||||
final Intent intent = argumentCaptor.getValue();
|
||||
|
||||
assertThat(intent.getAction()).isEqualTo(Intent.ACTION_VIEW);
|
||||
@@ -240,7 +243,8 @@ public class StorageItemPreferenceControllerTest {
|
||||
|
||||
@Test
|
||||
public void launchAppsIntent_forWork_settingsIntent() {
|
||||
mController = new StorageItemPreferenceController(mContext, mFragment, mVolume, mSvp, true);
|
||||
mController = new FakeStorageItemPreferenceController(mContext, mFragment, mVolume, mSvp,
|
||||
true /* isWorkProfile */);
|
||||
mPreference.setKey(StorageItemPreferenceController.APPS_KEY);
|
||||
mController.handlePreferenceTreeClick(mPreference);
|
||||
|
||||
@@ -270,11 +274,12 @@ public class StorageItemPreferenceControllerTest {
|
||||
mPreference.setKey(StorageItemPreferenceController.DOCUMENTS_AND_OTHER_KEY);
|
||||
final Context mockContext = getMockContext();
|
||||
mController = new StorageItemPreferenceController(mockContext, mFragment, mVolume,
|
||||
mSvp);
|
||||
mSvp, false /* isWorkProfile */);
|
||||
mController.handlePreferenceTreeClick(mPreference);
|
||||
|
||||
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
|
||||
verify(mockContext).startActivity(argumentCaptor.capture());
|
||||
verify(mockContext).startActivityAsUser(argumentCaptor.capture(),
|
||||
nullable(UserHandle.class));
|
||||
|
||||
Intent intent = argumentCaptor.getValue();
|
||||
assertThat(intent.getAction()).isEqualTo(Intent.ACTION_VIEW);
|
||||
@@ -304,11 +309,12 @@ public class StorageItemPreferenceControllerTest {
|
||||
mPreference.setKey(StorageItemPreferenceController.VIDEOS_KEY);
|
||||
final Context mockContext = getMockContext();
|
||||
mController = new StorageItemPreferenceController(mockContext, mFragment, mVolume,
|
||||
mSvp);
|
||||
mSvp, false /* isWorkProfile */);
|
||||
mController.handlePreferenceTreeClick(mPreference);
|
||||
|
||||
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
|
||||
verify(mockContext).startActivity(argumentCaptor.capture());
|
||||
verify(mockContext).startActivityAsUser(argumentCaptor.capture(),
|
||||
nullable(UserHandle.class));
|
||||
|
||||
Intent intent = argumentCaptor.getValue();
|
||||
assertThat(intent.getAction()).isEqualTo(Intent.ACTION_VIEW);
|
||||
@@ -468,4 +474,20 @@ public class StorageItemPreferenceControllerTest {
|
||||
when(resources.getString(anyInt())).thenReturn("");
|
||||
return context;
|
||||
}
|
||||
|
||||
private static class FakeStorageItemPreferenceController
|
||||
extends StorageItemPreferenceController {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
int getCurrentUserId() {
|
||||
return CURRENT_USER_ID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,138 +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.deviceinfo.storage;
|
||||
|
||||
import static com.android.settings.utils.FileSizeFormatter.MEGABYTE_IN_BYTES;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.SubSettings;
|
||||
import com.android.settings.deviceinfo.StorageProfileFragment;
|
||||
import com.android.settingslib.applications.StorageStatsSource;
|
||||
import com.android.settingslib.drawable.UserIconDrawable;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class UserProfileControllerTest {
|
||||
|
||||
private static final String TEST_NAME = "Fred";
|
||||
|
||||
@Mock
|
||||
private PreferenceScreen mScreen;
|
||||
|
||||
private Context mContext;
|
||||
private UserProfileController mController;
|
||||
private UserInfo mPrimaryProfile;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = spy(Robolectric.setupActivity(Activity.class));
|
||||
mPrimaryProfile = new UserInfo();
|
||||
mController = new UserProfileController(mContext, mPrimaryProfile, 0);
|
||||
when(mScreen.getContext()).thenReturn(mContext);
|
||||
mPrimaryProfile.name = TEST_NAME;
|
||||
mPrimaryProfile.id = 10;
|
||||
mController.displayPreference(mScreen);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void controllerAddsPrimaryProfilePreference() {
|
||||
final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
|
||||
verify(mScreen).addPreference(argumentCaptor.capture());
|
||||
final Preference preference = argumentCaptor.getValue();
|
||||
|
||||
assertThat(preference.getTitle()).isEqualTo(TEST_NAME);
|
||||
assertThat(preference.getKey()).isEqualTo("pref_profile_10");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tappingProfilePreferenceSendsToStorageProfileFragment() {
|
||||
|
||||
final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
|
||||
verify(mScreen).addPreference(argumentCaptor.capture());
|
||||
final Preference preference = argumentCaptor.getValue();
|
||||
assertThat(mController.handlePreferenceTreeClick(preference)).isTrue();
|
||||
final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
|
||||
verify(mContext).startActivity(intentCaptor.capture());
|
||||
|
||||
final Intent intent = intentCaptor.getValue();
|
||||
assertThat(intent.getComponent().getClassName()).isEqualTo(SubSettings.class.getName());
|
||||
assertThat(intent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
|
||||
.isEqualTo(StorageProfileFragment.class.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void acceptingResultUpdatesPreferenceSize() {
|
||||
final SparseArray<StorageAsyncLoader.AppsStorageResult> result = new SparseArray<>();
|
||||
final StorageAsyncLoader.AppsStorageResult userResult =
|
||||
new StorageAsyncLoader.AppsStorageResult();
|
||||
userResult.externalStats =
|
||||
new StorageStatsSource.ExternalStorageStats(
|
||||
99 * MEGABYTE_IN_BYTES,
|
||||
33 * MEGABYTE_IN_BYTES,
|
||||
33 * MEGABYTE_IN_BYTES,
|
||||
33 * MEGABYTE_IN_BYTES, 0);
|
||||
result.put(10, userResult);
|
||||
|
||||
mController.handleResult(result);
|
||||
final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
|
||||
verify(mScreen).addPreference(argumentCaptor.capture());
|
||||
final Preference preference = argumentCaptor.getValue();
|
||||
|
||||
assertThat(preference.getSummary()).isEqualTo("0.10 GB");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void iconCallbackChangesPreferenceIcon() {
|
||||
final SparseArray<Drawable> icons = new SparseArray<>();
|
||||
final UserIconDrawable drawable = mock(UserIconDrawable.class);
|
||||
when(drawable.mutate()).thenReturn(drawable);
|
||||
icons.put(mPrimaryProfile.id, drawable);
|
||||
|
||||
mController.handleUserIcons(icons);
|
||||
|
||||
final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
|
||||
verify(mScreen).addPreference(argumentCaptor.capture());
|
||||
final Preference preference = argumentCaptor.getValue();
|
||||
assertThat(preference.getIcon()).isEqualTo(drawable);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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.display;
|
||||
|
||||
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class AdaptiveSleepBatterySaverPreferenceControllerTest {
|
||||
private Context mContext;
|
||||
private AdaptiveSleepBatterySaverPreferenceController mController;
|
||||
|
||||
@Mock
|
||||
private PackageManager mPackageManager;
|
||||
@Mock
|
||||
private PreferenceScreen mScreen;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = spy(getApplicationContext());
|
||||
|
||||
doReturn(mPackageManager).when(mContext).getPackageManager();
|
||||
when(mPackageManager.getAttentionServicePackageName()).thenReturn("some.package");
|
||||
when(mPackageManager.checkPermission(any(), any())).thenReturn(
|
||||
PackageManager.PERMISSION_GRANTED);
|
||||
|
||||
mController = spy(new AdaptiveSleepBatterySaverPreferenceController(mContext));
|
||||
when(mController.isPowerSaveMode()).thenReturn(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addToScreen_normalCase_hidePreference() {
|
||||
mController.addToScreen(mScreen);
|
||||
|
||||
assertThat(mController.mPreference.isVisible()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addToScreen_powerSaveEnabled_showPreference() {
|
||||
when(mController.isPowerSaveMode()).thenReturn(true);
|
||||
|
||||
mController.addToScreen(mScreen);
|
||||
|
||||
assertThat(mController.mPreference.isVisible()).isTrue();
|
||||
}
|
||||
}
|
||||
@@ -83,9 +83,10 @@ public class AdaptiveSleepPreferenceControllerTest {
|
||||
when(mRestrictionUtils.checkIfRestrictionEnforced(any(),
|
||||
eq(UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT))).thenReturn(null);
|
||||
|
||||
mController = new AdaptiveSleepPreferenceController(mContext, mRestrictionUtils);
|
||||
mController = spy(new AdaptiveSleepPreferenceController(mContext, mRestrictionUtils));
|
||||
mController.initializePreference();
|
||||
when(mController.isCameraLocked()).thenReturn(false);
|
||||
when(mController.isPowerSaveMode()).thenReturn(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -174,4 +175,14 @@ public class AdaptiveSleepPreferenceControllerTest {
|
||||
|
||||
assertThat(mController.mPreference.isEnabled()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addToScreen_powerSaveEnabled_disablePreference() {
|
||||
when(mController.isPowerSaveMode()).thenReturn(true);
|
||||
|
||||
mController.addToScreen(mScreen);
|
||||
|
||||
assertThat(mController.mPreference.isEnabled()).isFalse();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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.display;
|
||||
|
||||
import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE;
|
||||
import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.ServiceInfo;
|
||||
|
||||
import com.android.settings.testutils.ResolveInfoBuilder;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class SmartAutoRotateBatterySaverControllerTest {
|
||||
|
||||
private static final String PACKAGE_NAME = "package_name";
|
||||
|
||||
private SmartAutoRotateBatterySaverController mController;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
final Context context = Mockito.spy(RuntimeEnvironment.application);
|
||||
final ContentResolver contentResolver = RuntimeEnvironment.application.getContentResolver();
|
||||
when(context.getContentResolver()).thenReturn(contentResolver);
|
||||
final PackageManager packageManager = Mockito.mock(PackageManager.class);
|
||||
when(context.getPackageManager()).thenReturn(packageManager);
|
||||
doReturn(PACKAGE_NAME).when(packageManager).getRotationResolverPackageName();
|
||||
mController = Mockito.spy(
|
||||
new SmartAutoRotateBatterySaverController(context, "smart_auto_rotate"));
|
||||
when(mController.isPowerSaveMode()).thenReturn(false);
|
||||
|
||||
final ResolveInfo resolveInfo = new ResolveInfoBuilder(PACKAGE_NAME).build();
|
||||
resolveInfo.serviceInfo = new ServiceInfo();
|
||||
when(packageManager.resolveService(any(), anyInt())).thenReturn(resolveInfo);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_returnUnsupportedOnDevice() {
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_powerSaveModeEnabled_returnAvailableUnSearchAble() {
|
||||
when(mController.isPowerSaveMode()).thenReturn(true);
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE_UNSEARCHABLE);
|
||||
}
|
||||
}
|
||||
@@ -74,8 +74,9 @@ public class SmartAutoRotateControllerTest {
|
||||
doReturn(PACKAGE_NAME).when(mPackageManager).getRotationResolverPackageName();
|
||||
doReturn(PackageManager.PERMISSION_GRANTED).when(mPackageManager).checkPermission(
|
||||
Manifest.permission.CAMERA, PACKAGE_NAME);
|
||||
mController = new SmartAutoRotateController(context, "test_key");
|
||||
mController = Mockito.spy(new SmartAutoRotateController(context, "test_key"));
|
||||
when(mController.isCameraLocked()).thenReturn(false);
|
||||
when(mController.isPowerSaveMode()).thenReturn(false);
|
||||
doReturn(mController.getPreferenceKey()).when(mPreference).getKey();
|
||||
|
||||
final ResolveInfo resolveInfo = new ResolveInfoBuilder(PACKAGE_NAME).build();
|
||||
@@ -115,6 +116,12 @@ public class SmartAutoRotateControllerTest {
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_DEPENDENT_SETTING);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_powerSaveEnabled_returnDisableDependentSetting() {
|
||||
when(mController.isPowerSaveMode()).thenReturn(true);
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_DEPENDENT_SETTING);
|
||||
}
|
||||
|
||||
private void enableAutoRotation() {
|
||||
Settings.System.putIntForUser(mContentResolver,
|
||||
Settings.System.ACCELEROMETER_ROTATION, 1, UserHandle.USER_CURRENT);
|
||||
|
||||
@@ -29,7 +29,10 @@ import static org.mockito.Mockito.when;
|
||||
import android.content.Context;
|
||||
import android.content.ContentValues;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.text.format.DateUtils;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
@@ -75,6 +78,8 @@ public final class BatteryChartPreferenceControllerTest {
|
||||
@Mock private PowerGaugePreference mPowerGaugePreference;
|
||||
@Mock private ExpandDividerPreference mExpandDividerPreference;
|
||||
@Mock private BatteryUtils mBatteryUtils;
|
||||
@Mock private Configuration mConfiguration;
|
||||
@Mock private Resources mResources;
|
||||
|
||||
private Context mContext;
|
||||
private BatteryDiffEntry mBatteryDiffEntry;
|
||||
@@ -103,6 +108,33 @@ public final class BatteryChartPreferenceControllerTest {
|
||||
createBatteryHistoryMap());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnResume_uiModeIsChanged_clearBatteryDiffEntryCache() {
|
||||
doReturn(mResources).when(mContext).getResources();
|
||||
doReturn(mConfiguration).when(mResources).getConfiguration();
|
||||
mConfiguration.uiMode = Configuration.UI_MODE_NIGHT_UNDEFINED;
|
||||
// Ensures the testing environment is correct.
|
||||
assertThat(BatteryDiffEntry.sResourceCache).hasSize(1);
|
||||
mBatteryChartPreferenceController.onResume();
|
||||
// Changes the uiMode in the configuration.
|
||||
mConfiguration.uiMode = Configuration.UI_MODE_NIGHT_YES;
|
||||
|
||||
mBatteryChartPreferenceController.onResume();
|
||||
assertThat(BatteryDiffEntry.sResourceCache).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnResume_uiModeIsNotChanged_notClearBatteryDiffEntryCache() {
|
||||
doReturn(mResources).when(mContext).getResources();
|
||||
doReturn(mConfiguration).when(mResources).getConfiguration();
|
||||
mConfiguration.uiMode = Configuration.UI_MODE_NIGHT_UNDEFINED;
|
||||
// Ensures the testing environment is correct.
|
||||
assertThat(BatteryDiffEntry.sResourceCache).hasSize(1);
|
||||
|
||||
mBatteryChartPreferenceController.onResume();
|
||||
assertThat(BatteryDiffEntry.sResourceCache).isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnDestroy_activityIsChanging_clearBatteryEntryCache() {
|
||||
doReturn(true).when(mSettingsActivity).isChangingConfigurations();
|
||||
@@ -559,6 +591,51 @@ public final class BatteryChartPreferenceControllerTest {
|
||||
.setTimestamps(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnSaveInstanceState_restoreSelectedIndexAndExpandState() {
|
||||
final int expectedIndex = 1;
|
||||
final boolean isExpanded = true;
|
||||
final Bundle bundle = new Bundle();
|
||||
mBatteryChartPreferenceController.mTrapezoidIndex = expectedIndex;
|
||||
mBatteryChartPreferenceController.mIsExpanded = isExpanded;
|
||||
mBatteryChartPreferenceController.onSaveInstanceState(bundle);
|
||||
// Replaces the original controller with other values.
|
||||
mBatteryChartPreferenceController.mTrapezoidIndex = -1;
|
||||
mBatteryChartPreferenceController.mIsExpanded = false;
|
||||
|
||||
mBatteryChartPreferenceController.onCreate(bundle);
|
||||
mBatteryChartPreferenceController.setBatteryHistoryMap(
|
||||
createBatteryHistoryMap());
|
||||
|
||||
assertThat(mBatteryChartPreferenceController.mTrapezoidIndex)
|
||||
.isEqualTo(expectedIndex);
|
||||
assertThat(mBatteryChartPreferenceController.mIsExpanded).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsValidToShowSummary_returnExpectedResult() {
|
||||
assertThat(mBatteryChartPreferenceController
|
||||
.isValidToShowSummary("com.google.android.apps.scone"))
|
||||
.isTrue();
|
||||
|
||||
// Verifies the item which is defined in the array list.
|
||||
assertThat(mBatteryChartPreferenceController
|
||||
.isValidToShowSummary("com.google.android.googlequicksearchbox"))
|
||||
.isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsValidToShowEntry_returnExpectedResult() {
|
||||
assertThat(mBatteryChartPreferenceController
|
||||
.isValidToShowEntry("com.google.android.apps.scone"))
|
||||
.isTrue();
|
||||
|
||||
// Verifies the items which are defined in the array list.
|
||||
assertThat(mBatteryChartPreferenceController
|
||||
.isValidToShowEntry("com.google.android.gms.persistent"))
|
||||
.isFalse();
|
||||
}
|
||||
|
||||
private static Map<Long, Map<String, BatteryHistEntry>> createBatteryHistoryMap() {
|
||||
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap = new HashMap<>();
|
||||
for (int index = 0; index < DESIRED_HISTORY_SIZE; index++) {
|
||||
|
||||
@@ -167,6 +167,17 @@ public class BatteryHeaderPreferenceControllerTest {
|
||||
verify(mBatteryUsageProgressBarPref).setBottomSummary(BATTERY_STATUS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updatePreference_statusAnomalous_showStatusLabel() {
|
||||
mBatteryInfo.remainingLabel = TIME_LEFT;
|
||||
mBatteryInfo.statusLabel = BATTERY_STATUS;
|
||||
mBatteryInfo.batteryStatus = BatteryManager.BATTERY_STATUS_NOT_CHARGING;
|
||||
|
||||
mController.updateHeaderPreference(mBatteryInfo);
|
||||
|
||||
verify(mBatteryUsageProgressBarPref).setBottomSummary(BATTERY_STATUS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updatePreference_charging_showFullText() {
|
||||
setChargingState(/* isDischarging */ false, /* updatedByStatusFeature */ false);
|
||||
@@ -184,7 +195,7 @@ public class BatteryHeaderPreferenceControllerTest {
|
||||
|
||||
mController.updateHeaderPreference(mBatteryInfo);
|
||||
|
||||
final String expectedResult = "Battery Saver is on • " + TIME_LEFT;
|
||||
final String expectedResult = "Battery Saver on • " + TIME_LEFT;
|
||||
verify(mBatteryUsageProgressBarPref).setBottomSummary(expectedResult);
|
||||
}
|
||||
|
||||
|
||||
@@ -220,6 +220,42 @@ public class RecentNotifyingAppsPreferenceControllerTest {
|
||||
verify(mSeeAllPref).setIcon(R.drawable.ic_chevron_right_24dp);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void display_noCrashIfLessThan3() throws Exception {
|
||||
List<Event> events = new ArrayList<>();
|
||||
Event app = new Event();
|
||||
app.mEventType = Event.NOTIFICATION_INTERRUPTION;
|
||||
app.mPackage = "a";
|
||||
app.mTimeStamp = System.currentTimeMillis();
|
||||
events.add(app);
|
||||
ApplicationsState.AppEntry app1Entry = mock(ApplicationsState.AppEntry.class);
|
||||
app1Entry.info = mApplicationInfo;
|
||||
app1Entry.label = "app 1";
|
||||
|
||||
when(mAppState.getEntry(app.getPackageName(), UserHandle.myUserId()))
|
||||
.thenReturn(app1Entry);
|
||||
when(mPackageManager.resolveActivity(any(Intent.class), anyInt())).thenReturn(
|
||||
new ResolveInfo());
|
||||
|
||||
UsageEvents usageEvents = getUsageEvents(
|
||||
new String[] {app.getPackageName()},
|
||||
events);
|
||||
when(mIUsageStatsManager.queryEventsForUser(anyLong(), anyLong(), anyInt(), anyString()))
|
||||
.thenReturn(usageEvents);
|
||||
|
||||
mAppEntry.info = mApplicationInfo;
|
||||
|
||||
mController.displayPreference(mScreen);
|
||||
|
||||
verify(mCategory).setTitle(R.string.recent_notifications);
|
||||
// Only add app1 & app2. app3 skipped because it's invalid app.
|
||||
assertThat(mApp1.getTitle()).isEqualTo(app1Entry.label);
|
||||
|
||||
verify(mCategory).removePreferenceRecursively("app2");
|
||||
|
||||
mController.refreshUi(mContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void display_showRecentsWithInstantApp() throws Exception {
|
||||
List<Event> events = new ArrayList<>();
|
||||
@@ -267,35 +303,12 @@ public class RecentNotifyingAppsPreferenceControllerTest {
|
||||
mController.displayPreference(mScreen);
|
||||
|
||||
assertThat(mApp1.getTitle()).isEqualTo(appEntry.label);
|
||||
assertThat(mApp1.getSummary()).isEqualTo("Just now");
|
||||
assertThat(mApp2.getTitle()).isEqualTo(app1Entry.label);
|
||||
|
||||
verify(mCategory).removePreferenceRecursively(mApp3.getKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void display_showRecents_formatSummary() throws Exception {
|
||||
List<Event> events = new ArrayList<>();
|
||||
Event app = new Event();
|
||||
app.mEventType = Event.NOTIFICATION_INTERRUPTION;
|
||||
app.mPackage = "pkg.class";
|
||||
app.mTimeStamp = System.currentTimeMillis();
|
||||
events.add(app);
|
||||
UsageEvents usageEvents = getUsageEvents(new String[] {"pkg.class"}, events);
|
||||
when(mIUsageStatsManager.queryEventsForUser(anyLong(), anyLong(), anyInt(), anyString()))
|
||||
.thenReturn(usageEvents);
|
||||
|
||||
when(mAppState.getEntry(app.getPackageName(), UserHandle.myUserId()))
|
||||
.thenReturn(mAppEntry);
|
||||
when(mPackageManager.resolveActivity(any(Intent.class), anyInt())).thenReturn(
|
||||
new ResolveInfo());
|
||||
|
||||
mAppEntry.info = mApplicationInfo;
|
||||
|
||||
mController.displayPreference(mScreen);
|
||||
|
||||
assertThat(mApp1.getSummary()).isEqualTo("Just now");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void reloadData() throws Exception {
|
||||
when(mUserManager.getProfileIdsWithDisabled(0)).thenReturn(new int[] {0, 10});
|
||||
|
||||
@@ -25,6 +25,7 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@@ -35,6 +36,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.robolectric.Shadows.shadowOf;
|
||||
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -56,6 +58,7 @@ import com.android.settings.testutils.shadow.ShadowDevicePolicyManager;
|
||||
import com.android.settings.testutils.shadow.ShadowUserManager;
|
||||
import com.android.settingslib.RestrictedLockUtils;
|
||||
import com.android.settingslib.RestrictedPreference;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
@@ -105,6 +108,8 @@ public class UserDetailsSettingsTest {
|
||||
private FragmentActivity mActivity;
|
||||
private Context mContext;
|
||||
private UserCapabilities mUserCapabilities;
|
||||
@Mock
|
||||
private MetricsFeatureProvider mMetricsFeatureProvider;
|
||||
private UserDetailsSettings mFragment;
|
||||
private Bundle mArguments;
|
||||
private UserInfo mUserInfo;
|
||||
@@ -128,6 +133,7 @@ public class UserDetailsSettingsTest {
|
||||
|
||||
ReflectionHelpers.setField(mFragment, "mUserManager", userManager);
|
||||
ReflectionHelpers.setField(mFragment, "mUserCaps", mUserCapabilities);
|
||||
ReflectionHelpers.setField(mFragment, "mMetricsFeatureProvider", mMetricsFeatureProvider);
|
||||
doReturn(mActivity).when(mFragment).getActivity();
|
||||
doReturn(mActivity).when(mFragment).getContext();
|
||||
|
||||
@@ -472,6 +478,23 @@ public class UserDetailsSettingsTest {
|
||||
mFragment.onPreferenceClick(mSwitchUserPref);
|
||||
|
||||
verify(mFragment).switchUser();
|
||||
verify(mMetricsFeatureProvider, never()).action(any(),
|
||||
eq(SettingsEnums.ACTION_SWITCH_TO_GUEST));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPreferenceClick_switchToGuestClicked_canSwitch_shouldSwitch() {
|
||||
setupSelectedGuest();
|
||||
mUserManager.setSwitchabilityStatus(SWITCHABILITY_STATUS_OK);
|
||||
mFragment.mSwitchUserPref = mSwitchUserPref;
|
||||
mFragment.mRemoveUserPref = mRemoveUserPref;
|
||||
mFragment.mAppAndContentAccessPref = mAppAndContentAccessPref;
|
||||
mFragment.mUserInfo = mUserInfo;
|
||||
|
||||
mFragment.onPreferenceClick(mSwitchUserPref);
|
||||
|
||||
verify(mFragment).switchUser();
|
||||
verify(mMetricsFeatureProvider).action(any(), eq(SettingsEnums.ACTION_SWITCH_TO_GUEST));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -176,6 +176,22 @@ public class UserSettingsTest {
|
||||
assertThat(UserSettings.assignDefaultPhoto(null, ACTIVE_USER_ID)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExitGuest_ShouldLogAction() {
|
||||
mUserCapabilities.mIsGuest = true;
|
||||
mFragment.exitGuest();
|
||||
verify(mMetricsFeatureProvider).action(any(),
|
||||
eq(SettingsEnums.ACTION_USER_GUEST_EXIT_CONFIRMED));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExitGuestWhenNotGuest_ShouldNotLogAction() {
|
||||
mUserCapabilities.mIsGuest = false;
|
||||
mFragment.exitGuest();
|
||||
verify(mMetricsFeatureProvider, never()).action(any(),
|
||||
eq(SettingsEnums.ACTION_USER_GUEST_EXIT_CONFIRMED));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withDisallowRemoveUser_ShouldDisableRemoveUser() {
|
||||
// TODO(b/115781615): Tidy robolectric tests
|
||||
|
||||
@@ -32,10 +32,8 @@ android_test {
|
||||
"platform-test-annotations",
|
||||
"truth-prebuilt",
|
||||
"ub-uiautomator",
|
||||
"SettingsLibSettingsSpinner",
|
||||
"SettingsLibUsageProgressBarPreference",
|
||||
"SettingsLibTwoTargetPreference",
|
||||
"SettingsLibMainSwitchPreference",
|
||||
// Don't add SettingsLib libraries here - you can use them directly as they are in the
|
||||
// instrumented Settings app.
|
||||
],
|
||||
|
||||
// Include all test java files.
|
||||
|
||||
@@ -360,7 +360,6 @@ public class InternetConnectivityPanelTest {
|
||||
|
||||
assertThat(mPanel.isProgressBarVisible()).isTrue();
|
||||
verify(mPanelContentCallback).onProgressBarVisibleChanged();
|
||||
verify(mPanelContentCallback).onHeaderChanged();
|
||||
verify(mMainThreadHandler).postDelayed(any() /* mHideProgressBarRunnable */, anyLong());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user