Add spinner to select Wi-Fi

For the regular installation path, we now need to show a spinner so we
don't regress from previous behavior where we can install certs for wifi
from the main installation screen.

You can also get to this from the Wi-Fi AP list, so only show it when
the intended use is ambiguous.

Bug: 8600545
Change-Id: I8e9c905ff84142ed7c1f50bf77eb3fb5574f8df1
diff --git a/res/layout/name_credential_dialog.xml b/res/layout/name_credential_dialog.xml
index 21588ff..f68c8f7 100644
--- a/res/layout/name_credential_dialog.xml
+++ b/res/layout/name_credential_dialog.xml
@@ -18,10 +18,10 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content">
 
-    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    <LinearLayout
             android:orientation="vertical"
             android:layout_width="match_parent"
-            android:layout_height="match_parent"
+            android:layout_height="wrap_content"
             android:padding="15dip">
 
         <TextView android:id="@+id/error"
@@ -31,17 +31,44 @@
                 android:textStyle="bold"
                 android:visibility="gone" />
 
-        <TextView android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:text="@string/credential_name" />
+        <TextView
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/credential_name"
+            android:textAppearance="?android:attr/textAppearanceMedium" />
+
         <EditText android:id="@+id/credential_name"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:singleLine="True"/>
 
-        <TextView android:layout_width="match_parent"
+        <LinearLayout
+            android:id="@+id/credential_usage_group"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical" >
+
+            <TextView
+                android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:text="@string/credential_info" />
+                android:paddingTop="12dp"
+                android:text="@string/credential_usage_label"
+                android:textAppearance="?android:attr/textAppearanceMedium" />
+
+            <Spinner
+                android:id="@+id/credential_usage"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:entries="@array/credential_usage" />
+
+        </LinearLayout>
+
+        <TextView
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingTop="12dp"
+            android:text="@string/credential_info" />
+
         <TextView android:id="@+id/credential_info"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content" />
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 34d70b0..e0bd560 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -74,4 +74,15 @@
     <!-- Message displayed when a user other than the owner on a multi-user system tries to
          install a certificate into the certificate store. [CHAR LIMIT=NONE] -->
     <string name="only_primary_user_allowed">Only the owner of this device may install certificates.</string>
+
+    <!-- Label for spinner that shows the possible usage for a credential. Shown when user is
+         installing a credential [CHAR LIMIT=40] -->
+    <string name="credential_usage_label">Credential use:</string>
+
+    <!-- Usage type for a credential that the user is installing. The label will restrict the
+         type of use for that credential. [CHAR LIMIT=40] -->
+    <string-array name="credential_usage">
+        <item>VPN and apps</item>
+        <item>Wi-Fi</item>
+    </string-array>
 </resources>
diff --git a/src/com/android/certinstaller/CertInstaller.java b/src/com/android/certinstaller/CertInstaller.java
index 8e06982..907646e 100644
--- a/src/com/android/certinstaller/CertInstaller.java
+++ b/src/com/android/certinstaller/CertInstaller.java
@@ -25,6 +25,7 @@
 import android.content.Intent;
 import android.os.AsyncTask;
 import android.os.Bundle;
+import android.os.Process;
 import android.security.Credentials;
 import android.security.KeyChain;
 import android.security.KeyChain.KeyChainConnection;
@@ -33,7 +34,10 @@
 import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemSelectedListener;
 import android.widget.EditText;
+import android.widget.Spinner;
 import android.widget.Toast;
 
 import java.io.Serializable;
@@ -63,6 +67,10 @@
     // key to KeyStore
     private static final String PKEY_MAP_KEY = "PKEY_MAP";
 
+    // Values for usage type spinner
+    private static final int USAGE_TYPE_SYSTEM = 0;
+    private static final int USAGE_TYPE_WIFI = 1;
+
     private final KeyStore mKeyStore = KeyStore.getInstance();
     private final ViewHelper mView = new ViewHelper();
 
@@ -359,6 +367,31 @@
         }
         mView.setText(R.id.credential_info, mCredentials.getDescription(this).toString());
         final EditText nameInput = (EditText) view.findViewById(R.id.credential_name);
+        if (mCredentials.isInstallAsUidSet()) {
+            view.findViewById(R.id.credential_usage_group).setVisibility(View.GONE);
+        } else {
+            final Spinner usageSpinner = (Spinner) view.findViewById(R.id.credential_usage);
+
+            usageSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
+                @Override
+                public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+                    switch ((int) id) {
+                        case USAGE_TYPE_SYSTEM:
+                            mCredentials.setInstallAsUid(KeyStore.UID_SELF);
+                            break;
+                        case USAGE_TYPE_WIFI:
+                            mCredentials.setInstallAsUid(Process.WIFI_UID);
+                            break;
+                        default:
+                            Log.w(TAG, "Unknown selection for scope: " + id);
+                    }
+                }
+
+                @Override
+                public void onNothingSelected(AdapterView<?> parent) {
+                }
+            });
+        }
         nameInput.setText(getDefaultName());
         nameInput.selectAll();
         Dialog d = new AlertDialog.Builder(this)
diff --git a/src/com/android/certinstaller/CredentialHelper.java b/src/com/android/certinstaller/CredentialHelper.java
index 5f59387..c131268 100644
--- a/src/com/android/certinstaller/CredentialHelper.java
+++ b/src/com/android/certinstaller/CredentialHelper.java
@@ -248,6 +248,14 @@
         return mName;
     }
 
+    void setInstallAsUid(int uid) {
+        mUid = uid;
+    }
+
+    boolean isInstallAsUidSet() {
+        return mUid != -1;
+    }
+
     Intent createSystemInstallIntent() {
         Intent intent = new Intent("com.android.credentials.INSTALL");
         // To prevent the private key from being sniffed, we explicitly spell