[NetworkRequest] Implement Single Specified SSID ALTERNATE FLOW V2

Implement new flow for Single SSID mode of NetworkRequestDialog.
There is a new design for single SSID mode of NetworkRequestDialog.

Bug: b/132904234
Test: make RunSettingsRoboTests -j32 ROBOTEST_FILTER=com.android.settings.wifi
Change-Id: Ice19842243ea6f24a3ea74cf6e90a473080b8983
This commit is contained in:
cosmohsieh
2019-07-11 10:23:45 +08:00
parent 395393bf68
commit a5e0148c7a
9 changed files with 480 additions and 269 deletions

View File

@@ -11138,6 +11138,10 @@
<string name="network_connection_connect_successful">Connection successful</string> <string name="network_connection_connect_successful">Connection successful</string>
<!-- Neutral button for Network connection request Dialog [CHAR LIMIT=30] --> <!-- Neutral button for Network connection request Dialog [CHAR LIMIT=30] -->
<string name="network_connection_request_dialog_showall">Show all</string> <string name="network_connection_request_dialog_showall">Show all</string>
<!-- Message for Network connection searching progress Dialog. Searching for wifi ap. [CHAR LIMIT=40] -->
<string name="network_connection_searching_message">Searching for device\u2026</string>
<!-- Message for Network connection connecting progress Dialog. Try to connect to wifi ap.[CHAR LIMIT=40] -->
<string name="network_connection_connecting_message">Connecting to device\u2026</string>
<!-- Summary for bluetooth devices count in Bluetooth devices slice. [CHAR LIMIT=NONE] --> <!-- Summary for bluetooth devices count in Bluetooth devices slice. [CHAR LIMIT=NONE] -->
<plurals name="show_bluetooth_devices"> <plurals name="show_bluetooth_devices">

View File

