Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2cc4d5ec authored by Fabian Kozynski's avatar Fabian Kozynski Committed by Android (Google) Code Review
Browse files

Merge "Migrate to WifiPickerTracker"

parents 829a1454 4d275860
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -78,6 +78,7 @@
    <uses-permission android:name="android.permission.REQUEST_NETWORK_SCORES" />
    <uses-permission android:name="android.permission.CONTROL_VPN" />
    <uses-permission android:name="android.permission.PEERS_MAC_ADDRESS"/>
    <uses-permission android:name="android.permission.READ_WIFI_CREDENTIAL"/>
    <!-- Physical hardware -->
    <uses-permission android:name="android.permission.MANAGE_USB" />
    <uses-permission android:name="android.permission.CONTROL_DISPLAY_BRIGHTNESS" />
+21 −15
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ import com.android.systemui.statusbar.policy.NetworkController.AccessPointContro
import com.android.systemui.statusbar.policy.NetworkController.IconState;
import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
import com.android.systemui.statusbar.policy.WifiIcons;
import com.android.wifitrackerlib.WifiEntry;

import java.util.List;

@@ -80,12 +81,13 @@ public class WifiTile extends QSTileImpl<SignalState> {
            StatusBarStateController statusBarStateController,
            ActivityStarter activityStarter,
            QSLogger qsLogger,
            NetworkController networkController
            NetworkController networkController,
            AccessPointController accessPointController
    ) {
        super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController,
                activityStarter, qsLogger);
        mController = networkController;
        mWifiController = mController.getAccessPointController();
        mWifiController = accessPointController;
        mDetailAdapter = (WifiDetailAdapter) createDetailAdapter();
        mController.observe(getLifecycle(), mSignalCallback);
    }
