blob: 6957bac0c1ebba0ab8c2f788fa46bdc55792007b [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
Michael Wright5203a8b2013-10-03 14:16:42 -0700222 boolean mDimensionsChanged = false;
223
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800224 public WallpaperConnection(WallpaperInfo info, WallpaperData wallpaper) {
Dianne Hackborneb034652009-09-07 00:49:58 -0700225 mInfo = info;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800226 mWallpaper = wallpaper;
Dianne Hackborneb034652009-09-07 00:49:58 -0700227 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700228
229 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700230 public void onServiceConnected(ComponentName name, IBinder service) {
231 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800232 if (mWallpaper.connection == this) {
233 mWallpaper.lastDiedTime = SystemClock.uptimeMillis();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700234 mService = IWallpaperService.Stub.asInterface(service);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800235 attachServiceLocked(this, mWallpaper);
Dianne Hackborneb034652009-09-07 00:49:58 -0700236 // XXX should probably do saveSettingsLocked() later
237 // when we have an engine, but I'm not sure about
238 // locking there and anyway we always need to be able to
239 // recover if there is something wrong.
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800240 saveSettingsLocked(mWallpaper);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700241 }
242 }
243 }
244
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700245 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700246 public void onServiceDisconnected(ComponentName name) {
247 synchronized (mLock) {
248 mService = null;
249 mEngine = null;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800250 if (mWallpaper.connection == this) {
251 Slog.w(TAG, "Wallpaper service gone: " + mWallpaper.wallpaperComponent);
252 if (!mWallpaper.wallpaperUpdating
253 && (mWallpaper.lastDiedTime + MIN_WALLPAPER_CRASH_TIME)
254 > SystemClock.uptimeMillis()
255 && mWallpaper.userId == mCurrentUserId) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800256 Slog.w(TAG, "Reverting to built-in wallpaper!");
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700257 clearWallpaperLocked(true, mWallpaper.userId, null);
Dianne Hackborn0cd48872009-08-13 18:51:59 -0700258 }
259 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700260 }
261 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800262
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700263 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700264 public void attachEngine(IWallpaperEngine engine) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700265 synchronized (mLock) {
266 mEngine = engine;
Michael Wright5203a8b2013-10-03 14:16:42 -0700267 if (mDimensionsChanged) {
268 try {
269 mEngine.setDesiredSize(mWallpaper.width, mWallpaper.height);
270 } catch (RemoteException e) {
271 Slog.w(TAG, "Failed to set wallpaper dimensions", e);
272 }
273 mDimensionsChanged = false;
274 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700275 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700276 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800277
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700278 @Override
279 public void engineShown(IWallpaperEngine engine) {
280 synchronized (mLock) {
281 if (mReply != null) {
282 long ident = Binder.clearCallingIdentity();
283 try {
284 mReply.sendResult(null);
285 } catch (RemoteException e) {
286 Binder.restoreCallingIdentity(ident);
287 }
288 mReply = null;
289 }
290 }
291 }
292
293 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700294 public ParcelFileDescriptor setWallpaper(String name) {
295 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800296 if (mWallpaper.connection == this) {
297 return updateWallpaperBitmapLocked(name, mWallpaper);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700298 }
299 return null;
300 }
301 }
302 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800303
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800304 class MyPackageMonitor extends PackageMonitor {
305 @Override
306 public void onPackageUpdateFinished(String packageName, int uid) {
307 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700308 if (mCurrentUserId != getChangingUserId()) {
309 return;
310 }
311 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
312 if (wallpaper != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800313 if (wallpaper.wallpaperComponent != null
314 && wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
315 wallpaper.wallpaperUpdating = false;
316 ComponentName comp = wallpaper.wallpaperComponent;
317 clearWallpaperComponentLocked(wallpaper);
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700318 if (!bindWallpaperComponentLocked(comp, false, false,
319 wallpaper, null)) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800320 Slog.w(TAG, "Wallpaper no longer available; reverting to default");
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700321 clearWallpaperLocked(false, wallpaper.userId, null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800322 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700323 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800324 }
325 }
326 }
327
328 @Override
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700329 public void onPackageModified(String packageName) {
330 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700331 if (mCurrentUserId != getChangingUserId()) {
332 return;
333 }
334 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
335 if (wallpaper != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800336 if (wallpaper.wallpaperComponent == null
337 || !wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700338 return;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800339 }
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700340 doPackagesChangedLocked(true, wallpaper);
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700341 }
342 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700343 }
344
345 @Override
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800346 public void onPackageUpdateStarted(String packageName, int uid) {
347 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700348 if (mCurrentUserId != getChangingUserId()) {
349 return;
350 }
351 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
352 if (wallpaper != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800353 if (wallpaper.wallpaperComponent != null
354 && wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
355 wallpaper.wallpaperUpdating = true;
356 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800357 }
358 }
359 }
360
361 @Override
362 public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700363 synchronized (mLock) {
364 boolean changed = false;
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700365 if (mCurrentUserId != getChangingUserId()) {
366 return false;
367 }
368 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
369 if (wallpaper != null) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700370 boolean res = doPackagesChangedLocked(doit, wallpaper);
371 changed |= res;
372 }
373 return changed;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800374 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800375 }
376
377 @Override
378 public void onSomePackagesChanged() {
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700379 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700380 if (mCurrentUserId != getChangingUserId()) {
381 return;
382 }
383 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
384 if (wallpaper != null) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700385 doPackagesChangedLocked(true, wallpaper);
386 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800387 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800388 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800389
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700390 boolean doPackagesChangedLocked(boolean doit, WallpaperData wallpaper) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800391 boolean changed = false;
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700392 if (wallpaper.wallpaperComponent != null) {
393 int change = isPackageDisappearing(wallpaper.wallpaperComponent
394 .getPackageName());
395 if (change == PACKAGE_PERMANENT_CHANGE
396 || change == PACKAGE_TEMPORARY_CHANGE) {
397 changed = true;
398 if (doit) {
399 Slog.w(TAG, "Wallpaper uninstalled, removing: "
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800400 + wallpaper.wallpaperComponent);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700401 clearWallpaperLocked(false, wallpaper.userId, null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800402 }
403 }
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700404 }
405 if (wallpaper.nextWallpaperComponent != null) {
406 int change = isPackageDisappearing(wallpaper.nextWallpaperComponent
407 .getPackageName());
408 if (change == PACKAGE_PERMANENT_CHANGE
409 || change == PACKAGE_TEMPORARY_CHANGE) {
410 wallpaper.nextWallpaperComponent = null;
411 }
412 }
413 if (wallpaper.wallpaperComponent != null
414 && isPackageModified(wallpaper.wallpaperComponent.getPackageName())) {
415 try {
416 mContext.getPackageManager().getServiceInfo(
417 wallpaper.wallpaperComponent, 0);
418 } catch (NameNotFoundException e) {
419 Slog.w(TAG, "Wallpaper component gone, removing: "
420 + wallpaper.wallpaperComponent);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700421 clearWallpaperLocked(false, wallpaper.userId, null);
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700422 }
423 }
424 if (wallpaper.nextWallpaperComponent != null
425 && isPackageModified(wallpaper.nextWallpaperComponent.getPackageName())) {
426 try {
427 mContext.getPackageManager().getServiceInfo(
428 wallpaper.nextWallpaperComponent, 0);
429 } catch (NameNotFoundException e) {
430 wallpaper.nextWallpaperComponent = null;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800431 }
432 }
433 return changed;
434 }
435 }
436
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700437 public WallpaperManagerService(Context context) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800438 if (DEBUG) Slog.v(TAG, "WallpaperService startup");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800439 mContext = context;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700440 mIWindowManager = IWindowManager.Stub.asInterface(
441 ServiceManager.getService(Context.WINDOW_SERVICE));
Amith Yamasani4e2820c2012-08-28 22:17:23 -0700442 mIPackageManager = AppGlobals.getPackageManager();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800443 mMonitor = new MyPackageMonitor();
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700444 mMonitor.register(context, null, UserHandle.ALL, true);
Amith Yamasani61f57372012-08-31 12:12:28 -0700445 getWallpaperDir(UserHandle.USER_OWNER).mkdirs();
446 loadSettingsLocked(UserHandle.USER_OWNER);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800447 }
448
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800449 private static File getWallpaperDir(int userId) {
Amith Yamasani61f57372012-08-31 12:12:28 -0700450 return Environment.getUserSystemDirectory(userId);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800451 }
452
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800453 @Override
454 protected void finalize() throws Throwable {
455 super.finalize();
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800456 for (int i = 0; i < mWallpaperMap.size(); i++) {
457 WallpaperData wallpaper = mWallpaperMap.valueAt(i);
458 wallpaper.wallpaperObserver.stopWatching();
459 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800460 }
Amith Yamasani13593602012-03-22 16:16:17 -0700461
Svetoslav Ganova0027152013-06-25 14:59:53 -0700462 public void systemRunning() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800463 if (DEBUG) Slog.v(TAG, "systemReady");
Amith Yamasani61f57372012-08-31 12:12:28 -0700464 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.USER_OWNER);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700465 switchWallpaper(wallpaper, null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800466 wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper);
467 wallpaper.wallpaperObserver.startWatching();
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800468
Amith Yamasani13593602012-03-22 16:16:17 -0700469 IntentFilter userFilter = new IntentFilter();
Amith Yamasani13593602012-03-22 16:16:17 -0700470 userFilter.addAction(Intent.ACTION_USER_REMOVED);
Amith Yamasani756901d2012-10-12 12:30:07 -0700471 userFilter.addAction(Intent.ACTION_USER_STOPPING);
Amith Yamasani13593602012-03-22 16:16:17 -0700472 mContext.registerReceiver(new BroadcastReceiver() {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800473 @Override
Amith Yamasani13593602012-03-22 16:16:17 -0700474 public void onReceive(Context context, Intent intent) {
475 String action = intent.getAction();
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700476 if (Intent.ACTION_USER_REMOVED.equals(action)) {
Amith Yamasani756901d2012-10-12 12:30:07 -0700477 onRemoveUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
478 UserHandle.USER_NULL));
Amith Yamasani13593602012-03-22 16:16:17 -0700479 }
Amith Yamasani0c293712012-10-30 12:23:52 -0700480 // TODO: Race condition causing problems when cleaning up on stopping a user.
481 // Comment this out for now.
482 // else if (Intent.ACTION_USER_STOPPING.equals(action)) {
483 // onStoppingUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
484 // UserHandle.USER_NULL));
485 // }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800486 }
Amith Yamasani13593602012-03-22 16:16:17 -0700487 }, userFilter);
Amith Yamasani756901d2012-10-12 12:30:07 -0700488
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700489 try {
490 ActivityManagerNative.getDefault().registerUserSwitchObserver(
491 new IUserSwitchObserver.Stub() {
492 @Override
493 public void onUserSwitching(int newUserId, IRemoteCallback reply) {
494 switchUser(newUserId, reply);
495 }
496
497 @Override
498 public void onUserSwitchComplete(int newUserId) throws RemoteException {
499 }
500 });
501 } catch (RemoteException e) {
502 // TODO Auto-generated catch block
503 e.printStackTrace();
504 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800505 }
506
507 String getName() {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700508 synchronized (mLock) {
509 return mWallpaperMap.get(0).name;
510 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800511 }
512
Amith Yamasani756901d2012-10-12 12:30:07 -0700513 void onStoppingUser(int userId) {
514 if (userId < 1) return;
Amith Yamasani13593602012-03-22 16:16:17 -0700515 synchronized (mLock) {
516 WallpaperData wallpaper = mWallpaperMap.get(userId);
517 if (wallpaper != null) {
Amith Yamasani756901d2012-10-12 12:30:07 -0700518 if (wallpaper.wallpaperObserver != null) {
519 wallpaper.wallpaperObserver.stopWatching();
520 wallpaper.wallpaperObserver = null;
521 }
Amith Yamasani13593602012-03-22 16:16:17 -0700522 mWallpaperMap.remove(userId);
523 }
Amith Yamasani756901d2012-10-12 12:30:07 -0700524 }
525 }
526
527 void onRemoveUser(int userId) {
528 if (userId < 1) return;
529 synchronized (mLock) {
530 onStoppingUser(userId);
Amith Yamasani13593602012-03-22 16:16:17 -0700531 File wallpaperFile = new File(getWallpaperDir(userId), WALLPAPER);
532 wallpaperFile.delete();
533 File wallpaperInfoFile = new File(getWallpaperDir(userId), WALLPAPER_INFO);
534 wallpaperInfoFile.delete();
535 }
536 }
537
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700538 void switchUser(int userId, IRemoteCallback reply) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800539 synchronized (mLock) {
540 mCurrentUserId = userId;
541 WallpaperData wallpaper = mWallpaperMap.get(userId);
542 if (wallpaper == null) {
543 wallpaper = new WallpaperData(userId);
544 mWallpaperMap.put(userId, wallpaper);
545 loadSettingsLocked(userId);
Amith Yamasani6474c4c2012-10-04 14:55:42 -0700546 }
547 // Not started watching yet, in case wallpaper data was loaded for other reasons.
548 if (wallpaper.wallpaperObserver == null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800549 wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper);
550 wallpaper.wallpaperObserver.startWatching();
551 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700552 switchWallpaper(wallpaper, reply);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800553 }
554 }
555
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700556 void switchWallpaper(WallpaperData wallpaper, IRemoteCallback reply) {
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700557 synchronized (mLock) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700558 RuntimeException e = null;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700559 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800560 ComponentName cname = wallpaper.wallpaperComponent != null ?
561 wallpaper.wallpaperComponent : wallpaper.nextWallpaperComponent;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700562 if (bindWallpaperComponentLocked(cname, true, false, wallpaper, reply)) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700563 return;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700564 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700565 } catch (RuntimeException e1) {
566 e = e1;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700567 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700568 Slog.w(TAG, "Failure starting previous wallpaper", e);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700569 clearWallpaperLocked(false, wallpaper.userId, reply);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800570 }
571 }
572
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800573 public void clearWallpaper() {
574 if (DEBUG) Slog.v(TAG, "clearWallpaper");
575 synchronized (mLock) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700576 clearWallpaperLocked(false, UserHandle.getCallingUserId(), null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800577 }
578 }
579
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700580 void clearWallpaperLocked(boolean defaultFailed, int userId, IRemoteCallback reply) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800581 WallpaperData wallpaper = mWallpaperMap.get(userId);
582 File f = new File(getWallpaperDir(userId), WALLPAPER);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800583 if (f.exists()) {
584 f.delete();
585 }
586 final long ident = Binder.clearCallingIdentity();
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700587 RuntimeException e = null;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800588 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800589 wallpaper.imageWallpaperPending = false;
590 if (userId != mCurrentUserId) return;
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700591 if (bindWallpaperComponentLocked(defaultFailed
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -0700592 ? IMAGE_WALLPAPER
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700593 : null, true, false, wallpaper, reply)) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700594 return;
595 }
596 } catch (IllegalArgumentException e1) {
597 e = e1;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800598 } finally {
599 Binder.restoreCallingIdentity(ident);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800600 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700601
602 // This can happen if the default wallpaper component doesn't
603 // exist. This should be a system configuration problem, but
604 // let's not let it crash the system and just live with no
605 // wallpaper.
606 Slog.e(TAG, "Default wallpaper component not found!", e);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800607 clearWallpaperComponentLocked(wallpaper);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700608 if (reply != null) {
609 try {
610 reply.sendResult(null);
611 } catch (RemoteException e1) {
612 }
613 }
614 }
615
616 public boolean hasNamedWallpaper(String name) {
617 synchronized (mLock) {
Amith Yamasani6474c4c2012-10-04 14:55:42 -0700618 List<UserInfo> users;
619 long ident = Binder.clearCallingIdentity();
620 try {
621 users = ((UserManager) mContext.getSystemService(Context.USER_SERVICE)).getUsers();
622 } finally {
623 Binder.restoreCallingIdentity(ident);
624 }
625 for (UserInfo user: users) {
626 WallpaperData wd = mWallpaperMap.get(user.id);
627 if (wd == null) {
628 // User hasn't started yet, so load her settings to peek at the wallpaper
629 loadSettingsLocked(user.id);
630 wd = mWallpaperMap.get(user.id);
631 }
632 if (wd != null && name.equals(wd.name)) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700633 return true;
634 }
635 }
636 }
637 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800638 }
639
640 public void setDimensionHints(int width, int height) throws RemoteException {
641 checkPermission(android.Manifest.permission.SET_WALLPAPER_HINTS);
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700642 synchronized (mLock) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700643 int userId = UserHandle.getCallingUserId();
644 WallpaperData wallpaper = mWallpaperMap.get(userId);
645 if (wallpaper == null) {
646 throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
647 }
648 if (width <= 0 || height <= 0) {
649 throw new IllegalArgumentException("width and height must be > 0");
650 }
651
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800652 if (width != wallpaper.width || height != wallpaper.height) {
653 wallpaper.width = width;
654 wallpaper.height = height;
655 saveSettingsLocked(wallpaper);
656 if (mCurrentUserId != userId) return; // Don't change the properties now
657 if (wallpaper.connection != null) {
658 if (wallpaper.connection.mEngine != null) {
Dianne Hackborn284ac932009-08-28 10:34:25 -0700659 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800660 wallpaper.connection.mEngine.setDesiredSize(
Dianne Hackborn284ac932009-08-28 10:34:25 -0700661 width, height);
662 } catch (RemoteException e) {
663 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800664 notifyCallbacksLocked(wallpaper);
Michael Wright5203a8b2013-10-03 14:16:42 -0700665 } else if (wallpaper.connection.mService != null) {
666 // We've attached to the service but the engine hasn't attached back to us
667 // yet. This means it will be created with the previous dimensions, so we
668 // need to update it to the new dimensions once it attaches.
669 wallpaper.connection.mDimensionsChanged = true;
Dianne Hackborn284ac932009-08-28 10:34:25 -0700670 }
671 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700672 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800673 }
674 }
675
676 public int getWidthHint() throws RemoteException {
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700677 synchronized (mLock) {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700678 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.getCallingUserId());
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800679 return wallpaper.width;
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700680 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800681 }
682
683 public int getHeightHint() throws RemoteException {
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700684 synchronized (mLock) {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700685 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.getCallingUserId());
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800686 return wallpaper.height;
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700687 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800688 }
689
Dianne Hackborn284ac932009-08-28 10:34:25 -0700690 public ParcelFileDescriptor getWallpaper(IWallpaperManagerCallback cb,
691 Bundle outParams) {
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700692 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800693 // This returns the current user's wallpaper, if called by a system service. Else it
694 // returns the wallpaper for the calling user.
695 int callingUid = Binder.getCallingUid();
696 int wallpaperUserId = 0;
697 if (callingUid == android.os.Process.SYSTEM_UID) {
698 wallpaperUserId = mCurrentUserId;
699 } else {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700700 wallpaperUserId = UserHandle.getUserId(callingUid);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800701 }
702 WallpaperData wallpaper = mWallpaperMap.get(wallpaperUserId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700703 try {
Dianne Hackborn284ac932009-08-28 10:34:25 -0700704 if (outParams != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800705 outParams.putInt("width", wallpaper.width);
706 outParams.putInt("height", wallpaper.height);
Dianne Hackborn284ac932009-08-28 10:34:25 -0700707 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800708 wallpaper.callbacks.register(cb);
709 File f = new File(getWallpaperDir(wallpaperUserId), WALLPAPER);
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700710 if (!f.exists()) {
711 return null;
712 }
713 return ParcelFileDescriptor.open(f, MODE_READ_ONLY);
714 } catch (FileNotFoundException e) {
715 /* Shouldn't happen as we check to see if the file exists */
Joe Onorato8a9b2202010-02-26 18:56:32 -0800716 Slog.w(TAG, "Error getting wallpaper", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800717 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700718 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800719 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800720 }
721
Dianne Hackborneb034652009-09-07 00:49:58 -0700722 public WallpaperInfo getWallpaperInfo() {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700723 int userId = UserHandle.getCallingUserId();
Dianne Hackborneb034652009-09-07 00:49:58 -0700724 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800725 WallpaperData wallpaper = mWallpaperMap.get(userId);
726 if (wallpaper.connection != null) {
727 return wallpaper.connection.mInfo;
Dianne Hackborneb034652009-09-07 00:49:58 -0700728 }
729 return null;
730 }
731 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800732
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700733 public ParcelFileDescriptor setWallpaper(String name) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800734 checkPermission(android.Manifest.permission.SET_WALLPAPER);
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700735 synchronized (mLock) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700736 if (DEBUG) Slog.v(TAG, "setWallpaper");
737 int userId = UserHandle.getCallingUserId();
738 WallpaperData wallpaper = mWallpaperMap.get(userId);
739 if (wallpaper == null) {
740 throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
741 }
Dianne Hackborn0cd48872009-08-13 18:51:59 -0700742 final long ident = Binder.clearCallingIdentity();
743 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800744 ParcelFileDescriptor pfd = updateWallpaperBitmapLocked(name, wallpaper);
Dianne Hackborn0cd48872009-08-13 18:51:59 -0700745 if (pfd != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800746 wallpaper.imageWallpaperPending = true;
Dianne Hackborn0cd48872009-08-13 18:51:59 -0700747 }
748 return pfd;
749 } finally {
750 Binder.restoreCallingIdentity(ident);
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700751 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800752 }
753 }
754
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800755 ParcelFileDescriptor updateWallpaperBitmapLocked(String name, WallpaperData wallpaper) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700756 if (name == null) name = "";
757 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800758 File dir = getWallpaperDir(wallpaper.userId);
759 if (!dir.exists()) {
760 dir.mkdir();
Dianne Hackbornebac48c2011-11-29 18:01:50 -0800761 FileUtils.setPermissions(
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800762 dir.getPath(),
Dianne Hackbornebac48c2011-11-29 18:01:50 -0800763 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
764 -1, -1);
765 }
rpcraig554cb0c2012-07-05 06:41:43 -0400766 File file = new File(dir, WALLPAPER);
767 ParcelFileDescriptor fd = ParcelFileDescriptor.open(file,
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700768 MODE_CREATE|MODE_READ_WRITE);
rpcraig554cb0c2012-07-05 06:41:43 -0400769 if (!SELinux.restorecon(file)) {
770 return null;
771 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800772 wallpaper.name = name;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700773 return fd;
774 } catch (FileNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800775 Slog.w(TAG, "Error setting wallpaper", e);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700776 }
777 return null;
778 }
779
780 public void setWallpaperComponent(ComponentName name) {
781 checkPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT);
782 synchronized (mLock) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700783 if (DEBUG) Slog.v(TAG, "setWallpaperComponent name=" + name);
784 int userId = UserHandle.getCallingUserId();
785 WallpaperData wallpaper = mWallpaperMap.get(userId);
786 if (wallpaper == null) {
787 throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
788 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700789 final long ident = Binder.clearCallingIdentity();
790 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800791 wallpaper.imageWallpaperPending = false;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700792 bindWallpaperComponentLocked(name, false, true, wallpaper, null);
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700793 } finally {
794 Binder.restoreCallingIdentity(ident);
795 }
796 }
797 }
798
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800799 boolean bindWallpaperComponentLocked(ComponentName componentName, boolean force,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700800 boolean fromUser, WallpaperData wallpaper, IRemoteCallback reply) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800801 if (DEBUG) Slog.v(TAG, "bindWallpaperComponentLocked: componentName=" + componentName);
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700802 // Has the component changed?
Dianne Hackborn9ea31632011-08-05 14:43:50 -0700803 if (!force) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800804 if (wallpaper.connection != null) {
805 if (wallpaper.wallpaperComponent == null) {
Dianne Hackborn9ea31632011-08-05 14:43:50 -0700806 if (componentName == null) {
807 if (DEBUG) Slog.v(TAG, "bindWallpaperComponentLocked: still using default");
808 // Still using default wallpaper.
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700809 return true;
Dianne Hackborn9ea31632011-08-05 14:43:50 -0700810 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800811 } else if (wallpaper.wallpaperComponent.equals(componentName)) {
Dianne Hackborn9ea31632011-08-05 14:43:50 -0700812 // Changing to same wallpaper.
813 if (DEBUG) Slog.v(TAG, "same wallpaper");
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700814 return true;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700815 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700816 }
817 }
818
819 try {
Mike Clerona428b2c2009-11-15 22:53:08 -0800820 if (componentName == null) {
Mike Cleron322b6ee2009-11-12 07:45:47 -0800821 String defaultComponent =
822 mContext.getString(com.android.internal.R.string.default_wallpaper_component);
Mike Clerona428b2c2009-11-15 22:53:08 -0800823 if (defaultComponent != null) {
Mike Cleron322b6ee2009-11-12 07:45:47 -0800824 // See if there is a default wallpaper component specified
Mike Clerona428b2c2009-11-15 22:53:08 -0800825 componentName = ComponentName.unflattenFromString(defaultComponent);
Joe Onorato8a9b2202010-02-26 18:56:32 -0800826 if (DEBUG) Slog.v(TAG, "Use default component wallpaper:" + componentName);
Mike Cleron322b6ee2009-11-12 07:45:47 -0800827 }
Mike Clerona428b2c2009-11-15 22:53:08 -0800828 if (componentName == null) {
Mike Cleron322b6ee2009-11-12 07:45:47 -0800829 // Fall back to static image wallpaper
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -0700830 componentName = IMAGE_WALLPAPER;
Mike Cleron322b6ee2009-11-12 07:45:47 -0800831 //clearWallpaperComponentLocked();
832 //return;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800833 if (DEBUG) Slog.v(TAG, "Using image wallpaper");
Mike Cleron322b6ee2009-11-12 07:45:47 -0800834 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700835 }
Amith Yamasani4e2820c2012-08-28 22:17:23 -0700836 int serviceUserId = wallpaper.userId;
837 ServiceInfo si = mIPackageManager.getServiceInfo(componentName,
838 PackageManager.GET_META_DATA | PackageManager.GET_PERMISSIONS, serviceUserId);
Christopher Tate90952202013-09-08 13:01:28 -0700839 if (si == null) {
840 // The wallpaper component we're trying to use doesn't exist
841 Slog.w(TAG, "Attempted wallpaper " + componentName + " is unavailable");
842 return false;
843 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700844 if (!android.Manifest.permission.BIND_WALLPAPER.equals(si.permission)) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700845 String msg = "Selected service does not require "
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700846 + android.Manifest.permission.BIND_WALLPAPER
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700847 + ": " + componentName;
848 if (fromUser) {
849 throw new SecurityException(msg);
850 }
851 Slog.w(TAG, msg);
852 return false;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700853 }
854
Dianne Hackborneb034652009-09-07 00:49:58 -0700855 WallpaperInfo wi = null;
856
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700857 Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -0700858 if (componentName != null && !componentName.equals(IMAGE_WALLPAPER)) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700859 // Make sure the selected service is actually a wallpaper service.
Amith Yamasani4e2820c2012-08-28 22:17:23 -0700860 List<ResolveInfo> ris =
861 mIPackageManager.queryIntentServices(intent,
862 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
863 PackageManager.GET_META_DATA, serviceUserId);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700864 for (int i=0; i<ris.size(); i++) {
865 ServiceInfo rsi = ris.get(i).serviceInfo;
866 if (rsi.name.equals(si.name) &&
867 rsi.packageName.equals(si.packageName)) {
Dianne Hackborneb034652009-09-07 00:49:58 -0700868 try {
869 wi = new WallpaperInfo(mContext, ris.get(i));
870 } catch (XmlPullParserException e) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700871 if (fromUser) {
872 throw new IllegalArgumentException(e);
873 }
874 Slog.w(TAG, e);
875 return false;
Dianne Hackborneb034652009-09-07 00:49:58 -0700876 } catch (IOException e) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700877 if (fromUser) {
878 throw new IllegalArgumentException(e);
879 }
880 Slog.w(TAG, e);
881 return false;
Dianne Hackborneb034652009-09-07 00:49:58 -0700882 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700883 break;
884 }
885 }
Dianne Hackborneb034652009-09-07 00:49:58 -0700886 if (wi == null) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700887 String msg = "Selected service is not a wallpaper: "
888 + componentName;
889 if (fromUser) {
890 throw new SecurityException(msg);
891 }
892 Slog.w(TAG, msg);
893 return false;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700894 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700895 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700896
897 // Bind the service!
Joe Onorato8a9b2202010-02-26 18:56:32 -0800898 if (DEBUG) Slog.v(TAG, "Binding to:" + componentName);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800899 WallpaperConnection newConn = new WallpaperConnection(wi, wallpaper);
Mike Clerona428b2c2009-11-15 22:53:08 -0800900 intent.setComponent(componentName);
Dianne Hackborndd9b82c2009-09-03 00:18:47 -0700901 intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
902 com.android.internal.R.string.wallpaper_binding_label);
Dianne Hackborn41203752012-08-31 14:05:51 -0700903 intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivityAsUser(
Dianne Hackborneb034652009-09-07 00:49:58 -0700904 mContext, 0,
905 Intent.createChooser(new Intent(Intent.ACTION_SET_WALLPAPER),
906 mContext.getText(com.android.internal.R.string.chooser_wallpaper)),
Dianne Hackborn41203752012-08-31 14:05:51 -0700907 0, null, new UserHandle(serviceUserId)));
Dianne Hackbornc8230512013-07-13 21:32:12 -0700908 if (!mContext.bindServiceAsUser(intent, newConn,
909 Context.BIND_AUTO_CREATE | Context.BIND_SHOWING_UI,
Amith Yamasani27b89e62013-01-16 12:30:11 -0800910 new UserHandle(serviceUserId))) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700911 String msg = "Unable to bind service: "
912 + componentName;
913 if (fromUser) {
914 throw new IllegalArgumentException(msg);
915 }
916 Slog.w(TAG, msg);
917 return false;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700918 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800919 if (wallpaper.userId == mCurrentUserId && mLastWallpaper != null) {
920 detachWallpaperLocked(mLastWallpaper);
921 }
922 wallpaper.wallpaperComponent = componentName;
923 wallpaper.connection = newConn;
924 wallpaper.lastDiedTime = SystemClock.uptimeMillis();
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700925 newConn.mReply = reply;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700926 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800927 if (wallpaper.userId == mCurrentUserId) {
928 if (DEBUG)
929 Slog.v(TAG, "Adding window token: " + newConn.mToken);
930 mIWindowManager.addWindowToken(newConn.mToken,
931 WindowManager.LayoutParams.TYPE_WALLPAPER);
932 mLastWallpaper = wallpaper;
933 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700934 } catch (RemoteException e) {
935 }
Amith Yamasani4e2820c2012-08-28 22:17:23 -0700936 } catch (RemoteException e) {
937 String msg = "Remote exception for " + componentName + "\n" + e;
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700938 if (fromUser) {
939 throw new IllegalArgumentException(msg);
940 }
941 Slog.w(TAG, msg);
942 return false;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700943 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700944 return true;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700945 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800946
947 void detachWallpaperLocked(WallpaperData wallpaper) {
948 if (wallpaper.connection != null) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700949 if (wallpaper.connection.mReply != null) {
950 try {
951 wallpaper.connection.mReply.sendResult(null);
952 } catch (RemoteException e) {
953 }
954 wallpaper.connection.mReply = null;
955 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800956 if (wallpaper.connection.mEngine != null) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700957 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800958 wallpaper.connection.mEngine.destroy();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700959 } catch (RemoteException e) {
960 }
961 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800962 mContext.unbindService(wallpaper.connection);
Dianne Hackborne9e9bca2009-08-18 15:08:22 -0700963 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800964 if (DEBUG)
965 Slog.v(TAG, "Removing window token: " + wallpaper.connection.mToken);
966 mIWindowManager.removeWindowToken(wallpaper.connection.mToken);
Dianne Hackborne9e9bca2009-08-18 15:08:22 -0700967 } catch (RemoteException e) {
968 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800969 wallpaper.connection.mService = null;
970 wallpaper.connection.mEngine = null;
971 wallpaper.connection = null;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700972 }
973 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800974
975 void clearWallpaperComponentLocked(WallpaperData wallpaper) {
976 wallpaper.wallpaperComponent = null;
977 detachWallpaperLocked(wallpaper);
978 }
979
980 void attachServiceLocked(WallpaperConnection conn, WallpaperData wallpaper) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700981 try {
Dianne Hackborn3be63c02009-08-20 19:31:38 -0700982 conn.mService.attach(conn, conn.mToken,
983 WindowManager.LayoutParams.TYPE_WALLPAPER, false,
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800984 wallpaper.width, wallpaper.height);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700985 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800986 Slog.w(TAG, "Failed attaching wallpaper; clearing", e);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800987 if (!wallpaper.wallpaperUpdating) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700988 bindWallpaperComponentLocked(null, false, false, wallpaper, null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800989 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700990 }
991 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800992
993 private void notifyCallbacksLocked(WallpaperData wallpaper) {
994 final int n = wallpaper.callbacks.beginBroadcast();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800995 for (int i = 0; i < n; i++) {
996 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800997 wallpaper.callbacks.getBroadcastItem(i).onWallpaperChanged();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800998 } catch (RemoteException e) {
999
1000 // The RemoteCallbackList will take care of removing
1001 // the dead object for us.
1002 }
1003 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001004 wallpaper.callbacks.finishBroadcast();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001005 final Intent intent = new Intent(Intent.ACTION_WALLPAPER_CHANGED);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001006 mContext.sendBroadcastAsUser(intent, new UserHandle(mCurrentUserId));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001007 }
1008
1009 private void checkPermission(String permission) {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001010 if (PackageManager.PERMISSION_GRANTED!= mContext.checkCallingOrSelfPermission(permission)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001011 throw new SecurityException("Access denied to process: " + Binder.getCallingPid()
1012 + ", must have permission " + permission);
1013 }
1014 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001015
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001016 private static JournaledFile makeJournaledFile(int userId) {
Amith Yamasani61f57372012-08-31 12:12:28 -07001017 final String base = new File(getWallpaperDir(userId), WALLPAPER_INFO).getAbsolutePath();
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001018 return new JournaledFile(new File(base), new File(base + ".tmp"));
1019 }
1020
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001021 private void saveSettingsLocked(WallpaperData wallpaper) {
1022 JournaledFile journal = makeJournaledFile(wallpaper.userId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001023 FileOutputStream stream = null;
1024 try {
1025 stream = new FileOutputStream(journal.chooseForWrite(), false);
1026 XmlSerializer out = new FastXmlSerializer();
1027 out.setOutput(stream, "utf-8");
1028 out.startDocument(null, true);
1029
1030 out.startTag(null, "wp");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001031 out.attribute(null, "width", Integer.toString(wallpaper.width));
1032 out.attribute(null, "height", Integer.toString(wallpaper.height));
1033 out.attribute(null, "name", wallpaper.name);
1034 if (wallpaper.wallpaperComponent != null
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -07001035 && !wallpaper.wallpaperComponent.equals(IMAGE_WALLPAPER)) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001036 out.attribute(null, "component",
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001037 wallpaper.wallpaperComponent.flattenToShortString());
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001038 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001039 out.endTag(null, "wp");
1040
1041 out.endDocument();
1042 stream.close();
1043 journal.commit();
1044 } catch (IOException e) {
1045 try {
1046 if (stream != null) {
1047 stream.close();
1048 }
1049 } catch (IOException ex) {
1050 // Ignore
1051 }
1052 journal.rollback();
1053 }
1054 }
1055
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001056 private void migrateFromOld() {
1057 File oldWallpaper = new File(WallpaperBackupHelper.WALLPAPER_IMAGE_KEY);
1058 File oldInfo = new File(WallpaperBackupHelper.WALLPAPER_INFO_KEY);
1059 if (oldWallpaper.exists()) {
1060 File newWallpaper = new File(getWallpaperDir(0), WALLPAPER);
1061 oldWallpaper.renameTo(newWallpaper);
1062 }
1063 if (oldInfo.exists()) {
1064 File newInfo = new File(getWallpaperDir(0), WALLPAPER_INFO);
1065 oldInfo.renameTo(newInfo);
1066 }
1067 }
1068
1069 private void loadSettingsLocked(int userId) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001070 if (DEBUG) Slog.v(TAG, "loadSettingsLocked");
Mike Clerona428b2c2009-11-15 22:53:08 -08001071
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001072 JournaledFile journal = makeJournaledFile(userId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001073 FileInputStream stream = null;
1074 File file = journal.chooseForRead();
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001075 if (!file.exists()) {
1076 // This should only happen one time, when upgrading from a legacy system
1077 migrateFromOld();
1078 }
1079 WallpaperData wallpaper = mWallpaperMap.get(userId);
1080 if (wallpaper == null) {
1081 wallpaper = new WallpaperData(userId);
1082 mWallpaperMap.put(userId, wallpaper);
1083 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001084 boolean success = false;
1085 try {
1086 stream = new FileInputStream(file);
1087 XmlPullParser parser = Xml.newPullParser();
1088 parser.setInput(stream, null);
1089
1090 int type;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001091 do {
1092 type = parser.next();
1093 if (type == XmlPullParser.START_TAG) {
1094 String tag = parser.getName();
1095 if ("wp".equals(tag)) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001096 wallpaper.width = Integer.parseInt(parser.getAttributeValue(null, "width"));
1097 wallpaper.height = Integer.parseInt(parser
1098 .getAttributeValue(null, "height"));
1099 wallpaper.name = parser.getAttributeValue(null, "name");
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001100 String comp = parser.getAttributeValue(null, "component");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001101 wallpaper.nextWallpaperComponent = comp != null
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001102 ? ComponentName.unflattenFromString(comp)
1103 : null;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001104 if (wallpaper.nextWallpaperComponent == null
1105 || "android".equals(wallpaper.nextWallpaperComponent
1106 .getPackageName())) {
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -07001107 wallpaper.nextWallpaperComponent = IMAGE_WALLPAPER;
Dianne Hackborn9ea31632011-08-05 14:43:50 -07001108 }
Mike Clerona428b2c2009-11-15 22:53:08 -08001109
1110 if (DEBUG) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001111 Slog.v(TAG, "mWidth:" + wallpaper.width);
1112 Slog.v(TAG, "mHeight:" + wallpaper.height);
1113 Slog.v(TAG, "mName:" + wallpaper.name);
1114 Slog.v(TAG, "mNextWallpaperComponent:"
1115 + wallpaper.nextWallpaperComponent);
Mike Clerona428b2c2009-11-15 22:53:08 -08001116 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001117 }
1118 }
1119 } while (type != XmlPullParser.END_DOCUMENT);
1120 success = true;
Dianne Hackborn13579ed2012-11-28 18:05:36 -08001121 } catch (FileNotFoundException e) {
1122 Slog.w(TAG, "no current wallpaper -- first boot?");
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001123 } catch (NullPointerException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001124 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001125 } catch (NumberFormatException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001126 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001127 } catch (XmlPullParserException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001128 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001129 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001130 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001131 } catch (IndexOutOfBoundsException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001132 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001133 }
1134 try {
1135 if (stream != null) {
1136 stream.close();
1137 }
1138 } catch (IOException e) {
1139 // Ignore
1140 }
1141
1142 if (!success) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001143 wallpaper.width = -1;
1144 wallpaper.height = -1;
1145 wallpaper.name = "";
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001146 }
Dianne Hackborn44bc17c2011-04-20 18:18:51 -07001147
1148 // We always want to have some reasonable width hint.
1149 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
1150 Display d = wm.getDefaultDisplay();
1151 int baseSize = d.getMaximumSizeDimension();
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001152 if (wallpaper.width < baseSize) {
1153 wallpaper.width = baseSize;
Dianne Hackborn44bc17c2011-04-20 18:18:51 -07001154 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001155 if (wallpaper.height < baseSize) {
1156 wallpaper.height = baseSize;
Dianne Hackborn44bc17c2011-04-20 18:18:51 -07001157 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001158 }
1159
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07001160 // Called by SystemBackupAgent after files are restored to disk.
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001161 void settingsRestored() {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001162 // TODO: If necessary, make it work for secondary users as well. This currently assumes
1163 // restores only to the primary user
Joe Onorato8a9b2202010-02-26 18:56:32 -08001164 if (DEBUG) Slog.v(TAG, "settingsRestored");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001165 WallpaperData wallpaper = null;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001166 boolean success = false;
1167 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001168 loadSettingsLocked(0);
1169 wallpaper = mWallpaperMap.get(0);
1170 if (wallpaper.nextWallpaperComponent != null
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -07001171 && !wallpaper.nextWallpaperComponent.equals(IMAGE_WALLPAPER)) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001172 if (!bindWallpaperComponentLocked(wallpaper.nextWallpaperComponent, false, false,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001173 wallpaper, null)) {
Christopher Tatee3ab4d02009-12-16 14:03:31 -08001174 // No such live wallpaper or other failure; fall back to the default
1175 // live wallpaper (since the profile being restored indicated that the
1176 // user had selected a live rather than static one).
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001177 bindWallpaperComponentLocked(null, false, false, wallpaper, null);
Christopher Tatee3ab4d02009-12-16 14:03:31 -08001178 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001179 success = true;
1180 } else {
Mike Clerona428b2c2009-11-15 22:53:08 -08001181 // If there's a wallpaper name, we use that. If that can't be loaded, then we
1182 // use the default.
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001183 if ("".equals(wallpaper.name)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001184 if (DEBUG) Slog.v(TAG, "settingsRestored: name is empty");
Mike Clerona428b2c2009-11-15 22:53:08 -08001185 success = true;
1186 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001187 if (DEBUG) Slog.v(TAG, "settingsRestored: attempting to restore named resource");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001188 success = restoreNamedResourceLocked(wallpaper);
Mike Clerona428b2c2009-11-15 22:53:08 -08001189 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08001190 if (DEBUG) Slog.v(TAG, "settingsRestored: success=" + success);
Mike Clerona428b2c2009-11-15 22:53:08 -08001191 if (success) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001192 bindWallpaperComponentLocked(wallpaper.nextWallpaperComponent, false, false,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001193 wallpaper, null);
Mike Clerona428b2c2009-11-15 22:53:08 -08001194 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001195 }
1196 }
1197
1198 if (!success) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001199 Slog.e(TAG, "Failed to restore wallpaper: '" + wallpaper.name + "'");
1200 wallpaper.name = "";
1201 getWallpaperDir(0).delete();
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001202 }
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07001203
1204 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001205 saveSettingsLocked(wallpaper);
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07001206 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001207 }
1208
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001209 boolean restoreNamedResourceLocked(WallpaperData wallpaper) {
1210 if (wallpaper.name.length() > 4 && "res:".equals(wallpaper.name.substring(0, 4))) {
1211 String resName = wallpaper.name.substring(4);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001212
1213 String pkg = null;
1214 int colon = resName.indexOf(':');
1215 if (colon > 0) {
1216 pkg = resName.substring(0, colon);
1217 }
1218
1219 String ident = null;
1220 int slash = resName.lastIndexOf('/');
1221 if (slash > 0) {
1222 ident = resName.substring(slash+1);
1223 }
1224
1225 String type = null;
1226 if (colon > 0 && slash > 0 && (slash-colon) > 1) {
1227 type = resName.substring(colon+1, slash);
1228 }
1229
1230 if (pkg != null && ident != null && type != null) {
1231 int resId = -1;
1232 InputStream res = null;
1233 FileOutputStream fos = null;
1234 try {
1235 Context c = mContext.createPackageContext(pkg, Context.CONTEXT_RESTRICTED);
1236 Resources r = c.getResources();
1237 resId = r.getIdentifier(resName, null, null);
1238 if (resId == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001239 Slog.e(TAG, "couldn't resolve identifier pkg=" + pkg + " type=" + type
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001240 + " ident=" + ident);
1241 return false;
1242 }
1243
1244 res = r.openRawResource(resId);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001245 if (wallpaper.wallpaperFile.exists()) {
1246 wallpaper.wallpaperFile.delete();
Dianne Hackborn1afd1c92010-03-18 22:47:17 -07001247 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001248 fos = new FileOutputStream(wallpaper.wallpaperFile);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001249
1250 byte[] buffer = new byte[32768];
1251 int amt;
1252 while ((amt=res.read(buffer)) > 0) {
1253 fos.write(buffer, 0, amt);
1254 }
1255 // mWallpaperObserver will notice the close and send the change broadcast
1256
Joe Onorato8a9b2202010-02-26 18:56:32 -08001257 Slog.v(TAG, "Restored wallpaper: " + resName);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001258 return true;
1259 } catch (NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001260 Slog.e(TAG, "Package name " + pkg + " not found");
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001261 } catch (Resources.NotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001262 Slog.e(TAG, "Resource not found: " + resId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001263 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001264 Slog.e(TAG, "IOException while restoring wallpaper ", e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001265 } finally {
1266 if (res != null) {
1267 try {
1268 res.close();
1269 } catch (IOException ex) {}
1270 }
1271 if (fos != null) {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07001272 FileUtils.sync(fos);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001273 try {
1274 fos.close();
1275 } catch (IOException ex) {}
1276 }
1277 }
1278 }
1279 }
1280 return false;
1281 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001282
Dianne Hackborneb034652009-09-07 00:49:58 -07001283 @Override
1284 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1285 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
1286 != PackageManager.PERMISSION_GRANTED) {
1287
1288 pw.println("Permission Denial: can't dump wallpaper service from from pid="
1289 + Binder.getCallingPid()
1290 + ", uid=" + Binder.getCallingUid());
1291 return;
1292 }
1293
1294 synchronized (mLock) {
1295 pw.println("Current Wallpaper Service state:");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001296 for (int i = 0; i < mWallpaperMap.size(); i++) {
1297 WallpaperData wallpaper = mWallpaperMap.valueAt(i);
1298 pw.println(" User " + wallpaper.userId + ":");
1299 pw.print(" mWidth=");
1300 pw.print(wallpaper.width);
1301 pw.print(" mHeight=");
1302 pw.println(wallpaper.height);
1303 pw.print(" mName=");
1304 pw.println(wallpaper.name);
1305 pw.print(" mWallpaperComponent=");
1306 pw.println(wallpaper.wallpaperComponent);
1307 if (wallpaper.connection != null) {
1308 WallpaperConnection conn = wallpaper.connection;
1309 pw.print(" Wallpaper connection ");
1310 pw.print(conn);
1311 pw.println(":");
1312 if (conn.mInfo != null) {
1313 pw.print(" mInfo.component=");
1314 pw.println(conn.mInfo.getComponent());
1315 }
1316 pw.print(" mToken=");
1317 pw.println(conn.mToken);
1318 pw.print(" mService=");
1319 pw.println(conn.mService);
1320 pw.print(" mEngine=");
1321 pw.println(conn.mEngine);
1322 pw.print(" mLastDiedTime=");
1323 pw.println(wallpaper.lastDiedTime - SystemClock.uptimeMillis());
1324 }
Dianne Hackborneb034652009-09-07 00:49:58 -07001325 }
1326 }
1327 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001328}