blob: ba0d34061e9e0ed6231c69c3b748a7d6d5b9c742 [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
Christopher Tatebe132e62016-02-10 12:59:49 -080019import static android.app.WallpaperManager.FLAG_SET_SYSTEM;
20import static android.app.WallpaperManager.FLAG_SET_LOCK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080021import static android.os.ParcelFileDescriptor.*;
Christopher Tate111bd4a2009-06-24 17:29:38 -070022
Dianne Hackborn5dc5a002012-09-15 19:33:48 -070023import android.app.ActivityManagerNative;
Amith Yamasani4e2820c2012-08-28 22:17:23 -070024import android.app.AppGlobals;
Benjamin Franzf3ece362015-02-11 10:51:10 +000025import android.app.AppOpsManager;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -070026import android.app.IUserSwitchObserver;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070027import android.app.IWallpaperManager;
28import android.app.IWallpaperManagerCallback;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070029import android.app.PendingIntent;
Dianne Hackborneb034652009-09-07 00:49:58 -070030import android.app.WallpaperInfo;
Jeff Sharkey28f08772014-04-16 09:41:58 -070031import android.app.WallpaperManager;
Oleksandr Peletskyif2519812016-01-26 20:16:06 +010032import android.app.admin.DevicePolicyManager;
Christopher Tate45281862010-03-05 15:46:30 -080033import android.app.backup.BackupManager;
Amith Yamasani37ce3a82012-02-06 12:04:42 -080034import android.app.backup.WallpaperBackupHelper;
Amith Yamasani13593602012-03-22 16:16:17 -070035import android.content.BroadcastReceiver;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070036import android.content.ComponentName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037import android.content.Context;
38import android.content.Intent;
Amith Yamasani13593602012-03-22 16:16:17 -070039import android.content.IntentFilter;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070040import android.content.ServiceConnection;
Amith Yamasani4e2820c2012-08-28 22:17:23 -070041import android.content.pm.IPackageManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042import android.content.pm.PackageManager;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070043import android.content.pm.ResolveInfo;
44import android.content.pm.ServiceInfo;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070045import android.content.pm.PackageManager.NameNotFoundException;
Amith Yamasani6474c4c2012-10-04 14:55:42 -070046import android.content.pm.UserInfo;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070047import android.content.res.Resources;
Christopher Tate1e1e2e02016-01-25 15:34:36 -080048import android.graphics.Bitmap;
49import android.graphics.BitmapFactory;
50import android.graphics.BitmapRegionDecoder;
John Spurlock41f64642013-11-04 13:48:38 -050051import android.graphics.Point;
Dianne Hackborn067e5f62014-09-07 23:14:30 -070052import android.graphics.Rect;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080053import android.os.Binder;
Dianne Hackborn284ac932009-08-28 10:34:25 -070054import android.os.Bundle;
Amith Yamasani13593602012-03-22 16:16:17 -070055import android.os.Environment;
Dianne Hackborn8bdf5932010-10-15 12:54:40 -070056import android.os.FileUtils;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070057import android.os.IBinder;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -070058import android.os.IRemoteCallback;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059import android.os.RemoteException;
60import android.os.FileObserver;
61import android.os.ParcelFileDescriptor;
62import android.os.RemoteCallbackList;
rpcraig554cb0c2012-07-05 06:41:43 -040063import android.os.SELinux;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070064import android.os.ServiceManager;
Dianne Hackborn0cd48872009-08-13 18:51:59 -070065import android.os.SystemClock;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070066import android.os.UserHandle;
Amith Yamasani6474c4c2012-10-04 14:55:42 -070067import android.os.UserManager;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070068import android.service.wallpaper.IWallpaperConnection;
69import android.service.wallpaper.IWallpaperEngine;
70import android.service.wallpaper.IWallpaperService;
71import android.service.wallpaper.WallpaperService;
Filip Gruszczynski5dcc3ac2014-10-13 15:51:39 -070072import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -080073import android.util.Slog;
Amith Yamasani37ce3a82012-02-06 12:04:42 -080074import android.util.SparseArray;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070075import android.util.Xml;
Dianne Hackborn44bc17c2011-04-20 18:18:51 -070076import android.view.Display;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070077import android.view.IWindowManager;
78import android.view.WindowManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079
Christopher Tate1e1e2e02016-01-25 15:34:36 -080080import java.io.BufferedOutputStream;
Dianne Hackborneb034652009-09-07 00:49:58 -070081import java.io.FileDescriptor;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070082import java.io.IOException;
83import java.io.InputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084import java.io.File;
85import java.io.FileNotFoundException;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070086import java.io.FileInputStream;
87import java.io.FileOutputStream;
Dianne Hackborneb034652009-09-07 00:49:58 -070088import java.io.PrintWriter;
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +010089import java.nio.charset.StandardCharsets;
Oleksandr Peletskyif2519812016-01-26 20:16:06 +010090import java.util.Arrays;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070091import java.util.List;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070092
93import org.xmlpull.v1.XmlPullParser;
94import org.xmlpull.v1.XmlPullParserException;
95import org.xmlpull.v1.XmlSerializer;
96
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080097import com.android.internal.content.PackageMonitor;
Dianne Hackborn2269d1572010-02-24 19:54:22 -080098import com.android.internal.util.FastXmlSerializer;
Dianne Hackborn1afd1c92010-03-18 22:47:17 -070099import com.android.internal.util.JournaledFile;
Justin Koh29c30162014-09-05 17:10:10 -0700100import com.android.internal.R;
Filip Gruszczynski5dcc3ac2014-10-13 15:51:39 -0700101import com.android.server.EventLogTags;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102
Christopher Tatead3c2592016-01-20 18:13:17 -0800103import libcore.io.IoUtils;
104
Amith Yamasani09e9cdc2013-11-06 14:54:50 -0800105public class WallpaperManagerService extends IWallpaperManager.Stub {
106 static final String TAG = "WallpaperManagerService";
Joe Onorato7e1693a2016-02-01 17:45:03 -0800107 static final boolean DEBUG = false;
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700108
Christopher Tatebe132e62016-02-10 12:59:49 -0800109 final Object mLock = new Object();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110
Dianne Hackborn0cd48872009-08-13 18:51:59 -0700111 /**
112 * Minimum time between crashes of a wallpaper service for us to consider
113 * restarting it vs. just reverting to the static wallpaper.
114 */
115 static final long MIN_WALLPAPER_CRASH_TIME = 10000;
Filip Gruszczynski5dcc3ac2014-10-13 15:51:39 -0700116 static final int MAX_WALLPAPER_COMPONENT_LOG_LENGTH = 128;
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800117 static final String WALLPAPER = "wallpaper_orig";
118 static final String WALLPAPER_CROP = "wallpaper";
Christopher Tatebe132e62016-02-10 12:59:49 -0800119 static final String WALLPAPER_LOCK_ORIG = "wallpaper_lock_orig";
120 static final String WALLPAPER_LOCK_CROP = "wallpaper_lock";
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800121 static final String WALLPAPER_INFO = "wallpaper_info.xml";
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -0700122
Christopher Tatebe132e62016-02-10 12:59:49 -0800123 // All the various per-user state files we need to be aware of
124 static final String[] sPerUserFiles = new String[] {
125 WALLPAPER, WALLPAPER_CROP,
126 WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP,
127 WALLPAPER_INFO
128 };
129
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -0700130 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800131 * Observes the wallpaper for changes and notifies all IWallpaperServiceCallbacks
132 * that the wallpaper has changed. The CREATE is triggered when there is no
133 * wallpaper set and is created for the first time. The CLOSE_WRITE is triggered
134 * everytime the wallpaper is changed.
135 */
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800136 private class WallpaperObserver extends FileObserver {
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700137
Christopher Tatebe132e62016-02-10 12:59:49 -0800138 final int mUserId;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800139 final WallpaperData mWallpaper;
140 final File mWallpaperDir;
141 final File mWallpaperFile;
Christopher Tatebe132e62016-02-10 12:59:49 -0800142 final File mWallpaperLockFile;
Amith Yamasani52d750c2014-12-10 14:09:05 -0800143 final File mWallpaperInfoFile;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800144
145 public WallpaperObserver(WallpaperData wallpaper) {
146 super(getWallpaperDir(wallpaper.userId).getAbsolutePath(),
Christopher Tateda058e22014-10-08 14:51:09 -0700147 CLOSE_WRITE | MOVED_TO | DELETE | DELETE_SELF);
Christopher Tatebe132e62016-02-10 12:59:49 -0800148 mUserId = wallpaper.userId;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800149 mWallpaperDir = getWallpaperDir(wallpaper.userId);
150 mWallpaper = wallpaper;
151 mWallpaperFile = new File(mWallpaperDir, WALLPAPER);
Christopher Tatebe132e62016-02-10 12:59:49 -0800152 mWallpaperLockFile = new File(mWallpaperDir, WALLPAPER_LOCK_ORIG);
Amith Yamasani52d750c2014-12-10 14:09:05 -0800153 mWallpaperInfoFile = new File(mWallpaperDir, WALLPAPER_INFO);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800154 }
155
Christopher Tatebe132e62016-02-10 12:59:49 -0800156 private WallpaperData dataForEvent(boolean sysChanged, boolean lockChanged) {
157 WallpaperData wallpaper = null;
158 synchronized (mLock) {
159 if (lockChanged) {
160 wallpaper = mLockWallpaperMap.get(mUserId);
161 }
162 if (wallpaper == null) {
163 // no lock-specific wallpaper exists, or sys case, handled together
164 wallpaper = mWallpaperMap.get(mUserId);
165 }
166 }
167 return (wallpaper != null) ? wallpaper : mWallpaper;
168 }
169
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800170 @Override
171 public void onEvent(int event, String path) {
172 if (path == null) {
173 return;
174 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800175 final boolean written = (event == CLOSE_WRITE || event == MOVED_TO);
176 final File changedFile = new File(mWallpaperDir, path);
177
Christopher Tatebe132e62016-02-10 12:59:49 -0800178 // System and system+lock changes happen on the system wallpaper input file;
179 // lock-only changes happen on the dedicated lock wallpaper input file
180 final boolean sysWallpaperChanged = (mWallpaperFile.equals(changedFile));
181 final boolean lockWallpaperChanged = (mWallpaperLockFile.equals(changedFile));
182 WallpaperData wallpaper = dataForEvent(sysWallpaperChanged, lockWallpaperChanged);
183
184 if (DEBUG) {
185 Slog.v(TAG, "Wallpaper file change: evt=" + event
186 + " path=" + path
187 + " sys=" + sysWallpaperChanged
188 + " lock=" + lockWallpaperChanged
189 + " imagePending=" + wallpaper.imageWallpaperPending
190 + " whichPending=0x" + Integer.toHexString(wallpaper.whichPending)
191 + " written=" + written);
192 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800193 synchronized (mLock) {
Christopher Tatebe132e62016-02-10 12:59:49 -0800194 if (sysWallpaperChanged || mWallpaperInfoFile.equals(changedFile)) {
Amith Yamasani52d750c2014-12-10 14:09:05 -0800195 // changing the wallpaper means we'll need to back up the new one
196 long origId = Binder.clearCallingIdentity();
197 BackupManager bm = new BackupManager(mContext);
198 bm.dataChanged();
199 Binder.restoreCallingIdentity(origId);
200 }
Christopher Tatebe132e62016-02-10 12:59:49 -0800201 if (sysWallpaperChanged || lockWallpaperChanged) {
202 notifyCallbacksLocked(wallpaper);
203 if (wallpaper.wallpaperComponent == null
Christopher Tateda058e22014-10-08 14:51:09 -0700204 || event != CLOSE_WRITE // includes the MOVED_TO case
Christopher Tatebe132e62016-02-10 12:59:49 -0800205 || wallpaper.imageWallpaperPending) {
Christopher Tateda058e22014-10-08 14:51:09 -0700206 if (written) {
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800207 // The image source has finished writing the source image,
208 // so we now produce the crop rect (in the background), and
209 // only publish the new displayable (sub)image as a result
210 // of that work.
Christopher Tatebe132e62016-02-10 12:59:49 -0800211 if (DEBUG) {
212 Slog.v(TAG, "Wallpaper written; generating crop");
213 }
214 generateCrop(wallpaper);
215 if (DEBUG) {
216 Slog.v(TAG, "Crop done; invoking completion callback");
217 }
218 wallpaper.imageWallpaperPending = false;
219 if (wallpaper.setComplete != null) {
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800220 try {
Christopher Tatebe132e62016-02-10 12:59:49 -0800221 wallpaper.setComplete.onWallpaperChanged();
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800222 } catch (RemoteException e) {
223 // if this fails we don't really care; the setting app may just
224 // have crashed and that sort of thing is a fact of life.
225 }
226 }
Christopher Tatebe132e62016-02-10 12:59:49 -0800227 if (sysWallpaperChanged) {
228 // If this was the system wallpaper, rebind...
229 bindWallpaperComponentLocked(mImageWallpaper, true,
230 false, wallpaper, null);
231 }
232 if (lockWallpaperChanged
233 || (wallpaper.whichPending & FLAG_SET_LOCK) != 0) {
Christopher Tatebe132e62016-02-10 12:59:49 -0800234 if (DEBUG) {
Christopher Tatedb27b842016-02-25 14:39:17 -0800235 Slog.i(TAG, "Lock-relevant wallpaper changed");
Christopher Tatebe132e62016-02-10 12:59:49 -0800236 }
Christopher Tatedb27b842016-02-25 14:39:17 -0800237 // either a lock-only wallpaper commit or a system+lock event.
238 // if it's system-plus-lock we need to wipe the lock bookkeeping;
239 // we're falling back to displaying the system wallpaper there.
240 if (!lockWallpaperChanged) {
241 mLockWallpaperMap.remove(wallpaper.userId);
242 }
243 // and in any case, tell keyguard about it
Christopher Tatebe132e62016-02-10 12:59:49 -0800244 final IWallpaperManagerCallback cb = mKeyguardListener;
245 if (cb != null) {
246 try {
247 cb.onWallpaperChanged();
248 } catch (RemoteException e) {
249 // Oh well it went away; no big deal
250 }
251 }
252 }
Christopher Tatedb27b842016-02-25 14:39:17 -0800253 saveSettingsLocked(wallpaper.userId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700254 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255 }
256 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800257 }
258 }
259 }
260
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800261 /**
262 * Once a new wallpaper has been written via setWallpaper(...), it needs to be cropped
263 * for display.
264 */
265 private void generateCrop(WallpaperData wallpaper) {
266 boolean success = false;
267 boolean needCrop = false;
Christopher Tatebe132e62016-02-10 12:59:49 -0800268 boolean needScale = false;
269
270 if (DEBUG) {
271 Slog.v(TAG, "Generating crop for new wallpaper(s): 0x"
272 + Integer.toHexString(wallpaper.whichPending)
273 + " to " + wallpaper.cropFile.getName());
274 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800275
276 // Analyse the source; needed in multiple cases
277 BitmapFactory.Options options = new BitmapFactory.Options();
278 options.inJustDecodeBounds = true;
279 BitmapFactory.decodeFile(wallpaper.wallpaperFile.getAbsolutePath(), options);
280
Christopher Tatebe132e62016-02-10 12:59:49 -0800281 // We'll need to scale if the crop is sufficiently bigger than the display
282
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800283 // Legacy case uses an empty crop rect here, so we just preserve the
284 // source image verbatim
285 if (!wallpaper.cropHint.isEmpty()) {
286 // ...clamp the crop rect to the measured bounds...
287 wallpaper.cropHint.right = Math.min(wallpaper.cropHint.right, options.outWidth);
288 wallpaper.cropHint.bottom = Math.min(wallpaper.cropHint.bottom, options.outHeight);
289 // ...and don't bother cropping if what we're left with is identity
290 needCrop = (options.outHeight >= wallpaper.cropHint.height()
291 && options.outWidth >= wallpaper.cropHint.width());
292 }
293
Christopher Tatebe132e62016-02-10 12:59:49 -0800294 if (!needCrop && !needScale) {
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800295 // Simple case: the nominal crop is at least as big as the source image,
296 // so we take the whole thing and just copy the image file directly.
297 if (DEBUG) {
298 Slog.v(TAG, "Null crop of new wallpaper; copying");
299 }
300 success = FileUtils.copyFile(wallpaper.wallpaperFile, wallpaper.cropFile);
301 if (!success) {
302 wallpaper.cropFile.delete();
303 // TODO: fall back to default wallpaper in this case
304 }
305 } else {
Christopher Tatebe132e62016-02-10 12:59:49 -0800306 // Fancy case: crop and/or scale
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800307 FileOutputStream f = null;
308 BufferedOutputStream bos = null;
309 try {
310 BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(
311 wallpaper.wallpaperFile.getAbsolutePath(), false);
312 Bitmap cropped = decoder.decodeRegion(wallpaper.cropHint, null);
313 decoder.recycle();
314
315 if (cropped == null) {
316 Slog.e(TAG, "Could not decode new wallpaper");
317 } else {
318 f = new FileOutputStream(wallpaper.cropFile);
319 bos = new BufferedOutputStream(f, 32*1024);
320 cropped.compress(Bitmap.CompressFormat.PNG, 90, bos);
321 bos.flush(); // don't rely on the implicit flush-at-close when noting success
322 success = true;
323 }
324 } catch (IOException e) {
325 if (DEBUG) {
326 Slog.e(TAG, "I/O error decoding crop: " + e.getMessage());
327 }
328 } finally {
329 IoUtils.closeQuietly(bos);
330 IoUtils.closeQuietly(f);
331 }
332 }
333
334 if (!success) {
335 Slog.e(TAG, "Unable to apply new wallpaper");
336 wallpaper.cropFile.delete();
337 }
338
339 if (wallpaper.cropFile.exists()) {
340 boolean didRestorecon = SELinux.restorecon(wallpaper.cropFile.getAbsoluteFile());
341 if (DEBUG) {
342 Slog.v(TAG, "restorecon() of crop file returned " + didRestorecon);
343 }
344 }
345 }
346
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700347 final Context mContext;
348 final IWindowManager mIWindowManager;
Amith Yamasani4e2820c2012-08-28 22:17:23 -0700349 final IPackageManager mIPackageManager;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800350 final MyPackageMonitor mMonitor;
Benjamin Franzf3ece362015-02-11 10:51:10 +0000351 final AppOpsManager mAppOpsManager;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800352 WallpaperData mLastWallpaper;
Christopher Tatebe132e62016-02-10 12:59:49 -0800353 IWallpaperManagerCallback mKeyguardListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800354
Justin Koh29c30162014-09-05 17:10:10 -0700355 /**
Christopher Tatead3c2592016-01-20 18:13:17 -0800356 * ID of the current wallpaper, changed every time anything sets a wallpaper.
357 * This is used for external detection of wallpaper update activity.
358 */
359 int mWallpaperId;
360
361 /**
Justin Koh29c30162014-09-05 17:10:10 -0700362 * Name of the component used to display bitmap wallpapers from either the gallery or
363 * built-in wallpapers.
364 */
365 final ComponentName mImageWallpaper;
366
Christopher Tatebe132e62016-02-10 12:59:49 -0800367 final SparseArray<WallpaperData> mWallpaperMap = new SparseArray<WallpaperData>();
368 final SparseArray<WallpaperData> mLockWallpaperMap = new SparseArray<WallpaperData>();
Dianne Hackborn07213e62011-08-24 20:05:39 -0700369
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800370 int mCurrentUserId;
Dianne Hackborn07213e62011-08-24 20:05:39 -0700371
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800372 static class WallpaperData {
373
374 int userId;
375
Christopher Tatebe132e62016-02-10 12:59:49 -0800376 final File wallpaperFile; // source image
377 final File cropFile; // eventual destination
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800378
379 /**
Christopher Tatebe132e62016-02-10 12:59:49 -0800380 * True while the client is writing a new wallpaper
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800381 */
382 boolean imageWallpaperPending;
383
384 /**
Christopher Tatebe132e62016-02-10 12:59:49 -0800385 * Which new wallpapers are being written; mirrors the 'which'
386 * selector bit field to setWallpaper().
387 */
388 int whichPending;
389
390 /**
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800391 * Callback once the set + crop is finished
392 */
393 IWallpaperManagerCallback setComplete;
394
395 /**
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800396 * Resource name if using a picture from the wallpaper gallery
397 */
398 String name = "";
399
400 /**
401 * The component name of the currently set live wallpaper.
402 */
403 ComponentName wallpaperComponent;
404
405 /**
406 * The component name of the wallpaper that should be set next.
407 */
408 ComponentName nextWallpaperComponent;
409
Christopher Tatead3c2592016-01-20 18:13:17 -0800410 /**
411 * The ID of this wallpaper
412 */
413 int wallpaperId;
414
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800415 WallpaperConnection connection;
416 long lastDiedTime;
417 boolean wallpaperUpdating;
418 WallpaperObserver wallpaperObserver;
419
420 /**
421 * List of callbacks registered they should each be notified when the wallpaper is changed.
422 */
423 private RemoteCallbackList<IWallpaperManagerCallback> callbacks
424 = new RemoteCallbackList<IWallpaperManagerCallback>();
425
426 int width = -1;
427 int height = -1;
428
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800429 /**
430 * The crop hint supplied for displaying a subset of the source image
431 */
432 final Rect cropHint = new Rect(0, 0, 0, 0);
433
Dianne Hackborn067e5f62014-09-07 23:14:30 -0700434 final Rect padding = new Rect(0, 0, 0, 0);
435
Christopher Tatebe132e62016-02-10 12:59:49 -0800436 WallpaperData(int userId, String inputFileName, String cropFileName) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800437 this.userId = userId;
Christopher Tatebe132e62016-02-10 12:59:49 -0800438 final File wallpaperDir = getWallpaperDir(userId);
439 wallpaperFile = new File(wallpaperDir, inputFileName);
440 cropFile = new File(wallpaperDir, cropFileName);
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800441 }
442
Christopher Tatebe132e62016-02-10 12:59:49 -0800443 // Called during initialization of a given user's wallpaper bookkeeping
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800444 boolean ensureCropExists() {
445 // if the crop file is not present, copy over the source image to use verbatim
446 if (!cropFile.exists()) {
447 return FileUtils.copyFile(wallpaperFile, cropFile);
448 }
449 return true;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800450 }
451 }
452
Christopher Tatead3c2592016-01-20 18:13:17 -0800453 int makeWallpaperIdLocked() {
454 do {
455 ++mWallpaperId;
456 } while (mWallpaperId == 0);
457 return mWallpaperId;
458 }
459
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700460 class WallpaperConnection extends IWallpaperConnection.Stub
461 implements ServiceConnection {
Dianne Hackborneb034652009-09-07 00:49:58 -0700462 final WallpaperInfo mInfo;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700463 final Binder mToken = new Binder();
464 IWallpaperService mService;
465 IWallpaperEngine mEngine;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800466 WallpaperData mWallpaper;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700467 IRemoteCallback mReply;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800468
Michael Wright5203a8b2013-10-03 14:16:42 -0700469 boolean mDimensionsChanged = false;
Dianne Hackborn067e5f62014-09-07 23:14:30 -0700470 boolean mPaddingChanged = false;
Michael Wright5203a8b2013-10-03 14:16:42 -0700471
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800472 public WallpaperConnection(WallpaperInfo info, WallpaperData wallpaper) {
Dianne Hackborneb034652009-09-07 00:49:58 -0700473 mInfo = info;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800474 mWallpaper = wallpaper;
Dianne Hackborneb034652009-09-07 00:49:58 -0700475 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700476
477 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700478 public void onServiceConnected(ComponentName name, IBinder service) {
479 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800480 if (mWallpaper.connection == this) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700481 mService = IWallpaperService.Stub.asInterface(service);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800482 attachServiceLocked(this, mWallpaper);
Dianne Hackborneb034652009-09-07 00:49:58 -0700483 // XXX should probably do saveSettingsLocked() later
484 // when we have an engine, but I'm not sure about
485 // locking there and anyway we always need to be able to
486 // recover if there is something wrong.
Christopher Tatedb27b842016-02-25 14:39:17 -0800487 saveSettingsLocked(mWallpaper.userId);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700488 }
489 }
490 }
491
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700492 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700493 public void onServiceDisconnected(ComponentName name) {
494 synchronized (mLock) {
495 mService = null;
496 mEngine = null;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800497 if (mWallpaper.connection == this) {
498 Slog.w(TAG, "Wallpaper service gone: " + mWallpaper.wallpaperComponent);
499 if (!mWallpaper.wallpaperUpdating
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800500 && mWallpaper.userId == mCurrentUserId) {
Selim Cinekebebadb2014-03-05 22:17:26 +0100501 // There is a race condition which causes
502 // {@link #mWallpaper.wallpaperUpdating} to be false even if it is
503 // currently updating since the broadcast notifying us is async.
504 // This race is overcome by the general rule that we only reset the
505 // wallpaper if its service was shut down twice
506 // during {@link #MIN_WALLPAPER_CRASH_TIME} millis.
507 if (mWallpaper.lastDiedTime != 0
508 && mWallpaper.lastDiedTime + MIN_WALLPAPER_CRASH_TIME
509 > SystemClock.uptimeMillis()) {
510 Slog.w(TAG, "Reverting to built-in wallpaper!");
Christopher Tatebe132e62016-02-10 12:59:49 -0800511 clearWallpaperLocked(true, FLAG_SET_SYSTEM, mWallpaper.userId, null);
Selim Cinekebebadb2014-03-05 22:17:26 +0100512 } else {
513 mWallpaper.lastDiedTime = SystemClock.uptimeMillis();
514 }
Filip Gruszczynski5a589432014-10-14 12:06:06 -0700515 final String flattened = name.flattenToString();
Filip Gruszczynski5dcc3ac2014-10-13 15:51:39 -0700516 EventLog.writeEvent(EventLogTags.WP_WALLPAPER_CRASHED,
Filip Gruszczynski5a589432014-10-14 12:06:06 -0700517 flattened.substring(0, Math.min(flattened.length(),
518 MAX_WALLPAPER_COMPONENT_LOG_LENGTH)));
Dianne Hackborn0cd48872009-08-13 18:51:59 -0700519 }
520 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700521 }
522 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800523
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700524 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700525 public void attachEngine(IWallpaperEngine engine) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700526 synchronized (mLock) {
527 mEngine = engine;
Michael Wright5203a8b2013-10-03 14:16:42 -0700528 if (mDimensionsChanged) {
529 try {
530 mEngine.setDesiredSize(mWallpaper.width, mWallpaper.height);
531 } catch (RemoteException e) {
532 Slog.w(TAG, "Failed to set wallpaper dimensions", e);
533 }
534 mDimensionsChanged = false;
535 }
Dianne Hackborn067e5f62014-09-07 23:14:30 -0700536 if (mPaddingChanged) {
537 try {
538 mEngine.setDisplayPadding(mWallpaper.padding);
539 } catch (RemoteException e) {
540 Slog.w(TAG, "Failed to set wallpaper padding", e);
541 }
542 mPaddingChanged = false;
543 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700544 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700545 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800546
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700547 @Override
548 public void engineShown(IWallpaperEngine engine) {
549 synchronized (mLock) {
550 if (mReply != null) {
551 long ident = Binder.clearCallingIdentity();
552 try {
553 mReply.sendResult(null);
554 } catch (RemoteException e) {
555 Binder.restoreCallingIdentity(ident);
556 }
557 mReply = null;
558 }
559 }
560 }
561
562 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700563 public ParcelFileDescriptor setWallpaper(String name) {
564 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800565 if (mWallpaper.connection == this) {
Christopher Tatead3c2592016-01-20 18:13:17 -0800566 return updateWallpaperBitmapLocked(name, mWallpaper, null);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700567 }
568 return null;
569 }
570 }
571 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800572
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800573 class MyPackageMonitor extends PackageMonitor {
574 @Override
575 public void onPackageUpdateFinished(String packageName, int uid) {
576 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700577 if (mCurrentUserId != getChangingUserId()) {
578 return;
579 }
580 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
581 if (wallpaper != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800582 if (wallpaper.wallpaperComponent != null
583 && wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
584 wallpaper.wallpaperUpdating = false;
585 ComponentName comp = wallpaper.wallpaperComponent;
586 clearWallpaperComponentLocked(wallpaper);
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700587 if (!bindWallpaperComponentLocked(comp, false, false,
588 wallpaper, null)) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800589 Slog.w(TAG, "Wallpaper no longer available; reverting to default");
Christopher Tatebe132e62016-02-10 12:59:49 -0800590 clearWallpaperLocked(false, FLAG_SET_SYSTEM, wallpaper.userId, null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800591 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700592 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800593 }
594 }
595 }
596
597 @Override
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700598 public void onPackageModified(String packageName) {
599 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700600 if (mCurrentUserId != getChangingUserId()) {
601 return;
602 }
603 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
604 if (wallpaper != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800605 if (wallpaper.wallpaperComponent == null
606 || !wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700607 return;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800608 }
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700609 doPackagesChangedLocked(true, wallpaper);
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700610 }
611 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700612 }
613
614 @Override
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800615 public void onPackageUpdateStarted(String packageName, int uid) {
616 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700617 if (mCurrentUserId != getChangingUserId()) {
618 return;
619 }
620 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
621 if (wallpaper != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800622 if (wallpaper.wallpaperComponent != null
623 && wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
624 wallpaper.wallpaperUpdating = true;
625 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800626 }
627 }
628 }
629
630 @Override
631 public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700632 synchronized (mLock) {
633 boolean changed = false;
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700634 if (mCurrentUserId != getChangingUserId()) {
635 return false;
636 }
637 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
638 if (wallpaper != null) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700639 boolean res = doPackagesChangedLocked(doit, wallpaper);
640 changed |= res;
641 }
642 return changed;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800643 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800644 }
645
646 @Override
647 public void onSomePackagesChanged() {
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700648 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700649 if (mCurrentUserId != getChangingUserId()) {
650 return;
651 }
652 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
653 if (wallpaper != null) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700654 doPackagesChangedLocked(true, wallpaper);
655 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800656 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800657 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800658
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700659 boolean doPackagesChangedLocked(boolean doit, WallpaperData wallpaper) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800660 boolean changed = false;
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700661 if (wallpaper.wallpaperComponent != null) {
662 int change = isPackageDisappearing(wallpaper.wallpaperComponent
663 .getPackageName());
664 if (change == PACKAGE_PERMANENT_CHANGE
665 || change == PACKAGE_TEMPORARY_CHANGE) {
666 changed = true;
667 if (doit) {
668 Slog.w(TAG, "Wallpaper uninstalled, removing: "
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800669 + wallpaper.wallpaperComponent);
Christopher Tatebe132e62016-02-10 12:59:49 -0800670 clearWallpaperLocked(false, FLAG_SET_SYSTEM, wallpaper.userId, null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800671 }
672 }
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700673 }
674 if (wallpaper.nextWallpaperComponent != null) {
675 int change = isPackageDisappearing(wallpaper.nextWallpaperComponent
676 .getPackageName());
677 if (change == PACKAGE_PERMANENT_CHANGE
678 || change == PACKAGE_TEMPORARY_CHANGE) {
679 wallpaper.nextWallpaperComponent = null;
680 }
681 }
682 if (wallpaper.wallpaperComponent != null
683 && isPackageModified(wallpaper.wallpaperComponent.getPackageName())) {
684 try {
685 mContext.getPackageManager().getServiceInfo(
686 wallpaper.wallpaperComponent, 0);
687 } catch (NameNotFoundException e) {
688 Slog.w(TAG, "Wallpaper component gone, removing: "
689 + wallpaper.wallpaperComponent);
Christopher Tatebe132e62016-02-10 12:59:49 -0800690 clearWallpaperLocked(false, FLAG_SET_SYSTEM, wallpaper.userId, null);
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700691 }
692 }
693 if (wallpaper.nextWallpaperComponent != null
694 && isPackageModified(wallpaper.nextWallpaperComponent.getPackageName())) {
695 try {
696 mContext.getPackageManager().getServiceInfo(
697 wallpaper.nextWallpaperComponent, 0);
698 } catch (NameNotFoundException e) {
699 wallpaper.nextWallpaperComponent = null;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800700 }
701 }
702 return changed;
703 }
704 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +0100705
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700706 public WallpaperManagerService(Context context) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800707 if (DEBUG) Slog.v(TAG, "WallpaperService startup");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800708 mContext = context;
Justin Koh29c30162014-09-05 17:10:10 -0700709 mImageWallpaper = ComponentName.unflattenFromString(
710 context.getResources().getString(R.string.image_wallpaper_component));
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700711 mIWindowManager = IWindowManager.Stub.asInterface(
712 ServiceManager.getService(Context.WINDOW_SERVICE));
Amith Yamasani4e2820c2012-08-28 22:17:23 -0700713 mIPackageManager = AppGlobals.getPackageManager();
Benjamin Franzf3ece362015-02-11 10:51:10 +0000714 mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800715 mMonitor = new MyPackageMonitor();
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700716 mMonitor.register(context, null, UserHandle.ALL, true);
Xiaohui Chen233d94c2015-07-30 15:08:00 -0700717 getWallpaperDir(UserHandle.USER_SYSTEM).mkdirs();
718 loadSettingsLocked(UserHandle.USER_SYSTEM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800719 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +0100720
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800721 private static File getWallpaperDir(int userId) {
Amith Yamasani61f57372012-08-31 12:12:28 -0700722 return Environment.getUserSystemDirectory(userId);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800723 }
724
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800725 @Override
726 protected void finalize() throws Throwable {
727 super.finalize();
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800728 for (int i = 0; i < mWallpaperMap.size(); i++) {
729 WallpaperData wallpaper = mWallpaperMap.valueAt(i);
730 wallpaper.wallpaperObserver.stopWatching();
731 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800732 }
Amith Yamasani13593602012-03-22 16:16:17 -0700733
Svetoslav Ganova0027152013-06-25 14:59:53 -0700734 public void systemRunning() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800735 if (DEBUG) Slog.v(TAG, "systemReady");
Xiaohui Chen233d94c2015-07-30 15:08:00 -0700736 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.USER_SYSTEM);
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800737 if (!wallpaper.ensureCropExists()) {
Christopher Tatebe132e62016-02-10 12:59:49 -0800738 clearWallpaperLocked(false, FLAG_SET_SYSTEM, UserHandle.USER_SYSTEM, null);
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800739 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700740 switchWallpaper(wallpaper, null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800741 wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper);
742 wallpaper.wallpaperObserver.startWatching();
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800743
Amith Yamasani13593602012-03-22 16:16:17 -0700744 IntentFilter userFilter = new IntentFilter();
Amith Yamasani13593602012-03-22 16:16:17 -0700745 userFilter.addAction(Intent.ACTION_USER_REMOVED);
Amith Yamasani756901d2012-10-12 12:30:07 -0700746 userFilter.addAction(Intent.ACTION_USER_STOPPING);
Amith Yamasani13593602012-03-22 16:16:17 -0700747 mContext.registerReceiver(new BroadcastReceiver() {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800748 @Override
Amith Yamasani13593602012-03-22 16:16:17 -0700749 public void onReceive(Context context, Intent intent) {
750 String action = intent.getAction();
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700751 if (Intent.ACTION_USER_REMOVED.equals(action)) {
Amith Yamasani756901d2012-10-12 12:30:07 -0700752 onRemoveUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
753 UserHandle.USER_NULL));
Amith Yamasani13593602012-03-22 16:16:17 -0700754 }
Amith Yamasani0c293712012-10-30 12:23:52 -0700755 // TODO: Race condition causing problems when cleaning up on stopping a user.
756 // Comment this out for now.
757 // else if (Intent.ACTION_USER_STOPPING.equals(action)) {
758 // onStoppingUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
759 // UserHandle.USER_NULL));
760 // }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800761 }
Amith Yamasani13593602012-03-22 16:16:17 -0700762 }, userFilter);
Amith Yamasani756901d2012-10-12 12:30:07 -0700763
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700764 try {
765 ActivityManagerNative.getDefault().registerUserSwitchObserver(
766 new IUserSwitchObserver.Stub() {
767 @Override
768 public void onUserSwitching(int newUserId, IRemoteCallback reply) {
769 switchUser(newUserId, reply);
770 }
771
772 @Override
773 public void onUserSwitchComplete(int newUserId) throws RemoteException {
774 }
Kenny Guy42979622015-04-13 18:03:05 +0000775
776 @Override
777 public void onForegroundProfileSwitch(int newProfileId) {
778 // Ignore.
779 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700780 });
781 } catch (RemoteException e) {
782 // TODO Auto-generated catch block
783 e.printStackTrace();
784 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800785 }
786
Amith Yamasani09e9cdc2013-11-06 14:54:50 -0800787 /** Called by SystemBackupAgent */
788 public String getName() {
789 // Verify caller is the system
790 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
791 throw new RuntimeException("getName() can only be called from the system process");
792 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700793 synchronized (mLock) {
794 return mWallpaperMap.get(0).name;
795 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800796 }
797
Christopher Tatebe132e62016-02-10 12:59:49 -0800798 void stopObserver(WallpaperData wallpaper) {
799 if (wallpaper != null) {
800 if (wallpaper.wallpaperObserver != null) {
801 wallpaper.wallpaperObserver.stopWatching();
802 wallpaper.wallpaperObserver = null;
Amith Yamasani13593602012-03-22 16:16:17 -0700803 }
Amith Yamasani756901d2012-10-12 12:30:07 -0700804 }
805 }
806
Christopher Tatebe132e62016-02-10 12:59:49 -0800807 void stopObserversLocked(int userId) {
808 stopObserver(mWallpaperMap.get(userId));
809 stopObserver(mLockWallpaperMap.get(userId));
810 mWallpaperMap.remove(userId);
811 mLockWallpaperMap.remove(userId);
812 }
813
Amith Yamasani756901d2012-10-12 12:30:07 -0700814 void onRemoveUser(int userId) {
815 if (userId < 1) return;
Christopher Tatebe132e62016-02-10 12:59:49 -0800816
817 final File wallpaperDir = getWallpaperDir(userId);
Amith Yamasani756901d2012-10-12 12:30:07 -0700818 synchronized (mLock) {
Christopher Tatebe132e62016-02-10 12:59:49 -0800819 stopObserversLocked(userId);
820 for (String filename : sPerUserFiles) {
821 new File(wallpaperDir, filename).delete();
822 }
Amith Yamasani13593602012-03-22 16:16:17 -0700823 }
824 }
825
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700826 void switchUser(int userId, IRemoteCallback reply) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800827 synchronized (mLock) {
828 mCurrentUserId = userId;
Christopher Tatebe132e62016-02-10 12:59:49 -0800829 WallpaperData wallpaper = getWallpaperSafeLocked(userId, FLAG_SET_SYSTEM);
Amith Yamasani6474c4c2012-10-04 14:55:42 -0700830 // Not started watching yet, in case wallpaper data was loaded for other reasons.
831 if (wallpaper.wallpaperObserver == null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800832 wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper);
833 wallpaper.wallpaperObserver.startWatching();
834 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700835 switchWallpaper(wallpaper, reply);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800836 }
837 }
838
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700839 void switchWallpaper(WallpaperData wallpaper, IRemoteCallback reply) {
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700840 synchronized (mLock) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700841 RuntimeException e = null;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700842 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800843 ComponentName cname = wallpaper.wallpaperComponent != null ?
844 wallpaper.wallpaperComponent : wallpaper.nextWallpaperComponent;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700845 if (bindWallpaperComponentLocked(cname, true, false, wallpaper, reply)) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700846 return;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700847 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700848 } catch (RuntimeException e1) {
849 e = e1;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700850 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700851 Slog.w(TAG, "Failure starting previous wallpaper", e);
Christopher Tatebe132e62016-02-10 12:59:49 -0800852 clearWallpaperLocked(false, FLAG_SET_SYSTEM, wallpaper.userId, reply);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800853 }
854 }
855
Christopher Tatebe132e62016-02-10 12:59:49 -0800856 @Override
857 public void clearWallpaper(String callingPackage, int which, int userId) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800858 if (DEBUG) Slog.v(TAG, "clearWallpaper");
Benjamin Franzf3ece362015-02-11 10:51:10 +0000859 checkPermission(android.Manifest.permission.SET_WALLPAPER);
Oleksandr Peletskyif2519812016-01-26 20:16:06 +0100860 if (!isWallpaperSupported(callingPackage) || !isWallpaperSettingAllowed(callingPackage)) {
Benjamin Franzf3ece362015-02-11 10:51:10 +0000861 return;
862 }
Christopher Tatebe132e62016-02-10 12:59:49 -0800863 if (userId != UserHandle.getCallingUserId()) {
864 // cross-user call
865 mContext.enforceCallingOrSelfPermission(
866 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
867 "WallpaperManagerService");
868 }
869
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800870 synchronized (mLock) {
Christopher Tatebe132e62016-02-10 12:59:49 -0800871 clearWallpaperLocked(false, which, userId, null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800872 }
873 }
874
Christopher Tatebe132e62016-02-10 12:59:49 -0800875 void clearWallpaperLocked(boolean defaultFailed, int which, int userId, IRemoteCallback reply) {
876 if (which != FLAG_SET_SYSTEM && which != FLAG_SET_LOCK) {
877 throw new IllegalArgumentException("Must specify exactly one kind of wallpaper to read");
878 }
879
880 WallpaperData wallpaper = null;
881 if (which == FLAG_SET_LOCK) {
882 wallpaper = mLockWallpaperMap.get(userId);
883 if (wallpaper == null) {
884 // It's already gone; we're done.
885 return;
886 }
887 } else {
888 wallpaper = mWallpaperMap.get(userId);
889 if (wallpaper == null) {
890 // Might need to bring it in the first time to establish our rewrite
891 loadSettingsLocked(userId);
892 wallpaper = mWallpaperMap.get(userId);
893 }
894 }
Benjamin Franzf3ece362015-02-11 10:51:10 +0000895 if (wallpaper == null) {
896 return;
897 }
Christopher Tatebe132e62016-02-10 12:59:49 -0800898
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800899 final long ident = Binder.clearCallingIdentity();
900 try {
Christopher Tatebe132e62016-02-10 12:59:49 -0800901 if (wallpaper.wallpaperFile.exists()) {
902 wallpaper.wallpaperFile.delete();
903 wallpaper.cropFile.delete();
904 if (which == FLAG_SET_LOCK) {
905 final IWallpaperManagerCallback cb = mKeyguardListener;
906 if (cb != null) {
907 try {
908 cb.onWallpaperChanged();
909 } catch (RemoteException e) {
910 // Oh well it went away; no big deal
911 }
912 }
913 return;
914 }
915 }
916
Christopher Tateecd827a2014-09-05 17:42:34 -0700917 RuntimeException e = null;
918 try {
919 wallpaper.imageWallpaperPending = false;
920 if (userId != mCurrentUserId) return;
921 if (bindWallpaperComponentLocked(defaultFailed
922 ? mImageWallpaper
923 : null, true, false, wallpaper, reply)) {
924 return;
925 }
926 } catch (IllegalArgumentException e1) {
927 e = e1;
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700928 }
Christopher Tateecd827a2014-09-05 17:42:34 -0700929
930 // This can happen if the default wallpaper component doesn't
931 // exist. This should be a system configuration problem, but
932 // let's not let it crash the system and just live with no
933 // wallpaper.
934 Slog.e(TAG, "Default wallpaper component not found!", e);
935 clearWallpaperComponentLocked(wallpaper);
936 if (reply != null) {
937 try {
938 reply.sendResult(null);
939 } catch (RemoteException e1) {
940 }
941 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800942 } finally {
943 Binder.restoreCallingIdentity(ident);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800944 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700945 }
946
947 public boolean hasNamedWallpaper(String name) {
948 synchronized (mLock) {
Amith Yamasani6474c4c2012-10-04 14:55:42 -0700949 List<UserInfo> users;
950 long ident = Binder.clearCallingIdentity();
951 try {
952 users = ((UserManager) mContext.getSystemService(Context.USER_SERVICE)).getUsers();
953 } finally {
954 Binder.restoreCallingIdentity(ident);
955 }
956 for (UserInfo user: users) {
Benjamin Franzf3ece362015-02-11 10:51:10 +0000957 // ignore managed profiles
958 if (user.isManagedProfile()) {
959 continue;
960 }
Amith Yamasani6474c4c2012-10-04 14:55:42 -0700961 WallpaperData wd = mWallpaperMap.get(user.id);
962 if (wd == null) {
963 // User hasn't started yet, so load her settings to peek at the wallpaper
964 loadSettingsLocked(user.id);
965 wd = mWallpaperMap.get(user.id);
966 }
967 if (wd != null && name.equals(wd.name)) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700968 return true;
969 }
970 }
971 }
972 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800973 }
974
John Spurlock41f64642013-11-04 13:48:38 -0500975 private Point getDefaultDisplaySize() {
976 Point p = new Point();
John Spurlockd6e836c2013-11-18 14:14:49 -0500977 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
978 Display d = wm.getDefaultDisplay();
979 d.getRealSize(p);
John Spurlock41f64642013-11-04 13:48:38 -0500980 return p;
981 }
982
Benjamin Franzf3ece362015-02-11 10:51:10 +0000983 public void setDimensionHints(int width, int height, String callingPackage)
984 throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800985 checkPermission(android.Manifest.permission.SET_WALLPAPER_HINTS);
Benjamin Franzf3ece362015-02-11 10:51:10 +0000986 if (!isWallpaperSupported(callingPackage)) {
987 return;
988 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700989 synchronized (mLock) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700990 int userId = UserHandle.getCallingUserId();
Christopher Tatebe132e62016-02-10 12:59:49 -0800991 WallpaperData wallpaper = getWallpaperSafeLocked(userId, FLAG_SET_SYSTEM);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700992 if (width <= 0 || height <= 0) {
993 throw new IllegalArgumentException("width and height must be > 0");
994 }
John Spurlock41f64642013-11-04 13:48:38 -0500995 // Make sure it is at least as large as the display.
996 Point displaySize = getDefaultDisplaySize();
997 width = Math.max(width, displaySize.x);
998 height = Math.max(height, displaySize.y);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700999
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001000 if (width != wallpaper.width || height != wallpaper.height) {
1001 wallpaper.width = width;
1002 wallpaper.height = height;
Christopher Tatedb27b842016-02-25 14:39:17 -08001003 saveSettingsLocked(userId);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001004 if (mCurrentUserId != userId) return; // Don't change the properties now
1005 if (wallpaper.connection != null) {
1006 if (wallpaper.connection.mEngine != null) {
Dianne Hackborn284ac932009-08-28 10:34:25 -07001007 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001008 wallpaper.connection.mEngine.setDesiredSize(
Dianne Hackborn284ac932009-08-28 10:34:25 -07001009 width, height);
1010 } catch (RemoteException e) {
1011 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001012 notifyCallbacksLocked(wallpaper);
Michael Wright5203a8b2013-10-03 14:16:42 -07001013 } else if (wallpaper.connection.mService != null) {
1014 // We've attached to the service but the engine hasn't attached back to us
1015 // yet. This means it will be created with the previous dimensions, so we
1016 // need to update it to the new dimensions once it attaches.
1017 wallpaper.connection.mDimensionsChanged = true;
Dianne Hackborn284ac932009-08-28 10:34:25 -07001018 }
1019 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001020 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001021 }
1022 }
1023
1024 public int getWidthHint() throws RemoteException {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001025 synchronized (mLock) {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07001026 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.getCallingUserId());
Benjamin Franzf3ece362015-02-11 10:51:10 +00001027 if (wallpaper != null) {
1028 return wallpaper.width;
1029 } else {
1030 return 0;
1031 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001032 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001033 }
1034
1035 public int getHeightHint() throws RemoteException {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001036 synchronized (mLock) {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07001037 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.getCallingUserId());
Benjamin Franzf3ece362015-02-11 10:51:10 +00001038 if (wallpaper != null) {
1039 return wallpaper.height;
1040 } else {
1041 return 0;
1042 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001043 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001044 }
1045
Benjamin Franzf3ece362015-02-11 10:51:10 +00001046 public void setDisplayPadding(Rect padding, String callingPackage) {
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001047 checkPermission(android.Manifest.permission.SET_WALLPAPER_HINTS);
Benjamin Franzf3ece362015-02-11 10:51:10 +00001048 if (!isWallpaperSupported(callingPackage)) {
1049 return;
1050 }
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001051 synchronized (mLock) {
1052 int userId = UserHandle.getCallingUserId();
Christopher Tatebe132e62016-02-10 12:59:49 -08001053 WallpaperData wallpaper = getWallpaperSafeLocked(userId, FLAG_SET_SYSTEM);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001054 if (padding.left < 0 || padding.top < 0 || padding.right < 0 || padding.bottom < 0) {
1055 throw new IllegalArgumentException("padding must be positive: " + padding);
1056 }
1057
1058 if (!padding.equals(wallpaper.padding)) {
1059 wallpaper.padding.set(padding);
Christopher Tatedb27b842016-02-25 14:39:17 -08001060 saveSettingsLocked(userId);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001061 if (mCurrentUserId != userId) return; // Don't change the properties now
1062 if (wallpaper.connection != null) {
1063 if (wallpaper.connection.mEngine != null) {
1064 try {
1065 wallpaper.connection.mEngine.setDisplayPadding(padding);
1066 } catch (RemoteException e) {
1067 }
1068 notifyCallbacksLocked(wallpaper);
1069 } else if (wallpaper.connection.mService != null) {
1070 // We've attached to the service but the engine hasn't attached back to us
1071 // yet. This means it will be created with the previous dimensions, so we
1072 // need to update it to the new dimensions once it attaches.
1073 wallpaper.connection.mPaddingChanged = true;
1074 }
1075 }
1076 }
1077 }
1078 }
1079
Yorke Leedcd93cc2016-01-08 14:12:55 -08001080 @Override
Christopher Tatebe132e62016-02-10 12:59:49 -08001081 public ParcelFileDescriptor getWallpaper(IWallpaperManagerCallback cb, final int which,
1082 Bundle outParams, int wallpaperUserId) {
1083 if (wallpaperUserId != UserHandle.getCallingUserId()) {
1084 // cross-user call
1085 mContext.enforceCallingOrSelfPermission(
1086 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
1087 "WallpaperManagerService");
1088 }
1089
1090 if (which != FLAG_SET_SYSTEM && which != FLAG_SET_LOCK) {
1091 throw new IllegalArgumentException("Must specify exactly one kind of wallpaper to read");
1092 }
1093
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001094 synchronized (mLock) {
Vadim Tryshev8cde0792016-02-19 17:02:15 -08001095 final SparseArray<WallpaperData> whichSet =
1096 (which == FLAG_SET_LOCK) ? mLockWallpaperMap : mWallpaperMap;
1097 WallpaperData wallpaper = whichSet.get(wallpaperUserId);
1098 if (wallpaper == null) {
1099 // common case, this is the first lookup post-boot of the system or
1100 // unified lock, so we bring up the saved state lazily now and recheck.
1101 loadSettingsLocked(wallpaperUserId);
1102 wallpaper = whichSet.get(wallpaperUserId);
Christopher Tatebe132e62016-02-10 12:59:49 -08001103 if (wallpaper == null) {
Christopher Tatebe132e62016-02-10 12:59:49 -08001104 return null;
1105 }
Benjamin Franzf3ece362015-02-11 10:51:10 +00001106 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001107 try {
Dianne Hackborn284ac932009-08-28 10:34:25 -07001108 if (outParams != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001109 outParams.putInt("width", wallpaper.width);
1110 outParams.putInt("height", wallpaper.height);
Dianne Hackborn284ac932009-08-28 10:34:25 -07001111 }
Christopher Tateea6724a2016-02-18 18:39:19 -08001112 if (cb != null) {
1113 wallpaper.callbacks.register(cb);
1114 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001115 if (!wallpaper.cropFile.exists()) {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001116 return null;
1117 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001118 return ParcelFileDescriptor.open(wallpaper.cropFile, MODE_READ_ONLY);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001119 } catch (FileNotFoundException e) {
1120 /* Shouldn't happen as we check to see if the file exists */
Joe Onorato8a9b2202010-02-26 18:56:32 -08001121 Slog.w(TAG, "Error getting wallpaper", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001122 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001123 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001124 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001125 }
1126
Dianne Hackborneb034652009-09-07 00:49:58 -07001127 public WallpaperInfo getWallpaperInfo() {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07001128 int userId = UserHandle.getCallingUserId();
Dianne Hackborneb034652009-09-07 00:49:58 -07001129 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001130 WallpaperData wallpaper = mWallpaperMap.get(userId);
Benjamin Franzf3ece362015-02-11 10:51:10 +00001131 if (wallpaper != null && wallpaper.connection != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001132 return wallpaper.connection.mInfo;
Dianne Hackborneb034652009-09-07 00:49:58 -07001133 }
1134 return null;
1135 }
1136 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001137
Christopher Tatead3c2592016-01-20 18:13:17 -08001138 @Override
Christopher Tatebe132e62016-02-10 12:59:49 -08001139 public boolean setLockWallpaperCallback(IWallpaperManagerCallback cb) {
1140 checkPermission(android.Manifest.permission.INTERNAL_SYSTEM_WINDOW);
1141 synchronized (mLock) {
1142 mKeyguardListener = cb;
1143 }
1144 return true;
1145 }
1146
1147 @Override
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001148 public ParcelFileDescriptor setWallpaper(String name, String callingPackage,
1149 Rect cropHint, Bundle extras, int which, IWallpaperManagerCallback completion) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001150 checkPermission(android.Manifest.permission.SET_WALLPAPER);
Christopher Tatead3c2592016-01-20 18:13:17 -08001151
Christopher Tatebe132e62016-02-10 12:59:49 -08001152 if ((which & (FLAG_SET_LOCK|FLAG_SET_SYSTEM)) == 0) {
1153 Slog.e(TAG, "Must specify a valid wallpaper category to set");
Christopher Tatead3c2592016-01-20 18:13:17 -08001154 return null;
1155 }
1156
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001157 if (!isWallpaperSupported(callingPackage) || !isWallpaperSettingAllowed(callingPackage)) {
Benjamin Franzf3ece362015-02-11 10:51:10 +00001158 return null;
1159 }
Christopher Tatead3c2592016-01-20 18:13:17 -08001160
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001161 // "null" means the no-op crop, preserving the full input image
1162 if (cropHint == null) {
1163 cropHint = new Rect(0, 0, 0, 0);
1164 } else {
1165 if (cropHint.isEmpty()
1166 || cropHint.left < 0
1167 || cropHint.top < 0) {
1168 return null;
1169 }
1170 }
1171
Christopher Tatebe132e62016-02-10 12:59:49 -08001172 final int userId = UserHandle.getCallingUserId();
1173
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001174 synchronized (mLock) {
Christopher Tatebe132e62016-02-10 12:59:49 -08001175 if (DEBUG) Slog.v(TAG, "setWallpaper which=0x" + Integer.toHexString(which));
1176 WallpaperData wallpaper;
1177
1178 wallpaper = getWallpaperSafeLocked(userId, which);
Dianne Hackborn0cd48872009-08-13 18:51:59 -07001179 final long ident = Binder.clearCallingIdentity();
1180 try {
Christopher Tatead3c2592016-01-20 18:13:17 -08001181 ParcelFileDescriptor pfd = updateWallpaperBitmapLocked(name, wallpaper, extras);
Dianne Hackborn0cd48872009-08-13 18:51:59 -07001182 if (pfd != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001183 wallpaper.imageWallpaperPending = true;
Christopher Tatebe132e62016-02-10 12:59:49 -08001184 wallpaper.whichPending = which;
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001185 wallpaper.setComplete = completion;
1186 wallpaper.cropHint.set(cropHint);
Dianne Hackborn0cd48872009-08-13 18:51:59 -07001187 }
1188 return pfd;
1189 } finally {
1190 Binder.restoreCallingIdentity(ident);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001191 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001192 }
1193 }
1194
Christopher Tatead3c2592016-01-20 18:13:17 -08001195 ParcelFileDescriptor updateWallpaperBitmapLocked(String name, WallpaperData wallpaper,
1196 Bundle extras) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001197 if (name == null) name = "";
1198 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001199 File dir = getWallpaperDir(wallpaper.userId);
1200 if (!dir.exists()) {
1201 dir.mkdir();
Dianne Hackbornebac48c2011-11-29 18:01:50 -08001202 FileUtils.setPermissions(
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001203 dir.getPath(),
Dianne Hackbornebac48c2011-11-29 18:01:50 -08001204 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
1205 -1, -1);
1206 }
Christopher Tatebe132e62016-02-10 12:59:49 -08001207 ParcelFileDescriptor fd = ParcelFileDescriptor.open(wallpaper.wallpaperFile,
Christopher Tate90f86ba2014-09-11 12:37:19 -07001208 MODE_CREATE|MODE_READ_WRITE|MODE_TRUNCATE);
Christopher Tatebe132e62016-02-10 12:59:49 -08001209 if (!SELinux.restorecon(wallpaper.wallpaperFile)) {
rpcraig554cb0c2012-07-05 06:41:43 -04001210 return null;
1211 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001212 wallpaper.name = name;
Christopher Tatead3c2592016-01-20 18:13:17 -08001213 wallpaper.wallpaperId = makeWallpaperIdLocked();
1214 if (extras != null) {
1215 extras.putInt(WallpaperManager.EXTRA_NEW_WALLPAPER_ID, wallpaper.wallpaperId);
1216 }
1217 if (DEBUG) {
1218 Slog.v(TAG, "updateWallpaperBitmapLocked() : id=" + wallpaper.wallpaperId
Christopher Tatebe132e62016-02-10 12:59:49 -08001219 + " name=" + name + " file=" + wallpaper.wallpaperFile.getName());
Christopher Tatead3c2592016-01-20 18:13:17 -08001220 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001221 return fd;
1222 } catch (FileNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001223 Slog.w(TAG, "Error setting wallpaper", e);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001224 }
1225 return null;
1226 }
1227
Benjamin Franzf3ece362015-02-11 10:51:10 +00001228 public void setWallpaperComponentChecked(ComponentName name, String callingPackage) {
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001229 if (isWallpaperSupported(callingPackage) && isWallpaperSettingAllowed(callingPackage)) {
Benjamin Franzf3ece362015-02-11 10:51:10 +00001230 setWallpaperComponent(name);
1231 }
1232 }
1233
1234 // ToDo: Remove this version of the function
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001235 public void setWallpaperComponent(ComponentName name) {
1236 checkPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT);
1237 synchronized (mLock) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001238 if (DEBUG) Slog.v(TAG, "setWallpaperComponent name=" + name);
1239 int userId = UserHandle.getCallingUserId();
1240 WallpaperData wallpaper = mWallpaperMap.get(userId);
1241 if (wallpaper == null) {
1242 throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
1243 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001244 final long ident = Binder.clearCallingIdentity();
1245 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001246 wallpaper.imageWallpaperPending = false;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001247 bindWallpaperComponentLocked(name, false, true, wallpaper, null);
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001248 } finally {
1249 Binder.restoreCallingIdentity(ident);
1250 }
1251 }
1252 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001253
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001254 boolean bindWallpaperComponentLocked(ComponentName componentName, boolean force,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001255 boolean fromUser, WallpaperData wallpaper, IRemoteCallback reply) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001256 if (DEBUG) Slog.v(TAG, "bindWallpaperComponentLocked: componentName=" + componentName);
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001257 // Has the component changed?
Dianne Hackborn9ea31632011-08-05 14:43:50 -07001258 if (!force) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001259 if (wallpaper.connection != null) {
1260 if (wallpaper.wallpaperComponent == null) {
Dianne Hackborn9ea31632011-08-05 14:43:50 -07001261 if (componentName == null) {
1262 if (DEBUG) Slog.v(TAG, "bindWallpaperComponentLocked: still using default");
1263 // Still using default wallpaper.
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001264 return true;
Dianne Hackborn9ea31632011-08-05 14:43:50 -07001265 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001266 } else if (wallpaper.wallpaperComponent.equals(componentName)) {
Dianne Hackborn9ea31632011-08-05 14:43:50 -07001267 // Changing to same wallpaper.
1268 if (DEBUG) Slog.v(TAG, "same wallpaper");
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001269 return true;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001270 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001271 }
1272 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001273
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001274 try {
Mike Clerona428b2c2009-11-15 22:53:08 -08001275 if (componentName == null) {
Jeff Sharkey28f08772014-04-16 09:41:58 -07001276 componentName = WallpaperManager.getDefaultWallpaperComponent(mContext);
Mike Clerona428b2c2009-11-15 22:53:08 -08001277 if (componentName == null) {
Mike Cleron322b6ee2009-11-12 07:45:47 -08001278 // Fall back to static image wallpaper
Justin Koh29c30162014-09-05 17:10:10 -07001279 componentName = mImageWallpaper;
Mike Cleron322b6ee2009-11-12 07:45:47 -08001280 //clearWallpaperComponentLocked();
1281 //return;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001282 if (DEBUG) Slog.v(TAG, "Using image wallpaper");
Mike Cleron322b6ee2009-11-12 07:45:47 -08001283 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001284 }
Amith Yamasani4e2820c2012-08-28 22:17:23 -07001285 int serviceUserId = wallpaper.userId;
1286 ServiceInfo si = mIPackageManager.getServiceInfo(componentName,
1287 PackageManager.GET_META_DATA | PackageManager.GET_PERMISSIONS, serviceUserId);
Christopher Tate90952202013-09-08 13:01:28 -07001288 if (si == null) {
1289 // The wallpaper component we're trying to use doesn't exist
1290 Slog.w(TAG, "Attempted wallpaper " + componentName + " is unavailable");
1291 return false;
1292 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001293 if (!android.Manifest.permission.BIND_WALLPAPER.equals(si.permission)) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001294 String msg = "Selected service does not require "
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001295 + android.Manifest.permission.BIND_WALLPAPER
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001296 + ": " + componentName;
1297 if (fromUser) {
1298 throw new SecurityException(msg);
1299 }
1300 Slog.w(TAG, msg);
1301 return false;
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001302 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001303
Dianne Hackborneb034652009-09-07 00:49:58 -07001304 WallpaperInfo wi = null;
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001305
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001306 Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
Justin Koh29c30162014-09-05 17:10:10 -07001307 if (componentName != null && !componentName.equals(mImageWallpaper)) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001308 // Make sure the selected service is actually a wallpaper service.
Amith Yamasani4e2820c2012-08-28 22:17:23 -07001309 List<ResolveInfo> ris =
1310 mIPackageManager.queryIntentServices(intent,
1311 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
1312 PackageManager.GET_META_DATA, serviceUserId);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001313 for (int i=0; i<ris.size(); i++) {
1314 ServiceInfo rsi = ris.get(i).serviceInfo;
1315 if (rsi.name.equals(si.name) &&
1316 rsi.packageName.equals(si.packageName)) {
Dianne Hackborneb034652009-09-07 00:49:58 -07001317 try {
1318 wi = new WallpaperInfo(mContext, ris.get(i));
1319 } catch (XmlPullParserException e) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001320 if (fromUser) {
1321 throw new IllegalArgumentException(e);
1322 }
1323 Slog.w(TAG, e);
1324 return false;
Dianne Hackborneb034652009-09-07 00:49:58 -07001325 } catch (IOException e) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001326 if (fromUser) {
1327 throw new IllegalArgumentException(e);
1328 }
1329 Slog.w(TAG, e);
1330 return false;
Dianne Hackborneb034652009-09-07 00:49:58 -07001331 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001332 break;
1333 }
1334 }
Dianne Hackborneb034652009-09-07 00:49:58 -07001335 if (wi == null) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001336 String msg = "Selected service is not a wallpaper: "
1337 + componentName;
1338 if (fromUser) {
1339 throw new SecurityException(msg);
1340 }
1341 Slog.w(TAG, msg);
1342 return false;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001343 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001344 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001345
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001346 // Bind the service!
Joe Onorato8a9b2202010-02-26 18:56:32 -08001347 if (DEBUG) Slog.v(TAG, "Binding to:" + componentName);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001348 WallpaperConnection newConn = new WallpaperConnection(wi, wallpaper);
Mike Clerona428b2c2009-11-15 22:53:08 -08001349 intent.setComponent(componentName);
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07001350 intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
1351 com.android.internal.R.string.wallpaper_binding_label);
Dianne Hackborn41203752012-08-31 14:05:51 -07001352 intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivityAsUser(
Dianne Hackborneb034652009-09-07 00:49:58 -07001353 mContext, 0,
1354 Intent.createChooser(new Intent(Intent.ACTION_SET_WALLPAPER),
1355 mContext.getText(com.android.internal.R.string.chooser_wallpaper)),
Dianne Hackborn41203752012-08-31 14:05:51 -07001356 0, null, new UserHandle(serviceUserId)));
Dianne Hackbornc8230512013-07-13 21:32:12 -07001357 if (!mContext.bindServiceAsUser(intent, newConn,
Dianne Hackbornd69e4c12015-04-24 09:54:54 -07001358 Context.BIND_AUTO_CREATE | Context.BIND_SHOWING_UI
1359 | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
Amith Yamasani27b89e62013-01-16 12:30:11 -08001360 new UserHandle(serviceUserId))) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001361 String msg = "Unable to bind service: "
1362 + componentName;
1363 if (fromUser) {
1364 throw new IllegalArgumentException(msg);
1365 }
1366 Slog.w(TAG, msg);
1367 return false;
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001368 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001369 if (wallpaper.userId == mCurrentUserId && mLastWallpaper != null) {
1370 detachWallpaperLocked(mLastWallpaper);
1371 }
1372 wallpaper.wallpaperComponent = componentName;
1373 wallpaper.connection = newConn;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001374 newConn.mReply = reply;
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001375 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001376 if (wallpaper.userId == mCurrentUserId) {
1377 if (DEBUG)
1378 Slog.v(TAG, "Adding window token: " + newConn.mToken);
1379 mIWindowManager.addWindowToken(newConn.mToken,
1380 WindowManager.LayoutParams.TYPE_WALLPAPER);
1381 mLastWallpaper = wallpaper;
1382 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001383 } catch (RemoteException e) {
1384 }
Amith Yamasani4e2820c2012-08-28 22:17:23 -07001385 } catch (RemoteException e) {
1386 String msg = "Remote exception for " + componentName + "\n" + e;
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001387 if (fromUser) {
1388 throw new IllegalArgumentException(msg);
1389 }
1390 Slog.w(TAG, msg);
1391 return false;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001392 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001393 return true;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001394 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001395
1396 void detachWallpaperLocked(WallpaperData wallpaper) {
1397 if (wallpaper.connection != null) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001398 if (wallpaper.connection.mReply != null) {
1399 try {
1400 wallpaper.connection.mReply.sendResult(null);
1401 } catch (RemoteException e) {
1402 }
1403 wallpaper.connection.mReply = null;
1404 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001405 if (wallpaper.connection.mEngine != null) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001406 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001407 wallpaper.connection.mEngine.destroy();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001408 } catch (RemoteException e) {
1409 }
1410 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001411 mContext.unbindService(wallpaper.connection);
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001412 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001413 if (DEBUG)
1414 Slog.v(TAG, "Removing window token: " + wallpaper.connection.mToken);
1415 mIWindowManager.removeWindowToken(wallpaper.connection.mToken);
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001416 } catch (RemoteException e) {
1417 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001418 wallpaper.connection.mService = null;
1419 wallpaper.connection.mEngine = null;
1420 wallpaper.connection = null;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001421 }
1422 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001423
1424 void clearWallpaperComponentLocked(WallpaperData wallpaper) {
1425 wallpaper.wallpaperComponent = null;
1426 detachWallpaperLocked(wallpaper);
1427 }
1428
1429 void attachServiceLocked(WallpaperConnection conn, WallpaperData wallpaper) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001430 try {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001431 conn.mService.attach(conn, conn.mToken,
1432 WindowManager.LayoutParams.TYPE_WALLPAPER, false,
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001433 wallpaper.width, wallpaper.height, wallpaper.padding);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001434 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001435 Slog.w(TAG, "Failed attaching wallpaper; clearing", e);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001436 if (!wallpaper.wallpaperUpdating) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001437 bindWallpaperComponentLocked(null, false, false, wallpaper, null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001438 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001439 }
1440 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001441
1442 private void notifyCallbacksLocked(WallpaperData wallpaper) {
1443 final int n = wallpaper.callbacks.beginBroadcast();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001444 for (int i = 0; i < n; i++) {
1445 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001446 wallpaper.callbacks.getBroadcastItem(i).onWallpaperChanged();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001447 } catch (RemoteException e) {
1448
1449 // The RemoteCallbackList will take care of removing
1450 // the dead object for us.
1451 }
1452 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001453 wallpaper.callbacks.finishBroadcast();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001454 final Intent intent = new Intent(Intent.ACTION_WALLPAPER_CHANGED);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001455 mContext.sendBroadcastAsUser(intent, new UserHandle(mCurrentUserId));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001456 }
1457
1458 private void checkPermission(String permission) {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001459 if (PackageManager.PERMISSION_GRANTED!= mContext.checkCallingOrSelfPermission(permission)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001460 throw new SecurityException("Access denied to process: " + Binder.getCallingPid()
1461 + ", must have permission " + permission);
1462 }
1463 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001464
Benjamin Franzf3ece362015-02-11 10:51:10 +00001465 /**
1466 * Certain user types do not support wallpapers (e.g. managed profiles). The check is
1467 * implemented through through the OP_WRITE_WALLPAPER AppOp.
1468 */
1469 public boolean isWallpaperSupported(String callingPackage) {
1470 return mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_WRITE_WALLPAPER, Binder.getCallingUid(),
1471 callingPackage) == AppOpsManager.MODE_ALLOWED;
1472 }
1473
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001474 @Override
1475 public boolean isWallpaperSettingAllowed(String callingPackage) {
1476 final PackageManager pm = mContext.getPackageManager();
1477 String[] uidPackages = pm.getPackagesForUid(Binder.getCallingUid());
1478 boolean uidMatchPackage = Arrays.asList(uidPackages).contains(callingPackage);
1479 if (!uidMatchPackage) {
1480 return false; // callingPackage was faked.
1481 }
1482
1483 final DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
1484 if (dpm.isDeviceOwnerApp(callingPackage) || dpm.isProfileOwnerApp(callingPackage)) {
1485 return true;
1486 }
1487 final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
1488 return !um.hasUserRestriction(UserManager.DISALLOW_SET_WALLPAPER);
1489 }
1490
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001491 private static JournaledFile makeJournaledFile(int userId) {
Amith Yamasani61f57372012-08-31 12:12:28 -07001492 final String base = new File(getWallpaperDir(userId), WALLPAPER_INFO).getAbsolutePath();
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001493 return new JournaledFile(new File(base), new File(base + ".tmp"));
1494 }
1495
Christopher Tatedb27b842016-02-25 14:39:17 -08001496 private void saveSettingsLocked(int userId) {
1497 JournaledFile journal = makeJournaledFile(userId);
1498 FileOutputStream fstream = null;
1499 BufferedOutputStream stream = null;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001500 try {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001501 XmlSerializer out = new FastXmlSerializer();
Christopher Tatedb27b842016-02-25 14:39:17 -08001502 fstream = new FileOutputStream(journal.chooseForWrite(), false);
1503 stream = new BufferedOutputStream(fstream);
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001504 out.setOutput(stream, StandardCharsets.UTF_8.name());
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001505 out.startDocument(null, true);
1506
Christopher Tatedb27b842016-02-25 14:39:17 -08001507 WallpaperData wallpaper;
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001508
Christopher Tatedb27b842016-02-25 14:39:17 -08001509 wallpaper = mWallpaperMap.get(userId);
1510 if (wallpaper != null) {
1511 writeWallpaperAttributes(out, "wp", wallpaper);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001512 }
Christopher Tatedb27b842016-02-25 14:39:17 -08001513 wallpaper = mLockWallpaperMap.get(userId);
1514 if (wallpaper != null) {
1515 writeWallpaperAttributes(out, "kwp", wallpaper);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001516 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001517
1518 out.endDocument();
Christopher Tatedb27b842016-02-25 14:39:17 -08001519
1520 stream.flush(); // also flushes fstream
1521 FileUtils.sync(fstream);
1522 stream.close(); // also closes fstream
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001523 journal.commit();
1524 } catch (IOException e) {
Christopher Tatead3c2592016-01-20 18:13:17 -08001525 IoUtils.closeQuietly(stream);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001526 journal.rollback();
1527 }
1528 }
1529
Christopher Tatedb27b842016-02-25 14:39:17 -08001530 private void writeWallpaperAttributes(XmlSerializer out, String tag, WallpaperData wallpaper)
1531 throws IllegalArgumentException, IllegalStateException, IOException {
1532 out.startTag(null, tag);
1533 out.attribute(null, "id", Integer.toString(wallpaper.wallpaperId));
1534 out.attribute(null, "width", Integer.toString(wallpaper.width));
1535 out.attribute(null, "height", Integer.toString(wallpaper.height));
1536
1537 out.attribute(null, "cropLeft", Integer.toString(wallpaper.cropHint.left));
1538 out.attribute(null, "cropTop", Integer.toString(wallpaper.cropHint.top));
1539 out.attribute(null, "cropRight", Integer.toString(wallpaper.cropHint.right));
1540 out.attribute(null, "cropBottom", Integer.toString(wallpaper.cropHint.bottom));
1541
1542 if (wallpaper.padding.left != 0) {
1543 out.attribute(null, "paddingLeft", Integer.toString(wallpaper.padding.left));
1544 }
1545 if (wallpaper.padding.top != 0) {
1546 out.attribute(null, "paddingTop", Integer.toString(wallpaper.padding.top));
1547 }
1548 if (wallpaper.padding.right != 0) {
1549 out.attribute(null, "paddingRight", Integer.toString(wallpaper.padding.right));
1550 }
1551 if (wallpaper.padding.bottom != 0) {
1552 out.attribute(null, "paddingBottom", Integer.toString(wallpaper.padding.bottom));
1553 }
1554
1555 out.attribute(null, "name", wallpaper.name);
1556 if (wallpaper.wallpaperComponent != null
1557 && !wallpaper.wallpaperComponent.equals(mImageWallpaper)) {
1558 out.attribute(null, "component",
1559 wallpaper.wallpaperComponent.flattenToShortString());
1560 }
1561 out.endTag(null, tag);
1562 }
1563
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001564 private void migrateFromOld() {
1565 File oldWallpaper = new File(WallpaperBackupHelper.WALLPAPER_IMAGE_KEY);
1566 File oldInfo = new File(WallpaperBackupHelper.WALLPAPER_INFO_KEY);
1567 if (oldWallpaper.exists()) {
1568 File newWallpaper = new File(getWallpaperDir(0), WALLPAPER);
1569 oldWallpaper.renameTo(newWallpaper);
1570 }
1571 if (oldInfo.exists()) {
1572 File newInfo = new File(getWallpaperDir(0), WALLPAPER_INFO);
1573 oldInfo.renameTo(newInfo);
1574 }
1575 }
1576
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001577 private int getAttributeInt(XmlPullParser parser, String name, int defValue) {
1578 String value = parser.getAttributeValue(null, name);
1579 if (value == null) {
1580 return defValue;
1581 }
1582 return Integer.parseInt(value);
1583 }
1584
Xiaohui Chenac531942015-05-13 13:20:52 -07001585 /**
1586 * Sometimes it is expected the wallpaper map may not have a user's data. E.g. This could
1587 * happen during user switch. The async user switch observer may not have received
1588 * the event yet. We use this safe method when we don't care about this ordering and just
1589 * want to update the data. The data is going to be applied when the user switch observer
1590 * is eventually executed.
1591 */
Christopher Tatebe132e62016-02-10 12:59:49 -08001592 private WallpaperData getWallpaperSafeLocked(int userId, int which) {
1593 // We're setting either just system (work with the system wallpaper),
1594 // both (also work with the system wallpaper), or just the lock
1595 // wallpaper (update against the existing lock wallpaper if any).
1596 // Combined or just-system operations use the 'system' WallpaperData
1597 // for this use; lock-only operations use the dedicated one.
1598 final SparseArray<WallpaperData> whichSet =
1599 (which == FLAG_SET_LOCK) ? mLockWallpaperMap : mWallpaperMap;
1600 WallpaperData wallpaper = whichSet.get(userId);
Xiaohui Chenac531942015-05-13 13:20:52 -07001601 if (wallpaper == null) {
Christopher Tatebe132e62016-02-10 12:59:49 -08001602 // common case, this is the first lookup post-boot of the system or
1603 // unified lock, so we bring up the saved state lazily now and recheck.
Xiaohui Chenac531942015-05-13 13:20:52 -07001604 loadSettingsLocked(userId);
Christopher Tatebe132e62016-02-10 12:59:49 -08001605 wallpaper = whichSet.get(userId);
1606 // if it's still null here, this is a lock-only operation and there is not
1607 // yet a lock-only wallpaper set for this user, so we need to establish
1608 // it now.
1609 if (wallpaper == null) {
1610 if (which == FLAG_SET_LOCK) {
1611 wallpaper = new WallpaperData(userId,
1612 WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP);
1613 mLockWallpaperMap.put(userId, wallpaper);
1614 } else {
1615 // sanity fallback: we're in bad shape, but establishing a known
1616 // valid system+lock WallpaperData will keep us from dying.
1617 Slog.wtf(TAG, "Didn't find wallpaper in non-lock case!");
1618 wallpaper = new WallpaperData(userId, WALLPAPER, WALLPAPER_CROP);
1619 mWallpaperMap.put(userId, wallpaper);
1620 }
1621 }
Xiaohui Chenac531942015-05-13 13:20:52 -07001622 }
1623 return wallpaper;
1624 }
1625
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001626 private void loadSettingsLocked(int userId) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001627 if (DEBUG) Slog.v(TAG, "loadSettingsLocked");
Benjamin Franzf3ece362015-02-11 10:51:10 +00001628
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001629 JournaledFile journal = makeJournaledFile(userId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001630 FileInputStream stream = null;
1631 File file = journal.chooseForRead();
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001632 if (!file.exists()) {
1633 // This should only happen one time, when upgrading from a legacy system
1634 migrateFromOld();
1635 }
1636 WallpaperData wallpaper = mWallpaperMap.get(userId);
1637 if (wallpaper == null) {
Christopher Tatebe132e62016-02-10 12:59:49 -08001638 wallpaper = new WallpaperData(userId, WALLPAPER, WALLPAPER_CROP);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001639 mWallpaperMap.put(userId, wallpaper);
Christopher Tatebe132e62016-02-10 12:59:49 -08001640 wallpaper.ensureCropExists();
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001641 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001642 boolean success = false;
1643 try {
1644 stream = new FileInputStream(file);
1645 XmlPullParser parser = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001646 parser.setInput(stream, StandardCharsets.UTF_8.name());
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001647
1648 int type;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001649 do {
1650 type = parser.next();
1651 if (type == XmlPullParser.START_TAG) {
1652 String tag = parser.getName();
1653 if ("wp".equals(tag)) {
Christopher Tatebe132e62016-02-10 12:59:49 -08001654 // Common to system + lock wallpapers
1655 parseWallpaperAttributes(parser, wallpaper);
Christopher Tatead3c2592016-01-20 18:13:17 -08001656
Christopher Tatebe132e62016-02-10 12:59:49 -08001657 // A system wallpaper might also be a live wallpaper
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001658 String comp = parser.getAttributeValue(null, "component");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001659 wallpaper.nextWallpaperComponent = comp != null
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001660 ? ComponentName.unflattenFromString(comp)
1661 : null;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001662 if (wallpaper.nextWallpaperComponent == null
1663 || "android".equals(wallpaper.nextWallpaperComponent
1664 .getPackageName())) {
Justin Koh29c30162014-09-05 17:10:10 -07001665 wallpaper.nextWallpaperComponent = mImageWallpaper;
Dianne Hackborn9ea31632011-08-05 14:43:50 -07001666 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001667
Mike Clerona428b2c2009-11-15 22:53:08 -08001668 if (DEBUG) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001669 Slog.v(TAG, "mWidth:" + wallpaper.width);
1670 Slog.v(TAG, "mHeight:" + wallpaper.height);
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001671 Slog.v(TAG, "cropRect:" + wallpaper.cropHint);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001672 Slog.v(TAG, "mName:" + wallpaper.name);
1673 Slog.v(TAG, "mNextWallpaperComponent:"
1674 + wallpaper.nextWallpaperComponent);
Mike Clerona428b2c2009-11-15 22:53:08 -08001675 }
Christopher Tatebe132e62016-02-10 12:59:49 -08001676 } else if ("kwp".equals(tag)) {
1677 // keyguard-specific wallpaper for this user
1678 WallpaperData lockWallpaper = mLockWallpaperMap.get(userId);
1679 if (lockWallpaper == null) {
1680 lockWallpaper = new WallpaperData(userId,
1681 WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP);
1682 mLockWallpaperMap.put(userId, lockWallpaper);
1683 }
1684 parseWallpaperAttributes(parser, lockWallpaper);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001685 }
1686 }
1687 } while (type != XmlPullParser.END_DOCUMENT);
1688 success = true;
Dianne Hackborn13579ed2012-11-28 18:05:36 -08001689 } catch (FileNotFoundException e) {
1690 Slog.w(TAG, "no current wallpaper -- first boot?");
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001691 } catch (NullPointerException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001692 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001693 } catch (NumberFormatException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001694 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001695 } catch (XmlPullParserException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001696 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001697 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001698 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001699 } catch (IndexOutOfBoundsException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001700 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001701 }
Christopher Tatead3c2592016-01-20 18:13:17 -08001702 IoUtils.closeQuietly(stream);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001703
1704 if (!success) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001705 wallpaper.width = -1;
1706 wallpaper.height = -1;
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001707 wallpaper.cropHint.set(0, 0, 0, 0);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001708 wallpaper.padding.set(0, 0, 0, 0);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001709 wallpaper.name = "";
Christopher Tatead3c2592016-01-20 18:13:17 -08001710 } else {
1711 if (wallpaper.wallpaperId <= 0) {
1712 wallpaper.wallpaperId = makeWallpaperIdLocked();
1713 if (DEBUG) {
1714 Slog.w(TAG, "Didn't set wallpaper id in loadSettingsLocked(" + userId
1715 + "); now " + wallpaper.wallpaperId);
1716 }
1717 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001718 }
Dianne Hackborn44bc17c2011-04-20 18:18:51 -07001719
1720 // We always want to have some reasonable width hint.
John Spurlock7ea91ec2013-11-04 13:48:38 -05001721 int baseSize = getMaximumSizeDimension();
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001722 if (wallpaper.width < baseSize) {
1723 wallpaper.width = baseSize;
Dianne Hackborn44bc17c2011-04-20 18:18:51 -07001724 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001725 if (wallpaper.height < baseSize) {
1726 wallpaper.height = baseSize;
Dianne Hackborn44bc17c2011-04-20 18:18:51 -07001727 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001728 // and crop, if not previously specified
1729 if (wallpaper.cropHint.width() <= 0
1730 || wallpaper.cropHint.height() <= 0) {
1731 wallpaper.cropHint.set(0, 0, wallpaper.width, wallpaper.height);
1732 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001733 }
1734
Christopher Tatebe132e62016-02-10 12:59:49 -08001735 private void parseWallpaperAttributes(XmlPullParser parser, WallpaperData wallpaper) {
1736 final String idString = parser.getAttributeValue(null, "id");
1737 if (idString != null) {
1738 final int id = wallpaper.wallpaperId = Integer.parseInt(idString);
1739 if (id > mWallpaperId) {
1740 mWallpaperId = id;
1741 }
1742 } else {
1743 wallpaper.wallpaperId = makeWallpaperIdLocked();
1744 }
1745
1746 wallpaper.width = Integer.parseInt(parser.getAttributeValue(null, "width"));
1747 wallpaper.height = Integer.parseInt(parser
1748 .getAttributeValue(null, "height"));
1749 wallpaper.cropHint.left = getAttributeInt(parser, "cropLeft", 0);
1750 wallpaper.cropHint.top = getAttributeInt(parser, "cropTop", 0);
1751 wallpaper.cropHint.right = getAttributeInt(parser, "cropRight", 0);
1752 wallpaper.cropHint.bottom = getAttributeInt(parser, "cropBottom", 0);
1753 wallpaper.padding.left = getAttributeInt(parser, "paddingLeft", 0);
1754 wallpaper.padding.top = getAttributeInt(parser, "paddingTop", 0);
1755 wallpaper.padding.right = getAttributeInt(parser, "paddingRight", 0);
1756 wallpaper.padding.bottom = getAttributeInt(parser, "paddingBottom", 0);
1757 wallpaper.name = parser.getAttributeValue(null, "name");
1758 }
1759
John Spurlock7ea91ec2013-11-04 13:48:38 -05001760 private int getMaximumSizeDimension() {
1761 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
1762 Display d = wm.getDefaultDisplay();
1763 return d.getMaximumSizeDimension();
1764 }
1765
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07001766 // Called by SystemBackupAgent after files are restored to disk.
Amith Yamasani09e9cdc2013-11-06 14:54:50 -08001767 public void settingsRestored() {
1768 // Verify caller is the system
1769 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
1770 throw new RuntimeException("settingsRestored() can only be called from the system process");
1771 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001772 // TODO: If necessary, make it work for secondary users as well. This currently assumes
1773 // restores only to the primary user
Joe Onorato8a9b2202010-02-26 18:56:32 -08001774 if (DEBUG) Slog.v(TAG, "settingsRestored");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001775 WallpaperData wallpaper = null;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001776 boolean success = false;
1777 synchronized (mLock) {
Christopher Tatedb27b842016-02-25 14:39:17 -08001778 loadSettingsLocked(UserHandle.USER_SYSTEM);
1779 wallpaper = mWallpaperMap.get(UserHandle.USER_SYSTEM);
Christopher Tatead3c2592016-01-20 18:13:17 -08001780 wallpaper.wallpaperId = makeWallpaperIdLocked(); // always bump id at restore
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001781 if (wallpaper.nextWallpaperComponent != null
Justin Koh29c30162014-09-05 17:10:10 -07001782 && !wallpaper.nextWallpaperComponent.equals(mImageWallpaper)) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001783 if (!bindWallpaperComponentLocked(wallpaper.nextWallpaperComponent, false, false,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001784 wallpaper, null)) {
Christopher Tatee3ab4d02009-12-16 14:03:31 -08001785 // No such live wallpaper or other failure; fall back to the default
1786 // live wallpaper (since the profile being restored indicated that the
1787 // user had selected a live rather than static one).
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001788 bindWallpaperComponentLocked(null, false, false, wallpaper, null);
Christopher Tatee3ab4d02009-12-16 14:03:31 -08001789 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001790 success = true;
1791 } else {
Mike Clerona428b2c2009-11-15 22:53:08 -08001792 // If there's a wallpaper name, we use that. If that can't be loaded, then we
1793 // use the default.
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001794 if ("".equals(wallpaper.name)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001795 if (DEBUG) Slog.v(TAG, "settingsRestored: name is empty");
Mike Clerona428b2c2009-11-15 22:53:08 -08001796 success = true;
1797 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001798 if (DEBUG) Slog.v(TAG, "settingsRestored: attempting to restore named resource");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001799 success = restoreNamedResourceLocked(wallpaper);
Mike Clerona428b2c2009-11-15 22:53:08 -08001800 }
Christopher Tatead3c2592016-01-20 18:13:17 -08001801 if (DEBUG) Slog.v(TAG, "settingsRestored: success=" + success
1802 + " id=" + wallpaper.wallpaperId);
Mike Clerona428b2c2009-11-15 22:53:08 -08001803 if (success) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001804 bindWallpaperComponentLocked(wallpaper.nextWallpaperComponent, false, false,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001805 wallpaper, null);
Mike Clerona428b2c2009-11-15 22:53:08 -08001806 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001807 }
1808 }
1809
1810 if (!success) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001811 Slog.e(TAG, "Failed to restore wallpaper: '" + wallpaper.name + "'");
1812 wallpaper.name = "";
Christopher Tatedb27b842016-02-25 14:39:17 -08001813 getWallpaperDir(UserHandle.USER_SYSTEM).delete();
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001814 }
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07001815
1816 synchronized (mLock) {
Christopher Tatedb27b842016-02-25 14:39:17 -08001817 saveSettingsLocked(UserHandle.USER_SYSTEM);
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07001818 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001819 }
1820
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001821 // Restore the named resource bitmap to both source + crop files
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001822 boolean restoreNamedResourceLocked(WallpaperData wallpaper) {
1823 if (wallpaper.name.length() > 4 && "res:".equals(wallpaper.name.substring(0, 4))) {
1824 String resName = wallpaper.name.substring(4);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001825
1826 String pkg = null;
1827 int colon = resName.indexOf(':');
1828 if (colon > 0) {
1829 pkg = resName.substring(0, colon);
1830 }
1831
1832 String ident = null;
1833 int slash = resName.lastIndexOf('/');
1834 if (slash > 0) {
1835 ident = resName.substring(slash+1);
1836 }
1837
1838 String type = null;
1839 if (colon > 0 && slash > 0 && (slash-colon) > 1) {
1840 type = resName.substring(colon+1, slash);
1841 }
1842
1843 if (pkg != null && ident != null && type != null) {
1844 int resId = -1;
1845 InputStream res = null;
1846 FileOutputStream fos = null;
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001847 FileOutputStream cos = null;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001848 try {
1849 Context c = mContext.createPackageContext(pkg, Context.CONTEXT_RESTRICTED);
1850 Resources r = c.getResources();
1851 resId = r.getIdentifier(resName, null, null);
1852 if (resId == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001853 Slog.e(TAG, "couldn't resolve identifier pkg=" + pkg + " type=" + type
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001854 + " ident=" + ident);
1855 return false;
1856 }
1857
1858 res = r.openRawResource(resId);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001859 if (wallpaper.wallpaperFile.exists()) {
1860 wallpaper.wallpaperFile.delete();
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001861 wallpaper.cropFile.delete();
Dianne Hackborn1afd1c92010-03-18 22:47:17 -07001862 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001863 fos = new FileOutputStream(wallpaper.wallpaperFile);
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001864 cos = new FileOutputStream(wallpaper.cropFile);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001865
1866 byte[] buffer = new byte[32768];
1867 int amt;
1868 while ((amt=res.read(buffer)) > 0) {
1869 fos.write(buffer, 0, amt);
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001870 cos.write(buffer, 0, amt);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001871 }
1872 // mWallpaperObserver will notice the close and send the change broadcast
1873
Joe Onorato8a9b2202010-02-26 18:56:32 -08001874 Slog.v(TAG, "Restored wallpaper: " + resName);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001875 return true;
1876 } catch (NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001877 Slog.e(TAG, "Package name " + pkg + " not found");
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001878 } catch (Resources.NotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001879 Slog.e(TAG, "Resource not found: " + resId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001880 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001881 Slog.e(TAG, "IOException while restoring wallpaper ", e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001882 } finally {
Christopher Tatead3c2592016-01-20 18:13:17 -08001883 IoUtils.closeQuietly(res);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001884 if (fos != null) {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07001885 FileUtils.sync(fos);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001886 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001887 if (cos != null) {
1888 FileUtils.sync(cos);
1889 }
1890 IoUtils.closeQuietly(fos);
1891 IoUtils.closeQuietly(cos);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001892 }
1893 }
1894 }
1895 return false;
1896 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001897
Dianne Hackborneb034652009-09-07 00:49:58 -07001898 @Override
1899 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1900 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
1901 != PackageManager.PERMISSION_GRANTED) {
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001902
Dianne Hackborneb034652009-09-07 00:49:58 -07001903 pw.println("Permission Denial: can't dump wallpaper service from from pid="
1904 + Binder.getCallingPid()
1905 + ", uid=" + Binder.getCallingUid());
1906 return;
1907 }
1908
1909 synchronized (mLock) {
1910 pw.println("Current Wallpaper Service state:");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001911 for (int i = 0; i < mWallpaperMap.size(); i++) {
1912 WallpaperData wallpaper = mWallpaperMap.valueAt(i);
Christopher Tatead3c2592016-01-20 18:13:17 -08001913 pw.print(" User "); pw.print(wallpaper.userId);
1914 pw.print(": id="); pw.println(wallpaper.wallpaperId);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001915 pw.print(" mWidth=");
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001916 pw.print(wallpaper.width);
1917 pw.print(" mHeight=");
1918 pw.println(wallpaper.height);
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001919 pw.print(" mCropHint="); pw.println(wallpaper.cropHint);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001920 pw.print(" mPadding="); pw.println(wallpaper.padding);
1921 pw.print(" mName="); pw.println(wallpaper.name);
1922 pw.print(" mWallpaperComponent="); pw.println(wallpaper.wallpaperComponent);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001923 if (wallpaper.connection != null) {
1924 WallpaperConnection conn = wallpaper.connection;
1925 pw.print(" Wallpaper connection ");
1926 pw.print(conn);
1927 pw.println(":");
1928 if (conn.mInfo != null) {
1929 pw.print(" mInfo.component=");
1930 pw.println(conn.mInfo.getComponent());
1931 }
1932 pw.print(" mToken=");
1933 pw.println(conn.mToken);
1934 pw.print(" mService=");
1935 pw.println(conn.mService);
1936 pw.print(" mEngine=");
1937 pw.println(conn.mEngine);
1938 pw.print(" mLastDiedTime=");
1939 pw.println(wallpaper.lastDiedTime - SystemClock.uptimeMillis());
1940 }
Dianne Hackborneb034652009-09-07 00:49:58 -07001941 }
1942 }
1943 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001944}