[DO NOT MERGE] Rollup changes from R am: 7830ab3251

Original change: https://android-review.googlesource.com/c/platform/packages/apps/CertInstaller/+/1363500

Change-Id: Iaf727935c6195a71d684188629e5c9cafae48b46
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 7d543fb..886b7ca 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -38,6 +38,7 @@
 
         <activity-alias android:name=".InstallCertAsUser"
              android:targetActivity=".CertInstallerMain"
+             android:exported="true"
              android:permission="com.android.certinstaller.INSTALL_AS_USER">
             <intent-filter>
                 <action android:name="android.credentials.INSTALL_AS_USER"/>
diff --git a/res/layout/name_certificate_dialog.xml b/res/layout/name_certificate_dialog.xml
new file mode 100644
index 0000000..baa15d9
--- /dev/null
+++ b/res/layout/name_certificate_dialog.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+
+    <LinearLayout
+            android:orientation="vertical"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:padding="16dp">
+
+        <TextView android:id="@+id/error"
+                  android:layout_width="match_parent"
+                  android:layout_height="wrap_content"
+                  android:textColor="@color/red"
+                  android:textStyle="bold"
+                  android:visibility="gone" />
+
+        <TextView android:layout_width="match_parent"
+                  android:layout_height="wrap_content"
+                  android:text="@string/certificate_name"
+                  android:textAppearance="?android:attr/textAppearanceSmall"
+                  android:textColor="?android:attr/colorAccent"/>
+
+        <EditText android:id="@+id/certificate_name"
+                  android:layout_width="match_parent"
+                  android:layout_height="wrap_content"
+                  style="@style/dialog_edit_text"/>
+
+    </LinearLayout>
+</ScrollView>
diff --git a/res/layout/name_credential_dialog.xml b/res/layout/name_credential_dialog.xml
deleted file mode 100644
index 6dd46ff..0000000
--- a/res/layout/name_credential_dialog.xml
+++ /dev/null
@@ -1,85 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content">
-
-    <LinearLayout
-            android:orientation="vertical"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:padding="15dip">
-
-        <TextView android:id="@+id/error"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:textColor="@color/red"
-                android:textStyle="bold"
-                android:visibility="gone" />
-
-        <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"/>
-
-        <LinearLayout
-            android:id="@+id/credential_usage_group"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="vertical" >
-
-            <TextView
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:paddingTop="12dp"
-                android:text="@string/credential_usage_label"
-                android:textAppearance="?android:attr/textAppearanceMedium" />
-
-            <Spinner
-                android:id="@+id/credential_usage"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:entries="@array/credential_usage" />
-
-            <TextView
-                android:id="@+id/credential_capabilities_warning"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:paddingTop="12dp"
-                android:text="@string/certificate_capabilities_warning"
-                android:textColor="@color/red" />
-
-        </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" />
-
-    </LinearLayout>
-</ScrollView>
diff --git a/res/layout/select_certificate_usage_dialog.xml b/res/layout/select_certificate_usage_dialog.xml
new file mode 100644
index 0000000..6a053a4
--- /dev/null
+++ b/res/layout/select_certificate_usage_dialog.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2019 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content">
+
+    <LinearLayout
+        android:orientation="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:padding="16dp">
+
+        <LinearLayout
+            android:id="@+id/certificate_usage_group"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical">
+
+            <TextView
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/select_certificate_usage_title"
+                style="@style/dialog_title"/>
+
+            <View
+                android:layout_width="match_parent"
+                android:layout_height="1dip"
+                android:background="?android:attr/dividerHorizontal"/>
+
+            <RadioGroup
+                android:id="@+id/certificate_usage"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="16dp">
+
+                <RadioButton
+                    android:id="@+id/user_certificate"
+                    style="@style/dialog_button"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:text="@string/user_certificate"
+                    android:checked="true"/>
+
+                <RadioButton
+                    android:id="@+id/wifi_certificate"
+                    style="@style/dialog_button"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:text="@string/wifi_certificate"/>
+
+            </RadioGroup>
+
+            <View
+                android:layout_width="match_parent"
+                android:layout_height="1dip"
+                android:background="?android:attr/dividerHorizontal"/>
+
+        </LinearLayout>
+
+    </LinearLayout>
+</ScrollView>
\ No newline at end of file
diff --git a/res/values/config.xml b/res/values/config.xml
index 062c1ce..25f6905 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -15,8 +15,6 @@
 -->
 
 <resources>
-  <bool name="config_auto_cert_approval">true</bool>
-
   <string name="config_system_install_component" translatable="false">com.android.settings/com.android.settings.security.CredentialStorage</string>
 </resources>
 
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 020a014..7cf78ce 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -26,10 +26,10 @@
     <string name="extracting_pkcs12">Extracting\u2026</string>
     <!-- Title of dialog to enter password for pkcs12 file -->
     <string name="pkcs12_file_password_dialog_title">Extract from %s</string>
-    <!-- Title of dialog to name a credential -->
-    <string name="name_credential_dialog_title">Name the certificate</string>
-    <!-- Description for the credential name input box -->
-    <string name="credential_name">Certificate name:</string>
+    <!-- Title of a dialog. This title is asking the user to name the certificate they're installing on their device. -->
+    <string name="name_credential_dialog_title">Name this certificate</string>
+    <!-- Input field in a dialog. This dialog is asking the user to name the certificate they are installing on their device. -->
+    <string name="certificate_name">Certificate name</string>
     <!-- Title of the credential info -->
     <!-- Description for the credential password input box -->
     <string name="credential_password">Type the password to extract the certificates.</string>
