Merge "[Wi-Fi] Apply WifiTrackerLib objects in Wi-Fi Slice"
This commit is contained in:
@@ -2201,6 +2201,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,44 +26,12 @@ 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