From 672c2aaaecb9b20a07919e666307bb8b16c46706 Mon Sep 17 00:00:00 2001 From: Alex Johnston Date: Fri, 27 Nov 2020 21:35:50 +0000 Subject: [PATCH] Add credential management app preference to Settings Background * This is part of the work to support a credential management app on unmanaged devices. Changes * Add a preference controller which will only be enabled if there is a credential management app. * Add a fragment to display details on the credential management app and its policy. Add a remove button to remove the credential management app. * Link CredentialManagementAppAdapter to new fragment and add expander. Manual Testing * Verify preference is disabled if there is no credential management app. * Verify preference summary shows credential mangement app name if a credential management app exists. * Verify fragment details page displays the authentication policy correctly. Bug: 165641221 Test: Manual testing make RunSettingsRoboTests -j ROBOTEST_FILTER=com.android.settings.security.CredentialManagementAppFragmentTest make RunSettingsRoboTests -j ROBOTEST_FILTER=com.android.settings.security.CredentialManagementAppControllerTest Change-Id: I06d6b88d0c89022f7a6cbf3031834defcb54bd51 --- res/drawable/ic_undo_24.xml | 25 ++++ res/layout/app_authentication_item.xml | 15 +++ .../credential_management_app_policy.xml | 31 +++++ res/values/strings.xml | 8 ++ res/values/styles.xml | 21 +++- .../credential_management_app_fragment.xml | 47 ++++++++ res/xml/encryption_and_credential.xml | 7 ++ .../CredentialManagementAppAdapter.java | 65 +++++++++-- ...dentialManagementAppButtonsController.java | 109 ++++++++++++++++++ .../CredentialManagementAppFragment.java | 52 +++++++++ ...edentialManagementAppHeaderController.java | 102 ++++++++++++++++ ...edentialManagementAppPolicyController.java | 49 ++++++++ ...edentialManagementAppPolicyPreference.java | 89 ++++++++++++++ ...tialManagementAppPreferenceController.java | 90 +++++++++++++++ .../security/RequestManageCredentials.java | 3 +- ...ialManagementAppButtonsControllerTest.java | 51 ++++++++ ...CredentialManagementAppControllerTest.java | 65 +++++++++++ .../CredentialManagementAppFragmentTest.java | 72 ++++++++++++ ...tialManagementAppHeaderControllerTest.java | 51 ++++++++ 19 files changed, 940 insertions(+), 12 deletions(-) create mode 100644 res/drawable/ic_undo_24.xml create mode 100644 res/layout/credential_management_app_policy.xml create mode 100644 res/xml/credential_management_app_fragment.xml create mode 100644 src/com/android/settings/security/CredentialManagementAppButtonsController.java create mode 100644 src/com/android/settings/security/CredentialManagementAppFragment.java create mode 100644 src/com/android/settings/security/CredentialManagementAppHeaderController.java create mode 100644 src/com/android/settings/security/CredentialManagementAppPolicyController.java create mode 100644 src/com/android/settings/security/CredentialManagementAppPolicyPreference.java create mode 100644 src/com/android/settings/security/CredentialManagementAppPreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/security/CredentialManagementAppButtonsControllerTest.java create mode 100644 tests/robotests/src/com/android/settings/security/CredentialManagementAppControllerTest.java create mode 100644 tests/robotests/src/com/android/settings/security/CredentialManagementAppFragmentTest.java create mode 100644 tests/robotests/src/com/android/settings/security/CredentialManagementAppHeaderControllerTest.java diff --git a/res/drawable/ic_undo_24.xml b/res/drawable/ic_undo_24.xml new file mode 100644 index 00000000000..0a8e1495287 --- /dev/null +++ b/res/drawable/ic_undo_24.xml @@ -0,0 +1,25 @@ + + + + \ No newline at end of file diff --git a/res/layout/app_authentication_item.xml b/res/layout/app_authentication_item.xml index 2df923f75f0..423722e5f70 100644 --- a/res/layout/app_authentication_item.xml +++ b/res/layout/app_authentication_item.xml @@ -30,6 +30,7 @@ android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_toRightOf="@id/app_icon" + android:layout_toLeftOf="@id/expand" android:layout_marginTop="16dp" android:layout_marginBottom="16dp" android:orientation="vertical"> @@ -40,6 +41,13 @@ android:layout_width="wrap_content" android:layout_height="wrap_content"/> + + + + diff --git a/res/layout/credential_management_app_policy.xml b/res/layout/credential_management_app_policy.xml new file mode 100644 index 00000000000..15153e94195 --- /dev/null +++ b/res/layout/credential_management_app_policy.xml @@ -0,0 +1,31 @@ + + + + + + diff --git a/res/values/strings.xml b/res/values/strings.xml index 4ce45c04bf5..764cc293ebd 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -6335,6 +6335,14 @@ Allow Show more + + Certificate management app + + None + + Certificates installed by this app identify you to the apps and URLs below + + Remove Emergency dialing signal diff --git a/res/values/styles.xml b/res/values/styles.xml index c447decd89c..e27095d962c 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -816,13 +816,13 @@ + + + + diff --git a/res/xml/credential_management_app_fragment.xml b/res/xml/credential_management_app_fragment.xml new file mode 100644 index 00000000000..93924145004 --- /dev/null +++ b/res/xml/credential_management_app_fragment.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + diff --git a/res/xml/encryption_and_credential.xml b/res/xml/encryption_and_credential.xml index fe0498d9045..f107b58b107 100644 --- a/res/xml/encryption_and_credential.xml +++ b/res/xml/encryption_and_credential.xml @@ -69,6 +69,13 @@ + + diff --git a/src/com/android/settings/security/CredentialManagementAppAdapter.java b/src/com/android/settings/security/CredentialManagementAppAdapter.java index 707f598445b..e56fc63c443 100644 --- a/src/com/android/settings/security/CredentialManagementAppAdapter.java +++ b/src/com/android/settings/security/CredentialManagementAppAdapter.java @@ -59,6 +59,9 @@ public class CredentialManagementAppAdapter extends RecyclerView.Adapter mExpandedApps; public AppAuthenticationViewHolder(View view) { super(view); mAppIconView = view.findViewById(R.id.app_icon); mAppNameView = view.findViewById(R.id.app_name); + mNumberOfUrisView = view.findViewById(R.id.number_of_uris); + mExpanderIconView = view.findViewById(R.id.expand); mChildRecyclerView = view.findViewById(R.id.uris); + mExpandedApps = new ArrayList<>(); + + mExpanderIconView.setOnClickListener(view1 -> { + final String appName = mSortedAppNames.get(getBindingAdapterPosition()); + if (mExpandedApps.contains(appName)) { + mExpandedApps.remove(appName); + } else { + mExpandedApps.add(appName); + } + bindPolicyView(appName); + }); } /** @@ -119,32 +138,63 @@ public class CredentialManagementAppAdapter extends RecyclerView.Adapter urisToAliases) { + private void bindChildView(Map urisToAliases) { LinearLayoutManager layoutManager = new LinearLayoutManager( mChildRecyclerView.getContext(), RecyclerView.VERTICAL, false); layoutManager.setInitialPrefetchItemCount(urisToAliases.size()); UriAuthenticationPolicyAdapter childItemAdapter = new UriAuthenticationPolicyAdapter(new ArrayList<>(urisToAliases.keySet())); mChildRecyclerView.setLayoutManager(layoutManager); + mChildRecyclerView.setVisibility(View.VISIBLE); mChildRecyclerView.setAdapter(childItemAdapter); mChildRecyclerView.setRecycledViewPool(mViewPool); } + + private String getNumberOfUrlsText(Map urisToAliases) { + String url = urisToAliases.size() > 1 ? " URLs" : " URL"; + return urisToAliases.size() + url; + } } public CredentialManagementAppAdapter(Context context, String credentialManagerPackage, - Map> appUriAuthentication) { + Map> appUriAuthentication, + boolean includeHeader, boolean includeExpander) { mContext = context; mCredentialManagerPackage = credentialManagerPackage; mPackageManager = context.getPackageManager(); mAppUriAuthentication = appUriAuthentication; mSortedAppNames = sortPackageNames(mAppUriAuthentication); mViewPool = new RecyclerView.RecycledViewPool(); + mIncludeHeader = includeHeader; + mIncludeExpander = includeExpander; } /** @@ -198,19 +248,20 @@ public class CredentialManagementAppAdapter extends RecyclerView.Adapter { + try { + IKeyChainService service = KeyChain.bind(mContext).getService(); + mHasCredentialManagerPackage = service.hasCredentialManagementApp(); + mCredentialManagerPackageName = service.getCredentialManagementAppPackageName(); + } catch (InterruptedException | RemoteException e) { + Log.e(TAG, "Unable to display credential management app buttons"); + } + mHandler.post(() -> displayButtons(screen)); + }); + } + + private void displayButtons(PreferenceScreen screen) { + if (mHasCredentialManagerPackage) { + ((ActionButtonsPreference) screen.findPreference(getPreferenceKey())) + .setButton1Text(R.string.remove_credential_management_app) + .setButton1Icon(R.drawable.ic_undo_24) + .setButton1OnClickListener(view -> removeCredentialManagementApp()); + } + } + + private void removeCredentialManagementApp() { + try { + ApplicationInfo appInfo = mPackageManager.getApplicationInfo( + mCredentialManagerPackageName, 0); + mAppOpsManager.setMode(AppOpsManager.OP_MANAGE_CREDENTIALS, + appInfo.uid, mCredentialManagerPackageName, AppOpsManager.MODE_DEFAULT); + mExecutor.execute(() -> { + try { + IKeyChainService service = KeyChain.bind(mContext).getService(); + service.removeCredentialManagementApp(); + } catch (InterruptedException | RemoteException e) { + Log.e(TAG, "Unable to remove the credential management app"); + } + }); + } catch (PackageManager.NameNotFoundException e) { + Log.e(TAG, "Unable to remove the credential management app"); + } + } +} diff --git a/src/com/android/settings/security/CredentialManagementAppFragment.java b/src/com/android/settings/security/CredentialManagementAppFragment.java new file mode 100644 index 00000000000..5544ee6cc7e --- /dev/null +++ b/src/com/android/settings/security/CredentialManagementAppFragment.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2020 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 com.android.settings.R; +import com.android.settings.dashboard.DashboardFragment; +import com.android.settings.search.BaseSearchIndexProvider; +import com.android.settingslib.search.SearchIndexable; + +/** + * Settings fragment containing the credential management app. The credential management app has + * the ability to manage the user's credentials on unmanaged devices. + */ +@SearchIndexable +public class CredentialManagementAppFragment extends DashboardFragment { + + private static final String TAG = "CredentialManagementApp"; + + @Override + protected int getPreferenceScreenResId() { + return R.xml.credential_management_app_fragment; + } + + @Override + protected String getLogTag() { + return TAG; + } + + @Override + public int getMetricsCategory() { + return SettingsEnums.CREDENTIAL_MANAGEMENT_APP; + } + + public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new BaseSearchIndexProvider(R.xml.credential_management_app_fragment); +} diff --git a/src/com/android/settings/security/CredentialManagementAppHeaderController.java b/src/com/android/settings/security/CredentialManagementAppHeaderController.java new file mode 100644 index 00000000000..975c49d0a04 --- /dev/null +++ b/src/com/android/settings/security/CredentialManagementAppHeaderController.java @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2020 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.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.os.Handler; +import android.os.Looper; +import android.os.RemoteException; +import android.security.IKeyChainService; +import android.security.KeyChain; +import android.util.Log; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.preference.PreferenceScreen; + +import com.android.settings.R; +import com.android.settings.core.BasePreferenceController; +import com.android.settingslib.widget.LayoutPreference; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * Controller that shows the header of the credential management app, which includes credential + * management app's name, icon and a description. + */ +public class CredentialManagementAppHeaderController extends BasePreferenceController { + + private static final String TAG = "CredentialManagementApp"; + + private final ExecutorService mExecutor = Executors.newSingleThreadExecutor(); + private final Handler mHandler = new Handler(Looper.getMainLooper()); + + public CredentialManagementAppHeaderController(Context context, String preferenceKey) { + super(context, preferenceKey); + mPackageManager = context.getPackageManager(); + } + + private final PackageManager mPackageManager; + private boolean mHasCredentialManagerPackage; + private String mCredentialManagerPackageName; + + @Override + public int getAvailabilityStatus() { + return AVAILABLE_UNSEARCHABLE; + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + + mExecutor.execute(() -> { + try { + IKeyChainService service = KeyChain.bind(mContext).getService(); + mHasCredentialManagerPackage = service.hasCredentialManagementApp(); + mCredentialManagerPackageName = service.getCredentialManagementAppPackageName(); + } catch (InterruptedException | RemoteException e) { + Log.e(TAG, "Unable to display credential management app header"); + } + mHandler.post(() -> displayHeader(screen)); + }); + } + + private void displayHeader(PreferenceScreen screen) { + LayoutPreference headerPref = screen.findPreference(getPreferenceKey()); + ImageView mAppIconView = headerPref.findViewById(R.id.entity_header_icon); + TextView mTitleView = headerPref.findViewById(R.id.entity_header_title); + TextView mDescriptionView = headerPref.findViewById(R.id.entity_header_summary); + + try { + ApplicationInfo applicationInfo = + mPackageManager.getApplicationInfo(mCredentialManagerPackageName, 0); + mAppIconView.setImageDrawable(mPackageManager.getApplicationIcon(applicationInfo)); + mTitleView.setText(applicationInfo.loadLabel(mPackageManager)); + } catch (PackageManager.NameNotFoundException e) { + mAppIconView.setImageDrawable(null); + mTitleView.setText(mCredentialManagerPackageName); + } + // TODO (b/165641221): The description should be multi-lined, which is currently a + // limitation of using Settings entity header. However, the Settings entity header + // should be used to be consistent with the rest of Settings. + mDescriptionView.setText( + mContext.getString(R.string.request_manage_credentials_description)); + } +} diff --git a/src/com/android/settings/security/CredentialManagementAppPolicyController.java b/src/com/android/settings/security/CredentialManagementAppPolicyController.java new file mode 100644 index 00000000000..9561c5f13f1 --- /dev/null +++ b/src/com/android/settings/security/CredentialManagementAppPolicyController.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2020 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.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE; + +import android.content.Context; + +import androidx.preference.PreferenceGroup; +import androidx.preference.PreferenceScreen; + +import com.android.settings.core.BasePreferenceController; + +/** + * Controller that shows the credential management app's authentication policy. + */ +public class CredentialManagementAppPolicyController extends BasePreferenceController { + + public CredentialManagementAppPolicyController(Context context, String preferenceKey) { + super(context, preferenceKey); + } + + @Override + public int getAvailabilityStatus() { + return AVAILABLE_UNSEARCHABLE; + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + + PreferenceGroup group = screen.findPreference(getPreferenceKey()); + group.addPreference(new CredentialManagementAppPolicyPreference(group.getContext())); + } +} diff --git a/src/com/android/settings/security/CredentialManagementAppPolicyPreference.java b/src/com/android/settings/security/CredentialManagementAppPolicyPreference.java new file mode 100644 index 00000000000..1747be30530 --- /dev/null +++ b/src/com/android/settings/security/CredentialManagementAppPolicyPreference.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2020 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.Handler; +import android.os.Looper; +import android.os.RemoteException; +import android.security.AppUriAuthenticationPolicy; +import android.security.IKeyChainService; +import android.security.KeyChain; +import android.util.Log; + +import androidx.preference.Preference; +import androidx.preference.PreferenceViewHolder; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.android.settings.R; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * Preference that shows the credential management app's authentication policy. + */ +public class CredentialManagementAppPolicyPreference extends Preference { + + private static final String TAG = "CredentialManagementApp"; + + private final ExecutorService mExecutor = Executors.newSingleThreadExecutor(); + private final Handler mHandler = new Handler(Looper.getMainLooper()); + + private final Context mContext; + + private boolean mHasCredentialManagerPackage; + private String mCredentialManagerPackageName; + private AppUriAuthenticationPolicy mCredentialManagerPolicy; + + public CredentialManagementAppPolicyPreference(Context context) { + super(context); + setLayoutResource(R.layout.credential_management_app_policy); + mContext = context; + } + + @Override + public void onBindViewHolder(PreferenceViewHolder view) { + super.onBindViewHolder(view); + + mExecutor.execute(() -> { + try { + IKeyChainService service = KeyChain.bind(mContext).getService(); + mHasCredentialManagerPackage = service.hasCredentialManagementApp(); + mCredentialManagerPackageName = service.getCredentialManagementAppPackageName(); + mCredentialManagerPolicy = service.getCredentialManagementAppPolicy(); + } catch (InterruptedException | RemoteException e) { + Log.e(TAG, "Unable to display credential management app policy"); + } + mHandler.post(() -> displayPolicy(view)); + }); + } + + private void displayPolicy(PreferenceViewHolder view) { + if (mHasCredentialManagerPackage) { + RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.recycler_view); + recyclerView.setLayoutManager(new LinearLayoutManager(mContext)); + + CredentialManagementAppAdapter recyclerViewAdapter = new CredentialManagementAppAdapter( + mContext, mCredentialManagerPackageName, + mCredentialManagerPolicy.getAppAndUriMappings(), + /* include header= */ false, /* include expander= */ true); + recyclerView.setAdapter(recyclerViewAdapter); + } + } +} diff --git a/src/com/android/settings/security/CredentialManagementAppPreferenceController.java b/src/com/android/settings/security/CredentialManagementAppPreferenceController.java new file mode 100644 index 00000000000..107b8f28b6a --- /dev/null +++ b/src/com/android/settings/security/CredentialManagementAppPreferenceController.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2020 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.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.os.Handler; +import android.os.Looper; +import android.os.RemoteException; +import android.security.IKeyChainService; +import android.security.KeyChain; +import android.util.Log; + +import androidx.preference.Preference; + +import com.android.settings.R; +import com.android.settings.core.BasePreferenceController; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * Controller that shows and updates the credential management app summary. + */ +public class CredentialManagementAppPreferenceController extends BasePreferenceController { + + private static final String TAG = "CredentialManagementApp"; + + private final ExecutorService mExecutor = Executors.newSingleThreadExecutor(); + private final Handler mHandler = new Handler(Looper.getMainLooper()); + + private final PackageManager mPackageManager; + private boolean mHasCredentialManagerPackage; + private String mCredentialManagerPackageName; + + public CredentialManagementAppPreferenceController(Context context, String key) { + super(context, key); + mPackageManager = context.getPackageManager(); + } + + @Override + public int getAvailabilityStatus() { + return AVAILABLE; + } + + @Override + public void updateState(Preference preference) { + mExecutor.execute(() -> { + try { + IKeyChainService service = KeyChain.bind(mContext).getService(); + mHasCredentialManagerPackage = service.hasCredentialManagementApp(); + mCredentialManagerPackageName = service.getCredentialManagementAppPackageName(); + } catch (InterruptedException | RemoteException e) { + Log.e(TAG, "Unable to display credential management app preference"); + } + mHandler.post(() -> displayPreference(preference)); + }); + } + + private void displayPreference(Preference preference) { + if (mHasCredentialManagerPackage) { + preference.setEnabled(true); + try { + ApplicationInfo applicationInfo = + mPackageManager.getApplicationInfo(mCredentialManagerPackageName, 0); + preference.setSummary(applicationInfo.loadLabel(mPackageManager)); + } catch (PackageManager.NameNotFoundException e) { + preference.setSummary(mCredentialManagerPackageName); + } + } else { + preference.setEnabled(false); + preference.setSummary(R.string.no_certificate_management_app); + } + } +} diff --git a/src/com/android/settings/security/RequestManageCredentials.java b/src/com/android/settings/security/RequestManageCredentials.java index 9d2d51e315d..36b055ab322 100644 --- a/src/com/android/settings/security/RequestManageCredentials.java +++ b/src/com/android/settings/security/RequestManageCredentials.java @@ -93,7 +93,8 @@ public class RequestManageCredentials extends Activity { mRecyclerView.setLayoutManager(mLayoutManager); CredentialManagementAppAdapter recyclerViewAdapter = new CredentialManagementAppAdapter( - this, mCredentialManagerPackage, mAuthenticationPolicy.getAppAndUriMappings()); + this, mCredentialManagerPackage, mAuthenticationPolicy.getAppAndUriMappings(), + /* include header= */ true, /* include expander= */ false); mRecyclerView.setAdapter(recyclerViewAdapter); } diff --git a/tests/robotests/src/com/android/settings/security/CredentialManagementAppButtonsControllerTest.java b/tests/robotests/src/com/android/settings/security/CredentialManagementAppButtonsControllerTest.java new file mode 100644 index 00000000000..ecc2f2dd1ca --- /dev/null +++ b/tests/robotests/src/com/android/settings/security/CredentialManagementAppButtonsControllerTest.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2020 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 com.android.settings.core.BasePreferenceController; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; + +@RunWith(RobolectricTestRunner.class) +public class CredentialManagementAppButtonsControllerTest { + + private Context mContext; + private CredentialManagementAppButtonsController mController; + + private static final String PREF_KEY_CREDENTIAL_MANAGEMENT_APP = "certificate_management_app"; + + @Before + public void setUp() { + mContext = RuntimeEnvironment.application; + mController = new CredentialManagementAppButtonsController( + mContext, PREF_KEY_CREDENTIAL_MANAGEMENT_APP); + } + + @Test + public void getAvailabilityStatus_shouldAlwaysReturnAvailableUnsearchable() { + assertThat(mController.getAvailabilityStatus()) + .isEqualTo(BasePreferenceController.AVAILABLE_UNSEARCHABLE); + } +} diff --git a/tests/robotests/src/com/android/settings/security/CredentialManagementAppControllerTest.java b/tests/robotests/src/com/android/settings/security/CredentialManagementAppControllerTest.java new file mode 100644 index 00000000000..1e6f203012a --- /dev/null +++ b/tests/robotests/src/com/android/settings/security/CredentialManagementAppControllerTest.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2020 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 androidx.preference.Preference; + +import com.android.settings.R; +import com.android.settings.core.BasePreferenceController; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; + +@RunWith(RobolectricTestRunner.class) +public class CredentialManagementAppControllerTest { + + private Context mContext; + private CredentialManagementAppPreferenceController mController; + private Preference mPreference; + + private static final String PREF_KEY_CREDENTIAL_MANAGEMENT_APP = "certificate_management_app"; + + @Before + public void setUp() { + mContext = RuntimeEnvironment.application; + mController = new CredentialManagementAppPreferenceController( + mContext, PREF_KEY_CREDENTIAL_MANAGEMENT_APP); + mPreference = new Preference(mContext); + } + + @Test + public void getAvailabilityStatus_shouldAlwaysReturnAvailable() { + assertThat(mController.getAvailabilityStatus()) + .isEqualTo(BasePreferenceController.AVAILABLE); + } + + @Test + public void updateState_noCredentialManagementApp_shouldDisablePreference() { + mController.updateState(mPreference); + + assertThat(mPreference.isEnabled()).isEqualTo(false); + assertThat(mPreference.getSummary()).isEqualTo( + mContext.getText(R.string.no_certificate_management_app)); + } +} diff --git a/tests/robotests/src/com/android/settings/security/CredentialManagementAppFragmentTest.java b/tests/robotests/src/com/android/settings/security/CredentialManagementAppFragmentTest.java new file mode 100644 index 00000000000..de19e5cce90 --- /dev/null +++ b/tests/robotests/src/com/android/settings/security/CredentialManagementAppFragmentTest.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2020 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 android.app.settings.SettingsEnums.CREDENTIAL_MANAGEMENT_APP; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; + +import android.content.Context; +import android.provider.SearchIndexableResource; + +import com.android.settings.R; +import com.android.settings.testutils.shadow.ShadowDashboardFragment; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +import java.util.List; + +@RunWith(RobolectricTestRunner.class) +@Config(shadows = ShadowDashboardFragment.class) +public class CredentialManagementAppFragmentTest { + + private CredentialManagementAppFragment mFragment; + private Context mContext; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + mContext = spy(RuntimeEnvironment.application); + mFragment = spy(new CredentialManagementAppFragment()); + + doReturn(mContext).when(mFragment).getContext(); + } + + @Test + public void searchIndexProvider_shouldIndexResource() { + final List indexRes = + CredentialManagementAppFragment.SEARCH_INDEX_DATA_PROVIDER + .getXmlResourcesToIndex(mContext, true /* enabled */); + + assertThat(indexRes).isNotNull(); + assertThat(indexRes.get(0).xmlResId).isEqualTo(R.xml.credential_management_app_fragment); + } + + @Test + public void getMetricsCategory_shouldReturnInstallCertificateFromStorage() { + assertThat(mFragment.getMetricsCategory()).isEqualTo(CREDENTIAL_MANAGEMENT_APP); + } +} diff --git a/tests/robotests/src/com/android/settings/security/CredentialManagementAppHeaderControllerTest.java b/tests/robotests/src/com/android/settings/security/CredentialManagementAppHeaderControllerTest.java new file mode 100644 index 00000000000..e77e4c18152 --- /dev/null +++ b/tests/robotests/src/com/android/settings/security/CredentialManagementAppHeaderControllerTest.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2020 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 com.android.settings.core.BasePreferenceController; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; + +@RunWith(RobolectricTestRunner.class) +public class CredentialManagementAppHeaderControllerTest { + + private Context mContext; + private CredentialManagementAppHeaderController mController; + + private static final String PREF_KEY_CREDENTIAL_MANAGEMENT_APP = "certificate_management_app"; + + @Before + public void setUp() { + mContext = RuntimeEnvironment.application; + mController = new CredentialManagementAppHeaderController( + mContext, PREF_KEY_CREDENTIAL_MANAGEMENT_APP); + } + + @Test + public void getAvailabilityStatus_shouldAlwaysReturnAvailableUnsearchable() { + assertThat(mController.getAvailabilityStatus()) + .isEqualTo(BasePreferenceController.AVAILABLE_UNSEARCHABLE); + } +}