Skip to content

Commit 2f20081

Browse files
committed
Avoid redundant wallpaper loading/drawing
Switching users causes wallpapers to get recreated 3 times. Other operations like startup and rotation cause similar redundant load/draw operations. This change tracks the various attributes that tell us when we really need to reload and redraw, causing only one of these expensive operation per one of these switches. Issue #7334664 Wallpaper draws several times when switching users Change-Id: Ic3072ef3a7eaf622d8632e87e34f50999f716c39
1 parent a3d5b68 commit 2f20081

File tree

1 file changed

+53
-50
lines changed

1 file changed

+53
-50
lines changed

packages/SystemUI/src/com/android/systemui/ImageWallpaper.java

Lines changed: 53 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,10 @@
3131
import android.renderscript.Matrix4f;
3232
import android.service.wallpaper.WallpaperService;
3333
import android.util.Log;
34+
import android.view.Display;
3435
import android.view.MotionEvent;
3536
import android.view.SurfaceHolder;
37+
import android.view.WindowManager;
3638

3739
import javax.microedition.khronos.egl.EGL10;
3840
import javax.microedition.khronos.egl.EGLConfig;
@@ -108,6 +110,7 @@ class DrawableEngine extends Engine {
108110

109111
Bitmap mBackground;
110112
int mBackgroundWidth = -1, mBackgroundHeight = -1;
113+
int mLastRotation = -1;
111114
float mXOffset;
112115
float mYOffset;
113116

@@ -156,7 +159,7 @@ public void onReceive(Context context, Intent intent) {
156159
mBackgroundWidth = mBackgroundHeight = -1;
157160
mBackground = null;
158161
mRedrawNeeded = true;
159-
drawFrameLocked(false);
162+
drawFrameLocked();
160163
}
161164
}
162165
}
@@ -225,7 +228,7 @@ void updateSurfaceSize(SurfaceHolder surfaceHolder) {
225228
@Override
226229
public void onVisibilityChanged(boolean visible) {
227230
if (DEBUG) {
228-
Log.d(TAG, "onVisibilityChanged: visible=" + visible);
231+
Log.d(TAG, "onVisibilityChanged: mVisible, visible=" + mVisible + ", " + visible);
229232
}
230233

231234
synchronized (mLock) {
@@ -234,7 +237,7 @@ public void onVisibilityChanged(boolean visible) {
234237
Log.d(TAG, "Visibility changed to visible=" + visible);
235238
}
236239
mVisible = visible;
237-
drawFrameLocked(false);
240+
drawFrameLocked();
238241
}
239242
}
240243
}
@@ -263,7 +266,7 @@ public void onOffsetsChanged(float xOffset, float yOffset,
263266
mYOffset = yOffset;
264267
mOffsetsChanged = true;
265268
}
266-
drawFrameLocked(false);
269+
drawFrameLocked();
267270
}
268271
}
269272

@@ -276,80 +279,81 @@ public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int he
276279
super.onSurfaceChanged(holder, format, width, height);
277280

278281
synchronized (mLock) {
279-
mRedrawNeeded = true;
280-
mBackgroundWidth = mBackgroundHeight = -1;
281-
drawFrameLocked(true);
282+
drawFrameLocked();
282283
}
283284
}
284285

286+
@Override
287+
public void onSurfaceDestroyed(SurfaceHolder holder) {
288+
super.onSurfaceDestroyed(holder);
289+
mBackgroundWidth = mBackgroundHeight = -1;
290+
}
291+
292+
@Override
293+
public void onSurfaceCreated(SurfaceHolder holder) {
294+
super.onSurfaceCreated(holder);
295+
mBackgroundWidth = mBackgroundHeight = -1;
296+
}
297+
285298
@Override
286299
public void onSurfaceRedrawNeeded(SurfaceHolder holder) {
287300
if (DEBUG) {
288-
Log.d(TAG, "onSurfaceRedrawNeeded:");
301+
Log.d(TAG, "onSurfaceRedrawNeeded");
289302
}
290303
super.onSurfaceRedrawNeeded(holder);
291304

292305
synchronized (mLock) {
293-
mRedrawNeeded = true;
294-
drawFrameLocked(false);
306+
drawFrameLocked();
295307
}
296308
}
297309