@@ -16,23 +16,242 @@
package com.android.settings.wifi; package com.android.settings.wifi;
import android.app.ProgressDialog;
import android.content.Intent;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.NetworkRequestMatchCallback;
import android.net.wifi.WifiManager.NetworkRequestUserSelectionCallback;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.Toast;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentActivity;
import com.android.settings.R;
import com.android.settings.wifi.NetworkRequestErrorDialogFragment.ERROR_DIALOG_TYPE;
import java.util.List;
/** /**
* When other applications request to have a wifi connection, framework will bring up this activity * When other applications request to have a wifi connection, framework will bring up this activity
* to let user select which wifi ap wanna to connect. This activity is just a door for framework * to let user select which wifi ap wanna to connect. This activity contains
* call, and main functional process is at {@code NetworkRequestDialogFragment}. * {@code NetworkRequestDialogFragment}, {@code NetworkRequestSingleSsidDialogFragment} to show UI
* and handles framework callback.
*/ */
public class NetworkRequestDialogActivity extends FragmentActivity { public class NetworkRequestDialogActivity extends FragmentActivity implements
NetworkRequestMatchCallback {
private static String TAG = "NetworkRequestDialogActivity";
/** Message sent to stop scanning wifi and pop up timeout dialog. */
private static final int MESSAGE_STOP_SCAN_WIFI_LIST = 0;
/** Delayed time to stop scanning wifi. */
private static final int DELAY_TIME_STOP_SCAN_MS = 30 * 1000;
final static String EXTRA_IS_SPECIFIED_SSID =
"com.android.settings.wifi.extra.REQUEST_IS_FOR_SINGLE_NETWORK";
private NetworkRequestDialogBaseFragment mDialogFragment;
private NetworkRequestUserSelectionCallback mUserSelectionCallback;
private boolean mIsSpecifiedSsid;
private boolean mShowingErrorDialog;
private WifiConfiguration mMatchedConfig;
private ProgressDialog mProgressDialog;
@Override @Override
protected void onCreate(@Nullable Bundle savedInstanceState) { protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
final NetworkRequestDialogFragment fragment = NetworkRequestDialogFragment.newInstance(); final Intent intent = getIntent();
fragment.show(getSupportFragmentManager(), "NetworkRequestDialogFragment"); if (intent != null) {
mIsSpecifiedSsid = intent.getBooleanExtra(EXTRA_IS_SPECIFIED_SSID, false);
}
if (mIsSpecifiedSsid) {
showProgressDialog(getString(R.string.network_connection_searching_message));
} else {
mDialogFragment = NetworkRequestDialogFragment.newInstance();
mDialogFragment.show(getSupportFragmentManager(), TAG);
}
}
private void showProgressDialog(String message) {
dismissDialogs();
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setIndeterminate(true);
mProgressDialog.setCancelable(false);
mProgressDialog.setMessage(message);
mProgressDialog.show();
}
private void showSingleSsidRequestDialog(String ssid, boolean isTryAgain) {
dismissDialogs();
mDialogFragment = new NetworkRequestSingleSsidDialogFragment();
final Bundle bundle = new Bundle();
bundle.putString(NetworkRequestSingleSsidDialogFragment.EXTRA_SSID, ssid);
bundle.putBoolean(NetworkRequestSingleSsidDialogFragment.EXTRA_TRYAGAIN, isTryAgain);
mDialogFragment.setArguments(bundle);
mDialogFragment.show(getSupportFragmentManager(), TAG);
}
private void dismissDialogs() {
if (mDialogFragment != null) {
mDialogFragment.dismiss();
mDialogFragment = null;
}
if (mProgressDialog != null) {
mProgressDialog.dismiss();
mProgressDialog = null;
}
}
@Override
protected void onResume() {
super.onResume();
final WifiManager wifiManager = getSystemService(WifiManager.class);
if (wifiManager != null) {
wifiManager.registerNetworkRequestMatchCallback(this, mHandler);
}
// Sets time-out to stop scanning.
mHandler.sendEmptyMessageDelayed(MESSAGE_STOP_SCAN_WIFI_LIST, DELAY_TIME_STOP_SCAN_MS);
}
@Override
protected void onPause() {
mHandler.removeMessages(MESSAGE_STOP_SCAN_WIFI_LIST);
final WifiManager wifiManager = getSystemService(WifiManager.class);
if (wifiManager != null) {
wifiManager.unregisterNetworkRequestMatchCallback(this);
}
super.onPause();
}
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_STOP_SCAN_WIFI_LIST:
removeMessages(MESSAGE_STOP_SCAN_WIFI_LIST);
stopScanningAndPopErrorDialog(ERROR_DIALOG_TYPE.TIME_OUT);
break;
default:
// Do nothing.
break;
}
}
};
protected void stopScanningAndPopErrorDialog(ERROR_DIALOG_TYPE type) {
dismissDialogs();
// Throws error dialog.
final DialogFragment dialogFragment = NetworkRequestErrorDialogFragment.newInstance();
final Bundle bundle = new Bundle();
bundle.putSerializable(NetworkRequestErrorDialogFragment.DIALOG_TYPE, type);
dialogFragment.setArguments(bundle);
dialogFragment.show(getSupportFragmentManager(), TAG);
mShowingErrorDialog = true;
}
@Override
public void onUserSelectionCallbackRegistration(
NetworkRequestUserSelectionCallback userSelectionCallback) {
if (mIsSpecifiedSsid) {
mUserSelectionCallback = userSelectionCallback;
return;
}
mDialogFragment.onUserSelectionCallbackRegistration(userSelectionCallback);
}
@Override
public void onAbort() {
stopScanningAndPopErrorDialog(ERROR_DIALOG_TYPE.ABORT);
}
@Override
public void onMatch(List<ScanResult> scanResults) {
if (mShowingErrorDialog) {
// Don't do anything since error dialog shows.
return;
}
mHandler.removeMessages(MESSAGE_STOP_SCAN_WIFI_LIST);
if (mIsSpecifiedSsid) {
// Prevent from throwing same dialog, because onMatch() will be called many times.
if (mMatchedConfig == null) {
mMatchedConfig = WifiUtils.getWifiConfig(
null /* accesspoint */, scanResults.get(0), null /* password */);
showSingleSsidRequestDialog(
WifiInfo.removeDoubleQuotes(mMatchedConfig.SSID), false /* isTryAgain */);
}
return;
}
mDialogFragment.onMatch(scanResults);
}
@Override
public void onUserSelectionConnectSuccess(WifiConfiguration wificonfiguration) {
if (!isFinishing()) {
Toast.makeText(this, R.string.network_connection_connect_successful,
Toast.LENGTH_SHORT).show();
setResult(RESULT_OK);
finish();
}
}
@Override
public void onUserSelectionConnectFailure(WifiConfiguration wificonfiguration) {
if (mIsSpecifiedSsid) {
showSingleSsidRequestDialog(
WifiInfo.removeDoubleQuotes(mMatchedConfig.SSID), true /* isTryAgain */);
return;
}
mDialogFragment.onUserSelectionConnectFailure(wificonfiguration);
}
// Called when user click "Connect" button. Called by
// {@code NetworkRequestSingleSsidDialogFragment}.
public void onClickConnectButton() {
if (mUserSelectionCallback != null) {
mUserSelectionCallback.select(mMatchedConfig);
showProgressDialog(getString(R.string.network_connection_connecting_message));
}
}
// Called when user click retry button. Called by {@link NetworkRequestErrorDialogFragment}.
public void onClickRescanButton() {
// Sets time-out to stop scanning.
mHandler.sendEmptyMessageDelayed(MESSAGE_STOP_SCAN_WIFI_LIST, DELAY_TIME_STOP_SCAN_MS);
mShowingErrorDialog = false;
if (mIsSpecifiedSsid) {
mMatchedConfig = null;
showProgressDialog(getString(R.string.network_connection_searching_message));
} else {
mDialogFragment = NetworkRequestDialogFragment.newInstance();
mDialogFragment.show(getSupportFragmentManager(), TAG);
}
}
// Called when user click cancel button.
public void onCancel() {
dismissDialogs();
if (mUserSelectionCallback != null) {
mUserSelectionCallback.reject();
}
finish();
} }
} }

