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.
|
* Config the MobileStatusTracker to start or stop monitoring platform signals.
|
||||||
*/
|
*/
|
||||||
public void setListening(boolean listening) {
|
public void setListening(boolean listening) {
|
||||||
|
if (mListening == listening) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
mListening = listening;
|
mListening = listening;
|
||||||
if (listening) {
|
if (listening) {
|
||||||
mPhone.registerTelephonyCallback(mReceiverHandler::post, mTelephonyCallback);
|
mPhone.registerTelephonyCallback(mReceiverHandler::post, mTelephonyCallback);
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import com.android.settingslib.graph.SignalDrawable;
|
|||||||
import com.android.systemui.DualToneHandler;
|
import com.android.systemui.DualToneHandler;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
|
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
|
||||||
|
import com.android.systemui.statusbar.phone.StatusBarIconController;
|
||||||
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
|
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -64,6 +65,15 @@ public class StatusBarMobileView extends FrameLayout implements DarkReceiver,
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Designated constructor
|
* 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(
|
public static StatusBarMobileView fromContext(
|
||||||
Context context,
|
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;
|
package com.android.systemui.statusbar.phone;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.Configuration;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.graphics.drawable.Icon;
|
import android.graphics.drawable.Icon;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@@ -29,13 +31,13 @@ import android.widget.LinearLayout;
|
|||||||
import com.android.internal.statusbar.StatusBarIcon;
|
import com.android.internal.statusbar.StatusBarIcon;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.demomode.DemoMode;
|
import com.android.systemui.demomode.DemoMode;
|
||||||
import com.android.systemui.flags.FeatureFlags;
|
|
||||||
import com.android.systemui.plugins.DarkIconDispatcher;
|
import com.android.systemui.plugins.DarkIconDispatcher;
|
||||||
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
|
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
|
||||||
import com.android.systemui.statusbar.StatusBarIconView;
|
import com.android.systemui.statusbar.StatusBarIconView;
|
||||||
import com.android.systemui.statusbar.StatusBarMobileView;
|
import com.android.systemui.statusbar.StatusBarMobileView;
|
||||||
import com.android.systemui.statusbar.StatusBarWifiView;
|
import com.android.systemui.statusbar.StatusBarWifiView;
|
||||||
import com.android.systemui.statusbar.StatusIconDisplayable;
|
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.MobileIconState;
|
||||||
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
|
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 LinearLayout mStatusIcons;
|
||||||
private final ArrayList<StatusBarMobileView> mMobileViews = new ArrayList<>();
|
private final ArrayList<StatusBarMobileView> mMobileViews = new ArrayList<>();
|
||||||
private final int mIconSize;
|
private final int mIconSize;
|
||||||
private final FeatureFlags mFeatureFlags;
|
|
||||||
|
|
||||||
private StatusBarWifiView mWifiView;
|
private StatusBarWifiView mWifiView;
|
||||||
private boolean mDemoMode;
|
private boolean mDemoMode;
|
||||||
@@ -57,14 +58,12 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da
|
|||||||
|
|
||||||
public DemoStatusIcons(
|
public DemoStatusIcons(
|
||||||
LinearLayout statusIcons,
|
LinearLayout statusIcons,
|
||||||
int iconSize,
|
int iconSize
|
||||||
FeatureFlags featureFlags
|
|
||||||
) {
|
) {
|
||||||
super(statusIcons.getContext());
|
super(statusIcons.getContext());
|
||||||
mStatusIcons = statusIcons;
|
mStatusIcons = statusIcons;
|
||||||
mIconSize = iconSize;
|
mIconSize = iconSize;
|
||||||
mColor = DarkIconDispatcher.DEFAULT_ICON_TINT;
|
mColor = DarkIconDispatcher.DEFAULT_ICON_TINT;
|
||||||
mFeatureFlags = featureFlags;
|
|
||||||
|
|
||||||
if (statusIcons instanceof StatusIconContainer) {
|
if (statusIcons instanceof StatusIconContainer) {
|
||||||
setShouldRestrictIcons(((StatusIconContainer) statusIcons).isRestrictingIcons());
|
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: ");
|
Log.d(TAG, "addMobileView: ");
|
||||||
StatusBarMobileView view = StatusBarMobileView.fromContext(mContext, state.slot);
|
StatusBarMobileView view = StatusBarMobileView
|
||||||
|
.fromContext(mobileContext, state.slot);
|
||||||
|
|
||||||
view.applyMobileState(state);
|
view.applyMobileState(state);
|
||||||
view.setStaticDrawableColor(mColor);
|
view.setStaticDrawableColor(mColor);
|
||||||
@@ -265,19 +268,24 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da
|
|||||||
addView(view, getChildCount(), createLayoutParams());
|
addView(view, getChildCount(), createLayoutParams());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateMobileState(MobileIconState state) {
|
/**
|
||||||
Log.d(TAG, "updateMobileState: ");
|
* Apply an update to a mobile icon view for the given {@link MobileIconState}. For
|
||||||
// If the view for this subId exists already, use it
|
* 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++) {
|
for (int i = 0; i < mMobileViews.size(); i++) {
|
||||||
StatusBarMobileView view = mMobileViews.get(i);
|
StatusBarMobileView view = mMobileViews.get(i);
|
||||||
if (view.getState().subId == state.subId) {
|
if (view.getState().subId == state.subId) {
|
||||||
view.applyMobileState(state);
|
removeView(view);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Else we have to add it
|
// Add the replacement or new icon
|
||||||
addMobileView(state);
|
addMobileView(state, mobileContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onRemoveIcon(StatusIconDisplayable view) {
|
public void onRemoveIcon(StatusIconDisplayable view) {
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ import com.android.internal.statusbar.StatusBarIcon;
|
|||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.dagger.SysUISingleton;
|
import com.android.systemui.dagger.SysUISingleton;
|
||||||
import com.android.systemui.demomode.DemoModeCommandReceiver;
|
import com.android.systemui.demomode.DemoModeCommandReceiver;
|
||||||
import com.android.systemui.flags.FeatureFlags;
|
|
||||||
import com.android.systemui.plugins.DarkIconDispatcher;
|
import com.android.systemui.plugins.DarkIconDispatcher;
|
||||||
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
|
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
|
||||||
import com.android.systemui.statusbar.BaseStatusBarWifiView;
|
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.StatusBarMobileView;
|
||||||
import com.android.systemui.statusbar.StatusBarWifiView;
|
import com.android.systemui.statusbar.StatusBarWifiView;
|
||||||
import com.android.systemui.statusbar.StatusIconDisplayable;
|
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.CallIndicatorIconState;
|
||||||
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
|
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
|
||||||
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
|
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
|
||||||
@@ -70,6 +70,7 @@ public interface StatusBarIconController {
|
|||||||
void addIconGroup(IconManager iconManager);
|
void addIconGroup(IconManager iconManager);
|
||||||
/** */
|
/** */
|
||||||
void removeIconGroup(IconManager iconManager);
|
void removeIconGroup(IconManager iconManager);
|
||||||
|
|
||||||
/** Refresh the state of an IconManager by recreating the views */
|
/** Refresh the state of an IconManager by recreating the views */
|
||||||
void refreshIconGroup(IconManager iconManager);
|
void refreshIconGroup(IconManager iconManager);
|
||||||
/** */
|
/** */
|
||||||
@@ -82,21 +83,25 @@ public interface StatusBarIconController {
|
|||||||
void setSignalIcon(String slot, WifiIconState state);
|
void setSignalIcon(String slot, WifiIconState state);
|
||||||
/** */
|
/** */
|
||||||
void setMobileIcons(String slot, List<MobileIconState> states);
|
void setMobileIcons(String slot, List<MobileIconState> states);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display the no calling & SMS icons.
|
* Display the no calling & SMS icons.
|
||||||
*/
|
*/
|
||||||
void setCallStrengthIcons(String slot, List<CallIndicatorIconState> states);
|
void setCallStrengthIcons(String slot, List<CallIndicatorIconState> states);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display the no calling & SMS icons.
|
* Display the no calling & SMS icons.
|
||||||
*/
|
*/
|
||||||
void setNoCallingIcons(String slot, List<CallIndicatorIconState> states);
|
void setNoCallingIcons(String slot, List<CallIndicatorIconState> states);
|
||||||
|
|
||||||
public void setIconVisibility(String slot, boolean b);
|
public void setIconVisibility(String slot, boolean b);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the live region mode for the icon
|
* 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
|
* @param accessibilityLiveRegion live region mode for the icon
|
||||||
|
* @see android.view.View#setAccessibilityLiveRegion(int)
|
||||||
*/
|
*/
|
||||||
void setIconAccessibilityLiveRegion(String slot, int accessibilityLiveRegion);
|
void setIconAccessibilityLiveRegion(String slot, int accessibilityLiveRegion);
|
||||||
|
|
||||||
@@ -134,11 +139,14 @@ public interface StatusBarIconController {
|
|||||||
|
|
||||||
public DarkIconManager(
|
public DarkIconManager(
|
||||||
LinearLayout linearLayout,
|
LinearLayout linearLayout,
|
||||||
FeatureFlags featureFlags,
|
|
||||||
StatusBarPipelineFlags statusBarPipelineFlags,
|
StatusBarPipelineFlags statusBarPipelineFlags,
|
||||||
Provider<WifiViewModel> wifiViewModelProvider,
|
Provider<WifiViewModel> wifiViewModelProvider,
|
||||||
|
MobileContextProvider mobileContextProvider,
|
||||||
DarkIconDispatcher darkIconDispatcher) {
|
DarkIconDispatcher darkIconDispatcher) {
|
||||||
super(linearLayout, featureFlags, statusBarPipelineFlags, wifiViewModelProvider);
|
super(linearLayout,
|
||||||
|
statusBarPipelineFlags,
|
||||||
|
wifiViewModelProvider,
|
||||||
|
mobileContextProvider);
|
||||||
mIconHPadding = mContext.getResources().getDimensionPixelSize(
|
mIconHPadding = mContext.getResources().getDimensionPixelSize(
|
||||||
R.dimen.status_bar_icon_padding);
|
R.dimen.status_bar_icon_padding);
|
||||||
mDarkIconDispatcher = darkIconDispatcher;
|
mDarkIconDispatcher = darkIconDispatcher;
|
||||||
@@ -195,41 +203,49 @@ public interface StatusBarIconController {
|
|||||||
|
|
||||||
@SysUISingleton
|
@SysUISingleton
|
||||||
public static class Factory {
|
public static class Factory {
|
||||||
private final FeatureFlags mFeatureFlags;
|
|
||||||
private final StatusBarPipelineFlags mStatusBarPipelineFlags;
|
private final StatusBarPipelineFlags mStatusBarPipelineFlags;
|
||||||
private final Provider<WifiViewModel> mWifiViewModelProvider;
|
private final Provider<WifiViewModel> mWifiViewModelProvider;
|
||||||
|
private final MobileContextProvider mMobileContextProvider;
|
||||||
private final DarkIconDispatcher mDarkIconDispatcher;
|
private final DarkIconDispatcher mDarkIconDispatcher;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public Factory(
|
public Factory(
|
||||||
FeatureFlags featureFlags,
|
|
||||||
StatusBarPipelineFlags statusBarPipelineFlags,
|
StatusBarPipelineFlags statusBarPipelineFlags,
|
||||||
Provider<WifiViewModel> wifiViewModelProvider,
|
Provider<WifiViewModel> wifiViewModelProvider,
|
||||||
|
MobileContextProvider mobileContextProvider,
|
||||||
DarkIconDispatcher darkIconDispatcher) {
|
DarkIconDispatcher darkIconDispatcher) {
|
||||||
mFeatureFlags = featureFlags;
|
|
||||||
mStatusBarPipelineFlags = statusBarPipelineFlags;
|
mStatusBarPipelineFlags = statusBarPipelineFlags;
|
||||||
mWifiViewModelProvider = wifiViewModelProvider;
|
mWifiViewModelProvider = wifiViewModelProvider;
|
||||||
|
mMobileContextProvider = mobileContextProvider;
|
||||||
mDarkIconDispatcher = darkIconDispatcher;
|
mDarkIconDispatcher = darkIconDispatcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DarkIconManager create(LinearLayout group) {
|
public DarkIconManager create(LinearLayout group) {
|
||||||
return new DarkIconManager(
|
return new DarkIconManager(
|
||||||
group, mFeatureFlags, mStatusBarPipelineFlags, mWifiViewModelProvider,
|
group,
|
||||||
|
mStatusBarPipelineFlags,
|
||||||
|
mWifiViewModelProvider,
|
||||||
|
mMobileContextProvider,
|
||||||
mDarkIconDispatcher);
|
mDarkIconDispatcher);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** */
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
class TintedIconManager extends IconManager {
|
class TintedIconManager extends IconManager {
|
||||||
private int mColor;
|
private int mColor;
|
||||||
|
|
||||||
public TintedIconManager(
|
public TintedIconManager(
|
||||||
ViewGroup group,
|
ViewGroup group,
|
||||||
FeatureFlags featureFlags,
|
|
||||||
StatusBarPipelineFlags statusBarPipelineFlags,
|
StatusBarPipelineFlags statusBarPipelineFlags,
|
||||||
Provider<WifiViewModel> wifiViewModelProvider) {
|
Provider<WifiViewModel> wifiViewModelProvider,
|
||||||
super(group, featureFlags, statusBarPipelineFlags, wifiViewModelProvider);
|
MobileContextProvider mobileContextProvider) {
|
||||||
|
super(group,
|
||||||
|
statusBarPipelineFlags,
|
||||||
|
wifiViewModelProvider,
|
||||||
|
mobileContextProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -261,23 +277,26 @@ public interface StatusBarIconController {
|
|||||||
|
|
||||||
@SysUISingleton
|
@SysUISingleton
|
||||||
public static class Factory {
|
public static class Factory {
|
||||||
private final FeatureFlags mFeatureFlags;
|
|
||||||
private final StatusBarPipelineFlags mStatusBarPipelineFlags;
|
private final StatusBarPipelineFlags mStatusBarPipelineFlags;
|
||||||
private final Provider<WifiViewModel> mWifiViewModelProvider;
|
private final Provider<WifiViewModel> mWifiViewModelProvider;
|
||||||
|
private final MobileContextProvider mMobileContextProvider;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public Factory(
|
public Factory(
|
||||||
FeatureFlags featureFlags,
|
|
||||||
StatusBarPipelineFlags statusBarPipelineFlags,
|
StatusBarPipelineFlags statusBarPipelineFlags,
|
||||||
Provider<WifiViewModel> wifiViewModelProvider) {
|
Provider<WifiViewModel> wifiViewModelProvider,
|
||||||
mFeatureFlags = featureFlags;
|
MobileContextProvider mobileContextProvider) {
|
||||||
mStatusBarPipelineFlags = statusBarPipelineFlags;
|
mStatusBarPipelineFlags = statusBarPipelineFlags;
|
||||||
mWifiViewModelProvider = wifiViewModelProvider;
|
mWifiViewModelProvider = wifiViewModelProvider;
|
||||||
|
mMobileContextProvider = mobileContextProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TintedIconManager create(ViewGroup group) {
|
public TintedIconManager create(ViewGroup group) {
|
||||||
return new TintedIconManager(
|
return new TintedIconManager(
|
||||||
group, mFeatureFlags, mStatusBarPipelineFlags, mWifiViewModelProvider);
|
group,
|
||||||
|
mStatusBarPipelineFlags,
|
||||||
|
mWifiViewModelProvider,
|
||||||
|
mMobileContextProvider);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -287,9 +306,9 @@ public interface StatusBarIconController {
|
|||||||
*/
|
*/
|
||||||
class IconManager implements DemoModeCommandReceiver {
|
class IconManager implements DemoModeCommandReceiver {
|
||||||
protected final ViewGroup mGroup;
|
protected final ViewGroup mGroup;
|
||||||
private final FeatureFlags mFeatureFlags;
|
|
||||||
private final StatusBarPipelineFlags mStatusBarPipelineFlags;
|
private final StatusBarPipelineFlags mStatusBarPipelineFlags;
|
||||||
private final Provider<WifiViewModel> mWifiViewModelProvider;
|
private final Provider<WifiViewModel> mWifiViewModelProvider;
|
||||||
|
private final MobileContextProvider mMobileContextProvider;
|
||||||
protected final Context mContext;
|
protected final Context mContext;
|
||||||
protected final int mIconSize;
|
protected final int mIconSize;
|
||||||
// Whether or not these icons show up in dumpsys
|
// Whether or not these icons show up in dumpsys
|
||||||
@@ -305,13 +324,13 @@ public interface StatusBarIconController {
|
|||||||
|
|
||||||
public IconManager(
|
public IconManager(
|
||||||
ViewGroup group,
|
ViewGroup group,
|
||||||
FeatureFlags featureFlags,
|
|
||||||
StatusBarPipelineFlags statusBarPipelineFlags,
|
StatusBarPipelineFlags statusBarPipelineFlags,
|
||||||
Provider<WifiViewModel> wifiViewModelProvider) {
|
Provider<WifiViewModel> wifiViewModelProvider,
|
||||||
|
MobileContextProvider mobileContextProvider) {
|
||||||
mGroup = group;
|
mGroup = group;
|
||||||
mFeatureFlags = featureFlags;
|
|
||||||
mStatusBarPipelineFlags = statusBarPipelineFlags;
|
mStatusBarPipelineFlags = statusBarPipelineFlags;
|
||||||
mWifiViewModelProvider = wifiViewModelProvider;
|
mWifiViewModelProvider = wifiViewModelProvider;
|
||||||
|
mMobileContextProvider = mobileContextProvider;
|
||||||
mContext = group.getContext();
|
mContext = group.getContext();
|
||||||
mIconSize = mContext.getResources().getDimensionPixelSize(
|
mIconSize = mContext.getResources().getDimensionPixelSize(
|
||||||
com.android.internal.R.dimen.status_bar_icon_size);
|
com.android.internal.R.dimen.status_bar_icon_size);
|
||||||
@@ -403,12 +422,15 @@ public interface StatusBarIconController {
|
|||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
protected StatusBarMobileView addMobileIcon(int index, String slot, MobileIconState state) {
|
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);
|
view.applyMobileState(state);
|
||||||
mGroup.addView(view, index, onCreateLayoutParams());
|
mGroup.addView(view, index, onCreateLayoutParams());
|
||||||
|
|
||||||
if (mIsInDemoMode) {
|
if (mIsInDemoMode) {
|
||||||
mDemoStatusIcons.addMobileView(state);
|
Context mobileContext = mMobileContextProvider
|
||||||
|
.getMobileContextForSub(state.subId, mContext);
|
||||||
|
mDemoStatusIcons.addMobileView(state, mobileContext);
|
||||||
}
|
}
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
@@ -427,8 +449,10 @@ public interface StatusBarIconController {
|
|||||||
mContext, slot, mWifiViewModelProvider.get());
|
mContext, slot, mWifiViewModelProvider.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
private StatusBarMobileView onCreateStatusBarMobileView(String slot) {
|
private StatusBarMobileView onCreateStatusBarMobileView(int subId, String slot) {
|
||||||
StatusBarMobileView view = StatusBarMobileView.fromContext(mContext, slot);
|
Context mobileContext = mMobileContextProvider.getMobileContextForSub(subId, mContext);
|
||||||
|
StatusBarMobileView view = StatusBarMobileView
|
||||||
|
.fromContext(mobileContext, slot);
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -516,7 +540,9 @@ public interface StatusBarIconController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mIsInDemoMode) {
|
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() {
|
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 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.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import android.testing.AndroidTestingRunner;
|
import android.testing.AndroidTestingRunner;
|
||||||
import android.testing.TestableLooper.RunWithLooper;
|
import android.testing.TestableLooper.RunWithLooper;
|
||||||
@@ -30,12 +33,12 @@ import android.widget.LinearLayout;
|
|||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
import com.android.internal.statusbar.StatusBarIcon;
|
import com.android.internal.statusbar.StatusBarIcon;
|
||||||
import com.android.systemui.flags.FeatureFlags;
|
|
||||||
import com.android.systemui.plugins.DarkIconDispatcher;
|
import com.android.systemui.plugins.DarkIconDispatcher;
|
||||||
import com.android.systemui.statusbar.StatusBarIconView;
|
import com.android.systemui.statusbar.StatusBarIconView;
|
||||||
import com.android.systemui.statusbar.StatusBarMobileView;
|
import com.android.systemui.statusbar.StatusBarMobileView;
|
||||||
import com.android.systemui.statusbar.StatusBarWifiView;
|
import com.android.systemui.statusbar.StatusBarWifiView;
|
||||||
import com.android.systemui.statusbar.StatusIconDisplayable;
|
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.DarkIconManager;
|
||||||
import com.android.systemui.statusbar.phone.StatusBarIconController.IconManager;
|
import com.android.systemui.statusbar.phone.StatusBarIconController.IconManager;
|
||||||
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
|
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
|
||||||
@@ -55,15 +58,19 @@ import javax.inject.Provider;
|
|||||||
@SmallTest
|
@SmallTest
|
||||||
public class StatusBarIconControllerTest extends LeakCheckedTest {
|
public class StatusBarIconControllerTest extends LeakCheckedTest {
|
||||||
|
|
||||||
|
private MobileContextProvider mMobileContextProvider = mock(MobileContextProvider.class);
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup() {
|
public void setup() {
|
||||||
injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
|
injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
|
||||||
|
// For testing, ignore context overrides
|
||||||
|
when(mMobileContextProvider.getMobileContextForSub(anyInt(), any())).thenReturn(mContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSetCalledOnAdd_IconManager() {
|
public void testSetCalledOnAdd_IconManager() {
|
||||||
LinearLayout layout = new LinearLayout(mContext);
|
LinearLayout layout = new LinearLayout(mContext);
|
||||||
TestIconManager manager = new TestIconManager(layout);
|
TestIconManager manager = new TestIconManager(layout, mMobileContextProvider);
|
||||||
testCallOnAdd_forManager(manager);
|
testCallOnAdd_forManager(manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,9 +79,9 @@ public class StatusBarIconControllerTest extends LeakCheckedTest {
|
|||||||
LinearLayout layout = new LinearLayout(mContext);
|
LinearLayout layout = new LinearLayout(mContext);
|
||||||
TestDarkIconManager manager = new TestDarkIconManager(
|
TestDarkIconManager manager = new TestDarkIconManager(
|
||||||
layout,
|
layout,
|
||||||
mock(FeatureFlags.class),
|
|
||||||
mock(StatusBarPipelineFlags.class),
|
mock(StatusBarPipelineFlags.class),
|
||||||
() -> mock(WifiViewModel.class),
|
() -> mock(WifiViewModel.class),
|
||||||
|
mMobileContextProvider,
|
||||||
mock(DarkIconDispatcher.class));
|
mock(DarkIconDispatcher.class));
|
||||||
testCallOnAdd_forManager(manager);
|
testCallOnAdd_forManager(manager);
|
||||||
}
|
}
|
||||||
@@ -114,11 +121,14 @@ public class StatusBarIconControllerTest extends LeakCheckedTest {
|
|||||||
|
|
||||||
TestDarkIconManager(
|
TestDarkIconManager(
|
||||||
LinearLayout group,
|
LinearLayout group,
|
||||||
FeatureFlags featureFlags,
|
|
||||||
StatusBarPipelineFlags statusBarPipelineFlags,
|
StatusBarPipelineFlags statusBarPipelineFlags,
|
||||||
Provider<WifiViewModel> wifiViewModelProvider,
|
Provider<WifiViewModel> wifiViewModelProvider,
|
||||||
|
MobileContextProvider contextProvider,
|
||||||
DarkIconDispatcher darkIconDispatcher) {
|
DarkIconDispatcher darkIconDispatcher) {
|
||||||
super(group, featureFlags, statusBarPipelineFlags, wifiViewModelProvider,
|
super(group,
|
||||||
|
statusBarPipelineFlags,
|
||||||
|
wifiViewModelProvider,
|
||||||
|
contextProvider,
|
||||||
darkIconDispatcher);
|
darkIconDispatcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,11 +163,11 @@ public class StatusBarIconControllerTest extends LeakCheckedTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static class TestIconManager extends IconManager implements TestableIconManager {
|
private static class TestIconManager extends IconManager implements TestableIconManager {
|
||||||
TestIconManager(ViewGroup group) {
|
TestIconManager(ViewGroup group, MobileContextProvider contextProvider) {
|
||||||
super(group,
|
super(group,
|
||||||
mock(FeatureFlags.class),
|
|
||||||
mock(StatusBarPipelineFlags.class),
|
mock(StatusBarPipelineFlags.class),
|
||||||
() -> mock(WifiViewModel.class));
|
() -> mock(WifiViewModel.class),
|
||||||
|
contextProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Reference in New Issue
Block a user