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

Commit d137da93 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Simplify synchronization and delete dead code."

parents b71324a1 5886a94d
Loading
Loading
Loading
Loading
+155 −203
Original line number Original line Diff line number Diff line
@@ -103,7 +103,6 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro
    // TODO: Allow control of this?
    // TODO: Allow control of this?
    // Combo scans can take 5-6s to complete - set to 10s.
    // Combo scans can take 5-6s to complete - set to 10s.
    private static final int WIFI_RESCAN_INTERVAL_MS = 10 * 1000;
    private static final int WIFI_RESCAN_INTERVAL_MS = 10 * 1000;
    private static final int NUM_SCANS_TO_CONFIRM_AP_LOSS = 3;


    private final Context mContext;
    private final Context mContext;
    private final WifiManager mWifiManager;
    private final WifiManager mWifiManager;
@@ -117,22 +116,32 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro


    private WifiTrackerNetworkCallback mNetworkCallback;
    private WifiTrackerNetworkCallback mNetworkCallback;


    @GuardedBy("mLock")
    /**
    private boolean mRegistered;
     * Synchronization lock for managing concurrency between main and worker threads.
     *
     * <p>This lock should be held for all modifications to {@link #mInternalAccessPoints}.
     */
    private final Object mLock = new Object();


    /** The list of AccessPoints, aggregated visible ScanResults with metadata. */
    /** The list of AccessPoints, aggregated visible ScanResults with metadata. */
    @GuardedBy("mLock")
    @GuardedBy("mLock")
    private final List<AccessPoint> mInternalAccessPoints = new ArrayList<>();
    private final List<AccessPoint> mInternalAccessPoints = new ArrayList<>();


    @GuardedBy("mLock")
    private final Set<NetworkKey> mRequestedScores = new ArraySet<>();

    /**
    /**
    * Synchronization lock for managing concurrency between main and worker threads.
     * Tracks whether fresh scan results have been received since scanning start.
     *
     *
    * <p>This lock should be held for all modifications to {@link #mInternalAccessPoints}.
     * <p>If this variable is false, we will not evict the scan result cache or invoke callbacks
     * so that we do not update the UI with stale data / clear out existing UI elements prematurely.
     */
     */
    private final Object mLock = new Object();
    private boolean mStaleScanResults = true;


    // TODO(sghuman): Change this to be keyed on AccessPoint.getKey
    // Does not need to be locked as it only updated on the worker thread, with the exception of
    // during onStart, which occurs before the receiver is registered on the work handler.
    private final HashMap<String, ScanResult> mScanResultCache = new HashMap<>();
    private final HashMap<String, ScanResult> mScanResultCache = new HashMap<>();
    private boolean mRegistered;


    private NetworkInfo mLastNetworkInfo;
    private NetworkInfo mLastNetworkInfo;
    private WifiInfo mLastInfo;
    private WifiInfo mLastInfo;
