Snap for 10120310 from 5f40973695 to udc-qpr1-release

Change-Id: Ia120731de3dc4f6c8a68d3c05e987d82b02105bb
This commit is contained in:
Android Build Coastguard Worker
2023-05-12 03:27:10 +00:00
40 changed files with 1124 additions and 479 deletions

View File

@@ -1581,6 +1581,22 @@
column="5"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;color name=&quot;switch_bar_state_disabled_color&quot;>#1FE3E3E3&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values-night/colors.xml"
line="76"
column="5"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
@@ -2957,6 +2973,22 @@
column="5"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;color name=&quot;switch_bar_state_disabled_color&quot;>#1F1F1F1F&lt;/color>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="219"
column="5"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
@@ -6253,6 +6285,38 @@
column="63"/>
</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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;solid android:color=&quot;@color/switch_bar_state_disabled_color&quot;/>"
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.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;solid android:color=&quot;@color/switch_bar_state_disabled_color&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/switch_bar_bg_disabled.xml"
line="22"
column="20"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"

View File

@@ -19,10 +19,11 @@ message BatteryOptimizeHistoricalLogEntry {
APPLY = 2;
RESET = 3;
RESTORE = 4;
BACKUP = 5;
}
optional string package_name = 1;
optional Action action = 2;
optional string action_description = 3;
optional int64 timestamp = 4;
}
}

View 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>

View File

@@ -96,4 +96,6 @@
</LinearLayout>
</LinearLayout>
<include layout="@layout/udfps_enroll_view" />
</com.google.android.setupdesign.GlifLayout>

View File

@@ -24,6 +24,7 @@
android:background="@android:color/transparent">
<FrameLayout
android:id="@+id/frame"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:paddingStart="@dimen/settingslib_switchbar_padding_left"

View File

@@ -18,6 +18,7 @@
<com.google.android.setupdesign.GlifLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/setup_wizard_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -41,10 +42,11 @@
<FrameLayout
android:id="@+id/layout_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="0dp"
android:clipChildren="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 -->
<com.airbnb.lottie.LottieAnimationView
@@ -59,6 +61,9 @@
android:clipChildren="false"
android:clipToPadding="false"
app:lottie_speed=".85" />
<include layout="@layout/udfps_enroll_view" />
</FrameLayout>
<TextView

View File

@@ -71,5 +71,8 @@
<!-- Flash notifications colors -->
<!-- Screen flash notification color selected stroke in color selection dialog -->
<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>

View File

@@ -214,4 +214,7 @@
<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_12">#667F00FF</color> <!-- 40% Violet -->
<!-- Switch bar disabled state color-->
<color name="switch_bar_state_disabled_color">#1F1F1F1F</color>
</resources>

View File

@@ -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] -->
<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] -->
<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] -->
<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] -->
<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] -->
@@ -1182,20 +1182,20 @@
<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]-->
<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]-->
<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]-->
<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]-->
<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]-->
<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]-->
<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]-->
<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]-->
<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>
<!-- 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>
<!-- 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. -->
<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] -->
<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] -->
<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] -->
<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] -->
@@ -10306,7 +10308,16 @@
<string name="credman_confirmation_message_title">Turn off %1$s\?</string>
<!-- 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] -->
<string name="credman_enable_confirmation_message_title">Use %1$s\?</string>

View File

