Merge "Add credential management app preference to Settings"
This commit is contained in:
committed by
Android (Google) Code Review
commit
25cca45c09
@@ -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);
|
||||
}
|
||||
bindChildView(mAppUriAuthentication.get(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -97,7 +97,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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user