Skip to content

Commit a8e5a2b

Browse files
committed
Optimize handling of scrolled wallpapers
Swiping the home screen causes the WindowManagerService to do a bunch of work to keep the wallpapers in sync. First, it lays out and places all windows. Also, it notifies the SystemUI process that the wallpaper position has changed. The layout/place operation is too much work - we only need to set the position values for the wallpaper, not relayout the whole system. The notification mechanism must exist, but should be optional. Most wallpapers don't care (especially static ImageWallpapers). So we'll give them a new API (WallpaperService.Engine.setWantsOffsets()) to allow wallpapers to opt out of this process and avoid the performance overhead. Change-Id: I66c38375438937f14f6f5550565b28eb204b1e06
1 parent 48ba413 commit a8e5a2b

File tree

5 files changed

+66
-11
lines changed

5 files changed

+66
-11
lines changed

api/current.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18669,6 +18669,7 @@ package android.service.wallpaper {
1866918669
method public void onSurfaceRedrawNeeded(android.view.SurfaceHolder);
1867018670
method public void onTouchEvent(android.view.MotionEvent);
1867118671
method public void onVisibilityChanged(boolean);
18672+
method public void setOffsetNotificationsEnabled(boolean);
1867218673
method public void setTouchEventsEnabled(boolean);
1867318674
}
1867418675

core/java/android/service/wallpaper/WallpaperService.java

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,10 @@ public class Engine {
148148
int mCurWidth;
149149
int mCurHeight;
150150
int mWindowFlags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
151+
int mWindowPrivateFlags =
152+
WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS;
151153
int mCurWindowFlags = mWindowFlags;
154+
int mCurWindowPrivateFlags = mWindowPrivateFlags;
152155
final Rect mVisibleInsets = new Rect();
153156
final Rect mWinFrame = new Rect();
154157
final Rect mContentInsets = new Rect();
@@ -359,6 +362,25 @@ public void setTouchEventsEnabled(boolean enabled) {
359362
updateSurface(false, false, false);
360363
}
361364
}
365+
366+
/**
367+
* Control whether this wallpaper will receive notifications when the wallpaper
368+
* has been scrolled. By default, wallpapers will receive notifications, although
369+
* the default static image wallpapers do not. It is a performance optimization to
370+
* set this to false.
371+
*
372+
* @param enabled whether the wallpaper wants to receive offset notifications
373+
*/
374+
public void setOffsetNotificationsEnabled(boolean enabled) {
375+
mWindowPrivateFlags = enabled
376+
? (mWindowPrivateFlags |
377+
WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS)
378+
: (mWindowPrivateFlags &
379+
~WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS);
380+
if (mCreated) {
381+
updateSurface(false, false, false);
382+
}
383+
}
362384

363385
/**
364386
* Called once to initialize the engine. After returning, the
@@ -478,6 +500,8 @@ protected void dump(String prefix, FileDescriptor fd, PrintWriter out, String[]
478500
out.print(prefix); out.print("mType="); out.print(mType);
479501
out.print(" mWindowFlags="); out.print(mWindowFlags);
480502
out.print(" mCurWindowFlags="); out.println(mCurWindowFlags);
503+
out.print(" mWindowPrivateFlags="); out.print(mWindowPrivateFlags);
504+
out.print(" mCurWindowPrivateFlags="); out.println(mCurWindowPrivateFlags);
481505
out.print(prefix); out.print("mVisibleInsets=");
482506
out.print(mVisibleInsets.toShortString());
483507
out.print(" mWinFrame="); out.print(mWinFrame.toShortString());
@@ -528,7 +552,8 @@ void updateSurface(boolean forceRelayout, boolean forceReport, boolean redrawNee
528552
final boolean formatChanged = mFormat != mSurfaceHolder.getRequestedFormat();
529553
boolean sizeChanged = mWidth != myWidth || mHeight != myHeight;
530554
final boolean typeChanged = mType != mSurfaceHolder.getRequestedType();
531-
final boolean flagsChanged = mCurWindowFlags != mWindowFlags;
555+
final boolean flagsChanged = mCurWindowFlags != mWindowFlags ||
556+
mCurWindowPrivateFlags != mWindowPrivateFlags;
532557
if (forceRelayout || creating || surfaceCreating || formatChanged || sizeChanged
533558
|| typeChanged || flagsChanged || redrawNeeded) {
534559

@@ -554,6 +579,8 @@ void updateSurface(boolean forceRelayout, boolean forceReport, boolean redrawNee
554579
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
555580
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
556581
;
582+
mCurWindowPrivateFlags = mWindowPrivateFlags;
583+
mLayout.privateFlags = mWindowPrivateFlags;
557584

558585
mLayout.memoryType = mType;
559586
mLayout.token = mWindowToken;

core/java/android/view/WindowManager.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -812,6 +812,17 @@ public static class LayoutParams extends ViewGroup.LayoutParams
812812
*/
813813
public static final int PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED = 0x00000002;
814814