@@ -17,16 +17,26 @@
package com.android.settings.accessibility;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.ColorInt;
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
import com.android.settings.R;
import com.android.settingslib.Utils;
/**
* Preference for Flash notifications preview.
*/
public class FlashNotificationsPreviewPreference extends Preference {
private Drawable mBackgroundEnabled;
private Drawable mBackgroundDisabled;
@ColorInt
private int mTextColorDisabled;
public FlashNotificationsPreviewPreference(Context context) {
super(context);
@@ -52,5 +62,32 @@ public class FlashNotificationsPreviewPreference extends Preference {
private void init() {
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();
}
}

View File

@@ -55,7 +55,7 @@ public class FlashNotificationsPreviewPreferenceController extends
new Handler(Looper.getMainLooper())) {
@Override
public void onChange(boolean selfChange, @Nullable Uri uri) {
onSettingChanged();
updateState(mPreference);
}
};
@@ -73,7 +73,7 @@ public class FlashNotificationsPreviewPreferenceController extends
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreference = screen.findPreference(getPreferenceKey());
onSettingChanged();
updateState(mPreference);
}
@Override
@@ -103,10 +103,13 @@ public class FlashNotificationsPreviewPreferenceController extends
}
}
private void onSettingChanged() {
if (mPreference == null) return;
mPreference.setEnabled(FlashNotificationsUtil.getFlashNotificationsState(mContext)
@Override
public void updateState(Preference preference) {
super.updateState(preference);
if (preference == null) {
return;
}
preference.setEnabled(FlashNotificationsUtil.getFlashNotificationsState(mContext)
!= FlashNotificationsUtil.State.OFF);
}
}

View File

@@ -554,19 +554,7 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
}
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 {
togglePackageNameDisabled(packageName);
}
togglePackageNameDisabled(packageName);
}
return true;
@@ -682,35 +670,6 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
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() {
if (mIsWorkProfile) {
UserHandle workProfile = Utils.getManagedProfile(UserManager.get(mContext));
@@ -800,46 +759,6 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
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
* enable the new provider.

View File

@@ -273,8 +273,13 @@ public class DefaultCombinedPicker extends DefaultAppPickerFragment {
@Override
protected CharSequence getConfirmationMessage(CandidateInfo appInfo) {
// If we are selecting none then show a warning label.
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 String message =

View File

@@ -261,6 +261,8 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
int rotation = getApplicationContext().getDisplay().getRotation();
final GlifLayout layout = (GlifLayout) getLayoutInflater().inflate(
R.layout.udfps_enroll_enrolling, null, false);
final UdfpsEnrollView udfpsEnrollView = layout.findViewById(R.id.udfps_animation_view);
updateUdfpsEnrollView(udfpsEnrollView, props.get(0));
switch (rotation) {
case Surface.ROTATION_90:
final View sudContent = layout.findViewById(R.id.sud_layout_content);
@@ -282,66 +284,52 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
? 0 : (int) getResources().getDimension(
R.dimen.rotation_90_enroll_padding_end), 0);
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);
break;
case Surface.ROTATION_0:
case Surface.ROTATION_180:
if (FeatureFlagUtils.isEnabled(getApplicationContext(),
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.
// 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(
R.id.layout_container);
final ViewGroup.LayoutParams containerLp =
portraitLayoutContainer.getLayoutParams();
containerLp.height = 0;
// In the portrait mode, layout_container's height is 0, so it's
// always shown at the bottom of the screen.
final FrameLayout portraitLayoutContainer = layout.findViewById(
R.id.layout_container);
// In the portrait mode, the title and lottie animation view may
// overlap when title needs three lines, so adding some paddings
// between them, and adjusting the fp progress view here accordingly.
final int layoutLottieAnimationPadding = (int) getResources()
.getDimension(R.dimen.udfps_lottie_padding_top);
portraitLayoutContainer.setPadding(0,
layoutLottieAnimationPadding, 0, 0);
final ImageView progressView = udfpsEnrollView.findViewById(
R.id.udfps_enroll_animation_fp_progress_view);
progressView.setPadding(0, -(layoutLottieAnimationPadding),
0, layoutLottieAnimationPadding);
final ImageView fingerprintView = udfpsEnrollView.findViewById(
R.id.udfps_enroll_animation_fp_view);
fingerprintView.setPadding(0, -layoutLottieAnimationPadding,
0, layoutLottieAnimationPadding);
// In the portrait mode, the title and lottie animation view may
// overlap when title needs three lines, so adding some paddings
// between them, and adjusting the fp progress view here accordingly.
final int layoutLottieAnimationPadding = (int) getResources()
.getDimension(R.dimen.udfps_lottie_padding_top);
portraitLayoutContainer.setPadding(0,
layoutLottieAnimationPadding, 0, 0);
final ImageView progressView = udfpsEnrollView.findViewById(
R.id.udfps_enroll_animation_fp_progress_view);
progressView.setPadding(0, -(layoutLottieAnimationPadding),
0, layoutLottieAnimationPadding);
final ImageView fingerprintView = udfpsEnrollView.findViewById(
R.id.udfps_enroll_animation_fp_view);
fingerprintView.setPadding(0, -layoutLottieAnimationPadding,
0, layoutLottieAnimationPadding);
portraitLayoutContainer.addView(udfpsEnrollView);
setOnHoverListener(false, layout, udfpsEnrollView);
}
// TODO(b/260970216) Instead of hiding the description text view, we should
// 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);
break;
case Surface.ROTATION_270:
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);
break;
}
@@ -1241,10 +1229,8 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
}
}
private UdfpsEnrollView addUdfpsEnrollView(FingerprintSensorPropertiesInternal udfpsProps) {
UdfpsEnrollView udfpsEnrollView = (UdfpsEnrollView) getLayoutInflater().inflate(
R.layout.udfps_enroll_view, null, false);
private UdfpsEnrollView updateUdfpsEnrollView(UdfpsEnrollView udfpsEnrollView,
FingerprintSensorPropertiesInternal udfpsProps) {
DisplayInfo displayInfo = new DisplayInfo();
getDisplay().getDisplayInfo(displayInfo);
mScaleFactor = mUdfpsUtils.getScaleFactor(displayInfo);
@@ -1311,6 +1297,24 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
: 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 {
@Override

View File

@@ -185,7 +185,8 @@ public class FingerprintSettings extends SubSettings {
private static final int MSG_FINGER_AUTH_HELP = 1004;
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
static final int ADD_FINGERPRINT_REQUEST = 10;
private static final int AUTO_ADD_FIRST_FINGERPRINT_REQUEST = 11;
@@ -1014,7 +1015,7 @@ public class FingerprintSettings extends SubSettings {
true);
intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
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);
}
}

View File

@@ -161,22 +161,20 @@ public class UdfpsEnrollView extends FrameLayout implements UdfpsEnrollHelper.Li
MarginLayoutParams marginLayoutParams = (MarginLayoutParams) getLayoutParams();
FrameLayout.LayoutParams params = (LayoutParams) getLayoutParams();
if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) {
parentView.getViewTreeObserver().addOnDrawListener(() -> {
final int[] coords = parentView.getLocationOnScreen();
final int parentLeft = coords[0];
final int parentTop = coords[1];
final int parentRight = parentLeft + parentView.getWidth();
params.gravity = Gravity.RIGHT | Gravity.TOP;
final int rightMargin = parentRight - rotatedBounds.right - getPaddingX();
final int topMargin = rotatedBounds.top - parentTop - getPaddingY();
if (marginLayoutParams.rightMargin == rightMargin
&& marginLayoutParams.topMargin == topMargin) {
return;
}
marginLayoutParams.rightMargin = rightMargin;
marginLayoutParams.topMargin = topMargin;
setLayoutParams(params);
});
final int[] coords = parentView.getLocationOnScreen();
final int parentLeft = coords[0];
final int parentTop = coords[1];
final int parentRight = parentLeft + parentView.getWidth();
params.gravity = Gravity.RIGHT | Gravity.TOP;
final int rightMargin = parentRight - rotatedBounds.right - getPaddingX();
final int topMargin = rotatedBounds.top - parentTop - getPaddingY();
if (marginLayoutParams.rightMargin == rightMargin
&& marginLayoutParams.topMargin == topMargin) {
return;
}
marginLayoutParams.rightMargin = rightMargin;
marginLayoutParams.topMargin = topMargin;
setLayoutParams(params);
} else {
final int[] coords = parentView.getLocationOnScreen();
final int parentLeft = coords[0];

View File

@@ -57,7 +57,9 @@ import com.android.settingslib.widget.LayoutPreference;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
@@ -92,13 +94,12 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont
@VisibleForTesting
final Map<String, Bitmap> mIconCache;
private CachedBluetoothDevice mCachedDevice;
private Set<BluetoothDevice> mBluetoothDevices;
@VisibleForTesting
BluetoothAdapter mBluetoothAdapter;
@VisibleForTesting
Handler mHandler = new Handler(Looper.getMainLooper());
@VisibleForTesting
boolean mIsRegisterCallback = false;
@VisibleForTesting
boolean mIsLeftDeviceEstimateReady;
@VisibleForTesting
boolean mIsRightDeviceEstimateReady;
@@ -141,23 +142,13 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont
if (!isAvailable()) {
return;
}
mIsRegisterCallback = true;
mCachedDevice.registerCallback(this);
mBluetoothAdapter.addOnMetadataChangedListener(mCachedDevice.getDevice(),
mContext.getMainExecutor(), mMetadataListener);
registerBluetoothDevice();
refresh();
}
@Override
public void onStop() {
if (!mIsRegisterCallback) {
return;
}
mCachedDevice.unregisterCallback(this);
mBluetoothAdapter.removeOnMetadataChangedListener(mCachedDevice.getDevice(),
mMetadataListener);
mIsRegisterCallback = false;
unRegisterBluetoothDevice();
}
@Override
@@ -175,6 +166,40 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont
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
void refresh() {
if (mLayoutPreference != null && mCachedDevice != null) {

View File

@@ -120,6 +120,10 @@ public class BluetoothDetailsProfilesController extends BluetoothDetailsControll
pref.setTitle(profile.getNameResource(mCachedDevice.getDevice()));
pref.setOnPreferenceClickListener(this);
pref.setOrder(profile.getOrdinal());
if (profile instanceof LeAudioProfile) {
pref.setSummary(R.string.device_details_leaudio_toggle_summary);
}
return pref;
}

View File

@@ -196,10 +196,11 @@ public abstract class DeviceListPreferenceFragment extends
}
// 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
|| (mFilter != null && mFilter.matches(cachedDevice.getDevice()))) {
if (mFilter != null && mFilter.matches(cachedDevice.getDevice())) {
createDevicePreference(cachedDevice);
}
}
@@ -325,7 +326,12 @@ public abstract class DeviceListPreferenceFragment extends
if (cachedDevice == null) {
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

View File

@@ -48,6 +48,8 @@ public class GraphicsDriverEnableAngleAsSystemDriverController
private final DevelopmentSettingsDashboardFragment mFragment;
private final GraphicsDriverSystemPropertiesWrapper mSystemProperties;
@VisibleForTesting
static final String PROPERTY_RO_GFX_ANGLE_SUPPORTED = "ro.gfx.angle.supported";
@@ -57,11 +59,34 @@ public class GraphicsDriverEnableAngleAsSystemDriverController
@VisibleForTesting
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(
Context context, DevelopmentSettingsDashboardFragment fragment) {
this(context, fragment, new Injector());
}
@VisibleForTesting
GraphicsDriverEnableAngleAsSystemDriverController(
Context context, DevelopmentSettingsDashboardFragment fragment, Injector injector) {
super(context);
mFragment = fragment;
mSystemProperties = injector.createSystemPropertiesWrapper();
}
@Override
@@ -76,20 +101,27 @@ public class GraphicsDriverEnableAngleAsSystemDriverController
// set "persist.graphics.egl" to "" if enableAngleAsSystemDriver is false
GraphicsEnvironment.getInstance().toggleAngleAsSystemDriver(enableAngleAsSystemDriver);
// 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(
mFragment, R.string.reboot_dialog_enable_angle_as_system_driver,
R.string.cancel, this);
return true;
}
@Override
public void updateState(Preference preference) {
// set switch on if "persist.graphics.egl" is "angle" and angle is built in /vendor
// 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 isAngleSupported =
TextUtils.equals(SystemProperties.get(PROPERTY_RO_GFX_ANGLE_SUPPORTED), "true");
final boolean isAngleSupported = TextUtils
.equals(mSystemProperties.get(PROPERTY_RO_GFX_ANGLE_SUPPORTED, ""), "true");
((SwitchPreference) mPreference).setChecked(isAngle && isAngleSupported);
((SwitchPreference) mPreference).setEnabled(isAngleSupported);
}
@@ -98,8 +130,8 @@ public class GraphicsDriverEnableAngleAsSystemDriverController
protected void onDeveloperOptionsSwitchEnabled() {
// 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
final boolean isAngleSupported =
TextUtils.equals(SystemProperties.get(PROPERTY_RO_GFX_ANGLE_SUPPORTED), "true");
final boolean isAngleSupported = TextUtils
.equals(mSystemProperties.get(PROPERTY_RO_GFX_ANGLE_SUPPORTED, ""), "true");
((SwitchPreference) mPreference).setEnabled(isAngleSupported);
}
@@ -116,7 +148,8 @@ public class GraphicsDriverEnableAngleAsSystemDriverController
@Override
public void onRebootCancelled() {
// 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 persist.graphics.egl = "angle", set the property value back to ""
GraphicsEnvironment.getInstance().toggleAngleAsSystemDriver(false);

View File

@@ -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);
}

