Snap for 11710546 from e24b145d48 to 24Q3-release

Change-Id: I7d3e8b929a2d437ebfc1d901e70ff144a69daef1
This commit is contained in:
Android Build Coastguard Worker
2024-04-13 01:21:37 +00:00
38 changed files with 793 additions and 249 deletions

View File

Before

Width:  |  Height:  |  Size: 95 B

After

Width:  |  Height:  |  Size: 95 B

View File

@@ -1339,9 +1339,9 @@
<!-- Label for button to retry creating private space again on creation error. [CHAR LIMIT=30] -->
<string name="private_space_tryagain_label">Try Again</string>
<!-- Title for private space lock setup screen. [CHAR LIMIT=90] -->
<string name="private_space_lockscreen_title">Use screen lock to unlock private space?</string>
<string name="private_space_lockscreen_title">Choose a new lock for private space?</string>
<!-- Summary for the private space lock setup screen. [CHAR LIMIT=NONE] -->
<string name="private_space_lockscreen_summary">You can unlock your private space the same way you unlock your device, or choose a different lock</string>
<string name="private_space_lockscreen_summary">You can set a new lock just for private space, or use the same lock you use to unlock your device</string>
<!-- Action label to use existing device lock for private space. [CHAR LIMIT=50] -->
<string name="private_space_use_screenlock_label">Use screen lock</string>
<!-- Label for private space lock setup button to choose a new lock. [CHAR LIMIT=50] -->
@@ -1826,11 +1826,11 @@
<!-- Bluetooth settings. Text displayed when Bluetooth is off and device list is empty [CHAR LIMIT=NONE]-->
<string name="bluetooth_empty_list_bluetooth_off">When Bluetooth is turned on, your device can communicate with other nearby Bluetooth devices</string>
<!-- Bluetooth settings. Text displayed when Bluetooth is off and device list is empty when auto-on feature is enabled [CHAR LIMIT=NONE]-->
<string name="bluetooth_empty_list_bluetooth_off_auto_on_available">When Bluetooth is on, your device can communicate with other nearby Bluetooth devices. Features like Quick Share, Find My Device, and device location use Bluetooth.</string>
<string name="bluetooth_empty_list_bluetooth_off_auto_on_available">When Bluetooth is on, your device can communicate with other nearby Bluetooth devices. Features like Quick Share and Find My Device use Bluetooth.</string>
<!-- Bluetooth settings. Text displayed when Bluetooth is off and bluetooth scanning is turned on [CHAR LIMIT=NONE] -->
<string name="bluetooth_scanning_on_info_message">When Bluetooth is turned on, your device can communicate with other nearby Bluetooth devices.\n\nTo improve device experience, apps and services can still scan for nearby devices at any time, even when Bluetooth is off. This can be used, for example, to improve location-based features and services. You can change this in Bluetooth scanning settings.</string>
<!-- Bluetooth settings. Text displayed when Bluetooth is off and bluetooth scanning is turned on [CHAR LIMIT=NONE] -->
<string name="bluetooth_scanning_on_info_message_auto_on_available">When Bluetooth is on, your device can communicate with other nearby Bluetooth devices. Features like Quick Share, Find My Device, and device location use Bluetooth.\n\nApps and services can still scan for nearby devices at any time, even when Bluetooth is off. This can be used, for example, to improve location-based features and services. You can change this in Bluetooth scanning settings.</string>
<string name="bluetooth_scanning_on_info_message_auto_on_available">When Bluetooth is on, your device can communicate with other nearby Bluetooth devices. Features like Quick Share and Find My Device use Bluetooth.\n\nApps and services can still scan for nearby devices at any time, even when Bluetooth is off. This can be used, for example, to improve location-based features and services. You can change this in Bluetooth scanning settings.</string>
<!-- Bluetooth settings. Link text to bring the user to "scanning settings" screen. [CHAR LIMIT=NONE]-->
<string name="bluetooth_scan_change">Change</string>

View File

@@ -16,7 +16,8 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:title="@string/configure_notification_settings">
android:title="@string/configure_notification_settings"
android:key="configure_notification_settings">
<PreferenceCategory
android:key="general_notifications_category"

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2021 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.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:title="@string/location_services_screen_title"
android:key="location_services_private_profile"
settings:controller="com.android.settings.location.LocationInjectedServicesForPrivateProfilePreferenceController">
</PreferenceScreen>

View File

@@ -126,6 +126,9 @@
<PreferenceCategory
android:key="ip_details_category"
android:title="@string/wifi_setup_detail">
<com.android.settings.spa.preference.ComposePreference
android:key="server_name"
settings:controller="com.android.settings.wifi.details2.ServerNamePreferenceController"/>
<Preference
android:key="type"
android:title="@string/wifi_type_title"

View File

@@ -30,7 +30,6 @@ import androidx.recyclerview.widget.RecyclerView;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.flags.Flags;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.search.SearchIndexable;
@@ -65,11 +64,7 @@ public class VibrationIntensitySettingsFragment extends DashboardFragment {
final int supportedIntensityLevels = context.getResources().getInteger(
R.integer.config_vibration_supported_intensity_levels);
final boolean hasVibrator = context.getSystemService(Vibrator.class).hasVibrator();
if (Flags.separateAccessibilityVibrationSettingsFragments()) {
return hasVibrator && supportedIntensityLevels > 1;
} else {
return false;
}
return hasVibrator && supportedIntensityLevels > 1;
}
@Override

View File

