summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/src/com/android/systemui/ImageWallpaper.java64
-rw-r--r--packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java17
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java164
3 files changed, 215 insertions, 30 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index e50d08c0cf9d..03bc738c8ab9 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -18,12 +18,14 @@ package com.android.systemui;
import android.app.ActivityManager;
import android.content.Context;
+import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.HandlerThread;
import android.os.Trace;
import android.service.wallpaper.WallpaperService;
import android.util.Log;
import android.util.Size;
+import android.view.DisplayInfo;
import android.view.SurfaceHolder;
import com.android.internal.annotations.VisibleForTesting;
@@ -93,14 +95,20 @@ public class ImageWallpaper extends WallpaperService {
private StatusBarStateController mController;
private final Runnable mFinishRenderingTask = this::finishRendering;
private final boolean mNeedTransition;
+ private boolean mShouldStopTransition;
+ @VisibleForTesting
+ final boolean mIsHighEndGfx;
+ private final boolean mDisplayNeedsBlanking;
+ private final DisplayInfo mDisplayInfo = new DisplayInfo();
private final Object mMonitor = new Object();
private boolean mNeedRedraw;
// This variable can only be accessed in synchronized block.
private boolean mWaitingForRendering;
GLEngine(Context context, DozeParameters dozeParameters) {
- mNeedTransition = ActivityManager.isHighEndGfx()
- && !dozeParameters.getDisplayNeedsBlanking();
+ mIsHighEndGfx = ActivityManager.isHighEndGfx();
+ mDisplayNeedsBlanking = dozeParameters.getDisplayNeedsBlanking();
+ mNeedTransition = mIsHighEndGfx && !mDisplayNeedsBlanking;
// We will preserve EGL context when we are in lock screen or aod
// to avoid janking in following transition, we need to release when back to home.
@@ -112,14 +120,23 @@ public class ImageWallpaper extends WallpaperService {
@Override
public void onCreate(SurfaceHolder surfaceHolder) {
- mEglHelper = new EglHelper();
+ mEglHelper = getEglHelperInstance();
// Deferred init renderer because we need to get wallpaper by display context.
- mRenderer = new ImageWallpaperRenderer(getDisplayContext(), this /* SurfaceProxy */);
+ mRenderer = getRendererInstance();
+ getDisplayContext().getDisplay().getDisplayInfo(mDisplayInfo);
setFixedSizeAllowed(true);
setOffsetNotificationsEnabled(true);
updateSurfaceSize();
}
+ EglHelper getEglHelperInstance() {
+ return new EglHelper();
+ }
+
+ ImageWallpaperRenderer getRendererInstance() {
+ return new ImageWallpaperRenderer(getDisplayContext(), this /* SurfaceProxy */);
+ }
+
private void updateSurfaceSize() {
SurfaceHolder holder = getSurfaceHolder();
Size frameSize = mRenderer.reportSurfaceSize();
@@ -128,6 +145,26 @@ public class ImageWallpaper extends WallpaperService {
holder.setFixedSize(width, height);
}
+ /**
+ * Check if necessary to stop transition with current wallpaper on this device. <br/>
+ * This should only be invoked after {@link #onSurfaceCreated(SurfaceHolder)}}
+ * is invoked since it needs display context and surface frame size.
+ * @return true if need to stop transition.
+ */
+ @VisibleForTesting
+ boolean checkIfShouldStopTransition() {
+ int orientation = getDisplayContext().getResources().getConfiguration().orientation;
+ Rect frame = getSurfaceHolder().getSurfaceFrame();
+ Rect display = new Rect();
+ if (orientation == Configuration.ORIENTATION_PORTRAIT) {
+ display.set(0, 0, mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
+ } else {
+ display.set(0, 0, mDisplayInfo.logicalHeight, mDisplayInfo.logicalWidth);
+ }
+ return mNeedTransition
+ && (frame.width() < display.width() || frame.height() < display.height());
+ }
+
@Override
public void onOffsetsChanged(float xOffset, float yOffset, float xOffsetStep,
float yOffsetStep, int xPixelOffset, int yPixelOffset) {
@@ -137,12 +174,14 @@ public class ImageWallpaper extends WallpaperService {
@Override
public void onAmbientModeChanged(boolean inAmbientMode, long animationDuration) {
if (!mNeedTransition) return;
+ final long duration = mShouldStopTransition ? 0 : animationDuration;
if (DEBUG) {
Log.d(TAG, "onAmbientModeChanged: inAmbient=" + inAmbientMode
- + ", duration=" + animationDuration);
+ + ", duration=" + duration
+ + ", mShouldStopTransition=" + mShouldStopTransition);
}
mWorker.getThreadHandler().post(
- () -> mRenderer.updateAmbientMode(inAmbientMode, animationDuration));
+ () -> mRenderer.updateAmbientMode(inAmbientMode, duration));
if (inAmbientMode && animationDuration == 0) {
// This means that we are transiting from home to aod, to avoid
// race condition between window visibility and transition,
@@ -183,6 +222,7 @@ public class ImageWallpaper extends WallpaperService {
@Override
public void onSurfaceCreated(SurfaceHolder holder) {
+ mShouldStopTransition = checkIfShouldStopTransition();
mWorker.getThreadHandler().post(() -> {
mEglHelper.init(holder, needSupportWideColorGamut());
mRenderer.onSurfaceCreated();
@@ -348,15 +388,13 @@ public class ImageWallpaper extends WallpaperService {
protected void dump(String prefix, FileDescriptor fd, PrintWriter out, String[] args) {
super.dump(prefix, fd, out, args);
out.print(prefix); out.print("Engine="); out.println(this);
-
- boolean isHighEndGfx = ActivityManager.isHighEndGfx();
- out.print(prefix); out.print("isHighEndGfx="); out.println(isHighEndGfx);
-
+ out.print(prefix); out.print("isHighEndGfx="); out.println(mIsHighEndGfx);
out.print(prefix); out.print("displayNeedsBlanking=");
- out.println(
- mDozeParameters != null ? mDozeParameters.getDisplayNeedsBlanking() : "null");
-
+ out.println(mDisplayNeedsBlanking);
+ out.print(prefix); out.print("displayInfo="); out.print(mDisplayInfo);
out.print(prefix); out.print("mNeedTransition="); out.println(mNeedTransition);
+ out.print(prefix); out.print("mShouldStopTransition=");
+ out.println(mShouldStopTransition);
out.print(prefix); out.print("StatusBarState=");
out.println(mController != null ? mController.getState() : "null");
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
index fa8269d1c198..ed6675dcba2e 100644
--- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
@@ -31,7 +31,6 @@ import android.util.Log;
import android.util.MathUtils;
import android.util.Size;
import android.view.DisplayInfo;
-import android.view.WindowManager;
import com.android.systemui.R;
@@ -71,8 +70,7 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer,
}
DisplayInfo displayInfo = new DisplayInfo();
- WindowManager wm = context.getSystemService(WindowManager.class);
- wm.getDefaultDisplay().getDisplayInfo(displayInfo);
+ context.getDisplay().getDisplayInfo(displayInfo);
// We only do transition in portrait currently, b/137962047.
int orientation = context.getResources().getConfiguration().orientation;
@@ -88,6 +86,10 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer,
mImageProcessHelper = new ImageProcessHelper();
mImageRevealHelper = new ImageRevealHelper(this);
+ startProcessingImage();
+ }
+
+ protected void startProcessingImage() {
if (loadBitmap()) {
// Compute threshold of the image, this is an async work.
mImageProcessHelper.start(mBitmap);
@@ -113,7 +115,7 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer,
mBitmap = null;
}
- private boolean loadBitmap() {
+ protected boolean loadBitmap() {
if (DEBUG) {
Log.d(TAG, "loadBitmap: mBitmap=" + mBitmap);
}
@@ -122,12 +124,7 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer,
mWcgContent = mWallpaperManager.wallpaperSupportsWcg(WallpaperManager.FLAG_SYSTEM);
mWallpaperManager.forgetLoadedWallpaper();
if (mBitmap != null) {
- float scale = (float) mScissor.height() / mBitmap.getHeight();
- int surfaceHeight = Math.max(mScissor.height(), mBitmap.getHeight());
- int surfaceWidth = scale > 1f
- ? Math.round(mBitmap.getWidth() * scale)
- : mBitmap.getWidth();
- mSurfaceSize.set(0, 0, surfaceWidth, surfaceHeight);
+ mSurfaceSize.set(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
}
}
if (DEBUG) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java b/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java
index 48a536924475..fc331d6adccc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java
@@ -16,35 +16,185 @@
package com.android.systemui;
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.WallpaperManager;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.ColorSpace;
+import android.graphics.Rect;
+import android.hardware.display.DisplayManagerGlobal;
import android.test.suitebuilder.annotation.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.util.Size;
+import android.view.Display;
+import android.view.DisplayInfo;
+import android.view.SurfaceHolder;
-import androidx.test.runner.AndroidJUnit4;
+import com.android.systemui.glwallpaper.ImageWallpaperRenderer;
+import com.android.systemui.statusbar.phone.DozeParameters;
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)
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
public class ImageWallpaperTest extends SysuiTestCase {
+ private static final int LOW_BMP_WIDTH = 128;
+ private static final int LOW_BMP_HEIGHT = 128;
+ private static final int INVALID_BMP_WIDTH = 1;
+ private static final int INVALID_BMP_HEIGHT = 1;
+ private static final int DISPLAY_WIDTH = 1920;
+ private static final int DISPLAY_HEIGHT = 1080;
+
+ @Mock
+ private SurfaceHolder mSurfaceHolder;
+ @Mock
+ private Context mMockContext;
+ @Mock
+ private Bitmap mWallpaperBitmap;
+ @Mock
+ private DozeParameters mDozeParam;
private CountDownLatch mEventCountdown;
- private CountDownLatch mAmbientEventCountdown;
@Before
public void setUp() throws Exception {
+ com.android.systemui.util.Assert.sMainLooper = TestableLooper.get(this).getLooper();
MockitoAnnotations.initMocks(this);
mEventCountdown = new CountDownLatch(1);
- mAmbientEventCountdown = new CountDownLatch(2);
+
+ WallpaperManager wallpaperManager = mock(WallpaperManager.class);
+ Resources resources = mock(Resources.class);
+
+ when(mMockContext.getSystemService(WallpaperManager.class)).thenReturn(wallpaperManager);
+ when(mMockContext.getResources()).thenReturn(resources);
+ when(resources.getConfiguration()).thenReturn(mock(Configuration.class));
+
+ DisplayInfo displayInfo = new DisplayInfo();
+ displayInfo.logicalWidth = DISPLAY_WIDTH;
+ displayInfo.logicalHeight = DISPLAY_HEIGHT;
+ when(mMockContext.getDisplay()).thenReturn(
+ new Display(mock(DisplayManagerGlobal.class), 0, displayInfo, (Resources) null));
+
+ when(wallpaperManager.getBitmap(false)).thenReturn(mWallpaperBitmap);
+ when(mWallpaperBitmap.getColorSpace()).thenReturn(ColorSpace.get(ColorSpace.Named.SRGB));
+ when(mWallpaperBitmap.getConfig()).thenReturn(Bitmap.Config.ARGB_8888);
+ when(mDozeParam.getDisplayNeedsBlanking()).thenReturn(false);
+ }
+
+ private ImageWallpaper createImageWallpaper() {
+ return new ImageWallpaper(mDozeParam) {
+ @Override
+ public Engine onCreateEngine() {
+ return new GLEngine(mMockContext, mDozeParam) {
+ @Override
+ public Context getDisplayContext() {
+ return mMockContext;
+ }
+
+ @Override
+ public SurfaceHolder getSurfaceHolder() {
+ return mSurfaceHolder;
+ }
+
+ @Override
+ public void setFixedSizeAllowed(boolean allowed) {
+ super.setFixedSizeAllowed(allowed);
+ assertWithMessage("mFixedSizeAllowed should be true").that(
+ allowed).isTrue();
+ mEventCountdown.countDown();
+ }
+ };
+ }
+ };
+ }
+
+ private ImageWallpaperRenderer createImageWallpaperRenderer(ImageWallpaper.GLEngine engine) {
+ return new ImageWallpaperRenderer(mMockContext, engine) {
+ @Override
+ public void startProcessingImage() {
+ loadBitmap();
+ }
+ };
}
@Test
- public void testDeliversAmbientModeChanged() {
- //TODO: We need add tests for GLEngine.
+ public void testBitmapWallpaper_normal() {
+ // Will use a image wallpaper with dimensions DISPLAY_WIDTH x DISPLAY_WIDTH.
+ // Then we expect the surface size will be also DISPLAY_WIDTH x DISPLAY_WIDTH.
+ // Finally, we assert the transition will not be stopped.
+ verifySurfaceSizeAndAssertTransition(DISPLAY_WIDTH /* bmpWidth */,
+ DISPLAY_WIDTH /* bmpHeight */,
+ DISPLAY_WIDTH /* surfaceWidth */,
+ DISPLAY_WIDTH /* surfaceHeight */,
+ false /* assertion */);
}
- // TODO: Add more test cases for GLEngine, tracing in b/124838911.
+ @Test
+ public void testBitmapWallpaper_low_resolution() {
+ // Will use a image wallpaper with dimensions BMP_WIDTH x BMP_HEIGHT.
+ // Then we expect the surface size will be also BMP_WIDTH x BMP_HEIGHT.
+ // Finally, we assert the transition will be stopped.
+ verifySurfaceSizeAndAssertTransition(LOW_BMP_WIDTH /* bmpWidth */,
+ LOW_BMP_HEIGHT /* bmpHeight */,
+ LOW_BMP_WIDTH /* surfaceWidth */,
+ LOW_BMP_HEIGHT /* surfaceHeight */,
+ true /* assertion */);
+ }
+
+ @Test
+ public void testBitmapWallpaper_too_small() {
+ // Will use a image wallpaper with dimensions INVALID_BMP_WIDTH x INVALID_BMP_HEIGHT.
+ // Then we expect the surface size will be also MIN_SURFACE_WIDTH x MIN_SURFACE_HEIGHT.
+ // Finally, we assert the transition will be stopped.
+ verifySurfaceSizeAndAssertTransition(INVALID_BMP_WIDTH /* bmpWidth */,
+ INVALID_BMP_HEIGHT /* bmpHeight */,
+ ImageWallpaper.GLEngine.MIN_SURFACE_WIDTH /* surfaceWidth */,
+ ImageWallpaper.GLEngine.MIN_SURFACE_HEIGHT /* surfaceHeight */,
+ true /* assertion */);
+ }
+
+ private void verifySurfaceSizeAndAssertTransition(int bmpWidth, int bmpHeight,
+ int surfaceWidth, int surfaceHeight, boolean assertion) {
+ ImageWallpaper.GLEngine wallpaperEngine =
+ (ImageWallpaper.GLEngine) createImageWallpaper().onCreateEngine();
+
+ ImageWallpaper.GLEngine engineSpy = spy(wallpaperEngine);
+ when(engineSpy.mIsHighEndGfx).thenReturn(true);
+
+ when(mWallpaperBitmap.getWidth()).thenReturn(bmpWidth);
+ when(mWallpaperBitmap.getHeight()).thenReturn(bmpHeight);
+
+ ImageWallpaperRenderer renderer = createImageWallpaperRenderer(engineSpy);
+ doReturn(renderer).when(engineSpy).getRendererInstance();
+ engineSpy.onCreate(engineSpy.getSurfaceHolder());
+
+ verify(mSurfaceHolder, times(1)).setFixedSize(surfaceWidth, surfaceHeight);
+ assertWithMessage("setFixedSizeAllowed should have been called.").that(
+ mEventCountdown.getCount()).isEqualTo(0);
+
+ Size frameSize = renderer.reportSurfaceSize();
+ Rect frame = new Rect(0, 0, frameSize.getWidth(), frameSize.getHeight());
+ when(mSurfaceHolder.getSurfaceFrame()).thenReturn(frame);
+
+ assertThat(engineSpy.checkIfShouldStopTransition()).isEqualTo(assertion);
+ }
}