Merge "Implement Wi-Fi DPP flow"
diff --git a/src/com/android/settings/wifi/dpp/WifiDppAddDeviceFragment.java b/src/com/android/settings/wifi/dpp/WifiDppAddDeviceFragment.java
index 12814f8..8fa58f3 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppAddDeviceFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppAddDeviceFragment.java
@@ -18,7 +18,10 @@
 
 import android.app.ActionBar;
 import android.app.Activity;
+import android.content.Context;
+import android.net.wifi.WifiManager;
 import android.os.Bundle;
+import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -35,11 +38,42 @@
  * to the Wi-Fi network.
  */
 public class WifiDppAddDeviceFragment extends WifiDppQrCodeBaseFragment {
+    private static final String TAG = "WifiDppAddDeviceFragment";
+
     private ImageView mWifiApPictureView;
     private TextView mChooseDifferentNetwork;
     private Button mButtonLeft;
     private Button mButtonRight;
 
+    private class DppStatusCallback extends android.net.wifi.DppStatusCallback {
+        @Override
+        public void onEnrolleeSuccess(int newNetworkId) {
+            // Do nothing
+        }
+
+        @Override
+        public void onConfiguratorSuccess(int code) {
+            // Update success UI.
+            mTitle.setText(R.string.wifi_dpp_wifi_shared_with_device);
+            mSummary.setVisibility(View.INVISIBLE);
+            mButtonLeft.setText(R.string.wifi_dpp_add_another_device);
+            mButtonLeft.setOnClickListener(v -> getFragmentManager().popBackStack());
+            mButtonRight.setText(R.string.done);
+            mButtonRight.setOnClickListener(v -> getActivity().finish());
+        }
+
+        @Override
+        public void onFailure(int code) {
+            //TODO(b/122429170): Show DPP configuration error state UI
+            Log.d(TAG, "DppStatusCallback.onFailure " + code);
+        }
+
+        @Override
+        public void onProgress(int code) {
+            // Do nothing
+        }
+    }
+
     @Override
     public int getMetricsCategory() {
         return MetricsProto.MetricsEvent.SETTINGS_WIFI_DPP_CONFIGURATOR;
@@ -86,6 +120,11 @@
     }
 
     private void startWifiDppInitiator() {
-        //TODO(b/122331217): starts Wi-Fi DPP initiator handshake here
+        final String enrolleeUri = ((WifiDppConfiguratorActivity) getActivity()).getDppUri();
+        final int networkId =
+                ((WifiDppConfiguratorActivity) getActivity()).getWifiNetworkConfig().getNetworkId();
+        final WifiManager wifiManager = getContext().getSystemService(WifiManager.class);
+        wifiManager.startDppAsConfiguratorInitiator(enrolleeUri, networkId,
+                WifiManager.DPP_NETWORK_ROLE_STA, /* handler */ null, new DppStatusCallback());
     }
 }
diff --git a/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java b/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java
index 9c65d10..b08546c 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java
@@ -66,11 +66,8 @@
     /** The Wi-Fi network which will be configured */
     private WifiNetworkConfig mWifiNetworkConfig;
 
-    /** The public key from Wi-Fi DPP QR code */
-    private String mPublicKey;
-
-    /** The information from Wi-Fi DPP QR code */
-    private String mInformation;
+    /** The uri from Wi-Fi DPP QR code */
+    private String mDppUri;
 
     /** The Wi-Fi DPP QR code from intent ACTION_PROCESS_WIFI_DPP_QR_CODE */
     private WifiQrCode mWifiDppQrCode;
@@ -228,12 +225,8 @@
         return mWifiNetworkConfig;
     }
 
