Snap for 8287852 from 48eb6726c3 to tm-release

Change-Id: I0d98913d8c240ddfc45a8bd08f076e24a057fe65
This commit is contained in:
Android Build Coastguard Worker
2022-03-11 02:08:44 +00:00
40 changed files with 1091 additions and 553 deletions

View File

@@ -1517,6 +1517,8 @@
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="package" />
</intent-filter>
<meta-data android:name="com.android.settings.HIGHLIGHT_MENU_KEY"
android:value="@string/menu_key_apps"/>
</activity-alias>
<activity android:name=".applications.InstalledAppOpenByDefaultActivity"
@@ -1529,6 +1531,8 @@
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="package" />
</intent-filter>
<meta-data android:name="com.android.settings.HIGHLIGHT_MENU_KEY"
android:value="@string/menu_key_apps"/>
</activity>
<!-- Provide direct entry into manage apps showing running services. -->
@@ -1947,8 +1951,7 @@
<activity android:name=".accessibility.AccessibilitySettingsForSetupWizardActivity"
android:icon="@drawable/ic_accessibility_suggestion"
android:label="@string/vision_settings_title"
android:exported="true"
android:theme="@style/GlifV3Theme.Light">
android:exported="true">
<intent-filter android:priority="1">
<action android:name="android.settings.ACCESSIBILITY_SETTINGS_FOR_SUW" />
<category android:name="android.intent.category.DEFAULT" />

File diff suppressed because it is too large Load Diff

View File

@@ -1,25 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:shape="rectangle">
<corners android:radius="100dp" />
<solid android:color="?androidprv:attr/colorAccentPrimary" />
</shape>

View File

@@ -20,13 +20,13 @@
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical"
android:background="@drawable/accessibility_qs_tooltips_background">
android:background="@drawable/accessibility_qs_tooltip_background">
<ImageView
android:id="@+id/qs_illustration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="@dimen/accessibility_qs_tooltips_margin_top"
android:paddingTop="@dimen/accessibility_qs_tooltip_margin_top"
android:layout_gravity="center_horizontal"
android:contentDescription="@null" />
@@ -34,7 +34,7 @@
android:id="@+id/qs_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/accessibility_qs_tooltips_margin"
android:padding="@dimen/accessibility_qs_tooltip_margin"
android:textColor="@android:color/black"
android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
android:textSize="16sp" />

View File

@@ -28,9 +28,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@drawable/accessibility_text_reading_reset_button_background"
android:paddingHorizontal="24dp"
android:paddingVertical="14dp"
android:text="@string/accessibility_text_reading_reset_button_title"
android:textAppearance="?android:attr/textAppearanceMedium" />
style="@style/ActionPrimaryButton"/>
</FrameLayout>

View File

@@ -1,49 +0,0 @@
<!--
Copyright (C) 2019 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.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:theme="@style/Theme.MaterialComponents.DayNight"
android:clipToPadding="true"
android:clipChildren="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.tabs.TabLayout
android:background="@android:color/transparent"
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMaxWidth="0dp"
app:tabGravity="fill"
app:tabMode="fixed"
app:tabIndicatorColor="@*android:color/accent_device_default"
app:tabSelectedTextColor="@*android:color/accent_device_default"
app:tabTextColor="?android:attr/textColorSecondary" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?android:attr/listDivider"/>
<androidx.viewpager.widget.ViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent">
</androidx.viewpager.widget.ViewPager>
</LinearLayout>

View File

@@ -33,6 +33,8 @@
android:layout_width="@dimen/admin_details_dialog_icon_size"
android:layout_height="@dimen/admin_details_dialog_icon_size"
android:scaleType="fitCenter"
android:src="@drawable/ic_lock_closed"
android:tint="?android:attr/colorAccent"
android:contentDescription="@null"/>
<TextView
android:id="@+id/admin_support_dialog_title"

View File

@@ -276,9 +276,9 @@
<dimen name="accessibility_icon_size">32dp</dimen>
<dimen name="accessibility_icon_foreground_size">18dp</dimen>
<!-- Accessibility quick settings tooltips -->
<dimen name="accessibility_qs_tooltips_margin">20dp</dimen>
<dimen name="accessibility_qs_tooltips_margin_top">27dp</dimen>
<!-- Accessibility quick settings tooltip -->
<dimen name="accessibility_qs_tooltip_margin">20dp</dimen>
<dimen name="accessibility_qs_tooltip_margin_top">27dp</dimen>
<!-- Restricted icon in switch bar -->
<dimen name="restricted_icon_margin_end">16dp</dimen>

View File

@@ -5555,9 +5555,9 @@
<!-- Used in the accessibility service settings to open the activity. [CHAR LIMIT=NONE] -->
<string name="accessibility_service_primary_open_title">Open <xliff:g id="accessibility_app_name" example="TalkBack">%1$s</xliff:g></string>
<!-- Used in the accessibility service settings to show quick settings tooltip for auto-added feature. [CHAR LIMIT=NONE] -->
<string name="accessibility_service_auto_added_qs_tooltips_content"><xliff:g id="accessibility_app_name" example="TalkBack">%1$s</xliff:g> added to Quick Settings. Swipe down to turn it on or off anytime.</string>
<string name="accessibility_service_auto_added_qs_tooltip_content"><xliff:g id="accessibility_app_name" example="TalkBack">%1$s</xliff:g> added to Quick Settings. Swipe down to turn it on or off anytime.</string>
<!-- Used in the accessibility service settings to show quick settings tooltip. [CHAR LIMIT=NONE] -->
<string name="accessibility_service_qs_tooltips_content">You can also add <xliff:g id="accessibility_app_name" example="TalkBack">%1$s</xliff:g> to Quick Settings from the top of your screen</string>
<string name="accessibility_service_qs_tooltip_content">You can also add <xliff:g id="accessibility_app_name" example="TalkBack">%1$s</xliff:g> to Quick Settings from the top of your screen</string>
<!-- Used in the color correction settings to show quick settings tooltip for auto-added feature. [CHAR LIMIT=NONE] -->
<string name="accessibility_color_correction_auto_added_qs_tooltip_content">Color correction added to Quick Settings. Swipe down to turn it on or off anytime.</string>
<!-- Used in the color correction settings to show quick settings tooltip. [CHAR LIMIT=NONE] -->
@@ -5575,7 +5575,7 @@
<!-- Used in the One-hand mode settings to show quick settings tooltip. [CHAR LIMIT=NONE] -->
<string name="accessibility_one_handed_mode_qs_tooltip_content">You can also add one-handed mode to Quick Settings from the top of your screen</string>
<!-- Used in the accessibility action for accessibility quick settings tooltip to dismiss. [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_tooltips_dismiss">Dismiss</string>
<string name="accessibility_quick_settings_tooltip_dismiss">Dismiss</string>
<!-- Intro for color correction settings screen to control turning on/off the feature entirely. [CHAR LIMIT=NONE] -->
<string name="accessibility_daltonizer_about_intro_text" product="default">Adjust how colors display on your phone</string>
<!-- Intro for color correction settings screen to control turning on/off the feature entirely. [CHAR LIMIT=NONE] -->
@@ -14026,4 +14026,13 @@
<!-- Text to explain an activity is a temporary placeholder [CHAR LIMIT=none] -->
<string name="placeholder_activity" translatable="false">*This is a temporary placeholder fallback activity.</string>
<!-- The title of the spatial audio [CHAR LIMIT=none] -->
<string name="bluetooth_details_spatial_audio_title">Spatial audio</string>
<!-- The summary of the spatial audio [CHAR LIMIT=none] -->
<string name="bluetooth_details_spatial_audio_summary">Immersive audio seems like it\u0027s coming from all around you. Only works with some media.</string>
<!-- The title of the head tracking [CHAR LIMIT=none] -->
<string name="bluetooth_details_head_tracking_title">Make audio more realistic</string>
<!-- The summary of the head tracking [CHAR LIMIT=none] -->
<string name="bluetooth_details_head_tracking_summary">Shift positioning of audio so it sounds more natural.</string>
</resources>

View File

@@ -52,6 +52,9 @@
<PreferenceCategory
android:key="device_companion_apps"/>
<PreferenceCategory
android:key="spatial_audio_group"/>
<PreferenceCategory
android:key="bluetooth_profiles"/>

View File

@@ -26,7 +26,7 @@
android:layout="@layout/settings_entity_header"
settings:controller="com.android.settings.applications.specialaccess.notificationaccess.HeaderPreferenceController"/>
<com.android.settings.widget.FilterTouchesSwitchPreference
<com.android.settingslib.RestrictedSwitchPreference
android:key="notification_access_switch"
android:title="@string/notification_access_detail_switch"
settings:controller="com.android.settings.applications.specialaccess.notificationaccess.ApprovalPreferenceController"/>

View File

@@ -116,7 +116,7 @@ public abstract class AccessibilityQuickSettingsPrimarySwitchPreferenceControlle
mTooltipWindow = new AccessibilityQuickSettingsTooltipWindow(mContext);
mTooltipWindow.setup(getTileTooltipContent(),
R.drawable.accessibility_auto_added_qs_tooltips_illustration);
R.drawable.accessibility_auto_added_qs_tooltip_illustration);
mTooltipWindow.showAtTopCenter(mPreference.getSwitch());
AccessibilityQuickSettingUtils.optInValueToSharedPreferences(mContext, tileComponentName);
mNeedsQSTooltipReshow = false;

