Merge "Move image wallpaper rendering works to background thread." into qt-dev

This commit is contained in:
TreeHugger Robot
2019-06-27 07:24:17 +00:00
committed by Android (Google) Code Review
3 changed files with 66 additions and 36 deletions

View File

@@ -19,6 +19,7 @@ package com.android.systemui;
import android.app.ActivityManager; import android.app.ActivityManager;
import android.content.Context; import android.content.Context;
import android.graphics.Rect; import android.graphics.Rect;
import android.os.HandlerThread;
import android.service.wallpaper.WallpaperService; import android.service.wallpaper.WallpaperService;
import android.util.Log; import android.util.Log;
import android.util.Size; import android.util.Size;
@@ -45,12 +46,27 @@ public class ImageWallpaper extends WallpaperService {
// We delayed destroy render context that subsequent render requests have chance to cancel it. // We delayed destroy render context that subsequent render requests have chance to cancel it.
// This is to avoid destroying then recreating render context in a very short time. // This is to avoid destroying then recreating render context in a very short time.
private static final int DELAY_FINISH_RENDERING = 1000; private static final int DELAY_FINISH_RENDERING = 1000;
private HandlerThread mWorker;
@Override
public void onCreate() {
super.onCreate();
mWorker = new HandlerThread(TAG);
mWorker.start();
}
@Override @Override
public Engine onCreateEngine() { public Engine onCreateEngine() {
return new GLEngine(this); return new GLEngine(this);
} }
@Override
public void onDestroy() {
super.onDestroy();
mWorker.quitSafely();
mWorker = null;
}
class GLEngine extends Engine implements GLWallpaperRenderer.SurfaceProxy, StateListener { class GLEngine extends Engine implements GLWallpaperRenderer.SurfaceProxy, StateListener {
// Surface is rejected if size below a threshold on some devices (ie. 8px on elfin) // Surface is rejected if size below a threshold on some devices (ie. 8px on elfin)
// set min to 64 px (CTS covers this), please refer to ag/4867989 for detail. // set min to 64 px (CTS covers this), please refer to ag/4867989 for detail.
@@ -98,13 +114,14 @@ public class ImageWallpaper extends WallpaperService {
@Override @Override
public void onOffsetsChanged(float xOffset, float yOffset, float xOffsetStep, public void onOffsetsChanged(float xOffset, float yOffset, float xOffsetStep,
float yOffsetStep, int xPixelOffset, int yPixelOffset) { float yOffsetStep, int xPixelOffset, int yPixelOffset) {
mRenderer.updateOffsets(xOffset, yOffset); mWorker.getThreadHandler().post(() -> mRenderer.updateOffsets(xOffset, yOffset));
} }
@Override @Override
public void onAmbientModeChanged(boolean inAmbientMode, long animationDuration) { public void onAmbientModeChanged(boolean inAmbientMode, long animationDuration) {
mRenderer.updateAmbientMode(inAmbientMode, long duration = mNeedTransition || animationDuration != 0 ? animationDuration : 0;
(mNeedTransition || animationDuration != 0) ? animationDuration : 0); mWorker.getThreadHandler().post(
() -> mRenderer.updateAmbientMode(inAmbientMode, duration));
} }
@Override @Override
@@ -113,53 +130,61 @@ public class ImageWallpaper extends WallpaperService {
mController.removeCallback(this /* StateListener */); mController.removeCallback(this /* StateListener */);
} }
mController = null; mController = null;
mWorker.getThreadHandler().post(() -> {
mRenderer.finish(); mRenderer.finish();
mRenderer = null; mRenderer = null;
mEglHelper.finish(); mEglHelper.finish();
mEglHelper = null; mEglHelper = null;
getSurfaceHolder().getSurface().hwuiDestroy(); getSurfaceHolder().getSurface().hwuiDestroy();
});
} }
@Override @Override
public void onSurfaceCreated(SurfaceHolder holder) { public void onSurfaceCreated(SurfaceHolder holder) {
mWorker.getThreadHandler().post(() -> {
mEglHelper.init(holder); mEglHelper.init(holder);
mRenderer.onSurfaceCreated(); mRenderer.onSurfaceCreated();
});
} }
@Override @Override
public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) { public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
mWorker.getThreadHandler().post(() -> {
mRenderer.onSurfaceChanged(width, height); mRenderer.onSurfaceChanged(width, height);
mNeedRedraw = true; mNeedRedraw = true;
});
} }
@Override @Override
public void onSurfaceRedrawNeeded(SurfaceHolder holder) { public void onSurfaceRedrawNeeded(SurfaceHolder holder) {
mWorker.getThreadHandler().post(() -> {
if (mNeedRedraw) { if (mNeedRedraw) {
preRender(); preRender();
requestRender(); requestRender();
postRender(); postRender();
mNeedRedraw = false; mNeedRedraw = false;
} }
} });
@Override
public SurfaceHolder getHolder() {
return getSurfaceHolder();
} }
@Override @Override
public void onStatePostChange() { public void onStatePostChange() {
// When back to home, we try to release EGL, which is preserved in lock screen or aod. // When back to home, we try to release EGL, which is preserved in lock screen or aod.
if (mController.getState() == StatusBarState.SHADE) { if (mController.getState() == StatusBarState.SHADE) {
scheduleFinishRendering(); mWorker.getThreadHandler().post(this::scheduleFinishRendering);
} }
} }
@Override @Override
public void preRender() { public void preRender() {
mWorker.getThreadHandler().post(this::preRenderInternal);
}
private void preRenderInternal() {
boolean contextRecreated = false; boolean contextRecreated = false;
Rect frame = getSurfaceHolder().getSurfaceFrame(); Rect frame = getSurfaceHolder().getSurfaceFrame();
getMainThreadHandler().removeCallbacks(mFinishRenderingTask); cancelFinishRenderingTask();
// Check if we need to recreate egl context. // Check if we need to recreate egl context.
if (!mEglHelper.hasEglContext()) { if (!mEglHelper.hasEglContext()) {
@@ -187,6 +212,10 @@ public class ImageWallpaper extends WallpaperService {
@Override @Override
public void requestRender() { public void requestRender() {
mWorker.getThreadHandler().post(this::requestRenderInternal);
}
private void requestRenderInternal() {
Rect frame = getSurfaceHolder().getSurfaceFrame(); Rect frame = getSurfaceHolder().getSurfaceFrame();
boolean readyToRender = mEglHelper.hasEglContext() && mEglHelper.hasEglSurface() boolean readyToRender = mEglHelper.hasEglContext() && mEglHelper.hasEglSurface()
&& frame.width() > 0 && frame.height() > 0; && frame.width() > 0 && frame.height() > 0;
@@ -205,12 +234,16 @@ public class ImageWallpaper extends WallpaperService {
@Override @Override
public void postRender() { public void postRender() {
scheduleFinishRendering(); mWorker.getThreadHandler().post(this::scheduleFinishRendering);
}
private void cancelFinishRenderingTask() {
mWorker.getThreadHandler().removeCallbacks(mFinishRenderingTask);
} }
private void scheduleFinishRendering() { private void scheduleFinishRendering() {
getMainThreadHandler().removeCallbacks(mFinishRenderingTask); cancelFinishRenderingTask();
getMainThreadHandler().postDelayed(mFinishRenderingTask, DELAY_FINISH_RENDERING); mWorker.getThreadHandler().postDelayed(mFinishRenderingTask, DELAY_FINISH_RENDERING);
} }
private void finishRendering() { private void finishRendering() {

View File

@@ -60,6 +60,9 @@ import java.io.PrintWriter;
*/ */
public class EglHelper { public class EglHelper {
private static final String TAG = EglHelper.class.getSimpleName(); private static final String TAG = EglHelper.class.getSimpleName();
// Below two constants make drawing at low priority, so other things can preempt our drawing.
private static final int EGL_CONTEXT_PRIORITY_LEVEL_IMG = 0x3100;
private static final int EGL_CONTEXT_PRIORITY_LOW_IMG = 0x3103;
private EGLDisplay mEglDisplay; private EGLDisplay mEglDisplay;
private EGLConfig mEglConfig; private EGLConfig mEglConfig;
@@ -181,7 +184,8 @@ public class EglHelper {
* @return true if EglContext is ready. * @return true if EglContext is ready.
*/ */
public boolean createEglContext() { public boolean createEglContext() {
int[] attrib_list = new int[] {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE}; int[] attrib_list = new int[] {EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_CONTEXT_PRIORITY_LEVEL_IMG, EGL_CONTEXT_PRIORITY_LOW_IMG, EGL_NONE};
mEglContext = eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT, attrib_list, 0); mEglContext = eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT, attrib_list, 0);
if (mEglContext == EGL_NO_CONTEXT) { if (mEglContext == EGL_NO_CONTEXT) {
Log.w(TAG, "eglCreateContext failed: " + GLUtils.getEGLErrorString(eglGetError())); Log.w(TAG, "eglCreateContext failed: " + GLUtils.getEGLErrorString(eglGetError()));

View File

@@ -17,7 +17,6 @@
package com.android.systemui.glwallpaper; package com.android.systemui.glwallpaper;
import android.util.Size; import android.util.Size;
import android.view.SurfaceHolder;
import java.io.FileDescriptor; import java.io.FileDescriptor;
import java.io.PrintWriter; import java.io.PrintWriter;
@@ -82,12 +81,6 @@ public interface GLWallpaperRenderer {
*/ */
interface SurfaceProxy { interface SurfaceProxy {
/**
* Get surface holder.
* @return surface holder.
*/
SurfaceHolder getHolder();
/** /**
* Ask proxy to start rendering frame to surface. * Ask proxy to start rendering frame to surface.
*/ */