blob: e6b6b93a1d466dce017b368138833fbc95ceb5cd [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;
John Spurlock41f64642013-11-04 13:48:38 -050043import android.graphics.Point;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044import android.os.Binder;
Dianne Hackborn284ac932009-08-28 10:34:25 -070045import android.os.Bundle;
Amith Yamasani13593602012-03-22 16:16:17 -070046import android.os.Environment;
Dianne Hackborn8bdf5932010-10-15 12:54:40 -070047import android.os.FileUtils;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070048import android.os.IBinder;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -070049import android.os.IRemoteCallback;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.os.RemoteException;
51import android.os.FileObserver;
52import android.os.ParcelFileDescriptor;
53import android.os.RemoteCallbackList;
rpcraig554cb0c2012-07-05 06:41:43 -040054import android.os.SELinux;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070055import android.os.ServiceManager;
Dianne Hackborn0cd48872009-08-13 18:51:59 -070056import android.os.SystemClock;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070057import android.os.UserHandle;
Amith Yamasani6474c4c2012-10-04 14:55:42 -070058import android.os.UserManager;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070059import android.service.wallpaper.IWallpaperConnection;
60import android.service.wallpaper.IWallpaperEngine;
61import android.service.wallpaper.IWallpaperService;
62import android.service.wallpaper.WallpaperService;
Joe Onorato8a9b2202010-02-26 18:56:32 -080063import android.util.Slog;
Amith Yamasani37ce3a82012-02-06 12:04:42 -080064import android.util.SparseArray;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070065import android.util.Xml;
Dianne Hackborn44bc17c2011-04-20 18:18:51 -070066import android.view.Display;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070067import android.view.IWindowManager;
68import android.view.WindowManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069
Dianne Hackborneb034652009-09-07 00:49:58 -070070import java.io.FileDescriptor;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070071import java.io.IOException;
72import java.io.InputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073import java.io.File;
74import java.io.FileNotFoundException;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070075import java.io.FileInputStream;
76import java.io.FileOutputStream;
Dianne Hackborneb034652009-09-07 00:49:58 -070077import java.io.PrintWriter;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070078import java.util.List;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070079
80import org.xmlpull.v1.XmlPullParser;
81import org.xmlpull.v1.XmlPullParserException;
82import org.xmlpull.v1.XmlSerializer;
83
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080084import com.android.internal.content.PackageMonitor;
Dianne Hackborn2269d1572010-02-24 19:54:22 -080085import com.android.internal.util.FastXmlSerializer;
Dianne Hackborn1afd1c92010-03-18 22:47:17 -070086import com.android.internal.util.JournaledFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070088class WallpaperManagerService extends IWallpaperManager.Stub {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070089 static final String TAG = "WallpaperService";
Dianne Hackborncbf15042009-08-18 18:29:09 -070090 static final boolean DEBUG = false;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070091
Romain Guy407ec782011-08-24 17:06:58 -070092 final Object mLock = new Object[0];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093
Dianne Hackborn0cd48872009-08-13 18:51:59 -070094 /**
95 * Minimum time between crashes of a wallpaper service for us to consider
96 * restarting it vs. just reverting to the static wallpaper.
97 */
98 static final long MIN_WALLPAPER_CRASH_TIME = 10000;
Dianne Hackborn0cd48872009-08-13 18:51:59 -070099 static final String WALLPAPER = "wallpaper";
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800100 static final String WALLPAPER_INFO = "wallpaper_info.xml";
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700101
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102 /**
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -0700103 * Name of the component used to display bitmap wallpapers from either the gallery or
104 * built-in wallpapers.
105 */
106 static final ComponentName IMAGE_WALLPAPER = new ComponentName("com.android.systemui",
107 "com.android.systemui.ImageWallpaper");
108
109 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110 * Observes the wallpaper for changes and notifies all IWallpaperServiceCallbacks
111 * that the wallpaper has changed. The CREATE is triggered when there is no
112 * wallpaper set and is created for the first time. The CLOSE_WRITE is triggered
113 * everytime the wallpaper is changed.
114 */
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800115 private class WallpaperObserver extends FileObserver {
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700116
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800117 final WallpaperData mWallpaper;
118 final File mWallpaperDir;
119 final File mWallpaperFile;
120
121 public WallpaperObserver(WallpaperData wallpaper) {
122 super(getWallpaperDir(wallpaper.userId).getAbsolutePath(),
123 CLOSE_WRITE | DELETE | DELETE_SELF);
124 mWallpaperDir = getWallpaperDir(wallpaper.userId);
125 mWallpaper = wallpaper;
126 mWallpaperFile = new File(mWallpaperDir, WALLPAPER);
127 }
128
129 @Override
130 public void onEvent(int event, String path) {
131 if (path == null) {
132 return;
133 }
134 synchronized (mLock) {
135 // changing the wallpaper means we'll need to back up the new one
136 long origId = Binder.clearCallingIdentity();
137 BackupManager bm = new BackupManager(mContext);
138 bm.dataChanged();
139 Binder.restoreCallingIdentity(origId);
140
141 File changedFile = new File(mWallpaperDir, path);
142 if (mWallpaperFile.equals(changedFile)) {
143 notifyCallbacksLocked(mWallpaper);
144 if (mWallpaper.wallpaperComponent == null || event != CLOSE_WRITE
145 || mWallpaper.imageWallpaperPending) {
146 if (event == CLOSE_WRITE) {
147 mWallpaper.imageWallpaperPending = false;
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700148 }
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -0700149 bindWallpaperComponentLocked(IMAGE_WALLPAPER, true,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700150 false, mWallpaper, null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800151 saveSettingsLocked(mWallpaper);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800152 }
153 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800154 }
155 }
156 }
157
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700158 final Context mContext;
159 final IWindowManager mIWindowManager;
Amith Yamasani4e2820c2012-08-28 22:17:23 -0700160 final IPackageManager mIPackageManager;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800161 final MyPackageMonitor mMonitor;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800162 WallpaperData mLastWallpaper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800163
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800164 SparseArray<WallpaperData> mWallpaperMap = new SparseArray<WallpaperData>();
Dianne Hackborn07213e62011-08-24 20:05:39 -0700165
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800166 int mCurrentUserId;
Dianne Hackborn07213e62011-08-24 20:05:39 -0700167
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800168 static class WallpaperData {
169
170 int userId;
171
172 File wallpaperFile;
173
174 /**
175 * Client is currently writing a new image wallpaper.
176 */
177 boolean imageWallpaperPending;
178
179 /**
180 * Resource name if using a picture from the wallpaper gallery
181 */
182 String name = "";
183
184 /**
185 * The component name of the currently set live wallpaper.
186 */
187 ComponentName wallpaperComponent;
188
189 /**
190 * The component name of the wallpaper that should be set next.
191 */
192 ComponentName nextWallpaperComponent;
193
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800194 WallpaperConnection connection;
195 long lastDiedTime;
196 boolean wallpaperUpdating;
197 WallpaperObserver wallpaperObserver;
198
199 /**
200 * List of callbacks registered they should each be notified when the wallpaper is changed.
201 */
202 private RemoteCallbackList<IWallpaperManagerCallback> callbacks
203 = new RemoteCallbackList<IWallpaperManagerCallback>();
204
205 int width = -1;
206 int height = -1;
207
208 WallpaperData(int userId) {
209 this.userId = userId;
210 wallpaperFile = new File(getWallpaperDir(userId), WALLPAPER);
211 }
212 }
213
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700214 class WallpaperConnection extends IWallpaperConnection.Stub
215 implements ServiceConnection {
Dianne Hackborneb034652009-09-07 00:49:58 -0700216 final WallpaperInfo mInfo;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700217 final Binder mToken = new Binder();
218 IWallpaperService mService;
219 IWallpaperEngine mEngine;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800220 WallpaperData mWallpaper;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700221 IRemoteCallback mReply;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800222
Michael Wright5203a8b2013-10-03 14:16:42 -0700223 boolean mDimensionsChanged = false;
224
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800225 public WallpaperConnection(WallpaperInfo info, WallpaperData wallpaper) {
Dianne Hackborneb034652009-09-07 00:49:58 -0700226 mInfo = info;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800227 mWallpaper = wallpaper;
Dianne Hackborneb034652009-09-07 00:49:58 -0700228 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700229
230 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700231 public void onServiceConnected(ComponentName name, IBinder service) {
232 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800233 if (mWallpaper.connection == this) {
234 mWallpaper.lastDiedTime = SystemClock.uptimeMillis();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700235 mService = IWallpaperService.Stub.asInterface(service);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800236 attachServiceLocked(this, mWallpaper);
Dianne Hackborneb034652009-09-07 00:49:58 -0700237 // XXX should probably do saveSettingsLocked() later
238 // when we have an engine, but I'm not sure about
239 // locking there and anyway we always need to be able to
240 // recover if there is something wrong.
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800241 saveSettingsLocked(mWallpaper);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700242 }
243 }
244 }
245
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700246 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700247 public void onServiceDisconnected(ComponentName name) {
248 synchronized (mLock) {
249 mService = null;
250 mEngine = null;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800251 if (mWallpaper.connection == this) {
252 Slog.w(TAG, "Wallpaper service gone: " + mWallpaper.wallpaperComponent);
253 if (!mWallpaper.wallpaperUpdating
254 && (mWallpaper.lastDiedTime + MIN_WALLPAPER_CRASH_TIME)
255 > SystemClock.uptimeMillis()
256 && mWallpaper.userId == mCurrentUserId) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800257 Slog.w(TAG, "Reverting to built-in wallpaper!");
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700258 clearWallpaperLocked(true, mWallpaper.userId, null);
Dianne Hackborn0cd48872009-08-13 18:51:59 -0700259 }
260 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700261 }
262 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800263
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700264 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700265 public void attachEngine(IWallpaperEngine engine) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700266 synchronized (mLock) {
267 mEngine = engine;
Michael Wright5203a8b2013-10-03 14:16:42 -0700268 if (mDimensionsChanged) {
269 try {
270 mEngine.setDesiredSize(mWallpaper.width, mWallpaper.height);
271 } catch (RemoteException e) {
272 Slog.w(TAG, "Failed to set wallpaper dimensions", e);
273 }
274 mDimensionsChanged = false;
275 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700276 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700277 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800278
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700279 @Override
280 public void engineShown(IWallpaperEngine engine) {
281 synchronized (mLock) {
282 if (mReply != null) {
283 long ident = Binder.clearCallingIdentity();
284 try {
285 mReply.sendResult(null);
286 } catch (RemoteException e) {
287 Binder.restoreCallingIdentity(ident);
288 }
289 mReply = null;
290 }
291 }
292 }
293
294 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700295 public ParcelFileDescriptor setWallpaper(String name) {
296 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800297 if (mWallpaper.connection == this) {
298 return updateWallpaperBitmapLocked(name, mWallpaper);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700299 }
300 return null;
301 }
302 }
303 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800304
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800305 class MyPackageMonitor extends PackageMonitor {
306 @Override
307 public void onPackageUpdateFinished(String packageName, int uid) {
308 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700309 if (mCurrentUserId != getChangingUserId()) {
310 return;
311 }
312 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
313 if (wallpaper != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800314 if (wallpaper.wallpaperComponent != null
315 && wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
316 wallpaper.wallpaperUpdating = false;
317 ComponentName comp = wallpaper.wallpaperComponent;
318 clearWallpaperComponentLocked(wallpaper);
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700319 if (!bindWallpaperComponentLocked(comp, false, false,
320 wallpaper, null)) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800321 Slog.w(TAG, "Wallpaper no longer available; reverting to default");
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700322 clearWallpaperLocked(false, wallpaper.userId, null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800323 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700324 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800325 }
326 }
327 }
328
329 @Override
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700330 public void onPackageModified(String packageName) {
331 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700332 if (mCurrentUserId != getChangingUserId()) {
333 return;
334 }
335 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
336 if (wallpaper != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800337 if (wallpaper.wallpaperComponent == null
338 || !wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700339 return;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800340 }
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700341 doPackagesChangedLocked(true, wallpaper);
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700342 }
343 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700344 }
345
346 @Override
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800347 public void onPackageUpdateStarted(String packageName, int uid) {
348 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700349 if (mCurrentUserId != getChangingUserId()) {
350 return;
351 }
352 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
353 if (wallpaper != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800354 if (wallpaper.wallpaperComponent != null
355 && wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
356 wallpaper.wallpaperUpdating = true;
357 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800358 }
359 }
360 }
361
362 @Override
363 public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700364 synchronized (mLock) {
365 boolean changed = false;
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700366 if (mCurrentUserId != getChangingUserId()) {
367 return false;
368 }
369 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
370 if (wallpaper != null) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700371 boolean res = doPackagesChangedLocked(doit, wallpaper);
372 changed |= res;
373 }
374 return changed;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800375 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800376 }
377
378 @Override
379 public void onSomePackagesChanged() {
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700380 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700381 if (mCurrentUserId != getChangingUserId()) {
382 return;
383 }
384 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
385 if (wallpaper != null) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700386 doPackagesChangedLocked(true, wallpaper);
387 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800388 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800389 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800390
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700391 boolean doPackagesChangedLocked(boolean doit, WallpaperData wallpaper) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800392 boolean changed = false;
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700393 if (wallpaper.wallpaperComponent != null) {
394 int change = isPackageDisappearing(wallpaper.wallpaperComponent
395 .getPackageName());
396 if (change == PACKAGE_PERMANENT_CHANGE
397 || change == PACKAGE_TEMPORARY_CHANGE) {
398 changed = true;
399 if (doit) {
400 Slog.w(TAG, "Wallpaper uninstalled, removing: "
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800401 + wallpaper.wallpaperComponent);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700402 clearWallpaperLocked(false, wallpaper.userId, null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800403 }
404 }
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700405 }
406 if (wallpaper.nextWallpaperComponent != null) {
407 int change = isPackageDisappearing(wallpaper.nextWallpaperComponent
408 .getPackageName());
409 if (change == PACKAGE_PERMANENT_CHANGE
410 || change == PACKAGE_TEMPORARY_CHANGE) {
411 wallpaper.nextWallpaperComponent = null;
412 }
413 }
414 if (wallpaper.wallpaperComponent != null
415 && isPackageModified(wallpaper.wallpaperComponent.getPackageName())) {
416 try {
417 mContext.getPackageManager().getServiceInfo(
418 wallpaper.wallpaperComponent, 0);
419 } catch (NameNotFoundException e) {
420 Slog.w(TAG, "Wallpaper component gone, removing: "
421 + wallpaper.wallpaperComponent);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700422 clearWallpaperLocked(false, wallpaper.userId, null);
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700423 }
424 }
425 if (wallpaper.nextWallpaperComponent != null
426 && isPackageModified(wallpaper.nextWallpaperComponent.getPackageName())) {
427 try {
428 mContext.getPackageManager().getServiceInfo(
429 wallpaper.nextWallpaperComponent, 0);
430 } catch (NameNotFoundException e) {
431 wallpaper.nextWallpaperComponent = null;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800432 }
433 }
434 return changed;
435 }
436 }
437
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700438 public WallpaperManagerService(Context context) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800439 if (DEBUG) Slog.v(TAG, "WallpaperService startup");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800440 mContext = context;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700441 mIWindowManager = IWindowManager.Stub.asInterface(
442 ServiceManager.getService(Context.WINDOW_SERVICE));
Amith Yamasani4e2820c2012-08-28 22:17:23 -0700443 mIPackageManager = AppGlobals.getPackageManager();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800444 mMonitor = new MyPackageMonitor();
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700445 mMonitor.register(context, null, UserHandle.ALL, true);
Amith Yamasani61f57372012-08-31 12:12:28 -0700446 getWallpaperDir(UserHandle.USER_OWNER).mkdirs();
447 loadSettingsLocked(UserHandle.USER_OWNER);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800448 }
449
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800450 private static File getWallpaperDir(int userId) {
Amith Yamasani61f57372012-08-31 12:12:28 -0700451 return Environment.getUserSystemDirectory(userId);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800452 }
453
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800454 @Override
455 protected void finalize() throws Throwable {
456 super.finalize();
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800457 for (int i = 0; i < mWallpaperMap.size(); i++) {
458 WallpaperData wallpaper = mWallpaperMap.valueAt(i);
459 wallpaper.wallpaperObserver.stopWatching();
460 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800461 }
Amith Yamasani13593602012-03-22 16:16:17 -0700462
Svetoslav Ganova0027152013-06-25 14:59:53 -0700463 public void systemRunning() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800464 if (DEBUG) Slog.v(TAG, "systemReady");
Amith Yamasani61f57372012-08-31 12:12:28 -0700465 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.USER_OWNER);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700466 switchWallpaper(wallpaper, null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800467 wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper);
468 wallpaper.wallpaperObserver.startWatching();
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800469
Amith Yamasani13593602012-03-22 16:16:17 -0700470 IntentFilter userFilter = new IntentFilter();
Amith Yamasani13593602012-03-22 16:16:17 -0700471 userFilter.addAction(Intent.ACTION_USER_REMOVED);
Amith Yamasani756901d2012-10-12 12:30:07 -0700472 userFilter.addAction(Intent.ACTION_USER_STOPPING);
Amith Yamasani13593602012-03-22 16:16:17 -0700473 mContext.registerReceiver(new BroadcastReceiver() {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800474 @Override
Amith Yamasani13593602012-03-22 16:16:17 -0700475 public void onReceive(Context context, Intent intent) {
476 String action = intent.getAction();
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700477 if (Intent.ACTION_USER_REMOVED.equals(action)) {
Amith Yamasani756901d2012-10-12 12:30:07 -0700478 onRemoveUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
479 UserHandle.USER_NULL));
Amith Yamasani13593602012-03-22 16:16:17 -0700480 }
Amith Yamasani0c293712012-10-30 12:23:52 -0700481 // TODO: Race condition causing problems when cleaning up on stopping a user.
482 // Comment this out for now.
483 // else if (Intent.ACTION_USER_STOPPING.equals(action)) {
484 // onStoppingUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
485 // UserHandle.USER_NULL));
486 // }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800487 }
Amith Yamasani13593602012-03-22 16:16:17 -0700488 }, userFilter);
Amith Yamasani756901d2012-10-12 12:30:07 -0700489
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700490 try {
491 ActivityManagerNative.getDefault().registerUserSwitchObserver(
492 new IUserSwitchObserver.Stub() {
493 @Override
494 public void onUserSwitching(int newUserId, IRemoteCallback reply) {
495 switchUser(newUserId, reply);
496 }
497
498 @Override
499 public void onUserSwitchComplete(int newUserId) throws RemoteException {
500 }
501 });
502 } catch (RemoteException e) {
503 // TODO Auto-generated catch block
504 e.printStackTrace();
505 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800506 }
507
508 String getName() {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700509 synchronized (mLock) {
510 return mWallpaperMap.get(0).name;
511 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800512 }
513
Amith Yamasani756901d2012-10-12 12:30:07 -0700514 void onStoppingUser(int userId) {
515 if (userId < 1) return;
Amith Yamasani13593602012-03-22 16:16:17 -0700516 synchronized (mLock) {
517 WallpaperData wallpaper = mWallpaperMap.get(userId);
518 if (wallpaper != null) {
Amith Yamasani756901d2012-10-12 12:30:07 -0700519 if (wallpaper.wallpaperObserver != null) {
520 wallpaper.wallpaperObserver.stopWatching();
521 wallpaper.wallpaperObserver = null;
522 }
Amith Yamasani13593602012-03-22 16:16:17 -0700523 mWallpaperMap.remove(userId);
524 }
Amith Yamasani756901d2012-10-12 12:30:07 -0700525 }
526 }
527
528 void onRemoveUser(int userId) {
529 if (userId < 1) return;
530 synchronized (mLock) {
531 onStoppingUser(userId);
Amith Yamasani13593602012-03-22 16:16:17 -0700532 File wallpaperFile = new File(getWallpaperDir(userId), WALLPAPER);
533 wallpaperFile.delete();
534 File wallpaperInfoFile = new File(getWallpaperDir(userId), WALLPAPER_INFO);
535 wallpaperInfoFile.delete();
536 }
537 }
538
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700539 void switchUser(int userId, IRemoteCallback reply) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800540 synchronized (mLock) {
541 mCurrentUserId = userId;
542 WallpaperData wallpaper = mWallpaperMap.get(userId);
543 if (wallpaper == null) {
544 wallpaper = new WallpaperData(userId);
545 mWallpaperMap.put(userId, wallpaper);
546 loadSettingsLocked(userId);
Amith Yamasani6474c4c2012-10-04 14:55:42 -0700547 }
548 // Not started watching yet, in case wallpaper data was loaded for other reasons.
549 if (wallpaper.wallpaperObserver == null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800550 wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper);
551 wallpaper.wallpaperObserver.startWatching();
552 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700553 switchWallpaper(wallpaper, reply);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800554 }
555 }
556
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700557 void switchWallpaper(WallpaperData wallpaper, IRemoteCallback reply) {
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700558 synchronized (mLock) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700559 RuntimeException e = null;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700560 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800561 ComponentName cname = wallpaper.wallpaperComponent != null ?
562 wallpaper.wallpaperComponent : wallpaper.nextWallpaperComponent;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700563 if (bindWallpaperComponentLocked(cname, true, false, wallpaper, reply)) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700564 return;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700565 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700566 } catch (RuntimeException e1) {
567 e = e1;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700568 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700569 Slog.w(TAG, "Failure starting previous wallpaper", e);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700570 clearWallpaperLocked(false, wallpaper.userId, reply);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800571 }
572 }
573
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800574 public void clearWallpaper() {
575 if (DEBUG) Slog.v(TAG, "clearWallpaper");
576 synchronized (mLock) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700577 clearWallpaperLocked(false, UserHandle.getCallingUserId(), null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800578 }
579 }
580
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700581 void clearWallpaperLocked(boolean defaultFailed, int userId, IRemoteCallback reply) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800582 WallpaperData wallpaper = mWallpaperMap.get(userId);
583 File f = new File(getWallpaperDir(userId), WALLPAPER);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800584 if (f.exists()) {
585 f.delete();
586 }
587 final long ident = Binder.clearCallingIdentity();
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700588 RuntimeException e = null;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800589 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800590 wallpaper.imageWallpaperPending = false;
591 if (userId != mCurrentUserId) return;
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700592 if (bindWallpaperComponentLocked(defaultFailed
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -0700593 ? IMAGE_WALLPAPER
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700594 : null, true, false, wallpaper, reply)) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700595 return;
596 }
597 } catch (IllegalArgumentException e1) {
598 e = e1;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800599 } finally {
600 Binder.restoreCallingIdentity(ident);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800601 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700602
603 // This can happen if the default wallpaper component doesn't
604 // exist. This should be a system configuration problem, but
605 // let's not let it crash the system and just live with no
606 // wallpaper.
607 Slog.e(TAG, "Default wallpaper component not found!", e);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800608 clearWallpaperComponentLocked(wallpaper);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700609 if (reply != null) {
610 try {
611 reply.sendResult(null);
612 } catch (RemoteException e1) {
613 }
614 }
615 }
616
617 public boolean hasNamedWallpaper(String name) {
618 synchronized (mLock) {
Amith Yamasani6474c4c2012-10-04 14:55:42 -0700619 List<UserInfo> users;
620 long ident = Binder.clearCallingIdentity();
621 try {
622 users = ((UserManager) mContext.getSystemService(Context.USER_SERVICE)).getUsers();
623 } finally {
624 Binder.restoreCallingIdentity(ident);
625 }
626 for (UserInfo user: users) {
627 WallpaperData wd = mWallpaperMap.get(user.id);
628 if (wd == null) {
629 // User hasn't started yet, so load her settings to peek at the wallpaper
630 loadSettingsLocked(user.id);
631 wd = mWallpaperMap.get(user.id);
632 }
633 if (wd != null && name.equals(wd.name)) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700634 return true;
635 }
636 }
637 }
638 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800639 }
640
John Spurlock41f64642013-11-04 13:48:38 -0500641 private Point getDefaultDisplaySize() {
642 Point p = new Point();
John Spurlockd6e836c2013-11-18 14:14:49 -0500643 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
644 Display d = wm.getDefaultDisplay();
645 d.getRealSize(p);
John Spurlock41f64642013-11-04 13:48:38 -0500646 return p;
647 }
648
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800649 public void setDimensionHints(int width, int height) throws RemoteException {
650 checkPermission(android.Manifest.permission.SET_WALLPAPER_HINTS);
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700651 synchronized (mLock) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700652 int userId = UserHandle.getCallingUserId();
653 WallpaperData wallpaper = mWallpaperMap.get(userId);
654 if (wallpaper == null) {
655 throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
656 }
657 if (width <= 0 || height <= 0) {
658 throw new IllegalArgumentException("width and height must be > 0");
659 }
John Spurlock41f64642013-11-04 13:48:38 -0500660 // Make sure it is at least as large as the display.
661 Point displaySize = getDefaultDisplaySize();
662 width = Math.max(width, displaySize.x);
663 height = Math.max(height, displaySize.y);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700664
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800665 if (width != wallpaper.width || height != wallpaper.height) {
666 wallpaper.width = width;
667 wallpaper.height = height;
668 saveSettingsLocked(wallpaper);
669 if (mCurrentUserId != userId) return; // Don't change the properties now
670 if (wallpaper.connection != null) {
671 if (wallpaper.connection.mEngine != null) {
Dianne Hackborn284ac932009-08-28 10:34:25 -0700672 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800673 wallpaper.connection.mEngine.setDesiredSize(
Dianne Hackborn284ac932009-08-28 10:34:25 -0700674 width, height);
675 } catch (RemoteException e) {
676 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800677 notifyCallbacksLocked(wallpaper);
Michael Wright5203a8b2013-10-03 14:16:42 -0700678 } else if (wallpaper.connection.mService != null) {
679 // We've attached to the service but the engine hasn't attached back to us
680 // yet. This means it will be created with the previous dimensions, so we
681 // need to update it to the new dimensions once it attaches.
682 wallpaper.connection.mDimensionsChanged = true;
Dianne Hackborn284ac932009-08-28 10:34:25 -0700683 }
684 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700685 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800686 }
687 }
688
689 public int getWidthHint() throws RemoteException {
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700690 synchronized (mLock) {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700691 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.getCallingUserId());
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800692 return wallpaper.width;
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700693 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800694 }
695
696 public int getHeightHint() throws RemoteException {
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700697 synchronized (mLock) {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700698 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.getCallingUserId());
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800699 return wallpaper.height;
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700700 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800701 }
702
Dianne Hackborn284ac932009-08-28 10:34:25 -0700703 public ParcelFileDescriptor getWallpaper(IWallpaperManagerCallback cb,
704 Bundle outParams) {
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700705 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800706 // This returns the current user's wallpaper, if called by a system service. Else it
707 // returns the wallpaper for the calling user.
708 int callingUid = Binder.getCallingUid();
709 int wallpaperUserId = 0;
710 if (callingUid == android.os.Process.SYSTEM_UID) {
711 wallpaperUserId = mCurrentUserId;
712 } else {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700713 wallpaperUserId = UserHandle.getUserId(callingUid);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800714 }
715 WallpaperData wallpaper = mWallpaperMap.get(wallpaperUserId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700716 try {
Dianne Hackborn284ac932009-08-28 10:34:25 -0700717 if (outParams != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800718 outParams.putInt("width", wallpaper.width);
719 outParams.putInt("height", wallpaper.height);
Dianne Hackborn284ac932009-08-28 10:34:25 -0700720 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800721 wallpaper.callbacks.register(cb);
722 File f = new File(getWallpaperDir(wallpaperUserId), WALLPAPER);
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700723 if (!f.exists()) {
724 return null;
725 }
726 return ParcelFileDescriptor.open(f, MODE_READ_ONLY);
727 } catch (FileNotFoundException e) {
728 /* Shouldn't happen as we check to see if the file exists */
Joe Onorato8a9b2202010-02-26 18:56:32 -0800729 Slog.w(TAG, "Error getting wallpaper", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800730 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700731 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800732 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800733 }
734
Dianne Hackborneb034652009-09-07 00:49:58 -0700735 public WallpaperInfo getWallpaperInfo() {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700736 int userId = UserHandle.getCallingUserId();
Dianne Hackborneb034652009-09-07 00:49:58 -0700737 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800738 WallpaperData wallpaper = mWallpaperMap.get(userId);
739 if (wallpaper.connection != null) {
740 return wallpaper.connection.mInfo;
Dianne Hackborneb034652009-09-07 00:49:58 -0700741 }
742 return null;
743 }
744 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800745
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700746 public ParcelFileDescriptor setWallpaper(String name) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800747 checkPermission(android.Manifest.permission.SET_WALLPAPER);
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700748 synchronized (mLock) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700749 if (DEBUG) Slog.v(TAG, "setWallpaper");
750 int userId = UserHandle.getCallingUserId();
751 WallpaperData wallpaper = mWallpaperMap.get(userId);
752 if (wallpaper == null) {
753 throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
754 }
Dianne Hackborn0cd48872009-08-13 18:51:59 -0700755 final long ident = Binder.clearCallingIdentity();
756 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800757 ParcelFileDescriptor pfd = updateWallpaperBitmapLocked(name, wallpaper);
Dianne Hackborn0cd48872009-08-13 18:51:59 -0700758 if (pfd != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800759 wallpaper.imageWallpaperPending = true;
Dianne Hackborn0cd48872009-08-13 18:51:59 -0700760 }
761 return pfd;
762 } finally {
763 Binder.restoreCallingIdentity(ident);
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700764 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800765 }
766 }
767
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800768 ParcelFileDescriptor updateWallpaperBitmapLocked(String name, WallpaperData wallpaper) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700769 if (name == null) name = "";
770 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800771 File dir = getWallpaperDir(wallpaper.userId);
772 if (!dir.exists()) {
773 dir.mkdir();
Dianne Hackbornebac48c2011-11-29 18:01:50 -0800774 FileUtils.setPermissions(
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800775 dir.getPath(),
Dianne Hackbornebac48c2011-11-29 18:01:50 -0800776 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
777 -1, -1);
778 }
rpcraig554cb0c2012-07-05 06:41:43 -0400779 File file = new File(dir, WALLPAPER);
780 ParcelFileDescriptor fd = ParcelFileDescriptor.open(file,
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700781 MODE_CREATE|MODE_READ_WRITE);
rpcraig554cb0c2012-07-05 06:41:43 -0400782 if (!SELinux.restorecon(file)) {
783 return null;
784 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800785 wallpaper.name = name;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700786 return fd;
787 } catch (FileNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800788 Slog.w(TAG, "Error setting wallpaper", e);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700789 }
790 return null;
791 }
792
793 public void setWallpaperComponent(ComponentName name) {
794 checkPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT);
795 synchronized (mLock) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700796 if (DEBUG) Slog.v(TAG, "setWallpaperComponent name=" + name);
797 int userId = UserHandle.getCallingUserId();
798 WallpaperData wallpaper = mWallpaperMap.get(userId);
799 if (wallpaper == null) {
800 throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
801 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700802 final long ident = Binder.clearCallingIdentity();
803 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800804 wallpaper.imageWallpaperPending = false;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700805 bindWallpaperComponentLocked(name, false, true, wallpaper, null);
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700806 } finally {
807 Binder.restoreCallingIdentity(ident);
808 }
809 }
810 }
811
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800812 boolean bindWallpaperComponentLocked(ComponentName componentName, boolean force,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700813 boolean fromUser, WallpaperData wallpaper, IRemoteCallback reply) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800814 if (DEBUG) Slog.v(TAG, "bindWallpaperComponentLocked: componentName=" + componentName);
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700815 // Has the component changed?
Dianne Hackborn9ea31632011-08-05 14:43:50 -0700816 if (!force) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800817 if (wallpaper.connection != null) {
818 if (wallpaper.wallpaperComponent == null) {
Dianne Hackborn9ea31632011-08-05 14:43:50 -0700819 if (componentName == null) {
820 if (DEBUG) Slog.v(TAG, "bindWallpaperComponentLocked: still using default");
821 // Still using default wallpaper.
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700822 return true;
Dianne Hackborn9ea31632011-08-05 14:43:50 -0700823 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800824 } else if (wallpaper.wallpaperComponent.equals(componentName)) {
Dianne Hackborn9ea31632011-08-05 14:43:50 -0700825 // Changing to same wallpaper.
826 if (DEBUG) Slog.v(TAG, "same wallpaper");
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700827 return true;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700828 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700829 }
830 }
831
832 try {
Mike Clerona428b2c2009-11-15 22:53:08 -0800833 if (componentName == null) {
Mike Cleron322b6ee2009-11-12 07:45:47 -0800834 String defaultComponent =
835 mContext.getString(com.android.internal.R.string.default_wallpaper_component);
Mike Clerona428b2c2009-11-15 22:53:08 -0800836 if (defaultComponent != null) {
Mike Cleron322b6ee2009-11-12 07:45:47 -0800837 // See if there is a default wallpaper component specified
Mike Clerona428b2c2009-11-15 22:53:08 -0800838 componentName = ComponentName.unflattenFromString(defaultComponent);
Joe Onorato8a9b2202010-02-26 18:56:32 -0800839 if (DEBUG) Slog.v(TAG, "Use default component wallpaper:" + componentName);
Mike Cleron322b6ee2009-11-12 07:45:47 -0800840 }
Mike Clerona428b2c2009-11-15 22:53:08 -0800841 if (componentName == null) {
Mike Cleron322b6ee2009-11-12 07:45:47 -0800842 // Fall back to static image wallpaper
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -0700843 componentName = IMAGE_WALLPAPER;
Mike Cleron322b6ee2009-11-12 07:45:47 -0800844 //clearWallpaperComponentLocked();
845 //return;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800846 if (DEBUG) Slog.v(TAG, "Using image wallpaper");
Mike Cleron322b6ee2009-11-12 07:45:47 -0800847 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700848 }
Amith Yamasani4e2820c2012-08-28 22:17:23 -0700849 int serviceUserId = wallpaper.userId;
850 ServiceInfo si = mIPackageManager.getServiceInfo(componentName,
851 PackageManager.GET_META_DATA | PackageManager.GET_PERMISSIONS, serviceUserId);
Christopher Tate90952202013-09-08 13:01:28 -0700852 if (si == null) {
853 // The wallpaper component we're trying to use doesn't exist
854 Slog.w(TAG, "Attempted wallpaper " + componentName + " is unavailable");
855 return false;
856 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700857 if (!android.Manifest.permission.BIND_WALLPAPER.equals(si.permission)) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700858 String msg = "Selected service does not require "
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700859 + android.Manifest.permission.BIND_WALLPAPER
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700860 + ": " + componentName;
861 if (fromUser) {
862 throw new SecurityException(msg);
863 }
864 Slog.w(TAG, msg);
865 return false;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700866 }
867
Dianne Hackborneb034652009-09-07 00:49:58 -0700868 WallpaperInfo wi = null;
869
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700870 Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -0700871 if (componentName != null && !componentName.equals(IMAGE_WALLPAPER)) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700872 // Make sure the selected service is actually a wallpaper service.
Amith Yamasani4e2820c2012-08-28 22:17:23 -0700873 List<ResolveInfo> ris =
874 mIPackageManager.queryIntentServices(intent,
875 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
876 PackageManager.GET_META_DATA, serviceUserId);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700877 for (int i=0; i<ris.size(); i++) {
878 ServiceInfo rsi = ris.get(i).serviceInfo;
879 if (rsi.name.equals(si.name) &&
880 rsi.packageName.equals(si.packageName)) {
Dianne Hackborneb034652009-09-07 00:49:58 -0700881 try {
882 wi = new WallpaperInfo(mContext, ris.get(i));
883 } catch (XmlPullParserException e) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700884 if (fromUser) {
885 throw new IllegalArgumentException(e);
886 }
887 Slog.w(TAG, e);
888 return false;
Dianne Hackborneb034652009-09-07 00:49:58 -0700889 } catch (IOException e) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700890 if (fromUser) {
891 throw new IllegalArgumentException(e);
892 }
893 Slog.w(TAG, e);
894 return false;
Dianne Hackborneb034652009-09-07 00:49:58 -0700895 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700896 break;
897 }
898 }
Dianne Hackborneb034652009-09-07 00:49:58 -0700899 if (wi == null) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700900 String msg = "Selected service is not a wallpaper: "
901 + componentName;
902 if (fromUser) {
903 throw new SecurityException(msg);
904 }
905 Slog.w(TAG, msg);
906 return false;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700907 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700908 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700909
910 // Bind the service!
Joe Onorato8a9b2202010-02-26 18:56:32 -0800911 if (DEBUG) Slog.v(TAG, "Binding to:" + componentName);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800912 WallpaperConnection newConn = new WallpaperConnection(wi, wallpaper);
Mike Clerona428b2c2009-11-15 22:53:08 -0800913 intent.setComponent(componentName);
Dianne Hackborndd9b82c2009-09-03 00:18:47 -0700914 intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
915 com.android.internal.R.string.wallpaper_binding_label);
Dianne Hackborn41203752012-08-31 14:05:51 -0700916 intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivityAsUser(
Dianne Hackborneb034652009-09-07 00:49:58 -0700917 mContext, 0,
918 Intent.createChooser(new Intent(Intent.ACTION_SET_WALLPAPER),
919 mContext.getText(com.android.internal.R.string.chooser_wallpaper)),
Dianne Hackborn41203752012-08-31 14:05:51 -0700920 0, null, new UserHandle(serviceUserId)));
Dianne Hackbornc8230512013-07-13 21:32:12 -0700921 if (!mContext.bindServiceAsUser(intent, newConn,
922 Context.BIND_AUTO_CREATE | Context.BIND_SHOWING_UI,
Amith Yamasani27b89e62013-01-16 12:30:11 -0800923 new UserHandle(serviceUserId))) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700924 String msg = "Unable to bind service: "
925 + componentName;
926 if (fromUser) {
927 throw new IllegalArgumentException(msg);
928 }
929 Slog.w(TAG, msg);
930 return false;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700931 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800932 if (wallpaper.userId == mCurrentUserId && mLastWallpaper != null) {
933 detachWallpaperLocked(mLastWallpaper);
934 }
935 wallpaper.wallpaperComponent = componentName;
936 wallpaper.connection = newConn;
937 wallpaper.lastDiedTime = SystemClock.uptimeMillis();
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700938 newConn.mReply = reply;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700939 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800940 if (wallpaper.userId == mCurrentUserId) {
941 if (DEBUG)
942 Slog.v(TAG, "Adding window token: " + newConn.mToken);
943 mIWindowManager.addWindowToken(newConn.mToken,
944 WindowManager.LayoutParams.TYPE_WALLPAPER);
945 mLastWallpaper = wallpaper;
946 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700947 } catch (RemoteException e) {
948 }
Amith Yamasani4e2820c2012-08-28 22:17:23 -0700949 } catch (RemoteException e) {
950 String msg = "Remote exception for " + componentName + "\n" + e;
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700951 if (fromUser) {
952 throw new IllegalArgumentException(msg);
953 }
954 Slog.w(TAG, msg);
955 return false;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700956 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700957 return true;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700958 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800959
960 void detachWallpaperLocked(WallpaperData wallpaper) {
961 if (wallpaper.connection != null) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700962 if (wallpaper.connection.mReply != null) {
963 try {
964 wallpaper.connection.mReply.sendResult(null);
965 } catch (RemoteException e) {
966 }
967 wallpaper.connection.mReply = null;
968 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800969 if (wallpaper.connection.mEngine != null) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700970 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800971 wallpaper.connection.mEngine.destroy();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700972 } catch (RemoteException e) {
973 }
974 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800975 mContext.unbindService(wallpaper.connection);
Dianne Hackborne9e9bca2009-08-18 15:08:22 -0700976 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800977 if (DEBUG)
978 Slog.v(TAG, "Removing window token: " + wallpaper.connection.mToken);
979 mIWindowManager.removeWindowToken(wallpaper.connection.mToken);
Dianne Hackborne9e9bca2009-08-18 15:08:22 -0700980 } catch (RemoteException e) {
981 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800982 wallpaper.connection.mService = null;
983 wallpaper.connection.mEngine = null;
984 wallpaper.connection = null;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700985 }
986 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800987
988 void clearWallpaperComponentLocked(WallpaperData wallpaper) {
989 wallpaper.wallpaperComponent = null;
990 detachWallpaperLocked(wallpaper);
991 }
992
993 void attachServiceLocked(WallpaperConnection conn, WallpaperData wallpaper) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700994 try {
Dianne Hackborn3be63c02009-08-20 19:31:38 -0700995 conn.mService.attach(conn, conn.mToken,
996 WindowManager.LayoutParams.TYPE_WALLPAPER, false,
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800997 wallpaper.width, wallpaper.height);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700998 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800999 Slog.w(TAG, "Failed attaching wallpaper; clearing", e);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001000 if (!wallpaper.wallpaperUpdating) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001001 bindWallpaperComponentLocked(null, false, false, wallpaper, null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001002 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001003 }
1004 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001005
1006 private void notifyCallbacksLocked(WallpaperData wallpaper) {
1007 final int n = wallpaper.callbacks.beginBroadcast();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001008 for (int i = 0; i < n; i++) {
1009 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001010 wallpaper.callbacks.getBroadcastItem(i).onWallpaperChanged();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001011 } catch (RemoteException e) {
1012
1013 // The RemoteCallbackList will take care of removing
1014 // the dead object for us.
1015 }
1016 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001017 wallpaper.callbacks.finishBroadcast();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001018 final Intent intent = new Intent(Intent.ACTION_WALLPAPER_CHANGED);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001019 mContext.sendBroadcastAsUser(intent, new UserHandle(mCurrentUserId));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001020 }
1021
1022 private void checkPermission(String permission) {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001023 if (PackageManager.PERMISSION_GRANTED!= mContext.checkCallingOrSelfPermission(permission)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001024 throw new SecurityException("Access denied to process: " + Binder.getCallingPid()
1025 + ", must have permission " + permission);
1026 }
1027 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001028
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001029 private static JournaledFile makeJournaledFile(int userId) {
Amith Yamasani61f57372012-08-31 12:12:28 -07001030 final String base = new File(getWallpaperDir(userId), WALLPAPER_INFO).getAbsolutePath();
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001031 return new JournaledFile(new File(base), new File(base + ".tmp"));
1032 }
1033
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001034 private void saveSettingsLocked(WallpaperData wallpaper) {
1035 JournaledFile journal = makeJournaledFile(wallpaper.userId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001036 FileOutputStream stream = null;
1037 try {
1038 stream = new FileOutputStream(journal.chooseForWrite(), false);
1039 XmlSerializer out = new FastXmlSerializer();
1040 out.setOutput(stream, "utf-8");
1041 out.startDocument(null, true);
1042
1043 out.startTag(null, "wp");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001044 out.attribute(null, "width", Integer.toString(wallpaper.width));
1045 out.attribute(null, "height", Integer.toString(wallpaper.height));
1046 out.attribute(null, "name", wallpaper.name);
1047 if (wallpaper.wallpaperComponent != null
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -07001048 && !wallpaper.wallpaperComponent.equals(IMAGE_WALLPAPER)) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001049 out.attribute(null, "component",
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001050 wallpaper.wallpaperComponent.flattenToShortString());
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001051 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001052 out.endTag(null, "wp");
1053
1054 out.endDocument();
1055 stream.close();
1056 journal.commit();
1057 } catch (IOException e) {
1058 try {
1059 if (stream != null) {
1060 stream.close();
1061 }
1062 } catch (IOException ex) {
1063 // Ignore
1064 }
1065 journal.rollback();
1066 }
1067 }
1068
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001069 private void migrateFromOld() {
1070 File oldWallpaper = new File(WallpaperBackupHelper.WALLPAPER_IMAGE_KEY);
1071 File oldInfo = new File(WallpaperBackupHelper.WALLPAPER_INFO_KEY);
1072 if (oldWallpaper.exists()) {
1073 File newWallpaper = new File(getWallpaperDir(0), WALLPAPER);
1074 oldWallpaper.renameTo(newWallpaper);
1075 }
1076 if (oldInfo.exists()) {
1077 File newInfo = new File(getWallpaperDir(0), WALLPAPER_INFO);
1078 oldInfo.renameTo(newInfo);
1079 }
1080 }
1081
1082 private void loadSettingsLocked(int userId) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001083 if (DEBUG) Slog.v(TAG, "loadSettingsLocked");
Mike Clerona428b2c2009-11-15 22:53:08 -08001084
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001085 JournaledFile journal = makeJournaledFile(userId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001086 FileInputStream stream = null;
1087 File file = journal.chooseForRead();
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001088 if (!file.exists()) {
1089 // This should only happen one time, when upgrading from a legacy system
1090 migrateFromOld();
1091 }
1092 WallpaperData wallpaper = mWallpaperMap.get(userId);
1093 if (wallpaper == null) {
1094 wallpaper = new WallpaperData(userId);
1095 mWallpaperMap.put(userId, wallpaper);
1096 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001097 boolean success = false;
1098 try {
1099 stream = new FileInputStream(file);
1100 XmlPullParser parser = Xml.newPullParser();
1101 parser.setInput(stream, null);
1102
1103 int type;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001104 do {
1105 type = parser.next();
1106 if (type == XmlPullParser.START_TAG) {
1107 String tag = parser.getName();
1108 if ("wp".equals(tag)) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001109 wallpaper.width = Integer.parseInt(parser.getAttributeValue(null, "width"));
1110 wallpaper.height = Integer.parseInt(parser
1111 .getAttributeValue(null, "height"));
1112 wallpaper.name = parser.getAttributeValue(null, "name");
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001113 String comp = parser.getAttributeValue(null, "component");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001114 wallpaper.nextWallpaperComponent = comp != null
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001115 ? ComponentName.unflattenFromString(comp)
1116 : null;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001117 if (wallpaper.nextWallpaperComponent == null
1118 || "android".equals(wallpaper.nextWallpaperComponent
1119 .getPackageName())) {
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -07001120 wallpaper.nextWallpaperComponent = IMAGE_WALLPAPER;
Dianne Hackborn9ea31632011-08-05 14:43:50 -07001121 }
Mike Clerona428b2c2009-11-15 22:53:08 -08001122
1123 if (DEBUG) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001124 Slog.v(TAG, "mWidth:" + wallpaper.width);
1125 Slog.v(TAG, "mHeight:" + wallpaper.height);
1126 Slog.v(TAG, "mName:" + wallpaper.name);
1127 Slog.v(TAG, "mNextWallpaperComponent:"
1128 + wallpaper.nextWallpaperComponent);
Mike Clerona428b2c2009-11-15 22:53:08 -08001129 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001130 }
1131 }
1132 } while (type != XmlPullParser.END_DOCUMENT);
1133 success = true;
Dianne Hackborn13579ed2012-11-28 18:05:36 -08001134 } catch (FileNotFoundException e) {
1135 Slog.w(TAG, "no current wallpaper -- first boot?");
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001136 } catch (NullPointerException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001137 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001138 } catch (NumberFormatException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001139 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001140 } catch (XmlPullParserException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001141 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001142 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001143 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001144 } catch (IndexOutOfBoundsException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001145 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001146 }
1147 try {
1148 if (stream != null) {
1149 stream.close();
1150 }
1151 } catch (IOException e) {
1152 // Ignore
1153 }
1154
1155 if (!success) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001156 wallpaper.width = -1;
1157 wallpaper.height = -1;
1158 wallpaper.name = "";
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001159 }
Dianne Hackborn44bc17c2011-04-20 18:18:51 -07001160
1161 // We always want to have some reasonable width hint.
John Spurlock7ea91ec2013-11-04 13:48:38 -05001162 int baseSize = getMaximumSizeDimension();
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001163 if (wallpaper.width < baseSize) {
1164 wallpaper.width = baseSize;
Dianne Hackborn44bc17c2011-04-20 18:18:51 -07001165 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001166 if (wallpaper.height < baseSize) {
1167 wallpaper.height = baseSize;
Dianne Hackborn44bc17c2011-04-20 18:18:51 -07001168 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001169 }
1170
John Spurlock7ea91ec2013-11-04 13:48:38 -05001171 private int getMaximumSizeDimension() {
1172 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
1173 Display d = wm.getDefaultDisplay();
1174 return d.getMaximumSizeDimension();
1175 }
1176
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07001177 // Called by SystemBackupAgent after files are restored to disk.
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001178 void settingsRestored() {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001179 // TODO: If necessary, make it work for secondary users as well. This currently assumes
1180 // restores only to the primary user
Joe Onorato8a9b2202010-02-26 18:56:32 -08001181 if (DEBUG) Slog.v(TAG, "settingsRestored");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001182 WallpaperData wallpaper = null;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001183 boolean success = false;
1184 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001185 loadSettingsLocked(0);
1186 wallpaper = mWallpaperMap.get(0);
1187 if (wallpaper.nextWallpaperComponent != null
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -07001188 && !wallpaper.nextWallpaperComponent.equals(IMAGE_WALLPAPER)) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001189 if (!bindWallpaperComponentLocked(wallpaper.nextWallpaperComponent, false, false,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001190 wallpaper, null)) {
Christopher Tatee3ab4d02009-12-16 14:03:31 -08001191 // No such live wallpaper or other failure; fall back to the default
1192 // live wallpaper (since the profile being restored indicated that the
1193 // user had selected a live rather than static one).
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001194 bindWallpaperComponentLocked(null, false, false, wallpaper, null);
Christopher Tatee3ab4d02009-12-16 14:03:31 -08001195 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001196 success = true;
1197 } else {
Mike Clerona428b2c2009-11-15 22:53:08 -08001198 // If there's a wallpaper name, we use that. If that can't be loaded, then we
1199 // use the default.
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001200 if ("".equals(wallpaper.name)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001201 if (DEBUG) Slog.v(TAG, "settingsRestored: name is empty");
Mike Clerona428b2c2009-11-15 22:53:08 -08001202 success = true;
1203 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001204 if (DEBUG) Slog.v(TAG, "settingsRestored: attempting to restore named resource");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001205 success = restoreNamedResourceLocked(wallpaper);
Mike Clerona428b2c2009-11-15 22:53:08 -08001206 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08001207 if (DEBUG) Slog.v(TAG, "settingsRestored: success=" + success);
Mike Clerona428b2c2009-11-15 22:53:08 -08001208 if (success) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001209 bindWallpaperComponentLocked(wallpaper.nextWallpaperComponent, false, false,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001210 wallpaper, null);
Mike Clerona428b2c2009-11-15 22:53:08 -08001211 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001212 }
1213 }
1214
1215 if (!success) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001216 Slog.e(TAG, "Failed to restore wallpaper: '" + wallpaper.name + "'");
1217 wallpaper.name = "";
1218 getWallpaperDir(0).delete();
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001219 }
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07001220
1221 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001222 saveSettingsLocked(wallpaper);
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07001223 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001224 }
1225
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001226 boolean restoreNamedResourceLocked(WallpaperData wallpaper) {
1227 if (wallpaper.name.length() > 4 && "res:".equals(wallpaper.name.substring(0, 4))) {
1228 String resName = wallpaper.name.substring(4);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001229
1230 String pkg = null;
1231 int colon = resName.indexOf(':');
1232 if (colon > 0) {
1233 pkg = resName.substring(0, colon);
1234 }
1235
1236 String ident = null;
1237 int slash = resName.lastIndexOf('/');
1238 if (slash > 0) {
1239 ident = resName.substring(slash+1);
1240 }
1241
1242 String type = null;
1243 if (colon > 0 && slash > 0 && (slash-colon) > 1) {
1244 type = resName.substring(colon+1, slash);
1245 }
1246
1247 if (pkg != null && ident != null && type != null) {
1248 int resId = -1;
1249 InputStream res = null;
1250 FileOutputStream fos = null;
1251 try {
1252 Context c = mContext.createPackageContext(pkg, Context.CONTEXT_RESTRICTED);
1253 Resources r = c.getResources();
1254 resId = r.getIdentifier(resName, null, null);
1255 if (resId == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001256 Slog.e(TAG, "couldn't resolve identifier pkg=" + pkg + " type=" + type
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001257 + " ident=" + ident);
1258 return false;
1259 }
1260
1261 res = r.openRawResource(resId);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001262 if (wallpaper.wallpaperFile.exists()) {
1263 wallpaper.wallpaperFile.delete();
Dianne Hackborn1afd1c92010-03-18 22:47:17 -07001264 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001265 fos = new FileOutputStream(wallpaper.wallpaperFile);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001266
1267 byte[] buffer = new byte[32768];
1268 int amt;
1269 while ((amt=res.read(buffer)) > 0) {
1270 fos.write(buffer, 0, amt);
1271 }
1272 // mWallpaperObserver will notice the close and send the change broadcast
1273
Joe Onorato8a9b2202010-02-26 18:56:32 -08001274 Slog.v(TAG, "Restored wallpaper: " + resName);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001275 return true;
1276 } catch (NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001277 Slog.e(TAG, "Package name " + pkg + " not found");
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001278 } catch (Resources.NotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001279 Slog.e(TAG, "Resource not found: " + resId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001280 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001281 Slog.e(TAG, "IOException while restoring wallpaper ", e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001282 } finally {
1283 if (res != null) {
1284 try {
1285 res.close();
1286 } catch (IOException ex) {}
1287 }
1288 if (fos != null) {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07001289 FileUtils.sync(fos);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001290 try {
1291 fos.close();
1292 } catch (IOException ex) {}
1293 }
1294 }
1295 }
1296 }
1297 return false;
1298 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001299
Dianne Hackborneb034652009-09-07 00:49:58 -07001300 @Override
1301 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1302 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
1303 != PackageManager.PERMISSION_GRANTED) {
1304
1305 pw.println("Permission Denial: can't dump wallpaper service from from pid="
1306 + Binder.getCallingPid()
1307 + ", uid=" + Binder.getCallingUid());
1308 return;
1309 }
1310
1311 synchronized (mLock) {
1312 pw.println("Current Wallpaper Service state:");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001313 for (int i = 0; i < mWallpaperMap.size(); i++) {
1314 WallpaperData wallpaper = mWallpaperMap.valueAt(i);
1315 pw.println(" User " + wallpaper.userId + ":");
1316 pw.print(" mWidth=");
1317 pw.print(wallpaper.width);
1318 pw.print(" mHeight=");
1319 pw.println(wallpaper.height);
1320 pw.print(" mName=");
1321 pw.println(wallpaper.name);
1322 pw.print(" mWallpaperComponent=");
1323 pw.println(wallpaper.wallpaperComponent);
1324 if (wallpaper.connection != null) {
1325 WallpaperConnection conn = wallpaper.connection;
1326 pw.print(" Wallpaper connection ");
1327 pw.print(conn);
1328 pw.println(":");
1329 if (conn.mInfo != null) {
1330 pw.print(" mInfo.component=");
1331 pw.println(conn.mInfo.getComponent());
1332 }
1333 pw.print(" mToken=");
1334 pw.println(conn.mToken);
1335 pw.print(" mService=");
1336 pw.println(conn.mService);
1337 pw.print(" mEngine=");
1338 pw.println(conn.mEngine);
1339 pw.print(" mLastDiedTime=");
1340 pw.println(wallpaper.lastDiedTime - SystemClock.uptimeMillis());
1341 }
Dianne Hackborneb034652009-09-07 00:49:58 -07001342 }
1343 }
1344 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001345}