blob: 20661d76f741e6e141d2fcd8d75c687b31ce8ae0 [file] [log] [blame]
Dianne Hackborn8cc6a502009-08-05 21:29:42 -07001/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.service.wallpaper;
18
19import com.android.internal.os.HandlerCaller;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070020import com.android.internal.view.BaseIWindow;
Jeff Brown46b9ac02010-04-22 18:58:52 -070021import com.android.internal.view.BaseInputHandler;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070022import com.android.internal.view.BaseSurfaceHolder;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070023
Dianne Hackbornd6847842010-01-12 18:14:19 -080024import android.annotation.SdkConstant;
25import android.annotation.SdkConstant.SdkConstantType;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070026import android.app.Service;
Dianne Hackborn759a39e2009-08-09 17:20:27 -070027import android.app.WallpaperManager;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070028import android.content.BroadcastReceiver;
29import android.content.Context;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070030import android.content.Intent;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070031import android.content.IntentFilter;
Dianne Hackborne36d6e22010-02-17 19:46:25 -080032import android.content.res.Configuration;
Mathias Agopian62bf4a02010-09-08 16:32:27 -070033import android.graphics.PixelFormat;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070034import android.graphics.Rect;
Dianne Hackborn75804932009-10-20 20:15:20 -070035import android.os.Bundle;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070036import android.os.IBinder;
Dianne Hackborn19382ac2009-09-11 21:13:37 -070037import android.os.Looper;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070038import android.os.Message;
Dianne Hackborna48a37f2011-02-01 16:30:38 -080039import android.os.Process;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070040import android.os.RemoteException;
41import android.util.Log;
Dianne Hackborn19382ac2009-09-11 21:13:37 -070042import android.util.LogPrinter;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070043import android.view.Gravity;
44import android.view.IWindowSession;
Jeff Brown46b9ac02010-04-22 18:58:52 -070045import android.view.InputChannel;
Jeff Brownc5ed5912010-07-14 18:48:53 -070046import android.view.InputDevice;
Jeff Brown46b9ac02010-04-22 18:58:52 -070047import android.view.InputHandler;
48import android.view.InputQueue;
49import android.view.KeyEvent;
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -070050import android.view.MotionEvent;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070051import android.view.SurfaceHolder;
52import android.view.View;
Dianne Hackborn72c82ab2009-08-11 21:13:54 -070053import android.view.ViewGroup;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070054import android.view.ViewRoot;
55import android.view.WindowManager;
56import android.view.WindowManagerImpl;
Jeff Brown46b9ac02010-04-22 18:58:52 -070057import android.view.WindowManagerPolicy;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070058
Dianne Hackbornaf1f42b2009-11-20 16:27:27 -080059import java.util.ArrayList;
60
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070061/**
62 * A wallpaper service is responsible for showing a live wallpaper behind
Dianne Hackborn23ef7b42009-11-18 18:20:39 -080063 * applications that would like to sit on top of it. This service object
64 * itself does very little -- its only purpose is to generate instances of
Dianne Hackborne4260f42009-11-18 21:15:59 -080065 * {@link Engine} as needed. Implementing a wallpaper thus
Dianne Hackborn23ef7b42009-11-18 18:20:39 -080066 * involves subclassing from this, subclassing an Engine implementation,
67 * and implementing {@link #onCreateEngine()} to return a new instance of
68 * your engine.
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070069 */
70public abstract class WallpaperService extends Service {
71 /**
72 * The {@link Intent} that must be declared as handled by the service.
Dianne Hackbornd6847842010-01-12 18:14:19 -080073 * To be supported, the service must also require the
74 * {@link android.Manifest.permission#BIND_WALLPAPER} permission so
75 * that other applications can not abuse it.
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070076 */
Dianne Hackbornd6847842010-01-12 18:14:19 -080077 @SdkConstant(SdkConstantType.SERVICE_ACTION)
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070078 public static final String SERVICE_INTERFACE =
Dianne Hackbornd6847842010-01-12 18:14:19 -080079 "android.service.wallpaper.WallpaperService";
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070080
Dianne Hackborneb034652009-09-07 00:49:58 -070081 /**
82 * Name under which a WallpaperService component publishes information
83 * about itself. This meta-data must reference an XML resource containing
84 * a <code>&lt;{@link android.R.styleable#Wallpaper wallpaper}&gt;</code>
85 * tag.
86 */
87 public static final String SERVICE_META_DATA = "android.service.wallpaper";
88
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070089 static final String TAG = "WallpaperService";
Dianne Hackborn72c82ab2009-08-11 21:13:54 -070090 static final boolean DEBUG = false;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070091
92 private static final int DO_ATTACH = 10;
93 private static final int DO_DETACH = 20;
Dianne Hackborn284ac932009-08-28 10:34:25 -070094 private static final int DO_SET_DESIRED_SIZE = 30;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070095
96 private static final int MSG_UPDATE_SURFACE = 10000;
Dianne Hackborn759a39e2009-08-09 17:20:27 -070097 private static final int MSG_VISIBILITY_CHANGED = 10010;
Dianne Hackborn72c82ab2009-08-11 21:13:54 -070098 private static final int MSG_WALLPAPER_OFFSETS = 10020;
Dianne Hackborn75804932009-10-20 20:15:20 -070099 private static final int MSG_WALLPAPER_COMMAND = 10025;
Dianne Hackborn7341d7a2009-08-14 11:37:52 -0700100 private static final int MSG_WINDOW_RESIZED = 10030;
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -0700101 private static final int MSG_TOUCH_EVENT = 10040;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700102
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700103 private Looper mCallbackLooper;
Dianne Hackbornaf1f42b2009-11-20 16:27:27 -0800104 private final ArrayList<Engine> mActiveEngines
105 = new ArrayList<Engine>();
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700106
Dianne Hackborn75804932009-10-20 20:15:20 -0700107 static final class WallpaperCommand {
108 String action;
109 int x;
110 int y;
111 int z;
112 Bundle extras;
113 boolean sync;
114 }
115
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700116 /**
117 * The actual implementation of a wallpaper. A wallpaper service may
118 * have multiple instances running (for example as a real wallpaper
119 * and as a preview), each of which is represented by its own Engine
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700120 * instance. You must implement {@link WallpaperService#onCreateEngine()}
121 * to return your concrete Engine implementation.
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700122 */
123 public class Engine {
124 IWallpaperEngineWrapper mIWallpaperEngine;
125
126 // Copies from mIWallpaperEngine.
127 HandlerCaller mCaller;
128 IWallpaperConnection mConnection;
129 IBinder mWindowToken;
130
131 boolean mInitializing = true;
Dianne Hackborn284ac932009-08-28 10:34:25 -0700132 boolean mVisible;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -0700133 boolean mScreenOn = true;
134 boolean mReportedVisible;
Dianne Hackborn284ac932009-08-28 10:34:25 -0700135 boolean mDestroyed;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700136
137 // Current window state.
138 boolean mCreated;
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700139 boolean mSurfaceCreated;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700140 boolean mIsCreating;
141 boolean mDrawingAllowed;
142 int mWidth;
143 int mHeight;
144 int mFormat;
145 int mType;
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700146 int mCurWidth;
147 int mCurHeight;
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -0700148 int mWindowFlags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
149 int mCurWindowFlags = mWindowFlags;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700150 final Rect mVisibleInsets = new Rect();
151 final Rect mWinFrame = new Rect();
152 final Rect mContentInsets = new Rect();
Dianne Hackborn694f79b2010-03-17 19:44:59 -0700153 final Configuration mConfiguration = new Configuration();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700154
155 final WindowManager.LayoutParams mLayout
156 = new WindowManager.LayoutParams();
157 IWindowSession mSession;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700158 InputChannel mInputChannel;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700159
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700160 final Object mLock = new Object();
161 boolean mOffsetMessageEnqueued;
162 float mPendingXOffset;
163 float mPendingYOffset;
Marco Nelissenbf6956b2009-11-09 15:21:13 -0800164 float mPendingXOffsetStep;
165 float mPendingYOffsetStep;
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700166 boolean mPendingSync;
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -0700167 MotionEvent mPendingMove;
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700168
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -0700169 final BroadcastReceiver mReceiver = new BroadcastReceiver() {
170 @Override
171 public void onReceive(Context context, Intent intent) {
172 if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())) {
173 mScreenOn = true;
174 reportVisibility();
175 } else if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {
176 mScreenOn = false;
177 reportVisibility();
178 }
179 }
180 };
181
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700182 final BaseSurfaceHolder mSurfaceHolder = new BaseSurfaceHolder() {
Mathias Agopian62bf4a02010-09-08 16:32:27 -0700183 {
184 mRequestedFormat = PixelFormat.RGB_565;
185 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700186
187 @Override
188 public boolean onAllowLockCanvas() {
189 return mDrawingAllowed;
190 }
191
192 @Override
193 public void onRelayoutContainer() {
194 Message msg = mCaller.obtainMessage(MSG_UPDATE_SURFACE);
195 mCaller.sendMessage(msg);
196 }
197
198 @Override
199 public void onUpdateSurface() {
200 Message msg = mCaller.obtainMessage(MSG_UPDATE_SURFACE);
201 mCaller.sendMessage(msg);
202 }
203
204 public boolean isCreating() {
205 return mIsCreating;
206 }
207
Dianne Hackborna48a37f2011-02-01 16:30:38 -0800208 @Override
209 public void setFixedSize(int width, int height) {
210 if (Process.myUid() != Process.SYSTEM_UID) {
211 // Regular apps can't do this. It can only work for
212 // certain designs of window animations, so you can't
213 // rely on it.
214 throw new UnsupportedOperationException(
215 "Wallpapers currently only support sizing from layout");
216 }
Michael Jurkab8f939f2011-02-01 20:50:30 -0800217 super.setFixedSize(width, height);
Dianne Hackborna48a37f2011-02-01 16:30:38 -0800218 }
219
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700220 public void setKeepScreenOn(boolean screenOn) {
Dianne Hackborn284ac932009-08-28 10:34:25 -0700221 throw new UnsupportedOperationException(
222 "Wallpapers do not support keep screen on");
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700223 }
224
225 };
226
Jeff Brown46b9ac02010-04-22 18:58:52 -0700227 final InputHandler mInputHandler = new BaseInputHandler() {
228 @Override
Jeff Brown3915bb82010-11-05 15:02:16 -0700229 public void handleMotion(MotionEvent event,
230 InputQueue.FinishedCallback finishedCallback) {
231 boolean handled = false;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700232 try {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700233 int source = event.getSource();
234 if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
235 dispatchPointer(event);
Jeff Brown3915bb82010-11-05 15:02:16 -0700236 handled = true;
Jeff Brownc5ed5912010-07-14 18:48:53 -0700237 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700238 } finally {
Jeff Brown3915bb82010-11-05 15:02:16 -0700239 finishedCallback.finished(handled);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700240 }
241 }
242 };
243
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700244 final BaseIWindow mWindow = new BaseIWindow() {
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -0700245 @Override
Dianne Hackborn7341d7a2009-08-14 11:37:52 -0700246 public void resized(int w, int h, Rect coveredInsets,
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800247 Rect visibleInsets, boolean reportDraw, Configuration newConfig) {
Dianne Hackborn7341d7a2009-08-14 11:37:52 -0700248 Message msg = mCaller.obtainMessageI(MSG_WINDOW_RESIZED,
249 reportDraw ? 1 : 0);
250 mCaller.sendMessage(msg);
251 }
252
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -0700253 @Override
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700254 public void dispatchAppVisibility(boolean visible) {
Dianne Hackborn284ac932009-08-28 10:34:25 -0700255 // We don't do this in preview mode; we'll let the preview
256 // activity tell us when to run.
257 if (!mIWallpaperEngine.mIsPreview) {
258 Message msg = mCaller.obtainMessageI(MSG_VISIBILITY_CHANGED,
259 visible ? 1 : 0);
260 mCaller.sendMessage(msg);
261 }
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700262 }
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700263
264 @Override
Marco Nelissenbf6956b2009-11-09 15:21:13 -0800265 public void dispatchWallpaperOffsets(float x, float y, float xStep, float yStep,
266 boolean sync) {
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700267 synchronized (mLock) {
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700268 if (DEBUG) Log.v(TAG, "Dispatch wallpaper offsets: " + x + ", " + y);
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700269 mPendingXOffset = x;
270 mPendingYOffset = y;
Marco Nelissenbf6956b2009-11-09 15:21:13 -0800271 mPendingXOffsetStep = xStep;
272 mPendingYOffsetStep = yStep;
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700273 if (sync) {
274 mPendingSync = true;
275 }
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700276 if (!mOffsetMessageEnqueued) {
277 mOffsetMessageEnqueued = true;
278 Message msg = mCaller.obtainMessage(MSG_WALLPAPER_OFFSETS);
279 mCaller.sendMessage(msg);
280 }
281 }
282 }
283
Dianne Hackborn75804932009-10-20 20:15:20 -0700284 public void dispatchWallpaperCommand(String action, int x, int y,
285 int z, Bundle extras, boolean sync) {
286 synchronized (mLock) {
287 if (DEBUG) Log.v(TAG, "Dispatch wallpaper command: " + x + ", " + y);
288 WallpaperCommand cmd = new WallpaperCommand();
289 cmd.action = action;
290 cmd.x = x;
291 cmd.y = y;
292 cmd.z = z;
293 cmd.extras = extras;
294 cmd.sync = sync;
295 Message msg = mCaller.obtainMessage(MSG_WALLPAPER_COMMAND);
296 msg.obj = cmd;
297 mCaller.sendMessage(msg);
298 }
299 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700300 };
301
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700302 /**
303 * Provides access to the surface in which this wallpaper is drawn.
304 */
305 public SurfaceHolder getSurfaceHolder() {
306 return mSurfaceHolder;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700307 }
308
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700309 /**
310 * Convenience for {@link WallpaperManager#getDesiredMinimumWidth()
311 * WallpaperManager.getDesiredMinimumWidth()}, returning the width
312 * that the system would like this wallpaper to run in.
313 */
314 public int getDesiredMinimumWidth() {
315 return mIWallpaperEngine.mReqWidth;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700316 }
317
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700318 /**
319 * Convenience for {@link WallpaperManager#getDesiredMinimumHeight()
320 * WallpaperManager.getDesiredMinimumHeight()}, returning the height
321 * that the system would like this wallpaper to run in.
322 */
323 public int getDesiredMinimumHeight() {
324 return mIWallpaperEngine.mReqHeight;
325 }
326
327 /**
Dianne Hackborn284ac932009-08-28 10:34:25 -0700328 * Return whether the wallpaper is currently visible to the user,
329 * this is the last value supplied to
330 * {@link #onVisibilityChanged(boolean)}.
331 */
332 public boolean isVisible() {
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -0700333 return mReportedVisible;
Dianne Hackborn284ac932009-08-28 10:34:25 -0700334 }
335
336 /**
Dianne Hackborn3be63c02009-08-20 19:31:38 -0700337 * Returns true if this engine is running in preview mode -- that is,
338 * it is being shown to the user before they select it as the actual
339 * wallpaper.
340 */
341 public boolean isPreview() {
342 return mIWallpaperEngine.mIsPreview;
343 }
344
345 /**
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -0700346 * Control whether this wallpaper will receive raw touch events
347 * from the window manager as the user interacts with the window
348 * that is currently displaying the wallpaper. By default they
349 * are turned off. If enabled, the events will be received in
350 * {@link #onTouchEvent(MotionEvent)}.
351 */
352 public void setTouchEventsEnabled(boolean enabled) {
353 mWindowFlags = enabled
354 ? (mWindowFlags&~WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE)
355 : (mWindowFlags|WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
356 if (mCreated) {
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700357 updateSurface(false, false, false);
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -0700358 }
359 }
360
361 /**
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700362 * Called once to initialize the engine. After returning, the
363 * engine's surface will be created by the framework.
364 */
365 public void onCreate(SurfaceHolder surfaceHolder) {
366 }
367
368 /**
369 * Called right before the engine is going away. After this the
370 * surface will be destroyed and this Engine object is no longer
371 * valid.
372 */
373 public void onDestroy() {
374 }
375
376 /**
377 * Called to inform you of the wallpaper becoming visible or
378 * hidden. <em>It is very important that a wallpaper only use
379 * CPU while it is visible.</em>.
380 */
381 public void onVisibilityChanged(boolean visible) {
382 }
383
384 /**
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -0700385 * Called as the user performs touch-screen interaction with the
386 * window that is currently showing this wallpaper. Note that the
387 * events you receive here are driven by the actual application the
Marco Nelissenae87bd02009-09-17 09:44:43 -0700388 * user is interacting with, so if it is slow you will get fewer
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -0700389 * move events.
390 */
391 public void onTouchEvent(MotionEvent event) {
392 }
393
394 /**
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700395 * Called to inform you of the wallpaper's offsets changing
396 * within its contain, corresponding to the container's
397 * call to {@link WallpaperManager#setWallpaperOffsets(IBinder, float, float)
398 * WallpaperManager.setWallpaperOffsets()}.
399 */
400 public void onOffsetsChanged(float xOffset, float yOffset,
Marco Nelissenbf6956b2009-11-09 15:21:13 -0800401 float xOffsetStep, float yOffsetStep,
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700402 int xPixelOffset, int yPixelOffset) {
403 }
404
405 /**
Dianne Hackborn75804932009-10-20 20:15:20 -0700406 * Process a command that was sent to the wallpaper with
Dianne Hackborn13bf82602009-11-05 21:45:51 -0800407 * {@link WallpaperManager#sendWallpaperCommand}.
Dianne Hackborn75804932009-10-20 20:15:20 -0700408 * The default implementation does nothing, and always returns null
409 * as the result.
410 *
411 * @param action The name of the command to perform. This tells you
412 * what to do and how to interpret the rest of the arguments.
413 * @param x Generic integer parameter.
414 * @param y Generic integer parameter.
415 * @param z Generic integer parameter.
416 * @param extras Any additional parameters.
417 * @param resultRequested If true, the caller is requesting that
418 * a result, appropriate for the command, be returned back.
419 * @return If returning a result, create a Bundle and place the
420 * result data in to it. Otherwise return null.
421 */
422 public Bundle onCommand(String action, int x, int y, int z,
423 Bundle extras, boolean resultRequested) {
424 return null;
425 }
426
427 /**
Dianne Hackborn284ac932009-08-28 10:34:25 -0700428 * Called when an application has changed the desired virtual size of
429 * the wallpaper.
430 */
431 public void onDesiredSizeChanged(int desiredWidth, int desiredHeight) {
432 }
433
434 /**
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700435 * Convenience for {@link SurfaceHolder.Callback#surfaceChanged
436 * SurfaceHolder.Callback.surfaceChanged()}.
437 */
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700438 public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
439 }
440
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700441 /**
Dianne Hackborn1d28f9c2010-07-13 20:38:06 -0700442 * Convenience for {@link SurfaceHolder.Callback2#surfaceRedrawNeeded
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700443 * SurfaceHolder.Callback.surfaceRedrawNeeded()}.
444 */
445 public void onSurfaceRedrawNeeded(SurfaceHolder holder) {
446 }
447
448 /**
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700449 * Convenience for {@link SurfaceHolder.Callback#surfaceCreated
450 * SurfaceHolder.Callback.surfaceCreated()}.
451 */
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700452 public void onSurfaceCreated(SurfaceHolder holder) {
453 }
454
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700455 /**
456 * Convenience for {@link SurfaceHolder.Callback#surfaceDestroyed
457 * SurfaceHolder.Callback.surfaceDestroyed()}.
458 */
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700459 public void onSurfaceDestroyed(SurfaceHolder holder) {
460 }
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700461
462 private void dispatchPointer(MotionEvent event) {
Jeff Brown33bbfd22011-02-24 20:55:35 -0800463 if (event.isTouchEvent()) {
464 synchronized (mLock) {
465 if (event.getAction() == MotionEvent.ACTION_MOVE) {
466 mPendingMove = event;
467 } else {
468 mPendingMove = null;
469 }
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700470 }
Jeff Brown33bbfd22011-02-24 20:55:35 -0800471 Message msg = mCaller.obtainMessageO(MSG_TOUCH_EVENT, event);
472 mCaller.sendMessage(msg);
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700473 }
474 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700475
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700476 void updateSurface(boolean forceRelayout, boolean forceReport, boolean redrawNeeded) {
Dianne Hackborn284ac932009-08-28 10:34:25 -0700477 if (mDestroyed) {
478 Log.w(TAG, "Ignoring updateSurface: destroyed");
479 }
480
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700481 int myWidth = mSurfaceHolder.getRequestedWidth();
Romain Guy980a9382010-01-08 15:06:28 -0800482 if (myWidth <= 0) myWidth = ViewGroup.LayoutParams.MATCH_PARENT;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700483 int myHeight = mSurfaceHolder.getRequestedHeight();
Romain Guy980a9382010-01-08 15:06:28 -0800484 if (myHeight <= 0) myHeight = ViewGroup.LayoutParams.MATCH_PARENT;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700485
486 final boolean creating = !mCreated;
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700487 final boolean surfaceCreating = !mSurfaceCreated;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700488 final boolean formatChanged = mFormat != mSurfaceHolder.getRequestedFormat();
Dianne Hackborn7341d7a2009-08-14 11:37:52 -0700489 boolean sizeChanged = mWidth != myWidth || mHeight != myHeight;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700490 final boolean typeChanged = mType != mSurfaceHolder.getRequestedType();
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -0700491 final boolean flagsChanged = mCurWindowFlags != mWindowFlags;
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700492 if (forceRelayout || creating || surfaceCreating || formatChanged || sizeChanged
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700493 || typeChanged || flagsChanged || redrawNeeded) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700494
Dianne Hackborn284ac932009-08-28 10:34:25 -0700495 if (DEBUG) Log.v(TAG, "Changes: creating=" + creating
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700496 + " format=" + formatChanged + " size=" + sizeChanged);
497
498 try {
499 mWidth = myWidth;
500 mHeight = myHeight;
501 mFormat = mSurfaceHolder.getRequestedFormat();
502 mType = mSurfaceHolder.getRequestedType();
503
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700504 mLayout.x = 0;
505 mLayout.y = 0;
506 mLayout.width = myWidth;
507 mLayout.height = myHeight;
508
509 mLayout.format = mFormat;
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -0700510
511 mCurWindowFlags = mWindowFlags;
512 mLayout.flags = mWindowFlags
513 | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
514 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
515 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
516 ;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700517
518 mLayout.memoryType = mType;
519 mLayout.token = mWindowToken;
520
521 if (!mCreated) {
Dianne Hackborn3be63c02009-08-20 19:31:38 -0700522 mLayout.type = mIWallpaperEngine.mWindowType;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700523 mLayout.gravity = Gravity.LEFT|Gravity.TOP;
Dianne Hackborn0586a1b2009-09-06 21:08:27 -0700524 mLayout.setTitle(WallpaperService.this.getClass().getName());
Dianne Hackborn284ac932009-08-28 10:34:25 -0700525 mLayout.windowAnimations =
526 com.android.internal.R.style.Animation_Wallpaper;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700527 mInputChannel = new InputChannel();
Mattias Peterssond9463f52011-01-12 15:38:55 +0100528 if (mSession.add(mWindow, mLayout, View.VISIBLE, mContentInsets,
529 mInputChannel) < 0) {
530 Log.w(TAG, "Failed to add window while updating wallpaper surface.");
531 return;
532 }
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700533 mCreated = true;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700534
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700535 InputQueue.registerInputChannel(mInputChannel, mInputHandler,
536 Looper.myQueue());
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700537 }
538
539 mSurfaceHolder.mSurfaceLock.lock();
540 mDrawingAllowed = true;
541
542 final int relayoutResult = mSession.relayout(
543 mWindow, mLayout, mWidth, mHeight,
544 View.VISIBLE, false, mWinFrame, mContentInsets,
Dianne Hackborn694f79b2010-03-17 19:44:59 -0700545 mVisibleInsets, mConfiguration, mSurfaceHolder.mSurface);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700546
Dianne Hackborn284ac932009-08-28 10:34:25 -0700547 if (DEBUG) Log.v(TAG, "New surface: " + mSurfaceHolder.mSurface
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700548 + ", frame=" + mWinFrame);
549
Dianne Hackborn7341d7a2009-08-14 11:37:52 -0700550 int w = mWinFrame.width();
551 if (mCurWidth != w) {
552 sizeChanged = true;
553 mCurWidth = w;
554 }
555 int h = mWinFrame.height();
556 if (mCurHeight != h) {
557 sizeChanged = true;
558 mCurHeight = h;
559 }
Jeff Brown30bc34f2011-01-25 12:56:56 -0800560
561 mSurfaceHolder.setSurfaceFrameSize(w, h);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700562 mSurfaceHolder.mSurfaceLock.unlock();
563
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700564 if (!mSurfaceHolder.mSurface.isValid()) {
565 reportSurfaceDestroyed();
566 if (DEBUG) Log.v(TAG, "Layout: Surface destroyed");
567 return;
568 }
569
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700570 try {
Dianne Hackborndc8a7f62010-05-10 11:29:34 -0700571 mSurfaceHolder.ungetCallbacks();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700572
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700573 if (surfaceCreating) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700574 mIsCreating = true;
Dianne Hackborn284ac932009-08-28 10:34:25 -0700575 if (DEBUG) Log.v(TAG, "onSurfaceCreated("
576 + mSurfaceHolder + "): " + this);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700577 onSurfaceCreated(mSurfaceHolder);
Dianne Hackborndc8a7f62010-05-10 11:29:34 -0700578 SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700579 if (callbacks != null) {
580 for (SurfaceHolder.Callback c : callbacks) {
581 c.surfaceCreated(mSurfaceHolder);
582 }
583 }
584 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700585
586 redrawNeeded |= creating
587 || (relayoutResult&WindowManagerImpl.RELAYOUT_FIRST_TIME) != 0;
588
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700589 if (forceReport || creating || surfaceCreating
590 || formatChanged || sizeChanged) {
Dianne Hackborncbf15042009-08-18 18:29:09 -0700591 if (DEBUG) {
592 RuntimeException e = new RuntimeException();
593 e.fillInStackTrace();
594 Log.w(TAG, "forceReport=" + forceReport + " creating=" + creating
595 + " formatChanged=" + formatChanged
596 + " sizeChanged=" + sizeChanged, e);
597 }
Dianne Hackborn284ac932009-08-28 10:34:25 -0700598 if (DEBUG) Log.v(TAG, "onSurfaceChanged("
599 + mSurfaceHolder + ", " + mFormat
600 + ", " + mCurWidth + ", " + mCurHeight
601 + "): " + this);
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700602 onSurfaceChanged(mSurfaceHolder, mFormat,
603 mCurWidth, mCurHeight);
Dianne Hackborndc8a7f62010-05-10 11:29:34 -0700604 SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700605 if (callbacks != null) {
606 for (SurfaceHolder.Callback c : callbacks) {
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700607 c.surfaceChanged(mSurfaceHolder, mFormat,
608 mCurWidth, mCurHeight);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700609 }
610 }
611 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700612
613 if (redrawNeeded) {
614 onSurfaceRedrawNeeded(mSurfaceHolder);
615 SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
616 if (callbacks != null) {
617 for (SurfaceHolder.Callback c : callbacks) {
618 if (c instanceof SurfaceHolder.Callback2) {
619 ((SurfaceHolder.Callback2)c).surfaceRedrawNeeded(
620 mSurfaceHolder);
621 }
622 }
623 }
624 }
625
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700626 } finally {
627 mIsCreating = false;
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700628 mSurfaceCreated = true;
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700629 if (redrawNeeded) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700630 mSession.finishDrawing(mWindow);
631 }
632 }
633 } catch (RemoteException ex) {
634 }
635 if (DEBUG) Log.v(
636 TAG, "Layout: x=" + mLayout.x + " y=" + mLayout.y +
637 " w=" + mLayout.width + " h=" + mLayout.height);
638 }
639 }
640
641 void attach(IWallpaperEngineWrapper wrapper) {
Dianne Hackborncbf15042009-08-18 18:29:09 -0700642 if (DEBUG) Log.v(TAG, "attach: " + this + " wrapper=" + wrapper);
Dianne Hackborn284ac932009-08-28 10:34:25 -0700643 if (mDestroyed) {
644 return;
645 }
646
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700647 mIWallpaperEngine = wrapper;
648 mCaller = wrapper.mCaller;
649 mConnection = wrapper.mConnection;
650 mWindowToken = wrapper.mWindowToken;
Dianne Hackborn284ac932009-08-28 10:34:25 -0700651 mSurfaceHolder.setSizeFromLayout();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700652 mInitializing = true;
653 mSession = ViewRoot.getWindowSession(getMainLooper());
Jeff Brown46b9ac02010-04-22 18:58:52 -0700654
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700655 mWindow.setSession(mSession);
656
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -0700657 IntentFilter filter = new IntentFilter();
658 filter.addAction(Intent.ACTION_SCREEN_ON);
659 filter.addAction(Intent.ACTION_SCREEN_OFF);
660 registerReceiver(mReceiver, filter);
661
Dianne Hackborn284ac932009-08-28 10:34:25 -0700662 if (DEBUG) Log.v(TAG, "onCreate(): " + this);
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700663 onCreate(mSurfaceHolder);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700664
665 mInitializing = false;
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700666 updateSurface(false, false, false);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700667 }
668
Dianne Hackborn284ac932009-08-28 10:34:25 -0700669 void doDesiredSizeChanged(int desiredWidth, int desiredHeight) {
670 if (!mDestroyed) {
671 if (DEBUG) Log.v(TAG, "onDesiredSizeChanged("
672 + desiredWidth + "," + desiredHeight + "): " + this);
Joe Onoratodcfae5c2010-10-28 18:03:23 -0700673 mIWallpaperEngine.mReqWidth = desiredWidth;
674 mIWallpaperEngine.mReqHeight = desiredHeight;
Dianne Hackborn284ac932009-08-28 10:34:25 -0700675 onDesiredSizeChanged(desiredWidth, desiredHeight);
Joe Onoratodcfae5c2010-10-28 18:03:23 -0700676 doOffsetsChanged();
Dianne Hackborn284ac932009-08-28 10:34:25 -0700677 }
678 }
679
680 void doVisibilityChanged(boolean visible) {
Dianne Hackbornaf1f42b2009-11-20 16:27:27 -0800681 if (!mDestroyed) {
682 mVisible = visible;
683 reportVisibility();
684 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -0700685 }
686
687 void reportVisibility() {
Dianne Hackborn284ac932009-08-28 10:34:25 -0700688 if (!mDestroyed) {
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -0700689 boolean visible = mVisible && mScreenOn;
690 if (mReportedVisible != visible) {
691 mReportedVisible = visible;
692 if (DEBUG) Log.v(TAG, "onVisibilityChanged(" + visible
693 + "): " + this);
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700694 if (visible) {
695 // If becoming visible, in preview mode the surface
696 // may have been destroyed so now we need to make
697 // sure it is re-created.
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700698 updateSurface(false, false, false);
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700699 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -0700700 onVisibilityChanged(visible);
701 }
Dianne Hackborn284ac932009-08-28 10:34:25 -0700702 }
703 }
704
705 void doOffsetsChanged() {
706 if (mDestroyed) {
707 return;
708 }
709
710 float xOffset;
711 float yOffset;
Marco Nelissenbf6956b2009-11-09 15:21:13 -0800712 float xOffsetStep;
713 float yOffsetStep;
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700714 boolean sync;
Dianne Hackborn284ac932009-08-28 10:34:25 -0700715 synchronized (mLock) {
716 xOffset = mPendingXOffset;
717 yOffset = mPendingYOffset;
Marco Nelissenbf6956b2009-11-09 15:21:13 -0800718 xOffsetStep = mPendingXOffsetStep;
719 yOffsetStep = mPendingYOffsetStep;
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700720 sync = mPendingSync;
721 mPendingSync = false;
Dianne Hackborn284ac932009-08-28 10:34:25 -0700722 mOffsetMessageEnqueued = false;
723 }
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700724
725 if (mSurfaceCreated) {
726 if (DEBUG) Log.v(TAG, "Offsets change in " + this
727 + ": " + xOffset + "," + yOffset);
728 final int availw = mIWallpaperEngine.mReqWidth-mCurWidth;
729 final int xPixels = availw > 0 ? -(int)(availw*xOffset+.5f) : 0;
730 final int availh = mIWallpaperEngine.mReqHeight-mCurHeight;
731 final int yPixels = availh > 0 ? -(int)(availh*yOffset+.5f) : 0;
732 onOffsetsChanged(xOffset, yOffset, xOffsetStep, yOffsetStep, xPixels, yPixels);
733 }
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700734
735 if (sync) {
736 try {
737 if (DEBUG) Log.v(TAG, "Reporting offsets change complete");
738 mSession.wallpaperOffsetsComplete(mWindow.asBinder());
739 } catch (RemoteException e) {
740 }
741 }
Dianne Hackborn284ac932009-08-28 10:34:25 -0700742 }
743
Dianne Hackborn75804932009-10-20 20:15:20 -0700744 void doCommand(WallpaperCommand cmd) {
745 Bundle result;
746 if (!mDestroyed) {
747 result = onCommand(cmd.action, cmd.x, cmd.y, cmd.z,
748 cmd.extras, cmd.sync);
749 } else {
750 result = null;
751 }
752 if (cmd.sync) {
753 try {
754 if (DEBUG) Log.v(TAG, "Reporting command complete");
755 mSession.wallpaperCommandComplete(mWindow.asBinder(), result);
756 } catch (RemoteException e) {
757 }
758 }
759 }
760
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700761 void reportSurfaceDestroyed() {
762 if (mSurfaceCreated) {
763 mSurfaceCreated = false;
Dianne Hackborndc8a7f62010-05-10 11:29:34 -0700764 mSurfaceHolder.ungetCallbacks();
765 SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
766 if (callbacks != null) {
767 for (SurfaceHolder.Callback c : callbacks) {
768 c.surfaceDestroyed(mSurfaceHolder);
769 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700770 }
Dianne Hackborn284ac932009-08-28 10:34:25 -0700771 if (DEBUG) Log.v(TAG, "onSurfaceDestroyed("
772 + mSurfaceHolder + "): " + this);
773 onSurfaceDestroyed(mSurfaceHolder);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700774 }
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700775 }
776
777 void detach() {
778 if (mDestroyed) {
779 return;
780 }
781
782 mDestroyed = true;
783
784 if (mVisible) {
785 mVisible = false;
786 if (DEBUG) Log.v(TAG, "onVisibilityChanged(false): " + this);
787 onVisibilityChanged(false);
788 }
789
790 reportSurfaceDestroyed();
Dianne Hackborn284ac932009-08-28 10:34:25 -0700791
792 if (DEBUG) Log.v(TAG, "onDestroy(): " + this);
793 onDestroy();
794
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -0700795 unregisterReceiver(mReceiver);
796
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700797 if (mCreated) {
798 try {
Dianne Hackbornba3e31d2010-04-22 18:59:03 -0700799 if (DEBUG) Log.v(TAG, "Removing window and destroying surface "
800 + mSurfaceHolder.getSurface() + " of: " + this);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700801
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700802 if (mInputChannel != null) {
803 InputQueue.unregisterInputChannel(mInputChannel);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700804 }
805
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700806 mSession.remove(mWindow);
807 } catch (RemoteException e) {
808 }
Dianne Hackborn0586a1b2009-09-06 21:08:27 -0700809 mSurfaceHolder.mSurface.release();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700810 mCreated = false;
Jeff Brown349703e2010-06-22 01:27:15 -0700811
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700812 // Dispose the input channel after removing the window so the Window Manager
813 // doesn't interpret the input channel being closed as an abnormal termination.
814 if (mInputChannel != null) {
815 mInputChannel.dispose();
816 mInputChannel = null;
Jeff Brown349703e2010-06-22 01:27:15 -0700817 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700818 }
819 }
820 }
821
822 class IWallpaperEngineWrapper extends IWallpaperEngine.Stub
823 implements HandlerCaller.Callback {
824 private final HandlerCaller mCaller;
825
826 final IWallpaperConnection mConnection;
827 final IBinder mWindowToken;
Dianne Hackborn3be63c02009-08-20 19:31:38 -0700828 final int mWindowType;
829 final boolean mIsPreview;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700830 int mReqWidth;
831 int mReqHeight;
832
833 Engine mEngine;
834
835 IWallpaperEngineWrapper(WallpaperService context,
836 IWallpaperConnection conn, IBinder windowToken,
Dianne Hackborn3be63c02009-08-20 19:31:38 -0700837 int windowType, boolean isPreview, int reqWidth, int reqHeight) {
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700838 if (DEBUG && mCallbackLooper != null) {
839 mCallbackLooper.setMessageLogging(new LogPrinter(Log.VERBOSE, TAG));
840 }
841 mCaller = new HandlerCaller(context,
842 mCallbackLooper != null
843 ? mCallbackLooper : context.getMainLooper(),
844 this);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700845 mConnection = conn;
846 mWindowToken = windowToken;
Dianne Hackborn3be63c02009-08-20 19:31:38 -0700847 mWindowType = windowType;
848 mIsPreview = isPreview;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700849 mReqWidth = reqWidth;
850 mReqHeight = reqHeight;
851
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700852 Message msg = mCaller.obtainMessage(DO_ATTACH);
853 mCaller.sendMessage(msg);
854 }
855
Dianne Hackborn284ac932009-08-28 10:34:25 -0700856 public void setDesiredSize(int width, int height) {
857 Message msg = mCaller.obtainMessageII(DO_SET_DESIRED_SIZE, width, height);
858 mCaller.sendMessage(msg);
859 }
860
861 public void setVisibility(boolean visible) {
862 Message msg = mCaller.obtainMessageI(MSG_VISIBILITY_CHANGED,
863 visible ? 1 : 0);
864 mCaller.sendMessage(msg);
865 }
866
Dianne Hackborn6adba242009-11-10 11:10:09 -0800867 public void dispatchPointer(MotionEvent event) {
868 if (mEngine != null) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700869 mEngine.dispatchPointer(event);
Dianne Hackborn6adba242009-11-10 11:10:09 -0800870 }
871 }
Jeff Brown9f3bdfe2010-10-13 06:01:27 -0700872
873 public void dispatchWallpaperCommand(String action, int x, int y,
874 int z, Bundle extras) {
875 if (mEngine != null) {
876 mEngine.mWindow.dispatchWallpaperCommand(action, x, y, z, extras, false);
877 }
878 }
879
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700880 public void destroy() {
881 Message msg = mCaller.obtainMessage(DO_DETACH);
882 mCaller.sendMessage(msg);
883 }
884
885 public void executeMessage(Message message) {
886 switch (message.what) {
887 case DO_ATTACH: {
Dianne Hackborn284ac932009-08-28 10:34:25 -0700888 try {
889 mConnection.attachEngine(this);
890 } catch (RemoteException e) {
891 Log.w(TAG, "Wallpaper host disappeared", e);
892 return;
893 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700894 Engine engine = onCreateEngine();
895 mEngine = engine;
Dianne Hackbornaf1f42b2009-11-20 16:27:27 -0800896 mActiveEngines.add(engine);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700897 engine.attach(this);
898 return;
899 }
900 case DO_DETACH: {
Dianne Hackbornaf1f42b2009-11-20 16:27:27 -0800901 mActiveEngines.remove(mEngine);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700902 mEngine.detach();
903 return;
904 }
Dianne Hackborn284ac932009-08-28 10:34:25 -0700905 case DO_SET_DESIRED_SIZE: {
906 mEngine.doDesiredSizeChanged(message.arg1, message.arg2);
907 return;
908 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700909 case MSG_UPDATE_SURFACE:
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700910 mEngine.updateSurface(true, false, false);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700911 break;
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700912 case MSG_VISIBILITY_CHANGED:
913 if (DEBUG) Log.v(TAG, "Visibility change in " + mEngine
914 + ": " + message.arg1);
Dianne Hackborn284ac932009-08-28 10:34:25 -0700915 mEngine.doVisibilityChanged(message.arg1 != 0);
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700916 break;
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700917 case MSG_WALLPAPER_OFFSETS: {
Dianne Hackborn284ac932009-08-28 10:34:25 -0700918 mEngine.doOffsetsChanged();
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700919 } break;
Dianne Hackborn75804932009-10-20 20:15:20 -0700920 case MSG_WALLPAPER_COMMAND: {
921 WallpaperCommand cmd = (WallpaperCommand)message.obj;
922 mEngine.doCommand(cmd);
923 } break;
Dianne Hackborn7341d7a2009-08-14 11:37:52 -0700924 case MSG_WINDOW_RESIZED: {
925 final boolean reportDraw = message.arg1 != 0;
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700926 mEngine.updateSurface(true, false, reportDraw);
Romain Guy04cde342010-03-04 16:07:49 -0800927 mEngine.doOffsetsChanged();
Dianne Hackborn7341d7a2009-08-14 11:37:52 -0700928 } break;
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -0700929 case MSG_TOUCH_EVENT: {
Jeff Brown840db1f2010-10-21 17:36:54 -0700930 boolean skip = false;
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -0700931 MotionEvent ev = (MotionEvent)message.obj;
Jeff Brown840db1f2010-10-21 17:36:54 -0700932 if (ev.getAction() == MotionEvent.ACTION_MOVE) {
933 synchronized (mEngine.mLock) {
934 if (mEngine.mPendingMove == ev) {
935 mEngine.mPendingMove = null;
936 } else {
937 // this is not the motion event we are looking for....
938 skip = true;
939 }
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -0700940 }
941 }
Jeff Brown840db1f2010-10-21 17:36:54 -0700942 if (!skip) {
943 if (DEBUG) Log.v(TAG, "Delivering touch event: " + ev);
944 mEngine.onTouchEvent(ev);
945 }
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -0700946 ev.recycle();
947 } break;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700948 default :
949 Log.w(TAG, "Unknown message type " + message.what);
950 }
951 }
952 }
953
954 /**
955 * Implements the internal {@link IWallpaperService} interface to convert
956 * incoming calls to it back to calls on an {@link WallpaperService}.
957 */
958 class IWallpaperServiceWrapper extends IWallpaperService.Stub {
959 private final WallpaperService mTarget;
960
961 public IWallpaperServiceWrapper(WallpaperService context) {
962 mTarget = context;
963 }
964
Dianne Hackborn3be63c02009-08-20 19:31:38 -0700965 public void attach(IWallpaperConnection conn, IBinder windowToken,
966 int windowType, boolean isPreview, int reqWidth, int reqHeight) {
967 new IWallpaperEngineWrapper(mTarget, conn, windowToken,
968 windowType, isPreview, reqWidth, reqHeight);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700969 }
970 }
971
Dianne Hackbornaf1f42b2009-11-20 16:27:27 -0800972 @Override
973 public void onCreate() {
974 super.onCreate();
975 }
976
977 @Override
978 public void onDestroy() {
979 super.onDestroy();
980 for (int i=0; i<mActiveEngines.size(); i++) {
981 mActiveEngines.get(i).detach();
982 }
983 mActiveEngines.clear();
984 }
985
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700986 /**
987 * Implement to return the implementation of the internal accessibility
988 * service interface. Subclasses should not override.
989 */
990 @Override
991 public final IBinder onBind(Intent intent) {
992 return new IWallpaperServiceWrapper(this);
993 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700994
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700995 /**
996 * This allows subclasses to change the thread that most callbacks
997 * occur on. Currently hidden because it is mostly needed for the
998 * image wallpaper (which runs in the system process and doesn't want
999 * to get stuck running on that seriously in use main thread). Not
1000 * exposed right now because the semantics of this are not totally
1001 * well defined and some callbacks can still happen on the main thread).
1002 * @hide
1003 */
1004 public void setCallbackLooper(Looper looper) {
1005 mCallbackLooper = looper;
1006 }
1007
Dianne Hackborn23ef7b42009-11-18 18:20:39 -08001008 /**
1009 * Must be implemented to return a new instance of the wallpaper's engine.
1010 * Note that multiple instances may be active at the same time, such as
1011 * when the wallpaper is currently set as the active wallpaper and the user
1012 * is in the wallpaper picker viewing a preview of it as well.
1013 */
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001014 public abstract Engine onCreateEngine();
Dianne Hackborn8cc6a502009-08-05 21:29:42 -07001015}