Implement Wi-Fi DPP flow

1. Wi-Fi DPP hanshake fail UI
2. Show Wi-Fi DPP QR code information field on WifiDppAddDeviceFragment if it's available.
3. Click 'Choose Different Network' button will show WifiDppChooseSavedWifiNetworkFragment
4. After QR code scanner scans success, WifiDppConfiguratorActivity caches WifiQrCode instead
   of just a QR code string

Bug: 122429170
Test: manual test
Change-Id: I1ce1b014ff86903b5a7a8f3575cc98eb1079583c
This commit is contained in:
Arc Wang
2019-01-09 11:54:38 +08:00
parent 7a14f706e1
commit a7d51370c8
7 changed files with 92 additions and 53 deletions

View File

@@ -2104,6 +2104,12 @@
<string name="wifi_dpp_add_another_device">Add another device</string>
<!-- Button label to choose different Wi-Fi network [CHAR LIMIT=80] -->
<string name="wifi_dpp_choose_different_network">Choose different network</string>
<!-- Hint for QR code detection [CHAR LIMIT=50] -->
<string name="wifi_dpp_could_not_add_device">Couldn\u2019t add device</string>
<!-- Title for the fragment to show that device found but naming known [CHAR LIMIT=50] -->
<string name="wifi_dpp_device_found">Device found</string>
<!-- Label for the try again button [CHAR LIMIT=20]-->
<string name="retry">Retry</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 -->

View File

