Device Policy API to choose a private key silently

Support for certificate chooser (keychain) to first query a profile
owner (if one exists) for a silent credentials grant which will be
passed back to the caller as an alias.

Bug: 15065444
Change-Id: I0729b435c218b7991e6cb5faedefb7900577afcc
diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java
index dfa41e8..e9c24dd 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -127,6 +127,12 @@
      * Extra for use with {@link #ACTION_CHOOSER}
      * @hide Also used by KeyChainActivity implementation
      */
+    public static final String EXTRA_URL = "url";
+
+    /**
+     * Extra for use with {@link #ACTION_CHOOSER}
+     * @hide Also used by KeyChainActivity implementation
+     */
     public static final String EXTRA_ALIAS = "alias";
 
     /**
@@ -224,6 +230,51 @@
      * selected alias or null will be returned via the
      * KeyChainAliasCallback callback.
      *
+     * <p>The device or profile owner can intercept this before the activity
+     * is shown, to pick a specific private key alias.
+     *
+     * <p>{@code keyTypes} and {@code issuers} may be used to
+     * highlight suggested choices to the user, although to cope with
+     * sometimes erroneous values provided by servers, the user may be
+     * able to override these suggestions.
+     *
+     * <p>{@code host} and {@code port} may be used to give the user
+     * more context about the server requesting the credentials.
+     *
+     * <p>{@code alias} allows the chooser to preselect an existing
+     * alias which will still be subject to user confirmation.
+     *
+     * @param activity The {@link Activity} context to use for
+     *     launching the new sub-Activity to prompt the user to select
+     *     a private key; used only to call startActivity(); must not
+     *     be null.
+     * @param response Callback to invoke when the request completes;
+     *     must not be null
+     * @param keyTypes The acceptable types of asymmetric keys such as
+     *     "RSA" or "DSA", or a null array.
+     * @param issuers The acceptable certificate issuers for the
+     *     certificate matching the private key, or null.
+     * @param host The host name of the server requesting the
+     *     certificate, or null if unavailable.
+     * @param port The port number of the server requesting the
+     *     certificate, or -1 if unavailable.
+     * @param alias The alias to preselect if available, or null if
+     *     unavailable.
+     */
+    public static void choosePrivateKeyAlias(Activity activity, KeyChainAliasCallback response,
+            String[] keyTypes, Principal[] issuers, String host, int port, String alias) {
+        choosePrivateKeyAlias(activity, response, keyTypes, issuers, host, port, null, alias);
+    }
+
+    /**
+     * Launches an {@code Activity} for the user to select the alias
+     * for a private key and certificate pair for authentication. The
+     * selected alias or null will be returned via the
+     * KeyChainAliasCallback callback.
+     *
+     * <p>The device or profile owner can intercept this before the activity
+     * is shown, to pick a specific private key alias.</p>
+     *
      * <p>{@code keyTypes} and {@code issuers} may be used to
      * highlight suggested choices to the user, although to cope with
      * sometimes erroneous values provided by servers, the user may be
@@ -249,12 +300,14 @@
      *     certificate, or null if unavailable.
      * @param port The port number of the server requesting the
      *     certificate, or -1 if unavailable.
+     * @param url The full url the server is requesting the certificate
+     *     for, or null if unavailable.
      * @param alias The alias to preselect if available, or null if
      *     unavailable.
      */
     public static void choosePrivateKeyAlias(Activity activity, KeyChainAliasCallback response,
                                              String[] keyTypes, Principal[] issuers,
-                                             String host, int port,
+                                             String host, int port, String url,
                                              String alias) {
         /*
          * TODO currently keyTypes, issuers are unused. They are meant
@@ -283,6 +336,7 @@
         intent.putExtra(EXTRA_RESPONSE, new AliasResponse(response));
         intent.putExtra(EXTRA_HOST, host);
         intent.putExtra(EXTRA_PORT, port);
+        intent.putExtra(EXTRA_URL, url);
         intent.putExtra(EXTRA_ALIAS, alias);
         // the PendingIntent is used to get calling package name
         intent.putExtra(EXTRA_SENDER, PendingIntent.getActivity(activity, 0, new Intent(), 0));