Merge "Add lost prefController to WifiTetherSettings"
diff --git a/color-check-baseline.xml b/color-check-baseline.xml
index 787c559..fd0fc6c 100644
--- a/color-check-baseline.xml
+++ b/color-check-baseline.xml
@@ -2,18 +2,6 @@
 <issues format="4">
 
     <issue
-        id="LintError"
-        severity="Error"
-        message="No `.class` files were found in project &quot;.&quot;, so none of the classfile based checks could be run. Does the project need to be built first?"
-        category="Lint"
-        priority="10"
-        summary="Lint Failure"
-        explanation="This issue type represents a problem running lint itself. Examples include failure to find bytecode for source files (which means certain detectors could not be run), parsing errors in lint configuration files, etc.&#xA;These errors are not errors in your own code, but they are shown to make it clear that some checks were not completed.">
-        <location
-            file="."/>
-    </issue>
-
-    <issue
         id="HardCodedColor"
         severity="Error"
         message="Avoid using hardcoded color"
@@ -1301,6 +1289,54 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+        errorLine1="    &lt;color name=&quot;qr_corner_line_color&quot;>#ffdadce0&lt;/color>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/values/colors.xml"
+            line="133"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="HardCodedColor"
+        severity="Error"
+        message="Avoid using hardcoded color"
+        category="Correctness"
+        priority="4"
+        summary="Using hardcoded color"
+        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+        errorLine1="    &lt;color name=&quot;qr_focused_corner_line_color&quot;>#ff1a73e8&lt;/color>"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/values/colors.xml"
+            line="134"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="HardCodedColor"
+        severity="Error"
+        message="Avoid using hardcoded color"
+        category="Correctness"
+        priority="4"
+        summary="Using hardcoded color"
+        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+        errorLine1="    &lt;color name=&quot;qr_background_color&quot;>#b3ffffff&lt;/color> &lt;!-- 70% white transparency -->"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/values/colors.xml"
+            line="135"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="HardCodedColor"
+        severity="Error"
+        message="Avoid using hardcoded color"
+        category="Correctness"
+        priority="4"
+        summary="Using hardcoded color"
+        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
         errorLine1="                android:background=&quot;@color/lock_pattern_background&quot; />"
         errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
@@ -2441,7 +2477,7 @@
         errorLine2="                                   ~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/strings.xml"
-            line="5805"
+            line="5883"
             column="36"/>
     </issue>
 
@@ -2473,7 +2509,7 @@
         errorLine2="                                           ^">
         <location
             file="res/values/styles.xml"
-            line="425"
+            line="415"
             column="44"/>
     </issue>
 
@@ -2489,7 +2525,7 @@
         errorLine2="                                           ^">
         <location
             file="res/values/styles.xml"
-            line="431"
+            line="421"
             column="44"/>
     </issue>
 
@@ -2505,7 +2541,7 @@
         errorLine2="                                           ^">
         <location
             file="res/values/styles.xml"
-            line="432"
+            line="422"
             column="44"/>
     </issue>
 
@@ -2521,23 +2557,7 @@
         errorLine2="                                 ^">
         <location
             file="res/values/styles.xml"
-            line="467"
-            column="34"/>
-    </issue>
-
-    <issue
-        id="HardCodedColor"
-        severity="Error"
-        message="Avoid using hardcoded color"
-        category="Correctness"
-        priority="4"
-        summary="Using hardcoded color"
-        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="        &lt;item name=&quot;strokeColor&quot;>@color/homepage_card_stroke_color&lt;/item>"
-        errorLine2="                                 ^">
-        <location
-            file="res/values/styles.xml"
-            line="474"
+            line="457"
             column="34"/>
     </issue>
 
@@ -2553,7 +2573,7 @@
         errorLine2="                                      ^">
         <location
             file="res/values/themes.xml"
-            line="54"
+            line="57"
             column="39"/>
     </issue>
 
@@ -2569,7 +2589,7 @@
         errorLine2="                                       ^">
         <location
             file="res/values/themes.xml"
-            line="55"
+            line="58"
             column="40"/>
     </issue>
 
@@ -2585,7 +2605,7 @@
         errorLine2="                                     ^">
         <location
             file="res/values/themes.xml"
-            line="56"
+            line="59"
             column="38"/>
     </issue>
 
@@ -2601,7 +2621,7 @@
         errorLine2="                                              ^">
         <location
             file="res/values/themes.xml"
-            line="90"
+            line="97"
             column="47"/>
     </issue>
 
@@ -2617,7 +2637,7 @@
         errorLine2="                                              ^">
         <location
             file="res/values/themes.xml"
-            line="90"
+            line="97"
             column="47"/>
     </issue>
 
@@ -2633,7 +2653,7 @@
         errorLine2="                                       ^">
         <location
             file="res/values/themes.xml"
-            line="96"
+            line="103"
             column="40"/>
     </issue>
 
@@ -2649,7 +2669,7 @@
         errorLine2="                                       ^">
         <location
             file="res/values/themes.xml"
-            line="96"
+            line="103"
             column="40"/>
     </issue>
 
@@ -2665,7 +2685,7 @@
         errorLine2="                                            ^">
         <location
             file="res/values/themes.xml"
-            line="159"
+            line="166"
             column="45"/>
     </issue>
 
@@ -2681,7 +2701,7 @@
         errorLine2="                                                ^">
         <location
             file="res/values/themes.xml"
-            line="160"
+            line="167"
             column="49"/>
     </issue>
 
@@ -2697,7 +2717,7 @@
         errorLine2="                                            ^">
         <location
             file="res/values/themes.xml"
-            line="168"
+            line="175"
             column="45"/>
     </issue>
 
@@ -2713,7 +2733,7 @@
         errorLine2="                                                ^">
         <location
             file="res/values/themes.xml"
-            line="169"
+            line="176"
             column="49"/>
     </issue>
 
@@ -2729,7 +2749,7 @@
         errorLine2="                                      ^">
         <location
             file="res/values/themes.xml"
-            line="185"
+            line="192"
             column="39"/>
     </issue>
 
@@ -2745,7 +2765,7 @@
         errorLine2="                                       ^">
         <location
             file="res/values/themes.xml"
-            line="186"
+            line="193"
             column="40"/>
     </issue>
 
@@ -2761,7 +2781,7 @@
         errorLine2="                                     ^">
         <location
             file="res/values/themes.xml"
-            line="187"
+            line="194"
             column="38"/>
     </issue>
 
diff --git a/res/layout-sw360dp/homepage_condition_full_tile.xml b/res/layout-sw360dp/homepage_condition_full_tile.xml
new file mode 100644
index 0000000..4a8ad0a
--- /dev/null
+++ b/res/layout-sw360dp/homepage_condition_full_tile.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2018 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.
+-->
+
+<com.google.android.material.card.MaterialCardView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    style="@style/ContextualCardStyle">
+
+    <LinearLayout
+        android:id="@+id/content"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingStart="@dimen/homepage_card_padding_start"
+        android:paddingEnd="@dimen/homepage_card_padding_end"
+        android:paddingTop="@dimen/homepage_condition_full_card_padding_top"
+        android:paddingBottom="@dimen/homepage_condition_full_card_padding_bottom"
+        android:orientation="horizontal"
+        android:gravity="center_vertical">
+
+        <ImageView
+            android:id="@android:id/icon"
+            android:layout_width="@dimen/homepage_card_icon_size"
+            android:layout_height="@dimen/homepage_card_icon_size"
+            android:tint="?android:attr/colorAccent"/>
+
+        <LinearLayout
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:paddingStart="@dimen/homepage_condition_full_card_padding_start"
+            android:paddingEnd="@dimen/homepage_condition_full_card_padding_end"
+            android:orientation="vertical">
+
+            <TextView
+                android:id="@android:id/title"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginBottom="@dimen/homepage_condition_card_title_margin_bottom"
+                android:textAppearance="@style/TextAppearance.ConditionCardTitle"/>
+
+            <TextView
+                android:id="@android:id/summary"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textAppearance="@style/TextAppearance.ConditionCardSummary"/>
+
+        </LinearLayout>
+
+        <include layout="@layout/vertical_divider"/>
+
+        <Button
+            android:id="@+id/first_action"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            style="@style/ConditionFullCardBorderlessButton"/>
+
+    </LinearLayout>
+
+</com.google.android.material.card.MaterialCardView>
diff --git a/res/layout/homepage_condition_full_tile.xml b/res/layout/homepage_condition_full_tile.xml
index 4b12625..2de1464 100644
--- a/res/layout/homepage_condition_full_tile.xml
+++ b/res/layout/homepage_condition_full_tile.xml
@@ -25,49 +25,50 @@
         android:id="@+id/content"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:paddingStart="@dimen/homepage_card_padding_start"
-        android:paddingEnd="@dimen/homepage_card_padding_end"
-        android:paddingTop="@dimen/homepage_condition_full_card_padding_top"
-        android:paddingBottom="@dimen/homepage_condition_full_card_padding_bottom"
-        android:orientation="horizontal"
-        android:gravity="center_vertical">
-
-        <ImageView
-            android:id="@android:id/icon"
-            android:layout_width="@dimen/homepage_card_icon_size"
-            android:layout_height="@dimen/homepage_card_icon_size"
-            android:tint="?android:attr/colorAccent"/>
+        android:paddingTop="@dimen/homepage_condition_half_card_padding_top"
+        android:orientation="vertical">
 
         <LinearLayout
-            android:layout_width="0dp"
+            android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_weight="1"
-            android:paddingStart="@dimen/homepage_condition_full_card_padding_start"
-            android:paddingEnd="@dimen/homepage_condition_full_card_padding_end"
+            android:paddingStart="@dimen/homepage_card_padding_start"
+            android:paddingEnd="@dimen/homepage_card_padding_end"
             android:orientation="vertical">
 
+            <ImageView
+                android:id="@android:id/icon"
+                android:layout_width="@dimen/homepage_card_icon_size"
+                android:layout_height="@dimen/homepage_card_icon_size"
+                android:tint="?android:attr/colorAccent"/>
+
             <TextView
                 android:id="@android:id/title"
-                android:layout_width="wrap_content"
+                android:layout_width="match_parent"
                 android:layout_height="wrap_content"
+                android:maxLines="1"
+                android:ellipsize="end"
+                android:layout_marginTop="@dimen/homepage_condition_half_card_title_margin_top"
                 android:layout_marginBottom="@dimen/homepage_condition_card_title_margin_bottom"
-                style="@style/TextAppearance.ConditionCardTitle"/>
+                android:textAppearance="@style/TextAppearance.ConditionCardTitle"/>
 
             <TextView
                 android:id="@android:id/summary"
-                android:layout_width="wrap_content"
+                android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                style="@style/TextAppearance.ConditionCardSummary"/>
+                android:maxLines="1"
+                android:ellipsize="end"
+                android:layout_marginBottom="@dimen/homepage_condition_half_card_summary_margin_bottom"
+                android:textAppearance="@style/TextAppearance.ConditionCardSummary"/>
+
+            <include layout="@layout/horizontal_divider"/>
 
         </LinearLayout>
