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

Commit 29ad9ea4 authored by Chris Göllner's avatar Chris Göllner
Browse files

Introduce StatusBarInitializerStore

Flag: com.android.systemui.status_bar_connected_displays
Test: Unit tests in this CL
Test: Manually build and run and verify everything works as before
Bug: 367592591
Change-Id: Ia97ed6b380ba5f2a6b907bd29f14841cd3521fe8
parent 116225fc
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@ class StatusBarInitializerTest : SysuiTestCase() {

    val underTest =
        StatusBarInitializerImpl(
            displayId = context.displayId,
            statusBarWindowControllerStore = windowControllerStore,
            collapsedStatusBarFragmentProvider = { mock(CollapsedStatusBarFragment::class.java) },
            creationListeners = setOf(),
+30 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.dagger.qualifiers;

import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;

import javax.inject.Qualifier;

@Qualifier
@Documented
@Retention(RUNTIME)
public @interface Default {
}
+14 −4
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@ package com.android.systemui.statusbar.core
import android.app.Fragment
import androidx.annotation.VisibleForTesting
import com.android.systemui.CoreStartable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.fragments.FragmentHostManager
import com.android.systemui.res.R
import com.android.systemui.statusbar.core.StatusBarInitializer.OnStatusBarViewInitializedListener
@@ -28,8 +27,10 @@ import com.android.systemui.statusbar.phone.PhoneStatusBarViewController
import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment
import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent
import com.android.systemui.statusbar.window.StatusBarWindowControllerStore
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import java.lang.IllegalStateException
import javax.inject.Inject
import javax.inject.Provider

/**
@@ -65,12 +66,16 @@ interface StatusBarInitializer {
            statusBarTransitions: PhoneStatusBarTransitions,
        )
    }

    interface Factory {
        fun create(displayId: Int): StatusBarInitializer
    }
}

@SysUISingleton
class StatusBarInitializerImpl
@Inject
@AssistedInject
constructor(
    @Assisted private val displayId: Int,
    private val statusBarWindowControllerStore: StatusBarWindowControllerStore,
    private val collapsedStatusBarFragmentProvider: Provider<CollapsedStatusBarFragment>,
    private val creationListeners: Set<@JvmSuppressWildcards OnStatusBarViewInitializedListener>,
@@ -137,4 +142,9 @@ constructor(
            )
            .commit()
    }

    @AssistedFactory
    interface Factory : StatusBarInitializer.Factory {
        override fun create(displayId: Int): StatusBarInitializerImpl
    }
}
+99 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.core

import android.view.Display
import com.android.systemui.CoreStartable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.display.data.repository.DisplayRepository
import java.util.concurrent.ConcurrentHashMap
import javax.inject.Inject
import kotlinx.coroutines.CoroutineName
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch

/** Provides per display instances of [StatusBarInitializer]. */
interface StatusBarInitializerStore {
    /**
     * The instance for the default/main display of the device. For example, on a phone or a tablet,
     * the default display is the internal/built-in display of the device.
     *
     * Note that the id of the default display is [Display.DEFAULT_DISPLAY].
     */
    val defaultDisplay: StatusBarInitializer

    /**
     * Returns an instance for a specific display id.
     *
     * @throws IllegalArgumentException if [displayId] doesn't match the id of any existing
     *   displays.
     */
    fun forDisplay(displayId: Int): StatusBarInitializer
}

@SysUISingleton
class MultiDisplayStatusBarInitializerStore
@Inject
constructor(
    @Background private val backgroundApplicationScope: CoroutineScope,
    private val factory: StatusBarInitializer.Factory,
    private val displayRepository: DisplayRepository,
) : StatusBarInitializerStore, CoreStartable {

    init {
        StatusBarConnectedDisplays.assertInNewMode()
    }

    private val perDisplayInitializers = ConcurrentHashMap<Int, StatusBarInitializer>()

    override val defaultDisplay: StatusBarInitializer
        get() = forDisplay(Display.DEFAULT_DISPLAY)

    override fun forDisplay(displayId: Int): StatusBarInitializer {
        if (displayRepository.getDisplay(displayId) == null) {
            throw IllegalArgumentException("Display with id $displayId doesn't exist.")
        }
        return perDisplayInitializers.computeIfAbsent(displayId) { factory.create(displayId) }
    }

    override fun start() {
        backgroundApplicationScope.launch(
            CoroutineName("MultiDisplayStatusBarInitializerStore#start")
        ) {
            displayRepository.displayRemovalEvent.collect { removedDisplayId ->
                perDisplayInitializers.remove(removedDisplayId)
            }
        }
    }
}

@SysUISingleton
class SingleDisplayStatusBarInitializerStore
@Inject
constructor(factory: StatusBarInitializerImpl.Factory) : StatusBarInitializerStore {

    init {
        StatusBarConnectedDisplays.assertInLegacyMode()
    }

    private val defaultInstance = factory.create(Display.DEFAULT_DISPLAY)

    override val defaultDisplay: StatusBarInitializer = defaultInstance

    override fun forDisplay(displayId: Int): StatusBarInitializer = defaultDisplay
}
+51 −2
Original line number Diff line number Diff line
@@ -15,12 +15,18 @@
 */
package com.android.systemui.statusbar.phone.dagger

import android.view.Display
import com.android.systemui.CoreStartable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Default
import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.statusbar.core.CommandQueueInitializer
import com.android.systemui.statusbar.core.MultiDisplayStatusBarInitializerStore
import com.android.systemui.statusbar.core.SingleDisplayStatusBarInitializerStore
import com.android.systemui.statusbar.core.StatusBarConnectedDisplays
import com.android.systemui.statusbar.core.StatusBarInitializer
import com.android.systemui.statusbar.core.StatusBarInitializerImpl
import com.android.systemui.statusbar.core.StatusBarInitializerStore
import com.android.systemui.statusbar.core.StatusBarOrchestrator
import com.android.systemui.statusbar.core.StatusBarSimpleFragment
import com.android.systemui.statusbar.phone.CentralSurfacesCommandQueueCallbacks
@@ -47,15 +53,31 @@ interface StatusBarPhoneModule {
        impl: CentralSurfacesCommandQueueCallbacks
    ): CommandQueue.Callbacks

    @Binds
    fun initializerFactory(
        implFactory: StatusBarInitializerImpl.Factory
    ): StatusBarInitializer.Factory

    /** Binds {@link StatusBarInitializer} as a {@link CoreStartable}. */
    @Binds
    @IntoMap
    @ClassKey(StatusBarInitializerImpl::class)
    fun bindStatusBarInitializer(impl: StatusBarInitializerImpl): CoreStartable
    fun bindStatusBarInitializer(@Default impl: StatusBarInitializerImpl): CoreStartable

    @Binds fun statusBarInitializer(impl: StatusBarInitializerImpl): StatusBarInitializer
    @Binds fun statusBarInitializer(@Default impl: StatusBarInitializerImpl): StatusBarInitializer

    companion object {
        // Dagger doesn't support providing AssistedInject types, without a qualifier. Using the
        // Default qualifier for this reason.
        @Default
        @Provides
        @SysUISingleton
        fun statusBarInitializerImpl(
            implFactory: StatusBarInitializerImpl.Factory
        ): StatusBarInitializerImpl {
            return implFactory.create(displayId = Display.DEFAULT_DISPLAY)
        }

        @Provides
        @SysUISingleton
        @IntoMap
@@ -83,5 +105,32 @@ interface StatusBarPhoneModule {
                CoreStartable.NOP
            }
        }

        @Provides
        @SysUISingleton
        @IntoMap
        @ClassKey(StatusBarInitializerStore::class)
        fun initializerStoreAsCoreStartable(
            multiDisplayStoreLazy: Lazy<MultiDisplayStatusBarInitializerStore>
        ): CoreStartable {
            return if (StatusBarConnectedDisplays.isEnabled) {
                multiDisplayStoreLazy.get()
            } else {
                CoreStartable.NOP
            }
        }

        @Provides
        @SysUISingleton
        fun initializerStore(
            singleDisplayStoreLazy: Lazy<SingleDisplayStatusBarInitializerStore>,
            multiDisplayStoreLazy: Lazy<MultiDisplayStatusBarInitializerStore>,
        ): StatusBarInitializerStore {
            return if (StatusBarConnectedDisplays.isEnabled) {
                multiDisplayStoreLazy.get()
            } else {
                singleDisplayStoreLazy.get()
            }
        }
    }
}
Loading