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

Commit 308bfd78 authored by Matías Hernández's avatar Matías Hernández
Browse files

Make ZenIconLoader injectable (in SystemUI)

And provide a direct-executor-service version for ZenModeInteractor in Kosmos.

(This allows us to get rid of all usages of ZenIconLoader.setInstance(), which was used exclusively for this exact purpose).

Bug: 360399800
Test: atest ModesTileTest ZenModeInteractorTest
Flag: android.app.modes_ui
Change-Id: I16219ef486b17b2e5f6819008bcc6fb0697b0f80
parent e4f5f6c4
Loading
Loading
Loading
Loading
+10 −14
Original line number Diff line number Diff line
@@ -31,7 +31,6 @@ import android.util.LruCache;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;

import com.google.common.util.concurrent.FluentFuture;
import com.google.common.util.concurrent.ListenableFuture;
@@ -53,25 +52,22 @@ public class ZenIconLoader {
    private final LruCache<ZenIcon.Key, Drawable> mCache;
    private final ListeningExecutorService mBackgroundExecutor;

    /** Obtains the singleton {@link ZenIconLoader}. */
    public static ZenIconLoader getInstance() {
        if (sInstance == null) {
            sInstance = new ZenIconLoader();
            sInstance = new ZenIconLoader(Executors.newFixedThreadPool(4));
        }
        return sInstance;
    }

    /** Replaces the singleton instance of {@link ZenIconLoader} by the provided one. */
    @VisibleForTesting(otherwise = VisibleForTesting.NONE)
    public static void setInstance(@Nullable ZenIconLoader instance) {
        sInstance = instance;
    }

    private ZenIconLoader() {
        this(Executors.newFixedThreadPool(4));
    }

    @VisibleForTesting
    public ZenIconLoader(ExecutorService backgroundExecutor) {
    /**
     * Constructs a ZenIconLoader with the specified {@code backgroundExecutor}.
     *
     * <p>ZenIconLoader <em>should be a singleton</em>, so this should only be used to instantiate
     * and provide the singleton instance in a module. If the app doesn't support dependency
     * injection, use {@link #getInstance} instead.
     */
    public ZenIconLoader(@NonNull ExecutorService backgroundExecutor) {
        mCache = new LruCache<>(50);
        mBackgroundExecutor =
                MoreExecutors.listeningDecorator(backgroundExecutor);
+0 −4
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@ import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.internal.R
import com.android.settingslib.notification.modes.ZenIconLoader
import com.android.systemui.SysuiTestCase
import com.android.systemui.common.shared.model.asIcon
import com.android.systemui.coroutines.collectLastValue
@@ -38,7 +37,6 @@ import com.android.systemui.statusbar.policy.data.repository.fakeZenModeReposito
import com.android.systemui.statusbar.policy.domain.interactor.zenModeInteractor
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import com.google.common.util.concurrent.MoreExecutors
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.toCollection
@@ -66,8 +64,6 @@ class ModesTileDataInteractorTest : SysuiTestCase() {
            addOverride(R.drawable.ic_zen_mode_type_bedtime, BEDTIME_DRAWABLE)
            addOverride(R.drawable.ic_zen_mode_type_driving, DRIVING_DRAWABLE)
        }
        // TODO: b/360399800 - Remove; ZenIconLoader should always use direct executor for tests
        ZenIconLoader.setInstance(ZenIconLoader(MoreExecutors.newDirectExecutorService()))
    }

    @EnableFlags(Flags.FLAG_MODES_UI)
+0 −9
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ import android.provider.Settings
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.settingslib.notification.modes.TestModeBuilder
import com.android.settingslib.notification.modes.ZenIconLoader
import com.android.settingslib.notification.modes.ZenMode
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
@@ -35,12 +34,10 @@ import com.android.systemui.statusbar.policy.ui.dialog.mockModesDialogDelegate
import com.android.systemui.statusbar.policy.ui.dialog.mockModesDialogEventLogger
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import com.google.common.util.concurrent.MoreExecutors
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.clearInvocations
@@ -67,12 +64,6 @@ class ModesDialogViewModelTest : SysuiTestCase() {
            mockDialogEventLogger
        )

    @Before
    fun setUp() {
        // TODO: b/360399800 - Remove; ZenIconLoader should always use direct executor for tests
        ZenIconLoader.setInstance(ZenIconLoader(MoreExecutors.newDirectExecutorService()))
    }

    @Test
    fun tiles_filtersOutUserDisabledModes() =
        testScope.runTest {
+11 −0
Original line number Diff line number Diff line
@@ -22,8 +22,10 @@ import android.os.UserManager;

import com.android.internal.R;
import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager;
import com.android.settingslib.notification.modes.ZenIconLoader;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.log.LogBuffer;
import com.android.systemui.log.LogBufferFactory;
import com.android.systemui.settings.UserTracker;
@@ -79,6 +81,7 @@ import dagger.Module;
import dagger.Provides;

import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;

import javax.inject.Named;

@@ -236,4 +239,12 @@ public interface StatusBarPolicyModule {
    static LogBuffer provideCastControllerLog(LogBufferFactory factory) {
        return factory.create("CastControllerLog", 50);
    }

    /** Provides a {@link ZenIconLoader} that fetches icons in a background thread. */
    @Provides
    @SysUISingleton
    static ZenIconLoader provideZenIconLoader(
            @UiBackground ExecutorService backgroundExecutorService) {
        return new ZenIconLoader(backgroundExecutorService);
    }
}
+1 −2
Original line number Diff line number Diff line
@@ -50,9 +50,8 @@ constructor(
    private val zenModeRepository: ZenModeRepository,
    private val notificationSettingsRepository: NotificationSettingsRepository,
    @Background private val bgDispatcher: CoroutineDispatcher,
    private val iconLoader: ZenIconLoader,
) {
    private val iconLoader: ZenIconLoader = ZenIconLoader.getInstance()

    val isZenModeEnabled: Flow<Boolean> =
        zenModeRepository.globalZenMode
            .map {
Loading