Merge "Handle the case when KeyChain binding fails"
diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java
index 254456c..538319c 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -763,28 +763,33 @@
* @see KeyChain#bind
*/
public static class KeyChainConnection implements Closeable {
- private final Context context;
- private final ServiceConnection serviceConnection;
- private final IKeyChainService service;
+ private final Context mContext;
+ private final ServiceConnection mServiceConnection;
+ private final IKeyChainService mService;
protected KeyChainConnection(Context context,
ServiceConnection serviceConnection,
IKeyChainService service) {
- this.context = context;
- this.serviceConnection = serviceConnection;
- this.service = service;
+ this.mContext = context;
+ this.mServiceConnection = serviceConnection;
+ this.mService = service;
}
@Override public void close() {
- context.unbindService(serviceConnection);
+ mContext.unbindService(mServiceConnection);
}
+
+ /** returns the service binder. */
public IKeyChainService getService() {
- return service;
+ return mService;
}
}
/**
- * @hide for reuse by CertInstaller and Settings.
- *
+ * Bind to KeyChainService in the current user.
* Caller should call unbindService on the result when finished.
+ *
+ *@throws InterruptedException if interrupted during binding.
+ *@throws AssertionError if unable to bind to KeyChainService.
+ * @hide for reuse by CertInstaller and Settings.
*/
@WorkerThread
public static KeyChainConnection bind(@NonNull Context context) throws InterruptedException {
@@ -792,6 +797,11 @@
}
/**
+ * Bind to KeyChainService in the target user.
+ * Caller should call unbindService on the result when finished.
+ *
+ * @throws InterruptedException if interrupted during binding.
+ * @throws AssertionError if unable to bind to KeyChainService.
* @hide
*/
@WorkerThread
@@ -814,6 +824,16 @@
}
}
}
+ @Override public void onBindingDied(ComponentName name) {
+ if (!mConnectedAtLeastOnce) {
+ mConnectedAtLeastOnce = true;
+ try {
+ q.put(null);
+ } catch (InterruptedException e) {
+ // will never happen, since the queue starts with one available slot
+ }
+ }
+ }
@Override public void onServiceDisconnected(ComponentName name) {}
};
Intent intent = new Intent(IKeyChainService.class.getName());
@@ -823,7 +843,13 @@
intent, keyChainServiceConnection, Context.BIND_AUTO_CREATE, user)) {
throw new AssertionError("could not bind to KeyChainService");
}
- return new KeyChainConnection(context, keyChainServiceConnection, q.take());
+ IKeyChainService service = q.take();
+ if (service != null) {
+ return new KeyChainConnection(context, keyChainServiceConnection, service);
+ } else {
+ context.unbindService(keyChainServiceConnection);
+ throw new AssertionError("KeyChainService died while binding");
+ }
}
private static void ensureNotOnMainThread(@NonNull Context context) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/CertificateMonitor.java b/services/devicepolicy/java/com/android/server/devicepolicy/CertificateMonitor.java
index 4a456f7..aa38880 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/CertificateMonitor.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/CertificateMonitor.java
@@ -17,7 +17,6 @@
package com.android.server.devicepolicy;
import android.app.Notification;
-import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -26,12 +25,9 @@
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
-import android.graphics.Color;
-import android.os.Build;
import android.os.Handler;
import android.os.RemoteException;
import android.os.UserHandle;
-import android.os.UserManager;
import android.os.storage.StorageManager;
import android.provider.Settings;
import android.security.Credentials;
@@ -39,9 +35,9 @@
import android.security.KeyChain.KeyChainConnection;
import android.util.Log;
+import com.android.internal.R;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
-import com.android.internal.R;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@@ -49,7 +45,6 @@
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.List;
-import java.util.Set;
public class CertificateMonitor {
protected static final String LOG_TAG = DevicePolicyManagerService.LOG_TAG;
@@ -111,13 +106,13 @@
}
}
- public List<String> getInstalledCaCertificates(UserHandle userHandle)
+ private List<String> getInstalledCaCertificates(UserHandle userHandle)
throws RemoteException, RuntimeException {
try (KeyChainConnection conn = mInjector.keyChainBindAsUser(userHandle)) {
return conn.getService().getUserCaAliases().getList();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
- return null;
+ throw new RuntimeException(e);
} catch (AssertionError e) {
throw new RuntimeException(e);
}