summaryrefslogtreecommitdiffstats
path: root/src/org/lineageos/profiles/ProfilesTrustAgent.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/org/lineageos/profiles/ProfilesTrustAgent.java')
-rw-r--r--src/org/lineageos/profiles/ProfilesTrustAgent.java323
1 files changed, 323 insertions, 0 deletions
diff --git a/src/org/lineageos/profiles/ProfilesTrustAgent.java b/src/org/lineageos/profiles/ProfilesTrustAgent.java
new file mode 100644
index 0000000..9c57709
--- /dev/null
+++ b/src/org/lineageos/profiles/ProfilesTrustAgent.java
@@ -0,0 +1,323 @@
+/*
+* Copyright (C) 2015 The CyanogenMod 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 org.cyanogenmod.profiles;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.net.wifi.WifiSsid;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.UserHandle;
+import android.service.trust.TrustAgentService;
+import android.util.ArraySet;
+import android.util.Log;
+import cyanogenmod.app.Profile;
+import cyanogenmod.app.ProfileManager;
+import cyanogenmod.providers.CMSettings;
+
+import java.lang.ref.WeakReference;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Profiles Trust Agent
+ *
+ * Watches for changes in the current {@link Profile} and grants or revokes trust (whether
+ * lock screen security is enforced).
+ */
+public class ProfilesTrustAgent extends TrustAgentService {
+
+ private static final String TAG = ProfilesTrustAgent.class.getSimpleName();
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ private static final int GRANT_DURATION_MS = 1000 * 60 * 5; // 5 minutes
+
+ private static final int MSG_UPDATE_STATE = 100;
+ private static final int MSG_ON_AGENT_CREATED = 101;
+ private static final int MSG_ON_TRIGGER_STATE_CHANGED = 102;
+ private static final int MSG_ON_USER_SWITCH = 103;
+
+ private BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ if (ProfileManager.INTENT_ACTION_PROFILE_TRIGGER_STATE_CHANGED.equals(action)) {
+ mHandler.obtainMessage(MSG_ON_TRIGGER_STATE_CHANGED,
+ intent.getExtras()).sendToTarget();
+ } else if (Intent.ACTION_USER_FOREGROUND.equals(action)) {
+ mHandler.sendEmptyMessage(MSG_ON_USER_SWITCH);
+ } else {
+ mHandler.sendEmptyMessage(MSG_UPDATE_STATE);
+ }
+ }
+ };
+
+ private ProfileManager mProfileManager;
+ private ProfileHandler mHandler;
+ private SystemProfilesSettingsObserver mObserver;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ if (UserHandle.myUserId() == UserHandle.USER_OWNER) {
+ mProfileManager = ProfileManager.getInstance(this);
+ mHandler = new ProfileHandler(ProfilesTrustAgent.this);
+
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(ProfileManager.INTENT_ACTION_PROFILE_SELECTED);
+ filter.addAction(ProfileManager.INTENT_ACTION_PROFILE_UPDATED);
+ filter.addAction(ProfileManager.INTENT_ACTION_PROFILE_TRIGGER_STATE_CHANGED);
+ filter.addAction(Intent.ACTION_USER_FOREGROUND);
+
+ registerReceiver(mReceiver, filter);
+ setManagingTrust(true);
+ mObserver = new SystemProfilesSettingsObserver(mHandler);
+ getContentResolver().registerContentObserver(
+ CMSettings.System.getUriFor(CMSettings.System.SYSTEM_PROFILES_ENABLED),
+ false, mObserver);
+ mHandler.sendEmptyMessage(MSG_ON_AGENT_CREATED);
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ if (UserHandle.myUserId() == UserHandle.USER_OWNER) {
+ mHandler = null;
+ mProfileManager = null;
+ setManagingTrust(false);
+ unregisterReceiver(mReceiver);
+ getContentResolver().unregisterContentObserver(mObserver);
+ }
+ super.onDestroy();
+ }
+
+ @Override
+ public void onTrustTimeout() {
+ if (UserHandle.myUserId() == UserHandle.USER_OWNER) {
+ mHandler.sendEmptyMessage(MSG_UPDATE_STATE);
+ }
+ }
+
+ private void handleApplyCurrentProfileState() {
+ /*final DevicePolicyManager devicePolicyManager =
+ (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
+ if (devicePolicyManager != null && devicePolicyManager.requireSecureKeyguard()) {
+ revokeTrust();
+ return;
+ }*/
+
+ Profile p = mProfileManager.getActiveProfile();
+ int lockscreenState = p != null ? p.getScreenLockMode().getValue()
+ : Profile.LockMode.DEFAULT;
+ switch (lockscreenState) {
+ case Profile.LockMode.DISABLE:
+ case Profile.LockMode.DEFAULT:
+ if (DEBUG) Log.w(TAG, "revoking trust.");
+ revokeTrust();
+ break;
+ case Profile.LockMode.INSECURE:
+ if (DEBUG) Log.w(TAG, "granting trust for profile " + p.getName());
+ grantTrust(getString(R.string.trust_by_profile), GRANT_DURATION_MS, false);
+ break;
+ }
+ }
+
+ private boolean shouldGrantTrustOnTriggerStateChanged(String triggerId, int triggerType,
+ int triggerState) {
+ final Profile activeProfile = mProfileManager.getActiveProfile();
+ if (activeProfile != null) {
+ final int lockMode = activeProfile.getScreenLockMode().getValue();
+ if (lockMode == Profile.LockMode.INSECURE) {
+ final List<Profile.ProfileTrigger> wifiTriggers
+ = activeProfile.getTriggersFromType(Profile.TriggerType.WIFI);
+ final List<Profile.ProfileTrigger> btTriggers
+ = activeProfile.getTriggersFromType(Profile.TriggerType.BLUETOOTH);
+ Set<String> onWiFiConnect = new ArraySet<>();
+ Set<String> onBTConnect = new ArraySet<>();
+
+ for (Profile.ProfileTrigger trigger : wifiTriggers) {
+ if (trigger.getState() == Profile.TriggerState.ON_CONNECT) {
+ onWiFiConnect.add(trigger.getId());
+ }
+ }
+ for (Profile.ProfileTrigger trigger : btTriggers) {
+ if (trigger.getState() == Profile.TriggerState.ON_CONNECT) {
+ onBTConnect.add(trigger.getId());
+ }
+ }
+
+ if (triggerState == Profile.TriggerState.ON_DISCONNECT) {
+ if (triggerType == Profile.TriggerType.BLUETOOTH
+ && onWiFiConnect.contains(getActiveSSID())) {
+ return true;
+ }
+
+ BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+ Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
+ Set<String> connectedBTDevices = new ArraySet<>();
+ for (BluetoothDevice device : pairedDevices) {
+ if (device.isConnected()) connectedBTDevices.add(device.getAddress());
+ }
+ for (Profile.ProfileTrigger btTrigger : btTriggers) {
+ if (connectedBTDevices.contains(btTrigger.getId())
+ && btTrigger.getState() == Profile.TriggerState.ON_CONNECT) {
+ return true;
+ }
+ }
+ } else if (triggerState == Profile.TriggerState.ON_CONNECT
+ && (onWiFiConnect.contains(triggerId) || onBTConnect.contains(triggerId))) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean shouldGrantTrustOnCreate() {
+ final Profile activeProfile = mProfileManager.getActiveProfile();
+ if (activeProfile != null) {
+ final int lockMode = activeProfile.getScreenLockMode().getValue();
+ if (lockMode == Profile.LockMode.INSECURE) {
+ final String ssid = getActiveSSID();
+ for (Profile.ProfileTrigger trigger
+ : activeProfile.getTriggersFromType(Profile.TriggerType.WIFI)) {
+ if (trigger.getId().equals(ssid)
+ && trigger.getState() == Profile.TriggerState.ON_CONNECT) {
+ return true;
+ }
+ }
+ BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+ Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
+ Set<String> connectedBTDevices = new ArraySet<>();
+ for (BluetoothDevice device : pairedDevices) {
+ if (device.isConnected()) connectedBTDevices.add(device.getAddress());
+ }
+ for (Profile.ProfileTrigger trigger
+ : activeProfile.getTriggersFromType(Profile.TriggerType.BLUETOOTH)) {
+ if (connectedBTDevices.contains(trigger.getId())
+ && trigger.getState() == Profile.TriggerState.ON_CONNECT) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ private String getActiveSSID() {
+ final WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
+ WifiInfo wifiinfo = wifiManager.getConnectionInfo();
+ if (wifiinfo == null) {
+ return null;
+ }
+ WifiSsid ssid = wifiinfo.getWifiSsid();
+ if (ssid == null) {
+ return null;
+ }
+ return ssid.toString();
+ }
+
+ private void onTrustAgentCreated() {
+ // Check if we connected to a tracking WiFi network/BT device before this agent was created.
+ // The agent is created AFTER the user authenticates at boot or when a new lock screen
+ // (PIN, pattern, etc) is set
+ final Profile p = mProfileManager.getActiveProfile();
+ if (p != null && shouldGrantTrustOnCreate()) {
+ if (DEBUG) Log.w(TAG, "granting trust for profile " + p.getName());
+ grantTrust(getString(R.string.trust_by_profile), GRANT_DURATION_MS, false);
+ } else {
+ if (DEBUG) Log.w(TAG, "revoking trust.");
+ revokeTrust();
+ }
+ }
+
+ private void onTriggerStateChanged(String triggerId, int triggerType, int triggerState) {
+ final Profile p = mProfileManager.getActiveProfile();
+ if (p != null
+ && shouldGrantTrustOnTriggerStateChanged(triggerId, triggerType, triggerState)) {
+ if (DEBUG) Log.w(TAG, "granting trust for profile " + p.getName());
+ grantTrust(getString(R.string.trust_by_profile), GRANT_DURATION_MS, false);
+ } else {
+ if (DEBUG) Log.w(TAG, "revoking trust.");
+ revokeTrust();
+ }
+ }
+
+ private static class ProfileHandler extends Handler {
+ private final WeakReference<ProfilesTrustAgent> mService;
+
+ private ProfileHandler(ProfilesTrustAgent service) {
+ this.mService = new WeakReference<ProfilesTrustAgent>(service);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_UPDATE_STATE: {
+ ProfilesTrustAgent service = mService.get();
+ if (service != null) {
+ service.handleApplyCurrentProfileState();
+ }
+ break;
+ }
+ case MSG_ON_USER_SWITCH:
+ case MSG_ON_AGENT_CREATED: {
+ ProfilesTrustAgent service = mService.get();
+ if (service != null) {
+ service.onTrustAgentCreated();
+ }
+ break;
+ }
+ case MSG_ON_TRIGGER_STATE_CHANGED: {
+ ProfilesTrustAgent service = mService.get();
+ if (service != null && msg.obj != null) {
+ Bundle bundle = (Bundle) msg.obj;
+ final String id = bundle.getString(ProfileManager.EXTRA_TRIGGER_ID);
+ final int type = bundle.getInt(ProfileManager.EXTRA_TRIGGER_TYPE);
+ final int state = bundle.getInt(ProfileManager.EXTRA_TRIGGER_STATE);
+ service.onTriggerStateChanged(id, type, state);
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ private class SystemProfilesSettingsObserver extends ContentObserver {
+
+ public SystemProfilesSettingsObserver(Handler handler) {
+ super(handler);
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ if (CMSettings.System.getUriFor(CMSettings.System.SYSTEM_PROFILES_ENABLED)
+ .compareTo(uri) == 0) {
+ mHandler.sendEmptyMessage(MSG_UPDATE_STATE);
+ }
+ }
+ }
+}