-
-        <include layout="@layout/vertical_divider"/>
-
         <Button
             android:id="@+id/first_action"
-            android:layout_width="wrap_content"
+            android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            style="@style/ConditionFullCardBorderlessButton"/>
+            android:scrollbars="none"
+            style="@style/ConditionHalfCardBorderlessButton"/>
 
     </LinearLayout>
 
diff --git a/res/layout/homepage_condition_half_tile.xml b/res/layout/homepage_condition_half_tile.xml
index 895183f..8f5af02 100644
--- a/res/layout/homepage_condition_half_tile.xml
+++ b/res/layout/homepage_condition_half_tile.xml
@@ -18,7 +18,7 @@
 <com.google.android.material.card.MaterialCardView
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="@dimen/homepage_condition_half_card_height"
+    android:layout_height="wrap_content"
     style="@style/ContextualCardStyle">
 
     <LinearLayout
@@ -49,7 +49,7 @@
                 android:ellipsize="end"
                 android:layout_marginTop="@dimen/homepage_condition_half_card_title_margin_top"
                 android:layout_marginBottom="@dimen/homepage_condition_card_title_margin_bottom"
-                style="@style/TextAppearance.ConditionCardTitle"/>
+                android:textAppearance="@style/TextAppearance.ConditionCardTitle"/>
 
             <TextView
                 android:id="@android:id/summary"
@@ -58,7 +58,7 @@
                 android:maxLines="1"
                 android:ellipsize="end"
                 android:layout_marginBottom="@dimen/homepage_condition_half_card_summary_margin_bottom"
-                style="@style/TextAppearance.ConditionCardSummary"/>
+                android:textAppearance="@style/TextAppearance.ConditionCardSummary"/>
 
             <include layout="@layout/horizontal_divider"/>
 
diff --git a/res/layout/wifi_dpp_fragment_header.xml b/res/layout/wifi_dpp_fragment_header.xml
index 266a3e8..20bcd7d 100644
--- a/res/layout/wifi_dpp_fragment_header.xml
+++ b/res/layout/wifi_dpp_fragment_header.xml
@@ -27,13 +27,13 @@
     android:paddingEnd="16dp">
 
     <ImageView
-        android:id="@+id/header_icon"
+        android:id="@android:id/icon"
         android:layout_width="48dp"
         android:layout_height="48dp"
         android:scaleType="fitCenter"/>
 
     <TextView
-        android:id="@+id/title"
+        android:id="@android:id/title"
         style="@style/TextAppearance.EntityHeaderTitle"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
@@ -44,7 +44,7 @@
         android:paddingEnd="32dp"/>
 
     <TextView
-        android:id="@+id/description"
+        android:id="@android:id/summary"
         style="@style/TextAppearance.EntityHeaderSummary"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
diff --git a/res/layout/wifi_dpp_qrcode_generator_fragment.xml b/res/layout/wifi_dpp_qrcode_generator_fragment.xml
index 789b3a3..c7c258b 100644
--- a/res/layout/wifi_dpp_qrcode_generator_fragment.xml
+++ b/res/layout/wifi_dpp_qrcode_generator_fragment.xml
@@ -25,9 +25,10 @@
     <include layout="@layout/wifi_dpp_fragment_header"/>
 
     <ImageView
-        android:id="@+id/barcode_view"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
+        android:id="@+id/qrcode_view"
+        android:layout_width="@dimen/qrcode_size"
+        android:layout_height="@dimen/qrcode_size"
+        android:src="@android:color/transparent"
         android:layout_gravity="center"/>
 
 </LinearLayout>
diff --git a/res/layout/wifi_dpp_qrcode_scanner_fragment.xml b/res/layout/wifi_dpp_qrcode_scanner_fragment.xml
index 913998f..f09fc69 100644
--- a/res/layout/wifi_dpp_qrcode_scanner_fragment.xml
+++ b/res/layout/wifi_dpp_qrcode_scanner_fragment.xml
@@ -39,10 +39,15 @@
             android:layout_gravity="center"/>
     </com.android.settings.wifi.qrcode.QrPreviewLayout>
 
-    <TextView android:id="@+id/error_message"
+    <TextView
+        android:id="@+id/error_message"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_gravity="center"/>
+        android:layout_gravity="center"
+        android:layout_marginTop="8dp"
+        android:text="@string/wifi_dpp_could_not_detect_valid_qr_code"
+        android:visibility="invisible"
+        android:textColor="?android:attr/colorError"/>
 
 </LinearLayout>
 
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index e80d151..6f336eb 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -1105,8 +1105,8 @@
     </string-array>
 
     <string-array name="wifi_privacy_entries">
-        <item>Default (use randomized MAC)</item>
-        <item>Trusted</item>
+        <item>Use device MAC</item>
+        <item>Use randomized MAC (default)</item>
     </string-array>
 
     <string-array name="wifi_hidden_entries">
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 587184b..2103649 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -128,5 +128,10 @@
 
     <!-- launcher icon color -->
     <color name="icon_launcher_setting_color">@*android:color/accent_device_default_light</color>
-</resources>
 
+    <!-- QR code scanner colors -->
+    <color name="qr_corner_line_color">#ffdadce0</color>
+    <color name="qr_focused_corner_line_color">#ff1a73e8</color>
+    <color name="qr_background_color">#b3ffffff</color> <!-- 70% white transparency -->
+    <!-- End of QR code scanner colors -->
+</resources>
\ No newline at end of file
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index a109d57..0859d2c 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -346,7 +346,6 @@
 
     <!-- Condition cards size and padding -->
     <dimen name="homepage_condition_card_title_margin_bottom">2dp</dimen>
-    <dimen name="homepage_condition_half_card_height">150dp</dimen>
     <dimen name="homepage_condition_half_card_padding_top">12dp</dimen>
     <dimen name="homepage_condition_half_card_title_margin_top">12dp</dimen>
     <dimen name="homepage_condition_half_card_summary_margin_bottom">12dp</dimen>
@@ -366,4 +365,7 @@
     <dimen name="homepage_condition_header_icon_width_height">24dp</dimen>
     <dimen name="homepage_condition_header_icon_margin_end">24dp</dimen>
 
+    <!-- QR code picture size -->
+    <dimen name="qrcode_size">264dp</dimen>
+
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index c6c066e..a45be06 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -2090,6 +2090,8 @@
     <string name="wifi_dpp_share_wifi">Share Wi\u2011Fi</string>
     <!-- Hint for the user to use another device to scan QR code on screen to join Wi-Fi [CHAR LIMIT=NONE] -->
     <string name="wifi_dpp_scan_qr_code_with_another_device">Scan this QR code with another device to join \u201c<xliff:g id="ssid" example="OfficeWifi">%1$s</xliff:g>\u201d</string>
+    <!-- Hint for QR code detection [CHAR LIMIT=NONE]  -->
+    <string name="wifi_dpp_could_not_detect_valid_qr_code">Could not detect valid QR code</string>
     <!-- Label for the check box to share a network with other users on the same device -->
     <string name="wifi_shared">Share with other device users</string>
     <!-- Hint for unchanged fields -->
@@ -10338,9 +10340,9 @@
     <string name="see_less">See less</string>
 
     <!-- Title for Network connection request Dialog [CHAR LIMIT=30] -->
-    <string name="network_connection_request_dialog_title">Choose device</string>
+    <string name="network_connection_request_dialog_title">Choose a device</string>
     <!-- Message for Network connection timeout Dialog [CHAR LIMIT=NONE] -->
-    <string name="network_connection_timeout_dialog_message">No devices found. Make sure the device is turned on and available to connect.</string>
+    <string name="network_connection_timeout_dialog_message">No devices found. Make sure devices are turned on and available to connect.</string>
     <!-- OK button for Network connection timeout Dialog [CHAR LIMIT=30] -->
     <string name="network_connection_timeout_dialog_ok">Try again</string>
     <!-- Message for Network connection error state Dialog [CHAR LIMIT=NONE] -->
diff --git a/src/com/android/settings/network/ApnSettings.java b/src/com/android/settings/network/ApnSettings.java
index 2b47c70..ac3b1f6 100755
--- a/src/com/android/settings/network/ApnSettings.java
+++ b/src/com/android/settings/network/ApnSettings.java
@@ -61,7 +61,8 @@
 
 import java.util.ArrayList;
 
