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

Commit 86618531 authored by Aurélien Pomini's avatar Aurélien Pomini
Browse files

Move ImageWallpaper tasks to its own thread

Previously, ImageWallpaper performed its long-running tasks (in particular the bitmap loading) with the @Background executor.

Since the bitmap loading can be very long (a few seconds) for some
wallpapers, and since the background executor is single-threaded and is
used for other UI tasks, we now use a dedicated executor to avoid
contention.

This CL also adds a provider to a Delayable LongRunning executor in SysUIConcurrencyModule, to be able to use the long running executor for the delayed bitmap unloading.

Test: manual
Test: atest GtsWallpaperTestCases
Test: atest WallpaperTest
Bug: 265018814
Bug: 265060422
Change-Id: I0f3320dee67c1ddd5f6294c92c4f5887237a9ed8
parent 2940697c
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -114,6 +114,17 @@ public abstract class SysUIConcurrencyModule {
        return new ExecutorImpl(looper);
    }

    /**
     * Provide a Long running Executor.
     */
    @Provides
    @SysUISingleton
    @LongRunning
    public static DelayableExecutor provideLongRunningDelayableExecutor(
            @LongRunning Looper looper) {
        return new ExecutorImpl(looper);
    }

    /**
     * Provide a Background-Thread Executor.
     */
+9 −10
Original line number Diff line number Diff line
@@ -35,7 +35,7 @@ import android.view.WindowManager;
import androidx.annotation.NonNull;

import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.LongRunning;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.util.concurrency.DelayableExecutor;

