Revert "[Wi-Fi] Apply WifiTrackerLib objects in Wi-Fi Slice"

This reverts commit 7b1aded2a6.

Reason for revert: Settings is crashing for WiFi selection in SetupWizard on wembley

Bug: 161434533
Change-Id: I1d90e9bae1b31862fba674db0d7497e43f987a7f
Test: Locally reverted, reflashed, and was able to select WiFi without Settings crashing.
Exempt-From-Owner-Approval: Revert to clear up P0 while all owners are outside of work hours
This commit is contained in:
Greg Kaiser
2020-07-16 13:23:09 +00:00
parent 7b1aded2a6
commit 9e9255fb2a
17 changed files with 928 additions and 587 deletions

View File

@@ -16,187 +16,243 @@
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 android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkScoreManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.HandlerThread;
import android.os.Process;
import android.os.SimpleClock;
import android.os.SystemClock;
import android.net.wifi.WifiInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log;
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.settingslib.utils.ThreadUtils;
import com.android.wifitrackerlib.WifiEntry;
import com.android.wifitrackerlib.WifiEntry.WifiEntryCallback;
import com.android.wifitrackerlib.WifiPickerTracker;
import com.android.settingslib.wifi.AccessPoint;
import com.android.settingslib.wifi.WifiTracker;
import java.time.Clock;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.List;
/**
* {@link SliceBackgroundWorker} for Wi-Fi, used by {@link WifiSlice}.
*/
public class WifiScanWorker extends SliceBackgroundWorker<WifiSliceItem> implements
WifiPickerTracker.WifiPickerTrackerCallback, LifecycleOwner, WifiEntryCallback {
public class WifiScanWorker extends SliceBackgroundWorker<AccessPoint> implements
WifiTracker.WifiListener {
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
WifiNetworkCallback mNetworkCallback;
@VisibleForTesting
final LifecycleRegistry mLifecycleRegistry;
@VisibleForTesting
WifiPickerTracker mWifiPickerTracker;
// Worker thread used for WifiPickerTracker work
private final HandlerThread mWorkerThread;
private final Context mContext;
private final ConnectivityManager mConnectivityManager;
private final WifiTracker mWifiTracker;
private static String sClickedWifiSsid;
public WifiScanWorker(Context context, Uri uri) {
super(context, uri);
mLifecycleRegistry = new LifecycleRegistry(this);
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);
mContext = context;
mConnectivityManager = context.getSystemService(ConnectivityManager.class);
mWifiTracker = new WifiTracker(mContext, this /* wifiListener */,
true /* includeSaved */, true /* includeScans */);
}
@Override
protected void onSlicePinned() {
mLifecycleRegistry.markState(Lifecycle.State.STARTED);
mLifecycleRegistry.markState(Lifecycle.State.RESUMED);
updateResults();
mWifiTracker.onStart();
onAccessPointsChanged();
}
@Override
protected void onSliceUnpinned() {
mLifecycleRegistry.markState(Lifecycle.State.STARTED);
mLifecycleRegistry.markState(Lifecycle.State.CREATED);
mWifiTracker.onStop();
unregisterNetworkCallback();
clearClickedWifiOnSliceUnpinned();
}
@Override
public void close() {
mLifecycleRegistry.markState(Lifecycle.State.DESTROYED);
mWorkerThread.quit();
mWifiTracker.onDestroy();
}
@Override
public Lifecycle getLifecycle() {
return mLifecycleRegistry;
}
/** Called when the state of Wifi has changed. */
@Override
public void onWifiStateChanged() {
updateResults();
}
/**
* Update the results when data changes
*/
@Override
public void onWifiEntriesChanged() {
updateResults();
}
/**
* Indicates the state of the WifiEntry has changed and clients may retrieve updates through
* the WifiEntry getter methods.
*/
@Override
public void onUpdated() {
public void onWifiStateChanged(int state) {
notifySliceChange();
}
@Override
public void onConnectedChanged() {
}
@Override
public void onAccessPointsChanged() {
// in case state has changed
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() {
return DEFAULT_EXPANDED_ROW_COUNT;
}
@Override
public void onNumSavedSubscriptionsChanged() {
// Do nothing.
private AccessPoint clone(AccessPoint accessPoint) {
final Bundle savedState = new Bundle();
accessPoint.saveWifiState(savedState);
return new AccessPoint(mContext, savedState);
}
@Override
public void onNumSavedNetworksChanged() {
// Do nothing.
}
protected boolean areListsTheSame(List<AccessPoint> a, List<AccessPoint> b) {
if (!a.equals(b)) {
return false;
}
/**
* To get the WifiEntry of key.
*/
public WifiEntry getWifiEntry(String key) {
// 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;
}
// compare access point states one by one
final int listSize = a.size();
for (int i = 0; i < listSize; i++) {
if (a.get(i).getDetailedState() != b.get(i).getDetailedState()) {
return false;
}
}
return keyWifiEntry;
return true;
}
@VisibleForTesting
void updateResults() {
if (mWifiPickerTracker.getWifiState() != WifiManager.WIFI_STATE_ENABLED
|| mLifecycleRegistry.getCurrentState() != Lifecycle.State.RESUMED) {
super.updateResults(null);
static void saveClickedWifi(AccessPoint accessPoint) {
sClickedWifiSsid = accessPoint.getSsidStr();
}
static void clearClickedWifi() {
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;
}
final List<WifiSliceItem> resultList = new ArrayList<>();
final WifiEntry connectedWifiEntry = mWifiPickerTracker.getConnectedWifiEntry();
if (connectedWifiEntry != null) {
connectedWifiEntry.setListener(this);
resultList.add(new WifiSliceItem(getContext(), connectedWifiEntry));
if (mNetworkCallback != null && mNetworkCallback.isSameNetwork(wifiNetwork)) {
return;
}
for (WifiEntry wifiEntry : mWifiPickerTracker.getWifiEntries()) {
if (resultList.size() >= getApRowCount()) {
break;
unregisterNetworkCallback();
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);
}
if (wifiEntry.getLevel() != WifiEntry.WIFI_LEVEL_UNREACHABLE) {
wifiEntry.setListener(this);
resultList.add(new WifiSliceItem(getContext(), wifiEntry));
mNetworkCallback = null;
}
}
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);
}
}
}