Hide RSSI next to single carrier name

If there's exactly one SIM, do not show the RSSI next to the name in
QSBH. Instead, show it with the other icons. If there's more than one
SIM, show each RSSI next to the carrier name, and not with the other
icons (not even in QQS).

Test: atest com.android.systemui.qs
Test: manual single sim
Bug: 187654917
Change-Id: I8b80bb14b8f60872d44d5a92ddfa7c5903420874
Merged-In: I8b80bb14b8f60872d44d5a92ddfa7c5903420874
This commit is contained in:
Fabian Kozynski
2021-07-16 16:15:47 -04:00
parent 1d2cbb6f50
commit 9d8c4f2de6
11 changed files with 485 additions and 120 deletions

View File

@@ -39,6 +39,13 @@
android:singleLine="true"
android:maxEms="7"/>
<View
android:id="@+id/spacer"
android:layout_width="@dimen/qs_carrier_margin_width"
android:layout_height="match_parent"
android:visibility="gone"
/>
<include
layout="@layout/mobile_signal_group"
android:layout_width="wrap_content"

View File

@@ -32,6 +32,8 @@ import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.Space;
import androidx.annotation.NonNull;
import com.android.settingslib.Utils;
import com.android.systemui.BatteryMeterView;
import com.android.systemui.R;
@@ -41,6 +43,8 @@ import com.android.systemui.statusbar.phone.StatusBarWindowView;
import com.android.systemui.statusbar.phone.StatusIconContainer;
import com.android.systemui.statusbar.policy.Clock;
import java.util.List;
/**
* View that contains the top-most bits of the QS panel (primarily the status bar with date, time,
* battery, carrier info and privacy icons) and also contains the {@link QuickQSPanel}.
@@ -86,18 +90,13 @@ public class QuickStatusBarHeader extends FrameLayout {
private float mKeyguardExpansionFraction;
private int mTextColorPrimary = Color.TRANSPARENT;
private int mTopViewMeasureHeight;
private boolean mProviderModel;
private final String mMobileSlotName;
private final String mNoCallingSlotName;
private final String mCallStrengthSlotName;
@NonNull
private List<String> mRssiIgnoredSlots;
private boolean mIsSingleCarrier;
public QuickStatusBarHeader(Context context, AttributeSet attrs) {
super(context, attrs);
mMobileSlotName = context.getString(com.android.internal.R.string.status_bar_mobile);
mNoCallingSlotName = context.getString(com.android.internal.R.string.status_bar_no_calling);
mCallStrengthSlotName =
context.getString(com.android.internal.R.string.status_bar_call_strength);
}
/**
@@ -148,9 +147,9 @@ public class QuickStatusBarHeader extends FrameLayout {
void onAttach(TintedIconManager iconManager,
QSExpansionPathInterpolator qsExpansionPathInterpolator,
boolean providerModel) {
mProviderModel = providerModel;
List<String> rssiIgnoredSlots) {
mTintedIconManager = iconManager;
mRssiIgnoredSlots = rssiIgnoredSlots;
int fillColor = Utils.getColorAttrDefaultColor(getContext(),
android.R.attr.textColorPrimary);
@@ -161,6 +160,11 @@ public class QuickStatusBarHeader extends FrameLayout {
updateAnimators();
}
void setIsSingleCarrier(boolean isSingleCarrier) {
mIsSingleCarrier = isSingleCarrier;
updateAlphaAnimator();
}
public QuickQSPanel getHeaderQsPanel() {
return mHeaderQsPanel;
}
@@ -267,39 +271,26 @@ public class QuickStatusBarHeader extends FrameLayout {
.setListener(new TouchAnimator.ListenerAdapter() {
@Override
public void onAnimationAtEnd() {
// TODO(b/185580157): Remove the mProviderModel if the mobile slot can be
// hidden in Provider model.
if (mProviderModel) {
mIconContainer.addIgnoredSlot(mNoCallingSlotName);
mIconContainer.addIgnoredSlot(mCallStrengthSlotName);
} else {
mIconContainer.addIgnoredSlot(mMobileSlotName);
super.onAnimationAtEnd();
if (!mIsSingleCarrier) {
mIconContainer.addIgnoredSlots(mRssiIgnoredSlots);
}
}
@Override
public void onAnimationStarted() {
if (mProviderModel) {
mIconContainer.addIgnoredSlot(mNoCallingSlotName);
mIconContainer.addIgnoredSlot(mCallStrengthSlotName);
} else {
mIconContainer.addIgnoredSlot(mMobileSlotName);
}
setSeparatorVisibility(false);
if (!mIsSingleCarrier) {
mIconContainer.addIgnoredSlots(mRssiIgnoredSlots);
}
}
@Override
public void onAnimationAtStart() {
super.onAnimationAtStart();
if (mProviderModel) {
mIconContainer.removeIgnoredSlot(mNoCallingSlotName);
mIconContainer.removeIgnoredSlot(mCallStrengthSlotName);
} else {
mIconContainer.removeIgnoredSlot(mMobileSlotName);
}
setSeparatorVisibility(mShowClockIconsSeparator);
// In QQS we never ignore RSSI.
mIconContainer.removeIgnoredSlots(mRssiIgnoredSlots);
}
});
mAlphaAnimator = builder.build();

View File

@@ -43,7 +43,6 @@ import com.android.systemui.statusbar.phone.StatusIconContainer;
import com.android.systemui.statusbar.policy.Clock;
import com.android.systemui.util.ViewController;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
@@ -76,6 +75,9 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
private boolean mMicCameraIndicatorsEnabled;
private boolean mLocationIndicatorsEnabled;
private boolean mPrivacyChipLogged;
private final String mCameraSlot;
private final String mMicSlot;
private final String mLocationSlot;
private SysuiColorExtractor mColorExtractor;
private ColorExtractor.OnColorsChangedListener mOnColorsChangedListener;
@@ -104,8 +106,7 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
}
private void update() {
StatusIconContainer iconContainer = mView.requireViewById(R.id.statusIcons);
iconContainer.setIgnoredSlots(getIgnoredIconSlots());
updatePrivacyIconSlots();
setChipVisibility(!mPrivacyChip.getPrivacyList().isEmpty());
}
};
@@ -154,7 +155,7 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
mClockView = mView.findViewById(R.id.clock);
mIconContainer = mView.findViewById(R.id.statusIcons);
mIconManager = new StatusBarIconController.TintedIconManager(mIconContainer, mFeatureFlags);
mIconManager = new StatusBarIconController.TintedIconManager(mIconContainer, featureFlags);
mDemoModeReceiver = new ClockDemoModeReceiver(mClockView);
mColorExtractor = colorExtractor;
mOnColorsChangedListener = (extractor, which) -> {
@@ -162,6 +163,10 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
mClockView.onColorsChanged(lightTheme);
};
mColorExtractor.addOnColorsChangedListener(mOnColorsChangedListener);
mCameraSlot = getResources().getString(com.android.internal.R.string.status_bar_camera);
mMicSlot = getResources().getString(com.android.internal.R.string.status_bar_microphone);
mLocationSlot = getResources().getString(com.android.internal.R.string.status_bar_location);
}
@Override
@@ -172,14 +177,30 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
mLocationIndicatorsEnabled = mPrivacyItemController.getLocationAvailable();
// Ignore privacy icons because they show in the space above QQS
mIconContainer.setIgnoredSlots(getIgnoredIconSlots());
updatePrivacyIconSlots();
mIconContainer.setShouldRestrictIcons(false);
mStatusBarIconController.addIconGroup(mIconManager);
setChipVisibility(mPrivacyChip.getVisibility() == View.VISIBLE);
mView.onAttach(mIconManager, mQSExpansionPathInterpolator,
mFeatureFlags.isCombinedStatusBarSignalIconsEnabled());
mView.setIsSingleCarrier(mQSCarrierGroupController.isSingleCarrier());
mQSCarrierGroupController
.setOnSingleCarrierChangedListener(mView::setIsSingleCarrier);
List<String> rssiIgnoredSlots;
if (mFeatureFlags.isCombinedStatusBarSignalIconsEnabled()) {
rssiIgnoredSlots = List.of(
getResources().getString(com.android.internal.R.string.status_bar_no_calling),
getResources().getString(com.android.internal.R.string.status_bar_call_strength)
);
} else {
rssiIgnoredSlots = List.of(
getResources().getString(com.android.internal.R.string.status_bar_mobile)
);
}
mView.onAttach(mIconManager, mQSExpansionPathInterpolator, rssiIgnoredSlots);
mDemoModeController.addCallback(mDemoModeReceiver);
}
@@ -189,6 +210,7 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
mColorExtractor.removeOnColorsChangedListener(mOnColorsChangedListener);
mPrivacyChip.setOnClickListener(null);
mStatusBarIconController.removeIconGroup(mIconManager);
mQSCarrierGroupController.setOnSingleCarrierChangedListener(null);
mDemoModeController.removeCallback(mDemoModeReceiver);
setListening(false);
}
@@ -236,21 +258,25 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
mView.setChipVisibility(chipVisible);
}
private List<String> getIgnoredIconSlots() {
ArrayList<String> ignored = new ArrayList<>();
private void updatePrivacyIconSlots() {
if (getChipEnabled()) {
if (mMicCameraIndicatorsEnabled) {
ignored.add(mView.getResources().getString(
com.android.internal.R.string.status_bar_camera));
ignored.add(mView.getResources().getString(
com.android.internal.R.string.status_bar_microphone));
mIconContainer.addIgnoredSlot(mCameraSlot);
mIconContainer.addIgnoredSlot(mMicSlot);
} else {
mIconContainer.removeIgnoredSlot(mCameraSlot);
mIconContainer.removeIgnoredSlot(mMicSlot);
}
if (mLocationIndicatorsEnabled) {
ignored.add(mView.getResources().getString(
com.android.internal.R.string.status_bar_location));
mIconContainer.addIgnoredSlot(mLocationSlot);
} else {
mIconContainer.removeIgnoredSlot(mLocationSlot);
}
} else {
mIconContainer.removeIgnoredSlot(mCameraSlot);
mIconContainer.removeIgnoredSlot(mMicSlot);
mIconContainer.removeIgnoredSlot(mLocationSlot);
}
return ignored;
}
private boolean getChipEnabled() {

View File

@@ -25,6 +25,8 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.VisibleForTesting;
import com.android.settingslib.Utils;
import com.android.settingslib.graph.SignalDrawable;
import com.android.systemui.R;
@@ -37,8 +39,10 @@ public class QSCarrier extends LinearLayout {
private TextView mCarrierText;
private ImageView mMobileSignal;
private ImageView mMobileRoaming;
private View mSpacer;
private CellSignalState mLastSignalState;
private boolean mProviderModelInitialized = false;
private boolean mIsSingleCarrier;
public QSCarrier(Context context) {
super(context);
@@ -63,18 +67,25 @@ public class QSCarrier extends LinearLayout {
mMobileRoaming = findViewById(R.id.mobile_roaming);
mMobileSignal = findViewById(R.id.mobile_signal);
mCarrierText = findViewById(R.id.qs_carrier_text);
mSpacer = findViewById(R.id.spacer);
}
/**
* Update the state of this view
* @param state the current state of the signal for this view
* @param isSingleCarrier whether there is a single carrier being shown in the container
* @return true if the state was actually changed
*/
public boolean updateState(CellSignalState state) {
if (Objects.equals(state, mLastSignalState)) return false;
public boolean updateState(CellSignalState state, boolean isSingleCarrier) {
if (Objects.equals(state, mLastSignalState) && isSingleCarrier == mIsSingleCarrier) {
return false;
}
mLastSignalState = state;
mMobileGroup.setVisibility(state.visible ? View.VISIBLE : View.GONE);
if (state.visible) {
mIsSingleCarrier = isSingleCarrier;
final boolean visible = state.visible && !isSingleCarrier;
mMobileGroup.setVisibility(visible ? View.VISIBLE : View.GONE);
mSpacer.setVisibility(isSingleCarrier ? View.VISIBLE : View.GONE);
if (visible) {
mMobileRoaming.setVisibility(state.roaming ? View.VISIBLE : View.GONE);
ColorStateList colorStateList = Utils.getColorAttr(mContext,
android.R.attr.textColorPrimary);
@@ -125,6 +136,11 @@ public class QSCarrier extends LinearLayout {
com.android.settingslib.R.string.not_default_data_content_description));
}
@VisibleForTesting
View getRSSIView() {
return mMobileGroup;
}
public void setCarrierText(CharSequence text) {
mCarrierText.setText(text);
}

View File

@@ -37,6 +37,7 @@ import com.android.keyguard.CarrierTextManager;
import com.android.settingslib.AccessibilityContentDescriptions;
import com.android.settingslib.mobile.TelephonyIcons;
import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
@@ -62,7 +63,8 @@ public class QSCarrierGroupController {
private final NetworkController mNetworkController;
private final CarrierTextManager mCarrierTextManager;
private final TextView mNoSimTextView;
private final H mMainHandler;
// Non final for testing
private H mMainHandler;
private final Callback mCallback;
private boolean mListening;
private final CellSignalState[] mInfos =
@@ -74,6 +76,11 @@ public class QSCarrierGroupController {
private final boolean mProviderModel;
private final CarrierConfigTracker mCarrierConfigTracker;
private boolean mIsSingleCarrier;
private OnSingleCarrierChangedListener mOnSingleCarrierChangedListener;
private final SlotIndexResolver mSlotIndexResolver;
private final NetworkController.SignalCallback mSignalCallback =
new NetworkController.SignalCallback() {
@Override
@@ -207,7 +214,8 @@ public class QSCarrierGroupController {
@Background Handler bgHandler, @Main Looper mainLooper,
NetworkController networkController,
CarrierTextManager.Builder carrierTextManagerBuilder, Context context,
CarrierConfigTracker carrierConfigTracker, FeatureFlags featureFlags) {
CarrierConfigTracker carrierConfigTracker, FeatureFlags featureFlags,
SlotIndexResolver slotIndexResolver) {
if (featureFlags.isCombinedStatusBarSignalIconsEnabled()) {
mProviderModel = true;
@@ -222,6 +230,7 @@ public class QSCarrierGroupController {
.setShowMissingSim(false)
.build();
mCarrierConfigTracker = carrierConfigTracker;
mSlotIndexResolver = slotIndexResolver;
View.OnClickListener onClickListener = v -> {
if (!v.isVisibleToUser()) {
return;
@@ -256,6 +265,7 @@ public class QSCarrierGroupController {
.toString();
mCarrierGroups[i].setOnClickListener(onClickListener);
}
mIsSingleCarrier = computeIsSingleCarrier();
view.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
view.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
@@ -272,10 +282,24 @@ public class QSCarrierGroupController {
@VisibleForTesting
protected int getSlotIndex(int subscriptionId) {
return SubscriptionManager.getSlotIndex(subscriptionId);
return mSlotIndexResolver.getSlotIndex(subscriptionId);
}
private boolean isSingleCarrier() {
/**
* Sets a {@link OnSingleCarrierChangedListener}.
*
* This will get notified when the number of carriers changes between 1 and "not one".
* @param listener
*/
public void setOnSingleCarrierChangedListener(OnSingleCarrierChangedListener listener) {
mOnSingleCarrierChangedListener = listener;
}
public boolean isSingleCarrier() {
return mIsSingleCarrier;
}
private boolean computeIsSingleCarrier() {
int carrierCount = 0;
for (int i = 0; i < SIM_SLOTS; i++) {
@@ -315,7 +339,9 @@ public class QSCarrierGroupController {
return;
}
if (isSingleCarrier()) {
boolean singleCarrier = computeIsSingleCarrier();
if (singleCarrier) {
for (int i = 0; i < SIM_SLOTS; i++) {
if (mInfos[i].visible
&& mInfos[i].mobileSignalIconId == R.drawable.ic_qs_sim_card) {
@@ -326,7 +352,7 @@ public class QSCarrierGroupController {
}
for (int i = 0; i < SIM_SLOTS; i++) {
mCarrierGroups[i].updateState(mInfos[i]);
mCarrierGroups[i].updateState(mInfos[i], singleCarrier);
}
mCarrierDividers[0].setVisibility(
@@ -337,6 +363,12 @@ public class QSCarrierGroupController {
mCarrierDividers[1].setVisibility(
(mInfos[1].visible && mInfos[2].visible)
|| (mInfos[0].visible && mInfos[2].visible) ? View.VISIBLE : View.GONE);
if (mIsSingleCarrier != singleCarrier) {
mIsSingleCarrier = singleCarrier;
if (mOnSingleCarrierChangedListener != null) {
mOnSingleCarrierChangedListener.onSingleCarrierChanged(singleCarrier);
}
}
}
@MainThread
@@ -433,12 +465,14 @@ public class QSCarrierGroupController {
private final Context mContext;
private final CarrierConfigTracker mCarrierConfigTracker;
private final FeatureFlags mFeatureFlags;
private final SlotIndexResolver mSlotIndexResolver;
@Inject
public Builder(ActivityStarter activityStarter, @Background Handler handler,
@Main Looper looper, NetworkController networkController,
CarrierTextManager.Builder carrierTextControllerBuilder, Context context,
CarrierConfigTracker carrierConfigTracker, FeatureFlags featureFlags) {
CarrierConfigTracker carrierConfigTracker, FeatureFlags featureFlags,
SlotIndexResolver slotIndexResolver) {
mActivityStarter = activityStarter;
mHandler = handler;
mLooper = looper;
@@ -447,6 +481,7 @@ public class QSCarrierGroupController {
mContext = context;
mCarrierConfigTracker = carrierConfigTracker;
mFeatureFlags = featureFlags;
mSlotIndexResolver = slotIndexResolver;
}
public Builder setQSCarrierGroup(QSCarrierGroup view) {
@@ -457,7 +492,43 @@ public class QSCarrierGroupController {
public QSCarrierGroupController build() {
return new QSCarrierGroupController(mView, mActivityStarter, mHandler, mLooper,
mNetworkController, mCarrierTextControllerBuilder, mContext,
mCarrierConfigTracker, mFeatureFlags);
mCarrierConfigTracker, mFeatureFlags, mSlotIndexResolver);
}
}
/**
* Notify when the state changes from 1 carrier to "not one" and viceversa
*/
@FunctionalInterface
public interface OnSingleCarrierChangedListener {
void onSingleCarrierChanged(boolean isSingleCarrier);
}
/**
* Interface for resolving slot index from subscription ID.
*/
@FunctionalInterface
public interface SlotIndexResolver {
/**
* Get slot index for given sub id.
*/
int getSlotIndex(int subscriptionId);
}
/**
* Default implementation for {@link SlotIndexResolver}.
*
* It retrieves the slot index using {@link SubscriptionManager#getSlotIndex}.
*/
@SysUISingleton
public static class SubscriptionManagerSlotIndexResolver implements SlotIndexResolver {
@Inject
public SubscriptionManagerSlotIndexResolver() {}
@Override
public int getSlotIndex(int subscriptionId) {
return SubscriptionManager.getSlotIndex(subscriptionId);
}
}
}

View File

@@ -33,6 +33,7 @@ import com.android.systemui.qs.QSFragment;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.qs.QuickQSPanel;
import com.android.systemui.qs.QuickStatusBarHeader;
import com.android.systemui.qs.carrier.QSCarrierGroupController;
import com.android.systemui.qs.customize.QSCustomizer;
import com.android.systemui.statusbar.phone.MultiUserSwitch;
@@ -146,4 +147,8 @@ public interface QSFragmentModule {
return useQsMediaPlayer(context);
}
/** */
@Binds
QSCarrierGroupController.SlotIndexResolver provideSlotIndexResolver(
QSCarrierGroupController.SubscriptionManagerSlotIndexResolver impl);
}

View File

@@ -89,5 +89,4 @@ public interface QSModule {
/** */
@Binds
QSHost provideQsHost(QSTileHost controllerImpl);
}

View File

@@ -245,8 +245,19 @@ public class StatusIconContainer extends AlphaOptimizedLinearLayout {
* @param slotName name of the icon slot to remove from the ignored list
*/
public void removeIgnoredSlot(String slotName) {
if (mIgnoredSlots.contains(slotName)) {
mIgnoredSlots.remove(slotName);
mIgnoredSlots.remove(slotName);
requestLayout();
}
/**
* Remove a list of slots from the list of ignored icon slots.
* It will then be shown when set to visible by the {@link StatusBarIconController}.
* @param slots name of the icon slots to remove from the ignored list
*/
public void removeIgnoredSlots(List<String> slots) {
for (String slot : slots) {
mIgnoredSlots.remove(slot);
}
requestLayout();

View File

@@ -48,6 +48,7 @@ import org.mockito.Answers
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
import org.mockito.Mockito.`when`
import org.mockito.Mockito.reset
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
@@ -98,6 +99,10 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() {
private lateinit var controller: QuickStatusBarHeaderController
private lateinit var cameraSlotName: String
private lateinit var microphoneSlotName: String
private lateinit var locationSlotName: String
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
@@ -108,6 +113,13 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() {
`when`(view.isAttachedToWindow).thenReturn(true)
`when`(view.context).thenReturn(context)
cameraSlotName = mContext.resources.getString(
com.android.internal.R.string.status_bar_camera)
microphoneSlotName = mContext.resources.getString(
com.android.internal.R.string.status_bar_microphone)
locationSlotName = mContext.resources.getString(
com.android.internal.R.string.status_bar_location)
controller = QuickStatusBarHeaderController(
view,
privacyItemController,
@@ -141,10 +153,9 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() {
controller.init()
val captor = argumentCaptor<List<String>>()
verify(iconContainer).setIgnoredSlots(capture(captor))
assertThat(captor.value).isEmpty()
verify(iconContainer).removeIgnoredSlot(cameraSlotName)
verify(iconContainer).removeIgnoredSlot(microphoneSlotName)
verify(iconContainer).removeIgnoredSlot(locationSlotName)
}
@Test
@@ -153,15 +164,9 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() {
controller.init()
val captor = argumentCaptor<List<String>>()
verify(iconContainer).setIgnoredSlots(capture(captor))
val cameraString = mContext.resources.getString(
com.android.internal.R.string.status_bar_camera)
val micString = mContext.resources.getString(
com.android.internal.R.string.status_bar_microphone)
assertThat(captor.value).containsExactly(cameraString, micString)
verify(iconContainer).addIgnoredSlot(cameraSlotName)
verify(iconContainer).addIgnoredSlot(microphoneSlotName)
verify(iconContainer).removeIgnoredSlot(locationSlotName)
}
@Test
@@ -170,13 +175,9 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() {
controller.init()
val captor = argumentCaptor<List<String>>()
verify(iconContainer).setIgnoredSlots(capture(captor))
val locationString = mContext.resources.getString(
com.android.internal.R.string.status_bar_location)
assertThat(captor.value).containsExactly(locationString)
verify(iconContainer).removeIgnoredSlot(cameraSlotName)
verify(iconContainer).removeIgnoredSlot(microphoneSlotName)
verify(iconContainer).addIgnoredSlot(locationSlotName)
}
@Test
@@ -185,17 +186,9 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() {
controller.init()
val captor = argumentCaptor<List<String>>()
verify(iconContainer).setIgnoredSlots(capture(captor))
val cameraString = mContext.resources.getString(
com.android.internal.R.string.status_bar_camera)
val micString = mContext.resources.getString(
com.android.internal.R.string.status_bar_microphone)
val locationString = mContext.resources.getString(
com.android.internal.R.string.status_bar_location)
assertThat(captor.value).containsExactly(cameraString, micString, locationString)
verify(iconContainer).addIgnoredSlot(cameraSlotName)
verify(iconContainer).addIgnoredSlot(microphoneSlotName)
verify(iconContainer).addIgnoredSlot(locationSlotName)
}
@Test
@@ -210,6 +203,71 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() {
verify(privacyDialogController).showDialog(any(Context::class.java))
}
@Test
fun testSingleCarrierListenerAttachedOnInit() {
controller.init()
verify(qsCarrierGroupController).setOnSingleCarrierChangedListener(any())
}
@Test
fun testSingleCarrierSetOnViewOnInit_false() {
`when`(qsCarrierGroupController.isSingleCarrier).thenReturn(false)
controller.init()
verify(view).setIsSingleCarrier(false)
}
@Test
fun testSingleCarrierSetOnViewOnInit_true() {
`when`(qsCarrierGroupController.isSingleCarrier).thenReturn(true)
controller.init()
verify(view).setIsSingleCarrier(true)
}
@Test
fun testRSSISlot_notCombined() {
`when`(featureFlags.isCombinedStatusBarSignalIconsEnabled).thenReturn(false)
controller.init()
val captor = argumentCaptor<List<String>>()
verify(view).onAttach(any(), any(), capture(captor))
assertThat(captor.value).containsExactly(
mContext.getString(com.android.internal.R.string.status_bar_mobile)
)
}
@Test
fun testRSSISlot_combined() {
`when`(featureFlags.isCombinedStatusBarSignalIconsEnabled).thenReturn(true)
controller.init()
val captor = argumentCaptor<List<String>>()
verify(view).onAttach(any(), any(), capture(captor))
assertThat(captor.value).containsExactly(
mContext.getString(com.android.internal.R.string.status_bar_no_calling),
mContext.getString(com.android.internal.R.string.status_bar_call_strength)
)
}
@Test
fun testSingleCarrierCallback() {
controller.init()
reset(view)
val captor = argumentCaptor<QSCarrierGroupController.OnSingleCarrierChangedListener>()
verify(qsCarrierGroupController).setOnSingleCarrierChangedListener(capture(captor))
captor.value.onSingleCarrierChanged(true)
verify(view).setIsSingleCarrier(true)
captor.value.onSingleCarrierChanged(false)
verify(view).setIsSingleCarrier(false)
}
private fun stubViews() {
`when`(view.findViewById<View>(anyInt())).thenReturn(mockView)
`when`(view.findViewById<QSCarrierGroup>(R.id.carrier_group)).thenReturn(qsCarrierGroup)

View File

@@ -17,15 +17,18 @@
package com.android.systemui.qs.carrier;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.os.Handler;
import android.telephony.SubscriptionManager;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.View;
@@ -46,9 +49,7 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.stubbing.Answer;
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
@@ -70,8 +71,18 @@ public class QSCarrierGroupControllerTest extends LeakCheckedTest {
private CarrierTextManager mCarrierTextManager;
@Mock
private CarrierConfigTracker mCarrierConfigTracker;
@Mock
private QSCarrier mQSCarrier1;
@Mock
private QSCarrier mQSCarrier2;
@Mock
private QSCarrier mQSCarrier3;
private TestableLooper mTestableLooper;
@Mock private FeatureFlags mFeatureFlags;
@Mock
private QSCarrierGroupController.OnSingleCarrierChangedListener mOnSingleCarrierChangedListener;
private FakeSlotIndexResolver mSlotIndexResolver;
@Before
public void setup() throws Exception {
@@ -96,29 +107,31 @@ public class QSCarrierGroupControllerTest extends LeakCheckedTest {
.setListening(any(CarrierTextManager.CarrierTextCallback.class));
when(mQSCarrierGroup.getNoSimTextView()).thenReturn(new TextView(mContext));
when(mQSCarrierGroup.getCarrier1View()).thenReturn(mock(QSCarrier.class));
when(mQSCarrierGroup.getCarrier2View()).thenReturn(mock(QSCarrier.class));
when(mQSCarrierGroup.getCarrier3View()).thenReturn(mock(QSCarrier.class));
when(mQSCarrierGroup.getCarrier1View()).thenReturn(mQSCarrier1);
when(mQSCarrierGroup.getCarrier2View()).thenReturn(mQSCarrier2);
when(mQSCarrierGroup.getCarrier3View()).thenReturn(mQSCarrier3);
when(mQSCarrierGroup.getCarrierDivider1()).thenReturn(new View(mContext));
when(mQSCarrierGroup.getCarrierDivider2()).thenReturn(new View(mContext));
mSlotIndexResolver = new FakeSlotIndexResolver();
mQSCarrierGroupController = new QSCarrierGroupController.Builder(
mActivityStarter, handler, TestableLooper.get(this).getLooper(),
mNetworkController, mCarrierTextControllerBuilder, mContext, mCarrierConfigTracker,
mFeatureFlags)
mFeatureFlags, mSlotIndexResolver)
.setQSCarrierGroup(mQSCarrierGroup)
.build();
mQSCarrierGroupController.setListening(true);
}
@Test
public void testInitiallyMultiCarrier() {
assertFalse(mQSCarrierGroupController.isSingleCarrier());
}
@Test // throws no Exception
public void testUpdateCarrierText_sameLengths() {
QSCarrierGroupController spiedCarrierGroupController =
Mockito.spy(mQSCarrierGroupController);
when(spiedCarrierGroupController.getSlotIndex(anyInt())).thenAnswer(
(Answer<Integer>) invocationOnMock -> invocationOnMock.getArgument(0));
// listOfCarriers length 1, subscriptionIds length 1, anySims false
CarrierTextManager.CarrierTextCallbackInfo
c1 = new CarrierTextManager.CarrierTextCallbackInfo(
@@ -160,11 +173,6 @@ public class QSCarrierGroupControllerTest extends LeakCheckedTest {
@Test // throws no Exception
public void testUpdateCarrierText_differentLength() {
QSCarrierGroupController spiedCarrierGroupController =
Mockito.spy(mQSCarrierGroupController);
when(spiedCarrierGroupController.getSlotIndex(anyInt())).thenAnswer(
(Answer<Integer>) invocationOnMock -> invocationOnMock.getArgument(0));
// listOfCarriers length 2, subscriptionIds length 1, anySims false
CarrierTextManager.CarrierTextCallbackInfo
c1 = new CarrierTextManager.CarrierTextCallbackInfo(
@@ -205,10 +213,7 @@ public class QSCarrierGroupControllerTest extends LeakCheckedTest {
@Test // throws no Exception
public void testUpdateCarrierText_invalidSim() {
QSCarrierGroupController spiedCarrierGroupController =
Mockito.spy(mQSCarrierGroupController);
when(spiedCarrierGroupController.getSlotIndex(anyInt())).thenReturn(
SubscriptionManager.INVALID_SIM_SLOT_INDEX);
mSlotIndexResolver.overrideInvalid = true;
CarrierTextManager.CarrierTextCallbackInfo
c4 = new CarrierTextManager.CarrierTextCallbackInfo(
@@ -222,6 +227,8 @@ public class QSCarrierGroupControllerTest extends LeakCheckedTest {
@Test // throws no Exception
public void testSetMobileDataIndicators_invalidSim() {
mSlotIndexResolver.overrideInvalid = true;
MobileDataIndicators indicators = new MobileDataIndicators(
mock(NetworkController.IconState.class),
mock(NetworkController.IconState.class),
@@ -242,4 +249,137 @@ public class QSCarrierGroupControllerTest extends LeakCheckedTest {
mTestableLooper.processAllMessages();
assertEquals(View.GONE, mQSCarrierGroup.getNoSimTextView().getVisibility());
}
@Test
public void testListenerNotCalledOnRegistreation() {
mQSCarrierGroupController
.setOnSingleCarrierChangedListener(mOnSingleCarrierChangedListener);
verify(mOnSingleCarrierChangedListener, never()).onSingleCarrierChanged(anyBoolean());
}
@Test
public void testSingleCarrier() {
// Only one element in the info
CarrierTextManager.CarrierTextCallbackInfo
info = new CarrierTextManager.CarrierTextCallbackInfo(
"",
new CharSequence[]{""},
true,
new int[]{0},
false /* airplaneMode */);
mCallback.updateCarrierInfo(info);
mTestableLooper.processAllMessages();
verify(mQSCarrier1).updateState(any(), eq(true));
verify(mQSCarrier2).updateState(any(), eq(true));
verify(mQSCarrier3).updateState(any(), eq(true));
}
@Test
public void testMultiCarrier() {
// More than one element in the info
CarrierTextManager.CarrierTextCallbackInfo
info = new CarrierTextManager.CarrierTextCallbackInfo(
"",
new CharSequence[]{"", ""},
true,
new int[]{0, 1},
false /* airplaneMode */);
mCallback.updateCarrierInfo(info);
mTestableLooper.processAllMessages();
verify(mQSCarrier1).updateState(any(), eq(false));
verify(mQSCarrier2).updateState(any(), eq(false));
verify(mQSCarrier3).updateState(any(), eq(false));
}
@Test
public void testSingleMultiCarrierSwitch() {
CarrierTextManager.CarrierTextCallbackInfo
singleCarrierInfo = new CarrierTextManager.CarrierTextCallbackInfo(
"",
new CharSequence[]{""},
true,
new int[]{0},
false /* airplaneMode */);
CarrierTextManager.CarrierTextCallbackInfo
multiCarrierInfo = new CarrierTextManager.CarrierTextCallbackInfo(
"",
new CharSequence[]{"", ""},
true,
new int[]{0, 1},
false /* airplaneMode */);
mCallback.updateCarrierInfo(singleCarrierInfo);
mTestableLooper.processAllMessages();
mQSCarrierGroupController
.setOnSingleCarrierChangedListener(mOnSingleCarrierChangedListener);
reset(mOnSingleCarrierChangedListener);
mCallback.updateCarrierInfo(multiCarrierInfo);
mTestableLooper.processAllMessages();
verify(mOnSingleCarrierChangedListener).onSingleCarrierChanged(false);
mCallback.updateCarrierInfo(singleCarrierInfo);
mTestableLooper.processAllMessages();
verify(mOnSingleCarrierChangedListener).onSingleCarrierChanged(true);
}
@Test
public void testNoCallbackIfSingleCarrierDoesntChange() {
CarrierTextManager.CarrierTextCallbackInfo
singleCarrierInfo = new CarrierTextManager.CarrierTextCallbackInfo(
"",
new CharSequence[]{""},
true,
new int[]{0},
false /* airplaneMode */);
mCallback.updateCarrierInfo(singleCarrierInfo);
mTestableLooper.processAllMessages();
mQSCarrierGroupController
.setOnSingleCarrierChangedListener(mOnSingleCarrierChangedListener);
mCallback.updateCarrierInfo(singleCarrierInfo);
mTestableLooper.processAllMessages();
verify(mOnSingleCarrierChangedListener, never()).onSingleCarrierChanged(anyBoolean());
}
@Test
public void testNoCallbackIfMultiCarrierDoesntChange() {
CarrierTextManager.CarrierTextCallbackInfo
multiCarrierInfo = new CarrierTextManager.CarrierTextCallbackInfo(
"",
new CharSequence[]{"", ""},
true,
new int[]{0, 1},
false /* airplaneMode */);
mCallback.updateCarrierInfo(multiCarrierInfo);
mTestableLooper.processAllMessages();
mQSCarrierGroupController
.setOnSingleCarrierChangedListener(mOnSingleCarrierChangedListener);
mCallback.updateCarrierInfo(multiCarrierInfo);
mTestableLooper.processAllMessages();
verify(mOnSingleCarrierChangedListener, never()).onSingleCarrierChanged(anyBoolean());
}
private class FakeSlotIndexResolver implements QSCarrierGroupController.SlotIndexResolver {
public boolean overrideInvalid;
@Override
public int getSlotIndex(int subscriptionId) {
return overrideInvalid ? -1 : subscriptionId;
}
}
}

View File

@@ -16,6 +16,7 @@
package com.android.systemui.qs.carrier;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -23,6 +24,7 @@ import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.FeatureFlagUtils;
import android.view.LayoutInflater;
import android.view.View;
import androidx.test.filters.SmallTest;
@@ -64,25 +66,64 @@ public class QSCarrierTest extends SysuiTestCase {
public void testUpdateState_first() {
CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false, false);
assertTrue(mQSCarrier.updateState(c));
assertTrue(mQSCarrier.updateState(c, false));
}
@Test
public void testUpdateState_same() {
CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false, false);
assertTrue(mQSCarrier.updateState(c));
assertFalse(mQSCarrier.updateState(c));
assertTrue(mQSCarrier.updateState(c, false));
assertFalse(mQSCarrier.updateState(c, false));
}
@Test
public void testUpdateState_changed() {
CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false, false);
assertTrue(mQSCarrier.updateState(c));
assertTrue(mQSCarrier.updateState(c, false));
CellSignalState other = c.changeVisibility(false);
assertTrue(mQSCarrier.updateState(other));
assertTrue(mQSCarrier.updateState(other, false));
}
@Test
public void testUpdateState_singleCarrier_first() {
CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false, false);
assertTrue(mQSCarrier.updateState(c, true));
}
@Test
public void testUpdateState_singleCarrier_noShowIcon() {
CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false, false);
mQSCarrier.updateState(c, true);
assertEquals(View.GONE, mQSCarrier.getRSSIView().getVisibility());
}
@Test
public void testUpdateState_multiCarrier_showIcon() {
CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false, false);
mQSCarrier.updateState(c, false);
assertEquals(View.VISIBLE, mQSCarrier.getRSSIView().getVisibility());
}
@Test
public void testUpdateState_changeSingleMultiSingle() {
CellSignalState c = new CellSignalState(true, mSignalIconId, "", "", false, false);
mQSCarrier.updateState(c, true);
assertEquals(View.GONE, mQSCarrier.getRSSIView().getVisibility());
mQSCarrier.updateState(c, false);
assertEquals(View.VISIBLE, mQSCarrier.getRSSIView().getVisibility());
mQSCarrier.updateState(c, true);
assertEquals(View.GONE, mQSCarrier.getRSSIView().getVisibility());
}
}