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

Commit f8758638 authored by Evan Laird's avatar Evan Laird
Browse files

[Sb] BindableIcon shim support for StatusBarIconConroller

Mostly an organizational task. BindableIcons can be supplied via the new
BindableIconsRegistry. They are statically defined dependencies
provided via Dagger into the prod implementation.

Upon init, StatusBarIconController will register these bindable icons,
and add them via the captured initialization closure when any group
shows up.

BindableIcons are responsible for their own display.

Future CLs to define the basic behavior for ModernStatusBarView and its
binder.

Bug: 308180461
Test: compile
Test: StatusBarIconControllerImplTest
Flag: NONE
Change-Id: I679039bd3a24147c88a76dd7cc3c3ba6b6543047
parent e803fa98
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@

package com.android.systemui.statusbar.phone;

import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_BINDABLE;
import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_ICON;
import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_MOBILE_NEW;
import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_WIFI_NEW;
@@ -40,11 +41,13 @@ import com.android.systemui.statusbar.BaseStatusBarFrameLayout;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.StatusIconDisplayable;
import com.android.systemui.statusbar.connectivity.ui.MobileContextProvider;
import com.android.systemui.statusbar.phone.StatusBarIconHolder.BindableIconHolder;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.CallIndicatorIconState;
import com.android.systemui.statusbar.pipeline.mobile.ui.MobileUiAdapter;
import com.android.systemui.statusbar.pipeline.mobile.ui.binder.MobileIconsBinder;
import com.android.systemui.statusbar.pipeline.mobile.ui.view.ModernStatusBarMobileView;
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel;
import com.android.systemui.statusbar.pipeline.shared.ui.view.ModernStatusBarView;
import com.android.systemui.statusbar.pipeline.wifi.ui.WifiUiAdapter;
import com.android.systemui.statusbar.pipeline.wifi.ui.view.ModernStatusBarWifiView;
import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.LocationBasedWifiViewModel;
@@ -432,6 +435,10 @@ public interface StatusBarIconController {

                case TYPE_MOBILE_NEW:
                    return addNewMobileIcon(index, slot, holder.getTag());

                case TYPE_BINDABLE:
                    // Safe cast, since only BindableIconHolders can set this tag on themselves
                    return addBindableIcon((BindableIconHolder) holder, index);
            }

            return null;
