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

Commit beeec066 authored by Fabian Kozynski's avatar Fabian Kozynski
Browse files

Enforce updates in main thread in QSCarrierGroup

Move all updates to a Handler in the Main thread

Test: atest QSCarrierGroup
Test: change display size and font in Secondary user and observe that QS
does not crash
Fixes: 141187305

Change-Id: I27c7e8076dad94878ed5a3556f2983d631840b56
parent a620de30
Loading
Loading
Loading
Loading
+80 −9
Original line number Diff line number Diff line
@@ -18,11 +18,16 @@ package com.android.systemui.qs;

import static com.android.systemui.Dependency.BG_HANDLER;
import static com.android.systemui.Dependency.BG_HANDLER_NAME;
import static com.android.systemui.Dependency.MAIN_LOOPER;
import static com.android.systemui.Dependency.MAIN_LOOPER_NAME;
import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;

import android.annotation.MainThread;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.provider.Settings;
import android.telephony.SubscriptionManager;
import android.util.AttributeSet;
@@ -39,6 +44,8 @@ import com.android.systemui.R;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.statusbar.policy.NetworkController;

import java.util.function.Consumer;

import javax.inject.Inject;
import javax.inject.Named;

@@ -46,7 +53,6 @@ import javax.inject.Named;
 * Displays Carrier name and network status in QS
 */
public class QSCarrierGroup extends LinearLayout implements
        CarrierTextController.CarrierTextCallback,
        NetworkController.SignalCallback, View.OnClickListener {

    private static final String TAG = "QSCarrierGroup";
@@ -56,12 +62,14 @@ public class QSCarrierGroup extends LinearLayout implements
    private static final int SIM_SLOTS = 3;
    private final NetworkController mNetworkController;
    private final Handler mBgHandler;
    private final H mMainHandler;

    private View[] mCarrierDividers = new View[SIM_SLOTS - 1];
    private QSCarrier[] mCarrierGroups = new QSCarrier[SIM_SLOTS];
    private TextView mNoSimTextView;
    private final CellSignalState[] mInfos = new CellSignalState[SIM_SLOTS];
    private CarrierTextController mCarrierTextController;
    private CarrierTextController.CarrierTextCallback mCallback;
    private ActivityStarter mActivityStarter;

    private boolean mListening;
@@ -69,11 +77,19 @@ public class QSCarrierGroup extends LinearLayout implements
    @Inject
    public QSCarrierGroup(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
            NetworkController networkController, ActivityStarter activityStarter,
            @Named(BG_HANDLER_NAME) Handler handler) {
            @Named(BG_HANDLER_NAME) Handler handler,
            @Named(MAIN_LOOPER_NAME) Looper looper) {
        super(context, attrs);
        mNetworkController = networkController;
        mActivityStarter = activityStarter;
        mBgHandler = handler;
        mMainHandler = new H(looper, this::handleUpdateCarrierInfo, this::handleUpdateState);
        mCallback = new Callback(mMainHandler);
    }

    @VisibleForTesting
    protected CarrierTextController.CarrierTextCallback getCallback() {
        return mCallback;
    }

    @VisibleForTesting
@@ -81,7 +97,8 @@ public class QSCarrierGroup extends LinearLayout implements
        this(context, attrs,
                Dependency.get(NetworkController.class),
                Dependency.get(ActivityStarter.class),
                Dependency.get(BG_HANDLER));
                Dependency.get(BG_HANDLER),
                Dependency.get(MAIN_LOOPER));
    }

    @Override
