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

Commit 6a1ca545 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes Icbc6fcac,I3651e364 into main

* changes:
  Introduce DarkIconDispatcherStore for multiple displays
  Prepare DarkIconDispatcher for multiple displays
parents 6e3cd07e 57807815
Loading
Loading
Loading
Loading
+73 −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.data.repository

import android.platform.test.annotations.EnableFlags
import android.view.Display.DEFAULT_DISPLAY
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.display.data.repository.displayRepository
import com.android.systemui.kosmos.testScope
import com.android.systemui.kosmos.useUnconfinedTestDispatcher
import com.android.systemui.statusbar.core.StatusBarConnectedDisplays
import com.android.systemui.testKosmos
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.never
import org.mockito.kotlin.verify

@SmallTest
@RunWith(AndroidJUnit4::class)
@EnableFlags(StatusBarConnectedDisplays.FLAG_NAME)
class MultiDisplayDarkIconDispatcherStoreTest : SysuiTestCase() {

    private val kosmos = testKosmos().useUnconfinedTestDispatcher()
    private val testScope = kosmos.testScope
    private val fakeDisplayRepository = kosmos.displayRepository

    // Lazy so that @EnableFlags has time to run before underTest is instantiated.
    private val underTest by lazy { kosmos.multiDisplayDarkIconDispatcherStore }

    @Before
    fun start() {
        underTest.start()
    }

    @Before fun addDisplays() = runBlocking { fakeDisplayRepository.addDisplay(DEFAULT_DISPLAY) }

    @Test
    fun beforeDisplayRemoved_doesNotStopInstances() =
        testScope.runTest {
            val instance = underTest.forDisplay(DEFAULT_DISPLAY)

            verify(instance, never()).stop()
        }

    @Test
    fun displayRemoved_stopsInstance() =
        testScope.runTest {
            val instance = underTest.forDisplay(DEFAULT_DISPLAY)

            fakeDisplayRepository.removeDisplay(DEFAULT_DISPLAY)

            verify(instance).stop()
        }
}
+3 −0
Original line number Diff line number Diff line
@@ -36,6 +36,9 @@ import java.util.Collection;
public interface DarkIconDispatcher {
    int VERSION = 2;

    /** Called when work should stop and resources should be cleaned up. */
    default void stop() {}

    /**
     * Sets the dark area so {@link #applyDark} only affects the icons in the specified area.
     *
+17 −3
Original line number Diff line number Diff line
@@ -16,7 +16,10 @@

package com.android.systemui.dagger;

import android.content.Context;

import com.android.systemui.classifier.FalsingManagerProxy;
import com.android.systemui.dagger.qualifiers.Default;
import com.android.systemui.globalactions.GlobalActionsComponent;
import com.android.systemui.globalactions.GlobalActionsImpl;
import com.android.systemui.plugins.ActivityStarter;
@@ -33,11 +36,12 @@ import com.android.systemui.volume.VolumeDialogControllerImpl;

import dagger.Binds;
import dagger.Module;
import dagger.Provides;

/**
 * Module for binding Plugin implementations.
 *
 * TODO(b/166258224): Many of these should be moved closer to their implementations.
 * <p>TODO(b/166258224): Many of these should be moved closer to their implementations.
 */
@Module
public abstract class PluginModule {
@@ -46,13 +50,23 @@ public abstract class PluginModule {
    @Binds
    abstract ActivityStarter provideActivityStarter(ActivityStarterImpl activityStarterImpl);

    /** */
    @Provides
    @SysUISingleton
    @Default
    static DarkIconDispatcherImpl darkIconDispatcherImpl(
            DarkIconDispatcherImpl.Factory factory, Context context) {
        return factory.create(context.getDisplayId(), context);
    }

    /** */
    @Binds
    abstract DarkIconDispatcher provideDarkIconDispatcher(DarkIconDispatcherImpl controllerImpl);
    abstract DarkIconDispatcher provideDarkIconDispatcher(
            @Default DarkIconDispatcherImpl controllerImpl);

    @Binds
    abstract SysuiDarkIconDispatcher provideSysuiDarkIconDispatcher(
            DarkIconDispatcherImpl controllerImpl);
            @Default DarkIconDispatcherImpl controllerImpl);