@@ -58,14 +58,49 @@
     <string name="action_missing_private_key">Private key required to install a certificate</string>
     <string name="action_missing_user_cert">Certificate required to install a private key</string>
 
-    <!-- toast message -->
-    <string name="cert_is_added"><xliff:g id="credential">%s</xliff:g> is installed.</string>
+    <!-- Title of dialog to select the certificate usage when installing a certificate outside Settings -->
+    <string name="select_certificate_usage_title">Choose a certificate type</string>
+    <!-- Title of dialog that lets the user know that they must install CA certificates
+        in Settings. -->
+    <string name="redirect_ca_certificate_title">Install CA certificates in Settings</string>
+    <!-- Message of dialog that lets the user know that they must install CA certificates in
+        Settings. The placeholder is the name of the app that was trying to install the CA
+        certificate. -->
+    <string name="redirect_ca_certificate_with_app_info_message">This certificate from
+        <xliff:g id="requesting_app" example="Some App">%1$s</xliff:g> must be installed in
+        Settings. Only install CA certificates from organizations you trust.</string>
+    <!-- Button of dialog to redirect user when installing a CA certificate outside Settings -->
+    <string name="redirect_ca_certificate_close_button">Close</string>
+    <!-- Title of dialog to inform user that certificate selected is invalid -->
+    <string name="invalid_certificate_title">Can\'t use this file</string>
+    <!-- Button of dialog to inform user that certificate selected is invalid -->
+    <string name="invalid_certificate_close_button">Close</string>
+    <!-- Message of dialog to inform user that certificate selected is invalid -->
+    <string name="invalid_certificate_message">This file can\'t be used as a <xliff:g id="certificate_usage">%1$s</xliff:g></string>
+    <!-- Default certificate type used in dialog to inform user that certificate selected is invalid -->
+    <string name="certificate">Certificate</string>
+    <!-- CA certificate type used in dialog to inform user that certificate selected is invalid -->
+    <string name="ca_certificate">CA certificate</string>
+    <!-- User certificate type used in dialog to inform user that certificate selected is invalid -->
+    <string name="user_certificate">VPN &amp; app user certificate</string>
+    <!-- WiFi certificate type used in dialog to inform user that certificate selected is invalid -->
+    <string name="wifi_certificate">Wi\u2011Fi certificate</string>
+
+
+    <!-- Confirmation toast. This toast lets the user know that they successfully installed a CA certificate on their device. -->
+    <string name="ca_cert_is_added">CA certificate installed</string>
+    <!-- Confirmation toast. This toast lets the user know that they successfully installed a user certificate on their device. -->
+    <string name="user_cert_is_added">User certificate installed</string>
+    <!-- Confirmation toast. This toast lets the user know that they successfully installed a Wi-Fi certificate on their device. -->
+    <string name="wifi_cert_is_added">Wi\u2011Fi certificate installed</string>
     <!-- toast message -->
     <string name="cert_too_large_error">Couldn\'t install because the certificate size is too large.</string>
     <!-- toast message -->
     <string name="cert_missing_error">Couldn\'t install because the certificate file couldn\'t be located.</string>
     <!-- toast message -->
     <string name="cert_read_error">Couldn\'t install because the certificate file couldn\'t be read.</string>
+    <!-- toast message -->
+    <string name="cert_temp_error">Temporary failure. Please try again later.</string>
 
     <!-- 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] -->
diff --git a/res/values/styles.xml b/res/values/styles.xml
index b1d493e..7bac29f 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -28,4 +28,20 @@
         <item name="android:textAppearance">@android:style/TextAppearance.Material.Subhead</item>
         <item name="android:textColor">?android:attr/textColorPrimary</item>
     </style>
+    <style name="dialog_title">
+        <item name="android:textColor">?android:attr/textColorPrimary</item>
+        <item name="android:textSize">20sp</item>
+        <item name="android:layout_marginBottom">16dp</item>
+    </style>
+    <style name="dialog_edit_text">
+        <item name="android:textColor">?android:attr/textColorPrimary</item>
+        <item name="android:backgroundTint">?android:attr/colorAccent</item>
+        <item name="android:singleLine">True</item>
+    </style>
+    <style name="dialog_button">
+        <item name="android:textColor">?android:attr/textColorPrimary</item>
+        <item name="android:textSize">16sp</item>
+        <item name="android:layout_marginBottom">12dp</item>
+        <item name="android:layout_marginLeft">4dp</item>
+    </style>
 </resources>
diff --git a/src/com/android/certinstaller/CertInstaller.java b/src/com/android/certinstaller/CertInstaller.java
index dd849a7..3a6b7b3 100644
--- a/src/com/android/certinstaller/CertInstaller.java
+++ b/src/com/android/certinstaller/CertInstaller.java
@@ -21,25 +21,24 @@
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.Dialog;
-import android.app.KeyguardManager;
 import android.app.ProgressDialog;
 import android.content.ActivityNotFoundException;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
 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;
-import android.security.KeyStore;
 import android.text.TextUtils;
 import android.util.Log;
+import android.util.Slog;
 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.RadioGroup;
 import android.widget.Toast;
 
 import java.io.Serializable;
@@ -57,17 +56,15 @@
     private static final int NAME_CREDENTIAL_DIALOG = 1;
     private static final int PKCS12_PASSWORD_DIALOG = 2;
     private static final int PROGRESS_BAR_DIALOG = 3;
