1/*
2 * Copyright (C) 2014 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
17package com.android.settings;
18
19import android.app.admin.DevicePolicyManager;
20import android.content.ComponentName;
21import android.content.Context;
22import android.content.Intent;
23import android.content.pm.PackageManager;
24import android.content.pm.ResolveInfo;
25import android.graphics.drawable.Drawable;
26import android.os.Bundle;
27import android.os.UserHandle;
28import android.service.trust.TrustAgentService;
29import android.support.v14.preference.SwitchPreference;
30import android.support.v7.preference.Preference;
31import android.support.v7.preference.PreferenceGroup;
32import android.util.ArrayMap;
33import android.util.ArraySet;
34
35import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
36import com.android.internal.widget.LockPatternUtils;
37import com.android.settings.overlay.FeatureFactory;
38import com.android.settings.trustagent.TrustAgentManager;
39import com.android.settingslib.RestrictedLockUtils;
40import com.android.settingslib.RestrictedSwitchPreference;
41
42import java.util.List;
43
44import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
45
46public class TrustAgentSettings extends SettingsPreferenceFragment implements
47        Preference.OnPreferenceChangeListener {
48    private static final String SERVICE_INTERFACE = TrustAgentService.SERVICE_INTERFACE;
49
50    private ArrayMap<ComponentName, AgentInfo> mAvailableAgents;
51    private final ArraySet<ComponentName> mActiveAgents = new ArraySet<ComponentName>();
52    private LockPatternUtils mLockPatternUtils;
53    private DevicePolicyManager mDpm;
54    private TrustAgentManager mTrustAgentManager;
55
56    public static final class AgentInfo {
57        CharSequence label;
58        ComponentName component; // service that implements ITrustAgent
59        SwitchPreference preference;
60        public Drawable icon;
61
62        @Override
63        public boolean equals(Object other) {
64            if (other instanceof AgentInfo) {
65                return component.equals(((AgentInfo)other).component);
66            }
67            return true;
68        }
69
70        public int compareTo(AgentInfo other) {
71            return component.compareTo(other.component);
72        }
73    }
74
75    @Override
76    public int getMetricsCategory() {
77        return MetricsEvent.TRUST_AGENT;
78    }
79
80    @Override
81    protected int getHelpResource() {
82        return R.string.help_url_trust_agent;
83    }
84
85    @Override
86    public void onCreate(Bundle icicle) {
87        super.onCreate(icicle);
88        mDpm = getActivity().getSystemService(DevicePolicyManager.class);
89        mTrustAgentManager =
90            FeatureFactory.getFactory(getActivity()).getSecurityFeatureProvider()
91                .getTrustAgentManager();
92
93        addPreferencesFromResource(R.xml.trust_agent_settings);
94    }
95
96    public void onResume() {
97        super.onResume();
98        removePreference("dummy_preference");
99        updateAgents();
100    };
101
102    private void updateAgents() {
103        final Context context = getActivity();
104        if (mAvailableAgents == null) {
105            mAvailableAgents = findAvailableTrustAgents();
106        }
107        if (mLockPatternUtils == null) {
108            mLockPatternUtils = new LockPatternUtils(getActivity());
109        }
110        loadActiveAgents();
111        PreferenceGroup category =
112                (PreferenceGroup) getPreferenceScreen().findPreference("trust_agents");
113        category.removeAll();
114
115        final EnforcedAdmin admin = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(context,
116                DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS, UserHandle.myUserId());
117
118        final int count = mAvailableAgents.size();
119        for (int i = 0; i < count; i++) {
120            AgentInfo agent = mAvailableAgents.valueAt(i);
121            final RestrictedSwitchPreference preference =
122                    new RestrictedSwitchPreference(getPrefContext());
123            preference.useAdminDisabledSummary(true);
124            agent.preference = preference;
125            preference.setPersistent(false);
126            preference.setTitle(agent.label);
127            preference.setIcon(agent.icon);
128            preference.setPersistent(false);
129            preference.setOnPreferenceChangeListener(this);
130            preference.setChecked(mActiveAgents.contains(agent.component));
131
132            if (admin != null
133                    && mDpm.getTrustAgentConfiguration(null, agent.component) == null) {
134                preference.setChecked(false);
135                preference.setDisabledByAdmin(admin);
136            }
137
138            category.addPreference(agent.preference);
139        }
140    }
141
142    private void loadActiveAgents() {
143        List<ComponentName> activeTrustAgents = mLockPatternUtils.getEnabledTrustAgents(
144                UserHandle.myUserId());
145        if (activeTrustAgents != null) {
146            mActiveAgents.addAll(activeTrustAgents);
147        }
148    }
149
150    private void saveActiveAgents() {
151        mLockPatternUtils.setEnabledTrustAgents(mActiveAgents,
152                UserHandle.myUserId());
153    }
154
155    ArrayMap<ComponentName, AgentInfo> findAvailableTrustAgents() {
156        PackageManager pm = getActivity().getPackageManager();
157        Intent trustAgentIntent = new Intent(SERVICE_INTERFACE);
158        List<ResolveInfo> resolveInfos = pm.queryIntentServices(trustAgentIntent,
159                PackageManager.GET_META_DATA);
160
161        ArrayMap<ComponentName, AgentInfo> agents = new ArrayMap<ComponentName, AgentInfo>();
162        final int count = resolveInfos.size();
163        agents.ensureCapacity(count);
164        for (int i = 0; i < count; i++ ) {
165            ResolveInfo resolveInfo = resolveInfos.get(i);
166            if (resolveInfo.serviceInfo == null) {
167                continue;
168            }
169            if (!mTrustAgentManager.shouldProvideTrust(resolveInfo, pm)) {
170                continue;
171            }
172            ComponentName name = TrustAgentUtils.getComponentName(resolveInfo);
173            AgentInfo agentInfo = new AgentInfo();
174            agentInfo.label = resolveInfo.loadLabel(pm);
175            agentInfo.icon = resolveInfo.loadIcon(pm);
176            agentInfo.component = name;
177            agents.put(name, agentInfo);
178        }
179        return agents;
180    }
181
182    @Override
183    public boolean onPreferenceChange(Preference preference, Object newValue) {
184        if (preference instanceof SwitchPreference) {
185            final int count = mAvailableAgents.size();
186            for (int i = 0; i < count; i++) {
187                AgentInfo agent = mAvailableAgents.valueAt(i);
188                if (agent.preference == preference) {
189                    if ((Boolean) newValue) {
190                        if (!mActiveAgents.contains(agent.component)) {
191                            mActiveAgents.add(agent.component);
192                        }
193                    } else {
194                        mActiveAgents.remove(agent.component);
195                    }
196                    saveActiveAgents();
197                    return true;
198                }
199            }
200        }
201        return false;
202    }
203
204}
205