View File

@@ -0,0 +1,90 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.wifi;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager.NetworkRequestUserSelectionCallback;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import java.util.List;
/**
* This is base fragment of {@link NetworkRequestDialogFragment} and
* {@link NetworkRequestSingleSsidDialogFragment} to handle activity callback methods.
*/
abstract public class NetworkRequestDialogBaseFragment extends InstrumentedDialogFragment {
@VisibleForTesting
final static String EXTRA_APP_NAME = "com.android.settings.wifi.extra.APP_NAME";
NetworkRequestDialogActivity mActivity = null;
protected String getTitle() {
final Intent intent = getActivity().getIntent();
String appName = "";
if (intent != null) {
appName = intent.getStringExtra(EXTRA_APP_NAME);
}
return getString(R.string.network_connection_request_dialog_title, appName);
}
@Override
public int getMetricsCategory() {
return SettingsEnums.WIFI_SCANNING_NEEDED_DIALOG;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof NetworkRequestDialogActivity) {
mActivity = (NetworkRequestDialogActivity) context;
}
}
@Override
public void onDetach() {
super.onDetach();
mActivity = null;
}
@Override
public void onCancel(@NonNull DialogInterface dialog) {
super.onCancel(dialog);
if (mActivity != null) {
mActivity.onCancel();
}
}
protected void onUserSelectionCallbackRegistration(
NetworkRequestUserSelectionCallback userSelectionCallback) {
}
protected void onMatch(List<ScanResult> scanResults) {
}
protected void onUserSelectionConnectFailure(WifiConfiguration wificonfiguration) {
}
}

View File