+    private static final int REDIRECT_CA_CERTIFICATE_DIALOG = 4;
+    private static final int SELECT_CERTIFICATE_USAGE_DIALOG = 5;
+    private static final int INVALID_CERTIFICATE_DIALOG = 6;
 
     private static final int REQUEST_SYSTEM_INSTALL_CODE = 1;
-    private static final int REQUEST_CONFIRM_CREDENTIALS = 2;
 
     // key to states Bundle
     private static final String NEXT_ACTION_KEY = "na";
 
-    // Values for usage type spinner
-    private static final int USAGE_TYPE_SYSTEM = 0;
-    private static final int USAGE_TYPE_WIFI = 1;
-
     private final ViewHelper mView = new ViewHelper();
 
     private int mState;
@@ -98,20 +95,8 @@
                 toastErrorAndFinish(R.string.no_cert_to_saved);
                 finish();
             } else {
-                // Confirm credentials if there's _only_ a CA certificate
-                // NOTE: This will affect WiFi CA certificates - those should not require
-                // confirming the lock screen credentials but the code currently cannot skip the
-                // confirmation for WiFi CA certificates because the user designates the certificate
-                // to a UID only after this stage.
-                if (mCredentials.hasCaCerts() && !mCredentials.hasPrivateKey() &&
-                        !mCredentials.hasUserCertificate()) {
-                    KeyguardManager keyguardManager = getSystemService(KeyguardManager.class);
-                    Intent intent = keyguardManager.createConfirmDeviceCredentialIntent(null, null);
-                    if (intent == null) { // No screenlock
-                        extractPkcs12OrInstall();
-                    } else {
-                        startActivityForResult(intent, REQUEST_CONFIRM_CREDENTIALS);
-                    }
+                if (installingCaCertificate()) {
+                    extractPkcs12OrInstall();
                 } else {
                     if (mCredentials.hasUserCertificate() && !mCredentials.hasPrivateKey()) {
                         toastErrorAndFinish(R.string.action_missing_private_key);
@@ -129,6 +114,11 @@
         }
     }
 
+    private boolean installingCaCertificate() {
+        return mCredentials.hasCaCerts() && !mCredentials.hasPrivateKey() &&
+                !mCredentials.hasUserCertificate();
+    }
+
     @Override
     protected void onResume() {
         super.onResume();
@@ -164,7 +154,7 @@
                 return createPkcs12PasswordDialog();
 
             case NAME_CREDENTIAL_DIALOG:
-                return createNameCredentialDialog();
+                return createNameCertificateDialog();
 
             case PROGRESS_BAR_DIALOG:
                 ProgressDialog dialog = new ProgressDialog(this);
@@ -173,6 +163,15 @@
                 dialog.setCancelable(false);
                 return dialog;
 
+            case REDIRECT_CA_CERTIFICATE_DIALOG:
+                return createRedirectCaCertificateDialog();
+
+            case SELECT_CERTIFICATE_USAGE_DIALOG:
+                return createSelectCertificateUsageDialog();
+
+            case INVALID_CERTIFICATE_DIALOG:
+                return createInvalidCertificateDialog();
+
             default:
                 return null;
         }
@@ -189,25 +188,14 @@
                 }
 
                 Log.d(TAG, "credential is added: " + mCredentials.getName());
-                Toast.makeText(this, getString(R.string.cert_is_added, mCredentials.getName()),
-                        Toast.LENGTH_LONG).show();
-
-                if (mCredentials.includesVpnAndAppsTrustAnchors()) {
-                    // more work to do, don't finish just yet
-                    new InstallVpnAndAppsTrustAnchorsTask().execute();
-                    return;
+                if (mCredentials.getCertUsageSelected().equals(Credentials.CERTIFICATE_USAGE_WIFI)) {
+                    Toast.makeText(this, R.string.wifi_cert_is_added, Toast.LENGTH_LONG).show();
+                } else {
+                    Toast.makeText(this, R.string.user_cert_is_added, Toast.LENGTH_LONG).show();
                 }
                 setResult(RESULT_OK);
                 finish();
                 break;
-            case REQUEST_CONFIRM_CREDENTIALS:
-                if (resultCode == RESULT_OK) {
-                    extractPkcs12OrInstall();
-                    return;
-                }
-                // Failed to confirm credentials, do nothing.
-                finish();
-                break;
             default:
                 Log.w(TAG, "unknown request code: " + requestCode);
                 finish();
@@ -223,14 +211,19 @@
                 new Pkcs12ExtractAction("").run(this);
             }
         } else {
-            MyAction action = new InstallOthersAction();
-            action.run(this);
+            if (mCredentials.calledBySettings()) {
+                MyAction action = new InstallOthersAction();
+                action.run(this);
+            } else {
+                createRedirectOrSelectUsageDialog();
+            }
         }
     }
 
     private class InstallVpnAndAppsTrustAnchorsTask extends AsyncTask<Void, Void, Boolean> {
 
-        @Override protected Boolean doInBackground(Void... unused) {
+        @Override
+        protected Boolean doInBackground(Void... unused) {
             try {
                 try (KeyChainConnection keyChainConnection = KeyChain.bind(CertInstaller.this)) {
                     return mCredentials.installVpnAndAppsTrustAnchors(CertInstaller.this,
@@ -242,8 +235,11 @@
             }
         }
 
-        @Override protected void onPostExecute(Boolean success) {
+        @Override
+        protected void onPostExecute(Boolean success) {
             if (success) {
+                Toast.makeText(getApplicationContext(), R.string.ca_cert_is_added,
+                        Toast.LENGTH_LONG).show();
                 setResult(RESULT_OK);
             }
             finish();
@@ -266,13 +262,38 @@
             return;
         }
 
-        nameCredential();
+        if (validCertificateSelected()) {
+            installCertificateOrShowNameDialog();
+        } else {
+            showDialog(INVALID_CERTIFICATE_DIALOG);
+        }
     }
 
-    private void nameCredential() {
+    private boolean validCertificateSelected() {
+        switch (mCredentials.getCertUsageSelected()) {
+            case Credentials.CERTIFICATE_USAGE_CA:
+                return mCredentials.hasOnlyVpnAndAppsTrustAnchors();
+            case Credentials.CERTIFICATE_USAGE_USER:
+                return mCredentials.hasUserCertificate()
+                        && !mCredentials.hasOnlyVpnAndAppsTrustAnchors();
+            case Credentials.CERTIFICATE_USAGE_WIFI:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    private void installCertificateOrShowNameDialog() {
         if (!mCredentials.hasAnyForSystemInstall()) {
             toastErrorAndFinish(R.string.no_cert_to_saved);
+        } else if (mCredentials.hasOnlyVpnAndAppsTrustAnchors()) {
+            // If there's only a CA certificate to install, then it's going to be used
+            // as a trust anchor. Install it and skip importing to Keystore.
+
+            // more work to do, don't finish just yet
+            new InstallVpnAndAppsTrustAnchorsTask().execute();
         } else {
+            // Name is required if installing User certificate
             showDialog(NAME_CREDENTIAL_DIALOG);
         }
     }
@@ -302,7 +323,15 @@
         removeDialog(PROGRESS_BAR_DIALOG);
         if (success) {
             removeDialog(PKCS12_PASSWORD_DIALOG);
-            nameCredential();
+            if (mCredentials.calledBySettings()) {
+                if (validCertificateSelected()) {
+                    installCertificateOrShowNameDialog();
+                } else {
+                    showDialog(INVALID_CERTIFICATE_DIALOG);
+                }
+            } else {
+                createRedirectOrSelectUsageDialog();
+            }
         } else {
             showDialog(PKCS12_PASSWORD_DIALOG);
             mView.setText(R.id.credential_password, "");
@@ -310,6 +339,103 @@
         }
     }
 
+    private void createRedirectOrSelectUsageDialog() {
+        if (mCredentials.hasOnlyVpnAndAppsTrustAnchors()) {
+            showDialog(REDIRECT_CA_CERTIFICATE_DIALOG);
+        } else {
+            showDialog(SELECT_CERTIFICATE_USAGE_DIALOG);
+        }
+    }
+
+    public CharSequence getCallingAppLabel() {
+        final String callingPkg = mCredentials.getReferrer();
+        if (callingPkg == null) {
+            Log.e(TAG, "Cannot get calling calling AppPackage");
+            return null;
+        }
+
+        final PackageManager pm = getPackageManager();
+        final ApplicationInfo appInfo;
+        try {
+            appInfo = pm.getApplicationInfo(callingPkg, PackageManager.MATCH_DISABLED_COMPONENTS);
+        } catch (PackageManager.NameNotFoundException e) {
+            Log.e(TAG, "Unable to find info for package: " + callingPkg);
+            return null;
+        }
+
+        return appInfo.loadLabel(pm);
+    }
+
+    private Dialog createRedirectCaCertificateDialog() {
+        final String message = getString(
+                R.string.redirect_ca_certificate_with_app_info_message, getCallingAppLabel());
+        Dialog d = new AlertDialog.Builder(this)
+                .setTitle(R.string.redirect_ca_certificate_title)
+                .setMessage(message)
+                .setPositiveButton(R.string.redirect_ca_certificate_close_button,
+                        (dialog, id) -> toastErrorAndFinish(R.string.cert_not_saved))
+                .create();
+        d.setOnCancelListener(dialog -> toastErrorAndFinish(R.string.cert_not_saved));
+        return d;
+    }
+
+    private Dialog createSelectCertificateUsageDialog() {
+        ViewGroup view = (ViewGroup) View.inflate(this, R.layout.select_certificate_usage_dialog,
+                null);
+        mView.setView(view);
+
+        RadioGroup radioGroup = view.findViewById(R.id.certificate_usage);
+        radioGroup.setOnCheckedChangeListener((group, checkedId) -> {
+            switch (checkedId) {
+                case R.id.user_certificate:
+                    mCredentials.setCertUsageSelectedAndUid(Credentials.CERTIFICATE_USAGE_USER);
+                    break;
+                case R.id.wifi_certificate:
+                    mCredentials.setCertUsageSelectedAndUid(Credentials.CERTIFICATE_USAGE_WIFI);
+                default:
+                    Slog.i(TAG, "Unknown selection for scope");
+            }
+        });
+
+
+        final Context appContext = getApplicationContext();
+        Dialog d = new AlertDialog.Builder(this)
+                .setView(view)
+                .setPositiveButton(android.R.string.ok, (dialog, id) -> {
+                    showDialog(NAME_CREDENTIAL_DIALOG);
+                })
+                .setNegativeButton(android.R.string.cancel,
+                        (dialog, id) -> toastErrorAndFinish(R.string.cert_not_saved))
+                .create();
+        d.setOnCancelListener(dialog -> toastErrorAndFinish(R.string.cert_not_saved));
+        return d;
+    }
+
+    private Dialog createInvalidCertificateDialog() {
+        Dialog d = new AlertDialog.Builder(this)
+                .setTitle(R.string.invalid_certificate_title)
+                .setMessage(getString(R.string.invalid_certificate_message,
+                        getCertificateUsageName()))
+                .setPositiveButton(R.string.invalid_certificate_close_button,
+                        (dialog, id) -> toastErrorAndFinish(R.string.cert_not_saved))
+                .create();
+        d.setOnCancelListener(dialog -> finish());
+        return d;
+    }
+
+    String getCertificateUsageName() {
+        switch (mCredentials.getCertUsageSelected()) {
+            case Credentials.CERTIFICATE_USAGE_CA:
+                return getString(R.string.ca_certificate);
+            case Credentials.CERTIFICATE_USAGE_USER:
+                return getString(R.string.user_certificate);
+            case Credentials.CERTIFICATE_USAGE_WIFI:
+                return getString(R.string.wifi_certificate);
+            default:
+                return getString(R.string.certificate);
+        }
+    }
+
     private Dialog createPkcs12PasswordDialog() {
         View view = View.inflate(this, R.layout.password_dialog, null);
         mView.setView(view);
@@ -337,53 +463,23 @@
         return d;
     }
 
-    private Dialog createNameCredentialDialog() {
-        ViewGroup view = (ViewGroup) View.inflate(this, R.layout.name_credential_dialog, null);
+    private Dialog createNameCertificateDialog() {
+        ViewGroup view = (ViewGroup) View.inflate(this, R.layout.name_certificate_dialog, null);
         mView.setView(view);
         if (mView.getHasEmptyError()) {
             mView.showError(R.string.name_empty_error);
             mView.setHasEmptyError(false);
         }
-        mView.setText(R.id.credential_info, mCredentials.getDescription(this).toString());
-        final EditText nameInput = view.findViewById(R.id.credential_name);
-        if (mCredentials.isInstallAsUidSet()) {
-            view.findViewById(R.id.credential_usage_group).setVisibility(View.GONE);
-        } else {
-            final Spinner usageSpinner = view.findViewById(R.id.credential_usage);
-            final View ca_capabilities_warning = view.findViewById(R.id.credential_capabilities_warning);
-
-            usageSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
-                @Override
-                public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
-                    switch ((int) id) {
-                        case USAGE_TYPE_SYSTEM:
-                            ca_capabilities_warning.setVisibility(
-                                    mCredentials.includesVpnAndAppsTrustAnchors() ?
-                                    View.VISIBLE : View.GONE);
-                            mCredentials.setInstallAsUid(KeyStore.UID_SELF);
-                            break;
-                        case USAGE_TYPE_WIFI:
-                            ca_capabilities_warning.setVisibility(View.GONE);
-                            mCredentials.setInstallAsUid(Process.WIFI_UID);
-                            break;
-                        default:
-                            Log.w(TAG, "Unknown selection for scope: " + id);
-                    }
-                }
-
-                @Override
-                public void onNothingSelected(AdapterView<?> parent) {
-                }
-            });
-        }
+        final EditText nameInput = view.findViewById(R.id.certificate_name);
         nameInput.setText(getDefaultName());
         nameInput.selectAll();
         final Context appContext = getApplicationContext();
+
         Dialog d = new AlertDialog.Builder(this)
                 .setView(view)
                 .setTitle(R.string.name_credential_dialog_title)
                 .setPositiveButton(android.R.string.ok, (dialog, id) -> {
-                    String name = mView.getText(R.id.credential_name);
+                    String name = mView.getText(R.id.certificate_name);
                     if (TextUtils.isEmpty(name)) {
                         mView.setHasEmptyError(true);
                         removeDialog(NAME_CREDENTIAL_DIALOG);
@@ -391,16 +487,7 @@
                     } else {
                         removeDialog(NAME_CREDENTIAL_DIALOG);
                         mCredentials.setName(name);
-
-                        // install everything to system keystore
-                        try {
-                            startActivityForResult(
-                                    mCredentials.createSystemInstallIntent(appContext),
-                                    REQUEST_SYSTEM_INSTALL_CODE);
-                        } catch (ActivityNotFoundException e) {
-                            Log.w(TAG, "systemInstall(): " + e);
-                            toastErrorAndFinish(R.string.cert_not_saved);
-                        }
+                        installCertificateToKeystore(appContext);
                     }
                 })
                 .setNegativeButton(android.R.string.cancel,
@@ -410,6 +497,17 @@
         return d;
     }
 
+    private void installCertificateToKeystore(Context context) {
+        try {
+            startActivityForResult(
+                    mCredentials.createSystemInstallIntent(context),
+                    REQUEST_SYSTEM_INSTALL_CODE);
+        } catch (ActivityNotFoundException e) {
+            Log.w(TAG, "installCertificateToKeystore(): ", e);
+            toastErrorAndFinish(R.string.cert_not_saved);
+        }
+    }
+
     private String getDefaultName() {
         String name = mCredentials.getName();
         if (TextUtils.isEmpty(name)) {
diff --git a/src/com/android/certinstaller/CertInstallerMain.java b/src/com/android/certinstaller/CertInstallerMain.java
index 7e93884..4cec5fc 100644
--- a/src/com/android/certinstaller/CertInstallerMain.java
+++ b/src/com/android/certinstaller/CertInstallerMain.java
@@ -16,10 +16,14 @@
 
 package com.android.certinstaller;
 
+import android.app.ActivityTaskManager;
+import android.app.IActivityTaskManager;
+import android.app.KeyguardManager;
 import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.RemoteException;
 import android.os.UserManager;
 import android.preference.PreferenceActivity;
 import android.provider.DocumentsContract;
@@ -28,6 +32,8 @@
 import android.util.Log;
 import android.widget.Toast;
 
+import libcore.io.IoUtils;
+
 import java.io.BufferedInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
@@ -35,8 +41,6 @@
 import java.util.HashMap;
 import java.util.Map;
 
-import libcore.io.IoUtils;
-
 /**
  * The main class for installing certificates to the system keystore. It reacts
  * to the public {@link Credentials#INSTALL_ACTION} intent.
@@ -46,6 +50,7 @@
 
     private static final int REQUEST_INSTALL = 1;
     private static final int REQUEST_OPEN_DOCUMENT = 2;
+    private static final int REQUEST_CONFIRM_CREDENTIALS = 3;
 
     private static final String INSTALL_CERT_AS_USER_CLASS = ".InstallCertAsUser";
 
@@ -72,7 +77,8 @@
         setResult(RESULT_CANCELED);
 
         UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE);
-        if (userManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_CREDENTIALS)) {
+        if (userManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_CREDENTIALS)
+                || userManager.isGuestUser()) {
             finish();
             return;
         }
@@ -99,27 +105,56 @@
             // If bundle is empty of any actual credentials, ask user to open.
             // Otherwise, pass extras to CertInstaller to install those credentials.
             // Either way, we use KeyChain.EXTRA_NAME as the default name if available.
-            if (bundle == null
-                    || bundle.isEmpty()
-                    || (bundle.size() == 1
-                        && (bundle.containsKey(KeyChain.EXTRA_NAME)
-                            || bundle.containsKey(Credentials.EXTRA_INSTALL_AS_UID)))) {
-                final String[] mimeTypes = MIME_MAPPINGS.keySet().toArray(new String[0]);
-                final Intent openIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
-                openIntent.setType("*/*");
-                openIntent.putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes);
-                openIntent.putExtra(DocumentsContract.EXTRA_SHOW_ADVANCED, true);
-                startActivityForResult(openIntent, REQUEST_OPEN_DOCUMENT);
+            if (nullOrEmptyBundle(bundle) || bundleContainsNameOnly(bundle)
+                    || bundleContainsInstallAsUidOnly(bundle)
+                    || bundleContainsExtraCertificateUsageOnly(bundle)) {
+
+                // Confirm credentials if there's only a CA certificate
+                if (installingCaCertificate(bundle)) {
+                    confirmDeviceCredential();
+                } else {
+                    startOpenDocumentActivity();
+                }
             } else {
-                final Intent installIntent = new Intent(this, CertInstaller.class);
-                installIntent.putExtras(intent);
-                startActivityForResult(installIntent, REQUEST_INSTALL);
+                startInstallActivity(intent);
             }
         } else if (Intent.ACTION_VIEW.equals(action)) {
             startInstallActivity(intent.getType(), intent.getData());
         }
     }
 
+    private boolean nullOrEmptyBundle(Bundle bundle) {
+        return bundle == null || bundle.isEmpty();
+    }
+
+    private boolean bundleContainsNameOnly(Bundle bundle) {
+        return bundle.size() == 1 && bundle.containsKey(KeyChain.EXTRA_NAME);
+    }
+
+    private boolean bundleContainsInstallAsUidOnly(Bundle bundle) {
+        return bundle.size() == 1 && bundle.containsKey(Credentials.EXTRA_INSTALL_AS_UID);
+    }
+
+    private boolean bundleContainsExtraCertificateUsageOnly(Bundle bundle) {
+        return bundle.size() == 1 && bundle.containsKey(Credentials.EXTRA_CERTIFICATE_USAGE);
+    }
+
+    private boolean installingCaCertificate(Bundle bundle) {
+        return bundle != null && bundle.size() == 1 && Credentials.CERTIFICATE_USAGE_CA.equals(
+                bundle.getString(Credentials.EXTRA_CERTIFICATE_USAGE));
+    }
+
+    private void confirmDeviceCredential() {
+        KeyguardManager keyguardManager = getSystemService(KeyguardManager.class);
+        Intent intent = keyguardManager.createConfirmDeviceCredentialIntent(null,
+                null);
+        if (intent == null) { // No screenlock
+            startOpenDocumentActivity();
+        } else {
+            startActivityForResult(intent, REQUEST_CONFIRM_CREDENTIALS);
+        }
+    }
+
     // The maximum amount of data to read into memory before aborting.
     // Without a limit, a sufficiently-large file will run us out of memory.  A
     // typical certificate or WiFi config is under 10k, so 10MiB should be more
@@ -146,6 +181,33 @@
         return bytes.toByteArray();
     }
 
+    private void startInstallActivity(Intent intent) {
+        final Intent installIntent = new Intent(this, CertInstaller.class);
+        if (intent.getExtras() != null && intent.getExtras().getString(Intent.EXTRA_REFERRER)
+                != null) {
+            Log.v(TAG, String.format(
+                    "Removing referrer extra with value %s which was not meant to be included",
+                    intent.getBundleExtra(Intent.EXTRA_REFERRER)));
+            intent.removeExtra(Intent.EXTRA_REFERRER);
+        }
+        installIntent.putExtras(intent);
+
+        try {
+            // The referrer is passed as an extra because the launched-from package needs to be
+            // obtained here and not in the CertInstaller.
+            // It is also safe to add the referrer as an extra because the CertInstaller activity
+            // is not exported, which means it cannot be called from other apps.
+            IActivityTaskManager activityTaskManager = ActivityTaskManager.getService();
+            installIntent.putExtra(Intent.EXTRA_REFERRER,
+                    activityTaskManager.getLaunchedFromPackage(getActivityToken()));
+            startActivityForResult(installIntent, REQUEST_INSTALL);
+        } catch (RemoteException e) {
+            Log.v(TAG, "Could not talk to activity manager.", e);
+            Toast.makeText(this, R.string.cert_temp_error, Toast.LENGTH_LONG).show();
+            finish();
+        }
+    }
+
     private void startInstallActivity(String mimeType, Uri uri) {
         if (mimeType == null) {
             mimeType = getContentResolver().getType(uri);
@@ -165,8 +227,10 @@
                 in = getContentResolver().openInputStream(uri);
 
                 final byte[] raw = readWithLimit(in);
-                startInstallActivity(target, raw);
 
+                Intent intent = getIntent();
+                intent.putExtra(target, raw);
+                startInstallActivity(intent);
             } catch (IOException e) {
                 Log.e(TAG, "Failed to read certificate: " + e);
                 Toast.makeText(this, R.string.cert_read_error, Toast.LENGTH_LONG).show();
@@ -176,13 +240,6 @@
         }
     }
 
-    private void startInstallActivity(String target, byte[] value) {
-        Intent intent = new Intent(this, CertInstaller.class);
-        intent.putExtra(target, value);
-
-        startActivityForResult(intent, REQUEST_INSTALL);
-    }
-
     private void startWifiInstallActivity(String mimeType, Uri uri) {
         Intent intent = new Intent(this, WiFiInstaller.class);
         try (BufferedInputStream in =
@@ -198,19 +255,40 @@
         }
     }
 
+    private void startOpenDocumentActivity() {
+        final String[] mimeTypes = MIME_MAPPINGS.keySet().toArray(new String[0]);
+        final Intent openIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
+        openIntent.setType("*/*");
+        openIntent.putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes);
+        openIntent.putExtra(DocumentsContract.EXTRA_SHOW_ADVANCED, true);
+        startActivityForResult(openIntent, REQUEST_OPEN_DOCUMENT);
+    }
+
     @Override
     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
-        if (requestCode == REQUEST_OPEN_DOCUMENT) {
-            if (resultCode == RESULT_OK) {
-                startInstallActivity(null, data.getData());
-            } else {
+        switch (requestCode) {
+            case REQUEST_INSTALL:
+                setResult(resultCode);
                 finish();
-            }
-        } else if (requestCode == REQUEST_INSTALL) {
-            setResult(resultCode);
-            finish();
-        } else {
-            Log.w(TAG, "unknown request code: " + requestCode);
+                break;
+            case REQUEST_OPEN_DOCUMENT:
+                if (resultCode == RESULT_OK) {
+                    startInstallActivity(null, data.getData());
+                } else {
+                    finish();
+                }
+                break;
+            case REQUEST_CONFIRM_CREDENTIALS:
+                if (resultCode == RESULT_OK) {
+                    startOpenDocumentActivity();
+                    return;
+                }
+                // Failed to confirm credentials, do nothing.
+                finish();
+                break;
+            default:
+                Log.w(TAG, "unknown request code: " + requestCode);
+                break;
         }
     }
 }
diff --git a/src/com/android/certinstaller/CredentialHelper.java b/src/com/android/certinstaller/CredentialHelper.java
index 4ec2e7e..a1e9314 100644
--- a/src/com/android/certinstaller/CredentialHelper.java
+++ b/src/com/android/certinstaller/CredentialHelper.java
@@ -16,20 +16,24 @@
 
 package com.android.certinstaller;
 
+import static android.security.KeyStore.UID_SELF;
+
 import android.app.KeyguardManager;
 import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.security.Credentials;
-import android.security.KeyChain;
 import android.security.IKeyChainService;
+import android.security.KeyChain;
 import android.text.Html;
 import android.text.TextUtils;
 import android.util.Log;
+
 import com.android.org.bouncycastle.asn1.ASN1InputStream;
 import com.android.org.bouncycastle.asn1.ASN1Sequence;
 import com.android.org.bouncycastle.asn1.DEROctetString;
@@ -39,9 +43,9 @@
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.security.KeyFactory;
+import java.security.KeyStore;
 import java.security.KeyStore.PasswordProtection;
 import java.security.KeyStore.PrivateKeyEntry;
-import java.security.KeyStore;
 import java.security.NoSuchAlgorithmException;
 import java.security.PrivateKey;
 import java.security.cert.Certificate;
@@ -64,6 +68,7 @@
     private static final String DATA_KEY = "data";
     private static final String CERTS_KEY = "crts";
     private static final String USER_KEY_ALGORITHM = "user_key_algorithm";
+    private static final String SETTINGS_PACKAGE = "com.android.settings";
 
     private static final String TAG = "CredentialHelper";
 
@@ -71,6 +76,8 @@
     private HashMap<String, byte[]> mBundle = new HashMap<String, byte[]>();
 
     private String mName = "";
+    private String mCertUsageSelected = "";
+    private String mReferrer = "";
     private int mUid = -1;
     private PrivateKey mUserKey;
     private X509Certificate mUserCert;
@@ -91,9 +98,21 @@
             mName = name;
         }
 
