From b2aae6cd57861228eca03abcb14acca1b6c9c4f1 Mon Sep 17 00:00:00 2001 From: Fan Zhang Date: Thu, 2 Nov 2017 14:09:34 -0700 Subject: [PATCH] Convert the rest of encryption page into pref controller Bug: 32953042 Test: robotests Change-Id: I6c1b28314a988e6499065ddaee2aeae0ac28c537 --- res/xml/encryption_and_credential.xml | 14 ++- ...CredentialStoragePreferenceController.java | 48 +++++++ .../security/EncryptionAndCredential.java | 119 ++---------------- ...nstallCredentialsPreferenceController.java | 35 ++++++ .../ResetCredentialsPreferenceController.java | 63 ++++++++++ ...trictedEncryptionPreferenceController.java | 45 +++++++ .../UserCredentialsPreferenceController.java | 35 ++++++ ...entialStoragePreferenceControllerTest.java | 72 +++++++++++ ...ryptionStatusPreferenceControllerTest.java | 2 +- ...tedEncryptionPreferenceControllerTest.java | 86 +++++++++++++ .../testutils/shadow/ShadowKeyStore.java | 43 +++++++ .../testutils/shadow/ShadowUserManager.java | 21 +++- 12 files changed, 465 insertions(+), 118 deletions(-) create mode 100644 src/com/android/settings/security/CredentialStoragePreferenceController.java create mode 100644 src/com/android/settings/security/InstallCredentialsPreferenceController.java create mode 100644 src/com/android/settings/security/ResetCredentialsPreferenceController.java create mode 100644 src/com/android/settings/security/RestrictedEncryptionPreferenceController.java create mode 100644 src/com/android/settings/security/UserCredentialsPreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/security/CredentialStoragePreferenceControllerTest.java create mode 100644 tests/robotests/src/com/android/settings/security/RestrictedEncryptionPreferenceControllerTest.java create mode 100644 tests/robotests/src/com/android/settings/testutils/shadow/ShadowKeyStore.java diff --git a/res/xml/encryption_and_credential.xml b/res/xml/encryption_and_credential.xml index 4960f257410..3e3130cdc14 100644 --- a/res/xml/encryption_and_credential.xml +++ b/res/xml/encryption_and_credential.xml @@ -16,6 +16,7 @@ @@ -39,7 +40,9 @@ + android:title="@string/credential_storage_type" + android:summary="@string/summary_placeholder" + settings:userRestriction="no_config_credentials" /> + android:fragment="com.android.settings.UserCredentialsSettings" + settings:userRestriction="no_config_credentials" /> + android:summary="@string/credentials_install_summary" + settings:userRestriction="no_config_credentials"> + android:summary="@string/credentials_reset_summary" + settings:userRestriction="no_config_credentials"> getPreferenceControllers(Context context) { - return buildPreferenceControllers(context); + return buildPreferenceControllers(context, getLifecycle()); } @Override @@ -78,7 +59,8 @@ public class EncryptionAndCredential extends DashboardFragment { return R.xml.encryption_and_credential; } - private static List buildPreferenceControllers(Context context) { + private static List buildPreferenceControllers(Context context, + Lifecycle lifecycle) { final List controllers = new ArrayList<>(); final EncryptionStatusPreferenceController encryptStatusController = new EncryptionStatusPreferenceController(context); @@ -86,76 +68,13 @@ public class EncryptionAndCredential extends DashboardFragment { controllers.add(new PreferenceCategoryController(context, "encryption_and_credentials_status_category", Arrays.asList(encryptStatusController))); + controllers.add(new CredentialStoragePreferenceController(context)); + controllers.add(new UserCredentialsPreferenceController(context)); + controllers.add(new ResetCredentialsPreferenceController(context, lifecycle)); + controllers.add(new InstallCredentialsPreferenceController(context)); return controllers; } - /** - * Important! - * - * Don't forget to update the SecuritySearchIndexProvider if you are doing any change in the - * logic or adding/removing preferences here. - */ - private PreferenceScreen createPreferenceHierarchy() { - final PreferenceScreen root = getPreferenceScreen(); - // Credential storage - mKeyStore = KeyStore.getInstance(); // needs to be initialized for onResume() - - if (!RestrictedLockUtils.hasBaseUserRestriction(getActivity(), - UserManager.DISALLOW_CONFIG_CREDENTIALS, MY_USER_ID)) { - RestrictedPreference userCredentials = (RestrictedPreference) root.findPreference( - KEY_USER_CREDENTIALS); - userCredentials.checkRestrictionAndSetDisabled( - UserManager.DISALLOW_CONFIG_CREDENTIALS); - RestrictedPreference credentialStorageType = (RestrictedPreference) root.findPreference( - KEY_CREDENTIAL_STORAGE_TYPE); - credentialStorageType.checkRestrictionAndSetDisabled( - UserManager.DISALLOW_CONFIG_CREDENTIALS); - RestrictedPreference installCredentials = (RestrictedPreference) root.findPreference( - KEY_CREDENTIALS_INSTALL); - installCredentials.checkRestrictionAndSetDisabled( - UserManager.DISALLOW_CONFIG_CREDENTIALS); - mResetCredentials = (RestrictedPreference) root.findPreference(KEY_RESET_CREDENTIALS); - mResetCredentials.checkRestrictionAndSetDisabled( - UserManager.DISALLOW_CONFIG_CREDENTIALS); - - final int storageSummaryRes = - mKeyStore.isHardwareBacked() ? R.string.credential_storage_type_hardware - : R.string.credential_storage_type_software; - credentialStorageType.setSummary(storageSummaryRes); - } else { - PreferenceGroup credentialsManager = (PreferenceGroup) - root.findPreference(KEY_CREDENTIALS_MANAGER); - credentialsManager.removePreference(root.findPreference(KEY_RESET_CREDENTIALS)); - credentialsManager.removePreference(root.findPreference(KEY_CREDENTIALS_INSTALL)); - credentialsManager.removePreference(root.findPreference(KEY_CREDENTIAL_STORAGE_TYPE)); - credentialsManager.removePreference(root.findPreference(KEY_USER_CREDENTIALS)); - } - - return root; - } - - @Override - public void onResume() { - super.onResume(); - - // Make sure we reload the preference hierarchy since some of these settings - // depend on others... - createPreferenceHierarchy(); - - if (mResetCredentials != null && !mResetCredentials.isDisabledByAdmin()) { - mResetCredentials.setEnabled(!mKeyStore.isEmpty()); - } - } - - /** - * see confirmPatternThenDisableAndClear - */ - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - createPreferenceHierarchy(); - } - @Override protected int getHelpResource() { return R.string.help_url_encryption; @@ -179,7 +98,7 @@ public class EncryptionAndCredential extends DashboardFragment { @Override public List getPreferenceControllers(Context context) { - return buildPreferenceControllers(context); + return buildPreferenceControllers(context, null /* lifecycle */); } @Override @@ -187,25 +106,5 @@ public class EncryptionAndCredential extends DashboardFragment { final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); return um.isAdminUser(); } - - @Override - public List getNonIndexableKeys(Context context) { - final List keys = super.getNonIndexableKeys(context); - if (!isPageSearchEnabled(context)) { - return keys; - } - final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); - - if (um.hasUserRestriction(UserManager.DISALLOW_CONFIG_CREDENTIALS)) { - keys.add(KEY_CREDENTIALS_MANAGER); - keys.add(KEY_RESET_CREDENTIALS); - keys.add(KEY_CREDENTIALS_INSTALL); - keys.add(KEY_CREDENTIAL_STORAGE_TYPE); - keys.add(KEY_USER_CREDENTIALS); - } - - return keys; - } } - } diff --git a/src/com/android/settings/security/InstallCredentialsPreferenceController.java b/src/com/android/settings/security/InstallCredentialsPreferenceController.java new file mode 100644 index 00000000000..ca9ed2657a5 --- /dev/null +++ b/src/com/android/settings/security/InstallCredentialsPreferenceController.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2017 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 android.content.Context; +import android.os.UserManager; + +public class InstallCredentialsPreferenceController extends + RestrictedEncryptionPreferenceController { + + private static final String KEY_CREDENTIALS_INSTALL = "credentials_install"; + + public InstallCredentialsPreferenceController(Context context) { + super(context, UserManager.DISALLOW_CONFIG_CREDENTIALS); + } + + @Override + public String getPreferenceKey() { + return KEY_CREDENTIALS_INSTALL; + } +} diff --git a/src/com/android/settings/security/ResetCredentialsPreferenceController.java b/src/com/android/settings/security/ResetCredentialsPreferenceController.java new file mode 100644 index 00000000000..7b91b154152 --- /dev/null +++ b/src/com/android/settings/security/ResetCredentialsPreferenceController.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2017 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 android.content.Context; +import android.os.UserManager; +import android.security.KeyStore; +import android.support.v7.preference.PreferenceScreen; + +import com.android.settingslib.RestrictedPreference; +import com.android.settingslib.core.lifecycle.Lifecycle; +import com.android.settingslib.core.lifecycle.LifecycleObserver; +import com.android.settingslib.core.lifecycle.events.OnResume; + +public class ResetCredentialsPreferenceController extends RestrictedEncryptionPreferenceController + implements LifecycleObserver, OnResume { + + private static final String KEY_RESET_CREDENTIALS = "credentials_reset"; + + private final KeyStore mKeyStore; + + private RestrictedPreference mPreference; + + public ResetCredentialsPreferenceController(Context context, Lifecycle lifecycle) { + super(context, UserManager.DISALLOW_CONFIG_CREDENTIALS); + mKeyStore = KeyStore.getInstance(); + if (lifecycle != null) { + lifecycle.addObserver(this); + } + } + + @Override + public String getPreferenceKey() { + return KEY_RESET_CREDENTIALS; + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + mPreference = (RestrictedPreference) screen.findPreference(getPreferenceKey()); + } + + @Override + public void onResume() { + if (mPreference != null && !mPreference.isDisabledByAdmin()) { + mPreference.setEnabled(!mKeyStore.isEmpty()); + } + } +} diff --git a/src/com/android/settings/security/RestrictedEncryptionPreferenceController.java b/src/com/android/settings/security/RestrictedEncryptionPreferenceController.java new file mode 100644 index 00000000000..2c5308fbc1b --- /dev/null +++ b/src/com/android/settings/security/RestrictedEncryptionPreferenceController.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2017 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 android.content.Context; +import android.os.UserHandle; +import android.os.UserManager; + +import com.android.settings.core.PreferenceControllerMixin; +import com.android.settingslib.core.AbstractPreferenceController; + +public abstract class RestrictedEncryptionPreferenceController extends + AbstractPreferenceController implements PreferenceControllerMixin { + + protected final UserManager mUserManager; + + private final UserHandle mUserHandle; + private final String mUserRestriction; + + public RestrictedEncryptionPreferenceController(Context context, String userRestriction) { + super(context); + mUserHandle = UserHandle.of(UserHandle.myUserId()); + mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); + mUserRestriction = userRestriction; + } + + @Override + public boolean isAvailable() { + return !mUserManager.hasBaseUserRestriction(mUserRestriction, mUserHandle); + } +} diff --git a/src/com/android/settings/security/UserCredentialsPreferenceController.java b/src/com/android/settings/security/UserCredentialsPreferenceController.java new file mode 100644 index 00000000000..48503f8375b --- /dev/null +++ b/src/com/android/settings/security/UserCredentialsPreferenceController.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2017 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 android.content.Context; +import android.os.UserManager; + +public class UserCredentialsPreferenceController extends + RestrictedEncryptionPreferenceController { + + private static final String KEY_USER_CREDENTIALS = "user_credentials"; + + public UserCredentialsPreferenceController(Context context) { + super(context, UserManager.DISALLOW_CONFIG_CREDENTIALS); + } + + @Override + public String getPreferenceKey() { + return KEY_USER_CREDENTIALS; + } +} diff --git a/tests/robotests/src/com/android/settings/security/CredentialStoragePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/security/CredentialStoragePreferenceControllerTest.java new file mode 100644 index 00000000000..71253d6a118 --- /dev/null +++ b/tests/robotests/src/com/android/settings/security/CredentialStoragePreferenceControllerTest.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2017 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.content.Context; +import android.support.v7.preference.Preference; + +import com.android.settings.R; +import com.android.settings.TestConfig; +import com.android.settings.testutils.SettingsRobolectricTestRunner; +import com.android.settings.testutils.shadow.ShadowKeyStore; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION_O, + shadows = { + ShadowKeyStore.class + }) +public class CredentialStoragePreferenceControllerTest { + + private Context mContext; + private CredentialStoragePreferenceController mController; + private Preference mPreference; + + @Before + public void setUp() { + mContext = RuntimeEnvironment.application; + mController = new CredentialStoragePreferenceController(mContext); + mPreference = new Preference(mContext); + } + + @Test + public void updateState_hardwareBacked_showHardwareSummary() { + ShadowKeyStore.setHardwareBacked(true); + + mController.updateState(mPreference); + + assertThat(mPreference.getSummary()) + .isEqualTo(mContext.getText(R.string.credential_storage_type_hardware)); + } + + @Test + public void updateState_hardwareBacked_showSoftwareSummary() { + ShadowKeyStore.setHardwareBacked(false); + + mController.updateState(mPreference); + + assertThat(mPreference.getSummary()) + .isEqualTo(mContext.getText(R.string.credential_storage_type_software)); + } +} diff --git a/tests/robotests/src/com/android/settings/security/EncryptionStatusPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/security/EncryptionStatusPreferenceControllerTest.java index a53ee4245d7..d66d49538bd 100644 --- a/tests/robotests/src/com/android/settings/security/EncryptionStatusPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/security/EncryptionStatusPreferenceControllerTest.java @@ -34,7 +34,7 @@ import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; @RunWith(SettingsRobolectricTestRunner.class) -@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION, +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION_O, shadows = { ShadowUserManager.class, ShadowLockPatternUtils.class diff --git a/tests/robotests/src/com/android/settings/security/RestrictedEncryptionPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/security/RestrictedEncryptionPreferenceControllerTest.java new file mode 100644 index 00000000000..8db679542e7 --- /dev/null +++ b/tests/robotests/src/com/android/settings/security/RestrictedEncryptionPreferenceControllerTest.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2017 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.content.Context; +import android.os.UserManager; + +import com.android.settings.TestConfig; +import com.android.settings.testutils.SettingsRobolectricTestRunner; +import com.android.settings.testutils.shadow.ShadowUserManager; +import com.android.settingslib.core.lifecycle.Lifecycle; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION_O, + shadows = { + ShadowUserManager.class + }) +public class RestrictedEncryptionPreferenceControllerTest { + + private Context mContext; + private ShadowUserManager mUserManager; + private CredentialStoragePreferenceController mCredentialStoragePreferenceController; + private InstallCredentialsPreferenceController mInstallCredentialsPreferenceController; + private ResetCredentialsPreferenceController mResetCredentialsPreferenceController; + private UserCredentialsPreferenceController mUserCredentialsPreferenceController; + + @Before + public void setUp() { + mContext = RuntimeEnvironment.application; + mCredentialStoragePreferenceController = + new CredentialStoragePreferenceController(mContext); + mInstallCredentialsPreferenceController = + new InstallCredentialsPreferenceController(mContext); + mResetCredentialsPreferenceController = + new ResetCredentialsPreferenceController(mContext, new Lifecycle()); + mUserCredentialsPreferenceController = + new UserCredentialsPreferenceController(mContext); + mUserManager = ShadowUserManager.getShadow(); + } + + @After + public void tearDown() { + mUserManager.reset(); + } + + @Test + public void isAvailable_noRestriction_shouldReturnTrue() { + assertThat(mCredentialStoragePreferenceController.isAvailable()).isTrue(); + assertThat(mInstallCredentialsPreferenceController.isAvailable()).isTrue(); + assertThat(mResetCredentialsPreferenceController.isAvailable()).isTrue(); + assertThat(mUserCredentialsPreferenceController.isAvailable()).isTrue(); + } + + @Test + public void isAvailable_hasRestriction_shouldReturnFalse() { + mUserManager.addBaseUserRestriction(UserManager.DISALLOW_CONFIG_CREDENTIALS); + + assertThat(mCredentialStoragePreferenceController.isAvailable()).isFalse(); + assertThat(mInstallCredentialsPreferenceController.isAvailable()).isFalse(); + assertThat(mResetCredentialsPreferenceController.isAvailable()).isFalse(); + assertThat(mUserCredentialsPreferenceController.isAvailable()).isFalse(); + } +} \ No newline at end of file diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowKeyStore.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowKeyStore.java new file mode 100644 index 00000000000..c025a33a2f5 --- /dev/null +++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowKeyStore.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2017 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.testutils.shadow; + +import android.security.KeyStore; + +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; +import org.robolectric.annotation.Resetter; + +@Implements(KeyStore.class) +public class ShadowKeyStore { + + private static boolean sIsHardwareBacked; + + @Resetter + public void reset() { + sIsHardwareBacked = false; + } + + @Implementation + public boolean isHardwareBacked() { + return sIsHardwareBacked; + } + + public static void setHardwareBacked(boolean hardwareBacked) { + sIsHardwareBacked = hardwareBacked; + } +} diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java index 888fa366216..f24837dfa72 100644 --- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java +++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java @@ -19,30 +19,36 @@ package com.android.settings.testutils.shadow; import android.annotation.UserIdInt; import android.content.Context; import android.content.pm.UserInfo; +import android.os.UserHandle; import android.os.UserManager; import android.util.SparseArray; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Implementation; import org.robolectric.annotation.Implements; +import org.robolectric.annotation.Resetter; import org.robolectric.shadow.api.Shadow; +import java.util.ArrayList; import java.util.Collections; import java.util.List; -/** - * This class provides the API 24 implementation of UserManager.get(Context). - */ @Implements(UserManager.class) public class ShadowUserManager extends org.robolectric.shadows.ShadowUserManager { private SparseArray mUserInfos = new SparseArray<>(); private boolean mAdminUser; + private List mRestrictions = new ArrayList<>(); public void setIsAdminUser(boolean isAdminUser) { mAdminUser = isAdminUser; } + @Resetter + public void reset() { + mRestrictions.clear(); + } + @Implementation public boolean isAdminUser() { return mAdminUser; @@ -72,6 +78,15 @@ public class ShadowUserManager extends org.robolectric.shadows.ShadowUserManager return (UserManager) context.getSystemService(Context.USER_SERVICE); } + @Implementation + public boolean hasBaseUserRestriction(String restrictionKey, UserHandle userHandle) { + return mRestrictions.contains(restrictionKey); + } + + public void addBaseUserRestriction(String restriction) { + mRestrictions.add(restriction); + } + public static ShadowUserManager getShadow() { return (ShadowUserManager) Shadow.extract( RuntimeEnvironment.application.getSystemService(UserManager.class));