Merge "Create Configuration overrides for MCC/MNC values" into tm-qpr-dev
This commit is contained in:
@@ -78,6 +78,9 @@ public class MobileStatusTracker {
|
||||
* Config the MobileStatusTracker to start or stop monitoring platform signals.
|
||||
*/
|
||||
public void setListening(boolean listening) {
|
||||
if (mListening == listening) {
|
||||
return;
|
||||
}
|
||||
mListening = listening;
|
||||
if (listening) {
|
||||
mPhone.registerTelephonyCallback(mReceiverHandler::post, mTelephonyCallback);
|
||||
|
||||
@@ -38,6 +38,7 @@ import com.android.settingslib.graph.SignalDrawable;
|
||||
import com.android.systemui.DualToneHandler;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
|
||||
import com.android.systemui.statusbar.phone.StatusBarIconController;
|
||||
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -64,6 +65,15 @@ public class StatusBarMobileView extends FrameLayout implements DarkReceiver,
|
||||
|
||||
/**
|
||||
* Designated constructor
|
||||
*
|
||||
* This view is special, in that it is the only view in SystemUI that allows for a configuration
|
||||
* override on a MCC/MNC-basis. This means that for every mobile view inflated, we have to
|
||||
* construct a context with that override, since the resource system doesn't have a way to
|
||||
* handle this for us.
|
||||
*
|
||||
* @param context A context with resources configured by MCC/MNC
|
||||
* @param slot The string key defining which slot this icon refers to. Always "mobile" for the
|
||||
* mobile icon
|
||||
*/
|
||||
public static StatusBarMobileView fromContext(
|
||||
Context context,
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.ui
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Configuration
|
||||
import android.os.Bundle
|
||||
import android.telephony.SubscriptionInfo
|
||||
import android.view.ContextThemeWrapper
|
||||
import com.android.systemui.Dumpable
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.demomode.DemoMode
|
||||
import com.android.systemui.demomode.DemoMode.COMMAND_NETWORK
|
||||
import com.android.systemui.demomode.DemoModeController
|
||||
import com.android.systemui.dump.DumpManager
|
||||
import com.android.systemui.statusbar.connectivity.NetworkController
|
||||
import com.android.systemui.statusbar.connectivity.SignalCallback
|
||||
import java.io.PrintWriter
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Every subscriptionId can have its own CarrierConfig associated with it, so we have to create our
|
||||
* own [Configuration] and track resources based on the full set of available mcc-mnc combinations.
|
||||
*
|
||||
* (for future reference: b/240555502 is the initiating bug for this)
|
||||
*/
|
||||
@SysUISingleton
|
||||
class MobileContextProvider
|
||||
@Inject
|
||||
constructor(
|
||||
networkController: NetworkController,
|
||||
dumpManager: DumpManager,
|
||||
private val demoModeController: DemoModeController,
|
||||
) : Dumpable, DemoMode {
|
||||
private val subscriptions = mutableMapOf<Int, SubscriptionInfo>()
|
||||
private val signalCallback =
|
||||
object : SignalCallback {
|
||||
override fun setSubs(subs: List<SubscriptionInfo>) {
|
||||
subscriptions.clear()
|
||||
subs.forEach { info -> subscriptions[info.subscriptionId] = info }
|
||||
}
|
||||
}
|
||||
|
||||
// These should always be null when not in demo mode
|
||||
private var demoMcc: Int? = null
|
||||
private var demoMnc: Int? = null
|
||||
|
||||
init {
|
||||
networkController.addCallback(signalCallback)
|
||||
dumpManager.registerDumpable(this)
|
||||
demoModeController.addCallback(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a context with the MCC/MNC [Configuration] values corresponding to this
|
||||
* subscriptionId
|
||||
*/
|
||||
fun getMobileContextForSub(subId: Int, context: Context): Context {
|
||||
if (demoModeController.isInDemoMode) {
|
||||
return createMobileContextForDemoMode(context)
|
||||
}
|
||||
|
||||
// Fail back to the given context if no sub exists
|
||||
val info = subscriptions[subId] ?: return context
|
||||
|
||||
return createCarrierConfigContext(context, info.mcc, info.mnc)
|
||||
}
|
||||
|
||||
/** For Demo mode (for now), just apply the same MCC/MNC override for all subIds */
|
||||
private fun createMobileContextForDemoMode(context: Context): Context {
|
||||
return createCarrierConfigContext(context, demoMcc ?: 0, demoMnc ?: 0)
|
||||
}
|
||||
|
||||
override fun dump(pw: PrintWriter, args: Array<out String>) {
|
||||
pw.println(
|
||||
"Subscriptions below will be inflated with a configuration context with " +
|
||||
"MCC/MNC overrides"
|
||||
)
|
||||
subscriptions.forEach { (subId, info) ->
|
||||
pw.println(" Subscription with subId($subId) with MCC/MNC(${info.mcc}/${info.mnc})")
|
||||
}
|
||||
pw.println(" MCC override: ${demoMcc ?: "(none)"}")
|
||||
pw.println(" MNC override: ${demoMnc ?: "(none)"}")
|
||||
}
|
||||
|
||||
override fun demoCommands(): List<String> {
|
||||
return listOf(COMMAND_NETWORK)
|
||||
}
|
||||
|
||||
override fun onDemoModeFinished() {
|
||||
demoMcc = null
|
||||
demoMnc = null
|
||||
}
|
||||
|
||||
override fun dispatchDemoCommand(command: String, args: Bundle) {
|
||||
val mccmnc = args.getString("mccmnc") ?: return
|
||||
// Only length 5/6 strings are valid
|
||||
if (!(mccmnc.length == 5 || mccmnc.length == 6)) {
|
||||
return
|
||||
}
|
||||
|
||||
// MCC is always the first 3 digits, and mnc is the last 2 or 3
|
||||
demoMcc = mccmnc.subSequence(0, 3).toString().toInt()
|
||||
demoMnc = mccmnc.subSequence(3, mccmnc.length).toString().toInt()
|
||||
}
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Creates a context based on this [SubscriptionInfo]'s MCC/MNC values, allowing the overlay
|
||||
* system to properly load different carrier's iconography
|
||||
*/
|
||||
private fun createCarrierConfigContext(context: Context, mcc: Int, mnc: Int): Context {
|
||||
// Copy the existing configuration
|
||||
val c = Configuration(context.resources.configuration)
|
||||
c.mcc = mcc
|
||||
c.mnc = mnc
|
||||
|
||||
return ContextThemeWrapper(context, context.theme).also { ctx ->
|
||||
ctx.applyOverrideConfiguration(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.systemui.statusbar.phone;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.os.Bundle;
|
||||
@@ -29,13 +31,13 @@ import android.widget.LinearLayout;
|
||||
import com.android.internal.statusbar.StatusBarIcon;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.demomode.DemoMode;
|
||||
import com.android.systemui.flags.FeatureFlags;
|
||||
import com.android.systemui.plugins.DarkIconDispatcher;
|
||||
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
|
||||
import com.android.systemui.statusbar.StatusBarIconView;
|
||||
import com.android.systemui.statusbar.StatusBarMobileView;
|
||||
import com.android.systemui.statusbar.StatusBarWifiView;
|
||||
import com.android.systemui.statusbar.StatusIconDisplayable;
|
||||
import com.android.systemui.statusbar.connectivity.ui.MobileContextProvider;
|
||||
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
|
||||
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
|
||||
|
||||
@@ -49,7 +51,6 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da
|
||||
private final LinearLayout mStatusIcons;
|
||||
private final ArrayList<StatusBarMobileView> mMobileViews = new ArrayList<>();
|
||||
private final int mIconSize;
|
||||
private final FeatureFlags mFeatureFlags;
|
||||
|
||||
private StatusBarWifiView mWifiView;
|
||||
private boolean mDemoMode;
|
||||
@@ -57,14 +58,12 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da
|
||||
|
||||
public DemoStatusIcons(
|
||||
LinearLayout statusIcons,
|
||||
int iconSize,
|
||||
FeatureFlags featureFlags
|
||||
int iconSize
|
||||
) {
|
||||
super(statusIcons.getContext());
|
||||
mStatusIcons = statusIcons;
|
||||
mIconSize = iconSize;
|
||||
mColor = DarkIconDispatcher.DEFAULT_ICON_TINT;
|
||||
mFeatureFlags = featureFlags;
|
||||
|
||||
if (statusIcons instanceof StatusIconContainer) {
|
||||
setShouldRestrictIcons(((StatusIconContainer) statusIcons).isRestrictingIcons());
|
||||
@@ -253,9 +252,13 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da
|
||||
}
|
||||
}
|
||||
|
||||
public void addMobileView(MobileIconState state) {
|
||||
/**
|
||||
* Add a new mobile icon view
|
||||
*/
|
||||
public void addMobileView(MobileIconState state, Context mobileContext) {
|
||||
Log.d(TAG, "addMobileView: ");
|
||||
StatusBarMobileView view = StatusBarMobileView.fromContext(mContext, state.slot);
|
||||
StatusBarMobileView view = StatusBarMobileView
|
||||
.fromContext(mobileContext, state.slot);
|
||||
|
||||
view.applyMobileState(state);
|
||||
view.setStaticDrawableColor(mColor);
|
||||
@@ -265,19 +268,24 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da
|
||||
addView(view, getChildCount(), createLayoutParams());
|
||||
}
|
||||
|
||||
public void updateMobileState(MobileIconState state) {
|
||||
Log.d(TAG, "updateMobileState: ");
|
||||
// If the view for this subId exists already, use it
|
||||
/**
|
||||
* Apply an update to a mobile icon view for the given {@link MobileIconState}. For
|
||||
* compatibility with {@link MobileContextProvider}, we have to recreate the view every time we
|
||||
* update it, since the context (and thus the {@link Configuration}) may have changed
|
||||
*/
|
||||
public void updateMobileState(MobileIconState state, Context mobileContext) {
|
||||
Log.d(TAG, "updateMobileState: " + state);
|
||||
|
||||
// The mobile config provided by MobileContextProvider could have changed; always recreate
|
||||
for (int i = 0; i < mMobileViews.size(); i++) {
|
||||
StatusBarMobileView view = mMobileViews.get(i);
|
||||
if (view.getState().subId == state.subId) {
|
||||
view.applyMobileState(state);
|
||||
return;
|
||||
removeView(view);
|
||||
}
|
||||
}
|
||||
|
||||
// Else we have to add it
|
||||
addMobileView(state);
|
||||
// Add the replacement or new icon
|
||||
addMobileView(state, mobileContext);
|
||||
}
|
||||
|
||||
public void onRemoveIcon(StatusIconDisplayable view) {
|
||||
|
||||
@@ -36,7 +36,6 @@ import com.android.internal.statusbar.StatusBarIcon;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.dagger.SysUISingleton;
|
||||
import com.android.systemui.demomode.DemoModeCommandReceiver;
|
||||
import com.android.systemui.flags.FeatureFlags;
|
||||
import com.android.systemui.plugins.DarkIconDispatcher;
|
||||
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
|
||||
import com.android.systemui.statusbar.BaseStatusBarWifiView;
|
||||
@@ -44,6 +43,7 @@ import com.android.systemui.statusbar.StatusBarIconView;
|
||||
import com.android.systemui.statusbar.StatusBarMobileView;
|
||||
import com.android.systemui.statusbar.StatusBarWifiView;
|
||||
import com.android.systemui.statusbar.StatusIconDisplayable;
|
||||
import com.android.systemui.statusbar.connectivity.ui.MobileContextProvider;
|
||||
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.CallIndicatorIconState;
|
||||
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
|
||||
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
|
||||
@@ -70,6 +70,7 @@ public interface StatusBarIconController {
|
||||
void addIconGroup(IconManager iconManager);
|
||||
/** */
|
||||
void removeIconGroup(IconManager iconManager);
|
||||
|
||||
/** Refresh the state of an IconManager by recreating the views */
|
||||
void refreshIconGroup(IconManager iconManager);
|
||||
/** */
|
||||
@@ -82,21 +83,25 @@ public interface StatusBarIconController {
|
||||
void setSignalIcon(String slot, WifiIconState state);
|
||||
/** */
|
||||
void setMobileIcons(String slot, List<MobileIconState> states);
|
||||
|
||||
/**
|
||||
* Display the no calling & SMS icons.
|
||||
*/
|
||||
void setCallStrengthIcons(String slot, List<CallIndicatorIconState> states);
|
||||
|
||||
/**
|
||||
* Display the no calling & SMS icons.
|
||||
*/
|
||||
void setNoCallingIcons(String slot, List<CallIndicatorIconState> states);
|
||||
|
||||
public void setIconVisibility(String slot, boolean b);
|
||||
|
||||
/**
|
||||
* Sets the live region mode for the icon
|
||||
* @see android.view.View#setAccessibilityLiveRegion(int)
|
||||
* @param slot Icon slot to set region for
|
||||
*
|
||||
* @param slot Icon slot to set region for
|
||||
* @param accessibilityLiveRegion live region mode for the icon
|
||||
* @see android.view.View#setAccessibilityLiveRegion(int)
|
||||
*/
|
||||
void setIconAccessibilityLiveRegion(String slot, int accessibilityLiveRegion);
|
||||
|
||||
@@ -115,8 +120,8 @@ public interface StatusBarIconController {
|
||||
static ArraySet<String> getIconHideList(Context context, String hideListStr) {
|
||||
ArraySet<String> ret = new ArraySet<>();
|
||||
String[] hideList = hideListStr == null
|
||||
? context.getResources().getStringArray(R.array.config_statusBarIconsToExclude)
|
||||
: hideListStr.split(",");
|
||||
? context.getResources().getStringArray(R.array.config_statusBarIconsToExclude)
|
||||
: hideListStr.split(",");
|
||||
for (String slot : hideList) {
|
||||
if (!TextUtils.isEmpty(slot)) {
|
||||
ret.add(slot);
|
||||
@@ -134,11 +139,14 @@ public interface StatusBarIconController {
|
||||
|
||||
public DarkIconManager(
|
||||
LinearLayout linearLayout,
|
||||
FeatureFlags featureFlags,
|
||||
StatusBarPipelineFlags statusBarPipelineFlags,
|
||||
Provider<WifiViewModel> wifiViewModelProvider,
|
||||
MobileContextProvider mobileContextProvider,
|
||||
DarkIconDispatcher darkIconDispatcher) {
|
||||
super(linearLayout, featureFlags, statusBarPipelineFlags, wifiViewModelProvider);
|
||||
super(linearLayout,
|
||||
statusBarPipelineFlags,
|
||||
wifiViewModelProvider,
|
||||
mobileContextProvider);
|
||||
mIconHPadding = mContext.getResources().getDimensionPixelSize(
|
||||
R.dimen.status_bar_icon_padding);
|
||||
mDarkIconDispatcher = darkIconDispatcher;
|
||||
@@ -195,41 +203,49 @@ public interface StatusBarIconController {
|
||||
|
||||
@SysUISingleton
|
||||
public static class Factory {
|
||||
private final FeatureFlags mFeatureFlags;
|
||||
private final StatusBarPipelineFlags mStatusBarPipelineFlags;
|
||||
private final Provider<WifiViewModel> mWifiViewModelProvider;
|
||||
private final MobileContextProvider mMobileContextProvider;
|
||||
private final DarkIconDispatcher mDarkIconDispatcher;
|
||||
|
||||
@Inject
|
||||
public Factory(
|
||||
FeatureFlags featureFlags,
|
||||
StatusBarPipelineFlags statusBarPipelineFlags,
|
||||
Provider<WifiViewModel> wifiViewModelProvider,
|
||||
MobileContextProvider mobileContextProvider,
|
||||
DarkIconDispatcher darkIconDispatcher) {
|
||||
mFeatureFlags = featureFlags;
|
||||
mStatusBarPipelineFlags = statusBarPipelineFlags;
|
||||
mWifiViewModelProvider = wifiViewModelProvider;
|
||||
mMobileContextProvider = mobileContextProvider;
|
||||
mDarkIconDispatcher = darkIconDispatcher;
|
||||
}
|
||||
|
||||
public DarkIconManager create(LinearLayout group) {
|
||||
return new DarkIconManager(
|
||||
group, mFeatureFlags, mStatusBarPipelineFlags, mWifiViewModelProvider,
|
||||
group,
|
||||
mStatusBarPipelineFlags,
|
||||
mWifiViewModelProvider,
|
||||
mMobileContextProvider,
|
||||
mDarkIconDispatcher);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** */
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class TintedIconManager extends IconManager {
|
||||
private int mColor;
|
||||
|
||||
public TintedIconManager(
|
||||
ViewGroup group,
|
||||
FeatureFlags featureFlags,
|
||||
StatusBarPipelineFlags statusBarPipelineFlags,
|
||||
Provider<WifiViewModel> wifiViewModelProvider) {
|
||||
super(group, featureFlags, statusBarPipelineFlags, wifiViewModelProvider);
|
||||
Provider<WifiViewModel> wifiViewModelProvider,
|
||||
MobileContextProvider mobileContextProvider) {
|
||||
super(group,
|
||||
statusBarPipelineFlags,
|
||||
wifiViewModelProvider,
|
||||
mobileContextProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -261,23 +277,26 @@ public interface StatusBarIconController {
|
||||
|
||||
@SysUISingleton
|
||||
public static class Factory {
|
||||
private final FeatureFlags mFeatureFlags;
|
||||
private final StatusBarPipelineFlags mStatusBarPipelineFlags;
|
||||
private final Provider<WifiViewModel> mWifiViewModelProvider;
|
||||
private final MobileContextProvider mMobileContextProvider;
|
||||
|
||||
@Inject
|
||||
public Factory(
|
||||
FeatureFlags featureFlags,
|
||||
StatusBarPipelineFlags statusBarPipelineFlags,
|
||||
Provider<WifiViewModel> wifiViewModelProvider) {
|
||||
mFeatureFlags = featureFlags;
|
||||
Provider<WifiViewModel> wifiViewModelProvider,
|
||||
MobileContextProvider mobileContextProvider) {
|
||||
mStatusBarPipelineFlags = statusBarPipelineFlags;
|
||||
mWifiViewModelProvider = wifiViewModelProvider;
|
||||
mMobileContextProvider = mobileContextProvider;
|
||||
}
|
||||
|
||||
public TintedIconManager create(ViewGroup group) {
|
||||
return new TintedIconManager(
|
||||
group, mFeatureFlags, mStatusBarPipelineFlags, mWifiViewModelProvider);
|
||||
group,
|
||||
mStatusBarPipelineFlags,
|
||||
mWifiViewModelProvider,
|
||||
mMobileContextProvider);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -287,9 +306,9 @@ public interface StatusBarIconController {
|
||||
*/
|
||||
class IconManager implements DemoModeCommandReceiver {
|
||||
protected final ViewGroup mGroup;
|
||||
private final FeatureFlags mFeatureFlags;
|
||||
private final StatusBarPipelineFlags mStatusBarPipelineFlags;
|
||||
private final Provider<WifiViewModel> mWifiViewModelProvider;
|
||||
private final MobileContextProvider mMobileContextProvider;
|
||||
protected final Context mContext;
|
||||
protected final int mIconSize;
|
||||
// Whether or not these icons show up in dumpsys
|
||||
@@ -305,13 +324,13 @@ public interface StatusBarIconController {
|
||||
|
||||
public IconManager(
|
||||
ViewGroup group,
|
||||
FeatureFlags featureFlags,
|
||||
StatusBarPipelineFlags statusBarPipelineFlags,
|
||||
Provider<WifiViewModel> wifiViewModelProvider) {
|
||||
Provider<WifiViewModel> wifiViewModelProvider,
|
||||
MobileContextProvider mobileContextProvider) {
|
||||
mGroup = group;
|
||||
mFeatureFlags = featureFlags;
|
||||
mStatusBarPipelineFlags = statusBarPipelineFlags;
|
||||
mWifiViewModelProvider = wifiViewModelProvider;
|
||||
mMobileContextProvider = mobileContextProvider;
|
||||
mContext = group.getContext();
|
||||
mIconSize = mContext.getResources().getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.status_bar_icon_size);
|
||||
@@ -403,12 +422,15 @@ public interface StatusBarIconController {
|
||||
|
||||
@VisibleForTesting
|
||||
protected StatusBarMobileView addMobileIcon(int index, String slot, MobileIconState state) {
|
||||
StatusBarMobileView view = onCreateStatusBarMobileView(slot);
|
||||
// Use the `subId` field as a key to query for the correct context
|
||||
StatusBarMobileView view = onCreateStatusBarMobileView(state.subId, slot);
|
||||
view.applyMobileState(state);
|
||||
mGroup.addView(view, index, onCreateLayoutParams());
|
||||
|
||||
if (mIsInDemoMode) {
|
||||
mDemoStatusIcons.addMobileView(state);
|
||||
Context mobileContext = mMobileContextProvider
|
||||
.getMobileContextForSub(state.subId, mContext);
|
||||
mDemoStatusIcons.addMobileView(state, mobileContext);
|
||||
}
|
||||
return view;
|
||||
}
|
||||
@@ -427,8 +449,10 @@ public interface StatusBarIconController {
|
||||
mContext, slot, mWifiViewModelProvider.get());
|
||||
}
|
||||
|
||||
private StatusBarMobileView onCreateStatusBarMobileView(String slot) {
|
||||
StatusBarMobileView view = StatusBarMobileView.fromContext(mContext, slot);
|
||||
private StatusBarMobileView onCreateStatusBarMobileView(int subId, String slot) {
|
||||
Context mobileContext = mMobileContextProvider.getMobileContextForSub(subId, mContext);
|
||||
StatusBarMobileView view = StatusBarMobileView
|
||||
.fromContext(mobileContext, slot);
|
||||
return view;
|
||||
}
|
||||
|
||||
@@ -516,7 +540,9 @@ public interface StatusBarIconController {
|
||||
}
|
||||
|
||||
if (mIsInDemoMode) {
|
||||
mDemoStatusIcons.updateMobileState(state);
|
||||
Context mobileContext = mMobileContextProvider
|
||||
.getMobileContextForSub(state.subId, mContext);
|
||||
mDemoStatusIcons.updateMobileState(state, mobileContext);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -553,7 +579,7 @@ public interface StatusBarIconController {
|
||||
}
|
||||
|
||||
protected DemoStatusIcons createDemoStatusIcons() {
|
||||
return new DemoStatusIcons((LinearLayout) mGroup, mIconSize, mFeatureFlags);
|
||||
return new DemoStatusIcons((LinearLayout) mGroup, mIconSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.ui
|
||||
|
||||
import android.telephony.SubscriptionInfo
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.demomode.DemoModeController
|
||||
import com.android.systemui.dump.DumpManager
|
||||
import com.android.systemui.statusbar.connectivity.NetworkController
|
||||
import com.android.systemui.statusbar.connectivity.SignalCallback
|
||||
import com.android.systemui.util.mockito.mock
|
||||
import com.android.systemui.util.mockito.withArgCaptor
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.Mockito.`when` as whenever
|
||||
import org.mockito.MockitoAnnotations
|
||||
|
||||
@SmallTest
|
||||
class MobileContextProviderTest : SysuiTestCase() {
|
||||
@Mock private lateinit var networkController: NetworkController
|
||||
@Mock private lateinit var dumpManager: DumpManager
|
||||
@Mock private lateinit var demoModeController: DemoModeController
|
||||
|
||||
private lateinit var provider: MobileContextProvider
|
||||
private lateinit var signalCallback: SignalCallback
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
provider =
|
||||
MobileContextProvider(
|
||||
networkController,
|
||||
dumpManager,
|
||||
demoModeController,
|
||||
)
|
||||
|
||||
signalCallback = withArgCaptor { verify(networkController).addCallback(capture()) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test_oneSubscription_contextHasMccMnc() {
|
||||
// GIVEN there is one SubscriptionInfo
|
||||
signalCallback.setSubs(listOf(SUB_1))
|
||||
|
||||
// WHEN we ask for a mobile context
|
||||
val ctx = provider.getMobileContextForSub(SUB_1_ID, context)
|
||||
|
||||
// THEN the configuration of that context reflect this subscription's MCC/MNC override
|
||||
val config = ctx.resources.configuration
|
||||
assertThat(config.mcc).isEqualTo(SUB_1_MCC)
|
||||
assertThat(config.mnc).isEqualTo(SUB_1_MNC)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test_twoSubscriptions_eachContextReflectsMccMnc() {
|
||||
// GIVEN there are two SubscriptionInfos
|
||||
signalCallback.setSubs(listOf(SUB_1, SUB_2))
|
||||
|
||||
// WHEN we ask for a mobile context for each sub
|
||||
val ctx1 = provider.getMobileContextForSub(SUB_1_ID, context)
|
||||
val ctx2 = provider.getMobileContextForSub(SUB_2_ID, context)
|
||||
|
||||
// THEN the configuration of each context reflect this subscription's MCC/MNC override
|
||||
val config1 = ctx1.resources.configuration
|
||||
assertThat(config1.mcc).isEqualTo(SUB_1_MCC)
|
||||
assertThat(config1.mnc).isEqualTo(SUB_1_MNC)
|
||||
|
||||
val config2 = ctx2.resources.configuration
|
||||
assertThat(config2.mcc).isEqualTo(SUB_2_MCC)
|
||||
assertThat(config2.mnc).isEqualTo(SUB_2_MNC)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test_requestingContextForNonexistentSubscription_returnsGivenContext() {
|
||||
// GIVEN no SubscriptionInfos
|
||||
signalCallback.setSubs(listOf())
|
||||
|
||||
// WHEN we ask for a mobile context for an unknown subscription
|
||||
val ctx = provider.getMobileContextForSub(SUB_1_ID, context)
|
||||
|
||||
// THEN we get the original context back
|
||||
assertThat(ctx).isEqualTo(context)
|
||||
}
|
||||
|
||||
private val SUB_1_ID = 1
|
||||
private val SUB_1_MCC = 123
|
||||
private val SUB_1_MNC = 456
|
||||
private val SUB_1 =
|
||||
mock<SubscriptionInfo>().also {
|
||||
whenever(it.subscriptionId).thenReturn(SUB_1_ID)
|
||||
whenever(it.mcc).thenReturn(SUB_1_MCC)
|
||||
whenever(it.mnc).thenReturn(SUB_1_MNC)
|
||||
}
|
||||
|
||||
private val SUB_2_ID = 2
|
||||
private val SUB_2_MCC = 666
|
||||
private val SUB_2_MNC = 777
|
||||
private val SUB_2 =
|
||||
mock<SubscriptionInfo>().also {
|
||||
whenever(it.subscriptionId).thenReturn(SUB_2_ID)
|
||||
whenever(it.mcc).thenReturn(SUB_2_MCC)
|
||||
whenever(it.mnc).thenReturn(SUB_2_MNC)
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,10 @@ import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_WIFI
|
||||
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper.RunWithLooper;
|
||||
@@ -30,12 +33,12 @@ import android.widget.LinearLayout;
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.internal.statusbar.StatusBarIcon;
|
||||
import com.android.systemui.flags.FeatureFlags;
|
||||
import com.android.systemui.plugins.DarkIconDispatcher;
|
||||
import com.android.systemui.statusbar.StatusBarIconView;
|
||||
import com.android.systemui.statusbar.StatusBarMobileView;
|
||||
import com.android.systemui.statusbar.StatusBarWifiView;
|
||||
import com.android.systemui.statusbar.StatusIconDisplayable;
|
||||
import com.android.systemui.statusbar.connectivity.ui.MobileContextProvider;
|
||||
import com.android.systemui.statusbar.phone.StatusBarIconController.DarkIconManager;
|
||||
import com.android.systemui.statusbar.phone.StatusBarIconController.IconManager;
|
||||
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
|
||||
@@ -55,15 +58,19 @@ import javax.inject.Provider;
|
||||
@SmallTest
|
||||
public class StatusBarIconControllerTest extends LeakCheckedTest {
|
||||
|
||||
private MobileContextProvider mMobileContextProvider = mock(MobileContextProvider.class);
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
|
||||
// For testing, ignore context overrides
|
||||
when(mMobileContextProvider.getMobileContextForSub(anyInt(), any())).thenReturn(mContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetCalledOnAdd_IconManager() {
|
||||
LinearLayout layout = new LinearLayout(mContext);
|
||||
TestIconManager manager = new TestIconManager(layout);
|
||||
TestIconManager manager = new TestIconManager(layout, mMobileContextProvider);
|
||||
testCallOnAdd_forManager(manager);
|
||||
}
|
||||
|
||||
@@ -72,9 +79,9 @@ public class StatusBarIconControllerTest extends LeakCheckedTest {
|
||||
LinearLayout layout = new LinearLayout(mContext);
|
||||
TestDarkIconManager manager = new TestDarkIconManager(
|
||||
layout,
|
||||
mock(FeatureFlags.class),
|
||||
mock(StatusBarPipelineFlags.class),
|
||||
() -> mock(WifiViewModel.class),
|
||||
mMobileContextProvider,
|
||||
mock(DarkIconDispatcher.class));
|
||||
testCallOnAdd_forManager(manager);
|
||||
}
|
||||
@@ -114,11 +121,14 @@ public class StatusBarIconControllerTest extends LeakCheckedTest {
|
||||
|
||||
TestDarkIconManager(
|
||||
LinearLayout group,
|
||||
FeatureFlags featureFlags,
|
||||
StatusBarPipelineFlags statusBarPipelineFlags,
|
||||
Provider<WifiViewModel> wifiViewModelProvider,
|
||||
MobileContextProvider contextProvider,
|
||||
DarkIconDispatcher darkIconDispatcher) {
|
||||
super(group, featureFlags, statusBarPipelineFlags, wifiViewModelProvider,
|
||||
super(group,
|
||||
statusBarPipelineFlags,
|
||||
wifiViewModelProvider,
|
||||
contextProvider,
|
||||
darkIconDispatcher);
|
||||
}
|
||||
|
||||
@@ -153,11 +163,11 @@ public class StatusBarIconControllerTest extends LeakCheckedTest {
|
||||
}
|
||||
|
||||
private static class TestIconManager extends IconManager implements TestableIconManager {
|
||||
TestIconManager(ViewGroup group) {
|
||||
TestIconManager(ViewGroup group, MobileContextProvider contextProvider) {
|
||||
super(group,
|
||||
mock(FeatureFlags.class),
|
||||
mock(StatusBarPipelineFlags.class),
|
||||
() -> mock(WifiViewModel.class));
|
||||
() -> mock(WifiViewModel.class),
|
||||
contextProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user