@@ -16,21 +16,15 @@
package com.android.settings.wifi; package com.android.settings.wifi;
import android.app.Activity;
import android.app.Dialog; import android.app.Dialog;
import android.app.settings.SettingsEnums;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.net.wifi.ScanResult; import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.NetworkRequestMatchCallback; import android.net.wifi.WifiManager.NetworkRequestMatchCallback;
import android.net.wifi.WifiManager.NetworkRequestUserSelectionCallback; import android.net.wifi.WifiManager.NetworkRequestUserSelectionCallback;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@@ -40,22 +34,16 @@ import android.widget.BaseAdapter;
import android.widget.Button; import android.widget.Button;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.preference.internal.PreferenceImageView; import androidx.preference.internal.PreferenceImageView;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.wifi.NetworkRequestErrorDialogFragment.ERROR_DIALOG_TYPE;
import com.android.settingslib.Utils; import com.android.settingslib.Utils;
import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.wifi.AccessPoint; import com.android.settingslib.wifi.AccessPoint;
import com.android.settingslib.wifi.WifiTracker; import com.android.settingslib.wifi.WifiTracker;
import com.android.settingslib.wifi.WifiTrackerFactory; import com.android.settingslib.wifi.WifiTrackerFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -64,11 +52,8 @@ import java.util.List;
* behaviors of the callback when requesting wifi network, except for error message. When error * behaviors of the callback when requesting wifi network, except for error message. When error
* happens, {@link NetworkRequestErrorDialogFragment} will be called to display error message. * happens, {@link NetworkRequestErrorDialogFragment} will be called to display error message.
*/ */
public class NetworkRequestDialogFragment extends InstrumentedDialogFragment implements public class NetworkRequestDialogFragment extends NetworkRequestDialogBaseFragment implements
DialogInterface.OnClickListener, NetworkRequestMatchCallback { DialogInterface.OnClickListener{
/** Message sent to us to stop scanning wifi and pop up timeout dialog. */
private static final int MESSAGE_STOP_SCAN_WIFI_LIST = 0;
/** /**
* Spec defines there should be 5 wifi ap on the list at most or just show all if {@code * Spec defines there should be 5 wifi ap on the list at most or just show all if {@code
@@ -77,20 +62,10 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp
private static final int MAX_NUMBER_LIST_ITEM = 5; private static final int MAX_NUMBER_LIST_ITEM = 5;
private boolean mShowLimitedItem = true; private boolean mShowLimitedItem = true;
/** Delayed time to stop scanning wifi. */
private static final int DELAY_TIME_STOP_SCAN_MS = 30 * 1000;
@VisibleForTesting
final static String EXTRA_APP_NAME = "com.android.settings.wifi.extra.APP_NAME";
final static String EXTRA_IS_SPECIFIED_SSID =
"com.android.settings.wifi.extra.REQUEST_IS_FOR_SINGLE_NETWORK";
private List<AccessPoint> mAccessPointList; private List<AccessPoint> mAccessPointList;
private FilterWifiTracker mFilterWifiTracker; private FilterWifiTracker mFilterWifiTracker;
private AccessPointAdapter mDialogAdapter; private AccessPointAdapter mDialogAdapter;
private NetworkRequestUserSelectionCallback mUserSelectionCallback; private NetworkRequestUserSelectionCallback mUserSelectionCallback;
private boolean mIsSpecifiedSsid;
private boolean mWaitingConnectCallback;
public static NetworkRequestDialogFragment newInstance() { public static NetworkRequestDialogFragment newInstance() {
NetworkRequestDialogFragment dialogFragment = new NetworkRequestDialogFragment(); NetworkRequestDialogFragment dialogFragment = new NetworkRequestDialogFragment();
@@ -108,11 +83,6 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp
final TextView title = customTitle.findViewById(R.id.network_request_title_text); final TextView title = customTitle.findViewById(R.id.network_request_title_text);
title.setText(getTitle()); title.setText(getTitle());
final Intent intent = getActivity().getIntent();
if (intent != null) {
mIsSpecifiedSsid = intent.getBooleanExtra(EXTRA_IS_SPECIFIED_SSID, false);
}
final ProgressBar progressBar = customTitle.findViewById( final ProgressBar progressBar = customTitle.findViewById(
R.id.network_request_title_progress); R.id.network_request_title_progress);
progressBar.setVisibility(View.VISIBLE); progressBar.setVisibility(View.VISIBLE);
@@ -128,9 +98,6 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp
// Do nothings, will replace the onClickListener to avoid auto closing dialog. // Do nothings, will replace the onClickListener to avoid auto closing dialog.
.setNeutralButton(R.string.network_connection_request_dialog_showall, .setNeutralButton(R.string.network_connection_request_dialog_showall,
null /* OnClickListener */); null /* OnClickListener */);
if (mIsSpecifiedSsid) {
builder.setPositiveButton(R.string.wifi_connect, null /* OnClickListener */);
}
// Clicking list item is to connect wifi ap. // Clicking list item is to connect wifi ap.
final AlertDialog dialog = builder.create(); final AlertDialog dialog = builder.create();
@@ -152,32 +119,10 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp
notifyAdapterRefresh(); notifyAdapterRefresh();
neutralBtn.setVisibility(View.GONE); neutralBtn.setVisibility(View.GONE);
}); });
// Replace Positive onClickListener to avoid closing dialog
if (mIsSpecifiedSsid) {
final Button positiveBtn = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
positiveBtn.setOnClickListener(v -> {
// When clicking connect button, should connect to the first and the only one
// list item.
this.onClick(dialog, 0 /* position */);
});
// Disable button in first, and enable it after there are some accesspoints in list.
positiveBtn.setEnabled(false);
}
}); });
return dialog; return dialog;
} }
private String getTitle() {
final Intent intent = getActivity().getIntent();
String appName = "";
if (intent != null) {
appName = intent.getStringExtra(EXTRA_APP_NAME);
}
return getString(R.string.network_connection_request_dialog_title, appName);
}
@NonNull @NonNull
List<AccessPoint> getAccessPointList() { List<AccessPoint> getAccessPointList() {
// Initials list for adapter, in case of display crashing. // Initials list for adapter, in case of display crashing.
@@ -211,9 +156,6 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp
if (wifiConfig != null) { if (wifiConfig != null) {
mUserSelectionCallback.select(wifiConfig); mUserSelectionCallback.select(wifiConfig);
mWaitingConnectCallback = true;
updateConnectButton(false);
} }
} }
} }
@@ -221,10 +163,6 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp
@Override @Override
public void onCancel(@NonNull DialogInterface dialog) { public void onCancel(@NonNull DialogInterface dialog) {
super.onCancel(dialog); super.onCancel(dialog);
// Finishes the activity when user clicks back key or outside of the dialog.
if (getActivity() != null) {
getActivity().finish();
}
if (mUserSelectionCallback != null) { if (mUserSelectionCallback != null) {
mUserSelectionCallback.reject(); mUserSelectionCallback.reject();
} }
@@ -234,13 +172,6 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp
public void onPause() { public void onPause() {
super.onPause(); super.onPause();
mHandler.removeMessages(MESSAGE_STOP_SCAN_WIFI_LIST);
final WifiManager wifiManager = getContext().getApplicationContext()
.getSystemService(WifiManager.class);
if (wifiManager != null) {
wifiManager.unregisterNetworkRequestMatchCallback(this);
}
if (mFilterWifiTracker != null) { if (mFilterWifiTracker != null) {
mFilterWifiTracker.onPause(); mFilterWifiTracker.onPause();
} }
@@ -268,23 +199,6 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp
} }
} }
private void updateConnectButton(boolean enabled) {
// The button is only showed in single SSID mode.
if (!mIsSpecifiedSsid) {
return;
}
final AlertDialog alertDialog = (AlertDialog) getDialog();
if (alertDialog == null) {
return;
}
final Button positiveBtn = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
if (positiveBtn != null) {
positiveBtn.setEnabled(enabled);
}
}
private void hideProgressIcon() { private void hideProgressIcon() {
final AlertDialog alertDialog = (AlertDialog) getDialog(); final AlertDialog alertDialog = (AlertDialog) getDialog();
if (alertDialog == null) { if (alertDialog == null) {
@@ -301,57 +215,12 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
final WifiManager wifiManager = getContext().getApplicationContext()
.getSystemService(WifiManager.class);
if (wifiManager != null) {
wifiManager.registerNetworkRequestMatchCallback(this, mHandler);
}
// Sets time-out to stop scanning.
mHandler.sendEmptyMessageDelayed(MESSAGE_STOP_SCAN_WIFI_LIST, DELAY_TIME_STOP_SCAN_MS);
if (mFilterWifiTracker == null) { if (mFilterWifiTracker == null) {
mFilterWifiTracker = new FilterWifiTracker(getActivity(), getSettingsLifecycle()); mFilterWifiTracker = new FilterWifiTracker(getActivity(), getSettingsLifecycle());
} }
mFilterWifiTracker.onResume(); mFilterWifiTracker.onResume();
} }
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_STOP_SCAN_WIFI_LIST:
removeMessages(MESSAGE_STOP_SCAN_WIFI_LIST);
stopScanningAndPopErrorDialog(ERROR_DIALOG_TYPE.TIME_OUT);
break;
default:
// Do nothing.
break;
}
}
};
protected void stopScanningAndPopErrorDialog(ERROR_DIALOG_TYPE type) {
// Dismisses current dialog.
final Dialog dialog = getDialog();
if (dialog != null && dialog.isShowing()) {
dismiss();
}
// Throws error dialog.
final NetworkRequestErrorDialogFragment fragment = NetworkRequestErrorDialogFragment
.newInstance();
final Bundle bundle = new Bundle();
bundle.putSerializable(NetworkRequestErrorDialogFragment.DIALOG_TYPE, type);
fragment.setArguments(bundle);
fragment.show(getActivity().getSupportFragmentManager(),
NetworkRequestDialogFragment.class.getSimpleName());
}
@Override
public int getMetricsCategory() {
return SettingsEnums.WIFI_SCANNING_NEEDED_DIALOG;
}
private class AccessPointAdapter extends ArrayAdapter<AccessPoint> { private class AccessPointAdapter extends ArrayAdapter<AccessPoint> {
private final int mResourceId; private final int mResourceId;
@@ -407,11 +276,6 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp
} }
} }
@Override
public void onAbort() {
stopScanningAndPopErrorDialog(ERROR_DIALOG_TYPE.ABORT);
}
@Override @Override
public void onUserSelectionCallbackRegistration( public void onUserSelectionCallbackRegistration(
NetworkRequestUserSelectionCallback userSelectionCallback) { NetworkRequestUserSelectionCallback userSelectionCallback) {
@@ -422,7 +286,6 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp
public void onMatch(List<ScanResult> scanResults) { public void onMatch(List<ScanResult> scanResults) {
// Shouldn't need to renew cached list, since input result is empty. // Shouldn't need to renew cached list, since input result is empty.
if (scanResults != null && scanResults.size() > 0) { if (scanResults != null && scanResults.size() > 0) {
mHandler.removeMessages(MESSAGE_STOP_SCAN_WIFI_LIST);
renewAccessPointList(scanResults); renewAccessPointList(scanResults);
notifyAdapterRefresh(); notifyAdapterRefresh();
@@ -455,21 +318,9 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp
} }
} }
@Override
public void onUserSelectionConnectSuccess(WifiConfiguration wificonfiguration) {
final Activity activity = getActivity();
if (activity != null) {
Toast.makeText(activity, R.string.network_connection_connect_successful,
Toast.LENGTH_SHORT).show();
activity.finish();
}
}
@Override @Override
public void onUserSelectionConnectFailure(WifiConfiguration wificonfiguration) { public void onUserSelectionConnectFailure(WifiConfiguration wificonfiguration) {
// Do nothing when selection is failed, let user could try again easily. // Do nothing when selection is failed, let user could try again easily.
mWaitingConnectCallback = false;
updateConnectButton(true);
} }
private final class FilterWifiTracker { private final class FilterWifiTracker {
@@ -526,13 +377,6 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp
if (count > 0) { if (count > 0) {
hideProgressIcon(); hideProgressIcon();
} }
// Enable connect button if there is Accesspoint item, except for the situation that
// user click but connected status doesn't come back yet.
if (count < 0) {
updateConnectButton(false);
} else if (!mWaitingConnectCallback) {
updateConnectButton(true);
}
return result; return result;
} }

View File

@@ -20,10 +20,8 @@ import android.app.Dialog;
import android.app.settings.SettingsEnums; import android.app.settings.SettingsEnums;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment; import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
@@ -64,7 +62,7 @@ public class NetworkRequestErrorDialogFragment extends InstrumentedDialogFragmen
if (msgType == ERROR_DIALOG_TYPE.TIME_OUT) { if (msgType == ERROR_DIALOG_TYPE.TIME_OUT) {
builder.setMessage(R.string.network_connection_timeout_dialog_message) builder.setMessage(R.string.network_connection_timeout_dialog_message)
.setPositiveButton(R.string.network_connection_timeout_dialog_ok, .setPositiveButton(R.string.network_connection_timeout_dialog_ok,
(dialog, which) -> startScanningDialog()) (dialog, which) -> onRescanClick())
.setNegativeButton(R.string.cancel, (dialog, which) -> getActivity().finish()); .setNegativeButton(R.string.cancel, (dialog, which) -> getActivity().finish());
} else { } else {
builder.setMessage(R.string.network_connection_errorstate_dialog_message) builder.setMessage(R.string.network_connection_errorstate_dialog_message)
@@ -78,9 +76,10 @@ public class NetworkRequestErrorDialogFragment extends InstrumentedDialogFragmen
return SettingsEnums.WIFI_SCANNING_NEEDED_DIALOG; return SettingsEnums.WIFI_SCANNING_NEEDED_DIALOG;
} }
protected void startScanningDialog() { protected void onRescanClick() {
final NetworkRequestDialogFragment fragment = NetworkRequestDialogFragment.newInstance(); if (getActivity() != null) {
fragment.show(getActivity().getSupportFragmentManager(), dismiss();
NetworkRequestErrorDialogFragment.class.getSimpleName()); ((NetworkRequestDialogActivity)getActivity()).onClickRescanButton();
}
} }
} }

