Loading packages/SystemUI/AndroidManifest.xml +5 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,11 @@ android:sharedUserId="android.uid.systemui" coreApp="true"> <!-- Using OpenGL ES 2.0 --> <uses-feature android:glEsVersion="0x00020000" android:required="true" /> <!-- SysUI must be the one to define this permission; its name is referenced by the core OS. --> <permission android:name="android.permission.systemui.IDENTITY" Loading packages/SystemUI/res/raw/image_wallpaper_fragment_shader.glsl 0 → 100644 +27 −0 Original line number Diff line number Diff line precision mediump float; uniform sampler2D uTexture; uniform float uCenterReveal; uniform float uReveal; uniform float uAod2Opacity; varying vec2 vTextureCoordinates; vec3 luminosity(vec3 color) { float lum = 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b; return vec3(lum); } vec4 transform(vec3 diffuse) { // TODO: Add well comments here, tracking on b/123615467. vec3 lum = luminosity(diffuse); diffuse = mix(diffuse, lum, smoothstep(0., uCenterReveal, uReveal)); float val = mix(uReveal, uCenterReveal, step(uCenterReveal, uReveal)); diffuse = smoothstep(val, 1.0, diffuse); diffuse *= uAod2Opacity * (1. - smoothstep(uCenterReveal, 1., uReveal)); return vec4(diffuse.r, diffuse.g, diffuse.b, 1.); } void main() { vec4 fragColor = texture2D(uTexture, vTextureCoordinates); gl_FragColor = transform(fragColor.rgb); } No newline at end of file packages/SystemUI/res/raw/image_wallpaper_vertex_shader.glsl 0 → 100644 +8 −0 Original line number Diff line number Diff line attribute vec4 aPosition; attribute vec2 aTextureCoordinates; varying vec2 vTextureCoordinates; void main() { vTextureCoordinates = aTextureCoordinates; gl_Position = aPosition; } No newline at end of file packages/SystemUI/src/com/android/systemui/ImageWallpaper.java +104 −2 Original line number Diff line number Diff line Loading @@ -28,7 +28,9 @@ import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Region.Op; import android.hardware.display.DisplayManager; import android.opengl.GLSurfaceView; import android.os.AsyncTask; import android.os.Build; import android.os.Handler; import android.os.Trace; import android.service.wallpaper.WallpaperService; Loading @@ -39,6 +41,7 @@ import android.view.Surface; import android.view.SurfaceHolder; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.glwallpaper.ImageWallpaperRenderer; import java.io.FileDescriptor; import java.io.IOException; Loading Loading @@ -73,10 +76,78 @@ public class ImageWallpaper extends WallpaperService { @Override public Engine onCreateEngine() { mEngine = new DrawableEngine(); return mEngine; if (Build.IS_DEBUGGABLE) { Log.v(TAG, "We are using GLEngine"); } return new GLEngine(this); } class GLEngine extends Engine { private GLWallpaperSurfaceView mWallpaperSurfaceView; GLEngine(Context context) { mWallpaperSurfaceView = new GLWallpaperSurfaceView(context); mWallpaperSurfaceView.setRenderer( new ImageWallpaperRenderer(context, mWallpaperSurfaceView)); mWallpaperSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); setOffsetNotificationsEnabled(true); } @Override public void onAmbientModeChanged(boolean inAmbientMode, long animationDuration) { if (mWallpaperSurfaceView != null) { mWallpaperSurfaceView.notifyAmbientModeChanged(inAmbientMode, animationDuration); } } @Override public void onOffsetsChanged(float xOffset, float yOffset, float xOffsetStep, float yOffsetStep, int xPixelOffset, int yPixelOffset) { if (mWallpaperSurfaceView != null) { mWallpaperSurfaceView.notifyOffsetsChanged(xOffset, yOffset); } } private class GLWallpaperSurfaceView extends GLSurfaceView implements ImageGLView { private WallpaperStatusListener mWallpaperChangedListener; GLWallpaperSurfaceView(Context context) { super(context); setEGLContextClientVersion(2); } @Override public SurfaceHolder getHolder() { return getSurfaceHolder(); } @Override public void setRenderer(Renderer renderer) { super.setRenderer(renderer); mWallpaperChangedListener = (WallpaperStatusListener) renderer; } private void notifyAmbientModeChanged(boolean inAmbient, long duration) { if (mWallpaperChangedListener != null) { mWallpaperChangedListener.onAmbientModeChanged(inAmbient, duration); } } private void notifyOffsetsChanged(float xOffset, float yOffset) { if (mWallpaperChangedListener != null) { mWallpaperChangedListener.onOffsetsChanged( xOffset, yOffset, getHolder().getSurfaceFrame()); } } @Override public void render() { requestRender(); } } } // TODO: Remove this engine, tracking on b/123617158. class DrawableEngine extends Engine { private final Runnable mUnloadWallpaperCallback = () -> { unloadWallpaper(false /* forgetSize */); Loading Loading @@ -564,4 +635,35 @@ public class ImageWallpaper extends WallpaperService { } } } /** * A listener to trace status of image wallpaper. */ public interface WallpaperStatusListener { /** * Called back while ambient mode changes. * @param inAmbientMode true if is in ambient mode, false otherwise. * @param duration the duration of animation. */ void onAmbientModeChanged(boolean inAmbientMode, long duration); /** * Called back while wallpaper offsets. * @param xOffset The offset portion along x. * @param yOffset The offset portion along y. */ void onOffsetsChanged(float xOffset, float yOffset, Rect frame); } /** * An abstraction for view of GLRenderer. */ public interface ImageGLView { /** * Ask the view to render. */ void render(); } } packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLProgram.java 0 → 100644 +115 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.glwallpaper; import static android.opengl.GLES20.GL_FRAGMENT_SHADER; import static android.opengl.GLES20.GL_VERTEX_SHADER; import static android.opengl.GLES20.glAttachShader; import static android.opengl.GLES20.glCompileShader; import static android.opengl.GLES20.glCreateProgram; import static android.opengl.GLES20.glCreateShader; import static android.opengl.GLES20.glGetAttribLocation; import static android.opengl.GLES20.glGetUniformLocation; import static android.opengl.GLES20.glLinkProgram; import static android.opengl.GLES20.glShaderSource; import static android.opengl.GLES20.glUseProgram; import android.content.Context; import android.content.res.Resources; import android.util.Log; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; /** * This class takes charge of linking shader codes and then return a handle for OpenGL ES program. */ class ImageGLProgram { private static final String TAG = ImageGLProgram.class.getSimpleName(); private Context mContext; private int mProgramHandle; ImageGLProgram(Context context) { mContext = context.getApplicationContext(); } private int loadShaderProgram(int vertexId, int fragmentId) { final String vertexSrc = getShaderResource(vertexId); final String fragmentSrc = getShaderResource(fragmentId); final int vertexHandle = getShaderHandle(GL_VERTEX_SHADER, vertexSrc); final int fragmentHandle = getShaderHandle(GL_FRAGMENT_SHADER, fragmentSrc); return getProgramHandle(vertexHandle, fragmentHandle); } private String getShaderResource(int shaderId) { Resources res = mContext.getResources(); StringBuilder code = new StringBuilder(); try (BufferedReader reader = new BufferedReader( new InputStreamReader(res.openRawResource(shaderId)))) { String nextLine; while ((nextLine = reader.readLine()) != null) { code.append(nextLine).append("\n"); } } catch (IOException | Resources.NotFoundException ex) { Log.d(TAG, "Can not read the shader source", ex); code = null; } return code == null ? "" : code.toString(); } private int getShaderHandle(int type, String src) { final int shader = glCreateShader(type); if (shader == 0) { Log.d(TAG, "Create shader failed, type=" + type); return 0; } glShaderSource(shader, src); glCompileShader(shader); return shader; } private int getProgramHandle(int vertexHandle, int fragmentHandle) { final int program = glCreateProgram(); if (program == 0) { Log.d(TAG, "Can not create OpenGL ES program"); return 0; } glAttachShader(program, vertexHandle); glAttachShader(program, fragmentHandle); glLinkProgram(program); return program; } boolean useGLProgram(int vertexResId, int fragmentResId) { mProgramHandle = loadShaderProgram(vertexResId, fragmentResId); glUseProgram(mProgramHandle); return true; } int getAttributeHandle(String name) { return glGetAttribLocation(mProgramHandle, name); } int getUniformHandle(String name) { return glGetUniformLocation(mProgramHandle, name); } } Loading
packages/SystemUI/AndroidManifest.xml +5 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,11 @@ android:sharedUserId="android.uid.systemui" coreApp="true"> <!-- Using OpenGL ES 2.0 --> <uses-feature android:glEsVersion="0x00020000" android:required="true" /> <!-- SysUI must be the one to define this permission; its name is referenced by the core OS. --> <permission android:name="android.permission.systemui.IDENTITY" Loading
packages/SystemUI/res/raw/image_wallpaper_fragment_shader.glsl 0 → 100644 +27 −0 Original line number Diff line number Diff line precision mediump float; uniform sampler2D uTexture; uniform float uCenterReveal; uniform float uReveal; uniform float uAod2Opacity; varying vec2 vTextureCoordinates; vec3 luminosity(vec3 color) { float lum = 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b; return vec3(lum); } vec4 transform(vec3 diffuse) { // TODO: Add well comments here, tracking on b/123615467. vec3 lum = luminosity(diffuse); diffuse = mix(diffuse, lum, smoothstep(0., uCenterReveal, uReveal)); float val = mix(uReveal, uCenterReveal, step(uCenterReveal, uReveal)); diffuse = smoothstep(val, 1.0, diffuse); diffuse *= uAod2Opacity * (1. - smoothstep(uCenterReveal, 1., uReveal)); return vec4(diffuse.r, diffuse.g, diffuse.b, 1.); } void main() { vec4 fragColor = texture2D(uTexture, vTextureCoordinates); gl_FragColor = transform(fragColor.rgb); } No newline at end of file
packages/SystemUI/res/raw/image_wallpaper_vertex_shader.glsl 0 → 100644 +8 −0 Original line number Diff line number Diff line attribute vec4 aPosition; attribute vec2 aTextureCoordinates; varying vec2 vTextureCoordinates; void main() { vTextureCoordinates = aTextureCoordinates; gl_Position = aPosition; } No newline at end of file
packages/SystemUI/src/com/android/systemui/ImageWallpaper.java +104 −2 Original line number Diff line number Diff line Loading @@ -28,7 +28,9 @@ import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Region.Op; import android.hardware.display.DisplayManager; import android.opengl.GLSurfaceView; import android.os.AsyncTask; import android.os.Build; import android.os.Handler; import android.os.Trace; import android.service.wallpaper.WallpaperService; Loading @@ -39,6 +41,7 @@ import android.view.Surface; import android.view.SurfaceHolder; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.glwallpaper.ImageWallpaperRenderer; import java.io.FileDescriptor; import java.io.IOException; Loading Loading @@ -73,10 +76,78 @@ public class ImageWallpaper extends WallpaperService { @Override public Engine onCreateEngine() { mEngine = new DrawableEngine(); return mEngine; if (Build.IS_DEBUGGABLE) { Log.v(TAG, "We are using GLEngine"); } return new GLEngine(this); } class GLEngine extends Engine { private GLWallpaperSurfaceView mWallpaperSurfaceView; GLEngine(Context context) { mWallpaperSurfaceView = new GLWallpaperSurfaceView(context); mWallpaperSurfaceView.setRenderer( new ImageWallpaperRenderer(context, mWallpaperSurfaceView)); mWallpaperSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); setOffsetNotificationsEnabled(true); } @Override public void onAmbientModeChanged(boolean inAmbientMode, long animationDuration) { if (mWallpaperSurfaceView != null) { mWallpaperSurfaceView.notifyAmbientModeChanged(inAmbientMode, animationDuration); } } @Override public void onOffsetsChanged(float xOffset, float yOffset, float xOffsetStep, float yOffsetStep, int xPixelOffset, int yPixelOffset) { if (mWallpaperSurfaceView != null) { mWallpaperSurfaceView.notifyOffsetsChanged(xOffset, yOffset); } } private class GLWallpaperSurfaceView extends GLSurfaceView implements ImageGLView { private WallpaperStatusListener mWallpaperChangedListener; GLWallpaperSurfaceView(Context context) { super(context); setEGLContextClientVersion(2); } @Override public SurfaceHolder getHolder() { return getSurfaceHolder(); } @Override public void setRenderer(Renderer renderer) { super.setRenderer(renderer); mWallpaperChangedListener = (WallpaperStatusListener) renderer; } private void notifyAmbientModeChanged(boolean inAmbient, long duration) { if (mWallpaperChangedListener != null) { mWallpaperChangedListener.onAmbientModeChanged(inAmbient, duration); } } private void notifyOffsetsChanged(float xOffset, float yOffset) { if (mWallpaperChangedListener != null) { mWallpaperChangedListener.onOffsetsChanged( xOffset, yOffset, getHolder().getSurfaceFrame()); } } @Override public void render() { requestRender(); } } } // TODO: Remove this engine, tracking on b/123617158. class DrawableEngine extends Engine { private final Runnable mUnloadWallpaperCallback = () -> { unloadWallpaper(false /* forgetSize */); Loading Loading @@ -564,4 +635,35 @@ public class ImageWallpaper extends WallpaperService { } } } /** * A listener to trace status of image wallpaper. */ public interface WallpaperStatusListener { /** * Called back while ambient mode changes. * @param inAmbientMode true if is in ambient mode, false otherwise. * @param duration the duration of animation. */ void onAmbientModeChanged(boolean inAmbientMode, long duration); /** * Called back while wallpaper offsets. * @param xOffset The offset portion along x. * @param yOffset The offset portion along y. */ void onOffsetsChanged(float xOffset, float yOffset, Rect frame); } /** * An abstraction for view of GLRenderer. */ public interface ImageGLView { /** * Ask the view to render. */ void render(); } }
packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLProgram.java 0 → 100644 +115 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.glwallpaper; import static android.opengl.GLES20.GL_FRAGMENT_SHADER; import static android.opengl.GLES20.GL_VERTEX_SHADER; import static android.opengl.GLES20.glAttachShader; import static android.opengl.GLES20.glCompileShader; import static android.opengl.GLES20.glCreateProgram; import static android.opengl.GLES20.glCreateShader; import static android.opengl.GLES20.glGetAttribLocation; import static android.opengl.GLES20.glGetUniformLocation; import static android.opengl.GLES20.glLinkProgram; import static android.opengl.GLES20.glShaderSource; import static android.opengl.GLES20.glUseProgram; import android.content.Context; import android.content.res.Resources; import android.util.Log; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; /** * This class takes charge of linking shader codes and then return a handle for OpenGL ES program. */ class ImageGLProgram { private static final String TAG = ImageGLProgram.class.getSimpleName(); private Context mContext; private int mProgramHandle; ImageGLProgram(Context context) { mContext = context.getApplicationContext(); } private int loadShaderProgram(int vertexId, int fragmentId) { final String vertexSrc = getShaderResource(vertexId); final String fragmentSrc = getShaderResource(fragmentId); final int vertexHandle = getShaderHandle(GL_VERTEX_SHADER, vertexSrc); final int fragmentHandle = getShaderHandle(GL_FRAGMENT_SHADER, fragmentSrc); return getProgramHandle(vertexHandle, fragmentHandle); } private String getShaderResource(int shaderId) { Resources res = mContext.getResources(); StringBuilder code = new StringBuilder(); try (BufferedReader reader = new BufferedReader( new InputStreamReader(res.openRawResource(shaderId)))) { String nextLine; while ((nextLine = reader.readLine()) != null) { code.append(nextLine).append("\n"); } } catch (IOException | Resources.NotFoundException ex) { Log.d(TAG, "Can not read the shader source", ex); code = null; } return code == null ? "" : code.toString(); } private int getShaderHandle(int type, String src) { final int shader = glCreateShader(type); if (shader == 0) { Log.d(TAG, "Create shader failed, type=" + type); return 0; } glShaderSource(shader, src); glCompileShader(shader); return shader; } private int getProgramHandle(int vertexHandle, int fragmentHandle) { final int program = glCreateProgram(); if (program == 0) { Log.d(TAG, "Can not create OpenGL ES program"); return 0; } glAttachShader(program, vertexHandle); glAttachShader(program, fragmentHandle); glLinkProgram(program); return program; } boolean useGLProgram(int vertexResId, int fragmentResId) { mProgramHandle = loadShaderProgram(vertexResId, fragmentResId); glUseProgram(mProgramHandle); return true; } int getAttributeHandle(String name) { return glGetAttribLocation(mProgramHandle, name); } int getUniformHandle(String name) { return glGetUniformLocation(mProgramHandle, name); } }