-public class ApnSettings extends RestrictedSettingsFragment {
+public class ApnSettings extends RestrictedSettingsFragment
+        implements Preference.OnPreferenceChangeListener {
     static final String TAG = "ApnSettings";
 
     public static final String EXTRA_POSITION = "position";
@@ -313,6 +314,7 @@
                 pref.setKey(key);
                 pref.setTitle(name);
                 pref.setPersistent(false);
+                pref.setOnPreferenceChangeListener(this);
                 pref.setSubId(subId);
                 if (mHidePresetApnDetails && edited == Telephony.Carriers.UNEDITED) {
                     pref.setHideDetails();
@@ -386,6 +388,7 @@
         startActivity(intent);
     }
 
+    @Override
     public boolean onPreferenceChange(Preference preference, Object newValue) {
         Log.d(TAG, "onPreferenceChange(): Preference - " + preference
                 + ", newValue - " + newValue + ", newValue type - "
diff --git a/src/com/android/settings/wifi/NetworkRequestDialogFragment.java b/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
index 30c2cd9..7a1bdb4 100644
--- a/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
+++ b/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
@@ -16,6 +16,7 @@
 
 package com.android.settings.wifi;
 
+import android.app.Activity;
 import android.app.Dialog;
 import android.content.Context;
 import android.content.DialogInterface;
@@ -328,8 +329,12 @@
 
     @Override
     public void onUserSelectionConnectSuccess(WifiConfiguration wificonfiguration) {
-        // Dismisses current dialog, since connection is success.
+        // Dismisses current dialog and finishes Activity, since connection is success.
         dismiss();
+        final Activity activity = getActivity();
+        if (activity != null) {
+            activity.finish();
+        }
     }
 
     @Override
diff --git a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
index f3e8fc1..fe71991 100644
--- a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
+++ b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
@@ -549,8 +549,8 @@
      * Show QR code to share the network represented by this preference.
      */
     public void launchQRCodeGenerator() {
-        Intent intent = WifiDppUtils.getConfiguratorQrCodeGeneratorIntent(mAccessPoint.getSsidStr(),
-                mAccessPoint.getSecurityString(/* concise */ false));
+        Intent intent = WifiDppUtils.getConfiguratorQrCodeGeneratorIntent(mContext, mWifiManager,
+                mAccessPoint);
         mContext.startActivity(intent);
     }
 
diff --git a/src/com/android/settings/wifi/dpp/WifiDppAddDeviceFragment.java b/src/com/android/settings/wifi/dpp/WifiDppAddDeviceFragment.java
index 8d6aa68..90fb850 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppAddDeviceFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppAddDeviceFragment.java
@@ -17,6 +17,13 @@
 package com.android.settings.wifi.dpp;
 
 import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.ProgressBar;
+import android.widget.TextView;
 
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
@@ -26,10 +33,11 @@
  * to the Wi-Fi network.
  */
 public class WifiDppAddDeviceFragment extends WifiDppQrCodeBaseFragment {
-    @Override
-    protected int getLayout() {
-        return R.layout.wifi_dpp_add_device_fragment;
-    }
+    private ProgressBar mProgressBar;
+    private ImageView mWifiApPictureView;
+    private TextView mChooseDifferentNetwork;
+    private Button mButtonLeft;
+    private Button mButtonRight;
 
     @Override
     public int getMetricsCategory() {
@@ -37,7 +45,20 @@
     }
 
     @Override
-    public void onActivityCreated (Bundle savedInstanceState) {
-        super.onActivityCreated(savedInstanceState);
+    public final View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        return inflater.inflate(R.layout.wifi_dpp_add_device_fragment, container,
+                /* attachToRoot */ false);
+    }
+
+    @Override
+    public void onViewCreated(View view, Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+
+        mProgressBar = view.findViewById(R.id.progress_bar);
+        mWifiApPictureView = view.findViewById(R.id.wifi_ap_picture_view);
+        mChooseDifferentNetwork = view.findViewById(R.id.choose_different_network);
+        mButtonLeft = view.findViewById(R.id.button_left);
+        mButtonRight = view.findViewById(R.id.button_right);
     }
 }
diff --git a/src/com/android/settings/wifi/dpp/WifiDppChooseSavedWifiNetworkFragment.java b/src/com/android/settings/wifi/dpp/WifiDppChooseSavedWifiNetworkFragment.java
index 66bc349..a3e6db3 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppChooseSavedWifiNetworkFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppChooseSavedWifiNetworkFragment.java
@@ -17,6 +17,11 @@
 package com.android.settings.wifi.dpp;
 
 import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.ListView;
 
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
@@ -26,10 +31,9 @@
  * {@code WifiDppConfiguratorActivity} to start with this fragment to choose a saved Wi-Fi network.
  */
 public class WifiDppChooseSavedWifiNetworkFragment extends WifiDppQrCodeBaseFragment {
-    @Override
-    protected int getLayout() {
-        return R.layout.wifi_dpp_choose_saved_wifi_network_fragment;
-    }
+    private ListView mSavedWifiNetworkList;
+    private Button mButtonLeft;
+    private Button mButtonRight;
 
     @Override
     public int getMetricsCategory() {
@@ -37,7 +41,18 @@
     }
 
     @Override
-    public void onActivityCreated (Bundle savedInstanceState) {
-        super.onActivityCreated(savedInstanceState);
+    public final View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        return inflater.inflate(R.layout.wifi_dpp_choose_saved_wifi_network_fragment, container,
+                /* attachToRoot */ false);
+    }
+
+    @Override
+    public void onViewCreated(View view, Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+
+        mSavedWifiNetworkList = view.findViewById(R.id.saved_wifi_network_list);
+        mButtonLeft = view.findViewById(R.id.button_left);
+        mButtonRight = view.findViewById(R.id.button_right);
     }
 }
diff --git a/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java b/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java
index 6c95f09..e89ebaa 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java
@@ -49,7 +49,9 @@
  */
 public class WifiDppConfiguratorActivity extends InstrumentedActivity implements
         WifiNetworkConfig.Retriever,
-        WifiDppQrCodeGeneratorFragment.OnQrCodeGeneratorFragmentAddButtonClickedListener {
+        WifiDppQrCodeGeneratorFragment.OnQrCodeGeneratorFragmentAddButtonClickedListener,
+        WifiDppQrCodeScannerFragment.OnScanWifiDppSuccessListener,
+        WifiDppQrCodeScannerFragment.OnScanZxingWifiFormatSuccessListener {
     private static final String TAG = "WifiDppConfiguratorActivity";
 
     public static final String ACTION_CONFIGURATOR_QR_CODE_SCANNER =
@@ -64,6 +66,12 @@
     /** 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;
+
     @Override
     public int getMetricsCategory() {
         return MetricsProto.MetricsEvent.SETTINGS_WIFI_DPP_CONFIGURATOR;
@@ -127,8 +135,8 @@
             return;
         }
 
-        WifiDppQrCodeScannerFragment fragment = new WifiDppQrCodeScannerFragment();
-        FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
+        final WifiDppQrCodeScannerFragment fragment = new WifiDppQrCodeScannerFragment();
+        final FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
 
         fragmentTransaction.replace(R.id.fragment_container, fragment,
                 WifiDppUtils.TAG_FRAGMENT_QR_CODE_SCANNER);
@@ -145,8 +153,8 @@
             return;
         }
 
-        WifiDppQrCodeGeneratorFragment fragment = new WifiDppQrCodeGeneratorFragment();
-        FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
+        final WifiDppQrCodeGeneratorFragment fragment = new WifiDppQrCodeGeneratorFragment();
+        final FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
 
         fragmentTransaction.replace(R.id.fragment_container, fragment,
                 WifiDppUtils.TAG_FRAGMENT_QR_CODE_GENERATOR);
@@ -160,9 +168,9 @@
             return;
         }
 
-        WifiDppChooseSavedWifiNetworkFragment fragment =
+        final WifiDppChooseSavedWifiNetworkFragment fragment =
                 new WifiDppChooseSavedWifiNetworkFragment();
-        FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
+        final FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
 
         fragmentTransaction.replace(R.id.fragment_container, fragment,
                 WifiDppUtils.TAG_FRAGMENT_CHOOSE_SAVED_WIFI_NETWORK);
@@ -172,11 +180,38 @@
         fragmentTransaction.commit();
     }
 
+    private void showAddDeviceFragment(boolean addToBackStack) {
+        // Avoid to replace the same fragment during configuration change
+        if (mFragmentManager.findFragmentByTag(
+                WifiDppUtils.TAG_FRAGMENT_ADD_DEVICE) != null) {
+            return;
+        }
+
+        final WifiDppAddDeviceFragment fragment =
+                new WifiDppAddDeviceFragment();
+        final FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
+
+        fragmentTransaction.replace(R.id.fragment_container, fragment,
+                WifiDppUtils.TAG_FRAGMENT_ADD_DEVICE);
+        if (addToBackStack) {
+            fragmentTransaction.addToBackStack(/* name */ null);
+        }
+        fragmentTransaction.commit();
+    }
+
     @Override
     public WifiNetworkConfig getWifiNetworkConfig() {
         return mWifiNetworkConfig;
     }
 
+    public String getPublicKey() {
+        return mPublicKey;
+    }
+
+    public String getInformation() {
+        return mInformation;
+    }
+
     @Override
     public boolean setWifiNetworkConfig(WifiNetworkConfig config) {
         if(!WifiNetworkConfig.isValidConfig(config)) {
@@ -201,7 +236,26 @@
         return false;
     }
 
-    @Override public void onQrCodeGeneratorFragmentAddButtonClicked() {
+    @Override
+    public void onQrCodeGeneratorFragmentAddButtonClicked() {
         showQrCodeScannerFragment(/* addToBackStack */ true);
     }
+
+    @Override
+    public void onScanWifiDppSuccess(String publicKey, String information) {
+        mPublicKey = publicKey;
+        mInformation = information;
+        mWifiNetworkConfig = null;
+
+        showAddDeviceFragment(/* addToBackStack */ true);
+    }
+
+    @Override
+    public void onScanZxingWifiFormatSuccess(WifiNetworkConfig wifiNetworkConfig) {
+        mPublicKey = null;
+        mInformation = 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 920e736..584a819 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppEnrolleeActivity.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppEnrolleeActivity.java
@@ -16,9 +16,11 @@
 
 package com.android.settings.wifi.dpp;
 
+import android.provider.Settings;
 import android.app.ActionBar;
 import android.app.Activity;
 import android.content.Intent;
+import android.net.wifi.WifiManager;
 import android.os.Bundle;
 import android.util.Log;
 
@@ -36,7 +38,10 @@
  * To use intent action {@code ACTION_ENROLLEE_QR_CODE_SCANNER}, specify the SSID string of the
  * Wi-Fi network to be provisioned in {@code WifiDppUtils.EXTRA_WIFI_SSID}.
  */
-public class WifiDppEnrolleeActivity extends InstrumentedActivity {
+public class WifiDppEnrolleeActivity extends InstrumentedActivity implements
+        WifiManager.ActionListener,
+        WifiDppQrCodeScannerFragment.OnScanWifiDppSuccessListener,
+        WifiDppQrCodeScannerFragment.OnScanZxingWifiFormatSuccessListener {
     private static final String TAG = "WifiDppEnrolleeActivity";
 
     public static final String ACTION_ENROLLEE_QR_CODE_SCANNER =
@@ -101,4 +106,31 @@
         finish();
         return true;
     }
+
+    @Override
+    public void onScanWifiDppSuccess(String publicKey, String information) {
+        // TODO(b/1023597): starts DPP enrollee handshake here
+    }
+
+    @Override
+    public void onScanZxingWifiFormatSuccess(WifiNetworkConfig wifiNetworkConfig) {
+        wifiNetworkConfig.connect(/* context */ this, /* listener */ this);
+    }
+
+    @Override
+    public void onSuccess() {
+        startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
+        setResult(Activity.RESULT_OK);
+        finish();
+    }
+
+    @Override
+    public void onFailure(int reason) {
+        Log.d(TAG, "Wi-Fi connect onFailure reason - " + reason);
+
+        final Fragment fragment = mFragmentManager.findFragmentById(R.id.fragment_container);
+        if (fragment instanceof WifiDppQrCodeScannerFragment) {
+            ((WifiDppQrCodeScannerFragment)fragment).showErrorMessage(true);
+        }
+    }
 }
diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeBaseFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeBaseFragment.java
index 6792dee..4ac5850 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeBaseFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeBaseFragment.java
@@ -17,25 +17,16 @@
 package com.android.settings.wifi.dpp;
 
 import android.os.Bundle;
-import android.view.LayoutInflater;
 import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Button;
 import android.widget.ImageView;
-import android.widget.ListView;
-import android.widget.ProgressBar;
 import android.widget.TextView;
 
 import com.android.settings.core.InstrumentedFragment;
 import com.android.settings.R;
 
 /**
- * TODO: b/120645817 should refine code to only initiate UI component in each child fragment.
- */
-
-/**
  * There are below 4 fragments for Wi-Fi DPP UI flow, to reduce redundant code of UI components,
- * this parent fragment instantiates all UI components and provides setting APIs for them.
+ * this parent fragment instantiates common UI components
  *
  * {@code WifiDppQrCodeScannerFragment}
  * {@code WifiDppQrCodeGeneratorFragment}
@@ -43,128 +34,16 @@
  * {@code WifiDppAddDeviceFragment}
  */
 public abstract class WifiDppQrCodeBaseFragment extends InstrumentedFragment {
-    private ImageView mHeaderIcon;
-    private TextView mTitle;
-    private TextView mDescription;
-
-    private TextView mErrorMessage;         //optional, for WifiDppQrCodeScannerFragment
-    private ListView mSavedWifiNetworkList; //optional, for WifiDppChooseSavedWifiNetworkFragment
-    private ProgressBar mProgressBar;       //optional, for WifiDppAddDeviceFragment
-    private ImageView mWifiApPictureView;   //optional, for WifiDppAddDeviceFragment
-    private TextView mChooseDifferentNetwork;//optional, for WifiDppAddDeviceFragment
-
-    private Button mButtonLeft;             //optional, for WifiDppChooseSavedWifiNetworkFragment,
-                                            //              WifiDppAddDeviceFragment
-    private Button mButtonRight;            //optional, for WifiDppChooseSavedWifiNetworkFragment,
-                                            //              WifiDppAddDeviceFragment
-
-    abstract protected int getLayout();
+    protected ImageView mHeaderIcon;
+    protected TextView mTitle;
+    protected TextView mSummary;
 
     @Override
-    public final void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-    }
+    public void onViewCreated(View view, Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
 
-    @Override
-    public final View onCreateView(LayoutInflater inflater, ViewGroup container,
-            Bundle savedInstanceState) {
-        View view = inflater.inflate(getLayout(), container, false);
-        initView(view);
-        return view;
-    }
-
-    private void initView(View view) {
-        mHeaderIcon = view.findViewById(R.id.header_icon);
-        mTitle = view.findViewById(R.id.title);
-        mDescription = view.findViewById(R.id.description);
-        mErrorMessage = view.findViewById(R.id.error_message);
-
-        mSavedWifiNetworkList = view.findViewById(R.id.saved_wifi_network_list);
-
-        mProgressBar = view.findViewById(R.id.progress_bar);
-        mWifiApPictureView = view.findViewById(R.id.wifi_ap_picture_view);
-        mChooseDifferentNetwork = view.findViewById(R.id.choose_different_network);
-
-        mButtonLeft = view.findViewById(R.id.button_left);
-        mButtonRight = view.findViewById(R.id.button_right);
-    }
-
-    protected void setHeaderIconImageResource(int resId) {
-        mHeaderIcon.setImageResource(resId);
-    }
-
-    protected void setTitle(String title) {
-        mTitle.setText(title);
-    }
-
-    protected void setDescription(String description) {
-        mDescription.setText(description);
-    }
-
-    /** optional, for WifiDppQrCodeScannerFragment */
-    protected void setErrorMessage(String errorMessage) {
-        if (mErrorMessage != null) {
-            mErrorMessage.setText(errorMessage);
-        }
-    }
-
-    /**
-     * optional, for WifiDppChooseSavedWifiNetworkFragment,
-     *               WifiDppAddDeviceFragment
-     */
-    protected void setLeftButtonText(String text) {
-        if (mButtonLeft != null) {
-            mButtonLeft.setText(text);
-        }
-    }
-
-    /**
-     * optional, for WifiDppChooseSavedWifiNetworkFragment,
-     *               WifiDppAddDeviceFragment
-     */
-    protected void setRightButtonText(String text) {
-        if (mButtonRight != null) {
-            mButtonRight.setText(text);
-        }
-    }
-
-    /**
-     * optional, for WifiDppChooseSavedWifiNetworkFragment,
-     *               WifiDppAddDeviceFragment
-     */
-    protected void hideLeftButton() {
-        if (mButtonLeft != null) {
-            mButtonLeft.setVisibility(View.INVISIBLE);
-        }
-    }
-
-    /**
-     * optional, for WifiDppChooseSavedWifiNetworkFragment,
-     *               WifiDppAddDeviceFragment
-     */
-    protected void hideRightButton() {
-        if (mButtonRight != null) {
-            mButtonRight.setVisibility(View.INVISIBLE);
-        }
-    }
-
-    /**
-     * optional, for WifiDppChooseSavedWifiNetworkFragment,
-     *               WifiDppAddDeviceFragment
-     */
-    protected void setLeftButtonOnClickListener(View.OnClickListener listener) {
-        if (mButtonLeft != null) {
-            mButtonLeft.setOnClickListener(listener);
-        }
-    }
-
-    /**
-     * optional, for WifiDppChooseSavedWifiNetworkFragment,
-     *               WifiDppAddDeviceFragment
-     */
-    protected void setRightButtonOnClickListener(View.OnClickListener listener) {
-        if (mButtonRight != null) {
-            mButtonRight.setOnClickListener(listener);
-        }
+        mHeaderIcon = view.findViewById(android.R.id.icon);
+        mTitle = view.findViewById(android.R.id.title);
+        mSummary = view.findViewById(android.R.id.summary);
     }
 }
diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java
index 81def9b..f4bbcc1 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java
@@ -18,23 +18,32 @@
 
 import android.app.ActionBar;
 import android.content.Context;
+import android.graphics.Bitmap;
 import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
 
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
+import com.android.settings.wifi.qrcode.QrCodeGenerator;
+
+import com.google.zxing.WriterException;
 
 /**
  * After sharing a saved Wi-Fi network, {@code WifiDppConfiguratorActivity} start with this fragment
  * to generate a Wi-Fi DPP QR code for other device to initiate as an enrollee.
  */
 public class WifiDppQrCodeGeneratorFragment extends WifiDppQrCodeBaseFragment {
-    @Override
-    protected int getLayout() {
-        return R.layout.wifi_dpp_qrcode_generator_fragment;
-    }
+    private static final String TAG = "WifiDppQrCodeGeneratorFragment";
+
+    private ImageView mQrCodeView;
+    private String mQrCode;
 
     @Override
     public int getMetricsCategory() {
@@ -51,18 +60,8 @@
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
 
-        setHeaderIconImageResource(R.drawable.ic_qrcode_24dp);
-        WifiNetworkConfig wifiNetworkConfig = ((WifiNetworkConfig.Retriever) getActivity())
-                .getWifiNetworkConfig();
-        if (!WifiNetworkConfig.isValidConfig(wifiNetworkConfig)) {
-            throw new IllegalArgumentException("Invalid Wi-Fi network for configuring");
-        }
-        setTitle(getString(R.string.wifi_dpp_share_wifi));
-        setDescription(getString(R.string.wifi_dpp_scan_qr_code_with_another_device,
-                wifiNetworkConfig.getSsid()));
-
         setHasOptionsMenu(true);
-        ActionBar actionBar = getActivity().getActionBar();
+        final ActionBar actionBar = getActivity().getActionBar();
         if (actionBar != null) {
             actionBar.setDisplayHomeAsUpEnabled(true);
             actionBar.show();
@@ -102,4 +101,42 @@
                 return super.onOptionsItemSelected(menuItem);
         }
     }
+
+    @Override
+    public final View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        return inflater.inflate(R.layout.wifi_dpp_qrcode_generator_fragment, container,
+                /* attachToRoot */ false);
+    }
+
+    @Override
+    public void onViewCreated(View view, Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+
+        mQrCodeView = view.findViewById(R.id.qrcode_view);
+
+        mHeaderIcon.setImageResource(R.drawable.ic_qrcode_24dp);
+        WifiNetworkConfig wifiNetworkConfig = ((WifiNetworkConfig.Retriever) getActivity())
+                .getWifiNetworkConfig();
+        if (!WifiNetworkConfig.isValidConfig(wifiNetworkConfig)) {
+            throw new IllegalStateException("Invalid Wi-Fi network for configuring");
+        }
+        mTitle.setText(R.string.wifi_dpp_share_wifi);
+        mSummary.setText(getString(R.string.wifi_dpp_scan_qr_code_with_another_device,
+                wifiNetworkConfig.getSsid()));
+
+        mQrCode = wifiNetworkConfig.getQrCode();
+        setQrCode();
+    }
+
+    private void setQrCode() {
+        try {
+            final int qrcodeSize = getContext().getResources().getDimensionPixelSize(
+                    R.dimen.qrcode_size);
+            final Bitmap bmp = QrCodeGenerator.encodeQrCode(mQrCode, qrcodeSize);
+            mQrCodeView.setImageBitmap(bmp);
+        } catch (WriterException e) {
+            Log.e(TAG, "Error generatting QR code bitmap " + e);
+        }
+    }
 }
diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
index 8cd3c562..c7c1461 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
@@ -16,7 +16,6 @@
 
 package com.android.settings.wifi.dpp;
 
-import android.annotation.Nullable;
 import android.app.ActionBar;
 import android.app.Activity;
 import android.content.Context;
@@ -25,13 +24,18 @@
 import android.graphics.Rect;
 import android.graphics.SurfaceTexture;
 import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
 import android.text.TextUtils;
 import android.util.Size;
+import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.TextureView;
 import android.view.TextureView.SurfaceTextureListener;
 import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
 
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
@@ -41,37 +45,69 @@
 public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment implements
         SurfaceTextureListener,
         QrCamera.ScannerCallback {
+    private static final String TAG = "WifiDppQrCodeScannerFragment";
+
+    /** Message sent to hide error message */
+    private static final int MESSAGE_HIDE_ERROR_MESSAGE = 1;
+
+    /** Message sent to show error message */
+    private static final int MESSAGE_SHOW_ERROR_MESSAGE = 2;
+
+    /** Message sent to manipulate Wi-Fi DPP QR code */
+    private static final int MESSAGE_SCAN_WIFI_DPP_SUCCESS = 3;
+
+    /** Message sent to manipulate ZXing Wi-Fi QR code */
+    private static final int MESSAGE_SCAN_ZXING_WIFI_FORMAT_SUCCESS = 4;
+
+    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";
+
     private QrCamera mCamera;
     private TextureView mTextureView;
     private QrDecorateView mDecorateView;
+    private TextView mErrorMessage;
 
     /** true if the fragment working for configurator, false enrollee*/
-    private final boolean mConfiguratorMode;
+    private final boolean mIsConfiguratorMode;
 
     /** The SSID of the Wi-Fi network which the user specify to enroll */
     private String mSsid;
 
-    @Override
-    protected int getLayout() {
-        return R.layout.wifi_dpp_qrcode_scanner_fragment;
-    }
+    /** QR code data scanned by camera */
+    private WifiQrCode mWifiQrCode;
 
     @Override
     public int getMetricsCategory() {
-        if (mConfiguratorMode) {
+        if (mIsConfiguratorMode) {
             return MetricsProto.MetricsEvent.SETTINGS_WIFI_DPP_CONFIGURATOR;
         } else {
             return MetricsProto.MetricsEvent.SETTINGS_WIFI_DPP_ENROLLEE;
         }
     }
 
+    // Container Activity must implement this interface
+    public interface OnScanWifiDppSuccessListener {
+        public void onScanWifiDppSuccess(String publicKey, String information);
+    }
+    OnScanWifiDppSuccessListener mScanWifiDppSuccessListener;
+
+    // Container Activity must implement this interface
+    public interface OnScanZxingWifiFormatSuccessListener {
+        public void onScanZxingWifiFormatSuccess(WifiNetworkConfig wifiNetworkConfig);
+    }
+    OnScanZxingWifiFormatSuccessListener mScanScanZxingWifiFormatSuccessListener;
+
     /**
      * Configurator container activity of the fragment should create instance with this constructor.
      */
     public WifiDppQrCodeScannerFragment() {
         super();
 
-        mConfiguratorMode = true;
+        mIsConfiguratorMode = true;
     }
 
     /**
@@ -81,7 +117,7 @@
     public WifiDppQrCodeScannerFragment(String ssid) {
         super();
 
-        mConfiguratorMode = false;
+        mIsConfiguratorMode = false;
         mSsid = ssid;
     }
 
@@ -89,30 +125,7 @@
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
 
-        setHeaderIconImageResource(R.drawable.ic_scan_24dp);
-
-        if (mConfiguratorMode) {
-            setTitle(getString(R.string.wifi_dpp_add_device_to_network));
-
-            WifiNetworkConfig wifiNetworkConfig = ((WifiNetworkConfig.Retriever) getActivity())
-                .getWifiNetworkConfig();
-            if (!WifiNetworkConfig.isValidConfig(wifiNetworkConfig)) {
-                throw new IllegalArgumentException("Invalid Wi-Fi network for configuring");
-            }
-            setDescription(getString(R.string.wifi_dpp_center_qr_code, wifiNetworkConfig.getSsid()));
-        } else {
-            setTitle(getString(R.string.wifi_dpp_scan_qr_code));
-
-            String description;
-            if (TextUtils.isEmpty(mSsid)) {
-                description = getString(R.string.wifi_dpp_scan_qr_code_join_unknown_network, mSsid);
-            } else {
-                description = getString(R.string.wifi_dpp_scan_qr_code_join_network, mSsid);
-            }
-            setDescription(description);
-        }
-
-        ActionBar actionBar = getActivity().getActionBar();
+        final ActionBar actionBar = getActivity().getActionBar();
         if (actionBar != null) {
             actionBar.setDisplayHomeAsUpEnabled(true);
             actionBar.show();
@@ -120,13 +133,61 @@
     }
 
     @Override
-    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
+    public void onAttach(Context context) {
+        super.onAttach(context);
+
+        mScanWifiDppSuccessListener = (OnScanWifiDppSuccessListener) context;
+        mScanScanZxingWifiFormatSuccessListener = (OnScanZxingWifiFormatSuccessListener) context;
+    }
+
+    @Override
+    public void onDetach() {
+        mScanWifiDppSuccessListener = null;
+        mScanScanZxingWifiFormatSuccessListener = null;
+
+        super.onDetach();
+    }
+
+    @Override
+    public final View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        return inflater.inflate(R.layout.wifi_dpp_qrcode_scanner_fragment, container,
+                /* attachToRoot */ false);
+    }
+
+    @Override
+    public void onViewCreated(View view, Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
 
         mTextureView = (TextureView) view.findViewById(R.id.preview_view);
         mTextureView.setSurfaceTextureListener(this);
 
         mDecorateView = (QrDecorateView) view.findViewById(R.id.decorate_view);
+
+        mHeaderIcon.setImageResource(R.drawable.ic_scan_24dp);
+        if (mIsConfiguratorMode) {
+            mTitle.setText(R.string.wifi_dpp_add_device_to_network);
+
+            WifiNetworkConfig wifiNetworkConfig = ((WifiNetworkConfig.Retriever) getActivity())
+                .getWifiNetworkConfig();
+            if (!WifiNetworkConfig.isValidConfig(wifiNetworkConfig)) {
+                throw new IllegalStateException("Invalid Wi-Fi network for configuring");
+            }
+            mSummary.setText(getString(R.string.wifi_dpp_center_qr_code,
+                    wifiNetworkConfig.getSsid()));
+        } else {
+            mTitle.setText(R.string.wifi_dpp_scan_qr_code);
+
+            String description;
+            if (TextUtils.isEmpty(mSsid)) {
+                description = getString(R.string.wifi_dpp_scan_qr_code_join_unknown_network, mSsid);
+            } else {
+                description = getString(R.string.wifi_dpp_scan_qr_code_join_network, mSsid);
+            }
+            mSummary.setText(description);
+        }
+
+        mErrorMessage = view.findViewById(R.id.error_message);
     }
 
     @Override
@@ -173,10 +234,75 @@
     }
 
     @Override
+    public boolean isValid(String qrCode) {
+        try {
+            mWifiQrCode = new WifiQrCode(qrCode);
+        } catch (IllegalArgumentException e) {
+            mHandler.sendEmptyMessage(MESSAGE_SHOW_ERROR_MESSAGE);
+            return false;
+        }
+
+        final String scheme = mWifiQrCode.getScheme();
+
+        // When SSID is specified for enrollee, avoid to connect to the Wi-Fi of different SSID
+        if (!mIsConfiguratorMode && WifiQrCode.SCHEME_ZXING_WIFI_NETWORK_CONFIG.equals(scheme)) {
+            final String ssidQrCode = mWifiQrCode.getWifiNetworkConfig().getSsid();
+            if (!TextUtils.isEmpty(mSsid) && !mSsid.equals(ssidQrCode)) {
+                mHandler.sendEmptyMessage(MESSAGE_SHOW_ERROR_MESSAGE);
+                return false;
+            }
+        }
+
+        // It's impossible to provision other device with ZXing Wi-Fi Network config format
+        if (mIsConfiguratorMode && WifiQrCode.SCHEME_ZXING_WIFI_NETWORK_CONFIG.equals(scheme)) {
+            mHandler.sendEmptyMessage(MESSAGE_SHOW_ERROR_MESSAGE);
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * This method is only called when QrCamera.ScannerCallback.isValid returns true; 
+     */
+    @Override
     public void handleSuccessfulResult(String qrCode) {
+        switch (mWifiQrCode.getScheme()) {
+            case WifiQrCode.SCHEME_DPP:
+                handleWifiDpp(mWifiQrCode.getPublicKey(), mWifiQrCode.getInformation());
+                break;
+
+            case WifiQrCode.SCHEME_ZXING_WIFI_NETWORK_CONFIG:
+                handleZxingWifiFormat(mWifiQrCode.getWifiNetworkConfig());
+                break;
+
+            default:
+                // continue below
+        }
+    }
+
+    private void handleWifiDpp(String publicKey, String information) {
         destroyCamera();
         mDecorateView.setFocused(true);
-        // TODO(b/120243131): Add a network by Wi-Fi Network config shared via QR code.
+
+        final Bundle bundle = new Bundle();
+        bundle.putString(KEY_PUBLIC_KEY, publicKey);
+        bundle.putString(KEY_INFORMATION, information);
+
+        Message message = mHandler.obtainMessage(MESSAGE_SCAN_WIFI_DPP_SUCCESS);
+        message.setData(bundle);
+
+        mHandler.sendMessageDelayed(message, SHOW_SUCCESS_SQUARE_INTERVAL);
+    }
+
+    private void handleZxingWifiFormat(WifiNetworkConfig wifiNetworkConfig) {
+        destroyCamera();
+        mDecorateView.setFocused(true);
+
+        Message message = mHandler.obtainMessage(MESSAGE_SCAN_ZXING_WIFI_FORMAT_SUCCESS);
+        message.obj = wifiNetworkConfig;
+
+        mHandler.sendMessageDelayed(message, SHOW_SUCCESS_SQUARE_INTERVAL);
     }
 
     @Override
@@ -198,4 +324,51 @@
             mCamera = null;
         }
     }
+
+    public void showErrorMessage(boolean show) {
+        mErrorMessage.setVisibility(show ? View.VISIBLE : View.INVISIBLE);
+
+        if (show) {
+            mHandler.removeMessages(MESSAGE_HIDE_ERROR_MESSAGE);
+            mHandler.sendEmptyMessageDelayed(MESSAGE_HIDE_ERROR_MESSAGE,
+                    SHOW_ERROR_MESSAGE_INTERVAL);
+        }
+    }
+
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MESSAGE_HIDE_ERROR_MESSAGE:
+                    showErrorMessage(false);
+                    break;
+
+                case MESSAGE_SHOW_ERROR_MESSAGE:
+                    showErrorMessage(true);
+                    break;
+
+                case MESSAGE_SCAN_WIFI_DPP_SUCCESS:
+                    if (mScanWifiDppSuccessListener == null) {
+                        return;
+                    }
+                    final Bundle bundle = msg.getData();
+                    final String publicKey = bundle.getString(KEY_PUBLIC_KEY);
+                    final String information = bundle.getString(KEY_INFORMATION);
+
+                    mScanWifiDppSuccessListener.onScanWifiDppSuccess(publicKey, information);
+                    break;
+
+                case MESSAGE_SCAN_ZXING_WIFI_FORMAT_SUCCESS:
+                    if (mScanScanZxingWifiFormatSuccessListener == null) {
+                        return;
+                    }
+                    mScanScanZxingWifiFormatSuccessListener.onScanZxingWifiFormatSuccess(
+                            (WifiNetworkConfig)msg.obj);
+                    break;
+
+                default:
+                    return;
+            }
+        }
+    };
 }