    /** */
    @Binds
+2 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
 */
package com.android.systemui.statusbar.data

import com.android.systemui.statusbar.data.repository.DarkIconDispatcherStoreModule
import com.android.systemui.statusbar.data.repository.KeyguardStatusBarRepositoryModule
import com.android.systemui.statusbar.data.repository.LightBarControllerStoreModule
import com.android.systemui.statusbar.data.repository.RemoteInputRepositoryModule
@@ -28,6 +29,7 @@ import dagger.Module
@Module(
    includes =
        [
            DarkIconDispatcherStoreModule::class,
            KeyguardStatusBarRepositoryModule::class,
            LightBarControllerStoreModule::class,
            RemoteInputRepositoryModule::class,
+142 −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.data.repository

import android.content.Context
import android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR
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 com.android.systemui.display.data.repository.DisplayWindowPropertiesRepository
import com.android.systemui.display.data.repository.PerDisplayStore
import com.android.systemui.display.data.repository.PerDisplayStoreImpl
import com.android.systemui.display.data.repository.SingleDisplayStore
import com.android.systemui.plugins.DarkIconDispatcher
import com.android.systemui.statusbar.core.StatusBarConnectedDisplays
import com.android.systemui.statusbar.phone.DarkIconDispatcherImpl
import com.android.systemui.statusbar.phone.SysuiDarkIconDispatcher
import dagger.Binds
import dagger.Lazy
import dagger.Module
import dagger.Provides
import dagger.multibindings.ClassKey
import dagger.multibindings.IntoMap
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope

/** Provides per display instances of [DarkIconDispatcher]. */
interface DarkIconDispatcherStore : PerDisplayStore<DarkIconDispatcher>

/** Provides per display instances of [SysuiDarkIconDispatcher]. */
interface SysuiDarkIconDispatcherStore : PerDisplayStore<SysuiDarkIconDispatcher>

/**
 * Multi display implementation that should be used when the [StatusBarConnectedDisplays] flag is
 * enabled.
 */
@SysUISingleton
class MultiDisplayDarkIconDispatcherStore
@Inject
constructor(
    @Background backgroundApplicationScope: CoroutineScope,
    displayRepository: DisplayRepository,
    private val factory: DarkIconDispatcherImpl.Factory,
    private val displayWindowPropertiesRepository: DisplayWindowPropertiesRepository,
) :
    SysuiDarkIconDispatcherStore,
    PerDisplayStoreImpl<SysuiDarkIconDispatcher>(backgroundApplicationScope, displayRepository) {

    init {
        StatusBarConnectedDisplays.assertInNewMode()
    }

    override fun createInstanceForDisplay(displayId: Int): SysuiDarkIconDispatcher {
        val properties = displayWindowPropertiesRepository.get(displayId, TYPE_STATUS_BAR)
        return factory.create(displayId, properties.context)
    }

    override suspend fun onDisplayRemovalAction(instance: SysuiDarkIconDispatcher) {
        instance.stop()
    }

    override val instanceClass = SysuiDarkIconDispatcher::class.java
}

/**
 * Single display implementation that should be used when the [StatusBarConnectedDisplays] flag is
 * disabled.
 */
@SysUISingleton
class SingleDisplayDarkIconDispatcherStore
@Inject
constructor(factory: DarkIconDispatcherImpl.Factory, context: Context) :
    SysuiDarkIconDispatcherStore,
    PerDisplayStore<SysuiDarkIconDispatcher> by SingleDisplayStore(
        defaultInstance = factory.create(context.displayId, context)
    ) {

    init {
        StatusBarConnectedDisplays.assertInLegacyMode()
    }
}

/** Extra implementation that simply implements the [DarkIconDispatcherStore] interface. */
@SysUISingleton
class DarkIconDispatcherStoreImpl
@Inject
constructor(private val store: SysuiDarkIconDispatcherStore) : DarkIconDispatcherStore {
    override val defaultDisplay: DarkIconDispatcher
        get() = store.defaultDisplay

    override fun forDisplay(displayId: Int): DarkIconDispatcher = store.forDisplay(displayId)
}

@Module
interface DarkIconDispatcherStoreModule {

    @Binds fun store(impl: DarkIconDispatcherStoreImpl): DarkIconDispatcherStore

    companion object {
        @Provides
        @SysUISingleton
        fun sysUiStore(
            singleDisplayLazy: Lazy<SingleDisplayDarkIconDispatcherStore>,
            multiDisplayLazy: Lazy<MultiDisplayDarkIconDispatcherStore>,
        ): SysuiDarkIconDispatcherStore {
            return if (StatusBarConnectedDisplays.isEnabled) {
                multiDisplayLazy.get()
            } else {
                singleDisplayLazy.get()
            }
        }

        @Provides
        @SysUISingleton
        @IntoMap
        @ClassKey(DarkIconDispatcherStore::class)
        fun storeAsCoreStartable(
            multiDisplayLazy: Lazy<MultiDisplayDarkIconDispatcherStore>
        ): CoreStartable {
            return if (StatusBarConnectedDisplays.isEnabled) {
                multiDisplayLazy.get()
            } else {
                CoreStartable.NOP
            }
        }
    }
}
Loading