@@ -325,7 +327,7 @@ public class WifiTile extends QSTileImpl<SignalState> {
            NetworkController.AccessPointController.AccessPointCallback, QSDetailItems.Callback {

        private QSDetailItems mItems;
        private AccessPoint[] mAccessPoints;
        private WifiEntry[] mAccessPoints;

        @Override
        public CharSequence getTitle() {
@@ -366,8 +368,8 @@ public class WifiTile extends QSTileImpl<SignalState> {
        }

        @Override
        public void onAccessPointsChanged(final List<AccessPoint> accessPoints) {
            mAccessPoints = accessPoints.toArray(new AccessPoint[accessPoints.size()]);
        public void onAccessPointsChanged(final List<WifiEntry> accessPoints) {
            mAccessPoints = accessPoints.toArray(new WifiEntry[accessPoints.size()]);
            filterUnreachableAPs();

            updateItems();
@@ -376,15 +378,15 @@ public class WifiTile extends QSTileImpl<SignalState> {
        /** Filter unreachable APs from mAccessPoints */
        private void filterUnreachableAPs() {
            int numReachable = 0;
            for (AccessPoint ap : mAccessPoints) {
                if (ap.isReachable()) numReachable++;
            for (WifiEntry ap : mAccessPoints) {
                if (isWifiEntryReachable(ap)) numReachable++;
            }
            if (numReachable != mAccessPoints.length) {
                AccessPoint[] unfiltered = mAccessPoints;
                mAccessPoints = new AccessPoint[numReachable];
                WifiEntry[] unfiltered = mAccessPoints;
                mAccessPoints = new WifiEntry[numReachable];
                int i = 0;
                for (AccessPoint ap : unfiltered) {
                    if (ap.isReachable()) mAccessPoints[i++] = ap;
                for (WifiEntry ap : unfiltered) {
                    if (isWifiEntryReachable(ap)) mAccessPoints[i++] = ap;
                }
            }
        }
@@ -397,8 +399,8 @@ public class WifiTile extends QSTileImpl<SignalState> {
        @Override
        public void onDetailItemClick(Item item) {
            if (item == null || item.tag == null) return;
            final AccessPoint ap = (AccessPoint) item.tag;
            if (!ap.isActive()) {
            final WifiEntry ap = (WifiEntry) item.tag;
            if (ap.getConnectedState() == WifiEntry.CONNECTED_STATE_DISCONNECTED) {
                if (mWifiController.connect(ap)) {
                    mHost.collapsePanels();
                }
@@ -442,12 +444,12 @@ public class WifiTile extends QSTileImpl<SignalState> {
            if (mAccessPoints != null) {
                items = new Item[mAccessPoints.length];
                for (int i = 0; i < mAccessPoints.length; i++) {
                    final AccessPoint ap = mAccessPoints[i];
                    final WifiEntry ap = mAccessPoints[i];
                    final Item item = new Item();
                    item.tag = ap;
                    item.iconResId = mWifiController.getIcon(ap);
                    item.line1 = ap.getSsid();
                    item.line2 = ap.isActive() ? ap.getSummary() : null;
                    item.line2 = ap.getSummary();
                    item.icon2 = ap.getSecurity() != AccessPoint.SECURITY_NONE
                            ? R.drawable.qs_ic_wifi_lock
                            : -1;
@@ -457,4 +459,8 @@ public class WifiTile extends QSTileImpl<SignalState> {
            mItems.setItems(items);
        }
    }

    private static boolean isWifiEntryReachable(WifiEntry ap) {
        return ap.getLevel() != WifiEntry.WIFI_LEVEL_UNREACHABLE;
    }
}
+201 −40
Original line number Diff line number Diff line
@@ -16,25 +16,47 @@

package com.android.systemui.statusbar.policy;

import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.net.wifi.WifiManager.ActionListener;
import android.net.ConnectivityManager;
import android.net.NetworkScoreManager;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.SimpleClock;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.util.IndentingPrintWriter;
import android.util.Log;

import com.android.settingslib.wifi.AccessPoint;
import com.android.settingslib.wifi.WifiTracker;
import com.android.settingslib.wifi.WifiTracker.WifiListener;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LifecycleRegistry;

import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.settings.UserTracker;
import com.android.wifitrackerlib.WifiEntry;
import com.android.wifitrackerlib.WifiPickerTracker;

import java.io.PrintWriter;
import java.time.Clock;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Executor;

import javax.inject.Inject;

public class AccessPointControllerImpl
        implements NetworkController.AccessPointController, WifiListener {
        implements NetworkController.AccessPointController,
        WifiPickerTracker.WifiPickerTrackerCallback, LifecycleOwner {
    private static final String TAG = "AccessPointController";
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);

@@ -44,24 +66,51 @@ public class AccessPointControllerImpl

    private static final int[] ICONS = WifiIcons.WIFI_FULL_ICONS;

    private final Context mContext;
    private final ArrayList<AccessPointCallback> mCallbacks = new ArrayList<AccessPointCallback>();
    private final WifiTracker mWifiTracker;
    private final UserManager mUserManager;
    private final Executor mMainExecutor;

    private @Nullable WifiPickerTracker mWifiPickerTracker;
    private WifiPickerTrackerFactory mWifiPickerTrackerFactory;

    private final LifecycleRegistry mLifecycle = new LifecycleRegistry(this);

    private int mCurrentUser;

    public AccessPointControllerImpl(Context context) {
        mContext = context;
        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
        mWifiTracker = new WifiTracker(context, this, false, true);
        mCurrentUser = ActivityManager.getCurrentUser();
    public AccessPointControllerImpl(
            UserManager userManager,
            UserTracker userTracker,
            Executor mainExecutor,
            WifiPickerTrackerFactory wifiPickerTrackerFactory
    ) {
        mUserManager = userManager;
        mCurrentUser = userTracker.getUserId();
        mMainExecutor = mainExecutor;
        mWifiPickerTrackerFactory = wifiPickerTrackerFactory;
        mMainExecutor.execute(() -> mLifecycle.setCurrentState(Lifecycle.State.CREATED));
    }

    /**
     * Initializes the controller.
     *
     * Will create a WifiPickerTracker associated to this controller.
     */
    public void init() {
        if (mWifiPickerTracker == null) {
            mWifiPickerTracker = mWifiPickerTrackerFactory.create(this.getLifecycle(), this);
        }
    }

    @NonNull
    @Override
    public Lifecycle getLifecycle() {
        return mLifecycle;
    }

    @Override
    protected void finalize() throws Throwable {
        mMainExecutor.execute(() -> mLifecycle.setCurrentState(Lifecycle.State.DESTROYED));
        super.finalize();
        mWifiTracker.onDestroy();
    }

    public boolean canConfigWifi() {
@@ -79,7 +128,7 @@ public class AccessPointControllerImpl
        if (DEBUG) Log.d(TAG, "addCallback " + callback);
        mCallbacks.add(callback);
        if (mCallbacks.size() == 1) {
            mWifiTracker.onStart();
            mMainExecutor.execute(() -> mLifecycle.setCurrentState(Lifecycle.State.STARTED));
        }
    }

@@ -89,37 +138,59 @@ public class AccessPointControllerImpl
        if (DEBUG) Log.d(TAG, "removeCallback " + callback);
        mCallbacks.remove(callback);
        if (mCallbacks.isEmpty()) {
            mWifiTracker.onStop();
            mMainExecutor.execute(() -> mLifecycle.setCurrentState(Lifecycle.State.CREATED));
        }
    }

    @Override
    public void scanForAccessPoints() {
        fireAcccessPointsCallback(mWifiTracker.getAccessPoints());
        if (mWifiPickerTracker == null) {
            fireAcccessPointsCallback(Collections.emptyList());
            return;
        }
        List<WifiEntry> entries = mWifiPickerTracker.getWifiEntries();
        WifiEntry connectedEntry = mWifiPickerTracker.getConnectedWifiEntry();
        if (connectedEntry != null) {
            entries.add(0, connectedEntry);
        }
        fireAcccessPointsCallback(entries);
    }

    @Override
    public int getIcon(AccessPoint ap) {
    public int getIcon(WifiEntry ap) {
        int level = ap.getLevel();
        return ICONS[level >= 0 ? level : 0];
        return ICONS[Math.max(0, level)];
    }

    public boolean connect(AccessPoint ap) {
    /**
     * Connects to a {@link WifiEntry} if it's saved or does not require security.
     *
     * If the entry is not saved and requires security, will trigger
     * {@link AccessPointCallback#onSettingsActivityTriggered}.
     * @param ap
     * @return {@code true} if {@link AccessPointCallback#onSettingsActivityTriggered} is triggered
     */
    public boolean connect(WifiEntry ap) {
        if (ap == null) return false;
        if (DEBUG) Log.d(TAG, "connect networkId=" + ap.getConfig().networkId);
        if (DEBUG) {
            if (ap.getWifiConfiguration() != null) {
                Log.d(TAG, "connect networkId=" + ap.getWifiConfiguration().networkId);
            } else {
                Log.d(TAG, "connect to unsaved network " + ap.getTitle());
            }
        }
        if (ap.isSaved()) {
            mWifiTracker.getManager().connect(ap.getConfig().networkId, mConnectListener);
            ap.connect(mConnectCallback);
        } else {
            // Unknown network, need to add it.
            if (ap.getSecurity() != AccessPoint.SECURITY_NONE) {
            if (ap.getSecurity() != WifiEntry.SECURITY_NONE) {
                Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS);
                intent.putExtra(EXTRA_START_CONNECT_SSID, ap.getSsidStr());
                intent.putExtra(EXTRA_START_CONNECT_SSID, ap.getSsid());
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                fireSettingsIntentCallback(intent);
                return true;
            } else {
                ap.generateOpenNetworkConfig();
                mWifiTracker.getManager().connect(ap.getConfig(), mConnectListener);
                ap.connect(mConnectCallback);
            }
        }
        return false;
@@ -131,39 +202,129 @@ public class AccessPointControllerImpl
        }
    }

    private void fireAcccessPointsCallback(List<AccessPoint> aps) {
    private void fireAcccessPointsCallback(List<WifiEntry> aps) {
        for (AccessPointCallback callback : mCallbacks) {
            callback.onAccessPointsChanged(aps);
        }
    }

    public void dump(PrintWriter pw) {
        mWifiTracker.dump(pw);
        IndentingPrintWriter ipw = new IndentingPrintWriter(pw);
        ipw.println("AccessPointControllerImpl:");
        ipw.increaseIndent();
        ipw.println("Callbacks: " + Arrays.toString(mCallbacks.toArray()));
        ipw.println("WifiPickerTracker: " + mWifiPickerTracker.toString());
        if (mWifiPickerTracker != null && !mCallbacks.isEmpty()) {
            ipw.println("Connected: " + mWifiPickerTracker.getConnectedWifiEntry());
            ipw.println("Other wifi entries: "
                    + Arrays.toString(mWifiPickerTracker.getWifiEntries().toArray()));
        } else if (mWifiPickerTracker != null) {
            ipw.println("WifiPickerTracker not started, cannot get reliable entries");
        }
        ipw.decreaseIndent();
    }

    @Override
    public void onWifiStateChanged() {
        scanForAccessPoints();
    }

    @Override
    public void onWifiStateChanged(int state) {
    public void onWifiEntriesChanged() {
        scanForAccessPoints();
    }

    @Override
    public void onConnectedChanged() {
        fireAcccessPointsCallback(mWifiTracker.getAccessPoints());
    public void onNumSavedNetworksChanged() {
        // Do nothing
    }

    @Override
    public void onAccessPointsChanged() {
        fireAcccessPointsCallback(mWifiTracker.getAccessPoints());
    public void onNumSavedSubscriptionsChanged() {
        // Do nothing
    }

    private final ActionListener mConnectListener = new ActionListener() {
    private final WifiEntry.ConnectCallback mConnectCallback = new WifiEntry.ConnectCallback() {
        @Override
        public void onSuccess() {
        public void onConnectResult(int status) {
            if (status == CONNECT_STATUS_SUCCESS) {
                if (DEBUG) Log.d(TAG, "connect success");
            } else {
                if (DEBUG) Log.d(TAG, "connect failure reason=" + status);
            }
        }
    };

    /**
     * Factory for creating {@link WifiPickerTracker}.
     *
     * Uses the same time intervals as the Settings page for Wifi.
     */
    @SysUISingleton
    public static class WifiPickerTrackerFactory {

        // 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;

        private final Context mContext;
        private final @Nullable WifiManager mWifiManager;
        private final ConnectivityManager mConnectivityManager;
        private final NetworkScoreManager mNetworkScoreManager;
        private final Handler mMainHandler;
        private final Handler mWorkerHandler;
        private final Clock mClock = new SimpleClock(ZoneOffset.UTC) {
            @Override
        public void onFailure(int reason) {
            if (DEBUG) Log.d(TAG, "connect failure reason=" + reason);
            public long millis() {
                return SystemClock.elapsedRealtime();
            }
        };

        @Inject
        public WifiPickerTrackerFactory(
                Context context,
                @Nullable WifiManager wifiManager,
                ConnectivityManager connectivityManager,
                NetworkScoreManager networkScoreManager,
                @Main Handler mainHandler,
                @Background Handler workerHandler
        ) {
            mContext = context;
            mWifiManager = wifiManager;
            mConnectivityManager = connectivityManager;
            mNetworkScoreManager = networkScoreManager;
            mMainHandler = mainHandler;
            mWorkerHandler = workerHandler;
        }

        /**
         * Create a {@link WifiPickerTracker}
         *
         * @param lifecycle
         * @param listener
         * @return a new {@link WifiPickerTracker} or {@code null} if {@link WifiManager} is null.
         */
        public @Nullable WifiPickerTracker create(
                Lifecycle lifecycle,
                WifiPickerTracker.WifiPickerTrackerCallback listener
        ) {
            if (mWifiManager == null) {
                return null;
            }
            return new WifiPickerTracker(
                    lifecycle,
                    mContext,
                    mWifiManager,
                    mConnectivityManager,
                    mNetworkScoreManager,
                    mMainHandler,
                    mWorkerHandler,
                    mClock,
                    MAX_SCAN_AGE_MILLIS,
                    SCAN_INTERVAL_MILLIS,
                    listener
            );
        }
    }
}
+4 −4
Original line number Diff line number Diff line
@@ -21,9 +21,9 @@ import android.content.Intent;
import android.telephony.SubscriptionInfo;

import com.android.settingslib.net.DataUsageController;
import com.android.settingslib.wifi.AccessPoint;
import com.android.systemui.demomode.DemoMode;
import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
import com.android.wifitrackerlib.WifiEntry;

import java.util.List;

@@ -123,12 +123,12 @@ public interface NetworkController extends CallbackController<SignalCallback>, D
        void addAccessPointCallback(AccessPointCallback callback);
        void removeAccessPointCallback(AccessPointCallback callback);
        void scanForAccessPoints();
        int getIcon(AccessPoint ap);
        boolean connect(AccessPoint ap);
        int getIcon(WifiEntry ap);
        boolean connect(WifiEntry ap);
        boolean canConfigWifi();

        public interface AccessPointCallback {
            void onAccessPointsChanged(List<AccessPoint> accessPoints);
            void onAccessPointsChanged(List<WifiEntry> accessPoints);
            void onSettingsActivityTriggered(Intent settingsIntent);
        }
    }
+2 −1
Original line number Diff line number Diff line
@@ -187,6 +187,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
            TelephonyManager telephonyManager,
            @Nullable WifiManager wifiManager,
            NetworkScoreManager networkScoreManager,
            AccessPointControllerImpl accessPointController,
            DemoModeController demoModeController) {
        this(context, connectivityManager,
                telephonyManager,
@@ -194,7 +195,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
                networkScoreManager,
                SubscriptionManager.from(context), Config.readConfig(context), bgLooper,
                new CallbackHandler(),
                new AccessPointControllerImpl(context),
                accessPointController,
                new DataUsageController(context),
                new SubscriptionDefaults(),
                deviceProvisionedController,
Loading