-        mUid = bundle.getInt(Credentials.EXTRA_INSTALL_AS_UID, -1);
+        String certUsageSelected = bundle.getString(Credentials.EXTRA_CERTIFICATE_USAGE);
+        bundle.remove(Credentials.EXTRA_CERTIFICATE_USAGE);
+        if (certUsageSelected != null) {
+            setCertUsageSelectedAndUid(certUsageSelected);
+        } else {
+            mUid = bundle.getInt(Credentials.EXTRA_INSTALL_AS_UID, -1);
+        }
         bundle.remove(Credentials.EXTRA_INSTALL_AS_UID);
 
+        String referrer = bundle.getString(Intent.EXTRA_REFERRER);
+        bundle.remove(Intent.EXTRA_REFERRER);
+        if (referrer != null) {
+            mReferrer = referrer;
+        }
+
         Log.d(TAG, "# extras: " + bundle.size());
         for (String key : bundle.keySet()) {
             byte[] bytes = bundle.getByteArray(key);
@@ -196,6 +215,14 @@
         return mBundle.containsKey(Credentials.EXTRA_PRIVATE_KEY);
     }
 
+    int getUidFromCertificateUsage(String certUsage) {
+        if (Credentials.CERTIFICATE_USAGE_WIFI.equals(certUsage)) {
+            return Process.WIFI_UID;
+        } else {
+            return UID_SELF;
+        }
+    }
+
     boolean hasUserCertificate() {
         return (mUserCert != null);
     }
