am 7580493b: Implement feature #2117336: Create event communication APIs for live wallpaper

Merge commit '7580493b014a2c7ea883cd291255798dc72ebbff' into eclair-mr2

* commit '7580493b014a2c7ea883cd291255798dc72ebbff':
  Implement feature #2117336: Create event communication APIs for live wallpaper
This commit is contained in:
Dianne Hackborn
2009-10-22 20:21:07 -07:00
committed by Android Git Automerger
9 changed files with 249 additions and 28 deletions

View File

@@ -24659,6 +24659,29 @@
visibility="public" visibility="public"
> >
</method> </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" <method name="setBitmap"
return="void" return="void"
abstract="false" abstract="false"

View File

@@ -591,6 +591,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 * Clear the offsets previously associated with this window through
* {@link #setWallpaperOffsets(IBinder, float, float)}. This reverts * {@link #setWallpaperOffsets(IBinder, float, float)}. This reverts

View File

@@ -27,6 +27,7 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.graphics.Rect; import android.graphics.Rect;
import android.os.Bundle;
import android.os.IBinder; import android.os.IBinder;
import android.os.Looper; import android.os.Looper;
import android.os.Message; 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_UPDATE_SURFACE = 10000;
private static final int MSG_VISIBILITY_CHANGED = 10010; private static final int MSG_VISIBILITY_CHANGED = 10010;
private static final int MSG_WALLPAPER_OFFSETS = 10020; 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_WINDOW_RESIZED = 10030;
private static final int MSG_TOUCH_EVENT = 10040; private static final int MSG_TOUCH_EVENT = 10040;
private Looper mCallbackLooper; 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 * The actual implementation of a wallpaper. A wallpaper service may
* have multiple instances running (for example as a real wallpaper * 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);
}
}
}; };
/** /**
@@ -337,6 +364,28 @@ public abstract class WallpaperService extends Service {
int xPixelOffset, int yPixelOffset) { int xPixelOffset, int yPixelOffset) {
} }
/**
* 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 * Called when an application has changed the desired virtual size of
* the wallpaper. * 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() { void detach() {
mDestroyed = true; mDestroyed = true;
@@ -709,6 +775,10 @@ public abstract class WallpaperService extends Service {
case MSG_WALLPAPER_OFFSETS: { case MSG_WALLPAPER_OFFSETS: {
mEngine.doOffsetsChanged(); mEngine.doOffsetsChanged();
} break; } break;
case MSG_WALLPAPER_COMMAND: {
WallpaperCommand cmd = (WallpaperCommand)message.obj;
mEngine.doCommand(cmd);
} break;
case MSG_WINDOW_RESIZED: { case MSG_WINDOW_RESIZED: {
final boolean reportDraw = message.arg1 != 0; final boolean reportDraw = message.arg1 != 0;
mEngine.updateSurface(true, false); mEngine.updateSurface(true, false);

View File

@@ -18,11 +18,11 @@
package android.view; package android.view;
import android.graphics.Rect; import android.graphics.Rect;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.os.ParcelFileDescriptor;
/** /**
* API back to a client window that the Window Manager uses to inform it of * API back to a client window that the Window Manager uses to inform it of
* interesting things happening. * interesting things happening.
@@ -63,4 +63,7 @@ oneway interface IWindow {
* Called for wallpaper windows when their offsets change. * Called for wallpaper windows when their offsets change.
*/ */
void dispatchWallpaperOffsets(float x, float y, boolean sync); void dispatchWallpaperOffsets(float x, float y, boolean sync);
void dispatchWallpaperCommand(String action, int x, int y,
int z, in Bundle extras, boolean sync);
} }

View File

@@ -19,6 +19,7 @@ package android.view;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.Region; import android.graphics.Region;
import android.os.Bundle;
import android.view.IWindow; import android.view.IWindow;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.WindowManager; import android.view.WindowManager;
@@ -116,4 +117,9 @@ interface IWindowSession {
void setWallpaperPosition(IBinder windowToken, float x, float y); void setWallpaperPosition(IBinder windowToken, float x, float y);
void wallpaperOffsetsComplete(IBinder window); 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);
} }

View File