@@ -61,17 +61,16 @@ public class ImageWallpaper extends WallpaperService {
    private final UserTracker mUserTracker;

    // used for most tasks (call canvas.drawBitmap, load/unload the bitmap)
    @Background
    private final DelayableExecutor mBackgroundExecutor;
    @LongRunning
    private final DelayableExecutor mLongExecutor;

    // wait at least this duration before unloading the bitmap
    private static final int DELAY_UNLOAD_BITMAP = 2000;

    @Inject
    public ImageWallpaper(@Background DelayableExecutor backgroundExecutor,
            UserTracker userTracker) {
    public ImageWallpaper(@LongRunning DelayableExecutor longExecutor, UserTracker userTracker) {
        super();
        mBackgroundExecutor = backgroundExecutor;
        mLongExecutor = longExecutor;
        mUserTracker = userTracker;
    }

@@ -105,7 +104,7 @@ public class ImageWallpaper extends WallpaperService {
            setFixedSizeAllowed(true);
            setShowForAllUsers(true);
            mWallpaperLocalColorExtractor = new WallpaperLocalColorExtractor(
                    mBackgroundExecutor,
                    mLongExecutor,
                    new WallpaperLocalColorExtractor.WallpaperLocalColorExtractorCallback() {
                        @Override
                        public void onColorsProcessed(List<RectF> regions,
@@ -202,7 +201,7 @@ public class ImageWallpaper extends WallpaperService {
        }

        private void drawFrame() {
            mBackgroundExecutor.execute(this::drawFrameSynchronized);
            mLongExecutor.execute(this::drawFrameSynchronized);
        }

        private void drawFrameSynchronized() {
@@ -257,7 +256,7 @@ public class ImageWallpaper extends WallpaperService {
        }

        private void unloadBitmapIfNotUsed() {
            mBackgroundExecutor.execute(this::unloadBitmapIfNotUsedSynchronized);
            mLongExecutor.execute(this::unloadBitmapIfNotUsedSynchronized);
        }

        private void unloadBitmapIfNotUsedSynchronized() {
@@ -341,7 +340,7 @@ public class ImageWallpaper extends WallpaperService {
                 *   - the mini bitmap from color extractor is recomputed
                 *   - the DELAY_UNLOAD_BITMAP has passed
                 */
                mBackgroundExecutor.executeDelayed(
                mLongExecutor.executeDelayed(
                        this::unloadBitmapIfNotUsedSynchronized, DELAY_UNLOAD_BITMAP);
            }
            // even if the bitmap cannot be loaded, call reportEngineShown
+12 −12
Original line number Diff line number Diff line
@@ -29,7 +29,7 @@ import android.util.MathUtils;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;

import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.LongRunning;
import com.android.systemui.util.Assert;

import java.io.FileDescriptor;
@@ -66,8 +66,8 @@ public class WallpaperLocalColorExtractor {
    private final List<RectF> mPendingRegions = new ArrayList<>();
    private final Set<RectF> mProcessedRegions = new ArraySet<>();

    @Background
    private final Executor mBackgroundExecutor;
    @LongRunning
    private final Executor mLongExecutor;

    private final WallpaperLocalColorExtractorCallback mWallpaperLocalColorExtractorCallback;

@@ -101,13 +101,13 @@ public class WallpaperLocalColorExtractor {

    /**
     * Creates a new color extractor.
     * @param backgroundExecutor the executor on which the color extraction will be performed
     * @param longExecutor the executor on which the color extraction will be performed
     * @param wallpaperLocalColorExtractorCallback an interface to handle the callbacks from
     *                                        the color extractor.
     */
    public WallpaperLocalColorExtractor(@Background Executor backgroundExecutor,
    public WallpaperLocalColorExtractor(@LongRunning Executor longExecutor,
            WallpaperLocalColorExtractorCallback wallpaperLocalColorExtractorCallback) {
        mBackgroundExecutor = backgroundExecutor;
        mLongExecutor = longExecutor;
        mWallpaperLocalColorExtractorCallback = wallpaperLocalColorExtractorCallback;
    }

@@ -117,7 +117,7 @@ public class WallpaperLocalColorExtractor {
     * not recomputed.
     */
    public void setDisplayDimensions(int displayWidth, int displayHeight) {
        mBackgroundExecutor.execute(() ->
        mLongExecutor.execute(() ->
                setDisplayDimensionsSynchronized(displayWidth, displayHeight));
    }

@@ -144,7 +144,7 @@ public class WallpaperLocalColorExtractor {
     * @param bitmap the new wallpaper
     */
    public void onBitmapChanged(@NonNull Bitmap bitmap) {
        mBackgroundExecutor.execute(() -> onBitmapChangedSynchronized(bitmap));
        mLongExecutor.execute(() -> onBitmapChangedSynchronized(bitmap));
    }

    private void onBitmapChangedSynchronized(@NonNull Bitmap bitmap) {
@@ -167,7 +167,7 @@ public class WallpaperLocalColorExtractor {
     * @param pages the total number of pages of the launcher
     */
    public void onPageChanged(int pages) {
        mBackgroundExecutor.execute(() -> onPageChangedSynchronized(pages));
        mLongExecutor.execute(() -> onPageChangedSynchronized(pages));
    }

    private void onPageChangedSynchronized(int pages) {
@@ -194,7 +194,7 @@ public class WallpaperLocalColorExtractor {
     */
    public void addLocalColorsAreas(@NonNull List<RectF> regions) {
        if (regions.size() > 0) {
            mBackgroundExecutor.execute(() -> addLocalColorsAreasSynchronized(regions));
            mLongExecutor.execute(() -> addLocalColorsAreasSynchronized(regions));
        } else {
            Log.w(TAG, "Attempt to add colors with an empty list");
        }
@@ -218,7 +218,7 @@ public class WallpaperLocalColorExtractor {
     * @param regions The areas of interest in our wallpaper (in screen pixel coordinates)
     */
    public void removeLocalColorAreas(@NonNull List<RectF> regions) {
        mBackgroundExecutor.execute(() -> removeLocalColorAreasSynchronized(regions));
        mLongExecutor.execute(() -> removeLocalColorAreasSynchronized(regions));
    }

    private void removeLocalColorAreasSynchronized(@NonNull List<RectF> regions) {
@@ -236,7 +236,7 @@ public class WallpaperLocalColorExtractor {
     * Clean up the memory (in particular, the mini bitmap) used by this class.
     */
    public void cleanUp() {
        mBackgroundExecutor.execute(this::cleanUpSynchronized);
        mLongExecutor.execute(this::cleanUpSynchronized);
    }

    private void cleanUpSynchronized() {
+7 −7
Original line number Diff line number Diff line
@@ -88,7 +88,7 @@ public class ImageWallpaperTest extends SysuiTestCase {
    @Mock
    private Bitmap mWallpaperBitmap;
    FakeSystemClock mFakeSystemClock = new FakeSystemClock();
    FakeExecutor mFakeBackgroundExecutor = new FakeExecutor(mFakeSystemClock);
    FakeExecutor mFakeExecutor = new FakeExecutor(mFakeSystemClock);

    @Before
    public void setUp() throws Exception {
@@ -125,7 +125,7 @@ public class ImageWallpaperTest extends SysuiTestCase {

    @Test
    public void testBitmapWallpaper_normal() {
        // Will use a image wallpaper with dimensions DISPLAY_WIDTH x DISPLAY_WIDTH.
        // Will use an image wallpaper with dimensions DISPLAY_WIDTH x DISPLAY_WIDTH.
        // Then we expect the surface size will be also DISPLAY_WIDTH x DISPLAY_WIDTH.
        int bitmapSide = DISPLAY_WIDTH;
        testSurfaceHelper(
@@ -137,7 +137,7 @@ public class ImageWallpaperTest extends SysuiTestCase {

    @Test
    public void testBitmapWallpaper_low_resolution() {
        // Will use a image wallpaper with dimensions BMP_WIDTH x BMP_HEIGHT.
        // Will use an image wallpaper with dimensions BMP_WIDTH x BMP_HEIGHT.
        // Then we expect the surface size will be also BMP_WIDTH x BMP_HEIGHT.
        testSurfaceHelper(LOW_BMP_WIDTH /* bitmapWidth */,
                LOW_BMP_HEIGHT /* bitmapHeight */,
@@ -161,13 +161,13 @@ public class ImageWallpaperTest extends SysuiTestCase {
        ImageWallpaper.CanvasEngine spyEngine = getSpyEngine();
        spyEngine.onCreate(mSurfaceHolder);
        spyEngine.onSurfaceRedrawNeeded(mSurfaceHolder);
        assertThat(mFakeBackgroundExecutor.numPending()).isAtLeast(1);
        assertThat(mFakeExecutor.numPending()).isAtLeast(1);

        int n = 0;
        while (mFakeBackgroundExecutor.numPending() >= 1) {
        while (mFakeExecutor.numPending() >= 1) {
            n++;
            assertThat(n).isAtMost(10);
            mFakeBackgroundExecutor.runNextReady();
            mFakeExecutor.runNextReady();
            mFakeSystemClock.advanceTime(1000);
        }

@@ -176,7 +176,7 @@ public class ImageWallpaperTest extends SysuiTestCase {
    }

    private ImageWallpaper createImageWallpaper() {
        return new ImageWallpaper(mFakeBackgroundExecutor, mUserTracker) {
        return new ImageWallpaper(mFakeExecutor, mUserTracker) {
            @Override
            public Engine onCreateEngine() {
                return new CanvasEngine() {