Merge "Move image wallpaper rendering works to background thread." into qt-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
84ed5df87f
@@ -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;
|
||||||
mRenderer.finish();
|
|
||||||
mRenderer = null;
|
mWorker.getThreadHandler().post(() -> {
|
||||||
mEglHelper.finish();
|
mRenderer.finish();
|
||||||
mEglHelper = null;
|
mRenderer = null;
|
||||||
getSurfaceHolder().getSurface().hwuiDestroy();
|
mEglHelper.finish();
|
||||||
|
mEglHelper = null;
|
||||||
|
getSurfaceHolder().getSurface().hwuiDestroy();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSurfaceCreated(SurfaceHolder holder) {
|
public void onSurfaceCreated(SurfaceHolder holder) {
|
||||||
mEglHelper.init(holder);
|
mWorker.getThreadHandler().post(() -> {
|
||||||
mRenderer.onSurfaceCreated();
|
mEglHelper.init(holder);
|
||||||
|
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) {
|
||||||
mRenderer.onSurfaceChanged(width, height);
|
mWorker.getThreadHandler().post(() -> {
|
||||||
mNeedRedraw = true;
|
mRenderer.onSurfaceChanged(width, height);
|
||||||
|
mNeedRedraw = true;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSurfaceRedrawNeeded(SurfaceHolder holder) {
|
public void onSurfaceRedrawNeeded(SurfaceHolder holder) {
|
||||||
if (mNeedRedraw) {
|
mWorker.getThreadHandler().post(() -> {
|
||||||
preRender();
|
if (mNeedRedraw) {
|
||||||
requestRender();
|
preRender();
|
||||||
postRender();
|
requestRender();
|
||||||
mNeedRedraw = false;
|
postRender();
|
||||||
}
|
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() {
|
||||||
|
|||||||
@@ -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()));
|
||||||
|
|||||||
@@ -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.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user