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
This commit is contained in:
Valentin Iftime
2018-08-24 17:17:26 +02:00
parent 589ce41dd3
commit 6239e53794
3 changed files with 172 additions and 10 deletions

View File

@@ -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,9 +765,19 @@ public abstract class WallpaperService extends Service {
mLayout.x = 0;
mLayout.y = 0;
mLayout.width = myWidth;
mLayout.height = myHeight;
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;
mCurWindowFlags = mWindowFlags;
@@ -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) {

View File

@@ -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;

View File

@@ -0,0 +1,135 @@
/*
* 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);
}
}