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);