View File

@@ -61,7 +61,7 @@ public class AccessibilityQuickSettingsTooltipWindow extends PopupWindow {
super.onInitializeAccessibilityNodeInfo(host, info);
final AccessibilityAction clickAction = new AccessibilityAction(
AccessibilityNodeInfo.ACTION_CLICK,
mContext.getString(R.string.accessibility_quick_settings_tooltips_dismiss));
mContext.getString(R.string.accessibility_quick_settings_tooltip_dismiss));
info.addAction(clickAction);
}
@@ -100,7 +100,7 @@ public class AccessibilityQuickSettingsTooltipWindow extends PopupWindow {
setBackgroundDrawable(new ColorDrawable(mContext.getColor(android.R.color.transparent)));
final LayoutInflater inflater = mContext.getSystemService(LayoutInflater.class);
final View popupView =
inflater.inflate(R.layout.accessibility_qs_tooltips, /* root= */ null);
inflater.inflate(R.layout.accessibility_qs_tooltip, /* root= */ null);
popupView.setFocusable(/* focusable= */ true);
popupView.setAccessibilityDelegate(mAccessibilityDelegate);
setContentView(popupView);
@@ -179,7 +179,7 @@ public class AccessibilityQuickSettingsTooltipWindow extends PopupWindow {
@VisibleForTesting
int getAvailableWindowWidth() {
final Resources res = mContext.getResources();
final int padding = res.getDimensionPixelSize(R.dimen.accessibility_qs_tooltips_margin);
final int padding = res.getDimensionPixelSize(R.dimen.accessibility_qs_tooltip_margin);
final int screenWidth = res.getDisplayMetrics().widthPixels;
return screenWidth - padding * 2;
}

View File

@@ -506,8 +506,8 @@ public abstract class AccessibilityShortcutPreferenceFragment extends DashboardF
}
final int imageResId = mNeedsQSTooltipType == QuickSettingsTooltipType.GUIDE_TO_EDIT
? R.drawable.accessibility_qs_tooltips_illustration
: R.drawable.accessibility_auto_added_qs_tooltips_illustration;
? R.drawable.accessibility_qs_tooltip_illustration
: R.drawable.accessibility_auto_added_qs_tooltip_illustration;
mTooltipWindow = new AccessibilityQuickSettingsTooltipWindow(getContext());
mTooltipWindow.setup(content, imageResId);
mTooltipWindow.showAtTopCenter(getView());

View File

@@ -141,8 +141,8 @@ public class LaunchAccessibilityActivityPreferenceFragment extends ToggleFeature
}
final int titleResId = type == QuickSettingsTooltipType.GUIDE_TO_EDIT
? R.string.accessibility_service_qs_tooltips_content
: R.string.accessibility_service_auto_added_qs_tooltips_content;
? R.string.accessibility_service_qs_tooltip_content
: R.string.accessibility_service_auto_added_qs_tooltip_content;
return getString(titleResId, tileName);
}

View File

@@ -252,8 +252,8 @@ public class ToggleAccessibilityServicePreferenceFragment extends
}
final int titleResId = type == QuickSettingsTooltipType.GUIDE_TO_EDIT
? R.string.accessibility_service_qs_tooltips_content
: R.string.accessibility_service_auto_added_qs_tooltips_content;
? R.string.accessibility_service_qs_tooltip_content
: R.string.accessibility_service_auto_added_qs_tooltip_content;
return getString(titleResId, tileName);
}

View File

@@ -877,8 +877,8 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference
}
final int imageResId = mNeedsQSTooltipType == QuickSettingsTooltipType.GUIDE_TO_EDIT
? R.drawable.accessibility_qs_tooltips_illustration
: R.drawable.accessibility_auto_added_qs_tooltips_illustration;
? R.drawable.accessibility_qs_tooltip_illustration
: R.drawable.accessibility_auto_added_qs_tooltip_illustration;
mTooltipWindow = new AccessibilityQuickSettingsTooltipWindow(getContext());
mTooltipWindow.setup(content, imageResId);
mTooltipWindow.showAtTopCenter(getView());

View File

