1 /* 2 * Copyright (C) 2018 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.trustagent; 18 19 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; 20 21 import android.app.admin.DevicePolicyManager; 22 import android.content.ComponentName; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.pm.PackageManager; 26 import android.content.pm.ResolveInfo; 27 import android.graphics.drawable.Drawable; 28 import android.os.UserHandle; 29 import android.service.trust.TrustAgentService; 30 import android.text.TextUtils; 31 import android.util.ArrayMap; 32 import android.util.ArraySet; 33 import android.util.IconDrawableFactory; 34 35 import androidx.preference.Preference; 36 import androidx.preference.PreferenceScreen; 37 import androidx.preference.SwitchPreference; 38 39 import com.android.internal.widget.LockPatternUtils; 40 import com.android.settings.core.BasePreferenceController; 41 import com.android.settings.overlay.FeatureFactory; 42 import com.android.settings.security.SecurityFeatureProvider; 43 import com.android.settingslib.RestrictedLockUtilsInternal; 44 import com.android.settingslib.RestrictedSwitchPreference; 45 import com.android.settingslib.core.lifecycle.LifecycleObserver; 46 import com.android.settingslib.core.lifecycle.events.OnStart; 47 48 import java.util.List; 49 50 public class TrustAgentsPreferenceController extends BasePreferenceController 51 implements Preference.OnPreferenceChangeListener, LifecycleObserver, OnStart { 52 53 private static final Intent TRUST_AGENT_INTENT = 54 new Intent(TrustAgentService.SERVICE_INTERFACE); 55 56 private final ArrayMap<ComponentName, TrustAgentInfo> mAvailableAgents; 57 private final ArraySet<ComponentName> mActiveAgents; 58 private final DevicePolicyManager mDevicePolicyManager; 59 private final IconDrawableFactory mIconDrawableFactory; 60 private final LockPatternUtils mLockPatternUtils; 61 private final PackageManager mPackageManager; 62 private final TrustAgentManager mTrustAgentManager; 63 64 private PreferenceScreen mScreen; 65 TrustAgentsPreferenceController(Context context, String key)66 public TrustAgentsPreferenceController(Context context, String key) { 67 super(context, key); 68 mAvailableAgents = new ArrayMap<>(); 69 mActiveAgents = new ArraySet<>(); 70 mDevicePolicyManager = context.getSystemService(DevicePolicyManager.class); 71 mIconDrawableFactory = IconDrawableFactory.newInstance(context); 72 final SecurityFeatureProvider securityFeatureProvider = 73 FeatureFactory.getFactory(context).getSecurityFeatureProvider(); 74 mTrustAgentManager = securityFeatureProvider.getTrustAgentManager(); 75 mLockPatternUtils = securityFeatureProvider.getLockPatternUtils(context); 76 mPackageManager = context.getPackageManager(); 77 } 78 79 @Override displayPreference(PreferenceScreen screen)80 public void displayPreference(PreferenceScreen screen) { 81 super.displayPreference(screen); 82 mScreen = screen; 83 } 84 85 @Override getAvailabilityStatus()86 public int getAvailabilityStatus() { 87 return AVAILABLE; 88 } 89 90 @Override onStart()91 public void onStart() { 92 updateAgents(); 93 } 94 updateAgents()95 private void updateAgents() { 96 findAvailableTrustAgents(); 97 loadActiveAgents(); 98 removeUselessExistingPreferences(); 99 100 final EnforcedAdmin admin = RestrictedLockUtilsInternal.checkIfKeyguardFeaturesDisabled( 101 mContext, DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS, UserHandle.myUserId()); 102 103 for (TrustAgentInfo agent : mAvailableAgents.values()) { 104 final ComponentName componentName = agent.getComponentName(); 105 RestrictedSwitchPreference preference = (RestrictedSwitchPreference) 106 mScreen.findPreference(componentName.flattenToString()); 107 if (preference == null) { 108 preference = new RestrictedSwitchPreference(mScreen.getContext()); 109 } 110 preference.setKey(componentName.flattenToString()); 111 preference.useAdminDisabledSummary(true); 112 preference.setTitle(agent.getLabel()); 113 preference.setIcon(agent.getIcon()); 114 preference.setOnPreferenceChangeListener(this); 115 preference.setChecked(mActiveAgents.contains(componentName)); 116 if (admin != null && mDevicePolicyManager.getTrustAgentConfiguration(null /* admin */, 117 componentName) == null) { 118 preference.setChecked(false); 119 preference.setDisabledByAdmin(admin); 120 } 121 mScreen.addPreference(preference); 122 } 123 } 124 loadActiveAgents()125 private void loadActiveAgents() { 126 final List<ComponentName> activeTrustAgents = mLockPatternUtils.getEnabledTrustAgents( 127 UserHandle.myUserId()); 128 if (activeTrustAgents != null) { 129 mActiveAgents.addAll(activeTrustAgents); 130 } 131 } 132 saveActiveAgents()133 private void saveActiveAgents() { 134 mLockPatternUtils.setEnabledTrustAgents(mActiveAgents, UserHandle.myUserId()); 135 } 136 findAvailableTrustAgents()137 private void findAvailableTrustAgents() { 138 final List<ResolveInfo> resolveInfos = mPackageManager.queryIntentServices( 139 TRUST_AGENT_INTENT, PackageManager.GET_META_DATA); 140 mAvailableAgents.clear(); 141 for (ResolveInfo resolveInfo : resolveInfos) { 142 if (resolveInfo.serviceInfo == null) { 143 continue; 144 } 145 if (!mTrustAgentManager.shouldProvideTrust(resolveInfo, mPackageManager)) { 146 continue; 147 } 148 final CharSequence label = resolveInfo.loadLabel(mPackageManager); 149 final ComponentName componentName = mTrustAgentManager.getComponentName(resolveInfo); 150 final Drawable icon = mIconDrawableFactory.getBadgedIcon( 151 resolveInfo.getComponentInfo().applicationInfo); 152 final TrustAgentInfo agentInfo = new TrustAgentInfo(label, componentName, icon); 153 mAvailableAgents.put(componentName, agentInfo); 154 } 155 } 156 removeUselessExistingPreferences()157 private void removeUselessExistingPreferences() { 158 final int count = mScreen.getPreferenceCount(); 159 if (count <= 0) { 160 return; 161 } 162 for (int i = count - 1; i >= 0; i--) { 163 final Preference pref = mScreen.getPreference(i); 164 final String[] names = TextUtils.split(pref.getKey(), "/"); 165 final ComponentName componentName = new ComponentName(names[0], names[1]); 166 if (!mAvailableAgents.containsKey(componentName)) { 167 mScreen.removePreference(pref); 168 mActiveAgents.remove(componentName); 169 } 170 } 171 } 172 173 @Override onPreferenceChange(Preference preference, Object newValue)174 public boolean onPreferenceChange(Preference preference, Object newValue) { 175 if (!(preference instanceof SwitchPreference)) { 176 return false; 177 } 178 for (TrustAgentInfo agent : mAvailableAgents.values()) { 179 final ComponentName componentName = agent.getComponentName(); 180 if (!TextUtils.equals(preference.getKey(), componentName.flattenToString())) { 181 continue; 182 } 183 if ((Boolean) newValue && !mActiveAgents.contains(componentName)) { 184 mActiveAgents.add(componentName); 185 } else { 186 mActiveAgents.remove(componentName); 187 } 188 saveActiveAgents(); 189 return true; 190 } 191 return false; 192 } 193 } 194