summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt1
-rw-r--r--core/java/android/app/Notification.java3
-rw-r--r--core/java/android/app/trust/ITrustListener.aidl1
-rw-r--r--core/java/android/app/trust/TrustManager.java17
-rw-r--r--core/java/android/content/pm/LauncherApps.java164
-rw-r--r--core/java/android/os/Build.java18
-rw-r--r--core/java/android/service/notification/NotificationListenerService.java42
-rw-r--r--core/java/android/service/trust/ITrustAgentService.aidl2
-rw-r--r--core/java/android/service/trust/ITrustAgentServiceCallback.aidl3
-rw-r--r--core/java/android/service/trust/TrustAgentService.java77
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java17
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java6
-rw-r--r--packages/Keyguard/test/SampleTrustAgent/res/layout/sample_trust_agent_settings.xml8
-rw-r--r--packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java40
-rw-r--r--packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java9
-rw-r--r--packages/SystemUI/res/drawable/trust_circle.xml22
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java15
-rw-r--r--services/core/java/com/android/server/trust/TrustAgentWrapper.java125
-rw-r--r--services/core/java/com/android/server/trust/TrustArchive.java28
-rw-r--r--services/core/java/com/android/server/trust/TrustManagerService.java68
21 files changed, 550 insertions, 118 deletions
diff --git a/api/current.txt b/api/current.txt
index d1ece22a5d09..a261bd6a5fd0 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -8582,6 +8582,7 @@ package android.content.pm {
public class LauncherApps {
method public void addOnAppsChangedCallback(android.content.pm.LauncherApps.OnAppsChangedCallback);
+ method public void addOnAppsChangedCallback(android.content.pm.LauncherApps.OnAppsChangedCallback, android.os.Handler);
method public java.util.List<android.content.pm.LauncherActivityInfo> getActivityList(java.lang.String, android.os.UserHandle);
method public boolean isActivityEnabledForProfile(android.content.ComponentName, android.os.UserHandle);
method public boolean isPackageEnabledForProfile(java.lang.String, android.os.UserHandle);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 5782edc3e498..983e347f50d8 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1708,6 +1708,9 @@ public class Notification implements Parcelable
if (headsUpContentView != null) {
headsUpContentView.setUser(user);
}
+ if (publicVersion != null) {
+ publicVersion.setUser(user);
+ }
}
/**
diff --git a/core/java/android/app/trust/ITrustListener.aidl b/core/java/android/app/trust/ITrustListener.aidl
index 46800438f490..45a066dfdf92 100644
--- a/core/java/android/app/trust/ITrustListener.aidl
+++ b/core/java/android/app/trust/ITrustListener.aidl
@@ -23,4 +23,5 @@ package android.app.trust;
*/
oneway interface ITrustListener {
void onTrustChanged(boolean enabled, int userId);
+ void onTrustManagedChanged(boolean managed, int userId);
} \ No newline at end of file
diff --git a/core/java/android/app/trust/TrustManager.java b/core/java/android/app/trust/TrustManager.java
index 6e90590385be..796e3cc3498e 100644
--- a/core/java/android/app/trust/TrustManager.java
+++ b/core/java/android/app/trust/TrustManager.java
@@ -31,6 +31,7 @@ import android.util.Log;
public class TrustManager {
private static final int MSG_TRUST_CHANGED = 1;
+ private static final int MSG_TRUST_MANAGED_CHANGED = 2;
private static final String TAG = "TrustManager";
@@ -98,6 +99,13 @@ public class TrustManager {
mHandler.obtainMessage(MSG_TRUST_CHANGED, (enabled ? 1 : 0), userId,
trustListener).sendToTarget();
}
+
+ @Override
+ public void onTrustManagedChanged(boolean managed, int userId)
+ throws RemoteException {
+ mHandler.obtainMessage(MSG_TRUST_MANAGED_CHANGED, (managed ? 1 : 0), userId,
+ trustListener).sendToTarget();
+ }
};
mService.registerTrustListener(iTrustListener);
mTrustListeners.put(trustListener, iTrustListener);
@@ -133,6 +141,8 @@ public class TrustManager {
case MSG_TRUST_CHANGED:
((TrustListener)msg.obj).onTrustChanged(msg.arg1 != 0, msg.arg2);
break;
+ case MSG_TRUST_MANAGED_CHANGED:
+ ((TrustListener)msg.obj).onTrustManagedChanged(msg.arg1 != 0, msg.arg2);
}
}
};
@@ -145,5 +155,12 @@ public class TrustManager {
* @param userId the user, for which the trust changed.
*/
void onTrustChanged(boolean enabled, int userId);
+
+ /**
+ * Reports that whether trust is managed has changed
+ * @param enabled if true, at least one trust agent is managing trust.
+ * @param userId the user, for which the state changed.
+ */
+ void onTrustManagedChanged(boolean enabled, int userId);
}
}
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index c95a5bf5c780..8c37e9e790b4 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -25,6 +25,9 @@ import android.content.pm.IOnAppsChangedListener;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Rect;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
@@ -55,8 +58,8 @@ public class LauncherApps {
private ILauncherApps mService;
private PackageManager mPm;
- private List<OnAppsChangedCallback> mCallbacks
- = new ArrayList<OnAppsChangedCallback>();
+ private List<CallbackMessageHandler> mCallbacks
+ = new ArrayList<CallbackMessageHandler>();
/**
* Callbacks for package changes to this and related managed profiles.
@@ -65,6 +68,9 @@ public class LauncherApps {
/**
* Indicates that a package was removed from the specified profile.
*
+ * If a package is removed while being updated onPackageChanged will be
+ * called instead.
+ *
* @param packageName The name of the package that was removed.
* @param user The UserHandle of the profile that generated the change.
*/
@@ -73,6 +79,9 @@ public class LauncherApps {
/**
* Indicates that a package was added to the specified profile.
*
+ * If a package is added while being updated then onPackageChanged will be
+ * called instead.
+ *
* @param packageName The name of the package that was added.
* @param user The UserHandle of the profile that generated the change.
*/
@@ -80,6 +89,8 @@ public class LauncherApps {
/**
* Indicates that a package was modified in the specified profile.
+ * This can happen, for example, when the package is updated or when
+ * one or more components are enabled or disabled.
*
* @param packageName The name of the package that has changed.
* @param user The UserHandle of the profile that generated the change.
@@ -286,10 +297,21 @@ public class LauncherApps {
* @param callback The callback to add.
*/
public void addOnAppsChangedCallback(OnAppsChangedCallback callback) {
+ addOnAppsChangedCallback(callback, null);
+ }
+
+ /**
+ * Adds a callback for changes to packages in current and managed profiles.
+ *
+ * @param callback The callback to add.
+ * @param handler that should be used to post callbacks on, may be null.
+ */
+ public void addOnAppsChangedCallback(OnAppsChangedCallback callback, Handler handler) {
synchronized (this) {
if (callback != null && !mCallbacks.contains(callback)) {
- mCallbacks.add(callback);
- if (mCallbacks.size() == 1) {
+ boolean addedFirstCallback = mCallbacks.size() == 0;
+ addCallbackLocked(callback, handler);
+ if (addedFirstCallback) {
try {
mService.addOnAppsChangedListener(mAppsChangedListener);
} catch (RemoteException re) {
@@ -307,7 +329,7 @@ public class LauncherApps {
*/
public void removeOnAppsChangedCallback(OnAppsChangedCallback callback) {
synchronized (this) {
- mCallbacks.remove(callback);
+ removeCallbackLocked(callback);
if (mCallbacks.size() == 0) {
try {
mService.removeOnAppsChangedListener(mAppsChangedListener);
@@ -317,16 +339,40 @@ public class LauncherApps {
}
}
+ private void removeCallbackLocked(OnAppsChangedCallback callback) {
+ if (callback == null) {
+ throw new IllegalArgumentException("Callback cannot be null");
+ }
+ final int size = mCallbacks.size();
+ for (int i = 0; i < size; ++i) {
+ if (mCallbacks.get(i).mCallback == callback) {
+ mCallbacks.remove(i);
+ return;
+ }
+ }
+ }
+
+ private void addCallbackLocked(OnAppsChangedCallback callback, Handler handler) {
+ // Remove if already present.
+ removeCallbackLocked(callback);
+ if (handler == null) {
+ handler = new Handler();
+ }
+ CallbackMessageHandler toAdd = new CallbackMessageHandler(handler.getLooper(), callback);
+ mCallbacks.add(toAdd);
+ }
+
private IOnAppsChangedListener.Stub mAppsChangedListener = new IOnAppsChangedListener.Stub() {
@Override
- public void onPackageRemoved(UserHandle user, String packageName) throws RemoteException {
+ public void onPackageRemoved(UserHandle user, String packageName)
+ throws RemoteException {
if (DEBUG) {
Log.d(TAG, "onPackageRemoved " + user.getIdentifier() + "," + packageName);
}
synchronized (LauncherApps.this) {
- for (OnAppsChangedCallback callback : mCallbacks) {
- callback.onPackageRemoved(packageName, user);
+ for (CallbackMessageHandler callback : mCallbacks) {
+ callback.postOnPackageRemoved(packageName, user);
}
}
}
@@ -337,8 +383,8 @@ public class LauncherApps {
Log.d(TAG, "onPackageChanged " + user.getIdentifier() + "," + packageName);
}
synchronized (LauncherApps.this) {
- for (OnAppsChangedCallback callback : mCallbacks) {
- callback.onPackageChanged(packageName, user);
+ for (CallbackMessageHandler callback : mCallbacks) {
+ callback.postOnPackageChanged(packageName, user);
}
}
}
@@ -349,8 +395,8 @@ public class LauncherApps {
Log.d(TAG, "onPackageAdded " + user.getIdentifier() + "," + packageName);
}
synchronized (LauncherApps.this) {
- for (OnAppsChangedCallback callback : mCallbacks) {
- callback.onPackageAdded(packageName, user);
+ for (CallbackMessageHandler callback : mCallbacks) {
+ callback.postOnPackageAdded(packageName, user);
}
}
}
@@ -362,8 +408,8 @@ public class LauncherApps {
Log.d(TAG, "onPackagesAvailable " + user.getIdentifier() + "," + packageNames);
}
synchronized (LauncherApps.this) {
- for (OnAppsChangedCallback callback : mCallbacks) {
- callback.onPackagesAvailable(packageNames, user, replacing);
+ for (CallbackMessageHandler callback : mCallbacks) {
+ callback.postOnPackagesAvailable(packageNames, user, replacing);
}
}
}
@@ -375,10 +421,96 @@ public class LauncherApps {
Log.d(TAG, "onPackagesUnavailable " + user.getIdentifier() + "," + packageNames);
}
synchronized (LauncherApps.this) {
- for (OnAppsChangedCallback callback : mCallbacks) {
- callback.onPackagesUnavailable(packageNames, user, replacing);
+ for (CallbackMessageHandler callback : mCallbacks) {
+ callback.postOnPackagesUnavailable(packageNames, user, replacing);
}
}
}
};
+
+ private static class CallbackMessageHandler extends Handler {
+ private static final int MSG_ADDED = 1;
+ private static final int MSG_REMOVED = 2;
+ private static final int MSG_CHANGED = 3;
+ private static final int MSG_AVAILABLE = 4;
+ private static final int MSG_UNAVAILABLE = 5;
+
+ private OnAppsChangedCallback mCallback;
+
+ private static class CallbackInfo {
+ String[] packageNames;
+ String packageName;
+ boolean replacing;
+ UserHandle user;
+ }
+
+ public CallbackMessageHandler(Looper looper, OnAppsChangedCallback callback) {
+ super(looper, null, true);
+ mCallback = callback;
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ if (mCallback == null || !(msg.obj instanceof CallbackInfo)) {
+ return;
+ }
+ CallbackInfo info = (CallbackInfo) msg.obj;
+ switch (msg.what) {
+ case MSG_ADDED:
+ mCallback.onPackageAdded(info.packageName, info.user);
+ break;
+ case MSG_REMOVED:
+ mCallback.onPackageRemoved(info.packageName, info.user);
+ break;
+ case MSG_CHANGED:
+ mCallback.onPackageChanged(info.packageName, info.user);
+ break;
+ case MSG_AVAILABLE:
+ mCallback.onPackagesAvailable(info.packageNames, info.user, info.replacing);
+ break;
+ case MSG_UNAVAILABLE:
+ mCallback.onPackagesUnavailable(info.packageNames, info.user, info.replacing);
+ break;
+ }
+ }
+
+ public void postOnPackageAdded(String packageName, UserHandle user) {
+ CallbackInfo info = new CallbackInfo();
+ info.packageName = packageName;
+ info.user = user;
+ obtainMessage(MSG_ADDED, info).sendToTarget();
+ }
+
+ public void postOnPackageRemoved(String packageName, UserHandle user) {
+ CallbackInfo info = new CallbackInfo();
+ info.packageName = packageName;
+ info.user = user;
+ obtainMessage(MSG_REMOVED, info).sendToTarget();
+ }
+
+ public void postOnPackageChanged(String packageName, UserHandle user) {
+ CallbackInfo info = new CallbackInfo();
+ info.packageName = packageName;
+ info.user = user;
+ obtainMessage(MSG_CHANGED, info).sendToTarget();
+ }
+
+ public void postOnPackagesAvailable(String[] packageNames, UserHandle user,
+ boolean replacing) {
+ CallbackInfo info = new CallbackInfo();
+ info.packageNames = packageNames;
+ info.replacing = replacing;
+ info.user = user;
+ obtainMessage(MSG_AVAILABLE, info).sendToTarget();
+ }
+
+ public void postOnPackagesUnavailable(String[] packageNames, UserHandle user,
+ boolean replacing) {
+ CallbackInfo info = new CallbackInfo();
+ info.packageNames = packageNames;
+ info.replacing = replacing;
+ info.user = user;
+ obtainMessage(MSG_UNAVAILABLE, info).sendToTarget();
+ }
+ }
}
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index b5c4cd61a933..b0e0b4972a58 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -96,8 +96,7 @@ public class Build {
*
* See {@link #SUPPORTED_32_BIT_ABIS} and {@link #SUPPORTED_64_BIT_ABIS}.
*/
- public static final String[] SUPPORTED_ABIS = SystemProperties.get("ro.product.cpu.abilist")
- .split(",");
+ public static final String[] SUPPORTED_ABIS = getStringList("ro.product.cpu.abilist", ",");
/**
* An ordered list of <b>32 bit</b> ABIs supported by this device. The most preferred ABI
@@ -106,7 +105,7 @@ public class Build {
* See {@link #SUPPORTED_ABIS} and {@link #SUPPORTED_64_BIT_ABIS}.
*/
public static final String[] SUPPORTED_32_BIT_ABIS =
- SystemProperties.get("ro.product.cpu.abilist32").split(",");
+ getStringList("ro.product.cpu.abilist32", ",");
/**
* An ordered list of <b>64 bit</b> ABIs supported by this device. The most preferred ABI
@@ -115,7 +114,7 @@ public class Build {
* See {@link #SUPPORTED_ABIS} and {@link #SUPPORTED_32_BIT_ABIS}.
*/
public static final String[] SUPPORTED_64_BIT_ABIS =
- SystemProperties.get("ro.product.cpu.abilist64").split(",");
+ getStringList("ro.product.cpu.abilist64", ",");
/** Various version strings. */
@@ -155,7 +154,7 @@ public class Build {
public static final String CODENAME = getString("ro.build.version.codename");
private static final String[] ALL_CODENAMES
- = getString("ro.build.version.all_codenames").split(",");
+ = getStringList("ro.build.version.all_codenames", ",");
/**
* @hide
@@ -614,6 +613,15 @@ public class Build {
return SystemProperties.get(property, UNKNOWN);
}
+ private static String[] getStringList(String property, String separator) {
+ String value = SystemProperties.get(property);
+ if (value.isEmpty()) {
+ return new String[0];
+ } else {
+ return value.split(separator);
+ }
+ }
+
private static long getLong(String property) {
try {
return Long.parseLong(SystemProperties.get(property));
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 1fc64e4d3e81..7c8624c5ffbe 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -29,8 +29,11 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.Log;
+import java.util.Collections;
import java.util.List;
/**
@@ -540,6 +543,8 @@ public abstract class NotificationListenerService extends Service {
*/
public static class RankingMap implements Parcelable {
private final NotificationRankingUpdate mRankingUpdate;
+ private ArrayMap<String,Integer> mRanks;
+ private ArraySet<Object> mIntercepted;
private RankingMap(NotificationRankingUpdate rankingUpdate) {
mRankingUpdate = rankingUpdate;
@@ -569,14 +574,13 @@ public abstract class NotificationListenerService extends Service {
}
private int getRank(String key) {
- // TODO: Optimize.
- String[] orderedKeys = mRankingUpdate.getOrderedKeys();
- for (int i = 0; i < orderedKeys.length; i++) {
- if (orderedKeys[i].equals(key)) {
- return i;
+ synchronized (this) {
+ if (mRanks == null) {
+ buildRanksLocked();
}
}
- return -1;
+ Integer rank = mRanks.get(key);
+ return rank != null ? rank : -1;
}
private boolean isAmbient(String key) {
@@ -585,13 +589,29 @@ public abstract class NotificationListenerService extends Service {
}
private boolean isIntercepted(String key) {
- // TODO: Optimize.
- for (String interceptedKey : mRankingUpdate.getInterceptedKeys()) {
- if (interceptedKey.equals(key)) {
- return true;
+ synchronized (this) {
+ if (mIntercepted == null) {
+ buildInterceptedSetLocked();
}
}
- return false;
+ return mIntercepted.contains(key);
+ }
+
+ // Locked by 'this'
+ private void buildRanksLocked() {
+ String[] orderedKeys = mRankingUpdate.getOrderedKeys();
+ mRanks = new ArrayMap<>(orderedKeys.length);
+ for (int i = 0; i < orderedKeys.length; i++) {
+ String key = orderedKeys[i];
+ mRanks.put(key, i);
+ }
+ }
+
+ // Locked by 'this'
+ private void buildInterceptedSetLocked() {
+ String[] dndInterceptedKeys = mRankingUpdate.getInterceptedKeys();
+ mIntercepted = new ArraySet<>(dndInterceptedKeys.length);
+ Collections.addAll(mIntercepted, dndInterceptedKeys);
}
// ----------- Parcelable
diff --git a/core/java/android/service/trust/ITrustAgentService.aidl b/core/java/android/service/trust/ITrustAgentService.aidl
index 49eb7bea4061..637d08070619 100644
--- a/core/java/android/service/trust/ITrustAgentService.aidl
+++ b/core/java/android/service/trust/ITrustAgentService.aidl
@@ -25,5 +25,5 @@ import android.service.trust.ITrustAgentServiceCallback;
interface ITrustAgentService {
oneway void onUnlockAttempt(boolean successful);
oneway void setCallback(ITrustAgentServiceCallback callback);
- boolean setTrustAgentFeaturesEnabled(in Bundle options);
+ oneway void setTrustAgentFeaturesEnabled(in Bundle options, IBinder token);
}
diff --git a/core/java/android/service/trust/ITrustAgentServiceCallback.aidl b/core/java/android/service/trust/ITrustAgentServiceCallback.aidl
index 9e4c2bf940fa..b107bccb4f84 100644
--- a/core/java/android/service/trust/ITrustAgentServiceCallback.aidl
+++ b/core/java/android/service/trust/ITrustAgentServiceCallback.aidl
@@ -16,6 +16,7 @@
package android.service.trust;
import android.os.Bundle;
+import android.os.IBinder;
import android.os.UserHandle;
/**
@@ -25,4 +26,6 @@ import android.os.UserHandle;
oneway interface ITrustAgentServiceCallback {
void grantTrust(CharSequence message, long durationMs, boolean initiatedByUser);
void revokeTrust();
+ void setManagingTrust(boolean managingTrust);
+ void onSetTrustAgentFeaturesEnabledCompleted(boolean result, IBinder token);
}
diff --git a/core/java/android/service/trust/TrustAgentService.java b/core/java/android/service/trust/TrustAgentService.java
index 61da85f613dd..51f07ecf16bb 100644
--- a/core/java/android/service/trust/TrustAgentService.java
+++ b/core/java/android/service/trust/TrustAgentService.java
@@ -28,6 +28,7 @@ import android.content.pm.ServiceInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
+import android.os.Message;
import android.os.RemoteException;
import android.util.Log;
import android.util.Slog;
@@ -66,6 +67,13 @@ import android.util.Slog;
public class TrustAgentService extends Service {
private final String TAG = TrustAgentService.class.getSimpleName() +
"[" + getClass().getSimpleName() + "]";
+ private static final boolean DEBUG = false;
+
+ // Temporary workaround to allow current trust agent implementations to continue working.
+ // This and the code guarded by this should be removed before shipping.
+ // If true, calls setManagingTrust(true) after onCreate, if it wasn't already set.
+ // TODO: Remove this once all agents are updated.
+ private static final boolean SET_MANAGED_FOR_LEGACY_AGENTS = true;
/**
* The {@link Intent} that must be declared as handled by the service.
@@ -87,13 +95,14 @@ public class TrustAgentService extends Service {
public static final String KEY_FEATURES = "trust_agent_features";
private static final int MSG_UNLOCK_ATTEMPT = 1;
-
- private static final boolean DEBUG = false;
+ private static final int MSG_SET_TRUST_AGENT_FEATURES_ENABLED = 2;
private ITrustAgentServiceCallback mCallback;
private Runnable mPendingGrantTrustTask;
+ private boolean mManagingTrust;
+
// Lock used to access mPendingGrantTrustTask and mCallback.
private final Object mLock = new Object();
@@ -103,12 +112,29 @@ public class TrustAgentService extends Service {
case MSG_UNLOCK_ATTEMPT:
onUnlockAttempt(msg.arg1 != 0);
break;
+ case MSG_SET_TRUST_AGENT_FEATURES_ENABLED:
+ Bundle features = msg.peekData();
+ IBinder token = (IBinder) msg.obj;
+ boolean result = onSetTrustAgentFeaturesEnabled(features);
+ try {
+ synchronized (mLock) {
+ mCallback.onSetTrustAgentFeaturesEnabledCompleted(result, token);
+ }
+ } catch (RemoteException e) {
+ onError("calling onSetTrustAgentFeaturesEnabledCompleted()");
+ }
+ break;
}
- };
+ }
};
@Override
public void onCreate() {
+ // TODO: Remove this once all agents are updated.
+ if (SET_MANAGED_FOR_LEGACY_AGENTS) {
+ setManagingTrust(true);
+ }
+
super.onCreate();
ComponentName component = new ComponentName(this, getClass());
try {
@@ -163,10 +189,15 @@ public class TrustAgentService extends Service {
* for this agent will automatically be revoked when the timeout expires.
* @param initiatedByUser indicates that the user has explicitly initiated an action that proves
* the user is about to use the device.
+ * @throws IllegalStateException if the agent is not currently managing trust.
*/
public final void grantTrust(
final CharSequence message, final long durationMs, final boolean initiatedByUser) {
synchronized (mLock) {
+ if (!mManagingTrust) {
+ throw new IllegalStateException("Cannot grant trust if agent is not managing trust."
+ + " Call setManagingTrust(true) first.");
+ }
if (mCallback != null) {
try {
mCallback.grantTrust(message.toString(), durationMs, initiatedByUser);
@@ -204,6 +235,29 @@ public class TrustAgentService extends Service {
}
}
+ /**
+ * Call to notify the system if the agent is ready to manage trust.
+ *
+ * This property is not persistent across recreating the service and defaults to false.
+ * Therefore this method is typically called when initializing the agent in {@link #onCreate}.
+ *
+ * @param managingTrust indicates if the agent would like to manage trust.
+ */
+ public final void setManagingTrust(boolean managingTrust) {
+ synchronized (mLock) {
+ if (mManagingTrust != managingTrust) {
+ mManagingTrust = managingTrust;
+ if (mCallback != null) {
+ try {
+ mCallback.setManagingTrust(managingTrust);
+ } catch (RemoteException e) {
+ onError("calling setManagingTrust()");
+ }
+ }
+ }
+ }
+ }
+
@Override
public final IBinder onBind(Intent intent) {
if (DEBUG) Slog.v(TAG, "onBind() intent = " + intent);
@@ -221,6 +275,15 @@ public class TrustAgentService extends Service {
public void setCallback(ITrustAgentServiceCallback callback) {
synchronized (mLock) {
mCallback = callback;
+ // The managingTrust property is false implicitly on the server-side, so we only
+ // need to set it here if the agent has decided to manage trust.
+ if (mManagingTrust) {
+ try {
+ mCallback.setManagingTrust(mManagingTrust);
+ } catch (RemoteException e ) {
+ onError("calling setManagingTrust()");
+ }
+ }
if (mPendingGrantTrustTask != null) {
mPendingGrantTrustTask.run();
mPendingGrantTrustTask = null;
@@ -229,10 +292,10 @@ public class TrustAgentService extends Service {
}
@Override
- public boolean setTrustAgentFeaturesEnabled(Bundle features) {
- synchronized (mLock) {
- return onSetTrustAgentFeaturesEnabled(features);
- }
+ public void setTrustAgentFeaturesEnabled(Bundle features, IBinder token) {
+ Message msg = mHandler.obtainMessage(MSG_SET_TRUST_AGENT_FEATURES_ENABLED, token);
+ msg.setData(features);
+ msg.sendToTarget();
}
}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index f0f5772acccd..e4d78507c0d4 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -216,6 +216,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
};
private SparseBooleanArray mUserHasTrust = new SparseBooleanArray();
+ private SparseBooleanArray mUserTrustIsManaged = new SparseBooleanArray();
private SparseBooleanArray mUserFingerprintRecognized = new SparseBooleanArray();
@Override
@@ -230,6 +231,18 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
}
}
+ @Override
+ public void onTrustManagedChanged(boolean managed, int userId) {
+ mUserTrustIsManaged.put(userId, managed);
+
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+ if (cb != null) {
+ cb.onTrustManagedChanged(userId);
+ }
+ }
+ }
+
private void onFingerprintRecognized(int userId) {
mUserFingerprintRecognized.put(userId, true);
for (int i = 0; i < mCallbacks.size(); i++) {
@@ -305,6 +318,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
|| mUserFingerprintRecognized.get(userId);
}
+ public boolean getUserTrustIsManaged(int userId) {
+ return mUserTrustIsManaged.get(userId) && !isTrustDisabled(userId);
+ }
+
static class DisplayClientState {
public int clientGeneration;
public boolean clearing;
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index 14c127835868..0aefa2d6d7ce 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -174,6 +174,11 @@ public class KeyguardUpdateMonitorCallback {
public void onTrustChanged(int userId) { }
/**
+ * Called when trust being managed changes for a user.
+ */
+ public void onTrustManagedChanged(int userId) { }
+
+ /**
* Called when a fingerprint is recognized.
* @param userId
*/
@@ -183,5 +188,4 @@ public class KeyguardUpdateMonitorCallback {
* Called when fingerprint is acquired but not yet recognized
*/
public void onFingerprintAcquired(int info) { }
-
}
diff --git a/packages/Keyguard/test/SampleTrustAgent/res/layout/sample_trust_agent_settings.xml b/packages/Keyguard/test/SampleTrustAgent/res/layout/sample_trust_agent_settings.xml
index 06a06bf876b0..796cefbe68c3 100644
--- a/packages/Keyguard/test/SampleTrustAgent/res/layout/sample_trust_agent_settings.xml
+++ b/packages/Keyguard/test/SampleTrustAgent/res/layout/sample_trust_agent_settings.xml
@@ -32,8 +32,16 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Crash" />
+ <CheckBox android:id="@+id/managing_trust"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"
+ android:text="Managing trust" />
<CheckBox android:id="@+id/report_unlock_attempts"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"
android:text="Report unlock attempts" />
</LinearLayout> \ No newline at end of file
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 50a3f822410e..ed17494a7fce 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
@@ -28,7 +28,8 @@ import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import android.widget.Toast;
-public class SampleTrustAgent extends TrustAgentService {
+public class SampleTrustAgent extends TrustAgentService
+ implements SharedPreferences.OnSharedPreferenceChangeListener {
LocalBroadcastManager mLocalBroadcastManager;
@@ -41,6 +42,8 @@ public class SampleTrustAgent extends TrustAgentService {
private static final String PREFERENCE_REPORT_UNLOCK_ATTEMPTS
= "preference.report_unlock_attempts";
+ private static final String PREFERENCE_MANAGING_TRUST
+ = "preference.managing_trust";
private static final String TAG = "SampleTrustAgent";
@@ -52,6 +55,9 @@ public class SampleTrustAgent extends TrustAgentService {
filter.addAction(ACTION_REVOKE_TRUST);
mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);
mLocalBroadcastManager.registerReceiver(mReceiver, filter);
+ setManagingTrust(getIsManagingTrust(this));
+ PreferenceManager.getDefaultSharedPreferences(this)
+ .registerOnSharedPreferenceChangeListener(this);
}
@Override
@@ -73,6 +79,8 @@ public class SampleTrustAgent extends TrustAgentService {
public void onDestroy() {
super.onDestroy();
mLocalBroadcastManager.unregisterReceiver(mReceiver);
+ PreferenceManager.getDefaultSharedPreferences(this)
+ .unregisterOnSharedPreferenceChangeListener(this);
}
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@@ -80,9 +88,14 @@ public class SampleTrustAgent extends TrustAgentService {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_GRANT_TRUST.equals(action)) {
- grantTrust(intent.getStringExtra(EXTRA_MESSAGE),
- intent.getLongExtra(EXTRA_DURATION, 0),
- false /* initiatedByUser */);
+ try {
+ grantTrust(intent.getStringExtra(EXTRA_MESSAGE),
+ intent.getLongExtra(EXTRA_DURATION, 0),
+ false /* initiatedByUser */);
+ } catch (IllegalStateException e) {
+ Toast.makeText(context,
+ "IllegalStateException: " + e.getMessage(), Toast.LENGTH_SHORT).show();
+ }
} else if (ACTION_REVOKE_TRUST.equals(action)) {
revokeTrust();
}
@@ -114,4 +127,23 @@ public class SampleTrustAgent extends TrustAgentService {
.getDefaultSharedPreferences(context);
return sharedPreferences.getBoolean(PREFERENCE_REPORT_UNLOCK_ATTEMPTS, false);
}
+
+ public static void setIsManagingTrust(Context context, boolean enabled) {
+ SharedPreferences sharedPreferences = PreferenceManager
+ .getDefaultSharedPreferences(context);
+ sharedPreferences.edit().putBoolean(PREFERENCE_MANAGING_TRUST, enabled).apply();
+ }
+
+ public static boolean getIsManagingTrust(Context context) {
+ SharedPreferences sharedPreferences = PreferenceManager
+ .getDefaultSharedPreferences(context);
+ return sharedPreferences.getBoolean(PREFERENCE_MANAGING_TRUST, false);
+ }
+
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
+ if (PREFERENCE_MANAGING_TRUST.equals(key)) {
+ setManagingTrust(getIsManagingTrust(this));
+ }
+ }
}
diff --git a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java
index 6b5f78b52ac2..2c856099c708 100644
--- a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java
+++ b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java
@@ -29,6 +29,7 @@ public class SampleTrustAgentSettings extends Activity implements View.OnClickLi
private static final int TRUST_DURATION_MS = 30 * 1000;
private CheckBox mReportUnlockAttempts;
+ private CheckBox mManagingTrust;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
@@ -41,12 +42,16 @@ public class SampleTrustAgentSettings extends Activity implements View.OnClickLi
mReportUnlockAttempts = (CheckBox) findViewById(R.id.report_unlock_attempts);
mReportUnlockAttempts.setOnCheckedChangeListener(this);
+
+ mManagingTrust = (CheckBox) findViewById(R.id.managing_trust);
+ mManagingTrust.setOnCheckedChangeListener(this);
}
@Override
protected void onResume() {
super.onResume();
mReportUnlockAttempts.setChecked(SampleTrustAgent.getReportUnlockAttempts(this));
+ mManagingTrust.setChecked(SampleTrustAgent.getIsManagingTrust(this));
}
@Override
@@ -64,8 +69,10 @@ public class SampleTrustAgentSettings extends Activity implements View.OnClickLi
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- if (buttonView.getId() == R.id.report_unlock_attempts) {
+ if (buttonView == mReportUnlockAttempts) {
SampleTrustAgent.setReportUnlockAttempts(this, isChecked);
+ } else if (buttonView == mManagingTrust) {
+ SampleTrustAgent.setIsManagingTrust(this, isChecked);
}
}
}
diff --git a/packages/SystemUI/res/drawable/trust_circle.xml b/packages/SystemUI/res/drawable/trust_circle.xml
new file mode 100644
index 000000000000..89f4a0b89e5a
--- /dev/null
+++ b/packages/SystemUI/res/drawable/trust_circle.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2014 The Android Open Source 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
+ -->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="ring"
+ android:innerRadius="24dp" android:thickness="1dp">
+ <solid android:color="#66ffffff" />
+</shape> \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index b5f517d25beb..82e59c0249ad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -237,6 +237,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
? R.drawable.ic_lock_open_24dp
: R.drawable.ic_lock_24dp;
mLockIcon.setImageResource(iconRes);
+ boolean trustManaged = mUnlockMethodCache.isTrustManaged();
+ mLockIcon.setBackgroundResource(trustManaged ? R.drawable.trust_circle : 0);
}
public KeyguardAffordanceView getPhoneView() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
index c9e0db68b0dd..58196f73e66e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
@@ -37,6 +37,7 @@ public class UnlockMethodCache {
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final ArrayList<OnUnlockMethodChangedListener> mListeners = new ArrayList<>();
private boolean mMethodInsecure;
+ private boolean mTrustManaged;
private UnlockMethodCache(Context ctx) {
mLockPatternUtils = new LockPatternUtils(ctx);
@@ -71,9 +72,11 @@ public class UnlockMethodCache {
int user = mLockPatternUtils.getCurrentUser();
boolean methodInsecure = !mLockPatternUtils.isSecure() ||
mKeyguardUpdateMonitor.getUserHasTrust(user);
- boolean changed = methodInsecure != mMethodInsecure;
+ boolean trustManaged = mKeyguardUpdateMonitor.getUserTrustIsManaged(user);
+ boolean changed = methodInsecure != mMethodInsecure || trustManaged != mTrustManaged;
if (changed || updateAlways) {
mMethodInsecure = methodInsecure;
+ mTrustManaged = trustManaged;
notifyListeners(mMethodInsecure);
}
}
@@ -96,15 +99,25 @@ public class UnlockMethodCache {
}
@Override
+ public void onTrustManagedChanged(int userId) {
+ updateMethodSecure(false /* updateAlways */);
+ }
+
+ @Override
public void onScreenTurnedOn() {
updateMethodSecure(false /* updateAlways */);
}
+ @Override
public void onFingerprintRecognized(int userId) {
updateMethodSecure(false /* updateAlways */);
}
};
+ public boolean isTrustManaged() {
+ return mTrustManaged;
+ }
+
public static interface OnUnlockMethodChangedListener {
void onMethodSecureChanged(boolean methodSecure);
}
diff --git a/services/core/java/com/android/server/trust/TrustAgentWrapper.java b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
index 0acb82ffff57..ee20b3c3c7a7 100644
--- a/services/core/java/com/android/server/trust/TrustAgentWrapper.java
+++ b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
@@ -17,12 +17,11 @@
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.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -51,7 +50,8 @@ public class TrustAgentWrapper {
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;
+ private static final int MSG_SET_TRUST_AGENT_FEATURES_COMPLETED = 5;
+ private static final int MSG_MANAGING_TRUST = 6;
/**
* Time in uptime millis that we wait for the service connection, both when starting
@@ -77,6 +77,8 @@ public class TrustAgentWrapper {
private boolean mTrusted;
private CharSequence mMessage;
private boolean mTrustDisabledByDpm;
+ private boolean mManagingTrust;
+ private IBinder mSetTrustAgentFeaturesToken;
private final Handler mHandler = new Handler() {
@Override
@@ -119,8 +121,30 @@ public class TrustAgentWrapper {
unbind();
mTrustManagerService.resetAgent(mName, mUserId);
break;
- case MSG_DPM_CHANGED:
- updateDevicePolicyFeatures(mName);
+ case MSG_SET_TRUST_AGENT_FEATURES_COMPLETED:
+ IBinder token = (IBinder) msg.obj;
+ boolean result = msg.arg1 != 0;
+ if (mSetTrustAgentFeaturesToken == token) {
+ mSetTrustAgentFeaturesToken = null;
+ if (mTrustDisabledByDpm && result) {
+ if (DEBUG) Log.v(TAG, "Re-enabling agent because it acknowledged "
+ + "enabled features: " + mName);
+ mTrustDisabledByDpm = false;
+ mTrustManagerService.updateTrust(mUserId);
+ }
+ } else {
+ if (DEBUG) Log.w(TAG, "Ignoring MSG_SET_TRUST_AGENT_FEATURES_COMPLETED "
+ + "with obsolete token: " + mName);
+ }
+ break;
+ case MSG_MANAGING_TRUST:
+ mManagingTrust = msg.arg1 != 0;
+ if (!mManagingTrust) {
+ mTrusted = false;
+ mMessage = null;
+ }
+ mTrustManagerService.mArchive.logManagingTrust(mUserId, mName, mManagingTrust);
+ mTrustManagerService.updateTrust(mUserId);
break;
}
}
@@ -144,6 +168,19 @@ public class TrustAgentWrapper {
if (DEBUG) Slog.v(TAG, "revokeTrust()");
mHandler.sendEmptyMessage(MSG_REVOKE_TRUST);
}
+
+ @Override
+ public void setManagingTrust(boolean managingTrust) {
+ if (DEBUG) Slog.v(TAG, "managingTrust()");
+ mHandler.obtainMessage(MSG_MANAGING_TRUST, managingTrust ? 1 : 0, 0).sendToTarget();
+ }
+
+ @Override
+ public void onSetTrustAgentFeaturesEnabledCompleted(boolean result, IBinder token) {
+ if (DEBUG) Slog.v(TAG, "onSetTrustAgentFeaturesEnabledCompleted(result=" + result);
+ mHandler.obtainMessage(MSG_SET_TRUST_AGENT_FEATURES_COMPLETED,
+ result ? 1 : 0, 0, token).sendToTarget();
+ }
};
private final ServiceConnection mConnection = new ServiceConnection() {
@@ -154,32 +191,21 @@ public class TrustAgentWrapper {
mTrustAgentService = ITrustAgentService.Stub.asInterface(service);
mTrustManagerService.mArchive.logAgentConnected(mUserId, name);
setCallback(mCallback);
- updateDevicePolicyFeatures(name);
- watchForDpmChanges(true);
+ updateDevicePolicyFeatures();
}
@Override
public void onServiceDisconnected(ComponentName name) {
if (DEBUG) Log.v(TAG, "TrustAgent disconnected : " + name.flattenToShortString());
mTrustAgentService = null;
+ mManagingTrust = false;
+ mSetTrustAgentFeaturesToken = null;
mTrustManagerService.mArchive.logAgentDied(mUserId, name);
mHandler.sendEmptyMessage(MSG_REVOKE_TRUST);
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);
- }
}
};
@@ -223,48 +249,32 @@ public class TrustAgentWrapper {
}
}
- 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 updateDevicePolicyFeatures() {
boolean trustDisabled = false;
- if (DEBUG) Slog.v(TAG, "updateDevicePolicyFeatures(" + name + ")");
+ if (DEBUG) Slog.v(TAG, "updateDevicePolicyFeatures(" + mName + ")");
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
+
+ if ((dpm.getKeyguardDisabledFeatures(null)
+ & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0) {
+ List<String> features = dpm.getTrustAgentFeaturesEnabled(null, mName);
+ trustDisabled = true;
+ 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 " + mName.flattenToShortString()
+ + " disabled until it acknowledges "+ features);
}
+ mSetTrustAgentFeaturesToken = new Binder();
+ mTrustAgentService.setTrustAgentFeaturesEnabled(bundle,
+ mSetTrustAgentFeaturesToken);
}
- } else {
- Log.e(TAG, "Can't get DevicePolicyManagerService: is it running?",
- new IllegalStateException("Stack trace:"));
}
}
} catch (RemoteException e) {
@@ -278,7 +288,11 @@ public class TrustAgentWrapper {
}
public boolean isTrusted() {
- return mTrusted && !mTrustDisabledByDpm;
+ return mTrusted && mManagingTrust && !mTrustDisabledByDpm;
+ }
+
+ public boolean isManagingTrust() {
+ return mManagingTrust && !mTrustDisabledByDpm;
}
public CharSequence getMessage() {
@@ -294,6 +308,7 @@ public class TrustAgentWrapper {
mContext.unbindService(mConnection);
mBound = false;
mTrustAgentService = null;
+ mSetTrustAgentFeaturesToken = null;
mHandler.sendEmptyMessage(MSG_REVOKE_TRUST);
mHandler.removeMessages(MSG_RESTART_TIMEOUT);
}
diff --git a/services/core/java/com/android/server/trust/TrustArchive.java b/services/core/java/com/android/server/trust/TrustArchive.java
index 5e32d86d27c0..d4ed86d4183d 100644
--- a/services/core/java/com/android/server/trust/TrustArchive.java
+++ b/services/core/java/com/android/server/trust/TrustArchive.java
@@ -35,6 +35,7 @@ public class TrustArchive {
private static final int TYPE_AGENT_DIED = 3;
private static final int TYPE_AGENT_CONNECTED = 4;
private static final int TYPE_AGENT_STOPPED = 5;
+ private static final int TYPE_MANAGING_TRUST = 6;
private static final int HISTORY_LIMIT = 200;
@@ -49,8 +50,11 @@ public class TrustArchive {
final long duration;
final boolean userInitiated;
+ // managingTrust
+ final boolean managingTrust;
+
private Event(int type, int userId, ComponentName agent, String message,
- long duration, boolean userInitiated) {
+ long duration, boolean userInitiated, boolean managingTrust) {
this.type = type;
this.userId = userId;
this.agent = agent;
@@ -58,6 +62,7 @@ public class TrustArchive {
this.message = message;
this.duration = duration;
this.userInitiated = userInitiated;
+ this.managingTrust = managingTrust;
}
}
@@ -66,27 +71,31 @@ public class TrustArchive {
public void logGrantTrust(int userId, ComponentName agent, String message,
long duration, boolean userInitiated) {
addEvent(new Event(TYPE_GRANT_TRUST, userId, agent, message, duration,
- userInitiated));
+ userInitiated, false));
}
public void logRevokeTrust(int userId, ComponentName agent) {
- addEvent(new Event(TYPE_REVOKE_TRUST, userId, agent, null, 0, false));
+ addEvent(new Event(TYPE_REVOKE_TRUST, userId, agent, null, 0, false, false));
}
public void logTrustTimeout(int userId, ComponentName agent) {
- addEvent(new Event(TYPE_TRUST_TIMEOUT, userId, agent, null, 0, false));
+ addEvent(new Event(TYPE_TRUST_TIMEOUT, userId, agent, null, 0, false, false));
}
public void logAgentDied(int userId, ComponentName agent) {
- addEvent(new Event(TYPE_AGENT_DIED, userId, agent, null, 0, false));
+ addEvent(new Event(TYPE_AGENT_DIED, userId, agent, null, 0, false, false));
}
public void logAgentConnected(int userId, ComponentName agent) {
- addEvent(new Event(TYPE_AGENT_CONNECTED, userId, agent, null, 0, false));
+ addEvent(new Event(TYPE_AGENT_CONNECTED, userId, agent, null, 0, false, false));
}
public void logAgentStopped(int userId, ComponentName agent) {
- addEvent(new Event(TYPE_AGENT_STOPPED, userId, agent, null, 0, false));
+ addEvent(new Event(TYPE_AGENT_STOPPED, userId, agent, null, 0, false, false));
+ }
+
+ public void logManagingTrust(int userId, ComponentName agent, boolean managing) {
+ addEvent(new Event(TYPE_MANAGING_TRUST, userId, agent, null, 0, false, managing));
}
private void addEvent(Event e) {
@@ -123,6 +132,9 @@ public class TrustArchive {
writer.printf(", message=\"%s\", duration=%s",
ev.message, formatDuration(ev.duration));
break;
+ case TYPE_MANAGING_TRUST:
+ writer.printf(", managingTrust=" + ev.managingTrust);
+ break;
default:
}
writer.println();
@@ -166,6 +178,8 @@ public class TrustArchive {
return "AgentConnected";
case TYPE_AGENT_STOPPED:
return "AgentStopped";
+ case TYPE_MANAGING_TRUST:
+ return "ManagingTrust";
default:
return "Unknown(" + type + ")";
}
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 9c2df55d8425..d3b8d5d1e8d2 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -153,10 +153,11 @@ public class TrustManagerService extends SystemService {
}
public void updateTrust(int userId) {
+ dispatchOnTrustManagedChanged(aggregateIsTrustManaged(userId), userId);
dispatchOnTrustChanged(aggregateIsTrusted(userId), userId);
}
- protected void refreshAgentList() {
+ void refreshAgentList() {
if (DEBUG) Slog.d(TAG, "refreshAgentList()");
PackageManager pm = mContext.getPackageManager();
@@ -167,13 +168,13 @@ public class TrustManagerService extends SystemService {
obsoleteAgents.addAll(mActiveAgents);
for (UserInfo userInfo : userInfos) {
- int disabledFeatures = lockPatternUtils.getDevicePolicyManager()
- .getKeyguardDisabledFeatures(null, userInfo.id);
+ DevicePolicyManager dpm = lockPatternUtils.getDevicePolicyManager();
+ int disabledFeatures = dpm.getKeyguardDisabledFeatures(null, userInfo.id);
final boolean disableTrustAgents =
(disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0;
List<ComponentName> enabledAgents = lockPatternUtils.getEnabledTrustAgents(userInfo.id);
- if (disableTrustAgents || enabledAgents == null) {
+ if (enabledAgents == null) {
continue;
}
List<ResolveInfo> resolveInfos = pm.queryIntentServicesAsUser(TRUST_AGENT_INTENT,
@@ -192,6 +193,13 @@ public class TrustManagerService extends SystemService {
ComponentName name = getComponentName(resolveInfo);
if (!enabledAgents.contains(name)) continue;
+ if (disableTrustAgents) {
+ List<String> features =
+ dpm.getTrustAgentFeaturesEnabled(null /* admin */, name);
+ // Disable agent if no features are enabled.
+ if (features == null || features.isEmpty()) continue;
+ }
+
AgentInfo agentInfo = new AgentInfo();
agentInfo.component = name;
agentInfo.userId = userInfo.id;
@@ -211,7 +219,7 @@ public class TrustManagerService extends SystemService {
boolean trustMayHaveChanged = false;
for (int i = 0; i < obsoleteAgents.size(); i++) {
AgentInfo info = obsoleteAgents.valueAt(i);
- if (info.agent.isTrusted()) {
+ if (info.agent.isManagingTrust()) {
trustMayHaveChanged = true;
}
info.agent.unbind();
@@ -223,13 +231,22 @@ public class TrustManagerService extends SystemService {
}
}
+ void updateDevicePolicyFeatures(int userId) {
+ for (int i = 0; i < mActiveAgents.size(); i++) {
+ AgentInfo info = mActiveAgents.valueAt(i);
+ if (info.agent.isConnected()) {
+ info.agent.updateDevicePolicyFeatures();
+ }
+ }
+ }
+
private void removeAgentsOfPackage(String packageName) {
boolean trustMayHaveChanged = false;
for (int i = mActiveAgents.size() - 1; i >= 0; i--) {
AgentInfo info = mActiveAgents.valueAt(i);
if (packageName.equals(info.component.getPackageName())) {
Log.i(TAG, "Resetting agent " + info.component.flattenToShortString());
- if (info.agent.isTrusted()) {
+ if (info.agent.isManagingTrust()) {
trustMayHaveChanged = true;
}
info.agent.unbind();
@@ -247,7 +264,7 @@ public class TrustManagerService extends SystemService {
AgentInfo info = mActiveAgents.valueAt(i);
if (name.equals(info.component) && userId == info.userId) {
Log.i(TAG, "Resetting agent " + info.component.flattenToShortString());
- if (info.agent.isTrusted()) {
+ if (info.agent.isManagingTrust()) {
trustMayHaveChanged = true;
}
info.agent.unbind();
@@ -333,6 +350,21 @@ public class TrustManagerService extends SystemService {
return false;
}
+ private boolean aggregateIsTrustManaged(int userId) {
+ if (!mUserHasAuthenticatedSinceBoot.get(userId)) {
+ return false;
+ }
+ for (int i = 0; i < mActiveAgents.size(); i++) {
+ AgentInfo info = mActiveAgents.valueAt(i);
+ if (info.userId == userId) {
+ if (info.agent.isManagingTrust()) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
private void dispatchUnlockAttempt(boolean successful, int userId) {
for (int i = 0; i < mActiveAgents.size(); i++) {
AgentInfo info = mActiveAgents.valueAt(i);
@@ -383,7 +415,21 @@ public class TrustManagerService extends SystemService {
try {
mTrustListeners.get(i).onTrustChanged(enabled, userId);
} catch (DeadObjectException e) {
- if (DEBUG) Slog.d(TAG, "Removing dead TrustListener.");
+ Slog.d(TAG, "Removing dead TrustListener.");
+ mTrustListeners.remove(i);
+ i--;
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Exception while notifying TrustListener.", e);
+ }
+ }
+ }
+
+ private void dispatchOnTrustManagedChanged(boolean managed, int userId) {
+ for (int i = 0; i < mTrustListeners.size(); i++) {
+ try {
+ mTrustListeners.get(i).onTrustManagedChanged(managed, userId);
+ } catch (DeadObjectException e) {
+ Slog.d(TAG, "Removing dead TrustListener.");
mTrustListeners.remove(i);
i--;
} catch (RemoteException e) {
@@ -472,6 +518,7 @@ public class TrustManagerService extends SystemService {
fout.print(" (current)");
}
fout.print(": trusted=" + dumpBool(aggregateIsTrusted(user.id)));
+ fout.print(", trustManaged=" + dumpBool(aggregateIsTrustManaged(user.id)));
fout.println();
fout.println(" Enabled agents:");
boolean duplicateSimpleNames = false;
@@ -482,7 +529,9 @@ public class TrustManagerService extends SystemService {
fout.print(" "); fout.println(info.component.flattenToShortString());
fout.print(" bound=" + dumpBool(info.agent.isBound()));
fout.print(", connected=" + dumpBool(info.agent.isConnected()));
- fout.println(", trusted=" + dumpBool(trusted));
+ fout.print(", managingTrust=" + dumpBool(info.agent.isManagingTrust()));
+ fout.print(", trusted=" + dumpBool(trusted));
+ fout.println();
if (trusted) {
fout.println(" message=\"" + info.agent.getMessage() + "\"");
}
@@ -554,6 +603,7 @@ public class TrustManagerService extends SystemService {
if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(
intent.getAction())) {
refreshAgentList();
+ updateDevicePolicyFeatures(getSendingUserId());
}
}