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
This commit is contained in:
25
res/drawable/ic_undo_24.xml
Normal file
25
res/drawable/ic_undo_24.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M14.1,8H7.83l2.59,-2.59L9,4 4,9l5,5 1.41,-1.41L7.83,10h6.27c2.15,0 3.9,1.57 3.9,3.5S16.25,17 14.1,17H7v2h7.1c3.25,0 5.9,-2.47 5.9,-5.5S17.35,8 14.1,8z"/>
|
||||
</vector>
|
@@ -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"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/number_of_uris"
|
||||
style="@style/AppAuthenticationPolicyNumberOfUrisText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/uris"
|
||||
android:layout_width="wrap_content"
|
||||
@@ -47,4 +55,11 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/expand"
|
||||
style="@style/AppAuthenticationExpander"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:visibility="gone"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
31
res/layout/credential_management_app_policy.xml
Normal file
31
res/layout/credential_management_app_policy.xml
Normal file
@@ -0,0 +1,31 @@
|
||||
<!--
|
||||
~ 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.
|
||||
-->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="5dip"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingTop="8dp"
|
||||
android:scrollbars="vertical"/>
|
||||
|
||||
</LinearLayout>
|
@@ -6335,6 +6335,14 @@
|
||||
<string name="request_manage_credentials_allow">Allow</string>
|
||||
<!-- Label for floating action button to scroll to the end of the authentication policy list [CHAR LIMIT=30] -->
|
||||
<string name="request_manage_credentials_more">Show more</string>
|
||||
<!-- Title of preference for the certificate management app [CHAR LIMIT=30] -->
|
||||
<string name="certificate_management_app">Certificate management app</string>
|
||||
<!-- Summary if there is no certificate management app [CHAR_LIMIT=NONE] -->
|
||||
<string name="no_certificate_management_app">None</string>
|
||||
<!-- Summary of preference if there is a certificate management app [CHAR LIMIT=NONE] -->
|
||||
<string name="certificate_management_app_description">Certificates installed by this app identify you to the apps and URLs below</string>
|
||||
<!-- Label for button to remove the credential management app [CHAR LIMIT=30] -->
|
||||
<string name="remove_credential_management_app">Remove</string>
|
||||
|
||||
<!-- Sound settings screen, setting check box label -->
|
||||
<string name="emergency_tone_title">Emergency dialing signal</string>
|
||||
|
@@ -816,13 +816,13 @@
|
||||
<style name="RequestManageCredentialsTitle">
|
||||
<item name="android:layout_marginTop">24dp</item>
|
||||
<item name="android:textSize">36sp</item>
|
||||
<item name="android:textColor">#202124</item>
|
||||
<item name="android:textColor">?android:attr/textColorPrimary</item>
|
||||
</style>
|
||||
|
||||
<style name="RequestManageCredentialsDescription">
|
||||
<item name="android:layout_marginTop">24dp</item>
|
||||
<item name="android:textSize">18sp</item>
|
||||
<item name="android:textColor">#202124</item>
|
||||
<item name="android:textColor">?android:attr/textColorPrimary</item>
|
||||
</style>
|
||||
|
||||
<style name="AppAuthenticationPolicyItem">
|
||||
@@ -838,12 +838,25 @@
|
||||
<style name="AppAuthenticationPolicyText">
|
||||
<item name="android:maxLines">1</item>
|
||||
<item name="android:textSize">20sp</item>
|
||||
<item name="android:textColor">#202124</item>
|
||||
<item name="android:textColor">?android:attr/textColorPrimary</item>
|
||||
</style>
|
||||
|
||||
<style name="AppAuthenticationPolicyNumberOfUrisText">
|
||||
<item name="android:layout_marginTop">4dp</item>
|
||||
<item name="android:textSize">16sp</item>
|
||||
<item name="android:textColor">?android:attr/textColorSecondary</item>
|
||||
<item name="android:alpha">0.7</item>
|
||||
</style>
|
||||
|
||||
<style name="AppAuthenticationExpander">
|
||||
<item name="android:layout_marginTop">24dp</item>
|
||||
<item name="android:layout_alignParentEnd">true</item>
|
||||
<item name="android:scaleType">fitEnd</item>
|
||||
</style>
|
||||
|
||||
<style name="AppUriAuthenticationPolicyText">
|
||||
<item name="android:maxLines">1</item>
|
||||
<item name="android:textSize">16sp</item>
|
||||
<item name="android:textColor">#5F6368</item>
|
||||
<item name="android:textColor">?android:attr/textColorSecondary</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
47
res/xml/credential_management_app_fragment.xml
Normal file
47
res/xml/credential_management_app_fragment.xml
Normal file
@@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ 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.
|
||||
-->
|
||||
<PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:settings="http://schemas.android.com/apk/res-auto"
|
||||
android:title="@string/certificate_management_app">
|
||||
|
||||
<!-- Header -->
|
||||
<com.android.settingslib.widget.LayoutPreference
|
||||
android:key="header"
|
||||
android:layout="@layout/settings_entity_header"
|
||||
android:selectable="false"
|
||||
android:order="-10000"
|
||||
settings:allowDividerBelow="true"
|
||||
settings:controller="com.android.settings.security.CredentialManagementAppHeaderController"/>
|
||||
|
||||
<!-- Buttons -->
|
||||
<com.android.settingslib.widget.ActionButtonsPreference
|
||||
android:key="buttons"
|
||||
android:selectable="true"
|
||||
android:order="-9999"
|
||||
settings:allowDividerAbove="true"
|
||||
settings:allowDividerBelow="true"
|
||||
settings:controller="com.android.settings.security.CredentialManagementAppButtonsController"/>
|
||||
|
||||
<!-- Authentication Policy -->
|
||||
<PreferenceCategory
|
||||
android:key="authentication_policy"
|
||||
android:layout="@layout/preference_category_no_label"
|
||||
android:title="@string/summary_placeholder"
|
||||
settings:controller="com.android.settings.security.CredentialManagementAppPolicyController"/>
|
||||
|
||||
</PreferenceScreen>
|
@@ -69,6 +69,13 @@
|
||||
|
||||
</com.android.settingslib.RestrictedPreference>
|
||||
|
||||
<Preference
|
||||
android:key="certificate_management_app"
|
||||
android:title="@string/certificate_management_app"
|
||||
android:summary="@string/summary_placeholder"
|
||||
android:fragment="com.android.settings.security.CredentialManagementAppFragment"
|
||||
settings:controller="com.android.settings.security.CredentialManagementAppPreferenceController"/>
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
</PreferenceScreen>
|
||||
|
@@ -59,6 +59,9 @@ public class CredentialManagementAppAdapter extends RecyclerView.Adapter<Recycle
|
||||
private final PackageManager mPackageManager;
|
||||
private final RecyclerView.RecycledViewPool mViewPool;
|
||||
|
||||
private final boolean mIncludeHeader;
|
||||
private final boolean mIncludeExpander;
|
||||
|
||||
/**
|
||||
* View holder for the header in the request manage credentials screen.
|
||||
*/
|
||||
@@ -96,13 +99,29 @@ public class CredentialManagementAppAdapter extends RecyclerView.Adapter<Recycle
|
||||
public class AppAuthenticationViewHolder extends RecyclerView.ViewHolder {
|
||||
private final ImageView mAppIconView;
|
||||
private final TextView mAppNameView;
|
||||
RecyclerView mChildRecyclerView;
|
||||
private final TextView mNumberOfUrisView;
|
||||
private final ImageView mExpanderIconView;
|
||||
private final RecyclerView mChildRecyclerView;
|
||||
private final List<String> 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<Recycle
|
||||
mAppIconView.setImageDrawable(null);
|
||||
mAppNameView.setText(appName);
|
||||
}
|
||||
bindPolicyView(appName);
|
||||
}
|
||||
|
||||
private void bindPolicyView(String appName) {
|
||||
if (mIncludeExpander) {
|
||||
mExpanderIconView.setVisibility(View.VISIBLE);
|
||||
if (mExpandedApps.contains(appName)) {
|
||||
mNumberOfUrisView.setVisibility(View.GONE);
|
||||
mExpanderIconView.setImageResource(R.drawable.ic_expand_less);
|
||||
bindChildView(mAppUriAuthentication.get(appName));
|
||||
} else {
|
||||
mChildRecyclerView.setVisibility(View.GONE);
|
||||
mNumberOfUrisView.setVisibility(View.VISIBLE);
|
||||
mNumberOfUrisView.setText(
|
||||
getNumberOfUrlsText(mAppUriAuthentication.get(appName)));
|
||||
mExpanderIconView.setImageResource(
|
||||
com.android.internal.R.drawable.ic_expand_more);
|
||||
}
|
||||
} else {
|
||||
mNumberOfUrisView.setVisibility(View.GONE);
|
||||
mExpanderIconView.setVisibility(View.GONE);
|
||||
bindChildView(mAppUriAuthentication.get(appName));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind the list of URIs for an app.
|
||||
*/
|
||||
public void bindChildView(Map<Uri, String> urisToAliases) {
|
||||
private void bindChildView(Map<Uri, String> 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<Uri, String> urisToAliases) {
|
||||
String url = urisToAliases.size() > 1 ? " URLs" : " URL";
|
||||
return urisToAliases.size() + url;
|
||||
}
|
||||
}
|
||||
|
||||
public CredentialManagementAppAdapter(Context context, String credentialManagerPackage,
|
||||
Map<String, Map<Uri, String>> appUriAuthentication) {
|
||||
Map<String, Map<Uri, String>> 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<Recycle
|
||||
if (viewHolder instanceof HeaderViewHolder) {
|
||||
((HeaderViewHolder) viewHolder).bindView();
|
||||
} else if (viewHolder instanceof AppAuthenticationViewHolder) {
|
||||
((AppAuthenticationViewHolder) viewHolder).bindView(i - 1);
|
||||
int position = mIncludeHeader ? i - 1 : i;
|
||||
((AppAuthenticationViewHolder) viewHolder).bindView(position);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
// Add an extra view to show the header view
|
||||
return mAppUriAuthentication.size() + 1;
|
||||
return mIncludeHeader ? mAppUriAuthentication.size() + 1 : mAppUriAuthentication.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
if (position == 0) {
|
||||
if (mIncludeHeader && position == 0) {
|
||||
return HEADER_VIEW;
|
||||
}
|
||||
return super.getItemViewType(position);
|
||||
|
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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.AppOpsManager;
|
||||
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.PreferenceScreen;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settingslib.widget.ActionButtonsPreference;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* Controller that shows the remove button of the credential management app, which allows the user
|
||||
* to remove the credential management app and its certificates.
|
||||
*/
|
||||
public class CredentialManagementAppButtonsController 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 final AppOpsManager mAppOpsManager;
|
||||
private boolean mHasCredentialManagerPackage;
|
||||
private String mCredentialManagerPackageName;
|
||||
|
||||
public CredentialManagementAppButtonsController(Context context, String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
mPackageManager = context.getPackageManager();
|
||||
mAppOpsManager = context.getSystemService(AppOpsManager.class);
|
||||
}
|
||||
|
||||
@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 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");
|
||||
}
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
@@ -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));
|
||||
}
|
||||
}
|
@@ -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()));
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -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));
|
||||
}
|
||||
}
|
@@ -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<SearchIndexableResource> 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);
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user