Merge "Crop avatar to circle when syncing from Contacts." into tm-qpr-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 8334466..564d5c2 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -2976,6 +2976,7 @@
android:taskAffinity="com.android.settings.FallbackHome"
android:exported="true"
android:theme="@style/FallbackHome"
+ android:permission="android.permission.DEVICE_POWER"
android:configChanges="keyboardHidden">
<intent-filter android:priority="-1000">
<action android:name="android.intent.action.MAIN" />
diff --git a/res/drawable/volume_dialog_button_background_outline.xml b/res/drawable/volume_dialog_button_background_outline.xml
index 78f3fcf..efbaec6 100644
--- a/res/drawable/volume_dialog_button_background_outline.xml
+++ b/res/drawable/volume_dialog_button_background_outline.xml
@@ -14,18 +14,21 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
- android:shape="rectangle">
- <stroke
- android:color="?androidprv:attr/colorAccentPrimaryVariant"
- android:width="1dp"/>
- <corners android:radius="24dp"/>
- <padding
- android:left="16dp"
- android:right="16dp"
- android:top="8dp"
- android:bottom="8dp" />
- <solid android:color="@android:color/transparent" />
-</shape>
\ No newline at end of file
+ android:insetTop="6dp"
+ android:insetBottom="6dp">
+ <shape
+ android:shape="rectangle">
+ <stroke
+ android:color="?androidprv:attr/colorAccentPrimaryVariant"
+ android:width="1dp"/>
+ <corners android:radius="24dp"/>
+ <padding
+ android:left="16dp"
+ android:right="16dp"
+ android:top="8dp"
+ android:bottom="8dp" />
+ <solid android:color="@android:color/transparent" />
+ </shape>
+</inset>
\ No newline at end of file
diff --git a/res/drawable/volume_dialog_button_background_solid.xml b/res/drawable/volume_dialog_button_background_solid.xml
index 1fa8f20..697131d 100644
--- a/res/drawable/volume_dialog_button_background_solid.xml
+++ b/res/drawable/volume_dialog_button_background_solid.xml
@@ -15,17 +15,20 @@
limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
- android:shape="rectangle">
- <stroke
- android:color="@android:color/transparent"
- android:width="1dp"/>
- <corners android:radius="20dp"/>
- <padding
- android:left="16dp"
- android:right="16dp"
- android:top="8dp"
- android:bottom="8dp" />
- <solid android:color="?androidprv:attr/colorAccentPrimary" />
-</shape>
\ No newline at end of file
+ android:insetTop="6dp"
+ android:insetBottom="6dp">
+ <shape android:shape="rectangle">
+ <stroke
+ android:color="@android:color/transparent"
+ android:width="1dp"/>
+ <corners android:radius="20dp"/>
+ <padding
+ android:left="16dp"
+ android:right="16dp"
+ android:top="8dp"
+ android:bottom="8dp" />
+ <solid android:color="?androidprv:attr/colorAccentPrimary" />
+ </shape>
+</inset>
\ No newline at end of file
diff --git a/res/layout/panel_layout.xml b/res/layout/panel_layout.xml
index 2b9daeb..f154abc 100644
--- a/res/layout/panel_layout.xml
+++ b/res/layout/panel_layout.xml
@@ -117,7 +117,7 @@
android:id="@+id/see_more"
style="@style/PanelOptionRoundedOutlinedButton"
android:layout_width="wrap_content"
- android:layout_height="36dp"
+ android:layout_height="wrap_content"
android:minWidth="0dp"
android:text="@string/settings_button"/>
@@ -130,7 +130,7 @@
android:id="@+id/done"
style="@style/PanelOptionRoundedSolidButton"
android:layout_width="wrap_content"
- android:layout_height="36dp"
+ android:layout_height="wrap_content"
android:minWidth="0dp"
android:text="@string/done"/>
</LinearLayout>
diff --git a/res/layout/sfps_enroll_finish_base.xml b/res/layout/sfps_enroll_finish_base.xml
index 6e468c6..1773337 100644
--- a/res/layout/sfps_enroll_finish_base.xml
+++ b/res/layout/sfps_enroll_finish_base.xml
@@ -30,12 +30,14 @@
android:clipToPadding="false"
android:clipChildren="false">
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_weight="1"
- android:gravity="center"
- android:orientation="vertical">
+ <com.android.settings.biometrics.fingerprint.FingerprintRequireScreenOnToAuthToggle
+ style="@style/SudSwitchStyle"
+ android:id="@+id/require_screen_on_to_auth_toggle"
+ android:layout_gravity="start"
+ android:paddingLeft="0dp"
+ android:paddingStart="0dp"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
<com.google.android.setupdesign.view.FillContentLayout
android:layout_width="@dimen/sfps_enrollment_finished_icon_max_size"
@@ -54,17 +56,6 @@
android:importantForAccessibility="no"
android:src="@drawable/sfps_enroll_finish" />
</com.google.android.setupdesign.view.FillContentLayout>
-
- <!-- Added to align elements with fingerprint_enroll_enrolling_base -->
- <TextView
- style="@style/TextAppearance.ErrorText"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal|bottom"
- android:visibility="invisible" />
-
- </LinearLayout>
-
</LinearLayout>
</com.google.android.setupdesign.GlifLayout>
diff --git a/res/layout/sfps_require_screen_on_to_auth_toggle.xml b/res/layout/sfps_require_screen_on_to_auth_toggle.xml
new file mode 100644
index 0000000..02bb979
--- /dev/null
+++ b/res/layout/sfps_require_screen_on_to_auth_toggle.xml
@@ -0,0 +1,62 @@
+<!--
+ ~ Copyright (C) 2022 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.
+ -->
+
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="start"
+ style="?attr/fingerprint_layout_theme">
+
+ <!-- Title -->
+ <com.google.android.setupdesign.view.RichTextView
+ android:id="@+id/title"
+ android:paddingTop="8dp"
+ android:paddingBottom="4dp"
+ android:layout_alignParentStart="true"
+ android:textAlignment="viewStart"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/security_settings_require_screen_on_to_auth_title"
+ android:textColor="?android:attr/textColorPrimary"
+ android:textSize="@dimen/sud_description_text_size"
+ />
+
+ <!-- Subtitle -->
+ <TextView
+ android:id="@+id/subtitle"
+ android:paddingBottom="8dp"
+ android:layout_alignParentStart="true"
+ android:textAlignment="viewStart"
+ android:layout_toStartOf="@+id/toggle"
+ android:layout_below="@+id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/security_settings_require_screen_on_to_auth_description"
+ android:textColor="?android:attr/textColorSecondary"/>
+
+ <!-- Toggle -->
+ <Switch
+ android:layout_alignParentEnd="true"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/toggle"
+ android:layout_centerVertical="true"
+ android:checked="false"
+ style="@style/SudSwitchStyle"/>
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 03a103e..96ffb8d 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1012,6 +1012,8 @@
<!-- Note: Update FingerprintEnrollParentalConsent.CONSENT_STRING_RESOURCES when any _consent_ strings are added or removed. -->
<!-- Title shown for menu item that launches fingerprint settings or enrollment [CHAR LIMIT=22] -->
<string name="security_settings_fingerprint_preference_title">Fingerprint</string>
+ <!-- Title for a category shown for the fingerprint settings page, followed by items that the user can toggle on/off to require/disable. [CHAR LIMIT=50] -->
+ <string name="security_settings_fingerprint_settings_preferences_category">When using Fingerprint Unlock</string>
<!-- Fingerprint enrollment and settings --><skip />
<!-- Title shown for work menu item that launches fingerprint settings or enrollment [CHAR LIMIT=22] -->
<string name="security_settings_work_fingerprint_preference_title">Fingerprint for work</string>
@@ -1293,6 +1295,12 @@
<string name="security_settings_fingerprint_enroll_finish_v2_message" product="device">Now you can use your fingerprint to unlock your device or verify it\u2019s you, like when you sign in to apps</string>
<!-- Message shown in fingerprint enrollment dialog once enrollment is completed (default) [CHAR LIMIT=NONE] -->
<string name="security_settings_fingerprint_enroll_finish_v2_message" product="default">Now you can use your fingerprint to unlock your phone or verify it\u2019s you, like when you sign in to apps</string>
+ <!-- Title for require screen on to auth toggle shown in fingerprint enrollment dialog once enrollment is completed. [CHAR LIMIT=NONE] -->
+ <string name="security_settings_require_screen_on_to_auth_title">Unlock only when screen is on</string>
+ <!-- Description for require screen on to auth toggle shown in fingerprint enrollment dialog once enrollment is completed. [CHAR LIMIT=NONE] -->
+ <string name="security_settings_require_screen_on_to_auth_description">The screen must be on before you can unlock with your fingerprint. This makes accidental unlocking less likely.</string>
+ <!-- Description for require screen on to auth toggle shown in fingerprint enrollment dialog once enrollment is completed. [CHAR LIMIT=NONE] -->
+ <string name="security_settings_require_screen_on_to_auth_keywords">Screen, Unlock</string>
<!-- Button text to skip enrollment of fingerprint [CHAR LIMIT=40] -->
<string name="security_settings_fingerprint_enroll_enrolling_skip">Do it later</string>
<!-- Accessibility message for fingerprint enrollment asking the user to place the tip of their finger on the fingerprint sensor [CHAR LIMIT=NONE] -->
diff --git a/res/xml/security_settings_fingerprint.xml b/res/xml/security_settings_fingerprint.xml
index 804ef88..a4ce545 100644
--- a/res/xml/security_settings_fingerprint.xml
+++ b/res/xml/security_settings_fingerprint.xml
@@ -16,5 +16,20 @@
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
- android:title="@string/security_settings_fingerprint_preference_title"/>
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
+ android:title="@string/security_settings_fingerprint_preference_title">
+ <PreferenceCategory
+ android:key="security_settings_fingerprint_unlock_category"
+ android:title="@string/security_settings_fingerprint_settings_preferences_category"
+ settings:controller="com.android.settings.biometrics.fingerprint.FingerprintUnlockCategoryPreferenceController">
+
+ <com.android.settingslib.RestrictedSwitchPreference
+ android:key="security_settings_require_screen_on_to_auth"
+ android:title="@string/security_settings_require_screen_on_to_auth_title"
+ android:summary="@string/security_settings_require_screen_on_to_auth_description"
+ settings:keywords="@string/security_settings_require_screen_on_to_auth_keywords"
+ settings:controller="com.android.settings.biometrics.fingerprint.FingerprintSettingsRequireScreenOnToAuthPreferenceController" />
+ </PreferenceCategory>
+
+</PreferenceScreen>
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFinish.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFinish.java
index 0c7ef98..4506310 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFinish.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFinish.java
@@ -25,6 +25,7 @@
import android.os.Bundle;
import android.util.Log;
import android.view.View;
+import android.widget.CompoundButton;
import androidx.annotation.VisibleForTesting;
@@ -44,16 +45,24 @@
public class FingerprintEnrollFinish extends BiometricEnrollBase {
private static final String TAG = "FingerprintEnrollFinish";
+ private static final String KEY_REQUIRE_SCREEN_ON_TO_AUTH = "require_screen_on_to_auth_toggle";
private static final String ACTION_FINGERPRINT_SETTINGS =
"android.settings.FINGERPRINT_SETTINGS";
@VisibleForTesting
static final String FINGERPRINT_SUGGESTION_ACTIVITY =
"com.android.settings.SetupFingerprintSuggestionActivity";
+
private FingerprintManager mFingerprintManager;
+
+ private FingerprintSettingsRequireScreenOnToAuthPreferenceController
+ mRequireScreenOnToAuthPreferenceController;
+ private FingerprintRequireScreenOnToAuthToggle mRequireScreenOnToAuthToggle;
private boolean mCanAssumeSfps;
private boolean mIsAddAnotherOrFinish;
+ private CompoundButton.OnCheckedChangeListener mRequireScreenOnToAuthToggleListener;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -63,6 +72,11 @@
mCanAssumeSfps = props != null && props.size() == 1 && props.get(0).isAnySidefpsType();
if (mCanAssumeSfps) {
setContentView(R.layout.sfps_enroll_finish);
+ mRequireScreenOnToAuthPreferenceController =
+ new FingerprintSettingsRequireScreenOnToAuthPreferenceController(
+ getApplicationContext(),
+ KEY_REQUIRE_SCREEN_ON_TO_AUTH
+ );
} else {
setContentView(R.layout.fingerprint_enroll_finish);
}
@@ -90,6 +104,20 @@
.setTheme(R.style.SudGlifButton_Primary)
.build()
);
+
+ if (mCanAssumeSfps) {
+ mRequireScreenOnToAuthToggleListener =
+ (buttonView, isChecked) -> {
+ mRequireScreenOnToAuthPreferenceController.setChecked(isChecked);
+ };
+ mRequireScreenOnToAuthToggle = findViewById(R.id.require_screen_on_to_auth_toggle);
+ mRequireScreenOnToAuthToggle.setChecked(
+ mRequireScreenOnToAuthPreferenceController.isChecked());
+ mRequireScreenOnToAuthToggle.setListener(mRequireScreenOnToAuthToggleListener);
+ mRequireScreenOnToAuthToggle.setOnClickListener(v -> {
+ mRequireScreenOnToAuthToggle.getSwitch().toggle();
+ });
+ }
}
@Override
@@ -103,6 +131,12 @@
@Override
protected void onResume() {
super.onResume();
+ if (mCanAssumeSfps) {
+ mRequireScreenOnToAuthToggleListener.onCheckedChanged(
+ mRequireScreenOnToAuthToggle.getSwitch(),
+ mRequireScreenOnToAuthToggle.isChecked()
+ );
+ }
FooterButton addButton = mFooterBarMixin.getSecondaryButton();
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintRequireScreenOnToAuthToggle.java b/src/com/android/settings/biometrics/fingerprint/FingerprintRequireScreenOnToAuthToggle.java
new file mode 100644
index 0000000..f88c9aa
--- /dev/null
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintRequireScreenOnToAuthToggle.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2022 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.biometrics.fingerprint;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.widget.CompoundButton;
+import android.widget.LinearLayout;
+import android.widget.Switch;
+
+import com.android.settings.R;
+
+/**
+ * A layout that contains a start-justified title, and an end-justified switch.
+ */
+public class FingerprintRequireScreenOnToAuthToggle extends LinearLayout {
+ private Switch mSwitch;
+
+ public FingerprintRequireScreenOnToAuthToggle(Context context) {
+ this(context, null /* attrs */);
+ }
+
+ public FingerprintRequireScreenOnToAuthToggle(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public FingerprintRequireScreenOnToAuthToggle(
+ Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+
+ LayoutInflater.from(context).inflate(R.layout.sfps_require_screen_on_to_auth_toggle,
+ this, true /* attachToRoot */);
+
+ mSwitch = findViewById(R.id.toggle);
+ mSwitch.setClickable(true);
+ mSwitch.setFocusable(false);
+ }
+
+ public boolean isChecked() {
+ return mSwitch.isChecked();
+ }
+
+ /**
+ *
+ * @param checked
+ */
+ public void setChecked(boolean checked) {
+ mSwitch.setChecked(checked);
+ }
+
+ /**
+ *
+ * @param listener
+ */
+ public void setListener(CompoundButton.OnCheckedChangeListener listener) {
+ mSwitch.setOnCheckedChangeListener(listener);
+ }
+
+ public Switch getSwitch() {
+ return mSwitch;
+ }
+}
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java b/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
index c031fe6..2cbef99 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
@@ -56,21 +56,24 @@
import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceScreen;
import androidx.preference.PreferenceViewHolder;
+import androidx.preference.SwitchPreference;
import com.android.settings.R;
-import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.SubSettings;
import com.android.settings.Utils;
import com.android.settings.biometrics.BiometricEnrollBase;
import com.android.settings.biometrics.BiometricUtils;
import com.android.settings.core.SettingsBaseActivity;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.password.ChooseLockGeneric;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settingslib.HelpUtils;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import com.android.settingslib.RestrictedLockUtilsInternal;
+import com.android.settingslib.RestrictedSwitchPreference;
+import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.transition.SettingsTransitionHelper;
import com.android.settingslib.widget.FooterPreference;
import com.android.settingslib.widget.TwoTargetPreference;
@@ -115,7 +118,26 @@
setTitle(msg);
}
- public static class FingerprintSettingsFragment extends SettingsPreferenceFragment
+ /**
+ * @param context
+ * @return true if the Fingerprint hardware is detected.
+ */
+ public static boolean isFingerprintHardwareDetected(Context context) {
+ FingerprintManager manager = Utils.getFingerprintManagerOrNull(context);
+ boolean isHardwareDetected = false;
+ if (manager == null) {
+ Log.d(TAG, "FingerprintManager is null");
+ } else {
+ isHardwareDetected = manager.isHardwareDetected();
+ Log.d(TAG, "FingerprintManager is not null. Hardware detected: " + isHardwareDetected);
+ }
+ return manager != null && isHardwareDetected;
+ }
+
+ /**
+ *
+ */
+ public static class FingerprintSettingsFragment extends DashboardFragment
implements OnPreferenceChangeListener, FingerprintPreference.OnDeleteClickListener {
private static class FooterColumn {
@@ -134,6 +156,8 @@
private static final String KEY_LAUNCHED_CONFIRM = "launched_confirm";
private static final String KEY_HAS_FIRST_ENROLLED = "has_first_enrolled";
private static final String KEY_IS_ENROLLING = "is_enrolled";
+ private static final String KEY_REQUIRE_SCREEN_ON_TO_AUTH =
+ "security_settings_require_screen_on_to_auth";
private static final int MSG_REFRESH_FINGERPRINT_TEMPLATES = 1000;
private static final int MSG_FINGER_AUTH_SUCCESS = 1001;
@@ -149,6 +173,11 @@
protected static final boolean DEBUG = false;
+ private List<AbstractPreferenceController> mControllers;
+ private FingerprintSettingsRequireScreenOnToAuthPreferenceController
+ mRequireScreenOnToAuthPreferenceController;
+ private RestrictedSwitchPreference mRequireScreenOnToAuthPreference;
+
private FingerprintManager mFingerprintManager;
private FingerprintUpdater mFingerprintUpdater;
private List<FingerprintSensorPropertiesInternal> mSensorProperties;
@@ -214,6 +243,9 @@
}
private void updateDialog() {
+ if (isSfps()) {
+ setRequireScreenOnToAuthVisibility();
+ }
RenameDialog renameDialog = (RenameDialog) getFragmentManager().
findFragmentByTag(RenameDialog.class.getName());
if (renameDialog != null) {
@@ -425,6 +457,15 @@
return false;
}
+ private boolean isSfps() {
+ for (FingerprintSensorPropertiesInternal prop : mSensorProperties) {
+ if (prop.isAnySidefpsType()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
protected void removeFingerprintPreference(int fingerprintId) {
String name = genKey(fingerprintId);
Preference prefToRemove = findPreference(name);
@@ -448,13 +489,40 @@
if (root != null) {
root.removeAll();
}
- addPreferencesFromResource(R.xml.security_settings_fingerprint);
root = getPreferenceScreen();
addFingerprintItemPreferences(root);
+ addPreferencesFromResource(getPreferenceScreenResId());
+ mRequireScreenOnToAuthPreference = findPreference(KEY_REQUIRE_SCREEN_ON_TO_AUTH);
+ for (AbstractPreferenceController controller : mControllers) {
+ ((FingerprintSettingsPreferenceController) controller).setUserId(mUserId);
+ }
+ mRequireScreenOnToAuthPreference.setChecked(
+ mRequireScreenOnToAuthPreferenceController.isChecked());
+ mRequireScreenOnToAuthPreference.setOnPreferenceChangeListener(
+ (preference, newValue) -> {
+ boolean isChecked = ((SwitchPreference) preference).isChecked();
+ mRequireScreenOnToAuthPreferenceController.setChecked(!isChecked);
+ return true;
+ });
+ mRequireScreenOnToAuthPreference.setVisible(false);
+ if (isSfps()) {
+ setRequireScreenOnToAuthVisibility();
+ }
setPreferenceScreen(root);
return root;
}
+ private void setRequireScreenOnToAuthVisibility() {
+ int fingerprintsEnrolled = mFingerprintManager.getEnrolledFingerprints(mUserId).size();
+ final boolean removalInProgress = mRemovalSidecar.inProgress();
+ // Removing last remaining fingerprint
+ if (fingerprintsEnrolled == 0 && removalInProgress) {
+ mRequireScreenOnToAuthPreference.setVisible(false);
+ } else {
+ mRequireScreenOnToAuthPreference.setVisible(true);
+ }
+ }
+
private void addFingerprintItemPreferences(PreferenceGroup root) {
root.removeAll();
final List<Fingerprint> items = mFingerprintManager.getEnrolledFingerprints(mUserId);
@@ -477,6 +545,7 @@
root.addPreference(pref);
pref.setOnPreferenceChangeListener(this);
}
+
Preference addPreference = new Preference(root.getContext());
addPreference.setKey(KEY_FINGERPRINT_ADD);
addPreference.setTitle(R.string.fingerprint_add_title);
@@ -569,6 +638,16 @@
}
@Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.security_settings_fingerprint;
+ }
+
+ @Override
+ protected String getLogTag() {
+ return TAG;
+ }
+
+ @Override
public void onSaveInstanceState(final Bundle outState) {
outState.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN,
mToken);
@@ -663,6 +742,27 @@
}
@Override
+ protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
+ if (!isFingerprintHardwareDetected(context)) {
+ return null;
+ }
+
+ mControllers = buildPreferenceControllers(context);
+ return mControllers;
+ }
+
+ private List<AbstractPreferenceController> buildPreferenceControllers(Context context) {
+ final List<AbstractPreferenceController> controllers = new ArrayList<>();
+ mRequireScreenOnToAuthPreferenceController =
+ new FingerprintSettingsRequireScreenOnToAuthPreferenceController(
+ context,
+ KEY_REQUIRE_SCREEN_ON_TO_AUTH
+ );
+ controllers.add(mRequireScreenOnToAuthPreferenceController);
+ return controllers;
+ }
+
+ @Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CONFIRM_REQUEST || requestCode == CHOOSE_LOCK_GENERIC_REQUEST) {
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsPreferenceController.java b/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsPreferenceController.java
new file mode 100644
index 0000000..2ca5da8
--- /dev/null
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsPreferenceController.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2022 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.biometrics.fingerprint;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+
+import com.android.settings.core.TogglePreferenceController;
+import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+import com.android.settingslib.RestrictedLockUtilsInternal;
+
+/**
+ * Abstract base class for all fingerprint settings toggles.
+ */
+public abstract class FingerprintSettingsPreferenceController extends TogglePreferenceController {
+
+ private int mUserId;
+
+ public FingerprintSettingsPreferenceController(Context context, String preferenceKey) {
+ super(context, preferenceKey);
+ }
+
+ public void setUserId(int userId) {
+ mUserId = userId;
+ }
+
+ protected int getUserId() {
+ return mUserId;
+ }
+
+ protected EnforcedAdmin getRestrictingAdmin() {
+ return RestrictedLockUtilsInternal.checkIfKeyguardFeaturesDisabled(
+ mContext, DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT, mUserId);
+ }
+
+ @Override
+ public final boolean isSliceable() {
+ return false;
+ }
+
+ @Override
+ public int getSliceHighlightMenuRes() {
+ // not needed since it's not sliceable
+ return NO_RES;
+ }
+}
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsRequireScreenOnToAuthPreferenceController.java b/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsRequireScreenOnToAuthPreferenceController.java
new file mode 100644
index 0000000..5b183c1
--- /dev/null
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsRequireScreenOnToAuthPreferenceController.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2022 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.biometrics.fingerprint;
+
+import android.content.Context;
+import android.hardware.fingerprint.FingerprintManager;
+import android.os.UserHandle;
+import android.provider.Settings;
+
+import androidx.preference.Preference;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settings.Utils;
+
+/**
+ * Preference controller that controls whether a SFPS device is required to be interactive for
+ * fingerprint authentication to unlock the device.
+ */
+public class FingerprintSettingsRequireScreenOnToAuthPreferenceController
+ extends FingerprintSettingsPreferenceController {
+ private static final String TAG =
+ "FingerprintSettingsRequireScreenOnToAuthPreferenceController";
+
+ @VisibleForTesting
+ protected FingerprintManager mFingerprintManager;
+
+ public FingerprintSettingsRequireScreenOnToAuthPreferenceController(
+ Context context, String prefKey) {
+ super(context, prefKey);
+ mFingerprintManager = Utils.getFingerprintManagerOrNull(context);
+ }
+
+ @Override
+ public boolean isChecked() {
+ if (!FingerprintSettings.isFingerprintHardwareDetected(mContext)) {
+ return false;
+ } else if (getRestrictingAdmin() != null) {
+ return false;
+ }
+ int defaultValue = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_requireScreenOnToAuthEnabled) ? 1 : 0;
+
+ return Settings.Secure.getIntForUser(
+ mContext.getContentResolver(),
+ Settings.Secure.SFPS_REQUIRE_SCREEN_ON_TO_AUTH_ENABLED,
+ defaultValue,
+ getUserHandle()) != 0;
+ }
+
+ @Override
+ public boolean setChecked(boolean isChecked) {
+ Settings.Secure.putIntForUser(
+ mContext.getContentResolver(),
+ Settings.Secure.SFPS_REQUIRE_SCREEN_ON_TO_AUTH_ENABLED,
+ isChecked ? 1 : 0,
+ getUserHandle());
+ return true;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ if (!FingerprintSettings.isFingerprintHardwareDetected(mContext)) {
+ preference.setEnabled(false);
+ } else if (!mFingerprintManager.hasEnrolledTemplates(getUserId())) {
+ preference.setEnabled(false);
+ } else {
+ preference.setEnabled(true);
+ }
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ if (mFingerprintManager != null
+ && mFingerprintManager.isHardwareDetected()
+ && mFingerprintManager.isPowerbuttonFps()) {
+ return mFingerprintManager.hasEnrolledTemplates(getUserId())
+ ? AVAILABLE : DISABLED_DEPENDENT_SETTING;
+ } else {
+ return UNSUPPORTED_ON_DEVICE;
+ }
+ }
+
+ private int getUserHandle() {
+ return UserHandle.of(getUserId()).getIdentifier();
+ }
+
+}
diff --git a/src/com/android/settings/bluetooth/BluetoothPermissionRequest.java b/src/com/android/settings/bluetooth/BluetoothPermissionRequest.java
index 8542fcd..a62bbe1 100644
--- a/src/com/android/settings/bluetooth/BluetoothPermissionRequest.java
+++ b/src/com/android/settings/bluetooth/BluetoothPermissionRequest.java
@@ -24,6 +24,7 @@
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.os.PowerManager;
import android.os.UserManager;
import android.util.Log;
@@ -125,8 +126,15 @@
// Create an intent triggered by clicking on the
// "Clear All Notifications" button
+ String bluetoothName;
+ try {
+ bluetoothName = Utils.findBluetoothPackageName(context);
+ } catch (NameNotFoundException e) {
+ e.printStackTrace();
+ return;
+ }
Intent deleteIntent = new Intent(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY);
- deleteIntent.setPackage("com.android.bluetooth");
+ deleteIntent.setPackage(bluetoothName);
deleteIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
deleteIntent.putExtra(BluetoothDevice.EXTRA_CONNECTION_ACCESS_RESULT,
BluetoothDevice.CONNECTION_ACCESS_NO);
diff --git a/src/com/android/settings/bluetooth/Utils.java b/src/com/android/settings/bluetooth/Utils.java
old mode 100755
new mode 100644
index ca8f9d3..24fe4e1
--- a/src/com/android/settings/bluetooth/Utils.java
+++ b/src/com/android/settings/bluetooth/Utils.java
@@ -16,11 +16,18 @@
package com.android.settings.bluetooth;
+import static android.os.Process.BLUETOOTH_UID;
+
import android.app.settings.SettingsEnums;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.DialogInterface;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.UserHandle;
import android.provider.DeviceConfig;
import android.provider.Settings;
import android.text.TextUtils;
@@ -189,4 +196,48 @@
}
return false;
}
+
+ /**
+ * Returns the Bluetooth Package name
+ */
+ public static String findBluetoothPackageName(Context context)
+ throws NameNotFoundException {
+ // this activity will always be in the package where the rest of Bluetooth lives
+ String sentinelActivity = "com.android.bluetooth.opp.BluetoothOppLauncherActivity";
+ PackageManager packageManager = context.createContextAsUser(UserHandle.SYSTEM, 0)
+ .getPackageManager();
+ String[] allPackages = packageManager.getPackagesForUid(BLUETOOTH_UID);
+ String matchedPackage = null;
+ for (String candidatePackage : allPackages) {
+ PackageInfo packageInfo;
+ try {
+ packageInfo =
+ packageManager.getPackageInfo(
+ candidatePackage,
+ PackageManager.GET_ACTIVITIES
+ | PackageManager.MATCH_ANY_USER
+ | PackageManager.MATCH_UNINSTALLED_PACKAGES
+ | PackageManager.MATCH_DISABLED_COMPONENTS);
+ } catch (NameNotFoundException e) {
+ // rethrow
+ throw e;
+ }
+ if (packageInfo.activities == null) {
+ continue;
+ }
+ for (ActivityInfo activity : packageInfo.activities) {
+ if (sentinelActivity.equals(activity.name)) {
+ if (matchedPackage == null) {
+ matchedPackage = candidatePackage;
+ } else {
+ throw new NameNotFoundException("multiple main bluetooth packages found");
+ }
+ }
+ }
+ }
+ if (matchedPackage != null) {
+ return matchedPackage;
+ }
+ throw new NameNotFoundException("Could not find main bluetooth package");
+ }
}
diff --git a/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceController.java b/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceController.java
index bd8169a..f1677f2 100644
--- a/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceController.java
+++ b/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceController.java
@@ -16,9 +16,8 @@
package com.android.settings.development;
+import android.bluetooth.BluetoothManager;
import android.content.Context;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
import android.os.SystemProperties;
import androidx.annotation.VisibleForTesting;
@@ -42,18 +41,15 @@
private int mDefaultMaxConnectedAudioDevices = 0;
+ private final BluetoothManager mBluetoothManager;
+
public BluetoothMaxConnectedAudioDevicesPreferenceController(Context context) {
super(context);
- try {
- Resources res = context.getPackageManager().getResourcesForApplication(
- "com.android.bluetooth");
- mDefaultMaxConnectedAudioDevices = res.getInteger(res.getIdentifier(
- "config_bluetooth_max_connected_audio_devices",
- "integer", "com.android.bluetooth"));
- } catch (PackageManager.NameNotFoundException e) {
- e.printStackTrace();
- }
+ mBluetoothManager = context.getSystemService(BluetoothManager.class);
+
+ mDefaultMaxConnectedAudioDevices =
+ mBluetoothManager.getAdapter().getMaxConnectedAudioDevices();
}
@Override
diff --git a/src/com/android/settings/notification/NotificationVolumePreferenceController.java b/src/com/android/settings/notification/NotificationVolumePreferenceController.java
index 322bb6c..112debc 100644
--- a/src/com/android/settings/notification/NotificationVolumePreferenceController.java
+++ b/src/com/android/settings/notification/NotificationVolumePreferenceController.java
@@ -16,6 +16,7 @@
package com.android.settings.notification;
+import android.app.ActivityThread;
import android.app.INotificationManager;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
@@ -29,26 +30,32 @@
import android.os.Message;
import android.os.ServiceManager;
import android.os.Vibrator;
+import android.provider.DeviceConfig;
import android.service.notification.NotificationListenerService;
import android.text.TextUtils;
import android.util.Log;
import androidx.lifecycle.OnLifecycleEvent;
+import androidx.preference.PreferenceScreen;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settingslib.core.lifecycle.Lifecycle;
import java.util.Objects;
+import java.util.Set;
/**
- * Update notification volume icon in Settings in response to user adjusting volume
+ * Update notification volume icon in Settings in response to user adjusting volume.
*/
public class NotificationVolumePreferenceController extends VolumeSeekBarPreferenceController {
private static final String TAG = "NotificationVolumePreferenceController";
private static final String KEY_NOTIFICATION_VOLUME = "notification_volume";
+ private static final boolean CONFIG_DEFAULT_VAL = false;
+ private boolean mSeparateNotification;
private Vibrator mVibrator;
private int mRingerMode = AudioManager.RINGER_MODE_NORMAL;
@@ -56,39 +63,74 @@
private final RingReceiver mReceiver = new RingReceiver();
private final H mHandler = new H();
private INotificationManager mNoMan;
-
-
private int mMuteIcon;
private final int mNormalIconId = R.drawable.ic_notifications;
private final int mVibrateIconId = R.drawable.ic_volume_ringer_vibrate;
private final int mSilentIconId = R.drawable.ic_notifications_off_24dp;
- private final boolean mRingNotificationAliased;
-
-
public NotificationVolumePreferenceController(Context context) {
this(context, KEY_NOTIFICATION_VOLUME);
}
public NotificationVolumePreferenceController(Context context, String key) {
super(context, key);
+
mVibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
if (mVibrator != null && !mVibrator.hasVibrator()) {
mVibrator = null;
}
- mRingNotificationAliased = mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_alias_ring_notif_stream_types);
updateRingerMode();
}
+ /**
+ * Allow for notification slider to be enabled in the scenario where the config switches on
+ * while settings page is already on the screen by always configuring the preference, even if it
+ * is currently inactive.
+ */
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ if (mPreference == null) {
+ setupVolPreference(screen);
+ }
+ mSeparateNotification = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.VOLUME_SEPARATE_NOTIFICATION, CONFIG_DEFAULT_VAL);
+ if (mPreference != null) {
+ mPreference.setVisible(getAvailabilityStatus() == AVAILABLE);
+ }
+ updateEffectsSuppressor();
+ updatePreferenceIconAndSliderState();
+ }
+
+ /**
+ * Only display the notification slider when the corresponding device config flag is set
+ */
+ private void onDeviceConfigChange(DeviceConfig.Properties properties) {
+ Set<String> changeSet = properties.getKeyset();
+
+ if (changeSet.contains(SystemUiDeviceConfigFlags.VOLUME_SEPARATE_NOTIFICATION)) {
+ boolean newVal = properties.getBoolean(
+ SystemUiDeviceConfigFlags.VOLUME_SEPARATE_NOTIFICATION, CONFIG_DEFAULT_VAL);
+ if (newVal != mSeparateNotification) {
+ mSeparateNotification = newVal;
+ // manually hiding the preference because being unavailable does not do the job
+ if (mPreference != null) {
+ mPreference.setVisible(getAvailabilityStatus() == AVAILABLE);
+ }
+ }
+ }
+ }
+
+
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
@Override
public void onResume() {
super.onResume();
mReceiver.register(true);
- updateEffectsSuppressor();
- updatePreferenceIconAndSliderState();
+ DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI,
+ ActivityThread.currentApplication().getMainExecutor(),
+ this::onDeviceConfigChange);
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
@@ -96,16 +138,17 @@
public void onPause() {
super.onPause();
mReceiver.register(false);
+ DeviceConfig.removeOnPropertiesChangedListener(this::onDeviceConfigChange);
}
@Override
public int getAvailabilityStatus() {
+ boolean separateNotification = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.VOLUME_SEPARATE_NOTIFICATION, false);
- // Show separate notification slider if ring/notification are not aliased by AudioManager --
- // if they are, notification volume is controlled by RingVolumePreferenceController.
return mContext.getResources().getBoolean(R.bool.config_show_notification_volume)
- && (!mRingNotificationAliased || !Utils.isVoiceCapable(mContext))
&& !mHelper.isSingleVolume()
+ && (separateNotification || !Utils.isVoiceCapable(mContext))
? AVAILABLE : UNSUPPORTED_ON_DEVICE;
}
diff --git a/src/com/android/settings/notification/RingVolumePreferenceController.java b/src/com/android/settings/notification/RingVolumePreferenceController.java
index a78689f..7fdb1e1 100644
--- a/src/com/android/settings/notification/RingVolumePreferenceController.java
+++ b/src/com/android/settings/notification/RingVolumePreferenceController.java
@@ -16,6 +16,7 @@
package com.android.settings.notification;
+import android.app.ActivityThread;
import android.app.INotificationManager;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
@@ -29,6 +30,7 @@
import android.os.Message;
import android.os.ServiceManager;
import android.os.Vibrator;
+import android.provider.DeviceConfig;
import android.service.notification.NotificationListenerService;
import android.text.TextUtils;
import android.util.Log;
@@ -36,11 +38,13 @@
import androidx.lifecycle.OnLifecycleEvent;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settingslib.core.lifecycle.Lifecycle;
import java.util.Objects;
+import java.util.Set;
/**
* This slider can represent both ring and notification, if the corresponding streams are aliased,
@@ -59,24 +63,21 @@
private int mMuteIcon;
- /*
- * Whether ring and notification streams are aliased together by AudioManager.
- * If they are, we'll present one volume control for both.
- * If not, we'll present separate volume controls.
- */
- private final boolean mRingAliasNotif;
-
- private final int mNormalIconId;
+ private int mNormalIconId;
@VisibleForTesting
- final int mVibrateIconId;
+ int mVibrateIconId;
@VisibleForTesting
- final int mSilentIconId;
+ int mSilentIconId;
@VisibleForTesting
- final int mTitleId;
+ int mTitleId;
+
+ private boolean mSeparateNotification;
private INotificationManager mNoMan;
+ private static final boolean CONFIG_DEFAULT_VAL = false;
+
public RingVolumePreferenceController(Context context) {
this(context, KEY_RING_VOLUME);
}
@@ -87,29 +88,56 @@
if (mVibrator != null && !mVibrator.hasVibrator()) {
mVibrator = null;
}
-
- mRingAliasNotif = isRingAliasNotification();
- if (mRingAliasNotif) {
- mTitleId = R.string.ring_volume_option_title;
-
- mNormalIconId = R.drawable.ic_notifications;
- mSilentIconId = R.drawable.ic_notifications_off_24dp;
- } else {
- mTitleId = R.string.separate_ring_volume_option_title;
-
- mNormalIconId = R.drawable.ic_ring_volume;
- mSilentIconId = R.drawable.ic_ring_volume_off;
- }
- // todo: set a distinct vibrate icon for ring vs notification
- mVibrateIconId = R.drawable.ic_volume_ringer_vibrate;
-
+ mSeparateNotification = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.VOLUME_SEPARATE_NOTIFICATION, CONFIG_DEFAULT_VAL);
+ loadPreferenceIconResources(mSeparateNotification);
updateRingerMode();
}
- @VisibleForTesting
- boolean isRingAliasNotification() {
- return mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_alias_ring_notif_stream_types);
+ private void loadPreferenceIconResources(boolean separateNotification) {
+ if (separateNotification) {
+ mTitleId = R.string.separate_ring_volume_option_title;
+ mNormalIconId = R.drawable.ic_ring_volume;
+ mSilentIconId = R.drawable.ic_ring_volume_off;
+ } else {
+ mTitleId = R.string.ring_volume_option_title;
+ mNormalIconId = R.drawable.ic_notifications;
+ mSilentIconId = R.drawable.ic_notifications_off_24dp;
+ }
+ // todo: set a distinct vibrate icon for ring vs notification
+ mVibrateIconId = R.drawable.ic_volume_ringer_vibrate;
+ }
+
+ /**
+ * As the responsibility of this slider changes, so should its title & icon
+ */
+ public void onDeviceConfigChange(DeviceConfig.Properties properties) {
+ Set<String> changeSet = properties.getKeyset();
+ if (changeSet.contains(SystemUiDeviceConfigFlags.VOLUME_SEPARATE_NOTIFICATION)) {
+ boolean valueUpdated = readSeparateNotificationVolumeConfig();
+ if (valueUpdated) {
+ updateEffectsSuppressor();
+ selectPreferenceIconState();
+ setPreferenceTitle();
+ }
+ }
+ }
+
+ /**
+ * side effect: updates the cached value of the config, and also the icon
+ * @return has the config changed?
+ */
+ private boolean readSeparateNotificationVolumeConfig() {
+ boolean newVal = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.VOLUME_SEPARATE_NOTIFICATION, CONFIG_DEFAULT_VAL);
+
+ boolean valueUpdated = newVal != mSeparateNotification;
+ if (valueUpdated) {
+ mSeparateNotification = newVal;
+ loadPreferenceIconResources(newVal);
+ }
+
+ return valueUpdated;
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
@@ -117,8 +145,11 @@
public void onResume() {
super.onResume();
mReceiver.register(true);
+ readSeparateNotificationVolumeConfig();
+ DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI,
+ ActivityThread.currentApplication().getMainExecutor(), this::onDeviceConfigChange);
updateEffectsSuppressor();
- updatePreferenceIcon();
+ selectPreferenceIconState();
setPreferenceTitle();
}
@@ -127,6 +158,7 @@
public void onPause() {
super.onPause();
mReceiver.register(false);
+ DeviceConfig.removeOnPropertiesChangedListener(this::onDeviceConfigChange);
}
@Override
@@ -170,7 +202,7 @@
final int ringerMode = mHelper.getRingerModeInternal();
if (mRingerMode == ringerMode) return;
mRingerMode = ringerMode;
- updatePreferenceIcon();
+ selectPreferenceIconState();
}
private void updateEffectsSuppressor() {
@@ -190,7 +222,8 @@
return;
}
- if (hintsMatch(hints, mRingAliasNotif)) {
+ if (hintsMatch(hints, DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.VOLUME_SEPARATE_NOTIFICATION, false))) {
mSuppressor = suppressor;
if (mPreference != null) {
final String text = SuppressorHelper.getSuppressionText(mContext, suppressor);
@@ -200,11 +233,11 @@
}
@VisibleForTesting
- boolean hintsMatch(int hints, boolean ringNotificationAliased) {
+ boolean hintsMatch(int hints, boolean notificationSeparated) {
return (hints & NotificationListenerService.HINT_HOST_DISABLE_CALL_EFFECTS) != 0
|| (hints & NotificationListenerService.HINT_HOST_DISABLE_EFFECTS) != 0
|| ((hints & NotificationListenerService.HINT_HOST_DISABLE_NOTIFICATION_EFFECTS)
- != 0 && ringNotificationAliased);
+ != 0 && !notificationSeparated);
}
@VisibleForTesting
@@ -217,7 +250,7 @@
mVibrator = vibrator;
}
- private void updatePreferenceIcon() {
+ private void selectPreferenceIconState() {
if (mPreference != null) {
if (mRingerMode == AudioManager.RINGER_MODE_NORMAL) {
mPreference.showIcon(mNormalIconId);
diff --git a/src/com/android/settings/notification/VolumeSeekBarPreferenceController.java b/src/com/android/settings/notification/VolumeSeekBarPreferenceController.java
index d170159..0414565 100644
--- a/src/com/android/settings/notification/VolumeSeekBarPreferenceController.java
+++ b/src/com/android/settings/notification/VolumeSeekBarPreferenceController.java
@@ -55,13 +55,17 @@
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
if (isAvailable()) {
- mPreference = screen.findPreference(getPreferenceKey());
- mPreference.setCallback(mVolumePreferenceCallback);
- mPreference.setStream(getAudioStream());
- mPreference.setMuteIcon(getMuteIcon());
+ setupVolPreference(screen);
}
}
+ protected void setupVolPreference(PreferenceScreen screen) {
+ mPreference = screen.findPreference(getPreferenceKey());
+ mPreference.setCallback(mVolumePreferenceCallback);
+ mPreference.setStream(getAudioStream());
+ mPreference.setMuteIcon(getMuteIcon());
+ }
+
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
public void onResume() {
if (mPreference != null) {
diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsRequireScreenOnToAuthPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsRequireScreenOnToAuthPreferenceControllerTest.java
new file mode 100644
index 0000000..ff74d59
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsRequireScreenOnToAuthPreferenceControllerTest.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2022 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.biometrics.fingerprint;
+
+import static com.android.settings.core.BasePreferenceController.AVAILABLE;
+import static com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING;
+import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.hardware.fingerprint.FingerprintManager;
+import android.provider.Settings;
+
+import com.android.settings.testutils.shadow.ShadowUtils;
+import com.android.settingslib.RestrictedSwitchPreference;
+
+import org.junit.After;
+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;
+import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowUtils.class})
+public class FingerprintSettingsRequireScreenOnToAuthPreferenceControllerTest {
+
+ @Mock
+ private FingerprintManager mFingerprintManager;
+ @Mock
+ private PackageManager mPackageManager;
+ @Mock
+ private RestrictedSwitchPreference mPreference;
+
+ private Context mContext;
+ private FingerprintSettingsRequireScreenOnToAuthPreferenceController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+ when(mContext.getSystemService(eq(Context.FINGERPRINT_SERVICE))).thenReturn(
+ mFingerprintManager);
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+
+ mController = spy(new FingerprintSettingsRequireScreenOnToAuthPreferenceController(mContext,
+ "test_key"));
+ ReflectionHelpers.setField(mController, "mFingerprintManager", mFingerprintManager);
+ }
+
+ @After
+ public void tearDown() {
+ ShadowUtils.reset();
+ }
+
+ @Test
+ public void onPreferenceChange_settingIsUpdated() {
+ boolean state = Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.SFPS_REQUIRE_SCREEN_ON_TO_AUTH_ENABLED, 1) != 0;
+
+ assertThat(mController.isChecked()).isFalse();
+ assertThat(mController.onPreferenceChange(mPreference, !state)).isTrue();
+ boolean newState = Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.SFPS_REQUIRE_SCREEN_ON_TO_AUTH_ENABLED, 1) != 0;
+ assertThat(newState).isEqualTo(!state);
+ }
+
+ @Test
+ public void isAvailable_isEnabled_whenSfpsHardwareDetected_AndHasEnrolledFingerprints() {
+ assertThat(mController.isAvailable()).isEqualTo(false);
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
+ configure_hardwareDetected_isSfps_hasEnrolledTemplates(
+ true /* isHardwareDetected */,
+ true /* isPowerbuttonFps */,
+ true /* hasEnrolledTemplates */);
+ assertThat(mController.isAvailable()).isEqualTo(true);
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+ }
+
+ @Test
+ public void isAvailable_isDisabled_whenSfpsHardwareDetected_AndNoEnrolledFingerprints() {
+ assertThat(mController.isAvailable()).isEqualTo(false);
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
+ configure_hardwareDetected_isSfps_hasEnrolledTemplates(
+ true /* isHardwareDetected */,
+ true /* isPowerbuttonFps */,
+ false /* hasEnrolledTemplates */);
+ assertThat(mController.isAvailable()).isEqualTo(true);
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_DEPENDENT_SETTING);
+ }
+
+ @Test
+ public void isUnavailable_whenHardwareNotDetected() {
+ assertThat(mController.isAvailable()).isFalse();
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
+ configure_hardwareDetected_isSfps_hasEnrolledTemplates(
+ false /* isHardwareDetected */,
+ true /* isPowerbuttonFps */,
+ true /* hasEnrolledTemplates */);
+ assertThat(mController.isAvailable()).isFalse();
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
+ }
+
+ @Test
+ public void isUnavailable_onNonSfpsDevice() {
+ assertThat(mController.isAvailable()).isFalse();
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
+ configure_hardwareDetected_isSfps_hasEnrolledTemplates(
+ true /* isHardwareDetected */,
+ false /* isPowerbuttonFps */,
+ true /* hasEnrolledTemplates */);
+ assertThat(mController.isAvailable()).isFalse();
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
+ }
+
+ private void configure_hardwareDetected_isSfps_hasEnrolledTemplates(
+ boolean isHardwareDetected, boolean isPowerbuttonFps, boolean hasEnrolledTemplates) {
+ when(mFingerprintManager.isHardwareDetected()).thenReturn(isHardwareDetected);
+ when(mFingerprintManager.isPowerbuttonFps()).thenReturn(isPowerbuttonFps);
+ when(mFingerprintManager.hasEnrolledTemplates(anyInt())).thenReturn(hasEnrolledTemplates);
+ }
+
+
+}
diff --git a/tests/robotests/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceControllerTest.java
index 72477b9..7ab311f 100644
--- a/tests/robotests/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceControllerTest.java
@@ -24,9 +24,9 @@
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.when;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothManager;
import android.content.Context;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
import android.os.SystemProperties;
@@ -54,6 +54,11 @@
@Spy
private Context mSpyContext = RuntimeEnvironment.application;
+ @Mock
+ private BluetoothManager mBluetoothManager;
+ @Mock
+ private BluetoothAdapter mBluetoothAdapter;
+
private ListPreference mPreference;
private BluetoothMaxConnectedAudioDevicesPreferenceController mController;
@@ -63,19 +68,15 @@
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
+ doReturn(mBluetoothManager).when(mSpyContext).getSystemService(BluetoothManager.class);
+ doReturn(mBluetoothAdapter).when(mBluetoothManager).getAdapter();
// Get XML values without mock
// Setup test list preference using XML values
mPreference = new ListPreference(mSpyContext);
mPreference.setEntries(R.array.bluetooth_max_connected_audio_devices);
mPreference.setEntryValues(R.array.bluetooth_max_connected_audio_devices_values);
- // Retrieve default max connected audio devices to a test controlled value
- try {
- Resources res = mSpyContext.getPackageManager().getResourcesForApplication("com.android.bluetooth");
- TEST_MAX_CONNECTED_AUDIO_DEVICES = res.getInteger(res.getIdentifier("config_bluetooth_max_connected_audio_devices", "integer", "com.android.bluetooth"));
- } catch (PackageManager.NameNotFoundException e) {
- e.printStackTrace();
- }
-
+ doReturn(TEST_MAX_CONNECTED_AUDIO_DEVICES).when(mBluetoothAdapter)
+ .getMaxConnectedAudioDevices();
// Init the actual controller
mController = new BluetoothMaxConnectedAudioDevicesPreferenceController(mSpyContext);
// Construct preference in the controller via a mocked preference screen object
diff --git a/tests/robotests/src/com/android/settings/notification/NotificationVolumePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/NotificationVolumePreferenceControllerTest.java
index 96b9e62..7e7ad10 100644
--- a/tests/robotests/src/com/android/settings/notification/NotificationVolumePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/NotificationVolumePreferenceControllerTest.java
@@ -18,6 +18,7 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
@@ -25,10 +26,17 @@
import android.content.res.Resources;
import android.media.AudioManager;
import android.os.Vibrator;
+import android.provider.DeviceConfig;
import android.service.notification.NotificationListenerService;
import android.telephony.TelephonyManager;
-import com.android.internal.R;
+import androidx.preference.PreferenceManager;
+import androidx.preference.PreferenceScreen;
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.testutils.shadow.ShadowDeviceConfig;
import org.junit.Before;
import org.junit.Test;
@@ -37,11 +45,12 @@
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
+import org.robolectric.Shadows;
import org.robolectric.annotation.Config;
@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowDeviceConfig.class})
public class NotificationVolumePreferenceControllerTest {
-
@Mock
private AudioHelper mHelper;
@Mock
@@ -52,6 +61,11 @@
private Vibrator mVibrator;
@Mock
private Resources mResources;
+ @Mock
+ private PreferenceManager mPreferenceManager;
+
+ private static final String READ_DEVICE_CONFIG_PERMISSION =
+ "android.permission.READ_DEVICE_CONFIG";
private Context mContext;
private NotificationVolumePreferenceController mController;
@@ -87,7 +101,9 @@
public void isAvailable_voiceCapable_aliasedWithRing_shouldReturnFalse() {
when(mResources.getBoolean(
com.android.settings.R.bool.config_show_notification_volume)).thenReturn(true);
- when(mResources.getBoolean(R.bool.config_alias_ring_notif_stream_types)).thenReturn(true);
+
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.VOLUME_SEPARATE_NOTIFICATION, "false", false);
NotificationVolumePreferenceController controller =
new NotificationVolumePreferenceController(mContext);
@@ -105,7 +121,9 @@
public void isAvailable_voiceCapable_separatedFromRing_shouldReturnTrue() {
when(mResources.getBoolean(
com.android.settings.R.bool.config_show_notification_volume)).thenReturn(true);
- when(mResources.getBoolean(R.bool.config_alias_ring_notif_stream_types)).thenReturn(false);
+
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.VOLUME_SEPARATE_NOTIFICATION, "true", false);
NotificationVolumePreferenceController controller =
new NotificationVolumePreferenceController(mContext);
@@ -170,4 +188,70 @@
.isTrue();
}
+ @Test
+ public void enableSeparateNotificationConfig_controllerBecomesAvailable() {
+ PreferenceScreen screen = spy(new PreferenceScreen(mContext, null));
+ VolumeSeekBarPreference volumeSeekBarPreference = mock(VolumeSeekBarPreference.class);
+ when(screen.getPreferenceManager()).thenReturn(mPreferenceManager);
+ when(screen.getContext()).thenReturn(mContext);
+ when(mResources.getBoolean(
+ com.android.settings.R.bool.config_show_notification_volume)).thenReturn(true);
+ // block the alternative condition to enable controller
+ when(mTelephonyManager.isVoiceCapable()).thenReturn(true);
+
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.VOLUME_SEPARATE_NOTIFICATION, "false", false);
+
+ NotificationVolumePreferenceController controller =
+ new NotificationVolumePreferenceController(mContext);
+ when(screen.findPreference(controller.getPreferenceKey()))
+ .thenReturn(volumeSeekBarPreference);
+
+ // allow the controller to subscribe
+ Shadows.shadowOf((android.app.Application) ApplicationProvider.getApplicationContext())
+ .grantPermissions(READ_DEVICE_CONFIG_PERMISSION);
+ controller.onResume();
+ controller.displayPreference(screen);
+
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.VOLUME_SEPARATE_NOTIFICATION, Boolean.toString(true),
+ false);
+
+ assertThat(controller.getAvailabilityStatus()
+ == BasePreferenceController.AVAILABLE).isTrue();
+ }
+
+ @Test
+ public void disableSeparateNotificationConfig_controllerBecomesUnavailable() {
+ PreferenceScreen screen = spy(new PreferenceScreen(mContext, null));
+ VolumeSeekBarPreference volumeSeekBarPreference = mock(VolumeSeekBarPreference.class);
+ when(screen.getPreferenceManager()).thenReturn(mPreferenceManager);
+ when(screen.getContext()).thenReturn(mContext);
+ when(mResources.getBoolean(
+ com.android.settings.R.bool.config_show_notification_volume)).thenReturn(true);
+
+ // block the alternative condition to enable controller
+ when(mTelephonyManager.isVoiceCapable()).thenReturn(true);
+
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.VOLUME_SEPARATE_NOTIFICATION, "true", false);
+
+ NotificationVolumePreferenceController controller =
+ new NotificationVolumePreferenceController(mContext);
+
+ when(screen.findPreference(controller.getPreferenceKey()))
+ .thenReturn(volumeSeekBarPreference);
+
+ Shadows.shadowOf((android.app.Application) ApplicationProvider.getApplicationContext())
+ .grantPermissions(READ_DEVICE_CONFIG_PERMISSION);
+ controller.onResume();
+ controller.displayPreference(screen);
+
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.VOLUME_SEPARATE_NOTIFICATION, "false", false);
+
+ assertThat(controller.getAvailabilityStatus()
+ == BasePreferenceController.UNSUPPORTED_ON_DEVICE).isTrue();
+ }
+
}
diff --git a/tests/robotests/src/com/android/settings/notification/RingVolumePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/RingVolumePreferenceControllerTest.java
index 02757d5..1ad26c7 100644
--- a/tests/robotests/src/com/android/settings/notification/RingVolumePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/RingVolumePreferenceControllerTest.java
@@ -27,10 +27,13 @@
import android.content.res.Resources;
import android.media.AudioManager;
import android.os.Vibrator;
+import android.provider.DeviceConfig;
import android.service.notification.NotificationListenerService;
import android.telephony.TelephonyManager;
+import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.settings.R;
+import com.android.settings.testutils.shadow.ShadowDeviceConfig;
import org.junit.Before;
import org.junit.Test;
@@ -39,9 +42,11 @@
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowApplication;
@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowDeviceConfig.class})
public class RingVolumePreferenceControllerTest {
@Mock
@@ -124,9 +129,10 @@
// todo: verify that the title change is displayed, by examining the underlying preference
@Test
public void ringNotificationStreamsNotAliased_sliderTitleSetToRingOnly() {
- when(mResources.getBoolean(
- com.android.internal.R.bool.config_alias_ring_notif_stream_types))
- .thenReturn(false);
+
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.VOLUME_SEPARATE_NOTIFICATION, "true", false);
+
final RingVolumePreferenceController controller =
new RingVolumePreferenceController(mContext);
@@ -138,8 +144,9 @@
@Test
public void ringNotificationStreamsAliased_sliderTitleIncludesBothRingNotification() {
- when(mResources.getBoolean(
- com.android.internal.R.bool.config_alias_ring_notif_stream_types)).thenReturn(true);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.VOLUME_SEPARATE_NOTIFICATION, "false", false);
+
final RingVolumePreferenceController control = new RingVolumePreferenceController(mContext);
int expectedTitleId = R.string.ring_volume_option_title;
@@ -150,39 +157,39 @@
@Test
public void setHintsRing_aliased_Matches() {
assertThat(mController.hintsMatch(
- NotificationListenerService.HINT_HOST_DISABLE_CALL_EFFECTS, true)).isTrue();
+ NotificationListenerService.HINT_HOST_DISABLE_CALL_EFFECTS, false)).isTrue();
}
@Test
public void setHintsRingNotification_aliased_Matches() {
assertThat(mController.hintsMatch(NotificationListenerService.HINT_HOST_DISABLE_EFFECTS,
- true)).isTrue();
+ false)).isTrue();
}
@Test
public void setHintNotification_aliased_Matches() {
assertThat(mController
.hintsMatch(NotificationListenerService.HINT_HOST_DISABLE_NOTIFICATION_EFFECTS,
- true)).isTrue();
+ false)).isTrue();
}
@Test
public void setHintsRing_unaliased_Matches() {
assertThat(mController.hintsMatch(
- NotificationListenerService.HINT_HOST_DISABLE_CALL_EFFECTS, false)).isTrue();
+ NotificationListenerService.HINT_HOST_DISABLE_CALL_EFFECTS, true)).isTrue();
}
@Test
public void setHintsRingNotification_unaliased_Matches() {
assertThat(mController.hintsMatch(NotificationListenerService.HINT_HOST_DISABLE_EFFECTS,
- false)).isTrue();
+ true)).isTrue();
}
@Test
public void setHintNotification_unaliased_doesNotMatch() {
assertThat(mController
.hintsMatch(NotificationListenerService.HINT_HOST_DISABLE_NOTIFICATION_EFFECTS,
- false)).isFalse();
+ true)).isFalse();
}
@Test