blob: 5db81689afb7a9cd250b262803b76071fccc822b [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;
21import com.android.internal.view.BaseSurfaceHolder;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070022
Dianne Hackbornd6847842010-01-12 18:14:19 -080023import android.annotation.SdkConstant;
24import android.annotation.SdkConstant.SdkConstantType;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070025import android.app.Service;
Dianne Hackborn759a39e2009-08-09 17:20:27 -070026import android.app.WallpaperManager;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070027import android.content.BroadcastReceiver;
28import android.content.Context;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070029import android.content.Intent;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070030import android.content.IntentFilter;
Dianne Hackborne36d6e22010-02-17 19:46:25 -080031import android.content.res.Configuration;
Mathias Agopian62bf4a02010-09-08 16:32:27 -070032import android.graphics.PixelFormat;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070033import android.graphics.Rect;
Dianne Hackborn75804932009-10-20 20:15:20 -070034import android.os.Bundle;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070035import android.os.IBinder;
Dianne Hackborn19382ac2009-09-11 21:13:37 -070036import android.os.Looper;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070037import android.os.Message;
Dianne Hackborn9fe6cb52011-09-09 13:02:43 -070038import android.os.PowerManager;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070039import android.os.RemoteException;
40import android.util.Log;
Dianne Hackborn19382ac2009-09-11 21:13:37 -070041import android.util.LogPrinter;
Craig Mautner6881a102012-07-27 13:04:51 -070042import android.view.Display;
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 Brown4952dfd2011-11-30 19:23:22 -080047import android.view.InputEvent;
Jeff Brown32cbc38552011-12-01 14:01:49 -080048import android.view.InputEventReceiver;
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -070049import android.view.MotionEvent;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070050import android.view.SurfaceHolder;
51import android.view.View;
Dianne Hackborn72c82ab2009-08-11 21:13:54 -070052import android.view.ViewGroup;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070053import android.view.WindowManager;
Jeff Brown98365d72012-08-19 20:30:52 -070054import android.view.WindowManagerGlobal;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070055
Dianne Hackborn527de8e2011-08-22 16:10:36 -070056import java.io.FileDescriptor;
57import java.io.PrintWriter;
Dianne Hackbornaf1f42b2009-11-20 16:27:27 -080058import java.util.ArrayList;
59
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070060/**
61 * A wallpaper service is responsible for showing a live wallpaper behind
Dianne Hackborn23ef7b42009-11-18 18:20:39 -080062 * applications that would like to sit on top of it. This service object
63 * itself does very little -- its only purpose is to generate instances of
Dianne Hackborne4260f42009-11-18 21:15:59 -080064 * {@link Engine} as needed. Implementing a wallpaper thus
Dianne Hackborn23ef7b42009-11-18 18:20:39 -080065 * involves subclassing from this, subclassing an Engine implementation,
66 * and implementing {@link #onCreateEngine()} to return a new instance of
67 * your engine.
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070068 */
69public abstract class WallpaperService extends Service {
70 /**
71 * The {@link Intent} that must be declared as handled by the service.
Dianne Hackbornd6847842010-01-12 18:14:19 -080072 * To be supported, the service must also require the
73 * {@link android.Manifest.permission#BIND_WALLPAPER} permission so
74 * that other applications can not abuse it.
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070075 */
Dianne Hackbornd6847842010-01-12 18:14:19 -080076 @SdkConstant(SdkConstantType.SERVICE_ACTION)
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070077 public static final String SERVICE_INTERFACE =
Dianne Hackbornd6847842010-01-12 18:14:19 -080078 "android.service.wallpaper.WallpaperService";
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070079
Dianne Hackborneb034652009-09-07 00:49:58 -070080 /**
81 * Name under which a WallpaperService component publishes information
82 * about itself. This meta-data must reference an XML resource containing
83 * a <code>&lt;{@link android.R.styleable#Wallpaper wallpaper}&gt;</code>
84 * tag.
85 */
86 public static final String SERVICE_META_DATA = "android.service.wallpaper";
Craig Mautnerb1ef3692012-11-16 17:31:04 -080087
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070088 static final String TAG = "WallpaperService";
Dianne Hackborn72c82ab2009-08-11 21:13:54 -070089 static final boolean DEBUG = false;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070090
91 private static final int DO_ATTACH = 10;
92 private static final int DO_DETACH = 20;
Dianne Hackborn284ac932009-08-28 10:34:25 -070093 private static final int DO_SET_DESIRED_SIZE = 30;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070094
95 private static final int MSG_UPDATE_SURFACE = 10000;
Dianne Hackborn759a39e2009-08-09 17:20:27 -070096 private static final int MSG_VISIBILITY_CHANGED = 10010;
Dianne Hackborn72c82ab2009-08-11 21:13:54 -070097 private static final int MSG_WALLPAPER_OFFSETS = 10020;
Dianne Hackborn75804932009-10-20 20:15:20 -070098 private static final int MSG_WALLPAPER_COMMAND = 10025;
Dianne Hackborn7341d7a2009-08-14 11:37:52 -070099 private static final int MSG_WINDOW_RESIZED = 10030;
Craig Mautner5702d4d2012-06-30 14:10:16 -0700100 private static final int MSG_WINDOW_MOVED = 10035;
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 Hackbornaf1f42b2009-11-20 16:27:27 -0800103 private final ArrayList<Engine> mActiveEngines
104 = new ArrayList<Engine>();
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700105
Dianne Hackborn75804932009-10-20 20:15:20 -0700106 static final class WallpaperCommand {
107 String action;
108 int x;
109 int y;
110 int z;
111 Bundle extras;
112 boolean sync;
113 }
114
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700115 /**
116 * The actual implementation of a wallpaper. A wallpaper service may
117 * have multiple instances running (for example as a real wallpaper
118 * and as a preview), each of which is represented by its own Engine
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700119 * instance. You must implement {@link WallpaperService#onCreateEngine()}
120 * to return your concrete Engine implementation.
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700121 */
122 public class Engine {
123 IWallpaperEngineWrapper mIWallpaperEngine;
124
125 // Copies from mIWallpaperEngine.
126 HandlerCaller mCaller;
127 IWallpaperConnection mConnection;
128 IBinder mWindowToken;
129
130 boolean mInitializing = true;
Dianne Hackborn284ac932009-08-28 10:34:25 -0700131 boolean mVisible;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -0700132 boolean mScreenOn = true;
133 boolean mReportedVisible;
Dianne Hackborn284ac932009-08-28 10:34:25 -0700134 boolean mDestroyed;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700135
136 // Current window state.
137 boolean mCreated;
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700138 boolean mSurfaceCreated;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700139 boolean mIsCreating;
140 boolean mDrawingAllowed;
Dianne Hackborn9e4e7272011-08-30 14:06:51 -0700141 boolean mOffsetsChanged;
Jeff Sharkey35be7562012-04-18 19:16:15 -0700142 boolean mFixedSizeAllowed;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700143 int mWidth;
144 int mHeight;
145 int mFormat;
146 int mType;
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700147 int mCurWidth;
148 int mCurHeight;
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -0700149 int mWindowFlags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
Chet Haasea8e5a2b2011-10-28 13:18:16 -0700150 int mWindowPrivateFlags =
151 WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS;
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -0700152 int mCurWindowFlags = mWindowFlags;
Chet Haasea8e5a2b2011-10-28 13:18:16 -0700153 int mCurWindowPrivateFlags = mWindowPrivateFlags;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700154 final Rect mVisibleInsets = new Rect();
155 final Rect mWinFrame = new Rect();
Dianne Hackbornc4aad012013-02-22 15:05:25 -0800156 final Rect mOverscanInsets = new Rect();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700157 final Rect mContentInsets = new Rect();
Dianne Hackborn694f79b2010-03-17 19:44:59 -0700158 final Configuration mConfiguration = new Configuration();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700159
160 final WindowManager.LayoutParams mLayout
161 = new WindowManager.LayoutParams();
162 IWindowSession mSession;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700163 InputChannel mInputChannel;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700164
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700165 final Object mLock = new Object();
166 boolean mOffsetMessageEnqueued;
167 float mPendingXOffset;
168 float mPendingYOffset;
Marco Nelissenbf6956b2009-11-09 15:21:13 -0800169 float mPendingXOffsetStep;
170 float mPendingYOffsetStep;
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700171 boolean mPendingSync;
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -0700172 MotionEvent mPendingMove;
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700173
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -0700174 final BroadcastReceiver mReceiver = new BroadcastReceiver() {
175 @Override
176 public void onReceive(Context context, Intent intent) {
177 if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())) {
178 mScreenOn = true;
179 reportVisibility();
180 } else if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {
181 mScreenOn = false;
182 reportVisibility();
183 }
184 }
185 };
186
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700187 final BaseSurfaceHolder mSurfaceHolder = new BaseSurfaceHolder() {
Mathias Agopian62bf4a02010-09-08 16:32:27 -0700188 {
Jeff Brown24572372011-06-09 19:05:15 -0700189 mRequestedFormat = PixelFormat.RGBX_8888;
Mathias Agopian62bf4a02010-09-08 16:32:27 -0700190 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700191
192 @Override
193 public boolean onAllowLockCanvas() {
194 return mDrawingAllowed;
195 }
196
197 @Override
198 public void onRelayoutContainer() {
199 Message msg = mCaller.obtainMessage(MSG_UPDATE_SURFACE);
200 mCaller.sendMessage(msg);
201 }
202
203 @Override
204 public void onUpdateSurface() {
205 Message msg = mCaller.obtainMessage(MSG_UPDATE_SURFACE);
206 mCaller.sendMessage(msg);
207 }
208
209 public boolean isCreating() {
210 return mIsCreating;
211 }
212
Dianne Hackborna48a37f2011-02-01 16:30:38 -0800213 @Override
214 public void setFixedSize(int width, int height) {
Jeff Sharkey35be7562012-04-18 19:16:15 -0700215 if (!mFixedSizeAllowed) {
Dianne Hackborna48a37f2011-02-01 16:30:38 -0800216 // Regular apps can't do this. It can only work for
217 // certain designs of window animations, so you can't
218 // rely on it.
219 throw new UnsupportedOperationException(
220 "Wallpapers currently only support sizing from layout");
221 }
Michael Jurkab8f939f2011-02-01 20:50:30 -0800222 super.setFixedSize(width, height);
Dianne Hackborna48a37f2011-02-01 16:30:38 -0800223 }
224
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700225 public void setKeepScreenOn(boolean screenOn) {
Dianne Hackborn284ac932009-08-28 10:34:25 -0700226 throw new UnsupportedOperationException(
227 "Wallpapers do not support keep screen on");
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700228 }
229
230 };
Jeff Brown32cbc38552011-12-01 14:01:49 -0800231
232 final class WallpaperInputEventReceiver extends InputEventReceiver {
233 public WallpaperInputEventReceiver(InputChannel inputChannel, Looper looper) {
234 super(inputChannel, looper);
235 }
236
Jeff Brown46b9ac02010-04-22 18:58:52 -0700237 @Override
Jeff Brown32cbc38552011-12-01 14:01:49 -0800238 public void onInputEvent(InputEvent event) {
Jeff Brown3915bb82010-11-05 15:02:16 -0700239 boolean handled = false;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700240 try {
Jeff Brown4952dfd2011-11-30 19:23:22 -0800241 if (event instanceof MotionEvent
242 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
Jeff Brown32cbc38552011-12-01 14:01:49 -0800243 MotionEvent dup = MotionEvent.obtainNoHistory((MotionEvent)event);
244 dispatchPointer(dup);
Jeff Brown3915bb82010-11-05 15:02:16 -0700245 handled = true;
Jeff Brownc5ed5912010-07-14 18:48:53 -0700246 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700247 } finally {
Jeff Brown32cbc38552011-12-01 14:01:49 -0800248 finishInputEvent(event, handled);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700249 }
250 }
Jeff Brown32cbc38552011-12-01 14:01:49 -0800251 }
252 WallpaperInputEventReceiver mInputEventReceiver;
253
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700254 final BaseIWindow mWindow = new BaseIWindow() {
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -0700255 @Override
Dianne Hackbornc4aad012013-02-22 15:05:25 -0800256 public void resized(Rect frame, Rect overscanInsets, Rect contentInsets,
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800257 Rect visibleInsets, boolean reportDraw, Configuration newConfig) {
Dianne Hackborn7341d7a2009-08-14 11:37:52 -0700258 Message msg = mCaller.obtainMessageI(MSG_WINDOW_RESIZED,
259 reportDraw ? 1 : 0);
260 mCaller.sendMessage(msg);
261 }
Craig Mautner5702d4d2012-06-30 14:10:16 -0700262
263 @Override
264 public void moved(int newX, int newY) {
265 Message msg = mCaller.obtainMessageII(MSG_WINDOW_MOVED, newX, newY);
266 mCaller.sendMessage(msg);
267 }
268
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -0700269 @Override
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700270 public void dispatchAppVisibility(boolean visible) {
Dianne Hackborn284ac932009-08-28 10:34:25 -0700271 // We don't do this in preview mode; we'll let the preview
272 // activity tell us when to run.
273 if (!mIWallpaperEngine.mIsPreview) {
274 Message msg = mCaller.obtainMessageI(MSG_VISIBILITY_CHANGED,
275 visible ? 1 : 0);
276 mCaller.sendMessage(msg);
277 }
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700278 }
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700279
280 @Override
Marco Nelissenbf6956b2009-11-09 15:21:13 -0800281 public void dispatchWallpaperOffsets(float x, float y, float xStep, float yStep,
282 boolean sync) {
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700283 synchronized (mLock) {
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700284 if (DEBUG) Log.v(TAG, "Dispatch wallpaper offsets: " + x + ", " + y);
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700285 mPendingXOffset = x;
286 mPendingYOffset = y;
Marco Nelissenbf6956b2009-11-09 15:21:13 -0800287 mPendingXOffsetStep = xStep;
288 mPendingYOffsetStep = yStep;
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700289 if (sync) {
290 mPendingSync = true;
291 }
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700292 if (!mOffsetMessageEnqueued) {
293 mOffsetMessageEnqueued = true;
294 Message msg = mCaller.obtainMessage(MSG_WALLPAPER_OFFSETS);
295 mCaller.sendMessage(msg);
296 }
297 }
298 }
Craig Mautner5702d4d2012-06-30 14:10:16 -0700299
300 @Override
Dianne Hackborn75804932009-10-20 20:15:20 -0700301 public void dispatchWallpaperCommand(String action, int x, int y,
302 int z, Bundle extras, boolean sync) {
303 synchronized (mLock) {
304 if (DEBUG) Log.v(TAG, "Dispatch wallpaper command: " + x + ", " + y);
305 WallpaperCommand cmd = new WallpaperCommand();
306 cmd.action = action;
307 cmd.x = x;
308 cmd.y = y;
309 cmd.z = z;
310 cmd.extras = extras;
311 cmd.sync = sync;
312 Message msg = mCaller.obtainMessage(MSG_WALLPAPER_COMMAND);
313 msg.obj = cmd;
314 mCaller.sendMessage(msg);
315 }
316 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700317 };
318
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700319 /**
320 * Provides access to the surface in which this wallpaper is drawn.
321 */
322 public SurfaceHolder getSurfaceHolder() {
323 return mSurfaceHolder;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700324 }
325
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700326 /**
327 * Convenience for {@link WallpaperManager#getDesiredMinimumWidth()
328 * WallpaperManager.getDesiredMinimumWidth()}, returning the width
329 * that the system would like this wallpaper to run in.
330 */
331 public int getDesiredMinimumWidth() {
332 return mIWallpaperEngine.mReqWidth;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700333 }
334
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700335 /**
336 * Convenience for {@link WallpaperManager#getDesiredMinimumHeight()
337 * WallpaperManager.getDesiredMinimumHeight()}, returning the height
338 * that the system would like this wallpaper to run in.
339 */
340 public int getDesiredMinimumHeight() {
341 return mIWallpaperEngine.mReqHeight;
342 }
343
344 /**
Dianne Hackborn284ac932009-08-28 10:34:25 -0700345 * Return whether the wallpaper is currently visible to the user,
346 * this is the last value supplied to
347 * {@link #onVisibilityChanged(boolean)}.
348 */
349 public boolean isVisible() {
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -0700350 return mReportedVisible;
Dianne Hackborn284ac932009-08-28 10:34:25 -0700351 }
352
353 /**
Dianne Hackborn3be63c02009-08-20 19:31:38 -0700354 * Returns true if this engine is running in preview mode -- that is,
355 * it is being shown to the user before they select it as the actual
356 * wallpaper.
357 */
358 public boolean isPreview() {
359 return mIWallpaperEngine.mIsPreview;
360 }
361
362 /**
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -0700363 * Control whether this wallpaper will receive raw touch events
364 * from the window manager as the user interacts with the window
365 * that is currently displaying the wallpaper. By default they
366 * are turned off. If enabled, the events will be received in
367 * {@link #onTouchEvent(MotionEvent)}.
368 */
369 public void setTouchEventsEnabled(boolean enabled) {
370 mWindowFlags = enabled
371 ? (mWindowFlags&~WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE)
372 : (mWindowFlags|WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
373 if (mCreated) {
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700374 updateSurface(false, false, false);
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -0700375 }
376 }
Chet Haasea8e5a2b2011-10-28 13:18:16 -0700377
378 /**
379 * Control whether this wallpaper will receive notifications when the wallpaper
380 * has been scrolled. By default, wallpapers will receive notifications, although
381 * the default static image wallpapers do not. It is a performance optimization to
382 * set this to false.
383 *
384 * @param enabled whether the wallpaper wants to receive offset notifications
385 */
386 public void setOffsetNotificationsEnabled(boolean enabled) {
387 mWindowPrivateFlags = enabled
388 ? (mWindowPrivateFlags |
389 WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS)
390 : (mWindowPrivateFlags &
391 ~WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS);
392 if (mCreated) {
393 updateSurface(false, false, false);
394 }
395 }
Jeff Sharkey35be7562012-04-18 19:16:15 -0700396
397 /** {@hide} */
398 public void setFixedSizeAllowed(boolean allowed) {
399 mFixedSizeAllowed = allowed;
400 }
401
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -0700402 /**
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700403 * Called once to initialize the engine. After returning, the
404 * engine's surface will be created by the framework.
405 */
406 public void onCreate(SurfaceHolder surfaceHolder) {
407 }
408
409 /**
410 * Called right before the engine is going away. After this the
411 * surface will be destroyed and this Engine object is no longer
412 * valid.
413 */
414 public void onDestroy() {
415 }
416
417 /**
418 * Called to inform you of the wallpaper becoming visible or
419 * hidden. <em>It is very important that a wallpaper only use
420 * CPU while it is visible.</em>.
421 */
422 public void onVisibilityChanged(boolean visible) {
423 }
424
425 /**
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -0700426 * Called as the user performs touch-screen interaction with the
427 * window that is currently showing this wallpaper. Note that the
428 * events you receive here are driven by the actual application the
Marco Nelissenae87bd02009-09-17 09:44:43 -0700429 * user is interacting with, so if it is slow you will get fewer
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -0700430 * move events.
431 */
432 public void onTouchEvent(MotionEvent event) {
433 }
434
435 /**
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700436 * Called to inform you of the wallpaper's offsets changing
437 * within its contain, corresponding to the container's
438 * call to {@link WallpaperManager#setWallpaperOffsets(IBinder, float, float)
439 * WallpaperManager.setWallpaperOffsets()}.
440 */
441 public void onOffsetsChanged(float xOffset, float yOffset,
Marco Nelissenbf6956b2009-11-09 15:21:13 -0800442 float xOffsetStep, float yOffsetStep,
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700443 int xPixelOffset, int yPixelOffset) {
444 }
445
446 /**
Dianne Hackborn75804932009-10-20 20:15:20 -0700447 * Process a command that was sent to the wallpaper with
Dianne Hackborn13bf82602009-11-05 21:45:51 -0800448 * {@link WallpaperManager#sendWallpaperCommand}.
Dianne Hackborn75804932009-10-20 20:15:20 -0700449 * The default implementation does nothing, and always returns null
450 * as the result.
451 *
452 * @param action The name of the command to perform. This tells you
453 * what to do and how to interpret the rest of the arguments.
454 * @param x Generic integer parameter.
455 * @param y Generic integer parameter.
456 * @param z Generic integer parameter.
457 * @param extras Any additional parameters.
458 * @param resultRequested If true, the caller is requesting that
459 * a result, appropriate for the command, be returned back.
460 * @return If returning a result, create a Bundle and place the
461 * result data in to it. Otherwise return null.
462 */
463 public Bundle onCommand(String action, int x, int y, int z,
464 Bundle extras, boolean resultRequested) {
465 return null;
466 }
467
468 /**
Dianne Hackborn284ac932009-08-28 10:34:25 -0700469 * Called when an application has changed the desired virtual size of
470 * the wallpaper.
471 */
472 public void onDesiredSizeChanged(int desiredWidth, int desiredHeight) {
473 }
474
475 /**
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700476 * Convenience for {@link SurfaceHolder.Callback#surfaceChanged
477 * SurfaceHolder.Callback.surfaceChanged()}.
478 */
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700479 public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
480 }
481
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700482 /**
Dianne Hackborn1d28f9c2010-07-13 20:38:06 -0700483 * Convenience for {@link SurfaceHolder.Callback2#surfaceRedrawNeeded
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700484 * SurfaceHolder.Callback.surfaceRedrawNeeded()}.
485 */
486 public void onSurfaceRedrawNeeded(SurfaceHolder holder) {
487 }
488
489 /**
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700490 * Convenience for {@link SurfaceHolder.Callback#surfaceCreated
491 * SurfaceHolder.Callback.surfaceCreated()}.
492 */
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700493 public void onSurfaceCreated(SurfaceHolder holder) {
494 }
495
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700496 /**
497 * Convenience for {@link SurfaceHolder.Callback#surfaceDestroyed
498 * SurfaceHolder.Callback.surfaceDestroyed()}.
499 */
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700500 public void onSurfaceDestroyed(SurfaceHolder holder) {
501 }
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700502
Dianne Hackborn527de8e2011-08-22 16:10:36 -0700503 protected void dump(String prefix, FileDescriptor fd, PrintWriter out, String[] args) {
504 out.print(prefix); out.print("mInitializing="); out.print(mInitializing);
505 out.print(" mDestroyed="); out.println(mDestroyed);
506 out.print(prefix); out.print("mVisible="); out.print(mVisible);
507 out.print(" mScreenOn="); out.print(mScreenOn);
508 out.print(" mReportedVisible="); out.println(mReportedVisible);
509 out.print(prefix); out.print("mCreated="); out.print(mCreated);
510 out.print(" mSurfaceCreated="); out.print(mSurfaceCreated);
511 out.print(" mIsCreating="); out.print(mIsCreating);
512 out.print(" mDrawingAllowed="); out.println(mDrawingAllowed);
513 out.print(prefix); out.print("mWidth="); out.print(mWidth);
514 out.print(" mCurWidth="); out.print(mCurWidth);
515 out.print(" mHeight="); out.print(mHeight);
516 out.print(" mCurHeight="); out.println(mCurHeight);
517 out.print(prefix); out.print("mType="); out.print(mType);
518 out.print(" mWindowFlags="); out.print(mWindowFlags);
519 out.print(" mCurWindowFlags="); out.println(mCurWindowFlags);
Chet Haasea8e5a2b2011-10-28 13:18:16 -0700520 out.print(" mWindowPrivateFlags="); out.print(mWindowPrivateFlags);
521 out.print(" mCurWindowPrivateFlags="); out.println(mCurWindowPrivateFlags);
Dianne Hackborn527de8e2011-08-22 16:10:36 -0700522 out.print(prefix); out.print("mVisibleInsets=");
523 out.print(mVisibleInsets.toShortString());
524 out.print(" mWinFrame="); out.print(mWinFrame.toShortString());
525 out.print(" mContentInsets="); out.println(mContentInsets.toShortString());
526 out.print(prefix); out.print("mConfiguration="); out.println(mConfiguration);
527 out.print(prefix); out.print("mLayout="); out.println(mLayout);
528 synchronized (mLock) {
529 out.print(prefix); out.print("mPendingXOffset="); out.print(mPendingXOffset);
530 out.print(" mPendingXOffset="); out.println(mPendingXOffset);
531 out.print(prefix); out.print("mPendingXOffsetStep=");
532 out.print(mPendingXOffsetStep);
533 out.print(" mPendingXOffsetStep="); out.println(mPendingXOffsetStep);
534 out.print(prefix); out.print("mOffsetMessageEnqueued=");
535 out.print(mOffsetMessageEnqueued);
536 out.print(" mPendingSync="); out.println(mPendingSync);
537 if (mPendingMove != null) {
538 out.print(prefix); out.print("mPendingMove="); out.println(mPendingMove);
539 }
540 }
541 }
542
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700543 private void dispatchPointer(MotionEvent event) {
Jeff Brown33bbfd22011-02-24 20:55:35 -0800544 if (event.isTouchEvent()) {
545 synchronized (mLock) {
546 if (event.getAction() == MotionEvent.ACTION_MOVE) {
547 mPendingMove = event;
548 } else {
549 mPendingMove = null;
550 }
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700551 }
Jeff Brown33bbfd22011-02-24 20:55:35 -0800552 Message msg = mCaller.obtainMessageO(MSG_TOUCH_EVENT, event);
553 mCaller.sendMessage(msg);
Jeff Brown32cbc38552011-12-01 14:01:49 -0800554 } else {
555 event.recycle();
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700556 }
557 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700558
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700559 void updateSurface(boolean forceRelayout, boolean forceReport, boolean redrawNeeded) {
Dianne Hackborn284ac932009-08-28 10:34:25 -0700560 if (mDestroyed) {
561 Log.w(TAG, "Ignoring updateSurface: destroyed");
562 }
563
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700564 int myWidth = mSurfaceHolder.getRequestedWidth();
Romain Guy980a9382010-01-08 15:06:28 -0800565 if (myWidth <= 0) myWidth = ViewGroup.LayoutParams.MATCH_PARENT;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700566 int myHeight = mSurfaceHolder.getRequestedHeight();
Romain Guy980a9382010-01-08 15:06:28 -0800567 if (myHeight <= 0) myHeight = ViewGroup.LayoutParams.MATCH_PARENT;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700568
569 final boolean creating = !mCreated;
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700570 final boolean surfaceCreating = !mSurfaceCreated;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700571 final boolean formatChanged = mFormat != mSurfaceHolder.getRequestedFormat();
Dianne Hackborn7341d7a2009-08-14 11:37:52 -0700572 boolean sizeChanged = mWidth != myWidth || mHeight != myHeight;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700573 final boolean typeChanged = mType != mSurfaceHolder.getRequestedType();
Chet Haasea8e5a2b2011-10-28 13:18:16 -0700574 final boolean flagsChanged = mCurWindowFlags != mWindowFlags ||
575 mCurWindowPrivateFlags != mWindowPrivateFlags;
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700576 if (forceRelayout || creating || surfaceCreating || formatChanged || sizeChanged
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -0700577 || typeChanged || flagsChanged || redrawNeeded
578 || !mIWallpaperEngine.mShownReported) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700579
Dianne Hackborn284ac932009-08-28 10:34:25 -0700580 if (DEBUG) Log.v(TAG, "Changes: creating=" + creating
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700581 + " format=" + formatChanged + " size=" + sizeChanged);
582
583 try {
584 mWidth = myWidth;
585 mHeight = myHeight;
586 mFormat = mSurfaceHolder.getRequestedFormat();
587 mType = mSurfaceHolder.getRequestedType();
588
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700589 mLayout.x = 0;
590 mLayout.y = 0;
591 mLayout.width = myWidth;
592 mLayout.height = myHeight;
593
594 mLayout.format = mFormat;
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -0700595
596 mCurWindowFlags = mWindowFlags;
597 mLayout.flags = mWindowFlags
598 | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
599 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
600 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
601 ;
Chet Haasea8e5a2b2011-10-28 13:18:16 -0700602 mCurWindowPrivateFlags = mWindowPrivateFlags;
603 mLayout.privateFlags = mWindowPrivateFlags;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700604
605 mLayout.memoryType = mType;
606 mLayout.token = mWindowToken;
607
608 if (!mCreated) {
Dianne Hackborn3be63c02009-08-20 19:31:38 -0700609 mLayout.type = mIWallpaperEngine.mWindowType;
Fabrice Di Meglioaac0d4e2012-07-19 19:21:26 -0700610 mLayout.gravity = Gravity.START|Gravity.TOP;
Dianne Hackborn0586a1b2009-09-06 21:08:27 -0700611 mLayout.setTitle(WallpaperService.this.getClass().getName());
Dianne Hackborn284ac932009-08-28 10:34:25 -0700612 mLayout.windowAnimations =
613 com.android.internal.R.style.Animation_Wallpaper;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700614 mInputChannel = new InputChannel();
Craig Mautner6881a102012-07-27 13:04:51 -0700615 if (mSession.addToDisplay(mWindow, mWindow.mSeq, mLayout, View.VISIBLE,
616 Display.DEFAULT_DISPLAY, mContentInsets, mInputChannel) < 0) {
Mattias Peterssond9463f52011-01-12 15:38:55 +0100617 Log.w(TAG, "Failed to add window while updating wallpaper surface.");
618 return;
619 }
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700620 mCreated = true;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700621
Jeff Brown32cbc38552011-12-01 14:01:49 -0800622 mInputEventReceiver = new WallpaperInputEventReceiver(
623 mInputChannel, Looper.myLooper());
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700624 }
625
626 mSurfaceHolder.mSurfaceLock.lock();
627 mDrawingAllowed = true;
628
629 final int relayoutResult = mSession.relayout(
Dianne Hackborn9a230e02011-10-06 11:51:27 -0700630 mWindow, mWindow.mSeq, mLayout, mWidth, mHeight,
Dianne Hackbornc4aad012013-02-22 15:05:25 -0800631 View.VISIBLE, 0, mWinFrame, mOverscanInsets, mContentInsets,
Dianne Hackborn694f79b2010-03-17 19:44:59 -0700632 mVisibleInsets, mConfiguration, mSurfaceHolder.mSurface);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700633
Dianne Hackborn284ac932009-08-28 10:34:25 -0700634 if (DEBUG) Log.v(TAG, "New surface: " + mSurfaceHolder.mSurface
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700635 + ", frame=" + mWinFrame);
636
Dianne Hackborn7341d7a2009-08-14 11:37:52 -0700637 int w = mWinFrame.width();
638 if (mCurWidth != w) {
639 sizeChanged = true;
640 mCurWidth = w;
641 }
642 int h = mWinFrame.height();
643 if (mCurHeight != h) {
644 sizeChanged = true;
645 mCurHeight = h;
646 }
Jeff Brown30bc34f2011-01-25 12:56:56 -0800647
648 mSurfaceHolder.setSurfaceFrameSize(w, h);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700649 mSurfaceHolder.mSurfaceLock.unlock();
650
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700651 if (!mSurfaceHolder.mSurface.isValid()) {
652 reportSurfaceDestroyed();
653 if (DEBUG) Log.v(TAG, "Layout: Surface destroyed");
654 return;
655 }
Dianne Hackborn9e4e7272011-08-30 14:06:51 -0700656
657 boolean didSurface = false;
658
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700659 try {
Dianne Hackborndc8a7f62010-05-10 11:29:34 -0700660 mSurfaceHolder.ungetCallbacks();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700661
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700662 if (surfaceCreating) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700663 mIsCreating = true;
Dianne Hackborn9e4e7272011-08-30 14:06:51 -0700664 didSurface = true;
Dianne Hackborn284ac932009-08-28 10:34:25 -0700665 if (DEBUG) Log.v(TAG, "onSurfaceCreated("
666 + mSurfaceHolder + "): " + this);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700667 onSurfaceCreated(mSurfaceHolder);
Dianne Hackborndc8a7f62010-05-10 11:29:34 -0700668 SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700669 if (callbacks != null) {
670 for (SurfaceHolder.Callback c : callbacks) {
671 c.surfaceCreated(mSurfaceHolder);
672 }
673 }
674 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700675
Jeff Brown98365d72012-08-19 20:30:52 -0700676 redrawNeeded |= creating || (relayoutResult
677 & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0;
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700678
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700679 if (forceReport || creating || surfaceCreating
680 || formatChanged || sizeChanged) {
Dianne Hackborncbf15042009-08-18 18:29:09 -0700681 if (DEBUG) {
682 RuntimeException e = new RuntimeException();
683 e.fillInStackTrace();
684 Log.w(TAG, "forceReport=" + forceReport + " creating=" + creating
685 + " formatChanged=" + formatChanged
686 + " sizeChanged=" + sizeChanged, e);
687 }
Dianne Hackborn284ac932009-08-28 10:34:25 -0700688 if (DEBUG) Log.v(TAG, "onSurfaceChanged("
689 + mSurfaceHolder + ", " + mFormat
690 + ", " + mCurWidth + ", " + mCurHeight
691 + "): " + this);
Dianne Hackborn9e4e7272011-08-30 14:06:51 -0700692 didSurface = true;
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700693 onSurfaceChanged(mSurfaceHolder, mFormat,
694 mCurWidth, mCurHeight);
Dianne Hackborndc8a7f62010-05-10 11:29:34 -0700695 SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700696 if (callbacks != null) {
697 for (SurfaceHolder.Callback c : callbacks) {
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700698 c.surfaceChanged(mSurfaceHolder, mFormat,
699 mCurWidth, mCurHeight);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700700 }
701 }
702 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700703
704 if (redrawNeeded) {
705 onSurfaceRedrawNeeded(mSurfaceHolder);
706 SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
707 if (callbacks != null) {
708 for (SurfaceHolder.Callback c : callbacks) {
709 if (c instanceof SurfaceHolder.Callback2) {
710 ((SurfaceHolder.Callback2)c).surfaceRedrawNeeded(
711 mSurfaceHolder);
712 }
713 }
714 }
715 }
716
Dianne Hackborn9e4e7272011-08-30 14:06:51 -0700717 if (didSurface && !mReportedVisible) {
718 // This wallpaper is currently invisible, but its
719 // surface has changed. At this point let's tell it
720 // again that it is invisible in case the report about
721 // the surface caused it to start running. We really
722 // don't want wallpapers running when not visible.
723 if (mIsCreating) {
724 // Some wallpapers will ignore this call if they
725 // had previously been told they were invisble,
726 // so if we are creating a new surface then toggle
727 // the state to get them to notice.
728 if (DEBUG) Log.v(TAG, "onVisibilityChanged(true) at surface: "
729 + this);
730 onVisibilityChanged(true);
731 }
732 if (DEBUG) Log.v(TAG, "onVisibilityChanged(false) at surface: "
733 + this);
734 onVisibilityChanged(false);
735 }
736
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700737 } finally {
738 mIsCreating = false;
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700739 mSurfaceCreated = true;
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700740 if (redrawNeeded) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700741 mSession.finishDrawing(mWindow);
742 }
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -0700743 mIWallpaperEngine.reportShown();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700744 }
745 } catch (RemoteException ex) {
746 }
747 if (DEBUG) Log.v(
748 TAG, "Layout: x=" + mLayout.x + " y=" + mLayout.y +
749 " w=" + mLayout.width + " h=" + mLayout.height);
750 }
751 }
752
753 void attach(IWallpaperEngineWrapper wrapper) {
Dianne Hackborncbf15042009-08-18 18:29:09 -0700754 if (DEBUG) Log.v(TAG, "attach: " + this + " wrapper=" + wrapper);
Dianne Hackborn284ac932009-08-28 10:34:25 -0700755 if (mDestroyed) {
756 return;
757 }
758
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700759 mIWallpaperEngine = wrapper;
760 mCaller = wrapper.mCaller;
761 mConnection = wrapper.mConnection;
762 mWindowToken = wrapper.mWindowToken;
Dianne Hackborn284ac932009-08-28 10:34:25 -0700763 mSurfaceHolder.setSizeFromLayout();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700764 mInitializing = true;
Jeff Brownf9e989d2013-04-04 23:04:03 -0700765 mSession = WindowManagerGlobal.getWindowSession();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700766
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700767 mWindow.setSession(mSession);
Dianne Hackborn9fe6cb52011-09-09 13:02:43 -0700768
769 mScreenOn = ((PowerManager)getSystemService(Context.POWER_SERVICE)).isScreenOn();
770
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -0700771 IntentFilter filter = new IntentFilter();
772 filter.addAction(Intent.ACTION_SCREEN_ON);
773 filter.addAction(Intent.ACTION_SCREEN_OFF);
774 registerReceiver(mReceiver, filter);
775
Dianne Hackborn284ac932009-08-28 10:34:25 -0700776 if (DEBUG) Log.v(TAG, "onCreate(): " + this);
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700777 onCreate(mSurfaceHolder);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700778
779 mInitializing = false;
Dianne Hackborn9e4e7272011-08-30 14:06:51 -0700780 mReportedVisible = false;
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700781 updateSurface(false, false, false);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700782 }
783
Dianne Hackborn284ac932009-08-28 10:34:25 -0700784 void doDesiredSizeChanged(int desiredWidth, int desiredHeight) {
785 if (!mDestroyed) {
786 if (DEBUG) Log.v(TAG, "onDesiredSizeChanged("
787 + desiredWidth + "," + desiredHeight + "): " + this);
Joe Onoratodcfae5c2010-10-28 18:03:23 -0700788 mIWallpaperEngine.mReqWidth = desiredWidth;
789 mIWallpaperEngine.mReqHeight = desiredHeight;
Dianne Hackborn284ac932009-08-28 10:34:25 -0700790 onDesiredSizeChanged(desiredWidth, desiredHeight);
Dianne Hackborn9e4e7272011-08-30 14:06:51 -0700791 doOffsetsChanged(true);
Dianne Hackborn284ac932009-08-28 10:34:25 -0700792 }
793 }
794
795 void doVisibilityChanged(boolean visible) {
Dianne Hackbornaf1f42b2009-11-20 16:27:27 -0800796 if (!mDestroyed) {
797 mVisible = visible;
798 reportVisibility();
799 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -0700800 }
801
802 void reportVisibility() {
Dianne Hackborn284ac932009-08-28 10:34:25 -0700803 if (!mDestroyed) {
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -0700804 boolean visible = mVisible && mScreenOn;
805 if (mReportedVisible != visible) {
806 mReportedVisible = visible;
807 if (DEBUG) Log.v(TAG, "onVisibilityChanged(" + visible
808 + "): " + this);
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700809 if (visible) {
810 // If becoming visible, in preview mode the surface
811 // may have been destroyed so now we need to make
812 // sure it is re-created.
Dianne Hackborn9e4e7272011-08-30 14:06:51 -0700813 doOffsetsChanged(false);
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700814 updateSurface(false, false, false);
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700815 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -0700816 onVisibilityChanged(visible);
817 }
Dianne Hackborn284ac932009-08-28 10:34:25 -0700818 }
819 }
820
Dianne Hackborn9e4e7272011-08-30 14:06:51 -0700821 void doOffsetsChanged(boolean always) {
Dianne Hackborn284ac932009-08-28 10:34:25 -0700822 if (mDestroyed) {
823 return;
824 }
Dianne Hackborn9e4e7272011-08-30 14:06:51 -0700825
826 if (!always && !mOffsetsChanged) {
827 return;
828 }
829
Dianne Hackborn284ac932009-08-28 10:34:25 -0700830 float xOffset;
831 float yOffset;
Marco Nelissenbf6956b2009-11-09 15:21:13 -0800832 float xOffsetStep;
833 float yOffsetStep;
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700834 boolean sync;
Dianne Hackborn284ac932009-08-28 10:34:25 -0700835 synchronized (mLock) {
836 xOffset = mPendingXOffset;
837 yOffset = mPendingYOffset;
Marco Nelissenbf6956b2009-11-09 15:21:13 -0800838 xOffsetStep = mPendingXOffsetStep;
839 yOffsetStep = mPendingYOffsetStep;
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700840 sync = mPendingSync;
841 mPendingSync = false;
Dianne Hackborn284ac932009-08-28 10:34:25 -0700842 mOffsetMessageEnqueued = false;
843 }
Dianne Hackborn9e4e7272011-08-30 14:06:51 -0700844
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700845 if (mSurfaceCreated) {
Dianne Hackborn9e4e7272011-08-30 14:06:51 -0700846 if (mReportedVisible) {
847 if (DEBUG) Log.v(TAG, "Offsets change in " + this
848 + ": " + xOffset + "," + yOffset);
849 final int availw = mIWallpaperEngine.mReqWidth-mCurWidth;
850 final int xPixels = availw > 0 ? -(int)(availw*xOffset+.5f) : 0;
851 final int availh = mIWallpaperEngine.mReqHeight-mCurHeight;
852 final int yPixels = availh > 0 ? -(int)(availh*yOffset+.5f) : 0;
853 onOffsetsChanged(xOffset, yOffset, xOffsetStep, yOffsetStep, xPixels, yPixels);
854 } else {
855 mOffsetsChanged = true;
856 }
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700857 }
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700858
859 if (sync) {
860 try {
861 if (DEBUG) Log.v(TAG, "Reporting offsets change complete");
862 mSession.wallpaperOffsetsComplete(mWindow.asBinder());
863 } catch (RemoteException e) {
864 }
865 }
Dianne Hackborn284ac932009-08-28 10:34:25 -0700866 }
867
Dianne Hackborn75804932009-10-20 20:15:20 -0700868 void doCommand(WallpaperCommand cmd) {
869 Bundle result;
870 if (!mDestroyed) {
871 result = onCommand(cmd.action, cmd.x, cmd.y, cmd.z,
872 cmd.extras, cmd.sync);
873 } else {
874 result = null;
875 }
876 if (cmd.sync) {
877 try {
878 if (DEBUG) Log.v(TAG, "Reporting command complete");
879 mSession.wallpaperCommandComplete(mWindow.asBinder(), result);
880 } catch (RemoteException e) {
881 }
882 }
883 }
884
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700885 void reportSurfaceDestroyed() {
886 if (mSurfaceCreated) {
887 mSurfaceCreated = false;
Dianne Hackborndc8a7f62010-05-10 11:29:34 -0700888 mSurfaceHolder.ungetCallbacks();
889 SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
890 if (callbacks != null) {
891 for (SurfaceHolder.Callback c : callbacks) {
892 c.surfaceDestroyed(mSurfaceHolder);
893 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700894 }
Dianne Hackborn284ac932009-08-28 10:34:25 -0700895 if (DEBUG) Log.v(TAG, "onSurfaceDestroyed("
896 + mSurfaceHolder + "): " + this);
897 onSurfaceDestroyed(mSurfaceHolder);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700898 }
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700899 }
900
901 void detach() {
902 if (mDestroyed) {
903 return;
904 }
905
906 mDestroyed = true;
907
908 if (mVisible) {
909 mVisible = false;
910 if (DEBUG) Log.v(TAG, "onVisibilityChanged(false): " + this);
911 onVisibilityChanged(false);
912 }
913
914 reportSurfaceDestroyed();
Dianne Hackborn284ac932009-08-28 10:34:25 -0700915
916 if (DEBUG) Log.v(TAG, "onDestroy(): " + this);
917 onDestroy();
918
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -0700919 unregisterReceiver(mReceiver);
920
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700921 if (mCreated) {
922 try {
Dianne Hackbornba3e31d2010-04-22 18:59:03 -0700923 if (DEBUG) Log.v(TAG, "Removing window and destroying surface "
924 + mSurfaceHolder.getSurface() + " of: " + this);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700925
Jeff Brown32cbc38552011-12-01 14:01:49 -0800926 if (mInputEventReceiver != null) {
927 mInputEventReceiver.dispose();
928 mInputEventReceiver = null;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700929 }
930
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700931 mSession.remove(mWindow);
932 } catch (RemoteException e) {
933 }
Dianne Hackborn0586a1b2009-09-06 21:08:27 -0700934 mSurfaceHolder.mSurface.release();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700935 mCreated = false;
Jeff Brown349703e2010-06-22 01:27:15 -0700936
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700937 // Dispose the input channel after removing the window so the Window Manager
938 // doesn't interpret the input channel being closed as an abnormal termination.
939 if (mInputChannel != null) {
940 mInputChannel.dispose();
941 mInputChannel = null;
Jeff Brown349703e2010-06-22 01:27:15 -0700942 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700943 }
944 }
945 }
946
947 class IWallpaperEngineWrapper extends IWallpaperEngine.Stub
948 implements HandlerCaller.Callback {
949 private final HandlerCaller mCaller;
950
951 final IWallpaperConnection mConnection;
952 final IBinder mWindowToken;
Dianne Hackborn3be63c02009-08-20 19:31:38 -0700953 final int mWindowType;
954 final boolean mIsPreview;
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -0700955 boolean mShownReported;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700956 int mReqWidth;
957 int mReqHeight;
958
959 Engine mEngine;
960
961 IWallpaperEngineWrapper(WallpaperService context,
962 IWallpaperConnection conn, IBinder windowToken,
Dianne Hackborn3be63c02009-08-20 19:31:38 -0700963 int windowType, boolean isPreview, int reqWidth, int reqHeight) {
Mita Yunaa8dc2e2012-12-10 18:32:03 -0800964 mCaller = new HandlerCaller(context, context.getMainLooper(), this, true);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700965 mConnection = conn;
966 mWindowToken = windowToken;
Dianne Hackborn3be63c02009-08-20 19:31:38 -0700967 mWindowType = windowType;
968 mIsPreview = isPreview;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700969 mReqWidth = reqWidth;
970 mReqHeight = reqHeight;
971
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700972 Message msg = mCaller.obtainMessage(DO_ATTACH);
973 mCaller.sendMessage(msg);
974 }
975
Dianne Hackborn284ac932009-08-28 10:34:25 -0700976 public void setDesiredSize(int width, int height) {
977 Message msg = mCaller.obtainMessageII(DO_SET_DESIRED_SIZE, width, height);
978 mCaller.sendMessage(msg);
979 }
980
981 public void setVisibility(boolean visible) {
982 Message msg = mCaller.obtainMessageI(MSG_VISIBILITY_CHANGED,
983 visible ? 1 : 0);
984 mCaller.sendMessage(msg);
985 }
986
Dianne Hackborn6adba242009-11-10 11:10:09 -0800987 public void dispatchPointer(MotionEvent event) {
988 if (mEngine != null) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700989 mEngine.dispatchPointer(event);
Jeff Brown32cbc38552011-12-01 14:01:49 -0800990 } else {
991 event.recycle();
Dianne Hackborn6adba242009-11-10 11:10:09 -0800992 }
993 }
Jeff Brown9f3bdfe2010-10-13 06:01:27 -0700994
995 public void dispatchWallpaperCommand(String action, int x, int y,
996 int z, Bundle extras) {
997 if (mEngine != null) {
998 mEngine.mWindow.dispatchWallpaperCommand(action, x, y, z, extras, false);
999 }
1000 }
1001
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -07001002 public void reportShown() {
1003 if (!mShownReported) {
1004 mShownReported = true;
1005 try {
1006 mConnection.engineShown(this);
1007 } catch (RemoteException e) {
1008 Log.w(TAG, "Wallpaper host disappeared", e);
1009 return;
1010 }
1011 }
1012 }
1013
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001014 public void destroy() {
1015 Message msg = mCaller.obtainMessage(DO_DETACH);
1016 mCaller.sendMessage(msg);
1017 }
1018
1019 public void executeMessage(Message message) {
1020 switch (message.what) {
1021 case DO_ATTACH: {
Dianne Hackborn284ac932009-08-28 10:34:25 -07001022 try {
1023 mConnection.attachEngine(this);
1024 } catch (RemoteException e) {
1025 Log.w(TAG, "Wallpaper host disappeared", e);
1026 return;
1027 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001028 Engine engine = onCreateEngine();
1029 mEngine = engine;
Dianne Hackbornaf1f42b2009-11-20 16:27:27 -08001030 mActiveEngines.add(engine);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001031 engine.attach(this);
1032 return;
1033 }
1034 case DO_DETACH: {
Dianne Hackbornaf1f42b2009-11-20 16:27:27 -08001035 mActiveEngines.remove(mEngine);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001036 mEngine.detach();
1037 return;
1038 }
Dianne Hackborn284ac932009-08-28 10:34:25 -07001039 case DO_SET_DESIRED_SIZE: {
1040 mEngine.doDesiredSizeChanged(message.arg1, message.arg2);
1041 return;
1042 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001043 case MSG_UPDATE_SURFACE:
Dianne Hackbornd76b67c2010-07-13 17:48:30 -07001044 mEngine.updateSurface(true, false, false);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001045 break;
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001046 case MSG_VISIBILITY_CHANGED:
1047 if (DEBUG) Log.v(TAG, "Visibility change in " + mEngine
1048 + ": " + message.arg1);
Dianne Hackborn284ac932009-08-28 10:34:25 -07001049 mEngine.doVisibilityChanged(message.arg1 != 0);
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001050 break;
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001051 case MSG_WALLPAPER_OFFSETS: {
Dianne Hackborn9e4e7272011-08-30 14:06:51 -07001052 mEngine.doOffsetsChanged(true);
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001053 } break;
Dianne Hackborn75804932009-10-20 20:15:20 -07001054 case MSG_WALLPAPER_COMMAND: {
1055 WallpaperCommand cmd = (WallpaperCommand)message.obj;
1056 mEngine.doCommand(cmd);
1057 } break;
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001058 case MSG_WINDOW_RESIZED: {
1059 final boolean reportDraw = message.arg1 != 0;
Dianne Hackbornd76b67c2010-07-13 17:48:30 -07001060 mEngine.updateSurface(true, false, reportDraw);
Dianne Hackborn9e4e7272011-08-30 14:06:51 -07001061 mEngine.doOffsetsChanged(true);
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001062 } break;
Craig Mautner5702d4d2012-06-30 14:10:16 -07001063 case MSG_WINDOW_MOVED: {
1064 // Do nothing. What does it mean for a Wallpaper to move?
1065 } break;
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07001066 case MSG_TOUCH_EVENT: {
Jeff Brown840db1f2010-10-21 17:36:54 -07001067 boolean skip = false;
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07001068 MotionEvent ev = (MotionEvent)message.obj;
Jeff Brown840db1f2010-10-21 17:36:54 -07001069 if (ev.getAction() == MotionEvent.ACTION_MOVE) {
1070 synchronized (mEngine.mLock) {
1071 if (mEngine.mPendingMove == ev) {
1072 mEngine.mPendingMove = null;
1073 } else {
1074 // this is not the motion event we are looking for....
1075 skip = true;
1076 }
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07001077 }
1078 }
Jeff Brown840db1f2010-10-21 17:36:54 -07001079 if (!skip) {
1080 if (DEBUG) Log.v(TAG, "Delivering touch event: " + ev);
1081 mEngine.onTouchEvent(ev);
1082 }
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07001083 ev.recycle();
1084 } break;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001085 default :
1086 Log.w(TAG, "Unknown message type " + message.what);
1087 }
1088 }
1089 }
1090
1091 /**
1092 * Implements the internal {@link IWallpaperService} interface to convert
1093 * incoming calls to it back to calls on an {@link WallpaperService}.
1094 */
1095 class IWallpaperServiceWrapper extends IWallpaperService.Stub {
1096 private final WallpaperService mTarget;
1097
1098 public IWallpaperServiceWrapper(WallpaperService context) {
1099 mTarget = context;
1100 }
1101
Craig Mautnerb1ef3692012-11-16 17:31:04 -08001102 @Override
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001103 public void attach(IWallpaperConnection conn, IBinder windowToken,
1104 int windowType, boolean isPreview, int reqWidth, int reqHeight) {
1105 new IWallpaperEngineWrapper(mTarget, conn, windowToken,
1106 windowType, isPreview, reqWidth, reqHeight);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001107 }
1108 }
Craig Mautnerb1ef3692012-11-16 17:31:04 -08001109
Dianne Hackbornaf1f42b2009-11-20 16:27:27 -08001110 @Override
1111 public void onCreate() {
1112 super.onCreate();
1113 }
1114
1115 @Override
1116 public void onDestroy() {
1117 super.onDestroy();
1118 for (int i=0; i<mActiveEngines.size(); i++) {
1119 mActiveEngines.get(i).detach();
1120 }
1121 mActiveEngines.clear();
1122 }
1123
Dianne Hackborn8cc6a502009-08-05 21:29:42 -07001124 /**
1125 * Implement to return the implementation of the internal accessibility
1126 * service interface. Subclasses should not override.
1127 */
1128 @Override
1129 public final IBinder onBind(Intent intent) {
1130 return new IWallpaperServiceWrapper(this);
1131 }
Craig Mautnerb1ef3692012-11-16 17:31:04 -08001132
Dianne Hackborn23ef7b42009-11-18 18:20:39 -08001133 /**
1134 * Must be implemented to return a new instance of the wallpaper's engine.
1135 * Note that multiple instances may be active at the same time, such as
1136 * when the wallpaper is currently set as the active wallpaper and the user
1137 * is in the wallpaper picker viewing a preview of it as well.
1138 */
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001139 public abstract Engine onCreateEngine();
Dianne Hackborn527de8e2011-08-22 16:10:36 -07001140
1141 @Override
1142 protected void dump(FileDescriptor fd, PrintWriter out, String[] args) {
1143 out.print("State of wallpaper "); out.print(this); out.println(":");
1144 for (int i=0; i<mActiveEngines.size(); i++) {
1145 Engine engine = mActiveEngines.get(i);
1146 out.print(" Engine "); out.print(engine); out.println(":");
1147 engine.dump(" ", fd, out, args);
1148 }
1149 }
Dianne Hackborn8cc6a502009-08-05 21:29:42 -07001150}