summaryrefslogtreecommitdiffstats
path: root/keystore
diff options
context:
space:
mode:
Diffstat (limited to 'keystore')
-rw-r--r--keystore/java/android/security/KeyChain.java82
1 files changed, 57 insertions, 25 deletions
diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java
index bcfd6da..08e05ef 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -29,6 +29,7 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import java.io.ByteArrayInputStream;
+import java.io.Closeable;
import java.io.IOException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
@@ -72,34 +73,11 @@ public final class KeyChain {
*/
public static KeyChainResult get(Context context, String alias)
throws InterruptedException, RemoteException {
- if (context == null) {
- throw new NullPointerException("context == null");
- }
if (alias == null) {
throw new NullPointerException("alias == null");
}
- ensureNotOnMainThread(context);
- final BlockingQueue<IKeyChainService> q = new LinkedBlockingQueue<IKeyChainService>(1);
- ServiceConnection keyChainServiceConnection = new ServiceConnection() {
- @Override public void onServiceConnected(ComponentName name, IBinder service) {
- try {
- q.put(IKeyChainService.Stub.asInterface(service));
- } catch (InterruptedException e) {
- throw new AssertionError(e);
- }
- }
- @Override public void onServiceDisconnected(ComponentName name) {}
- };
- boolean isBound = context.bindService(new Intent(IKeyChainService.class.getName()),
- keyChainServiceConnection,
- Context.BIND_AUTO_CREATE);
- if (!isBound) {
- throw new AssertionError("could not bind to KeyChainService");
- }
- IKeyChainService keyChainService;
+ KeyChainConnection keyChainConnection = bind(context);
try {
- keyChainService = q.take();
-
// Account is created if necessary during binding of the IKeyChainService
AccountManager accountManager = AccountManager.get(context);
Account account = accountManager.getAccountsByType(ACCOUNT_TYPE)[0];
@@ -131,12 +109,13 @@ public final class KeyChain {
if (authToken == null) {
throw new AssertionError("Invalid authtoken");
}
+ IKeyChainService keyChainService = keyChainConnection.getService();
byte[] privateKeyBytes = keyChainService.getPrivateKey(alias, authToken);
byte[] certificateBytes = keyChainService.getCertificate(alias, authToken);
return new KeyChainResult(toPrivateKey(privateKeyBytes),
toCertificate(certificateBytes));
} finally {
- context.unbindService(keyChainServiceConnection);
+ keyChainConnection.close();
}
}
@@ -167,6 +146,59 @@ public final class KeyChain {
}
}
+ /**
+ * @hide for reuse by CertInstaller and Settings.
+ * @see KeyChain#bind
+ */
+ public final static class KeyChainConnection implements Closeable {
+ private final Context context;
+ private final ServiceConnection serviceConnection;
+ private final IKeyChainService service;
+ private KeyChainConnection(Context context,
+ ServiceConnection serviceConnection,
+ IKeyChainService service) {
+ this.context = context;
+ this.serviceConnection = serviceConnection;
+ this.service = service;
+ }
+ @Override public void close() {
+ context.unbindService(serviceConnection);
+ }
+ public IKeyChainService getService() {
+ return service;
+ }
+ }
+
+ /**
+ * @hide for reuse by CertInstaller and Settings.
+ *
+ * Caller should call unbindService on the result when finished.
+ */
+ public static KeyChainConnection bind(Context context) throws InterruptedException {
+ if (context == null) {
+ throw new NullPointerException("context == null");
+ }
+ ensureNotOnMainThread(context);
+ final BlockingQueue<IKeyChainService> q = new LinkedBlockingQueue<IKeyChainService>(1);
+ ServiceConnection keyChainServiceConnection = new ServiceConnection() {
+ @Override public void onServiceConnected(ComponentName name, IBinder service) {
+ try {
+ q.put(IKeyChainService.Stub.asInterface(service));
+ } catch (InterruptedException e) {
+ throw new AssertionError(e);
+ }
+ }
+ @Override public void onServiceDisconnected(ComponentName name) {}
+ };
+ boolean isBound = context.bindService(new Intent(IKeyChainService.class.getName()),
+ keyChainServiceConnection,
+ Context.BIND_AUTO_CREATE);
+ if (!isBound) {
+ throw new AssertionError("could not bind to KeyChainService");
+ }
+ return new KeyChainConnection(context, keyChainServiceConnection, q.take());
+ }
+
private static void ensureNotOnMainThread(Context context) {
Looper looper = Looper.myLooper();
if (looper != null && looper == context.getMainLooper()) {