@@ -2904,6 +2904,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) {
}
}
}
} }
/** /**

View File

@@ -1,6 +1,7 @@
package com.android.internal.view; package com.android.internal.view;
import android.graphics.Rect; import android.graphics.Rect;
import android.os.Bundle;
import android.os.ParcelFileDescriptor; import android.os.ParcelFileDescriptor;
import android.os.RemoteException; import android.os.RemoteException;
import android.view.IWindow; 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) {
}
}
}
} }

View File

@@ -63,6 +63,7 @@ import android.graphics.Rect;
import android.graphics.Region; import android.graphics.Region;
import android.os.BatteryStats; import android.os.BatteryStats;
import android.os.Binder; import android.os.Binder;
import android.os.Bundle;
import android.os.Debug; import android.os.Debug;
import android.os.Handler; import android.os.Handler;
import android.os.IBinder; import android.os.IBinder;
@@ -432,8 +433,6 @@ public class WindowManagerService extends IWindowManager.Stub
int mWallpaperAnimLayerAdjustment; int mWallpaperAnimLayerAdjustment;
float mLastWallpaperX = -1; float mLastWallpaperX = -1;
float mLastWallpaperY = -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 // This is set when we are waiting for a wallpaper to tell us it is done
// changing its scroll position. // changing its scroll position.
WindowState mWaitingOnWallpaper; WindowState mWaitingOnWallpaper;
@@ -1604,34 +1603,30 @@ public class WindowManagerService extends IWindowManager.Stub
+ wallpaperWin + " x=" + wallpaperWin.mWallpaperX + wallpaperWin + " x=" + wallpaperWin.mWallpaperX
+ " y=" + wallpaperWin.mWallpaperY); + " y=" + wallpaperWin.mWallpaperY);
if (sync) { if (sync) {
synchronized (mWaitingOnWallpaperLock) { mWaitingOnWallpaper = wallpaperWin;
mWaitingOnWallpaper = wallpaperWin;
}
} }
wallpaperWin.mClient.dispatchWallpaperOffsets( wallpaperWin.mClient.dispatchWallpaperOffsets(
wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY, sync); wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY, sync);
if (sync) { if (sync) {
synchronized (mWaitingOnWallpaperLock) { if (mWaitingOnWallpaper != null) {
if (mWaitingOnWallpaper != null) { long start = SystemClock.uptimeMillis();
long start = SystemClock.uptimeMillis(); if ((mLastWallpaperTimeoutTime+WALLPAPER_TIMEOUT_RECOVERY)
if ((mLastWallpaperTimeoutTime+WALLPAPER_TIMEOUT_RECOVERY) < start) {
< start) { try {
try { if (DEBUG_WALLPAPER) Log.v(TAG,
if (DEBUG_WALLPAPER) Log.v(TAG, "Waiting for offset complete...");
"Waiting for offset complete..."); mWindowMap.wait(WALLPAPER_TIMEOUT);
mWaitingOnWallpaperLock.wait(WALLPAPER_TIMEOUT); } catch (InterruptedException e) {
} catch (InterruptedException e) { }
} if (DEBUG_WALLPAPER) Log.v(TAG, "Offset complete!");
if (DEBUG_WALLPAPER) Log.v(TAG, "Offset complete!"); if ((start+WALLPAPER_TIMEOUT)
if ((start+WALLPAPER_TIMEOUT) < SystemClock.uptimeMillis()) {
< SystemClock.uptimeMillis()) { Log.i(TAG, "Timeout waiting for wallpaper to offset: "
Log.i(TAG, "Timeout waiting for wallpaper to offset: " + wallpaperWin);
+ wallpaperWin); mLastWallpaperTimeoutTime = start;
mLastWallpaperTimeoutTime = start;
}
} }
mWaitingOnWallpaper = null;
} }
mWaitingOnWallpaper = null;
} }
} }
} catch (RemoteException e) { } catch (RemoteException e) {
@@ -1642,11 +1637,11 @@ public class WindowManagerService extends IWindowManager.Stub
} }
void wallpaperOffsetsComplete(IBinder window) { void wallpaperOffsetsComplete(IBinder window) {
synchronized (mWaitingOnWallpaperLock) { synchronized (mWindowMap) {
if (mWaitingOnWallpaper != null && if (mWaitingOnWallpaper != null &&
mWaitingOnWallpaper.mClient.asBinder() == window) { mWaitingOnWallpaper.mClient.asBinder() == window) {
mWaitingOnWallpaper = null; 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, public int relayoutWindow(Session session, IWindow client,
WindowManager.LayoutParams attrs, int requestedWidth, WindowManager.LayoutParams attrs, int requestedWidth,
int requestedHeight, int viewVisibility, boolean insetsPending, int requestedHeight, int viewVisibility, boolean insetsPending,
@@ -6565,6 +6601,24 @@ public class WindowManagerService extends IWindowManager.Stub
WindowManagerService.this.wallpaperOffsetsComplete(window); 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() { void windowAddedLocked() {
if (mSurfaceSession == null) { if (mSurfaceSession == null) {
if (localLOGV) Log.v( if (localLOGV) Log.v(

View File

@@ -36,6 +36,7 @@ import android.graphics.Rect;
import android.graphics.Region; import android.graphics.Region;
import android.graphics.Typeface; import android.graphics.Typeface;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.IBinder; import android.os.IBinder;
import android.os.Looper; import android.os.Looper;
@@ -1068,6 +1069,18 @@ public final class Bridge implements ILayoutBridge {
// pass for now. // pass for now.
} }
@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") @SuppressWarnings("unused")
public void closeSystemDialogs(String reason) { public void closeSystemDialogs(String reason) {
// pass for now. // pass for now.
@@ -1131,6 +1144,12 @@ public final class Bridge implements ILayoutBridge {
// pass for now. // pass for now.
} }
@SuppressWarnings("unused")
public void dispatchWallpaperCommand(String action, int x, int y,
int z, Bundle extras, boolean sync) {
// pass for now.
}
@SuppressWarnings("unused") @SuppressWarnings("unused")
public void closeSystemDialogs(String reason) { public void closeSystemDialogs(String reason) {
// pass for now. // pass for now.