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

Commit 6239e537 authored by Valentin Iftime's avatar Valentin Iftime
Browse files

Resize image wallpaper surface to match bitmap size in order to optimize memory

(on AndroidTV there is no need for wallpaper and RAM is wasted)

Bug: 74517029
Test: Push a low resolution wallpaper to the device (adb push new_wallpaper /data/system/users/0/wallpaper),
reboot and check the buffer size for com.android.systemui.ImageWallpaper (adb shell dumpsys SurfaceFlinger)

Change-Id: I992175997ed09360e8fc9c2cabf354fb4fabd1f9
parent 589ce41d
Loading
Loading
Loading
Loading
+21 −5
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ import android.util.Log;
import android.util.MergedConfiguration;
import android.view.Display;
import android.view.DisplayCutout;
import android.view.DisplayInfo;
import android.view.Gravity;
import android.view.IWindowSession;
import android.view.InputChannel;
@@ -163,7 +164,8 @@ public abstract class WallpaperService extends Service {
        int mType;
        int mCurWidth;
        int mCurHeight;
        int mWindowFlags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
        int mWindowFlags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
                         | WindowManager.LayoutParams.FLAG_SCALED;
        int mWindowPrivateFlags =
                WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS;
        int mCurWindowFlags = mWindowFlags;
@@ -763,8 +765,18 @@ public abstract class WallpaperService extends Service {

                    mLayout.x = 0;
                    mLayout.y = 0;

                    if (!fixedSize) {
                        mLayout.width = myWidth;
                        mLayout.height = myHeight;
                    } else {
                        // Force the wallpaper to cover the screen in both dimensions
                        // only internal implementations like ImageWallpaper
                        DisplayInfo displayInfo = new DisplayInfo();
                        mDisplay.getDisplayInfo(displayInfo);
                        mLayout.width = Math.max(displayInfo.logicalWidth, myWidth);
                        mLayout.height = Math.max(displayInfo.logicalHeight, myHeight);
                    }

                    mLayout.format = mFormat;
                    
@@ -773,7 +785,8 @@ public abstract class WallpaperService extends Service {
                            | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
                            | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
                            | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                            | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
                            | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                            | WindowManager.LayoutParams.FLAG_SCALED;
                    mCurWindowPrivateFlags = mWindowPrivateFlags;
                    mLayout.privateFlags = mWindowPrivateFlags;

@@ -847,6 +860,9 @@ public abstract class WallpaperService extends Service {
                        mStableInsets.bottom += padding.bottom;
                        mDisplayCutout.set(mDisplayCutout.get().inset(-padding.left, -padding.top,
                                -padding.right, -padding.bottom));
                    } else {
                        w = myWidth;
                        h = myHeight;
                    }

                    if (mCurWidth != w) {
+16 −5
Original line number Diff line number Diff line
@@ -35,6 +35,8 @@ import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.WindowManager;

import com.android.internal.annotations.VisibleForTesting;

import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
@@ -77,6 +79,13 @@ public class ImageWallpaper extends WallpaperService {
            unloadWallpaper(false /* forgetSize */);
        };

        // Surface is rejected if size below a threshold on some devices (ie. 8px on elfin)
        // set min to 64 px (CTS covers this)
        @VisibleForTesting
        static final int MIN_BACKGROUND_WIDTH = 64;
        @VisibleForTesting
        static final int MIN_BACKGROUND_HEIGHT = 64;

        Bitmap mBackground;
        int mBackgroundWidth = -1, mBackgroundHeight = -1;
        int mLastSurfaceWidth = -1, mLastSurfaceHeight = -1;
@@ -156,9 +165,9 @@ public class ImageWallpaper extends WallpaperService {
                hasWallpaper = false;
            }

            // Force the wallpaper to cover the screen in both dimensions
            int surfaceWidth = Math.max(displayInfo.logicalWidth, mBackgroundWidth);
            int surfaceHeight = Math.max(displayInfo.logicalHeight, mBackgroundHeight);
            // Set surface size equal to bitmap size, prevent memory waste
            int surfaceWidth = Math.max(MIN_BACKGROUND_WIDTH, mBackgroundWidth);
            int surfaceHeight = Math.max(MIN_BACKGROUND_HEIGHT, mBackgroundHeight);

            // Used a fixed size surface, because we are special.  We can do
            // this because we know the current design of window animations doesn't
@@ -257,7 +266,8 @@ public class ImageWallpaper extends WallpaperService {
            drawFrame();
        }

        private DisplayInfo getDefaultDisplayInfo() {
        @VisibleForTesting
        DisplayInfo getDefaultDisplayInfo() {
            mDefaultDisplay.getDisplayInfo(mTmpDisplayInfo);
            return mTmpDisplayInfo;
        }
@@ -420,7 +430,8 @@ public class ImageWallpaper extends WallpaperService {
            }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
        }

        private void updateBitmap(Bitmap bitmap) {
        @VisibleForTesting
        void updateBitmap(Bitmap bitmap) {
            mBackground = null;
            mBackgroundWidth = -1;
            mBackgroundHeight = -1;
+135 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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;


import static org.junit.Assert.assertNotNull;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;

import android.graphics.Bitmap;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.SmallTest;
import android.view.DisplayInfo;
import android.view.SurfaceHolder;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.util.concurrent.CountDownLatch;

@SmallTest
@RunWith(AndroidJUnit4.class)
public class ImageWallpaperTest extends SysuiTestCase {

    private static final int BMP_WIDTH = 128;
    private static final int BMP_HEIGHT = 128;

    private static final int INVALID_BMP_WIDTH = 1;
    private static final int INVALID_BMP_HEIGHT = 1;

    private ImageWallpaper mImageWallpaper;

    @Mock private SurfaceHolder mSurfaceHolder;
    @Mock private DisplayInfo mDisplayInfo;

    CountDownLatch mEventCountdown;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);

        mEventCountdown = new CountDownLatch(1);

        mImageWallpaper = new ImageWallpaper() {
            @Override
            public Engine onCreateEngine() {
                return new DrawableEngine() {
                    @Override
                    DisplayInfo getDefaultDisplayInfo() {
                        return mDisplayInfo;
                    }

                    @Override
                    public SurfaceHolder getSurfaceHolder() {
                        return mSurfaceHolder;
                    }

                    @Override
                    public void setFixedSizeAllowed(boolean allowed) {
                        super.setFixedSizeAllowed(allowed);
                        assertTrue("mFixedSizeAllowed should be true", allowed);
                        mEventCountdown.countDown();
                    }
                };
            }
        };
    }

    @Test
    public void testSetValidBitmapWallpaper() {
        ImageWallpaper.DrawableEngine wallpaperEngine =
                (ImageWallpaper.DrawableEngine) mImageWallpaper.onCreateEngine();

        assertEquals("setFixedSizeAllowed should have been called.",
                0, mEventCountdown.getCount());

        Bitmap mockedBitmap = mock(Bitmap.class);
        when(mockedBitmap.getWidth()).thenReturn(BMP_WIDTH);
        when(mockedBitmap.getHeight()).thenReturn(BMP_HEIGHT);

        wallpaperEngine.updateBitmap(mockedBitmap);

        assertEquals(BMP_WIDTH, wallpaperEngine.mBackgroundWidth);
        assertEquals(BMP_HEIGHT, wallpaperEngine.mBackgroundHeight);

        verify(mSurfaceHolder, times(1)).setFixedSize(BMP_WIDTH, BMP_HEIGHT);

    }

    @Test
    public void testSetTooSmallBitmapWallpaper() {
        ImageWallpaper.DrawableEngine wallpaperEngine =
                (ImageWallpaper.DrawableEngine) mImageWallpaper.onCreateEngine();

        assertEquals("setFixedSizeAllowed should have been called.",
                0, mEventCountdown.getCount());

        Bitmap mockedBitmap = mock(Bitmap.class);
        when(mockedBitmap.getWidth()).thenReturn(INVALID_BMP_WIDTH);
        when(mockedBitmap.getHeight()).thenReturn(INVALID_BMP_HEIGHT);

        wallpaperEngine.updateBitmap(mockedBitmap);

        assertEquals(INVALID_BMP_WIDTH, wallpaperEngine.mBackgroundWidth);
        assertEquals(INVALID_BMP_HEIGHT, wallpaperEngine.mBackgroundHeight);

        verify(mSurfaceHolder, times(1)).setFixedSize(ImageWallpaper.DrawableEngine.MIN_BACKGROUND_WIDTH, ImageWallpaper.DrawableEngine.MIN_BACKGROUND_HEIGHT);
    }

}