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_width="fill_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_toRightOf="@id/app_icon"
|
android:layout_toRightOf="@id/app_icon"
|
||||||
|
android:layout_toLeftOf="@id/expand"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:layout_marginBottom="16dp"
|
android:layout_marginBottom="16dp"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
@@ -40,6 +41,13 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="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
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/uris"
|
android:id="@+id/uris"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@@ -47,4 +55,11 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/expand"
|
||||||
|
style="@style/AppAuthenticationExpander"
|
||||||
|
android:layout_width="30dp"
|
||||||
|
android:layout_height="30dp"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
|
||||||
</RelativeLayout>
|
</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>
|
<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] -->
|
<!-- 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>
|
<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 -->
|
<!-- Sound settings screen, setting check box label -->
|
||||||
<string name="emergency_tone_title">Emergency dialing signal</string>
|
<string name="emergency_tone_title">Emergency dialing signal</string>
|
||||||
|
@@ -816,13 +816,13 @@
|
|||||||
<style name="RequestManageCredentialsTitle">
|
<style name="RequestManageCredentialsTitle">
|
||||||
<item name="android:layout_marginTop">24dp</item>
|
<item name="android:layout_marginTop">24dp</item>
|
||||||
<item name="android:textSize">36sp</item>
|
<item name="android:textSize">36sp</item>
|
||||||
<item name="android:textColor">#202124</item>
|
<item name="android:textColor">?android:attr/textColorPrimary</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="RequestManageCredentialsDescription">
|
<style name="RequestManageCredentialsDescription">
|
||||||
<item name="android:layout_marginTop">24dp</item>
|
<item name="android:layout_marginTop">24dp</item>
|
||||||
<item name="android:textSize">18sp</item>
|
<item name="android:textSize">18sp</item>
|
||||||
<item name="android:textColor">#202124</item>
|
<item name="android:textColor">?android:attr/textColorPrimary</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="AppAuthenticationPolicyItem">
|
<style name="AppAuthenticationPolicyItem">
|
||||||
@@ -838,12 +838,25 @@
|
|||||||
<style name="AppAuthenticationPolicyText">
|
<style name="AppAuthenticationPolicyText">
|
||||||
<item name="android:maxLines">1</item>
|
<item name="android:maxLines">1</item>
|
||||||
<item name="android:textSize">20sp</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>
|
||||||
|
|
||||||
<style name="AppUriAuthenticationPolicyText">
|
<style name="AppUriAuthenticationPolicyText">
|
||||||
<item name="android:maxLines">1</item>
|
<item name="android:maxLines">1</item>
|
||||||
<item name="android:textSize">16sp</item>
|
<item name="android:textSize">16sp</item>
|
||||||
<item name="android:textColor">#5F6368</item>
|
<item name="android:textColor">?android:attr/textColorSecondary</item>
|
||||||
</style>
|
</style>
|
||||||
</resources>
|
</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>
|
</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>
|
</PreferenceCategory>
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|
@@ -59,6 +59,9 @@ public class CredentialManagementAppAdapter extends RecyclerView.Adapter<Recycle
|
|||||||
private final PackageManager mPackageManager;
|
private final PackageManager mPackageManager;
|
||||||
private final RecyclerView.RecycledViewPool mViewPool;
|
private final RecyclerView.RecycledViewPool mViewPool;
|
||||||
|
|
||||||
|
private final boolean mIncludeHeader;
|
||||||
|
private final boolean mIncludeExpander;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* View holder for the header in the request manage credentials screen.
|
* 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 {
|
public class AppAuthenticationViewHolder extends RecyclerView.ViewHolder {
|
||||||
private final ImageView mAppIconView;
|
private final ImageView mAppIconView;
|
||||||
private final TextView mAppNameView;
|
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) {
|
public AppAuthenticationViewHolder(View view) {
|
||||||
super(view);
|
super(view);
|
||||||
mAppIconView = view.findViewById(R.id.app_icon);
|
mAppIconView = view.findViewById(R.id.app_icon);
|
||||||
mAppNameView = view.findViewById(R.id.app_name);
|
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);
|
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);
|
mAppIconView.setImageDrawable(null);
|
||||||
mAppNameView.setText(appName);
|
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));
|
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.
|
* 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(
|
LinearLayoutManager layoutManager = new LinearLayoutManager(
|
||||||
mChildRecyclerView.getContext(), RecyclerView.VERTICAL, false);
|
mChildRecyclerView.getContext(), RecyclerView.VERTICAL, false);
|
||||||
layoutManager.setInitialPrefetchItemCount(urisToAliases.size());
|
layoutManager.setInitialPrefetchItemCount(urisToAliases.size());
|
||||||
UriAuthenticationPolicyAdapter childItemAdapter =
|
UriAuthenticationPolicyAdapter childItemAdapter =
|
||||||
new UriAuthenticationPolicyAdapter(new ArrayList<>(urisToAliases.keySet()));
|
new UriAuthenticationPolicyAdapter(new ArrayList<>(urisToAliases.keySet()));
|
||||||
mChildRecyclerView.setLayoutManager(layoutManager);
|
mChildRecyclerView.setLayoutManager(layoutManager);
|
||||||
|
mChildRecyclerView.setVisibility(View.VISIBLE);
|
||||||
mChildRecyclerView.setAdapter(childItemAdapter);
|
mChildRecyclerView.setAdapter(childItemAdapter);
|
||||||
mChildRecyclerView.setRecycledViewPool(mViewPool);
|
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,
|
public CredentialManagementAppAdapter(Context context, String credentialManagerPackage,
|
||||||
Map<String, Map<Uri, String>> appUriAuthentication) {
|
Map<String, Map<Uri, String>> appUriAuthentication,
|
||||||
|
boolean includeHeader, boolean includeExpander) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mCredentialManagerPackage = credentialManagerPackage;
|
mCredentialManagerPackage = credentialManagerPackage;
|
||||||
mPackageManager = context.getPackageManager();
|
mPackageManager = context.getPackageManager();
|
||||||
mAppUriAuthentication = appUriAuthentication;
|
mAppUriAuthentication = appUriAuthentication;
|
||||||
mSortedAppNames = sortPackageNames(mAppUriAuthentication);
|
mSortedAppNames = sortPackageNames(mAppUriAuthentication);
|
||||||
mViewPool = new RecyclerView.RecycledViewPool();
|
mViewPool = new RecyclerView.RecycledViewPool();
|
||||||
|
mIncludeHeader = includeHeader;
|
||||||
|
mIncludeExpander = includeExpander;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -198,19 +248,20 @@ public class CredentialManagementAppAdapter extends RecyclerView.Adapter<Recycle
|
|||||||
if (viewHolder instanceof HeaderViewHolder) {
|
if (viewHolder instanceof HeaderViewHolder) {
|
||||||
((HeaderViewHolder) viewHolder).bindView();
|
((HeaderViewHolder) viewHolder).bindView();
|
||||||
} else if (viewHolder instanceof AppAuthenticationViewHolder) {
|
} else if (viewHolder instanceof AppAuthenticationViewHolder) {
|
||||||
((AppAuthenticationViewHolder) viewHolder).bindView(i - 1);
|
int position = mIncludeHeader ? i - 1 : i;
|
||||||
|
((AppAuthenticationViewHolder) viewHolder).bindView(position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemCount() {
|
public int getItemCount() {
|
||||||
// Add an extra view to show the header view
|
// Add an extra view to show the header view
|
||||||
return mAppUriAuthentication.size() + 1;
|
return mIncludeHeader ? mAppUriAuthentication.size() + 1 : mAppUriAuthentication.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemViewType(int position) {
|
public int getItemViewType(int position) {
|
||||||
if (position == 0) {
|
if (mIncludeHeader && position == 0) {
|
||||||
return HEADER_VIEW;
|
return HEADER_VIEW;
|
||||||
}
|
}
|
||||||
return super.getItemViewType(position);
|
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);
|
mRecyclerView.setLayoutManager(mLayoutManager);
|
||||||
|
|
||||||
CredentialManagementAppAdapter recyclerViewAdapter = new CredentialManagementAppAdapter(
|
CredentialManagementAppAdapter recyclerViewAdapter = new CredentialManagementAppAdapter(
|
||||||
this, mCredentialManagerPackage, mAuthenticationPolicy.getAppAndUriMappings());
|
this, mCredentialManagerPackage, mAuthenticationPolicy.getAppAndUriMappings(),
|
||||||
|
/* include header= */ true, /* include expander= */ false);
|
||||||
mRecyclerView.setAdapter(recyclerViewAdapter);
|
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