diff --git a/src/com/android/settings/wifi/dpp/WifiDppUtils.java b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
index cc75d44..3a40e25 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppUtils.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
@@ -18,9 +18,15 @@
 
 import android.content.Context;
 import android.content.Intent;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiManager;
 import android.text.TextUtils;
 import android.util.FeatureFlagUtils;
 
+import com.android.settingslib.wifi.AccessPoint;
+
+import java.util.List;
+
 /**
  * Here are the items shared by both WifiDppConfiguratorActivity & WifiDppEnrolleeActivity
  */
@@ -84,23 +90,81 @@
         return intent;
     }
 
+    private static String getPresharedKey(WifiManager wifiManager, WifiConfiguration config) {
+        String preSharedKey = config.preSharedKey;
+
+        final List<WifiConfiguration> wifiConfigs = wifiManager.getPrivilegedConfiguredNetworks();
+        for (WifiConfiguration wifiConfig : wifiConfigs) {
+            if (wifiConfig.networkId == config.networkId) {
+                preSharedKey = wifiConfig.preSharedKey;
+                break;
+            }
+        }
+
+        return preSharedKey;
+    }
+
+    private static String removeFirstAndLastDoubleQuotes(String str) {
+        if (TextUtils.isEmpty(str)) {
+            return str;
+        }
+
+        int begin = 0;
+        int end = str.length() - 1;
+        if (str.charAt(begin) == '\"') {
+            begin++;
+        }
+        if (str.charAt(end) == '\"') {
+            end--;
+        }
+        return str.substring(begin, end+1);
+    }
+
+    private static String getSecurityString(AccessPoint accessPoint) {
+        switch(accessPoint.getSecurity()) {
+            case AccessPoint.SECURITY_WEP:
+                return "WEP";
+            case AccessPoint.SECURITY_PSK:
+                return "WPA";
+            default:
+                return "nopass";
+        }
+    }
+
     /**
      * Returns an intent to launch QR code generator.
      *
-     * @param ssid     The data corresponding to {@code WifiConfiguration} SSID
-     * @param Security The data is from {@code AccessPoint.securityToString}
+     * @param context     The context to use for the content resolver
+     * @param wifiManager An instance of {@link WifiManager}
+     * @param accessPoint An instance of {@link AccessPoint}
      * @return Intent for launching QR code generator
      */