@@ -262,16 +289,17 @@
         return mName;
     }
 
-    void setInstallAsUid(int uid) {
-        mUid = uid;
+    void setCertUsageSelectedAndUid(String certUsageSelected) {
+        mCertUsageSelected = certUsageSelected;
+        mUid = getUidFromCertificateUsage(certUsageSelected);
     }
 
-    boolean isInstallAsUidSet() {
-        return mUid != -1;
+    String getCertUsageSelected() {
+        return mCertUsageSelected;
     }
 
-    int getInstallAsUid() {
-        return mUid;
+    boolean calledBySettings() {
+        return mReferrer != null && mReferrer.equals(SETTINGS_PACKAGE);
     }
 
     Intent createSystemInstallIntent(final Context context) {
@@ -281,22 +309,17 @@
         intent.setComponent(ComponentName.unflattenFromString(
                 context.getString(R.string.config_system_install_component)));
         intent.putExtra(Credentials.EXTRA_INSTALL_AS_UID, mUid);
+        intent.putExtra(Credentials.EXTRA_USER_KEY_ALIAS, mName);
         try {
             if (mUserKey != null) {
-                intent.putExtra(Credentials.EXTRA_USER_PRIVATE_KEY_NAME,
-                        Credentials.USER_PRIVATE_KEY + mName);
                 intent.putExtra(Credentials.EXTRA_USER_PRIVATE_KEY_DATA,
                         mUserKey.getEncoded());
             }
             if (mUserCert != null) {
-                intent.putExtra(Credentials.EXTRA_USER_CERTIFICATE_NAME,
-                        Credentials.USER_CERTIFICATE + mName);
                 intent.putExtra(Credentials.EXTRA_USER_CERTIFICATE_DATA,
                         Credentials.convertToPem(mUserCert));
             }
             if (!mCaCerts.isEmpty()) {
-                intent.putExtra(Credentials.EXTRA_CA_CERTIFICATES_NAME,
-                        Credentials.CA_CERTIFICATE + mName);
                 X509Certificate[] caCerts
                         = mCaCerts.toArray(new X509Certificate[mCaCerts.size()]);
                 intent.putExtra(Credentials.EXTRA_CA_CERTIFICATES_DATA,
@@ -340,12 +363,8 @@
     }
 
     private void maybeApproveCaCert(Context context, String alias) {
-        // Some CTS verifier test asks testers to reset auto approved CA cert by removing
-        // lock sreen, but it's not possible if we don't have Android lock screen. (e.g.
-        // Android is running in the container).  In this case, disable auto cert approval.
         final KeyguardManager keyguardManager = context.getSystemService(KeyguardManager.class);
-        if (keyguardManager.isDeviceSecure(UserHandle.myUserId())
-                && context.getResources().getBoolean(R.bool.config_auto_cert_approval)) {
+        if (keyguardManager.isDeviceSecure(UserHandle.myUserId())) {
             // Since the cert is installed by real user, the cert is approved by the user
             final DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
             dpm.approveCaCert(alias, UserHandle.myUserId(), true);
@@ -432,14 +451,14 @@
     }
 
     /**
-     * Returns whether this credential contains CA certificates to be used as trust anchors
+     * Returns true if this credential contains _only_ CA certificates to be used as trust anchors
      * for VPN and apps.
      */
-    public boolean includesVpnAndAppsTrustAnchors() {
+    public boolean hasOnlyVpnAndAppsTrustAnchors() {
         if (!hasCaCerts()) {
             return false;
         }
-        if (getInstallAsUid() != android.security.KeyStore.UID_SELF) {
+        if (mUid != UID_SELF) {
             // VPN and Apps trust anchors can only be installed under UID_SELF
             return false;
         }
@@ -452,4 +471,8 @@
             return true;
         }
     }
+
+    public String getReferrer() {
+        return mReferrer;
+    }
 }
diff --git a/src/com/android/certinstaller/WiFiInstaller.java b/src/com/android/certinstaller/WiFiInstaller.java
index 90b8eb7..41827f6 100644
--- a/src/com/android/certinstaller/WiFiInstaller.java
+++ b/src/com/android/certinstaller/WiFiInstaller.java
@@ -93,6 +93,13 @@
                         public void run() {
                             boolean success = true;
                             try {
+                                mWifiManager.removePasspointConfiguration(
+                                        mPasspointConfig.getHomeSp().getFqdn());
+                            } catch (IllegalArgumentException e) {
+                                // Do nothing. This is expected if a profile with this FQDN does not
+                                // exist.
+                            }
+                            try {
                                 mWifiManager.addOrUpdatePasspointConfiguration(mPasspointConfig);
                             } catch (RuntimeException rte) {
                                 Log.w(TAG, "Caught exception while installing wifi config: " +