-    public String getPublicKey() {
-        return mPublicKey;
-    }
-
-    public String getInformation() {
-        return mInformation;
+    public String getDppUri() {
+        return mDppUri;
     }
 
     public WifiQrCode getWifiDppQrCode() {
@@ -270,17 +263,15 @@
     }
 
     @Override
-    public void onScanWifiDppSuccess(String publicKey, String information) {
-        mPublicKey = publicKey;
-        mInformation = information;
+    public void onScanWifiDppSuccess(String uri) {
+        mDppUri = uri;
 
         showAddDeviceFragment(/* addToBackStack */ true);
     }
 
     @Override
     public void onScanZxingWifiFormatSuccess(WifiNetworkConfig wifiNetworkConfig) {
-        mPublicKey = null;
-        mInformation = null;
+        mDppUri = null;
         mWifiNetworkConfig = new WifiNetworkConfig(wifiNetworkConfig);
 
         showAddDeviceFragment(/* addToBackStack */ true);
diff --git a/src/com/android/settings/wifi/dpp/WifiDppEnrolleeActivity.java b/src/com/android/settings/wifi/dpp/WifiDppEnrolleeActivity.java
index 584a819..8c0e1f0 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppEnrolleeActivity.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppEnrolleeActivity.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.wifi.dpp;
 
+import android.content.Context;
+import android.net.wifi.WifiConfiguration;
 import android.provider.Settings;
 import android.app.ActionBar;
 import android.app.Activity;
@@ -32,6 +34,8 @@
 import com.android.settings.core.InstrumentedActivity;
 import com.android.settings.R;
 
+import java.util.List;
+
 /**
  * To provision "this" device with specified Wi-Fi network.
  *
@@ -49,6 +53,39 @@
 
     private FragmentManager mFragmentManager;
 
+    private class DppStatusCallback extends android.net.wifi.DppStatusCallback {
+        @Override
+        public void onEnrolleeSuccess(int newNetworkId) {
+            // Connect to the new network.
+            final WifiManager wifiManager = getSystemService(WifiManager.class);
+            final List<WifiConfiguration> wifiConfigs = wifiManager.getPrivilegedConfiguredNetworks();
+            for (WifiConfiguration wifiConfig : wifiConfigs) {
+                if (wifiConfig.networkId == newNetworkId) {
+                    wifiManager.connect(wifiConfig, WifiDppEnrolleeActivity.this);
+                    return;
+                }
+            }
+            Log.e(TAG, "Invalid networkId " + newNetworkId);
+            WifiDppEnrolleeActivity.this.onFailure(WifiManager.ERROR_AUTHENTICATING);
+        }
+
+        @Override
+        public void onConfiguratorSuccess(int code) {
+            // Do nothing
+        }
+
+        @Override
+        public void onFailure(int code) {
+            //TODO(b/122429170): Show DPP enrollee error state UI
+            Log.d(TAG, "DppStatusCallback.onFailure " + code);
+        }
+
+        @Override
+        public void onProgress(int code) {
+            // Do nothing
+        }
+    }
+
     @Override
     public int getMetricsCategory() {
         return MetricsProto.MetricsEvent.SETTINGS_WIFI_DPP_ENROLLEE;
@@ -108,8 +145,9 @@
     }
 
     @Override
-    public void onScanWifiDppSuccess(String publicKey, String information) {
-        // TODO(b/1023597): starts DPP enrollee handshake here
+    public void onScanWifiDppSuccess(String uri) {
+        final WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
+        wifiManager.startDppAsEnrolleeInitiator(uri, /* handler */ null, new DppStatusCallback());
     }
 
     @Override
diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
index c7c1461..2f59e18 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
@@ -62,9 +62,8 @@
     private static final long SHOW_ERROR_MESSAGE_INTERVAL = 2000;
     private static final long SHOW_SUCCESS_SQUARE_INTERVAL = 1000;
 
-    // Keys for Bundle usage
-    private static final String KEY_PUBLIC_KEY = "key_public_key";
-    private static final String KEY_INFORMATION = "key_information";
+    // Key for Bundle usage
+    private static final String KEY_PUBLIC_URI = "key_public_uri";
 
     private QrCamera mCamera;
     private TextureView mTextureView;
@@ -91,7 +90,7 @@
 
     // Container Activity must implement this interface
     public interface OnScanWifiDppSuccessListener {
-        public void onScanWifiDppSuccess(String publicKey, String information);
+        public void onScanWifiDppSuccess(String uri);
     }
     OnScanWifiDppSuccessListener mScanWifiDppSuccessListener;
 
@@ -269,7 +268,7 @@
     public void handleSuccessfulResult(String qrCode) {
         switch (mWifiQrCode.getScheme()) {
             case WifiQrCode.SCHEME_DPP:
-                handleWifiDpp(mWifiQrCode.getPublicKey(), mWifiQrCode.getInformation());
+                handleWifiDpp(qrCode);
                 break;
 
             case WifiQrCode.SCHEME_ZXING_WIFI_NETWORK_CONFIG:
@@ -281,13 +280,12 @@
         }
     }
 
-    private void handleWifiDpp(String publicKey, String information) {
+    private void handleWifiDpp(String uri) {
         destroyCamera();
         mDecorateView.setFocused(true);
 
         final Bundle bundle = new Bundle();
-        bundle.putString(KEY_PUBLIC_KEY, publicKey);
-        bundle.putString(KEY_INFORMATION, information);
+        bundle.putString(KEY_PUBLIC_URI, uri);
 
         Message message = mHandler.obtainMessage(MESSAGE_SCAN_WIFI_DPP_SUCCESS);
         message.setData(bundle);
@@ -352,10 +350,9 @@
                         return;
                     }
                     final Bundle bundle = msg.getData();
-                    final String publicKey = bundle.getString(KEY_PUBLIC_KEY);
-                    final String information = bundle.getString(KEY_INFORMATION);
+                    final String uri = bundle.getString(KEY_PUBLIC_URI);
 
-                    mScanWifiDppSuccessListener.onScanWifiDppSuccess(publicKey, information);
+                    mScanWifiDppSuccessListener.onScanWifiDppSuccess(uri);
                     break;
 
                 case MESSAGE_SCAN_ZXING_WIFI_FORMAT_SUCCESS:
diff --git a/src/com/android/settings/wifi/dpp/WifiDppUtils.java b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
index 3a40e25..0205ec1 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppUtils.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
@@ -64,6 +64,9 @@
     /** The data corresponding to {@code WifiConfiguration} hiddenSSID */
     public static final String EXTRA_WIFI_HIDDEN_SSID = "hiddenSsid";
 
+    /** The data corresponding to {@code WifiConfiguration} networkId */
+    public static final String EXTRA_WIFI_NETWORK_ID = "networkId";
+
     /** @see WifiQrCode */
     public static final String EXTRA_QR_CODE = "qrCode";
 
@@ -164,6 +167,11 @@
         if (!TextUtils.isEmpty(preSharedKey)) {
             intent.putExtra(EXTRA_WIFI_PRE_SHARED_KEY, preSharedKey);
         }
+        if (wifiConfig.networkId == WifiConfiguration.INVALID_NETWORK_ID) {
+            throw new IllegalArgumentException("Invalid network ID");
+        } else {
+            intent.putExtra(EXTRA_WIFI_NETWORK_ID, wifiConfig.networkId);
+        }
 
         return intent;
     }
diff --git a/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java b/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java
index c9bfbd6..a9e88a9 100644
--- a/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java
+++ b/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java
@@ -46,13 +46,15 @@
     private String mSsid;
     private String mPreSharedKey;
     private boolean mHiddenSsid;
+    private int mNetworkId;
 
-    private WifiNetworkConfig(String security, String ssid, String preSharedKey,
-            boolean hiddenSsid) {
+    private WifiNetworkConfig(String security, String ssid, String preSharedKey, boolean hiddenSsid,
+            int networkId) {
         mSecurity = security;
         mSsid = ssid;
         mPreSharedKey = preSharedKey;
         mHiddenSsid = hiddenSsid;
+        mNetworkId = networkId;
     }
 
     public WifiNetworkConfig(WifiNetworkConfig config) {
@@ -60,6 +62,7 @@
         mSsid = config.mSsid;
         mPreSharedKey = config.mPreSharedKey;
         mHiddenSsid = config.mHiddenSsid;
+        mNetworkId = config.mNetworkId;
     }
 
     /**
@@ -82,17 +85,19 @@
         String ssid = intent.getStringExtra(WifiDppUtils.EXTRA_WIFI_SSID);
         String preSharedKey = intent.getStringExtra(WifiDppUtils.EXTRA_WIFI_PRE_SHARED_KEY);
         boolean hiddenSsid = intent.getBooleanExtra(WifiDppUtils.EXTRA_WIFI_HIDDEN_SSID, false);
+        int networkId = intent.getIntExtra(WifiDppUtils.EXTRA_WIFI_NETWORK_ID,
+                WifiConfiguration.INVALID_NETWORK_ID);
 
-        return getValidConfigOrNull(security, ssid, preSharedKey, hiddenSsid);
+        return getValidConfigOrNull(security, ssid, preSharedKey, hiddenSsid, networkId);
     }
 
     public static WifiNetworkConfig getValidConfigOrNull(String security, String ssid,
-            String preSharedKey, boolean hiddenSsid) {
+            String preSharedKey, boolean hiddenSsid, int networkId) {
         if (!isValidConfig(security, ssid, preSharedKey, hiddenSsid)) {
             return null;
         }
 
-        return new WifiNetworkConfig(security, ssid, preSharedKey, hiddenSsid);
+        return new WifiNetworkConfig(security, ssid, preSharedKey, hiddenSsid, networkId);
     }
 
     public static boolean isValidConfig(WifiNetworkConfig config) {
@@ -184,6 +189,11 @@
         return mHiddenSsid;
     }
 
+    @Keep
+    public int getNetworkId() {
+        return mNetworkId;
+    }
+
     public void connect(Context context, WifiManager.ActionListener listener) {
         WifiConfiguration wifiConfiguration = getWifiConfigurationOrNull();
         if (wifiConfiguration == null) {
@@ -208,6 +218,7 @@
         final WifiConfiguration wifiConfiguration = new WifiConfiguration();
         wifiConfiguration.SSID = addQuotationIfNeeded(mSsid);
         wifiConfiguration.hiddenSSID = mHiddenSsid;
+        wifiConfiguration.networkId = mNetworkId;
 
         if (TextUtils.isEmpty(mSecurity) || SECURITY_NO_PASSWORD.equals(mSecurity)) {
             wifiConfiguration.allowedKeyManagement.set(KeyMgmt.NONE);
diff --git a/src/com/android/settings/wifi/dpp/WifiQrCode.java b/src/com/android/settings/wifi/dpp/WifiQrCode.java
index a8562bb..8eae3a4 100644
--- a/src/com/android/settings/wifi/dpp/WifiQrCode.java
+++ b/src/com/android/settings/wifi/dpp/WifiQrCode.java
@@ -17,6 +17,7 @@
 package com.android.settings.wifi.dpp;
 
 import android.content.Intent;
+import android.net.wifi.WifiConfiguration;
 import android.text.TextUtils;
 
 import androidx.annotation.Keep;
@@ -135,7 +136,7 @@
         password = removeBackSlash(password);
 
         mWifiNetworkConfig = WifiNetworkConfig.getValidConfigOrNull(security, ssid, password,
-                hiddenSsid);
+                hiddenSsid, WifiConfiguration.INVALID_NETWORK_ID);
 
         if (mWifiNetworkConfig == null) {
             throw new IllegalArgumentException("Invalid format");