blob: 4225913844c9bfe5be090802fa8915c25c557766 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2008 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 com.android.server;
18
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080019import static android.os.ParcelFileDescriptor.*;
Christopher Tate111bd4a2009-06-24 17:29:38 -070020
Dianne Hackborn5dc5a002012-09-15 19:33:48 -070021import android.app.ActivityManagerNative;
Amith Yamasani4e2820c2012-08-28 22:17:23 -070022import android.app.AppGlobals;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -070023import android.app.IUserSwitchObserver;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070024import android.app.IWallpaperManager;
25import android.app.IWallpaperManagerCallback;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070026import android.app.PendingIntent;
Dianne Hackborneb034652009-09-07 00:49:58 -070027import android.app.WallpaperInfo;
Christopher Tate45281862010-03-05 15:46:30 -080028import android.app.backup.BackupManager;
Amith Yamasani37ce3a82012-02-06 12:04:42 -080029import android.app.backup.WallpaperBackupHelper;
Amith Yamasani13593602012-03-22 16:16:17 -070030import android.content.BroadcastReceiver;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070031import android.content.ComponentName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.content.Context;
33import android.content.Intent;
Amith Yamasani13593602012-03-22 16:16:17 -070034import android.content.IntentFilter;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070035import android.content.ServiceConnection;
Amith Yamasani4e2820c2012-08-28 22:17:23 -070036import android.content.pm.IPackageManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037import android.content.pm.PackageManager;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070038import android.content.pm.ResolveInfo;
39import android.content.pm.ServiceInfo;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070040import android.content.pm.PackageManager.NameNotFoundException;
41import android.content.res.Resources;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042import android.os.Binder;
Dianne Hackborn284ac932009-08-28 10:34:25 -070043import android.os.Bundle;
Amith Yamasani13593602012-03-22 16:16:17 -070044import android.os.Environment;
Dianne Hackborn8bdf5932010-10-15 12:54:40 -070045import android.os.FileUtils;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070046import android.os.IBinder;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -070047import android.os.IRemoteCallback;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048import android.os.RemoteException;
49import android.os.FileObserver;
50import android.os.ParcelFileDescriptor;
51import android.os.RemoteCallbackList;
rpcraig554cb0c2012-07-05 06:41:43 -040052import android.os.SELinux;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070053import android.os.ServiceManager;
Dianne Hackborn0cd48872009-08-13 18:51:59 -070054import android.os.SystemClock;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070055import android.os.UserHandle;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070056import android.service.wallpaper.IWallpaperConnection;
57import android.service.wallpaper.IWallpaperEngine;
58import android.service.wallpaper.IWallpaperService;
59import android.service.wallpaper.WallpaperService;
Joe Onorato8a9b2202010-02-26 18:56:32 -080060import android.util.Slog;
Amith Yamasani37ce3a82012-02-06 12:04:42 -080061import android.util.SparseArray;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070062import android.util.Xml;
Dianne Hackborn44bc17c2011-04-20 18:18:51 -070063import android.view.Display;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070064import android.view.IWindowManager;
65import android.view.WindowManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066
Dianne Hackborneb034652009-09-07 00:49:58 -070067import java.io.FileDescriptor;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070068import java.io.IOException;
69import java.io.InputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070import java.io.File;
71import java.io.FileNotFoundException;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070072import java.io.FileInputStream;
73import java.io.FileOutputStream;
Dianne Hackborneb034652009-09-07 00:49:58 -070074import java.io.PrintWriter;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070075import java.util.List;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070076
77import org.xmlpull.v1.XmlPullParser;
78import org.xmlpull.v1.XmlPullParserException;
79import org.xmlpull.v1.XmlSerializer;
80
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080081import com.android.internal.content.PackageMonitor;
Dianne Hackborn2269d1572010-02-24 19:54:22 -080082import com.android.internal.util.FastXmlSerializer;
Dianne Hackborn1afd1c92010-03-18 22:47:17 -070083import com.android.internal.util.JournaledFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070085class WallpaperManagerService extends IWallpaperManager.Stub {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070086 static final String TAG = "WallpaperService";
Dianne Hackborncbf15042009-08-18 18:29:09 -070087 static final boolean DEBUG = false;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070088
Romain Guy407ec782011-08-24 17:06:58 -070089 final Object mLock = new Object[0];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090
Dianne Hackborn0cd48872009-08-13 18:51:59 -070091 /**
92 * Minimum time between crashes of a wallpaper service for us to consider
93 * restarting it vs. just reverting to the static wallpaper.
94 */
95 static final long MIN_WALLPAPER_CRASH_TIME = 10000;
Dianne Hackborn0cd48872009-08-13 18:51:59 -070096 static final String WALLPAPER = "wallpaper";
Amith Yamasani37ce3a82012-02-06 12:04:42 -080097 static final String WALLPAPER_INFO = "wallpaper_info.xml";
Joe Onorato9bb8fd72009-07-28 18:24:51 -070098
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099 /**
100 * Observes the wallpaper for changes and notifies all IWallpaperServiceCallbacks
101 * that the wallpaper has changed. The CREATE is triggered when there is no
102 * wallpaper set and is created for the first time. The CLOSE_WRITE is triggered
103 * everytime the wallpaper is changed.
104 */
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800105 private class WallpaperObserver extends FileObserver {
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700106
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800107 final WallpaperData mWallpaper;
108 final File mWallpaperDir;
109 final File mWallpaperFile;
110
111 public WallpaperObserver(WallpaperData wallpaper) {
112 super(getWallpaperDir(wallpaper.userId).getAbsolutePath(),
113 CLOSE_WRITE | DELETE | DELETE_SELF);
114 mWallpaperDir = getWallpaperDir(wallpaper.userId);
115 mWallpaper = wallpaper;
116 mWallpaperFile = new File(mWallpaperDir, WALLPAPER);
117 }
118
119 @Override
120 public void onEvent(int event, String path) {
121 if (path == null) {
122 return;
123 }
124 synchronized (mLock) {
125 // changing the wallpaper means we'll need to back up the new one
126 long origId = Binder.clearCallingIdentity();
127 BackupManager bm = new BackupManager(mContext);
128 bm.dataChanged();
129 Binder.restoreCallingIdentity(origId);
130
131 File changedFile = new File(mWallpaperDir, path);
132 if (mWallpaperFile.equals(changedFile)) {
133 notifyCallbacksLocked(mWallpaper);
134 if (mWallpaper.wallpaperComponent == null || event != CLOSE_WRITE
135 || mWallpaper.imageWallpaperPending) {
136 if (event == CLOSE_WRITE) {
137 mWallpaper.imageWallpaperPending = false;
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700138 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800139 bindWallpaperComponentLocked(mWallpaper.imageWallpaperComponent, true,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700140 false, mWallpaper, null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800141 saveSettingsLocked(mWallpaper);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800142 }
143 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800144 }
145 }
146 }
147
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700148 final Context mContext;
149 final IWindowManager mIWindowManager;
Amith Yamasani4e2820c2012-08-28 22:17:23 -0700150 final IPackageManager mIPackageManager;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800151 final MyPackageMonitor mMonitor;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800152 WallpaperData mLastWallpaper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800153
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800154 SparseArray<WallpaperData> mWallpaperMap = new SparseArray<WallpaperData>();
Dianne Hackborn07213e62011-08-24 20:05:39 -0700155
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800156 int mCurrentUserId;
Dianne Hackborn07213e62011-08-24 20:05:39 -0700157
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800158 static class WallpaperData {
159
160 int userId;
161
162 File wallpaperFile;
163
164 /**
165 * Client is currently writing a new image wallpaper.
166 */
167 boolean imageWallpaperPending;
168
169 /**
170 * Resource name if using a picture from the wallpaper gallery
171 */
172 String name = "";
173
174 /**
175 * The component name of the currently set live wallpaper.
176 */
177 ComponentName wallpaperComponent;
178
179 /**
180 * The component name of the wallpaper that should be set next.
181 */
182 ComponentName nextWallpaperComponent;
183
184 /**
185 * Name of the component used to display bitmap wallpapers from either the gallery or
186 * built-in wallpapers.
187 */
188 ComponentName imageWallpaperComponent = new ComponentName("com.android.systemui",
189 "com.android.systemui.ImageWallpaper");
190
191 WallpaperConnection connection;
192 long lastDiedTime;
193 boolean wallpaperUpdating;
194 WallpaperObserver wallpaperObserver;
195
196 /**
197 * List of callbacks registered they should each be notified when the wallpaper is changed.
198 */
199 private RemoteCallbackList<IWallpaperManagerCallback> callbacks
200 = new RemoteCallbackList<IWallpaperManagerCallback>();
201
202 int width = -1;
203 int height = -1;
204
205 WallpaperData(int userId) {
206 this.userId = userId;
207 wallpaperFile = new File(getWallpaperDir(userId), WALLPAPER);
208 }
209 }
210
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700211 class WallpaperConnection extends IWallpaperConnection.Stub
212 implements ServiceConnection {
Dianne Hackborneb034652009-09-07 00:49:58 -0700213 final WallpaperInfo mInfo;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700214 final Binder mToken = new Binder();
215 IWallpaperService mService;
216 IWallpaperEngine mEngine;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800217 WallpaperData mWallpaper;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700218 IRemoteCallback mReply;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800219
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800220 public WallpaperConnection(WallpaperInfo info, WallpaperData wallpaper) {
Dianne Hackborneb034652009-09-07 00:49:58 -0700221 mInfo = info;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800222 mWallpaper = wallpaper;
Dianne Hackborneb034652009-09-07 00:49:58 -0700223 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700224
225 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700226 public void onServiceConnected(ComponentName name, IBinder service) {
227 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800228 if (mWallpaper.connection == this) {
229 mWallpaper.lastDiedTime = SystemClock.uptimeMillis();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700230 mService = IWallpaperService.Stub.asInterface(service);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800231 attachServiceLocked(this, mWallpaper);
Dianne Hackborneb034652009-09-07 00:49:58 -0700232 // XXX should probably do saveSettingsLocked() later
233 // when we have an engine, but I'm not sure about
234 // locking there and anyway we always need to be able to
235 // recover if there is something wrong.
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800236 saveSettingsLocked(mWallpaper);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700237 }
238 }
239 }
240
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700241 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700242 public void onServiceDisconnected(ComponentName name) {
243 synchronized (mLock) {
244 mService = null;
245 mEngine = null;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800246 if (mWallpaper.connection == this) {
247 Slog.w(TAG, "Wallpaper service gone: " + mWallpaper.wallpaperComponent);
248 if (!mWallpaper.wallpaperUpdating
249 && (mWallpaper.lastDiedTime + MIN_WALLPAPER_CRASH_TIME)
250 > SystemClock.uptimeMillis()
251 && mWallpaper.userId == mCurrentUserId) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800252 Slog.w(TAG, "Reverting to built-in wallpaper!");
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700253 clearWallpaperLocked(true, mWallpaper.userId, null);
Dianne Hackborn0cd48872009-08-13 18:51:59 -0700254 }
255 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700256 }
257 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800258
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700259 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700260 public void attachEngine(IWallpaperEngine engine) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700261 synchronized (mLock) {
262 mEngine = engine;
263 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700264 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800265
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700266 @Override
267 public void engineShown(IWallpaperEngine engine) {
268 synchronized (mLock) {
269 if (mReply != null) {
270 long ident = Binder.clearCallingIdentity();
271 try {
272 mReply.sendResult(null);
273 } catch (RemoteException e) {
274 Binder.restoreCallingIdentity(ident);
275 }
276 mReply = null;
277 }
278 }
279 }
280
281 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700282 public ParcelFileDescriptor setWallpaper(String name) {
283 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800284 if (mWallpaper.connection == this) {
285 return updateWallpaperBitmapLocked(name, mWallpaper);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700286 }
287 return null;
288 }
289 }
290 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800291
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800292 class MyPackageMonitor extends PackageMonitor {
293 @Override
294 public void onPackageUpdateFinished(String packageName, int uid) {
295 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700296 if (mCurrentUserId != getChangingUserId()) {
297 return;
298 }
299 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
300 if (wallpaper != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800301 if (wallpaper.wallpaperComponent != null
302 && wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
303 wallpaper.wallpaperUpdating = false;
304 ComponentName comp = wallpaper.wallpaperComponent;
305 clearWallpaperComponentLocked(wallpaper);
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700306 if (!bindWallpaperComponentLocked(comp, false, false,
307 wallpaper, null)) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800308 Slog.w(TAG, "Wallpaper no longer available; reverting to default");
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700309 clearWallpaperLocked(false, wallpaper.userId, null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800310 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700311 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800312 }
313 }
314 }
315
316 @Override
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700317 public void onPackageModified(String packageName) {
318 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700319 if (mCurrentUserId != getChangingUserId()) {
320 return;
321 }
322 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
323 if (wallpaper != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800324 if (wallpaper.wallpaperComponent == null
325 || !wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700326 return;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800327 }
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700328 doPackagesChangedLocked(true, wallpaper);
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700329 }
330 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700331 }
332
333 @Override
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800334 public void onPackageUpdateStarted(String packageName, int uid) {
335 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700336 if (mCurrentUserId != getChangingUserId()) {
337 return;
338 }
339 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
340 if (wallpaper != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800341 if (wallpaper.wallpaperComponent != null
342 && wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
343 wallpaper.wallpaperUpdating = true;
344 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800345 }
346 }
347 }
348
349 @Override
350 public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700351 synchronized (mLock) {
352 boolean changed = false;
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700353 if (mCurrentUserId != getChangingUserId()) {
354 return false;
355 }
356 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
357 if (wallpaper != null) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700358 boolean res = doPackagesChangedLocked(doit, wallpaper);
359 changed |= res;
360 }
361 return changed;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800362 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800363 }
364
365 @Override
366 public void onSomePackagesChanged() {
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700367 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700368 if (mCurrentUserId != getChangingUserId()) {
369 return;
370 }
371 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
372 if (wallpaper != null) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700373 doPackagesChangedLocked(true, wallpaper);
374 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800375 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800376 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800377
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700378 boolean doPackagesChangedLocked(boolean doit, WallpaperData wallpaper) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800379 boolean changed = false;
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700380 if (wallpaper.wallpaperComponent != null) {
381 int change = isPackageDisappearing(wallpaper.wallpaperComponent
382 .getPackageName());
383 if (change == PACKAGE_PERMANENT_CHANGE
384 || change == PACKAGE_TEMPORARY_CHANGE) {
385 changed = true;
386 if (doit) {
387 Slog.w(TAG, "Wallpaper uninstalled, removing: "
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800388 + wallpaper.wallpaperComponent);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700389 clearWallpaperLocked(false, wallpaper.userId, null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800390 }
391 }
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700392 }
393 if (wallpaper.nextWallpaperComponent != null) {
394 int change = isPackageDisappearing(wallpaper.nextWallpaperComponent
395 .getPackageName());
396 if (change == PACKAGE_PERMANENT_CHANGE
397 || change == PACKAGE_TEMPORARY_CHANGE) {
398 wallpaper.nextWallpaperComponent = null;
399 }
400 }
401 if (wallpaper.wallpaperComponent != null
402 && isPackageModified(wallpaper.wallpaperComponent.getPackageName())) {
403 try {
404 mContext.getPackageManager().getServiceInfo(
405 wallpaper.wallpaperComponent, 0);
406 } catch (NameNotFoundException e) {
407 Slog.w(TAG, "Wallpaper component gone, removing: "
408 + wallpaper.wallpaperComponent);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700409 clearWallpaperLocked(false, wallpaper.userId, null);
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700410 }
411 }
412 if (wallpaper.nextWallpaperComponent != null
413 && isPackageModified(wallpaper.nextWallpaperComponent.getPackageName())) {
414 try {
415 mContext.getPackageManager().getServiceInfo(
416 wallpaper.nextWallpaperComponent, 0);
417 } catch (NameNotFoundException e) {
418 wallpaper.nextWallpaperComponent = null;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800419 }
420 }
421 return changed;
422 }
423 }
424
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700425 public WallpaperManagerService(Context context) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800426 if (DEBUG) Slog.v(TAG, "WallpaperService startup");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800427 mContext = context;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700428 mIWindowManager = IWindowManager.Stub.asInterface(
429 ServiceManager.getService(Context.WINDOW_SERVICE));
Amith Yamasani4e2820c2012-08-28 22:17:23 -0700430 mIPackageManager = AppGlobals.getPackageManager();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800431 mMonitor = new MyPackageMonitor();
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700432 mMonitor.register(context, null, UserHandle.ALL, true);
Amith Yamasani61f57372012-08-31 12:12:28 -0700433 getWallpaperDir(UserHandle.USER_OWNER).mkdirs();
434 loadSettingsLocked(UserHandle.USER_OWNER);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800435 }
436
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800437 private static File getWallpaperDir(int userId) {
Amith Yamasani61f57372012-08-31 12:12:28 -0700438 return Environment.getUserSystemDirectory(userId);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800439 }
440
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800441 @Override
442 protected void finalize() throws Throwable {
443 super.finalize();
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800444 for (int i = 0; i < mWallpaperMap.size(); i++) {
445 WallpaperData wallpaper = mWallpaperMap.valueAt(i);
446 wallpaper.wallpaperObserver.stopWatching();
447 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800448 }
Amith Yamasani13593602012-03-22 16:16:17 -0700449
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700450 public void systemReady() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800451 if (DEBUG) Slog.v(TAG, "systemReady");
Amith Yamasani61f57372012-08-31 12:12:28 -0700452 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.USER_OWNER);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700453 switchWallpaper(wallpaper, null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800454 wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper);
455 wallpaper.wallpaperObserver.startWatching();
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800456
Amith Yamasani13593602012-03-22 16:16:17 -0700457 IntentFilter userFilter = new IntentFilter();
Amith Yamasani13593602012-03-22 16:16:17 -0700458 userFilter.addAction(Intent.ACTION_USER_REMOVED);
459 mContext.registerReceiver(new BroadcastReceiver() {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800460 @Override
Amith Yamasani13593602012-03-22 16:16:17 -0700461 public void onReceive(Context context, Intent intent) {
462 String action = intent.getAction();
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700463 if (Intent.ACTION_USER_REMOVED.equals(action)) {
Amith Yamasani2a003292012-08-14 18:25:45 -0700464 removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
Amith Yamasani13593602012-03-22 16:16:17 -0700465 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800466 }
Amith Yamasani13593602012-03-22 16:16:17 -0700467 }, userFilter);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700468 try {
469 ActivityManagerNative.getDefault().registerUserSwitchObserver(
470 new IUserSwitchObserver.Stub() {
471 @Override
472 public void onUserSwitching(int newUserId, IRemoteCallback reply) {
473 switchUser(newUserId, reply);
474 }
475
476 @Override
477 public void onUserSwitchComplete(int newUserId) throws RemoteException {
478 }
479 });
480 } catch (RemoteException e) {
481 // TODO Auto-generated catch block
482 e.printStackTrace();
483 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800484 }
485
486 String getName() {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700487 synchronized (mLock) {
488 return mWallpaperMap.get(0).name;
489 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800490 }
491
Amith Yamasani13593602012-03-22 16:16:17 -0700492 void removeUser(int userId) {
493 synchronized (mLock) {
494 WallpaperData wallpaper = mWallpaperMap.get(userId);
495 if (wallpaper != null) {
496 wallpaper.wallpaperObserver.stopWatching();
497 mWallpaperMap.remove(userId);
498 }
499 File wallpaperFile = new File(getWallpaperDir(userId), WALLPAPER);
500 wallpaperFile.delete();
501 File wallpaperInfoFile = new File(getWallpaperDir(userId), WALLPAPER_INFO);
502 wallpaperInfoFile.delete();
503 }
504 }
505
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700506 void switchUser(int userId, IRemoteCallback reply) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800507 synchronized (mLock) {
508 mCurrentUserId = userId;
509 WallpaperData wallpaper = mWallpaperMap.get(userId);
510 if (wallpaper == null) {
511 wallpaper = new WallpaperData(userId);
512 mWallpaperMap.put(userId, wallpaper);
513 loadSettingsLocked(userId);
514 wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper);
515 wallpaper.wallpaperObserver.startWatching();
516 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700517 switchWallpaper(wallpaper, reply);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800518 }
519 }
520
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700521 void switchWallpaper(WallpaperData wallpaper, IRemoteCallback reply) {
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700522 synchronized (mLock) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700523 RuntimeException e = null;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700524 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800525 ComponentName cname = wallpaper.wallpaperComponent != null ?
526 wallpaper.wallpaperComponent : wallpaper.nextWallpaperComponent;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700527 if (bindWallpaperComponentLocked(cname, true, false, wallpaper, reply)) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700528 return;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700529 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700530 } catch (RuntimeException e1) {
531 e = e1;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700532 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700533 Slog.w(TAG, "Failure starting previous wallpaper", e);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700534 clearWallpaperLocked(false, wallpaper.userId, reply);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800535 }
536 }
537
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800538 public void clearWallpaper() {
539 if (DEBUG) Slog.v(TAG, "clearWallpaper");
540 synchronized (mLock) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700541 clearWallpaperLocked(false, UserHandle.getCallingUserId(), null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800542 }
543 }
544
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700545 void clearWallpaperLocked(boolean defaultFailed, int userId, IRemoteCallback reply) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800546 WallpaperData wallpaper = mWallpaperMap.get(userId);
547 File f = new File(getWallpaperDir(userId), WALLPAPER);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800548 if (f.exists()) {
549 f.delete();
550 }
551 final long ident = Binder.clearCallingIdentity();
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700552 RuntimeException e = null;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800553 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800554 wallpaper.imageWallpaperPending = false;
555 if (userId != mCurrentUserId) return;
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700556 if (bindWallpaperComponentLocked(defaultFailed
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800557 ? wallpaper.imageWallpaperComponent
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700558 : null, true, false, wallpaper, reply)) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700559 return;
560 }
561 } catch (IllegalArgumentException e1) {
562 e = e1;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800563 } finally {
564 Binder.restoreCallingIdentity(ident);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800565 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700566
567 // This can happen if the default wallpaper component doesn't
568 // exist. This should be a system configuration problem, but
569 // let's not let it crash the system and just live with no
570 // wallpaper.
571 Slog.e(TAG, "Default wallpaper component not found!", e);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800572 clearWallpaperComponentLocked(wallpaper);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700573 if (reply != null) {
574 try {
575 reply.sendResult(null);
576 } catch (RemoteException e1) {
577 }
578 }
579 }
580
581 public boolean hasNamedWallpaper(String name) {
582 synchronized (mLock) {
583 for (int i=0; i<mWallpaperMap.size(); i++) {
584 WallpaperData wd = mWallpaperMap.valueAt(i);
585 if (name.equals(wd.name)) {
586 return true;
587 }
588 }
589 }
590 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800591 }
592
593 public void setDimensionHints(int width, int height) throws RemoteException {
594 checkPermission(android.Manifest.permission.SET_WALLPAPER_HINTS);
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700595 synchronized (mLock) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700596 int userId = UserHandle.getCallingUserId();
597 WallpaperData wallpaper = mWallpaperMap.get(userId);
598 if (wallpaper == null) {
599 throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
600 }
601 if (width <= 0 || height <= 0) {
602 throw new IllegalArgumentException("width and height must be > 0");
603 }
604
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800605 if (width != wallpaper.width || height != wallpaper.height) {
606 wallpaper.width = width;
607 wallpaper.height = height;
608 saveSettingsLocked(wallpaper);
609 if (mCurrentUserId != userId) return; // Don't change the properties now
610 if (wallpaper.connection != null) {
611 if (wallpaper.connection.mEngine != null) {
Dianne Hackborn284ac932009-08-28 10:34:25 -0700612 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800613 wallpaper.connection.mEngine.setDesiredSize(
Dianne Hackborn284ac932009-08-28 10:34:25 -0700614 width, height);
615 } catch (RemoteException e) {
616 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800617 notifyCallbacksLocked(wallpaper);
Dianne Hackborn284ac932009-08-28 10:34:25 -0700618 }
619 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700620 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800621 }
622 }
623
624 public int getWidthHint() throws RemoteException {
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700625 synchronized (mLock) {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700626 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.getCallingUserId());
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800627 return wallpaper.width;
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700628 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800629 }
630
631 public int getHeightHint() throws RemoteException {
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700632 synchronized (mLock) {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700633 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.getCallingUserId());
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800634 return wallpaper.height;
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700635 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800636 }
637
Dianne Hackborn284ac932009-08-28 10:34:25 -0700638 public ParcelFileDescriptor getWallpaper(IWallpaperManagerCallback cb,
639 Bundle outParams) {
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700640 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800641 // This returns the current user's wallpaper, if called by a system service. Else it
642 // returns the wallpaper for the calling user.
643 int callingUid = Binder.getCallingUid();
644 int wallpaperUserId = 0;
645 if (callingUid == android.os.Process.SYSTEM_UID) {
646 wallpaperUserId = mCurrentUserId;
647 } else {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700648 wallpaperUserId = UserHandle.getUserId(callingUid);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800649 }
650 WallpaperData wallpaper = mWallpaperMap.get(wallpaperUserId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700651 try {
Dianne Hackborn284ac932009-08-28 10:34:25 -0700652 if (outParams != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800653 outParams.putInt("width", wallpaper.width);
654 outParams.putInt("height", wallpaper.height);
Dianne Hackborn284ac932009-08-28 10:34:25 -0700655 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800656 wallpaper.callbacks.register(cb);
657 File f = new File(getWallpaperDir(wallpaperUserId), WALLPAPER);
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700658 if (!f.exists()) {
659 return null;
660 }
661 return ParcelFileDescriptor.open(f, MODE_READ_ONLY);
662 } catch (FileNotFoundException e) {
663 /* Shouldn't happen as we check to see if the file exists */
Joe Onorato8a9b2202010-02-26 18:56:32 -0800664 Slog.w(TAG, "Error getting wallpaper", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800665 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700666 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800667 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800668 }
669
Dianne Hackborneb034652009-09-07 00:49:58 -0700670 public WallpaperInfo getWallpaperInfo() {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700671 int userId = UserHandle.getCallingUserId();
Dianne Hackborneb034652009-09-07 00:49:58 -0700672 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800673 WallpaperData wallpaper = mWallpaperMap.get(userId);
674 if (wallpaper.connection != null) {
675 return wallpaper.connection.mInfo;
Dianne Hackborneb034652009-09-07 00:49:58 -0700676 }
677 return null;
678 }
679 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800680
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700681 public ParcelFileDescriptor setWallpaper(String name) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800682 checkPermission(android.Manifest.permission.SET_WALLPAPER);
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700683 synchronized (mLock) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700684 if (DEBUG) Slog.v(TAG, "setWallpaper");
685 int userId = UserHandle.getCallingUserId();
686 WallpaperData wallpaper = mWallpaperMap.get(userId);
687 if (wallpaper == null) {
688 throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
689 }
Dianne Hackborn0cd48872009-08-13 18:51:59 -0700690 final long ident = Binder.clearCallingIdentity();
691 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800692 ParcelFileDescriptor pfd = updateWallpaperBitmapLocked(name, wallpaper);
Dianne Hackborn0cd48872009-08-13 18:51:59 -0700693 if (pfd != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800694 wallpaper.imageWallpaperPending = true;
Dianne Hackborn0cd48872009-08-13 18:51:59 -0700695 }
696 return pfd;
697 } finally {
698 Binder.restoreCallingIdentity(ident);
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700699 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800700 }
701 }
702
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800703 ParcelFileDescriptor updateWallpaperBitmapLocked(String name, WallpaperData wallpaper) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700704 if (name == null) name = "";
705 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800706 File dir = getWallpaperDir(wallpaper.userId);
707 if (!dir.exists()) {
708 dir.mkdir();
Dianne Hackbornebac48c2011-11-29 18:01:50 -0800709 FileUtils.setPermissions(
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800710 dir.getPath(),
Dianne Hackbornebac48c2011-11-29 18:01:50 -0800711 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
712 -1, -1);
713 }
rpcraig554cb0c2012-07-05 06:41:43 -0400714 File file = new File(dir, WALLPAPER);
715 ParcelFileDescriptor fd = ParcelFileDescriptor.open(file,
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700716 MODE_CREATE|MODE_READ_WRITE);
rpcraig554cb0c2012-07-05 06:41:43 -0400717 if (!SELinux.restorecon(file)) {
718 return null;
719 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800720 wallpaper.name = name;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700721 return fd;
722 } catch (FileNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800723 Slog.w(TAG, "Error setting wallpaper", e);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700724 }
725 return null;
726 }
727
728 public void setWallpaperComponent(ComponentName name) {
729 checkPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT);
730 synchronized (mLock) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700731 if (DEBUG) Slog.v(TAG, "setWallpaperComponent name=" + name);
732 int userId = UserHandle.getCallingUserId();
733 WallpaperData wallpaper = mWallpaperMap.get(userId);
734 if (wallpaper == null) {
735 throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
736 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700737 final long ident = Binder.clearCallingIdentity();
738 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800739 wallpaper.imageWallpaperPending = false;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700740 bindWallpaperComponentLocked(name, false, true, wallpaper, null);
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700741 } finally {
742 Binder.restoreCallingIdentity(ident);
743 }
744 }
745 }
746
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800747 boolean bindWallpaperComponentLocked(ComponentName componentName, boolean force,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700748 boolean fromUser, WallpaperData wallpaper, IRemoteCallback reply) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800749 if (DEBUG) Slog.v(TAG, "bindWallpaperComponentLocked: componentName=" + componentName);
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700750 // Has the component changed?
Dianne Hackborn9ea31632011-08-05 14:43:50 -0700751 if (!force) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800752 if (wallpaper.connection != null) {
753 if (wallpaper.wallpaperComponent == null) {
Dianne Hackborn9ea31632011-08-05 14:43:50 -0700754 if (componentName == null) {
755 if (DEBUG) Slog.v(TAG, "bindWallpaperComponentLocked: still using default");
756 // Still using default wallpaper.
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700757 return true;
Dianne Hackborn9ea31632011-08-05 14:43:50 -0700758 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800759 } else if (wallpaper.wallpaperComponent.equals(componentName)) {
Dianne Hackborn9ea31632011-08-05 14:43:50 -0700760 // Changing to same wallpaper.
761 if (DEBUG) Slog.v(TAG, "same wallpaper");
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700762 return true;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700763 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700764 }
765 }
766
767 try {
Mike Clerona428b2c2009-11-15 22:53:08 -0800768 if (componentName == null) {
Mike Cleron322b6ee2009-11-12 07:45:47 -0800769 String defaultComponent =
770 mContext.getString(com.android.internal.R.string.default_wallpaper_component);
Mike Clerona428b2c2009-11-15 22:53:08 -0800771 if (defaultComponent != null) {
Mike Cleron322b6ee2009-11-12 07:45:47 -0800772 // See if there is a default wallpaper component specified
Mike Clerona428b2c2009-11-15 22:53:08 -0800773 componentName = ComponentName.unflattenFromString(defaultComponent);
Joe Onorato8a9b2202010-02-26 18:56:32 -0800774 if (DEBUG) Slog.v(TAG, "Use default component wallpaper:" + componentName);
Mike Cleron322b6ee2009-11-12 07:45:47 -0800775 }
Mike Clerona428b2c2009-11-15 22:53:08 -0800776 if (componentName == null) {
Mike Cleron322b6ee2009-11-12 07:45:47 -0800777 // Fall back to static image wallpaper
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800778 componentName = wallpaper.imageWallpaperComponent;
Mike Cleron322b6ee2009-11-12 07:45:47 -0800779 //clearWallpaperComponentLocked();
780 //return;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800781 if (DEBUG) Slog.v(TAG, "Using image wallpaper");
Mike Cleron322b6ee2009-11-12 07:45:47 -0800782 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700783 }
Amith Yamasani4e2820c2012-08-28 22:17:23 -0700784 int serviceUserId = wallpaper.userId;
785 ServiceInfo si = mIPackageManager.getServiceInfo(componentName,
786 PackageManager.GET_META_DATA | PackageManager.GET_PERMISSIONS, serviceUserId);
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700787 if (!android.Manifest.permission.BIND_WALLPAPER.equals(si.permission)) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700788 String msg = "Selected service does not require "
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700789 + android.Manifest.permission.BIND_WALLPAPER
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700790 + ": " + componentName;
791 if (fromUser) {
792 throw new SecurityException(msg);
793 }
794 Slog.w(TAG, msg);
795 return false;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700796 }
797
Dianne Hackborneb034652009-09-07 00:49:58 -0700798 WallpaperInfo wi = null;
799
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700800 Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800801 if (componentName != null && !componentName.equals(wallpaper.imageWallpaperComponent)) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700802 // Make sure the selected service is actually a wallpaper service.
Amith Yamasani4e2820c2012-08-28 22:17:23 -0700803 List<ResolveInfo> ris =
804 mIPackageManager.queryIntentServices(intent,
805 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
806 PackageManager.GET_META_DATA, serviceUserId);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700807 for (int i=0; i<ris.size(); i++) {
808 ServiceInfo rsi = ris.get(i).serviceInfo;
809 if (rsi.name.equals(si.name) &&
810 rsi.packageName.equals(si.packageName)) {
Dianne Hackborneb034652009-09-07 00:49:58 -0700811 try {
812 wi = new WallpaperInfo(mContext, ris.get(i));
813 } catch (XmlPullParserException e) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700814 if (fromUser) {
815 throw new IllegalArgumentException(e);
816 }
817 Slog.w(TAG, e);
818 return false;
Dianne Hackborneb034652009-09-07 00:49:58 -0700819 } catch (IOException e) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700820 if (fromUser) {
821 throw new IllegalArgumentException(e);
822 }
823 Slog.w(TAG, e);
824 return false;
Dianne Hackborneb034652009-09-07 00:49:58 -0700825 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700826 break;
827 }
828 }
Dianne Hackborneb034652009-09-07 00:49:58 -0700829 if (wi == null) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700830 String msg = "Selected service is not a wallpaper: "
831 + componentName;
832 if (fromUser) {
833 throw new SecurityException(msg);
834 }
835 Slog.w(TAG, msg);
836 return false;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700837 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700838 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700839
840 // Bind the service!
Joe Onorato8a9b2202010-02-26 18:56:32 -0800841 if (DEBUG) Slog.v(TAG, "Binding to:" + componentName);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800842 WallpaperConnection newConn = new WallpaperConnection(wi, wallpaper);
Mike Clerona428b2c2009-11-15 22:53:08 -0800843 intent.setComponent(componentName);
Dianne Hackborndd9b82c2009-09-03 00:18:47 -0700844 intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
845 com.android.internal.R.string.wallpaper_binding_label);
Dianne Hackborn41203752012-08-31 14:05:51 -0700846 intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivityAsUser(
Dianne Hackborneb034652009-09-07 00:49:58 -0700847 mContext, 0,
848 Intent.createChooser(new Intent(Intent.ACTION_SET_WALLPAPER),
849 mContext.getText(com.android.internal.R.string.chooser_wallpaper)),
Dianne Hackborn41203752012-08-31 14:05:51 -0700850 0, null, new UserHandle(serviceUserId)));
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800851 if (!mContext.bindService(intent, newConn, Context.BIND_AUTO_CREATE, serviceUserId)) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700852 String msg = "Unable to bind service: "
853 + componentName;
854 if (fromUser) {
855 throw new IllegalArgumentException(msg);
856 }
857 Slog.w(TAG, msg);
858 return false;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700859 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800860 if (wallpaper.userId == mCurrentUserId && mLastWallpaper != null) {
861 detachWallpaperLocked(mLastWallpaper);
862 }
863 wallpaper.wallpaperComponent = componentName;
864 wallpaper.connection = newConn;
865 wallpaper.lastDiedTime = SystemClock.uptimeMillis();
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700866 newConn.mReply = reply;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700867 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800868 if (wallpaper.userId == mCurrentUserId) {
869 if (DEBUG)
870 Slog.v(TAG, "Adding window token: " + newConn.mToken);
871 mIWindowManager.addWindowToken(newConn.mToken,
872 WindowManager.LayoutParams.TYPE_WALLPAPER);
873 mLastWallpaper = wallpaper;
874 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700875 } catch (RemoteException e) {
876 }
Amith Yamasani4e2820c2012-08-28 22:17:23 -0700877 } catch (RemoteException e) {
878 String msg = "Remote exception for " + componentName + "\n" + e;
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700879 if (fromUser) {
880 throw new IllegalArgumentException(msg);
881 }
882 Slog.w(TAG, msg);
883 return false;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700884 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700885 return true;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700886 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800887
888 void detachWallpaperLocked(WallpaperData wallpaper) {
889 if (wallpaper.connection != null) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700890 if (wallpaper.connection.mReply != null) {
891 try {
892 wallpaper.connection.mReply.sendResult(null);
893 } catch (RemoteException e) {
894 }
895 wallpaper.connection.mReply = null;
896 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800897 if (wallpaper.connection.mEngine != null) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700898 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800899 wallpaper.connection.mEngine.destroy();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700900 } catch (RemoteException e) {
901 }
902 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800903 mContext.unbindService(wallpaper.connection);
Dianne Hackborne9e9bca2009-08-18 15:08:22 -0700904 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800905 if (DEBUG)
906 Slog.v(TAG, "Removing window token: " + wallpaper.connection.mToken);
907 mIWindowManager.removeWindowToken(wallpaper.connection.mToken);
Dianne Hackborne9e9bca2009-08-18 15:08:22 -0700908 } catch (RemoteException e) {
909 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800910 wallpaper.connection.mService = null;
911 wallpaper.connection.mEngine = null;
912 wallpaper.connection = null;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700913 }
914 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800915
916 void clearWallpaperComponentLocked(WallpaperData wallpaper) {
917 wallpaper.wallpaperComponent = null;
918 detachWallpaperLocked(wallpaper);
919 }
920
921 void attachServiceLocked(WallpaperConnection conn, WallpaperData wallpaper) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700922 try {
Dianne Hackborn3be63c02009-08-20 19:31:38 -0700923 conn.mService.attach(conn, conn.mToken,
924 WindowManager.LayoutParams.TYPE_WALLPAPER, false,
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800925 wallpaper.width, wallpaper.height);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700926 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800927 Slog.w(TAG, "Failed attaching wallpaper; clearing", e);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800928 if (!wallpaper.wallpaperUpdating) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700929 bindWallpaperComponentLocked(null, false, false, wallpaper, null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800930 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700931 }
932 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800933
934 private void notifyCallbacksLocked(WallpaperData wallpaper) {
935 final int n = wallpaper.callbacks.beginBroadcast();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800936 for (int i = 0; i < n; i++) {
937 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800938 wallpaper.callbacks.getBroadcastItem(i).onWallpaperChanged();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800939 } catch (RemoteException e) {
940
941 // The RemoteCallbackList will take care of removing
942 // the dead object for us.
943 }
944 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800945 wallpaper.callbacks.finishBroadcast();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800946 final Intent intent = new Intent(Intent.ACTION_WALLPAPER_CHANGED);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -0700947 mContext.sendBroadcastAsUser(intent, new UserHandle(mCurrentUserId));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800948 }
949
950 private void checkPermission(String permission) {
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700951 if (PackageManager.PERMISSION_GRANTED!= mContext.checkCallingOrSelfPermission(permission)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800952 throw new SecurityException("Access denied to process: " + Binder.getCallingPid()
953 + ", must have permission " + permission);
954 }
955 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700956
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800957 private static JournaledFile makeJournaledFile(int userId) {
Amith Yamasani61f57372012-08-31 12:12:28 -0700958 final String base = new File(getWallpaperDir(userId), WALLPAPER_INFO).getAbsolutePath();
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700959 return new JournaledFile(new File(base), new File(base + ".tmp"));
960 }
961
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800962 private void saveSettingsLocked(WallpaperData wallpaper) {
963 JournaledFile journal = makeJournaledFile(wallpaper.userId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700964 FileOutputStream stream = null;
965 try {
966 stream = new FileOutputStream(journal.chooseForWrite(), false);
967 XmlSerializer out = new FastXmlSerializer();
968 out.setOutput(stream, "utf-8");
969 out.startDocument(null, true);
970
971 out.startTag(null, "wp");
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800972 out.attribute(null, "width", Integer.toString(wallpaper.width));
973 out.attribute(null, "height", Integer.toString(wallpaper.height));
974 out.attribute(null, "name", wallpaper.name);
975 if (wallpaper.wallpaperComponent != null
976 && !wallpaper.wallpaperComponent.equals(wallpaper.imageWallpaperComponent)) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700977 out.attribute(null, "component",
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800978 wallpaper.wallpaperComponent.flattenToShortString());
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700979 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700980 out.endTag(null, "wp");
981
982 out.endDocument();
983 stream.close();
984 journal.commit();
985 } catch (IOException e) {
986 try {
987 if (stream != null) {
988 stream.close();
989 }
990 } catch (IOException ex) {
991 // Ignore
992 }
993 journal.rollback();
994 }
995 }
996
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800997 private void migrateFromOld() {
998 File oldWallpaper = new File(WallpaperBackupHelper.WALLPAPER_IMAGE_KEY);
999 File oldInfo = new File(WallpaperBackupHelper.WALLPAPER_INFO_KEY);
1000 if (oldWallpaper.exists()) {
1001 File newWallpaper = new File(getWallpaperDir(0), WALLPAPER);
1002 oldWallpaper.renameTo(newWallpaper);
1003 }
1004 if (oldInfo.exists()) {
1005 File newInfo = new File(getWallpaperDir(0), WALLPAPER_INFO);
1006 oldInfo.renameTo(newInfo);
1007 }
1008 }
1009
1010 private void loadSettingsLocked(int userId) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001011 if (DEBUG) Slog.v(TAG, "loadSettingsLocked");
Mike Clerona428b2c2009-11-15 22:53:08 -08001012
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001013 JournaledFile journal = makeJournaledFile(userId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001014 FileInputStream stream = null;
1015 File file = journal.chooseForRead();
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001016 if (!file.exists()) {
1017 // This should only happen one time, when upgrading from a legacy system
1018 migrateFromOld();
1019 }
1020 WallpaperData wallpaper = mWallpaperMap.get(userId);
1021 if (wallpaper == null) {
1022 wallpaper = new WallpaperData(userId);
1023 mWallpaperMap.put(userId, wallpaper);
1024 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001025 boolean success = false;
1026 try {
1027 stream = new FileInputStream(file);
1028 XmlPullParser parser = Xml.newPullParser();
1029 parser.setInput(stream, null);
1030
1031 int type;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001032 do {
1033 type = parser.next();
1034 if (type == XmlPullParser.START_TAG) {
1035 String tag = parser.getName();
1036 if ("wp".equals(tag)) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001037 wallpaper.width = Integer.parseInt(parser.getAttributeValue(null, "width"));
1038 wallpaper.height = Integer.parseInt(parser
1039 .getAttributeValue(null, "height"));
1040 wallpaper.name = parser.getAttributeValue(null, "name");
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001041 String comp = parser.getAttributeValue(null, "component");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001042 wallpaper.nextWallpaperComponent = comp != null
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001043 ? ComponentName.unflattenFromString(comp)
1044 : null;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001045 if (wallpaper.nextWallpaperComponent == null
1046 || "android".equals(wallpaper.nextWallpaperComponent
1047 .getPackageName())) {
1048 wallpaper.nextWallpaperComponent = wallpaper.imageWallpaperComponent;
Dianne Hackborn9ea31632011-08-05 14:43:50 -07001049 }
Mike Clerona428b2c2009-11-15 22:53:08 -08001050
1051 if (DEBUG) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001052 Slog.v(TAG, "mWidth:" + wallpaper.width);
1053 Slog.v(TAG, "mHeight:" + wallpaper.height);
1054 Slog.v(TAG, "mName:" + wallpaper.name);
1055 Slog.v(TAG, "mNextWallpaperComponent:"
1056 + wallpaper.nextWallpaperComponent);
Mike Clerona428b2c2009-11-15 22:53:08 -08001057 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001058 }
1059 }
1060 } while (type != XmlPullParser.END_DOCUMENT);
1061 success = true;
1062 } catch (NullPointerException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001063 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001064 } catch (NumberFormatException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001065 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001066 } catch (XmlPullParserException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001067 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001068 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001069 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001070 } catch (IndexOutOfBoundsException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001071 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001072 }
1073 try {
1074 if (stream != null) {
1075 stream.close();
1076 }
1077 } catch (IOException e) {
1078 // Ignore
1079 }
1080
1081 if (!success) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001082 wallpaper.width = -1;
1083 wallpaper.height = -1;
1084 wallpaper.name = "";
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001085 }
Dianne Hackborn44bc17c2011-04-20 18:18:51 -07001086
1087 // We always want to have some reasonable width hint.
1088 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
1089 Display d = wm.getDefaultDisplay();
1090 int baseSize = d.getMaximumSizeDimension();
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001091 if (wallpaper.width < baseSize) {
1092 wallpaper.width = baseSize;
Dianne Hackborn44bc17c2011-04-20 18:18:51 -07001093 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001094 if (wallpaper.height < baseSize) {
1095 wallpaper.height = baseSize;
Dianne Hackborn44bc17c2011-04-20 18:18:51 -07001096 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001097 }
1098
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07001099 // Called by SystemBackupAgent after files are restored to disk.
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001100 void settingsRestored() {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001101 // TODO: If necessary, make it work for secondary users as well. This currently assumes
1102 // restores only to the primary user
Joe Onorato8a9b2202010-02-26 18:56:32 -08001103 if (DEBUG) Slog.v(TAG, "settingsRestored");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001104 WallpaperData wallpaper = null;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001105 boolean success = false;
1106 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001107 loadSettingsLocked(0);
1108 wallpaper = mWallpaperMap.get(0);
1109 if (wallpaper.nextWallpaperComponent != null
1110 && !wallpaper.nextWallpaperComponent.equals(wallpaper.imageWallpaperComponent)) {
1111 if (!bindWallpaperComponentLocked(wallpaper.nextWallpaperComponent, false, false,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001112 wallpaper, null)) {
Christopher Tatee3ab4d02009-12-16 14:03:31 -08001113 // No such live wallpaper or other failure; fall back to the default
1114 // live wallpaper (since the profile being restored indicated that the
1115 // user had selected a live rather than static one).
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001116 bindWallpaperComponentLocked(null, false, false, wallpaper, null);
Christopher Tatee3ab4d02009-12-16 14:03:31 -08001117 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001118 success = true;
1119 } else {
Mike Clerona428b2c2009-11-15 22:53:08 -08001120 // If there's a wallpaper name, we use that. If that can't be loaded, then we
1121 // use the default.
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001122 if ("".equals(wallpaper.name)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001123 if (DEBUG) Slog.v(TAG, "settingsRestored: name is empty");
Mike Clerona428b2c2009-11-15 22:53:08 -08001124 success = true;
1125 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001126 if (DEBUG) Slog.v(TAG, "settingsRestored: attempting to restore named resource");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001127 success = restoreNamedResourceLocked(wallpaper);
Mike Clerona428b2c2009-11-15 22:53:08 -08001128 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08001129 if (DEBUG) Slog.v(TAG, "settingsRestored: success=" + success);
Mike Clerona428b2c2009-11-15 22:53:08 -08001130 if (success) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001131 bindWallpaperComponentLocked(wallpaper.nextWallpaperComponent, false, false,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001132 wallpaper, null);
Mike Clerona428b2c2009-11-15 22:53:08 -08001133 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001134 }
1135 }
1136
1137 if (!success) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001138 Slog.e(TAG, "Failed to restore wallpaper: '" + wallpaper.name + "'");
1139 wallpaper.name = "";
1140 getWallpaperDir(0).delete();
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001141 }
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07001142
1143 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001144 saveSettingsLocked(wallpaper);
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07001145 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001146 }
1147
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001148 boolean restoreNamedResourceLocked(WallpaperData wallpaper) {
1149 if (wallpaper.name.length() > 4 && "res:".equals(wallpaper.name.substring(0, 4))) {
1150 String resName = wallpaper.name.substring(4);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001151
1152 String pkg = null;
1153 int colon = resName.indexOf(':');
1154 if (colon > 0) {
1155 pkg = resName.substring(0, colon);
1156 }
1157
1158 String ident = null;
1159 int slash = resName.lastIndexOf('/');
1160 if (slash > 0) {
1161 ident = resName.substring(slash+1);
1162 }
1163
1164 String type = null;
1165 if (colon > 0 && slash > 0 && (slash-colon) > 1) {
1166 type = resName.substring(colon+1, slash);
1167 }
1168
1169 if (pkg != null && ident != null && type != null) {
1170 int resId = -1;
1171 InputStream res = null;
1172 FileOutputStream fos = null;
1173 try {
1174 Context c = mContext.createPackageContext(pkg, Context.CONTEXT_RESTRICTED);
1175 Resources r = c.getResources();
1176 resId = r.getIdentifier(resName, null, null);
1177 if (resId == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001178 Slog.e(TAG, "couldn't resolve identifier pkg=" + pkg + " type=" + type
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001179 + " ident=" + ident);
1180 return false;
1181 }
1182
1183 res = r.openRawResource(resId);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001184 if (wallpaper.wallpaperFile.exists()) {
1185 wallpaper.wallpaperFile.delete();
Dianne Hackborn1afd1c92010-03-18 22:47:17 -07001186 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001187 fos = new FileOutputStream(wallpaper.wallpaperFile);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001188
1189 byte[] buffer = new byte[32768];
1190 int amt;
1191 while ((amt=res.read(buffer)) > 0) {
1192 fos.write(buffer, 0, amt);
1193 }
1194 // mWallpaperObserver will notice the close and send the change broadcast
1195
Joe Onorato8a9b2202010-02-26 18:56:32 -08001196 Slog.v(TAG, "Restored wallpaper: " + resName);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001197 return true;
1198 } catch (NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001199 Slog.e(TAG, "Package name " + pkg + " not found");
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001200 } catch (Resources.NotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001201 Slog.e(TAG, "Resource not found: " + resId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001202 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001203 Slog.e(TAG, "IOException while restoring wallpaper ", e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001204 } finally {
1205 if (res != null) {
1206 try {
1207 res.close();
1208 } catch (IOException ex) {}
1209 }
1210 if (fos != null) {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07001211 FileUtils.sync(fos);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001212 try {
1213 fos.close();
1214 } catch (IOException ex) {}
1215 }
1216 }
1217 }
1218 }
1219 return false;
1220 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001221
Dianne Hackborneb034652009-09-07 00:49:58 -07001222 @Override
1223 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1224 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
1225 != PackageManager.PERMISSION_GRANTED) {
1226
1227 pw.println("Permission Denial: can't dump wallpaper service from from pid="
1228 + Binder.getCallingPid()
1229 + ", uid=" + Binder.getCallingUid());
1230 return;
1231 }
1232
1233 synchronized (mLock) {
1234 pw.println("Current Wallpaper Service state:");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001235 for (int i = 0; i < mWallpaperMap.size(); i++) {
1236 WallpaperData wallpaper = mWallpaperMap.valueAt(i);
1237 pw.println(" User " + wallpaper.userId + ":");
1238 pw.print(" mWidth=");
1239 pw.print(wallpaper.width);
1240 pw.print(" mHeight=");
1241 pw.println(wallpaper.height);
1242 pw.print(" mName=");
1243 pw.println(wallpaper.name);
1244 pw.print(" mWallpaperComponent=");
1245 pw.println(wallpaper.wallpaperComponent);
1246 if (wallpaper.connection != null) {
1247 WallpaperConnection conn = wallpaper.connection;
1248 pw.print(" Wallpaper connection ");
1249 pw.print(conn);
1250 pw.println(":");
1251 if (conn.mInfo != null) {
1252 pw.print(" mInfo.component=");
1253 pw.println(conn.mInfo.getComponent());
1254 }
1255 pw.print(" mToken=");
1256 pw.println(conn.mToken);
1257 pw.print(" mService=");
1258 pw.println(conn.mService);
1259 pw.print(" mEngine=");
1260 pw.println(conn.mEngine);
1261 pw.print(" mLastDiedTime=");
1262 pw.println(wallpaper.lastDiedTime - SystemClock.uptimeMillis());
1263 }
Dianne Hackborneb034652009-09-07 00:49:58 -07001264 }
1265 }
1266 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001267}