Merge "Move image wallpaper rendering works to background thread." into qt-dev
am: 84ed5df87f
Change-Id: Id7b816deec2b048e5f6fd641ed44de1ca23c91ff
This commit is contained in:
@@ -19,6 +19,7 @@ package com.android.systemui;
|
||||
import android.app.ActivityManager;
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.os.HandlerThread;
|
||||
import android.service.wallpaper.WallpaperService;
|
||||
import android.util.Log;
|
||||
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.
|
||||
// This is to avoid destroying then recreating render context in a very short time.
|
||||
private static final int DELAY_FINISH_RENDERING = 1000;
|
||||
private HandlerThread mWorker;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
mWorker = new HandlerThread(TAG);
|
||||
mWorker.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Engine onCreateEngine() {
|
||||
return new GLEngine(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
mWorker.quitSafely();
|
||||
mWorker = null;
|
||||
}
|
||||
|
||||
class GLEngine extends Engine implements GLWallpaperRenderer.SurfaceProxy, StateListener {
|
||||
// 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.
|
||||
@@ -98,13 +114,14 @@ public class ImageWallpaper extends WallpaperService {
|
||||
@Override
|
||||
public void onOffsetsChanged(float xOffset, float yOffset, float xOffsetStep,
|
||||
float yOffsetStep, int xPixelOffset, int yPixelOffset) {
|
||||
mRenderer.updateOffsets(xOffset, yOffset);
|
||||
mWorker.getThreadHandler().post(() -> mRenderer.updateOffsets(xOffset, yOffset));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAmbientModeChanged(boolean inAmbientMode, long animationDuration) {
|
||||
mRenderer.updateAmbientMode(inAmbientMode,
|
||||
(mNeedTransition || animationDuration != 0) ? animationDuration : 0);
|
||||
long duration = mNeedTransition || animationDuration != 0 ? animationDuration : 0;
|
||||
mWorker.getThreadHandler().post(
|
||||
() -> mRenderer.updateAmbientMode(inAmbientMode, duration));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -113,53 +130,61 @@ public class ImageWallpaper extends WallpaperService {
|
||||
mController.removeCallback(this /* StateListener */);
|
||||
}
|
||||
mController = null;
|
||||
mRenderer.finish();
|
||||
mRenderer = null;
|
||||
mEglHelper.finish();
|
||||
mEglHelper = null;
|
||||
getSurfaceHolder().getSurface().hwuiDestroy();
|
||||
|
||||
mWorker.getThreadHandler().post(() -> {
|
||||
mRenderer.finish();
|
||||
mRenderer = null;
|
||||
mEglHelper.finish();
|
||||
mEglHelper = null;
|
||||
getSurfaceHolder().getSurface().hwuiDestroy();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceCreated(SurfaceHolder holder) {
|
||||
mEglHelper.init(holder);
|
||||
mRenderer.onSurfaceCreated();
|
||||
mWorker.getThreadHandler().post(() -> {
|
||||
mEglHelper.init(holder);
|
||||
mRenderer.onSurfaceCreated();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
|
||||
mRenderer.onSurfaceChanged(width, height);
|
||||
mNeedRedraw = true;
|
||||
mWorker.getThreadHandler().post(() -> {
|
||||
mRenderer.onSurfaceChanged(width, height);
|
||||
mNeedRedraw = true;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceRedrawNeeded(SurfaceHolder holder) {
|
||||
if (mNeedRedraw) {
|
||||
preRender();
|
||||
requestRender();
|
||||
postRender();
|
||||
mNeedRedraw = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SurfaceHolder getHolder() {
|
||||
return getSurfaceHolder();
|
||||
mWorker.getThreadHandler().post(() -> {
|
||||
if (mNeedRedraw) {
|
||||
preRender();
|
||||
requestRender();
|
||||
postRender();
|
||||
mNeedRedraw = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStatePostChange() {
|
||||
// When back to home, we try to release EGL, which is preserved in lock screen or aod.
|
||||
if (mController.getState() == StatusBarState.SHADE) {
|
||||
scheduleFinishRendering();
|
||||
mWorker.getThreadHandler().post(this::scheduleFinishRendering);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRender() {
|
||||
mWorker.getThreadHandler().post(this::preRenderInternal);
|
||||
}
|
||||
|
||||
private void preRenderInternal() {
|
||||
boolean contextRecreated = false;
|
||||
Rect frame = getSurfaceHolder().getSurfaceFrame();
|
||||
getMainThreadHandler().removeCallbacks(mFinishRenderingTask);
|
||||
cancelFinishRenderingTask();
|
||||
|
||||
// Check if we need to recreate egl context.
|
||||
if (!mEglHelper.hasEglContext()) {
|
||||
@@ -187,6 +212,10 @@ public class ImageWallpaper extends WallpaperService {
|
||||
|
||||
@Override
|
||||
public void requestRender() {
|
||||
mWorker.getThreadHandler().post(this::requestRenderInternal);
|
||||
}
|
||||
|
||||
private void requestRenderInternal() {
|
||||
Rect frame = getSurfaceHolder().getSurfaceFrame();
|
||||
boolean readyToRender = mEglHelper.hasEglContext() && mEglHelper.hasEglSurface()
|
||||
&& frame.width() > 0 && frame.height() > 0;
|
||||
@@ -205,12 +234,16 @@ public class ImageWallpaper extends WallpaperService {
|
||||
|
||||
@Override
|
||||
public void postRender() {
|
||||
scheduleFinishRendering();
|
||||
mWorker.getThreadHandler().post(this::scheduleFinishRendering);
|
||||
}
|
||||
|
||||
private void cancelFinishRenderingTask() {
|
||||
mWorker.getThreadHandler().removeCallbacks(mFinishRenderingTask);
|
||||
}
|
||||
|
||||
private void scheduleFinishRendering() {
|
||||
getMainThreadHandler().removeCallbacks(mFinishRenderingTask);
|
||||
getMainThreadHandler().postDelayed(mFinishRenderingTask, DELAY_FINISH_RENDERING);
|
||||
cancelFinishRenderingTask();
|
||||
mWorker.getThreadHandler().postDelayed(mFinishRenderingTask, DELAY_FINISH_RENDERING);
|
||||
}
|
||||
|
||||
private void finishRendering() {
|
||||
|
||||
@@ -60,6 +60,9 @@ import java.io.PrintWriter;
|
||||
*/
|
||||
public class EglHelper {
|
||||
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 EGLConfig mEglConfig;
|
||||
@@ -181,7 +184,8 @@ public class EglHelper {
|
||||
* @return true if EglContext is ready.
|
||||
*/
|
||||
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);
|
||||
if (mEglContext == EGL_NO_CONTEXT) {
|
||||
Log.w(TAG, "eglCreateContext failed: " + GLUtils.getEGLErrorString(eglGetError()));
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package com.android.systemui.glwallpaper;
|
||||
|
||||
import android.util.Size;
|
||||
import android.view.SurfaceHolder;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
@@ -82,12 +81,6 @@ public interface GLWallpaperRenderer {
|
||||
*/
|
||||
interface SurfaceProxy {
|
||||
|
||||
/**
|
||||
* Get surface holder.
|
||||
* @return surface holder.
|
||||
*/
|
||||
SurfaceHolder getHolder();
|
||||
|
||||
/**
|
||||
* Ask proxy to start rendering frame to surface.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user