@@ -21,6 +21,7 @@ import android.app.Activity;
import android.content.Context;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -55,6 +56,7 @@ public class WifiDppAddDeviceFragment extends WifiDppQrCodeBaseFragment {
// Update success UI.
mTitle.setText(R.string.wifi_dpp_wifi_shared_with_device);
mSummary.setVisibility(View.INVISIBLE);
mChooseDifferentNetwork.setVisibility(View.INVISIBLE);
mButtonLeft.setText(R.string.wifi_dpp_add_another_device);
mButtonLeft.setOnClickListener(v -> getFragmentManager().popBackStack());
mButtonRight.setText(R.string.done);
@@ -63,8 +65,13 @@ public class WifiDppAddDeviceFragment extends WifiDppQrCodeBaseFragment {
@Override
public void onFailure(int code) {
//TODO(b/122429170): Show DPP configuration error state UI
Log.d(TAG, "DppStatusCallback.onFailure " + code);
// Update fail UI.
mTitle.setText(R.string.wifi_dpp_could_not_add_device);
mSummary.setVisibility(View.INVISIBLE);
mChooseDifferentNetwork.setVisibility(View.INVISIBLE);
mButtonRight.setText(R.string.retry);
}
@Override
@@ -99,6 +106,15 @@ public class WifiDppAddDeviceFragment extends WifiDppQrCodeBaseFragment {
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
final WifiQrCode wifiQrCode = ((WifiDppConfiguratorActivity) getActivity())
.getWifiDppQrCode();
final String information = wifiQrCode.getInformation();
if (TextUtils.isEmpty(information)) {
mTitle.setText(R.string.wifi_dpp_device_found);
} else {
mTitle.setText(information);
}
final WifiNetworkConfig wifiNetworkConfig = ((WifiDppConfiguratorActivity) getActivity())
.getWifiNetworkConfig();
if (!WifiNetworkConfig.isValidConfig(wifiNetworkConfig)) {
@@ -110,7 +126,8 @@ public class WifiDppAddDeviceFragment extends WifiDppQrCodeBaseFragment {
mWifiApPictureView = view.findViewById(R.id.wifi_ap_picture_view);
mChooseDifferentNetwork = view.findViewById(R.id.choose_different_network);
mChooseDifferentNetwork.setOnClickListener(v -> getFragmentManager().popBackStack());
mChooseDifferentNetwork.setOnClickListener(v ->
mClickChooseDifferentNetworkListener.onClickChooseDifferentNetwork());
mButtonLeft = view.findViewById(R.id.button_left);
mButtonLeft.setText(R.string.cancel);
@@ -125,11 +142,34 @@ public class WifiDppAddDeviceFragment extends WifiDppQrCodeBaseFragment {
}
private void startWifiDppInitiator() {
final String enrolleeUri = ((WifiDppConfiguratorActivity) getActivity()).getDppUri();
final WifiQrCode wifiQrCode = ((WifiDppConfiguratorActivity) getActivity())
.getWifiDppQrCode();
final String qrCode = wifiQrCode.getQrCode();
final int networkId =
((WifiDppConfiguratorActivity) getActivity()).getWifiNetworkConfig().getNetworkId();
final WifiManager wifiManager = getContext().getSystemService(WifiManager.class);
wifiManager.startDppAsConfiguratorInitiator(enrolleeUri, networkId,
wifiManager.startDppAsConfiguratorInitiator(qrCode, networkId,
WifiManager.DPP_NETWORK_ROLE_STA, /* handler */ null, new DppStatusCallback());
}
// Container Activity must implement this interface
public interface OnClickChooseDifferentNetworkListener {
public void onClickChooseDifferentNetwork();
}
OnClickChooseDifferentNetworkListener mClickChooseDifferentNetworkListener;
@Override
public void onAttach(Context context) {
super.onAttach(context);
mClickChooseDifferentNetworkListener = (OnClickChooseDifferentNetworkListener) context;
}
@Override
public void onDetach() {
mClickChooseDifferentNetworkListener = null;
super.onDetach();
}
}

View File

@@ -51,7 +51,8 @@ public class WifiDppConfiguratorActivity extends InstrumentedActivity implements
WifiNetworkConfig.Retriever,
WifiDppQrCodeGeneratorFragment.OnQrCodeGeneratorFragmentAddButtonClickedListener,
WifiDppQrCodeScannerFragment.OnScanWifiDppSuccessListener,
WifiDppQrCodeScannerFragment.OnScanZxingWifiFormatSuccessListener {
WifiDppQrCodeScannerFragment.OnScanZxingWifiFormatSuccessListener,
WifiDppAddDeviceFragment.OnClickChooseDifferentNetworkListener {
private static final String TAG = "WifiDppConfiguratorActivity";
public static final String ACTION_CONFIGURATOR_QR_CODE_SCANNER =
@@ -66,9 +67,6 @@ public class WifiDppConfiguratorActivity extends InstrumentedActivity implements
/** The Wi-Fi network which will be configured */
private WifiNetworkConfig mWifiNetworkConfig;
/** The uri from Wi-Fi DPP QR code */
private String mDppUri;
/** The Wi-Fi DPP QR code from intent ACTION_PROCESS_WIFI_DPP_QR_CODE */
private WifiQrCode mWifiDppQrCode;
@@ -117,7 +115,7 @@ public class WifiDppConfiguratorActivity extends InstrumentedActivity implements
break;
case ACTION_PROCESS_WIFI_DPP_QR_CODE:
String qrCode = intent.getStringExtra(WifiDppUtils.EXTRA_QR_CODE);
mWifiDppQrCode = getValidWiFiDppQrCodeOrNull(qrCode);
mWifiDppQrCode = getValidWifiDppQrCodeOrNull(qrCode);
if (mWifiDppQrCode == null) {
cancelActivity = true;
} else {
@@ -205,7 +203,7 @@ public class WifiDppConfiguratorActivity extends InstrumentedActivity implements
fragmentTransaction.commit();
}
private WifiQrCode getValidWiFiDppQrCodeOrNull(String qrCode) {
private WifiQrCode getValidWifiDppQrCodeOrNull(String qrCode) {
WifiQrCode wifiQrCode;
try {
wifiQrCode = new WifiQrCode(qrCode);
@@ -225,10 +223,6 @@ public class WifiDppConfiguratorActivity extends InstrumentedActivity implements
return mWifiNetworkConfig;
}
public String getDppUri() {
return mDppUri;
}
public WifiQrCode getWifiDppQrCode() {
return mWifiDppQrCode;
}
@@ -263,17 +257,21 @@ public class WifiDppConfiguratorActivity extends InstrumentedActivity implements
}
@Override
public void onScanWifiDppSuccess(String uri) {
mDppUri = uri;
public void onScanWifiDppSuccess(WifiQrCode wifiQrCode) {
mWifiDppQrCode = wifiQrCode;
showAddDeviceFragment(/* addToBackStack */ true);
}
@Override
public void onScanZxingWifiFormatSuccess(WifiNetworkConfig wifiNetworkConfig) {
mDppUri = null;
mWifiNetworkConfig = new WifiNetworkConfig(wifiNetworkConfig);
// Do nothing, it's impossible to be a configurator without a Wi-Fi DPP QR code
}
showAddDeviceFragment(/* addToBackStack */ true);
@Override
public void onClickChooseDifferentNetwork() {
mWifiNetworkConfig = null;
showChooseSavedWifiNetworkFragment(/* addToBackStack */ true);
}
}

View File

@@ -145,9 +145,10 @@ public class WifiDppEnrolleeActivity extends InstrumentedActivity implements
}
@Override
public void onScanWifiDppSuccess(String uri) {
public void onScanWifiDppSuccess(WifiQrCode wifiQrCode) {
final WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
wifiManager.startDppAsEnrolleeInitiator(uri, /* handler */ null, new DppStatusCallback());
wifiManager.startDppAsEnrolleeInitiator(wifiQrCode.getQrCode(), /* handler */ null,
new DppStatusCallback());
}
@Override

View File

@@ -100,7 +100,7 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
// Container Activity must implement this interface
public interface OnScanWifiDppSuccessListener {
public void onScanWifiDppSuccess(String uri);
public void onScanWifiDppSuccess(WifiQrCode wifiQrCode);
}
OnScanWifiDppSuccessListener mScanWifiDppSuccessListener;
@@ -108,7 +108,7 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
public interface OnScanZxingWifiFormatSuccessListener {
public void onScanZxingWifiFormatSuccess(WifiNetworkConfig wifiNetworkConfig);
}
OnScanZxingWifiFormatSuccessListener mScanScanZxingWifiFormatSuccessListener;
OnScanZxingWifiFormatSuccessListener mScanZxingWifiFormatSuccessListener;
/**
* Configurator container activity of the fragment should create instance with this constructor.
@@ -146,13 +146,13 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
super.onAttach(context);
mScanWifiDppSuccessListener = (OnScanWifiDppSuccessListener) context;
mScanScanZxingWifiFormatSuccessListener = (OnScanZxingWifiFormatSuccessListener) context;
mScanZxingWifiFormatSuccessListener = (OnScanZxingWifiFormatSuccessListener) context;
}
@Override
public void onDetach() {
mScanWifiDppSuccessListener = null;
mScanScanZxingWifiFormatSuccessListener = null;
mScanZxingWifiFormatSuccessListener = null;
super.onDetach();
}
@@ -278,11 +278,11 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
public void handleSuccessfulResult(String qrCode) {
switch (mWifiQrCode.getScheme()) {
case WifiQrCode.SCHEME_DPP:
handleWifiDpp(qrCode);
handleWifiDpp();
break;
case WifiQrCode.SCHEME_ZXING_WIFI_NETWORK_CONFIG:
handleZxingWifiFormat(mWifiQrCode.getWifiNetworkConfig());
handleZxingWifiFormat();
break;
default:
@@ -290,25 +290,22 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
}
}
private void handleWifiDpp(String uri) {
private void handleWifiDpp() {
destroyCamera();
mDecorateView.setFocused(true);
final Bundle bundle = new Bundle();
bundle.putString(KEY_PUBLIC_URI, uri);
Message message = mHandler.obtainMessage(MESSAGE_SCAN_WIFI_DPP_SUCCESS);
message.setData(bundle);
message.obj = new WifiQrCode(mWifiQrCode.getQrCode());
mHandler.sendMessageDelayed(message, SHOW_SUCCESS_SQUARE_INTERVAL);
}
private void handleZxingWifiFormat(WifiNetworkConfig wifiNetworkConfig) {
private void handleZxingWifiFormat() {
destroyCamera();
mDecorateView.setFocused(true);
Message message = mHandler.obtainMessage(MESSAGE_SCAN_ZXING_WIFI_FORMAT_SUCCESS);
message.obj = wifiNetworkConfig;
message.obj = new WifiQrCode(mWifiQrCode.getQrCode()).getWifiNetworkConfig();
mHandler.sendMessageDelayed(message, SHOW_SUCCESS_SQUARE_INTERVAL);
}
@@ -359,17 +356,14 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
if (mScanWifiDppSuccessListener == null) {
return;
}
final Bundle bundle = msg.getData();
final String uri = bundle.getString(KEY_PUBLIC_URI);
mScanWifiDppSuccessListener.onScanWifiDppSuccess(uri);
mScanWifiDppSuccessListener.onScanWifiDppSuccess((WifiQrCode)msg.obj);
break;
case MESSAGE_SCAN_ZXING_WIFI_FORMAT_SUCCESS:
if (mScanScanZxingWifiFormatSuccessListener == null) {
if (mScanZxingWifiFormatSuccessListener == null) {
return;
}
mScanScanZxingWifiFormatSuccessListener.onScanZxingWifiFormatSuccess(
mScanZxingWifiFormatSuccessListener.onScanZxingWifiFormatSuccess(
(WifiNetworkConfig)msg.obj);
break;

View File

@@ -20,7 +20,6 @@ import android.content.Intent;
import android.net.wifi.WifiConfiguration;
import android.text.TextUtils;
import androidx.annotation.Keep;
import androidx.annotation.VisibleForTesting;
import java.util.Arrays;
@@ -49,7 +48,6 @@ import java.util.regex.Pattern;
* H true Optional. True if the network SSID is hidden.
*
*/
@Keep
public class WifiQrCode {
public static final String SCHEME_DPP = "DPP";
public static final String SCHEME_ZXING_WIFI_NETWORK_CONFIG = "WIFI";
@@ -86,7 +84,6 @@ public class WifiQrCode {
// Data from parsed ZXing reader library's Wi-Fi Network config format
private WifiNetworkConfig mWifiNetworkConfig;
@Keep
public WifiQrCode(String qrCode) throws IllegalArgumentException {
if (TextUtils.isEmpty(qrCode)) {
throw new IllegalArgumentException("Empty QR code");
@@ -172,7 +169,6 @@ public class WifiQrCode {
return null;
}
@Keep
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
protected String removeBackSlash(String input) {
if (input == null) {
@@ -199,7 +195,6 @@ public class WifiQrCode {
return sb.toString();
}
@Keep
public String getQrCode() {
return mQrCode;
}
@@ -210,25 +205,22 @@ public class WifiQrCode {
* SCHEME_DPP for standard Wi-Fi device provision protocol; SCHEME_ZXING_WIFI_NETWORK_CONFIG
* for ZXing reader library' Wi-Fi Network config format
*/
@Keep
public String getScheme() {
return mScheme;
}
/** Available when {@code getScheme()} returns SCHEME_DPP */
@Keep
public String getPublicKey() {
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
protected String getPublicKey() {
return mPublicKey;
}
/** May be available when {@code getScheme()} returns SCHEME_DPP */
@Keep
public String getInformation() {
return mInformation;
}
/** Available when {@code getScheme()} returns SCHEME_ZXING_WIFI_NETWORK_CONFIG */
@Keep
public WifiNetworkConfig getWifiNetworkConfig() {
if (mWifiNetworkConfig == null) {
return null;

View File

@@ -101,4 +101,12 @@ public class WifiDppConfiguratorActivityTest {
assertThat(activity instanceof WifiDppQrCodeScannerFragment
.OnScanZxingWifiFormatSuccessListener).isEqualTo(true);
}
@Test
public void testActivity_shouldImplementsOnClickChooseDifferentNetworkCallback() {
WifiDppConfiguratorActivity activity = mActivityRule.getActivity();
assertThat(activity instanceof WifiDppAddDeviceFragment
.OnClickChooseDifferentNetworkListener).isEqualTo(true);
}
}