@@ -136,14 +153,20 @@ public class QSCarrierGroup extends LinearLayout implements
            if (mNetworkController.hasVoiceCallingFeature()) {
                mNetworkController.addCallback(this);
            }
            mCarrierTextController.setListening(this);
            mCarrierTextController.setListening(mCallback);
        } else {
            mNetworkController.removeCallback(this);
            mCarrierTextController.setListening(null);
        }
    }

    @MainThread
    private void handleUpdateState() {
        if (!mMainHandler.getLooper().isCurrentThread()) {
            mMainHandler.obtainMessage(H.MSG_UPDATE_STATE).sendToTarget();
            return;
        }

        for (int i = 0; i < SIM_SLOTS; i++) {
            mCarrierGroups[i].updateState(mInfos[i]);
        }
@@ -163,8 +186,13 @@ public class QSCarrierGroup extends LinearLayout implements
        return SubscriptionManager.getSlotIndex(subscriptionId);
    }

    @Override
    public void updateCarrierInfo(CarrierTextController.CarrierTextCallbackInfo info) {
    @MainThread
    private void handleUpdateCarrierInfo(CarrierTextController.CarrierTextCallbackInfo info) {
        if (!mMainHandler.getLooper().isCurrentThread()) {
            mMainHandler.obtainMessage(H.MSG_UPDATE_CARRIER_INFO, info).sendToTarget();
            return;
        }

        mNoSimTextView.setVisibility(View.GONE);
        if (!info.airplaneMode && info.anySimReady) {
            boolean[] slotSeen = new boolean[SIM_SLOTS];
@@ -207,7 +235,7 @@ public class QSCarrierGroup extends LinearLayout implements
            mNoSimTextView.setText(info.carrierText);
            mNoSimTextView.setVisibility(View.VISIBLE);
        }
        handleUpdateState();
        handleUpdateState(); // handleUpdateCarrierInfo is always called from main thread.
    }

    @Override
@@ -230,7 +258,7 @@ public class QSCarrierGroup extends LinearLayout implements
        mInfos[slotIndex].contentDescription = statusIcon.contentDescription;
        mInfos[slotIndex].typeContentDescription = typeContentDescription;
        mInfos[slotIndex].roaming = roaming;
        handleUpdateState();
        mMainHandler.obtainMessage(H.MSG_UPDATE_STATE).sendToTarget();
    }

    @Override
@@ -240,7 +268,7 @@ public class QSCarrierGroup extends LinearLayout implements
                mInfos[i].visible = false;
            }
        }
        handleUpdateState();
        mMainHandler.obtainMessage(H.MSG_UPDATE_STATE).sendToTarget();
    }

    static final class CellSignalState {
@@ -250,4 +278,47 @@ public class QSCarrierGroup extends LinearLayout implements
        String typeContentDescription;
        boolean roaming;
    }

    private static class H extends Handler {
        private Consumer<CarrierTextController.CarrierTextCallbackInfo> mUpdateCarrierInfo;
        private Runnable mUpdateState;
        static final int MSG_UPDATE_CARRIER_INFO = 0;
        static final int MSG_UPDATE_STATE = 1;

        H(Looper looper,
                Consumer<CarrierTextController.CarrierTextCallbackInfo> updateCarrierInfo,
                Runnable updateState) {
            super(looper);
            mUpdateCarrierInfo = updateCarrierInfo;
            mUpdateState = updateState;
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_UPDATE_CARRIER_INFO:
                    mUpdateCarrierInfo.accept(
                            (CarrierTextController.CarrierTextCallbackInfo) msg.obj);
                    break;
                case MSG_UPDATE_STATE:
                    mUpdateState.run();
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    }

    private static class Callback implements CarrierTextController.CarrierTextCallback {
        private H mMainHandler;

        Callback(H handler) {
            mMainHandler = handler;
        }

        @Override
        public void updateCarrierInfo(CarrierTextController.CarrierTextCallbackInfo info) {
            mMainHandler.obtainMessage(H.MSG_UPDATE_CARRIER_INFO, info).sendToTarget();
        }
    }
}
+23 −10
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import android.os.Handler;
import android.telephony.SubscriptionManager;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -28,6 +29,7 @@ import android.view.LayoutInflater;
import androidx.test.filters.SmallTest;

import com.android.keyguard.CarrierTextController;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.utils.leaks.LeakCheckedTest;
@@ -45,13 +47,20 @@ import org.mockito.stubbing.Answer;
public class QSCarrierGroupTest extends LeakCheckedTest {

    private QSCarrierGroup mCarrierGroup;
    private CarrierTextController.CarrierTextCallback mCallback;
    private TestableLooper mTestableLooper;