View File

@@ -22,6 +22,7 @@ import android.app.backup.BackupDataInputStream;
import android.app.backup.BackupDataOutput;
import android.app.backup.BackupHelper;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.os.IDeviceIdleController;
@@ -34,9 +35,11 @@ import android.util.Log;
import androidx.annotation.VisibleForTesting;
import com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action;
import com.android.settingslib.fuelgauge.PowerAllowlistBackend;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
@@ -47,6 +50,8 @@ public final class BatteryBackupHelper implements BackupHelper {
/** An inditifier for {@link BackupHelper}. */
public static final String TAG = "BatteryBackupHelper";
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_MODE = ":";
@@ -141,6 +146,7 @@ public final class BatteryBackupHelper implements BackupHelper {
int backupCount = 0;
final StringBuilder builder = new StringBuilder();
final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
final SharedPreferences sharedPreferences = getSharedPreferences(mContext);
// Converts application into the AppUsageState.
for (ApplicationInfo info : applications) {
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;
builder.append(packageOptimizeMode + DELIMITER);
Log.d(TAG, "backupOptimizationMode: " + packageOptimizeMode);
BatteryHistoricalLogUtil.writeLog(
sharedPreferences, Action.BACKUP, info.packageName,
/* actionDescription */ "mode: " + optimizationMode);
backupCount++;
}
@@ -210,6 +219,18 @@ public final class BatteryBackupHelper implements BackupHelper {
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(
String packageName, @BatteryOptimizeUtils.OptimizationMode int mode) {
final int uid = BatteryUtils.getInstance(mContext).getPackageUid(packageName);

View File

@@ -37,40 +37,40 @@ public final class BatteryHistoricalLogUtil {
@VisibleForTesting
static final int MAX_ENTRIES = 40;
/**
* Writes a log entry.
*
* <p>Keeps up to {@link #MAX_ENTRIES} in the log, once that number is exceeded, it prunes the
* oldest one.
*/
static void writeLog(Context context, Action action, String pkg, String actionDescription) {
/** Writes a log entry for battery optimization mode. */
static void writeLog(
Context context, Action action, String packageName, String actionDescription) {
writeLog(getSharedPreferences(context), action, packageName, actionDescription);
}
static void writeLog(SharedPreferences sharedPreferences, Action action,
String packageName, String actionDescription) {
writeLog(
context,
sharedPreferences,
BatteryOptimizeHistoricalLogEntry.newBuilder()
.setPackageName(pkg)
.setPackageName(packageName)
.setAction(action)
.setActionDescription(actionDescription)
.setTimestamp(System.currentTimeMillis())
.build());
}
private static void writeLog(Context context, BatteryOptimizeHistoricalLogEntry logEntry) {
SharedPreferences sharedPreferences = getSharedPreferences(context);
private static void writeLog(
SharedPreferences sharedPreferences, BatteryOptimizeHistoricalLogEntry logEntry) {
BatteryOptimizeHistoricalLog existingLog =
parseLogFromString(sharedPreferences.getString(LOGS_KEY, ""));
BatteryOptimizeHistoricalLog.Builder newLogBuilder = existingLog.toBuilder();
// Prune old entries
// Prune old entries to limit the max logging data count.
if (existingLog.getLogEntryCount() >= MAX_ENTRIES) {
newLogBuilder.removeLogEntry(0);
}
newLogBuilder.addLogEntry(logEntry);
String loggingContent =
Base64.encodeToString(newLogBuilder.build().toByteArray(), Base64.DEFAULT);
sharedPreferences
.edit()
.putString(
LOGS_KEY,
Base64.encodeToString(newLogBuilder.build().toByteArray(), Base64.DEFAULT))
.putString(LOGS_KEY, loggingContent)
.apply();
}
@@ -79,34 +79,36 @@ public final class BatteryHistoricalLogUtil {
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) {
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:");
SharedPreferences sharedPreferences = getSharedPreferences(context);
BatteryOptimizeHistoricalLog existingLog =
parseLogFromString(sharedPreferences.getString(LOGS_KEY, ""));
List<BatteryOptimizeHistoricalLogEntry> logEntryList = existingLog.getLogEntryList();
if (logEntryList.isEmpty()) {
writer.println("\tNo past logs.");
writer.println("\tnothing to dump");
} 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)));
}
}
/**
* Gets the unique key for logging, combined with package name, delimiter and user id.
*/
static String getPackageNameWithUserId(String pkgName, int userId) {
return pkgName + ":" + userId;
/** Gets the unique key for logging. */
static String getPackageNameWithUserId(String packageName, int userId) {
return packageName + ":" + userId;
}
private static String toString(BatteryOptimizeHistoricalLogEntry entry) {
return String.format("%s\tAction:%s\tEvent:%s\tTimestamp:%s", entry.getPackageName(),
entry.getAction(), entry.getActionDescription(),
ConvertUtils.utcToLocalTimeForLogging(entry.getTimestamp()));
return String.format("%s\t%s\taction:%s\tevent:%s",
ConvertUtils.utcToLocalTimeForLogging(entry.getTimestamp()),
entry.getPackageName(), entry.getAction(),
entry.getActionDescription());
}
@VisibleForTesting

View File

@@ -299,9 +299,10 @@ public class BatteryInfo {
(double) PowerUtil.convertUsToMs(info.remainingTimeUs), false /* withSeconds */,
true /* collapseTimeUnit */);
int resId = R.string.power_charging_duration;
info.remainingLabel = context.getString(R.string.power_remaining_charging_duration_only,
timeString);
info.chargeLabel = context.getString(resId, info.batteryPercentString, timeString);
info.remainingLabel = chargeTimeMs <= 0 ? null : context.getString(
R.string.power_remaining_charging_duration_only, timeString);
info.chargeLabel = chargeTimeMs <= 0 ? info.batteryPercentString
: context.getString(resId, info.batteryPercentString, timeString);
} else if (dockDefenderMode == BatteryUtils.DockDefenderMode.FUTURE_BYPASS) {
// Dock defender will be triggered in the future, charging will be optimized.
info.chargeLabel = context.getString(R.string.power_charging_future_paused,

View File

@@ -24,7 +24,6 @@ import android.content.Intent;
import android.os.UserManager;
import android.telephony.SubscriptionManager;
import android.telephony.euicc.EuiccManager;
import android.util.Log;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
@@ -135,6 +134,7 @@ public class MobileNetworkSummaryController extends AbstractPreferenceController
return mContext.getString(R.string.mobile_network_tap_to_activate, displayName);
} else {
return mSubInfoEntityList.stream()
.sorted((e1, e2) -> Integer.compare(e1.simSlotIndex, e2.simSlotIndex))
.map(SubscriptionInfoEntity::getUniqueDisplayName)
.collect(Collectors.joining(", "));
}

View File

@@ -59,8 +59,10 @@ public class PrivacyDashboardFragment extends DashboardFragment {
SafetyCenterUtils.getEnterpriseOverrideStringForPrivacyEntries();
for (int i = 0; i < privacyOverrideStrings.size(); i++) {
EnterpriseOverrideString overrideString = privacyOverrideStrings.get(i);
replaceEnterpriseStringTitle(overrideString.getPreferenceKey(),
overrideString.getOverrideKey(), overrideString.getResource());
replaceEnterpriseStringTitle(
overrideString.getPreferenceKey(),
overrideString.getOverrideKey(),
overrideString.getResource());
}
}
@@ -93,7 +95,9 @@ public class PrivacyDashboardFragment extends DashboardFragment {
@Override
public List<SearchIndexableResource> getXmlResourcesToIndex(
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 super.getXmlResourcesToIndex(context, enabled);
@@ -120,5 +124,10 @@ public class PrivacyDashboardFragment extends DashboardFragment {
keys.add(KEY_NOTIFICATION_WORK_PROFILE_NOTIFICATIONS);
return keys;
}
@Override
protected boolean isPageSearchEnabled(Context context) {
return !SafetyCenterManagerWrapper.get().isEnabled(context);
}
};
}

View File

@@ -77,21 +77,23 @@ public class MoreSecurityPrivacyFragment extends DashboardFragment {
SafetyCenterUtils.getEnterpriseOverrideStringForPrivacyEntries();
for (int i = 0; i < privacyOverrideStrings.size(); i++) {
EnterpriseOverrideString overrideString = privacyOverrideStrings.get(i);
replaceEnterpriseStringTitle(overrideString.getPreferenceKey(),
overrideString.getOverrideKey(), overrideString.getResource());
replaceEnterpriseStringTitle(
overrideString.getPreferenceKey(),
overrideString.getOverrideKey(),
overrideString.getResource());
}
List<EnterpriseOverrideString> securityOverrideStrings =
SafetyCenterUtils.getEnterpriseOverrideStringForSecurityEntries();
for (int i = 0; i < securityOverrideStrings.size(); i++) {
EnterpriseOverrideString overrideString = securityOverrideStrings.get(i);
replaceEnterpriseStringTitle(overrideString.getPreferenceKey(),
overrideString.getOverrideKey(), overrideString.getResource());
replaceEnterpriseStringTitle(
overrideString.getPreferenceKey(),
overrideString.getOverrideKey(),
overrideString.getResource());
}
}
/**
* see confirmPatternThenDisableAndClear
*/
/** see confirmPatternThenDisableAndClear */
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (use(TrustAgentListPreferenceController.class)
@@ -117,10 +119,8 @@ public class MoreSecurityPrivacyFragment extends DashboardFragment {
controllers.addAll(
SafetyCenterUtils.getControllersForAdvancedSecurity(context, lifecycle, host));
return controllers;
}
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider(R.xml.more_security_privacy_settings) {
/**
@@ -130,7 +130,9 @@ public class MoreSecurityPrivacyFragment extends DashboardFragment {
@Override
public List<SearchIndexableResource> getXmlResourcesToIndex(
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 super.getXmlResourcesToIndex(context, enabled);
@@ -157,5 +159,10 @@ public class MoreSecurityPrivacyFragment extends DashboardFragment {
keys.add(KEY_NOTIFICATION_WORK_PROFILE_NOTIFICATIONS);
return keys;
}
@Override
protected boolean isPageSearchEnabled(Context context) {
return SafetyCenterManagerWrapper.get().isEnabled(context);
}
};
}

View File

@@ -58,8 +58,10 @@ public class SecurityAdvancedSettings extends DashboardFragment {
SafetyCenterUtils.getEnterpriseOverrideStringForSecurityEntries();
for (int i = 0; i < securityOverrideStrings.size(); i++) {
EnterpriseOverrideString overrideString = securityOverrideStrings.get(i);
replaceEnterpriseStringTitle(overrideString.getPreferenceKey(),
overrideString.getOverrideKey(), overrideString.getResource());
replaceEnterpriseStringTitle(
overrideString.getPreferenceKey(),
overrideString.getOverrideKey(),
overrideString.getResource());
}
}
@@ -77,8 +79,7 @@ public class SecurityAdvancedSettings extends DashboardFragment {
return CategoryKey.CATEGORY_SECURITY_ADVANCED_SETTINGS;
} else {
final SecuritySettingsFeatureProvider securitySettingsFeatureProvider =
FeatureFactory.getFactory(context)
.getSecuritySettingsFeatureProvider();
FeatureFactory.getFactory(context).getSecuritySettingsFeatureProvider();
if (securitySettingsFeatureProvider.hasAlternativeSecuritySettingsFragment()) {
return securitySettingsFeatureProvider.getAlternativeAdvancedSettingsCategoryKey();
@@ -103,9 +104,7 @@ public class SecurityAdvancedSettings extends DashboardFragment {
return buildPreferenceControllers(context, getSettingsLifecycle(), this /* host*/);
}
/**
* see confirmPatternThenDisableAndClear
*/
/** see confirmPatternThenDisableAndClear */
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (use(TrustAgentListPreferenceController.class)
@@ -119,14 +118,12 @@ public class SecurityAdvancedSettings extends DashboardFragment {
super.onActivityResult(requestCode, resultCode, data);
}
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
Lifecycle lifecycle, DashboardFragment host) {
private static List<AbstractPreferenceController> buildPreferenceControllers(
Context context, Lifecycle lifecycle, DashboardFragment 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 =
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.
*/
@Override
public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
boolean enabled) {
if (SafetyCenterManagerWrapper.get().isEnabled(context)) {
public List<SearchIndexableResource> getXmlResourcesToIndex(
Context context, boolean enabled) {
// 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 super.getXmlResourcesToIndex(context, enabled);
}
@Override
public List<AbstractPreferenceController> createPreferenceControllers(Context
context) {
return buildPreferenceControllers(context, null /* lifecycle */,
null /* host*/);
public List<AbstractPreferenceController> createPreferenceControllers(
Context context) {
return buildPreferenceControllers(
context, null /* lifecycle */, null /* host*/);
}
@Override
protected boolean isPageSearchEnabled(Context context) {
return !SafetyCenterManagerWrapper.get().isEnabled(context);
}
};
}

View File

@@ -28,7 +28,6 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
@@ -83,6 +82,7 @@ import com.android.settingslib.RestrictedPreference;
import com.android.settingslib.drawable.CircleFramedDrawable;
import com.android.settingslib.search.SearchIndexable;
import com.android.settingslib.search.SearchIndexableRaw;
import com.android.settingslib.users.CreateUserDialogController;
import com.android.settingslib.users.EditUserInfoController;
import com.android.settingslib.users.GrantAdminDialogController;
import com.android.settingslib.users.UserCreatingDialog;
@@ -119,6 +119,7 @@ public class UserSettings extends SettingsPreferenceFragment
/** UserId of the user being removed */
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_ME = "user_me";
@@ -171,9 +172,6 @@ public class UserSettings extends SettingsPreferenceFragment
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_SUMMARY = "summary";
@@ -222,6 +220,8 @@ public class UserSettings extends SettingsPreferenceFragment
new GrantAdminDialogController();
private EditUserInfoController mEditUserInfoController =
new EditUserInfoController(Utils.FILE_PROVIDER_AUTHORITY);
private CreateUserDialogController mCreateUserDialogController =
new CreateUserDialogController(Utils.FILE_PROVIDER_AUTHORITY);
private AddUserWhenLockedPreferenceController mAddUserWhenLockedPreferenceController;
private GuestTelephonyPreferenceController mGuestTelephonyPreferenceController;
private RemoveGuestOnExitPreferenceController mRemoveGuestOnExitPreferenceController;
@@ -233,7 +233,7 @@ public class UserSettings extends SettingsPreferenceFragment
private CharSequence mPendingUserName;
private Drawable mPendingUserIcon;
private boolean mGrantAdmin;
private boolean mPendingUserIsAdmin;
// A place to cache the generated default avatar
private Drawable mDefaultIconDrawable;
@@ -348,7 +348,11 @@ public class UserSettings extends SettingsPreferenceFragment
if (icicle.containsKey(SAVE_REMOVING_USER)) {
mRemovingUserId = icicle.getInt(SAVE_REMOVING_USER);
}
mEditUserInfoController.onRestoreInstanceState(icicle);
if (icicle.containsKey(SAVE_CREATE_USER)) {
mCreateUserDialogController.onRestoreInstanceState(icicle);
} else {
mEditUserInfoController.onRestoreInstanceState(icicle);
}
}
mUserCaps = UserCapabilities.create(activity);
@@ -440,7 +444,12 @@ public class UserSettings extends SettingsPreferenceFragment
@Override
public void onSaveInstanceState(Bundle outState) {
mEditUserInfoController.onSaveInstanceState(outState);
if (mCreateUserDialogController.isActive()) {
outState.putBoolean(SAVE_CREATE_USER, mCreateUserDialogController.isActive());
mCreateUserDialogController.onSaveInstanceState(outState);
} else {
mEditUserInfoController.onSaveInstanceState(outState);
}
outState.putInt(SAVE_REMOVING_USER, mRemovingUserId);
super.onSaveInstanceState(outState);
}
@@ -448,6 +457,7 @@ public class UserSettings extends SettingsPreferenceFragment
@Override
public void startActivityForResult(Intent intent, int requestCode) {
mEditUserInfoController.startingActivityForResult();
mCreateUserDialogController.startingActivityForResult();
super.startActivityForResult(intent, requestCode);
}
@@ -562,6 +572,7 @@ public class UserSettings extends SettingsPreferenceFragment
&& resultCode == RESULT_GUEST_REMOVED) {
scheduleGuestCreation();
} else {
mCreateUserDialogController.onActivityResult(requestCode, resultCode, data);
mEditUserInfoController.onActivityResult(requestCode, resultCode, data);
}
}
@@ -704,37 +715,12 @@ public class UserSettings extends SettingsPreferenceFragment
.setPositiveButton(android.R.string.ok, null)
.create();
case DIALOG_ADD_USER: {
final SharedPreferences preferences = getActivity().getPreferences(
Context.MODE_PRIVATE);
final boolean longMessageDisplayed = preferences.getBoolean(
KEY_ADD_USER_LONG_MESSAGE_DISPLAYED, false);
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()) {
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();
synchronized (mUserLock) {
mPendingUserName = getString(
com.android.settingslib.R.string.user_new_user_name);
mPendingUserIcon = null;
}
return buildAddUserDialog(USER_TYPE_USER);
}
case DIALOG_CHOOSE_USER_TYPE: {
List<HashMap<String, String>> data = new ArrayList<HashMap<String, String>>();
@@ -919,17 +905,14 @@ public class UserSettings extends SettingsPreferenceFragment
private Dialog buildAddUserDialog(int userType) {
Dialog d;
synchronized (mUserLock) {
d = mEditUserInfoController.createDialog(
d = mCreateUserDialogController.createDialog(
getActivity(),
this::startActivityForResult,
null,
mPendingUserName.toString(),
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) -> {
UserManager.isMultipleAdminEnabled(),
(userName, userIcon, isAdmin) -> {
mPendingUserIcon = userIcon;
mPendingUserName = userName;
mPendingUserIsAdmin = isAdmin;
addUserNow(userType);
},
() -> {
@@ -943,26 +926,6 @@ public class UserSettings extends SettingsPreferenceFragment
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
public int getDialogMetricsCategory(int dialogId) {
switch (dialogId) {
@@ -1065,7 +1028,7 @@ public class UserSettings extends SettingsPreferenceFragment
userName,
mUserManager.USER_TYPE_FULL_SECONDARY,
0);
if (mGrantAdmin) {
if (mPendingUserIsAdmin) {
mUserManager.setUserAdmin(user.id);
}
} else {
@@ -1665,6 +1628,9 @@ public class UserSettings extends SettingsPreferenceFragment
synchronized (mUserLock) {
mRemovingUserId = -1;
updateUserList();
if (mCreateUserDialogController.isActive()) {
mCreateUserDialogController.clear();
}
}
}

View File

@@ -45,6 +45,8 @@ import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceScreen;
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.WifiTetherSecurityPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
@@ -94,6 +96,8 @@ public class AllInOneTetherSettingsTest {
mContext = spy(RuntimeEnvironment.application);
MockitoAnnotations.initMocks(this);
when(FakeFeatureFactory.setupForTest().getWifiFeatureProvider().getWifiHotspotRepository())
.thenReturn(mock(WifiHotspotRepository.class));
doReturn(mWifiManager).when(mContext).getSystemService(WifiManager.class);
doReturn(mConnectivityManager)
.when(mContext).getSystemService(Context.CONNECTIVITY_SERVICE);

View File

@@ -19,20 +19,26 @@ package com.android.settings.accessibility;
import static com.google.common.truth.Truth.assertThat;
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 com.android.settings.R;
import com.android.settingslib.Utils;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Spy;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.Shadows;
@RunWith(RobolectricTestRunner.class)
public class FlashNotificationsPreviewPreferenceTest {
@@ -41,37 +47,46 @@ public class FlashNotificationsPreviewPreferenceTest {
public MockitoRule mMockitoRule = MockitoJUnit.rule();
@Spy
private final Context mContext = ApplicationProvider.getApplicationContext();
private final AttributeSet mAttributeSet = Robolectric.buildAttributeSet().build();
private FlashNotificationsPreviewPreference mFlashNotificationsPreviewPreference;
private PreferenceViewHolder mPreferenceViewHolder;
@Test
public void constructor_assertLayoutResource_P00() {
FlashNotificationsPreviewPreference preference = new FlashNotificationsPreviewPreference(
mContext);
assertThat(preference.getLayoutResource())
.isEqualTo(R.layout.flash_notification_preview_preference);
@Before
public void setUp() {
mPreferenceViewHolder = PreferenceViewHolder.createInstanceForTests(
LayoutInflater.from(mContext).inflate(
R.layout.flash_notification_preview_preference, null));
mFlashNotificationsPreviewPreference = new FlashNotificationsPreviewPreference(mContext);
}
@Test
public void constructor_assertLayoutResource_P01() {
FlashNotificationsPreviewPreference preference = new FlashNotificationsPreviewPreference(
mContext, mAttributeSet);
assertThat(preference.getLayoutResource())
.isEqualTo(R.layout.flash_notification_preview_preference);
public void setEnabled_true_verifyEnabledUi() {
@ColorInt final int textColorEnabled = ((TextView) mPreferenceViewHolder.findViewById(
android.R.id.title)).getCurrentTextColor();
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
public void constructor_assertLayoutResource_P02() {
FlashNotificationsPreviewPreference preference = new FlashNotificationsPreviewPreference(
mContext, mAttributeSet, 0);
assertThat(preference.getLayoutResource())
.isEqualTo(R.layout.flash_notification_preview_preference);
}
public void setEnabled_false_verifyDisabledUi() {
@ColorInt final int textColorDisabled = Utils.getColorAttrDefaultColor(mContext,
android.R.attr.textColorPrimary);
@Test
public void constructor_assertLayoutResource_P03() {
FlashNotificationsPreviewPreference preference = new FlashNotificationsPreviewPreference(
mContext, mAttributeSet, 0, 0);
assertThat(preference.getLayoutResource())
.isEqualTo(R.layout.flash_notification_preview_preference);
mFlashNotificationsPreviewPreference.setEnabled(false);
mFlashNotificationsPreviewPreference.onBindViewHolder(mPreferenceViewHolder);
final View frame = mPreferenceViewHolder.findViewById(R.id.frame);
final int backgroundResId = Shadows.shadowOf(frame.getBackground()).getCreatedFromResId();
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);
}
}
}

View File

@@ -53,7 +53,6 @@ import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.Vibrator;
import android.util.FeatureFlagUtils;
import android.view.Display;
import android.view.Surface;
import android.view.View;
@@ -203,8 +202,6 @@ public class FingerprintEnrollEnrollingTest {
@Test
public void fingerprintUdfpsOverlayEnrollment_showOverlayPortrait() {
FeatureFlagUtils.setEnabled(mContext,
FeatureFlagUtils.SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS, true);
initializeActivityFor(TYPE_UDFPS_OPTICAL);
when(mMockDisplay.getRotation()).thenReturn(Surface.ROTATION_0);
@@ -216,8 +213,6 @@ public class FingerprintEnrollEnrollingTest {
@Test
public void fingerprintUdfpsOverlayEnrollment_showOverlayLandscape() {
FeatureFlagUtils.setEnabled(mContext,
FeatureFlagUtils.SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS, true);
initializeActivityFor(TYPE_UDFPS_OPTICAL);
when(mMockDisplay.getRotation()).thenReturn(Surface.ROTATION_90);
@@ -229,8 +224,6 @@ public class FingerprintEnrollEnrollingTest {
@Test
public void fingerprintUdfpsOverlayEnrollment_usesCorrectProgressBarFillColor() {
FeatureFlagUtils.setEnabled(mContext,
FeatureFlagUtils.SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS, true);
initializeActivityFor(TYPE_UDFPS_OPTICAL);
final TypedArray ta = mActivity.obtainStyledAttributes(null,
R.styleable.BiometricsEnrollView, R.attr.biometricsEnrollStyle,
@@ -250,9 +243,7 @@ public class FingerprintEnrollEnrollingTest {
@Test
public void fingerprintUdfpsOverlayEnrollment_checkViewOverlapPortrait() {
FeatureFlagUtils.setEnabled(mContext,
FeatureFlagUtils.SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS, true);
when(mMockDisplay.getRotation()).thenReturn(Surface.ROTATION_90);
when(mMockDisplay.getRotation()).thenReturn(Surface.ROTATION_0);
initializeActivityFor(TYPE_UDFPS_OPTICAL);
final GlifLayout defaultLayout = mActivity.findViewById(R.id.setup_wizard_layout);
@@ -294,9 +285,9 @@ public class FingerprintEnrollEnrollingTest {
udfpsEnrollView.getViewTreeObserver().addOnDrawListener(() -> {
udfpsEnrollView.getLocationOnScreen(udfpsEnrollViewPosition);
rectUdfpsEnrollView.set(new Rect(udfpsEnrollViewPosition[0],
udfpsEnrollViewPosition[1], udfpsEnrollViewPosition[0]
+ udfpsEnrollView.getWidth(), udfpsEnrollViewPosition[1]
+ udfpsEnrollView.getHeight()));
udfpsEnrollViewPosition[1], udfpsEnrollViewPosition[0]
+ udfpsEnrollView.getWidth(), udfpsEnrollViewPosition[1]
+ udfpsEnrollView.getHeight()));
});
lottieAnimationContainer.getViewTreeObserver().addOnDrawListener(() -> {
@@ -320,10 +311,36 @@ public class FingerprintEnrollEnrollingTest {
.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
public void forwardEnrollProgressEvents() {
FeatureFlagUtils.setEnabled(mContext,
FeatureFlagUtils.SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS, true);
initializeActivityFor(TYPE_UDFPS_OPTICAL);
EnrollListener listener = new EnrollListener(mActivity);
@@ -337,8 +354,6 @@ public class FingerprintEnrollEnrollingTest {
@Test
public void forwardEnrollHelpEvents() {
FeatureFlagUtils.setEnabled(mContext,
FeatureFlagUtils.SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS, true);
initializeActivityFor(TYPE_UDFPS_OPTICAL);
EnrollListener listener = new EnrollListener(mActivity);
@@ -352,8 +367,6 @@ public class FingerprintEnrollEnrollingTest {
@Test
public void forwardEnrollAcquiredEvents() {
FeatureFlagUtils.setEnabled(mContext,
FeatureFlagUtils.SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS, true);
initializeActivityFor(TYPE_UDFPS_OPTICAL);
EnrollListener listener = new EnrollListener(mActivity);
@@ -368,8 +381,6 @@ public class FingerprintEnrollEnrollingTest {
@Test
public void forwardEnrollPointerDownEvents() {
FeatureFlagUtils.setEnabled(mContext,
FeatureFlagUtils.SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS, true);
initializeActivityFor(TYPE_UDFPS_OPTICAL);
EnrollListener listener = new EnrollListener(mActivity);
@@ -383,8 +394,6 @@ public class FingerprintEnrollEnrollingTest {
@Test
public void forwardEnrollPointerUpEvents() {
FeatureFlagUtils.setEnabled(mContext,
FeatureFlagUtils.SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS, true);
initializeActivityFor(TYPE_UDFPS_OPTICAL);
EnrollListener listener = new EnrollListener(mActivity);

View File

@@ -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.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.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
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.testutils.FakeFeatureFactory;
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.ShadowUserManager;
import com.android.settings.testutils.shadow.ShadowUtils;
@@ -63,6 +67,7 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
@@ -74,7 +79,7 @@ import java.util.ArrayList;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowSettingsPreferenceFragment.class, ShadowUtils.class, ShadowFragment.class,
ShadowUserManager.class})
ShadowUserManager.class, ShadowLockPatternUtils.class})
public class FingerprintSettingsFragmentTest {
private FingerprintSettingsFragment mFragment;
private Context mContext;
@@ -92,10 +97,62 @@ public class FingerprintSettingsFragmentTest {
doReturn(true).when(mFingerprintManager).isHardwareDetected();
ShadowUtils.setFingerprintManager(mFingerprintManager);
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.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, new byte[0]);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, 1L);
if (!showChooseLock) {
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, new byte[0]);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, 1L);
}
mActivity = spy(Robolectric.buildActivity(FragmentActivity.class, intent).get());
mContext = spy(ApplicationProvider.getApplicationContext());
@@ -112,49 +169,12 @@ public class FingerprintSettingsFragmentTest {
doNothing().when(mFragment).startActivityForResult(any(Intent.class), anyInt());
setSensor();
}
@After
public void tearDown() {
ShadowUtils.reset();
}
@Test
public void testAddFingerprint_inFullScreen_noDialog() {
// Start fragment
mFragment.onAttach(mContext);
mFragment.onCreate(null);
mFragment.onCreateView(LayoutInflater.from(mContext), mock(ViewGroup.class), Bundle.EMPTY);
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() {

View File

@@ -56,6 +56,9 @@ import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import java.util.HashSet;
import java.util.Set;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowEntityHeaderController.class, ShadowDeviceConfig.class})
public class AdvancedBluetoothDetailsHeaderControllerTest {
@@ -380,40 +383,68 @@ public class AdvancedBluetoothDetailsHeaderControllerTest {
SettingsUIDeviceConfig.BT_ADVANCED_HEADER_ENABLED, "true", true);
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
.thenReturn("true".getBytes());
Set<CachedBluetoothDevice> cacheBluetoothDevices = new HashSet<>();
when(mCachedDevice.getMemberDevice()).thenReturn(cacheBluetoothDevices);
mController.onStart();
verify(mCachedDevice).registerCallback(mController);
verify(mBluetoothAdapter).addOnMetadataChangedListener(mBluetoothDevice,
mContext.getMainExecutor(), mController.mMetadataListener);
}
@Test
public void onStop_isRegisterCallback_unregisterCallback() {
mController.mIsRegisterCallback = true;
mController.onStop();
verify(mBluetoothAdapter).removeOnMetadataChangedListener(mBluetoothDevice,
mController.mMetadataListener);
}
@Test
public void onStart_notAvailable_registerCallback() {
public void onStart_notAvailable_notNeedToRegisterCallback() {
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
.thenReturn("false".getBytes());
mController.onStart();
verify(mCachedDevice, never()).registerCallback(mController);
verify(mBluetoothAdapter, never()).addOnMetadataChangedListener(mBluetoothDevice,
mContext.getMainExecutor(), mController.mMetadataListener);
}
@Test
public void onStop_notRegisterCallback_unregisterCallback() {
mController.mIsRegisterCallback = false;
public void onStart_isAvailableButNoBluetoothDevice_notNeedToRegisterCallback() {
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();
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,
mController.mMetadataListener);
}

View File

@@ -81,9 +81,10 @@ public class GraphicsDriverEnableAngleAsSystemDriverControllerTest {
// since GraphicsEnvironment is mocked in Robolectric test environment,
// we will override the system property persist.graphics.egl as if it is changed by
// mGraphicsEnvironment.toggleAngleAsSystemDriver(true).
// TODO: b/270994705 yuxinhu:
// add test coverage to test mGraphicsEnvironment.toggleAngleAsSystemDriver()
// works properly on Android devices / emulators.
// for test that actually verifies mGraphicsEnvironment.toggleAngleAsSystemDriver(true)
// on a device/emulator, please refer to
// GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest
ShadowSystemProperties.override(PROPERTY_PERSISTENT_GRAPHICS_EGL, ANGLE_DRIVER_SUFFIX);
mController.onPreferenceChange(mPreference, true);
final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
@@ -97,9 +98,10 @@ public class GraphicsDriverEnableAngleAsSystemDriverControllerTest {
// since GraphicsEnvironment is mocked in Robolectric test environment,
// we will override the system property persist.graphics.egl as if it is changed by
// mGraphicsEnvironment.toggleAngleAsSystemDriver(false).
// TODO: b/270994705 yuxinhu:
// add test coverage to test mGraphicsEnvironment.toggleAngleAsSystemDriver()
// works properly on Android devices / emulators.
// for test that actually verifies mGraphicsEnvironment.toggleAngleAsSystemDriver(true)
// on a device/emulator, please refer to
// GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest
ShadowSystemProperties.override(PROPERTY_PERSISTENT_GRAPHICS_EGL, "");
mController.onPreferenceChange(mPreference, false);
final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
@@ -124,20 +126,14 @@ public class GraphicsDriverEnableAngleAsSystemDriverControllerTest {
@Test
public void updateState_angleSupported_angleUsed_preferenceShouldBeChecked() {
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);
mController.updateState(mPreference);
verify(mPreference).setChecked(true); //false
verify(mPreference).setChecked(true);
}
@Test
public void updateState_angleSupported_angleNotUsed_preferenceShouldNotBeChecked() {
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, "");
mController.updateState(mPreference);
verify(mPreference).setChecked(false);

View File

@@ -70,6 +70,8 @@ import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.Resetter;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
@@ -84,6 +86,8 @@ public final class BatteryBackupHelperTest {
private static final int UID1 = 1;
private Context mContext;
private PrintWriter mPrintWriter;
private StringWriter mStringWriter;
private BatteryBackupHelper mBatteryBackupHelper;
@Mock
@@ -109,6 +113,8 @@ public final class BatteryBackupHelperTest {
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
mStringWriter = new StringWriter();
mPrintWriter = new PrintWriter(mStringWriter);
doReturn(mContext).when(mContext).getApplicationContext();
doReturn(mAppOpsManager).when(mContext).getSystemService(AppOpsManager.class);
doReturn(mUserManager).when(mContext).getSystemService(UserManager.class);
@@ -126,6 +132,7 @@ public final class BatteryBackupHelperTest {
@After
public void resetShadows() {
ShadowUserHandle.reset();
BatteryBackupHelper.getSharedPreferences(mContext).edit().clear().apply();
}
@Test
@@ -216,6 +223,8 @@ public final class BatteryBackupHelperTest {
// 2 for UNRESTRICTED mode and 1 for RESTRICTED mode.
final String expectedResult = PACKAGE_NAME1 + ":2," + PACKAGE_NAME2 + ":1,";
verifyBackupData(expectedResult);
verifyDumpHistoryData("com.android.testing.1\taction:BACKUP\tevent:mode: 2");
verifyDumpHistoryData("com.android.testing.2\taction:BACKUP\tevent:mode: 1");
}
@Test
@@ -232,6 +241,7 @@ public final class BatteryBackupHelperTest {
// "com.android.testing.2" for RESTRICTED mode.
final String expectedResult = PACKAGE_NAME2 + ":1,";
verifyBackupData(expectedResult);
verifyDumpHistoryData("com.android.testing.2\taction:BACKUP\tevent:mode: 1");
}
@Test
@@ -248,6 +258,7 @@ public final class BatteryBackupHelperTest {
// "com.android.testing.2" for RESTRICTED mode.
final String expectedResult = PACKAGE_NAME2 + ":1,";
verifyBackupData(expectedResult);
verifyDumpHistoryData("com.android.testing.2\taction:BACKUP\tevent:mode: 1");
}
@Test
@@ -357,6 +368,11 @@ public final class BatteryBackupHelperTest {
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 {
final byte[] expectedBytes = expectedResult.getBytes();
final ArgumentCaptor<byte[]> captor = ArgumentCaptor.forClass(byte[].class);

View File

@@ -49,7 +49,7 @@ public final class BatteryHistoricalLogUtilTest {
@Test
public void printHistoricalLog_withDefaultLogs() {
BatteryHistoricalLogUtil.printBatteryOptimizeHistoricalLog(mContext, mTestPrintWriter);
assertThat(mTestStringWriter.toString()).contains("No past logs");
assertThat(mTestStringWriter.toString()).contains("nothing to dump");
}
@Test
@@ -58,7 +58,7 @@ public final class BatteryHistoricalLogUtilTest {
BatteryHistoricalLogUtil.printBatteryOptimizeHistoricalLog(mContext, mTestPrintWriter);
assertThat(mTestStringWriter.toString()).contains(
"pkg1\tAction:APPLY\tEvent:logs\tTimestamp:");
"pkg1\taction:APPLY\tevent:logs");
}
@Test

View File

@@ -133,18 +133,12 @@ public class MobileNetworkSummaryControllerTest {
assertThat(mController.isAvailable()).isFalse();
}
@Ignore
@Test
public void getSummary_noSubscriptions_correctSummaryAndClickHandler() {
public void getSummary_noSubscriptions_returnSummaryCorrectly() {
mController.displayPreference(mPreferenceScreen);
mController.onResume();
assertThat(mController.getSummary()).isEqualTo("Add a network");
final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
doNothing().when(mContext).startActivity(intentCaptor.capture());
mPreference.getOnPreferenceClickListener().onPreferenceClick(mPreference);
assertThat(intentCaptor.getValue().getAction()).isEqualTo(
EuiccManager.ACTION_PROVISION_EMBEDDED_SUBSCRIPTION);
assertThat(mController.getSummary()).isEqualTo("Add a network");
}
@Test
@@ -300,15 +294,13 @@ public class MobileNetworkSummaryControllerTest {
assertThat(captor.getValue()).isFalse();
}
@Ignore
@Test
public void onResume_noSubscriptionEsimDisabled_isDisabled() {
public void onAvailableSubInfoChanged_noSubscriptionEsimDisabled_isDisabled() {
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0);
SubscriptionUtil.setAvailableSubscriptionsForTesting(null);
when(mEuiccManager.isEnabled()).thenReturn(false);
mController.displayPreference(mPreferenceScreen);
mController.onResume();
mController.onAvailableSubInfoChanged(null);
assertThat(mPreference.isEnabled()).isFalse();
}

View File

@@ -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_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_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_REQUESTED_MIN_COMPLEXITY;
@@ -126,7 +128,9 @@ public class ChooseLockGenericTest {
when(mFaceManager.isHardwareDetected()).thenReturn(true);
when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
when(mFakeFeatureFactory.mFaceFeatureProvider.isSetupWizardSupported(any())).thenReturn(
false);
true);
ShadowUtils.setFingerprintManager(mFingerprintManager);
ShadowUtils.setFaceManager(mFaceManager);
}
@After
@@ -540,35 +544,63 @@ public class ChooseLockGenericTest {
@Test
public void updatePreferenceText_supportBiometrics_showFaceAndFingerprint() {
ShadowLockPatternUtils.setRequiredPasswordComplexity(PASSWORD_COMPLEXITY_LOW);
final PasswordPolicy policy = new PasswordPolicy();
policy.quality = PASSWORD_QUALITY_ALPHABETIC;
ShadowLockPatternUtils.setRequestedProfilePasswordMetrics(policy.getMinMetrics());
ShadowStorageManager.setIsFileEncrypted(false);
final Intent intent = new Intent().putExtra(EXTRA_KEY_FOR_BIOMETRICS, true);
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(
R.string.security_settings_fingerprint));
final String supportFace = capitalize(mActivity.getResources().getString(
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(
supportFingerprint);
assertThat(mFragment.getBiometricsPreferenceTitle(ScreenLockType.PIN)).contains(
supportFace);
assertThat(mFragment.getBiometricsPreferenceTitle(ScreenLockType.PATTERN)).contains(
supportFingerprint);
assertThat(mFragment.getBiometricsPreferenceTitle(ScreenLockType.PATTERN)).contains(
supportFace);
assertThat(mFragment.getBiometricsPreferenceTitle(ScreenLockType.PASSWORD)).contains(
supportFingerprint);
assertThat(mFragment.getBiometricsPreferenceTitle(ScreenLockType.PASSWORD)).contains(
supportFace);
assertThat(pinTitle).contains(supportFingerprint);
assertThat(pinTitle).contains(supportFace);
assertThat(patternTitle).contains(supportFingerprint);
assertThat(patternTitle).contains(supportFace);
assertThat(passwordTitle).contains(supportFingerprint);
assertThat(passwordTitle).contains(supportFace);
}
@Test
public void updatePreferenceText_supportFingerprint_showFingerprint() {
ShadowStorageManager.setIsFileEncrypted(false);
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) {

View File

@@ -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);
}
}