View File

@@ -0,0 +1,59 @@
package com.android.settings.wifi;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import com.android.settings.R;
/**
* This is similar fragment with {@link NetworkRequestDialogFragment} but only for single SSID mode.
*/
public class NetworkRequestSingleSsidDialogFragment extends
NetworkRequestDialogBaseFragment {
public static final String EXTRA_SSID = "DIALOG_REQUEST_SSID";
public static final String EXTRA_TRYAGAIN = "DIALOG_IS_TRYAGAIN";
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
boolean isTryAgain = false;
String requestSsid = "";
if (getArguments() != null) {
isTryAgain = getArguments().getBoolean(EXTRA_TRYAGAIN, true);
requestSsid = getArguments().getString(EXTRA_SSID, "");
}
final Context context = getContext();
final LayoutInflater inflater = LayoutInflater.from(context);
final View customTitle = inflater.inflate(R.layout.network_request_dialog_title, null);
final TextView title = customTitle.findViewById(R.id.network_request_title_text);
title.setText(getTitle());
final ProgressBar progressBar = customTitle
.findViewById(R.id.network_request_title_progress);
progressBar.setVisibility(View.GONE);
final AlertDialog.Builder builder = new AlertDialog.Builder(context)
.setCustomTitle(customTitle)
.setMessage(requestSsid)
.setPositiveButton(isTryAgain ? R.string.network_connection_timeout_dialog_ok
: R.string.wifi_connect, (dialog, which) -> onUserClickConnectButton())
.setNeutralButton(R.string.cancel, (dialog, which) -> onCancel(dialog));
// Don't dismiss dialog when touching outside. User reports it is easy to touch outside.
// This causes dialog to close.
setCancelable(false);
return builder.create();
}
private void onUserClickConnectButton() {
if (mActivity != null) {
mActivity.onClickConnectButton();
}
}
}