298-
void drawFrameLocked(boolean force) {
299-
if (!force) {
300-
if (!mVisible) {
301-
if (DEBUG) {
302-
Log.d(TAG, "Suppressed drawFrame since wallpaper is not visible.");
303-
}
304-
return;
305-
}
306-
if (!mRedrawNeeded && !mOffsetsChanged) {
307-
if (DEBUG) {
308-
Log.d(TAG, "Suppressed drawFrame since redraw is not needed "
309-
+ "and offsets have not changed.");
310-
}
311-
return;
310+
void drawFrameLocked() {
311+
SurfaceHolder sh = getSurfaceHolder();
312+
final Rect frame = sh.getSurfaceFrame();
313+
final int dw = frame.width();
314+
final int dh = frame.height();
315+
int newRotation = ((WindowManager) getSystemService(WINDOW_SERVICE)).
316+
getDefaultDisplay().getRotation();
317+
318+
boolean redrawNeeded = dw != mBackgroundWidth || dh != mBackgroundHeight ||
319+
newRotation != mLastRotation;
320+
if (!redrawNeeded && !mOffsetsChanged) {
321+
if (DEBUG) {
322+
Log.d(TAG, "Suppressed drawFrame since redraw is not needed "
323+
+ "and offsets have not changed.");
312324
}
325+
return;
313326
}
314-
// If we don't yet know the size of the wallpaper bitmap,
315-
// we need to get it now.
316-
boolean updateWallpaper = mBackgroundWidth < 0 || mBackgroundHeight < 0 ;
317-
318-
// If we somehow got to this point after we have last flushed
319-
// the wallpaper, well we really need it to draw again. So
320-
// seems like we need to reload it. Ouch.
321-
updateWallpaper = updateWallpaper || mBackground == null;
327+
mLastRotation = newRotation;
322328

323-
if (updateWallpaper) {
329+
// Load bitmap if it is not yet loaded or if it was loaded at a different size
330+
if (mBackground == null || dw != mBackgroundWidth || dw != mBackgroundHeight) {
331+
if (DEBUG) {
332+
Log.d(TAG, "Reloading bitmap");
333+
}
334+
mWallpaperManager.forgetLoadedWallpaper();
324335
updateWallpaperLocked();
325336
}
326337

327-
SurfaceHolder sh = getSurfaceHolder();
328-
final Rect frame = sh.getSurfaceFrame();
329-
final int dw = frame.width();
330-
final int dh = frame.height();
331338
final int availw = dw - mBackgroundWidth;
332339
final int availh = dh - mBackgroundHeight;
333340
int xPixels = availw < 0 ? (int)(availw * mXOffset + .5f) : (availw / 2);
334341
int yPixels = availh < 0 ? (int)(availh * mYOffset + .5f) : (availh / 2);
335342

336343
mOffsetsChanged = false;
337-
if (!force && !mRedrawNeeded
338-
&& xPixels == mLastXTranslation && yPixels == mLastYTranslation) {
344+
mRedrawNeeded = false;
345+
mLastXTranslation = xPixels;
346+
mLastYTranslation = yPixels;
347+
if (!redrawNeeded && xPixels == mLastXTranslation && yPixels == mLastYTranslation) {
339348
if (DEBUG) {
340349
Log.d(TAG, "Suppressed drawFrame since the image has not "
341350
+ "actually moved an integral number of pixels.");
342351
}
343352
return;
344353
}
345-
mRedrawNeeded = false;
346-
mLastXTranslation = xPixels;
347-
mLastYTranslation = yPixels;
348354

349355
if (DEBUG) {
350-
Log.d(TAG, "drawFrameUnlocked(" + force + "): mBackgroundWxH=" + mBackgroundWidth + "x"
351-
+ mBackgroundHeight + " SurfaceFrame=" + frame.toShortString()
352-
+ " X,YOffset=" + mXOffset + "," + mYOffset);
356+
Log.d(TAG, "Redrawing wallpaper");
353357
}
354358
if (mIsHwAccelerated) {
355359
if (!drawWallpaperWithOpenGL(sh, availw, availh, xPixels, yPixels)) {
@@ -429,15 +433,14 @@ private boolean drawWallpaperWithOpenGL(SurfaceHolder sh, int w, int h, int left
429433
final float bottom = top + mBackgroundHeight;
430434

431435
final Rect frame = sh.getSurfaceFrame();
432-
433436
final Matrix4f ortho = new Matrix4f();
434437
ortho.loadOrtho(0.0f, frame.width(), frame.height(), 0.0f, -1.0f, 1.0f);
435438

436439
final FloatBuffer triangleVertices = createMesh(left, top, right, bottom);
437440

438441
final int texture = loadTexture(mBackground);
439442
final int program = buildProgram(sSimpleVS, sSimpleFS);
440-
443+
441444
final int attribPosition = glGetAttribLocation(program, "position");
442445
final int attribTexCoords = glGetAttribLocation(program, "texCoords");
443446
final int uniformTexture = glGetUniformLocation(program, "texture");
@@ -460,7 +463,7 @@ private boolean drawWallpaperWithOpenGL(SurfaceHolder sh, int w, int h, int left
460463
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
461464
glClear(GL_COLOR_BUFFER_BIT);
462465
}
463-
466+
464467
// drawQuad
465468
triangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
466469
glVertexAttribPointer(attribPosition, 3, GL_FLOAT, false,
@@ -471,12 +474,12 @@ private boolean drawWallpaperWithOpenGL(SurfaceHolder sh, int w, int h, int left
471474
TRIANGLE_VERTICES_DATA_STRIDE_BYTES, triangleVertices);
472475

473476
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
474-
477+
475478
if (!mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) {
476479
throw new RuntimeException("Cannot swap buffers");
477480
}
478481
checkEglError();
479-
482+
480483
finishGL();
481484

482485
return true;

0 commit comments

Comments
 (0)