blob: 8a3633544d7356827966f335d4d88089a584c07e [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
Amith Yamasani09e9cdc2013-11-06 14:54:50 -080017package com.android.server.wallpaper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080018
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;
Jeff Sharkey28f08772014-04-16 09:41:58 -070028import android.app.WallpaperManager;
Christopher Tate45281862010-03-05 15:46:30 -080029import android.app.backup.BackupManager;
Amith Yamasani37ce3a82012-02-06 12:04:42 -080030import android.app.backup.WallpaperBackupHelper;
Amith Yamasani13593602012-03-22 16:16:17 -070031import android.content.BroadcastReceiver;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070032import android.content.ComponentName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033import android.content.Context;
34import android.content.Intent;
Amith Yamasani13593602012-03-22 16:16:17 -070035import android.content.IntentFilter;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070036import android.content.ServiceConnection;
Amith Yamasani4e2820c2012-08-28 22:17:23 -070037import android.content.pm.IPackageManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038import android.content.pm.PackageManager;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070039import android.content.pm.ResolveInfo;
40import android.content.pm.ServiceInfo;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070041import android.content.pm.PackageManager.NameNotFoundException;
Amith Yamasani6474c4c2012-10-04 14:55:42 -070042import android.content.pm.UserInfo;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070043import android.content.res.Resources;
John Spurlock41f64642013-11-04 13:48:38 -050044import android.graphics.Point;
Dianne Hackborn067e5f62014-09-07 23:14:30 -070045import android.graphics.Rect;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046import android.os.Binder;
Dianne Hackborn284ac932009-08-28 10:34:25 -070047import android.os.Bundle;
Amith Yamasani13593602012-03-22 16:16:17 -070048import android.os.Environment;
Dianne Hackborn8bdf5932010-10-15 12:54:40 -070049import android.os.FileUtils;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070050import android.os.IBinder;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -070051import android.os.IRemoteCallback;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052import android.os.RemoteException;
53import android.os.FileObserver;
54import android.os.ParcelFileDescriptor;
55import android.os.RemoteCallbackList;
rpcraig554cb0c2012-07-05 06:41:43 -040056import android.os.SELinux;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070057import android.os.ServiceManager;
Dianne Hackborn0cd48872009-08-13 18:51:59 -070058import android.os.SystemClock;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070059import android.os.UserHandle;
Amith Yamasani6474c4c2012-10-04 14:55:42 -070060import android.os.UserManager;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070061import android.service.wallpaper.IWallpaperConnection;
62import android.service.wallpaper.IWallpaperEngine;
63import android.service.wallpaper.IWallpaperService;
64import android.service.wallpaper.WallpaperService;
Joe Onorato8a9b2202010-02-26 18:56:32 -080065import android.util.Slog;
Amith Yamasani37ce3a82012-02-06 12:04:42 -080066import android.util.SparseArray;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070067import android.util.Xml;
Dianne Hackborn44bc17c2011-04-20 18:18:51 -070068import android.view.Display;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070069import android.view.IWindowManager;
70import android.view.WindowManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071
Dianne Hackborneb034652009-09-07 00:49:58 -070072import java.io.FileDescriptor;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070073import java.io.IOException;
74import java.io.InputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075import java.io.File;
76import java.io.FileNotFoundException;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070077import java.io.FileInputStream;
78import java.io.FileOutputStream;
Dianne Hackborneb034652009-09-07 00:49:58 -070079import java.io.PrintWriter;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070080import java.util.List;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070081
82import org.xmlpull.v1.XmlPullParser;
83import org.xmlpull.v1.XmlPullParserException;
84import org.xmlpull.v1.XmlSerializer;
85
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080086import com.android.internal.content.PackageMonitor;
Dianne Hackborn2269d152010-02-24 19:54:22 -080087import com.android.internal.util.FastXmlSerializer;
Dianne Hackborn1afd1c92010-03-18 22:47:17 -070088import com.android.internal.util.JournaledFile;
Justin Koh29c30162014-09-05 17:10:10 -070089import com.android.internal.R;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090
Amith Yamasani09e9cdc2013-11-06 14:54:50 -080091public class WallpaperManagerService extends IWallpaperManager.Stub {
92 static final String TAG = "WallpaperManagerService";
Dianne Hackborncbf15042009-08-18 18:29:09 -070093 static final boolean DEBUG = false;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070094
Romain Guy407ec782011-08-24 17:06:58 -070095 final Object mLock = new Object[0];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096
Dianne Hackborn0cd48872009-08-13 18:51:59 -070097 /**
98 * Minimum time between crashes of a wallpaper service for us to consider
99 * restarting it vs. just reverting to the static wallpaper.
100 */
101 static final long MIN_WALLPAPER_CRASH_TIME = 10000;
Dianne Hackborn0cd48872009-08-13 18:51:59 -0700102 static final String WALLPAPER = "wallpaper";
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800103 static final String WALLPAPER_INFO = "wallpaper_info.xml";
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -0700104
105 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106 * Observes the wallpaper for changes and notifies all IWallpaperServiceCallbacks
107 * that the wallpaper has changed. The CREATE is triggered when there is no
108 * wallpaper set and is created for the first time. The CLOSE_WRITE is triggered
109 * everytime the wallpaper is changed.
110 */
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800111 private class WallpaperObserver extends FileObserver {
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700112
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800113 final WallpaperData mWallpaper;
114 final File mWallpaperDir;
115 final File mWallpaperFile;
116
117 public WallpaperObserver(WallpaperData wallpaper) {
118 super(getWallpaperDir(wallpaper.userId).getAbsolutePath(),
Christopher Tateda058e22014-10-08 14:51:09 -0700119 CLOSE_WRITE | MOVED_TO | DELETE | DELETE_SELF);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800120 mWallpaperDir = getWallpaperDir(wallpaper.userId);
121 mWallpaper = wallpaper;
122 mWallpaperFile = new File(mWallpaperDir, WALLPAPER);
123 }
124
125 @Override
126 public void onEvent(int event, String path) {
127 if (path == null) {
128 return;
129 }
130 synchronized (mLock) {
131 // changing the wallpaper means we'll need to back up the new one
132 long origId = Binder.clearCallingIdentity();
133 BackupManager bm = new BackupManager(mContext);
134 bm.dataChanged();
135 Binder.restoreCallingIdentity(origId);
136
137 File changedFile = new File(mWallpaperDir, path);
138 if (mWallpaperFile.equals(changedFile)) {
139 notifyCallbacksLocked(mWallpaper);
Christopher Tateda058e22014-10-08 14:51:09 -0700140 final boolean written = (event == CLOSE_WRITE || event == MOVED_TO);
141 if (mWallpaper.wallpaperComponent == null
142 || event != CLOSE_WRITE // includes the MOVED_TO case
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800143 || mWallpaper.imageWallpaperPending) {
Christopher Tateda058e22014-10-08 14:51:09 -0700144 if (written) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800145 mWallpaper.imageWallpaperPending = false;
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700146 }
Justin Koh29c30162014-09-05 17:10:10 -0700147 bindWallpaperComponentLocked(mImageWallpaper, true,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700148 false, mWallpaper, null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800149 saveSettingsLocked(mWallpaper);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800150 }
151 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800152 }
153 }
154 }
155
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700156 final Context mContext;
157 final IWindowManager mIWindowManager;
Amith Yamasani4e2820c2012-08-28 22:17:23 -0700158 final IPackageManager mIPackageManager;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800159 final MyPackageMonitor mMonitor;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800160 WallpaperData mLastWallpaper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800161
Justin Koh29c30162014-09-05 17:10:10 -0700162 /**
163 * Name of the component used to display bitmap wallpapers from either the gallery or
164 * built-in wallpapers.
165 */
166 final ComponentName mImageWallpaper;
167
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800168 SparseArray<WallpaperData> mWallpaperMap = new SparseArray<WallpaperData>();
Dianne Hackborn07213e62011-08-24 20:05:39 -0700169
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800170 int mCurrentUserId;
Dianne Hackborn07213e62011-08-24 20:05:39 -0700171
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800172 static class WallpaperData {
173
174 int userId;
175
176 File wallpaperFile;
177
178 /**
179 * Client is currently writing a new image wallpaper.
180 */
181 boolean imageWallpaperPending;
182
183 /**
184 * Resource name if using a picture from the wallpaper gallery
185 */
186 String name = "";
187
188 /**
189 * The component name of the currently set live wallpaper.
190 */
191 ComponentName wallpaperComponent;
192
193 /**
194 * The component name of the wallpaper that should be set next.
195 */
196 ComponentName nextWallpaperComponent;
197
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800198 WallpaperConnection connection;
199 long lastDiedTime;
200 boolean wallpaperUpdating;
201 WallpaperObserver wallpaperObserver;
202
203 /**
204 * List of callbacks registered they should each be notified when the wallpaper is changed.
205 */
206 private RemoteCallbackList<IWallpaperManagerCallback> callbacks
207 = new RemoteCallbackList<IWallpaperManagerCallback>();
208
209 int width = -1;
210 int height = -1;
211
Dianne Hackborn067e5f62014-09-07 23:14:30 -0700212 final Rect padding = new Rect(0, 0, 0, 0);
213
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800214 WallpaperData(int userId) {
215 this.userId = userId;
216 wallpaperFile = new File(getWallpaperDir(userId), WALLPAPER);
217 }
218 }
219
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700220 class WallpaperConnection extends IWallpaperConnection.Stub
221 implements ServiceConnection {
Dianne Hackborneb034652009-09-07 00:49:58 -0700222 final WallpaperInfo mInfo;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700223 final Binder mToken = new Binder();
224 IWallpaperService mService;
225 IWallpaperEngine mEngine;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800226 WallpaperData mWallpaper;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700227 IRemoteCallback mReply;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800228
Michael Wright5203a8b2013-10-03 14:16:42 -0700229 boolean mDimensionsChanged = false;
Dianne Hackborn067e5f62014-09-07 23:14:30 -0700230 boolean mPaddingChanged = false;
Michael Wright5203a8b2013-10-03 14:16:42 -0700231
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800232 public WallpaperConnection(WallpaperInfo info, WallpaperData wallpaper) {
Dianne Hackborneb034652009-09-07 00:49:58 -0700233 mInfo = info;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800234 mWallpaper = wallpaper;
Dianne Hackborneb034652009-09-07 00:49:58 -0700235 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700236
237 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700238 public void onServiceConnected(ComponentName name, IBinder service) {
239 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800240 if (mWallpaper.connection == this) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700241 mService = IWallpaperService.Stub.asInterface(service);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800242 attachServiceLocked(this, mWallpaper);
Dianne Hackborneb034652009-09-07 00:49:58 -0700243 // XXX should probably do saveSettingsLocked() later
244 // when we have an engine, but I'm not sure about
245 // locking there and anyway we always need to be able to
246 // recover if there is something wrong.
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800247 saveSettingsLocked(mWallpaper);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700248 }
249 }
250 }
251
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700252 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700253 public void onServiceDisconnected(ComponentName name) {
254 synchronized (mLock) {
255 mService = null;
256 mEngine = null;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800257 if (mWallpaper.connection == this) {
258 Slog.w(TAG, "Wallpaper service gone: " + mWallpaper.wallpaperComponent);
259 if (!mWallpaper.wallpaperUpdating
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800260 && mWallpaper.userId == mCurrentUserId) {
Selim Cinekebebadb2014-03-05 22:17:26 +0100261 // There is a race condition which causes
262 // {@link #mWallpaper.wallpaperUpdating} to be false even if it is
263 // currently updating since the broadcast notifying us is async.
264 // This race is overcome by the general rule that we only reset the
265 // wallpaper if its service was shut down twice
266 // during {@link #MIN_WALLPAPER_CRASH_TIME} millis.
267 if (mWallpaper.lastDiedTime != 0
268 && mWallpaper.lastDiedTime + MIN_WALLPAPER_CRASH_TIME
269 > SystemClock.uptimeMillis()) {
270 Slog.w(TAG, "Reverting to built-in wallpaper!");
271 clearWallpaperLocked(true, mWallpaper.userId, null);
272 } else {
273 mWallpaper.lastDiedTime = SystemClock.uptimeMillis();
274 }
Dianne Hackborn0cd48872009-08-13 18:51:59 -0700275 }
276 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700277 }
278 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800279
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700280 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700281 public void attachEngine(IWallpaperEngine engine) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700282 synchronized (mLock) {
283 mEngine = engine;
Michael Wright5203a8b2013-10-03 14:16:42 -0700284 if (mDimensionsChanged) {
285 try {
286 mEngine.setDesiredSize(mWallpaper.width, mWallpaper.height);
287 } catch (RemoteException e) {
288 Slog.w(TAG, "Failed to set wallpaper dimensions", e);
289 }
290 mDimensionsChanged = false;
291 }
Dianne Hackborn067e5f62014-09-07 23:14:30 -0700292 if (mPaddingChanged) {
293 try {
294 mEngine.setDisplayPadding(mWallpaper.padding);
295 } catch (RemoteException e) {
296 Slog.w(TAG, "Failed to set wallpaper padding", e);
297 }
298 mPaddingChanged = false;
299 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700300 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700301 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800302
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700303 @Override
304 public void engineShown(IWallpaperEngine engine) {
305 synchronized (mLock) {
306 if (mReply != null) {
307 long ident = Binder.clearCallingIdentity();
308 try {
309 mReply.sendResult(null);
310 } catch (RemoteException e) {
311 Binder.restoreCallingIdentity(ident);
312 }
313 mReply = null;
314 }
315 }
316 }
317
318 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700319 public ParcelFileDescriptor setWallpaper(String name) {
320 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800321 if (mWallpaper.connection == this) {
322 return updateWallpaperBitmapLocked(name, mWallpaper);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700323 }
324 return null;
325 }
326 }
327 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800328
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800329 class MyPackageMonitor extends PackageMonitor {
330 @Override
331 public void onPackageUpdateFinished(String packageName, int uid) {
332 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700333 if (mCurrentUserId != getChangingUserId()) {
334 return;
335 }
336 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
337 if (wallpaper != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800338 if (wallpaper.wallpaperComponent != null
339 && wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
340 wallpaper.wallpaperUpdating = false;
341 ComponentName comp = wallpaper.wallpaperComponent;
342 clearWallpaperComponentLocked(wallpaper);
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700343 if (!bindWallpaperComponentLocked(comp, false, false,
344 wallpaper, null)) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800345 Slog.w(TAG, "Wallpaper no longer available; reverting to default");
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700346 clearWallpaperLocked(false, wallpaper.userId, null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800347 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700348 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800349 }
350 }
351 }
352
353 @Override
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700354 public void onPackageModified(String packageName) {
355 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700356 if (mCurrentUserId != getChangingUserId()) {
357 return;
358 }
359 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
360 if (wallpaper != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800361 if (wallpaper.wallpaperComponent == null
362 || !wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700363 return;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800364 }
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700365 doPackagesChangedLocked(true, wallpaper);
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700366 }
367 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700368 }
369
370 @Override
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800371 public void onPackageUpdateStarted(String packageName, int uid) {
372 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700373 if (mCurrentUserId != getChangingUserId()) {
374 return;
375 }
376 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
377 if (wallpaper != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800378 if (wallpaper.wallpaperComponent != null
379 && wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
380 wallpaper.wallpaperUpdating = true;
381 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800382 }
383 }
384 }
385
386 @Override
387 public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700388 synchronized (mLock) {
389 boolean changed = false;
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700390 if (mCurrentUserId != getChangingUserId()) {
391 return false;
392 }
393 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
394 if (wallpaper != null) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700395 boolean res = doPackagesChangedLocked(doit, wallpaper);
396 changed |= res;
397 }
398 return changed;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800399 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800400 }
401
402 @Override
403 public void onSomePackagesChanged() {
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700404 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700405 if (mCurrentUserId != getChangingUserId()) {
406 return;
407 }
408 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
409 if (wallpaper != null) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700410 doPackagesChangedLocked(true, wallpaper);
411 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800412 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800413 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800414
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700415 boolean doPackagesChangedLocked(boolean doit, WallpaperData wallpaper) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800416 boolean changed = false;
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700417 if (wallpaper.wallpaperComponent != null) {
418 int change = isPackageDisappearing(wallpaper.wallpaperComponent
419 .getPackageName());
420 if (change == PACKAGE_PERMANENT_CHANGE
421 || change == PACKAGE_TEMPORARY_CHANGE) {
422 changed = true;
423 if (doit) {
424 Slog.w(TAG, "Wallpaper uninstalled, removing: "
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800425 + wallpaper.wallpaperComponent);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700426 clearWallpaperLocked(false, wallpaper.userId, null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800427 }
428 }
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700429 }
430 if (wallpaper.nextWallpaperComponent != null) {
431 int change = isPackageDisappearing(wallpaper.nextWallpaperComponent
432 .getPackageName());
433 if (change == PACKAGE_PERMANENT_CHANGE
434 || change == PACKAGE_TEMPORARY_CHANGE) {
435 wallpaper.nextWallpaperComponent = null;
436 }
437 }
438 if (wallpaper.wallpaperComponent != null
439 && isPackageModified(wallpaper.wallpaperComponent.getPackageName())) {
440 try {
441 mContext.getPackageManager().getServiceInfo(
442 wallpaper.wallpaperComponent, 0);
443 } catch (NameNotFoundException e) {
444 Slog.w(TAG, "Wallpaper component gone, removing: "
445 + wallpaper.wallpaperComponent);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700446 clearWallpaperLocked(false, wallpaper.userId, null);
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700447 }
448 }
449 if (wallpaper.nextWallpaperComponent != null
450 && isPackageModified(wallpaper.nextWallpaperComponent.getPackageName())) {
451 try {
452 mContext.getPackageManager().getServiceInfo(
453 wallpaper.nextWallpaperComponent, 0);
454 } catch (NameNotFoundException e) {
455 wallpaper.nextWallpaperComponent = null;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800456 }
457 }
458 return changed;
459 }
460 }
461
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700462 public WallpaperManagerService(Context context) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800463 if (DEBUG) Slog.v(TAG, "WallpaperService startup");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800464 mContext = context;
Justin Koh29c30162014-09-05 17:10:10 -0700465 mImageWallpaper = ComponentName.unflattenFromString(
466 context.getResources().getString(R.string.image_wallpaper_component));
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700467 mIWindowManager = IWindowManager.Stub.asInterface(
468 ServiceManager.getService(Context.WINDOW_SERVICE));
Amith Yamasani4e2820c2012-08-28 22:17:23 -0700469 mIPackageManager = AppGlobals.getPackageManager();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800470 mMonitor = new MyPackageMonitor();
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700471 mMonitor.register(context, null, UserHandle.ALL, true);
Amith Yamasani61f57372012-08-31 12:12:28 -0700472 getWallpaperDir(UserHandle.USER_OWNER).mkdirs();
473 loadSettingsLocked(UserHandle.USER_OWNER);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800474 }
475
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800476 private static File getWallpaperDir(int userId) {
Amith Yamasani61f57372012-08-31 12:12:28 -0700477 return Environment.getUserSystemDirectory(userId);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800478 }
479
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800480 @Override
481 protected void finalize() throws Throwable {
482 super.finalize();
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800483 for (int i = 0; i < mWallpaperMap.size(); i++) {
484 WallpaperData wallpaper = mWallpaperMap.valueAt(i);
485 wallpaper.wallpaperObserver.stopWatching();
486 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800487 }
Amith Yamasani13593602012-03-22 16:16:17 -0700488
Svetoslav Ganova0027152013-06-25 14:59:53 -0700489 public void systemRunning() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800490 if (DEBUG) Slog.v(TAG, "systemReady");
Amith Yamasani61f57372012-08-31 12:12:28 -0700491 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.USER_OWNER);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700492 switchWallpaper(wallpaper, null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800493 wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper);
494 wallpaper.wallpaperObserver.startWatching();
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800495
Amith Yamasani13593602012-03-22 16:16:17 -0700496 IntentFilter userFilter = new IntentFilter();
Amith Yamasani13593602012-03-22 16:16:17 -0700497 userFilter.addAction(Intent.ACTION_USER_REMOVED);
Amith Yamasani756901d2012-10-12 12:30:07 -0700498 userFilter.addAction(Intent.ACTION_USER_STOPPING);
Amith Yamasani13593602012-03-22 16:16:17 -0700499 mContext.registerReceiver(new BroadcastReceiver() {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800500 @Override
Amith Yamasani13593602012-03-22 16:16:17 -0700501 public void onReceive(Context context, Intent intent) {
502 String action = intent.getAction();
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700503 if (Intent.ACTION_USER_REMOVED.equals(action)) {
Amith Yamasani756901d2012-10-12 12:30:07 -0700504 onRemoveUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
505 UserHandle.USER_NULL));
Amith Yamasani13593602012-03-22 16:16:17 -0700506 }
Amith Yamasani0c293712012-10-30 12:23:52 -0700507 // TODO: Race condition causing problems when cleaning up on stopping a user.
508 // Comment this out for now.
509 // else if (Intent.ACTION_USER_STOPPING.equals(action)) {
510 // onStoppingUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
511 // UserHandle.USER_NULL));
512 // }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800513 }
Amith Yamasani13593602012-03-22 16:16:17 -0700514 }, userFilter);
Amith Yamasani756901d2012-10-12 12:30:07 -0700515
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700516 try {
517 ActivityManagerNative.getDefault().registerUserSwitchObserver(
518 new IUserSwitchObserver.Stub() {
519 @Override
520 public void onUserSwitching(int newUserId, IRemoteCallback reply) {
521 switchUser(newUserId, reply);
522 }
523
524 @Override
525 public void onUserSwitchComplete(int newUserId) throws RemoteException {
526 }
527 });
528 } catch (RemoteException e) {
529 // TODO Auto-generated catch block
530 e.printStackTrace();
531 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800532 }
533
Amith Yamasani09e9cdc2013-11-06 14:54:50 -0800534 /** Called by SystemBackupAgent */
535 public String getName() {
536 // Verify caller is the system
537 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
538 throw new RuntimeException("getName() can only be called from the system process");
539 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700540 synchronized (mLock) {
541 return mWallpaperMap.get(0).name;
542 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800543 }
544
Amith Yamasani756901d2012-10-12 12:30:07 -0700545 void onStoppingUser(int userId) {
546 if (userId < 1) return;
Amith Yamasani13593602012-03-22 16:16:17 -0700547 synchronized (mLock) {
548 WallpaperData wallpaper = mWallpaperMap.get(userId);
549 if (wallpaper != null) {
Amith Yamasani756901d2012-10-12 12:30:07 -0700550 if (wallpaper.wallpaperObserver != null) {
551 wallpaper.wallpaperObserver.stopWatching();
552 wallpaper.wallpaperObserver = null;
553 }
Amith Yamasani13593602012-03-22 16:16:17 -0700554 mWallpaperMap.remove(userId);
555 }
Amith Yamasani756901d2012-10-12 12:30:07 -0700556 }
557 }
558
559 void onRemoveUser(int userId) {
560 if (userId < 1) return;
561 synchronized (mLock) {
562 onStoppingUser(userId);
Amith Yamasani13593602012-03-22 16:16:17 -0700563 File wallpaperFile = new File(getWallpaperDir(userId), WALLPAPER);
564 wallpaperFile.delete();
565 File wallpaperInfoFile = new File(getWallpaperDir(userId), WALLPAPER_INFO);
566 wallpaperInfoFile.delete();
567 }
568 }
569
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700570 void switchUser(int userId, IRemoteCallback reply) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800571 synchronized (mLock) {
572 mCurrentUserId = userId;
573 WallpaperData wallpaper = mWallpaperMap.get(userId);
574 if (wallpaper == null) {
575 wallpaper = new WallpaperData(userId);
576 mWallpaperMap.put(userId, wallpaper);
577 loadSettingsLocked(userId);
Amith Yamasani6474c4c2012-10-04 14:55:42 -0700578 }
579 // Not started watching yet, in case wallpaper data was loaded for other reasons.
580 if (wallpaper.wallpaperObserver == null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800581 wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper);
582 wallpaper.wallpaperObserver.startWatching();
583 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700584 switchWallpaper(wallpaper, reply);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800585 }
586 }
587
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700588 void switchWallpaper(WallpaperData wallpaper, IRemoteCallback reply) {
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700589 synchronized (mLock) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700590 RuntimeException e = null;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700591 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800592 ComponentName cname = wallpaper.wallpaperComponent != null ?
593 wallpaper.wallpaperComponent : wallpaper.nextWallpaperComponent;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700594 if (bindWallpaperComponentLocked(cname, true, false, wallpaper, reply)) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700595 return;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700596 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700597 } catch (RuntimeException e1) {
598 e = e1;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700599 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700600 Slog.w(TAG, "Failure starting previous wallpaper", e);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700601 clearWallpaperLocked(false, wallpaper.userId, reply);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800602 }
603 }
604
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800605 public void clearWallpaper() {
606 if (DEBUG) Slog.v(TAG, "clearWallpaper");
607 synchronized (mLock) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700608 clearWallpaperLocked(false, UserHandle.getCallingUserId(), null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800609 }
610 }
611
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700612 void clearWallpaperLocked(boolean defaultFailed, int userId, IRemoteCallback reply) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800613 WallpaperData wallpaper = mWallpaperMap.get(userId);
614 File f = new File(getWallpaperDir(userId), WALLPAPER);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800615 if (f.exists()) {
616 f.delete();
617 }
618 final long ident = Binder.clearCallingIdentity();
619 try {
Christopher Tateecd827a2014-09-05 17:42:34 -0700620 RuntimeException e = null;
621 try {
622 wallpaper.imageWallpaperPending = false;
623 if (userId != mCurrentUserId) return;
624 if (bindWallpaperComponentLocked(defaultFailed
625 ? mImageWallpaper
626 : null, true, false, wallpaper, reply)) {
627 return;
628 }
629 } catch (IllegalArgumentException e1) {
630 e = e1;
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700631 }
Christopher Tateecd827a2014-09-05 17:42:34 -0700632
633 // This can happen if the default wallpaper component doesn't
634 // exist. This should be a system configuration problem, but
635 // let's not let it crash the system and just live with no
636 // wallpaper.
637 Slog.e(TAG, "Default wallpaper component not found!", e);
638 clearWallpaperComponentLocked(wallpaper);
639 if (reply != null) {
640 try {
641 reply.sendResult(null);
642 } catch (RemoteException e1) {
643 }
644 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800645 } finally {
646 Binder.restoreCallingIdentity(ident);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800647 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700648 }
649
650 public boolean hasNamedWallpaper(String name) {
651 synchronized (mLock) {
Amith Yamasani6474c4c2012-10-04 14:55:42 -0700652 List<UserInfo> users;
653 long ident = Binder.clearCallingIdentity();
654 try {
655 users = ((UserManager) mContext.getSystemService(Context.USER_SERVICE)).getUsers();
656 } finally {
657 Binder.restoreCallingIdentity(ident);
658 }
659 for (UserInfo user: users) {
660 WallpaperData wd = mWallpaperMap.get(user.id);
661 if (wd == null) {
662 // User hasn't started yet, so load her settings to peek at the wallpaper
663 loadSettingsLocked(user.id);
664 wd = mWallpaperMap.get(user.id);
665 }
666 if (wd != null && name.equals(wd.name)) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700667 return true;
668 }
669 }
670 }
671 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800672 }
673
John Spurlock41f64642013-11-04 13:48:38 -0500674 private Point getDefaultDisplaySize() {
675 Point p = new Point();
John Spurlockd6e836c2013-11-18 14:14:49 -0500676 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
677 Display d = wm.getDefaultDisplay();
678 d.getRealSize(p);
John Spurlock41f64642013-11-04 13:48:38 -0500679 return p;
680 }
681
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800682 public void setDimensionHints(int width, int height) throws RemoteException {
683 checkPermission(android.Manifest.permission.SET_WALLPAPER_HINTS);
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700684 synchronized (mLock) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700685 int userId = UserHandle.getCallingUserId();
686 WallpaperData wallpaper = mWallpaperMap.get(userId);
687 if (wallpaper == null) {
688 throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
689 }
690 if (width <= 0 || height <= 0) {
691 throw new IllegalArgumentException("width and height must be > 0");
692 }
John Spurlock41f64642013-11-04 13:48:38 -0500693 // Make sure it is at least as large as the display.
694 Point displaySize = getDefaultDisplaySize();
695 width = Math.max(width, displaySize.x);
696 height = Math.max(height, displaySize.y);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700697
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800698 if (width != wallpaper.width || height != wallpaper.height) {
699 wallpaper.width = width;
700 wallpaper.height = height;
701 saveSettingsLocked(wallpaper);
702 if (mCurrentUserId != userId) return; // Don't change the properties now
703 if (wallpaper.connection != null) {
704 if (wallpaper.connection.mEngine != null) {
Dianne Hackborn284ac932009-08-28 10:34:25 -0700705 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800706 wallpaper.connection.mEngine.setDesiredSize(
Dianne Hackborn284ac932009-08-28 10:34:25 -0700707 width, height);
708 } catch (RemoteException e) {
709 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800710 notifyCallbacksLocked(wallpaper);
Michael Wright5203a8b2013-10-03 14:16:42 -0700711 } else if (wallpaper.connection.mService != null) {
712 // We've attached to the service but the engine hasn't attached back to us
713 // yet. This means it will be created with the previous dimensions, so we
714 // need to update it to the new dimensions once it attaches.
715 wallpaper.connection.mDimensionsChanged = true;
Dianne Hackborn284ac932009-08-28 10:34:25 -0700716 }
717 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700718 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800719 }
720 }
721
722 public int getWidthHint() throws RemoteException {
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700723 synchronized (mLock) {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700724 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.getCallingUserId());
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800725 return wallpaper.width;
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700726 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800727 }
728
729 public int getHeightHint() throws RemoteException {
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700730 synchronized (mLock) {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700731 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.getCallingUserId());
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800732 return wallpaper.height;
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700733 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800734 }
735
Dianne Hackborn067e5f62014-09-07 23:14:30 -0700736 public void setDisplayPadding(Rect padding) {
737 checkPermission(android.Manifest.permission.SET_WALLPAPER_HINTS);
738 synchronized (mLock) {
739 int userId = UserHandle.getCallingUserId();
740 WallpaperData wallpaper = mWallpaperMap.get(userId);
741 if (wallpaper == null) {
742 throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
743 }
744 if (padding.left < 0 || padding.top < 0 || padding.right < 0 || padding.bottom < 0) {
745 throw new IllegalArgumentException("padding must be positive: " + padding);
746 }
747
748 if (!padding.equals(wallpaper.padding)) {
749 wallpaper.padding.set(padding);
750 saveSettingsLocked(wallpaper);
751 if (mCurrentUserId != userId) return; // Don't change the properties now
752 if (wallpaper.connection != null) {
753 if (wallpaper.connection.mEngine != null) {
754 try {
755 wallpaper.connection.mEngine.setDisplayPadding(padding);
756 } catch (RemoteException e) {
757 }
758 notifyCallbacksLocked(wallpaper);
759 } else if (wallpaper.connection.mService != null) {
760 // We've attached to the service but the engine hasn't attached back to us
761 // yet. This means it will be created with the previous dimensions, so we
762 // need to update it to the new dimensions once it attaches.
763 wallpaper.connection.mPaddingChanged = true;
764 }
765 }
766 }
767 }
768 }
769
Dianne Hackborn284ac932009-08-28 10:34:25 -0700770 public ParcelFileDescriptor getWallpaper(IWallpaperManagerCallback cb,
771 Bundle outParams) {
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700772 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800773 // This returns the current user's wallpaper, if called by a system service. Else it
774 // returns the wallpaper for the calling user.
775 int callingUid = Binder.getCallingUid();
776 int wallpaperUserId = 0;
777 if (callingUid == android.os.Process.SYSTEM_UID) {
778 wallpaperUserId = mCurrentUserId;
779 } else {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700780 wallpaperUserId = UserHandle.getUserId(callingUid);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800781 }
782 WallpaperData wallpaper = mWallpaperMap.get(wallpaperUserId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700783 try {
Dianne Hackborn284ac932009-08-28 10:34:25 -0700784 if (outParams != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800785 outParams.putInt("width", wallpaper.width);
786 outParams.putInt("height", wallpaper.height);
Dianne Hackborn284ac932009-08-28 10:34:25 -0700787 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800788 wallpaper.callbacks.register(cb);
789 File f = new File(getWallpaperDir(wallpaperUserId), WALLPAPER);
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700790 if (!f.exists()) {
791 return null;
792 }
793 return ParcelFileDescriptor.open(f, MODE_READ_ONLY);
794 } catch (FileNotFoundException e) {
795 /* Shouldn't happen as we check to see if the file exists */
Joe Onorato8a9b2202010-02-26 18:56:32 -0800796 Slog.w(TAG, "Error getting wallpaper", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800797 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700798 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800799 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800800 }
801
Dianne Hackborneb034652009-09-07 00:49:58 -0700802 public WallpaperInfo getWallpaperInfo() {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700803 int userId = UserHandle.getCallingUserId();
Dianne Hackborneb034652009-09-07 00:49:58 -0700804 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800805 WallpaperData wallpaper = mWallpaperMap.get(userId);
806 if (wallpaper.connection != null) {
807 return wallpaper.connection.mInfo;
Dianne Hackborneb034652009-09-07 00:49:58 -0700808 }
809 return null;
810 }
811 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800812
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700813 public ParcelFileDescriptor setWallpaper(String name) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800814 checkPermission(android.Manifest.permission.SET_WALLPAPER);
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700815 synchronized (mLock) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700816 if (DEBUG) Slog.v(TAG, "setWallpaper");
817 int userId = UserHandle.getCallingUserId();
818 WallpaperData wallpaper = mWallpaperMap.get(userId);
819 if (wallpaper == null) {
820 throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
821 }
Dianne Hackborn0cd48872009-08-13 18:51:59 -0700822 final long ident = Binder.clearCallingIdentity();
823 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800824 ParcelFileDescriptor pfd = updateWallpaperBitmapLocked(name, wallpaper);
Dianne Hackborn0cd48872009-08-13 18:51:59 -0700825 if (pfd != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800826 wallpaper.imageWallpaperPending = true;
Dianne Hackborn0cd48872009-08-13 18:51:59 -0700827 }
828 return pfd;
829 } finally {
830 Binder.restoreCallingIdentity(ident);
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700831 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800832 }
833 }
834
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800835 ParcelFileDescriptor updateWallpaperBitmapLocked(String name, WallpaperData wallpaper) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700836 if (name == null) name = "";
837 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800838 File dir = getWallpaperDir(wallpaper.userId);
839 if (!dir.exists()) {
840 dir.mkdir();
Dianne Hackbornebac48c2011-11-29 18:01:50 -0800841 FileUtils.setPermissions(
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800842 dir.getPath(),
Dianne Hackbornebac48c2011-11-29 18:01:50 -0800843 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
844 -1, -1);
845 }
rpcraig554cb0c2012-07-05 06:41:43 -0400846 File file = new File(dir, WALLPAPER);
847 ParcelFileDescriptor fd = ParcelFileDescriptor.open(file,
Christopher Tate90f86ba2014-09-11 12:37:19 -0700848 MODE_CREATE|MODE_READ_WRITE|MODE_TRUNCATE);
rpcraig554cb0c2012-07-05 06:41:43 -0400849 if (!SELinux.restorecon(file)) {
850 return null;
851 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800852 wallpaper.name = name;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700853 return fd;
854 } catch (FileNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800855 Slog.w(TAG, "Error setting wallpaper", e);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700856 }
857 return null;
858 }
859
860 public void setWallpaperComponent(ComponentName name) {
861 checkPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT);
862 synchronized (mLock) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700863 if (DEBUG) Slog.v(TAG, "setWallpaperComponent name=" + name);
864 int userId = UserHandle.getCallingUserId();
865 WallpaperData wallpaper = mWallpaperMap.get(userId);
866 if (wallpaper == null) {
867 throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
868 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700869 final long ident = Binder.clearCallingIdentity();
870 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800871 wallpaper.imageWallpaperPending = false;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700872 bindWallpaperComponentLocked(name, false, true, wallpaper, null);
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700873 } finally {
874 Binder.restoreCallingIdentity(ident);
875 }
876 }
877 }
878
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800879 boolean bindWallpaperComponentLocked(ComponentName componentName, boolean force,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700880 boolean fromUser, WallpaperData wallpaper, IRemoteCallback reply) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800881 if (DEBUG) Slog.v(TAG, "bindWallpaperComponentLocked: componentName=" + componentName);
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700882 // Has the component changed?
Dianne Hackborn9ea31632011-08-05 14:43:50 -0700883 if (!force) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800884 if (wallpaper.connection != null) {
885 if (wallpaper.wallpaperComponent == null) {
Dianne Hackborn9ea31632011-08-05 14:43:50 -0700886 if (componentName == null) {
887 if (DEBUG) Slog.v(TAG, "bindWallpaperComponentLocked: still using default");
888 // Still using default wallpaper.
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700889 return true;
Dianne Hackborn9ea31632011-08-05 14:43:50 -0700890 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800891 } else if (wallpaper.wallpaperComponent.equals(componentName)) {
Dianne Hackborn9ea31632011-08-05 14:43:50 -0700892 // Changing to same wallpaper.
893 if (DEBUG) Slog.v(TAG, "same wallpaper");
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700894 return true;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700895 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700896 }
897 }
898
899 try {
Mike Clerona428b2c2009-11-15 22:53:08 -0800900 if (componentName == null) {
Jeff Sharkey28f08772014-04-16 09:41:58 -0700901 componentName = WallpaperManager.getDefaultWallpaperComponent(mContext);
Mike Clerona428b2c2009-11-15 22:53:08 -0800902 if (componentName == null) {
Mike Cleron322b6ee2009-11-12 07:45:47 -0800903 // Fall back to static image wallpaper
Justin Koh29c30162014-09-05 17:10:10 -0700904 componentName = mImageWallpaper;
Mike Cleron322b6ee2009-11-12 07:45:47 -0800905 //clearWallpaperComponentLocked();
906 //return;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800907 if (DEBUG) Slog.v(TAG, "Using image wallpaper");
Mike Cleron322b6ee2009-11-12 07:45:47 -0800908 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700909 }
Amith Yamasani4e2820c2012-08-28 22:17:23 -0700910 int serviceUserId = wallpaper.userId;
911 ServiceInfo si = mIPackageManager.getServiceInfo(componentName,
912 PackageManager.GET_META_DATA | PackageManager.GET_PERMISSIONS, serviceUserId);
Christopher Tate90952202013-09-08 13:01:28 -0700913 if (si == null) {
914 // The wallpaper component we're trying to use doesn't exist
915 Slog.w(TAG, "Attempted wallpaper " + componentName + " is unavailable");
916 return false;
917 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700918 if (!android.Manifest.permission.BIND_WALLPAPER.equals(si.permission)) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700919 String msg = "Selected service does not require "
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700920 + android.Manifest.permission.BIND_WALLPAPER
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700921 + ": " + componentName;
922 if (fromUser) {
923 throw new SecurityException(msg);
924 }
925 Slog.w(TAG, msg);
926 return false;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700927 }
928
Dianne Hackborneb034652009-09-07 00:49:58 -0700929 WallpaperInfo wi = null;
930
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700931 Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
Justin Koh29c30162014-09-05 17:10:10 -0700932 if (componentName != null && !componentName.equals(mImageWallpaper)) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700933 // Make sure the selected service is actually a wallpaper service.
Amith Yamasani4e2820c2012-08-28 22:17:23 -0700934 List<ResolveInfo> ris =
935 mIPackageManager.queryIntentServices(intent,
936 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
937 PackageManager.GET_META_DATA, serviceUserId);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700938 for (int i=0; i<ris.size(); i++) {
939 ServiceInfo rsi = ris.get(i).serviceInfo;
940 if (rsi.name.equals(si.name) &&
941 rsi.packageName.equals(si.packageName)) {
Dianne Hackborneb034652009-09-07 00:49:58 -0700942 try {
943 wi = new WallpaperInfo(mContext, ris.get(i));
944 } catch (XmlPullParserException e) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700945 if (fromUser) {
946 throw new IllegalArgumentException(e);
947 }
948 Slog.w(TAG, e);
949 return false;
Dianne Hackborneb034652009-09-07 00:49:58 -0700950 } catch (IOException e) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700951 if (fromUser) {
952 throw new IllegalArgumentException(e);
953 }
954 Slog.w(TAG, e);
955 return false;
Dianne Hackborneb034652009-09-07 00:49:58 -0700956 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700957 break;
958 }
959 }
Dianne Hackborneb034652009-09-07 00:49:58 -0700960 if (wi == null) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700961 String msg = "Selected service is not a wallpaper: "
962 + componentName;
963 if (fromUser) {
964 throw new SecurityException(msg);
965 }
966 Slog.w(TAG, msg);
967 return false;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700968 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700969 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700970
971 // Bind the service!
Joe Onorato8a9b2202010-02-26 18:56:32 -0800972 if (DEBUG) Slog.v(TAG, "Binding to:" + componentName);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800973 WallpaperConnection newConn = new WallpaperConnection(wi, wallpaper);
Mike Clerona428b2c2009-11-15 22:53:08 -0800974 intent.setComponent(componentName);
Dianne Hackborndd9b82c2009-09-03 00:18:47 -0700975 intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
976 com.android.internal.R.string.wallpaper_binding_label);
Dianne Hackborn41203752012-08-31 14:05:51 -0700977 intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivityAsUser(
Dianne Hackborneb034652009-09-07 00:49:58 -0700978 mContext, 0,
979 Intent.createChooser(new Intent(Intent.ACTION_SET_WALLPAPER),
980 mContext.getText(com.android.internal.R.string.chooser_wallpaper)),
Dianne Hackborn41203752012-08-31 14:05:51 -0700981 0, null, new UserHandle(serviceUserId)));
Dianne Hackbornc8230512013-07-13 21:32:12 -0700982 if (!mContext.bindServiceAsUser(intent, newConn,
983 Context.BIND_AUTO_CREATE | Context.BIND_SHOWING_UI,
Amith Yamasani27b89e62013-01-16 12:30:11 -0800984 new UserHandle(serviceUserId))) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700985 String msg = "Unable to bind service: "
986 + componentName;
987 if (fromUser) {
988 throw new IllegalArgumentException(msg);
989 }
990 Slog.w(TAG, msg);
991 return false;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700992 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800993 if (wallpaper.userId == mCurrentUserId && mLastWallpaper != null) {
994 detachWallpaperLocked(mLastWallpaper);
995 }
996 wallpaper.wallpaperComponent = componentName;
997 wallpaper.connection = newConn;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700998 newConn.mReply = reply;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700999 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001000 if (wallpaper.userId == mCurrentUserId) {
1001 if (DEBUG)
1002 Slog.v(TAG, "Adding window token: " + newConn.mToken);
1003 mIWindowManager.addWindowToken(newConn.mToken,
1004 WindowManager.LayoutParams.TYPE_WALLPAPER);
1005 mLastWallpaper = wallpaper;
1006 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001007 } catch (RemoteException e) {
1008 }
Amith Yamasani4e2820c2012-08-28 22:17:23 -07001009 } catch (RemoteException e) {
1010 String msg = "Remote exception for " + componentName + "\n" + e;
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001011 if (fromUser) {
1012 throw new IllegalArgumentException(msg);
1013 }
1014 Slog.w(TAG, msg);
1015 return false;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001016 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001017 return true;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001018 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001019
1020 void detachWallpaperLocked(WallpaperData wallpaper) {
1021 if (wallpaper.connection != null) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001022 if (wallpaper.connection.mReply != null) {
1023 try {
1024 wallpaper.connection.mReply.sendResult(null);
1025 } catch (RemoteException e) {
1026 }
1027 wallpaper.connection.mReply = null;
1028 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001029 if (wallpaper.connection.mEngine != null) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001030 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001031 wallpaper.connection.mEngine.destroy();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001032 } catch (RemoteException e) {
1033 }
1034 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001035 mContext.unbindService(wallpaper.connection);
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001036 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001037 if (DEBUG)
1038 Slog.v(TAG, "Removing window token: " + wallpaper.connection.mToken);
1039 mIWindowManager.removeWindowToken(wallpaper.connection.mToken);
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001040 } catch (RemoteException e) {
1041 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001042 wallpaper.connection.mService = null;
1043 wallpaper.connection.mEngine = null;
1044 wallpaper.connection = null;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001045 }
1046 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001047
1048 void clearWallpaperComponentLocked(WallpaperData wallpaper) {
1049 wallpaper.wallpaperComponent = null;
1050 detachWallpaperLocked(wallpaper);
1051 }
1052
1053 void attachServiceLocked(WallpaperConnection conn, WallpaperData wallpaper) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001054 try {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001055 conn.mService.attach(conn, conn.mToken,
1056 WindowManager.LayoutParams.TYPE_WALLPAPER, false,
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001057 wallpaper.width, wallpaper.height, wallpaper.padding);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001058 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001059 Slog.w(TAG, "Failed attaching wallpaper; clearing", e);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001060 if (!wallpaper.wallpaperUpdating) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001061 bindWallpaperComponentLocked(null, false, false, wallpaper, null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001062 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001063 }
1064 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001065
1066 private void notifyCallbacksLocked(WallpaperData wallpaper) {
1067 final int n = wallpaper.callbacks.beginBroadcast();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001068 for (int i = 0; i < n; i++) {
1069 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001070 wallpaper.callbacks.getBroadcastItem(i).onWallpaperChanged();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001071 } catch (RemoteException e) {
1072
1073 // The RemoteCallbackList will take care of removing
1074 // the dead object for us.
1075 }
1076 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001077 wallpaper.callbacks.finishBroadcast();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001078 final Intent intent = new Intent(Intent.ACTION_WALLPAPER_CHANGED);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001079 mContext.sendBroadcastAsUser(intent, new UserHandle(mCurrentUserId));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001080 }
1081
1082 private void checkPermission(String permission) {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001083 if (PackageManager.PERMISSION_GRANTED!= mContext.checkCallingOrSelfPermission(permission)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001084 throw new SecurityException("Access denied to process: " + Binder.getCallingPid()
1085 + ", must have permission " + permission);
1086 }
1087 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001088
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001089 private static JournaledFile makeJournaledFile(int userId) {
Amith Yamasani61f57372012-08-31 12:12:28 -07001090 final String base = new File(getWallpaperDir(userId), WALLPAPER_INFO).getAbsolutePath();
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001091 return new JournaledFile(new File(base), new File(base + ".tmp"));
1092 }
1093
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001094 private void saveSettingsLocked(WallpaperData wallpaper) {
1095 JournaledFile journal = makeJournaledFile(wallpaper.userId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001096 FileOutputStream stream = null;
1097 try {
1098 stream = new FileOutputStream(journal.chooseForWrite(), false);
1099 XmlSerializer out = new FastXmlSerializer();
1100 out.setOutput(stream, "utf-8");
1101 out.startDocument(null, true);
1102
1103 out.startTag(null, "wp");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001104 out.attribute(null, "width", Integer.toString(wallpaper.width));
1105 out.attribute(null, "height", Integer.toString(wallpaper.height));
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001106 if (wallpaper.padding.left != 0) {
1107 out.attribute(null, "paddingLeft", Integer.toString(wallpaper.padding.left));
1108 }
1109 if (wallpaper.padding.top != 0) {
1110 out.attribute(null, "paddingTop", Integer.toString(wallpaper.padding.top));
1111 }
1112 if (wallpaper.padding.right != 0) {
1113 out.attribute(null, "paddingRight", Integer.toString(wallpaper.padding.right));
1114 }
1115 if (wallpaper.padding.bottom != 0) {
1116 out.attribute(null, "paddingBottom", Integer.toString(wallpaper.padding.bottom));
1117 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001118 out.attribute(null, "name", wallpaper.name);
1119 if (wallpaper.wallpaperComponent != null
Justin Koh29c30162014-09-05 17:10:10 -07001120 && !wallpaper.wallpaperComponent.equals(mImageWallpaper)) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001121 out.attribute(null, "component",
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001122 wallpaper.wallpaperComponent.flattenToShortString());
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001123 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001124 out.endTag(null, "wp");
1125
1126 out.endDocument();
1127 stream.close();
1128 journal.commit();
1129 } catch (IOException e) {
1130 try {
1131 if (stream != null) {
1132 stream.close();
1133 }
1134 } catch (IOException ex) {
1135 // Ignore
1136 }
1137 journal.rollback();
1138 }
1139 }
1140
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001141 private void migrateFromOld() {
1142 File oldWallpaper = new File(WallpaperBackupHelper.WALLPAPER_IMAGE_KEY);
1143 File oldInfo = new File(WallpaperBackupHelper.WALLPAPER_INFO_KEY);
1144 if (oldWallpaper.exists()) {
1145 File newWallpaper = new File(getWallpaperDir(0), WALLPAPER);
1146 oldWallpaper.renameTo(newWallpaper);
1147 }
1148 if (oldInfo.exists()) {
1149 File newInfo = new File(getWallpaperDir(0), WALLPAPER_INFO);
1150 oldInfo.renameTo(newInfo);
1151 }
1152 }
1153
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001154 private int getAttributeInt(XmlPullParser parser, String name, int defValue) {
1155 String value = parser.getAttributeValue(null, name);
1156 if (value == null) {
1157 return defValue;
1158 }
1159 return Integer.parseInt(value);
1160 }
1161
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001162 private void loadSettingsLocked(int userId) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001163 if (DEBUG) Slog.v(TAG, "loadSettingsLocked");
Mike Clerona428b2c2009-11-15 22:53:08 -08001164
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001165 JournaledFile journal = makeJournaledFile(userId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001166 FileInputStream stream = null;
1167 File file = journal.chooseForRead();
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001168 if (!file.exists()) {
1169 // This should only happen one time, when upgrading from a legacy system
1170 migrateFromOld();
1171 }
1172 WallpaperData wallpaper = mWallpaperMap.get(userId);
1173 if (wallpaper == null) {
1174 wallpaper = new WallpaperData(userId);
1175 mWallpaperMap.put(userId, wallpaper);
1176 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001177 boolean success = false;
1178 try {
1179 stream = new FileInputStream(file);
1180 XmlPullParser parser = Xml.newPullParser();
1181 parser.setInput(stream, null);
1182
1183 int type;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001184 do {
1185 type = parser.next();
1186 if (type == XmlPullParser.START_TAG) {
1187 String tag = parser.getName();
1188 if ("wp".equals(tag)) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001189 wallpaper.width = Integer.parseInt(parser.getAttributeValue(null, "width"));
1190 wallpaper.height = Integer.parseInt(parser
1191 .getAttributeValue(null, "height"));
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001192 wallpaper.padding.left = getAttributeInt(parser, "paddingLeft", 0);
1193 wallpaper.padding.top = getAttributeInt(parser, "paddingTop", 0);
1194 wallpaper.padding.right = getAttributeInt(parser, "paddingRight", 0);
1195 wallpaper.padding.bottom = getAttributeInt(parser, "paddingBottom", 0);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001196 wallpaper.name = parser.getAttributeValue(null, "name");
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001197 String comp = parser.getAttributeValue(null, "component");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001198 wallpaper.nextWallpaperComponent = comp != null
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001199 ? ComponentName.unflattenFromString(comp)
1200 : null;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001201 if (wallpaper.nextWallpaperComponent == null
1202 || "android".equals(wallpaper.nextWallpaperComponent
1203 .getPackageName())) {
Justin Koh29c30162014-09-05 17:10:10 -07001204 wallpaper.nextWallpaperComponent = mImageWallpaper;
Dianne Hackborn9ea31632011-08-05 14:43:50 -07001205 }
Mike Clerona428b2c2009-11-15 22:53:08 -08001206
1207 if (DEBUG) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001208 Slog.v(TAG, "mWidth:" + wallpaper.width);
1209 Slog.v(TAG, "mHeight:" + wallpaper.height);
1210 Slog.v(TAG, "mName:" + wallpaper.name);
1211 Slog.v(TAG, "mNextWallpaperComponent:"
1212 + wallpaper.nextWallpaperComponent);
Mike Clerona428b2c2009-11-15 22:53:08 -08001213 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001214 }
1215 }
1216 } while (type != XmlPullParser.END_DOCUMENT);
1217 success = true;
Dianne Hackborn13579ed2012-11-28 18:05:36 -08001218 } catch (FileNotFoundException e) {
1219 Slog.w(TAG, "no current wallpaper -- first boot?");
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001220 } catch (NullPointerException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001221 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001222 } catch (NumberFormatException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001223 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001224 } catch (XmlPullParserException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001225 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001226 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001227 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001228 } catch (IndexOutOfBoundsException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001229 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001230 }
1231 try {
1232 if (stream != null) {
1233 stream.close();
1234 }
1235 } catch (IOException e) {
1236 // Ignore
1237 }
1238
1239 if (!success) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001240 wallpaper.width = -1;
1241 wallpaper.height = -1;
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001242 wallpaper.padding.set(0, 0, 0, 0);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001243 wallpaper.name = "";
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001244 }
Dianne Hackborn44bc17c2011-04-20 18:18:51 -07001245
1246 // We always want to have some reasonable width hint.
John Spurlock7ea91ec2013-11-04 13:48:38 -05001247 int baseSize = getMaximumSizeDimension();
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001248 if (wallpaper.width < baseSize) {
1249 wallpaper.width = baseSize;
Dianne Hackborn44bc17c2011-04-20 18:18:51 -07001250 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001251 if (wallpaper.height < baseSize) {
1252 wallpaper.height = baseSize;
Dianne Hackborn44bc17c2011-04-20 18:18:51 -07001253 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001254 }
1255
John Spurlock7ea91ec2013-11-04 13:48:38 -05001256 private int getMaximumSizeDimension() {
1257 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
1258 Display d = wm.getDefaultDisplay();
1259 return d.getMaximumSizeDimension();
1260 }
1261
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07001262 // Called by SystemBackupAgent after files are restored to disk.
Amith Yamasani09e9cdc2013-11-06 14:54:50 -08001263 public void settingsRestored() {
1264 // Verify caller is the system
1265 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
1266 throw new RuntimeException("settingsRestored() can only be called from the system process");
1267 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001268 // TODO: If necessary, make it work for secondary users as well. This currently assumes
1269 // restores only to the primary user
Joe Onorato8a9b2202010-02-26 18:56:32 -08001270 if (DEBUG) Slog.v(TAG, "settingsRestored");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001271 WallpaperData wallpaper = null;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001272 boolean success = false;
1273 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001274 loadSettingsLocked(0);
1275 wallpaper = mWallpaperMap.get(0);
1276 if (wallpaper.nextWallpaperComponent != null
Justin Koh29c30162014-09-05 17:10:10 -07001277 && !wallpaper.nextWallpaperComponent.equals(mImageWallpaper)) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001278 if (!bindWallpaperComponentLocked(wallpaper.nextWallpaperComponent, false, false,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001279 wallpaper, null)) {
Christopher Tatee3ab4d02009-12-16 14:03:31 -08001280 // No such live wallpaper or other failure; fall back to the default
1281 // live wallpaper (since the profile being restored indicated that the
1282 // user had selected a live rather than static one).
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001283 bindWallpaperComponentLocked(null, false, false, wallpaper, null);
Christopher Tatee3ab4d02009-12-16 14:03:31 -08001284 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001285 success = true;
1286 } else {
Mike Clerona428b2c2009-11-15 22:53:08 -08001287 // If there's a wallpaper name, we use that. If that can't be loaded, then we
1288 // use the default.
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001289 if ("".equals(wallpaper.name)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001290 if (DEBUG) Slog.v(TAG, "settingsRestored: name is empty");
Mike Clerona428b2c2009-11-15 22:53:08 -08001291 success = true;
1292 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001293 if (DEBUG) Slog.v(TAG, "settingsRestored: attempting to restore named resource");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001294 success = restoreNamedResourceLocked(wallpaper);
Mike Clerona428b2c2009-11-15 22:53:08 -08001295 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08001296 if (DEBUG) Slog.v(TAG, "settingsRestored: success=" + success);
Mike Clerona428b2c2009-11-15 22:53:08 -08001297 if (success) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001298 bindWallpaperComponentLocked(wallpaper.nextWallpaperComponent, false, false,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001299 wallpaper, null);
Mike Clerona428b2c2009-11-15 22:53:08 -08001300 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001301 }
1302 }
1303
1304 if (!success) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001305 Slog.e(TAG, "Failed to restore wallpaper: '" + wallpaper.name + "'");
1306 wallpaper.name = "";
1307 getWallpaperDir(0).delete();
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001308 }
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07001309
1310 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001311 saveSettingsLocked(wallpaper);
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07001312 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001313 }
1314
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001315 boolean restoreNamedResourceLocked(WallpaperData wallpaper) {
1316 if (wallpaper.name.length() > 4 && "res:".equals(wallpaper.name.substring(0, 4))) {
1317 String resName = wallpaper.name.substring(4);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001318
1319 String pkg = null;
1320 int colon = resName.indexOf(':');
1321 if (colon > 0) {
1322 pkg = resName.substring(0, colon);
1323 }
1324
1325 String ident = null;
1326 int slash = resName.lastIndexOf('/');
1327 if (slash > 0) {
1328 ident = resName.substring(slash+1);
1329 }
1330
1331 String type = null;
1332 if (colon > 0 && slash > 0 && (slash-colon) > 1) {
1333 type = resName.substring(colon+1, slash);
1334 }
1335
1336 if (pkg != null && ident != null && type != null) {
1337 int resId = -1;
1338 InputStream res = null;
1339 FileOutputStream fos = null;
1340 try {
1341 Context c = mContext.createPackageContext(pkg, Context.CONTEXT_RESTRICTED);
1342 Resources r = c.getResources();
1343 resId = r.getIdentifier(resName, null, null);
1344 if (resId == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001345 Slog.e(TAG, "couldn't resolve identifier pkg=" + pkg + " type=" + type
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001346 + " ident=" + ident);
1347 return false;
1348 }
1349
1350 res = r.openRawResource(resId);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001351 if (wallpaper.wallpaperFile.exists()) {
1352 wallpaper.wallpaperFile.delete();
Dianne Hackborn1afd1c92010-03-18 22:47:17 -07001353 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001354 fos = new FileOutputStream(wallpaper.wallpaperFile);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001355
1356 byte[] buffer = new byte[32768];
1357 int amt;
1358 while ((amt=res.read(buffer)) > 0) {
1359 fos.write(buffer, 0, amt);
1360 }
1361 // mWallpaperObserver will notice the close and send the change broadcast
1362
Joe Onorato8a9b2202010-02-26 18:56:32 -08001363 Slog.v(TAG, "Restored wallpaper: " + resName);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001364 return true;
1365 } catch (NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001366 Slog.e(TAG, "Package name " + pkg + " not found");
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001367 } catch (Resources.NotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001368 Slog.e(TAG, "Resource not found: " + resId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001369 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001370 Slog.e(TAG, "IOException while restoring wallpaper ", e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001371 } finally {
1372 if (res != null) {
1373 try {
1374 res.close();
1375 } catch (IOException ex) {}
1376 }
1377 if (fos != null) {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07001378 FileUtils.sync(fos);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001379 try {
1380 fos.close();
1381 } catch (IOException ex) {}
1382 }
1383 }
1384 }
1385 }
1386 return false;
1387 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001388
Dianne Hackborneb034652009-09-07 00:49:58 -07001389 @Override
1390 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1391 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
1392 != PackageManager.PERMISSION_GRANTED) {
1393
1394 pw.println("Permission Denial: can't dump wallpaper service from from pid="
1395 + Binder.getCallingPid()
1396 + ", uid=" + Binder.getCallingUid());
1397 return;
1398 }
1399
1400 synchronized (mLock) {
1401 pw.println("Current Wallpaper Service state:");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001402 for (int i = 0; i < mWallpaperMap.size(); i++) {
1403 WallpaperData wallpaper = mWallpaperMap.valueAt(i);
1404 pw.println(" User " + wallpaper.userId + ":");
1405 pw.print(" mWidth=");
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001406 pw.print(wallpaper.width);
1407 pw.print(" mHeight=");
1408 pw.println(wallpaper.height);
1409 pw.print(" mPadding="); pw.println(wallpaper.padding);
1410 pw.print(" mName="); pw.println(wallpaper.name);
1411 pw.print(" mWallpaperComponent="); pw.println(wallpaper.wallpaperComponent);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001412 if (wallpaper.connection != null) {
1413 WallpaperConnection conn = wallpaper.connection;
1414 pw.print(" Wallpaper connection ");
1415 pw.print(conn);
1416 pw.println(":");
1417 if (conn.mInfo != null) {
1418 pw.print(" mInfo.component=");
1419 pw.println(conn.mInfo.getComponent());
1420 }
1421 pw.print(" mToken=");
1422 pw.println(conn.mToken);
1423 pw.print(" mService=");
1424 pw.println(conn.mService);
1425 pw.print(" mEngine=");
1426 pw.println(conn.mEngine);
1427 pw.print(" mLastDiedTime=");
1428 pw.println(wallpaper.lastDiedTime - SystemClock.uptimeMillis());
1429 }
Dianne Hackborneb034652009-09-07 00:49:58 -07001430 }
1431 }
1432 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001433}