@@ -27,10 +27,10 @@ import android.os.AsyncTask;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.SwitchPreference;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.RestrictedSwitchPreference;
public class ApprovalPreferenceController extends BasePreferenceController {
@@ -78,9 +78,11 @@ public class ApprovalPreferenceController extends BasePreferenceController {
@Override
public void updateState(Preference pref) {
final SwitchPreference preference = (SwitchPreference) pref;
final RestrictedSwitchPreference preference =
(RestrictedSwitchPreference) pref;
final CharSequence label = mPkgInfo.applicationInfo.loadLabel(mPm);
preference.setChecked(isServiceEnabled(mCn));
final boolean isEnabled = isServiceEnabled(mCn);
preference.setChecked(isEnabled);
preference.setOnPreferenceChangeListener((p, newValue) -> {
final boolean access = (Boolean) newValue;
if (!access) {
@@ -103,6 +105,7 @@ public class ApprovalPreferenceController extends BasePreferenceController {
return false;
}
});
preference.updateState(mCn.getPackageName(), mPkgInfo.applicationInfo.uid, isEnabled);
}
public void disable(final ComponentName cn) {

View File

@@ -55,6 +55,13 @@ public class CombinedBiometricStatusUtils {
return Utils.hasFingerprintHardware(mContext) && Utils.hasFaceHardware(mContext);
}
/**
* Returns whether at least one face template or fingerprint has been enrolled.
*/
public boolean hasEnrolled() {
return hasEnrolledFingerprints() || hasEnrolledFace();
}
/**
* Returns the {@link EnforcedAdmin} in case parental consent is required to change both
* face and fingerprint settings.
@@ -84,8 +91,7 @@ public class CombinedBiometricStatusUtils {
public String getSummary() {
final int numFingerprintsEnrolled = mFingerprintManager != null
? mFingerprintManager.getEnrolledFingerprints(mUserId).size() : 0;
final boolean faceEnrolled = mFaceManager != null
&& mFaceManager.hasEnrolledTemplates(mUserId);
final boolean faceEnrolled = hasEnrolledFace();
if (faceEnrolled && numFingerprintsEnrolled > 1) {
return mContext.getString(
@@ -105,6 +111,14 @@ public class CombinedBiometricStatusUtils {
}
}
private boolean hasEnrolledFingerprints() {
return mFingerprintManager != null && mFingerprintManager.hasEnrolledFingerprints(mUserId);
}
private boolean hasEnrolledFace() {
return mFaceManager != null && mFaceManager.hasEnrolledTemplates(mUserId);
}
/**
* Returns the class name of the Settings page corresponding to combined biometric settings.
*/

View File

@@ -75,7 +75,10 @@ public class FaceStatusUtils {
: FaceEnrollIntroduction.class.getName();
}
private boolean hasEnrolled() {
/**
* Returns whether at least one face template has been enrolled.
*/
public boolean hasEnrolled() {
return mFaceManager.hasEnrolledTemplates(mUserId);
}
}

View File

@@ -82,7 +82,10 @@ public class FingerprintStatusUtils {
: FingerprintEnrollIntroduction.class.getName();
}
private boolean hasEnrolled() {
/**
* Returns whether at least one fingerprint has been enrolled.
*/
public boolean hasEnrolled() {
return mFingerprintManager.hasEnrolledFingerprints(mUserId);
}
}

View File

@@ -0,0 +1,155 @@
/*
* 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.bluetooth;
import android.content.Context;
import android.media.AudioDeviceAttributes;
import android.media.AudioDeviceInfo;
import android.media.AudioManager;
import android.media.Spatializer;
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreference;
import com.android.settings.R;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.core.lifecycle.Lifecycle;
/**
* The controller of the Spatial audio setting in the bluetooth detail settings.
*/
public class BluetoothDetailsSpatialAudioController extends BluetoothDetailsController
implements Preference.OnPreferenceClickListener {
private static final String TAG = "BluetoothSpatialAudioController";
private static final String KEY_SPATIAL_AUDIO_GROUP = "spatial_audio_group";
private static final String KEY_SPATIAL_AUDIO = "spatial_audio";
private static final String KEY_HEAD_TRACKING = "head_tracking";
private final Spatializer mSpatializer;
@VisibleForTesting
PreferenceCategory mProfilesContainer;
@VisibleForTesting
AudioDeviceAttributes mAudioDevice;
public BluetoothDetailsSpatialAudioController(
Context context,
PreferenceFragmentCompat fragment,
CachedBluetoothDevice device,
Lifecycle lifecycle) {
super(context, fragment, device, lifecycle);
AudioManager audioManager = context.getSystemService(AudioManager.class);
mSpatializer = audioManager.getSpatializer();
mAudioDevice = new AudioDeviceAttributes(
AudioDeviceAttributes.ROLE_OUTPUT,
AudioDeviceInfo.TYPE_BLUETOOTH_A2DP,
mCachedDevice.getAddress());
}
@Override
public boolean isAvailable() {
return mSpatializer.isAvailableForDevice(mAudioDevice) ? true : false;
}
@Override
public boolean onPreferenceClick(Preference preference) {
SwitchPreference switchPreference = (SwitchPreference) preference;
String key = switchPreference.getKey();
if (TextUtils.equals(key, KEY_SPATIAL_AUDIO)) {
if (switchPreference.isChecked()) {
mSpatializer.addCompatibleAudioDevice(mAudioDevice);
} else {
mSpatializer.removeCompatibleAudioDevice(mAudioDevice);
}
refresh();
return true;
} else if (TextUtils.equals(key, KEY_HEAD_TRACKING)) {
mSpatializer.setHeadTrackerEnabled(switchPreference.isChecked(), mAudioDevice);
return true;
} else {
Log.w(TAG, "invalid key name.");
return false;
}
}
@Override
public String getPreferenceKey() {
return KEY_SPATIAL_AUDIO_GROUP;
}
@Override
protected void init(PreferenceScreen screen) {
mProfilesContainer = screen.findPreference(getPreferenceKey());
mProfilesContainer.setLayoutResource(R.layout.preference_bluetooth_profile_category);
refresh();
}
@Override
protected void refresh() {
SwitchPreference spatialAudioPref = mProfilesContainer.findPreference(KEY_SPATIAL_AUDIO);
if (spatialAudioPref == null) {
spatialAudioPref = createSpatialAudioPreference(mProfilesContainer.getContext());
mProfilesContainer.addPreference(spatialAudioPref);
}
boolean isSpatialAudioOn = mSpatializer.getCompatibleAudioDevices().contains(mAudioDevice);
Log.d(TAG, "refresh() isSpatialAudioOn : " + isSpatialAudioOn);
spatialAudioPref.setChecked(isSpatialAudioOn);
SwitchPreference headTrackingPref = mProfilesContainer.findPreference(KEY_HEAD_TRACKING);
if (headTrackingPref == null) {
headTrackingPref = createHeadTrackingPreference(mProfilesContainer.getContext());
mProfilesContainer.addPreference(headTrackingPref);
}
boolean isHeadTrackingAvailable =
isSpatialAudioOn && mSpatializer.hasHeadTracker(mAudioDevice);
Log.d(TAG, "refresh() has head tracker : " + mSpatializer.hasHeadTracker(mAudioDevice));
headTrackingPref.setVisible(isHeadTrackingAvailable);
if (isHeadTrackingAvailable) {
headTrackingPref.setChecked(mSpatializer.isHeadTrackerEnabled(mAudioDevice));
}
}
@VisibleForTesting
SwitchPreference createSpatialAudioPreference(Context context) {
SwitchPreference pref = new SwitchPreference(context);
pref.setKey(KEY_SPATIAL_AUDIO);
pref.setTitle(context.getString(R.string.bluetooth_details_spatial_audio_title));
pref.setSummary(context.getString(R.string.bluetooth_details_spatial_audio_summary));
pref.setOnPreferenceClickListener(this);
return pref;
}
@VisibleForTesting
SwitchPreference createHeadTrackingPreference(Context context) {
SwitchPreference pref = new SwitchPreference(context);
pref.setKey(KEY_HEAD_TRACKING);
pref.setTitle(context.getString(R.string.bluetooth_details_head_tracking_title));
pref.setSummary(context.getString(R.string.bluetooth_details_head_tracking_summary));
pref.setOnPreferenceClickListener(this);
return pref;
}
}

View File

@@ -187,6 +187,8 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment
lifecycle));
controllers.add(new BluetoothDetailsCompanionAppsController(context, this,
mCachedDevice, lifecycle));
controllers.add(new BluetoothDetailsSpatialAudioController(context, this, mCachedDevice,
lifecycle));
controllers.add(new BluetoothDetailsProfilesController(context, this, mManager,
mCachedDevice, lifecycle));
controllers.add(new BluetoothDetailsMacAddressController(context, this, mCachedDevice,

View File

@@ -31,6 +31,7 @@ import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.text.TextUtils;
import android.util.ArraySet;
import androidx.annotation.VisibleForTesting;
@@ -66,6 +67,8 @@ public class PlatformCompatDashboard extends DashboardFragment {
private AndroidBuildClassifier mAndroidBuildClassifier = new AndroidBuildClassifier();
private boolean mShouldStartAppPickerOnResume = true;
@VisibleForTesting
String mSelectedApp;
@@ -98,13 +101,67 @@ public class PlatformCompatDashboard extends DashboardFragment {
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
try {
mChanges = getPlatformCompat().listUIChanges();
} catch (RemoteException e) {
throw new RuntimeException("Could not list changes!", e);
}
if (icicle != null) {
mShouldStartAppPickerOnResume = false;
mSelectedApp = icicle.getString(COMPAT_APP);
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_COMPAT_CHANGE_APP) {
mShouldStartAppPickerOnResume = false;
switch (resultCode) {
case Activity.RESULT_OK:
mSelectedApp = data.getAction();
break;
case Activity.RESULT_CANCELED:
if (TextUtils.isEmpty(mSelectedApp)) {
finish();
}
break;
case AppPicker.RESULT_NO_MATCHING_APPS:
mSelectedApp = null;
break;
}
return;
}
super.onActivityResult(requestCode, resultCode, data);
}
@Override
public void onResume() {
super.onResume();
if (isFinishingOrDestroyed()) {
return;
}
if (!mShouldStartAppPickerOnResume) {
if (TextUtils.isEmpty(mSelectedApp)) {
new AlertDialog.Builder(getContext())
.setTitle(R.string.platform_compat_dialog_title_no_apps)
.setMessage(R.string.platform_compat_dialog_text_no_apps)
.setPositiveButton(R.string.okay, (dialog, which) -> finish())
.setOnDismissListener(dialog -> finish())
.setCancelable(false)
.show();
return;
}
try {
final ApplicationInfo applicationInfo = getApplicationInfo();
addPreferences(applicationInfo);
return;
} catch (PackageManager.NameNotFoundException e) {
mShouldStartAppPickerOnResume = true;
mSelectedApp = null;
}
}
startAppPicker();
}
@@ -114,31 +171,6 @@ public class PlatformCompatDashboard extends DashboardFragment {
outState.putString(COMPAT_APP, mSelectedApp);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_COMPAT_CHANGE_APP) {
if (resultCode == Activity.RESULT_OK) {
mSelectedApp = data.getAction();
try {
final ApplicationInfo applicationInfo = getApplicationInfo();
addPreferences(applicationInfo);
} catch (PackageManager.NameNotFoundException e) {
startAppPicker();
}
} else if (resultCode == AppPicker.RESULT_NO_MATCHING_APPS) {
new AlertDialog.Builder(getContext())
.setTitle(R.string.platform_compat_dialog_title_no_apps)
.setMessage(R.string.platform_compat_dialog_text_no_apps)
.setPositiveButton(R.string.okay, (dialog, which) -> finish())
.setOnDismissListener(dialog -> finish())
.setCancelable(false)
.show();
}
return;
}
super.onActivityResult(requestCode, resultCode, data);
}
private void addPreferences(ApplicationInfo applicationInfo) {
getPreferenceScreen().removeAll();
getPreferenceScreen().addPreference(createAppPreference(applicationInfo));

View File

@@ -65,6 +65,7 @@ public final class BiometricsSafetySource {
combinedBiometricStatusUtils.getSettingsClassName(), disablingAdmin,
Bundle.EMPTY),
disablingAdmin == null /* enabled */,
combinedBiometricStatusUtils.hasEnrolled(),
safetyEvent);
return;
}
@@ -82,6 +83,7 @@ public final class BiometricsSafetySource {
faceStatusUtils.getSettingsClassName(), disablingAdmin,
Bundle.EMPTY),
disablingAdmin == null /* enabled */,
faceStatusUtils.hasEnrolled(),
safetyEvent);
return;
@@ -101,6 +103,7 @@ public final class BiometricsSafetySource {
fingerprintStatusUtils.getSettingsClassName(), disablingAdmin,
Bundle.EMPTY),
disablingAdmin == null /* enabled */,
fingerprintStatusUtils.hasEnrolled(),
safetyEvent);
}
}
@@ -114,12 +117,14 @@ public final class BiometricsSafetySource {
}
private static void setBiometricSafetySourceData(Context context, String title, String summary,
Intent clickIntent, boolean enabled, SafetyEvent safetyEvent) {
Intent clickIntent, boolean enabled, boolean hasEnrolled, SafetyEvent safetyEvent) {
final PendingIntent pendingIntent = createPendingIntent(context, clickIntent);
final int statusLevel =
enabled && hasEnrolled ? SafetySourceStatus.STATUS_LEVEL_OK
: SafetySourceStatus.STATUS_LEVEL_NONE;
final SafetySourceStatus status = new SafetySourceStatus.Builder(title, summary,
SafetySourceStatus.STATUS_LEVEL_NONE, pendingIntent)
.setEnabled(enabled).build();
final SafetySourceStatus status = new SafetySourceStatus.Builder(
title, summary, statusLevel, pendingIntent).setEnabled(enabled).build();
final SafetySourceData safetySourceData =
new SafetySourceData.Builder().setStatus(status).build();

View File

@@ -41,6 +41,8 @@ public class WifiUtils extends com.android.settingslib.wifi.WifiUtils {
private static final int SSID_ASCII_MIN_LENGTH = 1;
private static final int SSID_ASCII_MAX_LENGTH = 32;
private static final int PSK_PASSPHRASE_ASCII_MIN_LENGTH = 8;
private static final int PSK_PASSPHRASE_ASCII_MAX_LENGTH = 63;
public static boolean isSSIDTooLong(String ssid) {
if (TextUtils.isEmpty(ssid)) {
@@ -62,6 +64,13 @@ public class WifiUtils extends com.android.settingslib.wifi.WifiUtils {
public static boolean isHotspotPasswordValid(String password, int securityType) {
final SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder();
try {
if (securityType == SoftApConfiguration.SECURITY_TYPE_WPA2_PSK
|| securityType == SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION) {
if (password.length() < PSK_PASSPHRASE_ASCII_MIN_LENGTH
|| password.length() > PSK_PASSPHRASE_ASCII_MAX_LENGTH) {
return false;
}
}
configBuilder.setPassphrase(password, securityType);
} catch (IllegalArgumentException e) {
return false;

View File

@@ -67,7 +67,7 @@ public class AccessibilityQuickSettingsTooltipWindowTest {
@Test
public void initTooltipView_atMostAvailableTextWidth() {
final String quickSettingsTooltipsContent = mContext.getString(
R.string.accessibility_service_qs_tooltips_content, TEST_PACKAGE_NAME);
R.string.accessibility_service_qs_tooltip_content, TEST_PACKAGE_NAME);
mTooltipView.setup(quickSettingsTooltipsContent, TEST_RES_ID);
final int getMaxWidth = mTooltipView.getAvailableWindowWidth();

View File

@@ -1,45 +0,0 @@
/*
* Copyright 2019 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.accessibility;
import static com.google.common.truth.Truth.assertThat;
import android.content.Intent;
import androidx.test.filters.SmallTest;
import com.android.settings.R;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
@RunWith(RobolectricTestRunner.class)
@SmallTest
public class AccessibilitySettingsForSetupWizardActivityTest {
@Test
public void createSetupAccessibilityActivity_shouldBeSUWTheme() {
final Intent intent = new Intent();
AccessibilitySettingsForSetupWizardActivity activity =
Robolectric.buildActivity(AccessibilitySettingsForSetupWizardActivity.class,
intent).get();
assertThat(activity.getThemeResId()).isEqualTo(R.style.GlifV3Theme_Light);
}
}

View File

@@ -20,6 +20,8 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.atLeast;
@@ -31,6 +33,7 @@ import static java.util.Collections.singletonList;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.accessibilityservice.AccessibilityShortcutInfo;
import android.app.AppOpsManager;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
@@ -110,6 +113,8 @@ public class AccessibilitySettingsTest {
@Mock
private PreferenceManager mPreferenceManager;
private ShadowAccessibilityManager mShadowAccessibilityManager;
@Mock
private AppOpsManager mAppOpsManager;
@Before
public void setup() {
@@ -121,6 +126,9 @@ public class AccessibilitySettingsTest {
when(mFragment.getPreferenceManager()).thenReturn(mPreferenceManager);
when(mFragment.getPreferenceManager().getContext()).thenReturn(mContext);
mContext.setTheme(R.style.Theme_AppCompat);
when(mContext.getSystemService(AppOpsManager.class)).thenReturn(mAppOpsManager);
when(mAppOpsManager.noteOpNoThrow(eq(AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS),
anyInt(), anyString())).thenReturn(AppOpsManager.MODE_ALLOWED);
}
@Test

View File

@@ -101,7 +101,7 @@ public class LaunchAccessibilityActivityPreferenceFragmentTest {
final CharSequence tileName =
mFragment.loadTileLabel(mContext, mFragment.getTileComponentName());
assertThat(tileTooltipContent.toString()).isEqualTo(
mContext.getString(R.string.accessibility_service_qs_tooltips_content, tileName));
mContext.getString(R.string.accessibility_service_qs_tooltip_content, tileName));
}
@Test
@@ -115,7 +115,7 @@ public class LaunchAccessibilityActivityPreferenceFragmentTest {
mFragment.loadTileLabel(mContext, mFragment.getTileComponentName());
assertThat(tileTooltipContent.toString()).isEqualTo(
mContext.getString(
R.string.accessibility_service_auto_added_qs_tooltips_content, tileName));
R.string.accessibility_service_auto_added_qs_tooltip_content, tileName));
}
@Test
@@ -130,7 +130,7 @@ public class LaunchAccessibilityActivityPreferenceFragmentTest {
final CharSequence tileName =
mFragment.loadTileLabel(mContext, mFragment.getTileComponentName());
assertThat(tileTooltipContent.toString()).isEqualTo(
mContext.getString(R.string.accessibility_service_qs_tooltips_content, tileName));
mContext.getString(R.string.accessibility_service_qs_tooltip_content, tileName));
}
@Test
@@ -146,7 +146,7 @@ public class LaunchAccessibilityActivityPreferenceFragmentTest {
mFragment.loadTileLabel(mContext, mFragment.getTileComponentName());
assertThat(tileTooltipContent.toString()).isEqualTo(
mContext.getString(
R.string.accessibility_service_auto_added_qs_tooltips_content, tileName));
R.string.accessibility_service_auto_added_qs_tooltip_content, tileName));
}
private void setupTileService(String packageName, String name, String tileName) {

View File

@@ -101,7 +101,7 @@ public class ToggleAccessibilityServicePreferenceFragmentTest {
final CharSequence tileName =
mFragment.loadTileLabel(mContext, mFragment.getTileComponentName());
assertThat(tileTooltipContent.toString()).isEqualTo(
mContext.getString(R.string.accessibility_service_qs_tooltips_content, tileName));
mContext.getString(R.string.accessibility_service_qs_tooltip_content, tileName));
}
@Test
@@ -115,7 +115,7 @@ public class ToggleAccessibilityServicePreferenceFragmentTest {
mFragment.loadTileLabel(mContext, mFragment.getTileComponentName());
assertThat(tileTooltipContent.toString()).isEqualTo(
mContext.getString(
R.string.accessibility_service_auto_added_qs_tooltips_content, tileName));
R.string.accessibility_service_auto_added_qs_tooltip_content, tileName));
}
@Test
@@ -130,7 +130,7 @@ public class ToggleAccessibilityServicePreferenceFragmentTest {
final CharSequence tileName =
mFragment.loadTileLabel(mContext, mFragment.getTileComponentName());
assertThat(tileTooltipContent.toString()).isEqualTo(
mContext.getString(R.string.accessibility_service_qs_tooltips_content, tileName));
mContext.getString(R.string.accessibility_service_qs_tooltip_content, tileName));
}
@Test
@@ -146,7 +146,7 @@ public class ToggleAccessibilityServicePreferenceFragmentTest {
mFragment.loadTileLabel(mContext, mFragment.getTileComponentName());
assertThat(tileTooltipContent.toString()).isEqualTo(
mContext.getString(
R.string.accessibility_service_auto_added_qs_tooltips_content, tileName));
R.string.accessibility_service_auto_added_qs_tooltip_content, tileName));
}
private void setupTileService(String packageName, String name, String tileName) {

View File

@@ -0,0 +1,206 @@
/*
* 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.bluetooth;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.media.AudioDeviceAttributes;
import android.media.AudioManager;
import android.media.Spatializer;
import androidx.preference.PreferenceCategory;
import androidx.preference.SwitchPreference;
import com.android.settingslib.core.lifecycle.Lifecycle;
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 java.util.ArrayList;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
public class BluetoothDetailsSpatialAudioControllerTest extends BluetoothDetailsControllerTestBase {
private static final String MAC_ADDRESS = "04:52:C7:0B:D8:3C";
private static final String KEY_SPATIAL_AUDIO = "spatial_audio";
private static final String KEY_HEAD_TRACKING = "head_tracking";
@Mock
private AudioManager mAudioManager;
@Mock
private Spatializer mSpatializer;
@Mock
private Lifecycle mSpatialAudioLifecycle;
@Mock
private PreferenceCategory mProfilesContainer;
private BluetoothDetailsSpatialAudioController mController;
private SwitchPreference mSpatialAudioPref;
private SwitchPreference mHeadTrackingPref;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
when(mContext.getSystemService(AudioManager.class)).thenReturn(mAudioManager);
when(mAudioManager.getSpatializer()).thenReturn(mSpatializer);
when(mCachedDevice.getAddress()).thenReturn(MAC_ADDRESS);
mController = new BluetoothDetailsSpatialAudioController(mContext, mFragment,
mCachedDevice, mSpatialAudioLifecycle);
mController.mProfilesContainer = mProfilesContainer;
mSpatialAudioPref = mController.createSpatialAudioPreference(mContext);
mHeadTrackingPref = mController.createHeadTrackingPreference(mContext);
when(mProfilesContainer.findPreference(KEY_SPATIAL_AUDIO)).thenReturn(mSpatialAudioPref);
when(mProfilesContainer.findPreference(KEY_HEAD_TRACKING)).thenReturn(mHeadTrackingPref);
}
@Test
public void isAvailable_spatialAudioIsAvailable_returnsTrue() {
when(mSpatializer.isAvailableForDevice(mController.mAudioDevice)).thenReturn(true);
assertThat(mController.isAvailable()).isTrue();
}
@Test
public void isAvailable_spatialAudioIsNotAvailable_returnsFalse() {
when(mSpatializer.isAvailableForDevice(mController.mAudioDevice)).thenReturn(false);
assertThat(mController.isAvailable()).isFalse();
}
@Test
public void refresh_spatialAudioIsTurnedOn_checksSpatialAudioPreference() {
List<AudioDeviceAttributes> compatibleAudioDevices = new ArrayList<>();
compatibleAudioDevices.add(mController.mAudioDevice);
when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices);
mController.refresh();
assertThat(mSpatialAudioPref.isChecked()).isTrue();
}
@Test
public void refresh_spatialAudioIsTurnedOff_unchecksSpatialAudioPreference() {
List<AudioDeviceAttributes> compatibleAudioDevices = new ArrayList<>();
when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices);
mController.refresh();
assertThat(mSpatialAudioPref.isChecked()).isFalse();
}
@Test
public void refresh_spatialAudioOnAndHeadTrackingIsAvailable_showsHeadTrackingPreference() {
List<AudioDeviceAttributes> compatibleAudioDevices = new ArrayList<>();
compatibleAudioDevices.add(mController.mAudioDevice);
when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices);
when(mSpatializer.hasHeadTracker(mController.mAudioDevice)).thenReturn(true);
mController.refresh();
assertThat(mHeadTrackingPref.isVisible()).isTrue();
}
@Test
public void
refresh_spatialAudioOnAndHeadTrackingIsNotAvailable_hidesHeadTrackingPreference() {
List<AudioDeviceAttributes> compatibleAudioDevices = new ArrayList<>();
compatibleAudioDevices.add(mController.mAudioDevice);
when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices);
when(mSpatializer.hasHeadTracker(mController.mAudioDevice)).thenReturn(false);
mController.refresh();
assertThat(mHeadTrackingPref.isVisible()).isFalse();
}
@Test
public void refresh_spatialAudioOff_hidesHeadTrackingPreference() {
List<AudioDeviceAttributes> compatibleAudioDevices = new ArrayList<>();
when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices);
mController.refresh();
assertThat(mHeadTrackingPref.isVisible()).isFalse();
}
@Test
public void refresh_headTrackingIsTurnedOn_checksHeadTrackingPreference() {
List<AudioDeviceAttributes> compatibleAudioDevices = new ArrayList<>();
compatibleAudioDevices.add(mController.mAudioDevice);
when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices);
when(mSpatializer.hasHeadTracker(mController.mAudioDevice)).thenReturn(true);
when(mSpatializer.isHeadTrackerEnabled(mController.mAudioDevice)).thenReturn(true);
mController.refresh();
assertThat(mHeadTrackingPref.isChecked()).isTrue();
}
@Test
public void refresh_headTrackingIsTurnedOff_unchecksHeadTrackingPreference() {
List<AudioDeviceAttributes> compatibleAudioDevices = new ArrayList<>();
compatibleAudioDevices.add(mController.mAudioDevice);
when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices);
when(mSpatializer.hasHeadTracker(mController.mAudioDevice)).thenReturn(true);
when(mSpatializer.isHeadTrackerEnabled(mController.mAudioDevice)).thenReturn(false);
mController.refresh();
assertThat(mHeadTrackingPref.isChecked()).isFalse();
}
@Test
public void turnedOnSpatialAudio_invokesAddCompatibleAudioDevice() {
mSpatialAudioPref.setChecked(true);
mController.onPreferenceClick(mSpatialAudioPref);
verify(mSpatializer).addCompatibleAudioDevice(mController.mAudioDevice);
}
@Test
public void turnedOffSpatialAudio_invokesRemoveCompatibleAudioDevice() {
mSpatialAudioPref.setChecked(false);
mController.onPreferenceClick(mSpatialAudioPref);
verify(mSpatializer).removeCompatibleAudioDevice(mController.mAudioDevice);
}
@Test
public void turnedOnHeadTracking_invokesSetHeadTrackerEnabled_setsTrue() {
mHeadTrackingPref.setChecked(true);
mController.onPreferenceClick(mHeadTrackingPref);
verify(mSpatializer).setHeadTrackerEnabled(true, mController.mAudioDevice);
}
@Test
public void turnedOffHeadTracking_invokesSetHeadTrackerEnabled_setsFalse() {
mHeadTrackingPref.setChecked(false);
mController.onPreferenceClick(mHeadTrackingPref);
verify(mSpatializer).setHeadTrackerEnabled(false, mController.mAudioDevice);
}
}

View File

@@ -18,12 +18,15 @@ package com.android.settings.applications.specialaccess.notificationaccess;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.AppOpsManager;
import android.app.NotificationManager;
import android.content.ComponentName;
import android.content.Context;
@@ -31,12 +34,12 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import androidx.preference.SwitchPreference;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settingslib.RestrictedSwitchPreference;
import org.junit.Before;
import org.junit.Test;
@@ -55,6 +58,8 @@ public class ApprovalPreferenceControllerTest {
@Mock
NotificationManager mNm;
@Mock
AppOpsManager mAppOpsManager;
@Mock
PackageManager mPm;
PackageInfo mPkgInfo;
ComponentName mCn = new ComponentName("a", "b");
@@ -75,15 +80,47 @@ public class ApprovalPreferenceControllerTest {
mController.setNm(mNm);
mController.setParent(mFragment);
mController.setPkgInfo(mPkgInfo);
}
@Test
public void updateState_checked() {
when(mAppOpsManager.noteOpNoThrow(anyInt(), anyInt(), anyString())).thenReturn(
AppOpsManager.MODE_ALLOWED);
when(mNm.isNotificationListenerAccessGranted(mCn)).thenReturn(true);
SwitchPreference pref = new SwitchPreference(mContext);
RestrictedSwitchPreference pref = new RestrictedSwitchPreference(
mContext);
pref.setAppOps(mAppOpsManager);
mController.updateState(pref);
assertThat(pref.isChecked()).isTrue();
assertThat(pref.isEnabled()).isTrue();
}
@Test
public void restrictedSettings_appOpsDisabled() {
when(mAppOpsManager.noteOpNoThrow(anyInt(), anyInt(), anyString())).thenReturn(
AppOpsManager.MODE_ERRORED);
when(mNm.isNotificationListenerAccessGranted(mCn)).thenReturn(false);
RestrictedSwitchPreference pref = new RestrictedSwitchPreference(
mContext);
pref.setAppOps(mAppOpsManager);
mController.updateState(pref);
assertThat(pref.isEnabled()).isFalse();
}
@Test
public void restrictedSettings_serviceAlreadyEnabled() {
when(mAppOpsManager.noteOpNoThrow(anyInt(), anyInt(), anyString())).thenReturn(
AppOpsManager.MODE_ERRORED);
when(mNm.isNotificationListenerAccessGranted(mCn)).thenReturn(true);
RestrictedSwitchPreference pref = new RestrictedSwitchPreference(
mContext);
pref.setAppOps(mAppOpsManager);
mController.updateState(pref);
assertThat(pref.isEnabled()).isTrue();
}
@Test

View File

@@ -57,8 +57,7 @@ public class CombinedBiometricStatusUtilsTest {
private static final ComponentName COMPONENT_NAME =
new ComponentName("package", "class");
private static final int USER_ID = UserHandle.myUserId();
private static final UserHandle USER_HANDLE = new UserHandle(USER_ID);;
private static final UserHandle USER_HANDLE = new UserHandle(USER_ID);
@Mock
private PackageManager mPackageManager;
@@ -122,6 +121,54 @@ public class CombinedBiometricStatusUtilsTest {
assertThat(mCombinedBiometricStatusUtils.isAvailable()).isTrue();
}
@Test
public void hasEnrolled_withoutFingerprintHardware_withoutFaceHardware_returnsFalse() {
when(mFingerprintManager.isHardwareDetected()).thenReturn(false);
when(mFaceManager.isHardwareDetected()).thenReturn(false);
assertThat(mCombinedBiometricStatusUtils.hasEnrolled()).isFalse();
}
@Test
public void hasEnrolled_withoutFingerprintEnroll_withoutFaceEnroll_returnsFalse() {
when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
when(mFaceManager.isHardwareDetected()).thenReturn(true);
when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(false);
when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(false);
assertThat(mCombinedBiometricStatusUtils.hasEnrolled()).isFalse();
}
@Test
public void hasEnrolled_withoutFingerprintEnroll_withFaceEnroll_returnsTrue() {
when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
when(mFaceManager.isHardwareDetected()).thenReturn(true);
when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(false);
when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
assertThat(mCombinedBiometricStatusUtils.hasEnrolled()).isTrue();
}
@Test
public void hasEnrolled_withFingerprintEnroll_withoutFaceEnroll_returnsTrue() {
when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
when(mFaceManager.isHardwareDetected()).thenReturn(true);
when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(true);
when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(false);
assertThat(mCombinedBiometricStatusUtils.hasEnrolled()).isTrue();
}
@Test
public void hasEnrolled_withFingerprintEnroll_withFaceEnroll_returnsTrue() {
when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
when(mFaceManager.isHardwareDetected()).thenReturn(true);
when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(true);
when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
assertThat(mCombinedBiometricStatusUtils.hasEnrolled()).isTrue();
}
@Test
public void getDisabledAdmin_whenFingerprintDisabled_whenFaceDisabled_returnsEnforcedAdmin() {
when(mDevicePolicyManager.getKeyguardDisabledFeatures(COMPONENT_NAME))

View File

@@ -114,6 +114,20 @@ public class FaceStatusUtilsTest {
assertThat(mFaceStatusUtils.isAvailable()).isFalse();
}
@Test
public void hasEnrolled_withEnrolledTemplates_returnsTrue() {
when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
assertThat(mFaceStatusUtils.hasEnrolled()).isTrue();
}
@Test
public void hasEnrolled_withoutEnrolledTemplates_returnsFalse() {
when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(false);
assertThat(mFaceStatusUtils.hasEnrolled()).isFalse();
}
@Test
public void getDisabledAdmin_whenFaceDisabled_returnsEnforcedAdmin() {
when(mDevicePolicyManager.getKeyguardDisabledFeatures(COMPONENT_NAME))

View File

@@ -118,6 +118,20 @@ public class FingerprintStatusUtilsTest {
assertThat(mFingerprintStatusUtils.isAvailable()).isFalse();
}
@Test
public void hasEnrolled_withEnrolledFingerprints_returnsTrue() {
when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(true);
assertThat(mFingerprintStatusUtils.hasEnrolled()).isTrue();
}
@Test
public void hasEnrolled_withoutEnrolledFingerprints_returnsFalse() {
when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(false);
assertThat(mFingerprintStatusUtils.hasEnrolled()).isFalse();
}
@Test
public void getDisabledAdmin_whenFingerprintDisabled_returnsEnforcedAdmin() {
when(mDevicePolicyManager.getKeyguardDisabledFeatures(COMPONENT_NAME))

View File

@@ -23,6 +23,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -112,8 +113,8 @@ public class BiometricsSafetySourceTest {
BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED);
verify(mSafetyCenterManagerWrapper, never()).setSafetySourceData(
any(), any(), any(), any());
verify(mSafetyCenterManagerWrapper, never())
.setSafetySourceData(any(), any(), any(), any());
}
@Test
@@ -124,8 +125,8 @@ public class BiometricsSafetySourceTest {
BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED);
verify(mSafetyCenterManagerWrapper, never()).setSafetySourceData(
any(), any(), any(), any());
verify(mSafetyCenterManagerWrapper, never())
.setSafetySourceData(any(), any(), any(), any());
}
@Test
@@ -137,11 +138,9 @@ public class BiometricsSafetySourceTest {
when(mDevicePolicyManager.getKeyguardDisabledFeatures(COMPONENT_NAME)).thenReturn(0);
BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED);
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
verify(mSafetyCenterManagerWrapper).setSafetySourceData(
any(), captor.capture(), any(), any());
assertThat(captor.getValue()).isEqualTo(BiometricsSafetySource.SAFETY_SOURCE_ID);
verify(mSafetyCenterManagerWrapper).setSafetySourceData(
any(), eq(BiometricsSafetySource.SAFETY_SOURCE_ID), any(), any());
}
@Test
@@ -153,11 +152,9 @@ public class BiometricsSafetySourceTest {
when(mDevicePolicyManager.getKeyguardDisabledFeatures(COMPONENT_NAME)).thenReturn(0);
BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED);
ArgumentCaptor<SafetyEvent> captor = ArgumentCaptor.forClass(SafetyEvent.class);
verify(mSafetyCenterManagerWrapper).setSafetySourceData(
any(), any(), any(), captor.capture());
assertThat(captor.getValue()).isEqualTo(EVENT_SOURCE_STATE_CHANGED);
verify(mSafetyCenterManagerWrapper)
.setSafetySourceData(any(), any(), any(), eq(EVENT_SOURCE_STATE_CHANGED));
}
@Test
@@ -429,6 +426,128 @@ public class BiometricsSafetySourceTest {
Settings.CombinedBiometricSettingsActivity.class.getName());
}
@Test
public void setSafetySourceData_faceAndFingerprint_whenFaceEnrolled_setsOkStatus() {
when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
when(mFaceManager.isHardwareDetected()).thenReturn(true);
when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(false);
BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED);
ArgumentCaptor<SafetySourceData> captor = ArgumentCaptor.forClass(SafetySourceData.class);
verify(mSafetyCenterManagerWrapper).setSafetySourceData(
any(), eq(BiometricsSafetySource.SAFETY_SOURCE_ID), captor.capture(), any());
SafetySourceStatus safetySourceStatus = captor.getValue().getStatus();
assertThat(safetySourceStatus.getStatusLevel())
.isEqualTo(SafetySourceStatus.STATUS_LEVEL_OK);
}
@Test
public void setSafetySourceData_faceAndFingerprint_whenFingerprintEnrolled_setsOkStatus() {
when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
when(mFaceManager.isHardwareDetected()).thenReturn(true);
when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(false);
when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(true);
BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED);
ArgumentCaptor<SafetySourceData> captor = ArgumentCaptor.forClass(SafetySourceData.class);
verify(mSafetyCenterManagerWrapper).setSafetySourceData(
any(), eq(BiometricsSafetySource.SAFETY_SOURCE_ID), captor.capture(), any());
SafetySourceStatus safetySourceStatus = captor.getValue().getStatus();
assertThat(safetySourceStatus.getStatusLevel())
.isEqualTo(SafetySourceStatus.STATUS_LEVEL_OK);
}
@Test
public void setSafetySourceData_faceAndFingerprint_whenNotEnrolled_setsNoneStatus() {
when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
when(mFaceManager.isHardwareDetected()).thenReturn(true);
when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(false);
when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(false);
BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED);
ArgumentCaptor<SafetySourceData> captor = ArgumentCaptor.forClass(SafetySourceData.class);
verify(mSafetyCenterManagerWrapper).setSafetySourceData(
any(), eq(BiometricsSafetySource.SAFETY_SOURCE_ID), captor.capture(), any());
SafetySourceStatus safetySourceStatus = captor.getValue().getStatus();
assertThat(safetySourceStatus.getStatusLevel())
.isEqualTo(SafetySourceStatus.STATUS_LEVEL_NONE);
}
@Test
public void setSafetySourceData_fingerprint_whenEnrolled_setsOKStatus() {
when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
when(mFaceManager.isHardwareDetected()).thenReturn(false);
when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(true);
BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED);
ArgumentCaptor<SafetySourceData> captor = ArgumentCaptor.forClass(SafetySourceData.class);
verify(mSafetyCenterManagerWrapper).setSafetySourceData(
any(), eq(BiometricsSafetySource.SAFETY_SOURCE_ID), captor.capture(), any());
SafetySourceStatus safetySourceStatus = captor.getValue().getStatus();
assertThat(safetySourceStatus.getStatusLevel())
.isEqualTo(SafetySourceStatus.STATUS_LEVEL_OK);
}
@Test
public void setSafetySourceData_fingerprint_whenNotEnrolled_setsNoneStatus() {
when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
when(mFaceManager.isHardwareDetected()).thenReturn(false);
when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(false);
BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED);
ArgumentCaptor<SafetySourceData> captor = ArgumentCaptor.forClass(SafetySourceData.class);
verify(mSafetyCenterManagerWrapper).setSafetySourceData(
any(), eq(BiometricsSafetySource.SAFETY_SOURCE_ID), captor.capture(), any());
SafetySourceStatus safetySourceStatus = captor.getValue().getStatus();
assertThat(safetySourceStatus.getStatusLevel())
.isEqualTo(SafetySourceStatus.STATUS_LEVEL_NONE);
}
@Test
public void setSafetySourceData_face_whenEnrolled_setsOKStatus() {
when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
when(mFingerprintManager.isHardwareDetected()).thenReturn(false);
when(mFaceManager.isHardwareDetected()).thenReturn(true);
when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED);
ArgumentCaptor<SafetySourceData> captor = ArgumentCaptor.forClass(SafetySourceData.class);
verify(mSafetyCenterManagerWrapper).setSafetySourceData(
any(), eq(BiometricsSafetySource.SAFETY_SOURCE_ID), captor.capture(), any());
SafetySourceStatus safetySourceStatus = captor.getValue().getStatus();
assertThat(safetySourceStatus.getStatusLevel())
.isEqualTo(SafetySourceStatus.STATUS_LEVEL_OK);
}
@Test
public void setSafetySourceData_face_whenNotEnrolled_setsNoneStatus() {
when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
when(mFingerprintManager.isHardwareDetected()).thenReturn(false);
when(mFaceManager.isHardwareDetected()).thenReturn(true);
when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(false);
BiometricsSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED);
ArgumentCaptor<SafetySourceData> captor = ArgumentCaptor.forClass(SafetySourceData.class);
verify(mSafetyCenterManagerWrapper).setSafetySourceData(
any(), eq(BiometricsSafetySource.SAFETY_SOURCE_ID), captor.capture(), any());
SafetySourceStatus safetySourceStatus = captor.getValue().getStatus();
assertThat(safetySourceStatus.getStatusLevel())
.isEqualTo(SafetySourceStatus.STATUS_LEVEL_NONE);
}
private void assertSafetySourceDisabledDataSetWithSingularSummary(String expectedTitleResName,
String expectedSummaryResName) {
assertSafetySourceDisabledDataSet(
@@ -478,13 +597,16 @@ public class BiometricsSafetySourceTest {
private void assertSafetySourceDisabledDataSet(String expectedTitle, String expectedSummary) {
ArgumentCaptor<SafetySourceData> captor = ArgumentCaptor.forClass(SafetySourceData.class);
verify(mSafetyCenterManagerWrapper).setSafetySourceData(
any(), any(), captor.capture(), any());
any(), eq(BiometricsSafetySource.SAFETY_SOURCE_ID), captor.capture(), any());
SafetySourceData safetySourceData = captor.getValue();
SafetySourceStatus safetySourceStatus = safetySourceData.getStatus();
assertThat(safetySourceStatus.getTitle().toString()).isEqualTo(expectedTitle);
assertThat(safetySourceStatus.getSummary().toString()).isEqualTo(expectedSummary);
assertThat(safetySourceStatus.isEnabled()).isFalse();
assertThat(safetySourceStatus.getStatusLevel())
.isEqualTo(SafetySourceStatus.STATUS_LEVEL_NONE);
final Intent clickIntent = safetySourceStatus.getPendingIntent().getIntent();
assertThat(clickIntent).isNotNull();
assertThat(clickIntent.getAction()).isEqualTo(ACTION_SHOW_ADMIN_SUPPORT_DETAILS);
@@ -494,7 +616,7 @@ public class BiometricsSafetySourceTest {
String expectedSettingsClassName) {
ArgumentCaptor<SafetySourceData> captor = ArgumentCaptor.forClass(SafetySourceData.class);
verify(mSafetyCenterManagerWrapper).setSafetySourceData(
any(), any(), captor.capture(), any());
any(), eq(BiometricsSafetySource.SAFETY_SOURCE_ID), captor.capture(), any());
SafetySourceData safetySourceData = captor.getValue();
SafetySourceStatus safetySourceStatus = safetySourceData.getStatus();
@@ -509,7 +631,6 @@ public class BiometricsSafetySourceTest {
.isEqualTo(expectedSettingsClassName);
}
private List<Fingerprint> createFingerprintList(int size) {
final List<Fingerprint> fingerprintList = new ArrayList<>(size);
for (int i = 0; i < size; i++) {