1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.security; 18 19 import android.content.Context; 20 import android.content.pm.ApplicationInfo; 21 import android.content.pm.PackageManager; 22 import android.os.Handler; 23 import android.os.Looper; 24 import android.os.RemoteException; 25 import android.security.IKeyChainService; 26 import android.security.KeyChain; 27 import android.util.Log; 28 29 import androidx.preference.Preference; 30 31 import com.android.internal.annotations.VisibleForTesting; 32 import com.android.settings.R; 33 import com.android.settings.core.BasePreferenceController; 34 35 import java.util.concurrent.ExecutorService; 36 import java.util.concurrent.Executors; 37 38 /** 39 * Controller that shows and updates the credential management app summary. 40 */ 41 public class CredentialManagementAppPreferenceController extends BasePreferenceController { 42 43 private static final String TAG = "CredentialManagementApp"; 44 45 private final ExecutorService mExecutor = Executors.newSingleThreadExecutor(); 46 private final Handler mHandler = new Handler(Looper.getMainLooper()); 47 48 private final PackageManager mPackageManager; 49 private boolean mHasCredentialManagerPackage; 50 private String mCredentialManagerPackageName; 51 CredentialManagementAppPreferenceController(Context context, String key)52 public CredentialManagementAppPreferenceController(Context context, String key) { 53 super(context, key); 54 mPackageManager = context.getPackageManager(); 55 } 56 57 @Override getAvailabilityStatus()58 public int getAvailabilityStatus() { 59 return AVAILABLE; 60 } 61 62 @Override updateState(Preference preference)63 public void updateState(Preference preference) { 64 mExecutor.execute(() -> { 65 try { 66 IKeyChainService service = KeyChain.bind(mContext).getService(); 67 mHasCredentialManagerPackage = service.hasCredentialManagementApp(); 68 mCredentialManagerPackageName = service.getCredentialManagementAppPackageName(); 69 } catch (InterruptedException | RemoteException e) { 70 Log.e(TAG, "Unable to display credential management app preference"); 71 } 72 mHandler.post(() -> displayPreference(preference)); 73 }); 74 } 75 76 @VisibleForTesting displayPreference(Preference preference)77 void displayPreference(Preference preference) { 78 if (mHasCredentialManagerPackage) { 79 preference.setEnabled(true); 80 try { 81 ApplicationInfo applicationInfo = 82 mPackageManager.getApplicationInfo(mCredentialManagerPackageName, 0); 83 preference.setSummary(applicationInfo.loadLabel(mPackageManager)); 84 } catch (PackageManager.NameNotFoundException e) { 85 preference.setSummary(mCredentialManagerPackageName); 86 } 87 } else { 88 preference.setEnabled(false); 89 preference.setSummary(R.string.no_certificate_management_app); 90 } 91 } 92 } 93