diff options
3 files changed, 66 insertions, 36 deletions
| diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java index e9eda4f5577b..9a0e9fc92af6 100644 --- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java +++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java @@ -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() { diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/EglHelper.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/EglHelper.java index 1744c4e5af19..d74112608491 100644 --- a/packages/SystemUI/src/com/android/systemui/glwallpaper/EglHelper.java +++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/EglHelper.java @@ -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())); diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/GLWallpaperRenderer.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/GLWallpaperRenderer.java index b615a5f32835..60ea1cdf6b22 100644 --- a/packages/SystemUI/src/com/android/systemui/glwallpaper/GLWallpaperRenderer.java +++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/GLWallpaperRenderer.java @@ -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; @@ -83,12 +82,6 @@ public interface GLWallpaperRenderer {      interface SurfaceProxy {          /** -         * Get surface holder. -         * @return surface holder. -         */ -        SurfaceHolder getHolder(); - -        /**           * Ask proxy to start rendering frame to surface.           */          void requestRender(); |