diff --git a/api/current.xml b/api/current.xml index 853ac9fce56af..cc7dc23255d62 100644 --- a/api/current.xml +++ b/api/current.xml @@ -9370,6 +9370,17 @@ visibility="public" > + + + + + + + + It is very important that a wallpaper only use + * CPU while it is visible.. + */ + public void onVisibilityChanged(boolean visible) { + } + + /** + * Convenience for {@link SurfaceHolder.Callback#surfaceChanged + * SurfaceHolder.Callback.surfaceChanged()}. + */ public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) { } + /** + * Convenience for {@link SurfaceHolder.Callback#surfaceCreated + * SurfaceHolder.Callback.surfaceCreated()}. + */ public void onSurfaceCreated(SurfaceHolder holder) { } + /** + * Convenience for {@link SurfaceHolder.Callback#surfaceDestroyed + * SurfaceHolder.Callback.surfaceDestroyed()}. + */ public void onSurfaceDestroyed(SurfaceHolder holder) { } @@ -249,14 +310,14 @@ public abstract class WallpaperService extends Service { mSession = ViewRoot.getWindowSession(getMainLooper()); mWindow.setSession(mSession); - onAttach(mSurfaceHolder); + onCreate(mSurfaceHolder); mInitializing = false; updateSurface(false); } void detach() { - onDetach(); + onDestroy(); if (mDestroyReportNeeded) { mDestroyReportNeeded = false; SurfaceHolder.Callback callbacks[]; @@ -330,6 +391,11 @@ public abstract class WallpaperService extends Service { case MSG_UPDATE_SURFACE: mEngine.updateSurface(false); break; + case MSG_VISIBILITY_CHANGED: + if (DEBUG) Log.v(TAG, "Visibility change in " + mEngine + + ": " + message.arg1); + mEngine.onVisibilityChanged(message.arg1 != 0); + break; default : Log.w(TAG, "Unknown message type " + message.what); } diff --git a/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java b/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java index 9c99e05b10418..7aa4f470f54ce 100644 --- a/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java +++ b/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java @@ -19,7 +19,11 @@ package com.android.internal.service.wallpaper; import android.app.WallpaperManager; import android.graphics.Canvas; import android.graphics.Paint; +import android.graphics.Rect; import android.graphics.drawable.Drawable; +import android.os.Handler; +import android.os.Message; +import android.os.SystemClock; import android.service.wallpaper.WallpaperService; import android.view.SurfaceHolder; @@ -29,30 +33,58 @@ import android.view.SurfaceHolder; public class ImageWallpaper extends WallpaperService { public WallpaperManager mWallpaperManager; + static final int MSG_DRAW = 1; + class MyEngine extends Engine { - + final Paint mTextPaint = new Paint(); + float mDensity; Drawable mBackground; + long mAnimStartTime; + boolean mAnimLarger; + + final Handler mHandler = new Handler() { + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_DRAW: + drawFrame(true); + mHandler.sendEmptyMessage(MSG_DRAW); + break; + default: + super.handleMessage(msg); + } + } + }; @Override - public void onAttach(SurfaceHolder surfaceHolder) { - super.onAttach(surfaceHolder); + public void onCreate(SurfaceHolder surfaceHolder) { + super.onCreate(surfaceHolder); mBackground = mWallpaperManager.getDrawable(); + mTextPaint.setAntiAlias(true); + mDensity = getResources().getDisplayMetrics().density; + mTextPaint.setTextSize(30 * mDensity); + mTextPaint.setShadowLayer(5*mDensity, 3*mDensity, 3*mDensity, 0xff000000); + mTextPaint.setARGB(255, 255, 255, 255); + mTextPaint.setTextAlign(Paint.Align.CENTER); } + @Override + public void onVisibilityChanged(boolean visible) { + mHandler.removeMessages(MSG_DRAW); + if (visible) { + mHandler.sendEmptyMessage(MSG_DRAW); + mAnimStartTime = SystemClock.uptimeMillis(); + mAnimLarger = true; + } else { + drawFrame(false); + } + } + @Override public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) { super.onSurfaceChanged(holder, format, width, height); - Canvas c = holder.lockCanvas(); - mBackground.setBounds(0, 0, width, height); - mBackground.draw(c); - Paint paint = new Paint(); - paint.setAntiAlias(true); - final float density = getResources().getDisplayMetrics().density; - paint.setTextSize(30 * density); - paint.setShadowLayer(5*density, 3*density, 3*density, 0xff000000); - paint.setARGB(255, 255, 255, 255); - c.drawText("Am I live?", 10, 60*density, paint); - holder.unlockCanvasAndPost(c); + drawFrame(false); } @Override @@ -65,6 +97,35 @@ public class ImageWallpaper extends WallpaperService { super.onSurfaceDestroyed(holder); } + void drawFrame(boolean drawText) { + SurfaceHolder sh = getSurfaceHolder(); + Canvas c = sh.lockCanvas(); + if (c != null) { + final Rect frame = sh.getSurfaceFrame(); + mBackground.setBounds(frame); + mBackground.draw(c); + + if (drawText) { + // Figure out animation. + long now = SystemClock.uptimeMillis(); + while (mAnimStartTime < (now-1000)) { + mAnimStartTime += 1000; + mAnimLarger = !mAnimLarger; + } + float size = (now-mAnimStartTime) / (float)1000; + if (!mAnimLarger) size = 1-size; + int alpha = (int)(255*(size*size)); + mTextPaint.setARGB(alpha, 255, 255, 255); + mTextPaint.setShadowLayer(5*mDensity, 3*mDensity, 3*mDensity, + alpha<<24); + mTextPaint.setTextSize(100 * mDensity * size); + c.drawText("Am I live?", + frame.left + (frame.right-frame.left)/2, + frame.top + (frame.bottom-frame.top)/2, mTextPaint); + } + } + sh.unlockCanvasAndPost(c); + } } @Override diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index ad6d94fb9163d..01253d330e26d 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -215,6 +215,9 @@ + + @@ -900,6 +903,7 @@ + diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index f8dd4c19b296f..ef87b179c6596 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -1167,9 +1167,13 @@ + + + + diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml index e3fffb74f11ab..1e3a4a88ef13f 100644 --- a/core/res/res/values/themes.xml +++ b/core/res/res/values/themes.xml @@ -280,6 +280,25 @@ @null + + + + + + + + + diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java index 1b7efeb36df73..69c48d39457bc 100644 --- a/services/java/com/android/server/WindowManagerService.java +++ b/services/java/com/android/server/WindowManagerService.java @@ -403,6 +403,11 @@ public class WindowManagerService extends IWindowManager.Stub final ArrayList mWallpaperTokens = new ArrayList(); + // If non-null, this is the currently visible window that is associated + // with the wallpaper. + WindowState mWallpaperTarget = null; + int mWallpaperAnimLayerAdjustment; + AppWindowToken mFocusedApp = null; PowerManagerService mPowerManager; @@ -1180,15 +1185,23 @@ public class WindowManagerService extends IWindowManager.Stub int N = localmWindows.size(); WindowState w = null; int i = N; + boolean visible = false; while (i > 0) { i--; w = (WindowState)localmWindows.get(i); - if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0 && w.isVisibleOrAdding()) { + if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0 && w.isReadyForDisplay()) { + visible = true; break; } } - if (w != null) { + if (!visible) w = null; + mWallpaperTarget = w; + + if (visible) { + mWallpaperAnimLayerAdjustment = w.mAppToken != null + ? w.mAppToken.animLayerAdjustment : 0; + // Now w is the window we are supposed to be behind... but we // need to be sure to also be behind any of its attached windows, // AND any starting window associated with it. @@ -1220,6 +1233,24 @@ public class WindowManagerService extends IWindowManager.Stub while (curWallpaperIndex > 0) { curWallpaperIndex--; WindowState wallpaper = token.windows.get(curWallpaperIndex); + + // First, make sure the client has the current visibility + // state. + if (wallpaper.mWallpaperVisible != visible) { + wallpaper.mWallpaperVisible = visible; + try { + if (DEBUG_VISIBILITY) Log.v(TAG, + "Setting visibility of wallpaper " + wallpaper + + ": " + visible); + wallpaper.mClient.dispatchAppVisibility(visible); + } catch (RemoteException e) { + } + } + + wallpaper.mAnimLayer = wallpaper.mLayer + mWallpaperAnimLayerAdjustment; + if (DEBUG_LAYERS) Log.v(TAG, "Wallpaper win " + wallpaper + + " anim layer: " + wallpaper.mAnimLayer); + // First, if this window is at the current index, then all // is well. if (wallpaper == w) { @@ -1248,6 +1279,24 @@ public class WindowManagerService extends IWindowManager.Stub return changed; } + void setWallpaperAnimLayerAdjustment(int adj) { + if (DEBUG_LAYERS) Log.v(TAG, "Setting wallpaper layer adj to " + adj); + mWallpaperAnimLayerAdjustment = adj; + int curTokenIndex = mWallpaperTokens.size(); + while (curTokenIndex > 0) { + curTokenIndex--; + WindowToken token = mWallpaperTokens.get(curTokenIndex); + int curWallpaperIndex = token.windows.size(); + while (curWallpaperIndex > 0) { + curWallpaperIndex--; + WindowState wallpaper = token.windows.get(curWallpaperIndex); + wallpaper.mAnimLayer = wallpaper.mLayer + adj; + if (DEBUG_LAYERS) Log.v(TAG, "Wallpaper win " + wallpaper + + " anim layer: " + wallpaper.mAnimLayer); + } + } + } + public int addWindow(Session session, IWindow client, WindowManager.LayoutParams attrs, int viewVisibility, Rect outContentInsets) { @@ -1867,6 +1916,9 @@ public class WindowManagerService extends IWindowManager.Stub synchronized(mWindowMap) { WindowState win = windowForClientLocked(session, client); if (win != null && win.finishDrawingLocked()) { + if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) { + adjustWallpaperWindowsLocked(); + } mLayoutNeeded = true; performLayoutAndPlaceSurfacesLocked(); } @@ -5842,6 +5894,7 @@ public class WindowManagerService extends IWindowManager.Stub Surface mSurface; boolean mAttachedHidden; // is our parent window hidden? boolean mLastHidden; // was this window last hidden? + boolean mWallpaperVisible; // for wallpaper, what was last vis report? int mRequestedWidth; int mRequestedHeight; int mLastRequestedWidth; @@ -6518,6 +6571,8 @@ public class WindowManagerService extends IWindowManager.Stub mAnimLayer = mLayer; if (mIsImWindow) { mAnimLayer += mInputMethodAnimLayerAdjustment; + } else if (mIsWallpaper) { + mAnimLayer += mWallpaperAnimLayerAdjustment; } if (DEBUG_LAYERS) Log.v(TAG, "Stepping win " + this + " anim layer: " + mAnimLayer); @@ -6604,6 +6659,19 @@ public class WindowManagerService extends IWindowManager.Stub Transformation appTransformation = (mAppToken != null && mAppToken.hasTransformation) ? mAppToken.transformation : null; + + // Wallpapers are animated based on the "real" window they + // are currently targeting. + if (mAttrs.type == TYPE_WALLPAPER && mWallpaperTarget != null) { + if (mWallpaperTarget.mHasLocalTransformation) { + attachedTransformation = mWallpaperTarget.mTransformation; + } + if (mWallpaperTarget.mAppToken != null && + mWallpaperTarget.mAppToken.hasTransformation) { + appTransformation = mWallpaperTarget.mAppToken.transformation; + } + } + if (selfTransformation || attachedTransformation != null || appTransformation != null) { // cache often used attributes locally @@ -6926,7 +6994,8 @@ public class WindowManagerService extends IWindowManager.Stub if (mIsImWindow || mIsWallpaper || mIsFloatingLayer) { pw.print(prefix); pw.print("mIsImWindow="); pw.print(mIsImWindow); pw.print(" mIsWallpaper="); pw.print(mIsWallpaper); - pw.print(" mIsFloatingLayer="); pw.println(mIsFloatingLayer); + pw.print(" mIsFloatingLayer="); pw.print(mIsFloatingLayer); + pw.print(" mWallpaperVisible="); pw.println(mWallpaperVisible); } pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer); pw.print(" mSubLayer="); pw.print(mSubLayer); @@ -7212,6 +7281,9 @@ public class WindowManagerService extends IWindowManager.Stub if (w == mInputMethodTarget) { setInputMethodAnimLayerAdjustment(adj); } + if (w == mWallpaperTarget) { + setWallpaperAnimLayerAdjustment(adj); + } } } @@ -7978,6 +8050,8 @@ public class WindowManagerService extends IWindowManager.Stub } if (w.mIsImWindow) { w.mAnimLayer += mInputMethodAnimLayerAdjustment; + } else if (w.mIsWallpaper) { + w.mAnimLayer += mWallpaperAnimLayerAdjustment; } if (DEBUG_LAYERS) Log.v(TAG, "Assign layer " + w + ": " + w.mAnimLayer); @@ -8659,7 +8733,8 @@ public class WindowManagerService extends IWindowManager.Stub } boolean opaqueDrawn = w.isOpaqueDrawn(); - if (opaqueDrawn && w.isFullscreen(dw, dh)) { + if ((opaqueDrawn && w.isFullscreen(dw, dh)) + || attrs.type == TYPE_WALLPAPER) { // This window completely covers everything behind it, // so we want to leave all of them as unblurred (for // performance reasons). @@ -9316,7 +9391,9 @@ public class WindowManagerService extends IWindowManager.Stub pw.print( " no DimAnimator "); } pw.print(" mInputMethodAnimLayerAdjustment="); - pw.println(mInputMethodAnimLayerAdjustment); + pw.print(mInputMethodAnimLayerAdjustment); + pw.print(" mWallpaperAnimLayerAdjustment="); + pw.println(mWallpaperAnimLayerAdjustment); pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen); pw.print(" mWindowsFreezingScreen="); pw.print(mWindowsFreezingScreen); pw.print(" mAppsFreezingScreen="); pw.println(mAppsFreezingScreen);