blob: e0f3814c4b22da92862116cf52b329014a687e67 [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;
Amith Yamasani6474c4c2012-10-04 14:55:42 -070041import android.content.pm.UserInfo;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070042import android.content.res.Resources;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043import android.os.Binder;
Dianne Hackborn284ac932009-08-28 10:34:25 -070044import android.os.Bundle;
Amith Yamasani13593602012-03-22 16:16:17 -070045import android.os.Environment;
Dianne Hackborn8bdf5932010-10-15 12:54:40 -070046import android.os.FileUtils;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070047import android.os.IBinder;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -070048import android.os.IRemoteCallback;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049import android.os.RemoteException;
50import android.os.FileObserver;
51import android.os.ParcelFileDescriptor;
52import android.os.RemoteCallbackList;
rpcraig554cb0c2012-07-05 06:41:43 -040053import android.os.SELinux;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070054import android.os.ServiceManager;
Dianne Hackborn0cd48872009-08-13 18:51:59 -070055import android.os.SystemClock;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070056import android.os.UserHandle;
Amith Yamasani6474c4c2012-10-04 14:55:42 -070057import android.os.UserManager;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070058import android.service.wallpaper.IWallpaperConnection;
59import android.service.wallpaper.IWallpaperEngine;
60import android.service.wallpaper.IWallpaperService;
61import android.service.wallpaper.WallpaperService;
Joe Onorato8a9b2202010-02-26 18:56:32 -080062import android.util.Slog;
Amith Yamasani37ce3a82012-02-06 12:04:42 -080063import android.util.SparseArray;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070064import android.util.Xml;
Dianne Hackborn44bc17c2011-04-20 18:18:51 -070065import android.view.Display;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070066import android.view.IWindowManager;
67import android.view.WindowManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080068
Dianne Hackborneb034652009-09-07 00:49:58 -070069import java.io.FileDescriptor;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070070import java.io.IOException;
71import java.io.InputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080072import java.io.File;
73import java.io.FileNotFoundException;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070074import java.io.FileInputStream;
75import java.io.FileOutputStream;
Dianne Hackborneb034652009-09-07 00:49:58 -070076import java.io.PrintWriter;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070077import java.util.List;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070078
79import org.xmlpull.v1.XmlPullParser;
80import org.xmlpull.v1.XmlPullParserException;
81import org.xmlpull.v1.XmlSerializer;
82
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080083import com.android.internal.content.PackageMonitor;
Dianne Hackborn2269d1572010-02-24 19:54:22 -080084import com.android.internal.util.FastXmlSerializer;
Dianne Hackborn1afd1c92010-03-18 22:47:17 -070085import com.android.internal.util.JournaledFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070087class WallpaperManagerService extends IWallpaperManager.Stub {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070088 static final String TAG = "WallpaperService";
Dianne Hackborncbf15042009-08-18 18:29:09 -070089 static final boolean DEBUG = false;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070090
Romain Guy407ec782011-08-24 17:06:58 -070091 final Object mLock = new Object[0];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092
Dianne Hackborn0cd48872009-08-13 18:51:59 -070093 /**
94 * Minimum time between crashes of a wallpaper service for us to consider
95 * restarting it vs. just reverting to the static wallpaper.
96 */
97 static final long MIN_WALLPAPER_CRASH_TIME = 10000;
Dianne Hackborn0cd48872009-08-13 18:51:59 -070098 static final String WALLPAPER = "wallpaper";
Amith Yamasani37ce3a82012-02-06 12:04:42 -080099 static final String WALLPAPER_INFO = "wallpaper_info.xml";
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700100
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101 /**
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -0700102 * Name of the component used to display bitmap wallpapers from either the gallery or
103 * built-in wallpapers.
104 */
105 static final ComponentName IMAGE_WALLPAPER = new ComponentName("com.android.systemui",
106 "com.android.systemui.ImageWallpaper");
107
108 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109 * Observes the wallpaper for changes and notifies all IWallpaperServiceCallbacks
110 * that the wallpaper has changed. The CREATE is triggered when there is no
111 * wallpaper set and is created for the first time. The CLOSE_WRITE is triggered
112 * everytime the wallpaper is changed.
113 */
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800114 private class WallpaperObserver extends FileObserver {
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700115
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800116 final WallpaperData mWallpaper;
117 final File mWallpaperDir;
118 final File mWallpaperFile;
119
120 public WallpaperObserver(WallpaperData wallpaper) {
121 super(getWallpaperDir(wallpaper.userId).getAbsolutePath(),
122 CLOSE_WRITE | DELETE | DELETE_SELF);
123 mWallpaperDir = getWallpaperDir(wallpaper.userId);
124 mWallpaper = wallpaper;
125 mWallpaperFile = new File(mWallpaperDir, WALLPAPER);
126 }
127
128 @Override
129 public void onEvent(int event, String path) {
130 if (path == null) {
131 return;
132 }
133 synchronized (mLock) {
134 // changing the wallpaper means we'll need to back up the new one
135 long origId = Binder.clearCallingIdentity();
136 BackupManager bm = new BackupManager(mContext);
137 bm.dataChanged();
138 Binder.restoreCallingIdentity(origId);
139
140 File changedFile = new File(mWallpaperDir, path);
141 if (mWallpaperFile.equals(changedFile)) {
142 notifyCallbacksLocked(mWallpaper);
143 if (mWallpaper.wallpaperComponent == null || event != CLOSE_WRITE
144 || mWallpaper.imageWallpaperPending) {
145 if (event == CLOSE_WRITE) {
146 mWallpaper.imageWallpaperPending = false;
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700147 }
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -0700148 bindWallpaperComponentLocked(IMAGE_WALLPAPER, true,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700149 false, mWallpaper, null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800150 saveSettingsLocked(mWallpaper);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800151 }
152 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800153 }
154 }
155 }
156
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700157 final Context mContext;
158 final IWindowManager mIWindowManager;
Amith Yamasani4e2820c2012-08-28 22:17:23 -0700159 final IPackageManager mIPackageManager;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800160 final MyPackageMonitor mMonitor;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800161 WallpaperData mLastWallpaper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800163 SparseArray<WallpaperData> mWallpaperMap = new SparseArray<WallpaperData>();
Dianne Hackborn07213e62011-08-24 20:05:39 -0700164
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800165 int mCurrentUserId;
Dianne Hackborn07213e62011-08-24 20:05:39 -0700166
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800167 static class WallpaperData {
168
169 int userId;
170
171 File wallpaperFile;
172
173 /**
174 * Client is currently writing a new image wallpaper.
175 */
176 boolean imageWallpaperPending;
177
178 /**
179 * Resource name if using a picture from the wallpaper gallery
180 */
181 String name = "";
182
183 /**
184 * The component name of the currently set live wallpaper.
185 */
186 ComponentName wallpaperComponent;
187
188 /**
189 * The component name of the wallpaper that should be set next.
190 */
191 ComponentName nextWallpaperComponent;
192
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800193 WallpaperConnection connection;
194 long lastDiedTime;
195 boolean wallpaperUpdating;
196 WallpaperObserver wallpaperObserver;
197
198 /**
199 * List of callbacks registered they should each be notified when the wallpaper is changed.
200 */
201 private RemoteCallbackList<IWallpaperManagerCallback> callbacks
202 = new RemoteCallbackList<IWallpaperManagerCallback>();
203
204 int width = -1;
205 int height = -1;
206
207 WallpaperData(int userId) {
208 this.userId = userId;
209 wallpaperFile = new File(getWallpaperDir(userId), WALLPAPER);
210 }
211 }
212
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700213 class WallpaperConnection extends IWallpaperConnection.Stub
214 implements ServiceConnection {
Dianne Hackborneb034652009-09-07 00:49:58 -0700215 final WallpaperInfo mInfo;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700216 final Binder mToken = new Binder();
217 IWallpaperService mService;
218 IWallpaperEngine mEngine;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800219 WallpaperData mWallpaper;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700220 IRemoteCallback mReply;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800221
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800222 public WallpaperConnection(WallpaperInfo info, WallpaperData wallpaper) {
Dianne Hackborneb034652009-09-07 00:49:58 -0700223 mInfo = info;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800224 mWallpaper = wallpaper;
Dianne Hackborneb034652009-09-07 00:49:58 -0700225 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700226
227 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700228 public void onServiceConnected(ComponentName name, IBinder service) {
229 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800230 if (mWallpaper.connection == this) {
231 mWallpaper.lastDiedTime = SystemClock.uptimeMillis();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700232 mService = IWallpaperService.Stub.asInterface(service);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800233 attachServiceLocked(this, mWallpaper);
Dianne Hackborneb034652009-09-07 00:49:58 -0700234 // XXX should probably do saveSettingsLocked() later
235 // when we have an engine, but I'm not sure about
236 // locking there and anyway we always need to be able to
237 // recover if there is something wrong.
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800238 saveSettingsLocked(mWallpaper);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700239 }
240 }
241 }
242
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700243 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700244 public void onServiceDisconnected(ComponentName name) {
245 synchronized (mLock) {
246 mService = null;
247 mEngine = null;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800248 if (mWallpaper.connection == this) {
249 Slog.w(TAG, "Wallpaper service gone: " + mWallpaper.wallpaperComponent);
250 if (!mWallpaper.wallpaperUpdating
251 && (mWallpaper.lastDiedTime + MIN_WALLPAPER_CRASH_TIME)
252 > SystemClock.uptimeMillis()
253 && mWallpaper.userId == mCurrentUserId) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800254 Slog.w(TAG, "Reverting to built-in wallpaper!");
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700255 clearWallpaperLocked(true, mWallpaper.userId, null);
Dianne Hackborn0cd48872009-08-13 18:51:59 -0700256 }
257 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700258 }
259 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800260
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700261 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700262 public void attachEngine(IWallpaperEngine engine) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700263 synchronized (mLock) {
264 mEngine = engine;
265 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700266 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800267
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700268 @Override
269 public void engineShown(IWallpaperEngine engine) {
270 synchronized (mLock) {
271 if (mReply != null) {
272 long ident = Binder.clearCallingIdentity();
273 try {
274 mReply.sendResult(null);
275 } catch (RemoteException e) {
276 Binder.restoreCallingIdentity(ident);
277 }
278 mReply = null;
279 }
280 }
281 }
282
283 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700284 public ParcelFileDescriptor setWallpaper(String name) {
285 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800286 if (mWallpaper.connection == this) {
287 return updateWallpaperBitmapLocked(name, mWallpaper);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700288 }
289 return null;
290 }
291 }
292 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800293
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800294 class MyPackageMonitor extends PackageMonitor {
295 @Override
296 public void onPackageUpdateFinished(String packageName, int uid) {
297 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700298 if (mCurrentUserId != getChangingUserId()) {
299 return;
300 }
301 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
302 if (wallpaper != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800303 if (wallpaper.wallpaperComponent != null
304 && wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
305 wallpaper.wallpaperUpdating = false;
306 ComponentName comp = wallpaper.wallpaperComponent;
307 clearWallpaperComponentLocked(wallpaper);
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700308 if (!bindWallpaperComponentLocked(comp, false, false,
309 wallpaper, null)) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800310 Slog.w(TAG, "Wallpaper no longer available; reverting to default");
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700311 clearWallpaperLocked(false, wallpaper.userId, null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800312 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700313 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800314 }
315 }
316 }
317
318 @Override
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700319 public void onPackageModified(String packageName) {
320 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700321 if (mCurrentUserId != getChangingUserId()) {
322 return;
323 }
324 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
325 if (wallpaper != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800326 if (wallpaper.wallpaperComponent == null
327 || !wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700328 return;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800329 }
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700330 doPackagesChangedLocked(true, wallpaper);
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700331 }
332 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700333 }
334
335 @Override
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800336 public void onPackageUpdateStarted(String packageName, int uid) {
337 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700338 if (mCurrentUserId != getChangingUserId()) {
339 return;
340 }
341 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
342 if (wallpaper != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800343 if (wallpaper.wallpaperComponent != null
344 && wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
345 wallpaper.wallpaperUpdating = true;
346 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800347 }
348 }
349 }
350
351 @Override
352 public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700353 synchronized (mLock) {
354 boolean changed = false;
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700355 if (mCurrentUserId != getChangingUserId()) {
356 return false;
357 }
358 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
359 if (wallpaper != null) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700360 boolean res = doPackagesChangedLocked(doit, wallpaper);
361 changed |= res;
362 }
363 return changed;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800364 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800365 }
366
367 @Override
368 public void onSomePackagesChanged() {
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700369 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700370 if (mCurrentUserId != getChangingUserId()) {
371 return;
372 }
373 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
374 if (wallpaper != null) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700375 doPackagesChangedLocked(true, wallpaper);
376 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800377 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800378 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800379
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700380 boolean doPackagesChangedLocked(boolean doit, WallpaperData wallpaper) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800381 boolean changed = false;
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700382 if (wallpaper.wallpaperComponent != null) {
383 int change = isPackageDisappearing(wallpaper.wallpaperComponent
384 .getPackageName());
385 if (change == PACKAGE_PERMANENT_CHANGE
386 || change == PACKAGE_TEMPORARY_CHANGE) {
387 changed = true;
388 if (doit) {
389 Slog.w(TAG, "Wallpaper uninstalled, removing: "
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800390 + wallpaper.wallpaperComponent);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700391 clearWallpaperLocked(false, wallpaper.userId, null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800392 }
393 }
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700394 }
395 if (wallpaper.nextWallpaperComponent != null) {
396 int change = isPackageDisappearing(wallpaper.nextWallpaperComponent
397 .getPackageName());
398 if (change == PACKAGE_PERMANENT_CHANGE
399 || change == PACKAGE_TEMPORARY_CHANGE) {
400 wallpaper.nextWallpaperComponent = null;
401 }
402 }
403 if (wallpaper.wallpaperComponent != null
404 && isPackageModified(wallpaper.wallpaperComponent.getPackageName())) {
405 try {
406 mContext.getPackageManager().getServiceInfo(
407 wallpaper.wallpaperComponent, 0);
408 } catch (NameNotFoundException e) {
409 Slog.w(TAG, "Wallpaper component gone, removing: "
410 + wallpaper.wallpaperComponent);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700411 clearWallpaperLocked(false, wallpaper.userId, null);
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700412 }
413 }
414 if (wallpaper.nextWallpaperComponent != null
415 && isPackageModified(wallpaper.nextWallpaperComponent.getPackageName())) {
416 try {
417 mContext.getPackageManager().getServiceInfo(
418 wallpaper.nextWallpaperComponent, 0);
419 } catch (NameNotFoundException e) {
420 wallpaper.nextWallpaperComponent = null;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800421 }
422 }
423 return changed;
424 }
425 }
426
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700427 public WallpaperManagerService(Context context) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800428 if (DEBUG) Slog.v(TAG, "WallpaperService startup");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800429 mContext = context;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700430 mIWindowManager = IWindowManager.Stub.asInterface(
431 ServiceManager.getService(Context.WINDOW_SERVICE));
Amith Yamasani4e2820c2012-08-28 22:17:23 -0700432 mIPackageManager = AppGlobals.getPackageManager();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800433 mMonitor = new MyPackageMonitor();
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700434 mMonitor.register(context, null, UserHandle.ALL, true);
Amith Yamasani61f57372012-08-31 12:12:28 -0700435 getWallpaperDir(UserHandle.USER_OWNER).mkdirs();
436 loadSettingsLocked(UserHandle.USER_OWNER);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800437 }
438
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800439 private static File getWallpaperDir(int userId) {
Amith Yamasani61f57372012-08-31 12:12:28 -0700440 return Environment.getUserSystemDirectory(userId);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800441 }
442
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800443 @Override
444 protected void finalize() throws Throwable {
445 super.finalize();
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800446 for (int i = 0; i < mWallpaperMap.size(); i++) {
447 WallpaperData wallpaper = mWallpaperMap.valueAt(i);
448 wallpaper.wallpaperObserver.stopWatching();
449 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800450 }
Amith Yamasani13593602012-03-22 16:16:17 -0700451
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700452 public void systemReady() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800453 if (DEBUG) Slog.v(TAG, "systemReady");
Amith Yamasani61f57372012-08-31 12:12:28 -0700454 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.USER_OWNER);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700455 switchWallpaper(wallpaper, null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800456 wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper);
457 wallpaper.wallpaperObserver.startWatching();
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800458
Amith Yamasani13593602012-03-22 16:16:17 -0700459 IntentFilter userFilter = new IntentFilter();
Amith Yamasani13593602012-03-22 16:16:17 -0700460 userFilter.addAction(Intent.ACTION_USER_REMOVED);
461 mContext.registerReceiver(new BroadcastReceiver() {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800462 @Override
Amith Yamasani13593602012-03-22 16:16:17 -0700463 public void onReceive(Context context, Intent intent) {
464 String action = intent.getAction();
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700465 if (Intent.ACTION_USER_REMOVED.equals(action)) {
Amith Yamasani2a003292012-08-14 18:25:45 -0700466 removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
Amith Yamasani13593602012-03-22 16:16:17 -0700467 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800468 }
Amith Yamasani13593602012-03-22 16:16:17 -0700469 }, userFilter);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700470 try {
471 ActivityManagerNative.getDefault().registerUserSwitchObserver(
472 new IUserSwitchObserver.Stub() {
473 @Override
474 public void onUserSwitching(int newUserId, IRemoteCallback reply) {
475 switchUser(newUserId, reply);
476 }
477
478 @Override
479 public void onUserSwitchComplete(int newUserId) throws RemoteException {
480 }
481 });
482 } catch (RemoteException e) {
483 // TODO Auto-generated catch block
484 e.printStackTrace();
485 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800486 }
487
488 String getName() {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700489 synchronized (mLock) {
490 return mWallpaperMap.get(0).name;
491 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800492 }
493
Amith Yamasani13593602012-03-22 16:16:17 -0700494 void removeUser(int userId) {
495 synchronized (mLock) {
496 WallpaperData wallpaper = mWallpaperMap.get(userId);
497 if (wallpaper != null) {
498 wallpaper.wallpaperObserver.stopWatching();
499 mWallpaperMap.remove(userId);
500 }
501 File wallpaperFile = new File(getWallpaperDir(userId), WALLPAPER);
502 wallpaperFile.delete();
503 File wallpaperInfoFile = new File(getWallpaperDir(userId), WALLPAPER_INFO);
504 wallpaperInfoFile.delete();
505 }
506 }
507
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700508 void switchUser(int userId, IRemoteCallback reply) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800509 synchronized (mLock) {
510 mCurrentUserId = userId;
511 WallpaperData wallpaper = mWallpaperMap.get(userId);
512 if (wallpaper == null) {
513 wallpaper = new WallpaperData(userId);
514 mWallpaperMap.put(userId, wallpaper);
515 loadSettingsLocked(userId);
Amith Yamasani6474c4c2012-10-04 14:55:42 -0700516 }
517 // Not started watching yet, in case wallpaper data was loaded for other reasons.
518 if (wallpaper.wallpaperObserver == null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800519 wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper);
520 wallpaper.wallpaperObserver.startWatching();
521 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700522 switchWallpaper(wallpaper, reply);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800523 }
524 }
525
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700526 void switchWallpaper(WallpaperData wallpaper, IRemoteCallback reply) {
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700527 synchronized (mLock) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700528 RuntimeException e = null;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700529 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800530 ComponentName cname = wallpaper.wallpaperComponent != null ?
531 wallpaper.wallpaperComponent : wallpaper.nextWallpaperComponent;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700532 if (bindWallpaperComponentLocked(cname, true, false, wallpaper, reply)) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700533 return;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700534 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700535 } catch (RuntimeException e1) {
536 e = e1;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700537 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700538 Slog.w(TAG, "Failure starting previous wallpaper", e);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700539 clearWallpaperLocked(false, wallpaper.userId, reply);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800540 }
541 }
542
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800543 public void clearWallpaper() {
544 if (DEBUG) Slog.v(TAG, "clearWallpaper");
545 synchronized (mLock) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700546 clearWallpaperLocked(false, UserHandle.getCallingUserId(), null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800547 }
548 }
549
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700550 void clearWallpaperLocked(boolean defaultFailed, int userId, IRemoteCallback reply) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800551 WallpaperData wallpaper = mWallpaperMap.get(userId);
552 File f = new File(getWallpaperDir(userId), WALLPAPER);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800553 if (f.exists()) {
554 f.delete();
555 }
556 final long ident = Binder.clearCallingIdentity();
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700557 RuntimeException e = null;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800558 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800559 wallpaper.imageWallpaperPending = false;
560 if (userId != mCurrentUserId) return;
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700561 if (bindWallpaperComponentLocked(defaultFailed
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -0700562 ? IMAGE_WALLPAPER
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700563 : null, true, false, wallpaper, reply)) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700564 return;
565 }
566 } catch (IllegalArgumentException e1) {
567 e = e1;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800568 } finally {
569 Binder.restoreCallingIdentity(ident);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800570 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700571
572 // This can happen if the default wallpaper component doesn't
573 // exist. This should be a system configuration problem, but
574 // let's not let it crash the system and just live with no
575 // wallpaper.
576 Slog.e(TAG, "Default wallpaper component not found!", e);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800577 clearWallpaperComponentLocked(wallpaper);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700578 if (reply != null) {
579 try {
580 reply.sendResult(null);
581 } catch (RemoteException e1) {
582 }
583 }
584 }
585
586 public boolean hasNamedWallpaper(String name) {
587 synchronized (mLock) {
Amith Yamasani6474c4c2012-10-04 14:55:42 -0700588 List<UserInfo> users;
589 long ident = Binder.clearCallingIdentity();
590 try {
591 users = ((UserManager) mContext.getSystemService(Context.USER_SERVICE)).getUsers();
592 } finally {
593 Binder.restoreCallingIdentity(ident);
594 }
595 for (UserInfo user: users) {
596 WallpaperData wd = mWallpaperMap.get(user.id);
597 if (wd == null) {
598 // User hasn't started yet, so load her settings to peek at the wallpaper
599 loadSettingsLocked(user.id);
600 wd = mWallpaperMap.get(user.id);
601 }
602 if (wd != null && name.equals(wd.name)) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700603 return true;
604 }
605 }
606 }
607 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800608 }
609
610 public void setDimensionHints(int width, int height) throws RemoteException {
611 checkPermission(android.Manifest.permission.SET_WALLPAPER_HINTS);
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700612 synchronized (mLock) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700613 int userId = UserHandle.getCallingUserId();
614 WallpaperData wallpaper = mWallpaperMap.get(userId);
615 if (wallpaper == null) {
616 throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
617 }
618 if (width <= 0 || height <= 0) {
619 throw new IllegalArgumentException("width and height must be > 0");
620 }
621
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800622 if (width != wallpaper.width || height != wallpaper.height) {
623 wallpaper.width = width;
624 wallpaper.height = height;
625 saveSettingsLocked(wallpaper);
626 if (mCurrentUserId != userId) return; // Don't change the properties now
627 if (wallpaper.connection != null) {
628 if (wallpaper.connection.mEngine != null) {
Dianne Hackborn284ac932009-08-28 10:34:25 -0700629 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800630 wallpaper.connection.mEngine.setDesiredSize(
Dianne Hackborn284ac932009-08-28 10:34:25 -0700631 width, height);
632 } catch (RemoteException e) {
633 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800634 notifyCallbacksLocked(wallpaper);
Dianne Hackborn284ac932009-08-28 10:34:25 -0700635 }
636 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700637 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800638 }
639 }
640
641 public int getWidthHint() throws RemoteException {
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700642 synchronized (mLock) {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700643 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.getCallingUserId());
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800644 return wallpaper.width;
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700645 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800646 }
647
648 public int getHeightHint() throws RemoteException {
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700649 synchronized (mLock) {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700650 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.getCallingUserId());
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800651 return wallpaper.height;
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700652 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800653 }
654
Dianne Hackborn284ac932009-08-28 10:34:25 -0700655 public ParcelFileDescriptor getWallpaper(IWallpaperManagerCallback cb,
656 Bundle outParams) {
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700657 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800658 // This returns the current user's wallpaper, if called by a system service. Else it
659 // returns the wallpaper for the calling user.
660 int callingUid = Binder.getCallingUid();
661 int wallpaperUserId = 0;
662 if (callingUid == android.os.Process.SYSTEM_UID) {
663 wallpaperUserId = mCurrentUserId;
664 } else {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700665 wallpaperUserId = UserHandle.getUserId(callingUid);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800666 }
667 WallpaperData wallpaper = mWallpaperMap.get(wallpaperUserId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700668 try {
Dianne Hackborn284ac932009-08-28 10:34:25 -0700669 if (outParams != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800670 outParams.putInt("width", wallpaper.width);
671 outParams.putInt("height", wallpaper.height);
Dianne Hackborn284ac932009-08-28 10:34:25 -0700672 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800673 wallpaper.callbacks.register(cb);
674 File f = new File(getWallpaperDir(wallpaperUserId), WALLPAPER);
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700675 if (!f.exists()) {
676 return null;
677 }
678 return ParcelFileDescriptor.open(f, MODE_READ_ONLY);
679 } catch (FileNotFoundException e) {
680 /* Shouldn't happen as we check to see if the file exists */
Joe Onorato8a9b2202010-02-26 18:56:32 -0800681 Slog.w(TAG, "Error getting wallpaper", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800682 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700683 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800684 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800685 }
686
Dianne Hackborneb034652009-09-07 00:49:58 -0700687 public WallpaperInfo getWallpaperInfo() {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700688 int userId = UserHandle.getCallingUserId();
Dianne Hackborneb034652009-09-07 00:49:58 -0700689 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800690 WallpaperData wallpaper = mWallpaperMap.get(userId);
691 if (wallpaper.connection != null) {
692 return wallpaper.connection.mInfo;
Dianne Hackborneb034652009-09-07 00:49:58 -0700693 }
694 return null;
695 }
696 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800697
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700698 public ParcelFileDescriptor setWallpaper(String name) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800699 checkPermission(android.Manifest.permission.SET_WALLPAPER);
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700700 synchronized (mLock) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700701 if (DEBUG) Slog.v(TAG, "setWallpaper");
702 int userId = UserHandle.getCallingUserId();
703 WallpaperData wallpaper = mWallpaperMap.get(userId);
704 if (wallpaper == null) {
705 throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
706 }
Dianne Hackborn0cd48872009-08-13 18:51:59 -0700707 final long ident = Binder.clearCallingIdentity();
708 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800709 ParcelFileDescriptor pfd = updateWallpaperBitmapLocked(name, wallpaper);
Dianne Hackborn0cd48872009-08-13 18:51:59 -0700710 if (pfd != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800711 wallpaper.imageWallpaperPending = true;
Dianne Hackborn0cd48872009-08-13 18:51:59 -0700712 }
713 return pfd;
714 } finally {
715 Binder.restoreCallingIdentity(ident);
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700716 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800717 }
718 }
719
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800720 ParcelFileDescriptor updateWallpaperBitmapLocked(String name, WallpaperData wallpaper) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700721 if (name == null) name = "";
722 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800723 File dir = getWallpaperDir(wallpaper.userId);
724 if (!dir.exists()) {
725 dir.mkdir();
Dianne Hackbornebac48c2011-11-29 18:01:50 -0800726 FileUtils.setPermissions(
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800727 dir.getPath(),
Dianne Hackbornebac48c2011-11-29 18:01:50 -0800728 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
729 -1, -1);
730 }
rpcraig554cb0c2012-07-05 06:41:43 -0400731 File file = new File(dir, WALLPAPER);
732 ParcelFileDescriptor fd = ParcelFileDescriptor.open(file,
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700733 MODE_CREATE|MODE_READ_WRITE);
rpcraig554cb0c2012-07-05 06:41:43 -0400734 if (!SELinux.restorecon(file)) {
735 return null;
736 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800737 wallpaper.name = name;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700738 return fd;
739 } catch (FileNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800740 Slog.w(TAG, "Error setting wallpaper", e);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700741 }
742 return null;
743 }
744
745 public void setWallpaperComponent(ComponentName name) {
746 checkPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT);
747 synchronized (mLock) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700748 if (DEBUG) Slog.v(TAG, "setWallpaperComponent name=" + name);
749 int userId = UserHandle.getCallingUserId();
750 WallpaperData wallpaper = mWallpaperMap.get(userId);
751 if (wallpaper == null) {
752 throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
753 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700754 final long ident = Binder.clearCallingIdentity();
755 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800756 wallpaper.imageWallpaperPending = false;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700757 bindWallpaperComponentLocked(name, false, true, wallpaper, null);
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700758 } finally {
759 Binder.restoreCallingIdentity(ident);
760 }
761 }
762 }
763
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800764 boolean bindWallpaperComponentLocked(ComponentName componentName, boolean force,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700765 boolean fromUser, WallpaperData wallpaper, IRemoteCallback reply) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800766 if (DEBUG) Slog.v(TAG, "bindWallpaperComponentLocked: componentName=" + componentName);
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700767 // Has the component changed?
Dianne Hackborn9ea31632011-08-05 14:43:50 -0700768 if (!force) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800769 if (wallpaper.connection != null) {
770 if (wallpaper.wallpaperComponent == null) {
Dianne Hackborn9ea31632011-08-05 14:43:50 -0700771 if (componentName == null) {
772 if (DEBUG) Slog.v(TAG, "bindWallpaperComponentLocked: still using default");
773 // Still using default wallpaper.
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700774 return true;
Dianne Hackborn9ea31632011-08-05 14:43:50 -0700775 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800776 } else if (wallpaper.wallpaperComponent.equals(componentName)) {
Dianne Hackborn9ea31632011-08-05 14:43:50 -0700777 // Changing to same wallpaper.
778 if (DEBUG) Slog.v(TAG, "same wallpaper");
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700779 return true;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700780 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700781 }
782 }
783
784 try {
Mike Clerona428b2c2009-11-15 22:53:08 -0800785 if (componentName == null) {
Mike Cleron322b6ee2009-11-12 07:45:47 -0800786 String defaultComponent =
787 mContext.getString(com.android.internal.R.string.default_wallpaper_component);
Mike Clerona428b2c2009-11-15 22:53:08 -0800788 if (defaultComponent != null) {
Mike Cleron322b6ee2009-11-12 07:45:47 -0800789 // See if there is a default wallpaper component specified
Mike Clerona428b2c2009-11-15 22:53:08 -0800790 componentName = ComponentName.unflattenFromString(defaultComponent);
Joe Onorato8a9b2202010-02-26 18:56:32 -0800791 if (DEBUG) Slog.v(TAG, "Use default component wallpaper:" + componentName);
Mike Cleron322b6ee2009-11-12 07:45:47 -0800792 }
Mike Clerona428b2c2009-11-15 22:53:08 -0800793 if (componentName == null) {
Mike Cleron322b6ee2009-11-12 07:45:47 -0800794 // Fall back to static image wallpaper
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -0700795 componentName = IMAGE_WALLPAPER;
Mike Cleron322b6ee2009-11-12 07:45:47 -0800796 //clearWallpaperComponentLocked();
797 //return;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800798 if (DEBUG) Slog.v(TAG, "Using image wallpaper");
Mike Cleron322b6ee2009-11-12 07:45:47 -0800799 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700800 }
Amith Yamasani4e2820c2012-08-28 22:17:23 -0700801 int serviceUserId = wallpaper.userId;
802 ServiceInfo si = mIPackageManager.getServiceInfo(componentName,
803 PackageManager.GET_META_DATA | PackageManager.GET_PERMISSIONS, serviceUserId);
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700804 if (!android.Manifest.permission.BIND_WALLPAPER.equals(si.permission)) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700805 String msg = "Selected service does not require "
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700806 + android.Manifest.permission.BIND_WALLPAPER
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700807 + ": " + componentName;
808 if (fromUser) {
809 throw new SecurityException(msg);
810 }
811 Slog.w(TAG, msg);
812 return false;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700813 }
814
Dianne Hackborneb034652009-09-07 00:49:58 -0700815 WallpaperInfo wi = null;
816
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700817 Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -0700818 if (componentName != null && !componentName.equals(IMAGE_WALLPAPER)) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700819 // Make sure the selected service is actually a wallpaper service.
Amith Yamasani4e2820c2012-08-28 22:17:23 -0700820 List<ResolveInfo> ris =
821 mIPackageManager.queryIntentServices(intent,
822 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
823 PackageManager.GET_META_DATA, serviceUserId);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700824 for (int i=0; i<ris.size(); i++) {
825 ServiceInfo rsi = ris.get(i).serviceInfo;
826 if (rsi.name.equals(si.name) &&
827 rsi.packageName.equals(si.packageName)) {
Dianne Hackborneb034652009-09-07 00:49:58 -0700828 try {
829 wi = new WallpaperInfo(mContext, ris.get(i));
830 } catch (XmlPullParserException e) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700831 if (fromUser) {
832 throw new IllegalArgumentException(e);
833 }
834 Slog.w(TAG, e);
835 return false;
Dianne Hackborneb034652009-09-07 00:49:58 -0700836 } catch (IOException e) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700837 if (fromUser) {
838 throw new IllegalArgumentException(e);
839 }
840 Slog.w(TAG, e);
841 return false;
Dianne Hackborneb034652009-09-07 00:49:58 -0700842 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700843 break;
844 }
845 }
Dianne Hackborneb034652009-09-07 00:49:58 -0700846 if (wi == null) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700847 String msg = "Selected service is not a wallpaper: "
848 + componentName;
849 if (fromUser) {
850 throw new SecurityException(msg);
851 }
852 Slog.w(TAG, msg);
853 return false;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700854 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700855 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700856
857 // Bind the service!
Joe Onorato8a9b2202010-02-26 18:56:32 -0800858 if (DEBUG) Slog.v(TAG, "Binding to:" + componentName);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800859 WallpaperConnection newConn = new WallpaperConnection(wi, wallpaper);
Mike Clerona428b2c2009-11-15 22:53:08 -0800860 intent.setComponent(componentName);
Dianne Hackborndd9b82c2009-09-03 00:18:47 -0700861 intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
862 com.android.internal.R.string.wallpaper_binding_label);
Dianne Hackborn41203752012-08-31 14:05:51 -0700863 intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivityAsUser(
Dianne Hackborneb034652009-09-07 00:49:58 -0700864 mContext, 0,
865 Intent.createChooser(new Intent(Intent.ACTION_SET_WALLPAPER),
866 mContext.getText(com.android.internal.R.string.chooser_wallpaper)),
Dianne Hackborn41203752012-08-31 14:05:51 -0700867 0, null, new UserHandle(serviceUserId)));
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800868 if (!mContext.bindService(intent, newConn, Context.BIND_AUTO_CREATE, serviceUserId)) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700869 String msg = "Unable to bind service: "
870 + componentName;
871 if (fromUser) {
872 throw new IllegalArgumentException(msg);
873 }
874 Slog.w(TAG, msg);
875 return false;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700876 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800877 if (wallpaper.userId == mCurrentUserId && mLastWallpaper != null) {
878 detachWallpaperLocked(mLastWallpaper);
879 }
880 wallpaper.wallpaperComponent = componentName;
881 wallpaper.connection = newConn;
882 wallpaper.lastDiedTime = SystemClock.uptimeMillis();
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700883 newConn.mReply = reply;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700884 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800885 if (wallpaper.userId == mCurrentUserId) {
886 if (DEBUG)
887 Slog.v(TAG, "Adding window token: " + newConn.mToken);
888 mIWindowManager.addWindowToken(newConn.mToken,
889 WindowManager.LayoutParams.TYPE_WALLPAPER);
890 mLastWallpaper = wallpaper;
891 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700892 } catch (RemoteException e) {
893 }
Amith Yamasani4e2820c2012-08-28 22:17:23 -0700894 } catch (RemoteException e) {
895 String msg = "Remote exception for " + componentName + "\n" + e;
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700896 if (fromUser) {
897 throw new IllegalArgumentException(msg);
898 }
899 Slog.w(TAG, msg);
900 return false;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700901 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700902 return true;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700903 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800904
905 void detachWallpaperLocked(WallpaperData wallpaper) {
906 if (wallpaper.connection != null) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700907 if (wallpaper.connection.mReply != null) {
908 try {
909 wallpaper.connection.mReply.sendResult(null);
910 } catch (RemoteException e) {
911 }
912 wallpaper.connection.mReply = null;
913 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800914 if (wallpaper.connection.mEngine != null) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700915 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800916 wallpaper.connection.mEngine.destroy();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700917 } catch (RemoteException e) {
918 }
919 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800920 mContext.unbindService(wallpaper.connection);
Dianne Hackborne9e9bca2009-08-18 15:08:22 -0700921 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800922 if (DEBUG)
923 Slog.v(TAG, "Removing window token: " + wallpaper.connection.mToken);
924 mIWindowManager.removeWindowToken(wallpaper.connection.mToken);
Dianne Hackborne9e9bca2009-08-18 15:08:22 -0700925 } catch (RemoteException e) {
926 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800927 wallpaper.connection.mService = null;
928 wallpaper.connection.mEngine = null;
929 wallpaper.connection = null;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700930 }
931 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800932
933 void clearWallpaperComponentLocked(WallpaperData wallpaper) {
934 wallpaper.wallpaperComponent = null;
935 detachWallpaperLocked(wallpaper);
936 }
937
938 void attachServiceLocked(WallpaperConnection conn, WallpaperData wallpaper) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700939 try {
Dianne Hackborn3be63c02009-08-20 19:31:38 -0700940 conn.mService.attach(conn, conn.mToken,
941 WindowManager.LayoutParams.TYPE_WALLPAPER, false,
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800942 wallpaper.width, wallpaper.height);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700943 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800944 Slog.w(TAG, "Failed attaching wallpaper; clearing", e);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800945 if (!wallpaper.wallpaperUpdating) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700946 bindWallpaperComponentLocked(null, false, false, wallpaper, null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800947 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700948 }
949 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800950
951 private void notifyCallbacksLocked(WallpaperData wallpaper) {
952 final int n = wallpaper.callbacks.beginBroadcast();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800953 for (int i = 0; i < n; i++) {
954 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800955 wallpaper.callbacks.getBroadcastItem(i).onWallpaperChanged();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800956 } catch (RemoteException e) {
957
958 // The RemoteCallbackList will take care of removing
959 // the dead object for us.
960 }
961 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800962 wallpaper.callbacks.finishBroadcast();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800963 final Intent intent = new Intent(Intent.ACTION_WALLPAPER_CHANGED);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -0700964 mContext.sendBroadcastAsUser(intent, new UserHandle(mCurrentUserId));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800965 }
966
967 private void checkPermission(String permission) {
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700968 if (PackageManager.PERMISSION_GRANTED!= mContext.checkCallingOrSelfPermission(permission)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800969 throw new SecurityException("Access denied to process: " + Binder.getCallingPid()
970 + ", must have permission " + permission);
971 }
972 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700973
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800974 private static JournaledFile makeJournaledFile(int userId) {
Amith Yamasani61f57372012-08-31 12:12:28 -0700975 final String base = new File(getWallpaperDir(userId), WALLPAPER_INFO).getAbsolutePath();
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700976 return new JournaledFile(new File(base), new File(base + ".tmp"));
977 }
978
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800979 private void saveSettingsLocked(WallpaperData wallpaper) {
980 JournaledFile journal = makeJournaledFile(wallpaper.userId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700981 FileOutputStream stream = null;
982 try {
983 stream = new FileOutputStream(journal.chooseForWrite(), false);
984 XmlSerializer out = new FastXmlSerializer();
985 out.setOutput(stream, "utf-8");
986 out.startDocument(null, true);
987
988 out.startTag(null, "wp");
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800989 out.attribute(null, "width", Integer.toString(wallpaper.width));
990 out.attribute(null, "height", Integer.toString(wallpaper.height));
991 out.attribute(null, "name", wallpaper.name);
992 if (wallpaper.wallpaperComponent != null
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -0700993 && !wallpaper.wallpaperComponent.equals(IMAGE_WALLPAPER)) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700994 out.attribute(null, "component",
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800995 wallpaper.wallpaperComponent.flattenToShortString());
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700996 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700997 out.endTag(null, "wp");
998
999 out.endDocument();
1000 stream.close();
1001 journal.commit();
1002 } catch (IOException e) {
1003 try {
1004 if (stream != null) {
1005 stream.close();
1006 }
1007 } catch (IOException ex) {
1008 // Ignore
1009 }
1010 journal.rollback();
1011 }
1012 }
1013
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001014 private void migrateFromOld() {
1015 File oldWallpaper = new File(WallpaperBackupHelper.WALLPAPER_IMAGE_KEY);
1016 File oldInfo = new File(WallpaperBackupHelper.WALLPAPER_INFO_KEY);
1017 if (oldWallpaper.exists()) {
1018 File newWallpaper = new File(getWallpaperDir(0), WALLPAPER);
1019 oldWallpaper.renameTo(newWallpaper);
1020 }
1021 if (oldInfo.exists()) {
1022 File newInfo = new File(getWallpaperDir(0), WALLPAPER_INFO);
1023 oldInfo.renameTo(newInfo);
1024 }
1025 }
1026
1027 private void loadSettingsLocked(int userId) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001028 if (DEBUG) Slog.v(TAG, "loadSettingsLocked");
Mike Clerona428b2c2009-11-15 22:53:08 -08001029
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001030 JournaledFile journal = makeJournaledFile(userId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001031 FileInputStream stream = null;
1032 File file = journal.chooseForRead();
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001033 if (!file.exists()) {
1034 // This should only happen one time, when upgrading from a legacy system
1035 migrateFromOld();
1036 }
1037 WallpaperData wallpaper = mWallpaperMap.get(userId);
1038 if (wallpaper == null) {
1039 wallpaper = new WallpaperData(userId);
1040 mWallpaperMap.put(userId, wallpaper);
1041 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001042 boolean success = false;
1043 try {
1044 stream = new FileInputStream(file);
1045 XmlPullParser parser = Xml.newPullParser();
1046 parser.setInput(stream, null);
1047
1048 int type;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001049 do {
1050 type = parser.next();
1051 if (type == XmlPullParser.START_TAG) {
1052 String tag = parser.getName();
1053 if ("wp".equals(tag)) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001054 wallpaper.width = Integer.parseInt(parser.getAttributeValue(null, "width"));
1055 wallpaper.height = Integer.parseInt(parser
1056 .getAttributeValue(null, "height"));
1057 wallpaper.name = parser.getAttributeValue(null, "name");
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001058 String comp = parser.getAttributeValue(null, "component");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001059 wallpaper.nextWallpaperComponent = comp != null
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001060 ? ComponentName.unflattenFromString(comp)
1061 : null;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001062 if (wallpaper.nextWallpaperComponent == null
1063 || "android".equals(wallpaper.nextWallpaperComponent
1064 .getPackageName())) {
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -07001065 wallpaper.nextWallpaperComponent = IMAGE_WALLPAPER;
Dianne Hackborn9ea31632011-08-05 14:43:50 -07001066 }
Mike Clerona428b2c2009-11-15 22:53:08 -08001067
1068 if (DEBUG) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001069 Slog.v(TAG, "mWidth:" + wallpaper.width);
1070 Slog.v(TAG, "mHeight:" + wallpaper.height);
1071 Slog.v(TAG, "mName:" + wallpaper.name);
1072 Slog.v(TAG, "mNextWallpaperComponent:"
1073 + wallpaper.nextWallpaperComponent);
Mike Clerona428b2c2009-11-15 22:53:08 -08001074 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001075 }
1076 }
1077 } while (type != XmlPullParser.END_DOCUMENT);
1078 success = true;
1079 } catch (NullPointerException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001080 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001081 } catch (NumberFormatException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001082 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001083 } catch (XmlPullParserException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001084 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001085 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001086 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001087 } catch (IndexOutOfBoundsException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001088 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001089 }
1090 try {
1091 if (stream != null) {
1092 stream.close();
1093 }
1094 } catch (IOException e) {
1095 // Ignore
1096 }
1097
1098 if (!success) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001099 wallpaper.width = -1;
1100 wallpaper.height = -1;
1101 wallpaper.name = "";
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001102 }
Dianne Hackborn44bc17c2011-04-20 18:18:51 -07001103
1104 // We always want to have some reasonable width hint.
1105 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
1106 Display d = wm.getDefaultDisplay();
1107 int baseSize = d.getMaximumSizeDimension();
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001108 if (wallpaper.width < baseSize) {
1109 wallpaper.width = baseSize;
Dianne Hackborn44bc17c2011-04-20 18:18:51 -07001110 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001111 if (wallpaper.height < baseSize) {
1112 wallpaper.height = baseSize;
Dianne Hackborn44bc17c2011-04-20 18:18:51 -07001113 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001114 }
1115
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07001116 // Called by SystemBackupAgent after files are restored to disk.
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001117 void settingsRestored() {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001118 // TODO: If necessary, make it work for secondary users as well. This currently assumes
1119 // restores only to the primary user
Joe Onorato8a9b2202010-02-26 18:56:32 -08001120 if (DEBUG) Slog.v(TAG, "settingsRestored");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001121 WallpaperData wallpaper = null;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001122 boolean success = false;
1123 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001124 loadSettingsLocked(0);
1125 wallpaper = mWallpaperMap.get(0);
1126 if (wallpaper.nextWallpaperComponent != null
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -07001127 && !wallpaper.nextWallpaperComponent.equals(IMAGE_WALLPAPER)) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001128 if (!bindWallpaperComponentLocked(wallpaper.nextWallpaperComponent, false, false,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001129 wallpaper, null)) {
Christopher Tatee3ab4d02009-12-16 14:03:31 -08001130 // No such live wallpaper or other failure; fall back to the default
1131 // live wallpaper (since the profile being restored indicated that the
1132 // user had selected a live rather than static one).
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001133 bindWallpaperComponentLocked(null, false, false, wallpaper, null);
Christopher Tatee3ab4d02009-12-16 14:03:31 -08001134 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001135 success = true;
1136 } else {
Mike Clerona428b2c2009-11-15 22:53:08 -08001137 // If there's a wallpaper name, we use that. If that can't be loaded, then we
1138 // use the default.
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001139 if ("".equals(wallpaper.name)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001140 if (DEBUG) Slog.v(TAG, "settingsRestored: name is empty");
Mike Clerona428b2c2009-11-15 22:53:08 -08001141 success = true;
1142 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001143 if (DEBUG) Slog.v(TAG, "settingsRestored: attempting to restore named resource");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001144 success = restoreNamedResourceLocked(wallpaper);
Mike Clerona428b2c2009-11-15 22:53:08 -08001145 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08001146 if (DEBUG) Slog.v(TAG, "settingsRestored: success=" + success);
Mike Clerona428b2c2009-11-15 22:53:08 -08001147 if (success) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001148 bindWallpaperComponentLocked(wallpaper.nextWallpaperComponent, false, false,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001149 wallpaper, null);
Mike Clerona428b2c2009-11-15 22:53:08 -08001150 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001151 }
1152 }
1153
1154 if (!success) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001155 Slog.e(TAG, "Failed to restore wallpaper: '" + wallpaper.name + "'");
1156 wallpaper.name = "";
1157 getWallpaperDir(0).delete();
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001158 }
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07001159
1160 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001161 saveSettingsLocked(wallpaper);
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07001162 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001163 }
1164
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001165 boolean restoreNamedResourceLocked(WallpaperData wallpaper) {
1166 if (wallpaper.name.length() > 4 && "res:".equals(wallpaper.name.substring(0, 4))) {
1167 String resName = wallpaper.name.substring(4);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001168
1169 String pkg = null;
1170 int colon = resName.indexOf(':');
1171 if (colon > 0) {
1172 pkg = resName.substring(0, colon);
1173 }
1174
1175 String ident = null;
1176 int slash = resName.lastIndexOf('/');
1177 if (slash > 0) {
1178 ident = resName.substring(slash+1);
1179 }
1180
1181 String type = null;
1182 if (colon > 0 && slash > 0 && (slash-colon) > 1) {
1183 type = resName.substring(colon+1, slash);
1184 }
1185
1186 if (pkg != null && ident != null && type != null) {
1187 int resId = -1;
1188 InputStream res = null;
1189 FileOutputStream fos = null;
1190 try {
1191 Context c = mContext.createPackageContext(pkg, Context.CONTEXT_RESTRICTED);
1192 Resources r = c.getResources();
1193 resId = r.getIdentifier(resName, null, null);
1194 if (resId == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001195 Slog.e(TAG, "couldn't resolve identifier pkg=" + pkg + " type=" + type
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001196 + " ident=" + ident);
1197 return false;
1198 }
1199
1200 res = r.openRawResource(resId);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001201 if (wallpaper.wallpaperFile.exists()) {
1202 wallpaper.wallpaperFile.delete();
Dianne Hackborn1afd1c92010-03-18 22:47:17 -07001203 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001204 fos = new FileOutputStream(wallpaper.wallpaperFile);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001205
1206 byte[] buffer = new byte[32768];
1207 int amt;
1208 while ((amt=res.read(buffer)) > 0) {
1209 fos.write(buffer, 0, amt);
1210 }
1211 // mWallpaperObserver will notice the close and send the change broadcast
1212
Joe Onorato8a9b2202010-02-26 18:56:32 -08001213 Slog.v(TAG, "Restored wallpaper: " + resName);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001214 return true;
1215 } catch (NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001216 Slog.e(TAG, "Package name " + pkg + " not found");
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001217 } catch (Resources.NotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001218 Slog.e(TAG, "Resource not found: " + resId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001219 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001220 Slog.e(TAG, "IOException while restoring wallpaper ", e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001221 } finally {
1222 if (res != null) {
1223 try {
1224 res.close();
1225 } catch (IOException ex) {}
1226 }
1227 if (fos != null) {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07001228 FileUtils.sync(fos);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001229 try {
1230 fos.close();
1231 } catch (IOException ex) {}
1232 }
1233 }
1234 }
1235 }
1236 return false;
1237 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001238
Dianne Hackborneb034652009-09-07 00:49:58 -07001239 @Override
1240 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1241 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
1242 != PackageManager.PERMISSION_GRANTED) {
1243
1244 pw.println("Permission Denial: can't dump wallpaper service from from pid="
1245 + Binder.getCallingPid()
1246 + ", uid=" + Binder.getCallingUid());
1247 return;
1248 }
1249
1250 synchronized (mLock) {
1251 pw.println("Current Wallpaper Service state:");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001252 for (int i = 0; i < mWallpaperMap.size(); i++) {
1253 WallpaperData wallpaper = mWallpaperMap.valueAt(i);
1254 pw.println(" User " + wallpaper.userId + ":");
1255 pw.print(" mWidth=");
1256 pw.print(wallpaper.width);
1257 pw.print(" mHeight=");
1258 pw.println(wallpaper.height);
1259 pw.print(" mName=");
1260 pw.println(wallpaper.name);
1261 pw.print(" mWallpaperComponent=");
1262 pw.println(wallpaper.wallpaperComponent);
1263 if (wallpaper.connection != null) {
1264 WallpaperConnection conn = wallpaper.connection;
1265 pw.print(" Wallpaper connection ");
1266 pw.print(conn);
1267 pw.println(":");
1268 if (conn.mInfo != null) {
1269 pw.print(" mInfo.component=");
1270 pw.println(conn.mInfo.getComponent());
1271 }
1272 pw.print(" mToken=");
1273 pw.println(conn.mToken);
1274 pw.print(" mService=");
1275 pw.println(conn.mService);
1276 pw.print(" mEngine=");
1277 pw.println(conn.mEngine);
1278 pw.print(" mLastDiedTime=");
1279 pw.println(wallpaper.lastDiedTime - SystemClock.uptimeMillis());
1280 }
Dianne Hackborneb034652009-09-07 00:49:58 -07001281 }
1282 }
1283 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001284}