[Wi-Fi] Apply WifiTrackerLib objects in Wi-Fi Slice
This change uses WifiTrackerLib's WifiPickerTracker & WifiEntry to replace SettingLib's WifiTracker & AccessPoint. This change includes 1. WifiScanWorker has the callbacks similar to a lifecycle component but it's not a lifecycle component. Let WifiScanWorker implements LifecycleOwner and provides #getLifecycle() for WifiPickerTracker. 2. Remove captive portal related code because WifiEntry#connect will handle captive portal login if it's necessary. 3. Create WifiSliceItem to wrap WifiEntry because WifiEntry is an abstract object and it does not provide copy constructor. Without copy construcor, Wi-Fi Slice may show unexpected information when a WifiEntry is updated. Bug: 155613549 Bug: 152571756 Test: make RunSettingsRoboTests ROBOTEST_FILTER=com.android.settings.wifi.slice make RunSettingsRoboTests ROBOTEST_FILTER=com.android.settings.wifi Change-Id: I2d66ea4905daca3244ec4cf8f2935cda817480b1
This commit is contained in:
@@ -2195,6 +2195,8 @@
|
|||||||
<string name="wifi_turned_on_message">Wi\u2011Fi turned on</string>
|
<string name="wifi_turned_on_message">Wi\u2011Fi turned on</string>
|
||||||
<!-- A notification for connected to a Wi-Fi network [CHAR LIMIT=NONE] -->
|
<!-- A notification for connected to a Wi-Fi network [CHAR LIMIT=NONE] -->
|
||||||
<string name="wifi_connected_to_message">Connected to <xliff:g id="network_name" example="MyNetwork">%1$s</xliff:g></string>
|
<string name="wifi_connected_to_message">Connected to <xliff:g id="network_name" example="MyNetwork">%1$s</xliff:g></string>
|
||||||
|
<!-- A notification for connecting to a Wi-Fi network [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="wifi_connecting_to_message">Connecting to <xliff:g id="network_name" example="MyNetwork">%1$s</xliff:g></string>
|
||||||
<!-- Button label to connecting progress to a Wi-Fi network [CHAR LIMIT=20] -->
|
<!-- Button label to connecting progress to a Wi-Fi network [CHAR LIMIT=20] -->
|
||||||
<string name="wifi_connecting">Connecting\u2026</string>
|
<string name="wifi_connecting">Connecting\u2026</string>
|
||||||
<!-- Failured notification for connect -->
|
<!-- Failured notification for connect -->
|
||||||
|
@@ -40,7 +40,6 @@ import com.android.settings.core.InstrumentedFragment;
|
|||||||
import com.android.settings.homepage.contextualcards.slices.BluetoothUpdateWorker;
|
import com.android.settings.homepage.contextualcards.slices.BluetoothUpdateWorker;
|
||||||
import com.android.settings.homepage.contextualcards.slices.SwipeDismissalDelegate;
|
import com.android.settings.homepage.contextualcards.slices.SwipeDismissalDelegate;
|
||||||
import com.android.settings.overlay.FeatureFactory;
|
import com.android.settings.overlay.FeatureFactory;
|
||||||
import com.android.settings.wifi.slice.ContextualWifiScanWorker;
|
|
||||||
|
|
||||||
public class ContextualCardsFragment extends InstrumentedFragment implements
|
public class ContextualCardsFragment extends InstrumentedFragment implements
|
||||||
FocusRecyclerView.FocusListener {
|
FocusRecyclerView.FocusListener {
|
||||||
@@ -80,7 +79,6 @@ public class ContextualCardsFragment extends InstrumentedFragment implements
|
|||||||
super.onStart();
|
super.onStart();
|
||||||
registerScreenOffReceiver();
|
registerScreenOffReceiver();
|
||||||
registerKeyEventReceiver();
|
registerKeyEventReceiver();
|
||||||
ContextualWifiScanWorker.newVisibleUiSession();
|
|
||||||
mContextualCardManager.loadContextualCards(LoaderManager.getInstance(this),
|
mContextualCardManager.loadContextualCards(LoaderManager.getInstance(this),
|
||||||
sRestartLoaderNeeded);
|
sRestartLoaderNeeded);
|
||||||
sRestartLoaderNeeded = false;
|
sRestartLoaderNeeded = false;
|
||||||
|
@@ -32,6 +32,7 @@ import androidx.annotation.VisibleForTesting;
|
|||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.core.InstrumentedFragment;
|
import com.android.settings.core.InstrumentedFragment;
|
||||||
|
import com.android.settings.wifi.dpp.WifiDppQrCodeScannerFragment;
|
||||||
import com.android.settings.wifi.dpp.WifiDppUtils;
|
import com.android.settings.wifi.dpp.WifiDppUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -116,7 +117,7 @@ public class AddNetworkFragment extends InstrumentedFragment implements WifiConf
|
|||||||
}
|
}
|
||||||
|
|
||||||
final WifiConfiguration config = data.getParcelableExtra(
|
final WifiConfiguration config = data.getParcelableExtra(
|
||||||
WifiDialogActivity.KEY_WIFI_CONFIGURATION);
|
WifiDppQrCodeScannerFragment.KEY_WIFI_CONFIGURATION);
|
||||||
successfullyFinish(config);
|
successfullyFinish(config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -57,7 +57,6 @@ import androidx.annotation.VisibleForTesting;
|
|||||||
import androidx.lifecycle.ViewModelProviders;
|
import androidx.lifecycle.ViewModelProviders;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.wifi.WifiDialogActivity;
|
|
||||||
import com.android.settings.wifi.qrcode.QrCamera;
|
import com.android.settings.wifi.qrcode.QrCamera;
|
||||||
import com.android.settings.wifi.qrcode.QrDecorateView;
|
import com.android.settings.wifi.qrcode.QrDecorateView;
|
||||||
import com.android.wifitrackerlib.WifiEntry;
|
import com.android.wifitrackerlib.WifiEntry;
|
||||||
@@ -91,7 +90,7 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
|
|||||||
// Key for Bundle usage
|
// Key for Bundle usage
|
||||||
private static final String KEY_IS_CONFIGURATOR_MODE = "key_is_configurator_mode";
|
private static final String KEY_IS_CONFIGURATOR_MODE = "key_is_configurator_mode";
|
||||||
private static final String KEY_LATEST_ERROR_CODE = "key_latest_error_code";
|
private static final String KEY_LATEST_ERROR_CODE = "key_latest_error_code";
|
||||||
private static final String KEY_WIFI_CONFIGURATION = "key_wifi_configuration";
|
public static final String KEY_WIFI_CONFIGURATION = "key_wifi_configuration";
|
||||||
|
|
||||||
private static final int ARG_RESTART_CAMERA = 1;
|
private static final int ARG_RESTART_CAMERA = 1;
|
||||||
|
|
||||||
@@ -689,8 +688,7 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
|
|||||||
@Override
|
@Override
|
||||||
public void onSuccess() {
|
public void onSuccess() {
|
||||||
final Intent resultIntent = new Intent();
|
final Intent resultIntent = new Intent();
|
||||||
resultIntent.putExtra(WifiDialogActivity.KEY_WIFI_CONFIGURATION,
|
resultIntent.putExtra(KEY_WIFI_CONFIGURATION, mEnrolleeWifiConfiguration);
|
||||||
mEnrolleeWifiConfiguration);
|
|
||||||
|
|
||||||
final Activity hostActivity = getActivity();
|
final Activity hostActivity = getActivity();
|
||||||
hostActivity.setResult(Activity.RESULT_OK, resultIntent);
|
hostActivity.setResult(Activity.RESULT_OK, resultIntent);
|
||||||
|
@@ -19,61 +19,74 @@ package com.android.settings.wifi.slice;
|
|||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.ConnectivityManager;
|
import android.text.TextUtils;
|
||||||
import android.net.Network;
|
import android.widget.Toast;
|
||||||
import android.net.wifi.WifiManager;
|
|
||||||
import android.os.Bundle;
|
|
||||||
|
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
|
|
||||||
import com.android.settings.wifi.WifiConnectListener;
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.slices.SliceBackgroundWorker;
|
||||||
import com.android.settings.wifi.WifiDialogActivity;
|
import com.android.settings.wifi.WifiDialogActivity;
|
||||||
import com.android.settings.wifi.WifiUtils;
|
import com.android.wifitrackerlib.WifiEntry;
|
||||||
import com.android.settingslib.wifi.AccessPoint;
|
import com.android.wifitrackerlib.WifiEntry.ConnectCallback;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This receiver helps connect to Wi-Fi network
|
* This receiver helps connect to Wi-Fi network
|
||||||
*/
|
*/
|
||||||
public class ConnectToWifiHandler extends BroadcastReceiver {
|
public class ConnectToWifiHandler extends BroadcastReceiver {
|
||||||
|
|
||||||
|
static final String KEY_CHOSEN_WIFIENTRY_KEY = "key_chosen_wifientry_key";
|
||||||
|
static final String KEY_WIFI_SLICE_URI = "key_wifi_slice_uri";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
if (context == null || intent == null) {
|
if (context == null || intent == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
final String key = intent.getStringExtra(KEY_CHOSEN_WIFIENTRY_KEY);
|
||||||
final Network network = intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK);
|
if (TextUtils.isEmpty(key)) {
|
||||||
final Bundle accessPointState = intent.getBundleExtra(
|
return;
|
||||||
WifiDialogActivity.KEY_ACCESS_POINT_STATE);
|
|
||||||
|
|
||||||
if (network != null) {
|
|
||||||
WifiScanWorker.clearClickedWifi();
|
|
||||||
final ConnectivityManager cm = context.getSystemService(ConnectivityManager.class);
|
|
||||||
// start captive portal app to sign in to network
|
|
||||||
cm.startCaptivePortalApp(network);
|
|
||||||
} else if (accessPointState != null) {
|
|
||||||
connect(context, new AccessPoint(context, accessPointState));
|
|
||||||
}
|
}
|
||||||
|
if (intent.getParcelableExtra(KEY_WIFI_SLICE_URI) == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final WifiScanWorker worker = getWifiScanWorker(intent);
|
||||||
|
if (worker == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final WifiEntry wifiEntry = worker.getWifiEntry(key);
|
||||||
|
if (wifiEntry == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wifiEntry.connect(new WifiEntryConnectCallback(context, wifiEntry));
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
void connect(Context context, AccessPoint accessPoint) {
|
WifiScanWorker getWifiScanWorker(Intent intent) {
|
||||||
ContextualWifiScanWorker.saveSession();
|
return SliceBackgroundWorker.getInstance(intent.getParcelableExtra(KEY_WIFI_SLICE_URI));
|
||||||
WifiScanWorker.saveClickedWifi(accessPoint);
|
}
|
||||||
|
|
||||||
final WifiConnectListener connectListener = new WifiConnectListener(context);
|
@VisibleForTesting
|
||||||
switch (WifiUtils.getConnectingType(accessPoint)) {
|
static class WifiEntryConnectCallback implements WifiEntry.ConnectCallback {
|
||||||
case WifiUtils.CONNECT_TYPE_OSU_PROVISION:
|
final Context mContext;
|
||||||
accessPoint.startOsuProvisioning(connectListener);
|
final WifiEntry mWifiEntry;
|
||||||
break;
|
|
||||||
|
|
||||||
case WifiUtils.CONNECT_TYPE_OPEN_NETWORK:
|
WifiEntryConnectCallback(Context context, WifiEntry connectWifiEntry) {
|
||||||
accessPoint.generateOpenNetworkConfig();
|
mContext = context;
|
||||||
|
mWifiEntry = connectWifiEntry;
|
||||||
|
}
|
||||||
|
|
||||||
case WifiUtils.CONNECT_TYPE_SAVED_NETWORK:
|
@Override
|
||||||
final WifiManager wifiManager = context.getSystemService(WifiManager.class);
|
public void onConnectResult(@ConnectStatus int status) {
|
||||||
wifiManager.connect(accessPoint.getConfig(), connectListener);
|
if (status == ConnectCallback.CONNECT_STATUS_FAILURE_NO_CONFIG) {
|
||||||
break;
|
final Intent intent = new Intent(mContext, WifiDialogActivity.class)
|
||||||
|
.putExtra(WifiDialogActivity.KEY_CHOSEN_WIFIENTRY_KEY, mWifiEntry.getKey());
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
mContext.startActivity(intent);
|
||||||
|
} else if (status == CONNECT_STATUS_FAILURE_UNKNOWN) {
|
||||||
|
Toast.makeText(mContext, R.string.wifi_failed_connect_message,
|
||||||
|
Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -18,7 +18,6 @@ package com.android.settings.wifi.slice;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.SystemClock;
|
|
||||||
|
|
||||||
import com.android.settings.slices.SliceBackgroundWorker;
|
import com.android.settings.slices.SliceBackgroundWorker;
|
||||||
|
|
||||||
@@ -27,42 +26,10 @@ import com.android.settings.slices.SliceBackgroundWorker;
|
|||||||
*/
|
*/
|
||||||
public class ContextualWifiScanWorker extends WifiScanWorker {
|
public class ContextualWifiScanWorker extends WifiScanWorker {
|
||||||
|
|
||||||
private static long sVisibleUiSessionToken;
|
|
||||||
private static long sActiveSession;
|
|
||||||
|
|
||||||
public ContextualWifiScanWorker(Context context, Uri uri) {
|
public ContextualWifiScanWorker(Context context, Uri uri) {
|
||||||
super(context, uri);
|
super(context, uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts a new visible UI session for the purpose of automatically starting captive portal.
|
|
||||||
*
|
|
||||||
* A visible UI session is defined as a duration of time when a UI screen is visible to user.
|
|
||||||
* Going to a sub-page and coming out breaks the continuation, leaving the page and coming back
|
|
||||||
* breaks it too.
|
|
||||||
*/
|
|
||||||
public static void newVisibleUiSession() {
|
|
||||||
sVisibleUiSessionToken = SystemClock.elapsedRealtime();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void saveSession() {
|
|
||||||
sActiveSession = sVisibleUiSessionToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void clearClickedWifiOnSliceUnpinned() {
|
|
||||||
// Do nothing for contextual Wi-Fi slice
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean isSessionValid() {
|
|
||||||
if (sVisibleUiSessionToken != sActiveSession) {
|
|
||||||
clearClickedWifi();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int getApRowCount() {
|
protected int getApRowCount() {
|
||||||
return ContextualWifiSlice.getApRowCount();
|
return ContextualWifiSlice.getApRowCount();
|
||||||
|
@@ -18,10 +18,8 @@ package com.android.settings.wifi.slice;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.net.ConnectivityManager;
|
||||||
import android.net.NetworkCapabilities;
|
import android.net.NetworkCapabilities;
|
||||||
import android.net.NetworkInfo;
|
|
||||||
import android.net.NetworkInfo.DetailedState;
|
|
||||||
import android.net.NetworkInfo.State;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.net.wifi.WifiInfo;
|
import android.net.wifi.WifiInfo;
|
||||||
import android.net.wifi.WifiManager;
|
import android.net.wifi.WifiManager;
|
||||||
@@ -37,7 +35,7 @@ import com.android.settings.Utils;
|
|||||||
import com.android.settings.overlay.FeatureFactory;
|
import com.android.settings.overlay.FeatureFactory;
|
||||||
import com.android.settings.slices.CustomSliceRegistry;
|
import com.android.settings.slices.CustomSliceRegistry;
|
||||||
import com.android.settings.slices.CustomSliceable;
|
import com.android.settings.slices.CustomSliceable;
|
||||||
import com.android.settingslib.wifi.AccessPoint;
|
import com.android.wifitrackerlib.WifiEntry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link CustomSliceable} for Wi-Fi, used by contextual homepage.
|
* {@link CustomSliceable} for Wi-Fi, used by contextual homepage.
|
||||||
@@ -52,8 +50,12 @@ public class ContextualWifiSlice extends WifiSlice {
|
|||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static boolean sApRowCollapsed;
|
static boolean sApRowCollapsed;
|
||||||
|
|
||||||
|
private final ConnectivityManager mConnectivityManager;
|
||||||
|
|
||||||
public ContextualWifiSlice(Context context) {
|
public ContextualWifiSlice(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
|
|
||||||
|
mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -84,16 +86,17 @@ public class ContextualWifiSlice extends WifiSlice {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ListBuilder.RowBuilder getHeaderRow(boolean isWifiEnabled, AccessPoint accessPoint) {
|
protected ListBuilder.RowBuilder getHeaderRow(boolean isWifiEnabled,
|
||||||
final ListBuilder.RowBuilder builder = super.getHeaderRow(isWifiEnabled, accessPoint);
|
WifiSliceItem wifiSliceItem) {
|
||||||
builder.setTitleItem(getHeaderIcon(isWifiEnabled, accessPoint), ListBuilder.ICON_IMAGE);
|
final ListBuilder.RowBuilder builder = super.getHeaderRow(isWifiEnabled, wifiSliceItem);
|
||||||
|
builder.setTitleItem(getHeaderIcon(isWifiEnabled, wifiSliceItem), ListBuilder.ICON_IMAGE);
|
||||||
if (sApRowCollapsed) {
|
if (sApRowCollapsed) {
|
||||||
builder.setSubtitle(getSubtitle(accessPoint));
|
builder.setSubtitle(getHeaderSubtitle(wifiSliceItem));
|
||||||
}
|
}
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IconCompat getHeaderIcon(boolean isWifiEnabled, AccessPoint accessPoint) {
|
private IconCompat getHeaderIcon(boolean isWifiEnabled, WifiSliceItem wifiSliceItem) {
|
||||||
final Drawable drawable;
|
final Drawable drawable;
|
||||||
final int tint;
|
final int tint;
|
||||||
if (!isWifiEnabled) {
|
if (!isWifiEnabled) {
|
||||||
@@ -103,7 +106,8 @@ public class ContextualWifiSlice extends WifiSlice {
|
|||||||
} else {
|
} else {
|
||||||
// get icon of medium signal strength
|
// get icon of medium signal strength
|
||||||
drawable = mContext.getDrawable(com.android.settingslib.Utils.getWifiIconResource(2));
|
drawable = mContext.getDrawable(com.android.settingslib.Utils.getWifiIconResource(2));
|
||||||
if (isNetworkConnected(accessPoint)) {
|
if (wifiSliceItem != null
|
||||||
|
&& wifiSliceItem.getConnectedState() == WifiEntry.CONNECTED_STATE_CONNECTED) {
|
||||||
tint = Utils.getColorAccentDefaultColor(mContext);
|
tint = Utils.getColorAccentDefaultColor(mContext);
|
||||||
} else {
|
} else {
|
||||||
tint = Utils.getColorAttrDefaultColor(mContext, android.R.attr.colorControlNormal);
|
tint = Utils.getColorAttrDefaultColor(mContext, android.R.attr.colorControlNormal);
|
||||||
@@ -113,49 +117,16 @@ public class ContextualWifiSlice extends WifiSlice {
|
|||||||
return Utils.createIconWithDrawable(drawable);
|
return Utils.createIconWithDrawable(drawable);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isNetworkConnected(AccessPoint accessPoint) {
|
private CharSequence getHeaderSubtitle(WifiSliceItem wifiSliceItem) {
|
||||||
if (accessPoint == null) {
|
if (wifiSliceItem == null
|
||||||
return false;
|
|| wifiSliceItem.getConnectedState() == WifiEntry.CONNECTED_STATE_DISCONNECTED) {
|
||||||
}
|
|
||||||
|
|
||||||
final NetworkInfo networkInfo = accessPoint.getNetworkInfo();
|
|
||||||
if (networkInfo == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return networkInfo.getState() == State.CONNECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
private CharSequence getSubtitle(AccessPoint accessPoint) {
|
|
||||||
if (isCaptivePortal()) {
|
|
||||||
final int id = mContext.getResources()
|
|
||||||
.getIdentifier("network_available_sign_in", "string", "android");
|
|
||||||
return mContext.getText(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (accessPoint == null) {
|
|
||||||
return mContext.getText(R.string.disconnected);
|
return mContext.getText(R.string.disconnected);
|
||||||
}
|
}
|
||||||
|
if (wifiSliceItem.getConnectedState() == WifiEntry.CONNECTED_STATE_CONNECTING) {
|
||||||
final NetworkInfo networkInfo = accessPoint.getNetworkInfo();
|
return mContext.getString(R.string.wifi_connecting_to_message,
|
||||||
if (networkInfo == null) {
|
wifiSliceItem.getTitle());
|
||||||
return mContext.getText(R.string.disconnected);
|
|
||||||
}
|
}
|
||||||
|
return mContext.getString(R.string.wifi_connected_to_message, wifiSliceItem.getTitle());
|
||||||
final State state = networkInfo.getState();
|
|
||||||
DetailedState detailedState;
|
|
||||||
if (state == State.CONNECTING) {
|
|
||||||
detailedState = DetailedState.CONNECTING;
|
|
||||||
} else if (state == State.CONNECTED) {
|
|
||||||
detailedState = DetailedState.CONNECTED;
|
|
||||||
} else {
|
|
||||||
detailedState = networkInfo.getDetailedState();
|
|
||||||
}
|
|
||||||
|
|
||||||
final String[] formats = mContext.getResources().getStringArray(
|
|
||||||
R.array.wifi_status_with_ssid);
|
|
||||||
final int index = detailedState.ordinal();
|
|
||||||
return String.format(formats[index], accessPoint.getTitle());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasWorkingNetwork() {
|
private boolean hasWorkingNetwork() {
|
||||||
|
@@ -16,243 +16,187 @@
|
|||||||
|
|
||||||
package com.android.settings.wifi.slice;
|
package com.android.settings.wifi.slice;
|
||||||
|
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
|
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
|
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
|
|
||||||
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
|
|
||||||
|
|
||||||
import static com.android.settings.wifi.slice.WifiSlice.DEFAULT_EXPANDED_ROW_COUNT;
|
import static com.android.settings.wifi.slice.WifiSlice.DEFAULT_EXPANDED_ROW_COUNT;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.net.ConnectivityManager.NetworkCallback;
|
import android.net.NetworkScoreManager;
|
||||||
import android.net.Network;
|
|
||||||
import android.net.NetworkCapabilities;
|
|
||||||
import android.net.NetworkRequest;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.net.wifi.WifiInfo;
|
import android.net.wifi.WifiManager;
|
||||||
import android.os.Bundle;
|
import android.os.HandlerThread;
|
||||||
import android.os.Handler;
|
import android.os.Process;
|
||||||
import android.os.Looper;
|
import android.os.SimpleClock;
|
||||||
import android.os.UserHandle;
|
import android.os.SystemClock;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
|
import androidx.lifecycle.Lifecycle;
|
||||||
|
import androidx.lifecycle.LifecycleOwner;
|
||||||
|
import androidx.lifecycle.LifecycleRegistry;
|
||||||
|
|
||||||
import com.android.internal.util.Preconditions;
|
|
||||||
import com.android.settings.slices.SliceBackgroundWorker;
|
import com.android.settings.slices.SliceBackgroundWorker;
|
||||||
import com.android.settingslib.wifi.AccessPoint;
|
import com.android.settingslib.utils.ThreadUtils;
|
||||||
import com.android.settingslib.wifi.WifiTracker;
|
import com.android.wifitrackerlib.WifiEntry;
|
||||||
|
import com.android.wifitrackerlib.WifiEntry.WifiEntryCallback;
|
||||||
|
import com.android.wifitrackerlib.WifiPickerTracker;
|
||||||
|
|
||||||
|
import java.time.Clock;
|
||||||
|
import java.time.ZoneOffset;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link SliceBackgroundWorker} for Wi-Fi, used by {@link WifiSlice}.
|
* {@link SliceBackgroundWorker} for Wi-Fi, used by {@link WifiSlice}.
|
||||||
*/
|
*/
|
||||||
public class WifiScanWorker extends SliceBackgroundWorker<AccessPoint> implements
|
public class WifiScanWorker extends SliceBackgroundWorker<WifiSliceItem> implements
|
||||||
WifiTracker.WifiListener {
|
WifiPickerTracker.WifiPickerTrackerCallback, LifecycleOwner, WifiEntryCallback {
|
||||||
|
|
||||||
private static final String TAG = "WifiScanWorker";
|
private static final String TAG = "WifiScanWorker";
|
||||||
|
|
||||||
|
// Max age of tracked WifiEntries.
|
||||||
|
private static final long MAX_SCAN_AGE_MILLIS = 15_000;
|
||||||
|
// Interval between initiating WifiPickerTracker scans.
|
||||||
|
private static final long SCAN_INTERVAL_MILLIS = 10_000;
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
WifiNetworkCallback mNetworkCallback;
|
final LifecycleRegistry mLifecycleRegistry;
|
||||||
|
@VisibleForTesting
|
||||||
private final Context mContext;
|
WifiPickerTracker mWifiPickerTracker;
|
||||||
private final ConnectivityManager mConnectivityManager;
|
// Worker thread used for WifiPickerTracker work
|
||||||
private final WifiTracker mWifiTracker;
|
private final HandlerThread mWorkerThread;
|
||||||
|
|
||||||
private static String sClickedWifiSsid;
|
|
||||||
|
|
||||||
public WifiScanWorker(Context context, Uri uri) {
|
public WifiScanWorker(Context context, Uri uri) {
|
||||||
super(context, uri);
|
super(context, uri);
|
||||||
mContext = context;
|
|
||||||
mConnectivityManager = context.getSystemService(ConnectivityManager.class);
|
mLifecycleRegistry = new LifecycleRegistry(this);
|
||||||
mWifiTracker = new WifiTracker(mContext, this /* wifiListener */,
|
|
||||||
true /* includeSaved */, true /* includeScans */);
|
mWorkerThread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND);
|
||||||
|
mWorkerThread.start();
|
||||||
|
final Clock elapsedRealtimeClock = new SimpleClock(ZoneOffset.UTC) {
|
||||||
|
@Override
|
||||||
|
public long millis() {
|
||||||
|
return SystemClock.elapsedRealtime();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
mWifiPickerTracker = new WifiPickerTracker(getLifecycle(), context,
|
||||||
|
context.getSystemService(WifiManager.class),
|
||||||
|
context.getSystemService(ConnectivityManager.class),
|
||||||
|
context.getSystemService(NetworkScoreManager.class),
|
||||||
|
ThreadUtils.getUiThreadHandler(),
|
||||||
|
mWorkerThread.getThreadHandler(),
|
||||||
|
elapsedRealtimeClock,
|
||||||
|
MAX_SCAN_AGE_MILLIS,
|
||||||
|
SCAN_INTERVAL_MILLIS,
|
||||||
|
this);
|
||||||
|
|
||||||
|
mLifecycleRegistry.markState(Lifecycle.State.INITIALIZED);
|
||||||
|
mLifecycleRegistry.markState(Lifecycle.State.CREATED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onSlicePinned() {
|
protected void onSlicePinned() {
|
||||||
mWifiTracker.onStart();
|
mLifecycleRegistry.markState(Lifecycle.State.STARTED);
|
||||||
onAccessPointsChanged();
|
mLifecycleRegistry.markState(Lifecycle.State.RESUMED);
|
||||||
|
updateResults();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onSliceUnpinned() {
|
protected void onSliceUnpinned() {
|
||||||
mWifiTracker.onStop();
|
mLifecycleRegistry.markState(Lifecycle.State.STARTED);
|
||||||
unregisterNetworkCallback();
|
mLifecycleRegistry.markState(Lifecycle.State.CREATED);
|
||||||
clearClickedWifiOnSliceUnpinned();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
mWifiTracker.onDestroy();
|
mLifecycleRegistry.markState(Lifecycle.State.DESTROYED);
|
||||||
|
mWorkerThread.quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onWifiStateChanged(int state) {
|
public Lifecycle getLifecycle() {
|
||||||
|
return mLifecycleRegistry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Called when the state of Wifi has changed. */
|
||||||
|
@Override
|
||||||
|
public void onWifiStateChanged() {
|
||||||
notifySliceChange();
|
notifySliceChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the results when data changes
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onConnectedChanged() {
|
public void onWifiEntriesChanged() {
|
||||||
|
updateResults();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates the state of the WifiEntry has changed and clients may retrieve updates through
|
||||||
|
* the WifiEntry getter methods.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onAccessPointsChanged() {
|
public void onUpdated() {
|
||||||
// in case state has changed
|
updateResults();
|
||||||
if (!mWifiTracker.getManager().isWifiEnabled()) {
|
|
||||||
updateResults(null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// AccessPoints are sorted by the WifiTracker
|
|
||||||
final List<AccessPoint> accessPoints = mWifiTracker.getAccessPoints();
|
|
||||||
final List<AccessPoint> resultList = new ArrayList<>();
|
|
||||||
final int apRowCount = getApRowCount();
|
|
||||||
for (AccessPoint ap : accessPoints) {
|
|
||||||
if (ap.isReachable()) {
|
|
||||||
resultList.add(clone(ap));
|
|
||||||
if (resultList.size() >= apRowCount) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
updateResults(resultList);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int getApRowCount() {
|
protected int getApRowCount() {
|
||||||
return DEFAULT_EXPANDED_ROW_COUNT;
|
return DEFAULT_EXPANDED_ROW_COUNT;
|
||||||
}
|
}
|
||||||
|
|
||||||
private AccessPoint clone(AccessPoint accessPoint) {
|
@Override
|
||||||
final Bundle savedState = new Bundle();
|
public void onNumSavedSubscriptionsChanged() {
|
||||||
accessPoint.saveWifiState(savedState);
|
// Do nothing.
|
||||||
return new AccessPoint(mContext, savedState);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean areListsTheSame(List<AccessPoint> a, List<AccessPoint> b) {
|
public void onNumSavedNetworksChanged() {
|
||||||
if (!a.equals(b)) {
|
// Do nothing.
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// compare access point states one by one
|
/**
|
||||||
final int listSize = a.size();
|
* To get the WifiEntry of key.
|
||||||
for (int i = 0; i < listSize; i++) {
|
*/
|
||||||
if (a.get(i).getDetailedState() != b.get(i).getDetailedState()) {
|
public WifiEntry getWifiEntry(String key) {
|
||||||
return false;
|
// Get specified WifiEntry.
|
||||||
|
WifiEntry keyWifiEntry = null;
|
||||||
|
final WifiEntry connectedWifiEntry = mWifiPickerTracker.getConnectedWifiEntry();
|
||||||
|
if (connectedWifiEntry != null && TextUtils.equals(key, connectedWifiEntry.getKey())) {
|
||||||
|
keyWifiEntry = connectedWifiEntry;
|
||||||
|
} else {
|
||||||
|
for (WifiEntry wifiEntry : mWifiPickerTracker.getWifiEntries()) {
|
||||||
|
if (TextUtils.equals(key, wifiEntry.getKey())) {
|
||||||
|
keyWifiEntry = wifiEntry;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return keyWifiEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void saveClickedWifi(AccessPoint accessPoint) {
|
@VisibleForTesting
|
||||||
sClickedWifiSsid = accessPoint.getSsidStr();
|
void updateResults() {
|
||||||
}
|
if (mWifiPickerTracker.getWifiState() != WifiManager.WIFI_STATE_ENABLED
|
||||||
|
|| mLifecycleRegistry.getCurrentState() != Lifecycle.State.RESUMED) {
|
||||||
static void clearClickedWifi() {
|
super.updateResults(null);
|
||||||
sClickedWifiSsid = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
static boolean isWifiClicked(WifiInfo info) {
|
|
||||||
final String ssid = WifiInfo.sanitizeSsid(info.getSSID());
|
|
||||||
return !TextUtils.isEmpty(ssid) && TextUtils.equals(ssid, sClickedWifiSsid);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void clearClickedWifiOnSliceUnpinned() {
|
|
||||||
clearClickedWifi();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean isSessionValid() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void registerNetworkCallback(Network wifiNetwork) {
|
|
||||||
if (wifiNetwork == null) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mNetworkCallback != null && mNetworkCallback.isSameNetwork(wifiNetwork)) {
|
final List<WifiSliceItem> resultList = new ArrayList<>();
|
||||||
return;
|
final WifiEntry connectedWifiEntry = mWifiPickerTracker.getConnectedWifiEntry();
|
||||||
|
if (connectedWifiEntry != null) {
|
||||||
|
connectedWifiEntry.setListener(this);
|
||||||
|
resultList.add(new WifiSliceItem(getContext(), connectedWifiEntry));
|
||||||
}
|
}
|
||||||
|
for (WifiEntry wifiEntry : mWifiPickerTracker.getWifiEntries()) {
|
||||||
unregisterNetworkCallback();
|
if (resultList.size() >= getApRowCount()) {
|
||||||
|
break;
|
||||||
mNetworkCallback = new WifiNetworkCallback(wifiNetwork);
|
|
||||||
mConnectivityManager.registerNetworkCallback(
|
|
||||||
new NetworkRequest.Builder()
|
|
||||||
.clearCapabilities()
|
|
||||||
.addTransportType(TRANSPORT_WIFI)
|
|
||||||
.build(),
|
|
||||||
mNetworkCallback,
|
|
||||||
new Handler(Looper.getMainLooper()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void unregisterNetworkCallback() {
|
|
||||||
if (mNetworkCallback != null) {
|
|
||||||
try {
|
|
||||||
mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
Log.e(TAG, "Unregistering CaptivePortalNetworkCallback failed.", e);
|
|
||||||
}
|
}
|
||||||
mNetworkCallback = null;
|
if (wifiEntry.getLevel() != WifiEntry.WIFI_LEVEL_UNREACHABLE) {
|
||||||
}
|
wifiEntry.setListener(this);
|
||||||
}
|
resultList.add(new WifiSliceItem(getContext(), wifiEntry));
|
||||||
|
|
||||||
class WifiNetworkCallback extends NetworkCallback {
|
|
||||||
|
|
||||||
private final Network mNetwork;
|
|
||||||
private boolean mIsCaptivePortal;
|
|
||||||
private boolean mHasPartialConnectivity;
|
|
||||||
private boolean mIsValidated;
|
|
||||||
|
|
||||||
WifiNetworkCallback(Network network) {
|
|
||||||
mNetwork = Preconditions.checkNotNull(network);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCapabilitiesChanged(Network network, NetworkCapabilities nc) {
|
|
||||||
if (!isSameNetwork(network)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final boolean prevIsCaptivePortal = mIsCaptivePortal;
|
|
||||||
final boolean prevHasPartialConnectivity = mHasPartialConnectivity;
|
|
||||||
final boolean prevIsValidated = mIsValidated;
|
|
||||||
|
|
||||||
mIsCaptivePortal = nc.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
|
|
||||||
mHasPartialConnectivity = nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY);
|
|
||||||
mIsValidated = nc.hasCapability(NET_CAPABILITY_VALIDATED);
|
|
||||||
|
|
||||||
if (prevIsCaptivePortal == mIsCaptivePortal
|
|
||||||
&& prevHasPartialConnectivity == mHasPartialConnectivity
|
|
||||||
&& prevIsValidated == mIsValidated) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
notifySliceChange();
|
|
||||||
|
|
||||||
// Automatically start captive portal
|
|
||||||
if (!prevIsCaptivePortal && mIsCaptivePortal
|
|
||||||
&& isWifiClicked(mWifiTracker.getManager().getConnectionInfo())
|
|
||||||
&& isSessionValid()) {
|
|
||||||
final Intent intent = new Intent(mContext, ConnectToWifiHandler.class)
|
|
||||||
.putExtra(ConnectivityManager.EXTRA_NETWORK, network)
|
|
||||||
.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
|
|
||||||
// Sending a broadcast in the system process needs to specify a user
|
|
||||||
mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
super.updateResults(resultList);
|
||||||
/**
|
|
||||||
* Returns true if the supplied network is not null and is the same as the originally
|
|
||||||
* supplied value.
|
|
||||||
*/
|
|
||||||
public boolean isSameNetwork(Network network) {
|
|
||||||
return mNetwork.equals(network);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -29,9 +29,6 @@ import android.content.Intent;
|
|||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.drawable.ColorDrawable;
|
import android.graphics.drawable.ColorDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.net.ConnectivityManager;
|
|
||||||
import android.net.NetworkCapabilities;
|
|
||||||
import android.net.NetworkInfo;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.net.wifi.WifiManager;
|
import android.net.wifi.WifiManager;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@@ -52,9 +49,8 @@ import com.android.settings.slices.SliceBackgroundWorker;
|
|||||||
import com.android.settings.slices.SliceBuilderUtils;
|
import com.android.settings.slices.SliceBuilderUtils;
|
||||||
import com.android.settings.wifi.WifiDialogActivity;
|
import com.android.settings.wifi.WifiDialogActivity;
|
||||||
import com.android.settings.wifi.WifiSettings;
|
import com.android.settings.wifi.WifiSettings;
|
||||||
import com.android.settings.wifi.WifiUtils;
|
import com.android.settings.wifi.details2.WifiNetworkDetailsFragment2;
|
||||||
import com.android.settings.wifi.details.WifiNetworkDetailsFragment;
|
import com.android.wifitrackerlib.WifiEntry;
|
||||||
import com.android.settingslib.wifi.AccessPoint;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -71,12 +67,10 @@ public class WifiSlice implements CustomSliceable {
|
|||||||
|
|
||||||
protected final Context mContext;
|
protected final Context mContext;
|
||||||
protected final WifiManager mWifiManager;
|
protected final WifiManager mWifiManager;
|
||||||
protected final ConnectivityManager mConnectivityManager;
|
|
||||||
|
|
||||||
public WifiSlice(Context context) {
|
public WifiSlice(Context context) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mWifiManager = mContext.getSystemService(WifiManager.class);
|
mWifiManager = mContext.getSystemService(WifiManager.class);
|
||||||
mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -87,17 +81,16 @@ public class WifiSlice implements CustomSliceable {
|
|||||||
@Override
|
@Override
|
||||||
public Slice getSlice() {
|
public Slice getSlice() {
|
||||||
final boolean isWifiEnabled = isWifiEnabled();
|
final boolean isWifiEnabled = isWifiEnabled();
|
||||||
ListBuilder listBuilder = getListBuilder(isWifiEnabled, null /* accessPoint */);
|
ListBuilder listBuilder = getListBuilder(isWifiEnabled, null /* wifiSliceItem */);
|
||||||
if (!isWifiEnabled) {
|
if (!isWifiEnabled) {
|
||||||
WifiScanWorker.clearClickedWifi();
|
|
||||||
return listBuilder.build();
|
return listBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
final WifiScanWorker worker = SliceBackgroundWorker.getInstance(getUri());
|
final WifiScanWorker worker = SliceBackgroundWorker.getInstance(getUri());
|
||||||
final List<AccessPoint> apList = worker != null ? worker.getResults() : null;
|
final List<WifiSliceItem> apList = worker != null ? worker.getResults() : null;
|
||||||
final int apCount = apList == null ? 0 : apList.size();
|
final int apCount = apList == null ? 0 : apList.size();
|
||||||
final boolean isFirstApActive = apCount > 0 && apList.get(0).isActive();
|
final boolean isFirstApActive = apCount > 0
|
||||||
handleNetworkCallback(worker, isFirstApActive);
|
&& apList.get(0).getConnectedState() != WifiEntry.CONNECTED_STATE_DISCONNECTED;
|
||||||
|
|
||||||
if (isFirstApActive) {
|
if (isFirstApActive) {
|
||||||
// refresh header subtext
|
// refresh header subtext
|
||||||
@@ -112,7 +105,7 @@ public class WifiSlice implements CustomSliceable {
|
|||||||
final CharSequence placeholder = mContext.getText(R.string.summary_placeholder);
|
final CharSequence placeholder = mContext.getText(R.string.summary_placeholder);
|
||||||
for (int i = 0; i < DEFAULT_EXPANDED_ROW_COUNT; i++) {
|
for (int i = 0; i < DEFAULT_EXPANDED_ROW_COUNT; i++) {
|
||||||
if (i < apCount) {
|
if (i < apCount) {
|
||||||
listBuilder.addRow(getAccessPointRow(apList.get(i)));
|
listBuilder.addRow(getWifiSliceItemRow(apList.get(i)));
|
||||||
} else if (i == apCount) {
|
} else if (i == apCount) {
|
||||||
listBuilder.addRow(getLoadingRow(placeholder));
|
listBuilder.addRow(getLoadingRow(placeholder));
|
||||||
} else {
|
} else {
|
||||||
@@ -124,22 +117,12 @@ public class WifiSlice implements CustomSliceable {
|
|||||||
return listBuilder.build();
|
return listBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleNetworkCallback(WifiScanWorker worker, boolean isFirstApActive) {
|
|
||||||
if (worker == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (isFirstApActive) {
|
|
||||||
worker.registerNetworkCallback(mWifiManager.getCurrentNetwork());
|
|
||||||
} else {
|
|
||||||
worker.unregisterNetworkCallback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean isApRowCollapsed() {
|
protected boolean isApRowCollapsed() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ListBuilder.RowBuilder getHeaderRow(boolean isWifiEnabled, AccessPoint accessPoint) {
|
protected ListBuilder.RowBuilder getHeaderRow(boolean isWifiEnabled,
|
||||||
|
WifiSliceItem wifiSliceItem) {
|
||||||
final IconCompat icon = IconCompat.createWithResource(mContext,
|
final IconCompat icon = IconCompat.createWithResource(mContext,
|
||||||
R.drawable.ic_settings_wireless);
|
R.drawable.ic_settings_wireless);
|
||||||
final String title = mContext.getString(R.string.wifi_settings);
|
final String title = mContext.getString(R.string.wifi_settings);
|
||||||
@@ -152,115 +135,90 @@ public class WifiSlice implements CustomSliceable {
|
|||||||
.setPrimaryAction(primarySliceAction);
|
.setPrimaryAction(primarySliceAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ListBuilder getListBuilder(boolean isWifiEnabled, AccessPoint accessPoint) {
|
private ListBuilder getListBuilder(boolean isWifiEnabled, WifiSliceItem wifiSliceItem) {
|
||||||
final PendingIntent toggleAction = getBroadcastIntent(mContext);
|
final PendingIntent toggleAction = getBroadcastIntent(mContext);
|
||||||
final SliceAction toggleSliceAction = SliceAction.createToggle(toggleAction,
|
final SliceAction toggleSliceAction = SliceAction.createToggle(toggleAction,
|
||||||
null /* actionTitle */, isWifiEnabled);
|
null /* actionTitle */, isWifiEnabled);
|
||||||
final ListBuilder builder = new ListBuilder(mContext, getUri(), ListBuilder.INFINITY)
|
final ListBuilder builder = new ListBuilder(mContext, getUri(), ListBuilder.INFINITY)
|
||||||
.setAccentColor(COLOR_NOT_TINTED)
|
.setAccentColor(COLOR_NOT_TINTED)
|
||||||
.setKeywords(getKeywords())
|
.setKeywords(getKeywords())
|
||||||
.addRow(getHeaderRow(isWifiEnabled, accessPoint))
|
.addRow(getHeaderRow(isWifiEnabled, wifiSliceItem))
|
||||||
.addAction(toggleSliceAction);
|
.addAction(toggleSliceAction);
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ListBuilder.RowBuilder getAccessPointRow(AccessPoint accessPoint) {
|
private ListBuilder.RowBuilder getWifiSliceItemRow(WifiSliceItem wifiSliceItem) {
|
||||||
final boolean isCaptivePortal = accessPoint.isActive() && isCaptivePortal();
|
final CharSequence title = wifiSliceItem.getTitle();
|
||||||
final CharSequence title = accessPoint.getTitle();
|
final IconCompat levelIcon = getWifiSliceItemLevelIcon(wifiSliceItem);
|
||||||
final CharSequence summary = getAccessPointSummary(accessPoint, isCaptivePortal);
|
|
||||||
final IconCompat levelIcon = getAccessPointLevelIcon(accessPoint);
|
|
||||||
final ListBuilder.RowBuilder rowBuilder = new ListBuilder.RowBuilder()
|
final ListBuilder.RowBuilder rowBuilder = new ListBuilder.RowBuilder()
|
||||||
.setTitleItem(levelIcon, ListBuilder.ICON_IMAGE)
|
.setTitleItem(levelIcon, ListBuilder.ICON_IMAGE)
|
||||||
.setTitle(title)
|
.setTitle(title)
|
||||||
.setSubtitle(summary)
|
.setSubtitle(wifiSliceItem.getSummary())
|
||||||
.setPrimaryAction(getAccessPointAction(accessPoint, isCaptivePortal, levelIcon,
|
.setContentDescription(wifiSliceItem.getContentDescription())
|
||||||
title));
|
.setPrimaryAction(getWifiEntryAction(wifiSliceItem, levelIcon, title));
|
||||||
|
|
||||||
if (isCaptivePortal) {
|
final IconCompat endIcon = getEndIcon(wifiSliceItem);
|
||||||
rowBuilder.addEndItem(getCaptivePortalEndAction(accessPoint, title));
|
if (endIcon != null) {
|
||||||
} else {
|
rowBuilder.addEndItem(endIcon, ListBuilder.ICON_IMAGE);
|
||||||
final IconCompat endIcon = getEndIcon(accessPoint);
|
|
||||||
if (endIcon != null) {
|
|
||||||
rowBuilder.addEndItem(endIcon, ListBuilder.ICON_IMAGE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return rowBuilder;
|
return rowBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CharSequence getAccessPointSummary(AccessPoint accessPoint, boolean isCaptivePortal) {
|
private IconCompat getWifiSliceItemLevelIcon(WifiSliceItem wifiSliceItem) {
|
||||||
if (isCaptivePortal) {
|
|
||||||
return mContext.getText(R.string.wifi_tap_to_sign_in);
|
|
||||||
}
|
|
||||||
|
|
||||||
final CharSequence summary = accessPoint.getSettingsSummary();
|
|
||||||
return TextUtils.isEmpty(summary) ? mContext.getText(R.string.disconnected) : summary;
|
|
||||||
}
|
|
||||||
|
|
||||||
private IconCompat getAccessPointLevelIcon(AccessPoint accessPoint) {
|
|
||||||
final @ColorInt int tint;
|
final @ColorInt int tint;
|
||||||
if (accessPoint.isActive()) {
|
if (wifiSliceItem.getConnectedState() == WifiEntry.CONNECTED_STATE_CONNECTED) {
|
||||||
final NetworkInfo.State state = accessPoint.getNetworkInfo().getState();
|
tint = Utils.getColorAccentDefaultColor(mContext);
|
||||||
if (state == NetworkInfo.State.CONNECTED) {
|
} else if (wifiSliceItem.getConnectedState() == WifiEntry.CONNECTED_STATE_DISCONNECTED) {
|
||||||
tint = Utils.getColorAccentDefaultColor(mContext);
|
|
||||||
} else { // connecting
|
|
||||||
tint = Utils.getDisabled(mContext, Utils.getColorAttrDefaultColor(mContext,
|
|
||||||
android.R.attr.colorControlNormal));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
tint = Utils.getColorAttrDefaultColor(mContext, android.R.attr.colorControlNormal);
|
tint = Utils.getColorAttrDefaultColor(mContext, android.R.attr.colorControlNormal);
|
||||||
|
} else {
|
||||||
|
tint = Utils.getDisabled(mContext, Utils.getColorAttrDefaultColor(mContext,
|
||||||
|
android.R.attr.colorControlNormal));
|
||||||
}
|
}
|
||||||
|
|
||||||
final Drawable drawable = mContext.getDrawable(
|
final Drawable drawable = mContext.getDrawable(
|
||||||
com.android.settingslib.Utils.getWifiIconResource(accessPoint.getLevel()));
|
com.android.settingslib.Utils.getWifiIconResource(wifiSliceItem.getLevel()));
|
||||||
drawable.setTint(tint);
|
drawable.setTint(tint);
|
||||||
return Utils.createIconWithDrawable(drawable);
|
return Utils.createIconWithDrawable(drawable);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IconCompat getEndIcon(AccessPoint accessPoint) {
|
private IconCompat getEndIcon(WifiSliceItem wifiSliceItem) {
|
||||||
if (accessPoint.isActive()) {
|
if (wifiSliceItem.getConnectedState() != WifiEntry.CONNECTED_STATE_DISCONNECTED) {
|
||||||
return null;
|
return null;
|
||||||
} else if (accessPoint.getSecurity() != AccessPoint.SECURITY_NONE) {
|
}
|
||||||
|
|
||||||
|
if (wifiSliceItem.getSecurity() != WifiEntry.SECURITY_NONE) {
|
||||||
return IconCompat.createWithResource(mContext, R.drawable.ic_friction_lock_closed);
|
return IconCompat.createWithResource(mContext, R.drawable.ic_friction_lock_closed);
|
||||||
} else if (accessPoint.isMetered()) {
|
|
||||||
return IconCompat.createWithResource(mContext, R.drawable.ic_friction_money);
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private SliceAction getCaptivePortalEndAction(AccessPoint accessPoint, CharSequence title) {
|
private SliceAction getWifiEntryAction(WifiSliceItem wifiSliceItem, IconCompat icon,
|
||||||
return getAccessPointAction(accessPoint, false /* isCaptivePortal */,
|
CharSequence title) {
|
||||||
IconCompat.createWithResource(mContext, R.drawable.ic_settings_accent), title);
|
final int requestCode = wifiSliceItem.getKey().hashCode();
|
||||||
}
|
|
||||||
|
|
||||||
private SliceAction getAccessPointAction(AccessPoint accessPoint, boolean isCaptivePortal,
|
if (wifiSliceItem.getConnectedState() != WifiEntry.CONNECTED_STATE_DISCONNECTED) {
|
||||||
IconCompat icon, CharSequence title) {
|
final Bundle bundle = new Bundle();
|
||||||
final int requestCode = accessPoint.hashCode();
|
bundle.putString(WifiNetworkDetailsFragment2.KEY_CHOSEN_WIFIENTRY_KEY,
|
||||||
if (isCaptivePortal) {
|
wifiSliceItem.getKey());
|
||||||
final Intent intent = new Intent(mContext, ConnectToWifiHandler.class)
|
|
||||||
.putExtra(ConnectivityManager.EXTRA_NETWORK, mWifiManager.getCurrentNetwork());
|
|
||||||
return getBroadcastAction(requestCode, intent, icon, title);
|
|
||||||
}
|
|
||||||
|
|
||||||
final Bundle extras = new Bundle();
|
|
||||||
accessPoint.saveWifiState(extras);
|
|
||||||
|
|
||||||
if (accessPoint.isActive()) {
|
|
||||||
final Intent intent = new SubSettingLauncher(mContext)
|
final Intent intent = new SubSettingLauncher(mContext)
|
||||||
.setTitleRes(R.string.pref_title_network_details)
|
.setTitleRes(R.string.pref_title_network_details)
|
||||||
.setDestination(WifiNetworkDetailsFragment.class.getName())
|
.setDestination(WifiNetworkDetailsFragment2.class.getName())
|
||||||
.setArguments(extras)
|
.setArguments(bundle)
|
||||||
.setSourceMetricsCategory(SettingsEnums.WIFI)
|
.setSourceMetricsCategory(SettingsEnums.WIFI)
|
||||||
.toIntent();
|
.toIntent();
|
||||||
return getActivityAction(requestCode, intent, icon, title);
|
return getActivityAction(requestCode, intent, icon, title);
|
||||||
} else if (WifiUtils.getConnectingType(accessPoint) != WifiUtils.CONNECT_TYPE_OTHERS) {
|
}
|
||||||
final Intent intent = new Intent(mContext, ConnectToWifiHandler.class)
|
|
||||||
.putExtra(WifiDialogActivity.KEY_ACCESS_POINT_STATE, extras);
|
if (wifiSliceItem.shouldEditBeforeConnect()) {
|
||||||
return getBroadcastAction(requestCode, intent, icon, title);
|
|
||||||
} else {
|
|
||||||
final Intent intent = new Intent(mContext, WifiDialogActivity.class)
|
final Intent intent = new Intent(mContext, WifiDialogActivity.class)
|
||||||
.putExtra(WifiDialogActivity.KEY_ACCESS_POINT_STATE, extras);
|
.putExtra(WifiDialogActivity.KEY_CHOSEN_WIFIENTRY_KEY, wifiSliceItem.getKey());
|
||||||
return getActivityAction(requestCode, intent, icon, title);
|
return getActivityAction(requestCode, intent, icon, title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final Intent intent = new Intent(mContext, ConnectToWifiHandler.class)
|
||||||
|
.putExtra(ConnectToWifiHandler.KEY_CHOSEN_WIFIENTRY_KEY, wifiSliceItem.getKey())
|
||||||
|
.putExtra(ConnectToWifiHandler.KEY_WIFI_SLICE_URI, getUri());
|
||||||
|
return getBroadcastAction(requestCode, intent, icon, title);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SliceAction getActivityAction(int requestCode, Intent intent, IconCompat icon,
|
private SliceAction getActivityAction(int requestCode, Intent intent, IconCompat icon,
|
||||||
@@ -291,12 +249,6 @@ public class WifiSlice implements CustomSliceable {
|
|||||||
.setSubtitle(title);
|
.setSubtitle(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isCaptivePortal() {
|
|
||||||
final NetworkCapabilities nc = mConnectivityManager.getNetworkCapabilities(
|
|
||||||
mWifiManager.getCurrentNetwork());
|
|
||||||
return WifiUtils.canSignIntoNetwork(nc);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the current wifi status to the boolean value keyed by
|
* Update the current wifi status to the boolean value keyed by
|
||||||
* {@link android.app.slice.Slice#EXTRA_TOGGLE_STATE} on {@param intent}.
|
* {@link android.app.slice.Slice#EXTRA_TOGGLE_STATE} on {@param intent}.
|
||||||
|
135
src/com/android/settings/wifi/slice/WifiSliceItem.java
Normal file
135
src/com/android/settings/wifi/slice/WifiSliceItem.java
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 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.slice;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
|
import com.android.settingslib.R;
|
||||||
|
import com.android.wifitrackerlib.WifiEntry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The data set which is needed by a Wi-Fi Slice, it collects necessary data from {@link WifiEntry}
|
||||||
|
* and provides similar getter methods for corresponding data.
|
||||||
|
*/
|
||||||
|
public class WifiSliceItem {
|
||||||
|
|
||||||
|
private final Context mContext;
|
||||||
|
private final String mKey;
|
||||||
|
private final String mTitle;
|
||||||
|
private final int mSecurity;
|
||||||
|
private final int mConnectedState;
|
||||||
|
private final int mLevel;
|
||||||
|
private final boolean mShouldEditBeforeConnect;
|
||||||
|
private final String mSummary;
|
||||||
|
|
||||||
|
// These values must be kept within [WifiEntry.WIFI_LEVEL_MIN, WifiEntry.WIFI_LEVEL_MAX]
|
||||||
|
private static final int[] WIFI_CONNECTION_STRENGTH = {
|
||||||
|
R.string.accessibility_no_wifi,
|
||||||
|
R.string.accessibility_wifi_one_bar,
|
||||||
|
R.string.accessibility_wifi_two_bars,
|
||||||
|
R.string.accessibility_wifi_three_bars,
|
||||||
|
R.string.accessibility_wifi_signal_full
|
||||||
|
};
|
||||||
|
|
||||||
|
public WifiSliceItem(Context context, WifiEntry wifiEntry) {
|
||||||
|
mContext = context;
|
||||||
|
mKey = wifiEntry.getKey();
|
||||||
|
mTitle = wifiEntry.getTitle();
|
||||||
|
mSecurity = wifiEntry.getSecurity();
|
||||||
|
mConnectedState = wifiEntry.getConnectedState();
|
||||||
|
mLevel = wifiEntry.getLevel();
|
||||||
|
mShouldEditBeforeConnect = wifiEntry.shouldEditBeforeConnect();
|
||||||
|
mSummary = wifiEntry.getSummary(false /* concise */);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object other) {
|
||||||
|
if (!(other instanceof WifiSliceItem)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final WifiSliceItem otherItem = (WifiSliceItem) other;
|
||||||
|
if (!TextUtils.equals(getKey(), otherItem.getKey())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (getConnectedState() != otherItem.getConnectedState()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (getLevel() != otherItem.getLevel()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!TextUtils.equals(getSummary(), otherItem.getSummary())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKey() {
|
||||||
|
return mKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return mTitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSecurity() {
|
||||||
|
return mSecurity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getConnectedState() {
|
||||||
|
return mConnectedState;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLevel() {
|
||||||
|
return mLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In Wi-Fi picker, when users click a saved network, it will connect to the Wi-Fi network.
|
||||||
|
* However, for some special cases, Wi-Fi picker should show Wi-Fi editor UI for users to edit
|
||||||
|
* security or password before connecting. Or users will always get connection fail results.
|
||||||
|
*/
|
||||||
|
public boolean shouldEditBeforeConnect() {
|
||||||
|
return mShouldEditBeforeConnect;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a 'NOT' concise summary, this is different from WifiEntry#getSummary().
|
||||||
|
*/
|
||||||
|
public String getSummary() {
|
||||||
|
return mSummary;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method has similar code as WifiEntryPreference#buildContentDescription().
|
||||||
|
* TODO(b/154191825): Adds WifiEntry#getContentDescription() to replace the duplicate code.
|
||||||
|
*/
|
||||||
|
public CharSequence getContentDescription() {
|
||||||
|
CharSequence contentDescription = mTitle;
|
||||||
|
if (!TextUtils.isEmpty(mSummary)) {
|
||||||
|
contentDescription = TextUtils.concat(contentDescription, ",", mSummary);
|
||||||
|
}
|
||||||
|
if (mLevel >= 0 && mLevel < WIFI_CONNECTION_STRENGTH.length) {
|
||||||
|
contentDescription = TextUtils.concat(contentDescription, ",",
|
||||||
|
mContext.getString(WIFI_CONNECTION_STRENGTH[mLevel]));
|
||||||
|
}
|
||||||
|
return TextUtils.concat(contentDescription, ",", mSecurity == WifiEntry.SECURITY_NONE
|
||||||
|
? mContext.getString(R.string.accessibility_wifi_security_type_none)
|
||||||
|
: mContext.getString(R.string.accessibility_wifi_security_type_secured));
|
||||||
|
}
|
||||||
|
}
|
@@ -18,6 +18,7 @@ package com.android.settings.testutils.shadow;
|
|||||||
|
|
||||||
import static org.robolectric.RuntimeEnvironment.application;
|
import static org.robolectric.RuntimeEnvironment.application;
|
||||||
|
|
||||||
|
import android.net.wifi.ScanResult;
|
||||||
import android.net.wifi.SoftApConfiguration;
|
import android.net.wifi.SoftApConfiguration;
|
||||||
import android.net.wifi.WifiConfiguration;
|
import android.net.wifi.WifiConfiguration;
|
||||||
import android.net.wifi.WifiManager;
|
import android.net.wifi.WifiManager;
|
||||||
@@ -81,6 +82,11 @@ public class ShadowWifiManager extends org.robolectric.shadows.ShadowWifiManager
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Implementation
|
||||||
|
protected List<ScanResult> getScanResults() {
|
||||||
|
return new ArrayList<ScanResult>();
|
||||||
|
}
|
||||||
|
|
||||||
public static ShadowWifiManager get() {
|
public static ShadowWifiManager get() {
|
||||||
return Shadow.extract(application.getSystemService(WifiManager.class));
|
return Shadow.extract(application.getSystemService(WifiManager.class));
|
||||||
}
|
}
|
||||||
|
@@ -26,95 +26,69 @@ import static org.mockito.Mockito.verify;
|
|||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.wifi.WifiConfiguration;
|
import android.content.Intent;
|
||||||
import android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
|
|
||||||
import android.net.wifi.WifiManager;
|
|
||||||
|
|
||||||
import com.android.settings.testutils.shadow.ShadowWifiManager;
|
import com.android.settings.wifi.WifiDialogActivity;
|
||||||
import com.android.settingslib.wifi.AccessPoint;
|
import com.android.wifitrackerlib.WifiEntry;
|
||||||
|
import com.android.wifitrackerlib.WifiEntry.ConnectCallback;
|
||||||
|
|
||||||
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;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
import org.robolectric.RobolectricTestRunner;
|
import org.robolectric.RobolectricTestRunner;
|
||||||
import org.robolectric.RuntimeEnvironment;
|
import org.robolectric.RuntimeEnvironment;
|
||||||
import org.robolectric.annotation.Config;
|
|
||||||
|
|
||||||
@RunWith(RobolectricTestRunner.class)
|
@RunWith(RobolectricTestRunner.class)
|
||||||
@Config(shadows = ShadowWifiManager.class)
|
|
||||||
public class ConnectToWifiHandlerTest {
|
public class ConnectToWifiHandlerTest {
|
||||||
|
|
||||||
private static final String AP_SSID = "\"ap\"";
|
private static final String AP_SSID = "\"ap\"";
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
private ConnectToWifiHandler mHandler;
|
private ConnectToWifiHandler mHandler;
|
||||||
private WifiConfiguration mWifiConfig;
|
|
||||||
@Mock
|
@Mock
|
||||||
private AccessPoint mAccessPoint;
|
private WifiScanWorker mWifiScanWorker;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
|
|
||||||
mContext = RuntimeEnvironment.application;
|
mContext = spy(RuntimeEnvironment.application);
|
||||||
mHandler = new ConnectToWifiHandler();
|
mHandler = spy(new ConnectToWifiHandler());
|
||||||
mWifiConfig = spy(new WifiConfiguration());
|
doReturn(mWifiScanWorker).when(mHandler).getWifiScanWorker(any());
|
||||||
mWifiConfig.SSID = AP_SSID;
|
|
||||||
doReturn(mWifiConfig).when(mAccessPoint).getConfig();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void connect_shouldConnectToUnsavedOpenNetwork() {
|
public void onReceive_nonNullKeyAndUri_shouldConnectWifintry() {
|
||||||
when(mAccessPoint.isSaved()).thenReturn(false);
|
final Intent intent = new Intent();
|
||||||
when(mAccessPoint.getSecurity()).thenReturn(AccessPoint.SECURITY_NONE);
|
final String key = "key";
|
||||||
|
intent.putExtra(ConnectToWifiHandler.KEY_CHOSEN_WIFIENTRY_KEY, key);
|
||||||
|
intent.putExtra(ConnectToWifiHandler.KEY_WIFI_SLICE_URI,
|
||||||
|
com.android.settings.slices.CustomSliceRegistry.WIFI_SLICE_URI);
|
||||||
|
final WifiEntry wifiEntry = mock(WifiEntry.class);
|
||||||
|
when(mWifiScanWorker.getWifiEntry(key)).thenReturn(wifiEntry);
|
||||||
|
|
||||||
mHandler.connect(mContext, mAccessPoint);
|
mHandler.onReceive(mContext, intent);
|
||||||
|
|
||||||
assertThat(ShadowWifiManager.get().savedWifiConfig.SSID).isEqualTo(AP_SSID);
|
verify(wifiEntry).connect(any());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void connect_shouldStartOsuProvisioning() {
|
public void onConnectResult_failNoConfig_shouldStartActivity() {
|
||||||
when(mAccessPoint.isSaved()).thenReturn(false);
|
final String key = "key";
|
||||||
when(mAccessPoint.isOsuProvider()).thenReturn(true);
|
final WifiEntry wifiEntry = mock(WifiEntry.class);
|
||||||
|
when(wifiEntry.getKey()).thenReturn(key);
|
||||||
|
final ConnectToWifiHandler.WifiEntryConnectCallback callback =
|
||||||
|
spy(new ConnectToWifiHandler.WifiEntryConnectCallback(mContext, wifiEntry));
|
||||||
|
|
||||||
mHandler.connect(mContext, mAccessPoint);
|
callback.onConnectResult(ConnectCallback.CONNECT_STATUS_FAILURE_NO_CONFIG);
|
||||||
|
|
||||||
verify(mAccessPoint).startOsuProvisioning(any(WifiManager.ActionListener.class));
|
final ArgumentCaptor<Intent> argument = ArgumentCaptor.forClass(Intent.class);
|
||||||
}
|
verify(mContext).startActivity(argument.capture());
|
||||||
|
assertThat(argument.getValue().getStringExtra(WifiDialogActivity.KEY_CHOSEN_WIFIENTRY_KEY))
|
||||||
|
.isEqualTo(key);
|
||||||
@Test
|
assertThat(argument.getValue().getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
public void connect_shouldConnectWithPasspointProvider() {
|
.isEqualTo(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
when(mAccessPoint.isSaved()).thenReturn(false);
|
|
||||||
when(mAccessPoint.isPasspoint()).thenReturn(true);
|
|
||||||
|
|
||||||
mHandler.connect(mContext, mAccessPoint);
|
|
||||||
|
|
||||||
assertThat(ShadowWifiManager.get().savedWifiConfig.SSID).isEqualTo(AP_SSID);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void connect_shouldConnectToSavedSecuredNetwork() {
|
|
||||||
when(mAccessPoint.isSaved()).thenReturn(true);
|
|
||||||
when(mAccessPoint.getSecurity()).thenReturn(AccessPoint.SECURITY_PSK);
|
|
||||||
final NetworkSelectionStatus status = mock(NetworkSelectionStatus.class);
|
|
||||||
when(status.hasEverConnected()).thenReturn(true);
|
|
||||||
when(mWifiConfig.getNetworkSelectionStatus()).thenReturn(status);
|
|
||||||
|
|
||||||
mHandler.connect(mContext, mAccessPoint);
|
|
||||||
|
|
||||||
assertThat(ShadowWifiManager.get().savedWifiConfig.SSID).isEqualTo(AP_SSID);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void connect_shouldNotConnectToUnsavedSecuredNetwork() {
|
|
||||||
when(mAccessPoint.isSaved()).thenReturn(false);
|
|
||||||
when(mAccessPoint.getSecurity()).thenReturn(AccessPoint.SECURITY_PSK);
|
|
||||||
|
|
||||||
mHandler.connect(mContext, mAccessPoint);
|
|
||||||
|
|
||||||
assertThat(ShadowWifiManager.get().savedWifiConfig).isNull();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,105 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.slice;
|
|
||||||
|
|
||||||
import static com.android.settings.slices.CustomSliceRegistry.CONTEXTUAL_WIFI_SLICE_URI;
|
|
||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
|
||||||
import static org.mockito.Mockito.never;
|
|
||||||
import static org.mockito.Mockito.spy;
|
|
||||||
import static org.mockito.Mockito.verify;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.net.ConnectivityManager;
|
|
||||||
import android.net.ConnectivityManager.NetworkCallback;
|
|
||||||
import android.net.Network;
|
|
||||||
import android.net.wifi.WifiManager;
|
|
||||||
import android.os.UserHandle;
|
|
||||||
|
|
||||||
import com.android.settings.testutils.shadow.ShadowWifiManager;
|
|
||||||
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.robolectric.RobolectricTestRunner;
|
|
||||||
import org.robolectric.RuntimeEnvironment;
|
|
||||||
import org.robolectric.annotation.Config;
|
|
||||||
|
|
||||||
@RunWith(RobolectricTestRunner.class)
|
|
||||||
@Config(shadows = {
|
|
||||||
ShadowWifiManager.class,
|
|
||||||
WifiScanWorkerTest.ShadowWifiTracker.class,
|
|
||||||
})
|
|
||||||
public class ContextualWifiScanWorkerTest {
|
|
||||||
|
|
||||||
private Context mContext;
|
|
||||||
private WifiManager mWifiManager;
|
|
||||||
private ConnectivityManager mConnectivityManager;
|
|
||||||
private ContextualWifiScanWorker mWifiScanWorker;
|
|
||||||
private ConnectToWifiHandler mConnectToWifiHandler;
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setUp() {
|
|
||||||
mContext = spy(RuntimeEnvironment.application);
|
|
||||||
mWifiManager = mContext.getSystemService(WifiManager.class);
|
|
||||||
mWifiManager.setWifiEnabled(true);
|
|
||||||
|
|
||||||
mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
|
|
||||||
mWifiScanWorker = new ContextualWifiScanWorker(mContext, CONTEXTUAL_WIFI_SLICE_URI);
|
|
||||||
mConnectToWifiHandler = new ConnectToWifiHandler();
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
public void tearDown() {
|
|
||||||
mWifiScanWorker.clearClickedWifi();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void NetworkCallback_onCapabilitiesChanged_sliceIsUnpinned_shouldSendBroadcast() {
|
|
||||||
final Intent intent = WifiScanWorkerTest.getIntentWithAccessPoint("ap1");
|
|
||||||
WifiScanWorkerTest.setConnectionInfoSSID("ap1");
|
|
||||||
final Network network = mConnectivityManager.getActiveNetwork();
|
|
||||||
mWifiScanWorker.registerNetworkCallback(network);
|
|
||||||
final NetworkCallback callback = mWifiScanWorker.mNetworkCallback;
|
|
||||||
|
|
||||||
mWifiScanWorker.onSlicePinned();
|
|
||||||
mConnectToWifiHandler.onReceive(mContext, intent);
|
|
||||||
mWifiScanWorker.onSliceUnpinned();
|
|
||||||
callback.onCapabilitiesChanged(network,
|
|
||||||
WifiSliceTest.makeCaptivePortalNetworkCapabilities());
|
|
||||||
|
|
||||||
verify(mContext).sendBroadcastAsUser(any(Intent.class), eq(UserHandle.CURRENT));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void NetworkCallback_onCapabilitiesChanged_newSession_shouldNotSendBroadcast() {
|
|
||||||
final Intent intent = WifiScanWorkerTest.getIntentWithAccessPoint("ap1");
|
|
||||||
WifiScanWorkerTest.setConnectionInfoSSID("ap1");
|
|
||||||
final Network network = mConnectivityManager.getActiveNetwork();
|
|
||||||
mWifiScanWorker.registerNetworkCallback(network);
|
|
||||||
|
|
||||||
mConnectToWifiHandler.onReceive(mContext, intent);
|
|
||||||
ContextualWifiScanWorker.newVisibleUiSession();
|
|
||||||
mWifiScanWorker.mNetworkCallback.onCapabilitiesChanged(network,
|
|
||||||
WifiSliceTest.makeCaptivePortalNetworkCapabilities());
|
|
||||||
|
|
||||||
verify(mContext, never()).sendBroadcastAsUser(any(Intent.class), eq(UserHandle.CURRENT));
|
|
||||||
}
|
|
||||||
}
|
|
@@ -17,216 +17,89 @@
|
|||||||
package com.android.settings.wifi.slice;
|
package com.android.settings.wifi.slice;
|
||||||
|
|
||||||
import static com.android.settings.slices.CustomSliceRegistry.WIFI_SLICE_URI;
|
import static com.android.settings.slices.CustomSliceRegistry.WIFI_SLICE_URI;
|
||||||
import static com.android.settings.wifi.WifiDialogActivity.KEY_ACCESS_POINT_STATE;
|
|
||||||
|
|
||||||
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.ArgumentMatchers.eq;
|
|
||||||
import static org.mockito.Mockito.doReturn;
|
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.never;
|
|
||||||
import static org.mockito.Mockito.spy;
|
|
||||||
import static org.mockito.Mockito.verify;
|
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import android.content.ContentResolver;
|
import androidx.lifecycle.Lifecycle;
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.net.ConnectivityManager;
|
|
||||||
import android.net.ConnectivityManager.NetworkCallback;
|
|
||||||
import android.net.Network;
|
|
||||||
import android.net.NetworkInfo;
|
|
||||||
import android.net.NetworkInfo.DetailedState;
|
|
||||||
import android.net.wifi.WifiInfo;
|
|
||||||
import android.net.wifi.WifiManager;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.UserHandle;
|
|
||||||
|
|
||||||
import com.android.settings.slices.ShadowSliceBackgroundWorker;
|
import com.android.wifitrackerlib.WifiEntry;
|
||||||
import com.android.settings.testutils.shadow.ShadowWifiManager;
|
import com.android.wifitrackerlib.WifiPickerTracker;
|
||||||
import com.android.settingslib.wifi.AccessPoint;
|
|
||||||
import com.android.settingslib.wifi.WifiTracker;
|
|
||||||
|
|
||||||
import org.junit.After;
|
|
||||||
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;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
import org.robolectric.RobolectricTestRunner;
|
import org.robolectric.RobolectricTestRunner;
|
||||||
import org.robolectric.RuntimeEnvironment;
|
import org.robolectric.RuntimeEnvironment;
|
||||||
import org.robolectric.annotation.Config;
|
|
||||||
import org.robolectric.annotation.Implementation;
|
|
||||||
import org.robolectric.annotation.Implements;
|
|
||||||
import org.robolectric.shadows.ShadowNetworkInfo;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@RunWith(RobolectricTestRunner.class)
|
@RunWith(RobolectricTestRunner.class)
|
||||||
@Config(shadows = {ShadowSliceBackgroundWorker.class, ShadowWifiManager.class,
|
|
||||||
WifiScanWorkerTest.ShadowWifiTracker.class})
|
|
||||||
public class WifiScanWorkerTest {
|
public class WifiScanWorkerTest {
|
||||||
|
|
||||||
private Context mContext;
|
|
||||||
private ContentResolver mResolver;
|
|
||||||
private WifiManager mWifiManager;
|
|
||||||
private ConnectivityManager mConnectivityManager;
|
|
||||||
private WifiScanWorker mWifiScanWorker;
|
private WifiScanWorker mWifiScanWorker;
|
||||||
private ConnectToWifiHandler mConnectToWifiHandler;
|
@Mock
|
||||||
|
WifiPickerTracker mWifiPickerTracker;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
mContext = spy(RuntimeEnvironment.application);
|
MockitoAnnotations.initMocks(this);
|
||||||
mResolver = mock(ContentResolver.class);
|
|
||||||
doReturn(mResolver).when(mContext).getContentResolver();
|
|
||||||
mWifiManager = mContext.getSystemService(WifiManager.class);
|
|
||||||
mWifiManager.setWifiEnabled(true);
|
|
||||||
|
|
||||||
mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
|
mWifiScanWorker = new WifiScanWorker(RuntimeEnvironment.application, WIFI_SLICE_URI);
|
||||||
mWifiScanWorker = new WifiScanWorker(mContext, WIFI_SLICE_URI);
|
mWifiScanWorker.mWifiPickerTracker = mWifiPickerTracker;
|
||||||
mConnectToWifiHandler = new ConnectToWifiHandler();
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
public void tearDown() {
|
|
||||||
mWifiScanWorker.clearClickedWifi();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onWifiStateChanged_shouldNotifyChange() {
|
public void onConstructor_shouldBeInCreatedState() {
|
||||||
mWifiScanWorker.onWifiStateChanged(WifiManager.WIFI_STATE_DISABLED);
|
assertThat(mWifiScanWorker.getLifecycle().getCurrentState())
|
||||||
|
.isEqualTo(Lifecycle.State.CREATED);
|
||||||
verify(mResolver).notifyChange(WIFI_SLICE_URI, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void AccessPointList_sameState_shouldBeTheSame() {
|
public void onSlicePinned_shouldBeInResumedState() {
|
||||||
final AccessPoint ap1 = createAccessPoint(DetailedState.CONNECTED);
|
|
||||||
final AccessPoint ap2 = createAccessPoint(DetailedState.CONNECTED);
|
|
||||||
|
|
||||||
assertThat(mWifiScanWorker.areListsTheSame(Arrays.asList(ap1), Arrays.asList(ap2)))
|
|
||||||
.isTrue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void AccessPointList_differentState_shouldBeDifferent() {
|
|
||||||
final AccessPoint ap1 = createAccessPoint(DetailedState.CONNECTING);
|
|
||||||
final AccessPoint ap2 = createAccessPoint(DetailedState.CONNECTED);
|
|
||||||
|
|
||||||
assertThat(mWifiScanWorker.areListsTheSame(Arrays.asList(ap1), Arrays.asList(ap2)))
|
|
||||||
.isFalse();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void AccessPointList_differentListLength_shouldBeDifferent() {
|
|
||||||
final AccessPoint ap1 = createAccessPoint(DetailedState.CONNECTED);
|
|
||||||
final AccessPoint ap2 = createAccessPoint(DetailedState.CONNECTED);
|
|
||||||
final List<AccessPoint> list = new ArrayList<>();
|
|
||||||
list.add(ap1);
|
|
||||||
list.add(ap2);
|
|
||||||
|
|
||||||
assertThat(mWifiScanWorker.areListsTheSame(list, Arrays.asList(ap1))).isFalse();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void NetworkCallback_onCapabilitiesChanged_shouldNotifyChange() {
|
|
||||||
final Network network = mConnectivityManager.getActiveNetwork();
|
|
||||||
mWifiScanWorker.registerNetworkCallback(network);
|
|
||||||
|
|
||||||
mWifiScanWorker.mNetworkCallback.onCapabilitiesChanged(network,
|
|
||||||
WifiSliceTest.makeCaptivePortalNetworkCapabilities());
|
|
||||||
|
|
||||||
verify(mResolver).notifyChange(WIFI_SLICE_URI, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void NetworkCallback_onCapabilitiesChanged_isClickedWifi_shouldSendBroadcast() {
|
|
||||||
final Intent intent = getIntentWithAccessPoint("ap1");
|
|
||||||
setConnectionInfoSSID("ap1");
|
|
||||||
final Network network = mConnectivityManager.getActiveNetwork();
|
|
||||||
mWifiScanWorker.registerNetworkCallback(network);
|
|
||||||
|
|
||||||
mConnectToWifiHandler.onReceive(mContext, intent);
|
|
||||||
mWifiScanWorker.mNetworkCallback.onCapabilitiesChanged(network,
|
|
||||||
WifiSliceTest.makeCaptivePortalNetworkCapabilities());
|
|
||||||
|
|
||||||
verify(mContext).sendBroadcastAsUser(any(Intent.class), eq(UserHandle.CURRENT));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void NetworkCallback_onCapabilitiesChanged_isNotClickedWifi_shouldNotSendBroadcast() {
|
|
||||||
final Intent intent = getIntentWithAccessPoint("ap1");
|
|
||||||
setConnectionInfoSSID("ap2");
|
|
||||||
final Network network = mConnectivityManager.getActiveNetwork();
|
|
||||||
mWifiScanWorker.registerNetworkCallback(network);
|
|
||||||
|
|
||||||
mConnectToWifiHandler.onReceive(mContext, intent);
|
|
||||||
mWifiScanWorker.mNetworkCallback.onCapabilitiesChanged(network,
|
|
||||||
WifiSliceTest.makeCaptivePortalNetworkCapabilities());
|
|
||||||
|
|
||||||
verify(mContext, never()).sendBroadcastAsUser(any(Intent.class), eq(UserHandle.CURRENT));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void NetworkCallback_onCapabilitiesChanged_neverClickWifi_shouldNotSendBroadcast() {
|
|
||||||
setConnectionInfoSSID("ap1");
|
|
||||||
final Network network = mConnectivityManager.getActiveNetwork();
|
|
||||||
mWifiScanWorker.registerNetworkCallback(network);
|
|
||||||
|
|
||||||
mWifiScanWorker.mNetworkCallback.onCapabilitiesChanged(network,
|
|
||||||
WifiSliceTest.makeCaptivePortalNetworkCapabilities());
|
|
||||||
|
|
||||||
verify(mContext, never()).sendBroadcastAsUser(any(Intent.class), eq(UserHandle.CURRENT));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void NetworkCallback_onCapabilitiesChanged_sliceIsUnpinned_shouldNotSendBroadcast() {
|
|
||||||
final Intent intent = getIntentWithAccessPoint("ap1");
|
|
||||||
setConnectionInfoSSID("ap1");
|
|
||||||
final Network network = mConnectivityManager.getActiveNetwork();
|
|
||||||
mWifiScanWorker.registerNetworkCallback(network);
|
|
||||||
final NetworkCallback callback = mWifiScanWorker.mNetworkCallback;
|
|
||||||
|
|
||||||
mWifiScanWorker.onSlicePinned();
|
mWifiScanWorker.onSlicePinned();
|
||||||
mConnectToWifiHandler.onReceive(mContext, intent);
|
|
||||||
|
assertThat(mWifiScanWorker.getLifecycle().getCurrentState())
|
||||||
|
.isEqualTo(Lifecycle.State.RESUMED);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onSliceUnpinned_shouldBeInCreatedState() {
|
||||||
mWifiScanWorker.onSliceUnpinned();
|
mWifiScanWorker.onSliceUnpinned();
|
||||||
callback.onCapabilitiesChanged(network,
|
|
||||||
WifiSliceTest.makeCaptivePortalNetworkCapabilities());
|
|
||||||
|
|
||||||
verify(mContext, never()).sendBroadcastAsUser(any(Intent.class), eq(UserHandle.CURRENT));
|
assertThat(mWifiScanWorker.getLifecycle().getCurrentState())
|
||||||
|
.isEqualTo(Lifecycle.State.CREATED);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Intent getIntentWithAccessPoint(String ssid) {
|
@Test
|
||||||
final Bundle savedState = new Bundle();
|
public void close_shouldBeInDestroyedState() {
|
||||||
savedState.putString("key_ssid", ssid);
|
mWifiScanWorker.close();
|
||||||
return new Intent().putExtra(KEY_ACCESS_POINT_STATE, savedState);
|
|
||||||
|
assertThat(mWifiScanWorker.getLifecycle().getCurrentState())
|
||||||
|
.isEqualTo(Lifecycle.State.DESTROYED);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setConnectionInfoSSID(String ssid) {
|
@Test
|
||||||
final WifiInfo wifiInfo = mock(WifiInfo.class);
|
public void getWifiEntry_connectedWifiKey_shouldGetConnectedWifi() {
|
||||||
when(wifiInfo.getSSID()).thenReturn(ssid);
|
final String key = "key";
|
||||||
ShadowWifiManager.get().setConnectionInfo(wifiInfo);
|
final WifiEntry connectedWifiEntry = mock(WifiEntry.class);
|
||||||
|
when(connectedWifiEntry.getKey()).thenReturn(key);
|
||||||
|
when(mWifiPickerTracker.getConnectedWifiEntry()).thenReturn(connectedWifiEntry);
|
||||||
|
|
||||||
|
assertThat(mWifiScanWorker.getWifiEntry(key)).isEqualTo(connectedWifiEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
private AccessPoint createAccessPoint(String ssid, DetailedState detailedState) {
|
@Test
|
||||||
final NetworkInfo info = ShadowNetworkInfo.newInstance(detailedState, 1 /* type */,
|
public void getWifiEntry_reachableWifiKey_shouldGetReachableWifi() {
|
||||||
0 /*subType */, true /* isAvailable */, true /* isConnected */);
|
final String key = "key";
|
||||||
final Bundle savedState = new Bundle();
|
final WifiEntry reachableWifiEntry = mock(WifiEntry.class);
|
||||||
savedState.putString("key_ssid", ssid);
|
when(reachableWifiEntry.getKey()).thenReturn(key);
|
||||||
savedState.putParcelable("key_networkinfo", info);
|
when(mWifiPickerTracker.getWifiEntries()).thenReturn(Arrays.asList(reachableWifiEntry));
|
||||||
return new AccessPoint(mContext, savedState);
|
|
||||||
}
|
|
||||||
|
|
||||||
private AccessPoint createAccessPoint(DetailedState detailedState) {
|
assertThat(mWifiScanWorker.getWifiEntry(key)).isEqualTo(reachableWifiEntry);
|
||||||
return createAccessPoint("ap", detailedState);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Implements(WifiTracker.class)
|
|
||||||
public static class ShadowWifiTracker {
|
|
||||||
@Implementation
|
|
||||||
public void onStart() {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -23,17 +23,14 @@ import static com.android.settings.wifi.slice.WifiSlice.DEFAULT_EXPANDED_ROW_COU
|
|||||||
|
|
||||||
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.doReturn;
|
import static org.mockito.Mockito.doReturn;
|
||||||
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.when;
|
||||||
|
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.ConnectivityManager;
|
|
||||||
import android.net.NetworkCapabilities;
|
|
||||||
import android.net.NetworkInfo;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.net.wifi.WifiManager;
|
import android.net.wifi.WifiManager;
|
||||||
|
|
||||||
@@ -49,7 +46,8 @@ import androidx.slice.widget.SliceLiveData;
|
|||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.slices.SliceBackgroundWorker;
|
import com.android.settings.slices.SliceBackgroundWorker;
|
||||||
import com.android.settings.testutils.SliceTester;
|
import com.android.settings.testutils.SliceTester;
|
||||||
import com.android.settingslib.wifi.AccessPoint;
|
import com.android.wifitrackerlib.WifiEntry;
|
||||||
|
import com.android.wifitrackerlib.WifiEntry.ConnectedState;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -74,7 +72,6 @@ public class WifiSliceTest {
|
|||||||
private Context mContext;
|
private Context mContext;
|
||||||
private ContentResolver mResolver;
|
private ContentResolver mResolver;
|
||||||
private WifiManager mWifiManager;
|
private WifiManager mWifiManager;
|
||||||
private ConnectivityManager mConnectivityManager;
|
|
||||||
private WifiSlice mWifiSlice;
|
private WifiSlice mWifiSlice;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
@@ -88,9 +85,6 @@ public class WifiSliceTest {
|
|||||||
SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
|
SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
|
||||||
mWifiManager.setWifiEnabled(true);
|
mWifiManager.setWifiEnabled(true);
|
||||||
|
|
||||||
mConnectivityManager = spy(mContext.getSystemService(ConnectivityManager.class));
|
|
||||||
doReturn(mConnectivityManager).when(mContext).getSystemService(ConnectivityManager.class);
|
|
||||||
|
|
||||||
mWifiSlice = new WifiSlice(mContext);
|
mWifiSlice = new WifiSlice(mContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,33 +132,42 @@ public class WifiSliceTest {
|
|||||||
mContext.getString(R.string.wifi_empty_list_wifi_on));
|
mContext.getString(R.string.wifi_empty_list_wifi_on));
|
||||||
}
|
}
|
||||||
|
|
||||||
private AccessPoint createAccessPoint(String name, boolean active, boolean reachable) {
|
private WifiSliceItem createWifiSliceItem(String title, @ConnectedState int connectedState) {
|
||||||
final AccessPoint accessPoint = mock(AccessPoint.class);
|
final WifiEntry wifiEntry = mock(WifiEntry.class);
|
||||||
doReturn(name).when(accessPoint).getTitle();
|
when(wifiEntry.getTitle()).thenReturn(title);
|
||||||
doReturn(active).when(accessPoint).isActive();
|
when(wifiEntry.getKey()).thenReturn("key");
|
||||||
doReturn(reachable).when(accessPoint).isReachable();
|
when(wifiEntry.getConnectedState()).thenReturn(connectedState);
|
||||||
if (active) {
|
when(wifiEntry.getLevel()).thenReturn(WifiEntry.WIFI_LEVEL_MAX);
|
||||||
final NetworkInfo networkInfo = mock(NetworkInfo.class);
|
return new WifiSliceItem(mContext, wifiEntry);
|
||||||
doReturn(networkInfo).when(accessPoint).getNetworkInfo();
|
|
||||||
doReturn(NetworkInfo.State.CONNECTED).when(networkInfo).getState();
|
|
||||||
}
|
|
||||||
return accessPoint;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setWorkerResults(AccessPoint... accessPoints) {
|
private void setWorkerResults(WifiSliceItem... wifiSliceItems) {
|
||||||
final ArrayList<AccessPoint> results = new ArrayList<>();
|
final ArrayList<WifiSliceItem> results = new ArrayList<>();
|
||||||
for (AccessPoint ap : accessPoints) {
|
for (WifiSliceItem wifiSliceItem : wifiSliceItems) {
|
||||||
results.add(ap);
|
results.add(wifiSliceItem);
|
||||||
}
|
}
|
||||||
final SliceBackgroundWorker worker = SliceBackgroundWorker.getInstance(mWifiSlice.getUri());
|
final SliceBackgroundWorker worker = SliceBackgroundWorker.getInstance(mWifiSlice.getUri());
|
||||||
doReturn(results).when(worker).getResults();
|
doReturn(results).when(worker).getResults();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getWifiSlice_noReachableAp_shouldReturnLoadingRow() {
|
public void getWifiSlice_oneConnectedAp_shouldReturnLoadingRow() {
|
||||||
|
setWorkerResults(createWifiSliceItem(AP1_NAME, WifiEntry.CONNECTED_STATE_CONNECTED));
|
||||||
|
|
||||||
|
final Slice wifiSlice = mWifiSlice.getSlice();
|
||||||
|
final List<SliceItem> sliceItems = wifiSlice.getItems();
|
||||||
|
|
||||||
|
SliceTester.assertAnySliceItemContainsTitle(sliceItems, AP1_NAME);
|
||||||
|
// Has scanning text
|
||||||
|
SliceTester.assertAnySliceItemContainsSubtitle(sliceItems,
|
||||||
|
mContext.getString(R.string.wifi_empty_list_wifi_on));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getWifiSlice_oneConnectedApAndOneDisconnectedAp_shouldReturnLoadingRow() {
|
||||||
setWorkerResults(
|
setWorkerResults(
|
||||||
createAccessPoint(AP1_NAME, false, false),
|
createWifiSliceItem(AP1_NAME, WifiEntry.CONNECTED_STATE_CONNECTED),
|
||||||
createAccessPoint(AP2_NAME, false, false));
|
createWifiSliceItem(AP2_NAME, WifiEntry.CONNECTED_STATE_DISCONNECTED));
|
||||||
|
|
||||||
final Slice wifiSlice = mWifiSlice.getSlice();
|
final Slice wifiSlice = mWifiSlice.getSlice();
|
||||||
final List<SliceItem> sliceItems = wifiSlice.getItems();
|
final List<SliceItem> sliceItems = wifiSlice.getItems();
|
||||||
@@ -177,8 +180,8 @@ public class WifiSliceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getWifiSlice_oneActiveAp_shouldReturnLoadingRow() {
|
public void getWifiSlice_oneDisconnectedAp_shouldReturnLoadingRow() {
|
||||||
setWorkerResults(createAccessPoint(AP1_NAME, true, true));
|
setWorkerResults(createWifiSliceItem(AP1_NAME, WifiEntry.CONNECTED_STATE_DISCONNECTED));
|
||||||
|
|
||||||
final Slice wifiSlice = mWifiSlice.getSlice();
|
final Slice wifiSlice = mWifiSlice.getSlice();
|
||||||
final List<SliceItem> sliceItems = wifiSlice.getItems();
|
final List<SliceItem> sliceItems = wifiSlice.getItems();
|
||||||
@@ -190,40 +193,11 @@ public class WifiSliceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getWifiSlice_oneActiveApAndOneUnreachableAp_shouldReturnLoadingRow() {
|
public void getWifiSlice_apReachExpandedCount_shouldNotReturnLoadingRow() {
|
||||||
setWorkerResults(
|
setWorkerResults(
|
||||||
createAccessPoint(AP1_NAME, true, true),
|
createWifiSliceItem(AP1_NAME, WifiEntry.CONNECTED_STATE_DISCONNECTED),
|
||||||
createAccessPoint(AP2_NAME, false, false));
|
createWifiSliceItem(AP2_NAME, WifiEntry.CONNECTED_STATE_DISCONNECTED),
|
||||||
|
createWifiSliceItem(AP3_NAME, WifiEntry.CONNECTED_STATE_DISCONNECTED));
|
||||||
final Slice wifiSlice = mWifiSlice.getSlice();
|
|
||||||
final List<SliceItem> sliceItems = wifiSlice.getItems();
|
|
||||||
|
|
||||||
SliceTester.assertAnySliceItemContainsTitle(sliceItems, AP1_NAME);
|
|
||||||
SliceTester.assertAnySliceItemContainsTitle(sliceItems, AP2_NAME);
|
|
||||||
// Has scanning text
|
|
||||||
SliceTester.assertAnySliceItemContainsSubtitle(sliceItems,
|
|
||||||
mContext.getString(R.string.wifi_empty_list_wifi_on));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getWifiSlice_oneReachableAp_shouldReturnLoadingRow() {
|
|
||||||
setWorkerResults(createAccessPoint(AP1_NAME, false, true));
|
|
||||||
|
|
||||||
final Slice wifiSlice = mWifiSlice.getSlice();
|
|
||||||
final List<SliceItem> sliceItems = wifiSlice.getItems();
|
|
||||||
|
|
||||||
SliceTester.assertAnySliceItemContainsTitle(sliceItems, AP1_NAME);
|
|
||||||
// Has scanning text
|
|
||||||
SliceTester.assertAnySliceItemContainsSubtitle(sliceItems,
|
|
||||||
mContext.getString(R.string.wifi_empty_list_wifi_on));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getWifiSlice_allReachableAps_shouldNotReturnLoadingRow() {
|
|
||||||
setWorkerResults(
|
|
||||||
createAccessPoint(AP1_NAME, false, true),
|
|
||||||
createAccessPoint(AP2_NAME, false, true),
|
|
||||||
createAccessPoint(AP3_NAME, false, true));
|
|
||||||
|
|
||||||
final Slice wifiSlice = mWifiSlice.getSlice();
|
final Slice wifiSlice = mWifiSlice.getSlice();
|
||||||
final List<SliceItem> sliceItems = wifiSlice.getItems();
|
final List<SliceItem> sliceItems = wifiSlice.getItems();
|
||||||
@@ -236,29 +210,6 @@ public class WifiSliceTest {
|
|||||||
mContext.getString(R.string.wifi_empty_list_wifi_on));
|
mContext.getString(R.string.wifi_empty_list_wifi_on));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getWifiSlice_isCaptivePortal_shouldHaveCaptivePortalItems() {
|
|
||||||
setWorkerResults(createAccessPoint(AP1_NAME, true, true));
|
|
||||||
doReturn(makeCaptivePortalNetworkCapabilities()).when(mConnectivityManager)
|
|
||||||
.getNetworkCapabilities(any());
|
|
||||||
final IconCompat expectedIcon = IconCompat.createWithResource(mContext,
|
|
||||||
R.drawable.ic_settings_accent);
|
|
||||||
|
|
||||||
final Slice wifiSlice = mWifiSlice.getSlice();
|
|
||||||
final List<SliceItem> sliceItems = wifiSlice.getItems();
|
|
||||||
|
|
||||||
SliceTester.assertAnySliceItemContainsTitle(sliceItems, AP1_NAME);
|
|
||||||
SliceTester.assertAnySliceItemContainsIcon(sliceItems, expectedIcon);
|
|
||||||
}
|
|
||||||
|
|
||||||
static NetworkCapabilities makeCaptivePortalNetworkCapabilities() {
|
|
||||||
final NetworkCapabilities nc = new NetworkCapabilities();
|
|
||||||
nc.clearAll();
|
|
||||||
nc.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
|
|
||||||
nc.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
|
|
||||||
return nc;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void handleUriChange_updatesWifi() {
|
public void handleUriChange_updatesWifi() {
|
||||||
final Intent intent = mWifiSlice.getIntent();
|
final Intent intent = mWifiSlice.getIntent();
|
||||||
|
Reference in New Issue
Block a user