@@ -29,7 +29,6 @@ import androidx.preference.Preference;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.flags.Flags;
/** Controller for "Vibration & haptics" settings page. */
public class VibrationPreferenceController extends BasePreferenceController {
@@ -66,8 +65,7 @@ public class VibrationPreferenceController extends BasePreferenceController {
@Override
public boolean handlePreferenceTreeClick(Preference preference) {
if (Flags.separateAccessibilityVibrationSettingsFragments()
&& TextUtils.equals(preference.getKey(), getPreferenceKey())) {
if (TextUtils.equals(preference.getKey(), getPreferenceKey())) {
if (mContext.getResources().getInteger(
R.integer.config_vibration_supported_intensity_levels) > 1) {
launchVibrationSettingsFragment(VibrationIntensitySettingsFragment.class);

View File

@@ -18,44 +18,23 @@ package com.android.settings.accessibility;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.Vibrator;
import android.provider.SearchIndexableResource;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.VisibleForTesting;
import androidx.recyclerview.widget.RecyclerView;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.flags.Flags;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.search.SearchIndexable;
import java.util.ArrayList;
import java.util.List;
/** Accessibility settings for the vibration. */
/**
* Accessibility settings for the vibration.
*/
@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
public class VibrationSettings extends DashboardFragment {
private static final String TAG = "VibrationSettings";
private static int getVibrationXmlResourceId(Context context) {
if (Flags.separateAccessibilityVibrationSettingsFragments()) {
return R.xml.accessibility_vibration_settings;
}
final int supportedIntensities = context.getResources().getInteger(
R.integer.config_vibration_supported_intensity_levels);
return supportedIntensities > 1
? R.xml.accessibility_vibration_intensity_settings
: R.xml.accessibility_vibration_settings;
}
@Override
public int getMetricsCategory() {
return SettingsEnums.ACCESSIBILITY_VIBRATION;
@@ -68,7 +47,7 @@ public class VibrationSettings extends DashboardFragment {
@Override
protected int getPreferenceScreenResId() {
return getVibrationXmlResourceId(getContext());
return R.xml.accessibility_vibration_settings;
}
@Override
@@ -76,53 +55,19 @@ public class VibrationSettings extends DashboardFragment {
return TAG;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (Flags.separateAccessibilityVibrationSettingsFragments()) {
return super.onCreateView(inflater, container, savedInstanceState);
}
final View view = super.onCreateView(inflater, container, savedInstanceState);
final RecyclerView rv = getListView();
final Resources res = view.getResources();
final int supportedIntensities = res.getInteger(
R.integer.config_vibration_supported_intensity_levels);
if (rv != null && supportedIntensities > 1) {
final int bottom_padding = res.getDimensionPixelSize(
com.android.settingslib.widget.theme.R.dimen.settingslib_listPreferredItemPaddingEnd);
rv.setPaddingRelative(rv.getPaddingStart(), rv.getPaddingTop(), rv.getPaddingEnd(),
rv.getPaddingBottom() + bottom_padding);
}
return view;
}
@VisibleForTesting
static boolean isPageSearchEnabled(Context context) {
final int supportedIntensityLevels = context.getResources().getInteger(
R.integer.config_vibration_supported_intensity_levels);
final boolean hasVibrator = context.getSystemService(Vibrator.class).hasVibrator();
if (Flags.separateAccessibilityVibrationSettingsFragments()) {
return hasVibrator && supportedIntensityLevels == 1;
} else {
return hasVibrator;
}
return hasVibrator && supportedIntensityLevels == 1;
}
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
new BaseSearchIndexProvider(R.xml.accessibility_vibration_settings) {
@Override
protected boolean isPageSearchEnabled(Context context) {
return VibrationSettings.isPageSearchEnabled(context);
}
@Override
public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
boolean enabled) {
final List<SearchIndexableResource> resourceData = new ArrayList<>();
final SearchIndexableResource sir = new SearchIndexableResource(context);
sir.xmlResId = getVibrationXmlResourceId(context);
resourceData.add(sir);
return resourceData;
}
};
}

View File

@@ -41,8 +41,8 @@ import android.text.Html;
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.Nullable;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.preference.Preference;
@@ -125,12 +125,12 @@ public class DefaultCombinedPicker extends DefaultAppPickerFragment {
protected CharSequence getPositiveButtonText() {
final Bundle bundle = getArguments();
if (TextUtils.isEmpty(bundle.getString(EXTRA_KEY))) {
return getContext().getString(
R.string.credman_confirmation_turn_off_positive_button);
return getContext()
.getString(R.string.credman_confirmation_turn_off_positive_button);
}
return getContext().getString(
R.string.credman_confirmation_change_provider_positive_button);
return getContext()
.getString(R.string.credman_confirmation_change_provider_positive_button);
}
}
@@ -259,21 +259,21 @@ public class DefaultCombinedPicker extends DefaultAppPickerFragment {
return mCredentialManager;
}
private List<CombinedProviderInfo> getAllProviders() {
private List<CombinedProviderInfo> getAllProviders(int userId) {
final Context context = getContext();
final List<AutofillServiceInfo> autofillProviders =
AutofillServiceInfo.getAvailableServices(context, getUser());
AutofillServiceInfo.getAvailableServices(context, userId);
final CredentialManager service = getCredentialProviderService();
final List<CredentialProviderInfo> credManProviders = new ArrayList<>();
if (service != null) {
credManProviders.addAll(
service.getCredentialProviderServices(
getUser(),
userId,
CredentialManager.PROVIDER_FILTER_USER_PROVIDERS_INCLUDING_HIDDEN));
}
final String selectedAutofillProvider = getSelectedAutofillProvider(context, getUser());
final String selectedAutofillProvider = getSelectedAutofillProvider(context, userId);
return CombinedProviderInfo.buildMergedList(
autofillProviders, credManProviders, selectedAutofillProvider);
}
@@ -285,7 +285,8 @@ public class DefaultCombinedPicker extends DefaultAppPickerFragment {
protected List<DefaultAppInfo> getCandidates() {
final Context context = getContext();
final List<CombinedProviderInfo> allProviders = getAllProviders();
final int userId = getUser();
final List<CombinedProviderInfo> allProviders = getAllProviders(userId);
final List<DefaultAppInfo> candidates = new ArrayList<>();
for (CombinedProviderInfo cpi : allProviders) {
@@ -295,10 +296,10 @@ public class DefaultCombinedPicker extends DefaultAppPickerFragment {
if (brandingService != null) {
candidates.add(
new CredentialManagerDefaultAppInfo(
context, mPm, getUser(), brandingService, cpi));
context, mPm, userId, brandingService, cpi));
} else if (appInfo != null) {
candidates.add(
new CredentialManagerDefaultAppInfo(context, mPm, getUser(), appInfo, cpi));
new CredentialManagerDefaultAppInfo(context, mPm, userId, appInfo, cpi));
}
}
@@ -361,9 +362,23 @@ public class DefaultCombinedPicker extends DefaultAppPickerFragment {
@Override
protected String getDefaultKey() {
final CombinedProviderInfo topProvider =
CombinedProviderInfo.getTopProvider(getAllProviders());
return topProvider == null ? "" : topProvider.getApplicationInfo().packageName;
final int userId = getUser();
final @Nullable CombinedProviderInfo topProvider =
CombinedProviderInfo.getTopProvider(getAllProviders(userId));
if (topProvider != null) {
// Apply device admin restrictions to top provider.
if (topProvider.getDeviceAdminRestrictions(getContext(), userId) != null) {
return "";
}
ApplicationInfo appInfo = topProvider.getApplicationInfo();
if (appInfo != null) {
return appInfo.packageName;
}
}
return "";
}
@Override
@@ -392,7 +407,7 @@ public class DefaultCombinedPicker extends DefaultAppPickerFragment {
@Override
protected boolean setDefaultKey(String key) {
// Get the list of providers and see if any match the key (package name).
final List<CombinedProviderInfo> allProviders = getAllProviders();
final List<CombinedProviderInfo> allProviders = getAllProviders(getUser());
CombinedProviderInfo matchedProvider = null;
for (CombinedProviderInfo cpi : allProviders) {
if (cpi.getApplicationInfo().packageName.equals(key)) {

View File

@@ -92,12 +92,14 @@ public class DefaultCombinedPreferenceController extends DefaultAppPreferenceCon
@Override
public void updateState(@NonNull Preference preference) {
final CombinedProviderInfo topProvider = getTopProvider();
final int userId = getUser();
if (topProvider != null && mContext != null) {
updatePreferenceForProvider(
preference,
topProvider.getAppName(mContext),
topProvider.getSettingsSubtitle(),
topProvider.getAppIcon(mContext, getUser()),
topProvider.getAppIcon(mContext, userId),
topProvider.getPackageName(),
topProvider.getSettingsActivity());
} else {
@@ -149,7 +151,17 @@ public class DefaultCombinedPreferenceController extends DefaultAppPreferenceCon
}
private @Nullable CombinedProviderInfo getTopProvider() {
return CombinedProviderInfo.getTopProvider(getAllProviders(getUser()));
final int userId = getUser();
final @Nullable CombinedProviderInfo topProvider =
CombinedProviderInfo.getTopProvider(getAllProviders(userId));
// Apply device admin restrictions to top provider.
if (topProvider != null
&& topProvider.getDeviceAdminRestrictions(mContext, userId) != null) {
return null;
}
return topProvider;
}
@Override

View File

@@ -20,6 +20,7 @@ import androidx.fragment.app.Fragment;
import com.android.settings.R;
import com.android.settings.location.LocationServices;
import com.android.settings.location.LocationServicesForPrivateProfile;
import com.android.settings.location.LocationServicesForWork;
/**
@@ -34,7 +35,7 @@ public class ProfileSelectLocationServicesFragment extends ProfileSelectFragment
null /* bundle */,
LocationServices::new,
LocationServicesForWork::new,
LocationServices::new);
LocationServicesForPrivateProfile::new);
}
@Override

View File

@@ -22,6 +22,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.location.SettingInjectorService;
import android.os.UserHandle;
import android.util.ArraySet;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
@@ -32,6 +33,7 @@ import androidx.preference.PreferenceScreen;
import com.android.settings.Utils;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import java.util.List;
@@ -110,13 +112,28 @@ public abstract class LocationInjectedServiceBasePreferenceController
}
protected Map<Integer, List<Preference>> getLocationServices() {
ArraySet<UserHandle> userHandles = new ArraySet<>();
userHandles.add(UserHandle.of(UserHandle.myUserId()));
// If location access is locked down by device policy then we only show injected settings
// for the primary profile.
final int profileUserId = Utils.getManagedProfileId(mUserManager, UserHandle.myUserId());
final int managedProfileId = Utils.getManagedProfileId(mUserManager, UserHandle.myUserId());
if (managedProfileId != UserHandle.USER_NULL
&& mLocationEnabler.getShareLocationEnforcedAdmin(managedProfileId) == null) {
userHandles.add(UserHandle.of(managedProfileId));
}
if (android.os.Flags.allowPrivateProfile()
&& android.multiuser.Flags.enablePrivateSpaceFeatures()
&& android.multiuser.Flags.handleInterleavedSettingsForPrivateSpace()) {
final UserHandle privateProfile = Utils.getProfileOfType(mUserManager,
ProfileSelectFragment.ProfileType.PRIVATE);
if (privateProfile != null && mLocationEnabler
.getShareLocationEnforcedAdmin(privateProfile.getIdentifier()) == null) {
userHandles.add(privateProfile);
}
}
return mInjector.getInjectedSettings(mFragment.getPreferenceManager().getContext(),
(profileUserId != UserHandle.USER_NULL
&& mLocationEnabler.getShareLocationEnforcedAdmin(profileUserId) != null)
? UserHandle.myUserId() : UserHandle.USER_CURRENT);
userHandles);
}
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright (C) 2024 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.location;
import android.content.Context;
import android.os.UserHandle;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.Utils;
import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
import com.android.settings.widget.RestrictedAppPreference;
import java.util.List;
import java.util.Map;
/**
* Retrieve the Location Services used in private profile user.
*/
public class LocationInjectedServicesForPrivateProfilePreferenceController extends
LocationInjectedServiceBasePreferenceController {
public LocationInjectedServicesForPrivateProfilePreferenceController(
Context context, String key) {
super(context, key);
}
@Override
protected void injectLocationServices(PreferenceScreen screen) {
if (!android.os.Flags.allowPrivateProfile()
|| !android.multiuser.Flags.enablePrivateSpaceFeatures()
|| !android.multiuser.Flags.handleInterleavedSettingsForPrivateSpace()) {
return;
}
final UserHandle privateProfile = Utils.getProfileOfType(mUserManager,
ProfileSelectFragment.ProfileType.PRIVATE);
if (privateProfile == null) {
return;
}
final Map<Integer, List<Preference>> prefs = getLocationServices();
for (Map.Entry<Integer, List<Preference>> entry : prefs.entrySet()) {
for (Preference pref : entry.getValue()) {
if (pref instanceof RestrictedAppPreference) {
((RestrictedAppPreference) pref).checkRestrictionAndSetDisabled();
}
}
if (entry.getKey() == privateProfile.getIdentifier()) {
LocationSettings.addPreferencesSorted(entry.getValue(), screen);
}
}
}
}

View File

@@ -22,6 +22,7 @@ import android.os.UserHandle;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.Utils;
import com.android.settings.widget.RestrictedAppPreference;
import java.util.List;
@@ -40,6 +41,7 @@ public class LocationInjectedServicesForWorkPreferenceController extends
@Override
protected void injectLocationServices(PreferenceScreen screen) {
final int managedProfileId = Utils.getManagedProfileId(mUserManager, UserHandle.myUserId());
final Map<Integer, List<Preference>> prefs = getLocationServices();
for (Map.Entry<Integer, List<Preference>> entry : prefs.entrySet()) {
for (Preference pref : entry.getValue()) {
@@ -47,7 +49,7 @@ public class LocationInjectedServicesForWorkPreferenceController extends
((RestrictedAppPreference) pref).checkRestrictionAndSetDisabled();
}
}
if (entry.getKey() != UserHandle.myUserId()) {
if (entry.getKey() == managedProfileId) {
LocationSettings.addPreferencesSorted(entry.getValue(), screen);
}
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright (C) 2024 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.location;
import android.app.settings.SettingsEnums;
import android.content.Context;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
public class LocationServicesForPrivateProfile extends DashboardFragment {
private static final String TAG = "LocationServicesForPrivateProfile";
@Override
public int getMetricsCategory() {
return SettingsEnums.LOCATION_SERVICES_FOR_PRIVATE_PROFILE;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.location_services_private_profile;
}
@Override
protected String getLogTag() {
return TAG;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
use(LocationInjectedServicesForPrivateProfilePreferenceController.class).init(this);
}
}

View File

@@ -112,11 +112,10 @@ public class PrivateSpaceMaintainer {
registerBroadcastReceiver();
try {
//TODO(b/313926659): To check and handle failure of startProfile
mActivityManager.startProfile(mUserHandle);
} catch (IllegalArgumentException e) {
Log.e(TAG, "Unexpected that " + mUserHandle.getIdentifier() + " is not a profile");
if (!startProfile()) {
// TODO(b/333884792): Add test to mock when startProfile fails.
Log.e(TAG, "profile not started, created profile is deleted");
deletePrivateSpace();
return false;
}
@@ -314,6 +313,16 @@ public class PrivateSpaceMaintainer {
return false;
}
@GuardedBy("this")
private boolean startProfile() {
try {
return mActivityManager.startProfile(mUserHandle);
} catch (IllegalArgumentException e) {
Log.e(TAG, "Unexpected that " + mUserHandle.getIdentifier() + " is not a profile");
}
return false;
}
@GuardedBy("this")
private void resetPrivateSpaceSettings() {
setHidePrivateSpaceEntryPointSetting(HIDE_PRIVATE_SPACE_ENTRY_POINT_DISABLED_VAL);

View File

@@ -63,16 +63,16 @@ public class PrivateSpaceSetLockFragment extends InstrumentedFragment {
final FooterBarMixin mixin = rootView.getMixin(FooterBarMixin.class);
mixin.setPrimaryButton(
new FooterButton.Builder(getContext())
.setText(R.string.private_space_use_screenlock_label)
.setListener(onClickUse())
.setText(R.string.private_space_set_lock_label)
.setListener(onClickNewLock())
.setButtonType(FooterButton.ButtonType.NEXT)
.setTheme(com.google.android.setupdesign.R.style.SudGlifButton_Primary)
.build());
mixin.setSecondaryButton(
new FooterButton.Builder(getContext())
.setText(R.string.private_space_set_lock_label)
.setListener(onClickNewLock())
.setButtonType(FooterButton.ButtonType.NEXT)
.setText(R.string.private_space_use_screenlock_label)
.setListener(onClickUse())
.setButtonType(FooterButton.ButtonType.SKIP)
.setTheme(com.google.android.setupdesign.R.style.SudGlifButton_Secondary)
.build());
OnBackPressedCallback callback =

View File

@@ -56,6 +56,7 @@ import com.android.settings.wifi.WifiDialog2;
import com.android.settings.wifi.WifiUtils;
import com.android.settings.wifi.details2.AddDevicePreferenceController2;
import com.android.settings.wifi.details2.CertificateDetailsPreferenceController;
import com.android.settings.wifi.details2.ServerNamePreferenceController;
import com.android.settings.wifi.details2.WifiAutoConnectPreferenceController2;
import com.android.settings.wifi.details2.WifiDetailPreferenceController2;
import com.android.settings.wifi.details2.WifiMeteredPreferenceController2;
@@ -129,6 +130,8 @@ public class WifiNetworkDetailsFragment extends RestrictedDashboardFragment impl
.setWifiEntryKey(wifiEntryKey);
use(CertificateDetailsPreferenceController.class)
.setWifiEntry(mNetworkDetailsTracker.getWifiEntry());
use(ServerNamePreferenceController.class)
.setWifiEntry(mNetworkDetailsTracker.getWifiEntry());
}
@Override

View File

@@ -37,6 +37,9 @@ import com.android.settingslib.spa.widget.preference.Preference
import com.android.settingslib.spa.widget.preference.PreferenceModel
import com.android.wifi.flags.Flags
import com.android.wifitrackerlib.WifiEntry
import com.android.wifitrackerlib.WifiEntry.CertificateInfo.CERTIFICATE_VALIDATION_METHOD_USING_CERTIFICATE_PINNING
import com.android.wifitrackerlib.WifiEntry.CertificateInfo.CERTIFICATE_VALIDATION_METHOD_USING_INSTALLED_ROOTCA
import com.android.wifitrackerlib.WifiEntry.CertificateInfo.CERTIFICATE_VALIDATION_METHOD_USING_SYSTEM_CERTIFICATE
import java.security.KeyStore
import java.security.cert.X509Certificate
@@ -44,15 +47,13 @@ class CertificateDetailsPreferenceController(context: Context, preferenceKey: St
ComposePreferenceController(context, preferenceKey) {
private lateinit var wifiEntry: WifiEntry
lateinit var certificateAliases: String
lateinit var certX509: X509Certificate
fun setWifiEntry(entry: WifiEntry) {
wifiEntry = entry
}
override fun getAvailabilityStatus(): Int {
return if (Flags.androidVWifiApi() && getCertX509(wifiEntry)) AVAILABLE
return if (Flags.androidVWifiApi() && isCertificateDetailsAvailable(wifiEntry)) AVAILABLE
else CONDITIONALLY_UNAVAILABLE
}
@@ -64,26 +65,52 @@ class CertificateDetailsPreferenceController(context: Context, preferenceKey: St
@Composable
fun CertificateDetails() {
val context = LocalContext.current
val validationMethod = wifiEntry.certificateInfo!!.validationMethod
val certificateDetailsSummary = when (validationMethod) {
CERTIFICATE_VALIDATION_METHOD_USING_SYSTEM_CERTIFICATE ->
stringResource(R.string.wifi_certificate_summary_system)
CERTIFICATE_VALIDATION_METHOD_USING_INSTALLED_ROOTCA -> {
val aliasesSize = wifiEntry.certificateInfo?.caCertificateAliases?.size
if (aliasesSize == 1) stringResource(R.string.one_cacrt)
else
String.format(
stringResource(R.string.wifi_certificate_summary_Certificates),
aliasesSize
)
}
else -> stringResource(R.string.wifi_certificate_summary_pinning)
}
Preference(object : PreferenceModel {
override val title = stringResource(com.android.internal.R.string.ssl_certificate)
override val summary = { certificateAliases }
override val onClick: () -> Unit = { createCertificateDetailsDialog(context, certX509) }
override val summary = { certificateDetailsSummary }
override val onClick: () -> Unit = {
if (validationMethod == CERTIFICATE_VALIDATION_METHOD_USING_INSTALLED_ROOTCA)
getCertX509(wifiEntry)?.let {
createCertificateDetailsDialog(
context,
it
)
}
}
})
}
private fun getCertX509(wifiEntry: WifiEntry): Boolean {
certificateAliases =
wifiEntry.wifiConfiguration?.enterpriseConfig?.caCertificateAliases?.get(0)
?: return false
private fun getCertX509(wifiEntry: WifiEntry): X509Certificate? {
val certificateAliases =
wifiEntry.certificateInfo?.caCertificateAliases?.get(0)
?: return null
return try {
val keyStore = KeyStore.getInstance("AndroidKeyStore")
keyStore.load(AndroidKeyStoreLoadStoreParameter(KeyProperties.NAMESPACE_WIFI))
val cert = keyStore.getCertificate(certificateAliases)
certX509 = KeyChain.toCertificate(cert.encoded)
true
KeyChain.toCertificate(cert.encoded)
} catch (e: Exception) {
Log.e(TAG, "Failed to open Android Keystore.", e)
false
null
}
}
@@ -124,6 +151,15 @@ class CertificateDetailsPreferenceController(context: Context, preferenceKey: St
dialog.getButton(AlertDialog.BUTTON_NEGATIVE).setEnabled(false)
}
private fun isCertificateDetailsAvailable(wifiEntry: WifiEntry): Boolean {
val validationMethod = wifiEntry.certificateInfo?.validationMethod
return validationMethod in listOf(
CERTIFICATE_VALIDATION_METHOD_USING_SYSTEM_CERTIFICATE,
CERTIFICATE_VALIDATION_METHOD_USING_INSTALLED_ROOTCA,
CERTIFICATE_VALIDATION_METHOD_USING_CERTIFICATE_PINNING
)
}
companion object {
const val TAG = "CertificateDetailsPreferenceController"
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (C) 2024 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.wifi.details2
import android.content.Context
import android.util.Log
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import com.android.settings.R
import com.android.settings.spa.preference.ComposePreferenceController
import com.android.settingslib.spa.widget.preference.Preference
import com.android.settingslib.spa.widget.preference.PreferenceModel
import com.android.wifi.flags.Flags
import com.android.wifitrackerlib.WifiEntry
class ServerNamePreferenceController(context: Context, preferenceKey: String) :
ComposePreferenceController(context, preferenceKey) {
private lateinit var wifiEntry: WifiEntry
fun setWifiEntry(entry: WifiEntry) {
wifiEntry = entry
}
override fun getAvailabilityStatus(): Int {
return if (Flags.androidVWifiApi() && wifiEntry.certificateInfo?.domain != null) AVAILABLE
else CONDITIONALLY_UNAVAILABLE
}
@Composable
override fun Content() {
ServerName()
}
@Composable
fun ServerName() {
Preference(object : PreferenceModel {
override val title = stringResource(R.string.server_name_title)
override val summary = { wifiEntry.certificateInfo?.domain ?: "" }
})
}
}

View File

@@ -17,35 +17,27 @@
package com.android.settings.accessibility;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.res.Resources;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
import com.android.settings.flags.Flags;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
/** Tests for {@link VibrationIntensitySettingsFragment}. */
@RunWith(RobolectricTestRunner.class)
@RequiresFlagsEnabled(Flags.FLAG_SEPARATE_ACCESSIBILITY_VIBRATION_SETTINGS_FRAGMENTS)
public class VibrationIntensitySettingsFragmentTest {
@Rule
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
private Context mContext;
private Resources mResources;
private VibrationIntensitySettingsFragment mFragment;

View File

@@ -18,7 +18,9 @@ package com.android.settings.accessibility;
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
@@ -29,9 +31,6 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.res.Resources;
import android.os.Vibrator;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.provider.Settings;
import androidx.preference.Preference;
@@ -39,10 +38,8 @@ import androidx.preference.PreferenceScreen;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
import com.android.settings.flags.Flags;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -51,10 +48,6 @@ import org.robolectric.RobolectricTestRunner;
@RunWith(RobolectricTestRunner.class)
public class VibrationPreferenceControllerTest {
@Rule
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
private static final String PREFERENCE_KEY = "preference_key";
private static final int OFF = 0;
private static final int ON = 1;
@@ -130,7 +123,6 @@ public class VibrationPreferenceControllerTest {
}
@Test
@RequiresFlagsEnabled(Flags.FLAG_SEPARATE_ACCESSIBILITY_VIBRATION_SETTINGS_FRAGMENTS)
public void handlePreferenceTreeClick_oneIntensityLevel_opensVibrationSettings() {
when(mResources.getInteger(R.integer.config_vibration_supported_intensity_levels))
.thenReturn(1);
@@ -143,7 +135,6 @@ public class VibrationPreferenceControllerTest {
}
@Test
@RequiresFlagsEnabled(Flags.FLAG_SEPARATE_ACCESSIBILITY_VIBRATION_SETTINGS_FRAGMENTS)
public void handlePreferenceTreeClick_multipleIntensityLevels_opensVibrationIntensity() {
when(mResources.getInteger(R.integer.config_vibration_supported_intensity_levels))
.thenReturn(2);

View File

@@ -17,35 +17,26 @@
package com.android.settings.accessibility;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.res.Resources;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
import com.android.settings.flags.Flags;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
/** Tests for {@link VibrationSettings} fragment. */
@RunWith(RobolectricTestRunner.class)
@RequiresFlagsEnabled(Flags.FLAG_SEPARATE_ACCESSIBILITY_VIBRATION_SETTINGS_FRAGMENTS)
public class VibrationSettingsTest {
@Rule
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
private Context mContext;
private Resources mResources;
private VibrationSettings mFragment;

View File

@@ -17,6 +17,11 @@
package com.android.settings.biometrics.fingerprint2.fragment
import android.content.Context
import android.hardware.biometrics.ComponentInfoInternal
import android.hardware.biometrics.SensorLocationInternal
import android.hardware.biometrics.SensorProperties
import android.hardware.fingerprint.FingerprintSensorProperties
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
import android.os.Bundle
import androidx.fragment.app.testing.FragmentScenario
import androidx.fragment.app.testing.launchFragmentInContainer
@@ -47,6 +52,7 @@ import com.android.settings.testutils2.FakeFingerprintManagerInteractor
import com.android.systemui.biometrics.shared.model.FingerprintSensor
import com.android.systemui.biometrics.shared.model.FingerprintSensorType
import com.android.systemui.biometrics.shared.model.SensorStrength
import com.android.systemui.biometrics.shared.model.toFingerprintSensor
import com.google.android.setupdesign.GlifLayout
import com.google.android.setupdesign.template.RequireScrollMixin
import kotlinx.coroutines.test.StandardTestDispatcher
@@ -67,7 +73,17 @@ class FingerprintEnrollIntroFragmentTest {
private val backgroundDispatcher = StandardTestDispatcher()
private lateinit var fragmentScenario: FragmentScenario<FingerprintEnrollIntroV2Fragment>
private val fingerprintSensor =
FingerprintSensor(1, SensorStrength.STRONG, 5, FingerprintSensorType.POWER_BUTTON)
FingerprintSensorPropertiesInternal(
0 /* sensorId */,
SensorProperties.STRENGTH_STRONG,
5 /* maxEnrollmentsPerUser */,
listOf<ComponentInfoInternal>(),
FingerprintSensorProperties.TYPE_POWER_BUTTON,
false /* halControlsIllumination */,
true /* resetLockoutRequiresHardwareAuthToken */,
listOf<SensorLocationInternal>(SensorLocationInternal.DEFAULT),
)
.toFingerprintSensor()
var enrollFlow = Default
val flowViewModel = FingerprintFlowViewModel(enrollFlow)

View File

@@ -538,7 +538,7 @@ public class BatteryInfoTest {
createIntentForGetBatteryInfoTest(
ChargingType.WIRED, ChargingSpeed.FAST, /* batteryLevel= */ 56);
var expectedStatusLabel = "Fast charging";
var expectedRemainingLabel = "Full by 1:30PM";
var expectedRemainingLabel = "Full by ";
var expectedChargeLabel = "56% - " + expectedStatusLabel + " - " + expectedRemainingLabel;
var currentTimeMillis = Instant.parse("2024-04-01T13:00:00Z").toEpochMilli();
@@ -559,7 +559,7 @@ public class BatteryInfoTest {
createIntentForGetBatteryInfoTest(
ChargingType.WIRED, ChargingSpeed.REGULAR, /* batteryLevel= */ 12);
var expectedStatusLabel = "Charging";
var expectedRemainingLabel = "Fully charged by 2:00PM";
var expectedRemainingLabel = "Fully charged by ";
var expectedChargeLabel = "12% - " + expectedRemainingLabel;
var currentTimeMillis = Instant.parse("2024-04-01T13:00:00Z").toEpochMilli();
@@ -580,7 +580,7 @@ public class BatteryInfoTest {
createIntentForGetBatteryInfoTest(
ChargingType.WIRED, ChargingSpeed.SLOW, /* batteryLevel= */ 18);
var expectedStatusLabel = "Charging";
var expectedRemainingLabel = "Fully charged by 3:00PM";
var expectedRemainingLabel = "Fully charged by";
var expectedChargeLabel = "18% - " + expectedRemainingLabel;
var currentTimeMillis = Instant.parse("2024-04-01T13:00:00Z").toEpochMilli();
@@ -601,7 +601,7 @@ public class BatteryInfoTest {
createIntentForGetBatteryInfoTest(
ChargingType.WIRELESS, ChargingSpeed.REGULAR, /* batteryLevel= */ 45);
var expectedStatusLabel = "Charging";
var expectedRemainingLabel = "Fully charged by 4:00PM";
var expectedRemainingLabel = "Fully charged by";
var expectedChargeLabel = "45% - " + expectedRemainingLabel;
var currentTimeMillis = Instant.parse("2024-04-01T15:00:00Z").toEpochMilli();
@@ -622,7 +622,7 @@ public class BatteryInfoTest {
createIntentForGetBatteryInfoTest(
ChargingType.DOCKED, ChargingSpeed.REGULAR, /* batteryLevel= */ 66);
var expectedStatusLabel = "Charging";
var expectedRemainingLabel = "Fully charged by 2:00PM";
var expectedRemainingLabel = "Fully charged by";
var expectedChargeLabel = "66% - " + expectedRemainingLabel;
var currentTimeMillis = Instant.parse("2021-02-09T13:00:00.00Z").toEpochMilli();
@@ -693,10 +693,10 @@ public class BatteryInfoTest {
.isEqualTo(expectedStatusLabel);
assertWithMessage("remainingLabel is incorrect")
.that(info.remainingLabel.toString())
.isEqualTo(expectedRemainingLabel);
.contains(expectedRemainingLabel);
assertWithMessage("chargeLabel is incorrect")
.that(info.chargeLabel.toString())
.isEqualTo(expectedChargeLabel);
.contains(expectedChargeLabel);
}
private static Intent createBatteryIntent(int plugged, int level, int status) {

View File

@@ -31,8 +31,10 @@ import android.content.Context;
import android.content.pm.UserInfo;
import android.os.UserHandle;
import android.os.UserManager;
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings;
import android.util.ArrayMap;
import android.util.ArraySet;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.Preference;
@@ -50,6 +52,7 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
@@ -65,6 +68,8 @@ import java.util.Map;
public class LocationInjectedServicesPreferenceControllerTest {
@Rule
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
private static final String KEY_LOCATION_SERVICES = "location_service";
@@ -140,8 +145,13 @@ public class LocationInjectedServicesPreferenceControllerTest {
when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()).thenReturn(componentName);
mController.displayPreference(mScreen);
ArgumentCaptor<ArraySet<UserHandle>> profilesArgumentCaptor =
ArgumentCaptor.forClass(ArraySet.class);
verify(mSettingsInjector).getInjectedSettings(
any(Context.class), eq(UserHandle.myUserId()));
any(Context.class), profilesArgumentCaptor.capture());
assertThat(profilesArgumentCaptor.getValue())
.doesNotContain(UserHandle.of(fakeWorkProfileId));
}
@Test
@@ -149,6 +159,9 @@ public class LocationInjectedServicesPreferenceControllerTest {
final int fakeWorkProfileId = 123;
ShadowUserManager.getShadow().setProfileIdsWithDisabled(
new int[]{UserHandle.myUserId(), fakeWorkProfileId});
ShadowUserManager.getShadow().addProfile(new UserInfo(UserHandle.myUserId(), "", 0));
ShadowUserManager.getShadow().addProfile(new UserInfo(fakeWorkProfileId, "",
UserInfo.FLAG_MANAGED_PROFILE | UserInfo.FLAG_PROFILE));
// Mock RestrictedLockUtils.checkIfRestrictionEnforced and let it return null.
// Empty enforcing users.
@@ -159,8 +172,77 @@ public class LocationInjectedServicesPreferenceControllerTest {
enforcingUsers);
mController.displayPreference(mScreen);
ArgumentCaptor<ArraySet<UserHandle>> profilesArgumentCaptor =
ArgumentCaptor.forClass(ArraySet.class);
verify(mSettingsInjector).getInjectedSettings(
any(Context.class), eq(UserHandle.USER_CURRENT));
any(Context.class), profilesArgumentCaptor.capture());
assertThat(profilesArgumentCaptor.getValue()).contains(UserHandle.of(fakeWorkProfileId));
}
@Test
public void privateProfileDisallowShareLocationOn_getParentUserLocationServicesOnly() {
mSetFlagsRule.enableFlags(
android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES,
android.multiuser.Flags.FLAG_HANDLE_INTERLEAVED_SETTINGS_FOR_PRIVATE_SPACE);
final int fakePrivateProfileId = 123;
ShadowUserManager.getShadow().setProfileIdsWithDisabled(
new int[]{UserHandle.myUserId(), fakePrivateProfileId});
ShadowUserManager.getShadow().addProfile(new UserInfo(UserHandle.myUserId(), "", 0));
ShadowUserManager.getShadow().setPrivateProfile(fakePrivateProfileId, "private", 0);
ShadowUserManager.getShadow().addUserProfile(UserHandle.of(fakePrivateProfileId));
// Mock RestrictedLockUtils.checkIfRestrictionEnforced and let it return non-null.
final List<UserManager.EnforcingUser> enforcingUsers = new ArrayList<>();
enforcingUsers.add(new UserManager.EnforcingUser(fakePrivateProfileId,
UserManager.RESTRICTION_SOURCE_DEVICE_OWNER));
final ComponentName componentName = new ComponentName("test", "test");
// Ensure that RestrictedLockUtils.checkIfRestrictionEnforced doesn't return null.
ShadowUserManager.getShadow().setUserRestrictionSources(
UserManager.DISALLOW_SHARE_LOCATION,
UserHandle.of(fakePrivateProfileId),
enforcingUsers);
when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()).thenReturn(componentName);
mController.displayPreference(mScreen);
ArgumentCaptor<ArraySet<UserHandle>> profilesArgumentCaptor =
ArgumentCaptor.forClass(ArraySet.class);
verify(mSettingsInjector).getInjectedSettings(
any(Context.class), profilesArgumentCaptor.capture());
assertThat(profilesArgumentCaptor.getValue())
.doesNotContain(UserHandle.of(fakePrivateProfileId));
}
@Test
public void privateProfileDisallowShareLocationOff_getAllUserLocationServices() {
mSetFlagsRule.enableFlags(
android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE,
android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES,
android.multiuser.Flags.FLAG_HANDLE_INTERLEAVED_SETTINGS_FOR_PRIVATE_SPACE);
final int fakePrivateProfileId = 123;
ShadowUserManager.getShadow().setProfileIdsWithDisabled(
new int[]{UserHandle.myUserId(), fakePrivateProfileId});
ShadowUserManager.getShadow().addProfile(new UserInfo(UserHandle.myUserId(), "", 0));
ShadowUserManager.getShadow().setPrivateProfile(fakePrivateProfileId, "private", 0);
ShadowUserManager.getShadow().addUserProfile(UserHandle.of(fakePrivateProfileId));
// Mock RestrictedLockUtils.checkIfRestrictionEnforced and let it return null.
// Empty enforcing users.
final List<UserManager.EnforcingUser> enforcingUsers = new ArrayList<>();
ShadowUserManager.getShadow().setUserRestrictionSources(
UserManager.DISALLOW_SHARE_LOCATION,
UserHandle.of(fakePrivateProfileId),
enforcingUsers);
mController.displayPreference(mScreen);
ArgumentCaptor<ArraySet<UserHandle>> profilesArgumentCaptor =
ArgumentCaptor.forClass(ArraySet.class);
verify(mSettingsInjector).getInjectedSettings(
any(Context.class), profilesArgumentCaptor.capture());
assertThat(profilesArgumentCaptor.getValue()).contains(UserHandle.of(fakePrivateProfileId));
}
@Test
@@ -180,7 +262,7 @@ public class LocationInjectedServicesPreferenceControllerTest {
final Map<Integer, List<Preference>> map = new ArrayMap<>();
map.put(UserHandle.myUserId(), preferences);
doReturn(map).when(mSettingsInjector)
.getInjectedSettings(any(Context.class), anyInt());
.getInjectedSettings(any(Context.class), any(ArraySet.class));
ShadowUserManager.getShadow().setProfileIdsWithDisabled(new int[]{UserHandle.myUserId()});
final int userId = UserHandle.myUserId();

View File

@@ -16,6 +16,11 @@
package com.android.settings.tests.screenshot.biometrics.fingerprint
import android.content.res.Configuration
import android.hardware.biometrics.ComponentInfoInternal
import android.hardware.biometrics.SensorLocationInternal
import android.hardware.biometrics.SensorProperties
import android.hardware.fingerprint.FingerprintSensorProperties
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
import android.view.Surface
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
@@ -39,9 +44,7 @@ import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.Fing
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintScrollViewModel
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.GatekeeperInfo
import com.android.settings.testutils2.FakeFingerprintManagerInteractor
import com.android.systemui.biometrics.shared.model.FingerprintSensor
import com.android.systemui.biometrics.shared.model.FingerprintSensorType
import com.android.systemui.biometrics.shared.model.SensorStrength
import com.android.systemui.biometrics.shared.model.toFingerprintSensor
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
@@ -56,7 +59,19 @@ import platform.test.screenshot.matchers.PixelPerfectMatcher
class Injector(step: FingerprintNavigationStep.UiStep) {
var enrollFlow = Default
var fingerprintSensor = FingerprintSensor(1, SensorStrength.STRONG, 5, FingerprintSensorType.REAR)
var fingerprintSensor =
FingerprintSensorPropertiesInternal(
0 /* sensorId */,
SensorProperties.STRENGTH_STRONG,
5 /* maxEnrollmentsPerUser */,
listOf<ComponentInfoInternal>(),
FingerprintSensorProperties.TYPE_REAR,
false /* halControlsIllumination */,
true /* resetLockoutRequiresHardwareAuthToken */,
listOf<SensorLocationInternal>(SensorLocationInternal.DEFAULT),
)
.toFingerprintSensor()
var accessibilityInteractor =
object : AccessibilityInteractor {
override val isAccessibilityEnabled: Flow<Boolean> = flowOf(true)

View File

@@ -16,6 +16,11 @@
package com.android.settings.testutils2
import android.hardware.biometrics.ComponentInfoInternal
import android.hardware.biometrics.SensorLocationInternal
import android.hardware.biometrics.SensorProperties
import android.hardware.fingerprint.FingerprintSensorProperties
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
import com.android.settings.biometrics.fingerprint2.lib.model.EnrollReason
import com.android.settings.biometrics.fingerprint2.lib.model.FingerEnrollState
@@ -23,7 +28,7 @@ import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintAuthAtt
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintData
import com.android.systemui.biometrics.shared.model.FingerprintSensor
import com.android.systemui.biometrics.shared.model.FingerprintSensorType
import com.android.systemui.biometrics.shared.model.SensorStrength
import com.android.systemui.biometrics.shared.model.toFingerprintSensor
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOf
@@ -35,16 +40,20 @@ class FakeFingerprintManagerInteractor : FingerprintManagerInteractor {
var enrolledFingerprintsInternal: MutableList<FingerprintData> = mutableListOf()
var challengeToGenerate: Pair<Long, ByteArray> = Pair(-1L, byteArrayOf())
var authenticateAttempt = FingerprintAuthAttemptModel.Success(1)
var enrollStateViewModel: List<FingerEnrollState> =
listOf(FingerEnrollState.EnrollProgress(5, 5))
var enrollStateViewModel: List<FingerEnrollState> = listOf(FingerEnrollState.EnrollProgress(5, 5))
var sensorProp =
FingerprintSensor(
0 /* sensorId */,
SensorStrength.STRONG,
5,
FingerprintSensorType.POWER_BUTTON
)
FingerprintSensorPropertiesInternal(
0 /* sensorId */,
SensorProperties.STRENGTH_STRONG,
5 /* maxEnrollmentsPerUser */,
listOf<ComponentInfoInternal>(),
FingerprintSensorProperties.TYPE_POWER_BUTTON,
false /* halControlsIllumination */,
true /* resetLockoutRequiresHardwareAuthToken */,
listOf<SensorLocationInternal>(SensorLocationInternal.DEFAULT),
)
.toFingerprintSensor()
override suspend fun authenticate(): FingerprintAuthAttemptModel {
return authenticateAttempt
@@ -68,7 +77,7 @@ class FakeFingerprintManagerInteractor : FingerprintManagerInteractor {
override suspend fun enroll(
hardwareAuthToken: ByteArray?,
enrollReason: EnrollReason
enrollReason: EnrollReason,
): Flow<FingerEnrollState> = flowOf(*enrollStateViewModel.toTypedArray())
override suspend fun removeFingerprint(fp: FingerprintData): Boolean {
@@ -84,5 +93,4 @@ class FakeFingerprintManagerInteractor : FingerprintManagerInteractor {
override suspend fun hasSideFps(): Boolean {
return sensorProp.sensorType == FingerprintSensorType.POWER_BUTTON
}
}

View File

@@ -17,6 +17,7 @@
package com.android.settings.wifi.details2
import android.content.Context
import android.platform.test.annotations.RequiresFlagsEnabled
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.test.assertIsDisplayed
@@ -24,13 +25,15 @@ import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import java.security.cert.X509Certificate
import com.android.settings.R
import com.android.wifitrackerlib.WifiEntry
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.any
import org.mockito.kotlin.doNothing
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.spy
import org.mockito.kotlin.whenever
@@ -40,21 +43,26 @@ class CertificateDetailsPreferenceControllerTest {
@get:Rule
val composeTestRule = createComposeRule()
private val mockCertX509 = mock<X509Certificate> {}
private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
doNothing().whenever(mock).startActivity(any())
}
private val controller = CertificateDetailsPreferenceController(context, TEST_KEY)
private val mockCertificateInfo = mock<WifiEntry.CertificateInfo> {
it.validationMethod =
WifiEntry.CertificateInfo.CERTIFICATE_VALIDATION_METHOD_USING_INSTALLED_ROOTCA
it.caCertificateAliases = arrayOf(MOCK_CA)
}
private val mockWifiEntry =
mock<WifiEntry> { on { certificateInfo } doReturn mockCertificateInfo }
@Before
fun setUp() {
controller.certificateAliases = MOCK_CA
controller.certX509 = mockCertX509
controller.setWifiEntry(mockWifiEntry)
}
@Test
@RequiresFlagsEnabled(com.android.wifi.flags.Flags.FLAG_ANDROID_V_WIFI_API)
fun title_isDisplayed() {
composeTestRule.setContent {
CompositionLocalProvider(LocalContext provides context) {
@@ -62,8 +70,21 @@ class CertificateDetailsPreferenceControllerTest {
}
}
composeTestRule.onNodeWithText(context.getString(com.android.internal.R.string.ssl_certificate))
.assertIsDisplayed()
composeTestRule.onNodeWithText(
context.getString(com.android.internal.R.string.ssl_certificate)
).assertIsDisplayed()
}
@Test
@RequiresFlagsEnabled(com.android.wifi.flags.Flags.FLAG_ANDROID_V_WIFI_API)
fun one_caCertificate_summary() {
composeTestRule.setContent {
CompositionLocalProvider(LocalContext provides context) {
controller.Content()
}
}
composeTestRule.onNodeWithText(context.getString(R.string.one_cacrt)).assertIsDisplayed()
}
private companion object {

View File

@@ -0,0 +1,92 @@
/*
* Copyright (C) 2024 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.wifi.details2
import android.content.Context
import android.platform.test.annotations.RequiresFlagsEnabled
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.R
import com.android.wifitrackerlib.WifiEntry
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.any
import org.mockito.kotlin.doNothing
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.spy
import org.mockito.kotlin.whenever
@RunWith(AndroidJUnit4::class)
class ServerNamePreferenceControllerTest {
@get:Rule
val composeTestRule = createComposeRule()
private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
doNothing().whenever(mock).startActivity(any())
}
private val controller = ServerNamePreferenceController(context, TEST_KEY)
private val mockCertificateInfo = mock<WifiEntry.CertificateInfo> {
it.domain = DOMAIN
}
private val mockWifiEntry =
mock<WifiEntry> { on { certificateInfo } doReturn mockCertificateInfo }
@Before
fun setUp() {
controller.setWifiEntry(mockWifiEntry)
}
@Test
@RequiresFlagsEnabled(com.android.wifi.flags.Flags.FLAG_ANDROID_V_WIFI_API)
fun title_isDisplayed() {
composeTestRule.setContent {
CompositionLocalProvider(LocalContext provides context) {
controller.Content()
}
}
composeTestRule.onNodeWithText(context.getString(R.string.server_name_title))
.assertIsDisplayed()
}
@Test
@RequiresFlagsEnabled(com.android.wifi.flags.Flags.FLAG_ANDROID_V_WIFI_API)
fun summary_isDisplayed() {
composeTestRule.setContent {
CompositionLocalProvider(LocalContext provides context) {
controller.Content()
}
}
composeTestRule.onNodeWithText(DOMAIN).assertIsDisplayed()
}
private companion object {
const val TEST_KEY = "test_key"
const val DOMAIN = "domain"
}
}

View File

@@ -18,18 +18,23 @@ package com.android.settings.fingerprint2.domain.interactor
import android.content.Context
import android.content.Intent
import android.hardware.biometrics.ComponentInfoInternal
import android.hardware.biometrics.SensorLocationInternal
import android.hardware.biometrics.SensorProperties
import android.hardware.fingerprint.Fingerprint
import android.hardware.fingerprint.FingerprintEnrollOptions
import android.hardware.fingerprint.FingerprintManager
import android.hardware.fingerprint.FingerprintManager.CryptoObject
import android.hardware.fingerprint.FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT
import android.hardware.fingerprint.FingerprintSensorProperties
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
import android.os.CancellationSignal
import android.os.Handler
import androidx.test.core.app.ApplicationProvider
import com.android.settings.biometrics.GatekeeperPasswordProvider
import com.android.settings.biometrics.fingerprint2.data.repository.FingerprintSensorRepository
import com.android.settings.biometrics.fingerprint2.domain.interactor.PressToAuthInteractor
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintManagerInteractorImpl
import com.android.settings.biometrics.fingerprint2.domain.interactor.PressToAuthInteractor
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
import com.android.settings.biometrics.fingerprint2.lib.model.Default
import com.android.settings.biometrics.fingerprint2.lib.model.EnrollReason
@@ -38,8 +43,7 @@ import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintAuthAtt
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintData
import com.android.settings.password.ChooseLockSettingsHelper
import com.android.systemui.biometrics.shared.model.FingerprintSensor
import com.android.systemui.biometrics.shared.model.FingerprintSensorType
import com.android.systemui.biometrics.shared.model.SensorStrength
import com.android.systemui.biometrics.shared.model.toFingerprintSensor
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.cancelAndJoin
import kotlinx.coroutines.flow.Flow
@@ -85,7 +89,18 @@ class FingerprintManagerInteractorTest {
@Before
fun setup() {
val sensor = FingerprintSensor(1, SensorStrength.STRONG, 5, FingerprintSensorType.POWER_BUTTON)
val sensor =
FingerprintSensorPropertiesInternal(
0 /* sensorId */,
SensorProperties.STRENGTH_STRONG,
5 /* maxEnrollmentsPerUser */,
listOf<ComponentInfoInternal>(),
FingerprintSensorProperties.TYPE_POWER_BUTTON,
false /* halControlsIllumination */,
true /* resetLockoutRequiresHardwareAuthToken */,
listOf<SensorLocationInternal>(SensorLocationInternal.DEFAULT),
)
.toFingerprintSensor()
val fingerprintSensorRepository =
object : FingerprintSensorRepository {
override val fingerprintSensor: Flow<FingerprintSensor> = flowOf(sensor)
@@ -135,7 +150,7 @@ class FingerprintManagerInteractorTest {
listOf(
Fingerprint("Finger 1,", 2, 3L),
Fingerprint("Finger 2,", 3, 3L),
Fingerprint("Finger 3,", 4, 3L)
Fingerprint("Finger 3,", 4, 3L),
)
val fingerprintList2: List<Fingerprint> =
fingerprintList1.plus(
@@ -160,7 +175,7 @@ class FingerprintManagerInteractorTest {
gateKeeperPasswordProvider.requestGatekeeperHat(
any(Intent::class.java),
anyLong(),
anyInt()
anyInt(),
)
)
.thenReturn(byteArray)
@@ -223,7 +238,7 @@ class FingerprintManagerInteractorTest {
removalCallback.value.onRemovalError(
fingerprintToRemove,
100,
"Oh no, we couldn't find that one"
"Oh no, we couldn't find that one",
)
runCurrent()
@@ -260,7 +275,7 @@ class FingerprintManagerInteractorTest {
any(CancellationSignal::class.java),
capture(authCallback),
nullable(Handler::class.java),
anyInt()
anyInt(),
)
authCallback.value.onAuthenticationSucceeded(
FingerprintManager.AuthenticationResult(null, fingerprint, 1, false)
@@ -287,7 +302,7 @@ class FingerprintManagerInteractorTest {
any(CancellationSignal::class.java),
capture(authCallback),
nullable(Handler::class.java),
anyInt()
anyInt(),
)
authCallback.value.onAuthenticationError(FINGERPRINT_ERROR_LOCKOUT_PERMANENT, "Lockout!!")

View File

@@ -18,6 +18,11 @@ package com.android.settings.fingerprint2.enrollment.viewmodel
import android.content.Context
import android.content.res.Configuration
import android.hardware.biometrics.ComponentInfoInternal
import android.hardware.biometrics.SensorLocationInternal
import android.hardware.biometrics.SensorProperties
import android.hardware.fingerprint.FingerprintSensorProperties
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
import android.view.Surface
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.test.core.app.ApplicationProvider
@@ -33,9 +38,7 @@ import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.Fing
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationViewModel
import com.android.settings.testutils2.FakeFingerprintManagerInteractor
import com.android.systemui.biometrics.shared.model.FingerprintSensor
import com.android.systemui.biometrics.shared.model.FingerprintSensorType
import com.android.systemui.biometrics.shared.model.SensorStrength
import com.android.systemui.biometrics.shared.model.toFingerprintSensor
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
@@ -94,7 +97,19 @@ class FingerprintEnrollFindSensorViewModelV2Test {
)
.create(FingerprintGatekeeperViewModel::class.java)
val sensor = FingerprintSensor(1, SensorStrength.STRONG, 5, FingerprintSensorType.POWER_BUTTON)
val sensor =
FingerprintSensorPropertiesInternal(
0 /* sensorId */,
SensorProperties.STRENGTH_STRONG,
5 /* maxEnrollmentsPerUser */,
listOf<ComponentInfoInternal>(),
FingerprintSensorProperties.TYPE_POWER_BUTTON,
false /* halControlsIllumination */,
true /* resetLockoutRequiresHardwareAuthToken */,
listOf<SensorLocationInternal>(SensorLocationInternal.DEFAULT),
)
.toFingerprintSensor()
val fingerprintFlowViewModel = FingerprintFlowViewModel(Default)
navigationViewModel =
FingerprintNavigationViewModel(
@@ -159,12 +174,17 @@ class FingerprintEnrollFindSensorViewModelV2Test {
fun udfpsLottieInfo() =
testScope.runTest {
fakeFingerprintManagerInteractor.sensorProp =
FingerprintSensor(
0 /* sensorId */,
SensorStrength.STRONG,
5,
FingerprintSensorType.UDFPS_OPTICAL,
)
FingerprintSensorPropertiesInternal(
0 /* sensorId */,
SensorProperties.STRENGTH_STRONG,
5 /* maxEnrollmentsPerUser */,
listOf<ComponentInfoInternal>(),
FingerprintSensorProperties.TYPE_UDFPS_OPTICAL,
false /* halControlsIllumination */,
true /* resetLockoutRequiresHardwareAuthToken */,
listOf<SensorLocationInternal>(SensorLocationInternal.DEFAULT),
)
.toFingerprintSensor()
var udfpsLottieInfo: Boolean? = null
val job = launch { underTest.udfpsLottieInfo.collect { udfpsLottieInfo = it } }
@@ -218,7 +238,17 @@ class FingerprintEnrollFindSensorViewModelV2Test {
fun rfpsAnimation() =
testScope.runTest {
fakeFingerprintManagerInteractor.sensorProp =
FingerprintSensor(0 /* sensorId */, SensorStrength.STRONG, 5, FingerprintSensorType.REAR)
FingerprintSensorPropertiesInternal(
0 /* sensorId */,
SensorProperties.STRENGTH_STRONG,
5 /* maxEnrollmentsPerUser */,
listOf<ComponentInfoInternal>(),
FingerprintSensorProperties.TYPE_REAR,
false /* halControlsIllumination */,
true /* resetLockoutRequiresHardwareAuthToken */,
listOf<SensorLocationInternal>(SensorLocationInternal.DEFAULT),
)
.toFingerprintSensor()
var showRfpsAnimation: Boolean? = null
val job = launch { underTest.showRfpsAnimation.collect { showRfpsAnimation = it } }
@@ -232,12 +262,17 @@ class FingerprintEnrollFindSensorViewModelV2Test {
fun showPrimaryButton_ifUdfps() =
testScope.runTest {
fakeFingerprintManagerInteractor.sensorProp =
FingerprintSensor(
0 /* sensorId */,
SensorStrength.STRONG,
5,
FingerprintSensorType.UDFPS_OPTICAL,
)
FingerprintSensorPropertiesInternal(
0 /* sensorId */,
SensorProperties.STRENGTH_STRONG,
5 /* maxEnrollmentsPerUser */,
listOf<ComponentInfoInternal>(),
FingerprintSensorProperties.TYPE_UDFPS_OPTICAL,
false /* halControlsIllumination */,
true /* resetLockoutRequiresHardwareAuthToken */,
listOf<SensorLocationInternal>(SensorLocationInternal.DEFAULT),
)
.toFingerprintSensor()
var showPrimaryButton: Boolean? = null
val job = launch { underTest.showPrimaryButton.collect { showPrimaryButton = it } }

View File

@@ -16,6 +16,11 @@
package com.android.settings.fingerprint2.ui.enrollment.viewmodel
import android.hardware.biometrics.ComponentInfoInternal
import android.hardware.biometrics.SensorLocationInternal
import android.hardware.biometrics.SensorProperties
import android.hardware.fingerprint.FingerprintSensorProperties
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import com.android.settings.biometrics.fingerprint2.lib.model.Default
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollConfirmationViewModel
@@ -26,6 +31,7 @@ import com.android.settings.testutils2.FakeFingerprintManagerInteractor
import com.android.systemui.biometrics.shared.model.FingerprintSensor
import com.android.systemui.biometrics.shared.model.FingerprintSensorType
import com.android.systemui.biometrics.shared.model.SensorStrength
import com.android.systemui.biometrics.shared.model.toFingerprintSensor
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.StandardTestDispatcher
@@ -68,8 +74,18 @@ class FingerprintEnrollConfirmationViewModelTest {
@Test
fun testCanEnrollFingerprints() =
testScope.runTest {
fakeFingerprintManagerInteractor.sensorProp =
FingerprintSensor(0 /* sensorId */, SensorStrength.STRONG, 5, FingerprintSensorType.REAR)
fakeFingerprintManagerInteractor.sensorProp = FingerprintSensorPropertiesInternal(
0 /* sensorId */,
SensorProperties.STRENGTH_STRONG,
5 /* maxEnrollmentsPerUser */,
listOf<ComponentInfoInternal>(),
FingerprintSensorProperties.TYPE_POWER_BUTTON,
false /* halControlsIllumination */,
true /* resetLockoutRequiresHardwareAuthToken */,
listOf<SensorLocationInternal>(SensorLocationInternal.DEFAULT),
)
.toFingerprintSensor()
fakeFingerprintManagerInteractor.enrolledFingerprintsInternal = mutableListOf()
fakeFingerprintManagerInteractor.enrollableFingerprints = 5

View File

@@ -16,6 +16,11 @@
package com.android.settings.fingerprint2.ui.enrollment.viewmodel
import android.hardware.biometrics.ComponentInfoInternal
import android.hardware.biometrics.SensorLocationInternal
import android.hardware.biometrics.SensorProperties
import android.hardware.fingerprint.FingerprintSensorProperties
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import com.android.settings.biometrics.fingerprint2.lib.model.Default
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.BackgroundViewModel
@@ -26,11 +31,8 @@ import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.Fing
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep.Enrollment
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationViewModel
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.GatekeeperInfo
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.NavigationState
import com.android.settings.testutils2.FakeFingerprintManagerInteractor
import com.android.systemui.biometrics.shared.model.FingerprintSensor
import com.android.systemui.biometrics.shared.model.FingerprintSensorType
import com.android.systemui.biometrics.shared.model.SensorStrength
import com.android.systemui.biometrics.shared.model.toFingerprintSensor
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -72,7 +74,18 @@ class FingerprintEnrollEnrollingViewModelTest {
fakeFingerprintManagerInteractor,
)
.create(FingerprintGatekeeperViewModel::class.java)
val sensor = FingerprintSensor(1, SensorStrength.STRONG, 5, FingerprintSensorType.POWER_BUTTON)
val sensor =
FingerprintSensorPropertiesInternal(
1 /* sensorId */,
SensorProperties.STRENGTH_STRONG,
5 /* maxEnrollmentsPerUser */,
listOf<ComponentInfoInternal>(),
FingerprintSensorProperties.TYPE_POWER_BUTTON,
false /* halControlsIllumination */,
true /* resetLockoutRequiresHardwareAuthToken */,
listOf<SensorLocationInternal>(SensorLocationInternal.DEFAULT),
)
.toFingerprintSensor()
val fingerprintFlowViewModel = FingerprintFlowViewModel(Default)
navigationViewModel =

View File

@@ -16,6 +16,11 @@
package com.android.settings.fingerprint2.ui.settings
import android.hardware.biometrics.ComponentInfoInternal
import android.hardware.biometrics.SensorLocationInternal
import android.hardware.biometrics.SensorProperties
import android.hardware.fingerprint.FingerprintSensorProperties
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintAuthAttemptModel
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintData
@@ -23,9 +28,7 @@ import com.android.settings.biometrics.fingerprint2.ui.settings.viewmodel.Finger
import com.android.settings.biometrics.fingerprint2.ui.settings.viewmodel.FingerprintSettingsViewModel
import com.android.settings.biometrics.fingerprint2.ui.settings.viewmodel.PreferenceViewModel
import com.android.settings.testutils2.FakeFingerprintManagerInteractor
import com.android.systemui.biometrics.shared.model.FingerprintSensor
import com.android.systemui.biometrics.shared.model.FingerprintSensorType
import com.android.systemui.biometrics.shared.model.SensorStrength
import com.android.systemui.biometrics.shared.model.toFingerprintSensor
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.collectLatest
@@ -96,12 +99,18 @@ class FingerprintSettingsViewModelTest {
fun authenticate_DoesNotRun_ifOptical() =
testScope.runTest {
fakeFingerprintManagerInteractor.sensorProp =
FingerprintSensor(
0 /* sensorId */,
SensorStrength.STRONG,
5 /* maxEnrollmentsPerUser */,
FingerprintSensorType.UDFPS_OPTICAL,
)
FingerprintSensorPropertiesInternal(
0 /* sensorId */,
SensorProperties.STRENGTH_STRONG,
5 /* maxEnrollmentsPerUser */,
listOf<ComponentInfoInternal>(),
FingerprintSensorProperties.TYPE_UDFPS_OPTICAL,
false /* halControlsIllumination */,
true /* resetLockoutRequiresHardwareAuthToken */,
listOf<SensorLocationInternal>(SensorLocationInternal.DEFAULT),
)
.toFingerprintSensor()
fakeFingerprintManagerInteractor.enrolledFingerprintsInternal =
mutableListOf(FingerprintData("a", 1, 3L))
@@ -132,12 +141,18 @@ class FingerprintSettingsViewModelTest {
fun authenticate_DoesNotRun_ifUltrasonic() =
testScope.runTest {
fakeFingerprintManagerInteractor.sensorProp =
FingerprintSensor(
0 /* sensorId */,
SensorStrength.STRONG,
5 /* maxEnrollmentsPerUser */,
FingerprintSensorType.UDFPS_ULTRASONIC,
)
FingerprintSensorPropertiesInternal(
0 /* sensorId */,
SensorProperties.STRENGTH_STRONG,
5 /* maxEnrollmentsPerUser */,
listOf<ComponentInfoInternal>(),
FingerprintSensorProperties.TYPE_UDFPS_ULTRASONIC,
false /* halControlsIllumination */,
true /* resetLockoutRequiresHardwareAuthToken */,
listOf<SensorLocationInternal>(SensorLocationInternal.DEFAULT),
)
.toFingerprintSensor()
fakeFingerprintManagerInteractor.enrolledFingerprintsInternal =
mutableListOf(FingerprintData("a", 1, 3L))
@@ -166,12 +181,18 @@ class FingerprintSettingsViewModelTest {
fun authenticate_DoesRun_ifNotUdfps() =
testScope.runTest {
fakeFingerprintManagerInteractor.sensorProp =
FingerprintSensor(
0 /* sensorId */,
SensorStrength.STRONG,
5 /* maxEnrollmentsPerUser */,
FingerprintSensorType.POWER_BUTTON
)
FingerprintSensorPropertiesInternal(
0 /* sensorId */,
SensorProperties.STRENGTH_STRONG,
5 /* maxEnrollmentsPerUser */,
listOf<ComponentInfoInternal>(),
FingerprintSensorProperties.TYPE_POWER_BUTTON,
false /* halControlsIllumination */,
true /* resetLockoutRequiresHardwareAuthToken */,
listOf<SensorLocationInternal>(SensorLocationInternal.DEFAULT),
)
.toFingerprintSensor()
fakeFingerprintManagerInteractor.enrolledFingerprintsInternal =
mutableListOf(FingerprintData("a", 1, 3L))
val success = FingerprintAuthAttemptModel.Success(1)
@@ -324,8 +345,7 @@ class FingerprintSettingsViewModelTest {
runCurrent()
assertThat(authAttempt).isEqualTo(success)
fakeFingerprintManagerInteractor.authenticateAttempt =
FingerprintAuthAttemptModel.Success(10)
fakeFingerprintManagerInteractor.authenticateAttempt = FingerprintAuthAttemptModel.Success(10)
underTest.shouldAuthenticate(false)
advanceTimeBy(400)
runCurrent()
@@ -372,14 +392,19 @@ class FingerprintSettingsViewModelTest {
private fun setupAuth(): MutableList<FingerprintData> {
fakeFingerprintManagerInteractor.sensorProp =
FingerprintSensor(
0 /* sensorId */,
SensorStrength.STRONG,
5 /* maxEnrollmentsPerUser */,
FingerprintSensorType.POWER_BUTTON
)
val fingerprints =
mutableListOf(FingerprintData("a", 1, 3L), FingerprintData("b", 2, 5L))
FingerprintSensorPropertiesInternal(
0 /* sensorId */,
SensorProperties.STRENGTH_STRONG,
5 /* maxEnrollmentsPerUser */,
listOf<ComponentInfoInternal>(),
FingerprintSensorProperties.TYPE_POWER_BUTTON,
false /* halControlsIllumination */,
true /* resetLockoutRequiresHardwareAuthToken */,
listOf<SensorLocationInternal>(SensorLocationInternal.DEFAULT),
)
.toFingerprintSensor()
val fingerprints = mutableListOf(FingerprintData("a", 1, 3L), FingerprintData("b", 2, 5L))
fakeFingerprintManagerInteractor.enrolledFingerprintsInternal = fingerprints
val success = FingerprintAuthAttemptModel.Success(1)
fakeFingerprintManagerInteractor.authenticateAttempt = success

View File

@@ -66,6 +66,7 @@ public class FaceFingerprintUnlockControllerTest {
final FakeFeatureFactory featureFactory = FakeFeatureFactory.setupForTest();
when(featureFactory.securityFeatureProvider.getLockPatternUtils(mContext))
.thenReturn(mLockPatternUtils);
doReturn(true).when(mLockPatternUtils).isSecure(anyInt());
mFaceFingerprintUnlockController =
new FaceFingerprintUnlockController(mContext, mLifecycle);

View File

@@ -72,6 +72,7 @@ public class PrivateSpaceLockControllerTest {
final FakeFeatureFactory featureFactory = FakeFeatureFactory.setupForTest();
when(featureFactory.securityFeatureProvider.getLockPatternUtils(mContext))
.thenReturn(mLockPatternUtils);
doReturn(true).when(mLockPatternUtils).isSecure(anyInt());
mPrivateSpaceLockController = new PrivateSpaceLockController(mContext,
mSettingsPreferenceFragment);

View File

@@ -68,6 +68,7 @@ public class UseOneLockControllerTest {
final FakeFeatureFactory featureFactory = FakeFeatureFactory.setupForTest();
when(featureFactory.securityFeatureProvider.getLockPatternUtils(mContext))
.thenReturn(mLockPatternUtils);
doReturn(true).when(mLockPatternUtils).isSecure(anyInt());
mUseOneLockController = new UseOneLockController(mContext, preferenceKey);
}