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