Implement NetworkRequestMatchCallback callback in NetworkRequestDialogFragment

Use this callback to communicate with framework wifi api.
Will get candidates wifi ap list and related callback to select which wifi ap wanted to use, and related operated result status.

Bug: 117399926
Test: RunSettingsRoboTests
Change-Id: Ic8ee678c06f21050761ebb58dc0fe50bc5732e53
This commit is contained in:
cosmohsieh
2018-11-14 17:24:18 +08:00
committed by Cosmo Hsieh
parent dbbbd7a83d
commit 75c8805a99
2 changed files with 306 additions and 18 deletions

View File

@@ -19,9 +19,18 @@ package com.android.settings.wifi;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.drawable.Drawable;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.NetworkRequestUserSelectionCallback;
import android.net.wifi.WifiManager.NetworkRequestMatchCallback;
import android.os.Handler;
import android.os.Message;
import android.widget.BaseAdapter;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.preference.internal.PreferenceImageView;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
@@ -32,20 +41,23 @@ import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settingslib.Utils;
import com.android.settingslib.wifi.AccessPoint;
import java.util.ArrayList;
import java.util.List;
public class NetworkRequestDialogFragment extends InstrumentedDialogFragment implements
DialogInterface.OnClickListener {
DialogInterface.OnClickListener, NetworkRequestMatchCallback {
/** Message sent to us 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;
private static final int DELAY_TIME_STOP_SCAN_MS = 30 * 1000;
private List<AccessPoint> mAccessPointList;
private AccessPointAdapter mDialogAdapter;
private NetworkRequestUserSelectionCallback mUserSelectionCallback;
public static NetworkRequestDialogFragment newInstance() {
NetworkRequestDialogFragment dialogFragment = new NetworkRequestDialogFragment();
@@ -54,28 +66,29 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Context context = getContext();
final Context context = getContext();
// Prepares title.
LayoutInflater inflater = LayoutInflater.from(context);
View customTitle = inflater.inflate(R.layout.network_request_dialog_title, null);
final LayoutInflater inflater = LayoutInflater.from(context);
final View customTitle = inflater.inflate(R.layout.network_request_dialog_title, null);
TextView title = customTitle.findViewById(R.id.network_request_title_text);
final TextView title = customTitle.findViewById(R.id.network_request_title_text);
title.setText(R.string.network_connection_request_dialog_title);
ProgressBar progressBar = customTitle.findViewById(R.id.network_request_title_progress);
final ProgressBar progressBar = customTitle.findViewById(R.id.network_request_title_progress);
progressBar.setVisibility(View.VISIBLE);
// Prepares adapter.
AccessPointAdapter adapter = new AccessPointAdapter(context,
mDialogAdapter = new AccessPointAdapter(context,
R.layout.preference_access_point, getAccessPointList());
AlertDialog.Builder builder = new AlertDialog.Builder(context)
final AlertDialog.Builder builder = new AlertDialog.Builder(context)
.setCustomTitle(customTitle)
.setAdapter(adapter, this)
.setAdapter(mDialogAdapter, this)
.setPositiveButton(R.string.cancel, (dialog, which) -> dialog.dismiss());
return builder.create();
}
@NonNull
List<AccessPoint> getAccessPointList() {
// Initials list for adapter, in case of display crashing.
if (mAccessPointList == null) {
@@ -84,8 +97,24 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp
return mAccessPointList;
}
private BaseAdapter getDialogAdapter() {
return mDialogAdapter;
}
@Override
public void onClick(DialogInterface dialog, int which) {
final List<AccessPoint> accessPointList = getAccessPointList();
if (accessPointList.size() == 0) {
return; // Invalid values.
}
if (mUserSelectionCallback == null) {
return; // Callback is missing or not ready.
}
if (which < accessPointList.size()) {
WifiConfiguration wifiConfig = accessPointList.get(which).getConfig();
mUserSelectionCallback.select(wifiConfig);
}
}
@Override
@@ -93,19 +122,27 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp
super.onPause();
mHandler.removeMessages(MESSAGE_STOP_SCAN_WIFI_LIST);
final WifiManager wifiManager = getContext().getApplicationContext()
.getSystemService(WifiManager.class);
if (wifiManager != null) {
wifiManager.unregisterNetworkRequestMatchCallback(this);
}
}
@Override
public void onResume() {
super.onResume();
// TODO(b/117399926): Starts to scan current WiFi.
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);
}
private Handler mHandler = new Handler() {
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
@@ -121,8 +158,12 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp
};
protected void stopScanningAndPopTimeoutDialog() {
// Dismisses current dialog.
dismiss();
NetworkRequestTimeoutDialogFragment fragment = NetworkRequestTimeoutDialogFragment.newInstance();
// Throws new timeout dialog.
final NetworkRequestTimeoutDialogFragment fragment = NetworkRequestTimeoutDialogFragment
.newInstance();
fragment.show(getActivity().getSupportFragmentManager(), null);
}
@@ -146,14 +187,108 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp
public View getView(int position, View view, ViewGroup parent) {
if (view == null) {
view = mInflater.inflate(mResourceId, parent, false);
}
// TODO: Sets correct information to list item.
final View divider = view.findViewById(com.android.settingslib.R.id.two_target_divider);
divider.setVisibility(View.GONE);
}
final AccessPoint accessPoint = getItem(position);
final TextView titleView = view.findViewById(android.R.id.title);
if (titleView != null) {
titleView.setText(accessPoint.getSsidStr());
}
final TextView summary = view.findViewById(android.R.id.summary);
if (summary != null) {
summary.setText(accessPoint.getSettingsSummary());
}
final PreferenceImageView imageView = view.findViewById(android.R.id.icon);
final int level = accessPoint.getLevel();
if (imageView != null) {
final Drawable drawable = getContext().getDrawable(Utils.getWifiIconResource(level));
drawable.setTintList(Utils.getColorAttr(getContext(), android.R.attr.colorControlNormal));
imageView.setImageDrawable(drawable);
}
return view;
}
}
}
@Override
public void onAbort() {
// TODO(b/117399926): We should have a UI notify user here.
}
@Override
public void onUserSelectionCallbackRegistration(
NetworkRequestUserSelectionCallback userSelectionCallback) {
mUserSelectionCallback = userSelectionCallback;
}
@Override
public void onMatch(List<ScanResult> scanResults) {
// TODO(b/119846365): Checks if we could escalate the converting effort.
// Converts ScanResult to WifiConfiguration.
List<WifiConfiguration> wifiConfigurations = null;
final WifiManager wifiManager = getContext().getApplicationContext()
.getSystemService(WifiManager.class);
if (wifiManager != null) {
wifiConfigurations = wifiManager.getAllMatchingWifiConfigs(scanResults);
}
setUpAccessPointList(wifiConfigurations);
if (getDialogAdapter() != null) {
getDialogAdapter().notifyDataSetChanged();
}
}
@Override
public void onUserSelectionConnectSuccess(WifiConfiguration wificonfiguration) {
if (getDialogAdapter() != null) {
updateAccessPointListItem(wificonfiguration);
getDialogAdapter().notifyDataSetChanged();
}
}
@Override
public void onUserSelectionConnectFailure(WifiConfiguration wificonfiguration) {
if (mDialogAdapter != null) {
updateAccessPointListItem(wificonfiguration);
getDialogAdapter().notifyDataSetChanged();
}
}
private void updateAccessPointListItem(WifiConfiguration wificonfiguration) {
if (wificonfiguration == null) {
return;
}
final List<AccessPoint> accessPointList = getAccessPointList();
final int accessPointListSize = accessPointList.size();
for (int i = 0; i < accessPointListSize; i++) {
AccessPoint accessPoint = accessPointList.get(i);
// It is the same AccessPoint SSID, and should be replaced to update latest properties.
if (accessPoint.matches(wificonfiguration)) {
accessPointList.set(i, new AccessPoint(getContext(), wificonfiguration));
break;
}
}
}
private void setUpAccessPointList(List<WifiConfiguration> wifiConfigurations) {
// Grants for zero size input, since maybe current wifi is off or somethings are wrong.
if (wifiConfigurations == null) {
return;
}
final List<AccessPoint> accessPointList = getAccessPointList();
accessPointList.clear();
for (WifiConfiguration config : wifiConfigurations) {
accessPointList.add(new AccessPoint(getContext(), config));
}
}
}

View File

@@ -17,18 +17,34 @@
package com.android.settings.wifi;
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.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.DialogInterface;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.NetworkRequestUserSelectionCallback;
import android.os.Bundle;
import android.widget.Button;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.FragmentActivity;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResourcesImpl;
import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
import com.android.settingslib.wifi.AccessPoint;
import java.util.ArrayList;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
import org.robolectric.shadows.ShadowLooper;
@@ -37,13 +53,17 @@ import org.robolectric.shadows.ShadowLooper;
@Config(shadows = {SettingsShadowResourcesImpl.class, ShadowAlertDialogCompat.class})
public class NetworkRequestDialogFragmentTest {
final String KEY_SSID = "key_ssid";
private FragmentActivity mActivity;
private NetworkRequestDialogFragment networkRequestDialogFragment;
private Context mContext;
@Before
public void setUp() {
mActivity = Robolectric.setupActivity(FragmentActivity.class);
networkRequestDialogFragment = spy(NetworkRequestDialogFragment.newInstance());
mContext = spy(RuntimeEnvironment.application);
}
@Test
@@ -88,4 +108,137 @@ public class NetworkRequestDialogFragmentTest {
bCalledStopAndPop = true;
}
}
@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_updateCorrectly() {
List<AccessPoint> accessPointList = spy(new ArrayList<>());
Bundle bundle = new Bundle();
bundle.putString(KEY_SSID, "Test AP 1");
accessPointList.add(new AccessPoint(mContext, bundle));
bundle.putString(KEY_SSID, "Test AP 2");
accessPointList.add(new AccessPoint(mContext, bundle));
bundle.putString(KEY_SSID, "Test AP 3");
accessPointList.add(new AccessPoint(mContext, bundle));
bundle.putString(KEY_SSID, "Test AP 4");
accessPointList.add(new AccessPoint(mContext, bundle));
when(networkRequestDialogFragment.getAccessPointList()).thenReturn(accessPointList);
networkRequestDialogFragment.show(mActivity.getSupportFragmentManager(), null);
// Test if config would update list.
WifiConfiguration config = new WifiConfiguration();
config.SSID = "Test AP 3";
networkRequestDialogFragment.onUserSelectionConnectSuccess(config);
AccessPoint verifyAccessPoint = new AccessPoint(mContext, config);
verify(accessPointList, times(1)).set(2, verifyAccessPoint);
}
@Test
public void updateAccessPointList_onUserSelectionConnectFailure_updateCorrectly() {
List<AccessPoint> accessPointList = spy(new ArrayList<>());
Bundle bundle = new Bundle();
bundle.putString(KEY_SSID, "Test AP 1");
accessPointList.add(new AccessPoint(mContext, bundle));
bundle.putString(KEY_SSID, "Test AP 2");
accessPointList.add(new AccessPoint(mContext, bundle));
bundle.putString(KEY_SSID, "Test AP 3");
accessPointList.add(new AccessPoint(mContext, bundle));
bundle.putString(KEY_SSID, "Test AP 4");
accessPointList.add(new AccessPoint(mContext, bundle));
when(networkRequestDialogFragment.getAccessPointList()).thenReturn(accessPointList);
networkRequestDialogFragment.show(mActivity.getSupportFragmentManager(), null);
// Test if config would update list.
WifiConfiguration config = new WifiConfiguration();
config.SSID = "Test AP 3";
networkRequestDialogFragment.onUserSelectionConnectFailure(config);
AccessPoint verifyAccessPoint = new AccessPoint(mContext, config);
verify(accessPointList, times(1)).set(2, verifyAccessPoint);
}
@Test
public void onUserSelectionCallbackRegistration_shouldCallSelect() {
List<AccessPoint> accessPointList = spy(new ArrayList<>());
Bundle bundle = new Bundle();
bundle.putString(KEY_SSID, "Test AP 1");
accessPointList.add(new AccessPoint(mContext, bundle));
bundle.putString(KEY_SSID, "Test AP 2");
accessPointList.add(new AccessPoint(mContext, bundle));
bundle.putString(KEY_SSID, "Test AP 3");
AccessPoint clickedAccessPoint = new AccessPoint(mContext, bundle);
accessPointList.add(clickedAccessPoint);
bundle.putString(KEY_SSID, "Test AP 4");
accessPointList.add(new AccessPoint(mContext, bundle));
when(networkRequestDialogFragment.getAccessPointList()).thenReturn(accessPointList);
NetworkRequestUserSelectionCallback selectionCallback = mock(
NetworkRequestUserSelectionCallback.class);
AlertDialog dialog = mock(AlertDialog.class);
networkRequestDialogFragment.onUserSelectionCallbackRegistration(selectionCallback);
networkRequestDialogFragment.onClick(dialog, 2);
verify(selectionCallback, times(1)).select(clickedAccessPoint.getConfig());
}
@Test
public void onMatch_shouldUpdatedList() {
// Prepares WifiManager.
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);
List<WifiConfiguration> wifiConfigurationList = new ArrayList<>();
WifiConfiguration config = new WifiConfiguration();
final String SSID_AP1 = "Test AP 1";
config.SSID = SSID_AP1;
wifiConfigurationList.add(config);
config = new WifiConfiguration();
final String SSID_AP2 = "Test AP 2";
config.SSID = SSID_AP2;
wifiConfigurationList.add(config);
// Prepares callback converted data.
List<ScanResult> scanResults = new ArrayList<>();
when(wifiManager.getAllMatchingWifiConfigs(scanResults)).thenReturn(wifiConfigurationList);
networkRequestDialogFragment.onMatch(scanResults);
List<AccessPoint> accessPointList = networkRequestDialogFragment.getAccessPointList();
assertThat(accessPointList).isNotEmpty();
assertThat(accessPointList.size()).isEqualTo(2);
assertThat(accessPointList.get(0).getSsid()).isEqualTo(SSID_AP1);
assertThat(accessPointList.get(1).getSsid()).isEqualTo(SSID_AP2);
}
}