summaryrefslogtreecommitdiff
path: root/keystore/java/android/security/KeyChain.java
diff options
context:
space:
mode:
Diffstat (limited to 'keystore/java/android/security/KeyChain.java')
-rw-r--r--keystore/java/android/security/KeyChain.java48
1 files changed, 37 insertions, 11 deletions
diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java
index 254456cea536..538319c3f1d7 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -763,28 +763,33 @@ public final class KeyChain {
* @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 @@ public final class KeyChain {
}
/**
+ * 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 @@ public final class KeyChain {
}
}
}
+ @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 @@ public final class KeyChain {
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) {