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

Commit ecc498ce authored by Evan Laird's avatar Evan Laird Committed by Android (Google) Code Review
Browse files

Merge "Create Configuration overrides for MCC/MNC values" into tm-qpr-dev

parents 54dd46a8 acf1eebc
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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);
+10 −0
Original line number Diff line number Diff line
@@ -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,
+137 −0
Original line number Diff line number Diff line
/*
 * 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)
            }
        }
    }
}
+22 −14
Original line number Diff line number Diff line
@@ -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) {
+56 −30
Original line number Diff line number Diff line
@@ -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 accessibilityLiveRegion live region mode for the icon
     * @see android.view.View#setAccessibilityLiveRegion(int)
     */
    void setIconAccessibilityLiveRegion(String slot, int accessibilityLiveRegion);

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