    @Before
    public void setup() throws Exception {
        injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
        TestableLooper.get(this).runWithLooper(
        mTestableLooper = TestableLooper.get(this);
        mDependency.injectTestDependency(
                Dependency.BG_HANDLER, new Handler(mTestableLooper.getLooper()));
        mDependency.injectTestDependency(Dependency.MAIN_LOOPER, mTestableLooper.getLooper());
        mTestableLooper.runWithLooper(
                () -> mCarrierGroup = (QSCarrierGroup) LayoutInflater.from(mContext).inflate(
                        R.layout.qs_carrier_group, null));
        mCallback = mCarrierGroup.getCallback();
    }

    @Test // throws no Exception
@@ -72,7 +81,7 @@ public class QSCarrierGroupTest extends LeakCheckedTest {
                new CharSequence[]{""},
                false,
                new int[]{0});
        spiedCarrierGroup.updateCarrierInfo(c1);
        mCallback.updateCarrierInfo(c1);

        // listOfCarriers length 1, subscriptionIds length 1, anySims true
        CarrierTextController.CarrierTextCallbackInfo
@@ -81,7 +90,7 @@ public class QSCarrierGroupTest extends LeakCheckedTest {
                new CharSequence[]{""},
                true,
                new int[]{0});
        spiedCarrierGroup.updateCarrierInfo(c2);
        mCallback.updateCarrierInfo(c2);

        // listOfCarriers length 2, subscriptionIds length 2, anySims false
        CarrierTextController.CarrierTextCallbackInfo
@@ -90,7 +99,7 @@ public class QSCarrierGroupTest extends LeakCheckedTest {
                new CharSequence[]{"", ""},
                false,
                new int[]{0, 1});
        spiedCarrierGroup.updateCarrierInfo(c3);
        mCallback.updateCarrierInfo(c3);

        // listOfCarriers length 2, subscriptionIds length 2, anySims true
        CarrierTextController.CarrierTextCallbackInfo
@@ -99,7 +108,9 @@ public class QSCarrierGroupTest extends LeakCheckedTest {
                new CharSequence[]{"", ""},
                true,
                new int[]{0, 1});
        spiedCarrierGroup.updateCarrierInfo(c4);
        mCallback.updateCarrierInfo(c4);

        mTestableLooper.processAllMessages();
    }

    @Test // throws no Exception
@@ -120,7 +131,7 @@ public class QSCarrierGroupTest extends LeakCheckedTest {
                new CharSequence[]{"", ""},
                false,
                new int[]{0});
        spiedCarrierGroup.updateCarrierInfo(c1);
        mCallback.updateCarrierInfo(c1);

        // listOfCarriers length 2, subscriptionIds length 1, anySims true
        CarrierTextController.CarrierTextCallbackInfo
@@ -129,7 +140,7 @@ public class QSCarrierGroupTest extends LeakCheckedTest {
                new CharSequence[]{"", ""},
                true,
                new int[]{0});
        spiedCarrierGroup.updateCarrierInfo(c2);
        mCallback.updateCarrierInfo(c2);

        // listOfCarriers length 1, subscriptionIds length 2, anySims false
        CarrierTextController.CarrierTextCallbackInfo
@@ -138,7 +149,7 @@ public class QSCarrierGroupTest extends LeakCheckedTest {
                new CharSequence[]{""},
                false,
                new int[]{0, 1});
        spiedCarrierGroup.updateCarrierInfo(c3);
        mCallback.updateCarrierInfo(c3);

        // listOfCarriers length 1, subscriptionIds length 2, anySims true
        CarrierTextController.CarrierTextCallbackInfo
@@ -147,7 +158,8 @@ public class QSCarrierGroupTest extends LeakCheckedTest {
                new CharSequence[]{""},
                true,
                new int[]{0, 1});
        spiedCarrierGroup.updateCarrierInfo(c4);
        mCallback.updateCarrierInfo(c4);
        mTestableLooper.processAllMessages();
    }

    @Test // throws no Exception
@@ -161,7 +173,8 @@ public class QSCarrierGroupTest extends LeakCheckedTest {
                new CharSequence[]{"", ""},
                true,
                new int[]{0, 1});
        spiedCarrierGroup.updateCarrierInfo(c4);
        mCallback.updateCarrierInfo(c4);
        mTestableLooper.processAllMessages();
    }

    @Test // throws no Exception