diff options
author | Dianne Hackborn <hackbod@google.com> | 2009-10-20 20:15:20 -0700 |
---|---|---|
committer | Dianne Hackborn <hackbod@google.com> | 2009-10-22 20:10:53 -0700 |
commit | 7580493b014a2c7ea883cd291255798dc72ebbff (patch) | |
tree | 22bffa58ac973192ea8b06ea747e1582526c1249 | |
parent | 86dc4d312216be0b4c2847a1e79d94efaf4b9559 (diff) | |
download | frameworks_base-7580493b014a2c7ea883cd291255798dc72ebbff.zip frameworks_base-7580493b014a2c7ea883cd291255798dc72ebbff.tar.gz frameworks_base-7580493b014a2c7ea883cd291255798dc72ebbff.tar.bz2 |
Implement feature #2117336: Create event communication APIs for live wallpaper
Note: currently only implements an async version (no result), and not yet
actually tested.
Change-Id: Id47ed045a4b0eb309ea8c58daf41a0e03eff1d3a
-rw-r--r-- | api/current.xml | 23 | ||||
-rw-r--r-- | core/java/android/app/WallpaperManager.java | 25 | ||||
-rw-r--r-- | core/java/android/service/wallpaper/WallpaperService.java | 70 | ||||
-rw-r--r-- | core/java/android/view/IWindow.aidl | 7 | ||||
-rw-r--r-- | core/java/android/view/IWindowSession.aidl | 6 | ||||
-rw-r--r-- | core/java/android/view/ViewRoot.java | 10 | ||||
-rw-r--r-- | core/java/com/android/internal/view/BaseIWindow.java | 11 | ||||
-rw-r--r-- | services/java/com/android/server/WindowManagerService.java | 106 | ||||
-rw-r--r-- | tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java | 19 |
9 files changed, 249 insertions, 28 deletions
diff --git a/api/current.xml b/api/current.xml index 6148047..8f83e39 100644 --- a/api/current.xml +++ b/api/current.xml @@ -24659,6 +24659,29 @@ visibility="public" > </method> +<method name="sendWallpaperCommand" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="windowToken" type="android.os.IBinder"> +</parameter> +<parameter name="action" type="java.lang.String"> +</parameter> +<parameter name="x" type="int"> +</parameter> +<parameter name="y" type="int"> +</parameter> +<parameter name="z" type="int"> +</parameter> +<parameter name="extras" type="android.os.Bundle"> +</parameter> +</method> <method name="setBitmap" return="void" abstract="false" diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index 69c87ee..5881694 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -592,6 +592,31 @@ public class WallpaperManager { } /** + * Send an arbitrary command to the current active wallpaper. + * + * @param windowToken The window who these offsets should be associated + * with, as returned by {@link android.view.View#getWindowToken() + * View.getWindowToken()}. + * @param action Name of the command to perform. This must be a scoped + * name to avoid collisions, such as "com.mycompany.wallpaper.DOIT". + * @param x Arbitrary integer argument based on command. + * @param y Arbitrary integer argument based on command. + * @param z Arbitrary integer argument based on command. + * @param extras Optional additional information for the command, or null. + */ + public void sendWallpaperCommand(IBinder windowToken, String action, + int x, int y, int z, Bundle extras) { + try { + //Log.v(TAG, "Sending new wallpaper offsets from app..."); + ViewRoot.getWindowSession(mContext.getMainLooper()).sendWallpaperCommand( + windowToken, action, x, y, z, extras, false); + //Log.v(TAG, "...app returning after sending offsets!"); + } catch (RemoteException e) { + // Ignore. + } + } + + /** * Clear the offsets previously associated with this window through * {@link #setWallpaperOffsets(IBinder, float, float)}. This reverts * the window to its default state, where it does not cause the wallpaper diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index da8d62c0..dfd6af9 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -27,6 +27,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.graphics.Rect; +import android.os.Bundle; import android.os.IBinder; import android.os.Looper; import android.os.Message; @@ -73,11 +74,21 @@ public abstract class WallpaperService extends Service { private static final int MSG_UPDATE_SURFACE = 10000; private static final int MSG_VISIBILITY_CHANGED = 10010; private static final int MSG_WALLPAPER_OFFSETS = 10020; + private static final int MSG_WALLPAPER_COMMAND = 10025; private static final int MSG_WINDOW_RESIZED = 10030; private static final int MSG_TOUCH_EVENT = 10040; private Looper mCallbackLooper; + static final class WallpaperCommand { + String action; + int x; + int y; + int z; + Bundle extras; + boolean sync; + } + /** * The actual implementation of a wallpaper. A wallpaper service may * have multiple instances running (for example as a real wallpaper @@ -233,6 +244,22 @@ public abstract class WallpaperService extends Service { } } + public void dispatchWallpaperCommand(String action, int x, int y, + int z, Bundle extras, boolean sync) { + synchronized (mLock) { + if (DEBUG) Log.v(TAG, "Dispatch wallpaper command: " + x + ", " + y); + WallpaperCommand cmd = new WallpaperCommand(); + cmd.action = action; + cmd.x = x; + cmd.y = y; + cmd.z = z; + cmd.extras = extras; + cmd.sync = sync; + Message msg = mCaller.obtainMessage(MSG_WALLPAPER_COMMAND); + msg.obj = cmd; + mCaller.sendMessage(msg); + } + } }; /** @@ -338,6 +365,28 @@ public abstract class WallpaperService extends Service { } /** + * Process a command that was sent to the wallpaper with + * {@link WallpaperManager#sendWallpaperCommand(String, int, int, int, Bundle)}. + * The default implementation does nothing, and always returns null + * as the result. + * + * @param action The name of the command to perform. This tells you + * what to do and how to interpret the rest of the arguments. + * @param x Generic integer parameter. + * @param y Generic integer parameter. + * @param z Generic integer parameter. + * @param extras Any additional parameters. + * @param resultRequested If true, the caller is requesting that + * a result, appropriate for the command, be returned back. + * @return If returning a result, create a Bundle and place the + * result data in to it. Otherwise return null. + */ + public Bundle onCommand(String action, int x, int y, int z, + Bundle extras, boolean resultRequested) { + return null; + } + + /** * Called when an application has changed the desired virtual size of * the wallpaper. */ @@ -585,6 +634,23 @@ public abstract class WallpaperService extends Service { } } + void doCommand(WallpaperCommand cmd) { + Bundle result; + if (!mDestroyed) { + result = onCommand(cmd.action, cmd.x, cmd.y, cmd.z, + cmd.extras, cmd.sync); + } else { + result = null; + } + if (cmd.sync) { + try { + if (DEBUG) Log.v(TAG, "Reporting command complete"); + mSession.wallpaperCommandComplete(mWindow.asBinder(), result); + } catch (RemoteException e) { + } + } + } + void detach() { mDestroyed = true; @@ -709,6 +775,10 @@ public abstract class WallpaperService extends Service { case MSG_WALLPAPER_OFFSETS: { mEngine.doOffsetsChanged(); } break; + case MSG_WALLPAPER_COMMAND: { + WallpaperCommand cmd = (WallpaperCommand)message.obj; + mEngine.doCommand(cmd); + } break; case MSG_WINDOW_RESIZED: { final boolean reportDraw = message.arg1 != 0; mEngine.updateSurface(true, false); diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl index 7977578..6bfc8b5 100644 --- a/core/java/android/view/IWindow.aidl +++ b/core/java/android/view/IWindow.aidl @@ -18,11 +18,11 @@ package android.view; import android.graphics.Rect; +import android.os.Bundle; +import android.os.ParcelFileDescriptor; import android.view.KeyEvent; import android.view.MotionEvent; -import android.os.ParcelFileDescriptor; - /** * API back to a client window that the Window Manager uses to inform it of * interesting things happening. @@ -63,4 +63,7 @@ oneway interface IWindow { * Called for wallpaper windows when their offsets change. */ void dispatchWallpaperOffsets(float x, float y, boolean sync); + + void dispatchWallpaperCommand(String action, int x, int y, + int z, in Bundle extras, boolean sync); } diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl index 9b8b6d4..7e7a38f 100644 --- a/core/java/android/view/IWindowSession.aidl +++ b/core/java/android/view/IWindowSession.aidl @@ -19,6 +19,7 @@ package android.view; import android.graphics.Rect; import android.graphics.Region; +import android.os.Bundle; import android.view.IWindow; import android.view.MotionEvent; import android.view.WindowManager; @@ -116,4 +117,9 @@ interface IWindowSession { void setWallpaperPosition(IBinder windowToken, float x, float y); void wallpaperOffsetsComplete(IBinder window); + + Bundle sendWallpaperCommand(IBinder window, String action, int x, int y, + int z, in Bundle extras, boolean sync); + + void wallpaperCommandComplete(IBinder window, in Bundle result); } diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java index 3b83044..f4593f5 100644 --- a/core/java/android/view/ViewRoot.java +++ b/core/java/android/view/ViewRoot.java @@ -2903,6 +2903,16 @@ public final class ViewRoot extends Handler implements ViewParent, } } } + + public void dispatchWallpaperCommand(String action, int x, int y, + int z, Bundle extras, boolean sync) { + if (sync) { + try { + sWindowSession.wallpaperCommandComplete(asBinder(), null); + } catch (RemoteException e) { + } + } + } } /** diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java index 38ef0c2..2674262 100644 --- a/core/java/com/android/internal/view/BaseIWindow.java +++ b/core/java/com/android/internal/view/BaseIWindow.java @@ -1,6 +1,7 @@ package com.android.internal.view; import android.graphics.Rect; +import android.os.Bundle; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.view.IWindow; @@ -101,4 +102,14 @@ public class BaseIWindow extends IWindow.Stub { } } } + + public void dispatchWallpaperCommand(String action, int x, int y, + int z, Bundle extras, boolean sync) { + if (sync) { + try { + mSession.wallpaperCommandComplete(asBinder(), null); + } catch (RemoteException e) { + } + } + } } diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java index e743513..cd6a371 100644 --- a/services/java/com/android/server/WindowManagerService.java +++ b/services/java/com/android/server/WindowManagerService.java @@ -63,6 +63,7 @@ import android.graphics.Rect; import android.graphics.Region; import android.os.BatteryStats; import android.os.Binder; +import android.os.Bundle; import android.os.Debug; import android.os.Handler; import android.os.IBinder; @@ -432,8 +433,6 @@ public class WindowManagerService extends IWindowManager.Stub int mWallpaperAnimLayerAdjustment; float mLastWallpaperX = -1; float mLastWallpaperY = -1; - // Lock for waiting for the wallpaper. - final Object mWaitingOnWallpaperLock = new Object(); // This is set when we are waiting for a wallpaper to tell us it is done // changing its scroll position. WindowState mWaitingOnWallpaper; @@ -1604,34 +1603,30 @@ public class WindowManagerService extends IWindowManager.Stub + wallpaperWin + " x=" + wallpaperWin.mWallpaperX + " y=" + wallpaperWin.mWallpaperY); if (sync) { - synchronized (mWaitingOnWallpaperLock) { - mWaitingOnWallpaper = wallpaperWin; - } + mWaitingOnWallpaper = wallpaperWin; } wallpaperWin.mClient.dispatchWallpaperOffsets( wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY, sync); if (sync) { - synchronized (mWaitingOnWallpaperLock) { - if (mWaitingOnWallpaper != null) { - long start = SystemClock.uptimeMillis(); - if ((mLastWallpaperTimeoutTime+WALLPAPER_TIMEOUT_RECOVERY) - < start) { - try { - if (DEBUG_WALLPAPER) Log.v(TAG, - "Waiting for offset complete..."); - mWaitingOnWallpaperLock.wait(WALLPAPER_TIMEOUT); - } catch (InterruptedException e) { - } - if (DEBUG_WALLPAPER) Log.v(TAG, "Offset complete!"); - if ((start+WALLPAPER_TIMEOUT) - < SystemClock.uptimeMillis()) { - Log.i(TAG, "Timeout waiting for wallpaper to offset: " - + wallpaperWin); - mLastWallpaperTimeoutTime = start; - } + if (mWaitingOnWallpaper != null) { + long start = SystemClock.uptimeMillis(); + if ((mLastWallpaperTimeoutTime+WALLPAPER_TIMEOUT_RECOVERY) + < start) { + try { + if (DEBUG_WALLPAPER) Log.v(TAG, + "Waiting for offset complete..."); + mWindowMap.wait(WALLPAPER_TIMEOUT); + } catch (InterruptedException e) { + } + if (DEBUG_WALLPAPER) Log.v(TAG, "Offset complete!"); + if ((start+WALLPAPER_TIMEOUT) + < SystemClock.uptimeMillis()) { + Log.i(TAG, "Timeout waiting for wallpaper to offset: " + + wallpaperWin); + mLastWallpaperTimeoutTime = start; } - mWaitingOnWallpaper = null; } + mWaitingOnWallpaper = null; } } } catch (RemoteException e) { @@ -1642,11 +1637,11 @@ public class WindowManagerService extends IWindowManager.Stub } void wallpaperOffsetsComplete(IBinder window) { - synchronized (mWaitingOnWallpaperLock) { + synchronized (mWindowMap) { if (mWaitingOnWallpaper != null && mWaitingOnWallpaper.mClient.asBinder() == window) { mWaitingOnWallpaper = null; - mWaitingOnWallpaperLock.notifyAll(); + mWindowMap.notifyAll(); } } } @@ -2196,6 +2191,47 @@ public class WindowManagerService extends IWindowManager.Stub } } + void wallpaperCommandComplete(IBinder window, Bundle result) { + synchronized (mWindowMap) { + if (mWaitingOnWallpaper != null && + mWaitingOnWallpaper.mClient.asBinder() == window) { + mWaitingOnWallpaper = null; + mWindowMap.notifyAll(); + } + } + } + + public Bundle sendWindowWallpaperCommandLocked(WindowState window, + String action, int x, int y, int z, Bundle extras, boolean sync) { + if (window == mWallpaperTarget || window == mLowerWallpaperTarget + || window == mUpperWallpaperTarget) { + boolean doWait = sync; + 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); + try { + wallpaper.mClient.dispatchWallpaperCommand(action, + x, y, z, extras, sync); + // We only want to be synchronous with one wallpaper. + sync = false; + } catch (RemoteException e) { + } + } + } + + if (doWait) { + // XXX Need to wait for result. + } + } + + return null; + } + public int relayoutWindow(Session session, IWindow client, WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewVisibility, boolean insetsPending, @@ -6565,6 +6601,24 @@ public class WindowManagerService extends IWindowManager.Stub WindowManagerService.this.wallpaperOffsetsComplete(window); } + public Bundle sendWallpaperCommand(IBinder window, String action, int x, int y, + int z, Bundle extras, boolean sync) { + synchronized(mWindowMap) { + long ident = Binder.clearCallingIdentity(); + try { + return sendWindowWallpaperCommandLocked( + windowForClientLocked(this, window), + action, x, y, z, extras, sync); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + } + + public void wallpaperCommandComplete(IBinder window, Bundle result) { + WindowManagerService.this.wallpaperCommandComplete(window, result); + } + void windowAddedLocked() { if (mSurfaceSession == null) { if (localLOGV) Log.v( diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java index d28a151..f0223e8 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java @@ -36,6 +36,7 @@ import android.graphics.Rect; import android.graphics.Region; import android.graphics.Typeface; import android.graphics.drawable.Drawable; +import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Looper; @@ -1069,6 +1070,18 @@ public final class Bridge implements ILayoutBridge { } @SuppressWarnings("unused") + public Bundle sendWallpaperCommand(IBinder window, String action, int x, int y, + int z, Bundle extras, boolean sync) { + // pass for now. + return null; + } + + @SuppressWarnings("unused") + public void wallpaperCommandComplete(IBinder window, Bundle result) { + // pass for now. + } + + @SuppressWarnings("unused") public void closeSystemDialogs(String reason) { // pass for now. } @@ -1132,6 +1145,12 @@ public final class Bridge implements ILayoutBridge { } @SuppressWarnings("unused") + public void dispatchWallpaperCommand(String action, int x, int y, + int z, Bundle extras, boolean sync) { + // pass for now. + } + + @SuppressWarnings("unused") public void closeSystemDialogs(String reason) { // pass for now. } |