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
This commit is contained in:
Fabian Kozynski
2019-09-24 10:34:00 -04:00
parent a620de30f4
commit beeec066be
2 changed files with 103 additions and 19 deletions

View File

@@ -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();
}
}
}

View File

@@ -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