blob: 4848523bb3f0a1b0f0a0e2267d69404bb78caa15 [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
Christopher Tatee409f0e2016-03-21 14:53:15 -070023import android.app.ActivityManager;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -070024import android.app.ActivityManagerNative;
Amith Yamasani4e2820c2012-08-28 22:17:23 -070025import android.app.AppGlobals;
Benjamin Franzf3ece362015-02-11 10:51:10 +000026import android.app.AppOpsManager;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -070027import android.app.IUserSwitchObserver;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070028import android.app.IWallpaperManager;
29import android.app.IWallpaperManagerCallback;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070030import android.app.PendingIntent;
Dianne Hackborneb034652009-09-07 00:49:58 -070031import android.app.WallpaperInfo;
Jeff Sharkey28f08772014-04-16 09:41:58 -070032import android.app.WallpaperManager;
Oleksandr Peletskyif2519812016-01-26 20:16:06 +010033import android.app.admin.DevicePolicyManager;
Christopher Tate45281862010-03-05 15:46:30 -080034import android.app.backup.BackupManager;
Amith Yamasani37ce3a82012-02-06 12:04:42 -080035import android.app.backup.WallpaperBackupHelper;
Amith Yamasani13593602012-03-22 16:16:17 -070036import android.content.BroadcastReceiver;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070037import android.content.ComponentName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038import android.content.Context;
39import android.content.Intent;
Amith Yamasani13593602012-03-22 16:16:17 -070040import android.content.IntentFilter;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070041import android.content.ServiceConnection;
Amith Yamasani4e2820c2012-08-28 22:17:23 -070042import android.content.pm.IPackageManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043import android.content.pm.PackageManager;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070044import android.content.pm.ResolveInfo;
45import android.content.pm.ServiceInfo;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070046import android.content.pm.PackageManager.NameNotFoundException;
Amith Yamasani6474c4c2012-10-04 14:55:42 -070047import android.content.pm.UserInfo;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070048import android.content.res.Resources;
Christopher Tate1e1e2e02016-01-25 15:34:36 -080049import android.graphics.Bitmap;
50import android.graphics.BitmapFactory;
51import android.graphics.BitmapRegionDecoder;
John Spurlock41f64642013-11-04 13:48:38 -050052import android.graphics.Point;
Dianne Hackborn067e5f62014-09-07 23:14:30 -070053import android.graphics.Rect;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054import android.os.Binder;
Dianne Hackborn284ac932009-08-28 10:34:25 -070055import android.os.Bundle;
Amith Yamasani13593602012-03-22 16:16:17 -070056import android.os.Environment;
Dianne Hackborn8bdf5932010-10-15 12:54:40 -070057import android.os.FileUtils;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070058import android.os.IBinder;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -070059import android.os.IRemoteCallback;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060import android.os.RemoteException;
61import android.os.FileObserver;
62import android.os.ParcelFileDescriptor;
63import android.os.RemoteCallbackList;
rpcraig554cb0c2012-07-05 06:41:43 -040064import android.os.SELinux;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070065import android.os.ServiceManager;
Dianne Hackborn0cd48872009-08-13 18:51:59 -070066import android.os.SystemClock;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070067import android.os.UserHandle;
Amith Yamasani6474c4c2012-10-04 14:55:42 -070068import android.os.UserManager;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070069import android.service.wallpaper.IWallpaperConnection;
70import android.service.wallpaper.IWallpaperEngine;
71import android.service.wallpaper.IWallpaperService;
72import android.service.wallpaper.WallpaperService;
Filip Gruszczynski5dcc3ac2014-10-13 15:51:39 -070073import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -080074import android.util.Slog;
Amith Yamasani37ce3a82012-02-06 12:04:42 -080075import android.util.SparseArray;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070076import android.util.Xml;
Dianne Hackborn44bc17c2011-04-20 18:18:51 -070077import android.view.Display;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070078import android.view.IWindowManager;
79import android.view.WindowManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080
Christopher Tate1e1e2e02016-01-25 15:34:36 -080081import java.io.BufferedOutputStream;
Dianne Hackborneb034652009-09-07 00:49:58 -070082import java.io.FileDescriptor;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070083import java.io.IOException;
84import java.io.InputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085import java.io.File;
86import java.io.FileNotFoundException;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070087import java.io.FileInputStream;
88import java.io.FileOutputStream;
Dianne Hackborneb034652009-09-07 00:49:58 -070089import java.io.PrintWriter;
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +010090import java.nio.charset.StandardCharsets;
Oleksandr Peletskyif2519812016-01-26 20:16:06 +010091import java.util.Arrays;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070092import java.util.List;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070093
94import org.xmlpull.v1.XmlPullParser;
95import org.xmlpull.v1.XmlPullParserException;
96import org.xmlpull.v1.XmlSerializer;
97
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080098import com.android.internal.content.PackageMonitor;
Dianne Hackborn2269d1572010-02-24 19:54:22 -080099import com.android.internal.util.FastXmlSerializer;
Dianne Hackborn1afd1c92010-03-18 22:47:17 -0700100import com.android.internal.util.JournaledFile;
Justin Koh29c30162014-09-05 17:10:10 -0700101import com.android.internal.R;
Filip Gruszczynski5dcc3ac2014-10-13 15:51:39 -0700102import com.android.server.EventLogTags;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103
Christopher Tatead3c2592016-01-20 18:13:17 -0800104import libcore.io.IoUtils;
105
Amith Yamasani09e9cdc2013-11-06 14:54:50 -0800106public class WallpaperManagerService extends IWallpaperManager.Stub {
107 static final String TAG = "WallpaperManagerService";
Joe Onorato7e1693a2016-02-01 17:45:03 -0800108 static final boolean DEBUG = false;
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700109
Christopher Tatebe132e62016-02-10 12:59:49 -0800110 final Object mLock = new Object();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111
Dianne Hackborn0cd48872009-08-13 18:51:59 -0700112 /**
113 * Minimum time between crashes of a wallpaper service for us to consider
114 * restarting it vs. just reverting to the static wallpaper.
115 */
116 static final long MIN_WALLPAPER_CRASH_TIME = 10000;
Filip Gruszczynski5dcc3ac2014-10-13 15:51:39 -0700117 static final int MAX_WALLPAPER_COMPONENT_LOG_LENGTH = 128;
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800118 static final String WALLPAPER = "wallpaper_orig";
119 static final String WALLPAPER_CROP = "wallpaper";
Christopher Tatebe132e62016-02-10 12:59:49 -0800120 static final String WALLPAPER_LOCK_ORIG = "wallpaper_lock_orig";
121 static final String WALLPAPER_LOCK_CROP = "wallpaper_lock";
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800122 static final String WALLPAPER_INFO = "wallpaper_info.xml";
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -0700123
Christopher Tatebe132e62016-02-10 12:59:49 -0800124 // All the various per-user state files we need to be aware of
125 static final String[] sPerUserFiles = new String[] {
126 WALLPAPER, WALLPAPER_CROP,
127 WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP,
128 WALLPAPER_INFO
129 };
130
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -0700131 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800132 * Observes the wallpaper for changes and notifies all IWallpaperServiceCallbacks
133 * that the wallpaper has changed. The CREATE is triggered when there is no
134 * wallpaper set and is created for the first time. The CLOSE_WRITE is triggered
135 * everytime the wallpaper is changed.
136 */
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800137 private class WallpaperObserver extends FileObserver {
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700138
Christopher Tatebe132e62016-02-10 12:59:49 -0800139 final int mUserId;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800140 final WallpaperData mWallpaper;
141 final File mWallpaperDir;
142 final File mWallpaperFile;
Christopher Tatebe132e62016-02-10 12:59:49 -0800143 final File mWallpaperLockFile;
Amith Yamasani52d750c2014-12-10 14:09:05 -0800144 final File mWallpaperInfoFile;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800145
146 public WallpaperObserver(WallpaperData wallpaper) {
147 super(getWallpaperDir(wallpaper.userId).getAbsolutePath(),
Christopher Tateda058e22014-10-08 14:51:09 -0700148 CLOSE_WRITE | MOVED_TO | DELETE | DELETE_SELF);
Christopher Tatebe132e62016-02-10 12:59:49 -0800149 mUserId = wallpaper.userId;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800150 mWallpaperDir = getWallpaperDir(wallpaper.userId);
151 mWallpaper = wallpaper;
152 mWallpaperFile = new File(mWallpaperDir, WALLPAPER);
Christopher Tatebe132e62016-02-10 12:59:49 -0800153 mWallpaperLockFile = new File(mWallpaperDir, WALLPAPER_LOCK_ORIG);
Amith Yamasani52d750c2014-12-10 14:09:05 -0800154 mWallpaperInfoFile = new File(mWallpaperDir, WALLPAPER_INFO);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800155 }
156
Christopher Tatebe132e62016-02-10 12:59:49 -0800157 private WallpaperData dataForEvent(boolean sysChanged, boolean lockChanged) {
158 WallpaperData wallpaper = null;
159 synchronized (mLock) {
160 if (lockChanged) {
161 wallpaper = mLockWallpaperMap.get(mUserId);
162 }
163 if (wallpaper == null) {
164 // no lock-specific wallpaper exists, or sys case, handled together
165 wallpaper = mWallpaperMap.get(mUserId);
166 }
167 }
168 return (wallpaper != null) ? wallpaper : mWallpaper;
169 }
170
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800171 @Override
172 public void onEvent(int event, String path) {
173 if (path == null) {
174 return;
175 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800176 final boolean written = (event == CLOSE_WRITE || event == MOVED_TO);
177 final File changedFile = new File(mWallpaperDir, path);
178
Christopher Tatebe132e62016-02-10 12:59:49 -0800179 // System and system+lock changes happen on the system wallpaper input file;
180 // lock-only changes happen on the dedicated lock wallpaper input file
181 final boolean sysWallpaperChanged = (mWallpaperFile.equals(changedFile));
182 final boolean lockWallpaperChanged = (mWallpaperLockFile.equals(changedFile));
183 WallpaperData wallpaper = dataForEvent(sysWallpaperChanged, lockWallpaperChanged);
184
185 if (DEBUG) {
186 Slog.v(TAG, "Wallpaper file change: evt=" + event
187 + " path=" + path
188 + " sys=" + sysWallpaperChanged
189 + " lock=" + lockWallpaperChanged
190 + " imagePending=" + wallpaper.imageWallpaperPending
191 + " whichPending=0x" + Integer.toHexString(wallpaper.whichPending)
192 + " written=" + written);
193 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800194 synchronized (mLock) {
Christopher Tatebe132e62016-02-10 12:59:49 -0800195 if (sysWallpaperChanged || mWallpaperInfoFile.equals(changedFile)) {
Amith Yamasani52d750c2014-12-10 14:09:05 -0800196 // changing the wallpaper means we'll need to back up the new one
197 long origId = Binder.clearCallingIdentity();
198 BackupManager bm = new BackupManager(mContext);
199 bm.dataChanged();
200 Binder.restoreCallingIdentity(origId);
201 }
Christopher Tatebe132e62016-02-10 12:59:49 -0800202 if (sysWallpaperChanged || lockWallpaperChanged) {
203 notifyCallbacksLocked(wallpaper);
204 if (wallpaper.wallpaperComponent == null
Christopher Tateda058e22014-10-08 14:51:09 -0700205 || event != CLOSE_WRITE // includes the MOVED_TO case
Christopher Tatebe132e62016-02-10 12:59:49 -0800206 || wallpaper.imageWallpaperPending) {
Christopher Tateda058e22014-10-08 14:51:09 -0700207 if (written) {
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800208 // The image source has finished writing the source image,
209 // so we now produce the crop rect (in the background), and
210 // only publish the new displayable (sub)image as a result
211 // of that work.
Christopher Tatebe132e62016-02-10 12:59:49 -0800212 if (DEBUG) {
213 Slog.v(TAG, "Wallpaper written; generating crop");
214 }
215 generateCrop(wallpaper);
216 if (DEBUG) {
217 Slog.v(TAG, "Crop done; invoking completion callback");
218 }
219 wallpaper.imageWallpaperPending = false;
220 if (wallpaper.setComplete != null) {
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800221 try {
Christopher Tatebe132e62016-02-10 12:59:49 -0800222 wallpaper.setComplete.onWallpaperChanged();
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800223 } catch (RemoteException e) {
224 // if this fails we don't really care; the setting app may just
225 // have crashed and that sort of thing is a fact of life.
226 }
227 }
Christopher Tatebe132e62016-02-10 12:59:49 -0800228 if (sysWallpaperChanged) {
229 // If this was the system wallpaper, rebind...
230 bindWallpaperComponentLocked(mImageWallpaper, true,
231 false, wallpaper, null);
232 }
233 if (lockWallpaperChanged
234 || (wallpaper.whichPending & FLAG_SET_LOCK) != 0) {
Christopher Tatebe132e62016-02-10 12:59:49 -0800235 if (DEBUG) {
Christopher Tatedb27b842016-02-25 14:39:17 -0800236 Slog.i(TAG, "Lock-relevant wallpaper changed");
Christopher Tatebe132e62016-02-10 12:59:49 -0800237 }
Christopher Tatedb27b842016-02-25 14:39:17 -0800238 // either a lock-only wallpaper commit or a system+lock event.
239 // if it's system-plus-lock we need to wipe the lock bookkeeping;
240 // we're falling back to displaying the system wallpaper there.
241 if (!lockWallpaperChanged) {
242 mLockWallpaperMap.remove(wallpaper.userId);
243 }
244 // and in any case, tell keyguard about it
Christopher Tatebe132e62016-02-10 12:59:49 -0800245 final IWallpaperManagerCallback cb = mKeyguardListener;
246 if (cb != null) {
247 try {
248 cb.onWallpaperChanged();
249 } catch (RemoteException e) {
250 // Oh well it went away; no big deal
251 }
252 }
253 }
Christopher Tatedb27b842016-02-25 14:39:17 -0800254 saveSettingsLocked(wallpaper.userId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700255 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800256 }
257 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800258 }
259 }
260 }
261
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800262 /**
263 * Once a new wallpaper has been written via setWallpaper(...), it needs to be cropped
264 * for display.
265 */
266 private void generateCrop(WallpaperData wallpaper) {
267 boolean success = false;
268 boolean needCrop = false;
Christopher Tatebe132e62016-02-10 12:59:49 -0800269 boolean needScale = false;
270
271 if (DEBUG) {
272 Slog.v(TAG, "Generating crop for new wallpaper(s): 0x"
273 + Integer.toHexString(wallpaper.whichPending)
274 + " to " + wallpaper.cropFile.getName());
275 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800276
277 // Analyse the source; needed in multiple cases
278 BitmapFactory.Options options = new BitmapFactory.Options();
279 options.inJustDecodeBounds = true;
280 BitmapFactory.decodeFile(wallpaper.wallpaperFile.getAbsolutePath(), options);
281
Christopher Tatebe132e62016-02-10 12:59:49 -0800282 // We'll need to scale if the crop is sufficiently bigger than the display
283
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800284 // Legacy case uses an empty crop rect here, so we just preserve the
285 // source image verbatim
286 if (!wallpaper.cropHint.isEmpty()) {
287 // ...clamp the crop rect to the measured bounds...
288 wallpaper.cropHint.right = Math.min(wallpaper.cropHint.right, options.outWidth);
289 wallpaper.cropHint.bottom = Math.min(wallpaper.cropHint.bottom, options.outHeight);
290 // ...and don't bother cropping if what we're left with is identity
291 needCrop = (options.outHeight >= wallpaper.cropHint.height()
292 && options.outWidth >= wallpaper.cropHint.width());
293 }
294
Christopher Tatebe132e62016-02-10 12:59:49 -0800295 if (!needCrop && !needScale) {
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800296 // Simple case: the nominal crop is at least as big as the source image,
297 // so we take the whole thing and just copy the image file directly.
298 if (DEBUG) {
299 Slog.v(TAG, "Null crop of new wallpaper; copying");
300 }
301 success = FileUtils.copyFile(wallpaper.wallpaperFile, wallpaper.cropFile);
302 if (!success) {
303 wallpaper.cropFile.delete();
304 // TODO: fall back to default wallpaper in this case
305 }
306 } else {
Christopher Tatebe132e62016-02-10 12:59:49 -0800307 // Fancy case: crop and/or scale
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800308 FileOutputStream f = null;
309 BufferedOutputStream bos = null;
310 try {
311 BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(
312 wallpaper.wallpaperFile.getAbsolutePath(), false);
313 Bitmap cropped = decoder.decodeRegion(wallpaper.cropHint, null);
314 decoder.recycle();
315
316 if (cropped == null) {
317 Slog.e(TAG, "Could not decode new wallpaper");
318 } else {
319 f = new FileOutputStream(wallpaper.cropFile);
320 bos = new BufferedOutputStream(f, 32*1024);
321 cropped.compress(Bitmap.CompressFormat.PNG, 90, bos);
322 bos.flush(); // don't rely on the implicit flush-at-close when noting success
323 success = true;
324 }
325 } catch (IOException e) {
326 if (DEBUG) {
327 Slog.e(TAG, "I/O error decoding crop: " + e.getMessage());
328 }
329 } finally {
330 IoUtils.closeQuietly(bos);
331 IoUtils.closeQuietly(f);
332 }
333 }
334
335 if (!success) {
336 Slog.e(TAG, "Unable to apply new wallpaper");
337 wallpaper.cropFile.delete();
338 }
339
340 if (wallpaper.cropFile.exists()) {
341 boolean didRestorecon = SELinux.restorecon(wallpaper.cropFile.getAbsoluteFile());
342 if (DEBUG) {
343 Slog.v(TAG, "restorecon() of crop file returned " + didRestorecon);
344 }
345 }
346 }
347
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700348 final Context mContext;
349 final IWindowManager mIWindowManager;
Amith Yamasani4e2820c2012-08-28 22:17:23 -0700350 final IPackageManager mIPackageManager;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800351 final MyPackageMonitor mMonitor;
Benjamin Franzf3ece362015-02-11 10:51:10 +0000352 final AppOpsManager mAppOpsManager;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800353 WallpaperData mLastWallpaper;
Christopher Tatebe132e62016-02-10 12:59:49 -0800354 IWallpaperManagerCallback mKeyguardListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800355
Justin Koh29c30162014-09-05 17:10:10 -0700356 /**
Christopher Tatead3c2592016-01-20 18:13:17 -0800357 * ID of the current wallpaper, changed every time anything sets a wallpaper.
358 * This is used for external detection of wallpaper update activity.
359 */
360 int mWallpaperId;
361
362 /**
Justin Koh29c30162014-09-05 17:10:10 -0700363 * Name of the component used to display bitmap wallpapers from either the gallery or
364 * built-in wallpapers.
365 */
366 final ComponentName mImageWallpaper;
367
Christopher Tatebe132e62016-02-10 12:59:49 -0800368 final SparseArray<WallpaperData> mWallpaperMap = new SparseArray<WallpaperData>();
369 final SparseArray<WallpaperData> mLockWallpaperMap = new SparseArray<WallpaperData>();
Dianne Hackborn07213e62011-08-24 20:05:39 -0700370
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800371 int mCurrentUserId;
Dianne Hackborn07213e62011-08-24 20:05:39 -0700372
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800373 static class WallpaperData {
374
375 int userId;
376
Christopher Tatebe132e62016-02-10 12:59:49 -0800377 final File wallpaperFile; // source image
378 final File cropFile; // eventual destination
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800379
380 /**
Christopher Tatebe132e62016-02-10 12:59:49 -0800381 * True while the client is writing a new wallpaper
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800382 */
383 boolean imageWallpaperPending;
384
385 /**
Christopher Tatebe132e62016-02-10 12:59:49 -0800386 * Which new wallpapers are being written; mirrors the 'which'
387 * selector bit field to setWallpaper().
388 */
389 int whichPending;
390
391 /**
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800392 * Callback once the set + crop is finished
393 */
394 IWallpaperManagerCallback setComplete;
395
396 /**
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800397 * Resource name if using a picture from the wallpaper gallery
398 */
399 String name = "";
400
401 /**
402 * The component name of the currently set live wallpaper.
403 */
404 ComponentName wallpaperComponent;
405
406 /**
407 * The component name of the wallpaper that should be set next.
408 */
409 ComponentName nextWallpaperComponent;
410
Christopher Tatead3c2592016-01-20 18:13:17 -0800411 /**
412 * The ID of this wallpaper
413 */
414 int wallpaperId;
415
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800416 WallpaperConnection connection;
417 long lastDiedTime;
418 boolean wallpaperUpdating;
419 WallpaperObserver wallpaperObserver;
420
421 /**
422 * List of callbacks registered they should each be notified when the wallpaper is changed.
423 */
424 private RemoteCallbackList<IWallpaperManagerCallback> callbacks
425 = new RemoteCallbackList<IWallpaperManagerCallback>();
426
427 int width = -1;
428 int height = -1;
429
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800430 /**
431 * The crop hint supplied for displaying a subset of the source image
432 */
433 final Rect cropHint = new Rect(0, 0, 0, 0);
434
Dianne Hackborn067e5f62014-09-07 23:14:30 -0700435 final Rect padding = new Rect(0, 0, 0, 0);
436
Christopher Tatebe132e62016-02-10 12:59:49 -0800437 WallpaperData(int userId, String inputFileName, String cropFileName) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800438 this.userId = userId;
Christopher Tatebe132e62016-02-10 12:59:49 -0800439 final File wallpaperDir = getWallpaperDir(userId);
440 wallpaperFile = new File(wallpaperDir, inputFileName);
441 cropFile = new File(wallpaperDir, cropFileName);
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800442 }
443
Christopher Tatebe132e62016-02-10 12:59:49 -0800444 // Called during initialization of a given user's wallpaper bookkeeping
Christopher Tate41297ff2016-03-10 16:46:15 -0800445 boolean cropExists() {
446 return cropFile.exists();
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800447 }
448 }
449
Christopher Tatead3c2592016-01-20 18:13:17 -0800450 int makeWallpaperIdLocked() {
451 do {
452 ++mWallpaperId;
453 } while (mWallpaperId == 0);
454 return mWallpaperId;
455 }
456
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700457 class WallpaperConnection extends IWallpaperConnection.Stub
458 implements ServiceConnection {
Dianne Hackborneb034652009-09-07 00:49:58 -0700459 final WallpaperInfo mInfo;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700460 final Binder mToken = new Binder();
461 IWallpaperService mService;
462 IWallpaperEngine mEngine;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800463 WallpaperData mWallpaper;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700464 IRemoteCallback mReply;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800465
Michael Wright5203a8b2013-10-03 14:16:42 -0700466 boolean mDimensionsChanged = false;
Dianne Hackborn067e5f62014-09-07 23:14:30 -0700467 boolean mPaddingChanged = false;
Michael Wright5203a8b2013-10-03 14:16:42 -0700468
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800469 public WallpaperConnection(WallpaperInfo info, WallpaperData wallpaper) {
Dianne Hackborneb034652009-09-07 00:49:58 -0700470 mInfo = info;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800471 mWallpaper = wallpaper;
Dianne Hackborneb034652009-09-07 00:49:58 -0700472 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700473
474 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700475 public void onServiceConnected(ComponentName name, IBinder service) {
476 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800477 if (mWallpaper.connection == this) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700478 mService = IWallpaperService.Stub.asInterface(service);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800479 attachServiceLocked(this, mWallpaper);
Dianne Hackborneb034652009-09-07 00:49:58 -0700480 // XXX should probably do saveSettingsLocked() later
481 // when we have an engine, but I'm not sure about
482 // locking there and anyway we always need to be able to
483 // recover if there is something wrong.
Christopher Tatedb27b842016-02-25 14:39:17 -0800484 saveSettingsLocked(mWallpaper.userId);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700485 }
486 }
487 }
488
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700489 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700490 public void onServiceDisconnected(ComponentName name) {
491 synchronized (mLock) {
492 mService = null;
493 mEngine = null;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800494 if (mWallpaper.connection == this) {
495 Slog.w(TAG, "Wallpaper service gone: " + mWallpaper.wallpaperComponent);
496 if (!mWallpaper.wallpaperUpdating
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800497 && mWallpaper.userId == mCurrentUserId) {
Selim Cinekebebadb2014-03-05 22:17:26 +0100498 // There is a race condition which causes
499 // {@link #mWallpaper.wallpaperUpdating} to be false even if it is
500 // currently updating since the broadcast notifying us is async.
501 // This race is overcome by the general rule that we only reset the
502 // wallpaper if its service was shut down twice
503 // during {@link #MIN_WALLPAPER_CRASH_TIME} millis.
504 if (mWallpaper.lastDiedTime != 0
505 && mWallpaper.lastDiedTime + MIN_WALLPAPER_CRASH_TIME
506 > SystemClock.uptimeMillis()) {
507 Slog.w(TAG, "Reverting to built-in wallpaper!");
Christopher Tatebe132e62016-02-10 12:59:49 -0800508 clearWallpaperLocked(true, FLAG_SET_SYSTEM, mWallpaper.userId, null);
Selim Cinekebebadb2014-03-05 22:17:26 +0100509 } else {
510 mWallpaper.lastDiedTime = SystemClock.uptimeMillis();
511 }
Filip Gruszczynski5a589432014-10-14 12:06:06 -0700512 final String flattened = name.flattenToString();
Filip Gruszczynski5dcc3ac2014-10-13 15:51:39 -0700513 EventLog.writeEvent(EventLogTags.WP_WALLPAPER_CRASHED,
Filip Gruszczynski5a589432014-10-14 12:06:06 -0700514 flattened.substring(0, Math.min(flattened.length(),
515 MAX_WALLPAPER_COMPONENT_LOG_LENGTH)));
Dianne Hackborn0cd48872009-08-13 18:51:59 -0700516 }
517 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700518 }
519 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800520
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700521 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700522 public void attachEngine(IWallpaperEngine engine) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700523 synchronized (mLock) {
524 mEngine = engine;
Michael Wright5203a8b2013-10-03 14:16:42 -0700525 if (mDimensionsChanged) {
526 try {
527 mEngine.setDesiredSize(mWallpaper.width, mWallpaper.height);
528 } catch (RemoteException e) {
529 Slog.w(TAG, "Failed to set wallpaper dimensions", e);
530 }
531 mDimensionsChanged = false;
532 }
Dianne Hackborn067e5f62014-09-07 23:14:30 -0700533 if (mPaddingChanged) {
534 try {
535 mEngine.setDisplayPadding(mWallpaper.padding);
536 } catch (RemoteException e) {
537 Slog.w(TAG, "Failed to set wallpaper padding", e);
538 }
539 mPaddingChanged = false;
540 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700541 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700542 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800543
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700544 @Override
545 public void engineShown(IWallpaperEngine engine) {
546 synchronized (mLock) {
547 if (mReply != null) {
548 long ident = Binder.clearCallingIdentity();
549 try {
550 mReply.sendResult(null);
551 } catch (RemoteException e) {
552 Binder.restoreCallingIdentity(ident);
553 }
554 mReply = null;
555 }
556 }
557 }
558
559 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700560 public ParcelFileDescriptor setWallpaper(String name) {
561 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800562 if (mWallpaper.connection == this) {
Christopher Tatead3c2592016-01-20 18:13:17 -0800563 return updateWallpaperBitmapLocked(name, mWallpaper, null);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700564 }
565 return null;
566 }
567 }
568 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800569
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800570 class MyPackageMonitor extends PackageMonitor {
571 @Override
572 public void onPackageUpdateFinished(String packageName, int uid) {
573 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700574 if (mCurrentUserId != getChangingUserId()) {
575 return;
576 }
577 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
578 if (wallpaper != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800579 if (wallpaper.wallpaperComponent != null
580 && wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
581 wallpaper.wallpaperUpdating = false;
582 ComponentName comp = wallpaper.wallpaperComponent;
583 clearWallpaperComponentLocked(wallpaper);
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700584 if (!bindWallpaperComponentLocked(comp, false, false,
585 wallpaper, null)) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800586 Slog.w(TAG, "Wallpaper no longer available; reverting to default");
Christopher Tatebe132e62016-02-10 12:59:49 -0800587 clearWallpaperLocked(false, FLAG_SET_SYSTEM, wallpaper.userId, null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800588 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700589 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800590 }
591 }
592 }
593
594 @Override
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700595 public void onPackageModified(String packageName) {
596 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700597 if (mCurrentUserId != getChangingUserId()) {
598 return;
599 }
600 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
601 if (wallpaper != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800602 if (wallpaper.wallpaperComponent == null
603 || !wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700604 return;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800605 }
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700606 doPackagesChangedLocked(true, wallpaper);
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700607 }
608 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700609 }
610
611 @Override
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800612 public void onPackageUpdateStarted(String packageName, int uid) {
613 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700614 if (mCurrentUserId != getChangingUserId()) {
615 return;
616 }
617 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
618 if (wallpaper != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800619 if (wallpaper.wallpaperComponent != null
620 && wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
621 wallpaper.wallpaperUpdating = true;
622 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800623 }
624 }
625 }
626
627 @Override
628 public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700629 synchronized (mLock) {
630 boolean changed = false;
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700631 if (mCurrentUserId != getChangingUserId()) {
632 return false;
633 }
634 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
635 if (wallpaper != null) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700636 boolean res = doPackagesChangedLocked(doit, wallpaper);
637 changed |= res;
638 }
639 return changed;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800640 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800641 }
642
643 @Override
644 public void onSomePackagesChanged() {
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700645 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700646 if (mCurrentUserId != getChangingUserId()) {
647 return;
648 }
649 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
650 if (wallpaper != null) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700651 doPackagesChangedLocked(true, wallpaper);
652 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800653 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800654 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800655
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700656 boolean doPackagesChangedLocked(boolean doit, WallpaperData wallpaper) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800657 boolean changed = false;
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700658 if (wallpaper.wallpaperComponent != null) {
659 int change = isPackageDisappearing(wallpaper.wallpaperComponent
660 .getPackageName());
661 if (change == PACKAGE_PERMANENT_CHANGE
662 || change == PACKAGE_TEMPORARY_CHANGE) {
663 changed = true;
664 if (doit) {
665 Slog.w(TAG, "Wallpaper uninstalled, removing: "
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800666 + wallpaper.wallpaperComponent);
Christopher Tatebe132e62016-02-10 12:59:49 -0800667 clearWallpaperLocked(false, FLAG_SET_SYSTEM, wallpaper.userId, null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800668 }
669 }
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700670 }
671 if (wallpaper.nextWallpaperComponent != null) {
672 int change = isPackageDisappearing(wallpaper.nextWallpaperComponent
673 .getPackageName());
674 if (change == PACKAGE_PERMANENT_CHANGE
675 || change == PACKAGE_TEMPORARY_CHANGE) {
676 wallpaper.nextWallpaperComponent = null;
677 }
678 }
679 if (wallpaper.wallpaperComponent != null
680 && isPackageModified(wallpaper.wallpaperComponent.getPackageName())) {
681 try {
682 mContext.getPackageManager().getServiceInfo(
683 wallpaper.wallpaperComponent, 0);
684 } catch (NameNotFoundException e) {
685 Slog.w(TAG, "Wallpaper component gone, removing: "
686 + wallpaper.wallpaperComponent);
Christopher Tatebe132e62016-02-10 12:59:49 -0800687 clearWallpaperLocked(false, FLAG_SET_SYSTEM, wallpaper.userId, null);
Dianne Hackbornd0d75032012-04-19 23:12:09 -0700688 }
689 }
690 if (wallpaper.nextWallpaperComponent != null
691 && isPackageModified(wallpaper.nextWallpaperComponent.getPackageName())) {
692 try {
693 mContext.getPackageManager().getServiceInfo(
694 wallpaper.nextWallpaperComponent, 0);
695 } catch (NameNotFoundException e) {
696 wallpaper.nextWallpaperComponent = null;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800697 }
698 }
699 return changed;
700 }
701 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +0100702
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700703 public WallpaperManagerService(Context context) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800704 if (DEBUG) Slog.v(TAG, "WallpaperService startup");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800705 mContext = context;
Justin Koh29c30162014-09-05 17:10:10 -0700706 mImageWallpaper = ComponentName.unflattenFromString(
707 context.getResources().getString(R.string.image_wallpaper_component));
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700708 mIWindowManager = IWindowManager.Stub.asInterface(
709 ServiceManager.getService(Context.WINDOW_SERVICE));
Amith Yamasani4e2820c2012-08-28 22:17:23 -0700710 mIPackageManager = AppGlobals.getPackageManager();
Benjamin Franzf3ece362015-02-11 10:51:10 +0000711 mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800712 mMonitor = new MyPackageMonitor();
Dianne Hackbornc72fc672012-09-20 13:12:03 -0700713 mMonitor.register(context, null, UserHandle.ALL, true);
Xiaohui Chen233d94c2015-07-30 15:08:00 -0700714 getWallpaperDir(UserHandle.USER_SYSTEM).mkdirs();
715 loadSettingsLocked(UserHandle.USER_SYSTEM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800716 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +0100717
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800718 private static File getWallpaperDir(int userId) {
Amith Yamasani61f57372012-08-31 12:12:28 -0700719 return Environment.getUserSystemDirectory(userId);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800720 }
721
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800722 @Override
723 protected void finalize() throws Throwable {
724 super.finalize();
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800725 for (int i = 0; i < mWallpaperMap.size(); i++) {
726 WallpaperData wallpaper = mWallpaperMap.valueAt(i);
727 wallpaper.wallpaperObserver.stopWatching();
728 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800729 }
Amith Yamasani13593602012-03-22 16:16:17 -0700730
Svetoslav Ganova0027152013-06-25 14:59:53 -0700731 public void systemRunning() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800732 if (DEBUG) Slog.v(TAG, "systemReady");
Xiaohui Chen233d94c2015-07-30 15:08:00 -0700733 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.USER_SYSTEM);
Christopher Tate2cdd3f22016-03-14 17:36:16 -0700734 // If we think we're going to be using the system image wallpaper imagery, make
735 // sure we have something to render
736 if (mImageWallpaper.equals(wallpaper.nextWallpaperComponent)) {
737 // No crop file? Make sure we've finished the processing sequence if necessary
738 if (!wallpaper.cropExists()) {
739 if (DEBUG) {
740 Slog.i(TAG, "No crop; regenerating from source");
741 }
742 generateCrop(wallpaper);
743 }
744 // Still nothing? Fall back to default.
745 if (!wallpaper.cropExists()) {
746 if (DEBUG) {
747 Slog.i(TAG, "Unable to regenerate crop; resetting");
748 }
749 clearWallpaperLocked(false, FLAG_SET_SYSTEM, UserHandle.USER_SYSTEM, null);
750 }
751 } else {
752 if (DEBUG) {
753 Slog.i(TAG, "Nondefault wallpaper component; gracefully ignoring");
754 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800755 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700756 switchWallpaper(wallpaper, null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800757 wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper);
758 wallpaper.wallpaperObserver.startWatching();
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800759
Amith Yamasani13593602012-03-22 16:16:17 -0700760 IntentFilter userFilter = new IntentFilter();
Amith Yamasani13593602012-03-22 16:16:17 -0700761 userFilter.addAction(Intent.ACTION_USER_REMOVED);
Amith Yamasani756901d2012-10-12 12:30:07 -0700762 userFilter.addAction(Intent.ACTION_USER_STOPPING);
Amith Yamasani13593602012-03-22 16:16:17 -0700763 mContext.registerReceiver(new BroadcastReceiver() {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800764 @Override
Amith Yamasani13593602012-03-22 16:16:17 -0700765 public void onReceive(Context context, Intent intent) {
766 String action = intent.getAction();
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700767 if (Intent.ACTION_USER_REMOVED.equals(action)) {
Amith Yamasani756901d2012-10-12 12:30:07 -0700768 onRemoveUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
769 UserHandle.USER_NULL));
Amith Yamasani13593602012-03-22 16:16:17 -0700770 }
Amith Yamasani0c293712012-10-30 12:23:52 -0700771 // TODO: Race condition causing problems when cleaning up on stopping a user.
772 // Comment this out for now.
773 // else if (Intent.ACTION_USER_STOPPING.equals(action)) {
774 // onStoppingUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
775 // UserHandle.USER_NULL));
776 // }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800777 }
Amith Yamasani13593602012-03-22 16:16:17 -0700778 }, userFilter);
Amith Yamasani756901d2012-10-12 12:30:07 -0700779
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700780 try {
781 ActivityManagerNative.getDefault().registerUserSwitchObserver(
782 new IUserSwitchObserver.Stub() {
783 @Override
784 public void onUserSwitching(int newUserId, IRemoteCallback reply) {
785 switchUser(newUserId, reply);
786 }
787
788 @Override
789 public void onUserSwitchComplete(int newUserId) throws RemoteException {
790 }
Kenny Guy42979622015-04-13 18:03:05 +0000791
792 @Override
793 public void onForegroundProfileSwitch(int newProfileId) {
794 // Ignore.
795 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700796 });
797 } catch (RemoteException e) {
798 // TODO Auto-generated catch block
799 e.printStackTrace();
800 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800801 }
802
Amith Yamasani09e9cdc2013-11-06 14:54:50 -0800803 /** Called by SystemBackupAgent */
804 public String getName() {
805 // Verify caller is the system
806 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
807 throw new RuntimeException("getName() can only be called from the system process");
808 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700809 synchronized (mLock) {
810 return mWallpaperMap.get(0).name;
811 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800812 }
813
Christopher Tatebe132e62016-02-10 12:59:49 -0800814 void stopObserver(WallpaperData wallpaper) {
815 if (wallpaper != null) {
816 if (wallpaper.wallpaperObserver != null) {
817 wallpaper.wallpaperObserver.stopWatching();
818 wallpaper.wallpaperObserver = null;
Amith Yamasani13593602012-03-22 16:16:17 -0700819 }
Amith Yamasani756901d2012-10-12 12:30:07 -0700820 }
821 }
822
Christopher Tatebe132e62016-02-10 12:59:49 -0800823 void stopObserversLocked(int userId) {
824 stopObserver(mWallpaperMap.get(userId));
825 stopObserver(mLockWallpaperMap.get(userId));
826 mWallpaperMap.remove(userId);
827 mLockWallpaperMap.remove(userId);
828 }
829
Amith Yamasani756901d2012-10-12 12:30:07 -0700830 void onRemoveUser(int userId) {
831 if (userId < 1) return;
Christopher Tatebe132e62016-02-10 12:59:49 -0800832
833 final File wallpaperDir = getWallpaperDir(userId);
Amith Yamasani756901d2012-10-12 12:30:07 -0700834 synchronized (mLock) {
Christopher Tatebe132e62016-02-10 12:59:49 -0800835 stopObserversLocked(userId);
836 for (String filename : sPerUserFiles) {
837 new File(wallpaperDir, filename).delete();
838 }
Amith Yamasani13593602012-03-22 16:16:17 -0700839 }
840 }
841
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700842 void switchUser(int userId, IRemoteCallback reply) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800843 synchronized (mLock) {
844 mCurrentUserId = userId;
Christopher Tatebe132e62016-02-10 12:59:49 -0800845 WallpaperData wallpaper = getWallpaperSafeLocked(userId, FLAG_SET_SYSTEM);
Amith Yamasani6474c4c2012-10-04 14:55:42 -0700846 // Not started watching yet, in case wallpaper data was loaded for other reasons.
847 if (wallpaper.wallpaperObserver == null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800848 wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper);
849 wallpaper.wallpaperObserver.startWatching();
850 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700851 switchWallpaper(wallpaper, reply);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800852 }
853 }
854
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700855 void switchWallpaper(WallpaperData wallpaper, IRemoteCallback reply) {
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700856 synchronized (mLock) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700857 RuntimeException e = null;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700858 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800859 ComponentName cname = wallpaper.wallpaperComponent != null ?
860 wallpaper.wallpaperComponent : wallpaper.nextWallpaperComponent;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700861 if (bindWallpaperComponentLocked(cname, true, false, wallpaper, reply)) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700862 return;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700863 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700864 } catch (RuntimeException e1) {
865 e = e1;
Dianne Hackbornf21adf62009-08-13 10:20:21 -0700866 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700867 Slog.w(TAG, "Failure starting previous wallpaper", e);
Christopher Tatebe132e62016-02-10 12:59:49 -0800868 clearWallpaperLocked(false, FLAG_SET_SYSTEM, wallpaper.userId, reply);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800869 }
870 }
871
Christopher Tatebe132e62016-02-10 12:59:49 -0800872 @Override
873 public void clearWallpaper(String callingPackage, int which, int userId) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800874 if (DEBUG) Slog.v(TAG, "clearWallpaper");
Benjamin Franzf3ece362015-02-11 10:51:10 +0000875 checkPermission(android.Manifest.permission.SET_WALLPAPER);
Oleksandr Peletskyif2519812016-01-26 20:16:06 +0100876 if (!isWallpaperSupported(callingPackage) || !isWallpaperSettingAllowed(callingPackage)) {
Benjamin Franzf3ece362015-02-11 10:51:10 +0000877 return;
878 }
Christopher Tatee409f0e2016-03-21 14:53:15 -0700879 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
880 Binder.getCallingUid(), userId, false, true, "clearWallpaper", null);
Christopher Tatebe132e62016-02-10 12:59:49 -0800881
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800882 synchronized (mLock) {
Christopher Tatebe132e62016-02-10 12:59:49 -0800883 clearWallpaperLocked(false, which, userId, null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800884 }
885 }
886
Christopher Tatebe132e62016-02-10 12:59:49 -0800887 void clearWallpaperLocked(boolean defaultFailed, int which, int userId, IRemoteCallback reply) {
888 if (which != FLAG_SET_SYSTEM && which != FLAG_SET_LOCK) {
889 throw new IllegalArgumentException("Must specify exactly one kind of wallpaper to read");
890 }
891
892 WallpaperData wallpaper = null;
893 if (which == FLAG_SET_LOCK) {
894 wallpaper = mLockWallpaperMap.get(userId);
895 if (wallpaper == null) {
896 // It's already gone; we're done.
Christopher Tate79a24572016-03-02 14:42:44 -0800897 if (DEBUG) {
898 Slog.i(TAG, "Lock wallpaper already cleared");
899 }
Christopher Tatebe132e62016-02-10 12:59:49 -0800900 return;
901 }
902 } else {
903 wallpaper = mWallpaperMap.get(userId);
904 if (wallpaper == null) {
905 // Might need to bring it in the first time to establish our rewrite
906 loadSettingsLocked(userId);
907 wallpaper = mWallpaperMap.get(userId);
908 }
909 }
Benjamin Franzf3ece362015-02-11 10:51:10 +0000910 if (wallpaper == null) {
911 return;
912 }
Christopher Tatebe132e62016-02-10 12:59:49 -0800913
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800914 final long ident = Binder.clearCallingIdentity();
915 try {
Christopher Tatebe132e62016-02-10 12:59:49 -0800916 if (wallpaper.wallpaperFile.exists()) {
917 wallpaper.wallpaperFile.delete();
918 wallpaper.cropFile.delete();
919 if (which == FLAG_SET_LOCK) {
Christopher Tate79a24572016-03-02 14:42:44 -0800920 mLockWallpaperMap.remove(userId);
Christopher Tatebe132e62016-02-10 12:59:49 -0800921 final IWallpaperManagerCallback cb = mKeyguardListener;
922 if (cb != null) {
Christopher Tate79a24572016-03-02 14:42:44 -0800923 if (DEBUG) {
924 Slog.i(TAG, "Notifying keyguard of lock wallpaper clear");
925 }
Christopher Tatebe132e62016-02-10 12:59:49 -0800926 try {
927 cb.onWallpaperChanged();
928 } catch (RemoteException e) {
929 // Oh well it went away; no big deal
930 }
931 }
Christopher Tate79a24572016-03-02 14:42:44 -0800932 saveSettingsLocked(userId);
Christopher Tatebe132e62016-02-10 12:59:49 -0800933 return;
934 }
935 }
936
Christopher Tateecd827a2014-09-05 17:42:34 -0700937 RuntimeException e = null;
938 try {
939 wallpaper.imageWallpaperPending = false;
940 if (userId != mCurrentUserId) return;
941 if (bindWallpaperComponentLocked(defaultFailed
942 ? mImageWallpaper
943 : null, true, false, wallpaper, reply)) {
944 return;
945 }
946 } catch (IllegalArgumentException e1) {
947 e = e1;
Dianne Hackborn80b902f2011-09-15 15:15:27 -0700948 }
Christopher Tateecd827a2014-09-05 17:42:34 -0700949
950 // This can happen if the default wallpaper component doesn't
951 // exist. This should be a system configuration problem, but
952 // let's not let it crash the system and just live with no
953 // wallpaper.
954 Slog.e(TAG, "Default wallpaper component not found!", e);
955 clearWallpaperComponentLocked(wallpaper);
956 if (reply != null) {
957 try {
958 reply.sendResult(null);
959 } catch (RemoteException e1) {
960 }
961 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800962 } finally {
963 Binder.restoreCallingIdentity(ident);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800964 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700965 }
966
967 public boolean hasNamedWallpaper(String name) {
968 synchronized (mLock) {
Amith Yamasani6474c4c2012-10-04 14:55:42 -0700969 List<UserInfo> users;
970 long ident = Binder.clearCallingIdentity();
971 try {
972 users = ((UserManager) mContext.getSystemService(Context.USER_SERVICE)).getUsers();
973 } finally {
974 Binder.restoreCallingIdentity(ident);
975 }
976 for (UserInfo user: users) {
Benjamin Franzf3ece362015-02-11 10:51:10 +0000977 // ignore managed profiles
978 if (user.isManagedProfile()) {
979 continue;
980 }
Amith Yamasani6474c4c2012-10-04 14:55:42 -0700981 WallpaperData wd = mWallpaperMap.get(user.id);
982 if (wd == null) {
983 // User hasn't started yet, so load her settings to peek at the wallpaper
984 loadSettingsLocked(user.id);
985 wd = mWallpaperMap.get(user.id);
986 }
987 if (wd != null && name.equals(wd.name)) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700988 return true;
989 }
990 }
991 }
992 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800993 }
994
John Spurlock41f64642013-11-04 13:48:38 -0500995 private Point getDefaultDisplaySize() {
996 Point p = new Point();
John Spurlockd6e836c2013-11-18 14:14:49 -0500997 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
998 Display d = wm.getDefaultDisplay();
999 d.getRealSize(p);
John Spurlock41f64642013-11-04 13:48:38 -05001000 return p;
1001 }
1002
Benjamin Franzf3ece362015-02-11 10:51:10 +00001003 public void setDimensionHints(int width, int height, String callingPackage)
1004 throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001005 checkPermission(android.Manifest.permission.SET_WALLPAPER_HINTS);
Benjamin Franzf3ece362015-02-11 10:51:10 +00001006 if (!isWallpaperSupported(callingPackage)) {
1007 return;
1008 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001009 synchronized (mLock) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001010 int userId = UserHandle.getCallingUserId();
Christopher Tatebe132e62016-02-10 12:59:49 -08001011 WallpaperData wallpaper = getWallpaperSafeLocked(userId, FLAG_SET_SYSTEM);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001012 if (width <= 0 || height <= 0) {
1013 throw new IllegalArgumentException("width and height must be > 0");
1014 }
John Spurlock41f64642013-11-04 13:48:38 -05001015 // Make sure it is at least as large as the display.
1016 Point displaySize = getDefaultDisplaySize();
1017 width = Math.max(width, displaySize.x);
1018 height = Math.max(height, displaySize.y);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001019
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001020 if (width != wallpaper.width || height != wallpaper.height) {
1021 wallpaper.width = width;
1022 wallpaper.height = height;
Christopher Tatedb27b842016-02-25 14:39:17 -08001023 saveSettingsLocked(userId);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001024 if (mCurrentUserId != userId) return; // Don't change the properties now
1025 if (wallpaper.connection != null) {
1026 if (wallpaper.connection.mEngine != null) {
Dianne Hackborn284ac932009-08-28 10:34:25 -07001027 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001028 wallpaper.connection.mEngine.setDesiredSize(
Dianne Hackborn284ac932009-08-28 10:34:25 -07001029 width, height);
1030 } catch (RemoteException e) {
1031 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001032 notifyCallbacksLocked(wallpaper);
Michael Wright5203a8b2013-10-03 14:16:42 -07001033 } else if (wallpaper.connection.mService != null) {
1034 // We've attached to the service but the engine hasn't attached back to us
1035 // yet. This means it will be created with the previous dimensions, so we
1036 // need to update it to the new dimensions once it attaches.
1037 wallpaper.connection.mDimensionsChanged = true;
Dianne Hackborn284ac932009-08-28 10:34:25 -07001038 }
1039 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001040 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001041 }
1042 }
1043
1044 public int getWidthHint() throws RemoteException {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001045 synchronized (mLock) {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07001046 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.getCallingUserId());
Benjamin Franzf3ece362015-02-11 10:51:10 +00001047 if (wallpaper != null) {
1048 return wallpaper.width;
1049 } else {
1050 return 0;
1051 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001052 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001053 }
1054
1055 public int getHeightHint() throws RemoteException {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001056 synchronized (mLock) {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07001057 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.getCallingUserId());
Benjamin Franzf3ece362015-02-11 10:51:10 +00001058 if (wallpaper != null) {
1059 return wallpaper.height;
1060 } else {
1061 return 0;
1062 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001063 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001064 }
1065
Benjamin Franzf3ece362015-02-11 10:51:10 +00001066 public void setDisplayPadding(Rect padding, String callingPackage) {
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001067 checkPermission(android.Manifest.permission.SET_WALLPAPER_HINTS);
Benjamin Franzf3ece362015-02-11 10:51:10 +00001068 if (!isWallpaperSupported(callingPackage)) {
1069 return;
1070 }
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001071 synchronized (mLock) {
1072 int userId = UserHandle.getCallingUserId();
Christopher Tatebe132e62016-02-10 12:59:49 -08001073 WallpaperData wallpaper = getWallpaperSafeLocked(userId, FLAG_SET_SYSTEM);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001074 if (padding.left < 0 || padding.top < 0 || padding.right < 0 || padding.bottom < 0) {
1075 throw new IllegalArgumentException("padding must be positive: " + padding);
1076 }
1077
1078 if (!padding.equals(wallpaper.padding)) {
1079 wallpaper.padding.set(padding);
Christopher Tatedb27b842016-02-25 14:39:17 -08001080 saveSettingsLocked(userId);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001081 if (mCurrentUserId != userId) return; // Don't change the properties now
1082 if (wallpaper.connection != null) {
1083 if (wallpaper.connection.mEngine != null) {
1084 try {
1085 wallpaper.connection.mEngine.setDisplayPadding(padding);
1086 } catch (RemoteException e) {
1087 }
1088 notifyCallbacksLocked(wallpaper);
1089 } else if (wallpaper.connection.mService != null) {
1090 // We've attached to the service but the engine hasn't attached back to us
1091 // yet. This means it will be created with the previous dimensions, so we
1092 // need to update it to the new dimensions once it attaches.
1093 wallpaper.connection.mPaddingChanged = true;
1094 }
1095 }
1096 }
1097 }
1098 }
1099
Yorke Leedcd93cc2016-01-08 14:12:55 -08001100 @Override
Christopher Tatebe132e62016-02-10 12:59:49 -08001101 public ParcelFileDescriptor getWallpaper(IWallpaperManagerCallback cb, final int which,
1102 Bundle outParams, int wallpaperUserId) {
Christopher Tatee409f0e2016-03-21 14:53:15 -07001103 wallpaperUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
1104 Binder.getCallingUid(), wallpaperUserId, false, true, "getWallpaper", null);
Christopher Tatebe132e62016-02-10 12:59:49 -08001105
1106 if (which != FLAG_SET_SYSTEM && which != FLAG_SET_LOCK) {
1107 throw new IllegalArgumentException("Must specify exactly one kind of wallpaper to read");
1108 }
1109
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001110 synchronized (mLock) {
Vadim Tryshev8cde0792016-02-19 17:02:15 -08001111 final SparseArray<WallpaperData> whichSet =
1112 (which == FLAG_SET_LOCK) ? mLockWallpaperMap : mWallpaperMap;
1113 WallpaperData wallpaper = whichSet.get(wallpaperUserId);
1114 if (wallpaper == null) {
1115 // common case, this is the first lookup post-boot of the system or
1116 // unified lock, so we bring up the saved state lazily now and recheck.
1117 loadSettingsLocked(wallpaperUserId);
1118 wallpaper = whichSet.get(wallpaperUserId);
Christopher Tatebe132e62016-02-10 12:59:49 -08001119 if (wallpaper == null) {
Christopher Tatebe132e62016-02-10 12:59:49 -08001120 return null;
1121 }
Benjamin Franzf3ece362015-02-11 10:51:10 +00001122 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001123 try {
Dianne Hackborn284ac932009-08-28 10:34:25 -07001124 if (outParams != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001125 outParams.putInt("width", wallpaper.width);
1126 outParams.putInt("height", wallpaper.height);
Dianne Hackborn284ac932009-08-28 10:34:25 -07001127 }
Christopher Tateea6724a2016-02-18 18:39:19 -08001128 if (cb != null) {
1129 wallpaper.callbacks.register(cb);
1130 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001131 if (!wallpaper.cropFile.exists()) {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001132 return null;
1133 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001134 return ParcelFileDescriptor.open(wallpaper.cropFile, MODE_READ_ONLY);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001135 } catch (FileNotFoundException e) {
1136 /* Shouldn't happen as we check to see if the file exists */
Joe Onorato8a9b2202010-02-26 18:56:32 -08001137 Slog.w(TAG, "Error getting wallpaper", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001138 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001139 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001140 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001141 }
1142
Christopher Tatee409f0e2016-03-21 14:53:15 -07001143 @Override
Dianne Hackborneb034652009-09-07 00:49:58 -07001144 public WallpaperInfo getWallpaperInfo() {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07001145 int userId = UserHandle.getCallingUserId();
Dianne Hackborneb034652009-09-07 00:49:58 -07001146 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001147 WallpaperData wallpaper = mWallpaperMap.get(userId);
Benjamin Franzf3ece362015-02-11 10:51:10 +00001148 if (wallpaper != null && wallpaper.connection != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001149 return wallpaper.connection.mInfo;
Dianne Hackborneb034652009-09-07 00:49:58 -07001150 }
1151 return null;
1152 }
1153 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001154
Christopher Tatead3c2592016-01-20 18:13:17 -08001155 @Override
Christopher Tatee409f0e2016-03-21 14:53:15 -07001156 public int getWallpaperIdForUser(int which, int userId) {
1157 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
1158 Binder.getCallingUid(), userId, false, true, "getWallpaperIdForUser", null);
1159
1160 if (which != FLAG_SET_SYSTEM && which != FLAG_SET_LOCK) {
1161 throw new IllegalArgumentException("Must specify exactly one kind of wallpaper");
1162 }
1163
1164 final SparseArray<WallpaperData> map =
1165 (which == FLAG_SET_LOCK) ? mLockWallpaperMap : mWallpaperMap;
1166 synchronized (mLock) {
1167 WallpaperData wallpaper = map.get(userId);
1168 if (wallpaper != null) {
1169 return wallpaper.wallpaperId;
1170 }
1171 }
1172 return -1;
1173 }
1174
1175 @Override
Christopher Tatebe132e62016-02-10 12:59:49 -08001176 public boolean setLockWallpaperCallback(IWallpaperManagerCallback cb) {
1177 checkPermission(android.Manifest.permission.INTERNAL_SYSTEM_WINDOW);
1178 synchronized (mLock) {
1179 mKeyguardListener = cb;
1180 }
1181 return true;
1182 }
1183
1184 @Override
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001185 public ParcelFileDescriptor setWallpaper(String name, String callingPackage,
1186 Rect cropHint, Bundle extras, int which, IWallpaperManagerCallback completion) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001187 checkPermission(android.Manifest.permission.SET_WALLPAPER);
Christopher Tatead3c2592016-01-20 18:13:17 -08001188
Christopher Tatebe132e62016-02-10 12:59:49 -08001189 if ((which & (FLAG_SET_LOCK|FLAG_SET_SYSTEM)) == 0) {
1190 Slog.e(TAG, "Must specify a valid wallpaper category to set");
Christopher Tatead3c2592016-01-20 18:13:17 -08001191 return null;
1192 }
1193
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001194 if (!isWallpaperSupported(callingPackage) || !isWallpaperSettingAllowed(callingPackage)) {
Benjamin Franzf3ece362015-02-11 10:51:10 +00001195 return null;
1196 }
Christopher Tatead3c2592016-01-20 18:13:17 -08001197
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001198 // "null" means the no-op crop, preserving the full input image
1199 if (cropHint == null) {
1200 cropHint = new Rect(0, 0, 0, 0);
1201 } else {
1202 if (cropHint.isEmpty()
1203 || cropHint.left < 0
1204 || cropHint.top < 0) {
1205 return null;
1206 }
1207 }
1208
Christopher Tatebe132e62016-02-10 12:59:49 -08001209 final int userId = UserHandle.getCallingUserId();
1210
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001211 synchronized (mLock) {
Christopher Tatebe132e62016-02-10 12:59:49 -08001212 if (DEBUG) Slog.v(TAG, "setWallpaper which=0x" + Integer.toHexString(which));
1213 WallpaperData wallpaper;
1214
1215 wallpaper = getWallpaperSafeLocked(userId, which);
Dianne Hackborn0cd48872009-08-13 18:51:59 -07001216 final long ident = Binder.clearCallingIdentity();
1217 try {
Christopher Tatead3c2592016-01-20 18:13:17 -08001218 ParcelFileDescriptor pfd = updateWallpaperBitmapLocked(name, wallpaper, extras);
Dianne Hackborn0cd48872009-08-13 18:51:59 -07001219 if (pfd != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001220 wallpaper.imageWallpaperPending = true;
Christopher Tatebe132e62016-02-10 12:59:49 -08001221 wallpaper.whichPending = which;
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001222 wallpaper.setComplete = completion;
1223 wallpaper.cropHint.set(cropHint);
Dianne Hackborn0cd48872009-08-13 18:51:59 -07001224 }
1225 return pfd;
1226 } finally {
1227 Binder.restoreCallingIdentity(ident);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001228 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001229 }
1230 }
1231
Christopher Tatead3c2592016-01-20 18:13:17 -08001232 ParcelFileDescriptor updateWallpaperBitmapLocked(String name, WallpaperData wallpaper,
1233 Bundle extras) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001234 if (name == null) name = "";
1235 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001236 File dir = getWallpaperDir(wallpaper.userId);
1237 if (!dir.exists()) {
1238 dir.mkdir();
Dianne Hackbornebac48c2011-11-29 18:01:50 -08001239 FileUtils.setPermissions(
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001240 dir.getPath(),
Dianne Hackbornebac48c2011-11-29 18:01:50 -08001241 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
1242 -1, -1);
1243 }
Christopher Tatebe132e62016-02-10 12:59:49 -08001244 ParcelFileDescriptor fd = ParcelFileDescriptor.open(wallpaper.wallpaperFile,
Christopher Tate90f86ba2014-09-11 12:37:19 -07001245 MODE_CREATE|MODE_READ_WRITE|MODE_TRUNCATE);
Christopher Tatebe132e62016-02-10 12:59:49 -08001246 if (!SELinux.restorecon(wallpaper.wallpaperFile)) {
rpcraig554cb0c2012-07-05 06:41:43 -04001247 return null;
1248 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001249 wallpaper.name = name;
Christopher Tatead3c2592016-01-20 18:13:17 -08001250 wallpaper.wallpaperId = makeWallpaperIdLocked();
1251 if (extras != null) {
1252 extras.putInt(WallpaperManager.EXTRA_NEW_WALLPAPER_ID, wallpaper.wallpaperId);
1253 }
1254 if (DEBUG) {
1255 Slog.v(TAG, "updateWallpaperBitmapLocked() : id=" + wallpaper.wallpaperId
Christopher Tatebe132e62016-02-10 12:59:49 -08001256 + " name=" + name + " file=" + wallpaper.wallpaperFile.getName());
Christopher Tatead3c2592016-01-20 18:13:17 -08001257 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001258 return fd;
1259 } catch (FileNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001260 Slog.w(TAG, "Error setting wallpaper", e);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001261 }
1262 return null;
1263 }
1264
Christopher Tated57d17c2016-03-25 13:41:46 -07001265 @Override
Benjamin Franzf3ece362015-02-11 10:51:10 +00001266 public void setWallpaperComponentChecked(ComponentName name, String callingPackage) {
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001267 if (isWallpaperSupported(callingPackage) && isWallpaperSettingAllowed(callingPackage)) {
Benjamin Franzf3ece362015-02-11 10:51:10 +00001268 setWallpaperComponent(name);
1269 }
1270 }
1271
1272 // ToDo: Remove this version of the function
Christopher Tated57d17c2016-03-25 13:41:46 -07001273 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001274 public void setWallpaperComponent(ComponentName name) {
1275 checkPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT);
1276 synchronized (mLock) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001277 if (DEBUG) Slog.v(TAG, "setWallpaperComponent name=" + name);
1278 int userId = UserHandle.getCallingUserId();
1279 WallpaperData wallpaper = mWallpaperMap.get(userId);
1280 if (wallpaper == null) {
1281 throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
1282 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001283 final long ident = Binder.clearCallingIdentity();
1284 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001285 wallpaper.imageWallpaperPending = false;
Christopher Tated57d17c2016-03-25 13:41:46 -07001286 if (bindWallpaperComponentLocked(name, false, true, wallpaper, null)) {
1287 wallpaper.wallpaperId = makeWallpaperIdLocked();
1288 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001289 } finally {
1290 Binder.restoreCallingIdentity(ident);
1291 }
1292 }
1293 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001294
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001295 boolean bindWallpaperComponentLocked(ComponentName componentName, boolean force,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001296 boolean fromUser, WallpaperData wallpaper, IRemoteCallback reply) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001297 if (DEBUG) Slog.v(TAG, "bindWallpaperComponentLocked: componentName=" + componentName);
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001298 // Has the component changed?
Dianne Hackborn9ea31632011-08-05 14:43:50 -07001299 if (!force) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001300 if (wallpaper.connection != null) {
1301 if (wallpaper.wallpaperComponent == null) {
Dianne Hackborn9ea31632011-08-05 14:43:50 -07001302 if (componentName == null) {
1303 if (DEBUG) Slog.v(TAG, "bindWallpaperComponentLocked: still using default");
1304 // Still using default wallpaper.
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001305 return true;
Dianne Hackborn9ea31632011-08-05 14:43:50 -07001306 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001307 } else if (wallpaper.wallpaperComponent.equals(componentName)) {
Dianne Hackborn9ea31632011-08-05 14:43:50 -07001308 // Changing to same wallpaper.
1309 if (DEBUG) Slog.v(TAG, "same wallpaper");
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001310 return true;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001311 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001312 }
1313 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001314
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001315 try {
Mike Clerona428b2c2009-11-15 22:53:08 -08001316 if (componentName == null) {
Jeff Sharkey28f08772014-04-16 09:41:58 -07001317 componentName = WallpaperManager.getDefaultWallpaperComponent(mContext);
Mike Clerona428b2c2009-11-15 22:53:08 -08001318 if (componentName == null) {
Mike Cleron322b6ee2009-11-12 07:45:47 -08001319 // Fall back to static image wallpaper
Justin Koh29c30162014-09-05 17:10:10 -07001320 componentName = mImageWallpaper;
Mike Cleron322b6ee2009-11-12 07:45:47 -08001321 //clearWallpaperComponentLocked();
1322 //return;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001323 if (DEBUG) Slog.v(TAG, "Using image wallpaper");
Mike Cleron322b6ee2009-11-12 07:45:47 -08001324 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001325 }
Amith Yamasani4e2820c2012-08-28 22:17:23 -07001326 int serviceUserId = wallpaper.userId;
1327 ServiceInfo si = mIPackageManager.getServiceInfo(componentName,
1328 PackageManager.GET_META_DATA | PackageManager.GET_PERMISSIONS, serviceUserId);
Christopher Tate90952202013-09-08 13:01:28 -07001329 if (si == null) {
1330 // The wallpaper component we're trying to use doesn't exist
1331 Slog.w(TAG, "Attempted wallpaper " + componentName + " is unavailable");
1332 return false;
1333 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001334 if (!android.Manifest.permission.BIND_WALLPAPER.equals(si.permission)) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001335 String msg = "Selected service does not require "
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001336 + android.Manifest.permission.BIND_WALLPAPER
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001337 + ": " + componentName;
1338 if (fromUser) {
1339 throw new SecurityException(msg);
1340 }
1341 Slog.w(TAG, msg);
1342 return false;
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001343 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001344
Dianne Hackborneb034652009-09-07 00:49:58 -07001345 WallpaperInfo wi = null;
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001346
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001347 Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
Justin Koh29c30162014-09-05 17:10:10 -07001348 if (componentName != null && !componentName.equals(mImageWallpaper)) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001349 // Make sure the selected service is actually a wallpaper service.
Amith Yamasani4e2820c2012-08-28 22:17:23 -07001350 List<ResolveInfo> ris =
1351 mIPackageManager.queryIntentServices(intent,
1352 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
Jeff Sharkeyd5896632016-03-04 16:16:00 -07001353 PackageManager.GET_META_DATA, serviceUserId).getList();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001354 for (int i=0; i<ris.size(); i++) {
1355 ServiceInfo rsi = ris.get(i).serviceInfo;
1356 if (rsi.name.equals(si.name) &&
1357 rsi.packageName.equals(si.packageName)) {
Dianne Hackborneb034652009-09-07 00:49:58 -07001358 try {
1359 wi = new WallpaperInfo(mContext, ris.get(i));
1360 } catch (XmlPullParserException e) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001361 if (fromUser) {
1362 throw new IllegalArgumentException(e);
1363 }
1364 Slog.w(TAG, e);
1365 return false;
Dianne Hackborneb034652009-09-07 00:49:58 -07001366 } catch (IOException e) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001367 if (fromUser) {
1368 throw new IllegalArgumentException(e);
1369 }
1370 Slog.w(TAG, e);
1371 return false;
Dianne Hackborneb034652009-09-07 00:49:58 -07001372 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001373 break;
1374 }
1375 }
Dianne Hackborneb034652009-09-07 00:49:58 -07001376 if (wi == null) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001377 String msg = "Selected service is not a wallpaper: "
1378 + componentName;
1379 if (fromUser) {
1380 throw new SecurityException(msg);
1381 }
1382 Slog.w(TAG, msg);
1383 return false;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001384 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001385 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001386
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001387 // Bind the service!
Joe Onorato8a9b2202010-02-26 18:56:32 -08001388 if (DEBUG) Slog.v(TAG, "Binding to:" + componentName);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001389 WallpaperConnection newConn = new WallpaperConnection(wi, wallpaper);
Mike Clerona428b2c2009-11-15 22:53:08 -08001390 intent.setComponent(componentName);
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07001391 intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
1392 com.android.internal.R.string.wallpaper_binding_label);
Dianne Hackborn41203752012-08-31 14:05:51 -07001393 intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivityAsUser(
Dianne Hackborneb034652009-09-07 00:49:58 -07001394 mContext, 0,
1395 Intent.createChooser(new Intent(Intent.ACTION_SET_WALLPAPER),
1396 mContext.getText(com.android.internal.R.string.chooser_wallpaper)),
Dianne Hackborn41203752012-08-31 14:05:51 -07001397 0, null, new UserHandle(serviceUserId)));
Dianne Hackbornc8230512013-07-13 21:32:12 -07001398 if (!mContext.bindServiceAsUser(intent, newConn,
Dianne Hackbornd69e4c12015-04-24 09:54:54 -07001399 Context.BIND_AUTO_CREATE | Context.BIND_SHOWING_UI
1400 | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
Amith Yamasani27b89e62013-01-16 12:30:11 -08001401 new UserHandle(serviceUserId))) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001402 String msg = "Unable to bind service: "
1403 + componentName;
1404 if (fromUser) {
1405 throw new IllegalArgumentException(msg);
1406 }
1407 Slog.w(TAG, msg);
1408 return false;
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001409 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001410 if (wallpaper.userId == mCurrentUserId && mLastWallpaper != null) {
1411 detachWallpaperLocked(mLastWallpaper);
1412 }
1413 wallpaper.wallpaperComponent = componentName;
1414 wallpaper.connection = newConn;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001415 newConn.mReply = reply;
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001416 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001417 if (wallpaper.userId == mCurrentUserId) {
1418 if (DEBUG)
1419 Slog.v(TAG, "Adding window token: " + newConn.mToken);
1420 mIWindowManager.addWindowToken(newConn.mToken,
1421 WindowManager.LayoutParams.TYPE_WALLPAPER);
1422 mLastWallpaper = wallpaper;
1423 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001424 } catch (RemoteException e) {
1425 }
Amith Yamasani4e2820c2012-08-28 22:17:23 -07001426 } catch (RemoteException e) {
1427 String msg = "Remote exception for " + componentName + "\n" + e;
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001428 if (fromUser) {
1429 throw new IllegalArgumentException(msg);
1430 }
1431 Slog.w(TAG, msg);
1432 return false;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001433 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001434 return true;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001435 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001436
1437 void detachWallpaperLocked(WallpaperData wallpaper) {
1438 if (wallpaper.connection != null) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001439 if (wallpaper.connection.mReply != null) {
1440 try {
1441 wallpaper.connection.mReply.sendResult(null);
1442 } catch (RemoteException e) {
1443 }
1444 wallpaper.connection.mReply = null;
1445 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001446 if (wallpaper.connection.mEngine != null) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001447 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001448 wallpaper.connection.mEngine.destroy();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001449 } catch (RemoteException e) {
1450 }
1451 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001452 mContext.unbindService(wallpaper.connection);
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001453 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001454 if (DEBUG)
1455 Slog.v(TAG, "Removing window token: " + wallpaper.connection.mToken);
1456 mIWindowManager.removeWindowToken(wallpaper.connection.mToken);
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001457 } catch (RemoteException e) {
1458 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001459 wallpaper.connection.mService = null;
1460 wallpaper.connection.mEngine = null;
1461 wallpaper.connection = null;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001462 }
1463 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001464
1465 void clearWallpaperComponentLocked(WallpaperData wallpaper) {
1466 wallpaper.wallpaperComponent = null;
1467 detachWallpaperLocked(wallpaper);
1468 }
1469
1470 void attachServiceLocked(WallpaperConnection conn, WallpaperData wallpaper) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001471 try {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001472 conn.mService.attach(conn, conn.mToken,
1473 WindowManager.LayoutParams.TYPE_WALLPAPER, false,
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001474 wallpaper.width, wallpaper.height, wallpaper.padding);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001475 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001476 Slog.w(TAG, "Failed attaching wallpaper; clearing", e);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001477 if (!wallpaper.wallpaperUpdating) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001478 bindWallpaperComponentLocked(null, false, false, wallpaper, null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001479 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001480 }
1481 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001482
1483 private void notifyCallbacksLocked(WallpaperData wallpaper) {
1484 final int n = wallpaper.callbacks.beginBroadcast();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001485 for (int i = 0; i < n; i++) {
1486 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001487 wallpaper.callbacks.getBroadcastItem(i).onWallpaperChanged();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001488 } catch (RemoteException e) {
1489
1490 // The RemoteCallbackList will take care of removing
1491 // the dead object for us.
1492 }
1493 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001494 wallpaper.callbacks.finishBroadcast();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001495 final Intent intent = new Intent(Intent.ACTION_WALLPAPER_CHANGED);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001496 mContext.sendBroadcastAsUser(intent, new UserHandle(mCurrentUserId));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001497 }
1498
1499 private void checkPermission(String permission) {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001500 if (PackageManager.PERMISSION_GRANTED!= mContext.checkCallingOrSelfPermission(permission)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001501 throw new SecurityException("Access denied to process: " + Binder.getCallingPid()
1502 + ", must have permission " + permission);
1503 }
1504 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001505
Benjamin Franzf3ece362015-02-11 10:51:10 +00001506 /**
1507 * Certain user types do not support wallpapers (e.g. managed profiles). The check is
1508 * implemented through through the OP_WRITE_WALLPAPER AppOp.
1509 */
1510 public boolean isWallpaperSupported(String callingPackage) {
1511 return mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_WRITE_WALLPAPER, Binder.getCallingUid(),
1512 callingPackage) == AppOpsManager.MODE_ALLOWED;
1513 }
1514
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001515 @Override
1516 public boolean isWallpaperSettingAllowed(String callingPackage) {
1517 final PackageManager pm = mContext.getPackageManager();
1518 String[] uidPackages = pm.getPackagesForUid(Binder.getCallingUid());
1519 boolean uidMatchPackage = Arrays.asList(uidPackages).contains(callingPackage);
1520 if (!uidMatchPackage) {
1521 return false; // callingPackage was faked.
1522 }
1523
1524 final DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
1525 if (dpm.isDeviceOwnerApp(callingPackage) || dpm.isProfileOwnerApp(callingPackage)) {
1526 return true;
1527 }
1528 final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
1529 return !um.hasUserRestriction(UserManager.DISALLOW_SET_WALLPAPER);
1530 }
1531
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001532 private static JournaledFile makeJournaledFile(int userId) {
Amith Yamasani61f57372012-08-31 12:12:28 -07001533 final String base = new File(getWallpaperDir(userId), WALLPAPER_INFO).getAbsolutePath();
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001534 return new JournaledFile(new File(base), new File(base + ".tmp"));
1535 }
1536
Christopher Tatedb27b842016-02-25 14:39:17 -08001537 private void saveSettingsLocked(int userId) {
1538 JournaledFile journal = makeJournaledFile(userId);
1539 FileOutputStream fstream = null;
1540 BufferedOutputStream stream = null;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001541 try {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001542 XmlSerializer out = new FastXmlSerializer();
Christopher Tatedb27b842016-02-25 14:39:17 -08001543 fstream = new FileOutputStream(journal.chooseForWrite(), false);
1544 stream = new BufferedOutputStream(fstream);
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001545 out.setOutput(stream, StandardCharsets.UTF_8.name());
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001546 out.startDocument(null, true);
1547
Christopher Tatedb27b842016-02-25 14:39:17 -08001548 WallpaperData wallpaper;
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001549
Christopher Tatedb27b842016-02-25 14:39:17 -08001550 wallpaper = mWallpaperMap.get(userId);
1551 if (wallpaper != null) {
1552 writeWallpaperAttributes(out, "wp", wallpaper);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001553 }
Christopher Tatedb27b842016-02-25 14:39:17 -08001554 wallpaper = mLockWallpaperMap.get(userId);
1555 if (wallpaper != null) {
1556 writeWallpaperAttributes(out, "kwp", wallpaper);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001557 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001558
1559 out.endDocument();
Christopher Tatedb27b842016-02-25 14:39:17 -08001560
1561 stream.flush(); // also flushes fstream
1562 FileUtils.sync(fstream);
1563 stream.close(); // also closes fstream
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001564 journal.commit();
1565 } catch (IOException e) {
Christopher Tatead3c2592016-01-20 18:13:17 -08001566 IoUtils.closeQuietly(stream);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001567 journal.rollback();
1568 }
1569 }
1570
Christopher Tatedb27b842016-02-25 14:39:17 -08001571 private void writeWallpaperAttributes(XmlSerializer out, String tag, WallpaperData wallpaper)
1572 throws IllegalArgumentException, IllegalStateException, IOException {
1573 out.startTag(null, tag);
1574 out.attribute(null, "id", Integer.toString(wallpaper.wallpaperId));
1575 out.attribute(null, "width", Integer.toString(wallpaper.width));
1576 out.attribute(null, "height", Integer.toString(wallpaper.height));
1577
1578 out.attribute(null, "cropLeft", Integer.toString(wallpaper.cropHint.left));
1579 out.attribute(null, "cropTop", Integer.toString(wallpaper.cropHint.top));
1580 out.attribute(null, "cropRight", Integer.toString(wallpaper.cropHint.right));
1581 out.attribute(null, "cropBottom", Integer.toString(wallpaper.cropHint.bottom));
1582
1583 if (wallpaper.padding.left != 0) {
1584 out.attribute(null, "paddingLeft", Integer.toString(wallpaper.padding.left));
1585 }
1586 if (wallpaper.padding.top != 0) {
1587 out.attribute(null, "paddingTop", Integer.toString(wallpaper.padding.top));
1588 }
1589 if (wallpaper.padding.right != 0) {
1590 out.attribute(null, "paddingRight", Integer.toString(wallpaper.padding.right));
1591 }
1592 if (wallpaper.padding.bottom != 0) {
1593 out.attribute(null, "paddingBottom", Integer.toString(wallpaper.padding.bottom));
1594 }
1595
1596 out.attribute(null, "name", wallpaper.name);
1597 if (wallpaper.wallpaperComponent != null
1598 && !wallpaper.wallpaperComponent.equals(mImageWallpaper)) {
1599 out.attribute(null, "component",
1600 wallpaper.wallpaperComponent.flattenToShortString());
1601 }
1602 out.endTag(null, tag);
1603 }
1604
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001605 private void migrateFromOld() {
1606 File oldWallpaper = new File(WallpaperBackupHelper.WALLPAPER_IMAGE_KEY);
1607 File oldInfo = new File(WallpaperBackupHelper.WALLPAPER_INFO_KEY);
1608 if (oldWallpaper.exists()) {
1609 File newWallpaper = new File(getWallpaperDir(0), WALLPAPER);
1610 oldWallpaper.renameTo(newWallpaper);
1611 }
1612 if (oldInfo.exists()) {
1613 File newInfo = new File(getWallpaperDir(0), WALLPAPER_INFO);
1614 oldInfo.renameTo(newInfo);
1615 }
1616 }
1617
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001618 private int getAttributeInt(XmlPullParser parser, String name, int defValue) {
1619 String value = parser.getAttributeValue(null, name);
1620 if (value == null) {
1621 return defValue;
1622 }
1623 return Integer.parseInt(value);
1624 }
1625
Xiaohui Chenac531942015-05-13 13:20:52 -07001626 /**
1627 * Sometimes it is expected the wallpaper map may not have a user's data. E.g. This could
1628 * happen during user switch. The async user switch observer may not have received
1629 * the event yet. We use this safe method when we don't care about this ordering and just
1630 * want to update the data. The data is going to be applied when the user switch observer
1631 * is eventually executed.
1632 */
Christopher Tatebe132e62016-02-10 12:59:49 -08001633 private WallpaperData getWallpaperSafeLocked(int userId, int which) {
1634 // We're setting either just system (work with the system wallpaper),
1635 // both (also work with the system wallpaper), or just the lock
1636 // wallpaper (update against the existing lock wallpaper if any).
1637 // Combined or just-system operations use the 'system' WallpaperData
1638 // for this use; lock-only operations use the dedicated one.
1639 final SparseArray<WallpaperData> whichSet =
1640 (which == FLAG_SET_LOCK) ? mLockWallpaperMap : mWallpaperMap;
1641 WallpaperData wallpaper = whichSet.get(userId);
Xiaohui Chenac531942015-05-13 13:20:52 -07001642 if (wallpaper == null) {
Christopher Tatebe132e62016-02-10 12:59:49 -08001643 // common case, this is the first lookup post-boot of the system or
1644 // unified lock, so we bring up the saved state lazily now and recheck.
Xiaohui Chenac531942015-05-13 13:20:52 -07001645 loadSettingsLocked(userId);
Christopher Tatebe132e62016-02-10 12:59:49 -08001646 wallpaper = whichSet.get(userId);
1647 // if it's still null here, this is a lock-only operation and there is not
1648 // yet a lock-only wallpaper set for this user, so we need to establish
1649 // it now.
1650 if (wallpaper == null) {
1651 if (which == FLAG_SET_LOCK) {
1652 wallpaper = new WallpaperData(userId,
1653 WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP);
1654 mLockWallpaperMap.put(userId, wallpaper);
1655 } else {
1656 // sanity fallback: we're in bad shape, but establishing a known
1657 // valid system+lock WallpaperData will keep us from dying.
1658 Slog.wtf(TAG, "Didn't find wallpaper in non-lock case!");
1659 wallpaper = new WallpaperData(userId, WALLPAPER, WALLPAPER_CROP);
1660 mWallpaperMap.put(userId, wallpaper);
1661 }
1662 }
Xiaohui Chenac531942015-05-13 13:20:52 -07001663 }
1664 return wallpaper;
1665 }
1666
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001667 private void loadSettingsLocked(int userId) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001668 if (DEBUG) Slog.v(TAG, "loadSettingsLocked");
Benjamin Franzf3ece362015-02-11 10:51:10 +00001669
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001670 JournaledFile journal = makeJournaledFile(userId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001671 FileInputStream stream = null;
1672 File file = journal.chooseForRead();
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001673 if (!file.exists()) {
1674 // This should only happen one time, when upgrading from a legacy system
1675 migrateFromOld();
1676 }
1677 WallpaperData wallpaper = mWallpaperMap.get(userId);
1678 if (wallpaper == null) {
Christopher Tatebe132e62016-02-10 12:59:49 -08001679 wallpaper = new WallpaperData(userId, WALLPAPER, WALLPAPER_CROP);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001680 mWallpaperMap.put(userId, wallpaper);
Christopher Tate41297ff2016-03-10 16:46:15 -08001681 if (!wallpaper.cropExists()) {
1682 generateCrop(wallpaper);
1683 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001684 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001685 boolean success = false;
1686 try {
1687 stream = new FileInputStream(file);
1688 XmlPullParser parser = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001689 parser.setInput(stream, StandardCharsets.UTF_8.name());
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001690
1691 int type;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001692 do {
1693 type = parser.next();
1694 if (type == XmlPullParser.START_TAG) {
1695 String tag = parser.getName();
1696 if ("wp".equals(tag)) {
Christopher Tatebe132e62016-02-10 12:59:49 -08001697 // Common to system + lock wallpapers
1698 parseWallpaperAttributes(parser, wallpaper);
Christopher Tatead3c2592016-01-20 18:13:17 -08001699
Christopher Tatebe132e62016-02-10 12:59:49 -08001700 // A system wallpaper might also be a live wallpaper
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001701 String comp = parser.getAttributeValue(null, "component");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001702 wallpaper.nextWallpaperComponent = comp != null
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001703 ? ComponentName.unflattenFromString(comp)
1704 : null;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001705 if (wallpaper.nextWallpaperComponent == null
1706 || "android".equals(wallpaper.nextWallpaperComponent
1707 .getPackageName())) {
Justin Koh29c30162014-09-05 17:10:10 -07001708 wallpaper.nextWallpaperComponent = mImageWallpaper;
Dianne Hackborn9ea31632011-08-05 14:43:50 -07001709 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001710
Mike Clerona428b2c2009-11-15 22:53:08 -08001711 if (DEBUG) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001712 Slog.v(TAG, "mWidth:" + wallpaper.width);
1713 Slog.v(TAG, "mHeight:" + wallpaper.height);
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001714 Slog.v(TAG, "cropRect:" + wallpaper.cropHint);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001715 Slog.v(TAG, "mName:" + wallpaper.name);
1716 Slog.v(TAG, "mNextWallpaperComponent:"
1717 + wallpaper.nextWallpaperComponent);
Mike Clerona428b2c2009-11-15 22:53:08 -08001718 }
Christopher Tatebe132e62016-02-10 12:59:49 -08001719 } else if ("kwp".equals(tag)) {
1720 // keyguard-specific wallpaper for this user
1721 WallpaperData lockWallpaper = mLockWallpaperMap.get(userId);
1722 if (lockWallpaper == null) {
1723 lockWallpaper = new WallpaperData(userId,
1724 WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP);
1725 mLockWallpaperMap.put(userId, lockWallpaper);
1726 }
1727 parseWallpaperAttributes(parser, lockWallpaper);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001728 }
1729 }
1730 } while (type != XmlPullParser.END_DOCUMENT);
1731 success = true;
Dianne Hackborn13579ed2012-11-28 18:05:36 -08001732 } catch (FileNotFoundException e) {
1733 Slog.w(TAG, "no current wallpaper -- first boot?");
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001734 } catch (NullPointerException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001735 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001736 } catch (NumberFormatException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001737 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001738 } catch (XmlPullParserException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001739 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001740 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001741 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001742 } catch (IndexOutOfBoundsException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001743 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001744 }
Christopher Tatead3c2592016-01-20 18:13:17 -08001745 IoUtils.closeQuietly(stream);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001746
1747 if (!success) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001748 wallpaper.width = -1;
1749 wallpaper.height = -1;
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001750 wallpaper.cropHint.set(0, 0, 0, 0);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001751 wallpaper.padding.set(0, 0, 0, 0);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001752 wallpaper.name = "";
Christopher Tatead3c2592016-01-20 18:13:17 -08001753 } else {
1754 if (wallpaper.wallpaperId <= 0) {
1755 wallpaper.wallpaperId = makeWallpaperIdLocked();
1756 if (DEBUG) {
1757 Slog.w(TAG, "Didn't set wallpaper id in loadSettingsLocked(" + userId
1758 + "); now " + wallpaper.wallpaperId);
1759 }
1760 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001761 }
Dianne Hackborn44bc17c2011-04-20 18:18:51 -07001762
1763 // We always want to have some reasonable width hint.
John Spurlock7ea91ec2013-11-04 13:48:38 -05001764 int baseSize = getMaximumSizeDimension();
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001765 if (wallpaper.width < baseSize) {
1766 wallpaper.width = baseSize;
Dianne Hackborn44bc17c2011-04-20 18:18:51 -07001767 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001768 if (wallpaper.height < baseSize) {
1769 wallpaper.height = baseSize;
Dianne Hackborn44bc17c2011-04-20 18:18:51 -07001770 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001771 // and crop, if not previously specified
1772 if (wallpaper.cropHint.width() <= 0
1773 || wallpaper.cropHint.height() <= 0) {
1774 wallpaper.cropHint.set(0, 0, wallpaper.width, wallpaper.height);
1775 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001776 }
1777
Christopher Tatebe132e62016-02-10 12:59:49 -08001778 private void parseWallpaperAttributes(XmlPullParser parser, WallpaperData wallpaper) {
1779 final String idString = parser.getAttributeValue(null, "id");
1780 if (idString != null) {
1781 final int id = wallpaper.wallpaperId = Integer.parseInt(idString);
1782 if (id > mWallpaperId) {
1783 mWallpaperId = id;
1784 }
1785 } else {
1786 wallpaper.wallpaperId = makeWallpaperIdLocked();
1787 }
1788
1789 wallpaper.width = Integer.parseInt(parser.getAttributeValue(null, "width"));
1790 wallpaper.height = Integer.parseInt(parser
1791 .getAttributeValue(null, "height"));
1792 wallpaper.cropHint.left = getAttributeInt(parser, "cropLeft", 0);
1793 wallpaper.cropHint.top = getAttributeInt(parser, "cropTop", 0);
1794 wallpaper.cropHint.right = getAttributeInt(parser, "cropRight", 0);
1795 wallpaper.cropHint.bottom = getAttributeInt(parser, "cropBottom", 0);
1796 wallpaper.padding.left = getAttributeInt(parser, "paddingLeft", 0);
1797 wallpaper.padding.top = getAttributeInt(parser, "paddingTop", 0);
1798 wallpaper.padding.right = getAttributeInt(parser, "paddingRight", 0);
1799 wallpaper.padding.bottom = getAttributeInt(parser, "paddingBottom", 0);
1800 wallpaper.name = parser.getAttributeValue(null, "name");
1801 }
1802
John Spurlock7ea91ec2013-11-04 13:48:38 -05001803 private int getMaximumSizeDimension() {
1804 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
1805 Display d = wm.getDefaultDisplay();
1806 return d.getMaximumSizeDimension();
1807 }
1808
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07001809 // Called by SystemBackupAgent after files are restored to disk.
Amith Yamasani09e9cdc2013-11-06 14:54:50 -08001810 public void settingsRestored() {
1811 // Verify caller is the system
1812 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
1813 throw new RuntimeException("settingsRestored() can only be called from the system process");
1814 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001815 // TODO: If necessary, make it work for secondary users as well. This currently assumes
1816 // restores only to the primary user
Joe Onorato8a9b2202010-02-26 18:56:32 -08001817 if (DEBUG) Slog.v(TAG, "settingsRestored");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001818 WallpaperData wallpaper = null;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001819 boolean success = false;
1820 synchronized (mLock) {
Christopher Tatedb27b842016-02-25 14:39:17 -08001821 loadSettingsLocked(UserHandle.USER_SYSTEM);
1822 wallpaper = mWallpaperMap.get(UserHandle.USER_SYSTEM);
Christopher Tatead3c2592016-01-20 18:13:17 -08001823 wallpaper.wallpaperId = makeWallpaperIdLocked(); // always bump id at restore
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001824 if (wallpaper.nextWallpaperComponent != null
Justin Koh29c30162014-09-05 17:10:10 -07001825 && !wallpaper.nextWallpaperComponent.equals(mImageWallpaper)) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001826 if (!bindWallpaperComponentLocked(wallpaper.nextWallpaperComponent, false, false,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001827 wallpaper, null)) {
Christopher Tatee3ab4d02009-12-16 14:03:31 -08001828 // No such live wallpaper or other failure; fall back to the default
1829 // live wallpaper (since the profile being restored indicated that the
1830 // user had selected a live rather than static one).
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001831 bindWallpaperComponentLocked(null, false, false, wallpaper, null);
Christopher Tatee3ab4d02009-12-16 14:03:31 -08001832 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001833 success = true;
1834 } else {
Mike Clerona428b2c2009-11-15 22:53:08 -08001835 // If there's a wallpaper name, we use that. If that can't be loaded, then we
1836 // use the default.
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001837 if ("".equals(wallpaper.name)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001838 if (DEBUG) Slog.v(TAG, "settingsRestored: name is empty");
Mike Clerona428b2c2009-11-15 22:53:08 -08001839 success = true;
1840 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001841 if (DEBUG) Slog.v(TAG, "settingsRestored: attempting to restore named resource");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001842 success = restoreNamedResourceLocked(wallpaper);
Mike Clerona428b2c2009-11-15 22:53:08 -08001843 }
Christopher Tatead3c2592016-01-20 18:13:17 -08001844 if (DEBUG) Slog.v(TAG, "settingsRestored: success=" + success
1845 + " id=" + wallpaper.wallpaperId);
Mike Clerona428b2c2009-11-15 22:53:08 -08001846 if (success) {
Christopher Tate41297ff2016-03-10 16:46:15 -08001847 generateCrop(wallpaper); // based on the new image + metadata
1848 bindWallpaperComponentLocked(wallpaper.nextWallpaperComponent, true, false,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001849 wallpaper, null);
Mike Clerona428b2c2009-11-15 22:53:08 -08001850 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001851 }
1852 }
1853
1854 if (!success) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001855 Slog.e(TAG, "Failed to restore wallpaper: '" + wallpaper.name + "'");
1856 wallpaper.name = "";
Christopher Tatedb27b842016-02-25 14:39:17 -08001857 getWallpaperDir(UserHandle.USER_SYSTEM).delete();
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001858 }
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07001859
1860 synchronized (mLock) {
Christopher Tatedb27b842016-02-25 14:39:17 -08001861 saveSettingsLocked(UserHandle.USER_SYSTEM);
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07001862 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001863 }
1864
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001865 // Restore the named resource bitmap to both source + crop files
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001866 boolean restoreNamedResourceLocked(WallpaperData wallpaper) {
1867 if (wallpaper.name.length() > 4 && "res:".equals(wallpaper.name.substring(0, 4))) {
1868 String resName = wallpaper.name.substring(4);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001869
1870 String pkg = null;
1871 int colon = resName.indexOf(':');
1872 if (colon > 0) {
1873 pkg = resName.substring(0, colon);
1874 }
1875
1876 String ident = null;
1877 int slash = resName.lastIndexOf('/');
1878 if (slash > 0) {
1879 ident = resName.substring(slash+1);
1880 }
1881
1882 String type = null;
1883 if (colon > 0 && slash > 0 && (slash-colon) > 1) {
1884 type = resName.substring(colon+1, slash);
1885 }
1886
1887 if (pkg != null && ident != null && type != null) {
1888 int resId = -1;
1889 InputStream res = null;
1890 FileOutputStream fos = null;
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001891 FileOutputStream cos = null;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001892 try {
1893 Context c = mContext.createPackageContext(pkg, Context.CONTEXT_RESTRICTED);
1894 Resources r = c.getResources();
1895 resId = r.getIdentifier(resName, null, null);
1896 if (resId == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001897 Slog.e(TAG, "couldn't resolve identifier pkg=" + pkg + " type=" + type
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001898 + " ident=" + ident);
1899 return false;
1900 }
1901
1902 res = r.openRawResource(resId);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001903 if (wallpaper.wallpaperFile.exists()) {
1904 wallpaper.wallpaperFile.delete();
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001905 wallpaper.cropFile.delete();
Dianne Hackborn1afd1c92010-03-18 22:47:17 -07001906 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001907 fos = new FileOutputStream(wallpaper.wallpaperFile);
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001908 cos = new FileOutputStream(wallpaper.cropFile);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001909
1910 byte[] buffer = new byte[32768];
1911 int amt;
1912 while ((amt=res.read(buffer)) > 0) {
1913 fos.write(buffer, 0, amt);
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001914 cos.write(buffer, 0, amt);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001915 }
1916 // mWallpaperObserver will notice the close and send the change broadcast
1917
Joe Onorato8a9b2202010-02-26 18:56:32 -08001918 Slog.v(TAG, "Restored wallpaper: " + resName);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001919 return true;
1920 } catch (NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001921 Slog.e(TAG, "Package name " + pkg + " not found");
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001922 } catch (Resources.NotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001923 Slog.e(TAG, "Resource not found: " + resId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001924 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001925 Slog.e(TAG, "IOException while restoring wallpaper ", e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001926 } finally {
Christopher Tatead3c2592016-01-20 18:13:17 -08001927 IoUtils.closeQuietly(res);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001928 if (fos != null) {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07001929 FileUtils.sync(fos);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001930 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001931 if (cos != null) {
1932 FileUtils.sync(cos);
1933 }
1934 IoUtils.closeQuietly(fos);
1935 IoUtils.closeQuietly(cos);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001936 }
1937 }
1938 }
1939 return false;
1940 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001941
Dianne Hackborneb034652009-09-07 00:49:58 -07001942 @Override
1943 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1944 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
1945 != PackageManager.PERMISSION_GRANTED) {
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001946
Dianne Hackborneb034652009-09-07 00:49:58 -07001947 pw.println("Permission Denial: can't dump wallpaper service from from pid="
1948 + Binder.getCallingPid()
1949 + ", uid=" + Binder.getCallingUid());
1950 return;
1951 }
1952
1953 synchronized (mLock) {
1954 pw.println("Current Wallpaper Service state:");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001955 for (int i = 0; i < mWallpaperMap.size(); i++) {
1956 WallpaperData wallpaper = mWallpaperMap.valueAt(i);
Christopher Tatead3c2592016-01-20 18:13:17 -08001957 pw.print(" User "); pw.print(wallpaper.userId);
1958 pw.print(": id="); pw.println(wallpaper.wallpaperId);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001959 pw.print(" mWidth=");
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001960 pw.print(wallpaper.width);
1961 pw.print(" mHeight=");
1962 pw.println(wallpaper.height);
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001963 pw.print(" mCropHint="); pw.println(wallpaper.cropHint);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001964 pw.print(" mPadding="); pw.println(wallpaper.padding);
1965 pw.print(" mName="); pw.println(wallpaper.name);
1966 pw.print(" mWallpaperComponent="); pw.println(wallpaper.wallpaperComponent);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001967 if (wallpaper.connection != null) {
1968 WallpaperConnection conn = wallpaper.connection;
1969 pw.print(" Wallpaper connection ");
1970 pw.print(conn);
1971 pw.println(":");
1972 if (conn.mInfo != null) {
1973 pw.print(" mInfo.component=");
1974 pw.println(conn.mInfo.getComponent());
1975 }
1976 pw.print(" mToken=");
1977 pw.println(conn.mToken);
1978 pw.print(" mService=");
1979 pw.println(conn.mService);
1980 pw.print(" mEngine=");
1981 pw.println(conn.mEngine);
1982 pw.print(" mLastDiedTime=");
1983 pw.println(wallpaper.lastDiedTime - SystemClock.uptimeMillis());
1984 }
Dianne Hackborneb034652009-09-07 00:49:58 -07001985 }
1986 }
1987 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001988}