@@ -446,6 +453,18 @@ public interface StatusBarIconController {
            return view;
        }

        /**
         * ModernStatusBarViews can be created and bound, and thus do not need to update their
         *  drawable by sending multiple calls to setIcon. Instead, by using a bindable
         * icon view, we can simply create the icon when requested and allow the
         * ViewBinder to control its visual state.
         */
        protected StatusIconDisplayable addBindableIcon(BindableIconHolder holder, int index) {
            ModernStatusBarView view = holder.getInitializer().createAndBind(mContext);
            mGroup.addView(view, index, onCreateLayoutParams());
            return view;
        }

        protected StatusIconDisplayable addNewWifiIcon(int index, String slot) {
            ModernStatusBarWifiView view = onCreateModernStatusBarWifiView(slot);
            mGroup.addView(view, index, onCreateLayoutParams());
@@ -530,6 +549,7 @@ public interface StatusBarIconController {
                    return;
                case TYPE_MOBILE_NEW:
                case TYPE_WIFI_NEW:
                case TYPE_BINDABLE:
                    // Nothing, the new icons update themselves
                    return;
                default:
+38 −1
Original line number Diff line number Diff line
@@ -38,8 +38,11 @@ import com.android.systemui.demomode.DemoModeController;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.StatusIconDisplayable;
import com.android.systemui.statusbar.phone.StatusBarIconHolder.BindableIconHolder;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.CallIndicatorIconState;
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags;
import com.android.systemui.statusbar.pipeline.icons.shared.BindableIconsRegistry;
import com.android.systemui.statusbar.pipeline.icons.shared.model.BindableIcon;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
import com.android.systemui.tuner.TunerService;
@@ -83,7 +86,8 @@ public class StatusBarIconControllerImpl implements Tunable,
            TunerService tunerService,
            DumpManager dumpManager,
            StatusBarIconList statusBarIconList,
            StatusBarPipelineFlags statusBarPipelineFlags
            StatusBarPipelineFlags statusBarPipelineFlags,
            BindableIconsRegistry modernIconsRegistry
    ) {
        mStatusBarIconList = statusBarIconList;
        mContext = context;
@@ -94,6 +98,28 @@ public class StatusBarIconControllerImpl implements Tunable,
        tunerService.addTunable(this, ICON_HIDE_LIST);
        demoModeController.addCallback(this);
        dumpManager.registerDumpable(getClass().getSimpleName(), this);

        addModernBindableIcons(modernIconsRegistry);
    }

    /**
     * BindableIcons will always produce ModernStatusBarViews, which will be initialized and bound
     * upon being added to any icon group. Because their view policy does not require subsequent
     * calls to setIcon(), we can simply register them all statically here and not have to build
     * CoreStartables for each modern icon.
     *
     * @param registry a statically defined provider of the modern icons
     */
    private void addModernBindableIcons(BindableIconsRegistry registry) {
        List<BindableIcon> icons = registry.getBindableIcons();

        // Initialization point for the bindable (modern) icons. These icons get their own slot
        // allocated immediately, and are required to control their own display properties
        for (BindableIcon i : icons) {
            if (i.getShouldBindIcon()) {
                addBindableIcon(i);
            }
        }
    }

    /** */
@@ -182,6 +208,17 @@ public class StatusBarIconControllerImpl implements Tunable,
        mIconGroups.forEach(l -> l.onIconAdded(viewIndex, slot, hidden, holder));
    }

    void addBindableIcon(BindableIcon icon) {
        StatusBarIconHolder existingHolder = mStatusBarIconList.getIconHolder(icon.getSlot(), 0);
        // Expected to be null
        if (existingHolder == null) {
            BindableIconHolder bindableIcon = new BindableIconHolder(icon.getInitializer());
            setIcon(icon.getSlot(), bindableIcon);
        } else {
            Log.e(TAG, "addBindableIcon called, but icon has already been added. Ignoring");
        }
    }

    /** */
    @Override
    public void setIcon(String slot, int resourceId, CharSequence contentDescription) {
+32 −5
Original line number Diff line number Diff line
@@ -21,23 +21,24 @@ import android.graphics.drawable.Icon
import android.os.UserHandle
import com.android.internal.statusbar.StatusBarIcon
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.CallIndicatorIconState
import com.android.systemui.statusbar.pipeline.icons.shared.model.ModernStatusBarViewCreator

/** Wraps [com.android.internal.statusbar.StatusBarIcon] so we can still have a uniform list */
class StatusBarIconHolder private constructor() {
    @IntDef(TYPE_ICON, TYPE_MOBILE_NEW, TYPE_WIFI_NEW)
open class StatusBarIconHolder private constructor() {
    @IntDef(TYPE_ICON, TYPE_MOBILE_NEW, TYPE_WIFI_NEW, TYPE_BINDABLE)
    @Retention(AnnotationRetention.SOURCE)
    internal annotation class IconType

    var icon: StatusBarIcon? = null

    @IconType
    var type = TYPE_ICON
        private set
    open var type = TYPE_ICON
        internal set

    var tag = 0
        private set

    var isVisible: Boolean
    open var isVisible: Boolean
        get() =
            when (type) {
                TYPE_ICON -> icon!!.visible
@@ -45,6 +46,7 @@ class StatusBarIconHolder private constructor() {
                // The new pipeline controls visibilities via the view model and
                // view binder, so
                // this is effectively an unused return value.
                TYPE_BINDABLE,
                TYPE_MOBILE_NEW,
                TYPE_WIFI_NEW -> true
                else -> true
@@ -55,6 +57,7 @@ class StatusBarIconHolder private constructor() {
            }
            when (type) {
                TYPE_ICON -> icon!!.visible = visible
                TYPE_BINDABLE,
                TYPE_MOBILE_NEW,
                TYPE_WIFI_NEW -> {}
            }
@@ -94,6 +97,9 @@ class StatusBarIconHolder private constructor() {
        )
        const val TYPE_WIFI_NEW = 4

        /** Only applicable to [BindableIconHolder] */
        const val TYPE_BINDABLE = 5

        /** Returns a human-readable string representing the given type. */
        fun getTypeString(@IconType type: Int): String {
            return when (type) {
@@ -154,4 +160,25 @@ class StatusBarIconHolder private constructor() {
            return holder
        }
    }

    /**
     * Subclass of StatusBarIconHolder that is responsible only for the registration of an icon into
     * the [StatusBarIconList]. A bindable icon takes care of its own display, including hiding
     * itself under the correct conditions.
     *
     * StatusBarIconController will register all available bindable icons on init (see
     * [BindableIconsRepository]), and will ignore any call to setIcon for these.
     *
     * [initializer] a view creator that can bind the relevant view models to the created view.
     */
    class BindableIconHolder(val initializer: ModernStatusBarViewCreator) : StatusBarIconHolder() {
        override var type: Int = TYPE_BINDABLE

        /** This is unused, as bindable icons use their own view binders to control visibility */
        override var isVisible: Boolean = true

        override fun toString(): String {
            return ("StatusBarIconHolder(type=BINDABLE)")
        }
    }
}
+5 −0
Original line number Diff line number Diff line
@@ -29,6 +29,8 @@ import com.android.systemui.statusbar.pipeline.airplane.data.repository.Airplane
import com.android.systemui.statusbar.pipeline.airplane.data.repository.AirplaneModeRepositoryImpl
import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModel
import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModelImpl
import com.android.systemui.statusbar.pipeline.icons.shared.BindableIconsRegistry
import com.android.systemui.statusbar.pipeline.icons.shared.BindableIconsRegistryImpl
import com.android.systemui.statusbar.pipeline.mobile.data.repository.CarrierConfigCoreStartable
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileRepositorySwitcher
@@ -75,6 +77,9 @@ abstract class StatusBarPipelineModule {
    @Binds
    abstract fun airplaneModeViewModel(impl: AirplaneModeViewModelImpl): AirplaneModeViewModel

    @Binds
    abstract fun bindableIconsRepository(impl: BindableIconsRegistryImpl): BindableIconsRegistry

    @Binds
    abstract fun connectivityRepository(impl: ConnectivityRepositoryImpl): ConnectivityRepository

+48 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.pipeline.icons.shared

import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.statusbar.pipeline.icons.shared.model.BindableIcon
import javax.inject.Inject

/**
 * Bindable status bar icons represent icon descriptions which can be registered with
 * StatusBarIconController and can also create their own bindings. A bound icon is responsible for
 * its own updates via the [repeatWhenAttached] view lifecycle utility. Thus,
 * StatusBarIconController can (and will) ignore any call to setIcon.
 *
 * In other words, these icons are bound once (at controller init) and they will control their
 * visibility on their own (while their overall appearance remains at the discretion of
 * StatusBarIconController, via the ModernStatusBarViewBinding interface).
 */
interface BindableIconsRegistry {
    val bindableIcons: List<BindableIcon>
}

@SysUISingleton
class BindableIconsRegistryImpl
@Inject
constructor(
/** Bindables go here */
) : BindableIconsRegistry {
    /**
     * Adding the injected bindables to this list will get them registered with
     * StatusBarIconController
     */
    override val bindableIcons: List<BindableIcon> = listOf()
}
Loading