View File

@@ -17,35 +17,109 @@
package com.android.settings.wifi; package com.android.settings.wifi;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import com.android.settings.testutils.shadow.ShadowAlertDialogCompat; import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
import com.android.settings.wifi.NetworkRequestErrorDialogFragment.ERROR_DIALOG_TYPE;
import com.android.settingslib.wifi.WifiTracker; import com.android.settingslib.wifi.WifiTracker;
import com.android.settingslib.wifi.WifiTrackerFactory; import com.android.settingslib.wifi.WifiTrackerFactory;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.robolectric.Robolectric; import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowLooper;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
@Config(shadows = ShadowAlertDialogCompat.class) @Config(shadows = ShadowAlertDialogCompat.class)
public class NetworkRequestDialogActivityTest { public class NetworkRequestDialogActivityTest {
@Test NetworkRequestDialogActivity mActivity;
public void LaunchActivity_shouldShowNetworkRequestDialog() { WifiManager mWifiManager;
// Mocks fake WifiTracker, in case of exception in NetworkRequestDialogFragment.onResume(). Context mContext;
@Before
public void setUp() {
mContext = spy(RuntimeEnvironment.application);
WifiTracker wifiTracker = mock(WifiTracker.class); WifiTracker wifiTracker = mock(WifiTracker.class);
WifiTrackerFactory.setTestingWifiTracker(wifiTracker); WifiTrackerFactory.setTestingWifiTracker(wifiTracker);
Robolectric.setupActivity(NetworkRequestDialogActivity.class); NetworkRequestDialogActivity activity =
Robolectric.setupActivity(NetworkRequestDialogActivity.class);
mActivity = spy(activity);
mWifiManager = mock(WifiManager.class);
when(mActivity.getSystemService(Context.WIFI_SERVICE)).thenReturn(mWifiManager);
}
@Test
public void LaunchActivity_shouldShowNetworkRequestDialog() {
AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog(); AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
assertThat(alertDialog.isShowing()).isTrue(); assertThat(alertDialog.isShowing()).isTrue();
} }
@Test
public void onResume_shouldRegisterCallback() {
mActivity.onResume();
verify(mWifiManager).registerNetworkRequestMatchCallback(any(), any());
}
@Test
public void onPause_shouldUnRegisterCallback() {
mActivity.onPause();
verify(mWifiManager).unregisterNetworkRequestMatchCallback(mActivity);
}
@Test
public void onResumeAndWaitTimeout_shouldCallTimeoutDialog() {
FakeNetworkRequestDialogActivity fakeActivity =
Robolectric.setupActivity(FakeNetworkRequestDialogActivity.class);
fakeActivity.onResume();
ShadowLooper.getShadowMainLooper().runToEndOfTasks();
assertThat(fakeActivity.bCalledStopAndPop).isTrue();
assertThat(fakeActivity.errorType).isEqualTo(ERROR_DIALOG_TYPE.TIME_OUT);
}
public static class FakeNetworkRequestDialogActivity extends NetworkRequestDialogActivity {
boolean bCalledStopAndPop = false;
ERROR_DIALOG_TYPE errorType = null;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public void stopScanningAndPopErrorDialog(ERROR_DIALOG_TYPE type) {
bCalledStopAndPop = true;
errorType = type;
}
}
@Test
public void updateAccessPointList_onUserSelectionConnectSuccess_shouldFinishActivity() {
final WifiConfiguration config = new WifiConfiguration();
config.SSID = "Test AP 3";
mActivity.onUserSelectionConnectSuccess(config);
verify(mActivity).finish();
}
} }

