Merge "Support dynamic search index for App pinning" into main
This commit is contained in:
@@ -22,6 +22,7 @@ import android.app.settings.SettingsEnums;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.res.Resources;
|
||||||
import android.icu.text.MessageFormat;
|
import android.icu.text.MessageFormat;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
@@ -30,6 +31,7 @@ import android.provider.Settings;
|
|||||||
import android.widget.CompoundButton;
|
import android.widget.CompoundButton;
|
||||||
import android.widget.CompoundButton.OnCheckedChangeListener;
|
import android.widget.CompoundButton.OnCheckedChangeListener;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
import androidx.preference.Preference.OnPreferenceChangeListener;
|
import androidx.preference.Preference.OnPreferenceChangeListener;
|
||||||
@@ -45,7 +47,11 @@ import com.android.settings.password.ChooseLockSettingsHelper;
|
|||||||
import com.android.settings.search.BaseSearchIndexProvider;
|
import com.android.settings.search.BaseSearchIndexProvider;
|
||||||
import com.android.settings.widget.SettingsMainSwitchBar;
|
import com.android.settings.widget.SettingsMainSwitchBar;
|
||||||
import com.android.settingslib.search.SearchIndexable;
|
import com.android.settingslib.search.SearchIndexable;
|
||||||
|
import com.android.settingslib.search.SearchIndexableRaw;
|
||||||
import com.android.settingslib.widget.FooterPreference;
|
import com.android.settingslib.widget.FooterPreference;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Screen pinning settings.
|
* Screen pinning settings.
|
||||||
*/
|
*/
|
||||||
@@ -174,9 +180,8 @@ public class ScreenPinningSettings extends SettingsPreferenceFragment
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getCurrentSecurityTitle() {
|
private static int getCurrentSecurityTitle(LockPatternUtils lockPatternUtils) {
|
||||||
int quality = mLockPatternUtils.getKeyguardStoredPasswordQuality(
|
int quality = lockPatternUtils.getKeyguardStoredPasswordQuality(UserHandle.myUserId());
|
||||||
UserHandle.myUserId());
|
|
||||||
switch (quality) {
|
switch (quality) {
|
||||||
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
|
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
|
||||||
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
|
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
|
||||||
@@ -187,7 +192,7 @@ public class ScreenPinningSettings extends SettingsPreferenceFragment
|
|||||||
case DevicePolicyManager.PASSWORD_QUALITY_MANAGED:
|
case DevicePolicyManager.PASSWORD_QUALITY_MANAGED:
|
||||||
return R.string.screen_pinning_unlock_password;
|
return R.string.screen_pinning_unlock_password;
|
||||||
case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
|
case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
|
||||||
if (mLockPatternUtils.isLockPatternEnabled(UserHandle.myUserId())) {
|
if (lockPatternUtils.isLockPatternEnabled(UserHandle.myUserId())) {
|
||||||
return R.string.screen_pinning_unlock_pattern;
|
return R.string.screen_pinning_unlock_pattern;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -232,7 +237,7 @@ public class ScreenPinningSettings extends SettingsPreferenceFragment
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
mUseScreenLock.setChecked(isScreenLockUsed());
|
mUseScreenLock.setChecked(isScreenLockUsed());
|
||||||
mUseScreenLock.setTitle(getCurrentSecurityTitle());
|
mUseScreenLock.setTitle(getCurrentSecurityTitle(mLockPatternUtils));
|
||||||
} else {
|
} else {
|
||||||
mFooterPreference.setSummary(getAppPinningContent());
|
mFooterPreference.setSummary(getAppPinningContent());
|
||||||
mUseScreenLock.setEnabled(false);
|
mUseScreenLock.setEnabled(false);
|
||||||
@@ -252,8 +257,30 @@ public class ScreenPinningSettings extends SettingsPreferenceFragment
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For search
|
* For search.
|
||||||
|
*
|
||||||
|
* This page only provides an index for the toggle preference of using screen lock for
|
||||||
|
* unpinning. The preference name will change with various lock configurations. Indexing data
|
||||||
|
* from XML isn't suitable since it uses a static title by default. So, we skip XML indexing
|
||||||
|
* by omitting the XML argument in the constructor and use a dynamic index method instead.
|
||||||
*/
|
*/
|
||||||
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||||
new BaseSearchIndexProvider(R.xml.screen_pinning_settings);
|
new BaseSearchIndexProvider() {
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public List<SearchIndexableRaw> getDynamicRawDataToIndex(@NonNull Context context,
|
||||||
|
boolean enabled) {
|
||||||
|
List<SearchIndexableRaw> dynamicRaws =
|
||||||
|
super.getDynamicRawDataToIndex(context, enabled);
|
||||||
|
final SearchIndexableRaw raw = new SearchIndexableRaw(context);
|
||||||
|
final Resources res = context.getResources();
|
||||||
|
final LockPatternUtils lockPatternUtils = new LockPatternUtils(context);
|
||||||
|
raw.key = KEY_USE_SCREEN_LOCK;
|
||||||
|
raw.title = res.getString(getCurrentSecurityTitle(lockPatternUtils));
|
||||||
|
raw.screenTitle = res.getString(R.string.screen_pinning_title);
|
||||||
|
dynamicRaws.add(raw);
|
||||||
|
return dynamicRaws;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
* 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.security;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import android.app.admin.DevicePolicyManager;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.UserHandle;
|
||||||
|
|
||||||
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
|
||||||
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.testutils.shadow.ShadowLockPatternUtils;
|
||||||
|
import com.android.settingslib.search.SearchIndexableRaw;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.robolectric.RobolectricTestRunner;
|
||||||
|
import org.robolectric.annotation.Config;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RunWith(RobolectricTestRunner.class)
|
||||||
|
@Config(shadows = ShadowLockPatternUtils.class)
|
||||||
|
public class ScreenPinningSettingsTest {
|
||||||
|
|
||||||
|
private Context mContext;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
mContext = ApplicationProvider.getApplicationContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
ShadowLockPatternUtils.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getDynamicRawDataToIndex_numericPassword_shouldIndexUnlockPinTitle() {
|
||||||
|
ShadowLockPatternUtils.setKeyguardStoredPasswordQuality(
|
||||||
|
DevicePolicyManager.PASSWORD_QUALITY_NUMERIC);
|
||||||
|
|
||||||
|
final List<SearchIndexableRaw> indexRaws =
|
||||||
|
ScreenPinningSettings.SEARCH_INDEX_DATA_PROVIDER.getDynamicRawDataToIndex(
|
||||||
|
mContext, /* enabled= */ true);
|
||||||
|
|
||||||
|
assertThat(indexRaws.size()).isEqualTo(1);
|
||||||
|
assertThat(indexRaws.get(0).title).isEqualTo(
|
||||||
|
mContext.getString(R.string.screen_pinning_unlock_pin));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getDynamicRawDataToIndex_alphabeticPassword_shouldIndexUnlockPasswordTitle() {
|
||||||
|
ShadowLockPatternUtils.setKeyguardStoredPasswordQuality(
|
||||||
|
DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC);
|
||||||
|
|
||||||
|
final List<SearchIndexableRaw> indexRaws =
|
||||||
|
ScreenPinningSettings.SEARCH_INDEX_DATA_PROVIDER.getDynamicRawDataToIndex(
|
||||||
|
mContext, /* enabled= */ true);
|
||||||
|
|
||||||
|
assertThat(indexRaws.size()).isEqualTo(1);
|
||||||
|
assertThat(indexRaws.get(0).title).isEqualTo(
|
||||||
|
mContext.getString(R.string.screen_pinning_unlock_password));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getDynamicRawDataToIndex_patternPassword_shouldIndexUnlockPatternTitle() {
|
||||||
|
ShadowLockPatternUtils.setKeyguardStoredPasswordQuality(
|
||||||
|
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
|
||||||
|
ShadowLockPatternUtils.setIsLockPatternEnabled(
|
||||||
|
UserHandle.myUserId(), /* isLockPatternEnabled= */ true);
|
||||||
|
|
||||||
|
final List<SearchIndexableRaw> indexRaws =
|
||||||
|
ScreenPinningSettings.SEARCH_INDEX_DATA_PROVIDER.getDynamicRawDataToIndex(
|
||||||
|
mContext, /* enabled= */ true);
|
||||||
|
|
||||||
|
assertThat(indexRaws.size()).isEqualTo(1);
|
||||||
|
assertThat(indexRaws.get(0).title).isEqualTo(
|
||||||
|
mContext.getString(R.string.screen_pinning_unlock_pattern));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getDynamicRawDataToIndex_nonePassword_shouldIndexUnlockNoneTitle() {
|
||||||
|
ShadowLockPatternUtils.setKeyguardStoredPasswordQuality(
|
||||||
|
DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
|
||||||
|
|
||||||
|
final List<SearchIndexableRaw> indexRaws =
|
||||||
|
ScreenPinningSettings.SEARCH_INDEX_DATA_PROVIDER.getDynamicRawDataToIndex(
|
||||||
|
mContext, /* enabled= */ true);
|
||||||
|
|
||||||
|
assertThat(indexRaws.size()).isEqualTo(1);
|
||||||
|
assertThat(indexRaws.get(0).title).isEqualTo(
|
||||||
|
mContext.getString(R.string.screen_pinning_unlock_none));
|
||||||
|
}
|
||||||
|
}
|
@@ -50,6 +50,7 @@ public class ShadowLockPatternUtils {
|
|||||||
private static Map<Integer, Boolean> sUserToVisiblePatternEnabledMap = new HashMap<>();
|
private static Map<Integer, Boolean> sUserToVisiblePatternEnabledMap = new HashMap<>();
|
||||||
private static Map<Integer, Boolean> sUserToBiometricAllowedMap = new HashMap<>();
|
private static Map<Integer, Boolean> sUserToBiometricAllowedMap = new HashMap<>();
|
||||||
private static Map<Integer, Boolean> sUserToLockPatternEnabledMap = new HashMap<>();
|
private static Map<Integer, Boolean> sUserToLockPatternEnabledMap = new HashMap<>();
|
||||||
|
private static Map<Integer, Integer> sKeyguardStoredPasswordQualityMap = new HashMap<>();
|
||||||
|
|
||||||
private static boolean sIsUserOwnsFrpCredential;
|
private static boolean sIsUserOwnsFrpCredential;
|
||||||
|
|
||||||
@@ -66,6 +67,7 @@ public class ShadowLockPatternUtils {
|
|||||||
sUserToLockPatternEnabledMap.clear();
|
sUserToLockPatternEnabledMap.clear();
|
||||||
sDeviceEncryptionEnabled = false;
|
sDeviceEncryptionEnabled = false;
|
||||||
sIsUserOwnsFrpCredential = false;
|
sIsUserOwnsFrpCredential = false;
|
||||||
|
sKeyguardStoredPasswordQualityMap.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Implementation
|
@Implementation
|
||||||
@@ -97,7 +99,7 @@ public class ShadowLockPatternUtils {
|
|||||||
|
|
||||||
@Implementation
|
@Implementation
|
||||||
protected int getKeyguardStoredPasswordQuality(int userHandle) {
|
protected int getKeyguardStoredPasswordQuality(int userHandle) {
|
||||||
return 1;
|
return sKeyguardStoredPasswordQualityMap.getOrDefault(userHandle, /* defaultValue= */ 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Implementation
|
@Implementation
|
||||||
@@ -171,7 +173,7 @@ public class ShadowLockPatternUtils {
|
|||||||
|
|
||||||
@Implementation
|
@Implementation
|
||||||
public boolean isLockPatternEnabled(int userId) {
|
public boolean isLockPatternEnabled(int userId) {
|
||||||
return sUserToBiometricAllowedMap.getOrDefault(userId, false);
|
return sUserToLockPatternEnabledMap.getOrDefault(userId, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setIsLockPatternEnabled(int userId, boolean isLockPatternEnabled) {
|
public static void setIsLockPatternEnabled(int userId, boolean isLockPatternEnabled) {
|
||||||
@@ -238,4 +240,8 @@ public class ShadowLockPatternUtils {
|
|||||||
public boolean isSeparateProfileChallengeEnabled(int userHandle) {
|
public boolean isSeparateProfileChallengeEnabled(int userHandle) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setKeyguardStoredPasswordQuality(int quality) {
|
||||||
|
sKeyguardStoredPasswordQualityMap.put(UserHandle.myUserId(), quality);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user