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

Commit 470ae84f authored by Evan Laird's avatar Evan Laird Committed by Malcolm Chen
Browse files

Guard against creating too many MobileSignalControllers

The PhoneStateListener that got added to NetworkControllerImpl used the
default (main) looper for its callbacks, which caused race conditions
when updating subscriptions. This resulted in zombie
MobileSignalControllers that were untracked and never stopped listening
for their updates.

To fix the problem we put the phone state listener on the same
background thread as the receiver handler, and also lock around updating
the subscriptions so that we can all have peace of mind.

This should fix a host of issues where the mobile signal is incorrectly
showing state such as disconnected or not showing the data type
indicator.

Fixes: 129717207
Test: visual; remove and insert sim and verify that the proper SIM state
is shown

Change-Id: Iace6a04c0629e24d2ef9c980a8de336a225d0f36
parent f8d48b03
Loading
Loading
Loading
Loading
+16 −10
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ import android.util.Log;
import android.util.MathUtils;
import android.util.SparseArray;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyIntents;
@@ -108,16 +109,10 @@ public class NetworkControllerImpl extends BroadcastReceiver
    private final SubscriptionDefaults mSubDefaults;
    private final DataSaverController mDataSaverController;
    private final CurrentUserTracker mUserTracker;
    private final Object mLock = new Object();
    private Config mConfig;

    private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
        @Override
        public void onActiveDataSubscriptionIdChanged(int subId) {
            mActiveMobileDataSubscription = subId;
            doUpdateMobileControllers();
        }
    };

    private PhoneStateListener mPhoneStateListener;
    private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID;

    // Subcontrollers.
@@ -279,6 +274,14 @@ public class NetworkControllerImpl extends BroadcastReceiver
        // TODO: Move off of the deprecated CONNECTIVITY_ACTION broadcast and rely on callbacks
        // exclusively for status bar icons.
        mConnectivityManager.registerDefaultNetworkCallback(callback, mReceiverHandler);
        // Register the listener on our bg looper
        mPhoneStateListener = new PhoneStateListener(bgLooper) {
            @Override
            public void onActiveDataSubscriptionIdChanged(int subId) {
                mActiveMobileDataSubscription = subId;
                doUpdateMobileControllers();
            }
        };
    }

    public DataSaverController getDataSaverController() {
@@ -600,7 +603,9 @@ public class NetworkControllerImpl extends BroadcastReceiver
            updateNoSims();
            return;
        }
        setCurrentSubscriptions(subscriptions);
        synchronized (mLock) {
            setCurrentSubscriptionsLocked(subscriptions);
        }
        updateNoSims();
        recalculateEmergency();
    }
@@ -628,8 +633,9 @@ public class NetworkControllerImpl extends BroadcastReceiver
        return false;
    }

    @GuardedBy("mLock")
    @VisibleForTesting
    void setCurrentSubscriptions(List<SubscriptionInfo> subscriptions) {
    public void setCurrentSubscriptionsLocked(List<SubscriptionInfo> subscriptions) {
        Collections.sort(subscriptions, new Comparator<SubscriptionInfo>() {
            @Override
            public int compare(SubscriptionInfo lhs, SubscriptionInfo rhs) {
+1 −1
Original line number Diff line number Diff line
@@ -300,7 +300,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest {
        // We can only test whether unregister gets called if it thinks its in a listening
        // state.
        mNetworkController.mListening = true;
        mNetworkController.setCurrentSubscriptions(subscriptions);
        mNetworkController.setCurrentSubscriptionsLocked(subscriptions);

        for (int i = 0; i < testSubscriptions.length; i++) {
            if (i == indexToSkipController) {