From 7659e53a9423affa3909e29067abdcb444c4662a Mon Sep 17 00:00:00 2001 From: Alex Johnston Date: Mon, 14 Oct 2019 17:50:21 +0100 Subject: [PATCH] Added functionality to select type of certificate to be installed from the Settings app This is part of the changes to improve the UX and language for installing certificates. Previously, the different types of certificate used the same installation flow. This CL introduces a new settings page, where the type of certificate to be installed can be selected. Bug: 139173976 Test: Atest com.android.settings.security manual testing from Settings by selecting the certificate type preference and ensuring the installation flow still worked as expected. Change-Id: Iea7c91aa3801e429f0e22d29469958f4151b3cba --- res/values/strings.xml | 14 ++- res/xml/encryption_and_credential.xml | 12 +-- res/xml/install_certificate_from_storage.xml | 70 ++++++++++++++ .../security/EncryptionAndCredential.java | 2 +- ...tallCaCertificatePreferenceController.java | 42 +++++++++ .../InstallCertificateFromStorage.java | 93 +++++++++++++++++++ ...stallCertificatePreferenceController.java} | 8 +- ...llUserCertificatePreferenceController.java | 42 +++++++++ ...llWifiCertificatePreferenceController.java | 42 +++++++++ .../InstallCertificateFromStorageTest.java | 87 +++++++++++++++++ ...tedEncryptionPreferenceControllerTest.java | 25 ++++- 11 files changed, 414 insertions(+), 23 deletions(-) create mode 100644 res/xml/install_certificate_from_storage.xml create mode 100644 src/com/android/settings/security/InstallCaCertificatePreferenceController.java create mode 100644 src/com/android/settings/security/InstallCertificateFromStorage.java rename src/com/android/settings/security/{InstallCredentialsPreferenceController.java => InstallCertificatePreferenceController.java} (78%) create mode 100644 src/com/android/settings/security/InstallUserCertificatePreferenceController.java create mode 100644 src/com/android/settings/security/InstallWifiCertificatePreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/security/InstallCertificateFromStorageTest.java diff --git a/res/values/strings.xml b/res/values/strings.xml index e1f360a6a5c..60febe7dff3 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -5834,10 +5834,8 @@ Credential storage - - Install from storage - - Install from SD card + + Install a certificate Install certificates from storage @@ -5876,6 +5874,12 @@ Credential storage couldn\u2019t be erased. Apps with usage access + + CA certificate + + VPN & app user certificate + + Wi\u2011Fi certificate Emergency dialing signal @@ -6833,6 +6837,8 @@ + + diff --git a/res/xml/encryption_and_credential.xml b/res/xml/encryption_and_credential.xml index f9d967964eb..f7e7184036c 100644 --- a/res/xml/encryption_and_credential.xml +++ b/res/xml/encryption_and_credential.xml @@ -58,17 +58,11 @@ settings:userRestriction="no_config_credentials" /> - - - - + android:fragment="com.android.settings.security.InstallCertificateFromStorage" + settings:userRestriction="no_config_credentials" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/com/android/settings/security/EncryptionAndCredential.java b/src/com/android/settings/security/EncryptionAndCredential.java index 3e88fa8e5fa..d87327102d0 100644 --- a/src/com/android/settings/security/EncryptionAndCredential.java +++ b/src/com/android/settings/security/EncryptionAndCredential.java @@ -75,7 +75,7 @@ public class EncryptionAndCredential extends DashboardFragment { controllers.add(new CredentialStoragePreferenceController(context)); controllers.add(new UserCredentialsPreferenceController(context)); controllers.add(new ResetCredentialsPreferenceController(context, lifecycle)); - controllers.add(new InstallCredentialsPreferenceController(context)); + controllers.add(new InstallCertificatePreferenceController(context)); return controllers; } diff --git a/src/com/android/settings/security/InstallCaCertificatePreferenceController.java b/src/com/android/settings/security/InstallCaCertificatePreferenceController.java new file mode 100644 index 00000000000..b2ded85b2c2 --- /dev/null +++ b/src/com/android/settings/security/InstallCaCertificatePreferenceController.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.security; + +import android.content.Context; +import android.os.UserManager; + +import com.android.settings.core.BasePreferenceController; + +public class InstallCaCertificatePreferenceController extends + BasePreferenceController { + + private static final String KEY_INSTALL_CA_CERTIFICATE = "install_ca_certificate"; + + public InstallCaCertificatePreferenceController(Context context) { + super(context, UserManager.DISALLOW_CONFIG_CREDENTIALS); + } + + @Override + public int getAvailabilityStatus() { + return AVAILABLE; + } + + @Override + public String getPreferenceKey() { + return KEY_INSTALL_CA_CERTIFICATE; + } +} diff --git a/src/com/android/settings/security/InstallCertificateFromStorage.java b/src/com/android/settings/security/InstallCertificateFromStorage.java new file mode 100644 index 00000000000..90e68d41164 --- /dev/null +++ b/src/com/android/settings/security/InstallCertificateFromStorage.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.security; + +import android.app.settings.SettingsEnums; +import android.content.Context; +import android.os.UserManager; + +import com.android.settings.R; +import com.android.settings.dashboard.DashboardFragment; +import com.android.settings.search.BaseSearchIndexProvider; +import com.android.settingslib.core.AbstractPreferenceController; +import com.android.settingslib.core.lifecycle.Lifecycle; +import com.android.settingslib.search.SearchIndexable; + +import java.util.ArrayList; +import java.util.List; + +/** + * Install certificate from storage settings. + */ +@SearchIndexable +public class InstallCertificateFromStorage extends DashboardFragment { + + private static final String TAG = "InstallCertificateFromStorage"; + + @Override + public int getMetricsCategory() { + return SettingsEnums.INSTALL_CERTIFICATE_FROM_STORAGE; + } + + @Override + protected int getPreferenceScreenResId() { + return R.xml.install_certificate_from_storage; + } + + @Override + protected String getLogTag() { + return TAG; + } + + @Override + protected List createPreferenceControllers(Context context) { + return new ArrayList(); + } + + private static List buildPreferenceControllers(Context context, + Lifecycle lifecycle) { + final List controllers = new ArrayList<>(); + controllers.add(new InstallCaCertificatePreferenceController(context)); + controllers.add(new InstallUserCertificatePreferenceController(context)); + controllers.add(new InstallWifiCertificatePreferenceController(context)); + return controllers; + } + + @Override + public int getHelpResource() { + return R.string.help_url_install_certificate; + } + + /** + * For Search. Please keep it in sync when updating "createPreferenceHierarchy()" + */ + public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new BaseSearchIndexProvider(R.xml.install_certificate_from_storage) { + @Override + public List createPreferenceControllers( + Context context) { + return buildPreferenceControllers(context, null /* lifecycle */); + } + + @Override + protected boolean isPageSearchEnabled(Context context) { + final UserManager um = (UserManager) context.getSystemService( + Context.USER_SERVICE); + return um.isAdminUser(); + } + }; +} diff --git a/src/com/android/settings/security/InstallCredentialsPreferenceController.java b/src/com/android/settings/security/InstallCertificatePreferenceController.java similarity index 78% rename from src/com/android/settings/security/InstallCredentialsPreferenceController.java rename to src/com/android/settings/security/InstallCertificatePreferenceController.java index ca9ed2657a5..2133069c94d 100644 --- a/src/com/android/settings/security/InstallCredentialsPreferenceController.java +++ b/src/com/android/settings/security/InstallCertificatePreferenceController.java @@ -19,17 +19,17 @@ package com.android.settings.security; import android.content.Context; import android.os.UserManager; -public class InstallCredentialsPreferenceController extends +public class InstallCertificatePreferenceController extends RestrictedEncryptionPreferenceController { - private static final String KEY_CREDENTIALS_INSTALL = "credentials_install"; + private static final String KEY_INSTALL_CERTIFICATE = "install_certificate"; - public InstallCredentialsPreferenceController(Context context) { + public InstallCertificatePreferenceController(Context context) { super(context, UserManager.DISALLOW_CONFIG_CREDENTIALS); } @Override public String getPreferenceKey() { - return KEY_CREDENTIALS_INSTALL; + return KEY_INSTALL_CERTIFICATE; } } diff --git a/src/com/android/settings/security/InstallUserCertificatePreferenceController.java b/src/com/android/settings/security/InstallUserCertificatePreferenceController.java new file mode 100644 index 00000000000..ad2a6068d64 --- /dev/null +++ b/src/com/android/settings/security/InstallUserCertificatePreferenceController.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.security; + +import android.content.Context; +import android.os.UserManager; + +import com.android.settings.core.BasePreferenceController; + +public class InstallUserCertificatePreferenceController extends + BasePreferenceController { + + private static final String KEY_INSTALL_USER_CERTIFICATE = "install_user_certificate"; + + public InstallUserCertificatePreferenceController(Context context) { + super(context, UserManager.DISALLOW_CONFIG_CREDENTIALS); + } + + @Override + public int getAvailabilityStatus() { + return AVAILABLE; + } + + @Override + public String getPreferenceKey() { + return KEY_INSTALL_USER_CERTIFICATE; + } +} diff --git a/src/com/android/settings/security/InstallWifiCertificatePreferenceController.java b/src/com/android/settings/security/InstallWifiCertificatePreferenceController.java new file mode 100644 index 00000000000..c7df34efd0c --- /dev/null +++ b/src/com/android/settings/security/InstallWifiCertificatePreferenceController.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.security; + +import android.content.Context; +import android.os.UserManager; + +import com.android.settings.core.BasePreferenceController; + +public class InstallWifiCertificatePreferenceController extends + BasePreferenceController { + + private static final String KEY_INSTALL_WIFI_CERTIFICATE = "install_wifi_certificate"; + + public InstallWifiCertificatePreferenceController(Context context) { + super(context, UserManager.DISALLOW_CONFIG_CREDENTIALS); + } + + @Override + public int getAvailabilityStatus() { + return AVAILABLE; + } + + @Override + public String getPreferenceKey() { + return KEY_INSTALL_WIFI_CERTIFICATE; + } +} diff --git a/tests/robotests/src/com/android/settings/security/InstallCertificateFromStorageTest.java b/tests/robotests/src/com/android/settings/security/InstallCertificateFromStorageTest.java new file mode 100644 index 00000000000..61c39fca933 --- /dev/null +++ b/tests/robotests/src/com/android/settings/security/InstallCertificateFromStorageTest.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.security; + +import static com.android.settings.security.InstallCertificateFromStorage.SEARCH_INDEX_DATA_PROVIDER; + +import static com.google.common.truth.Truth.assertThat; + +import android.app.admin.DevicePolicyManager; +import android.app.settings.SettingsEnums; +import android.content.Context; +import android.os.UserManager; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.shadows.ShadowApplication; + +import java.util.ArrayList; +import java.util.List; + +@RunWith(RobolectricTestRunner.class) +public class InstallCertificateFromStorageTest { + + @Mock + private UserManager mUserManager; + + @Mock + private DevicePolicyManager mDevicePolicyManager; + + private Context mContext; + + private List mTestKeys; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + ShadowApplication application = ShadowApplication.getInstance(); + application.setSystemService(Context.DEVICE_POLICY_SERVICE, mDevicePolicyManager); + application.setSystemService(Context.USER_SERVICE, mUserManager); + mContext = RuntimeEnvironment.application; + setUpTestKeys(); + } + + private void setUpTestKeys() { + mTestKeys = new ArrayList<>(); + mTestKeys.add("install_certificate_from_storage"); + mTestKeys.add("certificate_types"); + mTestKeys.add("install_ca_certificate"); + mTestKeys.add("install_user_certificate"); + mTestKeys.add("install_wifi_certificate"); + } + + @Test + public void getMetricsCategory_shouldReturnInstallCertificateFromStorage() { + InstallCertificateFromStorage fragment = new InstallCertificateFromStorage(); + assertThat(fragment.getMetricsCategory()).isEqualTo( + SettingsEnums.INSTALL_CERTIFICATE_FROM_STORAGE); + } + + @Test + public void getNonIndexableKeys_existInXmlLayout() { + final List nonIndexableKeys = + SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext); + + assertThat(nonIndexableKeys).containsAllIn(mTestKeys); + } + +} diff --git a/tests/robotests/src/com/android/settings/security/RestrictedEncryptionPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/security/RestrictedEncryptionPreferenceControllerTest.java index 79ece904dbb..672d31724d2 100644 --- a/tests/robotests/src/com/android/settings/security/RestrictedEncryptionPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/security/RestrictedEncryptionPreferenceControllerTest.java @@ -40,9 +40,12 @@ public class RestrictedEncryptionPreferenceControllerTest { private Context mContext; private ShadowUserManager mUserManager; private CredentialStoragePreferenceController mCredentialStoragePreferenceController; - private InstallCredentialsPreferenceController mInstallCredentialsPreferenceController; + private InstallCertificatePreferenceController mInstallCertificatePreferenceController; private ResetCredentialsPreferenceController mResetCredentialsPreferenceController; private UserCredentialsPreferenceController mUserCredentialsPreferenceController; + private InstallCaCertificatePreferenceController mInstallCaCertificatePreferenceController; + private InstallUserCertificatePreferenceController mInstallUserCertificatePreferenceController; + private InstallWifiCertificatePreferenceController mInstallWifiCertificatePreferenceController; private Lifecycle mLifecycle; private LifecycleOwner mLifecycleOwner; @@ -53,21 +56,30 @@ public class RestrictedEncryptionPreferenceControllerTest { mLifecycle = new Lifecycle(mLifecycleOwner); mCredentialStoragePreferenceController = new CredentialStoragePreferenceController(mContext); - mInstallCredentialsPreferenceController = - new InstallCredentialsPreferenceController(mContext); + mInstallCertificatePreferenceController = + new InstallCertificatePreferenceController(mContext); mResetCredentialsPreferenceController = new ResetCredentialsPreferenceController(mContext, mLifecycle); mUserCredentialsPreferenceController = new UserCredentialsPreferenceController(mContext); + mInstallCaCertificatePreferenceController = + new InstallCaCertificatePreferenceController(mContext); + mInstallUserCertificatePreferenceController = + new InstallUserCertificatePreferenceController(mContext); + mInstallWifiCertificatePreferenceController = + new InstallWifiCertificatePreferenceController(mContext); mUserManager = ShadowUserManager.getShadow(); } @Test public void isAvailable_noRestriction_shouldReturnTrue() { assertThat(mCredentialStoragePreferenceController.isAvailable()).isTrue(); - assertThat(mInstallCredentialsPreferenceController.isAvailable()).isTrue(); + assertThat(mInstallCertificatePreferenceController.isAvailable()).isTrue(); assertThat(mResetCredentialsPreferenceController.isAvailable()).isTrue(); assertThat(mUserCredentialsPreferenceController.isAvailable()).isTrue(); + assertThat(mInstallCaCertificatePreferenceController.isAvailable()).isTrue(); + assertThat(mInstallUserCertificatePreferenceController.isAvailable()).isTrue(); + assertThat(mInstallWifiCertificatePreferenceController.isAvailable()).isTrue(); } @Test @@ -75,8 +87,11 @@ public class RestrictedEncryptionPreferenceControllerTest { mUserManager.addBaseUserRestriction(UserManager.DISALLOW_CONFIG_CREDENTIALS); assertThat(mCredentialStoragePreferenceController.isAvailable()).isFalse(); - assertThat(mInstallCredentialsPreferenceController.isAvailable()).isFalse(); + assertThat(mInstallCertificatePreferenceController.isAvailable()).isFalse(); assertThat(mResetCredentialsPreferenceController.isAvailable()).isFalse(); assertThat(mUserCredentialsPreferenceController.isAvailable()).isFalse(); + assertThat(mInstallCaCertificatePreferenceController.isAvailable()).isFalse(); + assertThat(mInstallUserCertificatePreferenceController.isAvailable()).isFalse(); + assertThat(mInstallWifiCertificatePreferenceController.isAvailable()).isFalse(); } } \ No newline at end of file