blob: 77db2752a1a8c062c7de9fb13f1b6453ebc07359 [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) {
234 // either a lock-only wallpaper commit or a system+lock event,
235 // so tell keyguard about it
236 if (DEBUG) {
237 Slog.i(TAG, "Lock-relevant wallpaper changed; telling listener");
238 }
239 final IWallpaperManagerCallback cb = mKeyguardListener;
240 if (cb != null) {
241 try {
242 cb.onWallpaperChanged();
243 } catch (RemoteException e) {
244 // Oh well it went away; no big deal
245 }
246 }
247 }
248 saveSettingsLocked(wallpaper);
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700249 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800250 }
251 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800252 }
253 }
254 }
255
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800256 /**
257 * Once a new wallpaper has been written via setWallpaper(...), it needs to be cropped
258 * for display.
259 */
260 private void generateCrop(WallpaperData wallpaper) {
261 boolean success = false;
262 boolean needCrop = false;
Christopher Tatebe132e62016-02-10 12:59:49 -0800263 boolean needScale = false;
264
265 if (DEBUG) {
266 Slog.v(TAG, "Generating crop for new wallpaper(s): 0x"
267 + Integer.toHexString(wallpaper.whichPending)
268 + " to " + wallpaper.cropFile.getName());
269 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800270
271 // Analyse the source; needed in multiple cases
272 BitmapFactory.Options options = new BitmapFactory.Options();
273 options.inJustDecodeBounds = true;
274 BitmapFactory.decodeFile(wallpaper.wallpaperFile.getAbsolutePath(), options);
275
Christopher Tatebe132e62016-02-10 12:59:49 -0800276 // We'll need to scale if the crop is sufficiently bigger than the display
277
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800278 // Legacy case uses an empty crop rect here, so we just preserve the
279 // source image verbatim
280 if (!wallpaper.cropHint.isEmpty()) {
281 // ...clamp the crop rect to the measured bounds...
282 wallpaper.cropHint.right = Math.min(wallpaper.cropHint.right, options.outWidth);
283 wallpaper.cropHint.bottom = Math.min(wallpaper.cropHint.bottom, options.outHeight);
284 // ...and don't bother cropping if what we're left with is identity
285 needCrop = (options.outHeight >= wallpaper.cropHint.height()
286 && options.outWidth >= wallpaper.cropHint.width());
287 }
288
Christopher Tatebe132e62016-02-10 12:59:49 -0800289 if (!needCrop && !needScale) {
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800290 // Simple case: the nominal crop is at least as big as the source image,
291 // so we take the whole thing and just copy the image file directly.
292 if (DEBUG) {
293 Slog.v(TAG, "Null crop of new wallpaper; copying");
294 }
295 success = FileUtils.copyFile(wallpaper.wallpaperFile, wallpaper.cropFile);
296 if (!success) {
297 wallpaper.cropFile.delete();
298 // TODO: fall back to default wallpaper in this case
299 }
300 } else {
Christopher Tatebe132e62016-02-10 12:59:49 -0800301 // Fancy case: crop and/or scale
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800302 FileOutputStream f = null;
303 BufferedOutputStream bos = null;
304 try {
305 BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(
306 wallpaper.wallpaperFile.getAbsolutePath(), false);
307 Bitmap cropped = decoder.decodeRegion(wallpaper.cropHint, null);
308 decoder.recycle();
309
310 if (cropped == null) {
311 Slog.e(TAG, "Could not decode new wallpaper");
312 } else {
313 f = new FileOutputStream(wallpaper.cropFile);
314 bos = new BufferedOutputStream(f, 32*1024);
315 cropped.compress(Bitmap.CompressFormat.PNG, 90, bos);
316 bos.flush(); // don't rely on the implicit flush-at-close when noting success
317 success = true;
318 }
319 } catch (IOException e) {
320 if (DEBUG) {
321 Slog.e(TAG, "I/O error decoding crop: " + e.getMessage());
322 }
323 } finally {
324 IoUtils.closeQuietly(bos);
325 IoUtils.closeQuietly(f);
326 }
327 }
328
329 if (!success) {
330 Slog.e(TAG, "Unable to apply new wallpaper");
331 wallpaper.cropFile.delete();
332 }
333
334 if (wallpaper.cropFile.exists()) {
335 boolean didRestorecon = SELinux.restorecon(wallpaper.cropFile.getAbsoluteFile());
336 if (DEBUG) {
337 Slog.v(TAG, "restorecon() of crop file returned " + didRestorecon);
338 }
339 }
340 }
341
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700342 final Context mContext;
343 final IWindowManager mIWindowManager;
Amith Yamasani4e2820c2012-08-28 22:17:23 -0700344 final IPackageManager mIPackageManager;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800345 final MyPackageMonitor mMonitor;
Benjamin Franzf3ece362015-02-11 10:51:10 +0000346 final AppOpsManager mAppOpsManager;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800347 WallpaperData mLastWallpaper;
Christopher Tatebe132e62016-02-10 12:59:49 -0800348 IWallpaperManagerCallback mKeyguardListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800349
Justin Koh29c30162014-09-05 17:10:10 -0700350 /**
Christopher Tatead3c2592016-01-20 18:13:17 -0800351 * ID of the current wallpaper, changed every time anything sets a wallpaper.
352 * This is used for external detection of wallpaper update activity.
353 */
354 int mWallpaperId;
355
356 /**
Justin Koh29c30162014-09-05 17:10:10 -0700357 * Name of the component used to display bitmap wallpapers from either the gallery or
358 * built-in wallpapers.
359 */
360 final ComponentName mImageWallpaper;
361
Christopher Tatebe132e62016-02-10 12:59:49 -0800362 final SparseArray<WallpaperData> mWallpaperMap = new SparseArray<WallpaperData>();
363 final SparseArray<WallpaperData> mLockWallpaperMap = new SparseArray<WallpaperData>();
Dianne Hackborn07213e62011-08-24 20:05:39 -0700364
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800365 int mCurrentUserId;
Dianne Hackborn07213e62011-08-24 20:05:39 -0700366
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800367 static class WallpaperData {
368
369 int userId;
370
Christopher Tatebe132e62016-02-10 12:59:49 -0800371 final File wallpaperFile; // source image
372 final File cropFile; // eventual destination
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800373
374 /**
Christopher Tatebe132e62016-02-10 12:59:49 -0800375 * True while the client is writing a new wallpaper
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800376 */
377 boolean imageWallpaperPending;
378
379 /**
Christopher Tatebe132e62016-02-10 12:59:49 -0800380 * Which new wallpapers are being written; mirrors the 'which'
381 * selector bit field to setWallpaper().
382 */
383 int whichPending;
384
385 /**
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800386 * Callback once the set + crop is finished
387 */
388 IWallpaperManagerCallback setComplete;
389
390 /**
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800391 * Resource name if using a picture from the wallpaper gallery
392 */
393 String name = "";
394
395 /**
396 * The component name of the currently set live wallpaper.
397 */
398 ComponentName wallpaperComponent;
399
400 /**
401 * The component name of the wallpaper that should be set next.
402 */
403 ComponentName nextWallpaperComponent;
404
Christopher Tatead3c2592016-01-20 18:13:17 -0800405 /**
406 * The ID of this wallpaper
407 */
408 int wallpaperId;
409
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800410 WallpaperConnection connection;
411 long lastDiedTime;
412 boolean wallpaperUpdating;
413 WallpaperObserver wallpaperObserver;
414
415 /**
416 * List of callbacks registered they should each be notified when the wallpaper is changed.
417 */
418 private RemoteCallbackList<IWallpaperManagerCallback> callbacks
419 = new RemoteCallbackList<IWallpaperManagerCallback>();
420
421 int width = -1;
422 int height = -1;
423
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800424 /**
425 * The crop hint supplied for displaying a subset of the source image
426 */
427 final Rect cropHint = new Rect(0, 0, 0, 0);
428
Dianne Hackborn067e5f62014-09-07 23:14:30 -0700429 final Rect padding = new Rect(0, 0, 0, 0);
430
Christopher Tatebe132e62016-02-10 12:59:49 -0800431 WallpaperData(int userId, String inputFileName, String cropFileName) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800432 this.userId = userId;
Christopher Tatebe132e62016-02-10 12:59:49 -0800433 final File wallpaperDir = getWallpaperDir(userId);
434 wallpaperFile = new File(wallpaperDir, inputFileName);
435 cropFile = new File(wallpaperDir, cropFileName);
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800436 }
437
Christopher Tatebe132e62016-02-10 12:59:49 -0800438 // Called during initialization of a given user's wallpaper bookkeeping
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800439 boolean ensureCropExists() {
440 // if the crop file is not present, copy over the source image to use verbatim
441 if (!cropFile.exists()) {
442 return FileUtils.copyFile(wallpaperFile, cropFile);
443 }
444 return true;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800445 }
446 }
447
Christopher Tatead3c2592016-01-20 18:13:17 -0800448 int makeWallpaperIdLocked() {
449 do {
450 ++mWallpaperId;
451 } while (mWallpaperId == 0);
452 return mWallpaperId;
453 }
454
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700455 class WallpaperConnection extends IWallpaperConnection.Stub
456 implements ServiceConnection {
Dianne Hackborneb034652009-09-07 00:49:58 -0700457 final WallpaperInfo mInfo;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700458 final Binder mToken = new Binder();
459 IWallpaperService mService;
460 IWallpaperEngine mEngine;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800461 WallpaperData mWallpaper;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700462 IRemoteCallback mReply;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800463
Michael Wright5203a8b2013-10-03 14:16:42 -0700464 boolean mDimensionsChanged = false;
Dianne Hackborn067e5f62014-09-07 23:14:30 -0700465 boolean mPaddingChanged = false;
Michael Wright5203a8b2013-10-03 14:16:42 -0700466
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800467 public WallpaperConnection(WallpaperInfo info, WallpaperData wallpaper) {
Dianne Hackborneb034652009-09-07 00:49:58 -0700468 mInfo = info;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800469 mWallpaper = wallpaper;
Dianne Hackborneb034652009-09-07 00:49:58 -0700470 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700471
472 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700473 public void onServiceConnected(ComponentName name, IBinder service) {
474 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800475 if (mWallpaper.connection == this) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700476 mService = IWallpaperService.Stub.asInterface(service);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800477 attachServiceLocked(this, mWallpaper);
Dianne Hackborneb034652009-09-07 00:49:58 -0700478 // XXX should probably do saveSettingsLocked() later
479 // when we have an engine, but I'm not sure about
480 // locking there and anyway we always need to be able to
481 // recover if there is something wrong.
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800482 saveSettingsLocked(mWallpaper);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700483 }
484 }
485 }
486
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700487 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700488 public void onServiceDisconnected(ComponentName name) {
489 synchronized (mLock) {
490 mService = null;
491 mEngine = null;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800492 if (mWallpaper.connection == this) {
493 Slog.w(TAG, "Wallpaper service gone: " + mWallpaper.wallpaperComponent);
494 if (!mWallpaper.wallpaperUpdating
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800495 && mWallpaper.userId == mCurrentUserId) {
Selim Cinekebebadb2014-03-05 22:17:26 +0100496 // There is a race condition which causes
497 // {@link #mWallpaper.wallpaperUpdating} to be false even if it is
498 // currently updating since the broadcast notifying us is async.
499 // This race is overcome by the general rule that we only reset the
500 // wallpaper if its service was shut down twice
501 // during {@link #MIN_WALLPAPER_CRASH_TIME} millis.
502 if (mWallpaper.lastDiedTime != 0
503 && mWallpaper.lastDiedTime + MIN_WALLPAPER_CRASH_TIME
504 > SystemClock.uptimeMillis()) {
505 Slog.w(TAG, "Reverting to built-in wallpaper!");
Christopher Tatebe132e62016-02-10 12:59:49 -0800506 clearWallpaperLocked(true, FLAG_SET_SYSTEM, mWallpaper.userId, null);
Selim Cinekebebadb2014-03-05 22:17:26 +0100507 } else {
508 mWallpaper.lastDiedTime = SystemClock.uptimeMillis();
509 }
Filip Gruszczynski5a589432014-10-14 12:06:06 -0700510 final String flattened = name.flattenToString();
Filip Gruszczynski5dcc3ac2014-10-13 15:51:39 -0700511 EventLog.writeEvent(EventLogTags.WP_WALLPAPER_CRASHED,
Filip Gruszczynski5a589432014-10-14 12:06:06 -0700512 flattened.substring(0, Math.min(flattened.length(),
513 MAX_WALLPAPER_COMPONENT_LOG_LENGTH)));
Dianne Hackborn0cd48872009-08-13 18:51:59 -0700514 }
515 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700516 }
517 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800518
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700519 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700520 public void attachEngine(IWallpaperEngine engine) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700521 synchronized (mLock) {
522 mEngine = engine;
Michael Wright5203a8b2013-10-03 14:16:42 -0700523 if (mDimensionsChanged) {
524 try {
525 mEngine.setDesiredSize(mWallpaper.width, mWallpaper.height);
526 } catch (RemoteException e) {
527 Slog.w(TAG, "Failed to set wallpaper dimensions", e);
528 }
529 mDimensionsChanged = false;
530 }
Dianne Hackborn067e5f62014-09-07 23:14:30 -0700531 if (mPaddingChanged) {
532 try {
533 mEngine.setDisplayPadding(mWallpaper.padding);
534 } catch (RemoteException e) {
535 Slog.w(TAG, "Failed to set wallpaper padding", e);
536 }
537 mPaddingChanged = false;
538 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700539 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700540 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800541
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700542 @Override
543 public void engineShown(IWallpaperEngine engine) {
544 synchronized (mLock) {
545 if (mReply != null) {
546 long ident = Binder.clearCallingIdentity();
547 try {
548 mReply.sendResult(null);
549 } catch (RemoteException e) {
550 Binder.restoreCallingIdentity(ident);
551 }
552 mReply = null;
553 }
554 }
555 }
556
557 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700558 public ParcelFileDescriptor setWallpaper(String name) {
559 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800560 if (mWallpaper.connection == this) {
Christopher Tatead3c2592016-01-20 18:13:17 -0800561 return updateWallpaperBitmapLocked(name, mWallpaper, null);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700562 }
563 return null;
564 }
565 }
566 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800567
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800568 class MyPackageMonitor extends PackageMonitor {
569 @Override
570 public void onPackageUpdateFinished(String packageName, int uid) {
571 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700572 if (mCurrentUserId != getChangingUserId()) {
573 return;
574 }
575 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
576 if (wallpaper != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800577 if (wallpaper.wallpaperComponent != null
578 && wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
579 wallpaper.wallpaperUpdating = false;
580 ComponentName comp = wallpaper.wallpaperComponent;
581 clearWallpaperComponentLocked(wallpaper);
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700582 if (!bindWallpaperComponentLocked(comp, false, false,
583 wallpaper, null)) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800584 Slog.w(TAG, "Wallpaper no longer available; reverting to default");
Christopher Tatebe132e62016-02-10 12:59:49 -0800585 clearWallpaperLocked(false, FLAG_SET_SYSTEM, wallpaper.userId, null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800586 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700587 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800588 }
589 }
590 }
591
592 @Override
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700593 public void onPackageModified(String packageName) {
594 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700595 if (mCurrentUserId != getChangingUserId()) {
596 return;
597 }
598 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
599 if (wallpaper != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800600 if (wallpaper.wallpaperComponent == null
601 || !wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700602 return;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800603 }
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700604 doPackagesChangedLocked(true, wallpaper);
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700605 }
606 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700607 }
608
609 @Override
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800610 public void onPackageUpdateStarted(String packageName, int uid) {
611 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700612 if (mCurrentUserId != getChangingUserId()) {
613 return;
614 }
615 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
616 if (wallpaper != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800617 if (wallpaper.wallpaperComponent != null
618 && wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
619 wallpaper.wallpaperUpdating = true;
620 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800621 }
622 }
623 }
624
625 @Override
626 public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700627 synchronized (mLock) {
628 boolean changed = false;
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700629 if (mCurrentUserId != getChangingUserId()) {
630 return false;
631 }
632 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
633 if (wallpaper != null) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700634 boolean res = doPackagesChangedLocked(doit, wallpaper);
635 changed |= res;
636 }
637 return changed;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800638 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800639 }
640
641 @Override
642 public void onSomePackagesChanged() {
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700643 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700644 if (mCurrentUserId != getChangingUserId()) {
645 return;
646 }
647 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
648 if (wallpaper != null) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700649 doPackagesChangedLocked(true, wallpaper);
650 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800651 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800652 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800653
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700654 boolean doPackagesChangedLocked(boolean doit, WallpaperData wallpaper) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800655 boolean changed = false;
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700656 if (wallpaper.wallpaperComponent != null) {
657 int change = isPackageDisappearing(wallpaper.wallpaperComponent
658 .getPackageName());
659 if (change == PACKAGE_PERMANENT_CHANGE
660 || change == PACKAGE_TEMPORARY_CHANGE) {
661 changed = true;
662 if (doit) {
663 Slog.w(TAG, "Wallpaper uninstalled, removing: "
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800664 + wallpaper.wallpaperComponent);
Christopher Tatebe132e62016-02-10 12:59:49 -0800665 clearWallpaperLocked(false, FLAG_SET_SYSTEM, wallpaper.userId, null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800666 }
667 }
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700668 }
669 if (wallpaper.nextWallpaperComponent != null) {
670 int change = isPackageDisappearing(wallpaper.nextWallpaperComponent
671 .getPackageName());
672 if (change == PACKAGE_PERMANENT_CHANGE
673 || change == PACKAGE_TEMPORARY_CHANGE) {
674 wallpaper.nextWallpaperComponent = null;
675 }
676 }
677 if (wallpaper.wallpaperComponent != null
678 && isPackageModified(wallpaper.wallpaperComponent.getPackageName())) {
679 try {
680 mContext.getPackageManager().getServiceInfo(
681 wallpaper.wallpaperComponent, 0);
682 } catch (NameNotFoundException e) {
683 Slog.w(TAG, "Wallpaper component gone, removing: "
684 + wallpaper.wallpaperComponent);
Christopher Tatebe132e62016-02-10 12:59:49 -0800685 clearWallpaperLocked(false, FLAG_SET_SYSTEM, wallpaper.userId, null);
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700686 }
687 }
688 if (wallpaper.nextWallpaperComponent != null
689 && isPackageModified(wallpaper.nextWallpaperComponent.getPackageName())) {
690 try {
691 mContext.getPackageManager().getServiceInfo(
692 wallpaper.nextWallpaperComponent, 0);
693 } catch (NameNotFoundException e) {
694 wallpaper.nextWallpaperComponent = null;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800695 }
696 }
697 return changed;
698 }
699 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +0100700
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700701 public WallpaperManagerService(Context context) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800702 if (DEBUG) Slog.v(TAG, "WallpaperService startup");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800703 mContext = context;
Justin Koh29c30162014-09-05 17:10:10 -0700704 mImageWallpaper = ComponentName.unflattenFromString(
705 context.getResources().getString(R.string.image_wallpaper_component));
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700706 mIWindowManager = IWindowManager.Stub.asInterface(
707 ServiceManager.getService(Context.WINDOW_SERVICE));
Amith Yamasani4e2820c2012-08-28 22:17:23 -0700708 mIPackageManager = AppGlobals.getPackageManager();
Benjamin Franzf3ece362015-02-11 10:51:10 +0000709 mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800710 mMonitor = new MyPackageMonitor();
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700711 mMonitor.register(context, null, UserHandle.ALL, true);
Xiaohui Chen233d94c2015-07-30 15:08:00 -0700712 getWallpaperDir(UserHandle.USER_SYSTEM).mkdirs();
713 loadSettingsLocked(UserHandle.USER_SYSTEM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800714 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +0100715
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800716 private static File getWallpaperDir(int userId) {
Amith Yamasani61f57372012-08-31 12:12:28 -0700717 return Environment.getUserSystemDirectory(userId);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800718 }
719
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800720 @Override
721 protected void finalize() throws Throwable {
722 super.finalize();
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800723 for (int i = 0; i < mWallpaperMap.size(); i++) {
724 WallpaperData wallpaper = mWallpaperMap.valueAt(i);
725 wallpaper.wallpaperObserver.stopWatching();
726 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800727 }
Amith Yamasani13593602012-03-22 16:16:17 -0700728
Svetoslav Ganova0027152013-06-25 14:59:53 -0700729 public void systemRunning() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800730 if (DEBUG) Slog.v(TAG, "systemReady");
Xiaohui Chen233d94c2015-07-30 15:08:00 -0700731 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.USER_SYSTEM);
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800732 if (!wallpaper.ensureCropExists()) {
Christopher Tatebe132e62016-02-10 12:59:49 -0800733 clearWallpaperLocked(false, FLAG_SET_SYSTEM, UserHandle.USER_SYSTEM, null);
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800734 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700735 switchWallpaper(wallpaper, null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800736 wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper);
737 wallpaper.wallpaperObserver.startWatching();
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800738
Amith Yamasani13593602012-03-22 16:16:17 -0700739 IntentFilter userFilter = new IntentFilter();
Amith Yamasani13593602012-03-22 16:16:17 -0700740 userFilter.addAction(Intent.ACTION_USER_REMOVED);
Amith Yamasani756901d2012-10-12 12:30:07 -0700741 userFilter.addAction(Intent.ACTION_USER_STOPPING);
Amith Yamasani13593602012-03-22 16:16:17 -0700742 mContext.registerReceiver(new BroadcastReceiver() {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800743 @Override
Amith Yamasani13593602012-03-22 16:16:17 -0700744 public void onReceive(Context context, Intent intent) {
745 String action = intent.getAction();
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700746 if (Intent.ACTION_USER_REMOVED.equals(action)) {
Amith Yamasani756901d2012-10-12 12:30:07 -0700747 onRemoveUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
748 UserHandle.USER_NULL));
Amith Yamasani13593602012-03-22 16:16:17 -0700749 }
Amith Yamasani0c293712012-10-30 12:23:52 -0700750 // TODO: Race condition causing problems when cleaning up on stopping a user.
751 // Comment this out for now.
752 // else if (Intent.ACTION_USER_STOPPING.equals(action)) {
753 // onStoppingUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
754 // UserHandle.USER_NULL));
755 // }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800756 }
Amith Yamasani13593602012-03-22 16:16:17 -0700757 }, userFilter);
Amith Yamasani756901d2012-10-12 12:30:07 -0700758
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700759 try {
760 ActivityManagerNative.getDefault().registerUserSwitchObserver(
761 new IUserSwitchObserver.Stub() {
762 @Override
763 public void onUserSwitching(int newUserId, IRemoteCallback reply) {
764 switchUser(newUserId, reply);
765 }
766
767 @Override
768 public void onUserSwitchComplete(int newUserId) throws RemoteException {
769 }
Kenny Guy42979622015-04-13 18:03:05 +0000770
771 @Override
772 public void onForegroundProfileSwitch(int newProfileId) {
773 // Ignore.
774 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700775 });
776 } catch (RemoteException e) {
777 // TODO Auto-generated catch block
778 e.printStackTrace();
779 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800780 }
781
Amith Yamasani09e9cdc2013-11-06 14:54:50 -0800782 /** Called by SystemBackupAgent */
783 public String getName() {
784 // Verify caller is the system
785 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
786 throw new RuntimeException("getName() can only be called from the system process");
787 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700788 synchronized (mLock) {
789 return mWallpaperMap.get(0).name;
790 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800791 }
792
Christopher Tatebe132e62016-02-10 12:59:49 -0800793 void stopObserver(WallpaperData wallpaper) {
794 if (wallpaper != null) {
795 if (wallpaper.wallpaperObserver != null) {
796 wallpaper.wallpaperObserver.stopWatching();
797 wallpaper.wallpaperObserver = null;
Amith Yamasani13593602012-03-22 16:16:17 -0700798 }
Amith Yamasani756901d2012-10-12 12:30:07 -0700799 }
800 }
801
Christopher Tatebe132e62016-02-10 12:59:49 -0800802 void stopObserversLocked(int userId) {
803 stopObserver(mWallpaperMap.get(userId));
804 stopObserver(mLockWallpaperMap.get(userId));
805 mWallpaperMap.remove(userId);
806 mLockWallpaperMap.remove(userId);
807 }
808
Amith Yamasani756901d2012-10-12 12:30:07 -0700809 void onRemoveUser(int userId) {
810 if (userId < 1) return;
Christopher Tatebe132e62016-02-10 12:59:49 -0800811
812 final File wallpaperDir = getWallpaperDir(userId);
Amith Yamasani756901d2012-10-12 12:30:07 -0700813 synchronized (mLock) {
Christopher Tatebe132e62016-02-10 12:59:49 -0800814 stopObserversLocked(userId);
815 for (String filename : sPerUserFiles) {
816 new File(wallpaperDir, filename).delete();
817 }
Amith Yamasani13593602012-03-22 16:16:17 -0700818 }
819 }
820
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700821 void switchUser(int userId, IRemoteCallback reply) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800822 synchronized (mLock) {
823 mCurrentUserId = userId;
Christopher Tatebe132e62016-02-10 12:59:49 -0800824 WallpaperData wallpaper = getWallpaperSafeLocked(userId, FLAG_SET_SYSTEM);
Amith Yamasani6474c4c2012-10-04 14:55:42 -0700825 // Not started watching yet, in case wallpaper data was loaded for other reasons.
826 if (wallpaper.wallpaperObserver == null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800827 wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper);
828 wallpaper.wallpaperObserver.startWatching();
829 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700830 switchWallpaper(wallpaper, reply);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800831 }
832 }
833
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700834 void switchWallpaper(WallpaperData wallpaper, IRemoteCallback reply) {
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700835 synchronized (mLock) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700836 RuntimeException e = null;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700837 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800838 ComponentName cname = wallpaper.wallpaperComponent != null ?
839 wallpaper.wallpaperComponent : wallpaper.nextWallpaperComponent;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700840 if (bindWallpaperComponentLocked(cname, true, false, wallpaper, reply)) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700841 return;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700842 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700843 } catch (RuntimeException e1) {
844 e = e1;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700845 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700846 Slog.w(TAG, "Failure starting previous wallpaper", e);
Christopher Tatebe132e62016-02-10 12:59:49 -0800847 clearWallpaperLocked(false, FLAG_SET_SYSTEM, wallpaper.userId, reply);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800848 }
849 }
850
Christopher Tatebe132e62016-02-10 12:59:49 -0800851 @Override
852 public void clearWallpaper(String callingPackage, int which, int userId) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800853 if (DEBUG) Slog.v(TAG, "clearWallpaper");
Benjamin Franzf3ece362015-02-11 10:51:10 +0000854 checkPermission(android.Manifest.permission.SET_WALLPAPER);
Oleksandr Peletskyif2519812016-01-26 20:16:06 +0100855 if (!isWallpaperSupported(callingPackage) || !isWallpaperSettingAllowed(callingPackage)) {
Benjamin Franzf3ece362015-02-11 10:51:10 +0000856 return;
857 }
Christopher Tatebe132e62016-02-10 12:59:49 -0800858 if (userId != UserHandle.getCallingUserId()) {
859 // cross-user call
860 mContext.enforceCallingOrSelfPermission(
861 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
862 "WallpaperManagerService");
863 }
864
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800865 synchronized (mLock) {
Christopher Tatebe132e62016-02-10 12:59:49 -0800866 clearWallpaperLocked(false, which, userId, null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800867 }
868 }
869
Christopher Tatebe132e62016-02-10 12:59:49 -0800870 void clearWallpaperLocked(boolean defaultFailed, int which, int userId, IRemoteCallback reply) {
871 if (which != FLAG_SET_SYSTEM && which != FLAG_SET_LOCK) {
872 throw new IllegalArgumentException("Must specify exactly one kind of wallpaper to read");
873 }
874
875 WallpaperData wallpaper = null;
876 if (which == FLAG_SET_LOCK) {
877 wallpaper = mLockWallpaperMap.get(userId);
878 if (wallpaper == null) {
879 // It's already gone; we're done.
880 return;
881 }
882 } else {
883 wallpaper = mWallpaperMap.get(userId);
884 if (wallpaper == null) {
885 // Might need to bring it in the first time to establish our rewrite
886 loadSettingsLocked(userId);
887 wallpaper = mWallpaperMap.get(userId);
888 }
889 }
Benjamin Franzf3ece362015-02-11 10:51:10 +0000890 if (wallpaper == null) {
891 return;
892 }
Christopher Tatebe132e62016-02-10 12:59:49 -0800893
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800894 final long ident = Binder.clearCallingIdentity();
895 try {
Christopher Tatebe132e62016-02-10 12:59:49 -0800896 if (wallpaper.wallpaperFile.exists()) {
897 wallpaper.wallpaperFile.delete();
898 wallpaper.cropFile.delete();
899 if (which == FLAG_SET_LOCK) {
900 final IWallpaperManagerCallback cb = mKeyguardListener;
901 if (cb != null) {
902 try {
903 cb.onWallpaperChanged();
904 } catch (RemoteException e) {
905 // Oh well it went away; no big deal
906 }
907 }
908 return;
909 }
910 }
911
Christopher Tateecd827a2014-09-05 17:42:34 -0700912 RuntimeException e = null;
913 try {
914 wallpaper.imageWallpaperPending = false;
915 if (userId != mCurrentUserId) return;
916 if (bindWallpaperComponentLocked(defaultFailed
917 ? mImageWallpaper
918 : null, true, false, wallpaper, reply)) {
919 return;
920 }
921 } catch (IllegalArgumentException e1) {
922 e = e1;
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700923 }
Christopher Tateecd827a2014-09-05 17:42:34 -0700924
925 // This can happen if the default wallpaper component doesn't
926 // exist. This should be a system configuration problem, but
927 // let's not let it crash the system and just live with no
928 // wallpaper.
929 Slog.e(TAG, "Default wallpaper component not found!", e);
930 clearWallpaperComponentLocked(wallpaper);
931 if (reply != null) {
932 try {
933 reply.sendResult(null);
934 } catch (RemoteException e1) {
935 }
936 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800937 } finally {
938 Binder.restoreCallingIdentity(ident);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800939 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700940 }
941
942 public boolean hasNamedWallpaper(String name) {
943 synchronized (mLock) {
Amith Yamasani6474c4c2012-10-04 14:55:42 -0700944 List<UserInfo> users;
945 long ident = Binder.clearCallingIdentity();
946 try {
947 users = ((UserManager) mContext.getSystemService(Context.USER_SERVICE)).getUsers();
948 } finally {
949 Binder.restoreCallingIdentity(ident);
950 }
951 for (UserInfo user: users) {
Benjamin Franzf3ece362015-02-11 10:51:10 +0000952 // ignore managed profiles
953 if (user.isManagedProfile()) {
954 continue;
955 }
Amith Yamasani6474c4c2012-10-04 14:55:42 -0700956 WallpaperData wd = mWallpaperMap.get(user.id);
957 if (wd == null) {
958 // User hasn't started yet, so load her settings to peek at the wallpaper
959 loadSettingsLocked(user.id);
960 wd = mWallpaperMap.get(user.id);
961 }
962 if (wd != null && name.equals(wd.name)) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700963 return true;
964 }
965 }
966 }
967 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800968 }
969
John Spurlock41f64642013-11-04 13:48:38 -0500970 private Point getDefaultDisplaySize() {
971 Point p = new Point();
John Spurlockd6e836c2013-11-18 14:14:49 -0500972 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
973 Display d = wm.getDefaultDisplay();
974 d.getRealSize(p);
John Spurlock41f64642013-11-04 13:48:38 -0500975 return p;
976 }
977
Benjamin Franzf3ece362015-02-11 10:51:10 +0000978 public void setDimensionHints(int width, int height, String callingPackage)
979 throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800980 checkPermission(android.Manifest.permission.SET_WALLPAPER_HINTS);
Benjamin Franzf3ece362015-02-11 10:51:10 +0000981 if (!isWallpaperSupported(callingPackage)) {
982 return;
983 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700984 synchronized (mLock) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700985 int userId = UserHandle.getCallingUserId();
Christopher Tatebe132e62016-02-10 12:59:49 -0800986 WallpaperData wallpaper = getWallpaperSafeLocked(userId, FLAG_SET_SYSTEM);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700987 if (width <= 0 || height <= 0) {
988 throw new IllegalArgumentException("width and height must be > 0");
989 }
John Spurlock41f64642013-11-04 13:48:38 -0500990 // Make sure it is at least as large as the display.
991 Point displaySize = getDefaultDisplaySize();
992 width = Math.max(width, displaySize.x);
993 height = Math.max(height, displaySize.y);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700994
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800995 if (width != wallpaper.width || height != wallpaper.height) {
996 wallpaper.width = width;
997 wallpaper.height = height;
998 saveSettingsLocked(wallpaper);
999 if (mCurrentUserId != userId) return; // Don't change the properties now
1000 if (wallpaper.connection != null) {
1001 if (wallpaper.connection.mEngine != null) {
Dianne Hackborn284ac932009-08-28 10:34:25 -07001002 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001003 wallpaper.connection.mEngine.setDesiredSize(
Dianne Hackborn284ac932009-08-28 10:34:25 -07001004 width, height);
1005 } catch (RemoteException e) {
1006 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001007 notifyCallbacksLocked(wallpaper);
Michael Wright5203a8b2013-10-03 14:16:42 -07001008 } else if (wallpaper.connection.mService != null) {
1009 // We've attached to the service but the engine hasn't attached back to us
1010 // yet. This means it will be created with the previous dimensions, so we
1011 // need to update it to the new dimensions once it attaches.
1012 wallpaper.connection.mDimensionsChanged = true;
Dianne Hackborn284ac932009-08-28 10:34:25 -07001013 }
1014 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001015 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001016 }
1017 }
1018
1019 public int getWidthHint() throws RemoteException {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001020 synchronized (mLock) {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07001021 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.getCallingUserId());
Benjamin Franzf3ece362015-02-11 10:51:10 +00001022 if (wallpaper != null) {
1023 return wallpaper.width;
1024 } else {
1025 return 0;
1026 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001027 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001028 }
1029
1030 public int getHeightHint() throws RemoteException {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001031 synchronized (mLock) {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07001032 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.getCallingUserId());
Benjamin Franzf3ece362015-02-11 10:51:10 +00001033 if (wallpaper != null) {
1034 return wallpaper.height;
1035 } else {
1036 return 0;
1037 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001038 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001039 }
1040
Benjamin Franzf3ece362015-02-11 10:51:10 +00001041 public void setDisplayPadding(Rect padding, String callingPackage) {
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001042 checkPermission(android.Manifest.permission.SET_WALLPAPER_HINTS);
Benjamin Franzf3ece362015-02-11 10:51:10 +00001043 if (!isWallpaperSupported(callingPackage)) {
1044 return;
1045 }
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001046 synchronized (mLock) {
1047 int userId = UserHandle.getCallingUserId();
Christopher Tatebe132e62016-02-10 12:59:49 -08001048 WallpaperData wallpaper = getWallpaperSafeLocked(userId, FLAG_SET_SYSTEM);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001049 if (padding.left < 0 || padding.top < 0 || padding.right < 0 || padding.bottom < 0) {
1050 throw new IllegalArgumentException("padding must be positive: " + padding);
1051 }
1052
1053 if (!padding.equals(wallpaper.padding)) {
1054 wallpaper.padding.set(padding);
1055 saveSettingsLocked(wallpaper);
1056 if (mCurrentUserId != userId) return; // Don't change the properties now
1057 if (wallpaper.connection != null) {
1058 if (wallpaper.connection.mEngine != null) {
1059 try {
1060 wallpaper.connection.mEngine.setDisplayPadding(padding);
1061 } catch (RemoteException e) {
1062 }
1063 notifyCallbacksLocked(wallpaper);
1064 } else if (wallpaper.connection.mService != null) {
1065 // We've attached to the service but the engine hasn't attached back to us
1066 // yet. This means it will be created with the previous dimensions, so we
1067 // need to update it to the new dimensions once it attaches.
1068 wallpaper.connection.mPaddingChanged = true;
1069 }
1070 }
1071 }
1072 }
1073 }
1074
Yorke Leedcd93cc2016-01-08 14:12:55 -08001075 @Override
Christopher Tatebe132e62016-02-10 12:59:49 -08001076 public ParcelFileDescriptor getWallpaper(IWallpaperManagerCallback cb, final int which,
1077 Bundle outParams, int wallpaperUserId) {
1078 if (wallpaperUserId != UserHandle.getCallingUserId()) {
1079 // cross-user call
1080 mContext.enforceCallingOrSelfPermission(
1081 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
1082 "WallpaperManagerService");
1083 }
1084
1085 if (which != FLAG_SET_SYSTEM && which != FLAG_SET_LOCK) {
1086 throw new IllegalArgumentException("Must specify exactly one kind of wallpaper to read");
1087 }
1088
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001089 synchronized (mLock) {
Vadim Tryshev8cde0792016-02-19 17:02:15 -08001090 final SparseArray<WallpaperData> whichSet =
1091 (which == FLAG_SET_LOCK) ? mLockWallpaperMap : mWallpaperMap;
1092 WallpaperData wallpaper = whichSet.get(wallpaperUserId);
1093 if (wallpaper == null) {
1094 // common case, this is the first lookup post-boot of the system or
1095 // unified lock, so we bring up the saved state lazily now and recheck.
1096 loadSettingsLocked(wallpaperUserId);
1097 wallpaper = whichSet.get(wallpaperUserId);
Christopher Tatebe132e62016-02-10 12:59:49 -08001098 if (wallpaper == null) {
Christopher Tatebe132e62016-02-10 12:59:49 -08001099 return null;
1100 }
Benjamin Franzf3ece362015-02-11 10:51:10 +00001101 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001102 try {
Dianne Hackborn284ac932009-08-28 10:34:25 -07001103 if (outParams != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001104 outParams.putInt("width", wallpaper.width);
1105 outParams.putInt("height", wallpaper.height);
Dianne Hackborn284ac932009-08-28 10:34:25 -07001106 }
Christopher Tateea6724a2016-02-18 18:39:19 -08001107 if (cb != null) {
1108 wallpaper.callbacks.register(cb);
1109 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001110 if (!wallpaper.cropFile.exists()) {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001111 return null;
1112 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001113 return ParcelFileDescriptor.open(wallpaper.cropFile, MODE_READ_ONLY);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001114 } catch (FileNotFoundException e) {
1115 /* Shouldn't happen as we check to see if the file exists */
Joe Onorato8a9b2202010-02-26 18:56:32 -08001116 Slog.w(TAG, "Error getting wallpaper", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001117 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001118 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001119 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001120 }
1121
Dianne Hackborneb034652009-09-07 00:49:58 -07001122 public WallpaperInfo getWallpaperInfo() {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07001123 int userId = UserHandle.getCallingUserId();
Dianne Hackborneb034652009-09-07 00:49:58 -07001124 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001125 WallpaperData wallpaper = mWallpaperMap.get(userId);
Benjamin Franzf3ece362015-02-11 10:51:10 +00001126 if (wallpaper != null && wallpaper.connection != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001127 return wallpaper.connection.mInfo;
Dianne Hackborneb034652009-09-07 00:49:58 -07001128 }
1129 return null;
1130 }
1131 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001132
Christopher Tatead3c2592016-01-20 18:13:17 -08001133 @Override
Christopher Tatebe132e62016-02-10 12:59:49 -08001134 public boolean setLockWallpaperCallback(IWallpaperManagerCallback cb) {
1135 checkPermission(android.Manifest.permission.INTERNAL_SYSTEM_WINDOW);
1136 synchronized (mLock) {
1137 mKeyguardListener = cb;
1138 }
1139 return true;
1140 }
1141
1142 @Override
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001143 public ParcelFileDescriptor setWallpaper(String name, String callingPackage,
1144 Rect cropHint, Bundle extras, int which, IWallpaperManagerCallback completion) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001145 checkPermission(android.Manifest.permission.SET_WALLPAPER);
Christopher Tatead3c2592016-01-20 18:13:17 -08001146
Christopher Tatebe132e62016-02-10 12:59:49 -08001147 if ((which & (FLAG_SET_LOCK|FLAG_SET_SYSTEM)) == 0) {
1148 Slog.e(TAG, "Must specify a valid wallpaper category to set");
Christopher Tatead3c2592016-01-20 18:13:17 -08001149 return null;
1150 }
1151
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001152 if (!isWallpaperSupported(callingPackage) || !isWallpaperSettingAllowed(callingPackage)) {
Benjamin Franzf3ece362015-02-11 10:51:10 +00001153 return null;
1154 }
Christopher Tatead3c2592016-01-20 18:13:17 -08001155
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001156 // "null" means the no-op crop, preserving the full input image
1157 if (cropHint == null) {
1158 cropHint = new Rect(0, 0, 0, 0);
1159 } else {
1160 if (cropHint.isEmpty()
1161 || cropHint.left < 0
1162 || cropHint.top < 0) {
1163 return null;
1164 }
1165 }
1166
Christopher Tatebe132e62016-02-10 12:59:49 -08001167 final int userId = UserHandle.getCallingUserId();
1168
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001169 synchronized (mLock) {
Christopher Tatebe132e62016-02-10 12:59:49 -08001170 if (DEBUG) Slog.v(TAG, "setWallpaper which=0x" + Integer.toHexString(which));
1171 WallpaperData wallpaper;
1172
1173 wallpaper = getWallpaperSafeLocked(userId, which);
Dianne Hackborn0cd48872009-08-13 18:51:59 -07001174 final long ident = Binder.clearCallingIdentity();
1175 try {
Christopher Tatead3c2592016-01-20 18:13:17 -08001176 ParcelFileDescriptor pfd = updateWallpaperBitmapLocked(name, wallpaper, extras);
Dianne Hackborn0cd48872009-08-13 18:51:59 -07001177 if (pfd != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001178 wallpaper.imageWallpaperPending = true;
Christopher Tatebe132e62016-02-10 12:59:49 -08001179 wallpaper.whichPending = which;
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001180 wallpaper.setComplete = completion;
1181 wallpaper.cropHint.set(cropHint);
Dianne Hackborn0cd48872009-08-13 18:51:59 -07001182 }
1183 return pfd;
1184 } finally {
1185 Binder.restoreCallingIdentity(ident);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001186 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001187 }
1188 }
1189
Christopher Tatead3c2592016-01-20 18:13:17 -08001190 ParcelFileDescriptor updateWallpaperBitmapLocked(String name, WallpaperData wallpaper,
1191 Bundle extras) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001192 if (name == null) name = "";
1193 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001194 File dir = getWallpaperDir(wallpaper.userId);
1195 if (!dir.exists()) {
1196 dir.mkdir();
Dianne Hackbornebac48c2011-11-29 18:01:50 -08001197 FileUtils.setPermissions(
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001198 dir.getPath(),
Dianne Hackbornebac48c2011-11-29 18:01:50 -08001199 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
1200 -1, -1);
1201 }
Christopher Tatebe132e62016-02-10 12:59:49 -08001202 ParcelFileDescriptor fd = ParcelFileDescriptor.open(wallpaper.wallpaperFile,
Christopher Tate90f86ba2014-09-11 12:37:19 -07001203 MODE_CREATE|MODE_READ_WRITE|MODE_TRUNCATE);
Christopher Tatebe132e62016-02-10 12:59:49 -08001204 if (!SELinux.restorecon(wallpaper.wallpaperFile)) {
rpcraig554cb0c2012-07-05 06:41:43 -04001205 return null;
1206 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001207 wallpaper.name = name;
Christopher Tatead3c2592016-01-20 18:13:17 -08001208 wallpaper.wallpaperId = makeWallpaperIdLocked();
1209 if (extras != null) {
1210 extras.putInt(WallpaperManager.EXTRA_NEW_WALLPAPER_ID, wallpaper.wallpaperId);
1211 }
1212 if (DEBUG) {
1213 Slog.v(TAG, "updateWallpaperBitmapLocked() : id=" + wallpaper.wallpaperId
Christopher Tatebe132e62016-02-10 12:59:49 -08001214 + " name=" + name + " file=" + wallpaper.wallpaperFile.getName());
Christopher Tatead3c2592016-01-20 18:13:17 -08001215 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001216 return fd;
1217 } catch (FileNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001218 Slog.w(TAG, "Error setting wallpaper", e);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001219 }
1220 return null;
1221 }
1222
Benjamin Franzf3ece362015-02-11 10:51:10 +00001223 public void setWallpaperComponentChecked(ComponentName name, String callingPackage) {
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001224 if (isWallpaperSupported(callingPackage) && isWallpaperSettingAllowed(callingPackage)) {
Benjamin Franzf3ece362015-02-11 10:51:10 +00001225 setWallpaperComponent(name);
1226 }
1227 }
1228
1229 // ToDo: Remove this version of the function
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001230 public void setWallpaperComponent(ComponentName name) {
1231 checkPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT);
1232 synchronized (mLock) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001233 if (DEBUG) Slog.v(TAG, "setWallpaperComponent name=" + name);
1234 int userId = UserHandle.getCallingUserId();
1235 WallpaperData wallpaper = mWallpaperMap.get(userId);
1236 if (wallpaper == null) {
1237 throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
1238 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001239 final long ident = Binder.clearCallingIdentity();
1240 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001241 wallpaper.imageWallpaperPending = false;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001242 bindWallpaperComponentLocked(name, false, true, wallpaper, null);
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001243 } finally {
1244 Binder.restoreCallingIdentity(ident);
1245 }
1246 }
1247 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001248
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001249 boolean bindWallpaperComponentLocked(ComponentName componentName, boolean force,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001250 boolean fromUser, WallpaperData wallpaper, IRemoteCallback reply) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001251 if (DEBUG) Slog.v(TAG, "bindWallpaperComponentLocked: componentName=" + componentName);
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001252 // Has the component changed?
Dianne Hackborn9ea31632011-08-05 14:43:50 -07001253 if (!force) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001254 if (wallpaper.connection != null) {
1255 if (wallpaper.wallpaperComponent == null) {
Dianne Hackborn9ea31632011-08-05 14:43:50 -07001256 if (componentName == null) {
1257 if (DEBUG) Slog.v(TAG, "bindWallpaperComponentLocked: still using default");
1258 // Still using default wallpaper.
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001259 return true;
Dianne Hackborn9ea31632011-08-05 14:43:50 -07001260 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001261 } else if (wallpaper.wallpaperComponent.equals(componentName)) {
Dianne Hackborn9ea31632011-08-05 14:43:50 -07001262 // Changing to same wallpaper.
1263 if (DEBUG) Slog.v(TAG, "same wallpaper");
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001264 return true;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001265 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001266 }
1267 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001268
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001269 try {
Mike Clerona428b2c2009-11-15 22:53:08 -08001270 if (componentName == null) {
Jeff Sharkey28f08772014-04-16 09:41:58 -07001271 componentName = WallpaperManager.getDefaultWallpaperComponent(mContext);
Mike Clerona428b2c2009-11-15 22:53:08 -08001272 if (componentName == null) {
Mike Cleron322b6ee2009-11-12 07:45:47 -08001273 // Fall back to static image wallpaper
Justin Koh29c30162014-09-05 17:10:10 -07001274 componentName = mImageWallpaper;
Mike Cleron322b6ee2009-11-12 07:45:47 -08001275 //clearWallpaperComponentLocked();
1276 //return;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001277 if (DEBUG) Slog.v(TAG, "Using image wallpaper");
Mike Cleron322b6ee2009-11-12 07:45:47 -08001278 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001279 }
Amith Yamasani4e2820c2012-08-28 22:17:23 -07001280 int serviceUserId = wallpaper.userId;
1281 ServiceInfo si = mIPackageManager.getServiceInfo(componentName,
1282 PackageManager.GET_META_DATA | PackageManager.GET_PERMISSIONS, serviceUserId);
Christopher Tate90952202013-09-08 13:01:28 -07001283 if (si == null) {
1284 // The wallpaper component we're trying to use doesn't exist
1285 Slog.w(TAG, "Attempted wallpaper " + componentName + " is unavailable");
1286 return false;
1287 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001288 if (!android.Manifest.permission.BIND_WALLPAPER.equals(si.permission)) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001289 String msg = "Selected service does not require "
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001290 + android.Manifest.permission.BIND_WALLPAPER
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001291 + ": " + componentName;
1292 if (fromUser) {
1293 throw new SecurityException(msg);
1294 }
1295 Slog.w(TAG, msg);
1296 return false;
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001297 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001298
Dianne Hackborneb034652009-09-07 00:49:58 -07001299 WallpaperInfo wi = null;
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001300
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001301 Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
Justin Koh29c30162014-09-05 17:10:10 -07001302 if (componentName != null && !componentName.equals(mImageWallpaper)) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001303 // Make sure the selected service is actually a wallpaper service.
Amith Yamasani4e2820c2012-08-28 22:17:23 -07001304 List<ResolveInfo> ris =
1305 mIPackageManager.queryIntentServices(intent,
1306 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
1307 PackageManager.GET_META_DATA, serviceUserId);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001308 for (int i=0; i<ris.size(); i++) {
1309 ServiceInfo rsi = ris.get(i).serviceInfo;
1310 if (rsi.name.equals(si.name) &&
1311 rsi.packageName.equals(si.packageName)) {
Dianne Hackborneb034652009-09-07 00:49:58 -07001312 try {
1313 wi = new WallpaperInfo(mContext, ris.get(i));
1314 } catch (XmlPullParserException e) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001315 if (fromUser) {
1316 throw new IllegalArgumentException(e);
1317 }
1318 Slog.w(TAG, e);
1319 return false;
Dianne Hackborneb034652009-09-07 00:49:58 -07001320 } catch (IOException e) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001321 if (fromUser) {
1322 throw new IllegalArgumentException(e);
1323 }
1324 Slog.w(TAG, e);
1325 return false;
Dianne Hackborneb034652009-09-07 00:49:58 -07001326 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001327 break;
1328 }
1329 }
Dianne Hackborneb034652009-09-07 00:49:58 -07001330 if (wi == null) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001331 String msg = "Selected service is not a wallpaper: "
1332 + componentName;
1333 if (fromUser) {
1334 throw new SecurityException(msg);
1335 }
1336 Slog.w(TAG, msg);
1337 return false;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001338 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001339 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001340
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001341 // Bind the service!
Joe Onorato8a9b2202010-02-26 18:56:32 -08001342 if (DEBUG) Slog.v(TAG, "Binding to:" + componentName);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001343 WallpaperConnection newConn = new WallpaperConnection(wi, wallpaper);
Mike Clerona428b2c2009-11-15 22:53:08 -08001344 intent.setComponent(componentName);
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07001345 intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
1346 com.android.internal.R.string.wallpaper_binding_label);
Dianne Hackborn41203752012-08-31 14:05:51 -07001347 intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivityAsUser(
Dianne Hackborneb034652009-09-07 00:49:58 -07001348 mContext, 0,
1349 Intent.createChooser(new Intent(Intent.ACTION_SET_WALLPAPER),
1350 mContext.getText(com.android.internal.R.string.chooser_wallpaper)),
Dianne Hackborn41203752012-08-31 14:05:51 -07001351 0, null, new UserHandle(serviceUserId)));
Dianne Hackbornc8230512013-07-13 21:32:12 -07001352 if (!mContext.bindServiceAsUser(intent, newConn,
Dianne Hackbornd69e4c12015-04-24 09:54:54 -07001353 Context.BIND_AUTO_CREATE | Context.BIND_SHOWING_UI
1354 | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
Amith Yamasani27b89e62013-01-16 12:30:11 -08001355 new UserHandle(serviceUserId))) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001356 String msg = "Unable to bind service: "
1357 + componentName;
1358 if (fromUser) {
1359 throw new IllegalArgumentException(msg);
1360 }
1361 Slog.w(TAG, msg);
1362 return false;
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001363 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001364 if (wallpaper.userId == mCurrentUserId && mLastWallpaper != null) {
1365 detachWallpaperLocked(mLastWallpaper);
1366 }
1367 wallpaper.wallpaperComponent = componentName;
1368 wallpaper.connection = newConn;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001369 newConn.mReply = reply;
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001370 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001371 if (wallpaper.userId == mCurrentUserId) {
1372 if (DEBUG)
1373 Slog.v(TAG, "Adding window token: " + newConn.mToken);
1374 mIWindowManager.addWindowToken(newConn.mToken,
1375 WindowManager.LayoutParams.TYPE_WALLPAPER);
1376 mLastWallpaper = wallpaper;
1377 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001378 } catch (RemoteException e) {
1379 }
Amith Yamasani4e2820c2012-08-28 22:17:23 -07001380 } catch (RemoteException e) {
1381 String msg = "Remote exception for " + componentName + "\n" + e;
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001382 if (fromUser) {
1383 throw new IllegalArgumentException(msg);
1384 }
1385 Slog.w(TAG, msg);
1386 return false;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001387 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001388 return true;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001389 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001390
1391 void detachWallpaperLocked(WallpaperData wallpaper) {
1392 if (wallpaper.connection != null) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001393 if (wallpaper.connection.mReply != null) {
1394 try {
1395 wallpaper.connection.mReply.sendResult(null);
1396 } catch (RemoteException e) {
1397 }
1398 wallpaper.connection.mReply = null;
1399 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001400 if (wallpaper.connection.mEngine != null) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001401 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001402 wallpaper.connection.mEngine.destroy();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001403 } catch (RemoteException e) {
1404 }
1405 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001406 mContext.unbindService(wallpaper.connection);
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001407 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001408 if (DEBUG)
1409 Slog.v(TAG, "Removing window token: " + wallpaper.connection.mToken);
1410 mIWindowManager.removeWindowToken(wallpaper.connection.mToken);
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001411 } catch (RemoteException e) {
1412 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001413 wallpaper.connection.mService = null;
1414 wallpaper.connection.mEngine = null;
1415 wallpaper.connection = null;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001416 }
1417 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001418
1419 void clearWallpaperComponentLocked(WallpaperData wallpaper) {
1420 wallpaper.wallpaperComponent = null;
1421 detachWallpaperLocked(wallpaper);
1422 }
1423
1424 void attachServiceLocked(WallpaperConnection conn, WallpaperData wallpaper) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001425 try {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001426 conn.mService.attach(conn, conn.mToken,
1427 WindowManager.LayoutParams.TYPE_WALLPAPER, false,
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001428 wallpaper.width, wallpaper.height, wallpaper.padding);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001429 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001430 Slog.w(TAG, "Failed attaching wallpaper; clearing", e);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001431 if (!wallpaper.wallpaperUpdating) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001432 bindWallpaperComponentLocked(null, false, false, wallpaper, null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001433 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001434 }
1435 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001436
1437 private void notifyCallbacksLocked(WallpaperData wallpaper) {
1438 final int n = wallpaper.callbacks.beginBroadcast();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001439 for (int i = 0; i < n; i++) {
1440 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001441 wallpaper.callbacks.getBroadcastItem(i).onWallpaperChanged();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001442 } catch (RemoteException e) {
1443
1444 // The RemoteCallbackList will take care of removing
1445 // the dead object for us.
1446 }
1447 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001448 wallpaper.callbacks.finishBroadcast();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001449 final Intent intent = new Intent(Intent.ACTION_WALLPAPER_CHANGED);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001450 mContext.sendBroadcastAsUser(intent, new UserHandle(mCurrentUserId));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001451 }
1452
1453 private void checkPermission(String permission) {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001454 if (PackageManager.PERMISSION_GRANTED!= mContext.checkCallingOrSelfPermission(permission)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001455 throw new SecurityException("Access denied to process: " + Binder.getCallingPid()
1456 + ", must have permission " + permission);
1457 }
1458 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001459
Benjamin Franzf3ece362015-02-11 10:51:10 +00001460 /**
1461 * Certain user types do not support wallpapers (e.g. managed profiles). The check is
1462 * implemented through through the OP_WRITE_WALLPAPER AppOp.
1463 */
1464 public boolean isWallpaperSupported(String callingPackage) {
1465 return mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_WRITE_WALLPAPER, Binder.getCallingUid(),
1466 callingPackage) == AppOpsManager.MODE_ALLOWED;
1467 }
1468
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001469 @Override
1470 public boolean isWallpaperSettingAllowed(String callingPackage) {
1471 final PackageManager pm = mContext.getPackageManager();
1472 String[] uidPackages = pm.getPackagesForUid(Binder.getCallingUid());
1473 boolean uidMatchPackage = Arrays.asList(uidPackages).contains(callingPackage);
1474 if (!uidMatchPackage) {
1475 return false; // callingPackage was faked.
1476 }
1477
1478 final DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
1479 if (dpm.isDeviceOwnerApp(callingPackage) || dpm.isProfileOwnerApp(callingPackage)) {
1480 return true;
1481 }
1482 final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
1483 return !um.hasUserRestriction(UserManager.DISALLOW_SET_WALLPAPER);
1484 }
1485
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001486 private static JournaledFile makeJournaledFile(int userId) {
Amith Yamasani61f57372012-08-31 12:12:28 -07001487 final String base = new File(getWallpaperDir(userId), WALLPAPER_INFO).getAbsolutePath();
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001488 return new JournaledFile(new File(base), new File(base + ".tmp"));
1489 }
1490
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001491 private void saveSettingsLocked(WallpaperData wallpaper) {
1492 JournaledFile journal = makeJournaledFile(wallpaper.userId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001493 FileOutputStream stream = null;
1494 try {
1495 stream = new FileOutputStream(journal.chooseForWrite(), false);
1496 XmlSerializer out = new FastXmlSerializer();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001497 out.setOutput(stream, StandardCharsets.UTF_8.name());
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001498 out.startDocument(null, true);
1499
1500 out.startTag(null, "wp");
Christopher Tatead3c2592016-01-20 18:13:17 -08001501 out.attribute(null, "id", Integer.toString(wallpaper.wallpaperId));
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001502 out.attribute(null, "width", Integer.toString(wallpaper.width));
1503 out.attribute(null, "height", Integer.toString(wallpaper.height));
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001504
1505 out.attribute(null, "cropLeft", Integer.toString(wallpaper.cropHint.left));
1506 out.attribute(null, "cropTop", Integer.toString(wallpaper.cropHint.top));
1507 out.attribute(null, "cropRight", Integer.toString(wallpaper.cropHint.right));
1508 out.attribute(null, "cropBottom", Integer.toString(wallpaper.cropHint.bottom));
1509
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001510 if (wallpaper.padding.left != 0) {
1511 out.attribute(null, "paddingLeft", Integer.toString(wallpaper.padding.left));
1512 }
1513 if (wallpaper.padding.top != 0) {
1514 out.attribute(null, "paddingTop", Integer.toString(wallpaper.padding.top));
1515 }
1516 if (wallpaper.padding.right != 0) {
1517 out.attribute(null, "paddingRight", Integer.toString(wallpaper.padding.right));
1518 }
1519 if (wallpaper.padding.bottom != 0) {
1520 out.attribute(null, "paddingBottom", Integer.toString(wallpaper.padding.bottom));
1521 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001522
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001523 out.attribute(null, "name", wallpaper.name);
1524 if (wallpaper.wallpaperComponent != null
Justin Koh29c30162014-09-05 17:10:10 -07001525 && !wallpaper.wallpaperComponent.equals(mImageWallpaper)) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001526 out.attribute(null, "component",
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001527 wallpaper.wallpaperComponent.flattenToShortString());
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001528 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001529 out.endTag(null, "wp");
1530
1531 out.endDocument();
Kenny Guya526a1e2015-01-21 16:52:01 +00001532 stream.flush();
1533 FileUtils.sync(stream);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001534 stream.close();
1535 journal.commit();
1536 } catch (IOException e) {
Christopher Tatead3c2592016-01-20 18:13:17 -08001537 IoUtils.closeQuietly(stream);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001538 journal.rollback();
1539 }
1540 }
1541
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001542 private void migrateFromOld() {
1543 File oldWallpaper = new File(WallpaperBackupHelper.WALLPAPER_IMAGE_KEY);
1544 File oldInfo = new File(WallpaperBackupHelper.WALLPAPER_INFO_KEY);
1545 if (oldWallpaper.exists()) {
1546 File newWallpaper = new File(getWallpaperDir(0), WALLPAPER);
1547 oldWallpaper.renameTo(newWallpaper);
1548 }
1549 if (oldInfo.exists()) {
1550 File newInfo = new File(getWallpaperDir(0), WALLPAPER_INFO);
1551 oldInfo.renameTo(newInfo);
1552 }
1553 }
1554
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001555 private int getAttributeInt(XmlPullParser parser, String name, int defValue) {
1556 String value = parser.getAttributeValue(null, name);
1557 if (value == null) {
1558 return defValue;
1559 }
1560 return Integer.parseInt(value);
1561 }
1562
Xiaohui Chenac531942015-05-13 13:20:52 -07001563 /**
1564 * Sometimes it is expected the wallpaper map may not have a user's data. E.g. This could
1565 * happen during user switch. The async user switch observer may not have received
1566 * the event yet. We use this safe method when we don't care about this ordering and just
1567 * want to update the data. The data is going to be applied when the user switch observer
1568 * is eventually executed.
1569 */
Christopher Tatebe132e62016-02-10 12:59:49 -08001570 private WallpaperData getWallpaperSafeLocked(int userId, int which) {
1571 // We're setting either just system (work with the system wallpaper),
1572 // both (also work with the system wallpaper), or just the lock
1573 // wallpaper (update against the existing lock wallpaper if any).
1574 // Combined or just-system operations use the 'system' WallpaperData
1575 // for this use; lock-only operations use the dedicated one.
1576 final SparseArray<WallpaperData> whichSet =
1577 (which == FLAG_SET_LOCK) ? mLockWallpaperMap : mWallpaperMap;
1578 WallpaperData wallpaper = whichSet.get(userId);
Xiaohui Chenac531942015-05-13 13:20:52 -07001579 if (wallpaper == null) {
Christopher Tatebe132e62016-02-10 12:59:49 -08001580 // common case, this is the first lookup post-boot of the system or
1581 // unified lock, so we bring up the saved state lazily now and recheck.
Xiaohui Chenac531942015-05-13 13:20:52 -07001582 loadSettingsLocked(userId);
Christopher Tatebe132e62016-02-10 12:59:49 -08001583 wallpaper = whichSet.get(userId);
1584 // if it's still null here, this is a lock-only operation and there is not
1585 // yet a lock-only wallpaper set for this user, so we need to establish
1586 // it now.
1587 if (wallpaper == null) {
1588 if (which == FLAG_SET_LOCK) {
1589 wallpaper = new WallpaperData(userId,
1590 WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP);
1591 mLockWallpaperMap.put(userId, wallpaper);
1592 } else {
1593 // sanity fallback: we're in bad shape, but establishing a known
1594 // valid system+lock WallpaperData will keep us from dying.
1595 Slog.wtf(TAG, "Didn't find wallpaper in non-lock case!");
1596 wallpaper = new WallpaperData(userId, WALLPAPER, WALLPAPER_CROP);
1597 mWallpaperMap.put(userId, wallpaper);
1598 }
1599 }
Xiaohui Chenac531942015-05-13 13:20:52 -07001600 }
1601 return wallpaper;
1602 }
1603
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001604 private void loadSettingsLocked(int userId) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001605 if (DEBUG) Slog.v(TAG, "loadSettingsLocked");
Benjamin Franzf3ece362015-02-11 10:51:10 +00001606
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001607 JournaledFile journal = makeJournaledFile(userId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001608 FileInputStream stream = null;
1609 File file = journal.chooseForRead();
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001610 if (!file.exists()) {
1611 // This should only happen one time, when upgrading from a legacy system
1612 migrateFromOld();
1613 }
1614 WallpaperData wallpaper = mWallpaperMap.get(userId);
1615 if (wallpaper == null) {
Christopher Tatebe132e62016-02-10 12:59:49 -08001616 wallpaper = new WallpaperData(userId, WALLPAPER, WALLPAPER_CROP);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001617 mWallpaperMap.put(userId, wallpaper);
Christopher Tatebe132e62016-02-10 12:59:49 -08001618 wallpaper.ensureCropExists();
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001619 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001620 boolean success = false;
1621 try {
1622 stream = new FileInputStream(file);
1623 XmlPullParser parser = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001624 parser.setInput(stream, StandardCharsets.UTF_8.name());
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001625
1626 int type;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001627 do {
1628 type = parser.next();
1629 if (type == XmlPullParser.START_TAG) {
1630 String tag = parser.getName();
1631 if ("wp".equals(tag)) {
Christopher Tatebe132e62016-02-10 12:59:49 -08001632 // Common to system + lock wallpapers
1633 parseWallpaperAttributes(parser, wallpaper);
Christopher Tatead3c2592016-01-20 18:13:17 -08001634
Christopher Tatebe132e62016-02-10 12:59:49 -08001635 // A system wallpaper might also be a live wallpaper
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001636 String comp = parser.getAttributeValue(null, "component");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001637 wallpaper.nextWallpaperComponent = comp != null
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001638 ? ComponentName.unflattenFromString(comp)
1639 : null;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001640 if (wallpaper.nextWallpaperComponent == null
1641 || "android".equals(wallpaper.nextWallpaperComponent
1642 .getPackageName())) {
Justin Koh29c30162014-09-05 17:10:10 -07001643 wallpaper.nextWallpaperComponent = mImageWallpaper;
Dianne Hackborn9ea31632011-08-05 14:43:50 -07001644 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001645
Mike Clerona428b2c2009-11-15 22:53:08 -08001646 if (DEBUG) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001647 Slog.v(TAG, "mWidth:" + wallpaper.width);
1648 Slog.v(TAG, "mHeight:" + wallpaper.height);
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001649 Slog.v(TAG, "cropRect:" + wallpaper.cropHint);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001650 Slog.v(TAG, "mName:" + wallpaper.name);
1651 Slog.v(TAG, "mNextWallpaperComponent:"
1652 + wallpaper.nextWallpaperComponent);
Mike Clerona428b2c2009-11-15 22:53:08 -08001653 }
Christopher Tatebe132e62016-02-10 12:59:49 -08001654 } else if ("kwp".equals(tag)) {
1655 // keyguard-specific wallpaper for this user
1656 WallpaperData lockWallpaper = mLockWallpaperMap.get(userId);
1657 if (lockWallpaper == null) {
1658 lockWallpaper = new WallpaperData(userId,
1659 WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP);
1660 mLockWallpaperMap.put(userId, lockWallpaper);
1661 }
1662 parseWallpaperAttributes(parser, lockWallpaper);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001663 }
1664 }
1665 } while (type != XmlPullParser.END_DOCUMENT);
1666 success = true;
Dianne Hackborn13579ed2012-11-28 18:05:36 -08001667 } catch (FileNotFoundException e) {
1668 Slog.w(TAG, "no current wallpaper -- first boot?");
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001669 } catch (NullPointerException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001670 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001671 } catch (NumberFormatException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001672 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001673 } catch (XmlPullParserException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001674 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001675 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001676 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001677 } catch (IndexOutOfBoundsException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001678 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001679 }
Christopher Tatead3c2592016-01-20 18:13:17 -08001680 IoUtils.closeQuietly(stream);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001681
1682 if (!success) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001683 wallpaper.width = -1;
1684 wallpaper.height = -1;
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001685 wallpaper.cropHint.set(0, 0, 0, 0);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001686 wallpaper.padding.set(0, 0, 0, 0);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001687 wallpaper.name = "";
Christopher Tatead3c2592016-01-20 18:13:17 -08001688 } else {
1689 if (wallpaper.wallpaperId <= 0) {
1690 wallpaper.wallpaperId = makeWallpaperIdLocked();
1691 if (DEBUG) {
1692 Slog.w(TAG, "Didn't set wallpaper id in loadSettingsLocked(" + userId
1693 + "); now " + wallpaper.wallpaperId);
1694 }
1695 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001696 }
Dianne Hackborn44bc17c2011-04-20 18:18:51 -07001697
1698 // We always want to have some reasonable width hint.
John Spurlock7ea91ec2013-11-04 13:48:38 -05001699 int baseSize = getMaximumSizeDimension();
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001700 if (wallpaper.width < baseSize) {
1701 wallpaper.width = baseSize;
Dianne Hackborn44bc17c2011-04-20 18:18:51 -07001702 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001703 if (wallpaper.height < baseSize) {
1704 wallpaper.height = baseSize;
Dianne Hackborn44bc17c2011-04-20 18:18:51 -07001705 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001706 // and crop, if not previously specified
1707 if (wallpaper.cropHint.width() <= 0
1708 || wallpaper.cropHint.height() <= 0) {
1709 wallpaper.cropHint.set(0, 0, wallpaper.width, wallpaper.height);
1710 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001711 }
1712
Christopher Tatebe132e62016-02-10 12:59:49 -08001713 private void parseWallpaperAttributes(XmlPullParser parser, WallpaperData wallpaper) {
1714 final String idString = parser.getAttributeValue(null, "id");
1715 if (idString != null) {
1716 final int id = wallpaper.wallpaperId = Integer.parseInt(idString);
1717 if (id > mWallpaperId) {
1718 mWallpaperId = id;
1719 }
1720 } else {
1721 wallpaper.wallpaperId = makeWallpaperIdLocked();
1722 }
1723
1724 wallpaper.width = Integer.parseInt(parser.getAttributeValue(null, "width"));
1725 wallpaper.height = Integer.parseInt(parser
1726 .getAttributeValue(null, "height"));
1727 wallpaper.cropHint.left = getAttributeInt(parser, "cropLeft", 0);
1728 wallpaper.cropHint.top = getAttributeInt(parser, "cropTop", 0);
1729 wallpaper.cropHint.right = getAttributeInt(parser, "cropRight", 0);
1730 wallpaper.cropHint.bottom = getAttributeInt(parser, "cropBottom", 0);
1731 wallpaper.padding.left = getAttributeInt(parser, "paddingLeft", 0);
1732 wallpaper.padding.top = getAttributeInt(parser, "paddingTop", 0);
1733 wallpaper.padding.right = getAttributeInt(parser, "paddingRight", 0);
1734 wallpaper.padding.bottom = getAttributeInt(parser, "paddingBottom", 0);
1735 wallpaper.name = parser.getAttributeValue(null, "name");
1736 }
1737
John Spurlock7ea91ec2013-11-04 13:48:38 -05001738 private int getMaximumSizeDimension() {
1739 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
1740 Display d = wm.getDefaultDisplay();
1741 return d.getMaximumSizeDimension();
1742 }
1743
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07001744 // Called by SystemBackupAgent after files are restored to disk.
Amith Yamasani09e9cdc2013-11-06 14:54:50 -08001745 public void settingsRestored() {
1746 // Verify caller is the system
1747 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
1748 throw new RuntimeException("settingsRestored() can only be called from the system process");
1749 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001750 // TODO: If necessary, make it work for secondary users as well. This currently assumes
1751 // restores only to the primary user
Joe Onorato8a9b2202010-02-26 18:56:32 -08001752 if (DEBUG) Slog.v(TAG, "settingsRestored");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001753 WallpaperData wallpaper = null;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001754 boolean success = false;
1755 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001756 loadSettingsLocked(0);
1757 wallpaper = mWallpaperMap.get(0);
Christopher Tatead3c2592016-01-20 18:13:17 -08001758 wallpaper.wallpaperId = makeWallpaperIdLocked(); // always bump id at restore
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001759 if (wallpaper.nextWallpaperComponent != null
Justin Koh29c30162014-09-05 17:10:10 -07001760 && !wallpaper.nextWallpaperComponent.equals(mImageWallpaper)) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001761 if (!bindWallpaperComponentLocked(wallpaper.nextWallpaperComponent, false, false,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001762 wallpaper, null)) {
Christopher Tatee3ab4d02009-12-16 14:03:31 -08001763 // No such live wallpaper or other failure; fall back to the default
1764 // live wallpaper (since the profile being restored indicated that the
1765 // user had selected a live rather than static one).
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001766 bindWallpaperComponentLocked(null, false, false, wallpaper, null);
Christopher Tatee3ab4d02009-12-16 14:03:31 -08001767 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001768 success = true;
1769 } else {
Mike Clerona428b2c2009-11-15 22:53:08 -08001770 // If there's a wallpaper name, we use that. If that can't be loaded, then we
1771 // use the default.
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001772 if ("".equals(wallpaper.name)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001773 if (DEBUG) Slog.v(TAG, "settingsRestored: name is empty");
Mike Clerona428b2c2009-11-15 22:53:08 -08001774 success = true;
1775 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001776 if (DEBUG) Slog.v(TAG, "settingsRestored: attempting to restore named resource");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001777 success = restoreNamedResourceLocked(wallpaper);
Mike Clerona428b2c2009-11-15 22:53:08 -08001778 }
Christopher Tatead3c2592016-01-20 18:13:17 -08001779 if (DEBUG) Slog.v(TAG, "settingsRestored: success=" + success
1780 + " id=" + wallpaper.wallpaperId);
Mike Clerona428b2c2009-11-15 22:53:08 -08001781 if (success) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001782 bindWallpaperComponentLocked(wallpaper.nextWallpaperComponent, false, false,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001783 wallpaper, null);
Mike Clerona428b2c2009-11-15 22:53:08 -08001784 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001785 }
1786 }
1787
1788 if (!success) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001789 Slog.e(TAG, "Failed to restore wallpaper: '" + wallpaper.name + "'");
1790 wallpaper.name = "";
1791 getWallpaperDir(0).delete();
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001792 }
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07001793
1794 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001795 saveSettingsLocked(wallpaper);
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07001796 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001797 }
1798
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001799 // Restore the named resource bitmap to both source + crop files
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001800 boolean restoreNamedResourceLocked(WallpaperData wallpaper) {
1801 if (wallpaper.name.length() > 4 && "res:".equals(wallpaper.name.substring(0, 4))) {
1802 String resName = wallpaper.name.substring(4);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001803
1804 String pkg = null;
1805 int colon = resName.indexOf(':');
1806 if (colon > 0) {
1807 pkg = resName.substring(0, colon);
1808 }
1809
1810 String ident = null;
1811 int slash = resName.lastIndexOf('/');
1812 if (slash > 0) {
1813 ident = resName.substring(slash+1);
1814 }
1815
1816 String type = null;
1817 if (colon > 0 && slash > 0 && (slash-colon) > 1) {
1818 type = resName.substring(colon+1, slash);
1819 }
1820
1821 if (pkg != null && ident != null && type != null) {
1822 int resId = -1;
1823 InputStream res = null;
1824 FileOutputStream fos = null;
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001825 FileOutputStream cos = null;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001826 try {
1827 Context c = mContext.createPackageContext(pkg, Context.CONTEXT_RESTRICTED);
1828 Resources r = c.getResources();
1829 resId = r.getIdentifier(resName, null, null);
1830 if (resId == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001831 Slog.e(TAG, "couldn't resolve identifier pkg=" + pkg + " type=" + type
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001832 + " ident=" + ident);
1833 return false;
1834 }
1835
1836 res = r.openRawResource(resId);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001837 if (wallpaper.wallpaperFile.exists()) {
1838 wallpaper.wallpaperFile.delete();
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001839 wallpaper.cropFile.delete();
Dianne Hackborn1afd1c92010-03-18 22:47:17 -07001840 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001841 fos = new FileOutputStream(wallpaper.wallpaperFile);
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001842 cos = new FileOutputStream(wallpaper.cropFile);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001843
1844 byte[] buffer = new byte[32768];
1845 int amt;
1846 while ((amt=res.read(buffer)) > 0) {
1847 fos.write(buffer, 0, amt);
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001848 cos.write(buffer, 0, amt);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001849 }
1850 // mWallpaperObserver will notice the close and send the change broadcast
1851
Joe Onorato8a9b2202010-02-26 18:56:32 -08001852 Slog.v(TAG, "Restored wallpaper: " + resName);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001853 return true;
1854 } catch (NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001855 Slog.e(TAG, "Package name " + pkg + " not found");
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001856 } catch (Resources.NotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001857 Slog.e(TAG, "Resource not found: " + resId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001858 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001859 Slog.e(TAG, "IOException while restoring wallpaper ", e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001860 } finally {
Christopher Tatead3c2592016-01-20 18:13:17 -08001861 IoUtils.closeQuietly(res);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001862 if (fos != null) {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07001863 FileUtils.sync(fos);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001864 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001865 if (cos != null) {
1866 FileUtils.sync(cos);
1867 }
1868 IoUtils.closeQuietly(fos);
1869 IoUtils.closeQuietly(cos);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001870 }
1871 }
1872 }
1873 return false;
1874 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001875
Dianne Hackborneb034652009-09-07 00:49:58 -07001876 @Override
1877 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1878 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
1879 != PackageManager.PERMISSION_GRANTED) {
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001880
Dianne Hackborneb034652009-09-07 00:49:58 -07001881 pw.println("Permission Denial: can't dump wallpaper service from from pid="
1882 + Binder.getCallingPid()
1883 + ", uid=" + Binder.getCallingUid());
1884 return;
1885 }
1886
1887 synchronized (mLock) {
1888 pw.println("Current Wallpaper Service state:");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001889 for (int i = 0; i < mWallpaperMap.size(); i++) {
1890 WallpaperData wallpaper = mWallpaperMap.valueAt(i);
Christopher Tatead3c2592016-01-20 18:13:17 -08001891 pw.print(" User "); pw.print(wallpaper.userId);
1892 pw.print(": id="); pw.println(wallpaper.wallpaperId);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001893 pw.print(" mWidth=");
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001894 pw.print(wallpaper.width);
1895 pw.print(" mHeight=");
1896 pw.println(wallpaper.height);
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001897 pw.print(" mCropHint="); pw.println(wallpaper.cropHint);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001898 pw.print(" mPadding="); pw.println(wallpaper.padding);
1899 pw.print(" mName="); pw.println(wallpaper.name);
1900 pw.print(" mWallpaperComponent="); pw.println(wallpaper.wallpaperComponent);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001901 if (wallpaper.connection != null) {
1902 WallpaperConnection conn = wallpaper.connection;
1903 pw.print(" Wallpaper connection ");
1904 pw.print(conn);
1905 pw.println(":");
1906 if (conn.mInfo != null) {
1907 pw.print(" mInfo.component=");
1908 pw.println(conn.mInfo.getComponent());
1909 }
1910 pw.print(" mToken=");
1911 pw.println(conn.mToken);
1912 pw.print(" mService=");
1913 pw.println(conn.mService);
1914 pw.print(" mEngine=");
1915 pw.println(conn.mEngine);
1916 pw.print(" mLastDiedTime=");
1917 pw.println(wallpaper.lastDiedTime - SystemClock.uptimeMillis());
1918 }
Dianne Hackborneb034652009-09-07 00:49:58 -07001919 }
1920 }
1921 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001922}