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:
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user