Synchronize access to mCurrentState when updating
WifiSignalController expects broadcast updates to come in off the main thread, and WifiStatusTracker updates to come in on the main thread. This change ensures data access synchronization by making sure that all data access happens on a known background thread. Bug: 229425925 Test: atest NetworkControllerWifiTest Change-Id: Ifc04b2e25b0cc08ad6406030fa9de3df0ba2df2d
This commit is contained in:
@@ -33,7 +33,6 @@ import android.net.ConnectivityManager;
|
||||
import android.net.ConnectivityManager.NetworkCallback;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkCapabilities;
|
||||
import android.net.NetworkScoreManager;
|
||||
import android.net.wifi.ScanResult;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.AsyncTask;
|
||||
@@ -225,10 +224,10 @@ public class NetworkControllerImpl extends BroadcastReceiver
|
||||
TelephonyManager telephonyManager,
|
||||
TelephonyListenerManager telephonyListenerManager,
|
||||
@Nullable WifiManager wifiManager,
|
||||
NetworkScoreManager networkScoreManager,
|
||||
AccessPointControllerImpl accessPointController,
|
||||
DemoModeController demoModeController,
|
||||
CarrierConfigTracker carrierConfigTracker,
|
||||
WifiStatusTrackerFactory trackerFactory,
|
||||
@Main Handler handler,
|
||||
InternetDialogFactory internetDialogFactory,
|
||||
FeatureFlags featureFlags,
|
||||
@@ -237,7 +236,6 @@ public class NetworkControllerImpl extends BroadcastReceiver
|
||||
telephonyManager,
|
||||
telephonyListenerManager,
|
||||
wifiManager,
|
||||
networkScoreManager,
|
||||
subscriptionManager,
|
||||
Config.readConfig(context),
|
||||
bgLooper,
|
||||
@@ -250,6 +248,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
|
||||
broadcastDispatcher,
|
||||
demoModeController,
|
||||
carrierConfigTracker,
|
||||
trackerFactory,
|
||||
handler,
|
||||
featureFlags,
|
||||
dumpManager);
|
||||
@@ -262,8 +261,9 @@ public class NetworkControllerImpl extends BroadcastReceiver
|
||||
TelephonyManager telephonyManager,
|
||||
TelephonyListenerManager telephonyListenerManager,
|
||||
WifiManager wifiManager,
|
||||
NetworkScoreManager networkScoreManager,
|
||||
SubscriptionManager subManager, Config config, Looper bgLooper,
|
||||
SubscriptionManager subManager,
|
||||
Config config,
|
||||
Looper bgLooper,
|
||||
Executor bgExecutor,
|
||||
CallbackHandler callbackHandler,
|
||||
AccessPointControllerImpl accessPointController,
|
||||
@@ -273,6 +273,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
|
||||
BroadcastDispatcher broadcastDispatcher,
|
||||
DemoModeController demoModeController,
|
||||
CarrierConfigTracker carrierConfigTracker,
|
||||
WifiStatusTrackerFactory trackerFactory,
|
||||
@Main Handler handler,
|
||||
FeatureFlags featureFlags,
|
||||
DumpManager dumpManager
|
||||
@@ -315,9 +316,10 @@ public class NetworkControllerImpl extends BroadcastReceiver
|
||||
notifyControllersMobileDataChanged();
|
||||
}
|
||||
});
|
||||
|
||||
mWifiSignalController = new WifiSignalController(mContext, mHasMobileDataFeature,
|
||||
mCallbackHandler, this, mWifiManager, mConnectivityManager, networkScoreManager,
|
||||
mMainHandler, mReceiverHandler);
|
||||
mCallbackHandler, this, mWifiManager, trackerFactory,
|
||||
mReceiverHandler);
|
||||
|
||||
mEthernetSignalController = new EthernetSignalController(mContext, mCallbackHandler, this);
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ public abstract class SignalController<T extends ConnectivityState, I extends Ic
|
||||
protected final T mLastState;
|
||||
protected final int mTransportType;
|
||||
protected final Context mContext;
|
||||
// The owner of the SignalController (i.e. NetworkController will maintain the following
|
||||
// The owner of the SignalController (i.e. NetworkController) will maintain the following
|
||||
// lists and call notifyListeners whenever the list has changed to ensure everyone
|
||||
// is aware of current state.
|
||||
protected final NetworkControllerImpl mNetworkController;
|
||||
@@ -103,7 +103,7 @@ public abstract class SignalController<T extends ConnectivityState, I extends Ic
|
||||
* Determines if the state of this signal controller has changed and
|
||||
* needs to trigger callbacks related to it.
|
||||
*/
|
||||
public boolean isDirty() {
|
||||
boolean isDirty() {
|
||||
if (!mLastState.equals(mCurrentState)) {
|
||||
if (DEBUG) {
|
||||
Log.d(mTag, "Change in state from: " + mLastState + "\n"
|
||||
|
||||
@@ -21,14 +21,13 @@ import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_OU
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkCapabilities;
|
||||
import android.net.NetworkScoreManager;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.Handler;
|
||||
import android.text.Html;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.settingslib.SignalIcon.IconGroup;
|
||||
import com.android.settingslib.SignalIcon.MobileIconGroup;
|
||||
import com.android.settingslib.graph.SignalDrawable;
|
||||
@@ -36,8 +35,6 @@ import com.android.settingslib.mobile.TelephonyIcons;
|
||||
import com.android.settingslib.wifi.WifiStatusTracker;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.dagger.qualifiers.Background;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.util.Assert;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
@@ -49,21 +46,21 @@ public class WifiSignalController extends SignalController<WifiState, IconGroup>
|
||||
private final MobileIconGroup mCarrierMergedWifiIconGroup = TelephonyIcons.CARRIER_MERGED_WIFI;
|
||||
private final WifiManager mWifiManager;
|
||||
|
||||
private final Handler mBgHandler;
|
||||
|
||||
public WifiSignalController(
|
||||
Context context,
|
||||
boolean hasMobileDataFeature,
|
||||
CallbackHandler callbackHandler,
|
||||
NetworkControllerImpl networkController,
|
||||
WifiManager wifiManager,
|
||||
ConnectivityManager connectivityManager,
|
||||
NetworkScoreManager networkScoreManager,
|
||||
@Main Handler handler,
|
||||
@Background Handler backgroundHandler) {
|
||||
WifiStatusTrackerFactory trackerFactory,
|
||||
@Background Handler bgHandler) {
|
||||
super("WifiSignalController", context, NetworkCapabilities.TRANSPORT_WIFI,
|
||||
callbackHandler, networkController);
|
||||
mBgHandler = bgHandler;
|
||||
mWifiManager = wifiManager;
|
||||
mWifiTracker = new WifiStatusTracker(mContext, wifiManager, networkScoreManager,
|
||||
connectivityManager, this::handleStatusUpdated, handler, backgroundHandler);
|
||||
mWifiTracker = trackerFactory.createTracker(this::handleStatusUpdated, bgHandler);
|
||||
mWifiTracker.setListening(true);
|
||||
mHasMobileDataFeature = hasMobileDataFeature;
|
||||
if (wifiManager != null) {
|
||||
@@ -181,33 +178,51 @@ public class WifiSignalController extends SignalController<WifiState, IconGroup>
|
||||
* Fetches wifi initial state replacing the initial sticky broadcast.
|
||||
*/
|
||||
public void fetchInitialState() {
|
||||
mWifiTracker.fetchInitialState();
|
||||
copyWifiStates();
|
||||
notifyListenersIfNecessary();
|
||||
doInBackground(() -> {
|
||||
mWifiTracker.fetchInitialState();
|
||||
copyWifiStates();
|
||||
notifyListenersIfNecessary();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract wifi state directly from broadcasts about changes in wifi state.
|
||||
*/
|
||||
public void handleBroadcast(Intent intent) {
|
||||
mWifiTracker.handleBroadcast(intent);
|
||||
copyWifiStates();
|
||||
notifyListenersIfNecessary();
|
||||
void handleBroadcast(Intent intent) {
|
||||
doInBackground(() -> {
|
||||
mWifiTracker.handleBroadcast(intent);
|
||||
copyWifiStates();
|
||||
notifyListenersIfNecessary();
|
||||
});
|
||||
}
|
||||
|
||||
private void handleStatusUpdated() {
|
||||
Assert.isMainThread();
|
||||
copyWifiStates();
|
||||
notifyListenersIfNecessary();
|
||||
// The WifiStatusTracker callback comes in on the main thread, but the rest of our data
|
||||
// access happens on the bgHandler
|
||||
doInBackground(() -> {
|
||||
copyWifiStates();
|
||||
notifyListenersIfNecessary();
|
||||
});
|
||||
}
|
||||
|
||||
private void doInBackground(Runnable action) {
|
||||
if (Thread.currentThread() != mBgHandler.getLooper().getThread()) {
|
||||
mBgHandler.post(action);
|
||||
} else {
|
||||
action.run();
|
||||
}
|
||||
}
|
||||
|
||||
private void copyWifiStates() {
|
||||
// Data access should only happen on our bg thread
|
||||
Preconditions.checkState(mBgHandler.getLooper().isCurrentThread());
|
||||
|
||||
mCurrentState.enabled = mWifiTracker.enabled;
|
||||
mCurrentState.isDefault = mWifiTracker.isDefaultNetwork;
|
||||
mCurrentState.connected = mWifiTracker.connected;
|
||||
mCurrentState.ssid = mWifiTracker.ssid;
|
||||
mCurrentState.rssi = mWifiTracker.rssi;
|
||||
notifyWifiLevelChangeIfNecessary(mWifiTracker.level);
|
||||
boolean levelChanged = mCurrentState.level != mWifiTracker.level;
|
||||
mCurrentState.level = mWifiTracker.level;
|
||||
mCurrentState.statusLabel = mWifiTracker.statusLabel;
|
||||
mCurrentState.isCarrierMerged = mWifiTracker.isCarrierMerged;
|
||||
@@ -215,11 +230,9 @@ public class WifiSignalController extends SignalController<WifiState, IconGroup>
|
||||
mCurrentState.iconGroup =
|
||||
mCurrentState.isCarrierMerged ? mCarrierMergedWifiIconGroup
|
||||
: mUnmergedWifiIconGroup;
|
||||
}
|
||||
|
||||
void notifyWifiLevelChangeIfNecessary(int level) {
|
||||
if (level != mCurrentState.level) {
|
||||
mNetworkController.notifyWifiLevelChange(level);
|
||||
if (levelChanged) {
|
||||
mNetworkController.notifyWifiLevelChange(mCurrentState.level);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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.systemui.statusbar.connectivity
|
||||
|
||||
import android.content.Context
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.NetworkScoreManager
|
||||
import android.net.wifi.WifiManager
|
||||
import android.os.Handler
|
||||
|
||||
import com.android.settingslib.wifi.WifiStatusTracker
|
||||
import com.android.systemui.dagger.qualifiers.Main
|
||||
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Factory class for [WifiStatusTracker] which lives in SettingsLib (and thus doesn't use Dagger).
|
||||
* This enables the constructors for NetworkControllerImpl and WifiSignalController to be slightly
|
||||
* nicer.
|
||||
*/
|
||||
internal class WifiStatusTrackerFactory @Inject constructor(
|
||||
private val mContext: Context,
|
||||
private val mWifiManager: WifiManager?,
|
||||
private val mNetworkScoreManager: NetworkScoreManager,
|
||||
private val mConnectivityManager: ConnectivityManager,
|
||||
@Main private val mMainHandler: Handler
|
||||
) {
|
||||
fun createTracker(callback: Runnable?, bgHandler: Handler?): WifiStatusTracker {
|
||||
return WifiStatusTracker(mContext,
|
||||
mWifiManager,
|
||||
mNetworkScoreManager,
|
||||
mConnectivityManager,
|
||||
callback,
|
||||
mMainHandler,
|
||||
bgHandler)
|
||||
}
|
||||
}
|
||||
@@ -127,6 +127,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase {
|
||||
protected FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
|
||||
protected Handler mMainHandler;
|
||||
protected FeatureFlags mFeatureFlags;
|
||||
protected WifiStatusTrackerFactory mWifiStatusTrackerFactory;
|
||||
|
||||
protected int mSubId;
|
||||
|
||||
@@ -220,12 +221,14 @@ public class NetworkControllerBaseTest extends SysuiTestCase {
|
||||
return null;
|
||||
}).when(mMockProvisionController).addCallback(any());
|
||||
|
||||
mWifiStatusTrackerFactory = new WifiStatusTrackerFactory(
|
||||
mContext, mMockWm, mMockNsm, mMockCm, mMainHandler);
|
||||
|
||||
mNetworkController = new NetworkControllerImpl(mContext,
|
||||
mMockCm,
|
||||
mMockTm,
|
||||
mTelephonyListenerManager,
|
||||
mMockWm,
|
||||
mMockNsm,
|
||||
mMockSm,
|
||||
mConfig,
|
||||
TestableLooper.get(this).getLooper(),
|
||||
@@ -238,6 +241,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase {
|
||||
mMockBd,
|
||||
mDemoModeController,
|
||||
mCarrierConfigTracker,
|
||||
mWifiStatusTrackerFactory,
|
||||
mMainHandler,
|
||||
mFeatureFlags,
|
||||
mock(DumpManager.class)
|
||||
|
||||
@@ -127,11 +127,13 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest {
|
||||
mConfig.show4gForLte = true;
|
||||
mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm,
|
||||
mTelephonyListenerManager, mMockWm,
|
||||
mMockNsm, mMockSm, mConfig, Looper.getMainLooper(), mFakeExecutor, mCallbackHandler,
|
||||
mMockSm, mConfig, Looper.getMainLooper(), mFakeExecutor, mCallbackHandler,
|
||||
mock(AccessPointControllerImpl.class),
|
||||
mock(DataUsageController.class), mMockSubDefaults,
|
||||
mock(DeviceProvisionedController.class), mMockBd, mDemoModeController,
|
||||
mock(CarrierConfigTracker.class), new Handler(TestableLooper.get(this).getLooper()),
|
||||
mock(CarrierConfigTracker.class),
|
||||
mWifiStatusTrackerFactory,
|
||||
new Handler(TestableLooper.get(this).getLooper()),
|
||||
mFeatureFlags, mock(DumpManager.class));
|
||||
setupNetworkController();
|
||||
|
||||
|
||||
@@ -71,7 +71,6 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest {
|
||||
mMockTm,
|
||||
mTelephonyListenerManager,
|
||||
mMockWm,
|
||||
mMockNsm,
|
||||
mMockSm,
|
||||
mConfig,
|
||||
TestableLooper.get(this).getLooper(),
|
||||
@@ -84,6 +83,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest {
|
||||
mMockBd,
|
||||
mDemoModeController,
|
||||
mCarrierConfigTracker,
|
||||
mWifiStatusTrackerFactory,
|
||||
mMainHandler,
|
||||
mFeatureFlags,
|
||||
mock(DumpManager.class)
|
||||
@@ -105,7 +105,6 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest {
|
||||
mMockTm,
|
||||
mTelephonyListenerManager,
|
||||
mMockWm,
|
||||
mMockNsm,
|
||||
mMockSm,
|
||||
mConfig,
|
||||
TestableLooper.get(this).getLooper(),
|
||||
@@ -118,6 +117,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest {
|
||||
mMockBd,
|
||||
mDemoModeController,
|
||||
mCarrierConfigTracker,
|
||||
mWifiStatusTrackerFactory,
|
||||
mMainHandler,
|
||||
mFeatureFlags,
|
||||
mock(DumpManager.class)
|
||||
@@ -134,11 +134,12 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest {
|
||||
when(mMockTm.isDataCapable()).thenReturn(false);
|
||||
// Create a new NetworkController as this is currently handled in constructor.
|
||||
mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm,
|
||||
mTelephonyListenerManager, mMockWm, mMockNsm, mMockSm, mConfig,
|
||||
mTelephonyListenerManager, mMockWm, mMockSm, mConfig,
|
||||
Looper.getMainLooper(), mFakeExecutor, mCallbackHandler,
|
||||
mock(AccessPointControllerImpl.class), mock(DataUsageController.class),
|
||||
mMockSubDefaults, mock(DeviceProvisionedController.class), mMockBd,
|
||||
mDemoModeController, mock(CarrierConfigTracker.class),
|
||||
mWifiStatusTrackerFactory,
|
||||
mMainHandler, mFeatureFlags,
|
||||
mock(DumpManager.class));
|
||||
setupNetworkController();
|
||||
@@ -156,11 +157,12 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest {
|
||||
when(mMockSm.getCompleteActiveSubscriptionInfoList()).thenReturn(Collections.emptyList());
|
||||
|
||||
mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm,
|
||||
mTelephonyListenerManager, mMockWm, mMockNsm, mMockSm, mConfig,
|
||||
mTelephonyListenerManager, mMockWm, mMockSm, mConfig,
|
||||
Looper.getMainLooper(), mFakeExecutor, mCallbackHandler,
|
||||
mock(AccessPointControllerImpl.class), mock(DataUsageController.class),
|
||||
mMockSubDefaults, mock(DeviceProvisionedController.class), mMockBd,
|
||||
mDemoModeController, mock(CarrierConfigTracker.class),
|
||||
mWifiStatusTrackerFactory,
|
||||
mMainHandler, mFeatureFlags, mock(DumpManager.class));
|
||||
mNetworkController.registerListeners();
|
||||
|
||||
@@ -225,11 +227,12 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest {
|
||||
when(mMockTm.isDataCapable()).thenReturn(false);
|
||||
// Create a new NetworkController as this is currently handled in constructor.
|
||||
mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm,
|
||||
mTelephonyListenerManager, mMockWm, mMockNsm, mMockSm, mConfig,
|
||||
mTelephonyListenerManager, mMockWm, mMockSm, mConfig,
|
||||
Looper.getMainLooper(), mFakeExecutor, mCallbackHandler,
|
||||
mock(AccessPointControllerImpl.class), mock(DataUsageController.class),
|
||||
mMockSubDefaults, mock(DeviceProvisionedController.class), mMockBd,
|
||||
mDemoModeController, mock(CarrierConfigTracker.class),
|
||||
mWifiStatusTrackerFactory,
|
||||
mMainHandler, mFeatureFlags, mock(DumpManager.class));
|
||||
setupNetworkController();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user