View File

@@ -17,8 +17,6 @@
package com.android.settings.wifi; package com.android.settings.wifi;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
@@ -29,25 +27,20 @@ import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.net.wifi.ScanResult; import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager; import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.NetworkRequestUserSelectionCallback; import android.net.wifi.WifiManager.NetworkRequestUserSelectionCallback;
import android.os.Bundle; import android.os.Bundle;
import android.view.View; import android.view.View;
import android.widget.Button; import android.widget.Button;
import android.widget.TextView; import android.widget.TextView;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.FragmentActivity;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.testutils.shadow.ShadowAlertDialogCompat; import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
import com.android.settings.wifi.NetworkRequestErrorDialogFragment.ERROR_DIALOG_TYPE;
import com.android.settingslib.wifi.AccessPoint; import com.android.settingslib.wifi.AccessPoint;
import com.android.settingslib.wifi.WifiTracker;
import com.android.settingslib.wifi.WifiTrackerFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@@ -56,11 +49,6 @@ import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment; import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
import com.android.settingslib.wifi.WifiTracker;
import com.android.settingslib.wifi.WifiTrackerFactory;
import org.robolectric.shadows.ShadowLooper;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
@Config(shadows = ShadowAlertDialogCompat.class) @Config(shadows = ShadowAlertDialogCompat.class)
public class NetworkRequestDialogFragmentTest { public class NetworkRequestDialogFragmentTest {
@@ -69,14 +57,14 @@ public class NetworkRequestDialogFragmentTest {
private static final String KEY_SECURITY = "key_security"; private static final String KEY_SECURITY = "key_security";
private static final String TEST_APP_NAME = "TestAppName"; private static final String TEST_APP_NAME = "TestAppName";
private FragmentActivity mActivity; private NetworkRequestDialogActivity mActivity;
private NetworkRequestDialogFragment networkRequestDialogFragment; private NetworkRequestDialogFragment networkRequestDialogFragment;
private Context mContext; private Context mContext;
private WifiTracker mWifiTracker; private WifiTracker mWifiTracker;
@Before @Before
public void setUp() { public void setUp() {
mActivity = Robolectric.buildActivity(FragmentActivity.class, mActivity = Robolectric.buildActivity(NetworkRequestDialogActivity.class,
new Intent().putExtra(NetworkRequestDialogFragment.EXTRA_APP_NAME, new Intent().putExtra(NetworkRequestDialogFragment.EXTRA_APP_NAME,
TEST_APP_NAME)).setup().get(); TEST_APP_NAME)).setup().get();
networkRequestDialogFragment = spy(NetworkRequestDialogFragment.newInstance()); networkRequestDialogFragment = spy(NetworkRequestDialogFragment.newInstance());
@@ -118,73 +106,6 @@ public class NetworkRequestDialogFragmentTest {
assertThat(alertDialog.isShowing()).isFalse(); assertThat(alertDialog.isShowing()).isFalse();
} }
@Test
public void onResumeAndWaitTimeout_shouldCallTimeoutDialog() {
FakeNetworkRequestDialogFragment fakeFragment = new FakeNetworkRequestDialogFragment();
FakeNetworkRequestDialogFragment spyFakeFragment = spy(fakeFragment);
spyFakeFragment.show(mActivity.getSupportFragmentManager(), null);
assertThat(fakeFragment.bCalledStopAndPop).isFalse();
ShadowLooper.getShadowMainLooper().runToEndOfTasks();
assertThat(fakeFragment.bCalledStopAndPop).isTrue();
assertThat(fakeFragment.errorType).isEqualTo(ERROR_DIALOG_TYPE.TIME_OUT);
}
class FakeNetworkRequestDialogFragment extends NetworkRequestDialogFragment {
boolean bCalledStopAndPop = false;
ERROR_DIALOG_TYPE errorType = null;
@Override
public void stopScanningAndPopErrorDialog(ERROR_DIALOG_TYPE type) {
bCalledStopAndPop = true;
errorType = type;
}
}
@Test
public void onResume_shouldRegisterCallback() {
when(networkRequestDialogFragment.getContext()).thenReturn(mContext);
Context applicationContext = spy(RuntimeEnvironment.application.getApplicationContext());
when(mContext.getApplicationContext()).thenReturn(applicationContext);
WifiManager wifiManager = mock(WifiManager.class);
when(applicationContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(wifiManager);
networkRequestDialogFragment.onResume();
verify(wifiManager).registerNetworkRequestMatchCallback(any(), any());
}
@Test
public void onPause_shouldUnRegisterCallback() {
when(networkRequestDialogFragment.getContext()).thenReturn(mContext);
Context applicationContext = spy(RuntimeEnvironment.application.getApplicationContext());
when(mContext.getApplicationContext()).thenReturn(applicationContext);
WifiManager wifiManager = mock(WifiManager.class);
when(applicationContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(wifiManager);
networkRequestDialogFragment.onPause();
verify(wifiManager).unregisterNetworkRequestMatchCallback(networkRequestDialogFragment);
}
@Test
public void updateAccessPointList_onUserSelectionConnectSuccess_shouldFinishActivity() {
// Assert
final FragmentActivity spyActivity = spy(mActivity);
when(networkRequestDialogFragment.getActivity()).thenReturn(spyActivity);
networkRequestDialogFragment.show(spyActivity.getSupportFragmentManager(), "onUserSelectionConnectSuccess");
// Action
final WifiConfiguration config = new WifiConfiguration();
config.SSID = "Test AP 3";
networkRequestDialogFragment.onUserSelectionConnectSuccess(config);
// Check
verify(spyActivity).finish();
}
@Test @Test
public void onUserSelectionCallbackRegistration_onClick_shouldCallSelect() { public void onUserSelectionCallbackRegistration_onClick_shouldCallSelect() {
// Assert. // Assert.

View File

@@ -17,7 +17,7 @@
package com.android.settings.wifi; package com.android.settings.wifi;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.internal.verification.VerificationModeFactory.times; import static org.mockito.internal.verification.VerificationModeFactory.times;
@@ -25,14 +25,12 @@ import static org.mockito.internal.verification.VerificationModeFactory.times;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.os.Bundle; import android.os.Bundle;
import android.widget.Button; import android.widget.Button;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.FragmentActivity;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.testutils.shadow.ShadowAlertDialogCompat; import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
import com.android.settings.wifi.NetworkRequestErrorDialogFragment.ERROR_DIALOG_TYPE; import com.android.settings.wifi.NetworkRequestErrorDialogFragment.ERROR_DIALOG_TYPE;
import com.android.settingslib.wifi.WifiTracker;
import com.android.settingslib.wifi.WifiTrackerFactory;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@@ -45,12 +43,15 @@ import org.robolectric.annotation.Config;
@Config(shadows = ShadowAlertDialogCompat.class) @Config(shadows = ShadowAlertDialogCompat.class)
public class NetworkRequestErrorDialogFragmentTest { public class NetworkRequestErrorDialogFragmentTest {
private FragmentActivity mActivity; private NetworkRequestDialogActivity mActivity;
private NetworkRequestErrorDialogFragment mFragment; private NetworkRequestErrorDialogFragment mFragment;
@Before @Before
public void setUp() { public void setUp() {
mActivity = Robolectric.setupActivity(FragmentActivity.class); WifiTracker wifiTracker = mock(WifiTracker.class);
WifiTrackerFactory.setTestingWifiTracker(wifiTracker);
mActivity = Robolectric.setupActivity(NetworkRequestDialogActivity.class);
mFragment = spy(NetworkRequestErrorDialogFragment.newInstance()); mFragment = spy(NetworkRequestErrorDialogFragment.newInstance());
mFragment.show(mActivity.getSupportFragmentManager(), null); mFragment.show(mActivity.getSupportFragmentManager(), null);
} }
@@ -97,7 +98,7 @@ public class NetworkRequestErrorDialogFragmentTest {
assertThat(positiveButton).isNotNull(); assertThat(positiveButton).isNotNull();
positiveButton.performClick(); positiveButton.performClick();
verify(mFragment, times(1)).startScanningDialog(); verify(mFragment, times(1)).onRescanClick();
} }
@Test @Test