@@ -142,21 +151,11 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro
    private boolean mNetworkScoringUiEnabled;
    private boolean mNetworkScoringUiEnabled;
    private long mMaxSpeedLabelScoreCacheAge;
    private long mMaxSpeedLabelScoreCacheAge;


    @GuardedBy("mLock")

    private final Set<NetworkKey> mRequestedScores = new ArraySet<>();


    @VisibleForTesting
    @VisibleForTesting
    Scanner mScanner;
    Scanner mScanner;


    /**
     * Tracks whether fresh scan results have been received since scanning start.
     *
     * <p>If this variable is false, we will not evict the scan result cache or invoke callbacks
     * so that we do not update the UI with stale data / clear out existing UI elements prematurely.
     */
    @GuardedBy("mLock")
    private boolean mStaleScanResults = true;

    private static IntentFilter newIntentFilter() {
    private static IntentFilter newIntentFilter() {
        IntentFilter filter = new IntentFilter();
        IntentFilter filter = new IntentFilter();
        filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
        filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
@@ -239,9 +238,7 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro
        mScoreCache = new WifiNetworkScoreCache(mContext, new CacheListener(mWorkHandler) {
        mScoreCache = new WifiNetworkScoreCache(mContext, new CacheListener(mWorkHandler) {
            @Override
            @Override
            public void networkCacheUpdated(List<ScoredNetwork> networks) {
            public void networkCacheUpdated(List<ScoredNetwork> networks) {
                synchronized (mLock) {
                if (!mRegistered) return;
                if (!mRegistered) return;
                }


                if (Log.isLoggable(TAG, Log.VERBOSE)) {
                if (Log.isLoggable(TAG, Log.VERBOSE)) {
                    Log.v(TAG, "Score cache was updated with networks: " + networks);
                    Log.v(TAG, "Score cache was updated with networks: " + networks);
@@ -256,24 +253,6 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro
        mWorkThread.quit();
        mWorkThread.quit();
    }
    }


    /** Synchronously update the list of access points with the latest information. */
    @MainThread
    private void forceUpdate() {
        synchronized (mLock) {
            mLastInfo = mWifiManager.getConnectionInfo();
            mLastNetworkInfo = mConnectivityManager.getNetworkInfo(mWifiManager.getCurrentNetwork());

            final List<ScanResult> newScanResults = mWifiManager.getScanResults();
            if (isVerboseLoggingEnabled()) {
                Log.i(TAG, "Fetched scan results: " + newScanResults);
            }

            List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
            mInternalAccessPoints.clear();
            updateAccessPointsLocked(newScanResults, configs);
        }
    }

    /**
    /**
     * Temporarily stop scanning for wifi networks.
     * Temporarily stop scanning for wifi networks.
     *
     *
@@ -284,10 +263,8 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro
            mScanner.pause();
            mScanner.pause();
            mScanner = null;
            mScanner = null;
        }
        }
        synchronized (mLock) {
        mStaleScanResults = true;
        mStaleScanResults = true;
    }
    }
    }


    /**
    /**
     * Resume scanning for wifi networks after it has been paused.
     * Resume scanning for wifi networks after it has been paused.
@@ -313,7 +290,9 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro
    @Override
    @Override
    @MainThread
    @MainThread
    public void onStart() {
    public void onStart() {
        synchronized (mLock) {
        // fetch current ScanResults instead of waiting for broadcast of fresh results
        forceUpdate();

        registerScoreCache();
        registerScoreCache();


        mNetworkScoringUiEnabled =
        mNetworkScoringUiEnabled =
@@ -335,10 +314,20 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro
            mConnectivityManager.registerNetworkCallback(mNetworkRequest, mNetworkCallback);
            mConnectivityManager.registerNetworkCallback(mNetworkRequest, mNetworkCallback);
            mRegistered = true;
            mRegistered = true;
        }
        }

            // fetch current ScanResults instead of waiting for broadcast of fresh results
            forceUpdate();
    }
    }


    /**
     * Synchronously update the list of access points with the latest information.
     *
     * <p>Intended to only be invoked within {@link #onStart()}.
     */
    @MainThread
    private void forceUpdate() {
        mLastInfo = mWifiManager.getConnectionInfo();
        mLastNetworkInfo = mConnectivityManager.getNetworkInfo(mWifiManager.getCurrentNetwork());

        fetchScansAndConfigsAndUpdateAccessPoints();
    }
    }


    private void registerScoreCache() {
    private void registerScoreCache() {
@@ -373,7 +362,6 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro
    @Override
    @Override
    @MainThread
    @MainThread
    public void onStop() {
    public void onStop() {
        synchronized (mLock) {
        if (mRegistered) {
        if (mRegistered) {
            mContext.unregisterReceiver(mReceiver);
            mContext.unregisterReceiver(mReceiver);
            mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
            mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
@@ -384,7 +372,6 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro


        mWorkHandler.removeCallbacksAndMessages(null /* remove all */);
        mWorkHandler.removeCallbacksAndMessages(null /* remove all */);
    }
    }
    }


    private void unregisterScoreCache() {
    private void unregisterScoreCache() {
        mNetworkScoreManager.unregisterNetworkScoreCache(NetworkKey.TYPE_WIFI, mScoreCache);
        mNetworkScoreManager.unregisterNetworkScoreCache(NetworkKey.TYPE_WIFI, mScoreCache);
@@ -407,9 +394,6 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro
     */
     */
    @AnyThread
    @AnyThread
    public List<AccessPoint> getAccessPoints() {
    public List<AccessPoint> getAccessPoints() {
        // TODO(sghuman): Investigate how to eliminate or reduce the need for locking now that we
        // have transitioned to a single worker thread model.

        synchronized (mLock) {
        synchronized (mLock) {
            return new ArrayList<>(mInternalAccessPoints);
            return new ArrayList<>(mInternalAccessPoints);
        }
        }
@@ -444,13 +428,10 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro
        }
        }
    }
    }


    private void handleResume() {
        evictOldScans();
    }

    private ArrayMap<String, List<ScanResult>> updateScanResultCache(
    private ArrayMap<String, List<ScanResult>> updateScanResultCache(
            final List<ScanResult> newResults) {
            final List<ScanResult> newResults) {
        // TODO(sghuman): Delete this and replace it with the Map of Ap Keys to ScanResults
        // TODO(sghuman): Delete this and replace it with the Map of Ap Keys to ScanResults for
        // memory efficiency
        for (ScanResult newResult : newResults) {
        for (ScanResult newResult : newResults) {
            if (newResult.SSID == null || newResult.SSID.isEmpty()) {
            if (newResult.SSID == null || newResult.SSID.isEmpty()) {
                continue;
                continue;
@@ -517,36 +498,22 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro
    }
    }


    /**
    /**
     * Safely modify {@link #mInternalAccessPoints} by acquiring {@link #mLock} first.
     * Retrieves latest scan results and wifi configs, then calls
     *
     * {@link #updateAccessPoints(List, List)}.
     * <p>Will not perform the update if {@link #mStaleScanResults} is true
     */
     */
    private void updateAccessPoints() {
    private void fetchScansAndConfigsAndUpdateAccessPoints() {
        List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
        final List<ScanResult> newScanResults = mWifiManager.getScanResults();
        final List<ScanResult> newScanResults = mWifiManager.getScanResults();
        if (isVerboseLoggingEnabled()) {
        if (isVerboseLoggingEnabled()) {
            Log.i(TAG, "Fetched scan results: " + newScanResults);
            Log.i(TAG, "Fetched scan results: " + newScanResults);
        }
        }


        synchronized (mLock) {
        List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
            if(!mStaleScanResults) {
        updateAccessPoints(newScanResults, configs);
                updateAccessPointsLocked(newScanResults, configs);
            }
        }
    }
    }


    /**
    /** Update the internal list of access points. */
     * Update the internal list of access points.
    private void updateAccessPoints(final List<ScanResult> newScanResults,
     *
     * <p>Do not call directly (except for forceUpdate), use {@link #updateAccessPoints()} which
     * acquires the lock first.
     */
    @GuardedBy("mLock")
    private void updateAccessPointsLocked(final List<ScanResult> newScanResults,
            List<WifiConfiguration> configs) {
            List<WifiConfiguration> configs) {
        // TODO(sghuman): Reduce the synchronization time by only holding the lock when
        // modifying lists exposed to operations on the MainThread (getAccessPoints, stopTracking,
        // startTracking, etc).


        // Map configs and scan results necessary to make AccessPoints
        // Map configs and scan results necessary to make AccessPoints
        final Map<String, WifiConfiguration> configsByKey = new ArrayMap(configs.size());
        final Map<String, WifiConfiguration> configsByKey = new ArrayMap(configs.size());
@@ -560,15 +527,19 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro


        WifiConfiguration connectionConfig = null;
        WifiConfiguration connectionConfig = null;
        if (mLastInfo != null) {
        if (mLastInfo != null) {
            // TODO(sghuman): This call is unneccessary, as we already have all the configs.
            // TODO(sghuman): Refactor to match config network id when updating configs below, and
            // Refactor to match config network id when updating configs below, and then update
            // then update network info and wifi info only on match
            // networkinfo and wifi info only on match
            connectionConfig = getWifiConfigurationForNetworkId(
            connectionConfig = getWifiConfigurationForNetworkId(
                    mLastInfo.getNetworkId(), configs);
                    mLastInfo.getNetworkId(), configs);
        }
        }


        // Rather than dropping and reacquiring the lock multiple times in this method, we lock
        // once for efficiency of lock acquisition time and readability
        synchronized (mLock) {
            // Swap the current access points into a cached list for maintaining AP listeners
            // Swap the current access points into a cached list for maintaining AP listeners
        List<AccessPoint> cachedAccessPoints = new ArrayList<>(mInternalAccessPoints);
            List<AccessPoint> cachedAccessPoints;
            cachedAccessPoints = new ArrayList<>(mInternalAccessPoints);

            ArrayList<AccessPoint> accessPoints = new ArrayList<>();
            ArrayList<AccessPoint> accessPoints = new ArrayList<>();


            final List<NetworkKey> scoresToRequest = new ArrayList<>();
            final List<NetworkKey> scoresToRequest = new ArrayList<>();
@@ -624,6 +595,7 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro


            mInternalAccessPoints.clear();
            mInternalAccessPoints.clear();
            mInternalAccessPoints.addAll(accessPoints);
            mInternalAccessPoints.addAll(accessPoints);
        }


        conditionallyNotifyListeners();
        conditionallyNotifyListeners();
    }
    }
@@ -644,21 +616,6 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro
        return accessPoint;
        return accessPoint;
    }
    }


    @VisibleForTesting
    AccessPoint getCachedOrCreate(WifiConfiguration config, List<AccessPoint> cache) {
        final int N = cache.size();
        for (int i = 0; i < N; i++) {
            if (cache.get(i).matches(config)) {
                AccessPoint ret = cache.remove(i);
                ret.loadConfig(config);

                return ret;
            }
        }
        final AccessPoint accessPoint = new AccessPoint(mContext, config);
        return accessPoint;
    }

    private void updateNetworkInfo(NetworkInfo networkInfo) {
    private void updateNetworkInfo(NetworkInfo networkInfo) {


        /* Sticky broadcasts can call this when wifi is disabled */
        /* Sticky broadcasts can call this when wifi is disabled */
@@ -763,9 +720,6 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro
        public void onReceive(Context context, Intent intent) {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            String action = intent.getAction();


            // TODO(sghuman): Improve efficiency of synchronization by synchonizing on individual
            // methods and only use lock when iterating/modifying collections
            synchronized (mLock) {
            if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
            if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
                updateWifiState(
                updateWifiState(
                        intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
                        intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
@@ -773,26 +727,30 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro
            } else if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(action)) {
            } else if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(action)) {
                mStaleScanResults = false;
                mStaleScanResults = false;


                    updateAccessPoints();
                fetchScansAndConfigsAndUpdateAccessPoints();
            } else if (WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION.equals(action)
            } else if (WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION.equals(action)
                    || WifiManager.LINK_CONFIGURATION_CHANGED_ACTION.equals(action)) {
                    || WifiManager.LINK_CONFIGURATION_CHANGED_ACTION.equals(action)) {
                    updateAccessPoints();
                fetchScansAndConfigsAndUpdateAccessPoints();
            } else if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) {
            } else if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) {
                // TODO(sghuman): Refactor these methods so they cannot result in duplicate
                // TODO(sghuman): Refactor these methods so they cannot result in duplicate
                // onAccessPointsChanged updates being called from this intent.
                // onAccessPointsChanged updates being called from this intent.
                NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
                NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
                updateNetworkInfo(info);
                updateNetworkInfo(info);
                    updateAccessPoints();
                fetchScansAndConfigsAndUpdateAccessPoints();
            } else if (WifiManager.RSSI_CHANGED_ACTION.equals(action)) {
            } else if (WifiManager.RSSI_CHANGED_ACTION.equals(action)) {
                NetworkInfo info =
                NetworkInfo info =
                        mConnectivityManager.getNetworkInfo(mWifiManager.getCurrentNetwork());
                        mConnectivityManager.getNetworkInfo(mWifiManager.getCurrentNetwork());
                updateNetworkInfo(info);
                updateNetworkInfo(info);
            }
            }
        }
        }
        }
    };
    };


    /** Handles updates to WifiState. */
    /**
     * Handles updates to WifiState.
     *
     * <p>If Wifi is not enabled in the enabled state, {@link #mStaleScanResults} will be set to
     * true.
     */
    private void updateWifiState(int state) {
    private void updateWifiState(int state) {
        if (state == WifiManager.WIFI_STATE_ENABLED) {
        if (state == WifiManager.WIFI_STATE_ENABLED) {
            if (mScanner != null) {
            if (mScanner != null) {
@@ -807,10 +765,8 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro
            if (mScanner != null) {
            if (mScanner != null) {
                mScanner.pause();
                mScanner.pause();
            }
            }
            synchronized (mLock) {
            mStaleScanResults = true;
            mStaleScanResults = true;
        }
        }
        }
        mListener.onWifiStateChanged(state);
        mListener.onWifiStateChanged(state);
    }
    }


@@ -823,11 +779,7 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro
                // We don't send a NetworkInfo object along with this message, because even if we
                // We don't send a NetworkInfo object along with this message, because even if we
                // fetch one from ConnectivityManager, it might be older than the most recent
                // fetch one from ConnectivityManager, it might be older than the most recent
                // NetworkInfo message we got via a WIFI_STATE_CHANGED broadcast.
                // NetworkInfo message we got via a WIFI_STATE_CHANGED broadcast.
                mWorkHandler.post(() -> {
                mWorkHandler.post(() -> updateNetworkInfo(null));
                    synchronized (mLock) {
                        updateNetworkInfo(null);
                    }
                });
            }
            }
        }
        }
    }
    }