am 5de758d3: am f8a01f5f: am 6468d5c2: Merge "Restart trust agents when updated or when they are dead" into lmp-dev
* commit '5de758d3868b036f5067ad9f86ee7b02331e4818':
Restart trust agents when updated or when they are dead
diff --git a/packages/Keyguard/test/SampleTrustAgent/AndroidManifest.xml b/packages/Keyguard/test/SampleTrustAgent/AndroidManifest.xml
index f3125f1..a7c9105 100644
--- a/packages/Keyguard/test/SampleTrustAgent/AndroidManifest.xml
+++ b/packages/Keyguard/test/SampleTrustAgent/AndroidManifest.xml
@@ -38,6 +38,10 @@
android:label="@string/app_name"
android:exported="true"
android:launchMode="singleInstance" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
</activity>
</application>
</manifest>
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 01b107b..06a06bf 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
@@ -17,9 +17,9 @@
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
<Button android:id="@+id/enable_trust"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -28,6 +28,10 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Revoke trust" />
+ <Button android:id="@+id/crash"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="Crash" />
<CheckBox android:id="@+id/report_unlock_attempts"
android:layout_width="match_parent"
android:layout_height="wrap_content"
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 8e293fb..6b5f78b 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
@@ -37,6 +37,7 @@
findViewById(R.id.enable_trust).setOnClickListener(this);
findViewById(R.id.revoke_trust).setOnClickListener(this);
+ findViewById(R.id.crash).setOnClickListener(this);
mReportUnlockAttempts = (CheckBox) findViewById(R.id.report_unlock_attempts);
mReportUnlockAttempts.setOnCheckedChangeListener(this);
@@ -56,6 +57,8 @@
null /* extra */);
} else if (id == R.id.revoke_trust) {
SampleTrustAgent.sendRevokeTrust(this);
+ } else if (id == R.id.crash) {
+ throw new RuntimeException("crash");
}
}
diff --git a/services/core/java/com/android/server/trust/TrustAgentWrapper.java b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
index f18939f..51009af 100644
--- a/services/core/java/com/android/server/trust/TrustAgentWrapper.java
+++ b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
@@ -24,6 +24,7 @@
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.util.Log;
import android.util.Slog;
@@ -41,6 +42,13 @@
private static final int MSG_GRANT_TRUST = 1;
private static final int MSG_REVOKE_TRUST = 2;
private static final int MSG_TRUST_TIMEOUT = 3;
+ private static final int MSG_RESTART_TIMEOUT = 4;
+
+ /**
+ * Time in uptime millis that we wait for the service connection, both when starting
+ * and when the service disconnects.
+ */
+ private static final long RESTART_TIMEOUT_MILLIS = 5 * 60000;
/**
* Long extra for {@link #MSG_GRANT_TRUST}
@@ -53,6 +61,8 @@
private final ComponentName mName;
private ITrustAgentService mTrustAgentService;
+ private boolean mBound;
+ private long mScheduledRestartUptimeMillis;
// Trust state
private boolean mTrusted;
@@ -95,6 +105,10 @@
}
mTrustManagerService.updateTrust(mUserId);
break;
+ case MSG_RESTART_TIMEOUT:
+ unbind();
+ mTrustManagerService.resetAgent(mName, mUserId);
+ break;
}
}
};
@@ -123,6 +137,7 @@
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
if (DEBUG) Log.v(TAG, "TrustAgent started : " + name.flattenToString());
+ mHandler.removeMessages(MSG_RESTART_TIMEOUT);
mTrustAgentService = ITrustAgentService.Stub.asInterface(service);
mTrustManagerService.mArchive.logAgentConnected(mUserId, name);
setCallback(mCallback);
@@ -134,6 +149,9 @@
mTrustAgentService = null;
mTrustManagerService.mArchive.logAgentDied(mUserId, name);
mHandler.sendEmptyMessage(MSG_REVOKE_TRUST);
+ if (mBound) {
+ scheduleRestart();
+ }
}
};
@@ -144,9 +162,12 @@
mTrustManagerService = trustManagerService;
mUserId = user.getIdentifier();
mName = intent.getComponent();
- if (!context.bindServiceAsUser(intent, mConnection, Context.BIND_AUTO_CREATE, user)) {
- if (DEBUG) Log.v(TAG, "can't bind to TrustAgent " + mName.flattenToShortString());
- // TODO: retry somehow?
+ // Schedules a restart for when connecting times out. If the connection succeeds,
+ // the restart is canceled in mCallback's onConnected.
+ scheduleRestart();
+ mBound = context.bindServiceAsUser(intent, mConnection, Context.BIND_AUTO_CREATE, user);
+ if (!mBound) {
+ Log.e(TAG, "Can't bind to TrustAgent " + mName.flattenToShortString());
}
}
@@ -184,14 +205,38 @@
}
public void unbind() {
+ if (!mBound) {
+ return;
+ }
if (DEBUG) Log.v(TAG, "TrustAgent unbound : " + mName.flattenToShortString());
mTrustManagerService.mArchive.logAgentStopped(mUserId, mName);
mContext.unbindService(mConnection);
+ mBound = false;
mTrustAgentService = null;
mHandler.sendEmptyMessage(MSG_REVOKE_TRUST);
+ mHandler.removeMessages(MSG_RESTART_TIMEOUT);
}
public boolean isConnected() {
return mTrustAgentService != null;
}
+
+ public boolean isBound() {
+ return mBound;
+ }
+
+ /**
+ * If not connected, returns the time at which the agent is restarted.
+ *
+ * @return restart time in uptime millis.
+ */
+ public long getScheduledRestartUptimeMillis() {
+ return mScheduledRestartUptimeMillis;
+ }
+
+ private void scheduleRestart() {
+ mHandler.removeMessages(MSG_RESTART_TIMEOUT);
+ mScheduledRestartUptimeMillis = SystemClock.uptimeMillis() + RESTART_TIMEOUT_MILLIS;
+ mHandler.sendEmptyMessageAtTime(MSG_RESTART_TIMEOUT, mScheduledRestartUptimeMillis);
+ }
}
diff --git a/services/core/java/com/android/server/trust/TrustArchive.java b/services/core/java/com/android/server/trust/TrustArchive.java
index 56950d2..5e32d86 100644
--- a/services/core/java/com/android/server/trust/TrustArchive.java
+++ b/services/core/java/com/android/server/trust/TrustArchive.java
@@ -130,7 +130,7 @@
}
}
- private static String formatDuration(long duration) {
+ public static String formatDuration(long duration) {
StringBuilder sb = new StringBuilder();
TimeUtils.formatDuration(duration, sb);
return sb.toString();
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 60a8090..14436aa 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -45,6 +45,7 @@
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.service.trust.TrustAgentService;
@@ -99,12 +100,6 @@
private UserManager mUserManager;
- /**
- * Cache for {@link #refreshAgentList()}
- */
- private final ArraySet<AgentInfo> mObsoleteAgents = new ArraySet<AgentInfo>();
-
-
public TrustManagerService(Context context) {
super(context);
mContext = context;
@@ -168,8 +163,8 @@
List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */);
LockPatternUtils lockPatternUtils = new LockPatternUtils(mContext);
- mObsoleteAgents.clear();
- mObsoleteAgents.addAll(mActiveAgents);
+ ArraySet<AgentInfo> obsoleteAgents = new ArraySet<>();
+ obsoleteAgents.addAll(mActiveAgents);
for (UserInfo userInfo : userInfos) {
int disabledFeatures = lockPatternUtils.getDevicePolicyManager()
@@ -208,14 +203,14 @@
new Intent().setComponent(name), userInfo.getUserHandle());
mActiveAgents.add(agentInfo);
} else {
- mObsoleteAgents.remove(agentInfo);
+ obsoleteAgents.remove(agentInfo);
}
}
}
boolean trustMayHaveChanged = false;
- for (int i = 0; i < mObsoleteAgents.size(); i++) {
- AgentInfo info = mObsoleteAgents.valueAt(i);
+ for (int i = 0; i < obsoleteAgents.size(); i++) {
+ AgentInfo info = obsoleteAgents.valueAt(i);
if (info.agent.isTrusted()) {
trustMayHaveChanged = true;
}
@@ -228,6 +223,43 @@
}
}
+ 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()) {
+ trustMayHaveChanged = true;
+ }
+ info.agent.unbind();
+ mActiveAgents.removeAt(i);
+ }
+ }
+ if (trustMayHaveChanged) {
+ updateTrustAll();
+ }
+ }
+
+ public void resetAgent(ComponentName name, int userId) {
+ boolean trustMayHaveChanged = false;
+ for (int i = mActiveAgents.size() - 1; i >= 0; i--) {
+ 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()) {
+ trustMayHaveChanged = true;
+ }
+ info.agent.unbind();
+ mActiveAgents.removeAt(i);
+ }
+ }
+ if (trustMayHaveChanged) {
+ updateTrust(userId);
+ }
+ refreshAgentList();
+ }
+
private ComponentName getSettingsComponentName(PackageManager pm, ResolveInfo resolveInfo) {
if (resolveInfo == null || resolveInfo.serviceInfo == null
|| resolveInfo.serviceInfo.metaData == null) return null;
@@ -448,11 +480,18 @@
if (info.userId != user.id) { continue; }
boolean trusted = info.agent.isTrusted();
fout.print(" "); fout.println(info.component.flattenToShortString());
- fout.print(" connected=" + dumpBool(info.agent.isConnected()));
+ fout.print(" bound=" + dumpBool(info.agent.isBound()));
+ fout.print(", connected=" + dumpBool(info.agent.isConnected()));
fout.println(", trusted=" + dumpBool(trusted));
if (trusted) {
fout.println(" message=\"" + info.agent.getMessage() + "\"");
}
+ if (!info.agent.isConnected()) {
+ String restartTime = TrustArchive.formatDuration(
+ info.agent.getScheduledRestartUptimeMillis()
+ - SystemClock.uptimeMillis());
+ fout.println(" restartScheduledAt=" + restartTime);
+ }
if (!simpleNames.add(TrustArchive.getSimpleName(info.component))) {
duplicateSimpleNames = true;
}
@@ -501,6 +540,11 @@
// We're interested in all changes, even if just some components get enabled / disabled.
return true;
}
+
+ @Override
+ public void onPackageDisappeared(String packageName, int reason) {
+ removeAgentsOfPackage(packageName);
+ }
};
private class DevicePolicyReceiver extends BroadcastReceiver {