Merge "Add new DevicePolicyManager API to allow fine-grained TrustAgent management" into lmp-dev
diff --git a/api/current.txt b/api/current.txt
index d89f2dd..68056b8 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5332,6 +5332,7 @@
method public android.os.UserHandle createUser(android.content.ComponentName, java.lang.String);
method public void enableSystemApp(android.content.ComponentName, java.lang.String);
method public int enableSystemApp(android.content.ComponentName, android.content.Intent);
+ method public void setTrustAgentFeaturesEnabled(android.content.ComponentName, android.content.ComponentName, java.util.List<java.lang.String>);
method public java.lang.String[] getAccountTypesWithManagementDisabled();
method public java.util.List<android.content.ComponentName> getActiveAdmins();
method public android.os.Bundle getApplicationRestrictions(android.content.ComponentName, java.lang.String);
@@ -5357,6 +5358,7 @@
method public boolean getScreenCaptureDisabled(android.content.ComponentName);
method public boolean getStorageEncryption(android.content.ComponentName);
method public int getStorageEncryptionStatus();
+ method public java.util.List<java.lang.String> getTrustAgentFeaturesEnabled(android.content.ComponentName, android.content.ComponentName);
method public boolean hasAnyCaCertsInstalled();
method public boolean hasCaCertInstalled(byte[]);
method public boolean hasGrantedPolicy(android.content.ComponentName, int);
@@ -27414,8 +27416,10 @@
ctor public TrustAgentService();
method public final void grantTrust(java.lang.CharSequence, long, boolean);
method public final android.os.IBinder onBind(android.content.Intent);
+ method public boolean onSetTrustAgentFeaturesEnabled(android.os.Bundle);
method public void onUnlockAttempt(boolean);
method public final void revokeTrust();
+ field public static final java.lang.String KEY_FEATURES = "trust_agent_features";
field public static final java.lang.String SERVICE_INTERFACE = "android.service.trust.TrustAgentService";
field public static final java.lang.String TRUST_AGENT_META_DATA = "android.service.trust.trustagent";
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 76cf29a..20a0072 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -54,6 +54,7 @@
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
+import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@@ -2327,6 +2328,51 @@
}
/**
+ * Sets a list of features to enable for a TrustAgentService component. This is meant to be
+ * used in conjunction with {@link #KEYGUARD_DISABLE_TRUST_AGENTS}, which will disable all
+ * trust agents but those with features enabled by this function call.
+ *
+ * <p>The calling device admin must have requested
+ * {@link DeviceAdminInfo#USES_POLICY_DISABLE_KEYGUARD_FEATURES} to be able to call
+ * this method; if it has not, a security exception will be thrown.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param agent Which component to enable features for.
+ * @param features List of features to enable. Consult specific TrustAgent documentation for
+ * the feature list.
+ */
+ public void setTrustAgentFeaturesEnabled(ComponentName admin, ComponentName agent,
+ List<String> features) {
+ if (mService != null) {
+ try {
+ mService.setTrustAgentFeaturesEnabled(admin, agent, features, UserHandle.myUserId());
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ }
+
+ /**
+ * Gets list of enabled features for the given {@link TrustAgentService} agent. If admin is
+ * null, this will return the intersection of all features enabled for the given agent by all
+ * admins.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param agent Which component to get enabled features for.
+ * @return List of enabled features.
+ */
+ public List<String> getTrustAgentFeaturesEnabled(ComponentName admin, ComponentName agent) {
+ if (mService != null) {
+ try {
+ return mService.getTrustAgentFeaturesEnabled(admin, agent, UserHandle.myUserId());
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ return new ArrayList<String>(); // empty list
+ }
+
+ /**
* Called by a profile owner to set whether caller-Id information from the managed
* profile will be shown for incoming calls.
*
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 6499ae4..a6544e6 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -169,4 +169,8 @@
void setCrossProfileCallerIdDisabled(in ComponentName who, boolean disabled);
boolean getCrossProfileCallerIdDisabled(in ComponentName who);
boolean getCrossProfileCallerIdDisabledForUser(int userId);
+
+ void setTrustAgentFeaturesEnabled(in ComponentName admin, in ComponentName agent, in List<String> features, int userId);
+ List<String> getTrustAgentFeaturesEnabled(in ComponentName admin, in ComponentName agent, int userId);
+
}
diff --git a/core/java/android/service/trust/ITrustAgentService.aidl b/core/java/android/service/trust/ITrustAgentService.aidl
index 863a249..49eb7be 100644
--- a/core/java/android/service/trust/ITrustAgentService.aidl
+++ b/core/java/android/service/trust/ITrustAgentService.aidl
@@ -22,7 +22,8 @@
* Communication channel from TrustManagerService to the TrustAgent.
* @hide
*/
-oneway interface ITrustAgentService {
- void onUnlockAttempt(boolean successful);
- void setCallback(ITrustAgentServiceCallback callback);
+interface ITrustAgentService {
+ oneway void onUnlockAttempt(boolean successful);
+ oneway void setCallback(ITrustAgentServiceCallback callback);
+ boolean setTrustAgentFeaturesEnabled(in Bundle options);
}
diff --git a/core/java/android/service/trust/TrustAgentService.java b/core/java/android/service/trust/TrustAgentService.java
index 8fa45e6..333a892 100644
--- a/core/java/android/service/trust/TrustAgentService.java
+++ b/core/java/android/service/trust/TrustAgentService.java
@@ -19,10 +19,12 @@
import android.Manifest;
import android.annotation.SdkConstant;
import android.app.Service;
+import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
+import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
@@ -74,6 +76,12 @@
*/
public static final String TRUST_AGENT_META_DATA = "android.service.trust.trustagent";
+ /**
+ * A white list of features that the given trust agent should support when otherwise disabled
+ * by device policy.
+ */
+ public static final String KEY_FEATURES = "trust_agent_features";
+
private static final int MSG_UNLOCK_ATTEMPT = 1;
private static final boolean DEBUG = false;
@@ -124,6 +132,26 @@
}
/**
+ * Called when device policy wants to restrict features in the TrustAgent in response to
+ * {@link DevicePolicyManager#setTrustAgentFeaturesEnabled(ComponentName, ComponentName, java.util.List) }.
+ * TrustAgents that support this feature should overload this method and return 'true'.
+ *
+ * The list of options can be obtained by calling
+ * options.getStringArrayList({@link #KEY_FEATURES}). Presence of a feature string in the list
+ * means it should be enabled ("white-listed"). Absence of the feature means it should be
+ * disabled. An empty list means all features should be disabled.
+ *
+ * This function is only called if {@link DevicePolicyManager#KEYGUARD_DISABLE_TRUST_AGENTS} is
+ * set.
+ *
+ * @param options Option feature bundle.
+ * @return true if the {@link #TrustAgentService()} supports this feature.
+ */
+ public boolean onSetTrustAgentFeaturesEnabled(Bundle options) {
+ return false;
+ }
+
+ /**
* Call to grant trust on the device.
*
* @param message describes why the device is trusted, e.g. "Trusted by location".
@@ -185,6 +213,7 @@
.sendToTarget();
}
+ @Override
public void setCallback(ITrustAgentServiceCallback callback) {
synchronized (mLock) {
mCallback = callback;
@@ -194,6 +223,13 @@
}
}
}
+
+ @Override
+ public boolean setTrustAgentFeaturesEnabled(Bundle features) {
+ synchronized (mLock) {
+ return onSetTrustAgentFeaturesEnabled(features);
+ }
+ }
}
}
diff --git a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java
index a51ea75..50a3f82 100644
--- a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java
+++ b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java
@@ -25,6 +25,7 @@
import android.preference.PreferenceManager;
import android.service.trust.TrustAgentService;
import android.support.v4.content.LocalBroadcastManager;
+import android.util.Log;
import android.widget.Toast;
public class SampleTrustAgent extends TrustAgentService {
@@ -41,6 +42,8 @@
private static final String PREFERENCE_REPORT_UNLOCK_ATTEMPTS
= "preference.report_unlock_attempts";
+ private static final String TAG = "SampleTrustAgent";
+
@Override
public void onCreate() {
super.onCreate();
@@ -60,6 +63,13 @@
}
@Override
+ public boolean onSetTrustAgentFeaturesEnabled(Bundle options) {
+ Log.v(TAG, "Policy options received: " + options.getStringArrayList(KEY_FEATURES));
+ // TODO: Handle options
+ return true; // inform DPM that we support it
+ }
+
+ @Override
public void onDestroy() {
super.onDestroy();
mLocalBroadcastManager.unregisterReceiver(mReceiver);
diff --git a/services/core/java/com/android/server/trust/TrustAgentWrapper.java b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
index 51009af..0acb82f 100644
--- a/services/core/java/com/android/server/trust/TrustAgentWrapper.java
+++ b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
@@ -16,10 +16,14 @@
package com.android.server.trust;
+import android.app.admin.DevicePolicyManager;
+import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.ServiceConnection;
+import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
@@ -30,6 +34,10 @@
import android.util.Slog;
import android.service.trust.ITrustAgentService;
import android.service.trust.ITrustAgentServiceCallback;
+import android.service.trust.TrustAgentService;
+
+import java.util.ArrayList;
+import java.util.List;
/**
* A wrapper around a TrustAgentService interface. Coordinates communication between
@@ -43,6 +51,7 @@
private static final int MSG_REVOKE_TRUST = 2;
private static final int MSG_TRUST_TIMEOUT = 3;
private static final int MSG_RESTART_TIMEOUT = 4;
+ private static final int MSG_DPM_CHANGED = 5;
/**
* Time in uptime millis that we wait for the service connection, both when starting
@@ -67,6 +76,7 @@
// Trust state
private boolean mTrusted;
private CharSequence mMessage;
+ private boolean mTrustDisabledByDpm;
private final Handler mHandler = new Handler() {
@Override
@@ -109,6 +119,9 @@
unbind();
mTrustManagerService.resetAgent(mName, mUserId);
break;
+ case MSG_DPM_CHANGED:
+ updateDevicePolicyFeatures(mName);
+ break;
}
}
};
@@ -141,6 +154,8 @@
mTrustAgentService = ITrustAgentService.Stub.asInterface(service);
mTrustManagerService.mArchive.logAgentConnected(mUserId, name);
setCallback(mCallback);
+ updateDevicePolicyFeatures(name);
+ watchForDpmChanges(true);
}
@Override
@@ -152,9 +167,21 @@
if (mBound) {
scheduleRestart();
}
+ // mTrustDisabledByDpm maintains state
+ watchForDpmChanges(false);
}
};
+ private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED
+ .equals(intent.getAction())) {
+ mHandler.sendEmptyMessage(MSG_DPM_CHANGED);
+ }
+ }
+ };
public TrustAgentWrapper(Context context, TrustManagerService trustManagerService,
Intent intent, UserHandle user) {
@@ -196,8 +223,62 @@
}
}
+ private void watchForDpmChanges(boolean start) {
+ if (start) {
+ final IntentFilter filter = new IntentFilter();
+ filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
+ filter.addAction(Intent.ACTION_USER_REMOVED);
+ mContext.registerReceiver(mBroadcastReceiver, filter);
+ } else {
+ mContext.unregisterReceiver(mBroadcastReceiver);
+ }
+ }
+
+ private boolean updateDevicePolicyFeatures(ComponentName name) {
+ boolean trustDisabled = false;
+ if (DEBUG) Slog.v(TAG, "updateDevicePolicyFeatures(" + name + ")");
+ try {
+ if (mTrustAgentService != null) {
+ DevicePolicyManager dpm =
+ (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
+ if (dpm != null) {
+ // If trust disabled, only enable it if the options bundle is set and
+ // accepted by the TrustAgent.
+ if ((dpm.getKeyguardDisabledFeatures(null)
+ & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0) {
+ List<String> features = dpm.getTrustAgentFeaturesEnabled(null, name);
+ if (DEBUG) Slog.v(TAG, "Detected trust agents disabled. Features = " + features);
+ if (features != null && features.size() > 0) {
+ Bundle bundle = new Bundle();
+ bundle.putStringArrayList(TrustAgentService.KEY_FEATURES,
+ (ArrayList<String>)features);
+ if (DEBUG) {
+ Slog.v(TAG, "TrustAgent " + name.flattenToShortString()
+ + " disabled except "+ features);
+ }
+ trustDisabled = mTrustAgentService.setTrustAgentFeaturesEnabled(bundle);
+ } else {
+ if (DEBUG) Slog.v(TAG, "TrustAgent " + name + " disabled by flag");
+ trustDisabled = true; // trust agent should be disabled
+ }
+ }
+ } else {
+ Log.e(TAG, "Can't get DevicePolicyManagerService: is it running?",
+ new IllegalStateException("Stack trace:"));
+ }
+ }
+ } catch (RemoteException e) {
+ onError(e);
+ }
+ if (mTrustDisabledByDpm != trustDisabled) {
+ mTrustDisabledByDpm = trustDisabled;
+ mTrustManagerService.updateTrust(mUserId);
+ }
+ return trustDisabled;
+ }
+
public boolean isTrusted() {
- return mTrusted;
+ return mTrusted && !mTrustDisabledByDpm;
}
public CharSequence getMessage() {
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 14436aa..9c2df55 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -169,7 +169,7 @@
for (UserInfo userInfo : userInfos) {
int disabledFeatures = lockPatternUtils.getDevicePolicyManager()
.getKeyguardDisabledFeatures(null, userInfo.id);
- boolean disableTrustAgents =
+ final boolean disableTrustAgents =
(disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0;
List<ComponentName> enabledAgents = lockPatternUtils.getEnabledTrustAgents(userInfo.id);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 25f9e9b..f49451e 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -80,6 +80,7 @@
import android.security.IKeyChainService;
import android.security.KeyChain;
import android.security.KeyChain.KeyChainConnection;
+import android.service.trust.TrustAgentService;
import android.util.Log;
import android.util.PrintWriterPrinter;
import android.util.Printer;
@@ -89,6 +90,11 @@
import android.view.IWindowManager;
import org.xmlpull.v1.XmlPullParser;
+
+import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
+import static org.xmlpull.v1.XmlPullParser.END_TAG;
+import static org.xmlpull.v1.XmlPullParser.TEXT;
+
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
@@ -111,6 +117,8 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
/**
@@ -260,6 +268,9 @@
private static final String TAG_DISABLE_ACCOUNT_MANAGEMENT = "disable-account-management";
private static final String TAG_ACCOUNT_TYPE = "account-type";
private static final String TAG_ENCRYPTION_REQUESTED = "encryption-requested";
+ private static final String TAG_MANAGE_TRUST_AGENT_FEATURES = "manage-trust-agent-features";
+ private static final String TAG_TRUST_AGENT_FEATURE = "feature";
+ private static final String TAG_TRUST_AGENT_COMPONENT = "component";
private static final String TAG_PASSWORD_EXPIRATION_DATE = "password-expiration-date";
private static final String TAG_PASSWORD_EXPIRATION_TIMEOUT = "password-expiration-timeout";
private static final String TAG_GLOBAL_PROXY_EXCLUSION_LIST = "global-proxy-exclusion-list";
@@ -333,6 +344,7 @@
boolean specifiesGlobalProxy = false;
String globalProxySpec = null;
String globalProxyExclusionList = null;
+ HashMap<String, List<String>> trustAgentFeatures = new HashMap<String, List<String>>();
ActiveAdmin(DeviceAdminInfo _info) {
info = _info;
@@ -463,15 +475,30 @@
}
out.endTag(null, TAG_DISABLE_ACCOUNT_MANAGEMENT);
}
+ if (!trustAgentFeatures.isEmpty()) {
+ Set<Entry<String, List<String>>> set = trustAgentFeatures.entrySet();
+ out.startTag(null, TAG_MANAGE_TRUST_AGENT_FEATURES);
+ for (Entry<String, List<String>> component : set) {
+ out.startTag(null, TAG_TRUST_AGENT_COMPONENT);
+ out.attribute(null, ATTR_VALUE, component.getKey());
+ for (String feature : component.getValue()) {
+ out.startTag(null, TAG_TRUST_AGENT_FEATURE);
+ out.attribute(null, ATTR_VALUE, feature);
+ out.endTag(null, TAG_TRUST_AGENT_FEATURE);
+ }
+ out.endTag(null, TAG_TRUST_AGENT_COMPONENT);
+ }
+ out.endTag(null, TAG_MANAGE_TRUST_AGENT_FEATURES);
+ }
}
void readFromXml(XmlPullParser parser)
throws XmlPullParserException, IOException {
int outerDepth = parser.getDepth();
int type;
- while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
- if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+ while ((type=parser.next()) != END_DOCUMENT
+ && (type != END_TAG || parser.getDepth() > outerDepth)) {
+ if (type == END_TAG || type == TEXT) {
continue;
}
String tag = parser.getName();
@@ -541,22 +568,9 @@
disabledKeyguardFeatures = Integer.parseInt(
parser.getAttributeValue(null, ATTR_VALUE));
} else if (TAG_DISABLE_ACCOUNT_MANAGEMENT.equals(tag)) {
- int outerDepthDAM = parser.getDepth();
- int typeDAM;
- while ((typeDAM=parser.next()) != XmlPullParser.END_DOCUMENT
- && (typeDAM != XmlPullParser.END_TAG
- || parser.getDepth() > outerDepthDAM)) {
- if (typeDAM == XmlPullParser.END_TAG || typeDAM == XmlPullParser.TEXT) {
- continue;
- }
- String tagDAM = parser.getName();
- if (TAG_ACCOUNT_TYPE.equals(tagDAM)) {
- accountTypesWithManagementDisabled.add(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else {
- Slog.w(LOG_TAG, "Unknown tag under " + tag + ": " + tagDAM);
- }
- }
+ accountTypesWithManagementDisabled = readDisableAccountInfo(parser, tag);
+ } else if (TAG_MANAGE_TRUST_AGENT_FEATURES.equals(tag)) {
+ trustAgentFeatures = getAllTrustAgentFeatures(parser, tag);
} else {
Slog.w(LOG_TAG, "Unknown admin tag: " + tag);
}
@@ -564,6 +578,68 @@
}
}
+ private Set<String> readDisableAccountInfo(XmlPullParser parser, String tag)
+ throws XmlPullParserException, IOException {
+ int outerDepthDAM = parser.getDepth();
+ int typeDAM;
+ Set<String> result = new HashSet<String>();
+ while ((typeDAM=parser.next()) != END_DOCUMENT
+ && (typeDAM != END_TAG || parser.getDepth() > outerDepthDAM)) {
+ if (typeDAM == END_TAG || typeDAM == TEXT) {
+ continue;
+ }
+ String tagDAM = parser.getName();
+ if (TAG_ACCOUNT_TYPE.equals(tagDAM)) {
+ result.add(parser.getAttributeValue(null, ATTR_VALUE));
+ } else {
+ Slog.w(LOG_TAG, "Unknown tag under " + tag + ": " + tagDAM);
+ }
+ }
+ return result;
+ }
+
+ private HashMap<String, List<String>> getAllTrustAgentFeatures(XmlPullParser parser,
+ String tag) throws XmlPullParserException, IOException {
+ int outerDepthDAM = parser.getDepth();
+ int typeDAM;
+ HashMap<String, List<String>> result = new HashMap<String, List<String>>();
+ while ((typeDAM=parser.next()) != END_DOCUMENT
+ && (typeDAM != END_TAG || parser.getDepth() > outerDepthDAM)) {
+ if (typeDAM == END_TAG || typeDAM == TEXT) {
+ continue;
+ }
+ String tagDAM = parser.getName();
+ if (TAG_TRUST_AGENT_COMPONENT.equals(tagDAM)) {
+ final String component = parser.getAttributeValue(null, ATTR_VALUE);
+ result.put(component, getTrustAgentFeatures(parser, tag));
+ } else {
+ Slog.w(LOG_TAG, "Unknown tag under " + tag + ": " + tagDAM);
+ }
+ }
+ return result;
+ }
+
+ private List<String> getTrustAgentFeatures(XmlPullParser parser, String tag)
+ throws XmlPullParserException, IOException {
+ int outerDepthDAM = parser.getDepth();
+ int typeDAM;
+ ArrayList<String> result = new ArrayList<String>();
+ while ((typeDAM=parser.next()) != END_DOCUMENT
+ && (typeDAM != END_TAG || parser.getDepth() > outerDepthDAM)) {
+ if (typeDAM == END_TAG || typeDAM == TEXT) {
+ continue;
+ }
+ String tagDAM = parser.getName();
+ if (TAG_TRUST_AGENT_FEATURE.equals(tagDAM)) {
+ final String feature = parser.getAttributeValue(null, ATTR_VALUE);
+ result.add(feature);
+ } else {
+ Slog.w(LOG_TAG, "Unknown tag under " + tag + ": " + tagDAM);
+ }
+ }
+ return result;
+ }
+
void dump(String prefix, PrintWriter pw) {
pw.print(prefix); pw.print("uid="); pw.println(getUid());
pw.print(prefix); pw.println("policies:");
@@ -3533,6 +3609,76 @@
}
}
+ public void setTrustAgentFeaturesEnabled(ComponentName admin, ComponentName agent,
+ List<String>features, int userHandle) {
+ if (!mHasFeature) {
+ return;
+ }
+ enforceCrossUserPermission(userHandle);
+ enforceNotManagedProfile(userHandle, "manage trust agent features");
+ synchronized (this) {
+ if (admin == null) {
+ throw new NullPointerException("admin is null");
+ }
+ if (agent == null) {
+ throw new NullPointerException("agent is null");
+ }
+ ActiveAdmin ap = getActiveAdminForCallerLocked(admin,
+ DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_FEATURES);
+ ap.trustAgentFeatures.put(agent.flattenToString(), features);
+ saveSettingsLocked(userHandle);
+ syncDeviceCapabilitiesLocked(getUserData(userHandle));
+ }
+ }
+
+ public List<String> getTrustAgentFeaturesEnabled(ComponentName admin, ComponentName agent,
+ int userHandle) {
+ if (!mHasFeature) {
+ return null;
+ }
+ enforceCrossUserPermission(userHandle);
+ synchronized (this) {
+ if (agent == null) {
+ throw new NullPointerException("agent is null");
+ }
+ final String componentName = agent.flattenToString();
+ if (admin != null) {
+ final ActiveAdmin ap = getActiveAdminUncheckedLocked(admin, userHandle);
+ return (ap != null) ? ap.trustAgentFeatures.get(componentName) : null;
+ }
+
+ // Return strictest policy for this user and profiles that are visible from this user.
+ List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
+ List<String> result = null;
+ for (UserInfo userInfo : profiles) {
+ DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+ final int N = policy.mAdminList.size();
+ for (int i=0; i<N; i++) {
+ ActiveAdmin ap = policy.mAdminList.get(i);
+ // Compute the intersection of all features for active admins that disable
+ // trust agents:
+ if ((ap.disabledKeyguardFeatures
+ & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0) {
+ final List<String> features = ap.trustAgentFeatures.get(componentName);
+ if (result == null) {
+ if (features == null || features.size() == 0) {
+ result = new ArrayList<String>();
+ Slog.w(LOG_TAG, "admin " + ap.info.getPackageName()
+ + " has null trust agent feature set; all will be disabled");
+ } else {
+ result = new ArrayList<String>(features.size());
+ result.addAll(features);
+ }
+ } else {
+ result.retainAll(features);
+ }
+ }
+ }
+ }
+ return result;
+ }
+ }
+
@Override
public void setRestrictionsProvider(ComponentName who, ComponentName permissionProvider) {
synchronized (this) {