blob: 4aeba153cc6877c6540f8913844263fa8dad2a48 [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 Tateedf7d042016-03-29 18:24:25 -070019import static android.app.WallpaperManager.FLAG_LOCK;
Jeff Sharkey1cab76a2016-04-12 18:23:31 -060020import static android.app.WallpaperManager.FLAG_SYSTEM;
wilsonshihde93f492018-11-01 21:23:40 +080021import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AUTO;
Jeff Sharkey1cab76a2016-04-12 18:23:31 -060022import static android.os.ParcelFileDescriptor.MODE_CREATE;
23import static android.os.ParcelFileDescriptor.MODE_READ_ONLY;
24import static android.os.ParcelFileDescriptor.MODE_READ_WRITE;
25import static android.os.ParcelFileDescriptor.MODE_TRUNCATE;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -070026import static android.view.Display.DEFAULT_DISPLAY;
27import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
Christopher Tate111bd4a2009-06-24 17:29:38 -070028
Lucas Dupin50ba9912017-07-14 11:55:05 -070029import android.annotation.NonNull;
Christopher Tatee409f0e2016-03-21 14:53:15 -070030import android.app.ActivityManager;
Amith Yamasani4e2820c2012-08-28 22:17:23 -070031import android.app.AppGlobals;
Benjamin Franzf3ece362015-02-11 10:51:10 +000032import android.app.AppOpsManager;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070033import android.app.IWallpaperManager;
34import android.app.IWallpaperManagerCallback;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070035import android.app.PendingIntent;
Sudheer Shanka2c4522c2016-08-27 20:53:28 -070036import android.app.UserSwitchObserver;
Lucas Dupin75ec3792017-06-29 14:07:18 -070037import android.app.WallpaperColors;
Dianne Hackborneb034652009-09-07 00:49:58 -070038import android.app.WallpaperInfo;
Jeff Sharkey28f08772014-04-16 09:41:58 -070039import android.app.WallpaperManager;
Oleksandr Peletskyif2519812016-01-26 20:16:06 +010040import android.app.admin.DevicePolicyManager;
Amith Yamasani37ce3a82012-02-06 12:04:42 -080041import android.app.backup.WallpaperBackupHelper;
Amith Yamasani13593602012-03-22 16:16:17 -070042import android.content.BroadcastReceiver;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070043import android.content.ComponentName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044import android.content.Context;
45import android.content.Intent;
Amith Yamasani13593602012-03-22 16:16:17 -070046import android.content.IntentFilter;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070047import android.content.ServiceConnection;
Amith Yamasani4e2820c2012-08-28 22:17:23 -070048import android.content.pm.IPackageManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049import android.content.pm.PackageManager;
Jeff Sharkey1cab76a2016-04-12 18:23:31 -060050import android.content.pm.PackageManager.NameNotFoundException;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070051import android.content.pm.ResolveInfo;
52import android.content.pm.ServiceInfo;
Amith Yamasani6474c4c2012-10-04 14:55:42 -070053import android.content.pm.UserInfo;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070054import android.content.res.Resources;
Christopher Tate1e1e2e02016-01-25 15:34:36 -080055import android.graphics.Bitmap;
56import android.graphics.BitmapFactory;
57import android.graphics.BitmapRegionDecoder;
Lucas Dupinea1fb1e2017-04-05 17:39:44 -070058import android.graphics.Color;
Dianne Hackborn067e5f62014-09-07 23:14:30 -070059import android.graphics.Rect;
wilsonshihde93f492018-11-01 21:23:40 +080060import android.hardware.display.DisplayManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061import android.os.Binder;
Dianne Hackborn284ac932009-08-28 10:34:25 -070062import android.os.Bundle;
wilsonshiha282bf72018-11-30 12:48:05 +080063import android.os.Debug;
Amith Yamasani13593602012-03-22 16:16:17 -070064import android.os.Environment;
Jeff Sharkey1cab76a2016-04-12 18:23:31 -060065import android.os.FileObserver;
Dianne Hackborn8bdf5932010-10-15 12:54:40 -070066import android.os.FileUtils;
Christopher Tatec349e59f2017-05-05 17:37:43 -070067import android.os.Handler;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070068import android.os.IBinder;
Lucas Dupin50ba9912017-07-14 11:55:05 -070069import android.os.IInterface;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -070070import android.os.IRemoteCallback;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071import android.os.ParcelFileDescriptor;
Lucas Dupin75ec3792017-06-29 14:07:18 -070072import android.os.Process;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073import android.os.RemoteCallbackList;
Jeff Sharkey1cab76a2016-04-12 18:23:31 -060074import android.os.RemoteException;
rpcraig554cb0c2012-07-05 06:41:43 -040075import android.os.SELinux;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070076import android.os.ServiceManager;
Dianne Hackborn0cd48872009-08-13 18:51:59 -070077import android.os.SystemClock;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070078import android.os.UserHandle;
Amith Yamasani6474c4c2012-10-04 14:55:42 -070079import android.os.UserManager;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070080import android.service.wallpaper.IWallpaperConnection;
81import android.service.wallpaper.IWallpaperEngine;
82import android.service.wallpaper.IWallpaperService;
83import android.service.wallpaper.WallpaperService;
Christopher Tate8347b632016-04-29 18:59:18 -070084import android.system.ErrnoException;
85import android.system.Os;
Filip Gruszczynski5dcc3ac2014-10-13 15:51:39 -070086import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -080087import android.util.Slog;
Amith Yamasani37ce3a82012-02-06 12:04:42 -080088import android.util.SparseArray;
wilsonshiha282bf72018-11-30 12:48:05 +080089import android.util.SparseBooleanArray;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070090import android.util.Xml;
Dianne Hackborn44bc17c2011-04-20 18:18:51 -070091import android.view.Display;
Valentin Iftime3047bb12018-12-28 17:02:19 +010092import android.view.DisplayInfo;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070093import android.view.IWindowManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094
Jeff Sharkey1cab76a2016-04-12 18:23:31 -060095import com.android.internal.R;
96import com.android.internal.content.PackageMonitor;
Christopher Tate190e8532016-07-11 11:35:34 -070097import com.android.internal.os.BackgroundThread;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060098import com.android.internal.util.DumpUtils;
Jeff Sharkey1cab76a2016-04-12 18:23:31 -060099import com.android.internal.util.FastXmlSerializer;
100import com.android.internal.util.JournaledFile;
101import com.android.server.EventLogTags;
Adrian Roosc3f915e2016-09-06 11:40:53 -0700102import com.android.server.FgThread;
Jeff Sharkey1cab76a2016-04-12 18:23:31 -0600103import com.android.server.SystemService;
104
105import libcore.io.IoUtils;
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700106
107import org.xmlpull.v1.XmlPullParser;
108import org.xmlpull.v1.XmlPullParserException;
109import org.xmlpull.v1.XmlSerializer;
110
Jeff Sharkey1cab76a2016-04-12 18:23:31 -0600111import java.io.BufferedOutputStream;
112import java.io.File;
113import java.io.FileDescriptor;
114import java.io.FileInputStream;
115import java.io.FileNotFoundException;
116import java.io.FileOutputStream;
117import java.io.IOException;
118import java.io.InputStream;
119import java.io.PrintWriter;
120import java.nio.charset.StandardCharsets;
Lucas Dupinfb3ab2a2017-08-08 14:17:30 -0400121import java.util.ArrayList;
Jeff Sharkey1cab76a2016-04-12 18:23:31 -0600122import java.util.Arrays;
123import java.util.List;
Christopher Tate2a6c55f2017-03-31 12:28:30 -0700124import java.util.Objects;
wilsonshihde93f492018-11-01 21:23:40 +0800125import java.util.function.Consumer;
wilsonshiha282bf72018-11-30 12:48:05 +0800126import java.util.function.Predicate;
Christopher Tatead3c2592016-01-20 18:13:17 -0800127
Daichi Hirono4bbf8522017-12-06 10:34:18 +0900128public class WallpaperManagerService extends IWallpaperManager.Stub
129 implements IWallpaperManagerService {
wilsonshiha282bf72018-11-30 12:48:05 +0800130 private static final String TAG = "WallpaperManagerService";
131 private static final boolean DEBUG = false;
132 private static final boolean DEBUG_LIVE = true;
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700133
Jeff Sharkey1cab76a2016-04-12 18:23:31 -0600134 public static class Lifecycle extends SystemService {
Daichi Hirono4bbf8522017-12-06 10:34:18 +0900135 private IWallpaperManagerService mService;
Jeff Sharkey1cab76a2016-04-12 18:23:31 -0600136
137 public Lifecycle(Context context) {
138 super(context);
139 }
140
141 @Override
142 public void onStart() {
Daichi Hirono4bbf8522017-12-06 10:34:18 +0900143 try {
144 final Class<? extends IWallpaperManagerService> klass =
145 (Class<? extends IWallpaperManagerService>)Class.forName(
146 getContext().getResources().getString(
147 R.string.config_wallpaperManagerServiceName));
148 mService = klass.getConstructor(Context.class).newInstance(getContext());
149 publishBinderService(Context.WALLPAPER_SERVICE, mService);
150 } catch (Exception exp) {
151 Slog.wtf(TAG, "Failed to instantiate WallpaperManagerService", exp);
152 }
Jeff Sharkey1cab76a2016-04-12 18:23:31 -0600153 }
154
155 @Override
156 public void onBootPhase(int phase) {
Daichi Hirono4bbf8522017-12-06 10:34:18 +0900157 if (mService != null) {
158 mService.onBootPhase(phase);
Jeff Sharkey1cab76a2016-04-12 18:23:31 -0600159 }
160 }
161
162 @Override
163 public void onUnlockUser(int userHandle) {
Daichi Hirono4bbf8522017-12-06 10:34:18 +0900164 if (mService != null) {
165 mService.onUnlockUser(userHandle);
166 }
Jeff Sharkey1cab76a2016-04-12 18:23:31 -0600167 }
168 }
169
wilsonshiha282bf72018-11-30 12:48:05 +0800170 private final Object mLock = new Object();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800171
Dianne Hackborn0cd48872009-08-13 18:51:59 -0700172 /**
173 * Minimum time between crashes of a wallpaper service for us to consider
174 * restarting it vs. just reverting to the static wallpaper.
175 */
wilsonshiha282bf72018-11-30 12:48:05 +0800176 private static final long MIN_WALLPAPER_CRASH_TIME = 10000;
177 private static final int MAX_WALLPAPER_COMPONENT_LOG_LENGTH = 128;
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800178 static final String WALLPAPER = "wallpaper_orig";
179 static final String WALLPAPER_CROP = "wallpaper";
Christopher Tatebe132e62016-02-10 12:59:49 -0800180 static final String WALLPAPER_LOCK_ORIG = "wallpaper_lock_orig";
181 static final String WALLPAPER_LOCK_CROP = "wallpaper_lock";
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800182 static final String WALLPAPER_INFO = "wallpaper_info.xml";
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -0700183
Christopher Tatebe132e62016-02-10 12:59:49 -0800184 // All the various per-user state files we need to be aware of
wilsonshiha282bf72018-11-30 12:48:05 +0800185 private static final String[] sPerUserFiles = new String[] {
Christopher Tatebe132e62016-02-10 12:59:49 -0800186 WALLPAPER, WALLPAPER_CROP,
187 WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP,
188 WALLPAPER_INFO
189 };
190
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -0700191 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192 * Observes the wallpaper for changes and notifies all IWallpaperServiceCallbacks
193 * that the wallpaper has changed. The CREATE is triggered when there is no
194 * wallpaper set and is created for the first time. The CLOSE_WRITE is triggered
Christopher Tate190e8532016-07-11 11:35:34 -0700195 * every time the wallpaper is changed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800196 */
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800197 private class WallpaperObserver extends FileObserver {
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700198
Christopher Tatebe132e62016-02-10 12:59:49 -0800199 final int mUserId;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800200 final WallpaperData mWallpaper;
201 final File mWallpaperDir;
202 final File mWallpaperFile;
Christopher Tatebe132e62016-02-10 12:59:49 -0800203 final File mWallpaperLockFile;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800204
205 public WallpaperObserver(WallpaperData wallpaper) {
206 super(getWallpaperDir(wallpaper.userId).getAbsolutePath(),
Christopher Tateda058e22014-10-08 14:51:09 -0700207 CLOSE_WRITE | MOVED_TO | DELETE | DELETE_SELF);
Christopher Tatebe132e62016-02-10 12:59:49 -0800208 mUserId = wallpaper.userId;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800209 mWallpaperDir = getWallpaperDir(wallpaper.userId);
210 mWallpaper = wallpaper;
211 mWallpaperFile = new File(mWallpaperDir, WALLPAPER);
Christopher Tatebe132e62016-02-10 12:59:49 -0800212 mWallpaperLockFile = new File(mWallpaperDir, WALLPAPER_LOCK_ORIG);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800213 }
214
Christopher Tatebe132e62016-02-10 12:59:49 -0800215 private WallpaperData dataForEvent(boolean sysChanged, boolean lockChanged) {
216 WallpaperData wallpaper = null;
217 synchronized (mLock) {
218 if (lockChanged) {
219 wallpaper = mLockWallpaperMap.get(mUserId);
220 }
221 if (wallpaper == null) {
222 // no lock-specific wallpaper exists, or sys case, handled together
223 wallpaper = mWallpaperMap.get(mUserId);
224 }
225 }
226 return (wallpaper != null) ? wallpaper : mWallpaper;
227 }
228
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800229 @Override
230 public void onEvent(int event, String path) {
231 if (path == null) {
232 return;
233 }
Christopher Tated7faf532016-02-25 12:43:38 -0800234 final boolean moved = (event == MOVED_TO);
235 final boolean written = (event == CLOSE_WRITE || moved);
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800236 final File changedFile = new File(mWallpaperDir, path);
237
Christopher Tatebe132e62016-02-10 12:59:49 -0800238 // System and system+lock changes happen on the system wallpaper input file;
239 // lock-only changes happen on the dedicated lock wallpaper input file
240 final boolean sysWallpaperChanged = (mWallpaperFile.equals(changedFile));
241 final boolean lockWallpaperChanged = (mWallpaperLockFile.equals(changedFile));
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700242 int notifyColorsWhich = 0;
Christopher Tatebe132e62016-02-10 12:59:49 -0800243 WallpaperData wallpaper = dataForEvent(sysWallpaperChanged, lockWallpaperChanged);
244
245 if (DEBUG) {
246 Slog.v(TAG, "Wallpaper file change: evt=" + event
247 + " path=" + path
248 + " sys=" + sysWallpaperChanged
249 + " lock=" + lockWallpaperChanged
250 + " imagePending=" + wallpaper.imageWallpaperPending
251 + " whichPending=0x" + Integer.toHexString(wallpaper.whichPending)
252 + " written=" + written);
253 }
Christopher Tate8347b632016-04-29 18:59:18 -0700254
255 if (moved && lockWallpaperChanged) {
256 // We just migrated sys -> lock to preserve imagery for an impending
Christopher Tatefa7d97f2016-06-30 12:21:57 -0700257 // new system-only wallpaper. Tell keyguard about it and make sure it
258 // has the right SELinux label.
Christopher Tate8347b632016-04-29 18:59:18 -0700259 if (DEBUG) {
260 Slog.i(TAG, "Sys -> lock MOVED_TO");
261 }
Christopher Tatefa7d97f2016-06-30 12:21:57 -0700262 SELinux.restorecon(changedFile);
Christopher Tate8347b632016-04-29 18:59:18 -0700263 notifyLockWallpaperChanged();
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700264 notifyWallpaperColorsChanged(wallpaper, FLAG_LOCK);
Christopher Tate8347b632016-04-29 18:59:18 -0700265 return;
266 }
267
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800268 synchronized (mLock) {
Christopher Tatebe132e62016-02-10 12:59:49 -0800269 if (sysWallpaperChanged || lockWallpaperChanged) {
270 notifyCallbacksLocked(wallpaper);
271 if (wallpaper.wallpaperComponent == null
Christopher Tateda058e22014-10-08 14:51:09 -0700272 || event != CLOSE_WRITE // includes the MOVED_TO case
Christopher Tatebe132e62016-02-10 12:59:49 -0800273 || wallpaper.imageWallpaperPending) {
Christopher Tateda058e22014-10-08 14:51:09 -0700274 if (written) {
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800275 // The image source has finished writing the source image,
276 // so we now produce the crop rect (in the background), and
277 // only publish the new displayable (sub)image as a result
278 // of that work.
Christopher Tatebe132e62016-02-10 12:59:49 -0800279 if (DEBUG) {
280 Slog.v(TAG, "Wallpaper written; generating crop");
281 }
Christopher Tateebadfb12016-07-25 14:50:08 -0700282 SELinux.restorecon(changedFile);
Christopher Tated7faf532016-02-25 12:43:38 -0800283 if (moved) {
284 // This is a restore, so generate the crop using any just-restored new
285 // crop guidelines, making sure to preserve our local dimension hints.
Christopher Tatefa7d97f2016-06-30 12:21:57 -0700286 // We also make sure to reapply the correct SELinux label.
Christopher Tated7faf532016-02-25 12:43:38 -0800287 if (DEBUG) {
288 Slog.v(TAG, "moved-to, therefore restore; reloading metadata");
289 }
290 loadSettingsLocked(wallpaper.userId, true);
291 }
Christopher Tatebe132e62016-02-10 12:59:49 -0800292 generateCrop(wallpaper);
293 if (DEBUG) {
294 Slog.v(TAG, "Crop done; invoking completion callback");
295 }
296 wallpaper.imageWallpaperPending = false;
Christopher Tatebe132e62016-02-10 12:59:49 -0800297 if (sysWallpaperChanged) {
298 // If this was the system wallpaper, rebind...
299 bindWallpaperComponentLocked(mImageWallpaper, true,
300 false, wallpaper, null);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700301 notifyColorsWhich |= FLAG_SYSTEM;
Christopher Tatebe132e62016-02-10 12:59:49 -0800302 }
303 if (lockWallpaperChanged
Christopher Tateedf7d042016-03-29 18:24:25 -0700304 || (wallpaper.whichPending & FLAG_LOCK) != 0) {
Christopher Tatebe132e62016-02-10 12:59:49 -0800305 if (DEBUG) {
Christopher Tatedb27b842016-02-25 14:39:17 -0800306 Slog.i(TAG, "Lock-relevant wallpaper changed");
Christopher Tatebe132e62016-02-10 12:59:49 -0800307 }
Christopher Tatedb27b842016-02-25 14:39:17 -0800308 // either a lock-only wallpaper commit or a system+lock event.
309 // if it's system-plus-lock we need to wipe the lock bookkeeping;
310 // we're falling back to displaying the system wallpaper there.
311 if (!lockWallpaperChanged) {
312 mLockWallpaperMap.remove(wallpaper.userId);
313 }
314 // and in any case, tell keyguard about it
Christopher Tate8347b632016-04-29 18:59:18 -0700315 notifyLockWallpaperChanged();
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700316 notifyColorsWhich |= FLAG_LOCK;
Christopher Tatebe132e62016-02-10 12:59:49 -0800317 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700318
Christopher Tatedb27b842016-02-25 14:39:17 -0800319 saveSettingsLocked(wallpaper.userId);
Christopher Tate8efbe0d2017-08-29 16:50:13 -0700320
321 // Publish completion *after* we've persisted the changes
322 if (wallpaper.setComplete != null) {
323 try {
324 wallpaper.setComplete.onWallpaperChanged();
325 } catch (RemoteException e) {
326 // if this fails we don't really care; the setting app may just
327 // have crashed and that sort of thing is a fact of life.
328 }
329 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700330 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800331 }
332 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800333 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700334
335 // Outside of the lock since it will synchronize itself
336 if (notifyColorsWhich != 0) {
337 notifyWallpaperColorsChanged(wallpaper, notifyColorsWhich);
338 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800339 }
340 }
341
wilsonshiha282bf72018-11-30 12:48:05 +0800342 private void notifyLockWallpaperChanged() {
Christopher Tate8347b632016-04-29 18:59:18 -0700343 final IWallpaperManagerCallback cb = mKeyguardListener;
344 if (cb != null) {
345 try {
346 cb.onWallpaperChanged();
347 } catch (RemoteException e) {
348 // Oh well it went away; no big deal
349 }
350 }
351 }
352
Lucas Dupin50ba9912017-07-14 11:55:05 -0700353 private void notifyWallpaperColorsChanged(@NonNull WallpaperData wallpaper, int which) {
wilsonshih36597d42018-12-05 18:56:39 +0800354 if (wallpaper.connection != null) {
355 wallpaper.connection.forEachDisplayConnector(connector -> {
356 notifyWallpaperColorsChangedOnDisplay(wallpaper, which, connector.mDisplayId);
357 });
358 } else { // Lock wallpaper does not have WallpaperConnection.
359 notifyWallpaperColorsChangedOnDisplay(wallpaper, which, DEFAULT_DISPLAY);
360 }
361 }
362
363 private RemoteCallbackList<IWallpaperManagerCallback> getWallpaperCallbacks(int userId,
364 int displayId) {
365 RemoteCallbackList<IWallpaperManagerCallback> listeners = null;
366 final SparseArray<RemoteCallbackList<IWallpaperManagerCallback>> displayListeners =
367 mColorsChangedListeners.get(userId);
368 if (displayListeners != null) {
369 listeners = displayListeners.get(displayId);
370 }
371 return listeners;
372 }
373
374 private void notifyWallpaperColorsChangedOnDisplay(@NonNull WallpaperData wallpaper, int which,
375 int displayId) {
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700376 boolean needsExtraction;
377 synchronized (mLock) {
Lucas Dupin50ba9912017-07-14 11:55:05 -0700378 final RemoteCallbackList<IWallpaperManagerCallback> currentUserColorListeners =
wilsonshih36597d42018-12-05 18:56:39 +0800379 getWallpaperCallbacks(wallpaper.userId, displayId);
Lucas Dupin50ba9912017-07-14 11:55:05 -0700380 final RemoteCallbackList<IWallpaperManagerCallback> userAllColorListeners =
wilsonshih36597d42018-12-05 18:56:39 +0800381 getWallpaperCallbacks(UserHandle.USER_ALL, displayId);
Lucas Dupin50ba9912017-07-14 11:55:05 -0700382 // No-op until someone is listening to it.
383 if (emptyCallbackList(currentUserColorListeners) &&
384 emptyCallbackList(userAllColorListeners)) {
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700385 return;
Lucas Dupin50ba9912017-07-14 11:55:05 -0700386 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700387
388 if (DEBUG) {
wilsonshih36597d42018-12-05 18:56:39 +0800389 Slog.v(TAG, "notifyWallpaperColorsChangedOnDisplay " + which);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700390 }
391
392 needsExtraction = wallpaper.primaryColors == null;
393 }
394
Lucas Dupin75ec3792017-06-29 14:07:18 -0700395 // Let's notify the current values, it's fine if it's null, it just means
396 // that we don't know yet.
wilsonshih36597d42018-12-05 18:56:39 +0800397 notifyColorListeners(wallpaper.primaryColors, which, wallpaper.userId, displayId);
Lucas Dupin75ec3792017-06-29 14:07:18 -0700398
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700399 if (needsExtraction) {
400 extractColors(wallpaper);
Lucas Dupin50ba9912017-07-14 11:55:05 -0700401 synchronized (mLock) {
402 // Don't need to notify if nothing changed.
403 if (wallpaper.primaryColors == null) {
404 return;
405 }
406 }
wilsonshih36597d42018-12-05 18:56:39 +0800407 notifyColorListeners(wallpaper.primaryColors, which, wallpaper.userId, displayId);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700408 }
Lucas Dupin75ec3792017-06-29 14:07:18 -0700409 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700410
Lucas Dupin50ba9912017-07-14 11:55:05 -0700411 private static <T extends IInterface> boolean emptyCallbackList(RemoteCallbackList<T> list) {
412 return (list == null || list.getRegisteredCallbackCount() == 0);
413 }
414
415 private void notifyColorListeners(@NonNull WallpaperColors wallpaperColors, int which,
wilsonshih36597d42018-12-05 18:56:39 +0800416 int userId, int displayId) {
Lucas Dupin75ec3792017-06-29 14:07:18 -0700417 final IWallpaperManagerCallback keyguardListener;
Lucas Dupinfb3ab2a2017-08-08 14:17:30 -0400418 final ArrayList<IWallpaperManagerCallback> colorListeners = new ArrayList<>();
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700419 synchronized (mLock) {
Lucas Dupinfb3ab2a2017-08-08 14:17:30 -0400420 final RemoteCallbackList<IWallpaperManagerCallback> currentUserColorListeners =
wilsonshih36597d42018-12-05 18:56:39 +0800421 getWallpaperCallbacks(userId, displayId);
Lucas Dupinfb3ab2a2017-08-08 14:17:30 -0400422 final RemoteCallbackList<IWallpaperManagerCallback> userAllColorListeners =
wilsonshih36597d42018-12-05 18:56:39 +0800423 getWallpaperCallbacks(UserHandle.USER_ALL, displayId);
Lucas Dupin75ec3792017-06-29 14:07:18 -0700424 keyguardListener = mKeyguardListener;
Lucas Dupinfb3ab2a2017-08-08 14:17:30 -0400425
426 if (currentUserColorListeners != null) {
427 final int count = currentUserColorListeners.beginBroadcast();
428 for (int i = 0; i < count; i++) {
429 colorListeners.add(currentUserColorListeners.getBroadcastItem(i));
430 }
431 currentUserColorListeners.finishBroadcast();
432 }
433
434 if (userAllColorListeners != null) {
435 final int count = userAllColorListeners.beginBroadcast();
436 for (int i = 0; i < count; i++) {
437 colorListeners.add(userAllColorListeners.getBroadcastItem(i));
438 }
439 userAllColorListeners.finishBroadcast();
440 }
Lucas Dupin75ec3792017-06-29 14:07:18 -0700441 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700442
Lucas Dupinfb3ab2a2017-08-08 14:17:30 -0400443 final int count = colorListeners.size();
444 for (int i = 0; i < count; i++) {
445 try {
446 colorListeners.get(i).onWallpaperColorsChanged(wallpaperColors, which, userId);
447 } catch (RemoteException e) {
448 // Callback is gone, it's not necessary to unregister it since
449 // RemoteCallbackList#getBroadcastItem will take care of it.
Lucas Dupin75ec3792017-06-29 14:07:18 -0700450 }
451 }
452
wilsonshih36597d42018-12-05 18:56:39 +0800453 // Only shows Keyguard on default display
454 if (keyguardListener != null && displayId == DEFAULT_DISPLAY) {
Lucas Dupin75ec3792017-06-29 14:07:18 -0700455 try {
Lucas Dupin50ba9912017-07-14 11:55:05 -0700456 keyguardListener.onWallpaperColorsChanged(wallpaperColors, which, userId);
Lucas Dupin75ec3792017-06-29 14:07:18 -0700457 } catch (RemoteException e) {
458 // Oh well it went away; no big deal
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700459 }
460 }
461 }
462
Lucas Dupinbcae5852017-05-03 12:42:58 -0700463 /**
464 * We can easily extract colors from an ImageWallpaper since it's only a bitmap.
Lucas Dupin284836b2017-06-23 15:28:41 -0700465 * In this case, using the crop is more than enough. Live wallpapers are just ignored.
Lucas Dupinbcae5852017-05-03 12:42:58 -0700466 *
467 * @param wallpaper a wallpaper representation
468 */
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700469 private void extractColors(WallpaperData wallpaper) {
470 String cropFile = null;
wilsonshih31d70a12019-01-14 12:42:35 +0800471 boolean defaultImageWallpaper = false;
Lucas Dupin284836b2017-06-23 15:28:41 -0700472 int wallpaperId;
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700473
wilsonshih36597d42018-12-05 18:56:39 +0800474 if (wallpaper.equals(mFallbackWallpaper)) {
475 extractDefaultImageWallpaperColors();
476 return;
477 }
478
Lucas Dupinbcae5852017-05-03 12:42:58 -0700479 synchronized (mLock) {
Lucas Dupin284836b2017-06-23 15:28:41 -0700480 // Not having a wallpaperComponent means it's a lock screen wallpaper.
481 final boolean imageWallpaper = mImageWallpaper.equals(wallpaper.wallpaperComponent)
Lucas Dupinbcae5852017-05-03 12:42:58 -0700482 || wallpaper.wallpaperComponent == null;
Lucas Dupin284836b2017-06-23 15:28:41 -0700483 if (imageWallpaper && wallpaper.cropFile != null && wallpaper.cropFile.exists()) {
484 cropFile = wallpaper.cropFile.getAbsolutePath();
wilsonshih31d70a12019-01-14 12:42:35 +0800485 } else if (imageWallpaper && !wallpaper.cropExists() && !wallpaper.sourceExists()) {
486 defaultImageWallpaper = true;
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700487 }
488 wallpaperId = wallpaper.wallpaperId;
489 }
490
Lucas Dupin84b89d92017-05-09 12:16:19 -0700491 WallpaperColors colors = null;
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700492 if (cropFile != null) {
Lucas Dupin84b89d92017-05-09 12:16:19 -0700493 Bitmap bitmap = BitmapFactory.decodeFile(cropFile);
Lucas Dupin284836b2017-06-23 15:28:41 -0700494 if (bitmap != null) {
Lucas Dupinb5e50532018-05-24 16:33:14 +0000495 colors = WallpaperColors.fromBitmap(bitmap);
Lucas Dupin284836b2017-06-23 15:28:41 -0700496 bitmap.recycle();
497 }
wilsonshih31d70a12019-01-14 12:42:35 +0800498 } else if (defaultImageWallpaper) {
499 // There is no crop and source file because this is default image wallpaper.
500 try (final InputStream is =
501 WallpaperManager.openDefaultWallpaper(mContext, FLAG_SYSTEM)) {
502 if (is != null) {
503 try {
504 final BitmapFactory.Options options = new BitmapFactory.Options();
505 final Bitmap bitmap = BitmapFactory.decodeStream(is, null, options);
506 if (bitmap != null) {
507 colors = WallpaperColors.fromBitmap(bitmap);
508 bitmap.recycle();
509 }
510 } catch (OutOfMemoryError e) {
511 Slog.w(TAG, "Can't decode default wallpaper stream", e);
512 }
513 }
514 } catch (IOException e) {
515 Slog.w(TAG, "Can't close default wallpaper stream", e);
516 }
Lucas Dupinbcae5852017-05-03 12:42:58 -0700517 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700518
Lucas Dupin84b89d92017-05-09 12:16:19 -0700519 if (colors == null) {
Lucas Dupinbcae5852017-05-03 12:42:58 -0700520 Slog.w(TAG, "Cannot extract colors because wallpaper could not be read.");
521 return;
522 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700523
Lucas Dupinbcae5852017-05-03 12:42:58 -0700524 synchronized (mLock) {
525 if (wallpaper.wallpaperId == wallpaperId) {
Lucas Dupin84b89d92017-05-09 12:16:19 -0700526 wallpaper.primaryColors = colors;
Lucas Dupin75ec3792017-06-29 14:07:18 -0700527 // Now that we have the colors, let's save them into the xml
528 // to avoid having to run this again.
529 saveSettingsLocked(wallpaper.userId);
Lucas Dupinbcae5852017-05-03 12:42:58 -0700530 } else {
531 Slog.w(TAG, "Not setting primary colors since wallpaper changed");
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700532 }
533 }
534 }
535
wilsonshih36597d42018-12-05 18:56:39 +0800536 private void extractDefaultImageWallpaperColors() {
537 synchronized (mLock) {
538 if (mFallbackWallpaper.primaryColors != null) return;
539 }
540
541 if (DEBUG) Slog.d(TAG, "Extract default image wallpaper colors");
542 WallpaperColors colors = null;
543 final InputStream is = WallpaperManager.openDefaultWallpaper(mContext, FLAG_SYSTEM);
544 if (is != null) {
545 try {
546 final BitmapFactory.Options options = new BitmapFactory.Options();
547 final Bitmap bitmap = BitmapFactory.decodeStream(is, null, options);
548 if (bitmap != null) {
549 colors = WallpaperColors.fromBitmap(bitmap);
550 bitmap.recycle();
551 }
552 } catch (OutOfMemoryError e) {
553 Slog.w(TAG, "Can't decode default wallpaper stream", e);
554 } finally {
555 IoUtils.closeQuietly(is);
556 }
557 }
558
559 if (colors == null) {
560 Slog.e(TAG, "Extract default image wallpaper colors failed");
561 return;
562 }
563
564 synchronized (mLock) {
565 mFallbackWallpaper.primaryColors = colors;
566 }
567 }
568
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800569 /**
570 * Once a new wallpaper has been written via setWallpaper(...), it needs to be cropped
571 * for display.
572 */
573 private void generateCrop(WallpaperData wallpaper) {
574 boolean success = false;
Christopher Tate1a96b632016-03-22 15:25:42 -0700575
wilsonshih81e10a72018-11-15 10:54:21 +0800576 // Only generate crop for default display.
wilsonshiha282bf72018-11-30 12:48:05 +0800577 final DisplayData wpData = getDisplayDataOrCreate(DEFAULT_DISPLAY);
Christopher Tate1a96b632016-03-22 15:25:42 -0700578 Rect cropHint = new Rect(wallpaper.cropHint);
Christopher Tatebe132e62016-02-10 12:59:49 -0800579
580 if (DEBUG) {
581 Slog.v(TAG, "Generating crop for new wallpaper(s): 0x"
582 + Integer.toHexString(wallpaper.whichPending)
Christopher Tate1a96b632016-03-22 15:25:42 -0700583 + " to " + wallpaper.cropFile.getName()
584 + " crop=(" + cropHint.width() + 'x' + cropHint.height()
wilsonshih81e10a72018-11-15 10:54:21 +0800585 + ") dim=(" + wpData.mWidth + 'x' + wpData.mHeight + ')');
Christopher Tatebe132e62016-02-10 12:59:49 -0800586 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800587
588 // Analyse the source; needed in multiple cases
589 BitmapFactory.Options options = new BitmapFactory.Options();
590 options.inJustDecodeBounds = true;
591 BitmapFactory.decodeFile(wallpaper.wallpaperFile.getAbsolutePath(), options);
Christopher Tate1a96b632016-03-22 15:25:42 -0700592 if (options.outWidth <= 0 || options.outHeight <= 0) {
Joe LaPennac298b162016-05-02 15:25:50 -0700593 Slog.w(TAG, "Invalid wallpaper data");
Christopher Tate1a96b632016-03-22 15:25:42 -0700594 success = false;
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800595 } else {
Christopher Tate1a96b632016-03-22 15:25:42 -0700596 boolean needCrop = false;
597 boolean needScale = false;
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800598
Christopher Tate1a96b632016-03-22 15:25:42 -0700599 // Empty crop means use the full image
600 if (cropHint.isEmpty()) {
601 cropHint.left = cropHint.top = 0;
602 cropHint.right = options.outWidth;
603 cropHint.bottom = options.outHeight;
604 } else {
605 // force the crop rect to lie within the measured bounds
606 cropHint.offset(
607 (cropHint.right > options.outWidth ? options.outWidth - cropHint.right : 0),
608 (cropHint.bottom > options.outHeight ? options.outHeight - cropHint.bottom : 0));
609
Adrian Roos5c97ff22016-08-31 10:25:38 -0700610 // If the crop hint was larger than the image we just overshot. Patch things up.
611 if (cropHint.left < 0) {
612 cropHint.left = 0;
613 }
614 if (cropHint.top < 0) {
615 cropHint.top = 0;
616 }
617
Christopher Tate1a96b632016-03-22 15:25:42 -0700618 // Don't bother cropping if what we're left with is identity
Christopher Tateebadfb12016-07-25 14:50:08 -0700619 needCrop = (options.outHeight > cropHint.height()
Adrian Roos5c97ff22016-08-31 10:25:38 -0700620 || options.outWidth > cropHint.width());
Christopher Tate1a96b632016-03-22 15:25:42 -0700621 }
622
623 // scale if the crop height winds up not matching the recommended metrics
wilsonshih81e10a72018-11-15 10:54:21 +0800624 needScale = (wpData.mHeight != cropHint.height());
Christopher Tate1a96b632016-03-22 15:25:42 -0700625
Valentin Iftime3047bb12018-12-28 17:02:19 +0100626 //make sure screen aspect ratio is preserved if width is scaled under screen size
627 if (needScale) {
628 final DisplayInfo displayInfo = new DisplayInfo();
629 mDisplayManager.getDisplay(DEFAULT_DISPLAY).getDisplayInfo(displayInfo);
630 final float scaleByHeight = (float) wpData.mHeight / (float) cropHint.height();
631 final int newWidth = (int) (cropHint.width() * scaleByHeight);
632 if (newWidth < displayInfo.logicalWidth) {
633 final float screenAspectRatio =
634 (float) displayInfo.logicalHeight / (float) displayInfo.logicalWidth;
635 cropHint.bottom = (int) (cropHint.width() * screenAspectRatio);
636 needCrop = true;
637 }
638 }
639
Christopher Tate1a96b632016-03-22 15:25:42 -0700640 if (DEBUG) {
641 Slog.v(TAG, "crop: w=" + cropHint.width() + " h=" + cropHint.height());
wilsonshih81e10a72018-11-15 10:54:21 +0800642 Slog.v(TAG, "dims: w=" + wpData.mWidth + " h=" + wpData.mHeight);
Christopher Tate1a96b632016-03-22 15:25:42 -0700643 Slog.v(TAG, "meas: w=" + options.outWidth + " h=" + options.outHeight);
644 Slog.v(TAG, "crop?=" + needCrop + " scale?=" + needScale);
645 }
646
647 if (!needCrop && !needScale) {
648 // Simple case: the nominal crop fits what we want, so we take
649 // the whole thing and just copy the image file directly.
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800650 if (DEBUG) {
Christopher Tate1a96b632016-03-22 15:25:42 -0700651 Slog.v(TAG, "Null crop of new wallpaper; copying");
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800652 }
Christopher Tate1a96b632016-03-22 15:25:42 -0700653 success = FileUtils.copyFile(wallpaper.wallpaperFile, wallpaper.cropFile);
654 if (!success) {
655 wallpaper.cropFile.delete();
656 // TODO: fall back to default wallpaper in this case
657 }
658 } else {
659 // Fancy case: crop and scale. First, we decode and scale down if appropriate.
660 FileOutputStream f = null;
661 BufferedOutputStream bos = null;
662 try {
663 BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(
664 wallpaper.wallpaperFile.getAbsolutePath(), false);
665
666 // This actually downsamples only by powers of two, but that's okay; we do
667 // a proper scaling blit later. This is to minimize transient RAM use.
668 // We calculate the largest power-of-two under the actual ratio rather than
669 // just let the decode take care of it because we also want to remap where the
670 // cropHint rectangle lies in the decoded [super]rect.
671 final BitmapFactory.Options scaler;
wilsonshih81e10a72018-11-15 10:54:21 +0800672 final int actualScale = cropHint.height() / wpData.mHeight;
Christopher Tate1a96b632016-03-22 15:25:42 -0700673 int scale = 1;
674 while (2*scale < actualScale) {
675 scale *= 2;
676 }
677 if (scale > 1) {
678 scaler = new BitmapFactory.Options();
679 scaler.inSampleSize = scale;
680 if (DEBUG) {
681 Slog.v(TAG, "Downsampling cropped rect with scale " + scale);
682 }
683 } else {
684 scaler = null;
685 }
686 Bitmap cropped = decoder.decodeRegion(cropHint, scaler);
687 decoder.recycle();
688
689 if (cropped == null) {
690 Slog.e(TAG, "Could not decode new wallpaper");
691 } else {
692 // We've got the extracted crop; now we want to scale it properly to
693 // the desired rectangle. That's a height-biased operation: make it
694 // fit the hinted height, and accept whatever width we end up with.
695 cropHint.offsetTo(0, 0);
696 cropHint.right /= scale; // adjust by downsampling factor
697 cropHint.bottom /= scale;
wilsonshih81e10a72018-11-15 10:54:21 +0800698 final float heightR =
699 ((float) wpData.mHeight) / ((float) cropHint.height());
Christopher Tate1a96b632016-03-22 15:25:42 -0700700 if (DEBUG) {
701 Slog.v(TAG, "scale " + heightR + ", extracting " + cropHint);
702 }
703 final int destWidth = (int)(cropHint.width() * heightR);
704 final Bitmap finalCrop = Bitmap.createScaledBitmap(cropped,
wilsonshih81e10a72018-11-15 10:54:21 +0800705 destWidth, wpData.mHeight, true);
Christopher Tate1a96b632016-03-22 15:25:42 -0700706 if (DEBUG) {
707 Slog.v(TAG, "Final extract:");
wilsonshih81e10a72018-11-15 10:54:21 +0800708 Slog.v(TAG, " dims: w=" + wpData.mWidth
709 + " h=" + wpData.mHeight);
Christopher Tate1a96b632016-03-22 15:25:42 -0700710 Slog.v(TAG, " out: w=" + finalCrop.getWidth()
711 + " h=" + finalCrop.getHeight());
712 }
713
714 f = new FileOutputStream(wallpaper.cropFile);
715 bos = new BufferedOutputStream(f, 32*1024);
Christopher Tatec484f542016-05-11 14:31:34 -0700716 finalCrop.compress(Bitmap.CompressFormat.JPEG, 100, bos);
Christopher Tate1a96b632016-03-22 15:25:42 -0700717 bos.flush(); // don't rely on the implicit flush-at-close when noting success
718 success = true;
719 }
720 } catch (Exception e) {
721 if (DEBUG) {
722 Slog.e(TAG, "Error decoding crop", e);
723 }
724 } finally {
725 IoUtils.closeQuietly(bos);
726 IoUtils.closeQuietly(f);
727 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800728 }
729 }
730
731 if (!success) {
732 Slog.e(TAG, "Unable to apply new wallpaper");
733 wallpaper.cropFile.delete();
734 }
735
736 if (wallpaper.cropFile.exists()) {
737 boolean didRestorecon = SELinux.restorecon(wallpaper.cropFile.getAbsoluteFile());
738 if (DEBUG) {
739 Slog.v(TAG, "restorecon() of crop file returned " + didRestorecon);
740 }
741 }
742 }
743
wilsonshiha282bf72018-11-30 12:48:05 +0800744 private final Context mContext;
745 private final IWindowManager mIWindowManager;
746 private final IPackageManager mIPackageManager;
747 private final MyPackageMonitor mMonitor;
748 private final AppOpsManager mAppOpsManager;
wilsonshihde93f492018-11-01 21:23:40 +0800749
750 private final DisplayManager mDisplayManager;
751 private final DisplayManager.DisplayListener mDisplayListener =
752 new DisplayManager.DisplayListener() {
753
754 @Override
755 public void onDisplayAdded(int displayId) {
756 synchronized (mLock) {
757 if (mLastWallpaper != null) {
wilsonshiha282bf72018-11-30 12:48:05 +0800758 if (supportsMultiDisplay(mLastWallpaper.connection)) {
759 final WallpaperConnection.DisplayConnector connector =
760 mLastWallpaper.connection.getDisplayConnectorOrCreate(displayId);
761 if (connector == null) return;
762 connector.connectLocked(mLastWallpaper.connection, mLastWallpaper);
763 return;
764 }
765 // System wallpaper does not support multiple displays, attach this display to
766 // the fallback wallpaper.
767 if (mFallbackWallpaper != null) {
768 final WallpaperConnection.DisplayConnector connector = mFallbackWallpaper
769 .connection.getDisplayConnectorOrCreate(displayId);
770 if (connector == null) return;
771 connector.connectLocked(mFallbackWallpaper.connection, mFallbackWallpaper);
772 } else {
773 Slog.w(TAG, "No wallpaper can be added to the new display");
774 }
wilsonshihde93f492018-11-01 21:23:40 +0800775 }
776 }
777 }
778
779 @Override
780 public void onDisplayRemoved(int displayId) {
781 synchronized (mLock) {
782 if (mLastWallpaper != null) {
wilsonshiha282bf72018-11-30 12:48:05 +0800783 WallpaperData targetWallpaper = null;
784 if (mLastWallpaper.connection.containsDisplay(displayId)) {
785 targetWallpaper = mLastWallpaper;
786 } else if (mFallbackWallpaper.connection.containsDisplay(displayId)) {
787 targetWallpaper = mFallbackWallpaper;
788 }
789 if (targetWallpaper == null) return;
790 WallpaperConnection.DisplayConnector connector =
791 targetWallpaper.connection.getDisplayConnectorOrCreate(displayId);
wilsonshihde93f492018-11-01 21:23:40 +0800792 if (connector == null) return;
793 connector.disconnectLocked();
wilsonshiha282bf72018-11-30 12:48:05 +0800794 targetWallpaper.connection.removeDisplayConnector(displayId);
795 removeDisplayData(displayId);
wilsonshihde93f492018-11-01 21:23:40 +0800796 }
wilsonshih36597d42018-12-05 18:56:39 +0800797 for (int i = mColorsChangedListeners.size() - 1; i >= 0; i--) {
798 final SparseArray<RemoteCallbackList<IWallpaperManagerCallback>> callbacks =
799 mColorsChangedListeners.valueAt(i);
800 callbacks.delete(displayId);
801 }
wilsonshihde93f492018-11-01 21:23:40 +0800802 }
803 }
804
805 @Override
806 public void onDisplayChanged(int displayId) {
wilsonshihde93f492018-11-01 21:23:40 +0800807 }
808 };
809
Lucas Dupin50ba9912017-07-14 11:55:05 -0700810 /**
811 * Map of color listeners per user id.
wilsonshih36597d42018-12-05 18:56:39 +0800812 * The first key will be the id of a user or UserHandle.USER_ALL - for wildcard listeners.
813 * The secondary key will be the display id, which means which display the listener is
814 * interested in.
Lucas Dupin50ba9912017-07-14 11:55:05 -0700815 */
wilsonshih36597d42018-12-05 18:56:39 +0800816 private final SparseArray<SparseArray<RemoteCallbackList<IWallpaperManagerCallback>>>
wilsonshiha282bf72018-11-30 12:48:05 +0800817 mColorsChangedListeners;
818 private WallpaperData mLastWallpaper;
819 private IWallpaperManagerCallback mKeyguardListener;
820 private boolean mWaitingForUnlock;
821 private boolean mShuttingDown;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800822
Justin Koh29c30162014-09-05 17:10:10 -0700823 /**
Christopher Tatead3c2592016-01-20 18:13:17 -0800824 * ID of the current wallpaper, changed every time anything sets a wallpaper.
825 * This is used for external detection of wallpaper update activity.
826 */
wilsonshiha282bf72018-11-30 12:48:05 +0800827 private int mWallpaperId;
Christopher Tatead3c2592016-01-20 18:13:17 -0800828
829 /**
Justin Koh29c30162014-09-05 17:10:10 -0700830 * Name of the component used to display bitmap wallpapers from either the gallery or
831 * built-in wallpapers.
832 */
wilsonshiha282bf72018-11-30 12:48:05 +0800833 private final ComponentName mImageWallpaper;
Justin Koh29c30162014-09-05 17:10:10 -0700834
Christopher Tate2a6c55f2017-03-31 12:28:30 -0700835 /**
836 * Name of the default wallpaper component; might be different from mImageWallpaper
837 */
wilsonshiha282bf72018-11-30 12:48:05 +0800838 private final ComponentName mDefaultWallpaperComponent;
Christopher Tate2a6c55f2017-03-31 12:28:30 -0700839
wilsonshiha282bf72018-11-30 12:48:05 +0800840 private final SparseArray<WallpaperData> mWallpaperMap = new SparseArray<WallpaperData>();
841 private final SparseArray<WallpaperData> mLockWallpaperMap = new SparseArray<WallpaperData>();
Dianne Hackborn07213e62011-08-24 20:05:39 -0700842
wilsonshiha282bf72018-11-30 12:48:05 +0800843 private SparseArray<DisplayData> mDisplayDatas = new SparseArray<>();
844
845 private WallpaperData mFallbackWallpaper;
846
847 private final SparseBooleanArray mUserRestorecon = new SparseBooleanArray();
848 private int mCurrentUserId = UserHandle.USER_NULL;
849 private boolean mInAmbientMode;
Dianne Hackborn07213e62011-08-24 20:05:39 -0700850
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800851 static class WallpaperData {
852
853 int userId;
854
Christopher Tatebe132e62016-02-10 12:59:49 -0800855 final File wallpaperFile; // source image
856 final File cropFile; // eventual destination
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800857
858 /**
Christopher Tatebe132e62016-02-10 12:59:49 -0800859 * True while the client is writing a new wallpaper
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800860 */
861 boolean imageWallpaperPending;
862
863 /**
Christopher Tatebe132e62016-02-10 12:59:49 -0800864 * Which new wallpapers are being written; mirrors the 'which'
865 * selector bit field to setWallpaper().
866 */
867 int whichPending;
868
869 /**
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800870 * Callback once the set + crop is finished
871 */
872 IWallpaperManagerCallback setComplete;
873
874 /**
Christopher Tated7faf532016-02-25 12:43:38 -0800875 * Is the OS allowed to back up this wallpaper imagery?
876 */
877 boolean allowBackup;
878
879 /**
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800880 * Resource name if using a picture from the wallpaper gallery
881 */
882 String name = "";
883
884 /**
885 * The component name of the currently set live wallpaper.
886 */
887 ComponentName wallpaperComponent;
888
889 /**
890 * The component name of the wallpaper that should be set next.
891 */
892 ComponentName nextWallpaperComponent;
893
Christopher Tatead3c2592016-01-20 18:13:17 -0800894 /**
895 * The ID of this wallpaper
896 */
897 int wallpaperId;
898
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700899 /**
900 * Primary colors histogram
901 */
902 WallpaperColors primaryColors;
903
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800904 WallpaperConnection connection;
905 long lastDiedTime;
906 boolean wallpaperUpdating;
907 WallpaperObserver wallpaperObserver;
908
909 /**
910 * List of callbacks registered they should each be notified when the wallpaper is changed.
911 */
912 private RemoteCallbackList<IWallpaperManagerCallback> callbacks
913 = new RemoteCallbackList<IWallpaperManagerCallback>();
914
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800915 /**
916 * The crop hint supplied for displaying a subset of the source image
917 */
918 final Rect cropHint = new Rect(0, 0, 0, 0);
919
Christopher Tatebe132e62016-02-10 12:59:49 -0800920 WallpaperData(int userId, String inputFileName, String cropFileName) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800921 this.userId = userId;
Christopher Tatebe132e62016-02-10 12:59:49 -0800922 final File wallpaperDir = getWallpaperDir(userId);
923 wallpaperFile = new File(wallpaperDir, inputFileName);
924 cropFile = new File(wallpaperDir, cropFileName);
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800925 }
926
Christopher Tatebe132e62016-02-10 12:59:49 -0800927 // Called during initialization of a given user's wallpaper bookkeeping
Christopher Tate41297ff2016-03-10 16:46:15 -0800928 boolean cropExists() {
929 return cropFile.exists();
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800930 }
Christopher Tate2a6c55f2017-03-31 12:28:30 -0700931
932 boolean sourceExists() {
933 return wallpaperFile.exists();
934 }
wilsonshiha282bf72018-11-30 12:48:05 +0800935 }
wilsonshih81e10a72018-11-15 10:54:21 +0800936
wilsonshiha282bf72018-11-30 12:48:05 +0800937 private static final class DisplayData {
938 int mWidth = -1;
939 int mHeight = -1;
940 final Rect mPadding = new Rect(0, 0, 0, 0);
941 final int mDisplayId;
942
943 DisplayData(int displayId) {
944 mDisplayId = displayId;
wilsonshih81e10a72018-11-15 10:54:21 +0800945 }
946 }
947
wilsonshiha282bf72018-11-30 12:48:05 +0800948 private void removeDisplayData(int displayId) {
949 mDisplayDatas.remove(displayId);
950 }
951
952 private DisplayData getDisplayDataOrCreate(int displayId) {
953 DisplayData wpdData = mDisplayDatas.get(displayId);
wilsonshih81e10a72018-11-15 10:54:21 +0800954 if (wpdData == null) {
wilsonshiha282bf72018-11-30 12:48:05 +0800955 wpdData = new DisplayData(displayId);
wilsonshih81e10a72018-11-15 10:54:21 +0800956 ensureSaneWallpaperDisplaySize(wpdData, displayId);
wilsonshiha282bf72018-11-30 12:48:05 +0800957 mDisplayDatas.append(displayId, wpdData);
wilsonshih81e10a72018-11-15 10:54:21 +0800958 }
959 return wpdData;
960 }
961
wilsonshiha282bf72018-11-30 12:48:05 +0800962 private void ensureSaneWallpaperDisplaySize(DisplayData wpdData, int displayId) {
wilsonshih81e10a72018-11-15 10:54:21 +0800963 // We always want to have some reasonable width hint.
964 final int baseSize = getMaximumSizeDimension(displayId);
965 if (wpdData.mWidth < baseSize) {
966 wpdData.mWidth = baseSize;
967 }
968 if (wpdData.mHeight < baseSize) {
969 wpdData.mHeight = baseSize;
970 }
971 }
972
973 private int getMaximumSizeDimension(int displayId) {
974 Display display = mDisplayManager.getDisplay(displayId);
wilsonshiha282bf72018-11-30 12:48:05 +0800975 if (display == null) {
976 Slog.w(TAG, "Invalid displayId=" + displayId + " " + Debug.getCallers(4));
977 display = mDisplayManager.getDisplay(DEFAULT_DISPLAY);
978 }
wilsonshih81e10a72018-11-15 10:54:21 +0800979 return display.getMaximumSizeDimension();
980 }
981
wilsonshiha282bf72018-11-30 12:48:05 +0800982 void forEachDisplayData(Consumer<DisplayData> action) {
983 for (int i = mDisplayDatas.size() - 1; i >= 0; i--) {
984 final DisplayData wpdData = mDisplayDatas.valueAt(i);
wilsonshih81e10a72018-11-15 10:54:21 +0800985 action.accept(wpdData);
986 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800987 }
988
Christopher Tatead3c2592016-01-20 18:13:17 -0800989 int makeWallpaperIdLocked() {
990 do {
991 ++mWallpaperId;
992 } while (mWallpaperId == 0);
993 return mWallpaperId;
994 }
995
wilsonshiha282bf72018-11-30 12:48:05 +0800996 private boolean supportsMultiDisplay(WallpaperConnection connection) {
997 if (connection != null) {
998 return connection.mInfo == null // This is image wallpaper
999 || connection.mInfo.supportsMultipleDisplays();
1000 }
1001 return false;
1002 }
1003
1004 private void updateFallbackConnection() {
1005 if (mLastWallpaper == null || mFallbackWallpaper == null) return;
1006 final WallpaperConnection systemConnection = mLastWallpaper.connection;
1007 final WallpaperConnection fallbackConnection = mFallbackWallpaper.connection;
wilsonshih78268c32018-12-18 20:48:28 +08001008 if (fallbackConnection == null) {
1009 Slog.w(TAG, "Fallback wallpaper connection has not been created yet!!");
1010 return;
1011 }
wilsonshih507ada52019-01-19 11:22:09 +08001012 if (supportsMultiDisplay(systemConnection)) {
1013 if (fallbackConnection.mDisplayConnector.size() != 0) {
1014 fallbackConnection.forEachDisplayConnector(connector -> {
1015 if (connector.mEngine != null) {
1016 connector.disconnectLocked();
1017 }
1018 });
1019 fallbackConnection.mDisplayConnector.clear();
1020 }
wilsonshiha282bf72018-11-30 12:48:05 +08001021 } else {
1022 fallbackConnection.appendConnectorWithCondition(display ->
1023 fallbackConnection.isUsableDisplay(display)
1024 && display.getDisplayId() != DEFAULT_DISPLAY
1025 && !fallbackConnection.containsDisplay(display.getDisplayId()));
1026 fallbackConnection.forEachDisplayConnector(connector -> {
1027 if (connector.mEngine == null) {
1028 connector.connectLocked(fallbackConnection, mFallbackWallpaper);
1029 }
1030 });
1031 }
1032 }
1033
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001034 class WallpaperConnection extends IWallpaperConnection.Stub
1035 implements ServiceConnection {
Adrian Roosc3f915e2016-09-06 11:40:53 -07001036
wilsonshihde93f492018-11-01 21:23:40 +08001037 /**
1038 * Collect needed info for a display.
1039 */
1040 private final class DisplayConnector {
1041 final int mDisplayId;
1042 final Binder mToken = new Binder();
1043 IWallpaperEngine mEngine;
1044 boolean mDimensionsChanged;
1045 boolean mPaddingChanged;
1046
1047 DisplayConnector(int displayId) {
1048 mDisplayId = displayId;
1049 }
1050
1051 void ensureStatusHandled() {
wilsonshiha282bf72018-11-30 12:48:05 +08001052 final DisplayData wpdData = getDisplayDataOrCreate(mDisplayId);
wilsonshihde93f492018-11-01 21:23:40 +08001053 if (mDimensionsChanged) {
1054 try {
wilsonshih81e10a72018-11-15 10:54:21 +08001055 mEngine.setDesiredSize(wpdData.mWidth, wpdData.mHeight);
wilsonshihde93f492018-11-01 21:23:40 +08001056 } catch (RemoteException e) {
1057 Slog.w(TAG, "Failed to set wallpaper dimensions", e);
1058 }
1059 mDimensionsChanged = false;
1060 }
1061 if (mPaddingChanged) {
1062 try {
wilsonshih81e10a72018-11-15 10:54:21 +08001063 mEngine.setDisplayPadding(wpdData.mPadding);
wilsonshihde93f492018-11-01 21:23:40 +08001064 } catch (RemoteException e) {
1065 Slog.w(TAG, "Failed to set wallpaper padding", e);
1066 }
1067 mPaddingChanged = false;
1068 }
1069 }
1070
1071 void connectLocked(WallpaperConnection connection, WallpaperData wallpaper) {
wilsonshih674a4a02018-12-19 11:47:25 +08001072 if (connection.mService == null) {
1073 Slog.w(TAG, "WallpaperService is not connected yet");
1074 return;
1075 }
wilsonshihde93f492018-11-01 21:23:40 +08001076 if (DEBUG) Slog.v(TAG, "Adding window token: " + mToken);
1077 try {
1078 mIWindowManager.addWindowToken(mToken, TYPE_WALLPAPER, mDisplayId);
1079 } catch (RemoteException e) {
1080 Slog.e(TAG, "Failed add wallpaper window token on display " + mDisplayId, e);
1081 return;
1082 }
1083
wilsonshiha282bf72018-11-30 12:48:05 +08001084 final DisplayData wpdData = getDisplayDataOrCreate(mDisplayId);
wilsonshihde93f492018-11-01 21:23:40 +08001085 try {
wilsonshihde93f492018-11-01 21:23:40 +08001086 connection.mService.attach(connection, mToken, TYPE_WALLPAPER, false,
wilsonshih81e10a72018-11-15 10:54:21 +08001087 wpdData.mWidth, wpdData.mHeight,
1088 wpdData.mPadding, mDisplayId);
wilsonshihde93f492018-11-01 21:23:40 +08001089 } catch (RemoteException e) {
1090 Slog.w(TAG, "Failed attaching wallpaper on display", e);
wilsonshih674a4a02018-12-19 11:47:25 +08001091 if (wallpaper != null && !wallpaper.wallpaperUpdating
wilsonshih81e10a72018-11-15 10:54:21 +08001092 && connection.getConnectedEngineSize() == 0) {
wilsonshihde93f492018-11-01 21:23:40 +08001093 bindWallpaperComponentLocked(null /* componentName */, false /* force */,
1094 false /* fromUser */, wallpaper, null /* reply */);
1095 }
1096 }
1097 }
1098
1099 void disconnectLocked() {
1100 if (DEBUG) Slog.v(TAG, "Removing window token: " + mToken);
1101 try {
1102 mIWindowManager.removeWindowToken(mToken, mDisplayId);
1103 } catch (RemoteException e) {
1104 }
1105 try {
1106 if (mEngine != null) {
1107 mEngine.destroy();
1108 }
1109 } catch (RemoteException e) {
1110 }
1111 mEngine = null;
1112 }
1113 }
1114
1115 /**
1116 * A map for each display.
1117 * Use {@link #getDisplayConnectorOrCreate(int displayId)} to ensure the display is usable.
1118 */
1119 private SparseArray<DisplayConnector> mDisplayConnector = new SparseArray<>();
1120
Adrian Roosc3f915e2016-09-06 11:40:53 -07001121 /** Time in milliseconds until we expect the wallpaper to reconnect (unless we're in the
1122 * middle of an update). If exceeded, the wallpaper gets reset to the system default. */
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001123 private static final long WALLPAPER_RECONNECT_TIMEOUT_MS = 10000;
Adrian Roosc3f915e2016-09-06 11:40:53 -07001124
Dianne Hackborneb034652009-09-07 00:49:58 -07001125 final WallpaperInfo mInfo;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001126 IWallpaperService mService;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001127 WallpaperData mWallpaper;
wilsonshihde93f492018-11-01 21:23:40 +08001128 final int mClientUid;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001129 IRemoteCallback mReply;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001130
Adrian Roosc3f915e2016-09-06 11:40:53 -07001131 private Runnable mResetRunnable = () -> {
1132 synchronized (mLock) {
Christopher Tate762dfd12016-10-10 17:44:48 -07001133 if (mShuttingDown) {
1134 // Don't expect wallpaper services to relaunch during shutdown
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001135 if (DEBUG_LIVE) {
Christopher Tate762dfd12016-10-10 17:44:48 -07001136 Slog.i(TAG, "Ignoring relaunch timeout during shutdown");
1137 }
1138 return;
1139 }
1140
Adrian Roosc3f915e2016-09-06 11:40:53 -07001141 if (!mWallpaper.wallpaperUpdating
1142 && mWallpaper.userId == mCurrentUserId) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001143 Slog.w(TAG, "Wallpaper reconnect timed out for " + mWallpaper.wallpaperComponent
1144 + ", reverting to built-in wallpaper!");
Adrian Roosc3f915e2016-09-06 11:40:53 -07001145 clearWallpaperLocked(true, FLAG_SYSTEM, mWallpaper.userId,
1146 null);
1147 }
1148 }
1149 };
1150
wilsonshihde93f492018-11-01 21:23:40 +08001151 WallpaperConnection(WallpaperInfo info, WallpaperData wallpaper, int clientUid) {
Dianne Hackborneb034652009-09-07 00:49:58 -07001152 mInfo = info;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001153 mWallpaper = wallpaper;
wilsonshihde93f492018-11-01 21:23:40 +08001154 mClientUid = clientUid;
1155 initDisplayState();
1156 }
1157
1158 private void initDisplayState() {
wilsonshiha282bf72018-11-30 12:48:05 +08001159 // Do not initialize fallback wallpaper
1160 if (!mWallpaper.equals(mFallbackWallpaper)) {
1161 if (supportsMultiDisplay(this)) {
1162 // The system wallpaper is image wallpaper or it can supports multiple displays.
1163 appendConnectorWithCondition(this::isUsableDisplay);
1164 } else {
1165 // The system wallpaper does not support multiple displays, so just attach it on
1166 // default display.
1167 mDisplayConnector.append(DEFAULT_DISPLAY,
1168 new DisplayConnector(DEFAULT_DISPLAY));
wilsonshihde93f492018-11-01 21:23:40 +08001169 }
1170 }
1171 }
1172
wilsonshiha282bf72018-11-30 12:48:05 +08001173 private void appendConnectorWithCondition(Predicate<Display> tester) {
1174 final Display[] displays = mDisplayManager.getDisplays();
1175 for (Display display : displays) {
1176 if (tester.test(display)) {
1177 final int displayId = display.getDisplayId();
wilsonshih674a4a02018-12-19 11:47:25 +08001178 final DisplayConnector connector = mDisplayConnector.get(displayId);
1179 if (connector == null) {
1180 mDisplayConnector.append(displayId,
1181 new DisplayConnector(displayId));
1182 }
wilsonshiha282bf72018-11-30 12:48:05 +08001183 }
1184 }
1185 }
1186
wilsonshihde93f492018-11-01 21:23:40 +08001187 private boolean isUsableDisplay(Display display) {
1188 return display != null && display.hasAccess(mClientUid)
wilsonshihde93f492018-11-01 21:23:40 +08001189 && (display.supportsSystemDecorations()
1190 || display.getDisplayId() == DEFAULT_DISPLAY);
1191 }
1192
1193 void forEachDisplayConnector(Consumer<DisplayConnector> action) {
1194 for (int i = mDisplayConnector.size() - 1; i >= 0; i--) {
wilsonshih81e10a72018-11-15 10:54:21 +08001195 final DisplayConnector connector = mDisplayConnector.valueAt(i);
wilsonshihde93f492018-11-01 21:23:40 +08001196 action.accept(connector);
1197 }
1198 }
1199
wilsonshih81e10a72018-11-15 10:54:21 +08001200 int getConnectedEngineSize() {
1201 int engineSize = 0;
1202 for (int i = mDisplayConnector.size() - 1; i >= 0; i--) {
1203 final DisplayConnector connector = mDisplayConnector.valueAt(i);
1204 if (connector.mEngine != null) engineSize++;
1205 }
1206 return engineSize;
1207 }
1208
wilsonshihde93f492018-11-01 21:23:40 +08001209 DisplayConnector getDisplayConnectorOrCreate(int displayId) {
1210 DisplayConnector connector = mDisplayConnector.get(displayId);
1211 if (connector == null) {
1212 final Display display = mDisplayManager.getDisplay(displayId);
1213 if (isUsableDisplay(display)) {
1214 connector = new DisplayConnector(displayId);
1215 mDisplayConnector.append(displayId, connector);
1216 }
1217 }
1218 return connector;
1219 }
1220
wilsonshiha282bf72018-11-30 12:48:05 +08001221 boolean containsDisplay(int displayId) {
1222 return mDisplayConnector.get(displayId) != null;
1223 }
1224
wilsonshihde93f492018-11-01 21:23:40 +08001225 void removeDisplayConnector(int displayId) {
1226 final DisplayConnector connector = mDisplayConnector.get(displayId);
1227 if (connector != null) {
1228 mDisplayConnector.remove(displayId);
1229 }
Dianne Hackborneb034652009-09-07 00:49:58 -07001230 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001231
1232 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001233 public void onServiceConnected(ComponentName name, IBinder service) {
1234 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001235 if (mWallpaper.connection == this) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001236 mService = IWallpaperService.Stub.asInterface(service);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001237 attachServiceLocked(this, mWallpaper);
Dianne Hackborneb034652009-09-07 00:49:58 -07001238 // XXX should probably do saveSettingsLocked() later
1239 // when we have an engine, but I'm not sure about
1240 // locking there and anyway we always need to be able to
1241 // recover if there is something wrong.
wilsonshiha282bf72018-11-30 12:48:05 +08001242 if (!mWallpaper.equals(mFallbackWallpaper)) {
1243 saveSettingsLocked(mWallpaper.userId);
1244 }
Adrian Roosc3f915e2016-09-06 11:40:53 -07001245 FgThread.getHandler().removeCallbacks(mResetRunnable);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001246 }
1247 }
1248 }
1249
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001250 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001251 public void onServiceDisconnected(ComponentName name) {
1252 synchronized (mLock) {
Christopher Tatec349e59f2017-05-05 17:37:43 -07001253 Slog.w(TAG, "Wallpaper service gone: " + name);
1254 if (!Objects.equals(name, mWallpaper.wallpaperComponent)) {
1255 Slog.e(TAG, "Does not match expected wallpaper component "
1256 + mWallpaper.wallpaperComponent);
1257 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001258 mService = null;
wilsonshihde93f492018-11-01 21:23:40 +08001259 forEachDisplayConnector(connector -> connector.mEngine = null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001260 if (mWallpaper.connection == this) {
Christopher Tatec349e59f2017-05-05 17:37:43 -07001261 // There is an inherent ordering race between this callback and the
1262 // package monitor that receives notice that a package is being updated,
1263 // so we cannot quite trust at this moment that we know for sure that
1264 // this is not an update. If we think this is a genuine non-update
1265 // wallpaper outage, we do our "wait for reset" work as a continuation,
1266 // a short time in the future, specifically to allow any pending package
1267 // update message on this same looper thread to be processed.
1268 if (!mWallpaper.wallpaperUpdating) {
1269 mContext.getMainThreadHandler().postDelayed(() -> processDisconnect(this),
1270 1000);
1271 }
1272 }
1273 }
1274 }
1275
Tetsutoki Shiozawa06919212018-02-02 14:18:43 +09001276 public void scheduleTimeoutLocked() {
1277 // If we didn't reset it right away, do so after we couldn't connect to
1278 // it for an extended amount of time to avoid having a black wallpaper.
1279 final Handler fgHandler = FgThread.getHandler();
1280 fgHandler.removeCallbacks(mResetRunnable);
1281 fgHandler.postDelayed(mResetRunnable, WALLPAPER_RECONNECT_TIMEOUT_MS);
1282 if (DEBUG_LIVE) {
wilsonshihde93f492018-11-01 21:23:40 +08001283 Slog.i(TAG,
1284 "Started wallpaper reconnect timeout for " + mWallpaper.wallpaperComponent);
Tetsutoki Shiozawa06919212018-02-02 14:18:43 +09001285 }
1286 }
1287
Christopher Tatec349e59f2017-05-05 17:37:43 -07001288 private void processDisconnect(final ServiceConnection connection) {
1289 synchronized (mLock) {
1290 // The wallpaper disappeared. If this isn't a system-default one, track
1291 // crashes and fall back to default if it continues to misbehave.
1292 if (connection == mWallpaper.connection) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001293 final ComponentName wpService = mWallpaper.wallpaperComponent;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001294 if (!mWallpaper.wallpaperUpdating
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001295 && mWallpaper.userId == mCurrentUserId
1296 && !Objects.equals(mDefaultWallpaperComponent, wpService)
1297 && !Objects.equals(mImageWallpaper, wpService)) {
Selim Cinekebebadb2014-03-05 22:17:26 +01001298 // There is a race condition which causes
1299 // {@link #mWallpaper.wallpaperUpdating} to be false even if it is
1300 // currently updating since the broadcast notifying us is async.
1301 // This race is overcome by the general rule that we only reset the
1302 // wallpaper if its service was shut down twice
1303 // during {@link #MIN_WALLPAPER_CRASH_TIME} millis.
1304 if (mWallpaper.lastDiedTime != 0
1305 && mWallpaper.lastDiedTime + MIN_WALLPAPER_CRASH_TIME
Christopher Tatec349e59f2017-05-05 17:37:43 -07001306 > SystemClock.uptimeMillis()) {
Selim Cinekebebadb2014-03-05 22:17:26 +01001307 Slog.w(TAG, "Reverting to built-in wallpaper!");
Christopher Tateedf7d042016-03-29 18:24:25 -07001308 clearWallpaperLocked(true, FLAG_SYSTEM, mWallpaper.userId, null);
Selim Cinekebebadb2014-03-05 22:17:26 +01001309 } else {
1310 mWallpaper.lastDiedTime = SystemClock.uptimeMillis();
Adrian Roosc3f915e2016-09-06 11:40:53 -07001311
Tetsutoki Shiozawa06919212018-02-02 14:18:43 +09001312 clearWallpaperComponentLocked(mWallpaper);
1313 if (bindWallpaperComponentLocked(
1314 wpService, false, false, mWallpaper, null)) {
1315 mWallpaper.connection.scheduleTimeoutLocked();
1316 } else {
1317 Slog.w(TAG, "Reverting to built-in wallpaper!");
1318 clearWallpaperLocked(true, FLAG_SYSTEM, mWallpaper.userId, null);
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001319 }
Selim Cinekebebadb2014-03-05 22:17:26 +01001320 }
Christopher Tatec349e59f2017-05-05 17:37:43 -07001321 final String flattened = wpService.flattenToString();
Filip Gruszczynski5dcc3ac2014-10-13 15:51:39 -07001322 EventLog.writeEvent(EventLogTags.WP_WALLPAPER_CRASHED,
Filip Gruszczynski5a589432014-10-14 12:06:06 -07001323 flattened.substring(0, Math.min(flattened.length(),
1324 MAX_WALLPAPER_COMPONENT_LOG_LENGTH)));
Dianne Hackborn0cd48872009-08-13 18:51:59 -07001325 }
Christopher Tatec349e59f2017-05-05 17:37:43 -07001326 } else {
1327 if (DEBUG_LIVE) {
1328 Slog.i(TAG, "Wallpaper changed during disconnect tracking; ignoring");
1329 }
Dianne Hackborn0cd48872009-08-13 18:51:59 -07001330 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001331 }
1332 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001333
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07001334 /**
1335 * Called by a live wallpaper if its colors have changed.
1336 * @param primaryColors representation of wallpaper primary colors
wilsonshih36597d42018-12-05 18:56:39 +08001337 * @param displayId for which display
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07001338 */
1339 @Override
wilsonshih36597d42018-12-05 18:56:39 +08001340 public void onWallpaperColorsChanged(WallpaperColors primaryColors, int displayId) {
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07001341 int which;
1342 synchronized (mLock) {
1343 // Do not broadcast changes on ImageWallpaper since it's handled
1344 // internally by this class.
1345 if (mImageWallpaper.equals(mWallpaper.wallpaperComponent)) {
1346 return;
1347 }
1348
1349 mWallpaper.primaryColors = primaryColors;
1350
1351 // Live wallpapers always are system wallpapers.
1352 which = FLAG_SYSTEM;
wilsonshih36597d42018-12-05 18:56:39 +08001353 // It's also the lock screen wallpaper when we don't have a bitmap in there.
1354 if (displayId == DEFAULT_DISPLAY) {
1355 final WallpaperData lockedWallpaper = mLockWallpaperMap.get(mWallpaper.userId);
1356 if (lockedWallpaper == null) {
1357 which |= FLAG_LOCK;
1358 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07001359 }
1360 }
1361 if (which != 0) {
wilsonshih36597d42018-12-05 18:56:39 +08001362 notifyWallpaperColorsChangedOnDisplay(mWallpaper, which, displayId);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07001363 }
1364 }
1365
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001366 @Override
wilsonshihde93f492018-11-01 21:23:40 +08001367 public void attachEngine(IWallpaperEngine engine, int displayId) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001368 synchronized (mLock) {
wilsonshihde93f492018-11-01 21:23:40 +08001369 final DisplayConnector connector = getDisplayConnectorOrCreate(displayId);
1370 if (connector == null) {
Michael Wright5203a8b2013-10-03 14:16:42 -07001371 try {
wilsonshihde93f492018-11-01 21:23:40 +08001372 engine.destroy();
Michael Wright5203a8b2013-10-03 14:16:42 -07001373 } catch (RemoteException e) {
wilsonshihde93f492018-11-01 21:23:40 +08001374 Slog.w(TAG, "Failed to destroy engine", e);
Michael Wright5203a8b2013-10-03 14:16:42 -07001375 }
wilsonshihde93f492018-11-01 21:23:40 +08001376 return;
Michael Wright5203a8b2013-10-03 14:16:42 -07001377 }
wilsonshihde93f492018-11-01 21:23:40 +08001378 connector.mEngine = engine;
1379 connector.ensureStatusHandled();
1380
1381 // TODO(multi-display) TBD.
1382 if (mInfo != null && mInfo.supportsAmbientMode() && displayId == DEFAULT_DISPLAY) {
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001383 try {
Lucas Dupin4c8c3272018-11-06 17:47:48 -08001384 connector.mEngine.setInAmbientMode(mInAmbientMode, 0L /* duration */);
Lucas Dupin7517b5d2017-08-22 12:51:25 -07001385 } catch (RemoteException e) {
1386 Slog.w(TAG, "Failed to set ambient mode state", e);
1387 }
1388 }
wilsonshih36597d42018-12-05 18:56:39 +08001389 try {
1390 // This will trigger onComputeColors in the wallpaper engine.
1391 // It's fine to be locked in here since the binder is oneway.
1392 connector.mEngine.requestWallpaperColors();
1393 } catch (RemoteException e) {
1394 Slog.w(TAG, "Failed to request wallpaper colors", e);
Lucas Dupin50ba9912017-07-14 11:55:05 -07001395 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001396 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001397 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001398
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001399 @Override
1400 public void engineShown(IWallpaperEngine engine) {
1401 synchronized (mLock) {
1402 if (mReply != null) {
1403 long ident = Binder.clearCallingIdentity();
1404 try {
1405 mReply.sendResult(null);
1406 } catch (RemoteException e) {
1407 Binder.restoreCallingIdentity(ident);
1408 }
1409 mReply = null;
1410 }
1411 }
1412 }
1413
1414 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001415 public ParcelFileDescriptor setWallpaper(String name) {
1416 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001417 if (mWallpaper.connection == this) {
Christopher Tatead3c2592016-01-20 18:13:17 -08001418 return updateWallpaperBitmapLocked(name, mWallpaper, null);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001419 }
1420 return null;
1421 }
1422 }
1423 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001424
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001425 class MyPackageMonitor extends PackageMonitor {
1426 @Override
1427 public void onPackageUpdateFinished(String packageName, int uid) {
1428 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -07001429 if (mCurrentUserId != getChangingUserId()) {
1430 return;
1431 }
1432 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
1433 if (wallpaper != null) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001434 final ComponentName wpService = wallpaper.wallpaperComponent;
1435 if (wpService != null && wpService.getPackageName().equals(packageName)) {
1436 if (DEBUG_LIVE) {
1437 Slog.i(TAG, "Wallpaper " + wpService + " update has finished");
1438 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001439 wallpaper.wallpaperUpdating = false;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001440 clearWallpaperComponentLocked(wallpaper);
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001441 if (!bindWallpaperComponentLocked(wpService, false, false,
Dianne Hackbornc72fc672012-09-20 13:12:03 -07001442 wallpaper, null)) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001443 Slog.w(TAG, "Wallpaper " + wpService
1444 + " no longer available; reverting to default");
Christopher Tateedf7d042016-03-29 18:24:25 -07001445 clearWallpaperLocked(false, FLAG_SYSTEM, wallpaper.userId, null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001446 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001447 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001448 }
1449 }
1450 }
1451
1452 @Override
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001453 public void onPackageModified(String packageName) {
1454 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -07001455 if (mCurrentUserId != getChangingUserId()) {
1456 return;
1457 }
1458 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
1459 if (wallpaper != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001460 if (wallpaper.wallpaperComponent == null
1461 || !wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -07001462 return;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001463 }
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001464 doPackagesChangedLocked(true, wallpaper);
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001465 }
1466 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001467 }
1468
1469 @Override
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001470 public void onPackageUpdateStarted(String packageName, int uid) {
1471 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -07001472 if (mCurrentUserId != getChangingUserId()) {
1473 return;
1474 }
1475 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
1476 if (wallpaper != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001477 if (wallpaper.wallpaperComponent != null
1478 && wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001479 if (DEBUG_LIVE) {
1480 Slog.i(TAG, "Wallpaper service " + wallpaper.wallpaperComponent
1481 + " is updating");
1482 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001483 wallpaper.wallpaperUpdating = true;
Adrian Roosc3f915e2016-09-06 11:40:53 -07001484 if (wallpaper.connection != null) {
1485 FgThread.getHandler().removeCallbacks(
1486 wallpaper.connection.mResetRunnable);
1487 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001488 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001489 }
1490 }
1491 }
1492
1493 @Override
1494 public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001495 synchronized (mLock) {
1496 boolean changed = false;
Dianne Hackbornc72fc672012-09-20 13:12:03 -07001497 if (mCurrentUserId != getChangingUserId()) {
1498 return false;
1499 }
1500 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
1501 if (wallpaper != null) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001502 boolean res = doPackagesChangedLocked(doit, wallpaper);
1503 changed |= res;
1504 }
1505 return changed;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001506 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001507 }
1508
1509 @Override
1510 public void onSomePackagesChanged() {
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001511 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -07001512 if (mCurrentUserId != getChangingUserId()) {
1513 return;
1514 }
1515 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
1516 if (wallpaper != null) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001517 doPackagesChangedLocked(true, wallpaper);
1518 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001519 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001520 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001521
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001522 boolean doPackagesChangedLocked(boolean doit, WallpaperData wallpaper) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001523 boolean changed = false;
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001524 if (wallpaper.wallpaperComponent != null) {
1525 int change = isPackageDisappearing(wallpaper.wallpaperComponent
1526 .getPackageName());
1527 if (change == PACKAGE_PERMANENT_CHANGE
1528 || change == PACKAGE_TEMPORARY_CHANGE) {
1529 changed = true;
1530 if (doit) {
1531 Slog.w(TAG, "Wallpaper uninstalled, removing: "
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001532 + wallpaper.wallpaperComponent);
Christopher Tateedf7d042016-03-29 18:24:25 -07001533 clearWallpaperLocked(false, FLAG_SYSTEM, wallpaper.userId, null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001534 }
1535 }
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001536 }
1537 if (wallpaper.nextWallpaperComponent != null) {
1538 int change = isPackageDisappearing(wallpaper.nextWallpaperComponent
1539 .getPackageName());
1540 if (change == PACKAGE_PERMANENT_CHANGE
1541 || change == PACKAGE_TEMPORARY_CHANGE) {
1542 wallpaper.nextWallpaperComponent = null;
1543 }
1544 }
1545 if (wallpaper.wallpaperComponent != null
1546 && isPackageModified(wallpaper.wallpaperComponent.getPackageName())) {
1547 try {
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001548 mContext.getPackageManager().getServiceInfo(wallpaper.wallpaperComponent,
1549 PackageManager.MATCH_DIRECT_BOOT_AWARE
1550 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001551 } catch (NameNotFoundException e) {
1552 Slog.w(TAG, "Wallpaper component gone, removing: "
1553 + wallpaper.wallpaperComponent);
Christopher Tateedf7d042016-03-29 18:24:25 -07001554 clearWallpaperLocked(false, FLAG_SYSTEM, wallpaper.userId, null);
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001555 }
1556 }
1557 if (wallpaper.nextWallpaperComponent != null
1558 && isPackageModified(wallpaper.nextWallpaperComponent.getPackageName())) {
1559 try {
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001560 mContext.getPackageManager().getServiceInfo(wallpaper.nextWallpaperComponent,
1561 PackageManager.MATCH_DIRECT_BOOT_AWARE
1562 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001563 } catch (NameNotFoundException e) {
1564 wallpaper.nextWallpaperComponent = null;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001565 }
1566 }
1567 return changed;
1568 }
1569 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001570
Dianne Hackborn8cc6a502009-08-05 21:29:42 -07001571 public WallpaperManagerService(Context context) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001572 if (DEBUG) Slog.v(TAG, "WallpaperService startup");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001573 mContext = context;
Christopher Tate762dfd12016-10-10 17:44:48 -07001574 mShuttingDown = false;
Justin Koh29c30162014-09-05 17:10:10 -07001575 mImageWallpaper = ComponentName.unflattenFromString(
1576 context.getResources().getString(R.string.image_wallpaper_component));
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001577 mDefaultWallpaperComponent = WallpaperManager.getDefaultWallpaperComponent(context);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001578 mIWindowManager = IWindowManager.Stub.asInterface(
1579 ServiceManager.getService(Context.WINDOW_SERVICE));
Amith Yamasani4e2820c2012-08-28 22:17:23 -07001580 mIPackageManager = AppGlobals.getPackageManager();
Benjamin Franzf3ece362015-02-11 10:51:10 +00001581 mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
wilsonshihde93f492018-11-01 21:23:40 +08001582 mDisplayManager = mContext.getSystemService(DisplayManager.class);
1583 mDisplayManager.registerDisplayListener(mDisplayListener, null /* handler */);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001584 mMonitor = new MyPackageMonitor();
Jaekyun Seokad7d90f2018-04-04 01:57:18 +09001585 mColorsChangedListeners = new SparseArray<>();
1586 }
1587
1588 void initialize() {
1589 mMonitor.register(mContext, null, UserHandle.ALL, true);
Xiaohui Chen233d94c2015-07-30 15:08:00 -07001590 getWallpaperDir(UserHandle.USER_SYSTEM).mkdirs();
Christopher Tatef717b932017-09-11 15:52:54 -07001591
1592 // Initialize state from the persistent store, then guarantee that the
1593 // WallpaperData for the system imagery is instantiated & active, creating
1594 // it from defaults if necessary.
Christopher Tated7faf532016-02-25 12:43:38 -08001595 loadSettingsLocked(UserHandle.USER_SYSTEM, false);
Christopher Tatef717b932017-09-11 15:52:54 -07001596 getWallpaperSafeLocked(UserHandle.USER_SYSTEM, FLAG_SYSTEM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001597 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001598
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001599 private static File getWallpaperDir(int userId) {
Amith Yamasani61f57372012-08-31 12:12:28 -07001600 return Environment.getUserSystemDirectory(userId);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001601 }
1602
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001603 @Override
1604 protected void finalize() throws Throwable {
1605 super.finalize();
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001606 for (int i = 0; i < mWallpaperMap.size(); i++) {
1607 WallpaperData wallpaper = mWallpaperMap.valueAt(i);
1608 wallpaper.wallpaperObserver.stopWatching();
1609 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001610 }
Amith Yamasani13593602012-03-22 16:16:17 -07001611
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001612 void systemReady() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001613 if (DEBUG) Slog.v(TAG, "systemReady");
Jaekyun Seokad7d90f2018-04-04 01:57:18 +09001614 initialize();
1615
Xiaohui Chen233d94c2015-07-30 15:08:00 -07001616 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.USER_SYSTEM);
Christopher Tate2cdd3f22016-03-14 17:36:16 -07001617 // If we think we're going to be using the system image wallpaper imagery, make
1618 // sure we have something to render
1619 if (mImageWallpaper.equals(wallpaper.nextWallpaperComponent)) {
1620 // No crop file? Make sure we've finished the processing sequence if necessary
1621 if (!wallpaper.cropExists()) {
1622 if (DEBUG) {
1623 Slog.i(TAG, "No crop; regenerating from source");
1624 }
1625 generateCrop(wallpaper);
1626 }
1627 // Still nothing? Fall back to default.
1628 if (!wallpaper.cropExists()) {
1629 if (DEBUG) {
1630 Slog.i(TAG, "Unable to regenerate crop; resetting");
1631 }
Christopher Tateedf7d042016-03-29 18:24:25 -07001632 clearWallpaperLocked(false, FLAG_SYSTEM, UserHandle.USER_SYSTEM, null);
Christopher Tate2cdd3f22016-03-14 17:36:16 -07001633 }
1634 } else {
1635 if (DEBUG) {
1636 Slog.i(TAG, "Nondefault wallpaper component; gracefully ignoring");
1637 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001638 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001639
Amith Yamasani13593602012-03-22 16:16:17 -07001640 IntentFilter userFilter = new IntentFilter();
Amith Yamasani13593602012-03-22 16:16:17 -07001641 userFilter.addAction(Intent.ACTION_USER_REMOVED);
1642 mContext.registerReceiver(new BroadcastReceiver() {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001643 @Override
Amith Yamasani13593602012-03-22 16:16:17 -07001644 public void onReceive(Context context, Intent intent) {
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001645 final String action = intent.getAction();
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001646 if (Intent.ACTION_USER_REMOVED.equals(action)) {
Amith Yamasani756901d2012-10-12 12:30:07 -07001647 onRemoveUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
1648 UserHandle.USER_NULL));
Amith Yamasani13593602012-03-22 16:16:17 -07001649 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001650 }
Amith Yamasani13593602012-03-22 16:16:17 -07001651 }, userFilter);
Amith Yamasani756901d2012-10-12 12:30:07 -07001652
Christopher Tate762dfd12016-10-10 17:44:48 -07001653 final IntentFilter shutdownFilter = new IntentFilter(Intent.ACTION_SHUTDOWN);
1654 mContext.registerReceiver(new BroadcastReceiver() {
1655 @Override
1656 public void onReceive(Context context, Intent intent) {
1657 if (Intent.ACTION_SHUTDOWN.equals(intent.getAction())) {
1658 if (DEBUG) {
1659 Slog.i(TAG, "Shutting down");
1660 }
1661 synchronized (mLock) {
1662 mShuttingDown = true;
1663 }
1664 }
1665 }
1666 }, shutdownFilter);
1667
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001668 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001669 ActivityManager.getService().registerUserSwitchObserver(
Sudheer Shanka2c4522c2016-08-27 20:53:28 -07001670 new UserSwitchObserver() {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001671 @Override
1672 public void onUserSwitching(int newUserId, IRemoteCallback reply) {
1673 switchUser(newUserId, reply);
1674 }
Fyodor Kupolov0b77ef92016-06-20 17:16:52 -07001675 }, TAG);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001676 } catch (RemoteException e) {
Fyodor Kupolov0b77ef92016-06-20 17:16:52 -07001677 e.rethrowAsRuntimeException();
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001678 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001679 }
1680
Amith Yamasani09e9cdc2013-11-06 14:54:50 -08001681 /** Called by SystemBackupAgent */
1682 public String getName() {
1683 // Verify caller is the system
1684 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
1685 throw new RuntimeException("getName() can only be called from the system process");
1686 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001687 synchronized (mLock) {
1688 return mWallpaperMap.get(0).name;
1689 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001690 }
1691
Christopher Tatebe132e62016-02-10 12:59:49 -08001692 void stopObserver(WallpaperData wallpaper) {
1693 if (wallpaper != null) {
1694 if (wallpaper.wallpaperObserver != null) {
1695 wallpaper.wallpaperObserver.stopWatching();
1696 wallpaper.wallpaperObserver = null;
Amith Yamasani13593602012-03-22 16:16:17 -07001697 }
Amith Yamasani756901d2012-10-12 12:30:07 -07001698 }
1699 }
1700
Christopher Tatebe132e62016-02-10 12:59:49 -08001701 void stopObserversLocked(int userId) {
1702 stopObserver(mWallpaperMap.get(userId));
1703 stopObserver(mLockWallpaperMap.get(userId));
1704 mWallpaperMap.remove(userId);
1705 mLockWallpaperMap.remove(userId);
1706 }
1707
Daichi Hirono4bbf8522017-12-06 10:34:18 +09001708 @Override
1709 public void onBootPhase(int phase) {
1710 if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
1711 systemReady();
1712 } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
1713 switchUser(UserHandle.USER_SYSTEM, null);
1714 }
1715 }
1716
1717 @Override
1718 public void onUnlockUser(final int userId) {
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001719 synchronized (mLock) {
Christopher Tate38a5dc32016-07-20 15:10:18 -07001720 if (mCurrentUserId == userId) {
1721 if (mWaitingForUnlock) {
wilsonshiha47fcc92018-04-26 14:27:38 +08001722 // the desired wallpaper is not direct-boot aware, load it now
1723 final WallpaperData systemWallpaper =
1724 getWallpaperSafeLocked(userId, FLAG_SYSTEM);
1725 switchWallpaper(systemWallpaper, null);
Christopher Tate38a5dc32016-07-20 15:10:18 -07001726 }
Christopher Tate190e8532016-07-11 11:35:34 -07001727
1728 // Make sure that the SELinux labeling of all the relevant files is correct.
1729 // This corrects for mislabeling bugs that might have arisen from move-to
1730 // operations involving the wallpaper files. This isn't timing-critical,
1731 // so we do it in the background to avoid holding up the user unlock operation.
wilsonshiha282bf72018-11-30 12:48:05 +08001732 if (!mUserRestorecon.get(userId)) {
1733 mUserRestorecon.put(userId, true);
Christopher Tate38a5dc32016-07-20 15:10:18 -07001734 Runnable relabeler = new Runnable() {
1735 @Override
1736 public void run() {
1737 final File wallpaperDir = getWallpaperDir(userId);
1738 for (String filename : sPerUserFiles) {
1739 File f = new File(wallpaperDir, filename);
1740 if (f.exists()) {
1741 SELinux.restorecon(f);
1742 }
Christopher Tate190e8532016-07-11 11:35:34 -07001743 }
1744 }
Christopher Tate38a5dc32016-07-20 15:10:18 -07001745 };
1746 BackgroundThread.getHandler().post(relabeler);
1747 }
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001748 }
1749 }
1750 }
1751
Amith Yamasani756901d2012-10-12 12:30:07 -07001752 void onRemoveUser(int userId) {
1753 if (userId < 1) return;
Christopher Tatebe132e62016-02-10 12:59:49 -08001754
1755 final File wallpaperDir = getWallpaperDir(userId);
Amith Yamasani756901d2012-10-12 12:30:07 -07001756 synchronized (mLock) {
Christopher Tatebe132e62016-02-10 12:59:49 -08001757 stopObserversLocked(userId);
1758 for (String filename : sPerUserFiles) {
1759 new File(wallpaperDir, filename).delete();
1760 }
wilsonshiha282bf72018-11-30 12:48:05 +08001761 mUserRestorecon.delete(userId);
Amith Yamasani13593602012-03-22 16:16:17 -07001762 }
1763 }
1764
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001765 void switchUser(int userId, IRemoteCallback reply) {
Lucas Dupin9272d452017-09-14 14:15:42 -07001766 final WallpaperData systemWallpaper;
1767 final WallpaperData lockWallpaper;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001768 synchronized (mLock) {
Jaekyun Seokad7d90f2018-04-04 01:57:18 +09001769 if (mCurrentUserId == userId) {
1770 return;
1771 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001772 mCurrentUserId = userId;
Lucas Dupin50ba9912017-07-14 11:55:05 -07001773 systemWallpaper = getWallpaperSafeLocked(userId, FLAG_SYSTEM);
Lucas Dupin9272d452017-09-14 14:15:42 -07001774 final WallpaperData tmpLockWallpaper = mLockWallpaperMap.get(userId);
1775 lockWallpaper = tmpLockWallpaper == null ? systemWallpaper : tmpLockWallpaper;
Lucas Dupin50ba9912017-07-14 11:55:05 -07001776 // Not started watching yet, in case wallpaper data was loaded for other reasons.
1777 if (systemWallpaper.wallpaperObserver == null) {
1778 systemWallpaper.wallpaperObserver = new WallpaperObserver(systemWallpaper);
1779 systemWallpaper.wallpaperObserver.startWatching();
1780 }
1781 switchWallpaper(systemWallpaper, reply);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001782 }
Lucas Dupin9272d452017-09-14 14:15:42 -07001783
1784 // Offload color extraction to another thread since switchUser will be called
1785 // from the main thread.
1786 FgThread.getHandler().post(() -> {
1787 notifyWallpaperColorsChanged(systemWallpaper, FLAG_SYSTEM);
1788 notifyWallpaperColorsChanged(lockWallpaper, FLAG_LOCK);
wilsonshih36597d42018-12-05 18:56:39 +08001789 notifyWallpaperColorsChanged(mFallbackWallpaper, FLAG_SYSTEM);
Lucas Dupin9272d452017-09-14 14:15:42 -07001790 });
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001791 }
1792
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001793 void switchWallpaper(WallpaperData wallpaper, IRemoteCallback reply) {
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001794 synchronized (mLock) {
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001795 mWaitingForUnlock = false;
1796 final ComponentName cname = wallpaper.wallpaperComponent != null ?
1797 wallpaper.wallpaperComponent : wallpaper.nextWallpaperComponent;
1798 if (!bindWallpaperComponentLocked(cname, true, false, wallpaper, reply)) {
1799 // We failed to bind the desired wallpaper, but that might
1800 // happen if the wallpaper isn't direct-boot aware
1801 ServiceInfo si = null;
1802 try {
1803 si = mIPackageManager.getServiceInfo(cname,
1804 PackageManager.MATCH_DIRECT_BOOT_UNAWARE, wallpaper.userId);
1805 } catch (RemoteException ignored) {
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001806 }
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001807
1808 if (si == null) {
1809 Slog.w(TAG, "Failure starting previous wallpaper; clearing");
1810 clearWallpaperLocked(false, FLAG_SYSTEM, wallpaper.userId, reply);
1811 } else {
1812 Slog.w(TAG, "Wallpaper isn't direct boot aware; using fallback until unlocked");
1813 // We might end up persisting the current wallpaper data
1814 // while locked, so pretend like the component was actually
1815 // bound into place
1816 wallpaper.wallpaperComponent = wallpaper.nextWallpaperComponent;
1817 final WallpaperData fallback = new WallpaperData(wallpaper.userId,
1818 WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP);
wilsonshih81e10a72018-11-15 10:54:21 +08001819 ensureSaneWallpaperData(fallback, DEFAULT_DISPLAY);
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001820 bindWallpaperComponentLocked(mImageWallpaper, true, false, fallback, reply);
1821 mWaitingForUnlock = true;
1822 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001823 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001824 }
1825 }
1826
Christopher Tatebe132e62016-02-10 12:59:49 -08001827 @Override
1828 public void clearWallpaper(String callingPackage, int which, int userId) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001829 if (DEBUG) Slog.v(TAG, "clearWallpaper");
Benjamin Franzf3ece362015-02-11 10:51:10 +00001830 checkPermission(android.Manifest.permission.SET_WALLPAPER);
Christopher Tate98d609c2016-05-18 17:31:58 -07001831 if (!isWallpaperSupported(callingPackage) || !isSetWallpaperAllowed(callingPackage)) {
Benjamin Franzf3ece362015-02-11 10:51:10 +00001832 return;
1833 }
Christopher Tatee409f0e2016-03-21 14:53:15 -07001834 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
1835 Binder.getCallingUid(), userId, false, true, "clearWallpaper", null);
Christopher Tatebe132e62016-02-10 12:59:49 -08001836
Lucas Dupin41f69422017-05-03 15:26:22 -07001837 WallpaperData data = null;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001838 synchronized (mLock) {
Christopher Tatebe132e62016-02-10 12:59:49 -08001839 clearWallpaperLocked(false, which, userId, null);
Lucas Dupin41f69422017-05-03 15:26:22 -07001840
1841 if (which == FLAG_LOCK) {
1842 data = mLockWallpaperMap.get(userId);
1843 }
1844 if (which == FLAG_SYSTEM || data == null) {
1845 data = mWallpaperMap.get(userId);
1846 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001847 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07001848
1849 // When clearing a wallpaper, broadcast new valid colors
Lucas Dupin41f69422017-05-03 15:26:22 -07001850 if (data != null) {
1851 notifyWallpaperColorsChanged(data, which);
wilsonshih36597d42018-12-05 18:56:39 +08001852 notifyWallpaperColorsChanged(mFallbackWallpaper, FLAG_SYSTEM);
Lucas Dupin41f69422017-05-03 15:26:22 -07001853 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001854 }
1855
Christopher Tatebe132e62016-02-10 12:59:49 -08001856 void clearWallpaperLocked(boolean defaultFailed, int which, int userId, IRemoteCallback reply) {
Christopher Tateedf7d042016-03-29 18:24:25 -07001857 if (which != FLAG_SYSTEM && which != FLAG_LOCK) {
Christopher Tate105540d2018-03-21 13:03:09 -07001858 throw new IllegalArgumentException("Must specify exactly one kind of wallpaper to clear");
Christopher Tatebe132e62016-02-10 12:59:49 -08001859 }
1860
1861 WallpaperData wallpaper = null;
Christopher Tateedf7d042016-03-29 18:24:25 -07001862 if (which == FLAG_LOCK) {
Christopher Tatebe132e62016-02-10 12:59:49 -08001863 wallpaper = mLockWallpaperMap.get(userId);
1864 if (wallpaper == null) {
1865 // It's already gone; we're done.
Christopher Tate79a24572016-03-02 14:42:44 -08001866 if (DEBUG) {
1867 Slog.i(TAG, "Lock wallpaper already cleared");
1868 }
Christopher Tatebe132e62016-02-10 12:59:49 -08001869 return;
1870 }
1871 } else {
1872 wallpaper = mWallpaperMap.get(userId);
1873 if (wallpaper == null) {
1874 // Might need to bring it in the first time to establish our rewrite
Christopher Tated7faf532016-02-25 12:43:38 -08001875 loadSettingsLocked(userId, false);
Christopher Tatebe132e62016-02-10 12:59:49 -08001876 wallpaper = mWallpaperMap.get(userId);
1877 }
1878 }
Benjamin Franzf3ece362015-02-11 10:51:10 +00001879 if (wallpaper == null) {
1880 return;
1881 }
Christopher Tatebe132e62016-02-10 12:59:49 -08001882
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001883 final long ident = Binder.clearCallingIdentity();
1884 try {
Christopher Tatebe132e62016-02-10 12:59:49 -08001885 if (wallpaper.wallpaperFile.exists()) {
1886 wallpaper.wallpaperFile.delete();
1887 wallpaper.cropFile.delete();
Christopher Tateedf7d042016-03-29 18:24:25 -07001888 if (which == FLAG_LOCK) {
Christopher Tate79a24572016-03-02 14:42:44 -08001889 mLockWallpaperMap.remove(userId);
Christopher Tatebe132e62016-02-10 12:59:49 -08001890 final IWallpaperManagerCallback cb = mKeyguardListener;
1891 if (cb != null) {
Christopher Tate79a24572016-03-02 14:42:44 -08001892 if (DEBUG) {
1893 Slog.i(TAG, "Notifying keyguard of lock wallpaper clear");
1894 }
Christopher Tatebe132e62016-02-10 12:59:49 -08001895 try {
1896 cb.onWallpaperChanged();
1897 } catch (RemoteException e) {
1898 // Oh well it went away; no big deal
1899 }
1900 }
Christopher Tate79a24572016-03-02 14:42:44 -08001901 saveSettingsLocked(userId);
Christopher Tatebe132e62016-02-10 12:59:49 -08001902 return;
1903 }
1904 }
1905
Christopher Tateecd827a2014-09-05 17:42:34 -07001906 RuntimeException e = null;
1907 try {
Lucas Dupin75ec3792017-06-29 14:07:18 -07001908 wallpaper.primaryColors = null;
Christopher Tateecd827a2014-09-05 17:42:34 -07001909 wallpaper.imageWallpaperPending = false;
1910 if (userId != mCurrentUserId) return;
1911 if (bindWallpaperComponentLocked(defaultFailed
1912 ? mImageWallpaper
1913 : null, true, false, wallpaper, reply)) {
1914 return;
1915 }
1916 } catch (IllegalArgumentException e1) {
1917 e = e1;
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001918 }
Christopher Tateecd827a2014-09-05 17:42:34 -07001919
1920 // This can happen if the default wallpaper component doesn't
1921 // exist. This should be a system configuration problem, but
1922 // let's not let it crash the system and just live with no
1923 // wallpaper.
1924 Slog.e(TAG, "Default wallpaper component not found!", e);
1925 clearWallpaperComponentLocked(wallpaper);
1926 if (reply != null) {
1927 try {
1928 reply.sendResult(null);
1929 } catch (RemoteException e1) {
1930 }
1931 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001932 } finally {
1933 Binder.restoreCallingIdentity(ident);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001934 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001935 }
1936
1937 public boolean hasNamedWallpaper(String name) {
1938 synchronized (mLock) {
Amith Yamasani6474c4c2012-10-04 14:55:42 -07001939 List<UserInfo> users;
1940 long ident = Binder.clearCallingIdentity();
1941 try {
1942 users = ((UserManager) mContext.getSystemService(Context.USER_SERVICE)).getUsers();
1943 } finally {
1944 Binder.restoreCallingIdentity(ident);
1945 }
1946 for (UserInfo user: users) {
Benjamin Franzf3ece362015-02-11 10:51:10 +00001947 // ignore managed profiles
1948 if (user.isManagedProfile()) {
1949 continue;
1950 }
Amith Yamasani6474c4c2012-10-04 14:55:42 -07001951 WallpaperData wd = mWallpaperMap.get(user.id);
1952 if (wd == null) {
1953 // User hasn't started yet, so load her settings to peek at the wallpaper
Christopher Tated7faf532016-02-25 12:43:38 -08001954 loadSettingsLocked(user.id, false);
Amith Yamasani6474c4c2012-10-04 14:55:42 -07001955 wd = mWallpaperMap.get(user.id);
1956 }
1957 if (wd != null && name.equals(wd.name)) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001958 return true;
1959 }
1960 }
1961 }
1962 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001963 }
1964
wilsonshih81e10a72018-11-15 10:54:21 +08001965 private boolean isValidDisplay(int displayId) {
1966 return mDisplayManager.getDisplay(displayId) != null;
1967 }
1968
1969 /**
1970 * Sets the dimension hint for the wallpaper. These hints indicate the desired
1971 * minimum width and height for the wallpaper in a particular display.
1972 */
1973 public void setDimensionHints(int width, int height, String callingPackage, int displayId)
Benjamin Franzf3ece362015-02-11 10:51:10 +00001974 throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001975 checkPermission(android.Manifest.permission.SET_WALLPAPER_HINTS);
Benjamin Franzf3ece362015-02-11 10:51:10 +00001976 if (!isWallpaperSupported(callingPackage)) {
1977 return;
1978 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001979 synchronized (mLock) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001980 int userId = UserHandle.getCallingUserId();
Christopher Tateedf7d042016-03-29 18:24:25 -07001981 WallpaperData wallpaper = getWallpaperSafeLocked(userId, FLAG_SYSTEM);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001982 if (width <= 0 || height <= 0) {
1983 throw new IllegalArgumentException("width and height must be > 0");
1984 }
1985
wilsonshih81e10a72018-11-15 10:54:21 +08001986 if (!isValidDisplay(displayId)) {
1987 throw new IllegalArgumentException("Cannot find display with id=" + displayId);
1988 }
1989
wilsonshiha282bf72018-11-30 12:48:05 +08001990 final DisplayData wpdData = getDisplayDataOrCreate(displayId);
wilsonshih81e10a72018-11-15 10:54:21 +08001991 if (width != wpdData.mWidth || height != wpdData.mHeight) {
1992 wpdData.mWidth = width;
1993 wpdData.mHeight = height;
1994 if (displayId == DEFAULT_DISPLAY) saveSettingsLocked(userId);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001995 if (mCurrentUserId != userId) return; // Don't change the properties now
1996 if (wallpaper.connection != null) {
wilsonshih81e10a72018-11-15 10:54:21 +08001997 final WallpaperConnection.DisplayConnector connector = wallpaper.connection
1998 .getDisplayConnectorOrCreate(displayId);
1999 final IWallpaperEngine engine = connector != null ? connector.mEngine : null;
wilsonshihde93f492018-11-01 21:23:40 +08002000 if (engine != null) {
Dianne Hackborn284ac932009-08-28 10:34:25 -07002001 try {
wilsonshihde93f492018-11-01 21:23:40 +08002002 engine.setDesiredSize(width, height);
Dianne Hackborn284ac932009-08-28 10:34:25 -07002003 } catch (RemoteException e) {
2004 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002005 notifyCallbacksLocked(wallpaper);
wilsonshih81e10a72018-11-15 10:54:21 +08002006 } else if (wallpaper.connection.mService != null && connector != null) {
Michael Wright5203a8b2013-10-03 14:16:42 -07002007 // We've attached to the service but the engine hasn't attached back to us
2008 // yet. This means it will be created with the previous dimensions, so we
2009 // need to update it to the new dimensions once it attaches.
wilsonshih81e10a72018-11-15 10:54:21 +08002010 connector.mDimensionsChanged = true;
Dianne Hackborn284ac932009-08-28 10:34:25 -07002011 }
2012 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002013 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002014 }
2015 }
2016
wilsonshih81e10a72018-11-15 10:54:21 +08002017 /**
2018 * Returns the desired minimum width for the wallpaper in a particular display.
2019 */
2020 public int getWidthHint(int displayId) throws RemoteException {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002021 synchronized (mLock) {
wilsonshih81e10a72018-11-15 10:54:21 +08002022 if (!isValidDisplay(displayId)) {
2023 throw new IllegalArgumentException("Cannot find display with id=" + displayId);
2024 }
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07002025 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.getCallingUserId());
Benjamin Franzf3ece362015-02-11 10:51:10 +00002026 if (wallpaper != null) {
wilsonshiha282bf72018-11-30 12:48:05 +08002027 final DisplayData wpdData = getDisplayDataOrCreate(displayId);
wilsonshih81e10a72018-11-15 10:54:21 +08002028 return wpdData.mWidth;
Benjamin Franzf3ece362015-02-11 10:51:10 +00002029 } else {
2030 return 0;
2031 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002032 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002033 }
2034
wilsonshih81e10a72018-11-15 10:54:21 +08002035 /**
2036 * Returns the desired minimum height for the wallpaper in a particular display.
2037 */
2038 public int getHeightHint(int displayId) throws RemoteException {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002039 synchronized (mLock) {
wilsonshih81e10a72018-11-15 10:54:21 +08002040 if (!isValidDisplay(displayId)) {
2041 throw new IllegalArgumentException("Cannot find display with id=" + displayId);
2042 }
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07002043 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.getCallingUserId());
Benjamin Franzf3ece362015-02-11 10:51:10 +00002044 if (wallpaper != null) {
wilsonshiha282bf72018-11-30 12:48:05 +08002045 final DisplayData wpdData = getDisplayDataOrCreate(displayId);
wilsonshih81e10a72018-11-15 10:54:21 +08002046 return wpdData.mHeight;
Benjamin Franzf3ece362015-02-11 10:51:10 +00002047 } else {
2048 return 0;
2049 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002050 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002051 }
2052
wilsonshih81e10a72018-11-15 10:54:21 +08002053 /**
2054 * Sets extra padding that we would like the wallpaper to have outside of the display.
2055 */
2056 public void setDisplayPadding(Rect padding, String callingPackage, int displayId) {
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002057 checkPermission(android.Manifest.permission.SET_WALLPAPER_HINTS);
Benjamin Franzf3ece362015-02-11 10:51:10 +00002058 if (!isWallpaperSupported(callingPackage)) {
2059 return;
2060 }
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002061 synchronized (mLock) {
wilsonshih81e10a72018-11-15 10:54:21 +08002062 if (!isValidDisplay(displayId)) {
2063 throw new IllegalArgumentException("Cannot find display with id=" + displayId);
2064 }
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002065 int userId = UserHandle.getCallingUserId();
Christopher Tateedf7d042016-03-29 18:24:25 -07002066 WallpaperData wallpaper = getWallpaperSafeLocked(userId, FLAG_SYSTEM);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002067 if (padding.left < 0 || padding.top < 0 || padding.right < 0 || padding.bottom < 0) {
2068 throw new IllegalArgumentException("padding must be positive: " + padding);
2069 }
2070
wilsonshiha282bf72018-11-30 12:48:05 +08002071 final DisplayData wpdData = getDisplayDataOrCreate(displayId);
wilsonshih81e10a72018-11-15 10:54:21 +08002072 if (!padding.equals(wpdData.mPadding)) {
2073 wpdData.mPadding.set(padding);
2074 if (displayId == DEFAULT_DISPLAY) saveSettingsLocked(userId);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002075 if (mCurrentUserId != userId) return; // Don't change the properties now
2076 if (wallpaper.connection != null) {
wilsonshih81e10a72018-11-15 10:54:21 +08002077 final WallpaperConnection.DisplayConnector connector = wallpaper.connection
2078 .getDisplayConnectorOrCreate(displayId);
2079 final IWallpaperEngine engine = connector != null ? connector.mEngine : null;
wilsonshihde93f492018-11-01 21:23:40 +08002080 if (engine != null) {
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002081 try {
wilsonshihde93f492018-11-01 21:23:40 +08002082 engine.setDisplayPadding(padding);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002083 } catch (RemoteException e) {
2084 }
2085 notifyCallbacksLocked(wallpaper);
wilsonshih81e10a72018-11-15 10:54:21 +08002086 } else if (wallpaper.connection.mService != null && connector != null) {
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002087 // We've attached to the service but the engine hasn't attached back to us
2088 // yet. This means it will be created with the previous dimensions, so we
2089 // need to update it to the new dimensions once it attaches.
wilsonshih81e10a72018-11-15 10:54:21 +08002090 connector.mPaddingChanged = true;
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002091 }
2092 }
2093 }
2094 }
2095 }
2096
Christopher Tate93252de2017-06-15 14:48:41 -07002097 private void enforceCallingOrSelfPermissionAndAppOp(String permission, final String callingPkg,
2098 final int callingUid, String message) {
2099 mContext.enforceCallingOrSelfPermission(permission, message);
2100
2101 final String opName = AppOpsManager.permissionToOp(permission);
2102 if (opName != null) {
2103 final int appOpMode = mAppOpsManager.noteOp(opName, callingUid, callingPkg);
2104 if (appOpMode != AppOpsManager.MODE_ALLOWED) {
2105 throw new SecurityException(
2106 message + ": " + callingPkg + " is not allowed to " + permission);
2107 }
2108 }
2109 }
2110
Yorke Leedcd93cc2016-01-08 14:12:55 -08002111 @Override
Christopher Tate93252de2017-06-15 14:48:41 -07002112 public ParcelFileDescriptor getWallpaper(String callingPkg, IWallpaperManagerCallback cb,
2113 final int which, Bundle outParams, int wallpaperUserId) {
Christopher Tate8a71c482017-08-14 16:45:03 -07002114 final int hasPrivilege = mContext.checkCallingOrSelfPermission(
2115 android.Manifest.permission.READ_WALLPAPER_INTERNAL);
2116 if (hasPrivilege != PackageManager.PERMISSION_GRANTED) {
2117 enforceCallingOrSelfPermissionAndAppOp(android.Manifest.permission.READ_EXTERNAL_STORAGE,
2118 callingPkg, Binder.getCallingUid(), "read wallpaper");
2119 }
Christopher Tate93252de2017-06-15 14:48:41 -07002120
Christopher Tatee409f0e2016-03-21 14:53:15 -07002121 wallpaperUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
2122 Binder.getCallingUid(), wallpaperUserId, false, true, "getWallpaper", null);
Christopher Tatebe132e62016-02-10 12:59:49 -08002123
Christopher Tateedf7d042016-03-29 18:24:25 -07002124 if (which != FLAG_SYSTEM && which != FLAG_LOCK) {
Christopher Tatebe132e62016-02-10 12:59:49 -08002125 throw new IllegalArgumentException("Must specify exactly one kind of wallpaper to read");
2126 }
2127
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002128 synchronized (mLock) {
Vadim Tryshev8cde0792016-02-19 17:02:15 -08002129 final SparseArray<WallpaperData> whichSet =
Christopher Tateedf7d042016-03-29 18:24:25 -07002130 (which == FLAG_LOCK) ? mLockWallpaperMap : mWallpaperMap;
Vadim Tryshev8cde0792016-02-19 17:02:15 -08002131 WallpaperData wallpaper = whichSet.get(wallpaperUserId);
2132 if (wallpaper == null) {
Christopher Tatef717b932017-09-11 15:52:54 -07002133 // There is no established wallpaper imagery of this type (expected
2134 // only for lock wallpapers; a system WallpaperData is established at
2135 // user switch)
2136 return null;
Benjamin Franzf3ece362015-02-11 10:51:10 +00002137 }
wilsonshih81e10a72018-11-15 10:54:21 +08002138 // Only for default display.
wilsonshiha282bf72018-11-30 12:48:05 +08002139 final DisplayData wpdData = getDisplayDataOrCreate(DEFAULT_DISPLAY);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002140 try {
Dianne Hackborn284ac932009-08-28 10:34:25 -07002141 if (outParams != null) {
wilsonshih81e10a72018-11-15 10:54:21 +08002142 outParams.putInt("width", wpdData.mWidth);
2143 outParams.putInt("height", wpdData.mHeight);
Dianne Hackborn284ac932009-08-28 10:34:25 -07002144 }
Christopher Tateea6724a2016-02-18 18:39:19 -08002145 if (cb != null) {
2146 wallpaper.callbacks.register(cb);
2147 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08002148 if (!wallpaper.cropFile.exists()) {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002149 return null;
2150 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08002151 return ParcelFileDescriptor.open(wallpaper.cropFile, MODE_READ_ONLY);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002152 } catch (FileNotFoundException e) {
2153 /* Shouldn't happen as we check to see if the file exists */
Joe Onorato8a9b2202010-02-26 18:56:32 -08002154 Slog.w(TAG, "Error getting wallpaper", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002155 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002156 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002157 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002158 }
2159
Christopher Tatee409f0e2016-03-21 14:53:15 -07002160 @Override
Jorim Jaggie31f6b82016-07-01 16:15:09 -07002161 public WallpaperInfo getWallpaperInfo(int userId) {
2162 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
Christopher Tatef717b932017-09-11 15:52:54 -07002163 Binder.getCallingUid(), userId, false, true, "getWallpaperInfo", null);
Dianne Hackborneb034652009-09-07 00:49:58 -07002164 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002165 WallpaperData wallpaper = mWallpaperMap.get(userId);
Benjamin Franzf3ece362015-02-11 10:51:10 +00002166 if (wallpaper != null && wallpaper.connection != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002167 return wallpaper.connection.mInfo;
Dianne Hackborneb034652009-09-07 00:49:58 -07002168 }
2169 return null;
2170 }
2171 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002172
Christopher Tatead3c2592016-01-20 18:13:17 -08002173 @Override
Christopher Tatee409f0e2016-03-21 14:53:15 -07002174 public int getWallpaperIdForUser(int which, int userId) {
2175 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
2176 Binder.getCallingUid(), userId, false, true, "getWallpaperIdForUser", null);
2177
Christopher Tateedf7d042016-03-29 18:24:25 -07002178 if (which != FLAG_SYSTEM && which != FLAG_LOCK) {
Christopher Tatee409f0e2016-03-21 14:53:15 -07002179 throw new IllegalArgumentException("Must specify exactly one kind of wallpaper");
2180 }
2181
2182 final SparseArray<WallpaperData> map =
Christopher Tateedf7d042016-03-29 18:24:25 -07002183 (which == FLAG_LOCK) ? mLockWallpaperMap : mWallpaperMap;
Christopher Tatee409f0e2016-03-21 14:53:15 -07002184 synchronized (mLock) {
2185 WallpaperData wallpaper = map.get(userId);
2186 if (wallpaper != null) {
2187 return wallpaper.wallpaperId;
2188 }
2189 }
2190 return -1;
2191 }
2192
2193 @Override
wilsonshih36597d42018-12-05 18:56:39 +08002194 public void registerWallpaperColorsCallback(IWallpaperManagerCallback cb, int userId,
2195 int displayId) {
Lucas Dupin50ba9912017-07-14 11:55:05 -07002196 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
2197 userId, true, true, "registerWallpaperColorsCallback", null);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002198 synchronized (mLock) {
wilsonshih36597d42018-12-05 18:56:39 +08002199 SparseArray<RemoteCallbackList<IWallpaperManagerCallback>>
2200 userDisplayColorsChangedListeners = mColorsChangedListeners.get(userId);
2201 if (userDisplayColorsChangedListeners == null) {
2202 userDisplayColorsChangedListeners = new SparseArray<>();
2203 mColorsChangedListeners.put(userId, userDisplayColorsChangedListeners);
Lucas Dupin50ba9912017-07-14 11:55:05 -07002204 }
wilsonshih36597d42018-12-05 18:56:39 +08002205 RemoteCallbackList<IWallpaperManagerCallback> displayChangedListeners =
2206 userDisplayColorsChangedListeners.get(displayId);
2207 if (displayChangedListeners == null) {
2208 displayChangedListeners = new RemoteCallbackList<>();
2209 userDisplayColorsChangedListeners.put(displayId, displayChangedListeners);
2210 }
2211 displayChangedListeners.register(cb);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002212 }
2213 }
2214
2215 @Override
wilsonshih36597d42018-12-05 18:56:39 +08002216 public void unregisterWallpaperColorsCallback(IWallpaperManagerCallback cb, int userId,
2217 int displayId) {
Lucas Dupin50ba9912017-07-14 11:55:05 -07002218 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
2219 userId, true, true, "unregisterWallpaperColorsCallback", null);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002220 synchronized (mLock) {
wilsonshih36597d42018-12-05 18:56:39 +08002221 SparseArray<RemoteCallbackList<IWallpaperManagerCallback>>
2222 userDisplayColorsChangedListeners = mColorsChangedListeners.get(userId);
2223 if (userDisplayColorsChangedListeners != null) {
2224 RemoteCallbackList<IWallpaperManagerCallback> displayChangedListeners =
2225 userDisplayColorsChangedListeners.get(displayId);
2226 if (displayChangedListeners != null) {
2227 displayChangedListeners.unregister(cb);
2228 }
Lucas Dupin50ba9912017-07-14 11:55:05 -07002229 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002230 }
2231 }
2232
Lucas Dupin4c8c3272018-11-06 17:47:48 -08002233 /**
wilsonshih36597d42018-12-05 18:56:39 +08002234 * TODO(multi-display) Extends this method with specific display.
Lucas Dupin4c8c3272018-11-06 17:47:48 -08002235 * Propagate ambient state to wallpaper engine.
2236 *
2237 * @param inAmbientMode {@code true} when in ambient mode, {@code false} otherwise.
2238 * @param animationDuration Duration of the animation, or 0 when immediate.
2239 */
2240 public void setInAmbientMode(boolean inAmbientMode, long animationDuration) {
Lucas Dupin7517b5d2017-08-22 12:51:25 -07002241 final IWallpaperEngine engine;
2242 synchronized (mLock) {
Lucas Dupin4c8c3272018-11-06 17:47:48 -08002243 mInAmbientMode = inAmbientMode;
Lucas Dupin7517b5d2017-08-22 12:51:25 -07002244 final WallpaperData data = mWallpaperMap.get(mCurrentUserId);
Ahan Wu723a80e2018-11-07 20:39:32 +08002245 // The wallpaper info is null for image wallpaper, also use the engine in this case.
Ahan Wu67e7f102019-01-14 20:38:14 +08002246 if (data != null && data.connection != null && (data.connection.mInfo == null
2247 || data.connection.mInfo.supportsAmbientMode())) {
wilsonshih36597d42018-12-05 18:56:39 +08002248 // TODO(multi-display) Extends this method with specific display.
wilsonshihde93f492018-11-01 21:23:40 +08002249 engine = data.connection.getDisplayConnectorOrCreate(DEFAULT_DISPLAY).mEngine;
Lucas Dupin7517b5d2017-08-22 12:51:25 -07002250 } else {
2251 engine = null;
2252 }
2253 }
2254
2255 if (engine != null) {
2256 try {
Lucas Dupin4c8c3272018-11-06 17:47:48 -08002257 engine.setInAmbientMode(inAmbientMode, animationDuration);
Lucas Dupin7517b5d2017-08-22 12:51:25 -07002258 } catch (RemoteException e) {
2259 // Cannot talk to wallpaper engine.
2260 }
2261 }
2262 }
2263
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002264 @Override
Christopher Tatebe132e62016-02-10 12:59:49 -08002265 public boolean setLockWallpaperCallback(IWallpaperManagerCallback cb) {
2266 checkPermission(android.Manifest.permission.INTERNAL_SYSTEM_WINDOW);
2267 synchronized (mLock) {
2268 mKeyguardListener = cb;
2269 }
2270 return true;
2271 }
2272
2273 @Override
wilsonshih36597d42018-12-05 18:56:39 +08002274 public WallpaperColors getWallpaperColors(int which, int userId, int displayId)
2275 throws RemoteException {
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002276 if (which != FLAG_LOCK && which != FLAG_SYSTEM) {
2277 throw new IllegalArgumentException("which should be either FLAG_LOCK or FLAG_SYSTEM");
2278 }
Lucas Dupin50ba9912017-07-14 11:55:05 -07002279 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
2280 userId, false, true, "getWallpaperColors", null);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002281
2282 WallpaperData wallpaperData = null;
2283 boolean shouldExtract;
2284
2285 synchronized (mLock) {
2286 if (which == FLAG_LOCK) {
Lucas Dupin50ba9912017-07-14 11:55:05 -07002287 wallpaperData = mLockWallpaperMap.get(userId);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002288 }
2289
2290 // Try to get the system wallpaper anyway since it might
2291 // also be the lock screen wallpaper
2292 if (wallpaperData == null) {
wilsonshih36597d42018-12-05 18:56:39 +08002293 wallpaperData = findWallpaperAtDisplay(userId, displayId);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002294 }
2295
2296 if (wallpaperData == null) {
2297 return null;
2298 }
2299 shouldExtract = wallpaperData.primaryColors == null;
2300 }
2301
2302 if (shouldExtract) {
2303 extractColors(wallpaperData);
2304 }
2305
2306 synchronized (mLock) {
Lucas Dupin4b4c5302018-06-24 18:22:10 -07002307 return wallpaperData.primaryColors;
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002308 }
2309 }
2310
wilsonshih36597d42018-12-05 18:56:39 +08002311 private WallpaperData findWallpaperAtDisplay(int userId, int displayId) {
2312 if (mFallbackWallpaper != null && mFallbackWallpaper.connection != null
2313 && mFallbackWallpaper.connection.containsDisplay(displayId)) {
2314 return mFallbackWallpaper;
2315 } else {
2316 return mWallpaperMap.get(userId);
2317 }
2318 }
2319
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002320 @Override
Christopher Tate1e1e2e02016-01-25 15:34:36 -08002321 public ParcelFileDescriptor setWallpaper(String name, String callingPackage,
Christopher Tated7faf532016-02-25 12:43:38 -08002322 Rect cropHint, boolean allowBackup, Bundle extras, int which,
Jorim Jaggi6c902d02016-08-18 10:44:54 -07002323 IWallpaperManagerCallback completion, int userId) {
2324 userId = ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,
2325 false /* all */, true /* full */, "changing wallpaper", null /* pkg */);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002326 checkPermission(android.Manifest.permission.SET_WALLPAPER);
Christopher Tatead3c2592016-01-20 18:13:17 -08002327
Christopher Tateedf7d042016-03-29 18:24:25 -07002328 if ((which & (FLAG_LOCK|FLAG_SYSTEM)) == 0) {
Christopher Tate98d609c2016-05-18 17:31:58 -07002329 final String msg = "Must specify a valid wallpaper category to set";
2330 Slog.e(TAG, msg);
2331 throw new IllegalArgumentException(msg);
Christopher Tatead3c2592016-01-20 18:13:17 -08002332 }
2333
Christopher Tate98d609c2016-05-18 17:31:58 -07002334 if (!isWallpaperSupported(callingPackage) || !isSetWallpaperAllowed(callingPackage)) {
Benjamin Franzf3ece362015-02-11 10:51:10 +00002335 return null;
2336 }
Christopher Tatead3c2592016-01-20 18:13:17 -08002337
Christopher Tate1e1e2e02016-01-25 15:34:36 -08002338 // "null" means the no-op crop, preserving the full input image
2339 if (cropHint == null) {
2340 cropHint = new Rect(0, 0, 0, 0);
2341 } else {
2342 if (cropHint.isEmpty()
2343 || cropHint.left < 0
2344 || cropHint.top < 0) {
Christopher Tate98d609c2016-05-18 17:31:58 -07002345 throw new IllegalArgumentException("Invalid crop rect supplied: " + cropHint);
Christopher Tate1e1e2e02016-01-25 15:34:36 -08002346 }
2347 }
2348
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002349 synchronized (mLock) {
Christopher Tatebe132e62016-02-10 12:59:49 -08002350 if (DEBUG) Slog.v(TAG, "setWallpaper which=0x" + Integer.toHexString(which));
2351 WallpaperData wallpaper;
2352
Christopher Tate8347b632016-04-29 18:59:18 -07002353 /* If we're setting system but not lock, and lock is currently sharing the system
2354 * wallpaper, we need to migrate that image over to being lock-only before
2355 * the caller here writes new bitmap data.
2356 */
2357 if (which == FLAG_SYSTEM && mLockWallpaperMap.get(userId) == null) {
2358 if (DEBUG) {
2359 Slog.i(TAG, "Migrating system->lock to preserve");
2360 }
2361 migrateSystemToLockWallpaperLocked(userId);
2362 }
2363
Christopher Tatebe132e62016-02-10 12:59:49 -08002364 wallpaper = getWallpaperSafeLocked(userId, which);
Dianne Hackborn0cd48872009-08-13 18:51:59 -07002365 final long ident = Binder.clearCallingIdentity();
2366 try {
Christopher Tatead3c2592016-01-20 18:13:17 -08002367 ParcelFileDescriptor pfd = updateWallpaperBitmapLocked(name, wallpaper, extras);
Dianne Hackborn0cd48872009-08-13 18:51:59 -07002368 if (pfd != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002369 wallpaper.imageWallpaperPending = true;
Christopher Tatebe132e62016-02-10 12:59:49 -08002370 wallpaper.whichPending = which;
Christopher Tate1e1e2e02016-01-25 15:34:36 -08002371 wallpaper.setComplete = completion;
2372 wallpaper.cropHint.set(cropHint);
Christopher Tatec613c632016-08-12 14:13:02 -07002373 wallpaper.allowBackup = allowBackup;
Dianne Hackborn0cd48872009-08-13 18:51:59 -07002374 }
2375 return pfd;
2376 } finally {
2377 Binder.restoreCallingIdentity(ident);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002378 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002379 }
2380 }
2381
Christopher Tate8347b632016-04-29 18:59:18 -07002382 private void migrateSystemToLockWallpaperLocked(int userId) {
2383 WallpaperData sysWP = mWallpaperMap.get(userId);
2384 if (sysWP == null) {
2385 if (DEBUG) {
2386 Slog.i(TAG, "No system wallpaper? Not tracking for lock-only");
2387 }
2388 return;
2389 }
2390
2391 // We know a-priori that there is no lock-only wallpaper currently
2392 WallpaperData lockWP = new WallpaperData(userId,
2393 WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP);
2394 lockWP.wallpaperId = sysWP.wallpaperId;
2395 lockWP.cropHint.set(sysWP.cropHint);
Christopher Tateedd8dc82016-10-12 15:17:58 -07002396 lockWP.allowBackup = sysWP.allowBackup;
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002397 lockWP.primaryColors = sysWP.primaryColors;
Christopher Tate8347b632016-04-29 18:59:18 -07002398
2399 // Migrate the bitmap files outright; no need to copy
2400 try {
2401 Os.rename(sysWP.wallpaperFile.getAbsolutePath(), lockWP.wallpaperFile.getAbsolutePath());
2402 Os.rename(sysWP.cropFile.getAbsolutePath(), lockWP.cropFile.getAbsolutePath());
2403 } catch (ErrnoException e) {
2404 Slog.e(TAG, "Can't migrate system wallpaper: " + e.getMessage());
2405 lockWP.wallpaperFile.delete();
2406 lockWP.cropFile.delete();
2407 return;
2408 }
2409
2410 mLockWallpaperMap.put(userId, lockWP);
2411 }
2412
Christopher Tatead3c2592016-01-20 18:13:17 -08002413 ParcelFileDescriptor updateWallpaperBitmapLocked(String name, WallpaperData wallpaper,
2414 Bundle extras) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002415 if (name == null) name = "";
2416 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002417 File dir = getWallpaperDir(wallpaper.userId);
2418 if (!dir.exists()) {
2419 dir.mkdir();
Dianne Hackbornebac48c2011-11-29 18:01:50 -08002420 FileUtils.setPermissions(
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002421 dir.getPath(),
Dianne Hackbornebac48c2011-11-29 18:01:50 -08002422 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
2423 -1, -1);
2424 }
Christopher Tatebe132e62016-02-10 12:59:49 -08002425 ParcelFileDescriptor fd = ParcelFileDescriptor.open(wallpaper.wallpaperFile,
Christopher Tate90f86ba2014-09-11 12:37:19 -07002426 MODE_CREATE|MODE_READ_WRITE|MODE_TRUNCATE);
Christopher Tatebe132e62016-02-10 12:59:49 -08002427 if (!SELinux.restorecon(wallpaper.wallpaperFile)) {
rpcraig554cb0c2012-07-05 06:41:43 -04002428 return null;
2429 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002430 wallpaper.name = name;
Christopher Tatead3c2592016-01-20 18:13:17 -08002431 wallpaper.wallpaperId = makeWallpaperIdLocked();
2432 if (extras != null) {
2433 extras.putInt(WallpaperManager.EXTRA_NEW_WALLPAPER_ID, wallpaper.wallpaperId);
2434 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002435 // Nullify field to require new computation
2436 wallpaper.primaryColors = null;
Christopher Tatead3c2592016-01-20 18:13:17 -08002437 if (DEBUG) {
2438 Slog.v(TAG, "updateWallpaperBitmapLocked() : id=" + wallpaper.wallpaperId
Christopher Tatebe132e62016-02-10 12:59:49 -08002439 + " name=" + name + " file=" + wallpaper.wallpaperFile.getName());
Christopher Tatead3c2592016-01-20 18:13:17 -08002440 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002441 return fd;
2442 } catch (FileNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002443 Slog.w(TAG, "Error setting wallpaper", e);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002444 }
2445 return null;
2446 }
2447
Christopher Tated57d17c2016-03-25 13:41:46 -07002448 @Override
Adrian Roos40ea0832016-07-14 14:19:55 -07002449 public void setWallpaperComponentChecked(ComponentName name, String callingPackage,
2450 int userId) {
2451
Christopher Tate98d609c2016-05-18 17:31:58 -07002452 if (isWallpaperSupported(callingPackage) && isSetWallpaperAllowed(callingPackage)) {
Adrian Roos40ea0832016-07-14 14:19:55 -07002453 setWallpaperComponent(name, userId);
Benjamin Franzf3ece362015-02-11 10:51:10 +00002454 }
2455 }
2456
2457 // ToDo: Remove this version of the function
Christopher Tated57d17c2016-03-25 13:41:46 -07002458 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002459 public void setWallpaperComponent(ComponentName name) {
Adrian Roos40ea0832016-07-14 14:19:55 -07002460 setWallpaperComponent(name, UserHandle.getCallingUserId());
2461 }
2462
2463 private void setWallpaperComponent(ComponentName name, int userId) {
2464 userId = ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,
2465 false /* all */, true /* full */, "changing live wallpaper", null /* pkg */);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002466 checkPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT);
Adrian Roos40ea0832016-07-14 14:19:55 -07002467
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002468 int which = FLAG_SYSTEM;
2469 boolean shouldNotifyColors = false;
2470 WallpaperData wallpaper;
2471
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002472 synchronized (mLock) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002473 if (DEBUG) Slog.v(TAG, "setWallpaperComponent name=" + name);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002474 wallpaper = mWallpaperMap.get(userId);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002475 if (wallpaper == null) {
2476 throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
2477 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002478 final long ident = Binder.clearCallingIdentity();
Christopher Tate7cd00102016-12-19 14:38:44 -08002479
2480 // Live wallpapers can't be specified for keyguard. If we're using a static
2481 // system+lock image currently, migrate the system wallpaper to be a lock-only
2482 // image as part of making a different live component active as the system
2483 // wallpaper.
2484 if (mImageWallpaper.equals(wallpaper.wallpaperComponent)) {
2485 if (mLockWallpaperMap.get(userId) == null) {
2486 // We're using the static imagery and there is no lock-specific image in place,
2487 // therefore it's a shared system+lock image that we need to migrate.
2488 migrateSystemToLockWallpaperLocked(userId);
2489 }
2490 }
2491
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002492 // New live wallpaper is also a lock wallpaper if nothing is set
2493 if (mLockWallpaperMap.get(userId) == null) {
2494 which |= FLAG_LOCK;
2495 }
2496
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002497 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002498 wallpaper.imageWallpaperPending = false;
Lucas Dupin50ba9912017-07-14 11:55:05 -07002499 boolean same = changingToSame(name, wallpaper);
Christopher Tated57d17c2016-03-25 13:41:46 -07002500 if (bindWallpaperComponentLocked(name, false, true, wallpaper, null)) {
Lucas Dupin50ba9912017-07-14 11:55:05 -07002501 if (!same) {
2502 wallpaper.primaryColors = null;
2503 }
Christopher Tated57d17c2016-03-25 13:41:46 -07002504 wallpaper.wallpaperId = makeWallpaperIdLocked();
Sunny Goyal0572e182016-03-31 11:05:51 -07002505 notifyCallbacksLocked(wallpaper);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002506 shouldNotifyColors = true;
Christopher Tated57d17c2016-03-25 13:41:46 -07002507 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002508 } finally {
2509 Binder.restoreCallingIdentity(ident);
2510 }
2511 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002512
2513 if (shouldNotifyColors) {
2514 notifyWallpaperColorsChanged(wallpaper, which);
wilsonshih36597d42018-12-05 18:56:39 +08002515 notifyWallpaperColorsChanged(mFallbackWallpaper, FLAG_SYSTEM);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002516 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002517 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01002518
Lucas Dupin50ba9912017-07-14 11:55:05 -07002519 private boolean changingToSame(ComponentName componentName, WallpaperData wallpaper) {
2520 if (wallpaper.connection != null) {
2521 if (wallpaper.wallpaperComponent == null) {
2522 if (componentName == null) {
2523 if (DEBUG) Slog.v(TAG, "changingToSame: still using default");
2524 // Still using default wallpaper.
2525 return true;
2526 }
2527 } else if (wallpaper.wallpaperComponent.equals(componentName)) {
2528 // Changing to same wallpaper.
2529 if (DEBUG) Slog.v(TAG, "same wallpaper");
2530 return true;
2531 }
2532 }
2533 return false;
2534 }
2535
wilsonshiha282bf72018-11-30 12:48:05 +08002536 private boolean bindWallpaperComponentLocked(ComponentName componentName, boolean force,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002537 boolean fromUser, WallpaperData wallpaper, IRemoteCallback reply) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07002538 if (DEBUG_LIVE) {
2539 Slog.v(TAG, "bindWallpaperComponentLocked: componentName=" + componentName);
2540 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002541 // Has the component changed?
Lucas Dupin50ba9912017-07-14 11:55:05 -07002542 if (!force && changingToSame(componentName, wallpaper)) {
2543 return true;
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002544 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01002545
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002546 try {
Mike Clerona428b2c2009-11-15 22:53:08 -08002547 if (componentName == null) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07002548 componentName = mDefaultWallpaperComponent;
Mike Clerona428b2c2009-11-15 22:53:08 -08002549 if (componentName == null) {
Mike Cleron322b6ee2009-11-12 07:45:47 -08002550 // Fall back to static image wallpaper
Justin Koh29c30162014-09-05 17:10:10 -07002551 componentName = mImageWallpaper;
Mike Cleron322b6ee2009-11-12 07:45:47 -08002552 //clearWallpaperComponentLocked();
2553 //return;
Christopher Tate2a6c55f2017-03-31 12:28:30 -07002554 if (DEBUG_LIVE) Slog.v(TAG, "No default component; using image wallpaper");
Mike Cleron322b6ee2009-11-12 07:45:47 -08002555 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002556 }
Amith Yamasani4e2820c2012-08-28 22:17:23 -07002557 int serviceUserId = wallpaper.userId;
2558 ServiceInfo si = mIPackageManager.getServiceInfo(componentName,
2559 PackageManager.GET_META_DATA | PackageManager.GET_PERMISSIONS, serviceUserId);
Christopher Tate90952202013-09-08 13:01:28 -07002560 if (si == null) {
2561 // The wallpaper component we're trying to use doesn't exist
2562 Slog.w(TAG, "Attempted wallpaper " + componentName + " is unavailable");
2563 return false;
2564 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002565 if (!android.Manifest.permission.BIND_WALLPAPER.equals(si.permission)) {
Lucas Dupin4c8c3272018-11-06 17:47:48 -08002566 String msg = "Selected service does not have "
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002567 + android.Manifest.permission.BIND_WALLPAPER
Dianne Hackborn80b902f2011-09-15 15:15:27 -07002568 + ": " + componentName;
2569 if (fromUser) {
2570 throw new SecurityException(msg);
2571 }
2572 Slog.w(TAG, msg);
2573 return false;
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002574 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01002575
Dianne Hackborneb034652009-09-07 00:49:58 -07002576 WallpaperInfo wi = null;
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01002577
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002578 Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
Justin Koh29c30162014-09-05 17:10:10 -07002579 if (componentName != null && !componentName.equals(mImageWallpaper)) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002580 // Make sure the selected service is actually a wallpaper service.
Amith Yamasani4e2820c2012-08-28 22:17:23 -07002581 List<ResolveInfo> ris =
2582 mIPackageManager.queryIntentServices(intent,
2583 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
Jeff Sharkeyd5896632016-03-04 16:16:00 -07002584 PackageManager.GET_META_DATA, serviceUserId).getList();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002585 for (int i=0; i<ris.size(); i++) {
2586 ServiceInfo rsi = ris.get(i).serviceInfo;
2587 if (rsi.name.equals(si.name) &&
2588 rsi.packageName.equals(si.packageName)) {
Dianne Hackborneb034652009-09-07 00:49:58 -07002589 try {
2590 wi = new WallpaperInfo(mContext, ris.get(i));
2591 } catch (XmlPullParserException e) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -07002592 if (fromUser) {
2593 throw new IllegalArgumentException(e);
2594 }
2595 Slog.w(TAG, e);
2596 return false;
Dianne Hackborneb034652009-09-07 00:49:58 -07002597 } catch (IOException e) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -07002598 if (fromUser) {
2599 throw new IllegalArgumentException(e);
2600 }
2601 Slog.w(TAG, e);
2602 return false;
Dianne Hackborneb034652009-09-07 00:49:58 -07002603 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002604 break;
2605 }
2606 }
Dianne Hackborneb034652009-09-07 00:49:58 -07002607 if (wi == null) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -07002608 String msg = "Selected service is not a wallpaper: "
2609 + componentName;
2610 if (fromUser) {
2611 throw new SecurityException(msg);
2612 }
2613 Slog.w(TAG, msg);
2614 return false;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002615 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002616 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01002617
Lucas Dupin4c8c3272018-11-06 17:47:48 -08002618 if (wi != null && wi.supportsAmbientMode()) {
2619 final int hasPrivilege = mIPackageManager.checkPermission(
2620 android.Manifest.permission.AMBIENT_WALLPAPER, wi.getPackageName(),
2621 serviceUserId);
2622 if (hasPrivilege != PackageManager.PERMISSION_GRANTED) {
2623 String msg = "Selected service does not have "
2624 + android.Manifest.permission.AMBIENT_WALLPAPER
2625 + ": " + componentName;
2626 if (fromUser) {
2627 throw new SecurityException(msg);
2628 }
2629 Slog.w(TAG, msg);
2630 return false;
2631 }
2632 }
2633
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002634 // Bind the service!
Joe Onorato8a9b2202010-02-26 18:56:32 -08002635 if (DEBUG) Slog.v(TAG, "Binding to:" + componentName);
wilsonshihde93f492018-11-01 21:23:40 +08002636 final int componentUid = mIPackageManager.getPackageUid(componentName.getPackageName(),
2637 MATCH_DIRECT_BOOT_AUTO, wallpaper.userId);
2638 WallpaperConnection newConn = new WallpaperConnection(wi, wallpaper, componentUid);
Mike Clerona428b2c2009-11-15 22:53:08 -08002639 intent.setComponent(componentName);
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07002640 intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
2641 com.android.internal.R.string.wallpaper_binding_label);
Dianne Hackborn41203752012-08-31 14:05:51 -07002642 intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivityAsUser(
Dianne Hackborneb034652009-09-07 00:49:58 -07002643 mContext, 0,
2644 Intent.createChooser(new Intent(Intent.ACTION_SET_WALLPAPER),
2645 mContext.getText(com.android.internal.R.string.chooser_wallpaper)),
Dianne Hackborn41203752012-08-31 14:05:51 -07002646 0, null, new UserHandle(serviceUserId)));
Dianne Hackbornc8230512013-07-13 21:32:12 -07002647 if (!mContext.bindServiceAsUser(intent, newConn,
Dianne Hackbornd69e4c12015-04-24 09:54:54 -07002648 Context.BIND_AUTO_CREATE | Context.BIND_SHOWING_UI
2649 | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
Amith Yamasani27b89e62013-01-16 12:30:11 -08002650 new UserHandle(serviceUserId))) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -07002651 String msg = "Unable to bind service: "
2652 + componentName;
2653 if (fromUser) {
2654 throw new IllegalArgumentException(msg);
2655 }
2656 Slog.w(TAG, msg);
2657 return false;
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002658 }
wilsonshiha282bf72018-11-30 12:48:05 +08002659 if (wallpaper.userId == mCurrentUserId && mLastWallpaper != null
2660 && !wallpaper.equals(mFallbackWallpaper)) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002661 detachWallpaperLocked(mLastWallpaper);
2662 }
2663 wallpaper.wallpaperComponent = componentName;
2664 wallpaper.connection = newConn;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002665 newConn.mReply = reply;
wilsonshiha282bf72018-11-30 12:48:05 +08002666 if (wallpaper.userId == mCurrentUserId && !wallpaper.equals(mFallbackWallpaper)) {
wilsonshihde93f492018-11-01 21:23:40 +08002667 mLastWallpaper = wallpaper;
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002668 }
wilsonshiha282bf72018-11-30 12:48:05 +08002669 updateFallbackConnection();
Amith Yamasani4e2820c2012-08-28 22:17:23 -07002670 } catch (RemoteException e) {
2671 String msg = "Remote exception for " + componentName + "\n" + e;
Dianne Hackborn80b902f2011-09-15 15:15:27 -07002672 if (fromUser) {
2673 throw new IllegalArgumentException(msg);
2674 }
2675 Slog.w(TAG, msg);
2676 return false;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002677 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -07002678 return true;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002679 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002680
wilsonshiha282bf72018-11-30 12:48:05 +08002681 private void detachWallpaperLocked(WallpaperData wallpaper) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002682 if (wallpaper.connection != null) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002683 if (wallpaper.connection.mReply != null) {
2684 try {
2685 wallpaper.connection.mReply.sendResult(null);
2686 } catch (RemoteException e) {
2687 }
2688 wallpaper.connection.mReply = null;
2689 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002690 mContext.unbindService(wallpaper.connection);
wilsonshiha282bf72018-11-30 12:48:05 +08002691 wallpaper.connection.forEachDisplayConnector(
2692 WallpaperConnection.DisplayConnector::disconnectLocked);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002693 wallpaper.connection.mService = null;
wilsonshihde93f492018-11-01 21:23:40 +08002694 wallpaper.connection.mDisplayConnector.clear();
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002695 wallpaper.connection = null;
wilsonshihde93f492018-11-01 21:23:40 +08002696 if (wallpaper == mLastWallpaper) mLastWallpaper = null;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002697 }
2698 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002699
wilsonshiha282bf72018-11-30 12:48:05 +08002700 private void clearWallpaperComponentLocked(WallpaperData wallpaper) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002701 wallpaper.wallpaperComponent = null;
2702 detachWallpaperLocked(wallpaper);
2703 }
2704
wilsonshiha282bf72018-11-30 12:48:05 +08002705 private void attachServiceLocked(WallpaperConnection conn, WallpaperData wallpaper) {
wilsonshihde93f492018-11-01 21:23:40 +08002706 conn.forEachDisplayConnector(connector-> connector.connectLocked(conn, wallpaper));
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002707 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002708
2709 private void notifyCallbacksLocked(WallpaperData wallpaper) {
2710 final int n = wallpaper.callbacks.beginBroadcast();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002711 for (int i = 0; i < n; i++) {
2712 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002713 wallpaper.callbacks.getBroadcastItem(i).onWallpaperChanged();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002714 } catch (RemoteException e) {
2715
2716 // The RemoteCallbackList will take care of removing
2717 // the dead object for us.
2718 }
2719 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002720 wallpaper.callbacks.finishBroadcast();
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002721
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002722 final Intent intent = new Intent(Intent.ACTION_WALLPAPER_CHANGED);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07002723 mContext.sendBroadcastAsUser(intent, new UserHandle(mCurrentUserId));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002724 }
2725
2726 private void checkPermission(String permission) {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002727 if (PackageManager.PERMISSION_GRANTED!= mContext.checkCallingOrSelfPermission(permission)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002728 throw new SecurityException("Access denied to process: " + Binder.getCallingPid()
2729 + ", must have permission " + permission);
2730 }
2731 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002732
Benjamin Franzf3ece362015-02-11 10:51:10 +00002733 /**
2734 * Certain user types do not support wallpapers (e.g. managed profiles). The check is
2735 * implemented through through the OP_WRITE_WALLPAPER AppOp.
2736 */
2737 public boolean isWallpaperSupported(String callingPackage) {
2738 return mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_WRITE_WALLPAPER, Binder.getCallingUid(),
2739 callingPackage) == AppOpsManager.MODE_ALLOWED;
2740 }
2741
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01002742 @Override
Christopher Tate98d609c2016-05-18 17:31:58 -07002743 public boolean isSetWallpaperAllowed(String callingPackage) {
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01002744 final PackageManager pm = mContext.getPackageManager();
2745 String[] uidPackages = pm.getPackagesForUid(Binder.getCallingUid());
2746 boolean uidMatchPackage = Arrays.asList(uidPackages).contains(callingPackage);
2747 if (!uidMatchPackage) {
2748 return false; // callingPackage was faked.
2749 }
2750
2751 final DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
2752 if (dpm.isDeviceOwnerApp(callingPackage) || dpm.isProfileOwnerApp(callingPackage)) {
2753 return true;
2754 }
2755 final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
2756 return !um.hasUserRestriction(UserManager.DISALLOW_SET_WALLPAPER);
2757 }
2758
Christopher Tated7faf532016-02-25 12:43:38 -08002759 @Override
Christopher Tate61722662016-08-10 16:13:14 -07002760 public boolean isWallpaperBackupEligible(int which, int userId) {
Christopher Tated7faf532016-02-25 12:43:38 -08002761 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
2762 throw new SecurityException("Only the system may call isWallpaperBackupEligible");
2763 }
2764
Christopher Tate61722662016-08-10 16:13:14 -07002765 WallpaperData wallpaper = (which == FLAG_LOCK)
Christopher Tatef7d1b5d2016-08-19 11:21:07 -07002766 ? mLockWallpaperMap.get(userId)
2767 : mWallpaperMap.get(userId);
Christopher Tated7faf532016-02-25 12:43:38 -08002768 return (wallpaper != null) ? wallpaper.allowBackup : false;
2769 }
2770
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002771 private static JournaledFile makeJournaledFile(int userId) {
Amith Yamasani61f57372012-08-31 12:12:28 -07002772 final String base = new File(getWallpaperDir(userId), WALLPAPER_INFO).getAbsolutePath();
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002773 return new JournaledFile(new File(base), new File(base + ".tmp"));
2774 }
2775
Christopher Tatedb27b842016-02-25 14:39:17 -08002776 private void saveSettingsLocked(int userId) {
2777 JournaledFile journal = makeJournaledFile(userId);
2778 FileOutputStream fstream = null;
2779 BufferedOutputStream stream = null;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002780 try {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002781 XmlSerializer out = new FastXmlSerializer();
Christopher Tatedb27b842016-02-25 14:39:17 -08002782 fstream = new FileOutputStream(journal.chooseForWrite(), false);
2783 stream = new BufferedOutputStream(fstream);
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01002784 out.setOutput(stream, StandardCharsets.UTF_8.name());
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002785 out.startDocument(null, true);
2786
Christopher Tatedb27b842016-02-25 14:39:17 -08002787 WallpaperData wallpaper;
Christopher Tate1e1e2e02016-01-25 15:34:36 -08002788
Christopher Tatedb27b842016-02-25 14:39:17 -08002789 wallpaper = mWallpaperMap.get(userId);
2790 if (wallpaper != null) {
2791 writeWallpaperAttributes(out, "wp", wallpaper);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002792 }
Christopher Tatedb27b842016-02-25 14:39:17 -08002793 wallpaper = mLockWallpaperMap.get(userId);
2794 if (wallpaper != null) {
2795 writeWallpaperAttributes(out, "kwp", wallpaper);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002796 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002797
2798 out.endDocument();
Christopher Tatedb27b842016-02-25 14:39:17 -08002799
2800 stream.flush(); // also flushes fstream
2801 FileUtils.sync(fstream);
2802 stream.close(); // also closes fstream
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002803 journal.commit();
2804 } catch (IOException e) {
Christopher Tatead3c2592016-01-20 18:13:17 -08002805 IoUtils.closeQuietly(stream);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002806 journal.rollback();
2807 }
2808 }
2809
Christopher Tatedb27b842016-02-25 14:39:17 -08002810 private void writeWallpaperAttributes(XmlSerializer out, String tag, WallpaperData wallpaper)
2811 throws IllegalArgumentException, IllegalStateException, IOException {
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002812 if (DEBUG) {
Christopher Tatef717b932017-09-11 15:52:54 -07002813 Slog.v(TAG, "writeWallpaperAttributes id=" + wallpaper.wallpaperId);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002814 }
wilsonshiha282bf72018-11-30 12:48:05 +08002815 final DisplayData wpdData = getDisplayDataOrCreate(DEFAULT_DISPLAY);
Christopher Tatedb27b842016-02-25 14:39:17 -08002816 out.startTag(null, tag);
2817 out.attribute(null, "id", Integer.toString(wallpaper.wallpaperId));
wilsonshih81e10a72018-11-15 10:54:21 +08002818 out.attribute(null, "width", Integer.toString(wpdData.mWidth));
2819 out.attribute(null, "height", Integer.toString(wpdData.mHeight));
Christopher Tatedb27b842016-02-25 14:39:17 -08002820
2821 out.attribute(null, "cropLeft", Integer.toString(wallpaper.cropHint.left));
2822 out.attribute(null, "cropTop", Integer.toString(wallpaper.cropHint.top));
2823 out.attribute(null, "cropRight", Integer.toString(wallpaper.cropHint.right));
2824 out.attribute(null, "cropBottom", Integer.toString(wallpaper.cropHint.bottom));
2825
wilsonshih81e10a72018-11-15 10:54:21 +08002826 if (wpdData.mPadding.left != 0) {
2827 out.attribute(null, "paddingLeft", Integer.toString(wpdData.mPadding.left));
Christopher Tatedb27b842016-02-25 14:39:17 -08002828 }
wilsonshih81e10a72018-11-15 10:54:21 +08002829 if (wpdData.mPadding.top != 0) {
2830 out.attribute(null, "paddingTop", Integer.toString(wpdData.mPadding.top));
Christopher Tatedb27b842016-02-25 14:39:17 -08002831 }
wilsonshih81e10a72018-11-15 10:54:21 +08002832 if (wpdData.mPadding.right != 0) {
2833 out.attribute(null, "paddingRight", Integer.toString(wpdData.mPadding.right));
Christopher Tatedb27b842016-02-25 14:39:17 -08002834 }
wilsonshih81e10a72018-11-15 10:54:21 +08002835 if (wpdData.mPadding.bottom != 0) {
2836 out.attribute(null, "paddingBottom", Integer.toString(wpdData.mPadding.bottom));
Christopher Tatedb27b842016-02-25 14:39:17 -08002837 }
2838
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002839 if (wallpaper.primaryColors != null) {
Lucas Dupin84b89d92017-05-09 12:16:19 -07002840 int colorsCount = wallpaper.primaryColors.getMainColors().size();
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002841 out.attribute(null, "colorsCount", Integer.toString(colorsCount));
2842 if (colorsCount > 0) {
2843 for (int i = 0; i < colorsCount; i++) {
Lucas Dupin84b89d92017-05-09 12:16:19 -07002844 final Color wc = wallpaper.primaryColors.getMainColors().get(i);
2845 out.attribute(null, "colorValue"+i, Integer.toString(wc.toArgb()));
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002846 }
2847 }
Lucas Dupin75ec3792017-06-29 14:07:18 -07002848 out.attribute(null, "colorHints",
Lucas Dupin84b89d92017-05-09 12:16:19 -07002849 Integer.toString(wallpaper.primaryColors.getColorHints()));
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002850 }
2851
Christopher Tatedb27b842016-02-25 14:39:17 -08002852 out.attribute(null, "name", wallpaper.name);
2853 if (wallpaper.wallpaperComponent != null
2854 && !wallpaper.wallpaperComponent.equals(mImageWallpaper)) {
2855 out.attribute(null, "component",
2856 wallpaper.wallpaperComponent.flattenToShortString());
2857 }
Christopher Tated7faf532016-02-25 12:43:38 -08002858
2859 if (wallpaper.allowBackup) {
2860 out.attribute(null, "backup", "true");
2861 }
2862
Christopher Tatedb27b842016-02-25 14:39:17 -08002863 out.endTag(null, tag);
2864 }
2865
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002866 private void migrateFromOld() {
Christopher Tate9f224432017-08-01 16:32:49 -07002867 // Pre-N, what existed is the one we're now using as the display crop
2868 File preNWallpaper = new File(getWallpaperDir(0), WALLPAPER_CROP);
2869 // In the very-long-ago, imagery lived with the settings app
2870 File originalWallpaper = new File(WallpaperBackupHelper.WALLPAPER_IMAGE_KEY);
2871 File newWallpaper = new File(getWallpaperDir(0), WALLPAPER);
2872
2873 // Migrations from earlier wallpaper image storage schemas
2874 if (preNWallpaper.exists()) {
2875 if (!newWallpaper.exists()) {
2876 // we've got the 'wallpaper' crop file but not the nominal source image,
2877 // so do the simple "just take everything" straight copy of legacy data
2878 if (DEBUG) {
2879 Slog.i(TAG, "Migrating wallpaper schema");
2880 }
2881 FileUtils.copyFile(preNWallpaper, newWallpaper);
2882 } // else we're in the usual modern case: both source & crop exist
2883 } else if (originalWallpaper.exists()) {
2884 // VERY old schema; make sure things exist and are in the right place
2885 if (DEBUG) {
2886 Slog.i(TAG, "Migrating antique wallpaper schema");
2887 }
2888 File oldInfo = new File(WallpaperBackupHelper.WALLPAPER_INFO_KEY);
2889 if (oldInfo.exists()) {
2890 File newInfo = new File(getWallpaperDir(0), WALLPAPER_INFO);
2891 oldInfo.renameTo(newInfo);
2892 }
2893
2894 FileUtils.copyFile(originalWallpaper, preNWallpaper);
2895 originalWallpaper.renameTo(newWallpaper);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002896 }
2897 }
2898
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002899 private int getAttributeInt(XmlPullParser parser, String name, int defValue) {
2900 String value = parser.getAttributeValue(null, name);
2901 if (value == null) {
2902 return defValue;
2903 }
2904 return Integer.parseInt(value);
2905 }
2906
Xiaohui Chenac531942015-05-13 13:20:52 -07002907 /**
2908 * Sometimes it is expected the wallpaper map may not have a user's data. E.g. This could
2909 * happen during user switch. The async user switch observer may not have received
2910 * the event yet. We use this safe method when we don't care about this ordering and just
2911 * want to update the data. The data is going to be applied when the user switch observer
2912 * is eventually executed.
Christopher Tatef717b932017-09-11 15:52:54 -07002913 *
2914 * Important: this method loads settings to initialize the given user's wallpaper data if
2915 * there is no current in-memory state.
Xiaohui Chenac531942015-05-13 13:20:52 -07002916 */
Christopher Tatebe132e62016-02-10 12:59:49 -08002917 private WallpaperData getWallpaperSafeLocked(int userId, int which) {
2918 // We're setting either just system (work with the system wallpaper),
2919 // both (also work with the system wallpaper), or just the lock
2920 // wallpaper (update against the existing lock wallpaper if any).
2921 // Combined or just-system operations use the 'system' WallpaperData
2922 // for this use; lock-only operations use the dedicated one.
2923 final SparseArray<WallpaperData> whichSet =
Christopher Tateedf7d042016-03-29 18:24:25 -07002924 (which == FLAG_LOCK) ? mLockWallpaperMap : mWallpaperMap;
Christopher Tatebe132e62016-02-10 12:59:49 -08002925 WallpaperData wallpaper = whichSet.get(userId);
Xiaohui Chenac531942015-05-13 13:20:52 -07002926 if (wallpaper == null) {
Christopher Tatebe132e62016-02-10 12:59:49 -08002927 // common case, this is the first lookup post-boot of the system or
2928 // unified lock, so we bring up the saved state lazily now and recheck.
Christopher Tated7faf532016-02-25 12:43:38 -08002929 loadSettingsLocked(userId, false);
Christopher Tatebe132e62016-02-10 12:59:49 -08002930 wallpaper = whichSet.get(userId);
2931 // if it's still null here, this is a lock-only operation and there is not
2932 // yet a lock-only wallpaper set for this user, so we need to establish
2933 // it now.
2934 if (wallpaper == null) {
Christopher Tateedf7d042016-03-29 18:24:25 -07002935 if (which == FLAG_LOCK) {
Christopher Tatebe132e62016-02-10 12:59:49 -08002936 wallpaper = new WallpaperData(userId,
2937 WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP);
2938 mLockWallpaperMap.put(userId, wallpaper);
wilsonshih81e10a72018-11-15 10:54:21 +08002939 ensureSaneWallpaperData(wallpaper, DEFAULT_DISPLAY);
Christopher Tatebe132e62016-02-10 12:59:49 -08002940 } else {
2941 // sanity fallback: we're in bad shape, but establishing a known
2942 // valid system+lock WallpaperData will keep us from dying.
2943 Slog.wtf(TAG, "Didn't find wallpaper in non-lock case!");
2944 wallpaper = new WallpaperData(userId, WALLPAPER, WALLPAPER_CROP);
2945 mWallpaperMap.put(userId, wallpaper);
wilsonshih81e10a72018-11-15 10:54:21 +08002946 ensureSaneWallpaperData(wallpaper, DEFAULT_DISPLAY);
Christopher Tatebe132e62016-02-10 12:59:49 -08002947 }
2948 }
Xiaohui Chenac531942015-05-13 13:20:52 -07002949 }
2950 return wallpaper;
2951 }
2952
Christopher Tated7faf532016-02-25 12:43:38 -08002953 private void loadSettingsLocked(int userId, boolean keepDimensionHints) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002954 JournaledFile journal = makeJournaledFile(userId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002955 FileInputStream stream = null;
2956 File file = journal.chooseForRead();
Christopher Tate9f224432017-08-01 16:32:49 -07002957
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002958 WallpaperData wallpaper = mWallpaperMap.get(userId);
2959 if (wallpaper == null) {
Christopher Tate9f224432017-08-01 16:32:49 -07002960 // Do this once per boot
2961 migrateFromOld();
2962
Christopher Tatebe132e62016-02-10 12:59:49 -08002963 wallpaper = new WallpaperData(userId, WALLPAPER, WALLPAPER_CROP);
Christopher Tated7faf532016-02-25 12:43:38 -08002964 wallpaper.allowBackup = true;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002965 mWallpaperMap.put(userId, wallpaper);
Christopher Tate41297ff2016-03-10 16:46:15 -08002966 if (!wallpaper.cropExists()) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07002967 if (wallpaper.sourceExists()) {
2968 generateCrop(wallpaper);
2969 } else {
2970 Slog.i(TAG, "No static wallpaper imagery; defaults will be shown");
2971 }
Christopher Tate41297ff2016-03-10 16:46:15 -08002972 }
wilsonshiha282bf72018-11-30 12:48:05 +08002973 initializeFallbackWallpaper();
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002974 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002975 boolean success = false;
wilsonshiha282bf72018-11-30 12:48:05 +08002976 final DisplayData wpdData = getDisplayDataOrCreate(DEFAULT_DISPLAY);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002977 try {
2978 stream = new FileInputStream(file);
2979 XmlPullParser parser = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01002980 parser.setInput(stream, StandardCharsets.UTF_8.name());
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002981
2982 int type;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002983 do {
2984 type = parser.next();
2985 if (type == XmlPullParser.START_TAG) {
2986 String tag = parser.getName();
2987 if ("wp".equals(tag)) {
Christopher Tatebe132e62016-02-10 12:59:49 -08002988 // Common to system + lock wallpapers
Christopher Tated7faf532016-02-25 12:43:38 -08002989 parseWallpaperAttributes(parser, wallpaper, keepDimensionHints);
Christopher Tatead3c2592016-01-20 18:13:17 -08002990
Christopher Tatebe132e62016-02-10 12:59:49 -08002991 // A system wallpaper might also be a live wallpaper
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002992 String comp = parser.getAttributeValue(null, "component");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002993 wallpaper.nextWallpaperComponent = comp != null
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002994 ? ComponentName.unflattenFromString(comp)
2995 : null;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002996 if (wallpaper.nextWallpaperComponent == null
2997 || "android".equals(wallpaper.nextWallpaperComponent
2998 .getPackageName())) {
Justin Koh29c30162014-09-05 17:10:10 -07002999 wallpaper.nextWallpaperComponent = mImageWallpaper;
Dianne Hackborn9ea31632011-08-05 14:43:50 -07003000 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01003001
Mike Clerona428b2c2009-11-15 22:53:08 -08003002 if (DEBUG) {
wilsonshih81e10a72018-11-15 10:54:21 +08003003 Slog.v(TAG, "mWidth:" + wpdData.mWidth);
3004 Slog.v(TAG, "mHeight:" + wpdData.mHeight);
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003005 Slog.v(TAG, "cropRect:" + wallpaper.cropHint);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07003006 Slog.v(TAG, "primaryColors:" + wallpaper.primaryColors);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003007 Slog.v(TAG, "mName:" + wallpaper.name);
3008 Slog.v(TAG, "mNextWallpaperComponent:"
3009 + wallpaper.nextWallpaperComponent);
Mike Clerona428b2c2009-11-15 22:53:08 -08003010 }
Christopher Tatebe132e62016-02-10 12:59:49 -08003011 } else if ("kwp".equals(tag)) {
3012 // keyguard-specific wallpaper for this user
3013 WallpaperData lockWallpaper = mLockWallpaperMap.get(userId);
3014 if (lockWallpaper == null) {
3015 lockWallpaper = new WallpaperData(userId,
3016 WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP);
3017 mLockWallpaperMap.put(userId, lockWallpaper);
3018 }
Christopher Tated7faf532016-02-25 12:43:38 -08003019 parseWallpaperAttributes(parser, lockWallpaper, false);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003020 }
3021 }
3022 } while (type != XmlPullParser.END_DOCUMENT);
3023 success = true;
Dianne Hackborn13579ed2012-11-28 18:05:36 -08003024 } catch (FileNotFoundException e) {
3025 Slog.w(TAG, "no current wallpaper -- first boot?");
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003026 } catch (NullPointerException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003027 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003028 } catch (NumberFormatException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003029 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003030 } catch (XmlPullParserException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003031 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003032 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003033 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003034 } catch (IndexOutOfBoundsException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003035 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003036 }
Christopher Tatead3c2592016-01-20 18:13:17 -08003037 IoUtils.closeQuietly(stream);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003038
3039 if (!success) {
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003040 wallpaper.cropHint.set(0, 0, 0, 0);
wilsonshih81e10a72018-11-15 10:54:21 +08003041 wpdData.mPadding.set(0, 0, 0, 0);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003042 wallpaper.name = "";
Adrian Roosc28e3a92016-04-14 10:47:52 -07003043
3044 mLockWallpaperMap.remove(userId);
Christopher Tatead3c2592016-01-20 18:13:17 -08003045 } else {
3046 if (wallpaper.wallpaperId <= 0) {
3047 wallpaper.wallpaperId = makeWallpaperIdLocked();
3048 if (DEBUG) {
3049 Slog.w(TAG, "Didn't set wallpaper id in loadSettingsLocked(" + userId
3050 + "); now " + wallpaper.wallpaperId);
3051 }
3052 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003053 }
Dianne Hackborn44bc17c2011-04-20 18:18:51 -07003054
wilsonshihd9173df2018-11-29 11:52:15 +08003055 ensureSaneWallpaperDisplaySize(wpdData, DEFAULT_DISPLAY);
wilsonshih81e10a72018-11-15 10:54:21 +08003056 ensureSaneWallpaperData(wallpaper, DEFAULT_DISPLAY);
Adrian Roosc28e3a92016-04-14 10:47:52 -07003057 WallpaperData lockWallpaper = mLockWallpaperMap.get(userId);
3058 if (lockWallpaper != null) {
wilsonshih81e10a72018-11-15 10:54:21 +08003059 ensureSaneWallpaperData(lockWallpaper, DEFAULT_DISPLAY);
Adrian Roosc28e3a92016-04-14 10:47:52 -07003060 }
3061 }
3062
wilsonshiha282bf72018-11-30 12:48:05 +08003063 private void initializeFallbackWallpaper() {
3064 if (mFallbackWallpaper == null) {
3065 if (DEBUG) Slog.d(TAG, "Initialize fallback wallpaper");
3066 mFallbackWallpaper = new WallpaperData(
3067 UserHandle.USER_SYSTEM, WALLPAPER, WALLPAPER_CROP);
3068 mFallbackWallpaper.allowBackup = false;
3069 mFallbackWallpaper.wallpaperId = makeWallpaperIdLocked();
3070 bindWallpaperComponentLocked(mImageWallpaper, true, false, mFallbackWallpaper, null);
3071 }
3072 }
3073
wilsonshih81e10a72018-11-15 10:54:21 +08003074 private void ensureSaneWallpaperData(WallpaperData wallpaper, int displayId) {
wilsonshiha282bf72018-11-30 12:48:05 +08003075 final DisplayData size = getDisplayDataOrCreate(displayId);
wilsonshih81e10a72018-11-15 10:54:21 +08003076
3077 if (displayId == DEFAULT_DISPLAY) {
3078 // crop, if not previously specified
3079 if (wallpaper.cropHint.width() <= 0
3080 || wallpaper.cropHint.height() <= 0) {
3081 wallpaper.cropHint.set(0, 0, size.mWidth, size.mHeight);
3082 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003083 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003084 }
3085
Christopher Tated7faf532016-02-25 12:43:38 -08003086 private void parseWallpaperAttributes(XmlPullParser parser, WallpaperData wallpaper,
3087 boolean keepDimensionHints) {
Christopher Tatebe132e62016-02-10 12:59:49 -08003088 final String idString = parser.getAttributeValue(null, "id");
3089 if (idString != null) {
3090 final int id = wallpaper.wallpaperId = Integer.parseInt(idString);
3091 if (id > mWallpaperId) {
3092 mWallpaperId = id;
3093 }
3094 } else {
3095 wallpaper.wallpaperId = makeWallpaperIdLocked();
3096 }
3097
wilsonshiha282bf72018-11-30 12:48:05 +08003098 final DisplayData wpData = getDisplayDataOrCreate(DEFAULT_DISPLAY);
wilsonshih81e10a72018-11-15 10:54:21 +08003099
Christopher Tated7faf532016-02-25 12:43:38 -08003100 if (!keepDimensionHints) {
wilsonshih81e10a72018-11-15 10:54:21 +08003101 wpData.mWidth = Integer.parseInt(parser.getAttributeValue(null, "width"));
3102 wpData.mHeight = Integer.parseInt(parser.getAttributeValue(null, "height"));
Christopher Tated7faf532016-02-25 12:43:38 -08003103 }
Christopher Tatebe132e62016-02-10 12:59:49 -08003104 wallpaper.cropHint.left = getAttributeInt(parser, "cropLeft", 0);
3105 wallpaper.cropHint.top = getAttributeInt(parser, "cropTop", 0);
3106 wallpaper.cropHint.right = getAttributeInt(parser, "cropRight", 0);
3107 wallpaper.cropHint.bottom = getAttributeInt(parser, "cropBottom", 0);
wilsonshih81e10a72018-11-15 10:54:21 +08003108 wpData.mPadding.left = getAttributeInt(parser, "paddingLeft", 0);
3109 wpData.mPadding.top = getAttributeInt(parser, "paddingTop", 0);
3110 wpData.mPadding.right = getAttributeInt(parser, "paddingRight", 0);
3111 wpData.mPadding.bottom = getAttributeInt(parser, "paddingBottom", 0);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07003112 int colorsCount = getAttributeInt(parser, "colorsCount", 0);
3113 if (colorsCount > 0) {
Lucas Dupin84b89d92017-05-09 12:16:19 -07003114 Color primary = null, secondary = null, tertiary = null;
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07003115 for (int i = 0; i < colorsCount; i++) {
Lucas Dupin84b89d92017-05-09 12:16:19 -07003116 Color color = Color.valueOf(getAttributeInt(parser, "colorValue" + i, 0));
3117 if (i == 0) {
3118 primary = color;
3119 } else if (i == 1) {
3120 secondary = color;
3121 } else if (i == 2) {
3122 tertiary = color;
3123 } else {
3124 break;
3125 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07003126 }
Lucas Dupin84b89d92017-05-09 12:16:19 -07003127 int colorHints = getAttributeInt(parser, "colorHints", 0);
3128 wallpaper.primaryColors = new WallpaperColors(primary, secondary, tertiary, colorHints);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07003129 }
Christopher Tatebe132e62016-02-10 12:59:49 -08003130 wallpaper.name = parser.getAttributeValue(null, "name");
Christopher Tated7faf532016-02-25 12:43:38 -08003131 wallpaper.allowBackup = "true".equals(parser.getAttributeValue(null, "backup"));
Christopher Tatebe132e62016-02-10 12:59:49 -08003132 }
3133
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07003134 // Called by SystemBackupAgent after files are restored to disk.
Amith Yamasani09e9cdc2013-11-06 14:54:50 -08003135 public void settingsRestored() {
3136 // Verify caller is the system
3137 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
3138 throw new RuntimeException("settingsRestored() can only be called from the system process");
3139 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003140 // TODO: If necessary, make it work for secondary users as well. This currently assumes
3141 // restores only to the primary user
Joe Onorato8a9b2202010-02-26 18:56:32 -08003142 if (DEBUG) Slog.v(TAG, "settingsRestored");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003143 WallpaperData wallpaper = null;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003144 boolean success = false;
3145 synchronized (mLock) {
Christopher Tated7faf532016-02-25 12:43:38 -08003146 loadSettingsLocked(UserHandle.USER_SYSTEM, false);
Christopher Tatedb27b842016-02-25 14:39:17 -08003147 wallpaper = mWallpaperMap.get(UserHandle.USER_SYSTEM);
Christopher Tatead3c2592016-01-20 18:13:17 -08003148 wallpaper.wallpaperId = makeWallpaperIdLocked(); // always bump id at restore
Christopher Tated7faf532016-02-25 12:43:38 -08003149 wallpaper.allowBackup = true; // by definition if it was restored
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003150 if (wallpaper.nextWallpaperComponent != null
Justin Koh29c30162014-09-05 17:10:10 -07003151 && !wallpaper.nextWallpaperComponent.equals(mImageWallpaper)) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003152 if (!bindWallpaperComponentLocked(wallpaper.nextWallpaperComponent, false, false,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07003153 wallpaper, null)) {
Christopher Tatee3ab4d02009-12-16 14:03:31 -08003154 // No such live wallpaper or other failure; fall back to the default
3155 // live wallpaper (since the profile being restored indicated that the
3156 // user had selected a live rather than static one).
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07003157 bindWallpaperComponentLocked(null, false, false, wallpaper, null);
Christopher Tatee3ab4d02009-12-16 14:03:31 -08003158 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003159 success = true;
3160 } else {
Mike Clerona428b2c2009-11-15 22:53:08 -08003161 // If there's a wallpaper name, we use that. If that can't be loaded, then we
3162 // use the default.
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003163 if ("".equals(wallpaper.name)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003164 if (DEBUG) Slog.v(TAG, "settingsRestored: name is empty");
Mike Clerona428b2c2009-11-15 22:53:08 -08003165 success = true;
3166 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003167 if (DEBUG) Slog.v(TAG, "settingsRestored: attempting to restore named resource");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003168 success = restoreNamedResourceLocked(wallpaper);
Mike Clerona428b2c2009-11-15 22:53:08 -08003169 }
Christopher Tatead3c2592016-01-20 18:13:17 -08003170 if (DEBUG) Slog.v(TAG, "settingsRestored: success=" + success
3171 + " id=" + wallpaper.wallpaperId);
Mike Clerona428b2c2009-11-15 22:53:08 -08003172 if (success) {
wilsonshih81e10a72018-11-15 10:54:21 +08003173 generateCrop(wallpaper); // based on the new image + metadata
Christopher Tate41297ff2016-03-10 16:46:15 -08003174 bindWallpaperComponentLocked(wallpaper.nextWallpaperComponent, true, false,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07003175 wallpaper, null);
Mike Clerona428b2c2009-11-15 22:53:08 -08003176 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003177 }
3178 }
3179
3180 if (!success) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003181 Slog.e(TAG, "Failed to restore wallpaper: '" + wallpaper.name + "'");
3182 wallpaper.name = "";
Christopher Tatedb27b842016-02-25 14:39:17 -08003183 getWallpaperDir(UserHandle.USER_SYSTEM).delete();
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003184 }
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07003185
3186 synchronized (mLock) {
Christopher Tatedb27b842016-02-25 14:39:17 -08003187 saveSettingsLocked(UserHandle.USER_SYSTEM);
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07003188 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003189 }
3190
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003191 // Restore the named resource bitmap to both source + crop files
wilsonshiha282bf72018-11-30 12:48:05 +08003192 private boolean restoreNamedResourceLocked(WallpaperData wallpaper) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003193 if (wallpaper.name.length() > 4 && "res:".equals(wallpaper.name.substring(0, 4))) {
3194 String resName = wallpaper.name.substring(4);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003195
3196 String pkg = null;
3197 int colon = resName.indexOf(':');
3198 if (colon > 0) {
3199 pkg = resName.substring(0, colon);
3200 }
3201
3202 String ident = null;
3203 int slash = resName.lastIndexOf('/');
3204 if (slash > 0) {
3205 ident = resName.substring(slash+1);
3206 }
3207
3208 String type = null;
3209 if (colon > 0 && slash > 0 && (slash-colon) > 1) {
3210 type = resName.substring(colon+1, slash);
3211 }
3212
3213 if (pkg != null && ident != null && type != null) {
3214 int resId = -1;
3215 InputStream res = null;
3216 FileOutputStream fos = null;
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003217 FileOutputStream cos = null;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003218 try {
3219 Context c = mContext.createPackageContext(pkg, Context.CONTEXT_RESTRICTED);
3220 Resources r = c.getResources();
3221 resId = r.getIdentifier(resName, null, null);
3222 if (resId == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003223 Slog.e(TAG, "couldn't resolve identifier pkg=" + pkg + " type=" + type
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003224 + " ident=" + ident);
3225 return false;
3226 }
3227
3228 res = r.openRawResource(resId);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003229 if (wallpaper.wallpaperFile.exists()) {
3230 wallpaper.wallpaperFile.delete();
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003231 wallpaper.cropFile.delete();
Dianne Hackborn1afd1c92010-03-18 22:47:17 -07003232 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003233 fos = new FileOutputStream(wallpaper.wallpaperFile);
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003234 cos = new FileOutputStream(wallpaper.cropFile);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003235
3236 byte[] buffer = new byte[32768];
3237 int amt;
3238 while ((amt=res.read(buffer)) > 0) {
3239 fos.write(buffer, 0, amt);
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003240 cos.write(buffer, 0, amt);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003241 }
3242 // mWallpaperObserver will notice the close and send the change broadcast
3243
Joe Onorato8a9b2202010-02-26 18:56:32 -08003244 Slog.v(TAG, "Restored wallpaper: " + resName);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003245 return true;
3246 } catch (NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003247 Slog.e(TAG, "Package name " + pkg + " not found");
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003248 } catch (Resources.NotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003249 Slog.e(TAG, "Resource not found: " + resId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003250 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003251 Slog.e(TAG, "IOException while restoring wallpaper ", e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003252 } finally {
Christopher Tatead3c2592016-01-20 18:13:17 -08003253 IoUtils.closeQuietly(res);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003254 if (fos != null) {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07003255 FileUtils.sync(fos);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003256 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003257 if (cos != null) {
3258 FileUtils.sync(cos);
3259 }
3260 IoUtils.closeQuietly(fos);
3261 IoUtils.closeQuietly(cos);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003262 }
3263 }
3264 }
3265 return false;
3266 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003267
Dianne Hackborneb034652009-09-07 00:49:58 -07003268 @Override
3269 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06003270 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Dianne Hackborneb034652009-09-07 00:49:58 -07003271
3272 synchronized (mLock) {
Adrian Roosc28e3a92016-04-14 10:47:52 -07003273 pw.println("System wallpaper state:");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003274 for (int i = 0; i < mWallpaperMap.size(); i++) {
3275 WallpaperData wallpaper = mWallpaperMap.valueAt(i);
Christopher Tatead3c2592016-01-20 18:13:17 -08003276 pw.print(" User "); pw.print(wallpaper.userId);
wilsonshiha282bf72018-11-30 12:48:05 +08003277 pw.print(": id="); pw.println(wallpaper.wallpaperId);
3278 pw.println(" Display state:");
3279 forEachDisplayData(wpSize -> {
wilsonshih81e10a72018-11-15 10:54:21 +08003280 pw.print(" displayId=");
3281 pw.println(wpSize.mDisplayId);
3282 pw.print(" mWidth=");
3283 pw.print(wpSize.mWidth);
3284 pw.print(" mHeight=");
3285 pw.println(wpSize.mHeight);
3286 pw.print(" mPadding="); pw.println(wpSize.mPadding);
3287 });
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003288 pw.print(" mCropHint="); pw.println(wallpaper.cropHint);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07003289 pw.print(" mName="); pw.println(wallpaper.name);
Bryan Mawhinney0fa54f42017-07-06 17:09:37 +01003290 pw.print(" mAllowBackup="); pw.println(wallpaper.allowBackup);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07003291 pw.print(" mWallpaperComponent="); pw.println(wallpaper.wallpaperComponent);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003292 if (wallpaper.connection != null) {
3293 WallpaperConnection conn = wallpaper.connection;
3294 pw.print(" Wallpaper connection ");
3295 pw.print(conn);
3296 pw.println(":");
3297 if (conn.mInfo != null) {
3298 pw.print(" mInfo.component=");
3299 pw.println(conn.mInfo.getComponent());
3300 }
wilsonshihde93f492018-11-01 21:23:40 +08003301 conn.forEachDisplayConnector(connector -> {
wilsonshiha282bf72018-11-30 12:48:05 +08003302 pw.print(" mDisplayId=");
wilsonshihde93f492018-11-01 21:23:40 +08003303 pw.println(connector.mDisplayId);
wilsonshiha282bf72018-11-30 12:48:05 +08003304 pw.print(" mToken=");
wilsonshihde93f492018-11-01 21:23:40 +08003305 pw.println(connector.mToken);
wilsonshiha282bf72018-11-30 12:48:05 +08003306 pw.print(" mEngine=");
wilsonshihde93f492018-11-01 21:23:40 +08003307 pw.println(connector.mEngine);
3308 });
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003309 pw.print(" mService=");
3310 pw.println(conn.mService);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003311 pw.print(" mLastDiedTime=");
3312 pw.println(wallpaper.lastDiedTime - SystemClock.uptimeMillis());
3313 }
Dianne Hackborneb034652009-09-07 00:49:58 -07003314 }
Adrian Roosc28e3a92016-04-14 10:47:52 -07003315 pw.println("Lock wallpaper state:");
3316 for (int i = 0; i < mLockWallpaperMap.size(); i++) {
3317 WallpaperData wallpaper = mLockWallpaperMap.valueAt(i);
3318 pw.print(" User "); pw.print(wallpaper.userId);
wilsonshih81e10a72018-11-15 10:54:21 +08003319 pw.print(": id="); pw.println(wallpaper.wallpaperId);
Adrian Roosc28e3a92016-04-14 10:47:52 -07003320 pw.print(" mCropHint="); pw.println(wallpaper.cropHint);
Adrian Roosc28e3a92016-04-14 10:47:52 -07003321 pw.print(" mName="); pw.println(wallpaper.name);
Bryan Mawhinney0fa54f42017-07-06 17:09:37 +01003322 pw.print(" mAllowBackup="); pw.println(wallpaper.allowBackup);
Adrian Roosc28e3a92016-04-14 10:47:52 -07003323 }
wilsonshiha282bf72018-11-30 12:48:05 +08003324 pw.println("Fallback wallpaper state:");
3325 pw.print(" User "); pw.print(mFallbackWallpaper.userId);
3326 pw.print(": id="); pw.println(mFallbackWallpaper.wallpaperId);
3327 pw.print(" mCropHint="); pw.println(mFallbackWallpaper.cropHint);
3328 pw.print(" mName="); pw.println(mFallbackWallpaper.name);
3329 pw.print(" mAllowBackup="); pw.println(mFallbackWallpaper.allowBackup);
3330 if (mFallbackWallpaper.connection != null) {
3331 WallpaperConnection conn = mFallbackWallpaper.connection;
3332 pw.print(" Fallback Wallpaper connection ");
3333 pw.print(conn);
3334 pw.println(":");
3335 if (conn.mInfo != null) {
3336 pw.print(" mInfo.component=");
3337 pw.println(conn.mInfo.getComponent());
3338 }
3339 conn.forEachDisplayConnector(connector -> {
3340 pw.print(" mDisplayId=");
3341 pw.println(connector.mDisplayId);
3342 pw.print(" mToken=");
3343 pw.println(connector.mToken);
3344 pw.print(" mEngine=");
3345 pw.println(connector.mEngine);
3346 });
3347 pw.print(" mService=");
3348 pw.println(conn.mService);
3349 pw.print(" mLastDiedTime=");
3350 pw.println(mFallbackWallpaper.lastDiedTime - SystemClock.uptimeMillis());
3351 }
Dianne Hackborneb034652009-09-07 00:49:58 -07003352 }
3353 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003354}