815+
/**
816+
* By default, wallpapers are sent new offsets when the wallpaper is scrolled. Wallpapers
817+
* may elect to skp these notifications if they are no doing anything productive with
818+
* them (they do not affect the wallpaper scrolling operation) by calling
819+
* {@link
820+
* android.service.wallpaper.WallpaperService.Engine#setOffsetNotificationsEnabled(boolean)}.
821+
*
822+
* @hide
823+
*/
824+
public static final int PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS = 0x00000004;
825+
815826
/**
816827
* Control flags that are private to the platform.
817828
* @hide

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,8 @@ public void onCreate(SurfaceHolder surfaceHolder) {
170170
//registerReceiver(mReceiver, filter, null, mHandler);
171171

172172
updateSurfaceSize(surfaceHolder);
173+
174+
setOffsetNotificationsEnabled(false);
173175
}
174176

175177
@Override

services/java/com/android/server/wm/WindowManagerService.java

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1836,7 +1836,8 @@ boolean updateWallpaperOffsetLocked(WindowState wallpaperWin, int dw, int dh,
18361836
rawChanged = true;
18371837
}
18381838

1839-
if (rawChanged) {
1839+
if (rawChanged && (wallpaperWin.getAttrs().privateFlags &
1840+
WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS) != 0) {
18401841
try {
18411842
if (DEBUG_WALLPAPER) Slog.v(TAG, "Report new wp offset "
18421843
+ wallpaperWin + " x=" + wallpaperWin.mWallpaperX
@@ -1886,12 +1887,10 @@ void wallpaperOffsetsComplete(IBinder window) {
18861887
}
18871888
}
18881889

1889-
boolean updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
1890+
void updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
18901891
final int dw = mAppDisplayWidth;
18911892
final int dh = mAppDisplayHeight;
18921893

1893-
boolean changed = false;
1894-
18951894
WindowState target = mWallpaperTarget;
18961895
if (target != null) {
18971896
if (target.mWallpaperX >= 0) {
@@ -1916,14 +1915,31 @@ boolean updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
19161915
WindowState wallpaper = token.windows.get(curWallpaperIndex);
19171916
if (updateWallpaperOffsetLocked(wallpaper, dw, dh, sync)) {
19181917
wallpaper.computeShownFrameLocked();
1919-
changed = true;
1918+
// No need to lay out the windows - we can just set the wallpaper position
1919+
// directly.
1920+
if (wallpaper.mSurfaceX != wallpaper.mShownFrame.left
1921+
|| wallpaper.mSurfaceY != wallpaper.mShownFrame.top) {
1922+
Surface.openTransaction();
1923+
try {
1924+
if (SHOW_TRANSACTIONS) logSurface(wallpaper,
1925+
"POS " + wallpaper.mShownFrame.left
1926+
+ ", " + wallpaper.mShownFrame.top, null);
1927+
wallpaper.mSurfaceX = wallpaper.mShownFrame.left;
1928+
wallpaper.mSurfaceY = wallpaper.mShownFrame.top;
1929+
wallpaper.mSurface.setPosition(wallpaper.mShownFrame.left,
1930+
wallpaper.mShownFrame.top);
1931+
} catch (RuntimeException e) {
1932+
Slog.w(TAG, "Error positioning surface of " + wallpaper
1933+
+ " pos=(" + wallpaper.mShownFrame.left
1934+
+ "," + wallpaper.mShownFrame.top + ")", e);
1935+
}
1936+
Surface.closeTransaction();
1937+
}
19201938
// We only want to be synchronous with one wallpaper.
19211939
sync = false;
19221940
}
19231941
}
19241942
}
1925-
1926-
return changed;
19271943
}
19281944

19291945
void updateWallpaperVisibilityLocked() {
@@ -2436,9 +2452,7 @@ public void setWindowWallpaperPositionLocked(WindowState window, float x, float
24362452
window.mWallpaperY = y;
24372453
window.mWallpaperXStep = xStep;
24382454
window.mWallpaperYStep = yStep;
2439-
if (updateWallpaperOffsetLocked(window, true)) {
2440-
performLayoutAndPlaceSurfacesLocked();
2441-
}
2455+
updateWallpaperOffsetLocked(window, true);
24422456
}
24432457
}
24442458

0 commit comments

Comments
 (0)