blob: 03ce4e06cc9f3e5adf27632dedbcbeb3e395ffe7 [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;
Craig Mautner6881a102012-07-27 13:04:51 -070041import android.view.Display;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070042import android.view.Gravity;
43import android.view.IWindowSession;
Jeff Brown46b9ac02010-04-22 18:58:52 -070044import android.view.InputChannel;
Jeff Brownc5ed5912010-07-14 18:48:53 -070045import android.view.InputDevice;
Jeff Brown4952dfd2011-11-30 19:23:22 -080046import android.view.InputEvent;
Jeff Brown32cbc38552011-12-01 14:01:49 -080047import android.view.InputEventReceiver;
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -070048import android.view.MotionEvent;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070049import android.view.SurfaceHolder;
50import android.view.View;
Dianne Hackborn72c82ab2009-08-11 21:13:54 -070051import android.view.ViewGroup;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070052import android.view.WindowManager;
Jeff Brown98365d72012-08-19 20:30:52 -070053import android.view.WindowManagerGlobal;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070054
Dianne Hackborn527de8e2011-08-22 16:10:36 -070055import java.io.FileDescriptor;
56import java.io.PrintWriter;
Dianne Hackbornaf1f42b2009-11-20 16:27:27 -080057import java.util.ArrayList;
58
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070059/**
60 * A wallpaper service is responsible for showing a live wallpaper behind
Dianne Hackborn23ef7b42009-11-18 18:20:39 -080061 * applications that would like to sit on top of it. This service object
62 * itself does very little -- its only purpose is to generate instances of
Dianne Hackborne4260f42009-11-18 21:15:59 -080063 * {@link Engine} as needed. Implementing a wallpaper thus
Dianne Hackborn23ef7b42009-11-18 18:20:39 -080064 * involves subclassing from this, subclassing an Engine implementation,
65 * and implementing {@link #onCreateEngine()} to return a new instance of
66 * your engine.
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070067 */
68public abstract class WallpaperService extends Service {
69 /**
70 * The {@link Intent} that must be declared as handled by the service.
Dianne Hackbornd6847842010-01-12 18:14:19 -080071 * To be supported, the service must also require the
72 * {@link android.Manifest.permission#BIND_WALLPAPER} permission so
73 * that other applications can not abuse it.
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070074 */
Dianne Hackbornd6847842010-01-12 18:14:19 -080075 @SdkConstant(SdkConstantType.SERVICE_ACTION)
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070076 public static final String SERVICE_INTERFACE =
Dianne Hackbornd6847842010-01-12 18:14:19 -080077 "android.service.wallpaper.WallpaperService";
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070078
Dianne Hackborneb034652009-09-07 00:49:58 -070079 /**
80 * Name under which a WallpaperService component publishes information
81 * about itself. This meta-data must reference an XML resource containing
82 * a <code>&lt;{@link android.R.styleable#Wallpaper wallpaper}&gt;</code>
83 * tag.
84 */
85 public static final String SERVICE_META_DATA = "android.service.wallpaper";
Craig Mautnerb1ef3692012-11-16 17:31:04 -080086
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070087 static final String TAG = "WallpaperService";
Dianne Hackborn72c82ab2009-08-11 21:13:54 -070088 static final boolean DEBUG = false;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070089
90 private static final int DO_ATTACH = 10;
91 private static final int DO_DETACH = 20;
Dianne Hackborn284ac932009-08-28 10:34:25 -070092 private static final int DO_SET_DESIRED_SIZE = 30;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070093
94 private static final int MSG_UPDATE_SURFACE = 10000;
Dianne Hackborn759a39e2009-08-09 17:20:27 -070095 private static final int MSG_VISIBILITY_CHANGED = 10010;
Dianne Hackborn72c82ab2009-08-11 21:13:54 -070096 private static final int MSG_WALLPAPER_OFFSETS = 10020;
Dianne Hackborn75804932009-10-20 20:15:20 -070097 private static final int MSG_WALLPAPER_COMMAND = 10025;
Dianne Hackborn7341d7a2009-08-14 11:37:52 -070098 private static final int MSG_WINDOW_RESIZED = 10030;
Craig Mautner5702d4d2012-06-30 14:10:16 -070099 private static final int MSG_WINDOW_MOVED = 10035;
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -0700100 private static final int MSG_TOUCH_EVENT = 10040;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700101
Dianne Hackbornaf1f42b2009-11-20 16:27:27 -0800102 private final ArrayList<Engine> mActiveEngines
103 = new ArrayList<Engine>();
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700104
Dianne Hackborn75804932009-10-20 20:15:20 -0700105 static final class WallpaperCommand {
106 String action;
107 int x;
108 int y;
109 int z;
110 Bundle extras;
111 boolean sync;
112 }
113
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700114 /**
115 * The actual implementation of a wallpaper. A wallpaper service may
116 * have multiple instances running (for example as a real wallpaper
117 * and as a preview), each of which is represented by its own Engine
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700118 * instance. You must implement {@link WallpaperService#onCreateEngine()}
119 * to return your concrete Engine implementation.
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700120 */
121 public class Engine {
122 IWallpaperEngineWrapper mIWallpaperEngine;
123
124 // Copies from mIWallpaperEngine.
125 HandlerCaller mCaller;
126 IWallpaperConnection mConnection;
127 IBinder mWindowToken;
128
129 boolean mInitializing = true;
Dianne Hackborn284ac932009-08-28 10:34:25 -0700130 boolean mVisible;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -0700131 boolean mScreenOn = true;
132 boolean mReportedVisible;
Dianne Hackborn284ac932009-08-28 10:34:25 -0700133 boolean mDestroyed;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700134
135 // Current window state.
136 boolean mCreated;
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700137 boolean mSurfaceCreated;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700138 boolean mIsCreating;
139 boolean mDrawingAllowed;
Dianne Hackborn9e4e7272011-08-30 14:06:51 -0700140 boolean mOffsetsChanged;
Jeff Sharkey35be7562012-04-18 19:16:15 -0700141 boolean mFixedSizeAllowed;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700142 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;
Chet Haasea8e5a2b2011-10-28 13:18:16 -0700149 int mWindowPrivateFlags =
150 WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS;
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -0700151 int mCurWindowFlags = mWindowFlags;
Chet Haasea8e5a2b2011-10-28 13:18:16 -0700152 int mCurWindowPrivateFlags = mWindowPrivateFlags;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700153 final Rect mVisibleInsets = new Rect();
154 final Rect mWinFrame = new Rect();
Dianne Hackbornc4aad012013-02-22 15:05:25 -0800155 final Rect mOverscanInsets = new Rect();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700156 final Rect mContentInsets = new Rect();
Dianne Hackborn694f79b2010-03-17 19:44:59 -0700157 final Configuration mConfiguration = new Configuration();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700158
159 final WindowManager.LayoutParams mLayout
160 = new WindowManager.LayoutParams();
161 IWindowSession mSession;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700162 InputChannel mInputChannel;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700163
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700164 final Object mLock = new Object();
165 boolean mOffsetMessageEnqueued;
166 float mPendingXOffset;
167 float mPendingYOffset;
Marco Nelissenbf6956b2009-11-09 15:21:13 -0800168 float mPendingXOffsetStep;
169 float mPendingYOffsetStep;
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700170 boolean mPendingSync;
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -0700171 MotionEvent mPendingMove;
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700172
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -0700173 final BroadcastReceiver mReceiver = new BroadcastReceiver() {
174 @Override
175 public void onReceive(Context context, Intent intent) {
176 if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())) {
177 mScreenOn = true;
178 reportVisibility();
179 } else if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {
180 mScreenOn = false;
181 reportVisibility();
182 }
183 }
184 };
185
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700186 final BaseSurfaceHolder mSurfaceHolder = new BaseSurfaceHolder() {
Mathias Agopian62bf4a02010-09-08 16:32:27 -0700187 {
Jeff Brown24572372011-06-09 19:05:15 -0700188 mRequestedFormat = PixelFormat.RGBX_8888;
Mathias Agopian62bf4a02010-09-08 16:32:27 -0700189 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700190
191 @Override
192 public boolean onAllowLockCanvas() {
193 return mDrawingAllowed;
194 }
195
196 @Override
197 public void onRelayoutContainer() {
198 Message msg = mCaller.obtainMessage(MSG_UPDATE_SURFACE);
199 mCaller.sendMessage(msg);
200 }
201
202 @Override
203 public void onUpdateSurface() {
204 Message msg = mCaller.obtainMessage(MSG_UPDATE_SURFACE);
205 mCaller.sendMessage(msg);
206 }
207
208 public boolean isCreating() {
209 return mIsCreating;
210 }
211
Dianne Hackborna48a37f2011-02-01 16:30:38 -0800212 @Override
213 public void setFixedSize(int width, int height) {
Jeff Sharkey35be7562012-04-18 19:16:15 -0700214 if (!mFixedSizeAllowed) {
Dianne Hackborna48a37f2011-02-01 16:30:38 -0800215 // Regular apps can't do this. It can only work for
216 // certain designs of window animations, so you can't
217 // rely on it.
218 throw new UnsupportedOperationException(
219 "Wallpapers currently only support sizing from layout");
220 }
Michael Jurkab8f939f2011-02-01 20:50:30 -0800221 super.setFixedSize(width, height);
Dianne Hackborna48a37f2011-02-01 16:30:38 -0800222 }
223
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700224 public void setKeepScreenOn(boolean screenOn) {
Dianne Hackborn284ac932009-08-28 10:34:25 -0700225 throw new UnsupportedOperationException(
226 "Wallpapers do not support keep screen on");
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700227 }
228
229 };
Jeff Brown32cbc38552011-12-01 14:01:49 -0800230
231 final class WallpaperInputEventReceiver extends InputEventReceiver {
232 public WallpaperInputEventReceiver(InputChannel inputChannel, Looper looper) {
233 super(inputChannel, looper);
234 }
235
Jeff Brown46b9ac02010-04-22 18:58:52 -0700236 @Override
Jeff Brown32cbc38552011-12-01 14:01:49 -0800237 public void onInputEvent(InputEvent event) {
Jeff Brown3915bb82010-11-05 15:02:16 -0700238 boolean handled = false;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700239 try {
Jeff Brown4952dfd2011-11-30 19:23:22 -0800240 if (event instanceof MotionEvent
241 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
Jeff Brown32cbc38552011-12-01 14:01:49 -0800242 MotionEvent dup = MotionEvent.obtainNoHistory((MotionEvent)event);
243 dispatchPointer(dup);
Jeff Brown3915bb82010-11-05 15:02:16 -0700244 handled = true;
Jeff Brownc5ed5912010-07-14 18:48:53 -0700245 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700246 } finally {
Jeff Brown32cbc38552011-12-01 14:01:49 -0800247 finishInputEvent(event, handled);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700248 }
249 }
Jeff Brown32cbc38552011-12-01 14:01:49 -0800250 }
251 WallpaperInputEventReceiver mInputEventReceiver;
252
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700253 final BaseIWindow mWindow = new BaseIWindow() {
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -0700254 @Override
Dianne Hackbornc4aad012013-02-22 15:05:25 -0800255 public void resized(Rect frame, Rect overscanInsets, Rect contentInsets,
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800256 Rect visibleInsets, boolean reportDraw, Configuration newConfig) {
Dianne Hackborn7341d7a2009-08-14 11:37:52 -0700257 Message msg = mCaller.obtainMessageI(MSG_WINDOW_RESIZED,
258 reportDraw ? 1 : 0);
259 mCaller.sendMessage(msg);
260 }
Craig Mautner5702d4d2012-06-30 14:10:16 -0700261
262 @Override
263 public void moved(int newX, int newY) {
264 Message msg = mCaller.obtainMessageII(MSG_WINDOW_MOVED, newX, newY);
265 mCaller.sendMessage(msg);
266 }
267
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -0700268 @Override
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700269 public void dispatchAppVisibility(boolean visible) {
Dianne Hackborn284ac932009-08-28 10:34:25 -0700270 // We don't do this in preview mode; we'll let the preview
271 // activity tell us when to run.
272 if (!mIWallpaperEngine.mIsPreview) {
273 Message msg = mCaller.obtainMessageI(MSG_VISIBILITY_CHANGED,
274 visible ? 1 : 0);
275 mCaller.sendMessage(msg);
276 }
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700277 }
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700278
279 @Override
Marco Nelissenbf6956b2009-11-09 15:21:13 -0800280 public void dispatchWallpaperOffsets(float x, float y, float xStep, float yStep,
281 boolean sync) {
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700282 synchronized (mLock) {
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700283 if (DEBUG) Log.v(TAG, "Dispatch wallpaper offsets: " + x + ", " + y);
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700284 mPendingXOffset = x;
285 mPendingYOffset = y;
Marco Nelissenbf6956b2009-11-09 15:21:13 -0800286 mPendingXOffsetStep = xStep;
287 mPendingYOffsetStep = yStep;
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700288 if (sync) {
289 mPendingSync = true;
290 }
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700291 if (!mOffsetMessageEnqueued) {
292 mOffsetMessageEnqueued = true;
293 Message msg = mCaller.obtainMessage(MSG_WALLPAPER_OFFSETS);
294 mCaller.sendMessage(msg);
295 }
296 }
297 }
Craig Mautner5702d4d2012-06-30 14:10:16 -0700298
299 @Override
Dianne Hackborn75804932009-10-20 20:15:20 -0700300 public void dispatchWallpaperCommand(String action, int x, int y,
301 int z, Bundle extras, boolean sync) {
302 synchronized (mLock) {
303 if (DEBUG) Log.v(TAG, "Dispatch wallpaper command: " + x + ", " + y);
304 WallpaperCommand cmd = new WallpaperCommand();
305 cmd.action = action;
306 cmd.x = x;
307 cmd.y = y;
308 cmd.z = z;
309 cmd.extras = extras;
310 cmd.sync = sync;
311 Message msg = mCaller.obtainMessage(MSG_WALLPAPER_COMMAND);
312 msg.obj = cmd;
313 mCaller.sendMessage(msg);
314 }
315 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700316 };
317
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700318 /**
319 * Provides access to the surface in which this wallpaper is drawn.
320 */
321 public SurfaceHolder getSurfaceHolder() {
322 return mSurfaceHolder;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700323 }
324
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700325 /**
326 * Convenience for {@link WallpaperManager#getDesiredMinimumWidth()
327 * WallpaperManager.getDesiredMinimumWidth()}, returning the width
328 * that the system would like this wallpaper to run in.
329 */
330 public int getDesiredMinimumWidth() {
331 return mIWallpaperEngine.mReqWidth;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700332 }
333
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700334 /**
335 * Convenience for {@link WallpaperManager#getDesiredMinimumHeight()
336 * WallpaperManager.getDesiredMinimumHeight()}, returning the height
337 * that the system would like this wallpaper to run in.
338 */
339 public int getDesiredMinimumHeight() {
340 return mIWallpaperEngine.mReqHeight;
341 }
342
343 /**
Dianne Hackborn284ac932009-08-28 10:34:25 -0700344 * Return whether the wallpaper is currently visible to the user,
345 * this is the last value supplied to
346 * {@link #onVisibilityChanged(boolean)}.
347 */
348 public boolean isVisible() {
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -0700349 return mReportedVisible;
Dianne Hackborn284ac932009-08-28 10:34:25 -0700350 }
351
352 /**
Dianne Hackborn3be63c02009-08-20 19:31:38 -0700353 * Returns true if this engine is running in preview mode -- that is,
354 * it is being shown to the user before they select it as the actual
355 * wallpaper.
356 */
357 public boolean isPreview() {
358 return mIWallpaperEngine.mIsPreview;
359 }
360
361 /**
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -0700362 * Control whether this wallpaper will receive raw touch events
363 * from the window manager as the user interacts with the window
364 * that is currently displaying the wallpaper. By default they
365 * are turned off. If enabled, the events will be received in
366 * {@link #onTouchEvent(MotionEvent)}.
367 */
368 public void setTouchEventsEnabled(boolean enabled) {
369 mWindowFlags = enabled
370 ? (mWindowFlags&~WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE)
371 : (mWindowFlags|WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
372 if (mCreated) {
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700373 updateSurface(false, false, false);
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -0700374 }
375 }
Chet Haasea8e5a2b2011-10-28 13:18:16 -0700376
377 /**
378 * Control whether this wallpaper will receive notifications when the wallpaper
379 * has been scrolled. By default, wallpapers will receive notifications, although
380 * the default static image wallpapers do not. It is a performance optimization to
381 * set this to false.
382 *
383 * @param enabled whether the wallpaper wants to receive offset notifications
384 */
385 public void setOffsetNotificationsEnabled(boolean enabled) {
386 mWindowPrivateFlags = enabled
387 ? (mWindowPrivateFlags |
388 WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS)
389 : (mWindowPrivateFlags &
390 ~WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS);
391 if (mCreated) {
392 updateSurface(false, false, false);
393 }
394 }
Jeff Sharkey35be7562012-04-18 19:16:15 -0700395
396 /** {@hide} */
397 public void setFixedSizeAllowed(boolean allowed) {
398 mFixedSizeAllowed = allowed;
399 }
400
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -0700401 /**
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700402 * Called once to initialize the engine. After returning, the
403 * engine's surface will be created by the framework.
404 */
405 public void onCreate(SurfaceHolder surfaceHolder) {
406 }
407
408 /**
409 * Called right before the engine is going away. After this the
410 * surface will be destroyed and this Engine object is no longer
411 * valid.
412 */
413 public void onDestroy() {
414 }
415
416 /**
417 * Called to inform you of the wallpaper becoming visible or
418 * hidden. <em>It is very important that a wallpaper only use
419 * CPU while it is visible.</em>.
420 */
421 public void onVisibilityChanged(boolean visible) {
422 }
423
424 /**
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -0700425 * Called as the user performs touch-screen interaction with the
426 * window that is currently showing this wallpaper. Note that the
427 * events you receive here are driven by the actual application the
Marco Nelissenae87bd02009-09-17 09:44:43 -0700428 * user is interacting with, so if it is slow you will get fewer
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -0700429 * move events.
430 */
431 public void onTouchEvent(MotionEvent event) {
432 }
433
434 /**
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700435 * Called to inform you of the wallpaper's offsets changing
436 * within its contain, corresponding to the container's
437 * call to {@link WallpaperManager#setWallpaperOffsets(IBinder, float, float)
438 * WallpaperManager.setWallpaperOffsets()}.
439 */
440 public void onOffsetsChanged(float xOffset, float yOffset,
Marco Nelissenbf6956b2009-11-09 15:21:13 -0800441 float xOffsetStep, float yOffsetStep,
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700442 int xPixelOffset, int yPixelOffset) {
443 }
444
445 /**
Dianne Hackborn75804932009-10-20 20:15:20 -0700446 * Process a command that was sent to the wallpaper with
Dianne Hackborn13bf82602009-11-05 21:45:51 -0800447 * {@link WallpaperManager#sendWallpaperCommand}.
Dianne Hackborn75804932009-10-20 20:15:20 -0700448 * The default implementation does nothing, and always returns null
449 * as the result.
450 *
451 * @param action The name of the command to perform. This tells you
452 * what to do and how to interpret the rest of the arguments.
453 * @param x Generic integer parameter.
454 * @param y Generic integer parameter.
455 * @param z Generic integer parameter.
456 * @param extras Any additional parameters.
457 * @param resultRequested If true, the caller is requesting that
458 * a result, appropriate for the command, be returned back.
459 * @return If returning a result, create a Bundle and place the
460 * result data in to it. Otherwise return null.
461 */
462 public Bundle onCommand(String action, int x, int y, int z,
463 Bundle extras, boolean resultRequested) {
464 return null;
465 }
466
467 /**
Dianne Hackborn284ac932009-08-28 10:34:25 -0700468 * Called when an application has changed the desired virtual size of
469 * the wallpaper.
470 */
471 public void onDesiredSizeChanged(int desiredWidth, int desiredHeight) {
472 }
473
474 /**
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700475 * Convenience for {@link SurfaceHolder.Callback#surfaceChanged
476 * SurfaceHolder.Callback.surfaceChanged()}.
477 */
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700478 public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
479 }
480
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700481 /**
Dianne Hackborn1d28f9c2010-07-13 20:38:06 -0700482 * Convenience for {@link SurfaceHolder.Callback2#surfaceRedrawNeeded
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700483 * SurfaceHolder.Callback.surfaceRedrawNeeded()}.
484 */
485 public void onSurfaceRedrawNeeded(SurfaceHolder holder) {
486 }
487
488 /**
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700489 * Convenience for {@link SurfaceHolder.Callback#surfaceCreated
490 * SurfaceHolder.Callback.surfaceCreated()}.
491 */
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700492 public void onSurfaceCreated(SurfaceHolder holder) {
493 }
494
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700495 /**
496 * Convenience for {@link SurfaceHolder.Callback#surfaceDestroyed
497 * SurfaceHolder.Callback.surfaceDestroyed()}.
498 */
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700499 public void onSurfaceDestroyed(SurfaceHolder holder) {
500 }
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700501
Dianne Hackborn527de8e2011-08-22 16:10:36 -0700502 protected void dump(String prefix, FileDescriptor fd, PrintWriter out, String[] args) {
503 out.print(prefix); out.print("mInitializing="); out.print(mInitializing);
504 out.print(" mDestroyed="); out.println(mDestroyed);
505 out.print(prefix); out.print("mVisible="); out.print(mVisible);
506 out.print(" mScreenOn="); out.print(mScreenOn);
507 out.print(" mReportedVisible="); out.println(mReportedVisible);
508 out.print(prefix); out.print("mCreated="); out.print(mCreated);
509 out.print(" mSurfaceCreated="); out.print(mSurfaceCreated);
510 out.print(" mIsCreating="); out.print(mIsCreating);
511 out.print(" mDrawingAllowed="); out.println(mDrawingAllowed);
512 out.print(prefix); out.print("mWidth="); out.print(mWidth);
513 out.print(" mCurWidth="); out.print(mCurWidth);
514 out.print(" mHeight="); out.print(mHeight);
515 out.print(" mCurHeight="); out.println(mCurHeight);
516 out.print(prefix); out.print("mType="); out.print(mType);
517 out.print(" mWindowFlags="); out.print(mWindowFlags);
518 out.print(" mCurWindowFlags="); out.println(mCurWindowFlags);
Chet Haasea8e5a2b2011-10-28 13:18:16 -0700519 out.print(" mWindowPrivateFlags="); out.print(mWindowPrivateFlags);
520 out.print(" mCurWindowPrivateFlags="); out.println(mCurWindowPrivateFlags);
Dianne Hackborn527de8e2011-08-22 16:10:36 -0700521 out.print(prefix); out.print("mVisibleInsets=");
522 out.print(mVisibleInsets.toShortString());
523 out.print(" mWinFrame="); out.print(mWinFrame.toShortString());
524 out.print(" mContentInsets="); out.println(mContentInsets.toShortString());
525 out.print(prefix); out.print("mConfiguration="); out.println(mConfiguration);
526 out.print(prefix); out.print("mLayout="); out.println(mLayout);
527 synchronized (mLock) {
528 out.print(prefix); out.print("mPendingXOffset="); out.print(mPendingXOffset);
529 out.print(" mPendingXOffset="); out.println(mPendingXOffset);
530 out.print(prefix); out.print("mPendingXOffsetStep=");
531 out.print(mPendingXOffsetStep);
532 out.print(" mPendingXOffsetStep="); out.println(mPendingXOffsetStep);
533 out.print(prefix); out.print("mOffsetMessageEnqueued=");
534 out.print(mOffsetMessageEnqueued);
535 out.print(" mPendingSync="); out.println(mPendingSync);
536 if (mPendingMove != null) {
537 out.print(prefix); out.print("mPendingMove="); out.println(mPendingMove);
538 }
539 }
540 }
541
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700542 private void dispatchPointer(MotionEvent event) {
Jeff Brown33bbfd22011-02-24 20:55:35 -0800543 if (event.isTouchEvent()) {
544 synchronized (mLock) {
545 if (event.getAction() == MotionEvent.ACTION_MOVE) {
546 mPendingMove = event;
547 } else {
548 mPendingMove = null;
549 }
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700550 }
Jeff Brown33bbfd22011-02-24 20:55:35 -0800551 Message msg = mCaller.obtainMessageO(MSG_TOUCH_EVENT, event);
552 mCaller.sendMessage(msg);
Jeff Brown32cbc38552011-12-01 14:01:49 -0800553 } else {
554 event.recycle();
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700555 }
556 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700557
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700558 void updateSurface(boolean forceRelayout, boolean forceReport, boolean redrawNeeded) {
Dianne Hackborn284ac932009-08-28 10:34:25 -0700559 if (mDestroyed) {
560 Log.w(TAG, "Ignoring updateSurface: destroyed");
561 }
562
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700563 int myWidth = mSurfaceHolder.getRequestedWidth();
Romain Guy980a9382010-01-08 15:06:28 -0800564 if (myWidth <= 0) myWidth = ViewGroup.LayoutParams.MATCH_PARENT;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700565 int myHeight = mSurfaceHolder.getRequestedHeight();
Romain Guy980a9382010-01-08 15:06:28 -0800566 if (myHeight <= 0) myHeight = ViewGroup.LayoutParams.MATCH_PARENT;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700567
568 final boolean creating = !mCreated;
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700569 final boolean surfaceCreating = !mSurfaceCreated;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700570 final boolean formatChanged = mFormat != mSurfaceHolder.getRequestedFormat();
Dianne Hackborn7341d7a2009-08-14 11:37:52 -0700571 boolean sizeChanged = mWidth != myWidth || mHeight != myHeight;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700572 final boolean typeChanged = mType != mSurfaceHolder.getRequestedType();
Chet Haasea8e5a2b2011-10-28 13:18:16 -0700573 final boolean flagsChanged = mCurWindowFlags != mWindowFlags ||
574 mCurWindowPrivateFlags != mWindowPrivateFlags;
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700575 if (forceRelayout || creating || surfaceCreating || formatChanged || sizeChanged
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -0700576 || typeChanged || flagsChanged || redrawNeeded
577 || !mIWallpaperEngine.mShownReported) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700578
Dianne Hackborn284ac932009-08-28 10:34:25 -0700579 if (DEBUG) Log.v(TAG, "Changes: creating=" + creating
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700580 + " format=" + formatChanged + " size=" + sizeChanged);
581
582 try {
583 mWidth = myWidth;
584 mHeight = myHeight;
585 mFormat = mSurfaceHolder.getRequestedFormat();
586 mType = mSurfaceHolder.getRequestedType();
587
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700588 mLayout.x = 0;
589 mLayout.y = 0;
590 mLayout.width = myWidth;
591 mLayout.height = myHeight;
592
593 mLayout.format = mFormat;
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -0700594
595 mCurWindowFlags = mWindowFlags;
596 mLayout.flags = mWindowFlags
597 | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
598 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
599 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
600 ;
Chet Haasea8e5a2b2011-10-28 13:18:16 -0700601 mCurWindowPrivateFlags = mWindowPrivateFlags;
602 mLayout.privateFlags = mWindowPrivateFlags;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700603
604 mLayout.memoryType = mType;
605 mLayout.token = mWindowToken;
606
607 if (!mCreated) {
Dianne Hackborn3be63c02009-08-20 19:31:38 -0700608 mLayout.type = mIWallpaperEngine.mWindowType;
Fabrice Di Meglioaac0d4e2012-07-19 19:21:26 -0700609 mLayout.gravity = Gravity.START|Gravity.TOP;
Dianne Hackborn0586a1b2009-09-06 21:08:27 -0700610 mLayout.setTitle(WallpaperService.this.getClass().getName());
Dianne Hackborn284ac932009-08-28 10:34:25 -0700611 mLayout.windowAnimations =
612 com.android.internal.R.style.Animation_Wallpaper;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700613 mInputChannel = new InputChannel();
Craig Mautner6881a102012-07-27 13:04:51 -0700614 if (mSession.addToDisplay(mWindow, mWindow.mSeq, mLayout, View.VISIBLE,
615 Display.DEFAULT_DISPLAY, mContentInsets, mInputChannel) < 0) {
Mattias Peterssond9463f52011-01-12 15:38:55 +0100616 Log.w(TAG, "Failed to add window while updating wallpaper surface.");
617 return;
618 }
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700619 mCreated = true;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700620
Jeff Brown32cbc38552011-12-01 14:01:49 -0800621 mInputEventReceiver = new WallpaperInputEventReceiver(
622 mInputChannel, Looper.myLooper());
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700623 }
624
625 mSurfaceHolder.mSurfaceLock.lock();
626 mDrawingAllowed = true;
627
628 final int relayoutResult = mSession.relayout(
Dianne Hackborn9a230e02011-10-06 11:51:27 -0700629 mWindow, mWindow.mSeq, mLayout, mWidth, mHeight,
Dianne Hackbornc4aad012013-02-22 15:05:25 -0800630 View.VISIBLE, 0, mWinFrame, mOverscanInsets, mContentInsets,
Dianne Hackborn694f79b2010-03-17 19:44:59 -0700631 mVisibleInsets, mConfiguration, mSurfaceHolder.mSurface);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700632
Dianne Hackborn284ac932009-08-28 10:34:25 -0700633 if (DEBUG) Log.v(TAG, "New surface: " + mSurfaceHolder.mSurface
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700634 + ", frame=" + mWinFrame);
635
Dianne Hackborn7341d7a2009-08-14 11:37:52 -0700636 int w = mWinFrame.width();
637 if (mCurWidth != w) {
638 sizeChanged = true;
639 mCurWidth = w;
640 }
641 int h = mWinFrame.height();
642 if (mCurHeight != h) {
643 sizeChanged = true;
644 mCurHeight = h;
645 }
Jeff Brown30bc34f2011-01-25 12:56:56 -0800646
647 mSurfaceHolder.setSurfaceFrameSize(w, h);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700648 mSurfaceHolder.mSurfaceLock.unlock();
649
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700650 if (!mSurfaceHolder.mSurface.isValid()) {
651 reportSurfaceDestroyed();
652 if (DEBUG) Log.v(TAG, "Layout: Surface destroyed");
653 return;
654 }
Dianne Hackborn9e4e7272011-08-30 14:06:51 -0700655
656 boolean didSurface = false;
657
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700658 try {
Dianne Hackborndc8a7f62010-05-10 11:29:34 -0700659 mSurfaceHolder.ungetCallbacks();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700660
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700661 if (surfaceCreating) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700662 mIsCreating = true;
Dianne Hackborn9e4e7272011-08-30 14:06:51 -0700663 didSurface = true;
Dianne Hackborn284ac932009-08-28 10:34:25 -0700664 if (DEBUG) Log.v(TAG, "onSurfaceCreated("
665 + mSurfaceHolder + "): " + this);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700666 onSurfaceCreated(mSurfaceHolder);
Dianne Hackborndc8a7f62010-05-10 11:29:34 -0700667 SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700668 if (callbacks != null) {
669 for (SurfaceHolder.Callback c : callbacks) {
670 c.surfaceCreated(mSurfaceHolder);
671 }
672 }
673 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700674
Jeff Brown98365d72012-08-19 20:30:52 -0700675 redrawNeeded |= creating || (relayoutResult
676 & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0;
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700677
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700678 if (forceReport || creating || surfaceCreating
679 || formatChanged || sizeChanged) {
Dianne Hackborncbf15042009-08-18 18:29:09 -0700680 if (DEBUG) {
681 RuntimeException e = new RuntimeException();
682 e.fillInStackTrace();
683 Log.w(TAG, "forceReport=" + forceReport + " creating=" + creating
684 + " formatChanged=" + formatChanged
685 + " sizeChanged=" + sizeChanged, e);
686 }
Dianne Hackborn284ac932009-08-28 10:34:25 -0700687 if (DEBUG) Log.v(TAG, "onSurfaceChanged("
688 + mSurfaceHolder + ", " + mFormat
689 + ", " + mCurWidth + ", " + mCurHeight
690 + "): " + this);
Dianne Hackborn9e4e7272011-08-30 14:06:51 -0700691 didSurface = true;
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700692 onSurfaceChanged(mSurfaceHolder, mFormat,
693 mCurWidth, mCurHeight);
Dianne Hackborndc8a7f62010-05-10 11:29:34 -0700694 SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700695 if (callbacks != null) {
696 for (SurfaceHolder.Callback c : callbacks) {
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700697 c.surfaceChanged(mSurfaceHolder, mFormat,
698 mCurWidth, mCurHeight);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700699 }
700 }
701 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700702
703 if (redrawNeeded) {
704 onSurfaceRedrawNeeded(mSurfaceHolder);
705 SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
706 if (callbacks != null) {
707 for (SurfaceHolder.Callback c : callbacks) {
708 if (c instanceof SurfaceHolder.Callback2) {
709 ((SurfaceHolder.Callback2)c).surfaceRedrawNeeded(
710 mSurfaceHolder);
711 }
712 }
713 }
714 }
715
Dianne Hackborn9e4e7272011-08-30 14:06:51 -0700716 if (didSurface && !mReportedVisible) {
717 // This wallpaper is currently invisible, but its
718 // surface has changed. At this point let's tell it
719 // again that it is invisible in case the report about
720 // the surface caused it to start running. We really
721 // don't want wallpapers running when not visible.
722 if (mIsCreating) {
723 // Some wallpapers will ignore this call if they
724 // had previously been told they were invisble,
725 // so if we are creating a new surface then toggle
726 // the state to get them to notice.
727 if (DEBUG) Log.v(TAG, "onVisibilityChanged(true) at surface: "
728 + this);
729 onVisibilityChanged(true);
730 }
731 if (DEBUG) Log.v(TAG, "onVisibilityChanged(false) at surface: "
732 + this);
733 onVisibilityChanged(false);
734 }
735
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700736 } finally {
737 mIsCreating = false;
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700738 mSurfaceCreated = true;
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700739 if (redrawNeeded) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700740 mSession.finishDrawing(mWindow);
741 }
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -0700742 mIWallpaperEngine.reportShown();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700743 }
744 } catch (RemoteException ex) {
745 }
746 if (DEBUG) Log.v(
747 TAG, "Layout: x=" + mLayout.x + " y=" + mLayout.y +
748 " w=" + mLayout.width + " h=" + mLayout.height);
749 }
750 }
751
752 void attach(IWallpaperEngineWrapper wrapper) {
Dianne Hackborncbf15042009-08-18 18:29:09 -0700753 if (DEBUG) Log.v(TAG, "attach: " + this + " wrapper=" + wrapper);
Dianne Hackborn284ac932009-08-28 10:34:25 -0700754 if (mDestroyed) {
755 return;
756 }
757
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700758 mIWallpaperEngine = wrapper;
759 mCaller = wrapper.mCaller;
760 mConnection = wrapper.mConnection;
761 mWindowToken = wrapper.mWindowToken;
Dianne Hackborn284ac932009-08-28 10:34:25 -0700762 mSurfaceHolder.setSizeFromLayout();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700763 mInitializing = true;
Jeff Brownf9e989d2013-04-04 23:04:03 -0700764 mSession = WindowManagerGlobal.getWindowSession();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700765
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700766 mWindow.setSession(mSession);
Dianne Hackborn9fe6cb52011-09-09 13:02:43 -0700767
768 mScreenOn = ((PowerManager)getSystemService(Context.POWER_SERVICE)).isScreenOn();
769
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -0700770 IntentFilter filter = new IntentFilter();
771 filter.addAction(Intent.ACTION_SCREEN_ON);
772 filter.addAction(Intent.ACTION_SCREEN_OFF);
773 registerReceiver(mReceiver, filter);
774
Dianne Hackborn284ac932009-08-28 10:34:25 -0700775 if (DEBUG) Log.v(TAG, "onCreate(): " + this);
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700776 onCreate(mSurfaceHolder);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700777
778 mInitializing = false;
Dianne Hackborn9e4e7272011-08-30 14:06:51 -0700779 mReportedVisible = false;
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700780 updateSurface(false, false, false);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700781 }
782
Dianne Hackborn284ac932009-08-28 10:34:25 -0700783 void doDesiredSizeChanged(int desiredWidth, int desiredHeight) {
784 if (!mDestroyed) {
785 if (DEBUG) Log.v(TAG, "onDesiredSizeChanged("
786 + desiredWidth + "," + desiredHeight + "): " + this);
Joe Onoratodcfae5c2010-10-28 18:03:23 -0700787 mIWallpaperEngine.mReqWidth = desiredWidth;
788 mIWallpaperEngine.mReqHeight = desiredHeight;
Dianne Hackborn284ac932009-08-28 10:34:25 -0700789 onDesiredSizeChanged(desiredWidth, desiredHeight);
Dianne Hackborn9e4e7272011-08-30 14:06:51 -0700790 doOffsetsChanged(true);
Dianne Hackborn284ac932009-08-28 10:34:25 -0700791 }
792 }
793
794 void doVisibilityChanged(boolean visible) {
Dianne Hackbornaf1f42b2009-11-20 16:27:27 -0800795 if (!mDestroyed) {
796 mVisible = visible;
797 reportVisibility();
798 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -0700799 }
800
801 void reportVisibility() {
Dianne Hackborn284ac932009-08-28 10:34:25 -0700802 if (!mDestroyed) {
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -0700803 boolean visible = mVisible && mScreenOn;
804 if (mReportedVisible != visible) {
805 mReportedVisible = visible;
806 if (DEBUG) Log.v(TAG, "onVisibilityChanged(" + visible
807 + "): " + this);
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700808 if (visible) {
809 // If becoming visible, in preview mode the surface
810 // may have been destroyed so now we need to make
811 // sure it is re-created.
Dianne Hackborn9e4e7272011-08-30 14:06:51 -0700812 doOffsetsChanged(false);
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700813 updateSurface(false, false, false);
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700814 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -0700815 onVisibilityChanged(visible);
816 }
Dianne Hackborn284ac932009-08-28 10:34:25 -0700817 }
818 }
819
Dianne Hackborn9e4e7272011-08-30 14:06:51 -0700820 void doOffsetsChanged(boolean always) {
Dianne Hackborn284ac932009-08-28 10:34:25 -0700821 if (mDestroyed) {
822 return;
823 }
Dianne Hackborn9e4e7272011-08-30 14:06:51 -0700824
825 if (!always && !mOffsetsChanged) {
826 return;
827 }
828
Dianne Hackborn284ac932009-08-28 10:34:25 -0700829 float xOffset;
830 float yOffset;
Marco Nelissenbf6956b2009-11-09 15:21:13 -0800831 float xOffsetStep;
832 float yOffsetStep;
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700833 boolean sync;
Dianne Hackborn284ac932009-08-28 10:34:25 -0700834 synchronized (mLock) {
835 xOffset = mPendingXOffset;
836 yOffset = mPendingYOffset;
Marco Nelissenbf6956b2009-11-09 15:21:13 -0800837 xOffsetStep = mPendingXOffsetStep;
838 yOffsetStep = mPendingYOffsetStep;
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700839 sync = mPendingSync;
840 mPendingSync = false;
Dianne Hackborn284ac932009-08-28 10:34:25 -0700841 mOffsetMessageEnqueued = false;
842 }
Dianne Hackborn9e4e7272011-08-30 14:06:51 -0700843
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700844 if (mSurfaceCreated) {
Dianne Hackborn9e4e7272011-08-30 14:06:51 -0700845 if (mReportedVisible) {
846 if (DEBUG) Log.v(TAG, "Offsets change in " + this
847 + ": " + xOffset + "," + yOffset);
848 final int availw = mIWallpaperEngine.mReqWidth-mCurWidth;
849 final int xPixels = availw > 0 ? -(int)(availw*xOffset+.5f) : 0;
850 final int availh = mIWallpaperEngine.mReqHeight-mCurHeight;
851 final int yPixels = availh > 0 ? -(int)(availh*yOffset+.5f) : 0;
852 onOffsetsChanged(xOffset, yOffset, xOffsetStep, yOffsetStep, xPixels, yPixels);
853 } else {
854 mOffsetsChanged = true;
855 }
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700856 }
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700857
858 if (sync) {
859 try {
860 if (DEBUG) Log.v(TAG, "Reporting offsets change complete");
861 mSession.wallpaperOffsetsComplete(mWindow.asBinder());
862 } catch (RemoteException e) {
863 }
864 }
Dianne Hackborn284ac932009-08-28 10:34:25 -0700865 }
866
Dianne Hackborn75804932009-10-20 20:15:20 -0700867 void doCommand(WallpaperCommand cmd) {
868 Bundle result;
869 if (!mDestroyed) {
870 result = onCommand(cmd.action, cmd.x, cmd.y, cmd.z,
871 cmd.extras, cmd.sync);
872 } else {
873 result = null;
874 }
875 if (cmd.sync) {
876 try {
877 if (DEBUG) Log.v(TAG, "Reporting command complete");
878 mSession.wallpaperCommandComplete(mWindow.asBinder(), result);
879 } catch (RemoteException e) {
880 }
881 }
882 }
883
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700884 void reportSurfaceDestroyed() {
885 if (mSurfaceCreated) {
886 mSurfaceCreated = false;
Dianne Hackborndc8a7f62010-05-10 11:29:34 -0700887 mSurfaceHolder.ungetCallbacks();
888 SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
889 if (callbacks != null) {
890 for (SurfaceHolder.Callback c : callbacks) {
891 c.surfaceDestroyed(mSurfaceHolder);
892 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700893 }
Dianne Hackborn284ac932009-08-28 10:34:25 -0700894 if (DEBUG) Log.v(TAG, "onSurfaceDestroyed("
895 + mSurfaceHolder + "): " + this);
896 onSurfaceDestroyed(mSurfaceHolder);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700897 }
Dianne Hackborn18ee31e2010-04-27 15:54:02 -0700898 }
899
900 void detach() {
901 if (mDestroyed) {
902 return;
903 }
904
905 mDestroyed = true;
906
907 if (mVisible) {
908 mVisible = false;
909 if (DEBUG) Log.v(TAG, "onVisibilityChanged(false): " + this);
910 onVisibilityChanged(false);
911 }
912
913 reportSurfaceDestroyed();
Dianne Hackborn284ac932009-08-28 10:34:25 -0700914
915 if (DEBUG) Log.v(TAG, "onDestroy(): " + this);
916 onDestroy();
917
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -0700918 unregisterReceiver(mReceiver);
919
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700920 if (mCreated) {
921 try {
Dianne Hackbornba3e31d2010-04-22 18:59:03 -0700922 if (DEBUG) Log.v(TAG, "Removing window and destroying surface "
923 + mSurfaceHolder.getSurface() + " of: " + this);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700924
Jeff Brown32cbc38552011-12-01 14:01:49 -0800925 if (mInputEventReceiver != null) {
926 mInputEventReceiver.dispose();
927 mInputEventReceiver = null;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700928 }
929
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700930 mSession.remove(mWindow);
931 } catch (RemoteException e) {
932 }
Dianne Hackborn0586a1b2009-09-06 21:08:27 -0700933 mSurfaceHolder.mSurface.release();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700934 mCreated = false;
Jeff Brown349703e2010-06-22 01:27:15 -0700935
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700936 // Dispose the input channel after removing the window so the Window Manager
937 // doesn't interpret the input channel being closed as an abnormal termination.
938 if (mInputChannel != null) {
939 mInputChannel.dispose();
940 mInputChannel = null;
Jeff Brown349703e2010-06-22 01:27:15 -0700941 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700942 }
943 }
944 }
945
946 class IWallpaperEngineWrapper extends IWallpaperEngine.Stub
947 implements HandlerCaller.Callback {
948 private final HandlerCaller mCaller;
949
950 final IWallpaperConnection mConnection;
951 final IBinder mWindowToken;
Dianne Hackborn3be63c02009-08-20 19:31:38 -0700952 final int mWindowType;
953 final boolean mIsPreview;
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -0700954 boolean mShownReported;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700955 int mReqWidth;
956 int mReqHeight;
957
958 Engine mEngine;
959
960 IWallpaperEngineWrapper(WallpaperService context,
961 IWallpaperConnection conn, IBinder windowToken,
Dianne Hackborn3be63c02009-08-20 19:31:38 -0700962 int windowType, boolean isPreview, int reqWidth, int reqHeight) {
Mita Yunaa8dc2e2012-12-10 18:32:03 -0800963 mCaller = new HandlerCaller(context, context.getMainLooper(), this, true);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700964 mConnection = conn;
965 mWindowToken = windowToken;
Dianne Hackborn3be63c02009-08-20 19:31:38 -0700966 mWindowType = windowType;
967 mIsPreview = isPreview;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700968 mReqWidth = reqWidth;
969 mReqHeight = reqHeight;
970
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700971 Message msg = mCaller.obtainMessage(DO_ATTACH);
972 mCaller.sendMessage(msg);
973 }
974
Dianne Hackborn284ac932009-08-28 10:34:25 -0700975 public void setDesiredSize(int width, int height) {
976 Message msg = mCaller.obtainMessageII(DO_SET_DESIRED_SIZE, width, height);
977 mCaller.sendMessage(msg);
978 }
979
980 public void setVisibility(boolean visible) {
981 Message msg = mCaller.obtainMessageI(MSG_VISIBILITY_CHANGED,
982 visible ? 1 : 0);
983 mCaller.sendMessage(msg);
984 }
985
Dianne Hackborn6adba242009-11-10 11:10:09 -0800986 public void dispatchPointer(MotionEvent event) {
987 if (mEngine != null) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700988 mEngine.dispatchPointer(event);
Jeff Brown32cbc38552011-12-01 14:01:49 -0800989 } else {
990 event.recycle();
Dianne Hackborn6adba242009-11-10 11:10:09 -0800991 }
992 }
Jeff Brown9f3bdfe2010-10-13 06:01:27 -0700993
994 public void dispatchWallpaperCommand(String action, int x, int y,
995 int z, Bundle extras) {
996 if (mEngine != null) {
997 mEngine.mWindow.dispatchWallpaperCommand(action, x, y, z, extras, false);
998 }
999 }
1000
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -07001001 public void reportShown() {
1002 if (!mShownReported) {
1003 mShownReported = true;
1004 try {
1005 mConnection.engineShown(this);
1006 } catch (RemoteException e) {
1007 Log.w(TAG, "Wallpaper host disappeared", e);
1008 return;
1009 }
1010 }
1011 }
1012
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001013 public void destroy() {
1014 Message msg = mCaller.obtainMessage(DO_DETACH);
1015 mCaller.sendMessage(msg);
1016 }
1017
1018 public void executeMessage(Message message) {
1019 switch (message.what) {
1020 case DO_ATTACH: {
Dianne Hackborn284ac932009-08-28 10:34:25 -07001021 try {
1022 mConnection.attachEngine(this);
1023 } catch (RemoteException e) {
1024 Log.w(TAG, "Wallpaper host disappeared", e);
1025 return;
1026 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001027 Engine engine = onCreateEngine();
1028 mEngine = engine;
Dianne Hackbornaf1f42b2009-11-20 16:27:27 -08001029 mActiveEngines.add(engine);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001030 engine.attach(this);
1031 return;
1032 }
1033 case DO_DETACH: {
Dianne Hackbornaf1f42b2009-11-20 16:27:27 -08001034 mActiveEngines.remove(mEngine);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001035 mEngine.detach();
1036 return;
1037 }
Dianne Hackborn284ac932009-08-28 10:34:25 -07001038 case DO_SET_DESIRED_SIZE: {
1039 mEngine.doDesiredSizeChanged(message.arg1, message.arg2);
1040 return;
1041 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001042 case MSG_UPDATE_SURFACE:
Dianne Hackbornd76b67c2010-07-13 17:48:30 -07001043 mEngine.updateSurface(true, false, false);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001044 break;
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001045 case MSG_VISIBILITY_CHANGED:
1046 if (DEBUG) Log.v(TAG, "Visibility change in " + mEngine
1047 + ": " + message.arg1);
Dianne Hackborn284ac932009-08-28 10:34:25 -07001048 mEngine.doVisibilityChanged(message.arg1 != 0);
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001049 break;
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001050 case MSG_WALLPAPER_OFFSETS: {
Dianne Hackborn9e4e7272011-08-30 14:06:51 -07001051 mEngine.doOffsetsChanged(true);
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001052 } break;
Dianne Hackborn75804932009-10-20 20:15:20 -07001053 case MSG_WALLPAPER_COMMAND: {
1054 WallpaperCommand cmd = (WallpaperCommand)message.obj;
1055 mEngine.doCommand(cmd);
1056 } break;
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001057 case MSG_WINDOW_RESIZED: {
1058 final boolean reportDraw = message.arg1 != 0;
Dianne Hackbornd76b67c2010-07-13 17:48:30 -07001059 mEngine.updateSurface(true, false, reportDraw);
Dianne Hackborn9e4e7272011-08-30 14:06:51 -07001060 mEngine.doOffsetsChanged(true);
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001061 } break;
Craig Mautner5702d4d2012-06-30 14:10:16 -07001062 case MSG_WINDOW_MOVED: {
1063 // Do nothing. What does it mean for a Wallpaper to move?
1064 } break;
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07001065 case MSG_TOUCH_EVENT: {
Jeff Brown840db1f2010-10-21 17:36:54 -07001066 boolean skip = false;
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07001067 MotionEvent ev = (MotionEvent)message.obj;
Jeff Brown840db1f2010-10-21 17:36:54 -07001068 if (ev.getAction() == MotionEvent.ACTION_MOVE) {
1069 synchronized (mEngine.mLock) {
1070 if (mEngine.mPendingMove == ev) {
1071 mEngine.mPendingMove = null;
1072 } else {
1073 // this is not the motion event we are looking for....
1074 skip = true;
1075 }
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07001076 }
1077 }
Jeff Brown840db1f2010-10-21 17:36:54 -07001078 if (!skip) {
1079 if (DEBUG) Log.v(TAG, "Delivering touch event: " + ev);
1080 mEngine.onTouchEvent(ev);
1081 }
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07001082 ev.recycle();
1083 } break;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001084 default :
1085 Log.w(TAG, "Unknown message type " + message.what);
1086 }
1087 }
1088 }
1089
1090 /**
1091 * Implements the internal {@link IWallpaperService} interface to convert
1092 * incoming calls to it back to calls on an {@link WallpaperService}.
1093 */
1094 class IWallpaperServiceWrapper extends IWallpaperService.Stub {
1095 private final WallpaperService mTarget;
1096
1097 public IWallpaperServiceWrapper(WallpaperService context) {
1098 mTarget = context;
1099 }
1100
Craig Mautnerb1ef3692012-11-16 17:31:04 -08001101 @Override
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001102 public void attach(IWallpaperConnection conn, IBinder windowToken,
1103 int windowType, boolean isPreview, int reqWidth, int reqHeight) {
1104 new IWallpaperEngineWrapper(mTarget, conn, windowToken,
1105 windowType, isPreview, reqWidth, reqHeight);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001106 }
1107 }
Craig Mautnerb1ef3692012-11-16 17:31:04 -08001108
Dianne Hackbornaf1f42b2009-11-20 16:27:27 -08001109 @Override
1110 public void onCreate() {
1111 super.onCreate();
1112 }
1113
1114 @Override
1115 public void onDestroy() {
1116 super.onDestroy();
1117 for (int i=0; i<mActiveEngines.size(); i++) {
1118 mActiveEngines.get(i).detach();
1119 }
1120 mActiveEngines.clear();
1121 }
1122
Dianne Hackborn8cc6a502009-08-05 21:29:42 -07001123 /**
1124 * Implement to return the implementation of the internal accessibility
1125 * service interface. Subclasses should not override.
1126 */
1127 @Override
1128 public final IBinder onBind(Intent intent) {
1129 return new IWallpaperServiceWrapper(this);
1130 }
Craig Mautnerb1ef3692012-11-16 17:31:04 -08001131
Dianne Hackborn23ef7b42009-11-18 18:20:39 -08001132 /**
1133 * Must be implemented to return a new instance of the wallpaper's engine.
1134 * Note that multiple instances may be active at the same time, such as
1135 * when the wallpaper is currently set as the active wallpaper and the user
1136 * is in the wallpaper picker viewing a preview of it as well.
1137 */
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001138 public abstract Engine onCreateEngine();
Dianne Hackborn527de8e2011-08-22 16:10:36 -07001139
1140 @Override
1141 protected void dump(FileDescriptor fd, PrintWriter out, String[] args) {
1142 out.print("State of wallpaper "); out.print(this); out.println(":");
1143 for (int i=0; i<mActiveEngines.size(); i++) {
1144 Engine engine = mActiveEngines.get(i);
1145 out.print(" Engine "); out.print(engine); out.println(":");
1146 engine.dump(" ", fd, out, args);
1147 }
1148 }
Dianne Hackborn8cc6a502009-08-05 21:29:42 -07001149}