-    public static Intent getConfiguratorQrCodeGeneratorIntent(String ssid, String Security) {
-        //TODO: b/118794858#comment6 should put password & hideSsid in intent extra
-        final Intent intent = new Intent(
-                WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_GENERATOR);
+    public static Intent getConfiguratorQrCodeGeneratorIntent(Context context,
+            WifiManager wifiManager, AccessPoint accessPoint) {
+        final Intent intent = new Intent(context, WifiDppConfiguratorActivity.class);
+        intent.setAction(WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_GENERATOR);
+
+        final WifiConfiguration wifiConfig = accessPoint.getConfig();
+        final String ssid = removeFirstAndLastDoubleQuotes(wifiConfig.SSID);
+        final String security = getSecurityString(accessPoint);
+        String preSharedKey = wifiConfig.preSharedKey;
+
+        if (preSharedKey != null) {
+            // When the value of this key is read, the actual key is not returned, just a "*".
+            // Call privileged system API to obtain actual key.
+            preSharedKey = removeFirstAndLastDoubleQuotes(getPresharedKey(wifiManager, wifiConfig));
+        }
+
         if (!TextUtils.isEmpty(ssid)) {
             intent.putExtra(EXTRA_WIFI_SSID, ssid);
         }
-        if (!TextUtils.isEmpty(Security)) {
-            intent.putExtra(EXTRA_WIFI_SECURITY, Security);
+        if (!TextUtils.isEmpty(security)) {
+            intent.putExtra(EXTRA_WIFI_SECURITY, security);
         }
+        if (!TextUtils.isEmpty(preSharedKey)) {
+            intent.putExtra(EXTRA_WIFI_PRE_SHARED_KEY, preSharedKey);
+        }
+
         return intent;
     }
 }
diff --git a/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java b/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java
index bb64e05..c9bfbd6 100644
--- a/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java
+++ b/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java
@@ -16,8 +16,18 @@
 
 package com.android.settings.wifi.dpp;
 
+import static com.android.settings.wifi.dpp.WifiQrCode.SECURITY_NO_PASSWORD;
+import static com.android.settings.wifi.dpp.WifiQrCode.SECURITY_WEP;
+import static com.android.settings.wifi.dpp.WifiQrCode.SECURITY_WPA;
+
+import android.content.Context;
 import android.content.Intent;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiConfiguration.AuthAlgorithm;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
+import android.net.wifi.WifiManager;
 import android.text.TextUtils;
+import android.util.Log;
 
 import androidx.annotation.Keep;
 
@@ -30,8 +40,7 @@
  * EXTRA_QR_CODE
  */
 public class WifiNetworkConfig {
-    // Ignores password if security is NO_PASSWORD or absent
-    public static final String NO_PASSWORD = "nopass";
+    private static final String TAG = "WifiNetworkConfig";
 
     private String mSecurity;
     private String mSsid;
@@ -47,18 +56,9 @@
     }
 
     public WifiNetworkConfig(WifiNetworkConfig config) {
-        if (config.mSecurity != null) {
-            mSecurity = new String(config.mSecurity);
-        }
-
-        if (config.mSsid != null) {
-            mSsid = new String(config.mSsid);
-        }
-
-        if (config.mPreSharedKey != null) {
-            mPreSharedKey = new String(config.mPreSharedKey);
-        }
-
+        mSecurity = config.mSecurity;
+        mSsid = config.mSsid;
+        mPreSharedKey = config.mPreSharedKey;
         mHiddenSsid = config.mHiddenSsid;
     }
 
@@ -106,7 +106,7 @@
 
     public static boolean isValidConfig(String security, String ssid, String preSharedKey,
             boolean hiddenSsid) {
-        if (!TextUtils.isEmpty(security) && !NO_PASSWORD.equals(security)) {
+        if (!TextUtils.isEmpty(security) && !SECURITY_NO_PASSWORD.equals(security)) {
             if (TextUtils.isEmpty(preSharedKey)) {
                 return false;
             }
@@ -119,6 +119,51 @@
         return true;
     }
 
+    /**
+     * Escaped special characters "\", ";", ":", "," with a backslash
+     * See https://github.com/zxing/zxing/wiki/Barcode-Contents
+     */
+    private String escapeSpecialCharacters(String str) {
+        if (TextUtils.isEmpty(str)) {
+            return str;
+        }
+
+        StringBuilder buf = new StringBuilder();
+        for (int i = 0; i < str.length(); i++) {
+            char ch = str.charAt(i);
+            if (ch =='\\' || ch == ',' || ch == ';' || ch == ':') {
+                buf.append('\\');
+            }
+            buf.append(ch);
+        }
+
+        return buf.toString();
+    }
+
+    /**
+     * Construct a barcode string for WiFi network login.
+     * See https://en.wikipedia.org/wiki/QR_code#WiFi_network_login
+     */
+    public String getQrCode() {
+        final String empty = "";
+        String barcode = new StringBuilder("WIFI:")
+                .append("S:")
+                .append(escapeSpecialCharacters(mSsid))
+                .append(";")
+                .append("T:")
+                .append(TextUtils.isEmpty(mSecurity) ? empty : mSecurity)
+                .append(";")
+                .append("P:")
+                .append(TextUtils.isEmpty(mPreSharedKey) ? empty
+                        : escapeSpecialCharacters(mPreSharedKey))
+                .append(";")
+                .append("H:")
+                .append(mHiddenSsid)
+                .append(";;")
+                .toString();
+        return barcode;
+    }
+
     @Keep
     public String getSecurity() {
         return mSecurity;
@@ -138,4 +183,77 @@
     public boolean getHiddenSsid() {
         return mHiddenSsid;
     }
+
+    public void connect(Context context, WifiManager.ActionListener listener) {
+        WifiConfiguration wifiConfiguration = getWifiConfigurationOrNull();
+        if (wifiConfiguration == null) {
+            if (listener != null) {
+                listener.onFailure(WifiManager.ERROR);
+            }
+            return;
+        }
+
+        WifiManager wifiManager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);
+        wifiManager.connect(wifiConfiguration, listener);
+    }
+
+    /**
+     * This is a simplified method from {@code WifiConfigController.getConfig()}
+     */
+    private WifiConfiguration getWifiConfigurationOrNull() {
+        if (!isValidConfig(this)) {
+            return null;
+        }
+
+        final WifiConfiguration wifiConfiguration = new WifiConfiguration();
+        wifiConfiguration.SSID = addQuotationIfNeeded(mSsid);
+        wifiConfiguration.hiddenSSID = mHiddenSsid;
+
+        if (TextUtils.isEmpty(mSecurity) || SECURITY_NO_PASSWORD.equals(mSecurity)) {
+            wifiConfiguration.allowedKeyManagement.set(KeyMgmt.NONE);
+            return wifiConfiguration;
+        }
+
+        if (mSecurity.startsWith(SECURITY_WEP)) {
+            wifiConfiguration.allowedKeyManagement.set(KeyMgmt.NONE);
+            wifiConfiguration.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
+            wifiConfiguration.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
+
+            // WEP-40, WEP-104, and 256-bit WEP (WEP-232?)
+            final int length = mPreSharedKey.length();
+            if ((length == 10 || length == 26 || length == 58)
+                    && mPreSharedKey.matches("[0-9A-Fa-f]*")) {
+                wifiConfiguration.wepKeys[0] = mPreSharedKey;
+            } else {
+                wifiConfiguration.wepKeys[0] = addQuotationIfNeeded(mPreSharedKey);
+            }
+        } else if (mSecurity.startsWith(SECURITY_WPA)) {
+            wifiConfiguration.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
+
+            if (mPreSharedKey.matches("[0-9A-Fa-f]{64}")) {
+                wifiConfiguration.preSharedKey = mPreSharedKey;
+            } else {
+                wifiConfiguration.preSharedKey = addQuotationIfNeeded(mPreSharedKey);
+            }
+        } else {
+            Log.w(TAG, "Unsupported security");
+            return null;
+        }
+
+        return wifiConfiguration;
+    }
+
+    private String addQuotationIfNeeded(String input) {
+        if (TextUtils.isEmpty(input)) {
+            return "";
+        }
+
+        if (input.length() >= 2 && input.startsWith("\"") && input.endsWith("\"")) {
+            return input;
+        }
+
+        StringBuilder sb = new StringBuilder();
+        sb.append("\"").append(input).append("\"");
+        return sb.toString();
+    }
 }
diff --git a/src/com/android/settings/wifi/dpp/WifiQrCode.java b/src/com/android/settings/wifi/dpp/WifiQrCode.java
index ebc39c3..a8562bb 100644
--- a/src/com/android/settings/wifi/dpp/WifiQrCode.java
+++ b/src/com/android/settings/wifi/dpp/WifiQrCode.java
@@ -22,7 +22,8 @@
 import androidx.annotation.Keep;
 import androidx.annotation.VisibleForTesting;
 
-import java.util.regex.Matcher;
+import java.util.Arrays;
+import java.util.List;
 import java.util.regex.Pattern;
 
 /**
@@ -62,7 +63,12 @@
     public static final String PREFIX_ZXING_PASSWORD = "P:";
     public static final String PREFIX_ZXING_HIDDEN_SSID = "H:";
 
-    public static final String SUFFIX_QR_CODE = ";";
+    public static final String DELIMITER_QR_CODE = ";";
+
+    // Ignores password if security is SECURITY_NO_PASSWORD or absent
+    public static final String SECURITY_NO_PASSWORD = "nopass";
+    public static final String SECURITY_WEP = "WEP";
+    public static final String SECURITY_WPA = "WPA";
 
     private String mQrCode;
 
@@ -100,22 +106,27 @@
 
     /** Parses Wi-Fi DPP QR code string */
     private void parseWifiDppQrCode(String qrCode) throws IllegalArgumentException {
-        String publicKey = getSubStringOrNull(qrCode, PREFIX_DPP_PUBLIC_KEY, SUFFIX_QR_CODE);
+        List keyValueList = getKeyValueList(qrCode, PREFIX_DPP, DELIMITER_QR_CODE);
+
+        String publicKey = getValueOrNull(keyValueList, PREFIX_DPP_PUBLIC_KEY);
         if (TextUtils.isEmpty(publicKey)) {
             throw new IllegalArgumentException("Invalid format");
         }
         mPublicKey = publicKey;
 
-        mInformation = getSubStringOrNull(qrCode, PREFIX_DPP_INFORMATION, SUFFIX_QR_CODE);
+        mInformation = getValueOrNull(keyValueList, PREFIX_DPP_INFORMATION);
     }
 
     /** Parses ZXing reader library's Wi-Fi Network config format */
     private void parseZxingWifiQrCode(String qrCode) throws IllegalArgumentException {
-        String security = getSubStringOrNull(qrCode, PREFIX_ZXING_SECURITY, SUFFIX_QR_CODE);
-        String ssid = getSubStringOrNull(qrCode, PREFIX_ZXING_SSID, SUFFIX_QR_CODE);
-        String password = getSubStringOrNull(qrCode, PREFIX_ZXING_PASSWORD, SUFFIX_QR_CODE);
-        String hiddenSsidString = getSubStringOrNull(qrCode, PREFIX_ZXING_HIDDEN_SSID,
-                SUFFIX_QR_CODE);
+        List keyValueList = getKeyValueList(qrCode, PREFIX_ZXING_WIFI_NETWORK_CONFIG,
+                DELIMITER_QR_CODE);
+
+        String security = getValueOrNull(keyValueList, PREFIX_ZXING_SECURITY);
+        String ssid = getValueOrNull(keyValueList, PREFIX_ZXING_SSID);
+        String password = getValueOrNull(keyValueList, PREFIX_ZXING_PASSWORD);
+        String hiddenSsidString = getValueOrNull(keyValueList, PREFIX_ZXING_HIDDEN_SSID);
+
         boolean hiddenSsid = "true".equalsIgnoreCase(hiddenSsidString);
 
         //"\", ";", "," and ":" are escaped with a backslash "\", should remove at first
@@ -132,33 +143,37 @@
     }
 
     /**
-     * Gets the substring between prefix & suffix from input.
+     * Splits key/value pairs from qrCode
      *
-     * @param prefix the string before the returned substring
-     * @param suffix the string after the returned substring
-     * @return null if not exists, non-null otherwise
+     * @param qrCode the QR code raw string
+     * @param prefixQrCode the string before all key/value pairs in qrCode
+     * @param delimiter the string to split key/value pairs, can't contain a backslash
+     * @return a list contains string of key/value (e.g. K:key1)
      */
-    private static String getSubStringOrNull(String input, String prefix, String suffix) {
-        StringBuilder sb = new StringBuilder();
-        String regex = sb.append(prefix).append("(.*?)").append(suffix).toString();
-        Pattern pattern = Pattern.compile(regex);
-        Matcher matcher = pattern.matcher(input);
+    private List<String> getKeyValueList(String qrCode, String prefixQrCode,
+                String delimiter) {
+        String keyValueString = qrCode.substring(prefixQrCode.length());
 
-        if (!matcher.find()) {
-            return null;
+        // Should not treat \delimiter as a delimiter
+        String regex = "(?<!\\\\)" + Pattern.quote(delimiter);
+
+        List<String> result = Arrays.asList(keyValueString.split(regex));
+        return result;
+    }
+
+    private String getValueOrNull(List<String> keyValueList, String prefix) {
+        for (String keyValue : keyValueList) {
+            if (keyValue.startsWith(prefix)) {
+                return  keyValue.substring(prefix.length());
+            }
         }
 
-        String target = matcher.group(1);
-        if (TextUtils.isEmpty(target)) {
-            return null;
-        }
-
-        return target;
+        return null;
     }
 
     @Keep
     @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
-    protected static String removeBackSlash(String input) {
+    protected String removeBackSlash(String input) {
         if (input == null) {
             return null;
         }
diff --git a/src/com/android/settings/wifi/qrcode/QrCamera.java b/src/com/android/settings/wifi/qrcode/QrCamera.java
index c60c30e..af366bc 100644
--- a/src/com/android/settings/wifi/qrcode/QrCamera.java
+++ b/src/com/android/settings/wifi/qrcode/QrCamera.java
@@ -152,6 +152,15 @@
          * @param transform The transform to apply to the content of preview
          */
         void setTransform(Matrix transform);
+
+        /**
+         * Verify QR code is valid or not. The camera will stop scanning if this callback returns
+         * true.
+         *
+         * @param qrCode The result QR code after decoding.
+         * @return Returns true if qrCode hold valid information.
+         */
+        boolean isValid(String qrCode);
     }
 
     private void setCameraParameter() {
@@ -245,7 +254,9 @@
                         mReader.reset();
                     }
                     if (qrCode != null) {
-                        return qrCode.getText();
+                        if (mScannerCallback.isValid(qrCode.getText())) {
+                            return qrCode.getText();
+                        }
                     }
                 } catch (InterruptedException e) {
                     Thread.currentThread().interrupt();
diff --git a/src/com/android/settings/wifi/qrcode/QrDecorateView.java b/src/com/android/settings/wifi/qrcode/QrDecorateView.java
index 253bdb8..6952a63 100644
--- a/src/com/android/settings/wifi/qrcode/QrDecorateView.java
+++ b/src/com/android/settings/wifi/qrcode/QrDecorateView.java
@@ -17,10 +17,13 @@
 package com.android.settings.wifi.qrcode;
 
 import android.content.Context;
+import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.Point;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.util.AttributeSet;
@@ -33,11 +36,26 @@
  * Draws the lines at the corner of the inner frame.
  */
 public class QrDecorateView extends View {
-    private static final float CORNER_STROKE_WIDTH = 3f;    // 3dp
-    private static final float CORNER_LINE_LENGTH = 20f;    // 20dp
+    private static final float CORNER_STROKE_WIDTH = 4f;    // 4dp
+    private static final float CORNER_LINE_LENGTH = 264f;   // 264dp
+    private static final float CORNER_RADIUS = 16f;         // 16dp
 
-    final private Paint mPaint;
-    private RectF mFrame;
+    final private int mCornerColor;
+    final private int mFocusedCornerColor;
+    final private int mBackgroundColor;
+
+    final private Paint mStrokePaint;
+    final private Paint mTransparentPaint;
+    final private Paint mBackgroundPaint;
+
+    final private float mRadius;
+
+    private Bitmap mMaskBitmap;
+    private Canvas mMaskCanvas;
+
+    private RectF mOuterFrame;
+    private RectF mInnerFrame;
+
     private boolean mFocused;
 
     public QrDecorateView(Context context) {
@@ -54,78 +72,66 @@
 
     public QrDecorateView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
-        final float strokeWidth = TypedValue.applyDimension(
-                TypedValue.COMPLEX_UNIT_DIP,
-                CORNER_STROKE_WIDTH,
-                getResources().getDisplayMetrics()
-        );
-        mPaint = new Paint();
-        mPaint.setStrokeWidth(strokeWidth);
+
         mFocused = false;
+        mRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, CORNER_RADIUS,
+                getResources().getDisplayMetrics());
+
+        mCornerColor = context.getResources().getColor(R.color.qr_corner_line_color);
+        mFocusedCornerColor = context.getResources().getColor(R.color.qr_focused_corner_line_color);
+        mBackgroundColor = context.getResources().getColor(R.color.qr_background_color);
+
+        mStrokePaint = new Paint();
+        mStrokePaint.setAntiAlias(true);
+
+        mTransparentPaint = new Paint();
+        mTransparentPaint.setAntiAlias(true);
+        mTransparentPaint.setColor(getResources().getColor(android.R.color.transparent));
+        mTransparentPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
+
+        mBackgroundPaint = new Paint();
+        mBackgroundPaint.setColor(mBackgroundColor);
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
+
+        if(mMaskBitmap == null) {
+            mMaskBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
+            mMaskCanvas = new Canvas(mMaskBitmap);
+        }
+
+        calculateFramePos();
     }
 
     @Override
     protected void onDraw(Canvas canvas) {
-        calculateFramePos();
-        final float cornerLineLength = TypedValue.applyDimension(
-                TypedValue.COMPLEX_UNIT_DIP,
-                CORNER_LINE_LENGTH,
-                getResources().getDisplayMetrics()
-        );
-        mPaint.setColor(mFocused ? Color.GREEN : Color.WHITE);
-        drawCorner(mFrame, cornerLineLength, canvas);
-        super.onDraw(canvas);
-    }
+        // Set frame line color.
+        mStrokePaint.setColor(mFocused ? mFocusedCornerColor : mCornerColor);
+        // Draw background color.
+        mMaskCanvas.drawColor(mBackgroundColor);
+        // Draw outer corner.
+        mMaskCanvas.drawRoundRect(mOuterFrame, mRadius, mRadius, mStrokePaint);
+        // Draw inner transparent corner.
+        mMaskCanvas.drawRoundRect(mInnerFrame, mRadius, mRadius, mTransparentPaint);
 
-    private void drawCorner(RectF frame, float lineLength, Canvas canvas) {
-        final float strokeWidth = TypedValue.applyDimension(
-                TypedValue.COMPLEX_UNIT_DIP,
-                CORNER_STROKE_WIDTH,
-                getResources().getDisplayMetrics()
-        );
-        // Draw top-left corner.
-        canvas.drawLine(
-                frame.left - strokeWidth / 2,
-                frame.top,
-                frame.left + lineLength,
-                frame.top,
-                mPaint);
-        canvas.drawLine(frame.left, frame.top, frame.left, frame.top + lineLength, mPaint);
-        // Draw top-right corner.
-        canvas.drawLine(
-                frame.right + strokeWidth / 2,
-                frame.top,
-                frame.right - lineLength,
-                frame.top,
-                mPaint);
-        canvas.drawLine(frame.right, frame.top, frame.right, frame.top + lineLength, mPaint);
-        // Draw bottom-left corner.
-        canvas.drawLine(
-                frame.left - strokeWidth / 2,
-                frame.bottom,
-                frame.left + lineLength,
-                frame.bottom,
-                mPaint);
-        canvas.drawLine(frame.left, frame.bottom, frame.left, frame.bottom - lineLength, mPaint);
-        // Draw bottom-right corner.
-        canvas.drawLine(
-                frame.right + strokeWidth / 2,
-                frame.bottom,
-                frame.right - lineLength,
-                frame.bottom,
-                mPaint);
-        canvas.drawLine(frame.right, frame.bottom, frame.right, frame.bottom - lineLength, mPaint);
+        canvas.drawBitmap(mMaskBitmap, 0, 0, mBackgroundPaint);
+        super.onDraw(canvas);
     }
 
     private void calculateFramePos() {
         final int centralX = getWidth() / 2;
         final int centralY = getHeight() / 2;
-        final float halfFrameWidth = getWidth() / 3;
-        mFrame = new RectF(
-                centralX - halfFrameWidth,
-                centralY - halfFrameWidth,
-                centralX + halfFrameWidth,
-                centralY + halfFrameWidth);
+        final float cornerLineLength = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+                CORNER_LINE_LENGTH, getResources().getDisplayMetrics()) / 2;
+        final float strokeWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+                CORNER_STROKE_WIDTH, getResources().getDisplayMetrics()) / 2;
+
+        mOuterFrame = new RectF(centralX - cornerLineLength, centralY - cornerLineLength,
+                centralX + cornerLineLength, centralY + cornerLineLength);
+        mInnerFrame = new RectF(mOuterFrame.left + strokeWidth, mOuterFrame.top + strokeWidth,
+                mOuterFrame.right - strokeWidth, mOuterFrame.bottom - strokeWidth);
     }
 
     // Draws green lines if focued. Otherwise, draws white lines.
diff --git a/tests/robotests/src/com/android/settings/wifi/details/WifiPrivacyPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/details/WifiPrivacyPreferenceControllerTest.java
index 8bbb2be..20c5838 100644
--- a/tests/robotests/src/com/android/settings/wifi/details/WifiPrivacyPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/details/WifiPrivacyPreferenceControllerTest.java
@@ -38,8 +38,8 @@
 @RunWith(RobolectricTestRunner.class)
 public class WifiPrivacyPreferenceControllerTest {
 
-    private static final int PRIVACY_RANDOMIZED = 0;
-    private static final int PRIVACY_TRUSTED = 1;
+    private static final int PRIVACY_RANDOMIZED = WifiConfiguration.RANDOMIZATION_PERSISTENT;
+    private static final int PRIVACY_TRUSTED = WifiConfiguration.RANDOMIZATION_NONE;
 
     @Mock
     private WifiConfiguration mWifiConfiguration;
@@ -47,6 +47,7 @@
     private WifiPrivacyPreferenceController mPreferenceController;
     private Context mContext;
     private DropDownPreference mDropDownPreference;
+    private String[] perferenceString;
 
     @Before
     public void setUp() {
@@ -59,6 +60,8 @@
         mDropDownPreference = new DropDownPreference(mContext);
         mDropDownPreference.setEntries(R.array.wifi_privacy_entries);
         mDropDownPreference.setEntryValues(R.array.wifi_privacy_values);
+
+        perferenceString = mContext.getResources().getStringArray(R.array.wifi_privacy_entries);
     }
 
     @Test
@@ -67,7 +70,8 @@
 
         mPreferenceController.updateState(mDropDownPreference);
 
-        assertThat(mDropDownPreference.getEntry()).isEqualTo("Trusted");
+
+        assertThat(mDropDownPreference.getEntry()).isEqualTo(perferenceString[PRIVACY_TRUSTED]);
     }
 
     @Test
@@ -76,7 +80,7 @@
 
         mPreferenceController.updateState(mDropDownPreference);
 
-        assertThat(mDropDownPreference.getEntry()).isEqualTo("Default (use randomized MAC)");
+        assertThat(mDropDownPreference.getEntry()).isEqualTo(perferenceString[PRIVACY_RANDOMIZED]);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/wifi/dpp/WifiNetworkConfigTest.java b/tests/robotests/src/com/android/settings/wifi/dpp/WifiNetworkConfigTest.java
new file mode 100644
index 0000000..1b7c0a8
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/wifi/dpp/WifiNetworkConfigTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package com.android.settings.wifi.dpp;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Intent;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+public class WifiNetworkConfigTest {
+    private WifiNetworkConfig mWifiConfig;
+
+    @Before
+    public void setUp() {
+        Intent intent = new Intent();
+        intent.putExtra(WifiDppUtils.EXTRA_WIFI_SSID, "Pixel:_ABCD;");
+        intent.putExtra(WifiDppUtils.EXTRA_WIFI_SECURITY, "WPA");
+        intent.putExtra(WifiDppUtils.EXTRA_WIFI_PRE_SHARED_KEY, "\\012345678,");
+        mWifiConfig = WifiNetworkConfig.getValidConfigOrNull(intent);
+    }
+
+    @Test
+    public void testInitConfig_IntentReceived_QRCodeValue() {
+        String qrcode = mWifiConfig.getQrCode();
+        assertThat(qrcode).isEqualTo("WIFI:S:Pixel\\:_ABCD\\;;T:WPA;P:\\\\012345678\\,;H:false;;");
+    }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/wifi/qrcode/QrCameraTest.java b/tests/robotests/src/com/android/settings/wifi/qrcode/QrCameraTest.java
index 0ef0273..a57fefc 100644
--- a/tests/robotests/src/com/android/settings/wifi/qrcode/QrCameraTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/qrcode/QrCameraTest.java
@@ -85,6 +85,11 @@
         public void setTransform(Matrix transform) {
             // Do nothing
         }
+
+        @Override
+        public boolean isValid(String qrCode) {
+            return true;
+        }
     }
 
     private ScannerTestCallback mScannerCallback;
diff --git a/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java
index 235f182..61033e9 100644
--- a/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java
+++ b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivityTest.java
@@ -80,4 +80,20 @@
         assertThat(activity instanceof WifiDppQrCodeGeneratorFragment
                 .OnQrCodeGeneratorFragmentAddButtonClickedListener).isEqualTo(true);
     }
+
+    @Test
+    public void testActivity_shouldImplementsOnScanWifiDppSuccessCallback() {
+        WifiDppConfiguratorActivity activity = mActivityRule.getActivity();
+
+        assertThat(activity instanceof WifiDppQrCodeScannerFragment
+                .OnScanWifiDppSuccessListener).isEqualTo(true);
+    }
+
+    @Test
+    public void testActivity_shouldImplementsOnScanZxingWifiFormatSuccessCallback() {
+        WifiDppConfiguratorActivity activity = mActivityRule.getActivity();
+
+        assertThat(activity instanceof WifiDppQrCodeScannerFragment
+                .OnScanZxingWifiFormatSuccessListener).isEqualTo(true);
+    }
 }
diff --git a/tests/unit/src/com/android/settings/wifi/dpp/WifiDppEnrolleeActivityTest.java b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppEnrolleeActivityTest.java
new file mode 100644
index 0000000..283da13
--- /dev/null
+++ b/tests/unit/src/com/android/settings/wifi/dpp/WifiDppEnrolleeActivityTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package com.android.settings.wifi.dpp;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class WifiDppEnrolleeActivityTest {
+    @Rule
+    public final ActivityTestRule<WifiDppEnrolleeActivity> mActivityRule =
+            new ActivityTestRule<>(WifiDppEnrolleeActivity.class);
+
+    @Test
+    public void testActivity_shouldImplementsOnScanWifiDppSuccessCallback() {
+        WifiDppEnrolleeActivity activity = mActivityRule.getActivity();
+
+        assertThat(activity instanceof WifiDppQrCodeScannerFragment
+                .OnScanWifiDppSuccessListener).isEqualTo(true);
+    }
+
+    @Test
+    public void testActivity_shouldImplementsOnScanZxingWifiFormatSuccessCallback() {
+        WifiDppEnrolleeActivity activity = mActivityRule.getActivity();
+
+        assertThat(activity instanceof WifiDppQrCodeScannerFragment
+                .OnScanZxingWifiFormatSuccessListener).isEqualTo(true);
+    }
+}
diff --git a/tests/unit/src/com/android/settings/wifi/dpp/WifiQrCodetest.java b/tests/unit/src/com/android/settings/wifi/dpp/WifiQrCodeTest.java
similarity index 83%
rename from tests/unit/src/com/android/settings/wifi/dpp/WifiQrCodetest.java
rename to tests/unit/src/com/android/settings/wifi/dpp/WifiQrCodeTest.java
index 775ca48..3595597 100644
--- a/tests/unit/src/com/android/settings/wifi/dpp/WifiQrCodetest.java
+++ b/tests/unit/src/com/android/settings/wifi/dpp/WifiQrCodeTest.java
@@ -29,7 +29,7 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class WifiQrCodetest {
+public class WifiQrCodeTest {
     // Valid Wi-Fi DPP QR code & it's parameters
     private static final String VALID_WIFI_DPP_QR_CODE = "DPP:I:SN=4774LH2b4044;M:010203040506;K:"
             + "MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgADURzxmttZoIRIPWGoQMV00XHWCAQIhXruVWOz0NjlkIA=;;";
@@ -57,6 +57,13 @@
     private static final String SSID_OF_VALID_ZXING_WIFI_QR_CODE = "mynetwork";
     private static final String PASSWORD_OF_VALID_ZXING_WIFI_QR_CODE = "mypass";
 
+    // Valid ZXing reader library's Wi-Fi Network config format - escaped characters
+    private static final String VALID_ZXING_WIFI_QR_CODE_SPECIAL_CHARACTERS =
+            "WIFI:T:WPA;S:mynetwork;P:m\\;y\\:p\\\\a\\,ss;H:true;;";
+
+    private static final String PASSWORD_OF_VALID_ZXING_WIFI_QR_CODE_SPECIAL_CHARACTERS =
+            "m;y:p\\a,ss";
+
     // Invalid scheme QR code
     private static final String INVALID_SCHEME_QR_CODE = "BT:T:WPA;S:mynetwork;P:mypass;H:true;;";
 
@@ -118,19 +125,35 @@
 
         assertEquals(WifiQrCode.SCHEME_ZXING_WIFI_NETWORK_CONFIG, wifiQrCode.getScheme());
         assertNotNull(config);
-        assertNull(config.getSecurity());
+        assertEquals("", config.getSecurity());
         assertEquals(SSID_OF_VALID_ZXING_WIFI_QR_CODE, config.getSsid());
-        assertNull(config.getPreSharedKey());
+        assertEquals("", config.getPreSharedKey());
         assertEquals(false, config.getHiddenSsid());
     }
 
     @Test
+    public void parseValidZxingWifiQrCode_specialCharacters() {
+        WifiQrCode wifiQrCode = new WifiQrCode(VALID_ZXING_WIFI_QR_CODE_SPECIAL_CHARACTERS);
+        WifiNetworkConfig config = wifiQrCode.getWifiNetworkConfig();
+
+        assertEquals(WifiQrCode.SCHEME_ZXING_WIFI_NETWORK_CONFIG, wifiQrCode.getScheme());
+        assertNotNull(config);
+        assertEquals(SECURITY_OF_VALID_ZXING_WIFI_QR_CODE, config.getSecurity());
+        assertEquals(SSID_OF_VALID_ZXING_WIFI_QR_CODE, config.getSsid());
+        assertEquals(PASSWORD_OF_VALID_ZXING_WIFI_QR_CODE_SPECIAL_CHARACTERS,
+                config.getPreSharedKey());
+        assertEquals(true, config.getHiddenSsid());
+    }
+
+    @Test
     public void testRemoveBackSlash() {
-        assertEquals("\\", WifiQrCode.removeBackSlash("\\\\"));
-        assertEquals("ab", WifiQrCode.removeBackSlash("a\\b"));
-        assertEquals("a", WifiQrCode.removeBackSlash("\\a"));
-        assertEquals("\\b", WifiQrCode.removeBackSlash("\\\\b"));
-        assertEquals("c\\", WifiQrCode.removeBackSlash("c\\\\"));
+        WifiQrCode wifiQrCode = new WifiQrCode(VALID_WIFI_DPP_QR_CODE);
+
+        assertEquals("\\", wifiQrCode.removeBackSlash("\\\\"));
+        assertEquals("ab", wifiQrCode.removeBackSlash("a\\b"));
+        assertEquals("a", wifiQrCode.removeBackSlash("\\a"));
+        assertEquals("\\b", wifiQrCode.removeBackSlash("\\\\b"));
+        assertEquals("c\\", wifiQrCode.removeBackSlash("c\\\\"));
     }
 
     @Test