Snap for 12205827 from 1a888b6e8f to 24Q4-release
Change-Id: I88b150906cf68bc5133d1571c6957e4b969d9259
This commit is contained in:
@@ -1,22 +0,0 @@
|
||||
<?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.
|
||||
-->
|
||||
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@color/settingslib_materialColorSurfaceBright" />
|
||||
<corners android:radius="@dimen/battery_tips_card_corner_radius_normal" />
|
||||
</shape>
|
||||
@@ -1,21 +0,0 @@
|
||||
<?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 android:drawable="@drawable/battery_tips_all_rounded_bg"/>
|
||||
</ripple>
|
||||
@@ -1,27 +0,0 @@
|
||||
<?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.
|
||||
-->
|
||||
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@color/settingslib_dialog_background"/>
|
||||
<corners
|
||||
android:topLeftRadius="@dimen/battery_tips_card_corner_radius_small"
|
||||
android:topRightRadius="@dimen/battery_tips_card_corner_radius_small"
|
||||
android:bottomLeftRadius="@dimen/battery_tips_card_corner_radius_normal"
|
||||
android:bottomRightRadius="@dimen/battery_tips_card_corner_radius_normal"
|
||||
/>
|
||||
</shape>
|
||||
@@ -1,27 +0,0 @@
|
||||
<?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.
|
||||
-->
|
||||
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@color/settingslib_dialog_background"/>
|
||||
<corners
|
||||
android:topLeftRadius="@dimen/battery_tips_card_corner_radius_normal"
|
||||
android:topRightRadius="@dimen/battery_tips_card_corner_radius_normal"
|
||||
android:bottomLeftRadius="@dimen/battery_tips_card_corner_radius_small"
|
||||
android:bottomRightRadius="@dimen/battery_tips_card_corner_radius_small"
|
||||
/>
|
||||
</shape>
|
||||
@@ -1,61 +0,0 @@
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/battery_tips_card"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
|
||||
android:layout_marginEnd="?android:attr/listPreferredItemPaddingEnd"
|
||||
android:background="@drawable/battery_tips_all_rounded_bg_ripple"
|
||||
android:orientation="vertical"
|
||||
android:padding="20dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical|start"
|
||||
android:contentDescription="@string/battery_usage_anomaly_content_description"
|
||||
android:src="@drawable/ic_battery_tips_lightbulb" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:textAlignment="viewStart"
|
||||
android:textAppearance="@style/TextAppearance.Material3.TitleMedium"
|
||||
android:textColor="@color/settingslib_materialColorOnSurface" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:gravity="end"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/dismiss_button"
|
||||
style="@style/Widget.Material3.Button.TextButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end|center_vertical"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:text="@string/battery_tips_card_dismiss_button"
|
||||
android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle2"
|
||||
android:textColor="@color/color_accent_selector" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/main_button"
|
||||
style="@style/Widget.Material3.Button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end|center_vertical"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:text="@string/battery_tips_card_action_button"
|
||||
android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle2"
|
||||
android:textColor="@color/settingslib_materialColorOnPrimary"
|
||||
app:backgroundTint="@color/color_accent_selector" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
@@ -937,7 +937,7 @@
|
||||
<!-- Message showing that multiple fingerprints, face, and the current watch is set up. Shown for a menu item that launches fingerprint, face, and active unlock settings or enrollment. [CHAR LIMIT=80]-->
|
||||
<string name="security_settings_fingerprint_multiple_face_watch_preference_summary">Face, fingerprints, and <xliff:g id="watch" example="Dani's Watch">%s</xliff:g> added</string>
|
||||
<!-- Description for mandatory biometrics prompt-->
|
||||
<string name="mandatory_biometrics_prompt_description">This is needed since Identity Check is on</string>
|
||||
<string name="mandatory_biometrics_prompt_description">Identity Check is on</string>
|
||||
<!-- RemoteAuth unlock enrollment and settings --><skip />
|
||||
<!-- Title shown for menu item that launches watch unlock settings. [CHAR LIMIT=40] -->
|
||||
<string name ="security_settings_remoteauth_preference_title">Remote Authenticator Unlock</string>
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
"com.android.settings.fuelgauge.batteryusage.BatteryTipsController"
|
||||
settings:isPreferenceVisible="false">
|
||||
|
||||
<com.android.settings.fuelgauge.batteryusage.BatteryTipsCardPreference
|
||||
<com.android.settings.widget.TipCardPreference
|
||||
android:key="battery_tips_card"
|
||||
settings:isPreferenceVisible="false" />
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import static android.app.Activity.RESULT_CANCELED;
|
||||
import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE;
|
||||
import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS;
|
||||
import static android.provider.Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED;
|
||||
import static android.provider.Settings.Secure.ACCESSIBILITY_GESTURE_TARGETS;
|
||||
import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_TWO_FINGER_TRIPLE_TAP_ENABLED;
|
||||
import static android.provider.Settings.Secure.ACCESSIBILITY_QS_TARGETS;
|
||||
import static android.provider.Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE;
|
||||
@@ -93,7 +94,8 @@ public class EditShortcutsPreferenceFragment extends DashboardFragment {
|
||||
Settings.Secure.getUriFor(ACCESSIBILITY_BUTTON_MODE);
|
||||
private static final Uri BUTTON_SHORTCUT_SETTING =
|
||||
Settings.Secure.getUriFor(ACCESSIBILITY_BUTTON_TARGETS);
|
||||
|
||||
private static final Uri GESTURE_SHORTCUT_SETTING =
|
||||
Settings.Secure.getUriFor(ACCESSIBILITY_GESTURE_TARGETS);
|
||||
private static final Uri TRIPLE_TAP_SHORTCUT_SETTING =
|
||||
Settings.Secure.getUriFor(ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED);
|
||||
private static final Uri TWO_FINGERS_DOUBLE_TAP_SHORTCUT_SETTING =
|
||||
@@ -107,6 +109,7 @@ public class EditShortcutsPreferenceFragment extends DashboardFragment {
|
||||
VOLUME_KEYS_SHORTCUT_SETTING,
|
||||
BUTTON_SHORTCUT_MODE_SETTING,
|
||||
BUTTON_SHORTCUT_SETTING,
|
||||
GESTURE_SHORTCUT_SETTING,
|
||||
TRIPLE_TAP_SHORTCUT_SETTING,
|
||||
TWO_FINGERS_DOUBLE_TAP_SHORTCUT_SETTING,
|
||||
QUICK_SETTINGS_SHORTCUT_SETTING,
|
||||
@@ -173,6 +176,8 @@ public class EditShortcutsPreferenceFragment extends DashboardFragment {
|
||||
} else if (BUTTON_SHORTCUT_MODE_SETTING.equals(uri)
|
||||
|| BUTTON_SHORTCUT_SETTING.equals(uri)) {
|
||||
refreshSoftwareShortcutControllers();
|
||||
} else if (GESTURE_SHORTCUT_SETTING.equals(uri)) {
|
||||
refreshPreferenceController(GestureShortcutOptionController.class);
|
||||
} else if (TRIPLE_TAP_SHORTCUT_SETTING.equals(uri)) {
|
||||
refreshPreferenceController(TripleTapShortcutOptionController.class);
|
||||
} else if (TWO_FINGERS_DOUBLE_TAP_SHORTCUT_SETTING.equals(uri)) {
|
||||
|
||||
@@ -50,8 +50,15 @@ public class FloatingButtonShortcutOptionController
|
||||
|
||||
@Override
|
||||
protected boolean isShortcutAvailable() {
|
||||
if (android.provider.Flags.a11yStandaloneGestureEnabled()) {
|
||||
// FAB should be available when in gesture navigation mode,
|
||||
// or if we're in the FAB button mode while in navbar navigation mode.
|
||||
return AccessibilityUtil.isGestureNavigateEnabled(mContext)
|
||||
|| AccessibilityUtil.isFloatingMenuEnabled(mContext);
|
||||
} else {
|
||||
return AccessibilityUtil.isFloatingMenuEnabled(mContext);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.settings.accessibility.shortcuts;
|
||||
|
||||
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.GESTURE;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.SpannableStringBuilder;
|
||||
|
||||
@@ -51,11 +53,22 @@ public class GestureShortcutOptionController extends SoftwareShortcutOptionPrefe
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getShortcutType() {
|
||||
return android.provider.Flags.a11yStandaloneGestureEnabled()
|
||||
? GESTURE : super.getShortcutType();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isShortcutAvailable() {
|
||||
if (android.provider.Flags.a11yStandaloneGestureEnabled()) {
|
||||
return !isInSetupWizard()
|
||||
&& !AccessibilityUtil.isFloatingMenuEnabled(mContext)
|
||||
&& AccessibilityUtil.isGestureNavigateEnabled(mContext);
|
||||
} else {
|
||||
return !isInSetupWizard()
|
||||
&& AccessibilityUtil.isGestureNavigateEnabled(mContext)
|
||||
&& !AccessibilityUtil.isFloatingMenuEnabled(mContext);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -68,9 +81,8 @@ public class GestureShortcutOptionController extends SoftwareShortcutOptionPrefe
|
||||
|
||||
final SpannableStringBuilder sb = new SpannableStringBuilder();
|
||||
sb.append(instruction);
|
||||
if (!isInSetupWizard()) {
|
||||
sb.append("\n\n");
|
||||
sb.append(getCustomizeAccessibilityButtonLink());
|
||||
if (!isInSetupWizard() && !android.provider.Flags.a11yStandaloneGestureEnabled()) {
|
||||
sb.append("\n\n").append(getCustomizeAccessibilityButtonLink());
|
||||
}
|
||||
|
||||
return sb;
|
||||
|
||||
@@ -42,6 +42,8 @@ import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.os.VibrationEffect;
|
||||
import android.os.Vibrator;
|
||||
import android.text.InputFilter;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextUtils;
|
||||
@@ -109,6 +111,9 @@ public class FingerprintSettings extends SubSettings {
|
||||
private static final int RESULT_FINISHED = BiometricEnrollBase.RESULT_FINISHED;
|
||||
private static final int RESULT_SKIP = BiometricEnrollBase.RESULT_SKIP;
|
||||
private static final int RESULT_TIMEOUT = BiometricEnrollBase.RESULT_TIMEOUT;
|
||||
@VisibleForTesting
|
||||
static final VibrationEffect SUCCESS_VIBRATION_EFFECT =
|
||||
VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
|
||||
|
||||
@Override
|
||||
public Intent getIntent() {
|
||||
@@ -285,6 +290,7 @@ public class FingerprintSettings extends SubSettings {
|
||||
private FingerprintAuthenticateSidecar mAuthenticateSidecar;
|
||||
private FingerprintRemoveSidecar mRemovalSidecar;
|
||||
private HashMap<Integer, String> mFingerprintsRenaming;
|
||||
private Vibrator mVibrator;
|
||||
|
||||
@Nullable
|
||||
private UdfpsEnrollCalibrator mCalibrator;
|
||||
@@ -367,10 +373,10 @@ public class FingerprintSettings extends SubSettings {
|
||||
break;
|
||||
case MSG_FINGER_AUTH_HELP: {
|
||||
// Not used
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -511,6 +517,7 @@ public class FingerprintSettings extends SubSettings {
|
||||
addFirstFingerprint(null);
|
||||
}
|
||||
}
|
||||
mVibrator = getContext().getSystemService(Vibrator.class);
|
||||
final PreferenceScreen root = getPreferenceScreen();
|
||||
root.removeAll();
|
||||
addPreferencesFromResource(getPreferenceScreenResId());
|
||||
@@ -1095,6 +1102,7 @@ public class FingerprintSettings extends SubSettings {
|
||||
}
|
||||
|
||||
private void highlightFingerprintItem(int fpId) {
|
||||
mVibrator.vibrate(SUCCESS_VIBRATION_EFFECT);
|
||||
String prefName = genKey(fpId);
|
||||
FingerprintPreference fpref = (FingerprintPreference) findPreference(prefName);
|
||||
final Drawable highlight = getHighlightDrawable();
|
||||
|
||||
@@ -28,10 +28,11 @@ import androidx.annotation.Nullable;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.core.SubSettingLauncher;
|
||||
import com.android.settings.widget.TipCardPreference;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
final class AnomalyEventWrapper {
|
||||
class AnomalyEventWrapper {
|
||||
private static final String TAG = "AnomalyEventWrapper";
|
||||
|
||||
private final Context mContext;
|
||||
@@ -235,16 +236,16 @@ final class AnomalyEventWrapper {
|
||||
return mHighlightSlotPair;
|
||||
}
|
||||
|
||||
boolean updateTipsCardPreference(BatteryTipsCardPreference preference) {
|
||||
boolean updateTipsCardPreference(TipCardPreference preference) {
|
||||
final String titleString = getTitleString();
|
||||
if (TextUtils.isEmpty(titleString)) {
|
||||
return false;
|
||||
}
|
||||
preference.setTitle(titleString);
|
||||
preference.setIconResourceId(getIconResId());
|
||||
preference.setButtonColorResourceId(getColorResId());
|
||||
preference.setMainButtonLabel(getMainBtnString());
|
||||
preference.setDismissButtonLabel(getDismissBtnString());
|
||||
preference.setIconResId(getIconResId());
|
||||
preference.setTintColorResId(getColorResId());
|
||||
preference.setPrimaryButtonText(getDismissBtnString());
|
||||
preference.setSecondaryButtonText(getMainBtnString());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,150 +0,0 @@
|
||||
/*
|
||||
* 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.fuelgauge.batteryusage;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
import com.google.android.material.button.MaterialButton;
|
||||
|
||||
/** A preference for displaying the battery tips card view. */
|
||||
public class BatteryTipsCardPreference extends Preference implements View.OnClickListener {
|
||||
|
||||
private static final String TAG = "BatteryTipsCardPreference";
|
||||
|
||||
interface OnConfirmListener {
|
||||
void onConfirm();
|
||||
}
|
||||
|
||||
interface OnRejectListener {
|
||||
void onReject();
|
||||
}
|
||||
|
||||
private OnConfirmListener mOnConfirmListener;
|
||||
private OnRejectListener mOnRejectListener;
|
||||
private int mIconResourceId = 0;
|
||||
private int mButtonColorResourceId = 0;
|
||||
|
||||
@VisibleForTesting CharSequence mMainButtonLabel;
|
||||
@VisibleForTesting CharSequence mDismissButtonLabel;
|
||||
|
||||
public BatteryTipsCardPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
setLayoutResource(R.layout.battery_tips_card);
|
||||
setViewId(R.id.battery_tips_card);
|
||||
setSelectable(false);
|
||||
}
|
||||
|
||||
public void setOnConfirmListener(OnConfirmListener listener) {
|
||||
mOnConfirmListener = listener;
|
||||
}
|
||||
|
||||
public void setOnRejectListener(OnRejectListener listener) {
|
||||
mOnRejectListener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the icon in tips card.
|
||||
*/
|
||||
public void setIconResourceId(int resourceId) {
|
||||
if (mIconResourceId != resourceId) {
|
||||
mIconResourceId = resourceId;
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the background color for main button and the text color for dismiss button.
|
||||
*/
|
||||
public void setButtonColorResourceId(int resourceId) {
|
||||
if (mButtonColorResourceId != resourceId) {
|
||||
mButtonColorResourceId = resourceId;
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the label of main button in tips card.
|
||||
*/
|
||||
public void setMainButtonLabel(CharSequence label) {
|
||||
if (!TextUtils.equals(mMainButtonLabel, label)) {
|
||||
mMainButtonLabel = label;
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the label of dismiss button in tips card.
|
||||
*/
|
||||
public void setDismissButtonLabel(CharSequence label) {
|
||||
if (!TextUtils.equals(mDismissButtonLabel, label)) {
|
||||
mDismissButtonLabel = label;
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
final int viewId = view.getId();
|
||||
if (viewId == R.id.main_button || viewId == R.id.battery_tips_card) {
|
||||
if (mOnConfirmListener != null) {
|
||||
mOnConfirmListener.onConfirm();
|
||||
}
|
||||
} else if (viewId == R.id.dismiss_button) {
|
||||
if (mOnRejectListener != null) {
|
||||
mOnRejectListener.onReject();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(PreferenceViewHolder view) {
|
||||
super.onBindViewHolder(view);
|
||||
|
||||
((TextView) view.findViewById(R.id.title)).setText(getTitle());
|
||||
|
||||
final LinearLayout tipsCard = (LinearLayout) view.findViewById(R.id.battery_tips_card);
|
||||
tipsCard.setOnClickListener(this);
|
||||
final MaterialButton mainButton = (MaterialButton) view.findViewById(R.id.main_button);
|
||||
mainButton.setOnClickListener(this);
|
||||
mainButton.setText(mMainButtonLabel);
|
||||
final MaterialButton dismissButton =
|
||||
(MaterialButton) view.findViewById(R.id.dismiss_button);
|
||||
dismissButton.setOnClickListener(this);
|
||||
dismissButton.setText(mDismissButtonLabel);
|
||||
if (mButtonColorResourceId != 0) {
|
||||
final int colorInt = getContext().getColor(mButtonColorResourceId);
|
||||
mainButton.setBackgroundColor(colorInt);
|
||||
dismissButton.setTextColor(colorInt);
|
||||
}
|
||||
|
||||
if (mIconResourceId != 0) {
|
||||
((ImageView) view.findViewById(R.id.icon)).setImageResource(mIconResourceId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import androidx.preference.PreferenceScreen;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settings.widget.TipCardPreference;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
|
||||
/** Controls the update for battery tips card */
|
||||
@@ -50,10 +51,9 @@ public class BatteryTipsController extends BasePreferenceController {
|
||||
void onAnomalyReject();
|
||||
}
|
||||
|
||||
private OnAnomalyConfirmListener mOnAnomalyConfirmListener;
|
||||
private OnAnomalyRejectListener mOnAnomalyRejectListener;
|
||||
|
||||
@VisibleForTesting BatteryTipsCardPreference mCardPreference;
|
||||
@VisibleForTesting OnAnomalyConfirmListener mOnAnomalyConfirmListener;
|
||||
@VisibleForTesting OnAnomalyRejectListener mOnAnomalyRejectListener;
|
||||
@VisibleForTesting TipCardPreference mCardPreference;
|
||||
@VisibleForTesting AnomalyEventWrapper mAnomalyEventWrapper = null;
|
||||
@VisibleForTesting Boolean mIsAcceptable = false;
|
||||
|
||||
@@ -117,9 +117,48 @@ public class BatteryTipsController extends BasePreferenceController {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set battery tips card listener
|
||||
mCardPreference.setOnConfirmListener(
|
||||
mCardPreference.setPrimaryButtonAction(
|
||||
() -> {
|
||||
onBatteryTipsCardDismiss(anomalyKeyNumber);
|
||||
return null;
|
||||
});
|
||||
mCardPreference.setSecondaryButtonAction(
|
||||
() -> {
|
||||
onBatteryTipsCardAccept(anomalyKeyNumber);
|
||||
return null;
|
||||
});
|
||||
|
||||
mCardPreference.setPrimaryButtonVisibility(true);
|
||||
mCardPreference.setSecondaryButtonVisibility(true);
|
||||
mCardPreference.buildContent();
|
||||
mCardPreference.setVisible(true);
|
||||
mMetricsFeatureProvider.action(
|
||||
/* attribution= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
/* action= */ SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
|
||||
/* pageId= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
/* key= */ ANOMALY_KEY,
|
||||
/* value= */ anomalyKeyNumber);
|
||||
}
|
||||
|
||||
private void onBatteryTipsCardDismiss(final int anomalyKeyNumber) {
|
||||
mCardPreference.setVisible(false);
|
||||
if (mOnAnomalyRejectListener != null) {
|
||||
mOnAnomalyRejectListener.onAnomalyReject();
|
||||
}
|
||||
// For anomaly events with same record key, dismissed until next time full charged.
|
||||
final String dismissRecordKey = mAnomalyEventWrapper.getDismissRecordKey();
|
||||
if (!TextUtils.isEmpty(dismissRecordKey)) {
|
||||
DatabaseUtils.setDismissedPowerAnomalyKeys(mContext, dismissRecordKey);
|
||||
}
|
||||
mMetricsFeatureProvider.action(
|
||||
/* attribution= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
/* action= */ SettingsEnums.ACTION_BATTERY_TIPS_CARD_DISMISS,
|
||||
/* pageId= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
/* key= */ ANOMALY_KEY,
|
||||
/* value= */ anomalyKeyNumber);
|
||||
}
|
||||
|
||||
private void onBatteryTipsCardAccept(final int anomalyKeyNumber) {
|
||||
mCardPreference.setVisible(false);
|
||||
if (mOnAnomalyConfirmListener != null) {
|
||||
mOnAnomalyConfirmListener.onAnomalyConfirm();
|
||||
@@ -132,33 +171,5 @@ public class BatteryTipsController extends BasePreferenceController {
|
||||
/* key= */ ANOMALY_KEY,
|
||||
/* value= */ anomalyKeyNumber);
|
||||
}
|
||||
});
|
||||
mCardPreference.setOnRejectListener(
|
||||
() -> {
|
||||
mCardPreference.setVisible(false);
|
||||
if (mOnAnomalyRejectListener != null) {
|
||||
mOnAnomalyRejectListener.onAnomalyReject();
|
||||
}
|
||||
// For anomaly events with same record key, dismissed until next time full
|
||||
// charged.
|
||||
final String dismissRecordKey = mAnomalyEventWrapper.getDismissRecordKey();
|
||||
if (!TextUtils.isEmpty(dismissRecordKey)) {
|
||||
DatabaseUtils.setDismissedPowerAnomalyKeys(mContext, dismissRecordKey);
|
||||
}
|
||||
mMetricsFeatureProvider.action(
|
||||
/* attribution= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
/* action= */ SettingsEnums.ACTION_BATTERY_TIPS_CARD_DISMISS,
|
||||
/* pageId= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
/* key= */ ANOMALY_KEY,
|
||||
/* value= */ anomalyKeyNumber);
|
||||
});
|
||||
|
||||
mCardPreference.setVisible(true);
|
||||
mMetricsFeatureProvider.action(
|
||||
/* attribution= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
/* action= */ SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
|
||||
/* pageId= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
/* key= */ ANOMALY_KEY,
|
||||
/* value= */ anomalyKeyNumber);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.settings.network.ims;
|
||||
import static android.telephony.ims.ProvisioningManager.KEY_VOIMS_OPT_IN_STATUS;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.telecom.TelecomManager;
|
||||
import android.telephony.AccessNetworkConstants;
|
||||
import android.telephony.SubscriptionManager;
|
||||
@@ -143,6 +144,11 @@ public class VolteQueryImsState extends ImsQueryController {
|
||||
* @return true when VoIMS opt-in has been enabled, otherwise false
|
||||
*/
|
||||
public boolean isVoImsOptInEnabled() {
|
||||
if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY_IMS)) {
|
||||
// If the device does not have PackageManager.FEATURE_TELEPHONY_IMS,
|
||||
// ProvisioningManager.getProvisioningIntValue() could not be called.
|
||||
return false;
|
||||
}
|
||||
int voImsOptInStatus = ProvisioningManager.createForSubscriptionId(mSubId)
|
||||
.getProvisioningIntValue(KEY_VOIMS_OPT_IN_STATUS);
|
||||
return voImsOptInStatus == ProvisioningManager.PROVISIONING_VALUE_ENABLED;
|
||||
|
||||
@@ -104,6 +104,7 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
|
||||
private boolean mForceVerifyPath = false;
|
||||
private boolean mGoingToBackground;
|
||||
private boolean mWaitingForBiometricCallback;
|
||||
private int mBiometricsAuthenticators;
|
||||
|
||||
private Executor mExecutor = (runnable -> {
|
||||
mHandler.post(runnable);
|
||||
@@ -122,8 +123,14 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
|
||||
Log.i(TAG, "Finishing, user no longer valid: " + mUserId);
|
||||
finish();
|
||||
} else {
|
||||
if ((mBiometricsAuthenticators
|
||||
& BiometricManager.Authenticators.DEVICE_CREDENTIAL) != 0) {
|
||||
// All other errors go to some version of CC
|
||||
showConfirmCredentials();
|
||||
} else {
|
||||
Log.i(TAG, "Finishing, device credential not requested");
|
||||
finish();
|
||||
}
|
||||
}
|
||||
} else if (mWaitingForBiometricCallback) { // mGoingToBackground is true
|
||||
mWaitingForBiometricCallback = false;
|
||||
@@ -188,7 +195,7 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
|
||||
mDetails = intent.getCharSequenceExtra(KeyguardManager.EXTRA_DESCRIPTION);
|
||||
String alternateButton = intent.getStringExtra(
|
||||
KeyguardManager.EXTRA_ALTERNATE_BUTTON_LABEL);
|
||||
final int authenticators = intent.getIntExtra(BIOMETRIC_PROMPT_AUTHENTICATORS,
|
||||
mBiometricsAuthenticators = intent.getIntExtra(BIOMETRIC_PROMPT_AUTHENTICATORS,
|
||||
BiometricManager.Authenticators.DEVICE_CREDENTIAL
|
||||
| BiometricManager.Authenticators.BIOMETRIC_WEAK);
|
||||
final String negativeButtonText = intent.getStringExtra(
|
||||
@@ -229,7 +236,7 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
|
||||
promptInfo.setTitle(mTitle);
|
||||
promptInfo.setDescription(mDetails);
|
||||
promptInfo.setDisallowBiometricsIfPolicyExists(mCheckDevicePolicyManager);
|
||||
promptInfo.setAuthenticators(authenticators);
|
||||
promptInfo.setAuthenticators(mBiometricsAuthenticators);
|
||||
promptInfo.setNegativeButtonText(negativeButtonText);
|
||||
|
||||
if (android.multiuser.Flags.enablePrivateSpaceFeatures()
|
||||
|
||||
@@ -120,6 +120,16 @@ public class SettingsSliceProvider extends SliceProvider {
|
||||
* permission can use them.
|
||||
*/
|
||||
private static final List<Uri> PUBLICLY_SUPPORTED_CUSTOM_SLICE_URIS =
|
||||
android.app.Flags.modesUi()
|
||||
?
|
||||
Arrays.asList(
|
||||
CustomSliceRegistry.BLUETOOTH_URI,
|
||||
CustomSliceRegistry.FLASHLIGHT_SLICE_URI,
|
||||
CustomSliceRegistry.LOCATION_SLICE_URI,
|
||||
CustomSliceRegistry.MOBILE_DATA_SLICE_URI,
|
||||
CustomSliceRegistry.WIFI_CALLING_URI,
|
||||
CustomSliceRegistry.WIFI_SLICE_URI
|
||||
) :
|
||||
Arrays.asList(
|
||||
CustomSliceRegistry.BLUETOOTH_URI,
|
||||
CustomSliceRegistry.FLASHLIGHT_SLICE_URI,
|
||||
@@ -184,7 +194,9 @@ public class SettingsSliceProvider extends SliceProvider {
|
||||
}
|
||||
|
||||
if (CustomSliceRegistry.ZEN_MODE_SLICE_URI.equals(sliceUri)) {
|
||||
if (!android.app.Flags.modesUi()) {
|
||||
registerIntentToUri(ZenModeSliceBuilder.INTENT_FILTER, sliceUri);
|
||||
}
|
||||
return;
|
||||
} else if (CustomSliceRegistry.BLUETOOTH_URI.equals(sliceUri)) {
|
||||
registerIntentToUri(BluetoothSliceBuilder.INTENT_FILTER, sliceUri);
|
||||
@@ -256,7 +268,8 @@ public class SettingsSliceProvider extends SliceProvider {
|
||||
.getSlicesFeatureProvider()
|
||||
.getNewWifiCallingSliceHelper(getContext())
|
||||
.createWifiCallingSlice(sliceUri);
|
||||
} else if (CustomSliceRegistry.ZEN_MODE_SLICE_URI.equals(sliceUri)) {
|
||||
} else if (!android.app.Flags.modesUi()
|
||||
&& CustomSliceRegistry.ZEN_MODE_SLICE_URI.equals(sliceUri)) {
|
||||
return ZenModeSliceBuilder.getSlice(getContext());
|
||||
} else if (CustomSliceRegistry.BLUETOOTH_URI.equals(sliceUri)) {
|
||||
return BluetoothSliceBuilder.getSlice(getContext());
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.settings.widget
|
||||
import android.content.Context
|
||||
import android.content.res.Resources
|
||||
import android.util.AttributeSet
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import com.android.settings.spa.preference.ComposePreference
|
||||
@@ -37,6 +38,9 @@ constructor(
|
||||
/** A icon resource id for displaying icon on tips card. */
|
||||
var iconResId: Int? = null
|
||||
|
||||
/** A color resource id for displaying icon and button text on tips card. */
|
||||
var tintColorResId: Int? = null
|
||||
|
||||
/** The primary button's text. */
|
||||
var primaryButtonText: String = ""
|
||||
|
||||
@@ -85,6 +89,8 @@ constructor(
|
||||
title = title?.toString() ?: "",
|
||||
text = summary?.toString() ?: "",
|
||||
buttons = listOfNotNull(configPrimaryButton(), configSecondaryButton()),
|
||||
tintColor = tintColorResId?.let { Color(context.getColor(it)) }
|
||||
?: Color.Unspecified,
|
||||
onDismiss = onDismiss,
|
||||
imageVector =
|
||||
iconResId
|
||||
|
||||
@@ -16,37 +16,46 @@
|
||||
|
||||
package com.android.settings.accessibility.shortcuts;
|
||||
|
||||
import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU;
|
||||
import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_GESTURE;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.spy;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
import android.platform.test.annotations.EnableFlags;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
import android.provider.Flags;
|
||||
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.testutils.AccessibilityTestUtils;
|
||||
import com.android.settings.testutils.shadow.SettingsShadowResources;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Tests for {@link FloatingButtonShortcutOptionController}
|
||||
*/
|
||||
@Config(shadows = SettingsShadowResources.class)
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class FloatingButtonShortcutOptionControllerTest {
|
||||
@Rule
|
||||
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
|
||||
|
||||
private static final String PREF_KEY = "prefKey";
|
||||
private static final String TARGET =
|
||||
new ComponentName("FakePackage", "FakeClass").flattenToString();
|
||||
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||
private final Context mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
private FloatingButtonShortcutOptionController mController;
|
||||
private ShortcutOptionPreference mShortcutOptionPreference;
|
||||
|
||||
@@ -61,7 +70,6 @@ public class FloatingButtonShortcutOptionControllerTest {
|
||||
mShortcutOptionPreference.setKey(PREF_KEY);
|
||||
mPreferenceScreen = new PreferenceManager(mContext).createPreferenceScreen(mContext);
|
||||
mPreferenceScreen.addPreference(mShortcutOptionPreference);
|
||||
setFloatingButtonEnabled(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -95,23 +103,26 @@ public class FloatingButtonShortcutOptionControllerTest {
|
||||
|
||||
@Test
|
||||
public void isShortcutAvailable_floatingMenuEnabled_returnTrue() {
|
||||
setFloatingButtonEnabled(true);
|
||||
AccessibilityTestUtils.setSoftwareShortcutMode(
|
||||
mContext, /* gestureNavEnabled= */ false, /* floatingButtonEnabled= */ true);
|
||||
|
||||
assertThat(mController.isShortcutAvailable()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isShortcutAvailable_floatingMenuDisabled_returnFalse() {
|
||||
setFloatingButtonEnabled(false);
|
||||
AccessibilityTestUtils.setSoftwareShortcutMode(
|
||||
mContext, /* gestureNavEnabled= */ false, /* floatingButtonEnabled= */ false);
|
||||
|
||||
assertThat(mController.isShortcutAvailable()).isFalse();
|
||||
}
|
||||
|
||||
private void setFloatingButtonEnabled(boolean enable) {
|
||||
int mode = enable
|
||||
? ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU : ACCESSIBILITY_BUTTON_MODE_GESTURE;
|
||||
@Test
|
||||
@EnableFlags(Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED)
|
||||
public void isShortcutAvailable_gestureNavigationMode_returnsTrue() {
|
||||
AccessibilityTestUtils.setSoftwareShortcutMode(
|
||||
mContext, /* gestureNavEnabled= */ true, /* floatingButtonEnabled= */ false);
|
||||
|
||||
Settings.Secure.putInt(mContext.getContentResolver(),
|
||||
Settings.Secure.ACCESSIBILITY_BUTTON_MODE, mode);
|
||||
assertThat(mController.isShortcutAvailable()).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.settings.accessibility.shortcuts;
|
||||
|
||||
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.GESTURE;
|
||||
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.SOFTWARE;
|
||||
import static com.android.settings.testutils.AccessibilityTestUtils.setupMockAccessibilityManager;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
@@ -25,6 +27,10 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.platform.test.annotations.DisableFlags;
|
||||
import android.platform.test.annotations.EnableFlags;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
import android.provider.Flags;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
|
||||
import androidx.preference.PreferenceManager;
|
||||
@@ -37,6 +43,7 @@ import com.android.settings.testutils.shadow.SettingsShadowResources;
|
||||
import com.android.settingslib.utils.StringUtil;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
@@ -50,6 +57,8 @@ import java.util.Set;
|
||||
@Config(shadows = SettingsShadowResources.class)
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class GestureShortcutOptionControllerTest {
|
||||
@Rule
|
||||
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
|
||||
private static final String PREF_KEY = "prefKey";
|
||||
private static final String TARGET =
|
||||
new ComponentName("FakePackage", "FakeClass").flattenToString();
|
||||
@@ -136,6 +145,18 @@ public class GestureShortcutOptionControllerTest {
|
||||
assertThat(mController.getSummary().toString()).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
@EnableFlags(Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED)
|
||||
public void getSummary_standaloneGestureFlagOn_verifyNoCustomizeA11yButtonTest() {
|
||||
enableTouchExploration(true);
|
||||
String expected = StringUtil.getIcuPluralsString(
|
||||
mContext,
|
||||
/* count= */ 3,
|
||||
R.string.accessibility_shortcut_edit_dialog_summary_gesture);
|
||||
|
||||
assertThat(mController.getSummary().toString()).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isShortcutAvailable_inSuw_returnFalse() {
|
||||
mController.setInSetupWizard(true);
|
||||
@@ -144,6 +165,7 @@ public class GestureShortcutOptionControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisableFlags(Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED)
|
||||
public void isShortcutAvailable_notInSuwUseGestureNavSystemUseFab_returnFalse() {
|
||||
mController.setInSetupWizard(false);
|
||||
AccessibilityTestUtils.setSoftwareShortcutMode(
|
||||
@@ -179,6 +201,28 @@ public class GestureShortcutOptionControllerTest {
|
||||
assertThat(mController.isShortcutAvailable()).isFalse();
|
||||
}
|
||||
|
||||
@EnableFlags(Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED)
|
||||
@Test
|
||||
public void isShortcutAvailable_floatingMenuEnabled_gestureNavEnabled_returnsTrue() {
|
||||
mController.setInSetupWizard(false);
|
||||
AccessibilityTestUtils.setSoftwareShortcutMode(
|
||||
mContext, /* gestureNavEnabled= */ true, /* floatingButtonEnabled= */ true);
|
||||
|
||||
assertThat(mController.isShortcutAvailable()).isTrue();
|
||||
}
|
||||
|
||||
@EnableFlags(Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED)
|
||||
@Test
|
||||
public void getShortcutType_gesture() {
|
||||
assertThat(mController.getShortcutType()).isEqualTo(GESTURE);
|
||||
}
|
||||
|
||||
@DisableFlags(Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED)
|
||||
@Test
|
||||
public void getShortcutType_software() {
|
||||
assertThat(mController.getShortcutType()).isEqualTo(SOFTWARE);
|
||||
}
|
||||
|
||||
private void enableTouchExploration(boolean enable) {
|
||||
AccessibilityManager am = setupMockAccessibilityManager(mContext);
|
||||
when(am.isTouchExplorationEnabled()).thenReturn(enable);
|
||||
|
||||
@@ -54,6 +54,7 @@ import android.os.Bundle;
|
||||
import android.os.CancellationSignal;
|
||||
import android.os.Looper;
|
||||
import android.os.UserHandle;
|
||||
import android.os.Vibrator;
|
||||
import android.platform.test.annotations.EnableFlags;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
import android.provider.Settings;
|
||||
@@ -128,6 +129,9 @@ public class FingerprintSettingsFragmentTest {
|
||||
mAuthenticationCallbackArgumentCaptor = ArgumentCaptor.forClass(
|
||||
FingerprintManager.AuthenticationCallback.class);
|
||||
|
||||
@Mock
|
||||
private Vibrator mVibrator;
|
||||
|
||||
private FingerprintAuthenticateSidecar mFingerprintAuthenticateSidecar;
|
||||
private FingerprintRemoveSidecar mFingerprintRemoveSidecar;
|
||||
|
||||
@@ -141,6 +145,7 @@ public class FingerprintSettingsFragmentTest {
|
||||
doReturn(mContext).when(mFragment).getContext();
|
||||
doReturn(mBiometricManager).when(mContext).getSystemService(BiometricManager.class);
|
||||
doReturn(true).when(mFingerprintManager).isHardwareDetected();
|
||||
doReturn(mVibrator).when(mContext).getSystemService(Vibrator.class);
|
||||
when(mBiometricManager.canAuthenticate(
|
||||
BiometricManager.Authenticators.MANDATORY_BIOMETRICS))
|
||||
.thenReturn(BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE);
|
||||
@@ -287,6 +292,28 @@ public class FingerprintSettingsFragmentTest {
|
||||
assertThat(mFragment.isVisible()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("b/353726774")
|
||||
public void fingerprintVibratesOnAuthSuccess() {
|
||||
setUpFragment(false);
|
||||
|
||||
doNothing().when(mFingerprintManager).authenticate(any(),
|
||||
mCancellationSignalArgumentCaptor.capture(),
|
||||
mAuthenticationCallbackArgumentCaptor.capture(), any(), anyInt());
|
||||
|
||||
mFingerprintAuthenticateSidecar.startAuthentication(1);
|
||||
|
||||
assertThat(mAuthenticationCallbackArgumentCaptor.getValue()).isNotNull();
|
||||
assertThat(mCancellationSignalArgumentCaptor.getValue()).isNotNull();
|
||||
|
||||
mAuthenticationCallbackArgumentCaptor.getValue()
|
||||
.onAuthenticationSucceeded(new FingerprintManager.AuthenticationResult(null,
|
||||
new Fingerprint("finger 1", 1, 1), 0 /* userId */, false));
|
||||
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
verify(mVibrator).vibrate(FingerprintSettings.SUCCESS_VIBRATION_EFFECT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotIndexable_whenDisabled() {
|
||||
doReturn(mPackageManager).when(mContext).getPackageManager();
|
||||
|
||||
@@ -1,293 +0,0 @@
|
||||
/*
|
||||
* 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.fuelgauge.batteryusage;
|
||||
|
||||
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.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.provider.Settings;
|
||||
import android.util.Pair;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.settings.DisplaySettings;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.testutils.BatteryTestUtils;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.TimeZone;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public final class BatteryTipsCardPreferenceTest {
|
||||
|
||||
private Context mContext;
|
||||
private FakeFeatureFactory mFeatureFactory;
|
||||
private BatteryTipsCardPreference mBatteryTipsCardPreference;
|
||||
private PowerUsageAdvanced mPowerUsageAdvanced;
|
||||
private BatteryTipsController mBatteryTipsController;
|
||||
private BatteryChartPreferenceController mBatteryChartPreferenceController;
|
||||
|
||||
@Mock private View mFakeView;
|
||||
@Mock private BatteryUsageBreakdownController mBatteryUsageBreakdownController;
|
||||
@Mock private BatteryDiffEntry mFakeEntry;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
TimeZone.setDefault(TimeZone.getTimeZone("GMT+8"));
|
||||
mContext = spy(RuntimeEnvironment.application);
|
||||
mFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||
mBatteryTipsCardPreference = new BatteryTipsCardPreference(mContext, /* attrs= */ null);
|
||||
mBatteryTipsController = new BatteryTipsController(mContext);
|
||||
mBatteryChartPreferenceController =
|
||||
spy(new BatteryChartPreferenceController(mContext, null, null));
|
||||
mBatteryChartPreferenceController.mPrefContext = mContext;
|
||||
mBatteryTipsController.mCardPreference = mBatteryTipsCardPreference;
|
||||
|
||||
mPowerUsageAdvanced = spy(new PowerUsageAdvanced());
|
||||
doReturn(mContext).when(mPowerUsageAdvanced).getContext();
|
||||
mPowerUsageAdvanced.mBatteryTipsController = mBatteryTipsController;
|
||||
mPowerUsageAdvanced.mBatteryChartPreferenceController = mBatteryChartPreferenceController;
|
||||
mPowerUsageAdvanced.mBatteryUsageBreakdownController = mBatteryUsageBreakdownController;
|
||||
mPowerUsageAdvanced.mBatteryLevelData =
|
||||
Optional.of(
|
||||
new BatteryLevelData(
|
||||
Map.of(
|
||||
1694354400000L, 1, // 2023-09-10 22:00:00
|
||||
1694361600000L, 2, // 2023-09-11 00:00:00
|
||||
1694368800000L, 3))); // 2023-09-11 02:00:00
|
||||
doReturn("TestEntriesKey").when(mFakeEntry).getKey();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructor_returnExpectedResult() {
|
||||
assertThat(mBatteryTipsCardPreference.getLayoutResource())
|
||||
.isEqualTo(R.layout.battery_tips_card);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onClick_mainBtnOfSettingsAnomalyLaunchPage_getAdaptiveBrightnessLauncher() {
|
||||
final ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
|
||||
PowerAnomalyEvent adaptiveBrightnessAnomaly =
|
||||
BatteryTestUtils.createAdaptiveBrightnessAnomalyEvent(/* changeSettings= */ false);
|
||||
when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true);
|
||||
when(mFakeView.getId()).thenReturn(R.id.main_button);
|
||||
doNothing().when(mContext).startActivity(captor.capture());
|
||||
|
||||
mPowerUsageAdvanced.onDisplayAnomalyEventUpdated(
|
||||
adaptiveBrightnessAnomaly, adaptiveBrightnessAnomaly);
|
||||
mBatteryTipsCardPreference.onClick(mFakeView);
|
||||
|
||||
assertThat(mBatteryTipsCardPreference.isVisible()).isFalse();
|
||||
verify(mContext).startActivity(any(Intent.class));
|
||||
final Intent intent = captor.getValue();
|
||||
assertThat(intent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
|
||||
.isEqualTo(DisplaySettings.class.getName());
|
||||
assertThat(intent.getIntExtra(MetricsFeatureProvider.EXTRA_SOURCE_METRICS_CATEGORY, -1))
|
||||
.isEqualTo(SettingsEnums.DISPLAY);
|
||||
verify(mFeatureFactory.metricsFeatureProvider)
|
||||
.action(
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
BatteryTipsController.ANOMALY_KEY,
|
||||
PowerAnomalyKey.KEY_BRIGHTNESS.getNumber());
|
||||
verify(mFeatureFactory.metricsFeatureProvider)
|
||||
.action(
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
SettingsEnums.ACTION_BATTERY_TIPS_CARD_ACCEPT,
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
BatteryTipsController.ANOMALY_KEY,
|
||||
PowerAnomalyKey.KEY_BRIGHTNESS.getNumber());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onClick_mainBtnOfSettingsAnomalyChangeSettings_settingsChanged()
|
||||
throws Settings.SettingNotFoundException {
|
||||
Settings.System.putInt(
|
||||
mContext.getContentResolver(),
|
||||
Settings.System.SCREEN_BRIGHTNESS_MODE,
|
||||
Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
|
||||
final ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
|
||||
PowerAnomalyEvent adaptiveBrightnessAnomaly =
|
||||
BatteryTestUtils.createAdaptiveBrightnessAnomalyEvent(/* changeSettings= */ true);
|
||||
when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true);
|
||||
when(mFakeView.getId()).thenReturn(R.id.main_button);
|
||||
doNothing().when(mContext).startActivity(captor.capture());
|
||||
|
||||
mPowerUsageAdvanced.onDisplayAnomalyEventUpdated(
|
||||
adaptiveBrightnessAnomaly, adaptiveBrightnessAnomaly);
|
||||
mBatteryTipsCardPreference.onClick(mFakeView);
|
||||
|
||||
assertThat(mBatteryTipsCardPreference.isVisible()).isFalse();
|
||||
assertThat(
|
||||
Settings.System.getInt(
|
||||
mContext.getContentResolver(),
|
||||
Settings.System.SCREEN_BRIGHTNESS_MODE))
|
||||
.isEqualTo(Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
|
||||
verify(mContext, never()).startActivity(any(Intent.class));
|
||||
verify(mFeatureFactory.metricsFeatureProvider)
|
||||
.action(
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
BatteryTipsController.ANOMALY_KEY,
|
||||
PowerAnomalyKey.KEY_BRIGHTNESS.getNumber());
|
||||
verify(mFeatureFactory.metricsFeatureProvider)
|
||||
.action(
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
SettingsEnums.ACTION_BATTERY_TIPS_CARD_ACCEPT,
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
BatteryTipsController.ANOMALY_KEY,
|
||||
PowerAnomalyKey.KEY_BRIGHTNESS.getNumber());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onClick_dismissBtnOfSettingsAnomaly_cardDismissAndLogged() {
|
||||
final PowerAnomalyEvent screenTimeoutAnomaly =
|
||||
BatteryTestUtils.createScreenTimeoutAnomalyEvent();
|
||||
DatabaseUtils.removeDismissedPowerAnomalyKeys(mContext);
|
||||
when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true);
|
||||
when(mFakeView.getId()).thenReturn(R.id.dismiss_button);
|
||||
|
||||
mPowerUsageAdvanced.onDisplayAnomalyEventUpdated(
|
||||
screenTimeoutAnomaly, screenTimeoutAnomaly);
|
||||
mBatteryTipsCardPreference.onClick(mFakeView);
|
||||
|
||||
assertThat(mBatteryTipsCardPreference.isVisible()).isFalse();
|
||||
assertThat(DatabaseUtils.getDismissedPowerAnomalyKeys(mContext)).hasSize(1);
|
||||
assertThat(DatabaseUtils.getDismissedPowerAnomalyKeys(mContext))
|
||||
.contains(PowerAnomalyKey.KEY_SCREEN_TIMEOUT.name());
|
||||
verify(mFeatureFactory.metricsFeatureProvider)
|
||||
.action(
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
BatteryTipsController.ANOMALY_KEY,
|
||||
PowerAnomalyKey.KEY_SCREEN_TIMEOUT.getNumber());
|
||||
verify(mFeatureFactory.metricsFeatureProvider)
|
||||
.action(
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
SettingsEnums.ACTION_BATTERY_TIPS_CARD_DISMISS,
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
BatteryTipsController.ANOMALY_KEY,
|
||||
PowerAnomalyKey.KEY_SCREEN_TIMEOUT.getNumber());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onClick_mainBtnOfAppsAnomaly_selectHighlightSlot() {
|
||||
final PowerAnomalyEvent appsAnomaly = BatteryTestUtils.createAppAnomalyEvent();
|
||||
when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true);
|
||||
when(mFakeView.getId()).thenReturn(R.id.main_button);
|
||||
doNothing().when(mBatteryChartPreferenceController).selectHighlightSlotIndex();
|
||||
when(mPowerUsageAdvanced.findRelatedBatteryDiffEntry(any())).thenReturn(mFakeEntry);
|
||||
|
||||
mPowerUsageAdvanced.onDisplayAnomalyEventUpdated(appsAnomaly, appsAnomaly);
|
||||
assertHighlightSlotIndexPair(1, 0);
|
||||
mBatteryTipsCardPreference.onClick(mFakeView);
|
||||
|
||||
assertThat(mBatteryTipsCardPreference.isVisible()).isFalse();
|
||||
verify(mContext, never()).startActivity(any(Intent.class));
|
||||
verify(mBatteryChartPreferenceController).onHighlightSlotIndexUpdate(eq(1), eq(0));
|
||||
verify(mBatteryChartPreferenceController).selectHighlightSlotIndex();
|
||||
verify(mFeatureFactory.metricsFeatureProvider)
|
||||
.action(
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
BatteryTipsController.ANOMALY_KEY,
|
||||
PowerAnomalyKey.KEY_APP_TOTAL_HIGHER_THAN_USUAL.getNumber());
|
||||
verify(mFeatureFactory.metricsFeatureProvider)
|
||||
.action(
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
SettingsEnums.ACTION_BATTERY_TIPS_CARD_ACCEPT,
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
BatteryTipsController.ANOMALY_KEY,
|
||||
PowerAnomalyKey.KEY_APP_TOTAL_HIGHER_THAN_USUAL.getNumber());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onClick_dismissBtnOfAppsAnomaly_keepHighlightSlotIndex() {
|
||||
final PowerAnomalyEvent appsAnomaly = BatteryTestUtils.createAppAnomalyEvent();
|
||||
when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true);
|
||||
when(mFakeView.getId()).thenReturn(R.id.dismiss_button);
|
||||
when(mPowerUsageAdvanced.findRelatedBatteryDiffEntry(any())).thenReturn(mFakeEntry);
|
||||
|
||||
mPowerUsageAdvanced.onDisplayAnomalyEventUpdated(appsAnomaly, appsAnomaly);
|
||||
assertHighlightSlotIndexPair(1, 0);
|
||||
mBatteryTipsCardPreference.onClick(mFakeView);
|
||||
|
||||
assertThat(mBatteryTipsCardPreference.isVisible()).isFalse();
|
||||
verify(mContext, never()).startActivity(any(Intent.class));
|
||||
verify(mBatteryChartPreferenceController).onHighlightSlotIndexUpdate(eq(1), eq(0));
|
||||
verify(mBatteryChartPreferenceController, never()).selectHighlightSlotIndex();
|
||||
verify(mFeatureFactory.metricsFeatureProvider)
|
||||
.action(
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
BatteryTipsController.ANOMALY_KEY,
|
||||
PowerAnomalyKey.KEY_APP_TOTAL_HIGHER_THAN_USUAL.getNumber());
|
||||
verify(mFeatureFactory.metricsFeatureProvider)
|
||||
.action(
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
SettingsEnums.ACTION_BATTERY_TIPS_CARD_DISMISS,
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
BatteryTipsController.ANOMALY_KEY,
|
||||
PowerAnomalyKey.KEY_APP_TOTAL_HIGHER_THAN_USUAL.getNumber());
|
||||
}
|
||||
|
||||
private void assertHighlightSlotIndexPair(
|
||||
int dailyHighlightSlotIndex, int hourlyHighlightSlotIndex) {
|
||||
assertThat(mPowerUsageAdvanced.mBatteryLevelData.isPresent()).isTrue();
|
||||
assertThat(mPowerUsageAdvanced.mHighlightEventWrapper.isPresent()).isTrue();
|
||||
Pair<Integer, Integer> slotIndexPair =
|
||||
mPowerUsageAdvanced
|
||||
.mHighlightEventWrapper
|
||||
.get()
|
||||
.getHighlightSlotPair(mPowerUsageAdvanced.mBatteryLevelData.get());
|
||||
assertThat(slotIndexPair)
|
||||
.isEqualTo(Pair.create(dailyHighlightSlotIndex, hourlyHighlightSlotIndex));
|
||||
assertThat(mPowerUsageAdvanced.mBatteryChartPreferenceController.mDailyHighlightSlotIndex)
|
||||
.isEqualTo(dailyHighlightSlotIndex);
|
||||
assertThat(mPowerUsageAdvanced.mBatteryChartPreferenceController.mHourlyHighlightSlotIndex)
|
||||
.isEqualTo(hourlyHighlightSlotIndex);
|
||||
}
|
||||
}
|
||||
@@ -16,8 +16,13 @@
|
||||
|
||||
package com.android.settings.fuelgauge.batteryusage;
|
||||
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@@ -29,11 +34,11 @@ import android.os.LocaleList;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.testutils.BatteryTestUtils;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settings.widget.TipCardPreference;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
@@ -47,134 +52,156 @@ public final class BatteryTipsControllerTest {
|
||||
private Context mContext;
|
||||
private FakeFeatureFactory mFeatureFactory;
|
||||
private BatteryTipsController mBatteryTipsController;
|
||||
|
||||
@Mock private BatteryTipsCardPreference mBatteryTipsCardPreference;
|
||||
private TipCardPreference mCardPreference;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
Locale.setDefault(new Locale("en_US"));
|
||||
org.robolectric.shadows.ShadowSettings.set24HourTimeFormat(false);
|
||||
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
|
||||
|
||||
mContext = spy(RuntimeEnvironment.application);
|
||||
final Resources resources = spy(mContext.getResources());
|
||||
resources.getConfiguration().setLocales(new LocaleList(new Locale("en_US")));
|
||||
doReturn(resources).when(mContext).getResources();
|
||||
mFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||
mBatteryTipsController = new BatteryTipsController(mContext);
|
||||
mBatteryTipsController.mCardPreference = mBatteryTipsCardPreference;
|
||||
mBatteryTipsController = spy(new BatteryTipsController(mContext));
|
||||
mCardPreference = new TipCardPreference(mContext);
|
||||
mBatteryTipsController.mCardPreference = mCardPreference;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleBatteryTipsCardUpdated_null_hidePreference() {
|
||||
mBatteryTipsController.handleBatteryTipsCardUpdated(/* powerAnomalyEvents= */ null, false);
|
||||
|
||||
verify(mBatteryTipsCardPreference).setVisible(false);
|
||||
assertThat(mCardPreference.isVisible()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleBatteryTipsCardUpdated_adaptiveBrightnessAnomaly_showAnomaly() {
|
||||
PowerAnomalyEvent event = BatteryTestUtils.createAdaptiveBrightnessAnomalyEvent();
|
||||
AnomalyEventWrapper anomalyEventWrapper =
|
||||
spy(
|
||||
new AnomalyEventWrapper(
|
||||
mContext,
|
||||
BatteryTestUtils.createAdaptiveBrightnessAnomalyEvent(true)));
|
||||
when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true);
|
||||
|
||||
mBatteryTipsController.handleBatteryTipsCardUpdated(
|
||||
new AnomalyEventWrapper(mContext, event), false);
|
||||
mBatteryTipsController.handleBatteryTipsCardUpdated(anomalyEventWrapper, false);
|
||||
|
||||
// Check pre-defined string
|
||||
verify(mBatteryTipsCardPreference)
|
||||
.setTitle("Turn on adaptive brightness to extend battery life");
|
||||
verify(mBatteryTipsCardPreference).setIconResourceId(R.drawable.ic_battery_tips_lightbulb);
|
||||
verify(mBatteryTipsCardPreference).setButtonColorResourceId(R.color.color_accent_selector);
|
||||
verify(mBatteryTipsCardPreference).setMainButtonLabel("View Settings");
|
||||
verify(mBatteryTipsCardPreference).setDismissButtonLabel("Got it");
|
||||
// Check proto info
|
||||
verify(mBatteryTipsCardPreference).setVisible(true);
|
||||
verify(mFeatureFactory.metricsFeatureProvider)
|
||||
.action(
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
BatteryTipsController.ANOMALY_KEY,
|
||||
PowerAnomalyKey.KEY_BRIGHTNESS.getNumber());
|
||||
assertThat(mCardPreference.getTitle())
|
||||
.isEqualTo("Turn on adaptive brightness to extend battery life");
|
||||
assertThat(mCardPreference.getPrimaryButtonText()).isEqualTo("Got it");
|
||||
assertThat(mCardPreference.getSecondaryButtonText()).isEqualTo("View Settings");
|
||||
assertThat(mCardPreference.getIconResId()).isEqualTo(R.drawable.ic_battery_tips_lightbulb);
|
||||
assertThat(mCardPreference.getTintColorResId()).isEqualTo(R.color.color_accent_selector);
|
||||
assertThat(mCardPreference.getPrimaryButtonVisibility()).isTrue();
|
||||
assertThat(mCardPreference.getSecondaryButtonVisibility()).isTrue();
|
||||
assertCardButtonActionAndMetrics(anomalyEventWrapper);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleBatteryTipsCardUpdated_screenTimeoutAnomaly_showAnomaly() {
|
||||
PowerAnomalyEvent event = BatteryTestUtils.createScreenTimeoutAnomalyEvent();
|
||||
AnomalyEventWrapper anomalyEventWrapper =
|
||||
spy(
|
||||
new AnomalyEventWrapper(
|
||||
mContext, BatteryTestUtils.createScreenTimeoutAnomalyEvent(true)));
|
||||
when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true);
|
||||
|
||||
mBatteryTipsController.handleBatteryTipsCardUpdated(
|
||||
new AnomalyEventWrapper(mContext, event), false);
|
||||
mBatteryTipsController.handleBatteryTipsCardUpdated(anomalyEventWrapper, false);
|
||||
|
||||
verify(mBatteryTipsCardPreference).setTitle("Reduce screen timeout to extend battery life");
|
||||
verify(mBatteryTipsCardPreference).setIconResourceId(R.drawable.ic_battery_tips_lightbulb);
|
||||
verify(mBatteryTipsCardPreference).setButtonColorResourceId(R.color.color_accent_selector);
|
||||
verify(mBatteryTipsCardPreference).setMainButtonLabel("View Settings");
|
||||
verify(mBatteryTipsCardPreference).setDismissButtonLabel("Got it");
|
||||
verify(mBatteryTipsCardPreference).setVisible(true);
|
||||
verify(mFeatureFactory.metricsFeatureProvider)
|
||||
.action(
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
BatteryTipsController.ANOMALY_KEY,
|
||||
PowerAnomalyKey.KEY_SCREEN_TIMEOUT.getNumber());
|
||||
assertThat(mCardPreference.getTitle())
|
||||
.isEqualTo("Reduce screen timeout to extend battery life");
|
||||
assertThat(mCardPreference.getPrimaryButtonText()).isEqualTo("Got it");
|
||||
assertThat(mCardPreference.getSecondaryButtonText()).isEqualTo("View Settings");
|
||||
assertThat(mCardPreference.getIconResId()).isEqualTo(R.drawable.ic_battery_tips_lightbulb);
|
||||
assertThat(mCardPreference.getTintColorResId()).isEqualTo(R.color.color_accent_selector);
|
||||
assertThat(mCardPreference.getPrimaryButtonVisibility()).isTrue();
|
||||
assertThat(mCardPreference.getSecondaryButtonVisibility()).isTrue();
|
||||
assertCardButtonActionAndMetrics(anomalyEventWrapper);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleBatteryTipsCardUpdated_screenTimeoutAnomalyHasTitle_showAnomaly() {
|
||||
PowerAnomalyEvent event = BatteryTestUtils.createScreenTimeoutAnomalyEvent();
|
||||
PowerAnomalyEvent anomalyEvent = BatteryTestUtils.createScreenTimeoutAnomalyEvent(true);
|
||||
String testTitle = "TestTitle";
|
||||
event =
|
||||
event.toBuilder()
|
||||
anomalyEvent =
|
||||
anomalyEvent.toBuilder()
|
||||
.setWarningBannerInfo(
|
||||
event.getWarningBannerInfo().toBuilder()
|
||||
anomalyEvent.getWarningBannerInfo().toBuilder()
|
||||
.setTitleString(testTitle)
|
||||
.build())
|
||||
.build();
|
||||
AnomalyEventWrapper anomalyEventWrapper =
|
||||
spy(new AnomalyEventWrapper(mContext, anomalyEvent));
|
||||
when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true);
|
||||
|
||||
mBatteryTipsController.handleBatteryTipsCardUpdated(
|
||||
new AnomalyEventWrapper(mContext, event), false);
|
||||
mBatteryTipsController.handleBatteryTipsCardUpdated(anomalyEventWrapper, false);
|
||||
|
||||
verify(mBatteryTipsCardPreference).setTitle(testTitle);
|
||||
verify(mBatteryTipsCardPreference).setIconResourceId(R.drawable.ic_battery_tips_lightbulb);
|
||||
verify(mBatteryTipsCardPreference).setButtonColorResourceId(R.color.color_accent_selector);
|
||||
verify(mBatteryTipsCardPreference).setMainButtonLabel("View Settings");
|
||||
verify(mBatteryTipsCardPreference).setDismissButtonLabel("Got it");
|
||||
verify(mBatteryTipsCardPreference).setVisible(true);
|
||||
verify(mFeatureFactory.metricsFeatureProvider)
|
||||
.action(
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
BatteryTipsController.ANOMALY_KEY,
|
||||
PowerAnomalyKey.KEY_SCREEN_TIMEOUT.getNumber());
|
||||
assertThat(mCardPreference.getTitle()).isEqualTo(testTitle);
|
||||
assertThat(mCardPreference.getPrimaryButtonText()).isEqualTo("Got it");
|
||||
assertThat(mCardPreference.getSecondaryButtonText()).isEqualTo("View Settings");
|
||||
assertThat(mCardPreference.getIconResId()).isEqualTo(R.drawable.ic_battery_tips_lightbulb);
|
||||
assertThat(mCardPreference.getTintColorResId()).isEqualTo(R.color.color_accent_selector);
|
||||
assertThat(mCardPreference.getPrimaryButtonVisibility()).isTrue();
|
||||
assertThat(mCardPreference.getSecondaryButtonVisibility()).isTrue();
|
||||
assertCardButtonActionAndMetrics(anomalyEventWrapper);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleBatteryTipsCardUpdated_appAnomaly_showAnomaly() {
|
||||
PowerAnomalyEvent event = BatteryTestUtils.createAppAnomalyEvent();
|
||||
AnomalyEventWrapper anomalyEventWrapper =
|
||||
spy(new AnomalyEventWrapper(mContext, BatteryTestUtils.createAppAnomalyEvent()));
|
||||
when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true);
|
||||
|
||||
AnomalyEventWrapper eventWrapper = new AnomalyEventWrapper(mContext, event);
|
||||
eventWrapper.setRelatedBatteryDiffEntry(new BatteryDiffEntry(mContext, "", "Chrome", 0));
|
||||
mBatteryTipsController.handleBatteryTipsCardUpdated(eventWrapper, false);
|
||||
anomalyEventWrapper.setRelatedBatteryDiffEntry(
|
||||
new BatteryDiffEntry(mContext, "", "Chrome", 0));
|
||||
mBatteryTipsController.setOnAnomalyConfirmListener(
|
||||
() -> mBatteryTipsController.acceptTipsCard());
|
||||
mBatteryTipsController.handleBatteryTipsCardUpdated(anomalyEventWrapper, true);
|
||||
|
||||
verify(mBatteryTipsCardPreference).setTitle("Chrome used more battery than usual");
|
||||
verify(mBatteryTipsCardPreference)
|
||||
.setIconResourceId(R.drawable.ic_battery_tips_warning_icon);
|
||||
verify(mBatteryTipsCardPreference)
|
||||
.setButtonColorResourceId(R.color.color_battery_anomaly_app_warning_selector);
|
||||
verify(mBatteryTipsCardPreference).setMainButtonLabel("Check");
|
||||
verify(mBatteryTipsCardPreference).setDismissButtonLabel("Got it");
|
||||
verify(mBatteryTipsCardPreference).setVisible(true);
|
||||
assertThat(mCardPreference.getTitle()).isEqualTo("Chrome used more battery than usual");
|
||||
assertThat(mCardPreference.getPrimaryButtonText()).isEqualTo("Got it");
|
||||
assertThat(mCardPreference.getSecondaryButtonText()).isEqualTo("Check");
|
||||
assertThat(mCardPreference.getIconResId())
|
||||
.isEqualTo(R.drawable.ic_battery_tips_warning_icon);
|
||||
assertThat(mCardPreference.getTintColorResId())
|
||||
.isEqualTo(R.color.color_battery_anomaly_app_warning_selector);
|
||||
assertThat(mCardPreference.getPrimaryButtonVisibility()).isTrue();
|
||||
assertThat(mCardPreference.getSecondaryButtonVisibility()).isTrue();
|
||||
assertThat(mCardPreference.isVisible()).isTrue();
|
||||
assertCardButtonActionAndMetrics(anomalyEventWrapper);
|
||||
}
|
||||
|
||||
private void assertCardButtonActionAndMetrics(final AnomalyEventWrapper anomalyEventWrapper) {
|
||||
when(anomalyEventWrapper.updateSystemSettingsIfAvailable()).thenReturn(true);
|
||||
|
||||
final int powerAnomalyKeyNumber = anomalyEventWrapper.getAnomalyKeyNumber();
|
||||
assertCardMetrics(SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW, powerAnomalyKeyNumber);
|
||||
assertThat(mCardPreference.isVisible()).isTrue();
|
||||
|
||||
// Check accept button action
|
||||
mCardPreference.setVisible(true);
|
||||
mCardPreference.getSecondaryButtonAction().invoke();
|
||||
assertCardMetrics(SettingsEnums.ACTION_BATTERY_TIPS_CARD_ACCEPT, powerAnomalyKeyNumber);
|
||||
assertThat(mCardPreference.isVisible()).isFalse();
|
||||
final boolean isAppAnomalyCard = powerAnomalyKeyNumber > 1;
|
||||
verify(anomalyEventWrapper, isAppAnomalyCard ? never() : times(1))
|
||||
.updateSystemSettingsIfAvailable();
|
||||
|
||||
// Check reject button action
|
||||
mCardPreference.setVisible(true);
|
||||
mCardPreference.getPrimaryButtonAction().invoke();
|
||||
assertCardMetrics(SettingsEnums.ACTION_BATTERY_TIPS_CARD_DISMISS, powerAnomalyKeyNumber);
|
||||
assertThat(mCardPreference.isVisible()).isFalse();
|
||||
}
|
||||
|
||||
private void assertCardMetrics(final int action, final int powerAnomalyKeyNumber) {
|
||||
verify(mFeatureFactory.metricsFeatureProvider)
|
||||
.action(
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
|
||||
action,
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
BatteryTipsController.ANOMALY_KEY,
|
||||
PowerAnomalyKey.KEY_APP_TOTAL_HIGHER_THAN_USUAL.getNumber());
|
||||
powerAnomalyKeyNumber);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
@@ -131,7 +130,13 @@ public class SettingsSliceProviderTest {
|
||||
CustomSliceRegistry.LOCATION_SLICE_URI
|
||||
);
|
||||
|
||||
private static final List<Uri> SPECIAL_CASE_OEM_URIS = Arrays.asList(
|
||||
private static final List<Uri> SPECIAL_CASE_OEM_URIS = android.app.Flags.modesUi()
|
||||
? Arrays.asList(
|
||||
CustomSliceRegistry.FLASHLIGHT_SLICE_URI,
|
||||
CustomSliceRegistry.MOBILE_DATA_SLICE_URI,
|
||||
CustomSliceRegistry.WIFI_CALLING_URI
|
||||
) :
|
||||
Arrays.asList(
|
||||
CustomSliceRegistry.ZEN_MODE_SLICE_URI,
|
||||
CustomSliceRegistry.FLASHLIGHT_SLICE_URI,
|
||||
CustomSliceRegistry.MOBILE_DATA_SLICE_URI,
|
||||
|
||||
@@ -20,6 +20,8 @@ import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATIN
|
||||
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
|
||||
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@@ -46,20 +48,15 @@ public class AccessibilityTestUtils {
|
||||
|
||||
public static void setSoftwareShortcutMode(
|
||||
Context context, boolean gestureNavEnabled, boolean floatingButtonEnabled) {
|
||||
int mode = floatingButtonEnabled ? ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU : -1;
|
||||
int buttonMode = floatingButtonEnabled ? ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU : -1;
|
||||
int navMode = gestureNavEnabled ? NAV_BAR_MODE_GESTURAL : NAV_BAR_MODE_3BUTTON;
|
||||
|
||||
Settings.Secure.putInt(context.getContentResolver(),
|
||||
Settings.Secure.ACCESSIBILITY_BUTTON_MODE, mode);
|
||||
|
||||
if (gestureNavEnabled) {
|
||||
Settings.Secure.ACCESSIBILITY_BUTTON_MODE, buttonMode);
|
||||
SettingsShadowResources.overrideResource(
|
||||
com.android.internal.R.integer.config_navBarInteractionMode,
|
||||
NAV_BAR_MODE_GESTURAL);
|
||||
} else {
|
||||
SettingsShadowResources.overrideResource(
|
||||
com.android.internal.R.integer.config_navBarInteractionMode,
|
||||
NAV_BAR_MODE_3BUTTON);
|
||||
}
|
||||
com.android.internal.R.integer.config_navBarInteractionMode, navMode);
|
||||
assertThat(context.getResources().getInteger(
|
||||
com.android.internal.R.integer.config_navBarInteractionMode)).isEqualTo(navMode);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -264,18 +264,28 @@ public class BatteryTestUtils {
|
||||
|
||||
/** Create a power anomaly event proto of screen timeout. */
|
||||
public static PowerAnomalyEvent createScreenTimeoutAnomalyEvent() {
|
||||
return createScreenTimeoutAnomalyEvent(false);
|
||||
}
|
||||
|
||||
/** Create a power anomaly event proto of screen timeout. */
|
||||
public static PowerAnomalyEvent createScreenTimeoutAnomalyEvent(boolean changeSettings) {
|
||||
WarningBannerInfo.Builder warningBannerInfoBuilder =
|
||||
WarningBannerInfo.newBuilder()
|
||||
.setMainButtonDestination(ScreenTimeoutSettings.class.getName())
|
||||
.setMainButtonSourceMetricsCategory(SettingsEnums.SCREEN_TIMEOUT)
|
||||
.setMainButtonSourceHighlightKey("60000");
|
||||
if (changeSettings) {
|
||||
warningBannerInfoBuilder
|
||||
.setMainButtonConfigSettingsName(Settings.System.SCREEN_OFF_TIMEOUT)
|
||||
.setMainButtonConfigSettingsValue(60000);
|
||||
}
|
||||
return PowerAnomalyEvent.newBuilder()
|
||||
.setEventId("ScreenTimeoutAnomaly")
|
||||
.setType(PowerAnomalyType.TYPE_SETTINGS_BANNER)
|
||||
.setKey(PowerAnomalyKey.KEY_SCREEN_TIMEOUT)
|
||||
.setDismissRecordKey(PowerAnomalyKey.KEY_SCREEN_TIMEOUT.name())
|
||||
.setScore(1.1f)
|
||||
.setWarningBannerInfo(
|
||||
WarningBannerInfo.newBuilder()
|
||||
.setMainButtonDestination(ScreenTimeoutSettings.class.getName())
|
||||
.setMainButtonSourceMetricsCategory(SettingsEnums.SCREEN_TIMEOUT)
|
||||
.setMainButtonSourceHighlightKey("60000")
|
||||
.build())
|
||||
.setWarningBannerInfo(warningBannerInfoBuilder.build())
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user