1b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom/*
2b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom * Copyright (C) 2011 The Android Open Source Project
3b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom *
4b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom * Licensed under the Apache License, Version 2.0 (the "License");
5b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom * you may not use this file except in compliance with the License.
6b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom * You may obtain a copy of the License at
7b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom *
8b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom *      http://www.apache.org/licenses/LICENSE-2.0
9b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom *
10b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom * Unless required by applicable law or agreed to in writing, software
11b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom * distributed under the License is distributed on an "AS IS" BASIS,
12b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom * See the License for the specific language governing permissions and
14b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom * limitations under the License.
15b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom */
16b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrompackage android.security;
17b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom
18ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstromimport android.app.Activity;
1967c30dfe8e4bff11a4660ac23e8679b5deb59457Brian Carlstromimport android.app.PendingIntent;
20b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstromimport android.content.ComponentName;
21b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstromimport android.content.Context;
22b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstromimport android.content.Intent;
23b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstromimport android.content.ServiceConnection;
24b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstromimport android.os.IBinder;
25b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstromimport android.os.Looper;
26b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstromimport android.os.RemoteException;
27b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstromimport java.io.ByteArrayInputStream;
28d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstromimport java.io.Closeable;
295423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Rootimport java.security.InvalidKeyException;
3093201f545b67da15cb69830a5988810aef52c0b2Brian Carlstromimport java.security.Principal;
31b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstromimport java.security.PrivateKey;
32b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstromimport java.security.cert.Certificate;
33b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstromimport java.security.cert.CertificateException;
34b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstromimport java.security.cert.CertificateFactory;
35b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstromimport java.security.cert.X509Certificate;
36db93b78385d694402760ad63de0795f3902030d9Brian Carlstromimport java.util.List;
378e9929c4d0730de4c9f01435a7cfe2db8855e24dBrian Carlstromimport java.util.concurrent.BlockingQueue;
388e9929c4d0730de4c9f01435a7cfe2db8855e24dBrian Carlstromimport java.util.concurrent.LinkedBlockingQueue;
395423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root
405423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Rootimport org.apache.harmony.xnet.provider.jsse.OpenSSLEngine;
41db93b78385d694402760ad63de0795f3902030d9Brian Carlstromimport org.apache.harmony.xnet.provider.jsse.TrustedCertificateStore;
42b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom
43b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom/**
4493201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom * The {@code KeyChain} class provides access to private keys and
4593201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom * their corresponding certificate chains in credential storage.
4693201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom *
4793201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom * <p>Applications accessing the {@code KeyChain} normally go through
4893201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom * these steps:
4993201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom *
5093201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom * <ol>
5193201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom *
5293201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom * <li>Receive a callback from an {@link javax.net.ssl.X509KeyManager
5393201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom * X509KeyManager} that a private key is requested.
5493201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom *
5593201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom * <li>Call {@link #choosePrivateKeyAlias
5693201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom * choosePrivateKeyAlias} to allow the user to select from a
5793201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom * list of currently available private keys and corresponding
5893201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom * certificate chains. The chosen alias will be returned by the
5993201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom * callback {@link KeyChainAliasCallback#alias}, or null if no private
6093201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom * key is available or the user cancels the request.
6193201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom *
6293201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom * <li>Call {@link #getPrivateKey} and {@link #getCertificateChain} to
6393201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom * retrieve the credentials to return to the corresponding {@link
6493201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom * javax.net.ssl.X509KeyManager} callbacks.
6593201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom *
6693201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom * </ol>
6793201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom *
6893201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom * <p>An application may remember the value of a selected alias to
6993201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom * avoid prompting the user with {@link #choosePrivateKeyAlias
7093201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom * choosePrivateKeyAlias} on subsequent connections. If the alias is
7193201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom * no longer valid, null will be returned on lookups using that value
72ca43c458ad0ee8cfa7f5eabc8ba1a65ae473976bBrian Carlstrom *
73ca43c458ad0ee8cfa7f5eabc8ba1a65ae473976bBrian Carlstrom * <p>An application can request the installation of private keys and
74ca43c458ad0ee8cfa7f5eabc8ba1a65ae473976bBrian Carlstrom * certificates via the {@code Intent} provided by {@link
75ca43c458ad0ee8cfa7f5eabc8ba1a65ae473976bBrian Carlstrom * #createInstallIntent}. Private keys installed via this {@code
76ca43c458ad0ee8cfa7f5eabc8ba1a65ae473976bBrian Carlstrom * Intent} will be accessible via {@link #choosePrivateKeyAlias} while
77ca43c458ad0ee8cfa7f5eabc8ba1a65ae473976bBrian Carlstrom * Certificate Authority (CA) certificates will be trusted by all
78ca43c458ad0ee8cfa7f5eabc8ba1a65ae473976bBrian Carlstrom * applications through the default {@code X509TrustManager}.
79b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom */
8093201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom// TODO reference intent for credential installation when public
81b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrompublic final class KeyChain {
82b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom
83b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom    private static final String TAG = "KeyChain";
84b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom
85b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom    /**
86b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom     * @hide Also used by KeyChainService implementation
87b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom     */
88b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom    public static final String ACCOUNT_TYPE = "com.android.keychain";
89b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom
90b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom    /**
91a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     * Action to bring up the KeyChainActivity
92a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     */
93a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom    private static final String ACTION_CHOOSER = "com.android.keychain.CHOOSER";
94a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom
95a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom    /**
96a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     * Extra for use with {@link #ACTION_CHOOSER}
97ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom     * @hide Also used by KeyChainActivity implementation
98b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom     */
99ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom    public static final String EXTRA_RESPONSE = "response";
100b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom
101b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom    /**
102a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     * Extra for use with {@link #ACTION_CHOOSER}
10367c30dfe8e4bff11a4660ac23e8679b5deb59457Brian Carlstrom     * @hide Also used by KeyChainActivity implementation
10467c30dfe8e4bff11a4660ac23e8679b5deb59457Brian Carlstrom     */
10567c30dfe8e4bff11a4660ac23e8679b5deb59457Brian Carlstrom    public static final String EXTRA_HOST = "host";
10667c30dfe8e4bff11a4660ac23e8679b5deb59457Brian Carlstrom
10767c30dfe8e4bff11a4660ac23e8679b5deb59457Brian Carlstrom    /**
108a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     * Extra for use with {@link #ACTION_CHOOSER}
10967c30dfe8e4bff11a4660ac23e8679b5deb59457Brian Carlstrom     * @hide Also used by KeyChainActivity implementation
11067c30dfe8e4bff11a4660ac23e8679b5deb59457Brian Carlstrom     */
11167c30dfe8e4bff11a4660ac23e8679b5deb59457Brian Carlstrom    public static final String EXTRA_PORT = "port";
11267c30dfe8e4bff11a4660ac23e8679b5deb59457Brian Carlstrom
11367c30dfe8e4bff11a4660ac23e8679b5deb59457Brian Carlstrom    /**
114a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     * Extra for use with {@link #ACTION_CHOOSER}
11567c30dfe8e4bff11a4660ac23e8679b5deb59457Brian Carlstrom     * @hide Also used by KeyChainActivity implementation
11667c30dfe8e4bff11a4660ac23e8679b5deb59457Brian Carlstrom     */
11767c30dfe8e4bff11a4660ac23e8679b5deb59457Brian Carlstrom    public static final String EXTRA_ALIAS = "alias";
11867c30dfe8e4bff11a4660ac23e8679b5deb59457Brian Carlstrom
11967c30dfe8e4bff11a4660ac23e8679b5deb59457Brian Carlstrom    /**
120a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     * Extra for use with {@link #ACTION_CHOOSER}
12167c30dfe8e4bff11a4660ac23e8679b5deb59457Brian Carlstrom     * @hide Also used by KeyChainActivity implementation
12267c30dfe8e4bff11a4660ac23e8679b5deb59457Brian Carlstrom     */
12367c30dfe8e4bff11a4660ac23e8679b5deb59457Brian Carlstrom    public static final String EXTRA_SENDER = "sender";
12467c30dfe8e4bff11a4660ac23e8679b5deb59457Brian Carlstrom
12567c30dfe8e4bff11a4660ac23e8679b5deb59457Brian Carlstrom    /**
12693ba4fedebb78ba47c24e8472c8960ea8fdc933aSelim Gurun     * Action to bring up the CertInstaller.
127a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     */
128a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom    private static final String ACTION_INSTALL = "android.credentials.INSTALL";
129a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom
130a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom    /**
131a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     * Optional extra to specify a {@code String} credential name on
132a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     * the {@code Intent} returned by {@link #createInstallIntent}.
133a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     */
134a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom    // Compatible with old com.android.certinstaller.CredentialHelper.CERT_NAME_KEY
135a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom    public static final String EXTRA_NAME = "name";
136a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom
137a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom    /**
138a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     * Optional extra to specify an X.509 certificate to install on
139a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     * the {@code Intent} returned by {@link #createInstallIntent}.
140a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     * The extra value should be a PEM or ASN.1 DER encoded {@code
141a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     * byte[]}. An {@link X509Certificate} can be converted to DER
142a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     * encoded bytes with {@link X509Certificate#getEncoded}.
143a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     *
144a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     * <p>{@link #EXTRA_NAME} may be used to provide a default alias
145a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     * name for the installed certificate.
146a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     */
147a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom    // Compatible with old android.security.Credentials.CERTIFICATE
148a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom    public static final String EXTRA_CERTIFICATE = "CERT";
149a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom
150a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom    /**
151a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     * Optional extra for use with the {@code Intent} returned by
152a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     * {@link #createInstallIntent} to specify a PKCS#12 key store to
153a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     * install. The extra value should be a {@code byte[]}. The bytes
154a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     * may come from an external source or be generated with {@link
155ca43c458ad0ee8cfa7f5eabc8ba1a65ae473976bBrian Carlstrom     * java.security.KeyStore#store} on a "PKCS12" instance.
156a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     *
157a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     * <p>The user will be prompted for the password to load the key store.
158a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     *
159a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     * <p>The key store will be scanned for {@link
160a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     * java.security.KeyStore.PrivateKeyEntry} entries and both the
161a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     * private key and associated certificate chain will be installed.
162a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     *
163a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     * <p>{@link #EXTRA_NAME} may be used to provide a default alias
164a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     * name for the installed credentials.
165a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     */
166a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom    // Compatible with old android.security.Credentials.PKCS12
167a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom    public static final String EXTRA_PKCS12 = "PKCS12";
168a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom
16993ba4fedebb78ba47c24e8472c8960ea8fdc933aSelim Gurun
17093ba4fedebb78ba47c24e8472c8960ea8fdc933aSelim Gurun    /**
17193ba4fedebb78ba47c24e8472c8960ea8fdc933aSelim Gurun     * Broadcast Action: Indicates the trusted storage has changed. Sent when
17293ba4fedebb78ba47c24e8472c8960ea8fdc933aSelim Gurun     * one of this happens:
17393ba4fedebb78ba47c24e8472c8960ea8fdc933aSelim Gurun     *
17493ba4fedebb78ba47c24e8472c8960ea8fdc933aSelim Gurun     * <ul>
17593ba4fedebb78ba47c24e8472c8960ea8fdc933aSelim Gurun     * <li>a new CA is added,
17693ba4fedebb78ba47c24e8472c8960ea8fdc933aSelim Gurun     * <li>an existing CA is removed or disabled,
17793ba4fedebb78ba47c24e8472c8960ea8fdc933aSelim Gurun     * <li>a disabled CA is enabled,
17893ba4fedebb78ba47c24e8472c8960ea8fdc933aSelim Gurun     * <li>trusted storage is reset (all user certs are cleared),
17993ba4fedebb78ba47c24e8472c8960ea8fdc933aSelim Gurun     * <li>when permission to access a private key is changed.
18093ba4fedebb78ba47c24e8472c8960ea8fdc933aSelim Gurun     * </ul>
18193ba4fedebb78ba47c24e8472c8960ea8fdc933aSelim Gurun     */
18293ba4fedebb78ba47c24e8472c8960ea8fdc933aSelim Gurun    public static final String ACTION_STORAGE_CHANGED = "android.security.STORAGE_CHANGED";
18393ba4fedebb78ba47c24e8472c8960ea8fdc933aSelim Gurun
184a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom    /**
185a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     * Returns an {@code Intent} that can be used for credential
186a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     * installation. The intent may be used without any extras, in
187a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     * which case the user will be able to install credentials from
188a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     * their own source.
189a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     *
190a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     * <p>Alternatively, {@link #EXTRA_CERTIFICATE} or {@link
191a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     * #EXTRA_PKCS12} maybe used to specify the bytes of an X.509
192a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     * certificate or a PKCS#12 key store for installation. These
193ca43c458ad0ee8cfa7f5eabc8ba1a65ae473976bBrian Carlstrom     * extras may be combined with {@link #EXTRA_NAME} to provide a
194a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     * default alias name for credentials being installed.
195a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     *
196a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     * <p>When used with {@link Activity#startActivityForResult},
197a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     * {@link Activity#RESULT_OK} will be returned if a credential was
198a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     * successfully installed, otherwise {@link
199a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     * Activity#RESULT_CANCELED} will be returned.
200a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom     */
201a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom    public static Intent createInstallIntent() {
202a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom        Intent intent = new Intent(ACTION_INSTALL);
203a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom        intent.setClassName("com.android.certinstaller",
204a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom                            "com.android.certinstaller.CertInstallerMain");
205a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom        return intent;
206a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom    }
207a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom
208a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom    /**
209ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom     * Launches an {@code Activity} for the user to select the alias
210ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom     * for a private key and certificate pair for authentication. The
211ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom     * selected alias or null will be returned via the
21293201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom     * KeyChainAliasCallback callback.
21393201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom     *
21493201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom     * <p>{@code keyTypes} and {@code issuers} may be used to
21593201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom     * highlight suggested choices to the user, although to cope with
21693201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom     * sometimes erroneous values provided by servers, the user may be
21793201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom     * able to override these suggestions.
21893201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom     *
21993201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom     * <p>{@code host} and {@code port} may be used to give the user
22093201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom     * more context about the server requesting the credentials.
22193201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom     *
22267c30dfe8e4bff11a4660ac23e8679b5deb59457Brian Carlstrom     * <p>{@code alias} allows the chooser to preselect an existing
22367c30dfe8e4bff11a4660ac23e8679b5deb59457Brian Carlstrom     * alias which will still be subject to user confirmation.
22467c30dfe8e4bff11a4660ac23e8679b5deb59457Brian Carlstrom     *
22593201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom     * @param activity The {@link Activity} context to use for
22693201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom     *     launching the new sub-Activity to prompt the user to select
22793201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom     *     a private key; used only to call startActivity(); must not
22893201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom     *     be null.
22993201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom     * @param response Callback to invoke when the request completes;
23093201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom     *     must not be null
23193201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom     * @param keyTypes The acceptable types of asymmetric keys such as
23293201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom     *     "RSA" or "DSA", or a null array.
23393201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom     * @param issuers The acceptable certificate issuers for the
23493201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom     *     certificate matching the private key, or null.
23593201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom     * @param host The host name of the server requesting the
23693201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom     *     certificate, or null if unavailable.
23793201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom     * @param port The port number of the server requesting the
23893201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom     *     certificate, or -1 if unavailable.
23967c30dfe8e4bff11a4660ac23e8679b5deb59457Brian Carlstrom     * @param alias The alias to preselect if available, or null if
24067c30dfe8e4bff11a4660ac23e8679b5deb59457Brian Carlstrom     *     unavailable.
241b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom     */
24293201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom    public static void choosePrivateKeyAlias(Activity activity, KeyChainAliasCallback response,
24393201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom                                             String[] keyTypes, Principal[] issuers,
24467c30dfe8e4bff11a4660ac23e8679b5deb59457Brian Carlstrom                                             String host, int port,
24567c30dfe8e4bff11a4660ac23e8679b5deb59457Brian Carlstrom                                             String alias) {
24693201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom        /*
24767c30dfe8e4bff11a4660ac23e8679b5deb59457Brian Carlstrom         * TODO currently keyTypes, issuers are unused. They are meant
24867c30dfe8e4bff11a4660ac23e8679b5deb59457Brian Carlstrom         * to follow the semantics and purpose of X509KeyManager
24967c30dfe8e4bff11a4660ac23e8679b5deb59457Brian Carlstrom         * method arguments.
25093201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom         *
25193201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom         * keyTypes would allow the list to be filtered and typically
25293201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom         * will be set correctly by the server. In practice today,
25393201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom         * most all users will want only RSA, rarely DSA, and usually
25493201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom         * only a small number of certs will be available.
25593201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom         *
25693201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom         * issuers is typically not useful. Some servers historically
25793201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom         * will send the entire list of public CAs known to the
25893201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom         * server. Others will send none. If this is used, if there
25993201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom         * are no matches after applying the constraint, it should be
26093201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom         * ignored.
26193201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom         */
262ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom        if (activity == null) {
263ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom            throw new NullPointerException("activity == null");
264b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom        }
265ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom        if (response == null) {
266ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom            throw new NullPointerException("response == null");
267ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom        }
268a00a2b33ccc6bc079c3ee57a938f62947b48a001Brian Carlstrom        Intent intent = new Intent(ACTION_CHOOSER);
269ab8b84ad3847788d83da557606aa27d4102e6b52Fred Quintana        intent.putExtra(EXTRA_RESPONSE, new AliasResponse(response));
27067c30dfe8e4bff11a4660ac23e8679b5deb59457Brian Carlstrom        intent.putExtra(EXTRA_HOST, host);
27167c30dfe8e4bff11a4660ac23e8679b5deb59457Brian Carlstrom        intent.putExtra(EXTRA_PORT, port);
27267c30dfe8e4bff11a4660ac23e8679b5deb59457Brian Carlstrom        intent.putExtra(EXTRA_ALIAS, alias);
27367c30dfe8e4bff11a4660ac23e8679b5deb59457Brian Carlstrom        // the PendingIntent is used to get calling package name
27467c30dfe8e4bff11a4660ac23e8679b5deb59457Brian Carlstrom        intent.putExtra(EXTRA_SENDER, PendingIntent.getActivity(activity, 0, new Intent(), 0));
275ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom        activity.startActivity(intent);
276ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom    }
277ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom
27893201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom    private static class AliasResponse extends IKeyChainAliasCallback.Stub {
27993201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom        private final KeyChainAliasCallback keyChainAliasResponse;
280ab8b84ad3847788d83da557606aa27d4102e6b52Fred Quintana        private AliasResponse(KeyChainAliasCallback keyChainAliasResponse) {
281ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom            this.keyChainAliasResponse = keyChainAliasResponse;
282ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom        }
283ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom        @Override public void alias(String alias) {
284ab8b84ad3847788d83da557606aa27d4102e6b52Fred Quintana            keyChainAliasResponse.alias(alias);
285ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom        }
286ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom    }
287b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom
288ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom    /**
289ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom     * Returns the {@code PrivateKey} for the requested alias, or null
290ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom     * if no there is no result.
29193201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom     *
29293201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom     * @param alias The alias of the desired private key, typically
29393201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom     * returned via {@link KeyChainAliasCallback#alias}.
29493201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom     * @throws KeyChainException if the alias was valid but there was some problem accessing it.
295ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom     */
296ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom    public static PrivateKey getPrivateKey(Context context, String alias)
29793201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom            throws KeyChainException, InterruptedException {
298ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom        if (alias == null) {
299ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom            throw new NullPointerException("alias == null");
300ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom        }
301ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom        KeyChainConnection keyChainConnection = bind(context);
302ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom        try {
3035423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root            final IKeyChainService keyChainService = keyChainConnection.getService();
3045423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root            final String keyId = keyChainService.requestPrivateKey(alias);
3055423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root            if (keyId == null) {
3065423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root                throw new KeyChainException("keystore had a problem");
3075423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root            }
3085423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root
3095423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root            final OpenSSLEngine engine = OpenSSLEngine.getInstance("keystore");
3105423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root            return engine.getPrivateKeyById(keyId);
31193201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom        } catch (RemoteException e) {
31293201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom            throw new KeyChainException(e);
31393201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom        } catch (RuntimeException e) {
31493201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom            // only certain RuntimeExceptions can be propagated across the IKeyChainService call
31593201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom            throw new KeyChainException(e);
3165423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root        } catch (InvalidKeyException e) {
3175423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root            throw new KeyChainException(e);
318ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom        } finally {
319ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom            keyChainConnection.close();
320ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom        }
321ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom    }
322ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom
323ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom    /**
324ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom     * Returns the {@code X509Certificate} chain for the requested
325ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom     * alias, or null if no there is no result.
32693201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom     *
32793201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom     * @param alias The alias of the desired certificate chain, typically
32893201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom     * returned via {@link KeyChainAliasCallback#alias}.
32993201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom     * @throws KeyChainException if the alias was valid but there was some problem accessing it.
330ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom     */
331ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom    public static X509Certificate[] getCertificateChain(Context context, String alias)
33293201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom            throws KeyChainException, InterruptedException {
333ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom        if (alias == null) {
334ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom            throw new NullPointerException("alias == null");
335ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom        }
336ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom        KeyChainConnection keyChainConnection = bind(context);
337ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom        try {
338ba1a667b1d6c95050f6c88316ac58fe9e0ff878bBrian Carlstrom            IKeyChainService keyChainService = keyChainConnection.getService();
339ab8b84ad3847788d83da557606aa27d4102e6b52Fred Quintana            byte[] certificateBytes = keyChainService.getCertificate(alias);
340db93b78385d694402760ad63de0795f3902030d9Brian Carlstrom            TrustedCertificateStore store = new TrustedCertificateStore();
34154e03afcfe34e9875efa56650c1af3ebc8f58a89Kenny Root            List<X509Certificate> chain = store
34254e03afcfe34e9875efa56650c1af3ebc8f58a89Kenny Root                    .getCertificateChain(toCertificate(certificateBytes));
343db93b78385d694402760ad63de0795f3902030d9Brian Carlstrom            return chain.toArray(new X509Certificate[chain.size()]);
34493201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom        } catch (RemoteException e) {
34593201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom            throw new KeyChainException(e);
34693201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom        } catch (RuntimeException e) {
34793201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom            // only certain RuntimeExceptions can be propagated across the IKeyChainService call
34893201f545b67da15cb69830a5988810aef52c0b2Brian Carlstrom            throw new KeyChainException(e);
3498e9929c4d0730de4c9f01435a7cfe2db8855e24dBrian Carlstrom        } finally {
350d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom            keyChainConnection.close();
351b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom        }
352b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom    }
353b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom
3548e9929c4d0730de4c9f01435a7cfe2db8855e24dBrian Carlstrom    private static X509Certificate toCertificate(byte[] bytes) {
355b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom        if (bytes == null) {
3568e9929c4d0730de4c9f01435a7cfe2db8855e24dBrian Carlstrom            throw new IllegalArgumentException("bytes == null");
357b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom        }
358b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom        try {
359b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom            CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
360b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom            Certificate cert = certFactory.generateCertificate(new ByteArrayInputStream(bytes));
361b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom            return (X509Certificate) cert;
362b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom        } catch (CertificateException e) {
363b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom            throw new AssertionError(e);
364b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom        }
365b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom    }
366b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom
367d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom    /**
368d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom     * @hide for reuse by CertInstaller and Settings.
369d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom     * @see KeyChain#bind
370d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom     */
371d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom    public final static class KeyChainConnection implements Closeable {
372d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom        private final Context context;
373d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom        private final ServiceConnection serviceConnection;
374d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom        private final IKeyChainService service;
375d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom        private KeyChainConnection(Context context,
376d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom                                   ServiceConnection serviceConnection,
377d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom                                   IKeyChainService service) {
378d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom            this.context = context;
379d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom            this.serviceConnection = serviceConnection;
380d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom            this.service = service;
381d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom        }
382d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom        @Override public void close() {
383d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom            context.unbindService(serviceConnection);
384d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom        }
385d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom        public IKeyChainService getService() {
386d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom            return service;
387d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom        }
388d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom    }
389d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom
390d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom    /**
391d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom     * @hide for reuse by CertInstaller and Settings.
392d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom     *
393d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom     * Caller should call unbindService on the result when finished.
394d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom     */
395d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom    public static KeyChainConnection bind(Context context) throws InterruptedException {
396d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom        if (context == null) {
397d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom            throw new NullPointerException("context == null");
398d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom        }
399d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom        ensureNotOnMainThread(context);
400d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom        final BlockingQueue<IKeyChainService> q = new LinkedBlockingQueue<IKeyChainService>(1);
401d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom        ServiceConnection keyChainServiceConnection = new ServiceConnection() {
402ab8b84ad3847788d83da557606aa27d4102e6b52Fred Quintana            volatile boolean mConnectedAtLeastOnce = false;
403d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom            @Override public void onServiceConnected(ComponentName name, IBinder service) {
404ab8b84ad3847788d83da557606aa27d4102e6b52Fred Quintana                if (!mConnectedAtLeastOnce) {
405ab8b84ad3847788d83da557606aa27d4102e6b52Fred Quintana                    mConnectedAtLeastOnce = true;
406ab8b84ad3847788d83da557606aa27d4102e6b52Fred Quintana                    try {
407ab8b84ad3847788d83da557606aa27d4102e6b52Fred Quintana                        q.put(IKeyChainService.Stub.asInterface(service));
408ab8b84ad3847788d83da557606aa27d4102e6b52Fred Quintana                    } catch (InterruptedException e) {
409ab8b84ad3847788d83da557606aa27d4102e6b52Fred Quintana                        // will never happen, since the queue starts with one available slot
410ab8b84ad3847788d83da557606aa27d4102e6b52Fred Quintana                    }
411d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom                }
412d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom            }
413d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom            @Override public void onServiceDisconnected(ComponentName name) {}
414d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom        };
415d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom        boolean isBound = context.bindService(new Intent(IKeyChainService.class.getName()),
416d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom                                              keyChainServiceConnection,
417d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom                                              Context.BIND_AUTO_CREATE);
418d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom        if (!isBound) {
419d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom            throw new AssertionError("could not bind to KeyChainService");
420d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom        }
421d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom        return new KeyChainConnection(context, keyChainServiceConnection, q.take());
422d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom    }
423d752472d9abf03fda637d43716bc6bd632e1f5c3Brian Carlstrom
4248e9929c4d0730de4c9f01435a7cfe2db8855e24dBrian Carlstrom    private static void ensureNotOnMainThread(Context context) {
425b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom        Looper looper = Looper.myLooper();
4268e9929c4d0730de4c9f01435a7cfe2db8855e24dBrian Carlstrom        if (looper != null && looper == context.getMainLooper()) {
427b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom            throw new IllegalStateException(
428b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom                    "calling this from your main thread can lead to deadlock");
429b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom        }
430b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom    }
431b9a07c18e678da35b4c2a618b315fa174a21e818Brian Carlstrom}
432