Snap for 10120310 from 5f40973695 to udc-qpr1-release
Change-Id: Ia120731de3dc4f6c8a68d3c05e987d82b02105bb
This commit is contained in:
@@ -1581,6 +1581,22 @@
|
|||||||
column="5"/>
|
column="5"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
|
<issue
|
||||||
|
id="HardCodedColor"
|
||||||
|
severity="Error"
|
||||||
|
message="Avoid using hardcoded color"
|
||||||
|
category="Correctness"
|
||||||
|
priority="4"
|
||||||
|
summary="Using hardcoded color"
|
||||||
|
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
|
||||||
|
errorLine1=" <color name="switch_bar_state_disabled_color">#1FE3E3E3</color>"
|
||||||
|
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||||
|
<location
|
||||||
|
file="res/values-night/colors.xml"
|
||||||
|
line="76"
|
||||||
|
column="5"/>
|
||||||
|
</issue>
|
||||||
|
|
||||||
<issue
|
<issue
|
||||||
id="HardCodedColor"
|
id="HardCodedColor"
|
||||||
severity="Error"
|
severity="Error"
|
||||||
@@ -2957,6 +2973,22 @@
|
|||||||
column="5"/>
|
column="5"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
|
<issue
|
||||||
|
id="HardCodedColor"
|
||||||
|
severity="Error"
|
||||||
|
message="Avoid using hardcoded color"
|
||||||
|
category="Correctness"
|
||||||
|
priority="4"
|
||||||
|
summary="Using hardcoded color"
|
||||||
|
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
|
||||||
|
errorLine1=" <color name="switch_bar_state_disabled_color">#1F1F1F1F</color>"
|
||||||
|
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||||
|
<location
|
||||||
|
file="res/values/colors.xml"
|
||||||
|
line="219"
|
||||||
|
column="5"/>
|
||||||
|
</issue>
|
||||||
|
|
||||||
<issue
|
<issue
|
||||||
id="HardCodedColor"
|
id="HardCodedColor"
|
||||||
severity="Error"
|
severity="Error"
|
||||||
@@ -6253,6 +6285,38 @@
|
|||||||
column="63"/>
|
column="63"/>
|
||||||
</issue>
|
</issue>
|
||||||
|
|
||||||
|
<issue
|
||||||
|
id="HardCodedColor"
|
||||||
|
severity="Error"
|
||||||
|
message="Avoid using hardcoded color"
|
||||||
|
category="Correctness"
|
||||||
|
priority="4"
|
||||||
|
summary="Using hardcoded color"
|
||||||
|
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
|
||||||
|
errorLine1=" <solid android:color="@color/switch_bar_state_disabled_color"/>"
|
||||||
|
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||||
|
<location
|
||||||
|
file="res/drawable/switch_bar_bg_disabled.xml"
|
||||||
|
line="22"
|
||||||
|
column="20"/>
|
||||||
|
</issue>
|
||||||
|
|
||||||
|
<issue
|
||||||
|
id="HardCodedColor"
|
||||||
|
severity="Error"
|
||||||
|
message="Avoid using hardcoded color"
|
||||||
|
category="Correctness"
|
||||||
|
priority="4"
|
||||||
|
summary="Using hardcoded color"
|
||||||
|
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
|
||||||
|
errorLine1=" <solid android:color="@color/switch_bar_state_disabled_color"/>"
|
||||||
|
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||||
|
<location
|
||||||
|
file="res/drawable/switch_bar_bg_disabled.xml"
|
||||||
|
line="22"
|
||||||
|
column="20"/>
|
||||||
|
</issue>
|
||||||
|
|
||||||
<issue
|
<issue
|
||||||
id="HardCodedColor"
|
id="HardCodedColor"
|
||||||
severity="Error"
|
severity="Error"
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ message BatteryOptimizeHistoricalLogEntry {
|
|||||||
APPLY = 2;
|
APPLY = 2;
|
||||||
RESET = 3;
|
RESET = 3;
|
||||||
RESTORE = 4;
|
RESTORE = 4;
|
||||||
|
BACKUP = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
optional string package_name = 1;
|
optional string package_name = 1;
|
||||||
|
|||||||
26
res/drawable/switch_bar_bg_disabled.xml
Normal file
26
res/drawable/switch_bar_bg_disabled.xml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
Copyright (C) 2023 The Android Open Source Project
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:color="?android:attr/colorControlHighlight">
|
||||||
|
<item>
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<solid android:color="@color/switch_bar_state_disabled_color"/>
|
||||||
|
<corners android:radius="@dimen/settingslib_switch_bar_radius"/>
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</ripple>
|
||||||
@@ -96,4 +96,6 @@
|
|||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<include layout="@layout/udfps_enroll_view" />
|
||||||
</com.google.android.setupdesign.GlifLayout>
|
</com.google.android.setupdesign.GlifLayout>
|
||||||
@@ -24,6 +24,7 @@
|
|||||||
android:background="@android:color/transparent">
|
android:background="@android:color/transparent">
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
|
android:id="@+id/frame"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:paddingStart="@dimen/settingslib_switchbar_padding_left"
|
android:paddingStart="@dimen/settingslib_switchbar_padding_left"
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
<com.google.android.setupdesign.GlifLayout
|
<com.google.android.setupdesign.GlifLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:id="@+id/setup_wizard_layout"
|
android:id="@+id/setup_wizard_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
@@ -41,10 +42,11 @@
|
|||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/layout_container"
|
android:id="@+id/layout_container"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="0dp"
|
||||||
android:clipChildren="false"
|
android:clipChildren="false"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:layout_gravity="center_horizontal|bottom">
|
android:layout_gravity="center_horizontal|bottom"
|
||||||
|
tools:ignore="Suspicious0dp">
|
||||||
|
|
||||||
<!-- Animation res MUST be set in code -->
|
<!-- Animation res MUST be set in code -->
|
||||||
<com.airbnb.lottie.LottieAnimationView
|
<com.airbnb.lottie.LottieAnimationView
|
||||||
@@ -59,6 +61,9 @@
|
|||||||
android:clipChildren="false"
|
android:clipChildren="false"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
app:lottie_speed=".85" />
|
app:lottie_speed=".85" />
|
||||||
|
|
||||||
|
<include layout="@layout/udfps_enroll_view" />
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
|||||||
@@ -71,5 +71,8 @@
|
|||||||
<!-- Flash notifications colors -->
|
<!-- Flash notifications colors -->
|
||||||
<!-- Screen flash notification color selected stroke in color selection dialog -->
|
<!-- Screen flash notification color selected stroke in color selection dialog -->
|
||||||
<color name="screen_flash_color_button_outer_circle_stroke_color">#FFFFFF</color>
|
<color name="screen_flash_color_button_outer_circle_stroke_color">#FFFFFF</color>
|
||||||
|
|
||||||
|
<!-- Switch bar disabled state color-->
|
||||||
|
<color name="switch_bar_state_disabled_color">#1FE3E3E3</color>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
||||||
|
|||||||
@@ -214,4 +214,7 @@
|
|||||||
<color name="screen_flash_preset_opacity_color_10">#4DFF017E</color> <!-- 30% Rose -->
|
<color name="screen_flash_preset_opacity_color_10">#4DFF017E</color> <!-- 30% Rose -->
|
||||||
<color name="screen_flash_preset_opacity_color_11">#4DFF00FE</color> <!-- 30% Magenta -->
|
<color name="screen_flash_preset_opacity_color_11">#4DFF00FE</color> <!-- 30% Magenta -->
|
||||||
<color name="screen_flash_preset_opacity_color_12">#667F00FF</color> <!-- 40% Violet -->
|
<color name="screen_flash_preset_opacity_color_12">#667F00FF</color> <!-- 40% Violet -->
|
||||||
|
|
||||||
|
<!-- Switch bar disabled state color-->
|
||||||
|
<color name="switch_bar_state_disabled_color">#1F1F1F1F</color>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -119,9 +119,9 @@
|
|||||||
<!-- Connected devices settings. Title of the dialog to hint user to pair other ear of the hearing aid device. Shows when only one of the hearing aid device set is connected. [CHAR LIMIT=25] -->
|
<!-- Connected devices settings. Title of the dialog to hint user to pair other ear of the hearing aid device. Shows when only one of the hearing aid device set is connected. [CHAR LIMIT=25] -->
|
||||||
<string name="bluetooth_pair_other_ear_dialog_title">Pair your other ear</string>
|
<string name="bluetooth_pair_other_ear_dialog_title">Pair your other ear</string>
|
||||||
<!-- Connected devices settings. Message of the dialog to hint user to pair right ear of the hearing aid device. Shows when only left side of hearing aid device set is connected. [CHAR LIMIT=NONE] -->
|
<!-- Connected devices settings. Message of the dialog to hint user to pair right ear of the hearing aid device. Shows when only left side of hearing aid device set is connected. [CHAR LIMIT=NONE] -->
|
||||||
<string name="bluetooth_pair_other_ear_dialog_left_ear_message">Your left hearing aid is connected.\n\nTo pair the right one, make sure it\u2019s turned on and ready to pair.</string>
|
<string name="bluetooth_pair_other_ear_dialog_left_ear_message">Your left hearing device is connected.\n\nTo pair the right one, make sure it\u2019s turned on and ready to pair.</string>
|
||||||
<!-- Connected devices settings. Message of the dialog to hint user to pair other ear of the hearing aid device. Shows when only right side of the hearing aid device set is connected. [CHAR LIMIT=NONE] -->
|
<!-- Connected devices settings. Message of the dialog to hint user to pair other ear of the hearing aid device. Shows when only right side of the hearing aid device set is connected. [CHAR LIMIT=NONE] -->
|
||||||
<string name="bluetooth_pair_other_ear_dialog_right_ear_message">Your right hearing aid is connected.\n\nTo pair the left one, make sure it\u2019s turned on and ready to pair.</string>
|
<string name="bluetooth_pair_other_ear_dialog_right_ear_message">Your right hearing device is connected.\n\nTo pair the left one, make sure it\u2019s turned on and ready to pair.</string>
|
||||||
<!-- Connected devices settings. Positive button of the dialog to help user to pair right ear of the hearing aid device. Dialog shows when only one of the hearing aid device set is connected. [CHAR LIMIT=20] -->
|
<!-- Connected devices settings. Positive button of the dialog to help user to pair right ear of the hearing aid device. Dialog shows when only one of the hearing aid device set is connected. [CHAR LIMIT=20] -->
|
||||||
<string name="bluetooth_pair_other_ear_dialog_right_ear_positive_button">Pair right ear</string>
|
<string name="bluetooth_pair_other_ear_dialog_right_ear_positive_button">Pair right ear</string>
|
||||||
<!-- Connected devices settings. Positive button of the dialog to help user to pair left ear of the hearing aid device. Dialog shows when only one of the hearing aid device set is connected. [CHAR LIMIT=20] -->
|
<!-- Connected devices settings. Positive button of the dialog to help user to pair left ear of the hearing aid device. Dialog shows when only one of the hearing aid device set is connected. [CHAR LIMIT=20] -->
|
||||||
@@ -1182,20 +1182,20 @@
|
|||||||
<string name="current_screen_lock">Current screen lock</string>
|
<string name="current_screen_lock">Current screen lock</string>
|
||||||
|
|
||||||
<!-- Title for preference that guides the user through creating a backup unlock pattern for fingerprint [CHAR LIMIT=45]-->
|
<!-- Title for preference that guides the user through creating a backup unlock pattern for fingerprint [CHAR LIMIT=45]-->
|
||||||
<string name="fingerprint_unlock_set_unlock_pattern">Fingerprint + Pattern</string>
|
<string name="fingerprint_unlock_set_unlock_pattern">Pattern \u2022 Fingerprint</string>
|
||||||
<!-- Title for preference that guides the user through creating a backup unlock PIN for fingerprint [CHAR LIMIT=45]-->
|
<!-- Title for preference that guides the user through creating a backup unlock PIN for fingerprint [CHAR LIMIT=45]-->
|
||||||
<string name="fingerprint_unlock_set_unlock_pin">Fingerprint + PIN</string>
|
<string name="fingerprint_unlock_set_unlock_pin">PIN \u2022 Fingerprint</string>
|
||||||
<!-- Title for preference that guides the user through creating a backup unlock password for fingerprint [CHAR LIMIT=45]-->
|
<!-- Title for preference that guides the user through creating a backup unlock password for fingerprint [CHAR LIMIT=45]-->
|
||||||
<string name="fingerprint_unlock_set_unlock_password">Fingerprint + Password</string>
|
<string name="fingerprint_unlock_set_unlock_password">Password \u2022 Fingerprint</string>
|
||||||
<!-- Title for preference that guides the user to skip fingerprint setup [CHAR LIMIT=60]-->
|
<!-- Title for preference that guides the user to skip fingerprint setup [CHAR LIMIT=60]-->
|
||||||
<string name="fingerprint_unlock_skip_fingerprint">Continue without fingerprint</string>
|
<string name="fingerprint_unlock_skip_fingerprint">Continue without fingerprint</string>
|
||||||
|
|
||||||
<!-- Title for preference that guides the user through creating a backup unlock pattern for Face Unlock [CHAR LIMIT=45]-->
|
<!-- Title for preference that guides the user through creating a backup unlock pattern for Face Unlock [CHAR LIMIT=45]-->
|
||||||
<string name="face_unlock_set_unlock_pattern">Face Unlock + Pattern</string>
|
<string name="face_unlock_set_unlock_pattern">Pattern \u2022 Face</string>
|
||||||
<!-- Title for preference that guides the user through creating a backup unlock PIN for Face Unlock [CHAR LIMIT=45]-->
|
<!-- Title for preference that guides the user through creating a backup unlock PIN for Face Unlock [CHAR LIMIT=45]-->
|
||||||
<string name="face_unlock_set_unlock_pin">Face Unlock + PIN</string>
|
<string name="face_unlock_set_unlock_pin">PIN \u2022 Face</string>
|
||||||
<!-- Title for preference that guides the user through creating a backup unlock password for Face Unlock [CHAR LIMIT=45]-->
|
<!-- Title for preference that guides the user through creating a backup unlock password for Face Unlock [CHAR LIMIT=45]-->
|
||||||
<string name="face_unlock_set_unlock_password">Face Unlock + Password</string>
|
<string name="face_unlock_set_unlock_password">Password \u2022 Face</string>
|
||||||
<!-- Title for preference that guides the user to skip Face Unlock setup [CHAR LIMIT=60]-->
|
<!-- Title for preference that guides the user to skip Face Unlock setup [CHAR LIMIT=60]-->
|
||||||
<string name="face_unlock_skip_face">Continue without Face Unlock</string>
|
<string name="face_unlock_skip_face">Continue without Face Unlock</string>
|
||||||
|
|
||||||
@@ -1505,6 +1505,8 @@
|
|||||||
<string name="bluetooth_companion_app_remove_association_dialog_title">Disconnect App?</string>
|
<string name="bluetooth_companion_app_remove_association_dialog_title">Disconnect App?</string>
|
||||||
<!-- Bluetooth device details companion apps. The body of confirmation dialog for remove association. [CHAR LIMIT=60] -->
|
<!-- Bluetooth device details companion apps. The body of confirmation dialog for remove association. [CHAR LIMIT=60] -->
|
||||||
<string name="bluetooth_companion_app_body"><xliff:g id="app_name" example="App Name">%1$s</xliff:g> app will no longer connect to your <xliff:g id="device_name" example="Device Name">%2$s</xliff:g></string>
|
<string name="bluetooth_companion_app_body"><xliff:g id="app_name" example="App Name">%1$s</xliff:g> app will no longer connect to your <xliff:g id="device_name" example="Device Name">%2$s</xliff:g></string>
|
||||||
|
<!-- Summary of Bluetooth LE Audio toggle in Device Details. [CHAR LIMIT=40] -->
|
||||||
|
<string name="device_details_leaudio_toggle_summary">Experimental. Improves audio quality.</string>
|
||||||
|
|
||||||
<!-- Bluetooth device details. In the confirmation dialog for unpairing a paired device, this is the label on the button that will complete the unpairing action. -->
|
<!-- Bluetooth device details. In the confirmation dialog for unpairing a paired device, this is the label on the button that will complete the unpairing action. -->
|
||||||
<string name="bluetooth_unpair_dialog_forget_confirm_button">Forget device</string>
|
<string name="bluetooth_unpair_dialog_forget_confirm_button">Forget device</string>
|
||||||
@@ -4670,7 +4672,7 @@
|
|||||||
<!-- Introduction for the Hearing devices page to introduce feature. [CHAR LIMIT=NONE] -->
|
<!-- Introduction for the Hearing devices page to introduce feature. [CHAR LIMIT=NONE] -->
|
||||||
<string name="accessibility_hearingaid_intro">You can use hearing aids, cochlear implants, and other amplification devices with your phone</string>
|
<string name="accessibility_hearingaid_intro">You can use hearing aids, cochlear implants, and other amplification devices with your phone</string>
|
||||||
<!-- Summary for the accessibility preference for hearing aid when not connected. [CHAR LIMIT=50] -->
|
<!-- Summary for the accessibility preference for hearing aid when not connected. [CHAR LIMIT=50] -->
|
||||||
<string name="accessibility_hearingaid_not_connected_summary">No hearing aids connected</string>
|
<string name="accessibility_hearingaid_not_connected_summary">No hearing devices connected</string>
|
||||||
<!-- Summary for the accessibility preference for hearing aid when adding new devices. [CHAR LIMIT=50] -->
|
<!-- Summary for the accessibility preference for hearing aid when adding new devices. [CHAR LIMIT=50] -->
|
||||||
<string name="accessibility_hearingaid_adding_summary">Add hearing aids</string>
|
<string name="accessibility_hearingaid_adding_summary">Add hearing aids</string>
|
||||||
<!-- Title of the pair instruction dialog. Dialog shows to ask the user to make sure that their hearing aid devices are in pairing mode. [CHAR LIMIT=25] -->
|
<!-- Title of the pair instruction dialog. Dialog shows to ask the user to make sure that their hearing aid devices are in pairing mode. [CHAR LIMIT=25] -->
|
||||||
@@ -10306,7 +10308,16 @@
|
|||||||
<string name="credman_confirmation_message_title">Turn off %1$s\?</string>
|
<string name="credman_confirmation_message_title">Turn off %1$s\?</string>
|
||||||
|
|
||||||
<!-- Message of the warning dialog for disabling the credential provider. [CHAR_LIMIT=NONE] -->
|
<!-- Message of the warning dialog for disabling the credential provider. [CHAR_LIMIT=NONE] -->
|
||||||
<string name="credman_confirmation_message">Saved info like addresses or payment methods won\'t be filled in when you sign in. To keep your saved info filled in, set enable a password, passkey and data/or service.</string>
|
<string name="credman_confirmation_message">
|
||||||
|
<![CDATA[
|
||||||
|
<b>Turn off this service?</b>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
Saved info like passwords, passkeys, payment methods, and other info won\'t be filled
|
||||||
|
in when you sign in. To use your saved info, choose a password, passkey, or data
|
||||||
|
service.
|
||||||
|
]]>
|
||||||
|
</string>
|
||||||
|
|
||||||
<!-- Title of the warning dialog for enabling the credential provider. [CHAR_LIMIT=NONE] -->
|
<!-- Title of the warning dialog for enabling the credential provider. [CHAR_LIMIT=NONE] -->
|
||||||
<string name="credman_enable_confirmation_message_title">Use %1$s\?</string>
|
<string name="credman_enable_confirmation_message_title">Use %1$s\?</string>
|
||||||
|
|||||||
@@ -17,16 +17,26 @@
|
|||||||
package com.android.settings.accessibility;
|
package com.android.settings.accessibility;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.ColorInt;
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
|
import androidx.preference.PreferenceViewHolder;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
|
import com.android.settingslib.Utils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Preference for Flash notifications preview.
|
* Preference for Flash notifications preview.
|
||||||
*/
|
*/
|
||||||
public class FlashNotificationsPreviewPreference extends Preference {
|
public class FlashNotificationsPreviewPreference extends Preference {
|
||||||
|
private Drawable mBackgroundEnabled;
|
||||||
|
private Drawable mBackgroundDisabled;
|
||||||
|
@ColorInt
|
||||||
|
private int mTextColorDisabled;
|
||||||
|
|
||||||
public FlashNotificationsPreviewPreference(Context context) {
|
public FlashNotificationsPreviewPreference(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
@@ -52,5 +62,32 @@ public class FlashNotificationsPreviewPreference extends Preference {
|
|||||||
|
|
||||||
private void init() {
|
private void init() {
|
||||||
setLayoutResource(R.layout.flash_notification_preview_preference);
|
setLayoutResource(R.layout.flash_notification_preview_preference);
|
||||||
|
mBackgroundEnabled = getContext().getDrawable(R.drawable.settingslib_switch_bar_bg_on);
|
||||||
|
mBackgroundDisabled = getContext().getDrawable(R.drawable.switch_bar_bg_disabled);
|
||||||
|
mTextColorDisabled = Utils.getColorAttrDefaultColor(getContext(),
|
||||||
|
android.R.attr.textColorPrimary);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(PreferenceViewHolder holder) {
|
||||||
|
super.onBindViewHolder(holder);
|
||||||
|
|
||||||
|
final boolean enabled = isEnabled();
|
||||||
|
final View frame = holder.findViewById(R.id.frame);
|
||||||
|
if (frame != null) {
|
||||||
|
frame.setBackground(enabled ? mBackgroundEnabled : mBackgroundDisabled);
|
||||||
|
}
|
||||||
|
final TextView title = (TextView) holder.findViewById(android.R.id.title);
|
||||||
|
if (title != null) {
|
||||||
|
@ColorInt final int textColorEnabled = title.getCurrentTextColor();
|
||||||
|
title.setAlpha(enabled ? 1f : 0.38f);
|
||||||
|
title.setTextColor(enabled ? textColorEnabled : mTextColorDisabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setEnabled(boolean enabled) {
|
||||||
|
super.setEnabled(enabled);
|
||||||
|
notifyChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ public class FlashNotificationsPreviewPreferenceController extends
|
|||||||
new Handler(Looper.getMainLooper())) {
|
new Handler(Looper.getMainLooper())) {
|
||||||
@Override
|
@Override
|
||||||
public void onChange(boolean selfChange, @Nullable Uri uri) {
|
public void onChange(boolean selfChange, @Nullable Uri uri) {
|
||||||
onSettingChanged();
|
updateState(mPreference);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ public class FlashNotificationsPreviewPreferenceController extends
|
|||||||
public void displayPreference(PreferenceScreen screen) {
|
public void displayPreference(PreferenceScreen screen) {
|
||||||
super.displayPreference(screen);
|
super.displayPreference(screen);
|
||||||
mPreference = screen.findPreference(getPreferenceKey());
|
mPreference = screen.findPreference(getPreferenceKey());
|
||||||
onSettingChanged();
|
updateState(mPreference);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -103,10 +103,13 @@ public class FlashNotificationsPreviewPreferenceController extends
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onSettingChanged() {
|
@Override
|
||||||
if (mPreference == null) return;
|
public void updateState(Preference preference) {
|
||||||
|
super.updateState(preference);
|
||||||
mPreference.setEnabled(FlashNotificationsUtil.getFlashNotificationsState(mContext)
|
if (preference == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
preference.setEnabled(FlashNotificationsUtil.getFlashNotificationsState(mContext)
|
||||||
!= FlashNotificationsUtil.State.OFF);
|
!= FlashNotificationsUtil.State.OFF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -553,21 +553,9 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
|
|||||||
mPrefs.get(packageName).setChecked(true);
|
mPrefs.get(packageName).setChecked(true);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} else {
|
|
||||||
// If we are disabling the last enabled provider then show a warning.
|
|
||||||
if (mEnabledPackageNames.size() <= 1) {
|
|
||||||
final DialogFragment fragment =
|
|
||||||
newConfirmationDialogFragment(packageName, title, pref);
|
|
||||||
|
|
||||||
if (fragment == null || mFragmentManager == null) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
fragment.show(mFragmentManager, ConfirmationDialogFragment.TAG);
|
|
||||||
} else {
|
} else {
|
||||||
togglePackageNameDisabled(packageName);
|
togglePackageNameDisabled(packageName);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
@@ -682,35 +670,6 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
|
|||||||
return new ErrorDialogFragment(host);
|
return new ErrorDialogFragment(host);
|
||||||
}
|
}
|
||||||
|
|
||||||
private @Nullable ConfirmationDialogFragment newConfirmationDialogFragment(
|
|
||||||
@NonNull String packageName,
|
|
||||||
@NonNull CharSequence appName,
|
|
||||||
@NonNull SwitchPreference pref) {
|
|
||||||
DialogHost host =
|
|
||||||
new DialogHost() {
|
|
||||||
@Override
|
|
||||||
public void onDialogClick(int whichButton) {
|
|
||||||
if (whichButton == DialogInterface.BUTTON_POSITIVE) {
|
|
||||||
// Since the package is now enabled then we
|
|
||||||
// should remove it from the enabled list.
|
|
||||||
togglePackageNameDisabled(packageName);
|
|
||||||
} else if (whichButton == DialogInterface.BUTTON_NEGATIVE) {
|
|
||||||
// Set the checked back to true because we
|
|
||||||
// backed out of turning this off.
|
|
||||||
pref.setChecked(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCancel() {
|
|
||||||
// If we dismiss the dialog then re-enable.
|
|
||||||
pref.setChecked(true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return new ConfirmationDialogFragment(host, packageName, appName);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected int getUser() {
|
protected int getUser() {
|
||||||
if (mIsWorkProfile) {
|
if (mIsWorkProfile) {
|
||||||
UserHandle workProfile = Utils.getManagedProfile(UserManager.get(mContext));
|
UserHandle workProfile = Utils.getManagedProfile(UserManager.get(mContext));
|
||||||
@@ -800,46 +759,6 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
|
|||||||
public void onClick(DialogInterface dialog, int which) {}
|
public void onClick(DialogInterface dialog, int which) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Confirmation dialog fragment shows a dialog to the user to confirm that they are disabling a
|
|
||||||
* provider.
|
|
||||||
*/
|
|
||||||
public static class ConfirmationDialogFragment extends CredentialManagerDialogFragment {
|
|
||||||
|
|
||||||
ConfirmationDialogFragment(
|
|
||||||
DialogHost dialogHost, @NonNull String packageName, @NonNull CharSequence appName) {
|
|
||||||
super(dialogHost);
|
|
||||||
|
|
||||||
final Bundle argument = new Bundle();
|
|
||||||
argument.putString(PACKAGE_NAME_KEY, packageName);
|
|
||||||
argument.putCharSequence(APP_NAME_KEY, appName);
|
|
||||||
setArguments(argument);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
|
||||||
final Bundle bundle = getArguments();
|
|
||||||
final String title =
|
|
||||||
getContext()
|
|
||||||
.getString(
|
|
||||||
R.string.credman_confirmation_message_title,
|
|
||||||
bundle.getCharSequence(
|
|
||||||
CredentialManagerDialogFragment.APP_NAME_KEY));
|
|
||||||
|
|
||||||
return new AlertDialog.Builder(getActivity())
|
|
||||||
.setTitle(title)
|
|
||||||
.setMessage(getContext().getString(R.string.credman_confirmation_message))
|
|
||||||
.setPositiveButton(R.string.credman_confirmation_message_positive_button, this)
|
|
||||||
.setNegativeButton(android.R.string.cancel, this)
|
|
||||||
.create();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
|
||||||
getDialogHost().onDialogClick(which);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Confirmation dialog fragment shows a dialog to the user to confirm that they would like to
|
* Confirmation dialog fragment shows a dialog to the user to confirm that they would like to
|
||||||
* enable the new provider.
|
* enable the new provider.
|
||||||
|
|||||||
@@ -273,8 +273,13 @@ public class DefaultCombinedPicker extends DefaultAppPickerFragment {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected CharSequence getConfirmationMessage(CandidateInfo appInfo) {
|
protected CharSequence getConfirmationMessage(CandidateInfo appInfo) {
|
||||||
|
// If we are selecting none then show a warning label.
|
||||||
if (appInfo == null) {
|
if (appInfo == null) {
|
||||||
return null;
|
final String message =
|
||||||
|
getContext()
|
||||||
|
.getString(
|
||||||
|
R.string.credman_confirmation_message);
|
||||||
|
return Html.fromHtml(message);
|
||||||
}
|
}
|
||||||
final CharSequence appName = appInfo.loadLabel();
|
final CharSequence appName = appInfo.loadLabel();
|
||||||
final String message =
|
final String message =
|
||||||
|
|||||||
@@ -261,6 +261,8 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
|
|||||||
int rotation = getApplicationContext().getDisplay().getRotation();
|
int rotation = getApplicationContext().getDisplay().getRotation();
|
||||||
final GlifLayout layout = (GlifLayout) getLayoutInflater().inflate(
|
final GlifLayout layout = (GlifLayout) getLayoutInflater().inflate(
|
||||||
R.layout.udfps_enroll_enrolling, null, false);
|
R.layout.udfps_enroll_enrolling, null, false);
|
||||||
|
final UdfpsEnrollView udfpsEnrollView = layout.findViewById(R.id.udfps_animation_view);
|
||||||
|
updateUdfpsEnrollView(udfpsEnrollView, props.get(0));
|
||||||
switch (rotation) {
|
switch (rotation) {
|
||||||
case Surface.ROTATION_90:
|
case Surface.ROTATION_90:
|
||||||
final View sudContent = layout.findViewById(R.id.sud_layout_content);
|
final View sudContent = layout.findViewById(R.id.sud_layout_content);
|
||||||
@@ -282,33 +284,17 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
|
|||||||
? 0 : (int) getResources().getDimension(
|
? 0 : (int) getResources().getDimension(
|
||||||
R.dimen.rotation_90_enroll_padding_end), 0);
|
R.dimen.rotation_90_enroll_padding_end), 0);
|
||||||
layoutContainer.setLayoutParams(lp);
|
layoutContainer.setLayoutParams(lp);
|
||||||
if (FeatureFlagUtils.isEnabled(getApplicationContext(),
|
|
||||||
FeatureFlagUtils.SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS)) {
|
|
||||||
final UdfpsEnrollView udfpsEnrollView = addUdfpsEnrollView(props.get(0));
|
|
||||||
layout.addView(udfpsEnrollView);
|
|
||||||
setOnHoverListener(true, layout, udfpsEnrollView);
|
setOnHoverListener(true, layout, udfpsEnrollView);
|
||||||
}
|
|
||||||
setContentView(layout, lp);
|
setContentView(layout, lp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Surface.ROTATION_0:
|
case Surface.ROTATION_0:
|
||||||
case Surface.ROTATION_180:
|
case Surface.ROTATION_180:
|
||||||
if (FeatureFlagUtils.isEnabled(getApplicationContext(),
|
// In the portrait mode, layout_container's height is 0, so it's
|
||||||
FeatureFlagUtils.SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS)) {
|
|
||||||
final UdfpsEnrollView udfpsEnrollView = addUdfpsEnrollView(props.get(0));
|
|
||||||
// In the portrait mode, set layout_container's height 0, so it's
|
|
||||||
// always shown at the bottom of the screen.
|
// always shown at the bottom of the screen.
|
||||||
// Add udfps enroll view into layout_container instead of
|
|
||||||
// udfps_enroll_enrolling, so that when the content is too long to
|
|
||||||
// make udfps_enroll_enrolling larger than the screen, udfps enroll
|
|
||||||
// view could still be set to right position by setting bottom margin to
|
|
||||||
// its parent view (layout_container) because it's always at the
|
|
||||||
// bottom of the screen.
|
|
||||||
final FrameLayout portraitLayoutContainer = layout.findViewById(
|
final FrameLayout portraitLayoutContainer = layout.findViewById(
|
||||||
R.id.layout_container);
|
R.id.layout_container);
|
||||||
final ViewGroup.LayoutParams containerLp =
|
|
||||||
portraitLayoutContainer.getLayoutParams();
|
|
||||||
containerLp.height = 0;
|
|
||||||
|
|
||||||
// In the portrait mode, the title and lottie animation view may
|
// In the portrait mode, the title and lottie animation view may
|
||||||
// overlap when title needs three lines, so adding some paddings
|
// overlap when title needs three lines, so adding some paddings
|
||||||
@@ -326,22 +312,24 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
|
|||||||
fingerprintView.setPadding(0, -layoutLottieAnimationPadding,
|
fingerprintView.setPadding(0, -layoutLottieAnimationPadding,
|
||||||
0, layoutLottieAnimationPadding);
|
0, layoutLottieAnimationPadding);
|
||||||
|
|
||||||
portraitLayoutContainer.addView(udfpsEnrollView);
|
// TODO(b/260970216) Instead of hiding the description text view, we should
|
||||||
setOnHoverListener(false, layout, udfpsEnrollView);
|
// make the header view scrollable if the text is too long.
|
||||||
|
// If description text view has overlap with udfps progress view, hide it.
|
||||||
|
View view = layout.getDescriptionTextView();
|
||||||
|
layout.getViewTreeObserver().addOnDrawListener(() -> {
|
||||||
|
if (view.getVisibility() == View.VISIBLE
|
||||||
|
&& hasOverlap(view, udfpsEnrollView)) {
|
||||||
|
view.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
setOnHoverListener(false, layout, udfpsEnrollView);
|
||||||
setContentView(layout);
|
setContentView(layout);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Surface.ROTATION_270:
|
case Surface.ROTATION_270:
|
||||||
default:
|
default:
|
||||||
if (FeatureFlagUtils.isEnabled(getApplicationContext(),
|
|
||||||
FeatureFlagUtils.SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS)) {
|
|
||||||
final UdfpsEnrollView udfpsEnrollView = addUdfpsEnrollView(props.get(0));
|
|
||||||
layout.addView(udfpsEnrollView);
|
|
||||||
setOnHoverListener(true, layout, udfpsEnrollView);
|
setOnHoverListener(true, layout, udfpsEnrollView);
|
||||||
}
|
|
||||||
|
|
||||||
setContentView(layout);
|
setContentView(layout);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1241,10 +1229,8 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private UdfpsEnrollView addUdfpsEnrollView(FingerprintSensorPropertiesInternal udfpsProps) {
|
private UdfpsEnrollView updateUdfpsEnrollView(UdfpsEnrollView udfpsEnrollView,
|
||||||
UdfpsEnrollView udfpsEnrollView = (UdfpsEnrollView) getLayoutInflater().inflate(
|
FingerprintSensorPropertiesInternal udfpsProps) {
|
||||||
R.layout.udfps_enroll_view, null, false);
|
|
||||||
|
|
||||||
DisplayInfo displayInfo = new DisplayInfo();
|
DisplayInfo displayInfo = new DisplayInfo();
|
||||||
getDisplay().getDisplayInfo(displayInfo);
|
getDisplay().getDisplayInfo(displayInfo);
|
||||||
mScaleFactor = mUdfpsUtils.getScaleFactor(displayInfo);
|
mScaleFactor = mUdfpsUtils.getScaleFactor(displayInfo);
|
||||||
@@ -1311,6 +1297,24 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
|
|||||||
: R.id.sud_layout_content).setOnHoverListener(onHoverListener);
|
: R.id.sud_layout_content).setOnHoverListener(onHoverListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@VisibleForTesting boolean hasOverlap(View view1, View view2) {
|
||||||
|
int[] firstPosition = new int[2];
|
||||||
|
int[] secondPosition = new int[2];
|
||||||
|
|
||||||
|
view1.getLocationOnScreen(firstPosition);
|
||||||
|
view2.getLocationOnScreen(secondPosition);
|
||||||
|
|
||||||
|
// Rect constructor parameters: left, top, right, bottom
|
||||||
|
Rect rectView1 = new Rect(firstPosition[0], firstPosition[1],
|
||||||
|
firstPosition[0] + view1.getMeasuredWidth(),
|
||||||
|
firstPosition[1] + view1.getMeasuredHeight());
|
||||||
|
Rect rectView2 = new Rect(secondPosition[0], secondPosition[1],
|
||||||
|
secondPosition[0] + view2.getMeasuredWidth(),
|
||||||
|
secondPosition[1] + view2.getMeasuredHeight());
|
||||||
|
return rectView1.intersect(rectView2);
|
||||||
|
}
|
||||||
|
|
||||||
public static class IconTouchDialog extends InstrumentedDialogFragment {
|
public static class IconTouchDialog extends InstrumentedDialogFragment {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -185,7 +185,8 @@ public class FingerprintSettings extends SubSettings {
|
|||||||
private static final int MSG_FINGER_AUTH_HELP = 1004;
|
private static final int MSG_FINGER_AUTH_HELP = 1004;
|
||||||
|
|
||||||
private static final int CONFIRM_REQUEST = 101;
|
private static final int CONFIRM_REQUEST = 101;
|
||||||
private static final int CHOOSE_LOCK_GENERIC_REQUEST = 102;
|
@VisibleForTesting
|
||||||
|
static final int CHOOSE_LOCK_GENERIC_REQUEST = 102;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static final int ADD_FINGERPRINT_REQUEST = 10;
|
static final int ADD_FINGERPRINT_REQUEST = 10;
|
||||||
private static final int AUTO_ADD_FIRST_FINGERPRINT_REQUEST = 11;
|
private static final int AUTO_ADD_FIRST_FINGERPRINT_REQUEST = 11;
|
||||||
@@ -1014,7 +1015,7 @@ public class FingerprintSettings extends SubSettings {
|
|||||||
true);
|
true);
|
||||||
intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
|
intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
|
||||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, true);
|
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, true);
|
||||||
intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
|
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, true);
|
||||||
startActivityForResult(intent, CHOOSE_LOCK_GENERIC_REQUEST);
|
startActivityForResult(intent, CHOOSE_LOCK_GENERIC_REQUEST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -161,7 +161,6 @@ public class UdfpsEnrollView extends FrameLayout implements UdfpsEnrollHelper.Li
|
|||||||
MarginLayoutParams marginLayoutParams = (MarginLayoutParams) getLayoutParams();
|
MarginLayoutParams marginLayoutParams = (MarginLayoutParams) getLayoutParams();
|
||||||
FrameLayout.LayoutParams params = (LayoutParams) getLayoutParams();
|
FrameLayout.LayoutParams params = (LayoutParams) getLayoutParams();
|
||||||
if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) {
|
if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) {
|
||||||
parentView.getViewTreeObserver().addOnDrawListener(() -> {
|
|
||||||
final int[] coords = parentView.getLocationOnScreen();
|
final int[] coords = parentView.getLocationOnScreen();
|
||||||
final int parentLeft = coords[0];
|
final int parentLeft = coords[0];
|
||||||
final int parentTop = coords[1];
|
final int parentTop = coords[1];
|
||||||
@@ -176,7 +175,6 @@ public class UdfpsEnrollView extends FrameLayout implements UdfpsEnrollHelper.Li
|
|||||||
marginLayoutParams.rightMargin = rightMargin;
|
marginLayoutParams.rightMargin = rightMargin;
|
||||||
marginLayoutParams.topMargin = topMargin;
|
marginLayoutParams.topMargin = topMargin;
|
||||||
setLayoutParams(params);
|
setLayoutParams(params);
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
final int[] coords = parentView.getLocationOnScreen();
|
final int[] coords = parentView.getLocationOnScreen();
|
||||||
final int parentLeft = coords[0];
|
final int parentLeft = coords[0];
|
||||||
|
|||||||
@@ -57,7 +57,9 @@ import com.android.settingslib.widget.LayoutPreference;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -92,13 +94,12 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont
|
|||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
final Map<String, Bitmap> mIconCache;
|
final Map<String, Bitmap> mIconCache;
|
||||||
private CachedBluetoothDevice mCachedDevice;
|
private CachedBluetoothDevice mCachedDevice;
|
||||||
|
private Set<BluetoothDevice> mBluetoothDevices;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
BluetoothAdapter mBluetoothAdapter;
|
BluetoothAdapter mBluetoothAdapter;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
Handler mHandler = new Handler(Looper.getMainLooper());
|
Handler mHandler = new Handler(Looper.getMainLooper());
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
boolean mIsRegisterCallback = false;
|
|
||||||
@VisibleForTesting
|
|
||||||
boolean mIsLeftDeviceEstimateReady;
|
boolean mIsLeftDeviceEstimateReady;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
boolean mIsRightDeviceEstimateReady;
|
boolean mIsRightDeviceEstimateReady;
|
||||||
@@ -141,23 +142,13 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont
|
|||||||
if (!isAvailable()) {
|
if (!isAvailable()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mIsRegisterCallback = true;
|
registerBluetoothDevice();
|
||||||
mCachedDevice.registerCallback(this);
|
|
||||||
mBluetoothAdapter.addOnMetadataChangedListener(mCachedDevice.getDevice(),
|
|
||||||
mContext.getMainExecutor(), mMetadataListener);
|
|
||||||
|
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStop() {
|
public void onStop() {
|
||||||
if (!mIsRegisterCallback) {
|
unRegisterBluetoothDevice();
|
||||||
return;
|
|
||||||
}
|
|
||||||
mCachedDevice.unregisterCallback(this);
|
|
||||||
mBluetoothAdapter.removeOnMetadataChangedListener(mCachedDevice.getDevice(),
|
|
||||||
mMetadataListener);
|
|
||||||
mIsRegisterCallback = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -175,6 +166,40 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont
|
|||||||
mCachedDevice = cachedBluetoothDevice;
|
mCachedDevice = cachedBluetoothDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void registerBluetoothDevice() {
|
||||||
|
if (mBluetoothDevices == null) {
|
||||||
|
mBluetoothDevices = new HashSet<>();
|
||||||
|
}
|
||||||
|
mBluetoothDevices.clear();
|
||||||
|
if (mCachedDevice.getDevice() != null) {
|
||||||
|
mBluetoothDevices.add(mCachedDevice.getDevice());
|
||||||
|
}
|
||||||
|
mCachedDevice.getMemberDevice().forEach(cbd -> {
|
||||||
|
if (cbd != null) {
|
||||||
|
mBluetoothDevices.add(cbd.getDevice());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (mBluetoothDevices.isEmpty()) {
|
||||||
|
Log.d(TAG, "No BT devcie to register.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mCachedDevice.registerCallback(this);
|
||||||
|
mBluetoothDevices.forEach(bd ->
|
||||||
|
mBluetoothAdapter.addOnMetadataChangedListener(bd,
|
||||||
|
mContext.getMainExecutor(), mMetadataListener));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void unRegisterBluetoothDevice() {
|
||||||
|
if (mBluetoothDevices == null || mBluetoothDevices.isEmpty()) {
|
||||||
|
Log.d(TAG, "No BT devcie to unregister.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mCachedDevice.unregisterCallback(this);
|
||||||
|
mBluetoothDevices.forEach(bd -> mBluetoothAdapter.removeOnMetadataChangedListener(bd,
|
||||||
|
mMetadataListener));
|
||||||
|
mBluetoothDevices.clear();
|
||||||
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
void refresh() {
|
void refresh() {
|
||||||
if (mLayoutPreference != null && mCachedDevice != null) {
|
if (mLayoutPreference != null && mCachedDevice != null) {
|
||||||
|
|||||||
@@ -120,6 +120,10 @@ public class BluetoothDetailsProfilesController extends BluetoothDetailsControll
|
|||||||
pref.setTitle(profile.getNameResource(mCachedDevice.getDevice()));
|
pref.setTitle(profile.getNameResource(mCachedDevice.getDevice()));
|
||||||
pref.setOnPreferenceClickListener(this);
|
pref.setOnPreferenceClickListener(this);
|
||||||
pref.setOrder(profile.getOrdinal());
|
pref.setOrder(profile.getOrdinal());
|
||||||
|
|
||||||
|
if (profile instanceof LeAudioProfile) {
|
||||||
|
pref.setSummary(R.string.device_details_leaudio_toggle_summary);
|
||||||
|
}
|
||||||
return pref;
|
return pref;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -196,10 +196,11 @@ public abstract class DeviceListPreferenceFragment extends
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Prevent updates while the list shows one of the state messages
|
// Prevent updates while the list shows one of the state messages
|
||||||
if (mBluetoothAdapter.getState() != BluetoothAdapter.STATE_ON) return;
|
if (mBluetoothAdapter.getState() != BluetoothAdapter.STATE_ON) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (mLeScanFilters != null
|
if (mFilter != null && mFilter.matches(cachedDevice.getDevice())) {
|
||||||
|| (mFilter != null && mFilter.matches(cachedDevice.getDevice()))) {
|
|
||||||
createDevicePreference(cachedDevice);
|
createDevicePreference(cachedDevice);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -325,7 +326,12 @@ public abstract class DeviceListPreferenceFragment extends
|
|||||||
if (cachedDevice == null) {
|
if (cachedDevice == null) {
|
||||||
cachedDevice = mCachedDeviceManager.addDevice(device);
|
cachedDevice = mCachedDeviceManager.addDevice(device);
|
||||||
}
|
}
|
||||||
onDeviceAdded(cachedDevice);
|
// Only add device preference when it's not found in the map and there's no other
|
||||||
|
// state message showing in the list
|
||||||
|
if (mDevicePreferenceMap.get(cachedDevice) == null
|
||||||
|
&& mBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) {
|
||||||
|
createDevicePreference(cachedDevice);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -48,6 +48,8 @@ public class GraphicsDriverEnableAngleAsSystemDriverController
|
|||||||
|
|
||||||
private final DevelopmentSettingsDashboardFragment mFragment;
|
private final DevelopmentSettingsDashboardFragment mFragment;
|
||||||
|
|
||||||
|
private final GraphicsDriverSystemPropertiesWrapper mSystemProperties;
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static final String PROPERTY_RO_GFX_ANGLE_SUPPORTED = "ro.gfx.angle.supported";
|
static final String PROPERTY_RO_GFX_ANGLE_SUPPORTED = "ro.gfx.angle.supported";
|
||||||
|
|
||||||
@@ -57,11 +59,34 @@ public class GraphicsDriverEnableAngleAsSystemDriverController
|
|||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static final String ANGLE_DRIVER_SUFFIX = "angle";
|
static final String ANGLE_DRIVER_SUFFIX = "angle";
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
static class Injector {
|
||||||
|
public GraphicsDriverSystemPropertiesWrapper createSystemPropertiesWrapper() {
|
||||||
|
return new GraphicsDriverSystemPropertiesWrapper() {
|
||||||
|
@Override
|
||||||
|
public String get(String key, String def) {
|
||||||
|
return SystemProperties.get(key, def);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void set(String key, String val) {
|
||||||
|
SystemProperties.set(key, val);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public GraphicsDriverEnableAngleAsSystemDriverController(
|
public GraphicsDriverEnableAngleAsSystemDriverController(
|
||||||
Context context, DevelopmentSettingsDashboardFragment fragment) {
|
Context context, DevelopmentSettingsDashboardFragment fragment) {
|
||||||
|
this(context, fragment, new Injector());
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
GraphicsDriverEnableAngleAsSystemDriverController(
|
||||||
|
Context context, DevelopmentSettingsDashboardFragment fragment, Injector injector) {
|
||||||
super(context);
|
super(context);
|
||||||
mFragment = fragment;
|
mFragment = fragment;
|
||||||
|
mSystemProperties = injector.createSystemPropertiesWrapper();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -76,20 +101,27 @@ public class GraphicsDriverEnableAngleAsSystemDriverController
|
|||||||
// set "persist.graphics.egl" to "" if enableAngleAsSystemDriver is false
|
// set "persist.graphics.egl" to "" if enableAngleAsSystemDriver is false
|
||||||
GraphicsEnvironment.getInstance().toggleAngleAsSystemDriver(enableAngleAsSystemDriver);
|
GraphicsEnvironment.getInstance().toggleAngleAsSystemDriver(enableAngleAsSystemDriver);
|
||||||
// pop up a window asking user to reboot to make the new "persist.graphics.egl" take effect
|
// pop up a window asking user to reboot to make the new "persist.graphics.egl" take effect
|
||||||
|
showRebootDialog();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
void showRebootDialog() {
|
||||||
RebootConfirmationDialogFragment.show(
|
RebootConfirmationDialogFragment.show(
|
||||||
mFragment, R.string.reboot_dialog_enable_angle_as_system_driver,
|
mFragment, R.string.reboot_dialog_enable_angle_as_system_driver,
|
||||||
R.string.cancel, this);
|
R.string.cancel, this);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateState(Preference preference) {
|
public void updateState(Preference preference) {
|
||||||
// set switch on if "persist.graphics.egl" is "angle" and angle is built in /vendor
|
// set switch on if "persist.graphics.egl" is "angle" and angle is built in /vendor
|
||||||
// set switch off otherwise.
|
// set switch off otherwise.
|
||||||
final String currentGlesDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
|
final String currentGlesDriver =
|
||||||
|
mSystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL, "");
|
||||||
final boolean isAngle = TextUtils.equals(ANGLE_DRIVER_SUFFIX, currentGlesDriver);
|
final boolean isAngle = TextUtils.equals(ANGLE_DRIVER_SUFFIX, currentGlesDriver);
|
||||||
final boolean isAngleSupported =
|
final boolean isAngleSupported = TextUtils
|
||||||
TextUtils.equals(SystemProperties.get(PROPERTY_RO_GFX_ANGLE_SUPPORTED), "true");
|
.equals(mSystemProperties.get(PROPERTY_RO_GFX_ANGLE_SUPPORTED, ""), "true");
|
||||||
((SwitchPreference) mPreference).setChecked(isAngle && isAngleSupported);
|
((SwitchPreference) mPreference).setChecked(isAngle && isAngleSupported);
|
||||||
((SwitchPreference) mPreference).setEnabled(isAngleSupported);
|
((SwitchPreference) mPreference).setEnabled(isAngleSupported);
|
||||||
}
|
}
|
||||||
@@ -98,8 +130,8 @@ public class GraphicsDriverEnableAngleAsSystemDriverController
|
|||||||
protected void onDeveloperOptionsSwitchEnabled() {
|
protected void onDeveloperOptionsSwitchEnabled() {
|
||||||
// only enable the switch if ro.gfx.angle.supported is true
|
// only enable the switch if ro.gfx.angle.supported is true
|
||||||
// we use ro.gfx.angle.supported to indicate if ANGLE libs are installed under /vendor
|
// we use ro.gfx.angle.supported to indicate if ANGLE libs are installed under /vendor
|
||||||
final boolean isAngleSupported =
|
final boolean isAngleSupported = TextUtils
|
||||||
TextUtils.equals(SystemProperties.get(PROPERTY_RO_GFX_ANGLE_SUPPORTED), "true");
|
.equals(mSystemProperties.get(PROPERTY_RO_GFX_ANGLE_SUPPORTED, ""), "true");
|
||||||
((SwitchPreference) mPreference).setEnabled(isAngleSupported);
|
((SwitchPreference) mPreference).setEnabled(isAngleSupported);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,7 +148,8 @@ public class GraphicsDriverEnableAngleAsSystemDriverController
|
|||||||
@Override
|
@Override
|
||||||
public void onRebootCancelled() {
|
public void onRebootCancelled() {
|
||||||
// if user presses button "Cancel", do not reboot the device, and toggles switch back
|
// if user presses button "Cancel", do not reboot the device, and toggles switch back
|
||||||
final String currentGlesDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
|
final String currentGlesDriver =
|
||||||
|
mSystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL, "");
|
||||||
if (TextUtils.equals(ANGLE_DRIVER_SUFFIX, currentGlesDriver)) {
|
if (TextUtils.equals(ANGLE_DRIVER_SUFFIX, currentGlesDriver)) {
|
||||||
// if persist.graphics.egl = "angle", set the property value back to ""
|
// if persist.graphics.egl = "angle", set the property value back to ""
|
||||||
GraphicsEnvironment.getInstance().toggleAngleAsSystemDriver(false);
|
GraphicsEnvironment.getInstance().toggleAngleAsSystemDriver(false);
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.android.settings.development.graphicsdriver;
|
||||||
|
import android.annotation.NonNull;
|
||||||
|
import android.annotation.Nullable;
|
||||||
|
import android.os.SystemProperties;
|
||||||
|
/**
|
||||||
|
* Wrapper interface to access {@link SystemProperties}.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
interface GraphicsDriverSystemPropertiesWrapper {
|
||||||
|
/**
|
||||||
|
* Get the String value for the given {@code key}.
|
||||||
|
*
|
||||||
|
* @param key the key to lookup
|
||||||
|
* @param def the default value in case the property is not set or empty
|
||||||
|
* @return if the {@code key} isn't found, return {@code def} if it isn't null, or an empty
|
||||||
|
* string otherwise
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
String get(@NonNull String key, @Nullable String def);
|
||||||
|
/**
|
||||||
|
* Set the value for the given {@code key} to {@code val}.
|
||||||
|
*
|
||||||
|
* @throws IllegalArgumentException if the {@code val} exceeds 91 characters
|
||||||
|
* @throws RuntimeException if the property cannot be set, for example, if it was blocked by
|
||||||
|
* SELinux. libc will log the underlying reason.
|
||||||
|
*/
|
||||||
|
void set(@NonNull String key, @Nullable String val);
|
||||||
|
}
|
||||||
@@ -22,6 +22,7 @@ import android.app.backup.BackupDataInputStream;
|
|||||||
import android.app.backup.BackupDataOutput;
|
import android.app.backup.BackupDataOutput;
|
||||||
import android.app.backup.BackupHelper;
|
import android.app.backup.BackupHelper;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.IPackageManager;
|
import android.content.pm.IPackageManager;
|
||||||
import android.os.IDeviceIdleController;
|
import android.os.IDeviceIdleController;
|
||||||
@@ -34,9 +35,11 @@ import android.util.Log;
|
|||||||
|
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
|
|
||||||
|
import com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action;
|
||||||
import com.android.settingslib.fuelgauge.PowerAllowlistBackend;
|
import com.android.settingslib.fuelgauge.PowerAllowlistBackend;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -47,6 +50,8 @@ public final class BatteryBackupHelper implements BackupHelper {
|
|||||||
/** An inditifier for {@link BackupHelper}. */
|
/** An inditifier for {@link BackupHelper}. */
|
||||||
public static final String TAG = "BatteryBackupHelper";
|
public static final String TAG = "BatteryBackupHelper";
|
||||||
private static final String DEVICE_IDLE_SERVICE = "deviceidle";
|
private static final String DEVICE_IDLE_SERVICE = "deviceidle";
|
||||||
|
private static final String BATTERY_OPTIMIZE_BACKUP_FILE_NAME =
|
||||||
|
"battery_optimize_backup_historical_logs";
|
||||||
|
|
||||||
static final String DELIMITER = ",";
|
static final String DELIMITER = ",";
|
||||||
static final String DELIMITER_MODE = ":";
|
static final String DELIMITER_MODE = ":";
|
||||||
@@ -141,6 +146,7 @@ public final class BatteryBackupHelper implements BackupHelper {
|
|||||||
int backupCount = 0;
|
int backupCount = 0;
|
||||||
final StringBuilder builder = new StringBuilder();
|
final StringBuilder builder = new StringBuilder();
|
||||||
final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
|
final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
|
||||||
|
final SharedPreferences sharedPreferences = getSharedPreferences(mContext);
|
||||||
// Converts application into the AppUsageState.
|
// Converts application into the AppUsageState.
|
||||||
for (ApplicationInfo info : applications) {
|
for (ApplicationInfo info : applications) {
|
||||||
final int mode = BatteryOptimizeUtils.getMode(appOps, info.uid, info.packageName);
|
final int mode = BatteryOptimizeUtils.getMode(appOps, info.uid, info.packageName);
|
||||||
@@ -157,6 +163,9 @@ public final class BatteryBackupHelper implements BackupHelper {
|
|||||||
info.packageName + DELIMITER_MODE + optimizationMode;
|
info.packageName + DELIMITER_MODE + optimizationMode;
|
||||||
builder.append(packageOptimizeMode + DELIMITER);
|
builder.append(packageOptimizeMode + DELIMITER);
|
||||||
Log.d(TAG, "backupOptimizationMode: " + packageOptimizeMode);
|
Log.d(TAG, "backupOptimizationMode: " + packageOptimizeMode);
|
||||||
|
BatteryHistoricalLogUtil.writeLog(
|
||||||
|
sharedPreferences, Action.BACKUP, info.packageName,
|
||||||
|
/* actionDescription */ "mode: " + optimizationMode);
|
||||||
backupCount++;
|
backupCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,6 +219,18 @@ public final class BatteryBackupHelper implements BackupHelper {
|
|||||||
restoreCount, (System.currentTimeMillis() - timestamp)));
|
restoreCount, (System.currentTimeMillis() - timestamp)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Dump the app optimization mode backup history data. */
|
||||||
|
public static void dumpHistoricalData(Context context, PrintWriter writer) {
|
||||||
|
BatteryHistoricalLogUtil.printBatteryOptimizeHistoricalLog(
|
||||||
|
getSharedPreferences(context), writer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
static SharedPreferences getSharedPreferences(Context context) {
|
||||||
|
return context.getSharedPreferences(
|
||||||
|
BATTERY_OPTIMIZE_BACKUP_FILE_NAME, Context.MODE_PRIVATE);
|
||||||
|
}
|
||||||
|
|
||||||
private void restoreOptimizationMode(
|
private void restoreOptimizationMode(
|
||||||
String packageName, @BatteryOptimizeUtils.OptimizationMode int mode) {
|
String packageName, @BatteryOptimizeUtils.OptimizationMode int mode) {
|
||||||
final int uid = BatteryUtils.getInstance(mContext).getPackageUid(packageName);
|
final int uid = BatteryUtils.getInstance(mContext).getPackageUid(packageName);
|
||||||
|
|||||||
@@ -37,40 +37,40 @@ public final class BatteryHistoricalLogUtil {
|
|||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static final int MAX_ENTRIES = 40;
|
static final int MAX_ENTRIES = 40;
|
||||||
|
|
||||||
/**
|
/** Writes a log entry for battery optimization mode. */
|
||||||
* Writes a log entry.
|
static void writeLog(
|
||||||
*
|
Context context, Action action, String packageName, String actionDescription) {
|
||||||
* <p>Keeps up to {@link #MAX_ENTRIES} in the log, once that number is exceeded, it prunes the
|
writeLog(getSharedPreferences(context), action, packageName, actionDescription);
|
||||||
* oldest one.
|
}
|
||||||
*/
|
|
||||||
static void writeLog(Context context, Action action, String pkg, String actionDescription) {
|
static void writeLog(SharedPreferences sharedPreferences, Action action,
|
||||||
|
String packageName, String actionDescription) {
|
||||||
writeLog(
|
writeLog(
|
||||||
context,
|
sharedPreferences,
|
||||||
BatteryOptimizeHistoricalLogEntry.newBuilder()
|
BatteryOptimizeHistoricalLogEntry.newBuilder()
|
||||||
.setPackageName(pkg)
|
.setPackageName(packageName)
|
||||||
.setAction(action)
|
.setAction(action)
|
||||||
.setActionDescription(actionDescription)
|
.setActionDescription(actionDescription)
|
||||||
.setTimestamp(System.currentTimeMillis())
|
.setTimestamp(System.currentTimeMillis())
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void writeLog(Context context, BatteryOptimizeHistoricalLogEntry logEntry) {
|
private static void writeLog(
|
||||||
SharedPreferences sharedPreferences = getSharedPreferences(context);
|
SharedPreferences sharedPreferences, BatteryOptimizeHistoricalLogEntry logEntry) {
|
||||||
|
|
||||||
BatteryOptimizeHistoricalLog existingLog =
|
BatteryOptimizeHistoricalLog existingLog =
|
||||||
parseLogFromString(sharedPreferences.getString(LOGS_KEY, ""));
|
parseLogFromString(sharedPreferences.getString(LOGS_KEY, ""));
|
||||||
BatteryOptimizeHistoricalLog.Builder newLogBuilder = existingLog.toBuilder();
|
BatteryOptimizeHistoricalLog.Builder newLogBuilder = existingLog.toBuilder();
|
||||||
// Prune old entries
|
// Prune old entries to limit the max logging data count.
|
||||||
if (existingLog.getLogEntryCount() >= MAX_ENTRIES) {
|
if (existingLog.getLogEntryCount() >= MAX_ENTRIES) {
|
||||||
newLogBuilder.removeLogEntry(0);
|
newLogBuilder.removeLogEntry(0);
|
||||||
}
|
}
|
||||||
newLogBuilder.addLogEntry(logEntry);
|
newLogBuilder.addLogEntry(logEntry);
|
||||||
|
|
||||||
|
String loggingContent =
|
||||||
|
Base64.encodeToString(newLogBuilder.build().toByteArray(), Base64.DEFAULT);
|
||||||
sharedPreferences
|
sharedPreferences
|
||||||
.edit()
|
.edit()
|
||||||
.putString(
|
.putString(LOGS_KEY, loggingContent)
|
||||||
LOGS_KEY,
|
|
||||||
Base64.encodeToString(newLogBuilder.build().toByteArray(), Base64.DEFAULT))
|
|
||||||
.apply();
|
.apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,34 +79,36 @@ public final class BatteryHistoricalLogUtil {
|
|||||||
storedLogs, BatteryOptimizeHistoricalLog.getDefaultInstance());
|
storedLogs, BatteryOptimizeHistoricalLog.getDefaultInstance());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Prints the historical log that has previously been stored by this utility. */
|
||||||
* Prints the historical log that has previously been stored by this utility.
|
|
||||||
*/
|
|
||||||
public static void printBatteryOptimizeHistoricalLog(Context context, PrintWriter writer) {
|
public static void printBatteryOptimizeHistoricalLog(Context context, PrintWriter writer) {
|
||||||
|
printBatteryOptimizeHistoricalLog(getSharedPreferences(context), writer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Prints the historical log that has previously been stored by this utility. */
|
||||||
|
public static void printBatteryOptimizeHistoricalLog(
|
||||||
|
SharedPreferences sharedPreferences, PrintWriter writer) {
|
||||||
writer.println("Battery optimize state history:");
|
writer.println("Battery optimize state history:");
|
||||||
SharedPreferences sharedPreferences = getSharedPreferences(context);
|
|
||||||
BatteryOptimizeHistoricalLog existingLog =
|
BatteryOptimizeHistoricalLog existingLog =
|
||||||
parseLogFromString(sharedPreferences.getString(LOGS_KEY, ""));
|
parseLogFromString(sharedPreferences.getString(LOGS_KEY, ""));
|
||||||
List<BatteryOptimizeHistoricalLogEntry> logEntryList = existingLog.getLogEntryList();
|
List<BatteryOptimizeHistoricalLogEntry> logEntryList = existingLog.getLogEntryList();
|
||||||
if (logEntryList.isEmpty()) {
|
if (logEntryList.isEmpty()) {
|
||||||
writer.println("\tNo past logs.");
|
writer.println("\tnothing to dump");
|
||||||
} else {
|
} else {
|
||||||
writer.println("0:RESTRICTED 1:UNRESTRICTED 2:OPTIMIZED 3:UNKNOWN");
|
writer.println("0:UNKNOWN 1:RESTRICTED 2:UNRESTRICTED 3:OPTIMIZED");
|
||||||
logEntryList.forEach(entry -> writer.println(toString(entry)));
|
logEntryList.forEach(entry -> writer.println(toString(entry)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Gets the unique key for logging. */
|
||||||
* Gets the unique key for logging, combined with package name, delimiter and user id.
|
static String getPackageNameWithUserId(String packageName, int userId) {
|
||||||
*/
|
return packageName + ":" + userId;
|
||||||
static String getPackageNameWithUserId(String pkgName, int userId) {
|
|
||||||
return pkgName + ":" + userId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String toString(BatteryOptimizeHistoricalLogEntry entry) {
|
private static String toString(BatteryOptimizeHistoricalLogEntry entry) {
|
||||||
return String.format("%s\tAction:%s\tEvent:%s\tTimestamp:%s", entry.getPackageName(),
|
return String.format("%s\t%s\taction:%s\tevent:%s",
|
||||||
entry.getAction(), entry.getActionDescription(),
|
ConvertUtils.utcToLocalTimeForLogging(entry.getTimestamp()),
|
||||||
ConvertUtils.utcToLocalTimeForLogging(entry.getTimestamp()));
|
entry.getPackageName(), entry.getAction(),
|
||||||
|
entry.getActionDescription());
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
|
|||||||
@@ -299,9 +299,10 @@ public class BatteryInfo {
|
|||||||
(double) PowerUtil.convertUsToMs(info.remainingTimeUs), false /* withSeconds */,
|
(double) PowerUtil.convertUsToMs(info.remainingTimeUs), false /* withSeconds */,
|
||||||
true /* collapseTimeUnit */);
|
true /* collapseTimeUnit */);
|
||||||
int resId = R.string.power_charging_duration;
|
int resId = R.string.power_charging_duration;
|
||||||
info.remainingLabel = context.getString(R.string.power_remaining_charging_duration_only,
|
info.remainingLabel = chargeTimeMs <= 0 ? null : context.getString(
|
||||||
timeString);
|
R.string.power_remaining_charging_duration_only, timeString);
|
||||||
info.chargeLabel = context.getString(resId, info.batteryPercentString, timeString);
|
info.chargeLabel = chargeTimeMs <= 0 ? info.batteryPercentString
|
||||||
|
: context.getString(resId, info.batteryPercentString, timeString);
|
||||||
} else if (dockDefenderMode == BatteryUtils.DockDefenderMode.FUTURE_BYPASS) {
|
} else if (dockDefenderMode == BatteryUtils.DockDefenderMode.FUTURE_BYPASS) {
|
||||||
// Dock defender will be triggered in the future, charging will be optimized.
|
// Dock defender will be triggered in the future, charging will be optimized.
|
||||||
info.chargeLabel = context.getString(R.string.power_charging_future_paused,
|
info.chargeLabel = context.getString(R.string.power_charging_future_paused,
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import android.content.Intent;
|
|||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
import android.telephony.SubscriptionManager;
|
import android.telephony.SubscriptionManager;
|
||||||
import android.telephony.euicc.EuiccManager;
|
import android.telephony.euicc.EuiccManager;
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import androidx.lifecycle.Lifecycle;
|
import androidx.lifecycle.Lifecycle;
|
||||||
import androidx.lifecycle.LifecycleObserver;
|
import androidx.lifecycle.LifecycleObserver;
|
||||||
@@ -135,6 +134,7 @@ public class MobileNetworkSummaryController extends AbstractPreferenceController
|
|||||||
return mContext.getString(R.string.mobile_network_tap_to_activate, displayName);
|
return mContext.getString(R.string.mobile_network_tap_to_activate, displayName);
|
||||||
} else {
|
} else {
|
||||||
return mSubInfoEntityList.stream()
|
return mSubInfoEntityList.stream()
|
||||||
|
.sorted((e1, e2) -> Integer.compare(e1.simSlotIndex, e2.simSlotIndex))
|
||||||
.map(SubscriptionInfoEntity::getUniqueDisplayName)
|
.map(SubscriptionInfoEntity::getUniqueDisplayName)
|
||||||
.collect(Collectors.joining(", "));
|
.collect(Collectors.joining(", "));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,8 +59,10 @@ public class PrivacyDashboardFragment extends DashboardFragment {
|
|||||||
SafetyCenterUtils.getEnterpriseOverrideStringForPrivacyEntries();
|
SafetyCenterUtils.getEnterpriseOverrideStringForPrivacyEntries();
|
||||||
for (int i = 0; i < privacyOverrideStrings.size(); i++) {
|
for (int i = 0; i < privacyOverrideStrings.size(); i++) {
|
||||||
EnterpriseOverrideString overrideString = privacyOverrideStrings.get(i);
|
EnterpriseOverrideString overrideString = privacyOverrideStrings.get(i);
|
||||||
replaceEnterpriseStringTitle(overrideString.getPreferenceKey(),
|
replaceEnterpriseStringTitle(
|
||||||
overrideString.getOverrideKey(), overrideString.getResource());
|
overrideString.getPreferenceKey(),
|
||||||
|
overrideString.getOverrideKey(),
|
||||||
|
overrideString.getResource());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,7 +95,9 @@ public class PrivacyDashboardFragment extends DashboardFragment {
|
|||||||
@Override
|
@Override
|
||||||
public List<SearchIndexableResource> getXmlResourcesToIndex(
|
public List<SearchIndexableResource> getXmlResourcesToIndex(
|
||||||
Context context, boolean enabled) {
|
Context context, boolean enabled) {
|
||||||
if (SafetyCenterManagerWrapper.get().isEnabled(context)) {
|
// NOTE: This check likely should be moved to the super method. This is done
|
||||||
|
// here to avoid potentially undesired side effects for existing implementors.
|
||||||
|
if (!isPageSearchEnabled(context)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return super.getXmlResourcesToIndex(context, enabled);
|
return super.getXmlResourcesToIndex(context, enabled);
|
||||||
@@ -120,5 +124,10 @@ public class PrivacyDashboardFragment extends DashboardFragment {
|
|||||||
keys.add(KEY_NOTIFICATION_WORK_PROFILE_NOTIFICATIONS);
|
keys.add(KEY_NOTIFICATION_WORK_PROFILE_NOTIFICATIONS);
|
||||||
return keys;
|
return keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isPageSearchEnabled(Context context) {
|
||||||
|
return !SafetyCenterManagerWrapper.get().isEnabled(context);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,21 +77,23 @@ public class MoreSecurityPrivacyFragment extends DashboardFragment {
|
|||||||
SafetyCenterUtils.getEnterpriseOverrideStringForPrivacyEntries();
|
SafetyCenterUtils.getEnterpriseOverrideStringForPrivacyEntries();
|
||||||
for (int i = 0; i < privacyOverrideStrings.size(); i++) {
|
for (int i = 0; i < privacyOverrideStrings.size(); i++) {
|
||||||
EnterpriseOverrideString overrideString = privacyOverrideStrings.get(i);
|
EnterpriseOverrideString overrideString = privacyOverrideStrings.get(i);
|
||||||
replaceEnterpriseStringTitle(overrideString.getPreferenceKey(),
|
replaceEnterpriseStringTitle(
|
||||||
overrideString.getOverrideKey(), overrideString.getResource());
|
overrideString.getPreferenceKey(),
|
||||||
|
overrideString.getOverrideKey(),
|
||||||
|
overrideString.getResource());
|
||||||
}
|
}
|
||||||
List<EnterpriseOverrideString> securityOverrideStrings =
|
List<EnterpriseOverrideString> securityOverrideStrings =
|
||||||
SafetyCenterUtils.getEnterpriseOverrideStringForSecurityEntries();
|
SafetyCenterUtils.getEnterpriseOverrideStringForSecurityEntries();
|
||||||
for (int i = 0; i < securityOverrideStrings.size(); i++) {
|
for (int i = 0; i < securityOverrideStrings.size(); i++) {
|
||||||
EnterpriseOverrideString overrideString = securityOverrideStrings.get(i);
|
EnterpriseOverrideString overrideString = securityOverrideStrings.get(i);
|
||||||
replaceEnterpriseStringTitle(overrideString.getPreferenceKey(),
|
replaceEnterpriseStringTitle(
|
||||||
overrideString.getOverrideKey(), overrideString.getResource());
|
overrideString.getPreferenceKey(),
|
||||||
|
overrideString.getOverrideKey(),
|
||||||
|
overrideString.getResource());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** see confirmPatternThenDisableAndClear */
|
||||||
* see confirmPatternThenDisableAndClear
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
if (use(TrustAgentListPreferenceController.class)
|
if (use(TrustAgentListPreferenceController.class)
|
||||||
@@ -117,10 +119,8 @@ public class MoreSecurityPrivacyFragment extends DashboardFragment {
|
|||||||
controllers.addAll(
|
controllers.addAll(
|
||||||
SafetyCenterUtils.getControllersForAdvancedSecurity(context, lifecycle, host));
|
SafetyCenterUtils.getControllersForAdvancedSecurity(context, lifecycle, host));
|
||||||
return controllers;
|
return controllers;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||||
new BaseSearchIndexProvider(R.xml.more_security_privacy_settings) {
|
new BaseSearchIndexProvider(R.xml.more_security_privacy_settings) {
|
||||||
/**
|
/**
|
||||||
@@ -130,7 +130,9 @@ public class MoreSecurityPrivacyFragment extends DashboardFragment {
|
|||||||
@Override
|
@Override
|
||||||
public List<SearchIndexableResource> getXmlResourcesToIndex(
|
public List<SearchIndexableResource> getXmlResourcesToIndex(
|
||||||
Context context, boolean enabled) {
|
Context context, boolean enabled) {
|
||||||
if (!SafetyCenterManagerWrapper.get().isEnabled(context)) {
|
// NOTE: This check likely should be moved to the super method. This is done
|
||||||
|
// here to avoid potentially undesired side effects for existing implementors.
|
||||||
|
if (!isPageSearchEnabled(context)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return super.getXmlResourcesToIndex(context, enabled);
|
return super.getXmlResourcesToIndex(context, enabled);
|
||||||
@@ -157,5 +159,10 @@ public class MoreSecurityPrivacyFragment extends DashboardFragment {
|
|||||||
keys.add(KEY_NOTIFICATION_WORK_PROFILE_NOTIFICATIONS);
|
keys.add(KEY_NOTIFICATION_WORK_PROFILE_NOTIFICATIONS);
|
||||||
return keys;
|
return keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isPageSearchEnabled(Context context) {
|
||||||
|
return SafetyCenterManagerWrapper.get().isEnabled(context);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,8 +58,10 @@ public class SecurityAdvancedSettings extends DashboardFragment {
|
|||||||
SafetyCenterUtils.getEnterpriseOverrideStringForSecurityEntries();
|
SafetyCenterUtils.getEnterpriseOverrideStringForSecurityEntries();
|
||||||
for (int i = 0; i < securityOverrideStrings.size(); i++) {
|
for (int i = 0; i < securityOverrideStrings.size(); i++) {
|
||||||
EnterpriseOverrideString overrideString = securityOverrideStrings.get(i);
|
EnterpriseOverrideString overrideString = securityOverrideStrings.get(i);
|
||||||
replaceEnterpriseStringTitle(overrideString.getPreferenceKey(),
|
replaceEnterpriseStringTitle(
|
||||||
overrideString.getOverrideKey(), overrideString.getResource());
|
overrideString.getPreferenceKey(),
|
||||||
|
overrideString.getOverrideKey(),
|
||||||
|
overrideString.getResource());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,8 +79,7 @@ public class SecurityAdvancedSettings extends DashboardFragment {
|
|||||||
return CategoryKey.CATEGORY_SECURITY_ADVANCED_SETTINGS;
|
return CategoryKey.CATEGORY_SECURITY_ADVANCED_SETTINGS;
|
||||||
} else {
|
} else {
|
||||||
final SecuritySettingsFeatureProvider securitySettingsFeatureProvider =
|
final SecuritySettingsFeatureProvider securitySettingsFeatureProvider =
|
||||||
FeatureFactory.getFactory(context)
|
FeatureFactory.getFactory(context).getSecuritySettingsFeatureProvider();
|
||||||
.getSecuritySettingsFeatureProvider();
|
|
||||||
|
|
||||||
if (securitySettingsFeatureProvider.hasAlternativeSecuritySettingsFragment()) {
|
if (securitySettingsFeatureProvider.hasAlternativeSecuritySettingsFragment()) {
|
||||||
return securitySettingsFeatureProvider.getAlternativeAdvancedSettingsCategoryKey();
|
return securitySettingsFeatureProvider.getAlternativeAdvancedSettingsCategoryKey();
|
||||||
@@ -103,9 +104,7 @@ public class SecurityAdvancedSettings extends DashboardFragment {
|
|||||||
return buildPreferenceControllers(context, getSettingsLifecycle(), this /* host*/);
|
return buildPreferenceControllers(context, getSettingsLifecycle(), this /* host*/);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** see confirmPatternThenDisableAndClear */
|
||||||
* see confirmPatternThenDisableAndClear
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
if (use(TrustAgentListPreferenceController.class)
|
if (use(TrustAgentListPreferenceController.class)
|
||||||
@@ -119,14 +118,12 @@ public class SecurityAdvancedSettings extends DashboardFragment {
|
|||||||
super.onActivityResult(requestCode, resultCode, data);
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
|
private static List<AbstractPreferenceController> buildPreferenceControllers(
|
||||||
Lifecycle lifecycle, DashboardFragment host) {
|
Context context, Lifecycle lifecycle, DashboardFragment host) {
|
||||||
return SafetyCenterUtils.getControllersForAdvancedSecurity(context, lifecycle, host);
|
return SafetyCenterUtils.getControllersForAdvancedSecurity(context, lifecycle, host);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** For Search. Please keep it in sync when updating "createPreferenceHierarchy()" */
|
||||||
* For Search. Please keep it in sync when updating "createPreferenceHierarchy()"
|
|
||||||
*/
|
|
||||||
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||||
new BaseSearchIndexProvider(R.xml.security_advanced_settings) {
|
new BaseSearchIndexProvider(R.xml.security_advanced_settings) {
|
||||||
/**
|
/**
|
||||||
@@ -134,19 +131,26 @@ public class SecurityAdvancedSettings extends DashboardFragment {
|
|||||||
* page, and we don't want to index these entries.
|
* page, and we don't want to index these entries.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
|
public List<SearchIndexableResource> getXmlResourcesToIndex(
|
||||||
boolean enabled) {
|
Context context, boolean enabled) {
|
||||||
if (SafetyCenterManagerWrapper.get().isEnabled(context)) {
|
// NOTE: This check likely should be moved to the super method. This is done
|
||||||
|
// here to avoid potentially undesired side effects for existing implementors.
|
||||||
|
if (!isPageSearchEnabled(context)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return super.getXmlResourcesToIndex(context, enabled);
|
return super.getXmlResourcesToIndex(context, enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<AbstractPreferenceController> createPreferenceControllers(Context
|
public List<AbstractPreferenceController> createPreferenceControllers(
|
||||||
context) {
|
Context context) {
|
||||||
return buildPreferenceControllers(context, null /* lifecycle */,
|
return buildPreferenceControllers(
|
||||||
null /* host*/);
|
context, null /* lifecycle */, null /* host*/);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isPageSearchEnabled(Context context) {
|
||||||
|
return !SafetyCenterManagerWrapper.get().isEnabled(context);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import android.content.Context;
|
|||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.content.pm.UserInfo;
|
import android.content.pm.UserInfo;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
@@ -83,6 +82,7 @@ import com.android.settingslib.RestrictedPreference;
|
|||||||
import com.android.settingslib.drawable.CircleFramedDrawable;
|
import com.android.settingslib.drawable.CircleFramedDrawable;
|
||||||
import com.android.settingslib.search.SearchIndexable;
|
import com.android.settingslib.search.SearchIndexable;
|
||||||
import com.android.settingslib.search.SearchIndexableRaw;
|
import com.android.settingslib.search.SearchIndexableRaw;
|
||||||
|
import com.android.settingslib.users.CreateUserDialogController;
|
||||||
import com.android.settingslib.users.EditUserInfoController;
|
import com.android.settingslib.users.EditUserInfoController;
|
||||||
import com.android.settingslib.users.GrantAdminDialogController;
|
import com.android.settingslib.users.GrantAdminDialogController;
|
||||||
import com.android.settingslib.users.UserCreatingDialog;
|
import com.android.settingslib.users.UserCreatingDialog;
|
||||||
@@ -119,6 +119,7 @@ public class UserSettings extends SettingsPreferenceFragment
|
|||||||
|
|
||||||
/** UserId of the user being removed */
|
/** UserId of the user being removed */
|
||||||
private static final String SAVE_REMOVING_USER = "removing_user";
|
private static final String SAVE_REMOVING_USER = "removing_user";
|
||||||
|
private static final String SAVE_CREATE_USER = "create_user";
|
||||||
|
|
||||||
private static final String KEY_USER_LIST = "user_list";
|
private static final String KEY_USER_LIST = "user_list";
|
||||||
private static final String KEY_USER_ME = "user_me";
|
private static final String KEY_USER_ME = "user_me";
|
||||||
@@ -171,9 +172,6 @@ public class UserSettings extends SettingsPreferenceFragment
|
|||||||
|
|
||||||
static final int RESULT_GUEST_REMOVED = 100;
|
static final int RESULT_GUEST_REMOVED = 100;
|
||||||
|
|
||||||
private static final String KEY_ADD_USER_LONG_MESSAGE_DISPLAYED =
|
|
||||||
"key_add_user_long_message_displayed";
|
|
||||||
|
|
||||||
private static final String KEY_TITLE = "title";
|
private static final String KEY_TITLE = "title";
|
||||||
private static final String KEY_SUMMARY = "summary";
|
private static final String KEY_SUMMARY = "summary";
|
||||||
|
|
||||||
@@ -222,6 +220,8 @@ public class UserSettings extends SettingsPreferenceFragment
|
|||||||
new GrantAdminDialogController();
|
new GrantAdminDialogController();
|
||||||
private EditUserInfoController mEditUserInfoController =
|
private EditUserInfoController mEditUserInfoController =
|
||||||
new EditUserInfoController(Utils.FILE_PROVIDER_AUTHORITY);
|
new EditUserInfoController(Utils.FILE_PROVIDER_AUTHORITY);
|
||||||
|
private CreateUserDialogController mCreateUserDialogController =
|
||||||
|
new CreateUserDialogController(Utils.FILE_PROVIDER_AUTHORITY);
|
||||||
private AddUserWhenLockedPreferenceController mAddUserWhenLockedPreferenceController;
|
private AddUserWhenLockedPreferenceController mAddUserWhenLockedPreferenceController;
|
||||||
private GuestTelephonyPreferenceController mGuestTelephonyPreferenceController;
|
private GuestTelephonyPreferenceController mGuestTelephonyPreferenceController;
|
||||||
private RemoveGuestOnExitPreferenceController mRemoveGuestOnExitPreferenceController;
|
private RemoveGuestOnExitPreferenceController mRemoveGuestOnExitPreferenceController;
|
||||||
@@ -233,7 +233,7 @@ public class UserSettings extends SettingsPreferenceFragment
|
|||||||
|
|
||||||
private CharSequence mPendingUserName;
|
private CharSequence mPendingUserName;
|
||||||
private Drawable mPendingUserIcon;
|
private Drawable mPendingUserIcon;
|
||||||
private boolean mGrantAdmin;
|
private boolean mPendingUserIsAdmin;
|
||||||
|
|
||||||
// A place to cache the generated default avatar
|
// A place to cache the generated default avatar
|
||||||
private Drawable mDefaultIconDrawable;
|
private Drawable mDefaultIconDrawable;
|
||||||
@@ -348,8 +348,12 @@ public class UserSettings extends SettingsPreferenceFragment
|
|||||||
if (icicle.containsKey(SAVE_REMOVING_USER)) {
|
if (icicle.containsKey(SAVE_REMOVING_USER)) {
|
||||||
mRemovingUserId = icicle.getInt(SAVE_REMOVING_USER);
|
mRemovingUserId = icicle.getInt(SAVE_REMOVING_USER);
|
||||||
}
|
}
|
||||||
|
if (icicle.containsKey(SAVE_CREATE_USER)) {
|
||||||
|
mCreateUserDialogController.onRestoreInstanceState(icicle);
|
||||||
|
} else {
|
||||||
mEditUserInfoController.onRestoreInstanceState(icicle);
|
mEditUserInfoController.onRestoreInstanceState(icicle);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mUserCaps = UserCapabilities.create(activity);
|
mUserCaps = UserCapabilities.create(activity);
|
||||||
mUserManager = (UserManager) activity.getSystemService(Context.USER_SERVICE);
|
mUserManager = (UserManager) activity.getSystemService(Context.USER_SERVICE);
|
||||||
@@ -440,7 +444,12 @@ public class UserSettings extends SettingsPreferenceFragment
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSaveInstanceState(Bundle outState) {
|
public void onSaveInstanceState(Bundle outState) {
|
||||||
|
if (mCreateUserDialogController.isActive()) {
|
||||||
|
outState.putBoolean(SAVE_CREATE_USER, mCreateUserDialogController.isActive());
|
||||||
|
mCreateUserDialogController.onSaveInstanceState(outState);
|
||||||
|
} else {
|
||||||
mEditUserInfoController.onSaveInstanceState(outState);
|
mEditUserInfoController.onSaveInstanceState(outState);
|
||||||
|
}
|
||||||
outState.putInt(SAVE_REMOVING_USER, mRemovingUserId);
|
outState.putInt(SAVE_REMOVING_USER, mRemovingUserId);
|
||||||
super.onSaveInstanceState(outState);
|
super.onSaveInstanceState(outState);
|
||||||
}
|
}
|
||||||
@@ -448,6 +457,7 @@ public class UserSettings extends SettingsPreferenceFragment
|
|||||||
@Override
|
@Override
|
||||||
public void startActivityForResult(Intent intent, int requestCode) {
|
public void startActivityForResult(Intent intent, int requestCode) {
|
||||||
mEditUserInfoController.startingActivityForResult();
|
mEditUserInfoController.startingActivityForResult();
|
||||||
|
mCreateUserDialogController.startingActivityForResult();
|
||||||
super.startActivityForResult(intent, requestCode);
|
super.startActivityForResult(intent, requestCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -562,6 +572,7 @@ public class UserSettings extends SettingsPreferenceFragment
|
|||||||
&& resultCode == RESULT_GUEST_REMOVED) {
|
&& resultCode == RESULT_GUEST_REMOVED) {
|
||||||
scheduleGuestCreation();
|
scheduleGuestCreation();
|
||||||
} else {
|
} else {
|
||||||
|
mCreateUserDialogController.onActivityResult(requestCode, resultCode, data);
|
||||||
mEditUserInfoController.onActivityResult(requestCode, resultCode, data);
|
mEditUserInfoController.onActivityResult(requestCode, resultCode, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -704,37 +715,12 @@ public class UserSettings extends SettingsPreferenceFragment
|
|||||||
.setPositiveButton(android.R.string.ok, null)
|
.setPositiveButton(android.R.string.ok, null)
|
||||||
.create();
|
.create();
|
||||||
case DIALOG_ADD_USER: {
|
case DIALOG_ADD_USER: {
|
||||||
final SharedPreferences preferences = getActivity().getPreferences(
|
synchronized (mUserLock) {
|
||||||
Context.MODE_PRIVATE);
|
mPendingUserName = getString(
|
||||||
final boolean longMessageDisplayed = preferences.getBoolean(
|
com.android.settingslib.R.string.user_new_user_name);
|
||||||
KEY_ADD_USER_LONG_MESSAGE_DISPLAYED, false);
|
mPendingUserIcon = null;
|
||||||
final int messageResId = longMessageDisplayed
|
|
||||||
? com.android.settingslib.R.string.user_add_user_message_short
|
|
||||||
: com.android.settingslib.R.string.user_add_user_message_long;
|
|
||||||
Dialog dlg = new AlertDialog.Builder(context)
|
|
||||||
.setTitle(com.android.settingslib.R.string.user_add_user_title)
|
|
||||||
.setMessage(messageResId)
|
|
||||||
.setPositiveButton(android.R.string.ok,
|
|
||||||
new DialogInterface.OnClickListener() {
|
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
|
||||||
if (!longMessageDisplayed) {
|
|
||||||
preferences.edit().putBoolean(
|
|
||||||
KEY_ADD_USER_LONG_MESSAGE_DISPLAYED,
|
|
||||||
true).apply();
|
|
||||||
}
|
}
|
||||||
if (UserManager.isMultipleAdminEnabled()) {
|
return buildAddUserDialog(USER_TYPE_USER);
|
||||||
showDialog(DIALOG_GRANT_ADMIN);
|
|
||||||
} else {
|
|
||||||
showDialog(DIALOG_USER_PROFILE_EDITOR_ADD_USER);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.setNegativeButton(android.R.string.cancel, null)
|
|
||||||
.create();
|
|
||||||
return dlg;
|
|
||||||
}
|
|
||||||
case DIALOG_GRANT_ADMIN: {
|
|
||||||
return buildGrantAdminDialog();
|
|
||||||
}
|
}
|
||||||
case DIALOG_CHOOSE_USER_TYPE: {
|
case DIALOG_CHOOSE_USER_TYPE: {
|
||||||
List<HashMap<String, String>> data = new ArrayList<HashMap<String, String>>();
|
List<HashMap<String, String>> data = new ArrayList<HashMap<String, String>>();
|
||||||
@@ -919,17 +905,14 @@ public class UserSettings extends SettingsPreferenceFragment
|
|||||||
private Dialog buildAddUserDialog(int userType) {
|
private Dialog buildAddUserDialog(int userType) {
|
||||||
Dialog d;
|
Dialog d;
|
||||||
synchronized (mUserLock) {
|
synchronized (mUserLock) {
|
||||||
d = mEditUserInfoController.createDialog(
|
d = mCreateUserDialogController.createDialog(
|
||||||
getActivity(),
|
getActivity(),
|
||||||
this::startActivityForResult,
|
this::startActivityForResult,
|
||||||
null,
|
UserManager.isMultipleAdminEnabled(),
|
||||||
mPendingUserName.toString(),
|
(userName, userIcon, isAdmin) -> {
|
||||||
getString(userType == USER_TYPE_USER
|
|
||||||
? com.android.settingslib.R.string.user_info_settings_title
|
|
||||||
: com.android.settingslib.R.string.profile_info_settings_title),
|
|
||||||
(userName, userIcon) -> {
|
|
||||||
mPendingUserIcon = userIcon;
|
mPendingUserIcon = userIcon;
|
||||||
mPendingUserName = userName;
|
mPendingUserName = userName;
|
||||||
|
mPendingUserIsAdmin = isAdmin;
|
||||||
addUserNow(userType);
|
addUserNow(userType);
|
||||||
},
|
},
|
||||||
() -> {
|
() -> {
|
||||||
@@ -943,26 +926,6 @@ public class UserSettings extends SettingsPreferenceFragment
|
|||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Dialog buildGrantAdminDialog() {
|
|
||||||
return mGrantAdminDialogController.createDialog(
|
|
||||||
getActivity(),
|
|
||||||
(grantAdmin) -> {
|
|
||||||
mGrantAdmin = grantAdmin;
|
|
||||||
if (mGrantAdmin) {
|
|
||||||
mMetricsFeatureProvider.action(getActivity(),
|
|
||||||
SettingsEnums.ACTION_GRANT_ADMIN_FROM_SETTINGS_CREATION_DIALOG);
|
|
||||||
} else {
|
|
||||||
mMetricsFeatureProvider.action(getActivity(),
|
|
||||||
SettingsEnums.ACTION_NOT_GRANT_ADMIN_FROM_SETTINGS_CREATION_DIALOG);
|
|
||||||
}
|
|
||||||
showDialog(DIALOG_USER_PROFILE_EDITOR_ADD_USER);
|
|
||||||
},
|
|
||||||
() -> {
|
|
||||||
mGrantAdmin = false;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getDialogMetricsCategory(int dialogId) {
|
public int getDialogMetricsCategory(int dialogId) {
|
||||||
switch (dialogId) {
|
switch (dialogId) {
|
||||||
@@ -1065,7 +1028,7 @@ public class UserSettings extends SettingsPreferenceFragment
|
|||||||
userName,
|
userName,
|
||||||
mUserManager.USER_TYPE_FULL_SECONDARY,
|
mUserManager.USER_TYPE_FULL_SECONDARY,
|
||||||
0);
|
0);
|
||||||
if (mGrantAdmin) {
|
if (mPendingUserIsAdmin) {
|
||||||
mUserManager.setUserAdmin(user.id);
|
mUserManager.setUserAdmin(user.id);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -1665,6 +1628,9 @@ public class UserSettings extends SettingsPreferenceFragment
|
|||||||
synchronized (mUserLock) {
|
synchronized (mUserLock) {
|
||||||
mRemovingUserId = -1;
|
mRemovingUserId = -1;
|
||||||
updateUserList();
|
updateUserList();
|
||||||
|
if (mCreateUserDialogController.isActive()) {
|
||||||
|
mCreateUserDialogController.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ import androidx.preference.PreferenceGroup;
|
|||||||
import androidx.preference.PreferenceScreen;
|
import androidx.preference.PreferenceScreen;
|
||||||
|
|
||||||
import com.android.settings.core.FeatureFlags;
|
import com.android.settings.core.FeatureFlags;
|
||||||
|
import com.android.settings.testutils.FakeFeatureFactory;
|
||||||
|
import com.android.settings.wifi.repository.WifiHotspotRepository;
|
||||||
import com.android.settings.wifi.tether.WifiTetherAutoOffPreferenceController;
|
import com.android.settings.wifi.tether.WifiTetherAutoOffPreferenceController;
|
||||||
import com.android.settings.wifi.tether.WifiTetherSecurityPreferenceController;
|
import com.android.settings.wifi.tether.WifiTetherSecurityPreferenceController;
|
||||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||||
@@ -94,6 +96,8 @@ public class AllInOneTetherSettingsTest {
|
|||||||
mContext = spy(RuntimeEnvironment.application);
|
mContext = spy(RuntimeEnvironment.application);
|
||||||
|
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
|
when(FakeFeatureFactory.setupForTest().getWifiFeatureProvider().getWifiHotspotRepository())
|
||||||
|
.thenReturn(mock(WifiHotspotRepository.class));
|
||||||
doReturn(mWifiManager).when(mContext).getSystemService(WifiManager.class);
|
doReturn(mWifiManager).when(mContext).getSystemService(WifiManager.class);
|
||||||
doReturn(mConnectivityManager)
|
doReturn(mConnectivityManager)
|
||||||
.when(mContext).getSystemService(Context.CONNECTIVITY_SERVICE);
|
.when(mContext).getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||||
|
|||||||
@@ -19,20 +19,26 @@ package com.android.settings.accessibility;
|
|||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.AttributeSet;
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.ColorInt;
|
||||||
|
import androidx.preference.PreferenceViewHolder;
|
||||||
import androidx.test.core.app.ApplicationProvider;
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
|
import com.android.settingslib.Utils;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.Spy;
|
import org.mockito.Spy;
|
||||||
import org.mockito.junit.MockitoJUnit;
|
import org.mockito.junit.MockitoJUnit;
|
||||||
import org.mockito.junit.MockitoRule;
|
import org.mockito.junit.MockitoRule;
|
||||||
import org.robolectric.Robolectric;
|
|
||||||
import org.robolectric.RobolectricTestRunner;
|
import org.robolectric.RobolectricTestRunner;
|
||||||
|
import org.robolectric.Shadows;
|
||||||
|
|
||||||
@RunWith(RobolectricTestRunner.class)
|
@RunWith(RobolectricTestRunner.class)
|
||||||
public class FlashNotificationsPreviewPreferenceTest {
|
public class FlashNotificationsPreviewPreferenceTest {
|
||||||
@@ -41,37 +47,46 @@ public class FlashNotificationsPreviewPreferenceTest {
|
|||||||
public MockitoRule mMockitoRule = MockitoJUnit.rule();
|
public MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||||
@Spy
|
@Spy
|
||||||
private final Context mContext = ApplicationProvider.getApplicationContext();
|
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||||
private final AttributeSet mAttributeSet = Robolectric.buildAttributeSet().build();
|
private FlashNotificationsPreviewPreference mFlashNotificationsPreviewPreference;
|
||||||
|
private PreferenceViewHolder mPreferenceViewHolder;
|
||||||
|
|
||||||
@Test
|
@Before
|
||||||
public void constructor_assertLayoutResource_P00() {
|
public void setUp() {
|
||||||
FlashNotificationsPreviewPreference preference = new FlashNotificationsPreviewPreference(
|
mPreferenceViewHolder = PreferenceViewHolder.createInstanceForTests(
|
||||||
mContext);
|
LayoutInflater.from(mContext).inflate(
|
||||||
assertThat(preference.getLayoutResource())
|
R.layout.flash_notification_preview_preference, null));
|
||||||
.isEqualTo(R.layout.flash_notification_preview_preference);
|
mFlashNotificationsPreviewPreference = new FlashNotificationsPreviewPreference(mContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void constructor_assertLayoutResource_P01() {
|
public void setEnabled_true_verifyEnabledUi() {
|
||||||
FlashNotificationsPreviewPreference preference = new FlashNotificationsPreviewPreference(
|
@ColorInt final int textColorEnabled = ((TextView) mPreferenceViewHolder.findViewById(
|
||||||
mContext, mAttributeSet);
|
android.R.id.title)).getCurrentTextColor();
|
||||||
assertThat(preference.getLayoutResource())
|
|
||||||
.isEqualTo(R.layout.flash_notification_preview_preference);
|
mFlashNotificationsPreviewPreference.setEnabled(true);
|
||||||
|
mFlashNotificationsPreviewPreference.onBindViewHolder(mPreferenceViewHolder);
|
||||||
|
|
||||||
|
final View frame = mPreferenceViewHolder.findViewById(R.id.frame);
|
||||||
|
final int backgroundResId = Shadows.shadowOf(frame.getBackground()).getCreatedFromResId();
|
||||||
|
assertThat(backgroundResId).isEqualTo(R.drawable.settingslib_switch_bar_bg_on);
|
||||||
|
final TextView title = (TextView) mPreferenceViewHolder.findViewById(android.R.id.title);
|
||||||
|
assertThat(title.getAlpha()).isEqualTo(1f);
|
||||||
|
assertThat(title.getCurrentTextColor()).isEqualTo(textColorEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void constructor_assertLayoutResource_P02() {
|
public void setEnabled_false_verifyDisabledUi() {
|
||||||
FlashNotificationsPreviewPreference preference = new FlashNotificationsPreviewPreference(
|
@ColorInt final int textColorDisabled = Utils.getColorAttrDefaultColor(mContext,
|
||||||
mContext, mAttributeSet, 0);
|
android.R.attr.textColorPrimary);
|
||||||
assertThat(preference.getLayoutResource())
|
|
||||||
.isEqualTo(R.layout.flash_notification_preview_preference);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
mFlashNotificationsPreviewPreference.setEnabled(false);
|
||||||
public void constructor_assertLayoutResource_P03() {
|
mFlashNotificationsPreviewPreference.onBindViewHolder(mPreferenceViewHolder);
|
||||||
FlashNotificationsPreviewPreference preference = new FlashNotificationsPreviewPreference(
|
|
||||||
mContext, mAttributeSet, 0, 0);
|
final View frame = mPreferenceViewHolder.findViewById(R.id.frame);
|
||||||
assertThat(preference.getLayoutResource())
|
final int backgroundResId = Shadows.shadowOf(frame.getBackground()).getCreatedFromResId();
|
||||||
.isEqualTo(R.layout.flash_notification_preview_preference);
|
assertThat(backgroundResId).isEqualTo(R.drawable.switch_bar_bg_disabled);
|
||||||
|
final TextView title = (TextView) mPreferenceViewHolder.findViewById(android.R.id.title);
|
||||||
|
assertThat(title.getAlpha()).isEqualTo(0.38f);
|
||||||
|
assertThat(title.getCurrentTextColor()).isEqualTo(textColorDisabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -53,7 +53,6 @@ import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.CancellationSignal;
|
import android.os.CancellationSignal;
|
||||||
import android.os.Vibrator;
|
import android.os.Vibrator;
|
||||||
import android.util.FeatureFlagUtils;
|
|
||||||
import android.view.Display;
|
import android.view.Display;
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -203,8 +202,6 @@ public class FingerprintEnrollEnrollingTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void fingerprintUdfpsOverlayEnrollment_showOverlayPortrait() {
|
public void fingerprintUdfpsOverlayEnrollment_showOverlayPortrait() {
|
||||||
FeatureFlagUtils.setEnabled(mContext,
|
|
||||||
FeatureFlagUtils.SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS, true);
|
|
||||||
initializeActivityFor(TYPE_UDFPS_OPTICAL);
|
initializeActivityFor(TYPE_UDFPS_OPTICAL);
|
||||||
when(mMockDisplay.getRotation()).thenReturn(Surface.ROTATION_0);
|
when(mMockDisplay.getRotation()).thenReturn(Surface.ROTATION_0);
|
||||||
|
|
||||||
@@ -216,8 +213,6 @@ public class FingerprintEnrollEnrollingTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void fingerprintUdfpsOverlayEnrollment_showOverlayLandscape() {
|
public void fingerprintUdfpsOverlayEnrollment_showOverlayLandscape() {
|
||||||
FeatureFlagUtils.setEnabled(mContext,
|
|
||||||
FeatureFlagUtils.SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS, true);
|
|
||||||
initializeActivityFor(TYPE_UDFPS_OPTICAL);
|
initializeActivityFor(TYPE_UDFPS_OPTICAL);
|
||||||
when(mMockDisplay.getRotation()).thenReturn(Surface.ROTATION_90);
|
when(mMockDisplay.getRotation()).thenReturn(Surface.ROTATION_90);
|
||||||
|
|
||||||
@@ -229,8 +224,6 @@ public class FingerprintEnrollEnrollingTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void fingerprintUdfpsOverlayEnrollment_usesCorrectProgressBarFillColor() {
|
public void fingerprintUdfpsOverlayEnrollment_usesCorrectProgressBarFillColor() {
|
||||||
FeatureFlagUtils.setEnabled(mContext,
|
|
||||||
FeatureFlagUtils.SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS, true);
|
|
||||||
initializeActivityFor(TYPE_UDFPS_OPTICAL);
|
initializeActivityFor(TYPE_UDFPS_OPTICAL);
|
||||||
final TypedArray ta = mActivity.obtainStyledAttributes(null,
|
final TypedArray ta = mActivity.obtainStyledAttributes(null,
|
||||||
R.styleable.BiometricsEnrollView, R.attr.biometricsEnrollStyle,
|
R.styleable.BiometricsEnrollView, R.attr.biometricsEnrollStyle,
|
||||||
@@ -250,9 +243,7 @@ public class FingerprintEnrollEnrollingTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void fingerprintUdfpsOverlayEnrollment_checkViewOverlapPortrait() {
|
public void fingerprintUdfpsOverlayEnrollment_checkViewOverlapPortrait() {
|
||||||
FeatureFlagUtils.setEnabled(mContext,
|
when(mMockDisplay.getRotation()).thenReturn(Surface.ROTATION_0);
|
||||||
FeatureFlagUtils.SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS, true);
|
|
||||||
when(mMockDisplay.getRotation()).thenReturn(Surface.ROTATION_90);
|
|
||||||
initializeActivityFor(TYPE_UDFPS_OPTICAL);
|
initializeActivityFor(TYPE_UDFPS_OPTICAL);
|
||||||
|
|
||||||
final GlifLayout defaultLayout = mActivity.findViewById(R.id.setup_wizard_layout);
|
final GlifLayout defaultLayout = mActivity.findViewById(R.id.setup_wizard_layout);
|
||||||
@@ -320,10 +311,36 @@ public class FingerprintEnrollEnrollingTest {
|
|||||||
.intersect(rectUdfpsEnrollView.get())).isFalse();
|
.intersect(rectUdfpsEnrollView.get())).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void fingerprintUdfpsOverlayEnrollment_descriptionViewGoneWithOverlap() {
|
||||||
|
initializeActivityWithoutCreate(TYPE_UDFPS_OPTICAL);
|
||||||
|
doReturn(true).when(mActivity).hasOverlap(any(), any());
|
||||||
|
when(mMockDisplay.getRotation()).thenReturn(Surface.ROTATION_0);
|
||||||
|
createActivity();
|
||||||
|
|
||||||
|
final GlifLayout defaultLayout = spy(mActivity.findViewById(R.id.setup_wizard_layout));
|
||||||
|
final TextView descriptionTextView = defaultLayout.getDescriptionTextView();
|
||||||
|
|
||||||
|
defaultLayout.getViewTreeObserver().dispatchOnDraw();
|
||||||
|
assertThat(descriptionTextView.getVisibility()).isEqualTo(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void fingerprintUdfpsOverlayEnrollment_descriptionViewVisibleWithoutOverlap() {
|
||||||
|
initializeActivityWithoutCreate(TYPE_UDFPS_OPTICAL);
|
||||||
|
doReturn(false).when(mActivity).hasOverlap(any(), any());
|
||||||
|
when(mMockDisplay.getRotation()).thenReturn(Surface.ROTATION_0);
|
||||||
|
createActivity();
|
||||||
|
|
||||||
|
final GlifLayout defaultLayout = spy(mActivity.findViewById(R.id.setup_wizard_layout));
|
||||||
|
final TextView descriptionTextView = defaultLayout.getDescriptionTextView();
|
||||||
|
|
||||||
|
defaultLayout.getViewTreeObserver().dispatchOnDraw();
|
||||||
|
assertThat(descriptionTextView.getVisibility()).isEqualTo(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void forwardEnrollProgressEvents() {
|
public void forwardEnrollProgressEvents() {
|
||||||
FeatureFlagUtils.setEnabled(mContext,
|
|
||||||
FeatureFlagUtils.SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS, true);
|
|
||||||
initializeActivityFor(TYPE_UDFPS_OPTICAL);
|
initializeActivityFor(TYPE_UDFPS_OPTICAL);
|
||||||
|
|
||||||
EnrollListener listener = new EnrollListener(mActivity);
|
EnrollListener listener = new EnrollListener(mActivity);
|
||||||
@@ -337,8 +354,6 @@ public class FingerprintEnrollEnrollingTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void forwardEnrollHelpEvents() {
|
public void forwardEnrollHelpEvents() {
|
||||||
FeatureFlagUtils.setEnabled(mContext,
|
|
||||||
FeatureFlagUtils.SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS, true);
|
|
||||||
initializeActivityFor(TYPE_UDFPS_OPTICAL);
|
initializeActivityFor(TYPE_UDFPS_OPTICAL);
|
||||||
|
|
||||||
EnrollListener listener = new EnrollListener(mActivity);
|
EnrollListener listener = new EnrollListener(mActivity);
|
||||||
@@ -352,8 +367,6 @@ public class FingerprintEnrollEnrollingTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void forwardEnrollAcquiredEvents() {
|
public void forwardEnrollAcquiredEvents() {
|
||||||
FeatureFlagUtils.setEnabled(mContext,
|
|
||||||
FeatureFlagUtils.SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS, true);
|
|
||||||
initializeActivityFor(TYPE_UDFPS_OPTICAL);
|
initializeActivityFor(TYPE_UDFPS_OPTICAL);
|
||||||
|
|
||||||
EnrollListener listener = new EnrollListener(mActivity);
|
EnrollListener listener = new EnrollListener(mActivity);
|
||||||
@@ -368,8 +381,6 @@ public class FingerprintEnrollEnrollingTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void forwardEnrollPointerDownEvents() {
|
public void forwardEnrollPointerDownEvents() {
|
||||||
FeatureFlagUtils.setEnabled(mContext,
|
|
||||||
FeatureFlagUtils.SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS, true);
|
|
||||||
initializeActivityFor(TYPE_UDFPS_OPTICAL);
|
initializeActivityFor(TYPE_UDFPS_OPTICAL);
|
||||||
|
|
||||||
EnrollListener listener = new EnrollListener(mActivity);
|
EnrollListener listener = new EnrollListener(mActivity);
|
||||||
@@ -383,8 +394,6 @@ public class FingerprintEnrollEnrollingTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void forwardEnrollPointerUpEvents() {
|
public void forwardEnrollPointerUpEvents() {
|
||||||
FeatureFlagUtils.setEnabled(mContext,
|
|
||||||
FeatureFlagUtils.SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS, true);
|
|
||||||
initializeActivityFor(TYPE_UDFPS_OPTICAL);
|
initializeActivityFor(TYPE_UDFPS_OPTICAL);
|
||||||
|
|
||||||
EnrollListener listener = new EnrollListener(mActivity);
|
EnrollListener listener = new EnrollListener(mActivity);
|
||||||
|
|||||||
@@ -20,8 +20,11 @@ import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFP
|
|||||||
|
|
||||||
import static com.android.settings.biometrics.fingerprint.FingerprintSettings.FingerprintSettingsFragment;
|
import static com.android.settings.biometrics.fingerprint.FingerprintSettings.FingerprintSettingsFragment;
|
||||||
import static com.android.settings.biometrics.fingerprint.FingerprintSettings.FingerprintSettingsFragment.ADD_FINGERPRINT_REQUEST;
|
import static com.android.settings.biometrics.fingerprint.FingerprintSettings.FingerprintSettingsFragment.ADD_FINGERPRINT_REQUEST;
|
||||||
|
import static com.android.settings.biometrics.fingerprint.FingerprintSettings.FingerprintSettingsFragment.CHOOSE_LOCK_GENERIC_REQUEST;
|
||||||
import static com.android.settings.biometrics.fingerprint.FingerprintSettings.FingerprintSettingsFragment.KEY_FINGERPRINT_ADD;
|
import static com.android.settings.biometrics.fingerprint.FingerprintSettings.FingerprintSettingsFragment.KEY_FINGERPRINT_ADD;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
import static org.mockito.ArgumentMatchers.anyString;
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
@@ -54,6 +57,7 @@ import com.android.settings.biometrics.BiometricsSplitScreenDialog;
|
|||||||
import com.android.settings.password.ChooseLockSettingsHelper;
|
import com.android.settings.password.ChooseLockSettingsHelper;
|
||||||
import com.android.settings.testutils.FakeFeatureFactory;
|
import com.android.settings.testutils.FakeFeatureFactory;
|
||||||
import com.android.settings.testutils.shadow.ShadowFragment;
|
import com.android.settings.testutils.shadow.ShadowFragment;
|
||||||
|
import com.android.settings.testutils.shadow.ShadowLockPatternUtils;
|
||||||
import com.android.settings.testutils.shadow.ShadowSettingsPreferenceFragment;
|
import com.android.settings.testutils.shadow.ShadowSettingsPreferenceFragment;
|
||||||
import com.android.settings.testutils.shadow.ShadowUserManager;
|
import com.android.settings.testutils.shadow.ShadowUserManager;
|
||||||
import com.android.settings.testutils.shadow.ShadowUtils;
|
import com.android.settings.testutils.shadow.ShadowUtils;
|
||||||
@@ -63,6 +67,7 @@ import org.junit.Before;
|
|||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.junit.MockitoJUnit;
|
import org.mockito.junit.MockitoJUnit;
|
||||||
import org.mockito.junit.MockitoRule;
|
import org.mockito.junit.MockitoRule;
|
||||||
@@ -74,7 +79,7 @@ import java.util.ArrayList;
|
|||||||
|
|
||||||
@RunWith(RobolectricTestRunner.class)
|
@RunWith(RobolectricTestRunner.class)
|
||||||
@Config(shadows = {ShadowSettingsPreferenceFragment.class, ShadowUtils.class, ShadowFragment.class,
|
@Config(shadows = {ShadowSettingsPreferenceFragment.class, ShadowUtils.class, ShadowFragment.class,
|
||||||
ShadowUserManager.class})
|
ShadowUserManager.class, ShadowLockPatternUtils.class})
|
||||||
public class FingerprintSettingsFragmentTest {
|
public class FingerprintSettingsFragmentTest {
|
||||||
private FingerprintSettingsFragment mFragment;
|
private FingerprintSettingsFragment mFragment;
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
@@ -92,10 +97,62 @@ public class FingerprintSettingsFragmentTest {
|
|||||||
doReturn(true).when(mFingerprintManager).isHardwareDetected();
|
doReturn(true).when(mFingerprintManager).isHardwareDetected();
|
||||||
ShadowUtils.setFingerprintManager(mFingerprintManager);
|
ShadowUtils.setFingerprintManager(mFingerprintManager);
|
||||||
FakeFeatureFactory.setupForTest();
|
FakeFeatureFactory.setupForTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
ShadowUtils.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddFingerprint_inFullScreen_noDialog() {
|
||||||
|
setUpFragment(false);
|
||||||
|
// Click "Add Fingerprint"
|
||||||
|
final Preference preference = new Preference(mContext);
|
||||||
|
preference.setKey(KEY_FINGERPRINT_ADD);
|
||||||
|
mFragment.onPreferenceTreeClick(preference);
|
||||||
|
|
||||||
|
verify(mFragment).startActivityForResult(any(), eq(ADD_FINGERPRINT_REQUEST));
|
||||||
|
verify(mFragmentTransaction, never()).add(any(),
|
||||||
|
eq(BiometricsSplitScreenDialog.class.getName()));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddFingerprint_inMultiWindow_showsDialog() {
|
||||||
|
setUpFragment(false);
|
||||||
|
|
||||||
|
doReturn(true).when(mActivity).isInMultiWindowMode();
|
||||||
|
|
||||||
|
// Click "Add Fingerprint"
|
||||||
|
final Preference preference = new Preference(mContext);
|
||||||
|
preference.setKey(KEY_FINGERPRINT_ADD);
|
||||||
|
mFragment.onPreferenceTreeClick(preference);
|
||||||
|
|
||||||
|
verify(mFragment, times(0)).startActivityForResult(any(), eq(ADD_FINGERPRINT_REQUEST));
|
||||||
|
verify(mFragmentTransaction).add(any(), eq(BiometricsSplitScreenDialog.class.getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testChooseLockKeyForFingerprint() {
|
||||||
|
setUpFragment(true);
|
||||||
|
ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(
|
||||||
|
Intent.class);
|
||||||
|
verify(mFragment).startActivityForResult(intentArgumentCaptor.capture(),
|
||||||
|
eq(CHOOSE_LOCK_GENERIC_REQUEST));
|
||||||
|
|
||||||
|
Intent intent = intentArgumentCaptor.getValue();
|
||||||
|
assertThat(intent.getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT,
|
||||||
|
false)).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setUpFragment(boolean showChooseLock) {
|
||||||
Intent intent = new Intent();
|
Intent intent = new Intent();
|
||||||
|
if (!showChooseLock) {
|
||||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, new byte[0]);
|
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, new byte[0]);
|
||||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, 1L);
|
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, 1L);
|
||||||
|
}
|
||||||
|
|
||||||
mActivity = spy(Robolectric.buildActivity(FragmentActivity.class, intent).get());
|
mActivity = spy(Robolectric.buildActivity(FragmentActivity.class, intent).get());
|
||||||
mContext = spy(ApplicationProvider.getApplicationContext());
|
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||||
|
|
||||||
@@ -112,49 +169,12 @@ public class FingerprintSettingsFragmentTest {
|
|||||||
doNothing().when(mFragment).startActivityForResult(any(Intent.class), anyInt());
|
doNothing().when(mFragment).startActivityForResult(any(Intent.class), anyInt());
|
||||||
|
|
||||||
setSensor();
|
setSensor();
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
public void tearDown() {
|
|
||||||
ShadowUtils.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testAddFingerprint_inFullScreen_noDialog() {
|
|
||||||
// Start fragment
|
// Start fragment
|
||||||
mFragment.onAttach(mContext);
|
mFragment.onAttach(mContext);
|
||||||
mFragment.onCreate(null);
|
mFragment.onCreate(null);
|
||||||
mFragment.onCreateView(LayoutInflater.from(mContext), mock(ViewGroup.class), Bundle.EMPTY);
|
mFragment.onCreateView(LayoutInflater.from(mContext), mock(ViewGroup.class), Bundle.EMPTY);
|
||||||
mFragment.onResume();
|
mFragment.onResume();
|
||||||
|
|
||||||
// Click "Add Fingerprint"
|
|
||||||
final Preference preference = new Preference(mContext);
|
|
||||||
preference.setKey(KEY_FINGERPRINT_ADD);
|
|
||||||
mFragment.onPreferenceTreeClick(preference);
|
|
||||||
|
|
||||||
verify(mFragment).startActivityForResult(any(), eq(ADD_FINGERPRINT_REQUEST));
|
|
||||||
verify(mFragmentTransaction, never()).add(any(),
|
|
||||||
eq(BiometricsSplitScreenDialog.class.getName()));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testAddFingerprint_inMultiWindow_showsDialog() {
|
|
||||||
// Start fragment
|
|
||||||
mFragment.onAttach(mContext);
|
|
||||||
mFragment.onCreate(null);
|
|
||||||
mFragment.onCreateView(LayoutInflater.from(mContext), mock(ViewGroup.class), Bundle.EMPTY);
|
|
||||||
mFragment.onResume();
|
|
||||||
|
|
||||||
doReturn(true).when(mActivity).isInMultiWindowMode();
|
|
||||||
|
|
||||||
// Click "Add Fingerprint"
|
|
||||||
final Preference preference = new Preference(mContext);
|
|
||||||
preference.setKey(KEY_FINGERPRINT_ADD);
|
|
||||||
mFragment.onPreferenceTreeClick(preference);
|
|
||||||
|
|
||||||
verify(mFragment, times(0)).startActivityForResult(any(), eq(ADD_FINGERPRINT_REQUEST));
|
|
||||||
verify(mFragmentTransaction).add(any(), eq(BiometricsSplitScreenDialog.class.getName()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setSensor() {
|
private void setSensor() {
|
||||||
|
|||||||
@@ -56,6 +56,9 @@ import org.robolectric.RobolectricTestRunner;
|
|||||||
import org.robolectric.RuntimeEnvironment;
|
import org.robolectric.RuntimeEnvironment;
|
||||||
import org.robolectric.annotation.Config;
|
import org.robolectric.annotation.Config;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
@RunWith(RobolectricTestRunner.class)
|
@RunWith(RobolectricTestRunner.class)
|
||||||
@Config(shadows = {ShadowEntityHeaderController.class, ShadowDeviceConfig.class})
|
@Config(shadows = {ShadowEntityHeaderController.class, ShadowDeviceConfig.class})
|
||||||
public class AdvancedBluetoothDetailsHeaderControllerTest {
|
public class AdvancedBluetoothDetailsHeaderControllerTest {
|
||||||
@@ -380,40 +383,68 @@ public class AdvancedBluetoothDetailsHeaderControllerTest {
|
|||||||
SettingsUIDeviceConfig.BT_ADVANCED_HEADER_ENABLED, "true", true);
|
SettingsUIDeviceConfig.BT_ADVANCED_HEADER_ENABLED, "true", true);
|
||||||
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
|
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
|
||||||
.thenReturn("true".getBytes());
|
.thenReturn("true".getBytes());
|
||||||
|
Set<CachedBluetoothDevice> cacheBluetoothDevices = new HashSet<>();
|
||||||
|
when(mCachedDevice.getMemberDevice()).thenReturn(cacheBluetoothDevices);
|
||||||
|
|
||||||
mController.onStart();
|
mController.onStart();
|
||||||
|
|
||||||
|
verify(mCachedDevice).registerCallback(mController);
|
||||||
verify(mBluetoothAdapter).addOnMetadataChangedListener(mBluetoothDevice,
|
verify(mBluetoothAdapter).addOnMetadataChangedListener(mBluetoothDevice,
|
||||||
mContext.getMainExecutor(), mController.mMetadataListener);
|
mContext.getMainExecutor(), mController.mMetadataListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onStop_isRegisterCallback_unregisterCallback() {
|
public void onStart_notAvailable_notNeedToRegisterCallback() {
|
||||||
mController.mIsRegisterCallback = true;
|
|
||||||
|
|
||||||
mController.onStop();
|
|
||||||
|
|
||||||
verify(mBluetoothAdapter).removeOnMetadataChangedListener(mBluetoothDevice,
|
|
||||||
mController.mMetadataListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void onStart_notAvailable_registerCallback() {
|
|
||||||
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
|
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
|
||||||
.thenReturn("false".getBytes());
|
.thenReturn("false".getBytes());
|
||||||
|
|
||||||
mController.onStart();
|
mController.onStart();
|
||||||
|
|
||||||
|
verify(mCachedDevice, never()).registerCallback(mController);
|
||||||
verify(mBluetoothAdapter, never()).addOnMetadataChangedListener(mBluetoothDevice,
|
verify(mBluetoothAdapter, never()).addOnMetadataChangedListener(mBluetoothDevice,
|
||||||
mContext.getMainExecutor(), mController.mMetadataListener);
|
mContext.getMainExecutor(), mController.mMetadataListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onStop_notRegisterCallback_unregisterCallback() {
|
public void onStart_isAvailableButNoBluetoothDevice_notNeedToRegisterCallback() {
|
||||||
mController.mIsRegisterCallback = false;
|
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SETTINGS_UI,
|
||||||
|
SettingsUIDeviceConfig.BT_ADVANCED_HEADER_ENABLED, "true", true);
|
||||||
|
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
|
||||||
|
.thenReturn("true".getBytes());
|
||||||
|
when(mCachedDevice.getDevice()).thenReturn(null);
|
||||||
|
Set<CachedBluetoothDevice> cacheBluetoothDevices = new HashSet<>();
|
||||||
|
when(mCachedDevice.getMemberDevice()).thenReturn(cacheBluetoothDevices);
|
||||||
|
|
||||||
|
mController.onStart();
|
||||||
|
|
||||||
|
verify(mCachedDevice, never()).registerCallback(mController);
|
||||||
|
verify(mBluetoothAdapter, never()).addOnMetadataChangedListener(mBluetoothDevice,
|
||||||
|
mContext.getMainExecutor(), mController.mMetadataListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onStop_availableAndHasBluetoothDevice_unregisterCallback() {
|
||||||
|
onStart_isAvailable_registerCallback();
|
||||||
|
|
||||||
mController.onStop();
|
mController.onStop();
|
||||||
|
|
||||||
|
verify(mCachedDevice).unregisterCallback(mController);
|
||||||
|
verify(mBluetoothAdapter).removeOnMetadataChangedListener(mBluetoothDevice,
|
||||||
|
mController.mMetadataListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onStop_noBluetoothDevice_noNeedToUnregisterCallback() {
|
||||||
|
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SETTINGS_UI,
|
||||||
|
SettingsUIDeviceConfig.BT_ADVANCED_HEADER_ENABLED, "true", true);
|
||||||
|
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
|
||||||
|
.thenReturn("true".getBytes());
|
||||||
|
when(mCachedDevice.getDevice()).thenReturn(null);
|
||||||
|
|
||||||
|
mController.onStart();
|
||||||
|
mController.onStop();
|
||||||
|
|
||||||
|
verify(mCachedDevice, never()).unregisterCallback(mController);
|
||||||
verify(mBluetoothAdapter, never()).removeOnMetadataChangedListener(mBluetoothDevice,
|
verify(mBluetoothAdapter, never()).removeOnMetadataChangedListener(mBluetoothDevice,
|
||||||
mController.mMetadataListener);
|
mController.mMetadataListener);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,9 +81,10 @@ public class GraphicsDriverEnableAngleAsSystemDriverControllerTest {
|
|||||||
// since GraphicsEnvironment is mocked in Robolectric test environment,
|
// since GraphicsEnvironment is mocked in Robolectric test environment,
|
||||||
// we will override the system property persist.graphics.egl as if it is changed by
|
// we will override the system property persist.graphics.egl as if it is changed by
|
||||||
// mGraphicsEnvironment.toggleAngleAsSystemDriver(true).
|
// mGraphicsEnvironment.toggleAngleAsSystemDriver(true).
|
||||||
// TODO: b/270994705 yuxinhu:
|
|
||||||
// add test coverage to test mGraphicsEnvironment.toggleAngleAsSystemDriver()
|
// for test that actually verifies mGraphicsEnvironment.toggleAngleAsSystemDriver(true)
|
||||||
// works properly on Android devices / emulators.
|
// on a device/emulator, please refer to
|
||||||
|
// GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest
|
||||||
ShadowSystemProperties.override(PROPERTY_PERSISTENT_GRAPHICS_EGL, ANGLE_DRIVER_SUFFIX);
|
ShadowSystemProperties.override(PROPERTY_PERSISTENT_GRAPHICS_EGL, ANGLE_DRIVER_SUFFIX);
|
||||||
mController.onPreferenceChange(mPreference, true);
|
mController.onPreferenceChange(mPreference, true);
|
||||||
final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
|
final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
|
||||||
@@ -97,9 +98,10 @@ public class GraphicsDriverEnableAngleAsSystemDriverControllerTest {
|
|||||||
// since GraphicsEnvironment is mocked in Robolectric test environment,
|
// since GraphicsEnvironment is mocked in Robolectric test environment,
|
||||||
// we will override the system property persist.graphics.egl as if it is changed by
|
// we will override the system property persist.graphics.egl as if it is changed by
|
||||||
// mGraphicsEnvironment.toggleAngleAsSystemDriver(false).
|
// mGraphicsEnvironment.toggleAngleAsSystemDriver(false).
|
||||||
// TODO: b/270994705 yuxinhu:
|
|
||||||
// add test coverage to test mGraphicsEnvironment.toggleAngleAsSystemDriver()
|
// for test that actually verifies mGraphicsEnvironment.toggleAngleAsSystemDriver(true)
|
||||||
// works properly on Android devices / emulators.
|
// on a device/emulator, please refer to
|
||||||
|
// GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest
|
||||||
ShadowSystemProperties.override(PROPERTY_PERSISTENT_GRAPHICS_EGL, "");
|
ShadowSystemProperties.override(PROPERTY_PERSISTENT_GRAPHICS_EGL, "");
|
||||||
mController.onPreferenceChange(mPreference, false);
|
mController.onPreferenceChange(mPreference, false);
|
||||||
final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
|
final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
|
||||||
@@ -124,20 +126,14 @@ public class GraphicsDriverEnableAngleAsSystemDriverControllerTest {
|
|||||||
@Test
|
@Test
|
||||||
public void updateState_angleSupported_angleUsed_preferenceShouldBeChecked() {
|
public void updateState_angleSupported_angleUsed_preferenceShouldBeChecked() {
|
||||||
ShadowSystemProperties.override(PROPERTY_RO_GFX_ANGLE_SUPPORTED, "true");
|
ShadowSystemProperties.override(PROPERTY_RO_GFX_ANGLE_SUPPORTED, "true");
|
||||||
// TODO: b/270994705 yuxinhu:
|
|
||||||
// add test coverage to test mGraphicsEnvironment.toggleAngleAsSystemDriver()
|
|
||||||
// works properly on Android devices / emulators.
|
|
||||||
ShadowSystemProperties.override(PROPERTY_PERSISTENT_GRAPHICS_EGL, ANGLE_DRIVER_SUFFIX);
|
ShadowSystemProperties.override(PROPERTY_PERSISTENT_GRAPHICS_EGL, ANGLE_DRIVER_SUFFIX);
|
||||||
mController.updateState(mPreference);
|
mController.updateState(mPreference);
|
||||||
verify(mPreference).setChecked(true); //false
|
verify(mPreference).setChecked(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void updateState_angleSupported_angleNotUsed_preferenceShouldNotBeChecked() {
|
public void updateState_angleSupported_angleNotUsed_preferenceShouldNotBeChecked() {
|
||||||
ShadowSystemProperties.override(PROPERTY_RO_GFX_ANGLE_SUPPORTED, "true");
|
ShadowSystemProperties.override(PROPERTY_RO_GFX_ANGLE_SUPPORTED, "true");
|
||||||
// TODO: b/270994705 yuxinhu:
|
|
||||||
// add test coverage to test mGraphicsEnvironment.toggleAngleAsSystemDriver(false)
|
|
||||||
// works properly on Android devices / emulators.
|
|
||||||
ShadowSystemProperties.override(PROPERTY_PERSISTENT_GRAPHICS_EGL, "");
|
ShadowSystemProperties.override(PROPERTY_PERSISTENT_GRAPHICS_EGL, "");
|
||||||
mController.updateState(mPreference);
|
mController.updateState(mPreference);
|
||||||
verify(mPreference).setChecked(false);
|
verify(mPreference).setChecked(false);
|
||||||
|
|||||||
@@ -70,6 +70,8 @@ import org.robolectric.annotation.Implementation;
|
|||||||
import org.robolectric.annotation.Implements;
|
import org.robolectric.annotation.Implements;
|
||||||
import org.robolectric.annotation.Resetter;
|
import org.robolectric.annotation.Resetter;
|
||||||
|
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -84,6 +86,8 @@ public final class BatteryBackupHelperTest {
|
|||||||
private static final int UID1 = 1;
|
private static final int UID1 = 1;
|
||||||
|
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
|
private PrintWriter mPrintWriter;
|
||||||
|
private StringWriter mStringWriter;
|
||||||
private BatteryBackupHelper mBatteryBackupHelper;
|
private BatteryBackupHelper mBatteryBackupHelper;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
@@ -109,6 +113,8 @@ public final class BatteryBackupHelperTest {
|
|||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
mContext = spy(RuntimeEnvironment.application);
|
mContext = spy(RuntimeEnvironment.application);
|
||||||
|
mStringWriter = new StringWriter();
|
||||||
|
mPrintWriter = new PrintWriter(mStringWriter);
|
||||||
doReturn(mContext).when(mContext).getApplicationContext();
|
doReturn(mContext).when(mContext).getApplicationContext();
|
||||||
doReturn(mAppOpsManager).when(mContext).getSystemService(AppOpsManager.class);
|
doReturn(mAppOpsManager).when(mContext).getSystemService(AppOpsManager.class);
|
||||||
doReturn(mUserManager).when(mContext).getSystemService(UserManager.class);
|
doReturn(mUserManager).when(mContext).getSystemService(UserManager.class);
|
||||||
@@ -126,6 +132,7 @@ public final class BatteryBackupHelperTest {
|
|||||||
@After
|
@After
|
||||||
public void resetShadows() {
|
public void resetShadows() {
|
||||||
ShadowUserHandle.reset();
|
ShadowUserHandle.reset();
|
||||||
|
BatteryBackupHelper.getSharedPreferences(mContext).edit().clear().apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -216,6 +223,8 @@ public final class BatteryBackupHelperTest {
|
|||||||
// 2 for UNRESTRICTED mode and 1 for RESTRICTED mode.
|
// 2 for UNRESTRICTED mode and 1 for RESTRICTED mode.
|
||||||
final String expectedResult = PACKAGE_NAME1 + ":2," + PACKAGE_NAME2 + ":1,";
|
final String expectedResult = PACKAGE_NAME1 + ":2," + PACKAGE_NAME2 + ":1,";
|
||||||
verifyBackupData(expectedResult);
|
verifyBackupData(expectedResult);
|
||||||
|
verifyDumpHistoryData("com.android.testing.1\taction:BACKUP\tevent:mode: 2");
|
||||||
|
verifyDumpHistoryData("com.android.testing.2\taction:BACKUP\tevent:mode: 1");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -232,6 +241,7 @@ public final class BatteryBackupHelperTest {
|
|||||||
// "com.android.testing.2" for RESTRICTED mode.
|
// "com.android.testing.2" for RESTRICTED mode.
|
||||||
final String expectedResult = PACKAGE_NAME2 + ":1,";
|
final String expectedResult = PACKAGE_NAME2 + ":1,";
|
||||||
verifyBackupData(expectedResult);
|
verifyBackupData(expectedResult);
|
||||||
|
verifyDumpHistoryData("com.android.testing.2\taction:BACKUP\tevent:mode: 1");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -248,6 +258,7 @@ public final class BatteryBackupHelperTest {
|
|||||||
// "com.android.testing.2" for RESTRICTED mode.
|
// "com.android.testing.2" for RESTRICTED mode.
|
||||||
final String expectedResult = PACKAGE_NAME2 + ":1,";
|
final String expectedResult = PACKAGE_NAME2 + ":1,";
|
||||||
verifyBackupData(expectedResult);
|
verifyBackupData(expectedResult);
|
||||||
|
verifyDumpHistoryData("com.android.testing.2\taction:BACKUP\tevent:mode: 1");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -357,6 +368,11 @@ public final class BatteryBackupHelperTest {
|
|||||||
doReturn(dataKey).when(mBackupDataInputStream).getKey();
|
doReturn(dataKey).when(mBackupDataInputStream).getKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void verifyDumpHistoryData(String expectedResult) {
|
||||||
|
BatteryBackupHelper.dumpHistoricalData(mContext, mPrintWriter);
|
||||||
|
assertThat(mStringWriter.toString().contains(expectedResult)).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
private void verifyBackupData(String expectedResult) throws Exception {
|
private void verifyBackupData(String expectedResult) throws Exception {
|
||||||
final byte[] expectedBytes = expectedResult.getBytes();
|
final byte[] expectedBytes = expectedResult.getBytes();
|
||||||
final ArgumentCaptor<byte[]> captor = ArgumentCaptor.forClass(byte[].class);
|
final ArgumentCaptor<byte[]> captor = ArgumentCaptor.forClass(byte[].class);
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ public final class BatteryHistoricalLogUtilTest {
|
|||||||
@Test
|
@Test
|
||||||
public void printHistoricalLog_withDefaultLogs() {
|
public void printHistoricalLog_withDefaultLogs() {
|
||||||
BatteryHistoricalLogUtil.printBatteryOptimizeHistoricalLog(mContext, mTestPrintWriter);
|
BatteryHistoricalLogUtil.printBatteryOptimizeHistoricalLog(mContext, mTestPrintWriter);
|
||||||
assertThat(mTestStringWriter.toString()).contains("No past logs");
|
assertThat(mTestStringWriter.toString()).contains("nothing to dump");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -58,7 +58,7 @@ public final class BatteryHistoricalLogUtilTest {
|
|||||||
BatteryHistoricalLogUtil.printBatteryOptimizeHistoricalLog(mContext, mTestPrintWriter);
|
BatteryHistoricalLogUtil.printBatteryOptimizeHistoricalLog(mContext, mTestPrintWriter);
|
||||||
|
|
||||||
assertThat(mTestStringWriter.toString()).contains(
|
assertThat(mTestStringWriter.toString()).contains(
|
||||||
"pkg1\tAction:APPLY\tEvent:logs\tTimestamp:");
|
"pkg1\taction:APPLY\tevent:logs");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -133,18 +133,12 @@ public class MobileNetworkSummaryControllerTest {
|
|||||||
assertThat(mController.isAvailable()).isFalse();
|
assertThat(mController.isAvailable()).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
@Test
|
||||||
public void getSummary_noSubscriptions_correctSummaryAndClickHandler() {
|
public void getSummary_noSubscriptions_returnSummaryCorrectly() {
|
||||||
mController.displayPreference(mPreferenceScreen);
|
mController.displayPreference(mPreferenceScreen);
|
||||||
mController.onResume();
|
mController.onResume();
|
||||||
assertThat(mController.getSummary()).isEqualTo("Add a network");
|
|
||||||
|
|
||||||
final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
|
assertThat(mController.getSummary()).isEqualTo("Add a network");
|
||||||
doNothing().when(mContext).startActivity(intentCaptor.capture());
|
|
||||||
mPreference.getOnPreferenceClickListener().onPreferenceClick(mPreference);
|
|
||||||
assertThat(intentCaptor.getValue().getAction()).isEqualTo(
|
|
||||||
EuiccManager.ACTION_PROVISION_EMBEDDED_SUBSCRIPTION);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -300,15 +294,13 @@ public class MobileNetworkSummaryControllerTest {
|
|||||||
assertThat(captor.getValue()).isFalse();
|
assertThat(captor.getValue()).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
@Test
|
||||||
public void onResume_noSubscriptionEsimDisabled_isDisabled() {
|
public void onAvailableSubInfoChanged_noSubscriptionEsimDisabled_isDisabled() {
|
||||||
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0);
|
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0);
|
||||||
SubscriptionUtil.setAvailableSubscriptionsForTesting(null);
|
|
||||||
when(mEuiccManager.isEnabled()).thenReturn(false);
|
when(mEuiccManager.isEnabled()).thenReturn(false);
|
||||||
mController.displayPreference(mPreferenceScreen);
|
mController.displayPreference(mPreferenceScreen);
|
||||||
|
|
||||||
mController.onResume();
|
mController.onAvailableSubInfoChanged(null);
|
||||||
|
|
||||||
assertThat(mPreference.isEnabled()).isFalse();
|
assertThat(mPreference.isEnabled()).isFalse();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ import static com.android.settings.password.ChooseLockGeneric.ChooseLockGenericF
|
|||||||
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_CALLER_APP_NAME;
|
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_CALLER_APP_NAME;
|
||||||
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_DEVICE_PASSWORD_REQUIREMENT_ONLY;
|
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_DEVICE_PASSWORD_REQUIREMENT_ONLY;
|
||||||
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS;
|
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS;
|
||||||
|
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE;
|
||||||
|
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT;
|
||||||
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_IS_CALLING_APP_ADMIN;
|
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_IS_CALLING_APP_ADMIN;
|
||||||
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_REQUESTED_MIN_COMPLEXITY;
|
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_REQUESTED_MIN_COMPLEXITY;
|
||||||
|
|
||||||
@@ -126,7 +128,9 @@ public class ChooseLockGenericTest {
|
|||||||
when(mFaceManager.isHardwareDetected()).thenReturn(true);
|
when(mFaceManager.isHardwareDetected()).thenReturn(true);
|
||||||
when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
|
when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
|
||||||
when(mFakeFeatureFactory.mFaceFeatureProvider.isSetupWizardSupported(any())).thenReturn(
|
when(mFakeFeatureFactory.mFaceFeatureProvider.isSetupWizardSupported(any())).thenReturn(
|
||||||
false);
|
true);
|
||||||
|
ShadowUtils.setFingerprintManager(mFingerprintManager);
|
||||||
|
ShadowUtils.setFaceManager(mFaceManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
@@ -540,35 +544,63 @@ public class ChooseLockGenericTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void updatePreferenceText_supportBiometrics_showFaceAndFingerprint() {
|
public void updatePreferenceText_supportBiometrics_showFaceAndFingerprint() {
|
||||||
ShadowLockPatternUtils.setRequiredPasswordComplexity(PASSWORD_COMPLEXITY_LOW);
|
ShadowStorageManager.setIsFileEncrypted(false);
|
||||||
final PasswordPolicy policy = new PasswordPolicy();
|
|
||||||
policy.quality = PASSWORD_QUALITY_ALPHABETIC;
|
|
||||||
ShadowLockPatternUtils.setRequestedProfilePasswordMetrics(policy.getMinMetrics());
|
|
||||||
|
|
||||||
final Intent intent = new Intent().putExtra(EXTRA_KEY_FOR_BIOMETRICS, true);
|
final Intent intent = new Intent().putExtra(EXTRA_KEY_FOR_BIOMETRICS, true);
|
||||||
initActivity(intent);
|
initActivity(intent);
|
||||||
|
|
||||||
final Intent passwordIntent = mFragment.getLockPatternIntent();
|
|
||||||
assertThat(passwordIntent.getIntExtra(ChooseLockPassword.EXTRA_KEY_MIN_COMPLEXITY,
|
|
||||||
PASSWORD_COMPLEXITY_NONE)).isEqualTo(PASSWORD_COMPLEXITY_LOW);
|
|
||||||
|
|
||||||
final String supportFingerprint = capitalize(mActivity.getResources().getString(
|
final String supportFingerprint = capitalize(mActivity.getResources().getString(
|
||||||
R.string.security_settings_fingerprint));
|
R.string.security_settings_fingerprint));
|
||||||
final String supportFace = capitalize(mActivity.getResources().getString(
|
final String supportFace = capitalize(mActivity.getResources().getString(
|
||||||
R.string.keywords_face_settings));
|
R.string.keywords_face_settings));
|
||||||
|
String pinTitle =
|
||||||
|
(String) mFragment.findPreference(ScreenLockType.PIN.preferenceKey).getTitle();
|
||||||
|
String patternTitle =
|
||||||
|
(String) mFragment.findPreference(ScreenLockType.PATTERN.preferenceKey).getTitle();
|
||||||
|
String passwordTitle =
|
||||||
|
(String) mFragment.findPreference(ScreenLockType.PASSWORD.preferenceKey).getTitle();
|
||||||
|
|
||||||
assertThat(mFragment.getBiometricsPreferenceTitle(ScreenLockType.PIN)).contains(
|
assertThat(pinTitle).contains(supportFingerprint);
|
||||||
supportFingerprint);
|
assertThat(pinTitle).contains(supportFace);
|
||||||
assertThat(mFragment.getBiometricsPreferenceTitle(ScreenLockType.PIN)).contains(
|
assertThat(patternTitle).contains(supportFingerprint);
|
||||||
supportFace);
|
assertThat(patternTitle).contains(supportFace);
|
||||||
assertThat(mFragment.getBiometricsPreferenceTitle(ScreenLockType.PATTERN)).contains(
|
assertThat(passwordTitle).contains(supportFingerprint);
|
||||||
supportFingerprint);
|
assertThat(passwordTitle).contains(supportFace);
|
||||||
assertThat(mFragment.getBiometricsPreferenceTitle(ScreenLockType.PATTERN)).contains(
|
}
|
||||||
supportFace);
|
|
||||||
assertThat(mFragment.getBiometricsPreferenceTitle(ScreenLockType.PASSWORD)).contains(
|
@Test
|
||||||
supportFingerprint);
|
public void updatePreferenceText_supportFingerprint_showFingerprint() {
|
||||||
assertThat(mFragment.getBiometricsPreferenceTitle(ScreenLockType.PASSWORD)).contains(
|
ShadowStorageManager.setIsFileEncrypted(false);
|
||||||
supportFace);
|
final Intent intent = new Intent().putExtra(EXTRA_KEY_FOR_FINGERPRINT, true);
|
||||||
|
initActivity(intent);
|
||||||
|
mFragment.updatePreferencesOrFinish(false /* isRecreatingActivity */);
|
||||||
|
|
||||||
|
assertThat(mFragment.findPreference(ScreenLockType.PIN.preferenceKey).getTitle()).isEqualTo(
|
||||||
|
mFragment.getString(R.string.fingerprint_unlock_set_unlock_pin));
|
||||||
|
assertThat(mFragment.findPreference(
|
||||||
|
ScreenLockType.PATTERN.preferenceKey).getTitle()).isEqualTo(
|
||||||
|
mFragment.getString(R.string.fingerprint_unlock_set_unlock_pattern));
|
||||||
|
assertThat(mFragment.findPreference(
|
||||||
|
ScreenLockType.PASSWORD.preferenceKey).getTitle()).isEqualTo(
|
||||||
|
mFragment.getString(R.string.fingerprint_unlock_set_unlock_password));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void updatePreferenceText_supportFace_showFace() {
|
||||||
|
|
||||||
|
ShadowStorageManager.setIsFileEncrypted(false);
|
||||||
|
final Intent intent = new Intent().putExtra(EXTRA_KEY_FOR_FACE, true);
|
||||||
|
initActivity(intent);
|
||||||
|
mFragment.updatePreferencesOrFinish(false /* isRecreatingActivity */);
|
||||||
|
|
||||||
|
assertThat(mFragment.findPreference(ScreenLockType.PIN.preferenceKey).getTitle()).isEqualTo(
|
||||||
|
mFragment.getString(R.string.face_unlock_set_unlock_pin));
|
||||||
|
assertThat(mFragment.findPreference(
|
||||||
|
ScreenLockType.PATTERN.preferenceKey).getTitle()).isEqualTo(
|
||||||
|
mFragment.getString(R.string.face_unlock_set_unlock_pattern));
|
||||||
|
assertThat(mFragment.findPreference(
|
||||||
|
ScreenLockType.PASSWORD.preferenceKey).getTitle()).isEqualTo(
|
||||||
|
mFragment.getString(R.string.face_unlock_set_unlock_password));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initActivity(@Nullable Intent intent) {
|
private void initActivity(@Nullable Intent intent) {
|
||||||
|
|||||||
@@ -0,0 +1,325 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.development.graphicsdriver;
|
||||||
|
|
||||||
|
import static com.android.settings.development.graphicsdriver.GraphicsDriverEnableAngleAsSystemDriverController.ANGLE_DRIVER_SUFFIX;
|
||||||
|
import static com.android.settings.development.graphicsdriver.GraphicsDriverEnableAngleAsSystemDriverController.Injector;
|
||||||
|
import static com.android.settings.development.graphicsdriver.GraphicsDriverEnableAngleAsSystemDriverController.PROPERTY_PERSISTENT_GRAPHICS_EGL;
|
||||||
|
import static com.android.settings.development.graphicsdriver.GraphicsDriverEnableAngleAsSystemDriverController.PROPERTY_RO_GFX_ANGLE_SUPPORTED;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.os.SystemProperties;
|
||||||
|
|
||||||
|
import androidx.preference.PreferenceManager;
|
||||||
|
import androidx.preference.PreferenceScreen;
|
||||||
|
import androidx.preference.SwitchPreference;
|
||||||
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
|
||||||
|
import com.android.settings.development.DevelopmentSettingsDashboardFragment;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
public class GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest {
|
||||||
|
private Context mContext;
|
||||||
|
private SwitchPreference mPreference;
|
||||||
|
|
||||||
|
private GraphicsDriverEnableAngleAsSystemDriverController mController;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private DevelopmentSettingsDashboardFragment mFragment;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private GraphicsDriverSystemPropertiesWrapper mSystemPropertiesMock;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
if (Looper.myLooper() == null) {
|
||||||
|
Looper.prepare();
|
||||||
|
}
|
||||||
|
|
||||||
|
mContext = ApplicationProvider.getApplicationContext();
|
||||||
|
|
||||||
|
// Construct a GraphicsDriverEnableAngleAsSystemDriverController with two Overrides:
|
||||||
|
// 1) Override the mSystemProperties with mSystemPropertiesMock,
|
||||||
|
// so we can force the SystemProperties with values we need to run tests.
|
||||||
|
// 2) Override the showRebootDialog() to do nothing.
|
||||||
|
// We do not need to pop up the reboot dialog in the test.
|
||||||
|
mController = new GraphicsDriverEnableAngleAsSystemDriverController(
|
||||||
|
mContext, mFragment, new Injector(){
|
||||||
|
@Override
|
||||||
|
public GraphicsDriverSystemPropertiesWrapper createSystemPropertiesWrapper() {
|
||||||
|
return mSystemPropertiesMock;
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
@Override
|
||||||
|
void showRebootDialog() {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
final PreferenceManager preferenceManager = new PreferenceManager(mContext);
|
||||||
|
final PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext);
|
||||||
|
mPreference = new SwitchPreference(mContext);
|
||||||
|
mPreference.setKey(mController.getPreferenceKey());
|
||||||
|
screen.addPreference(mPreference);
|
||||||
|
mController.displayPreference(screen);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onPreferenceChange_switchOn_shouldEnableAngleAsSystemDriver() {
|
||||||
|
// Add a callback when SystemProperty changes.
|
||||||
|
// This allows the thread to wait until
|
||||||
|
// GpuService::toggleAngleAsSystemDriver() updates the persist.graphics.egl.
|
||||||
|
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||||
|
Runnable countDown = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
countDownLatch.countDown();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
SystemProperties.addChangeCallback(countDown);
|
||||||
|
|
||||||
|
// Test onPreferenceChange(true) updates the persist.graphics.egl to "angle"
|
||||||
|
mController.onPreferenceChange(mPreference, true);
|
||||||
|
try {
|
||||||
|
countDownLatch.await(100, TimeUnit.MILLISECONDS);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Assert.fail(e.getMessage());
|
||||||
|
}
|
||||||
|
final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
|
||||||
|
assertThat(systemEGLDriver).isEqualTo(ANGLE_DRIVER_SUFFIX);
|
||||||
|
|
||||||
|
// Done with the test, remove the callback
|
||||||
|
SystemProperties.removeChangeCallback(countDown);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onPreferenceChange_switchOff_shouldDisableAngleAsSystemDriver() {
|
||||||
|
// Add a callback when SystemProperty changes.
|
||||||
|
// This allows the thread to wait until
|
||||||
|
// GpuService::toggleAngleAsSystemDriver() updates the persist.graphics.egl.
|
||||||
|
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||||
|
Runnable countDown = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
countDownLatch.countDown();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
SystemProperties.addChangeCallback(countDown);
|
||||||
|
|
||||||
|
// Test onPreferenceChange(false) updates the persist.graphics.egl to ""
|
||||||
|
mController.onPreferenceChange(mPreference, false);
|
||||||
|
try {
|
||||||
|
countDownLatch.await(100, TimeUnit.MILLISECONDS);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Assert.fail(e.getMessage());
|
||||||
|
}
|
||||||
|
final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
|
||||||
|
assertThat(systemEGLDriver).isEqualTo("");
|
||||||
|
|
||||||
|
// Done with the test, remove the callback
|
||||||
|
SystemProperties.removeChangeCallback(countDown);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void updateState_angleNotSupported_PreferenceShouldDisabled() {
|
||||||
|
when(mSystemPropertiesMock.get(eq(PROPERTY_RO_GFX_ANGLE_SUPPORTED), any())).thenReturn("");
|
||||||
|
mController.updateState(mPreference);
|
||||||
|
assertThat(mPreference.isEnabled()).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void updateState_angleNotSupported_PreferenceShouldNotBeChecked() {
|
||||||
|
when(mSystemPropertiesMock.get(eq(PROPERTY_RO_GFX_ANGLE_SUPPORTED), any()))
|
||||||
|
.thenReturn("");
|
||||||
|
mController.updateState(mPreference);
|
||||||
|
assertThat(mPreference.isChecked()).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void updateState_angleSupported_PreferenceShouldEnabled() {
|
||||||
|
when(mSystemPropertiesMock.get(eq(PROPERTY_RO_GFX_ANGLE_SUPPORTED), any()))
|
||||||
|
.thenReturn("true");
|
||||||
|
mController.updateState(mPreference);
|
||||||
|
assertThat(mPreference.isEnabled()).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void updateState_angleSupported_angleIsSystemGLESDriver_PreferenceShouldBeChecked() {
|
||||||
|
when(mSystemPropertiesMock.get(eq(PROPERTY_RO_GFX_ANGLE_SUPPORTED), any()))
|
||||||
|
.thenReturn("true");
|
||||||
|
when(mSystemPropertiesMock.get(eq(PROPERTY_PERSISTENT_GRAPHICS_EGL), any()))
|
||||||
|
.thenReturn(ANGLE_DRIVER_SUFFIX);
|
||||||
|
mController.updateState(mPreference);
|
||||||
|
assertThat(mPreference.isChecked()).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void
|
||||||
|
updateState_angleSupported_angleIsNotSystemGLESDriver_PreferenceShouldNotBeChecked() {
|
||||||
|
when(mSystemPropertiesMock.get(eq(PROPERTY_RO_GFX_ANGLE_SUPPORTED), any()))
|
||||||
|
.thenReturn("true");
|
||||||
|
when(mSystemPropertiesMock.get(eq(PROPERTY_PERSISTENT_GRAPHICS_EGL), any()))
|
||||||
|
.thenReturn("");
|
||||||
|
mController.updateState(mPreference);
|
||||||
|
assertThat(mPreference.isChecked()).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onDeveloperOptionSwitchEnabled_angleSupported_PreferenceShouldEnabled() {
|
||||||
|
when(mSystemPropertiesMock.get(eq(PROPERTY_RO_GFX_ANGLE_SUPPORTED), any()))
|
||||||
|
.thenReturn("true");
|
||||||
|
mController.onDeveloperOptionsSwitchEnabled();
|
||||||
|
assertThat(mPreference.isEnabled()).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onDeveloperOptionSwitchEnabled_angleNotSupported_PrefenceShouldDisabled() {
|
||||||
|
when(mSystemPropertiesMock.get(eq(PROPERTY_RO_GFX_ANGLE_SUPPORTED), any()))
|
||||||
|
.thenReturn("false");
|
||||||
|
mController.onDeveloperOptionsSwitchEnabled();
|
||||||
|
assertThat(mPreference.isEnabled()).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onDeveloperOptionSwitchDisabled_angleIsNotSystemGLESDriver() {
|
||||||
|
// Add a callback when SystemProperty changes.
|
||||||
|
// This allows the thread to wait until
|
||||||
|
// GpuService::toggleAngleAsSystemDriver() updates the persist.graphics.egl.
|
||||||
|
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||||
|
Runnable countDown = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
countDownLatch.countDown();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
SystemProperties.addChangeCallback(countDown);
|
||||||
|
|
||||||
|
// Test that onDeveloperOptionSwitchDisabled,
|
||||||
|
// persist.graphics.egl updates to ""
|
||||||
|
mController.onDeveloperOptionsSwitchDisabled();
|
||||||
|
try {
|
||||||
|
countDownLatch.await(100, TimeUnit.MILLISECONDS);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Assert.fail(e.getMessage());
|
||||||
|
}
|
||||||
|
final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
|
||||||
|
assertThat(systemEGLDriver).isEqualTo("");
|
||||||
|
|
||||||
|
// Done with the test, remove the callback
|
||||||
|
SystemProperties.removeChangeCallback(countDown);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onDeveloperOptionSwitchDisabled_PreferenceShouldNotBeChecked() {
|
||||||
|
mController.onDeveloperOptionsSwitchDisabled();
|
||||||
|
assertThat(mPreference.isChecked()).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onDeveloperOptionSwitchDisabled_PreferenceShouldDisabled() {
|
||||||
|
mController.onDeveloperOptionsSwitchDisabled();
|
||||||
|
assertThat(mPreference.isEnabled()).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onRebootCancelled_ToggleSwitchFromOnToOff() {
|
||||||
|
// Add a callback when SystemProperty changes.
|
||||||
|
// This allows the thread to wait until
|
||||||
|
// GpuService::toggleAngleAsSystemDriver() updates the persist.graphics.egl.
|
||||||
|
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||||
|
Runnable countDown = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
countDownLatch.countDown();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
SystemProperties.addChangeCallback(countDown);
|
||||||
|
|
||||||
|
// Test that if the current persist.graphics.egl is "angle",
|
||||||
|
// when reboot is cancelled, persist.graphics.egl is changed back to "",
|
||||||
|
// and switch is set to unchecked.
|
||||||
|
when(mSystemPropertiesMock.get(eq(PROPERTY_PERSISTENT_GRAPHICS_EGL), any()))
|
||||||
|
.thenReturn(ANGLE_DRIVER_SUFFIX);
|
||||||
|
mController.onRebootCancelled();
|
||||||
|
try {
|
||||||
|
countDownLatch.await(100, TimeUnit.MILLISECONDS);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Assert.fail(e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
|
||||||
|
assertThat(systemEGLDriver).isEqualTo("");
|
||||||
|
assertThat(mPreference.isChecked()).isFalse();
|
||||||
|
|
||||||
|
// Done with the test, remove the callback.
|
||||||
|
SystemProperties.removeChangeCallback(countDown);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onRebootCancelled_ToggleSwitchFromOffToOn() {
|
||||||
|
// Add a callback when SystemProperty changes.
|
||||||
|
// This allows the thread to wait until
|
||||||
|
// GpuService::toggleAngleAsSystemDriver() updates the persist.graphics.egl.
|
||||||
|
final CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||||
|
Runnable countDown = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
countDownLatch.countDown();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
SystemProperties.addChangeCallback(countDown);
|
||||||
|
|
||||||
|
// Test that if the current persist.graphics.egl is "",
|
||||||
|
// when reboot is cancelled, persist.graphics.egl is changed back to "angle",
|
||||||
|
// and switch is set to checked.
|
||||||
|
when(mSystemPropertiesMock.get(eq(PROPERTY_PERSISTENT_GRAPHICS_EGL), any()))
|
||||||
|
.thenReturn("");
|
||||||
|
mController.onRebootCancelled();
|
||||||
|
try {
|
||||||
|
countDownLatch.await(100, TimeUnit.MILLISECONDS);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Assert.fail(e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
|
||||||
|
assertThat(systemEGLDriver).isEqualTo(ANGLE_DRIVER_SUFFIX);
|
||||||
|
assertThat(mPreference.isChecked()).isTrue();
|
||||||
|
|
||||||
|
// Done with the test, remove the callback.
|
||||||
|
SystemProperties.removeChangeCallback(countDown);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user