blob: b0ef8a0d420980cb2a35a75f2872393a6f1b2576 [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;
Ahan Wu723a80e2018-11-07 20:39:32 +080087import android.util.FeatureFlagUtils;
Joe Onorato8a9b2202010-02-26 18:56:32 -080088import android.util.Slog;
Amith Yamasani37ce3a82012-02-06 12:04:42 -080089import android.util.SparseArray;
wilsonshiha282bf72018-11-30 12:48:05 +080090import android.util.SparseBooleanArray;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070091import android.util.Xml;
Dianne Hackborn44bc17c2011-04-20 18:18:51 -070092import android.view.Display;
Valentin Iftime3047bb12018-12-28 17:02:19 +010093import android.view.DisplayInfo;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070094import android.view.IWindowManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095
Jeff Sharkey1cab76a2016-04-12 18:23:31 -060096import com.android.internal.R;
97import com.android.internal.content.PackageMonitor;
Christopher Tate190e8532016-07-11 11:35:34 -070098import com.android.internal.os.BackgroundThread;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060099import com.android.internal.util.DumpUtils;
Jeff Sharkey1cab76a2016-04-12 18:23:31 -0600100import com.android.internal.util.FastXmlSerializer;
101import com.android.internal.util.JournaledFile;
102import com.android.server.EventLogTags;
Adrian Roosc3f915e2016-09-06 11:40:53 -0700103import com.android.server.FgThread;
Jeff Sharkey1cab76a2016-04-12 18:23:31 -0600104import com.android.server.SystemService;
105
106import libcore.io.IoUtils;
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700107
108import org.xmlpull.v1.XmlPullParser;
109import org.xmlpull.v1.XmlPullParserException;
110import org.xmlpull.v1.XmlSerializer;
111
Jeff Sharkey1cab76a2016-04-12 18:23:31 -0600112import java.io.BufferedOutputStream;
113import java.io.File;
114import java.io.FileDescriptor;
115import java.io.FileInputStream;
116import java.io.FileNotFoundException;
117import java.io.FileOutputStream;
118import java.io.IOException;
119import java.io.InputStream;
120import java.io.PrintWriter;
121import java.nio.charset.StandardCharsets;
Lucas Dupinfb3ab2a2017-08-08 14:17:30 -0400122import java.util.ArrayList;
Jeff Sharkey1cab76a2016-04-12 18:23:31 -0600123import java.util.Arrays;
124import java.util.List;
Christopher Tate2a6c55f2017-03-31 12:28:30 -0700125import java.util.Objects;
wilsonshihde93f492018-11-01 21:23:40 +0800126import java.util.function.Consumer;
wilsonshiha282bf72018-11-30 12:48:05 +0800127import java.util.function.Predicate;
Christopher Tatead3c2592016-01-20 18:13:17 -0800128
Daichi Hirono4bbf8522017-12-06 10:34:18 +0900129public class WallpaperManagerService extends IWallpaperManager.Stub
130 implements IWallpaperManagerService {
wilsonshiha282bf72018-11-30 12:48:05 +0800131 private static final String TAG = "WallpaperManagerService";
132 private static final boolean DEBUG = false;
133 private static final boolean DEBUG_LIVE = true;
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700134
Jeff Sharkey1cab76a2016-04-12 18:23:31 -0600135 public static class Lifecycle extends SystemService {
Daichi Hirono4bbf8522017-12-06 10:34:18 +0900136 private IWallpaperManagerService mService;
Jeff Sharkey1cab76a2016-04-12 18:23:31 -0600137
138 public Lifecycle(Context context) {
139 super(context);
140 }
141
142 @Override
143 public void onStart() {
Daichi Hirono4bbf8522017-12-06 10:34:18 +0900144 try {
145 final Class<? extends IWallpaperManagerService> klass =
146 (Class<? extends IWallpaperManagerService>)Class.forName(
147 getContext().getResources().getString(
148 R.string.config_wallpaperManagerServiceName));
149 mService = klass.getConstructor(Context.class).newInstance(getContext());
150 publishBinderService(Context.WALLPAPER_SERVICE, mService);
151 } catch (Exception exp) {
152 Slog.wtf(TAG, "Failed to instantiate WallpaperManagerService", exp);
153 }
Jeff Sharkey1cab76a2016-04-12 18:23:31 -0600154 }
155
156 @Override
157 public void onBootPhase(int phase) {
Daichi Hirono4bbf8522017-12-06 10:34:18 +0900158 if (mService != null) {
159 mService.onBootPhase(phase);
Jeff Sharkey1cab76a2016-04-12 18:23:31 -0600160 }
161 }
162
163 @Override
164 public void onUnlockUser(int userHandle) {
Daichi Hirono4bbf8522017-12-06 10:34:18 +0900165 if (mService != null) {
166 mService.onUnlockUser(userHandle);
167 }
Jeff Sharkey1cab76a2016-04-12 18:23:31 -0600168 }
169 }
170
wilsonshiha282bf72018-11-30 12:48:05 +0800171 private final Object mLock = new Object();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800172
Dianne Hackborn0cd48872009-08-13 18:51:59 -0700173 /**
174 * Minimum time between crashes of a wallpaper service for us to consider
175 * restarting it vs. just reverting to the static wallpaper.
176 */
wilsonshiha282bf72018-11-30 12:48:05 +0800177 private static final long MIN_WALLPAPER_CRASH_TIME = 10000;
178 private static final int MAX_WALLPAPER_COMPONENT_LOG_LENGTH = 128;
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800179 static final String WALLPAPER = "wallpaper_orig";
180 static final String WALLPAPER_CROP = "wallpaper";
Christopher Tatebe132e62016-02-10 12:59:49 -0800181 static final String WALLPAPER_LOCK_ORIG = "wallpaper_lock_orig";
182 static final String WALLPAPER_LOCK_CROP = "wallpaper_lock";
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800183 static final String WALLPAPER_INFO = "wallpaper_info.xml";
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -0700184
Christopher Tatebe132e62016-02-10 12:59:49 -0800185 // All the various per-user state files we need to be aware of
wilsonshiha282bf72018-11-30 12:48:05 +0800186 private static final String[] sPerUserFiles = new String[] {
Christopher Tatebe132e62016-02-10 12:59:49 -0800187 WALLPAPER, WALLPAPER_CROP,
188 WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP,
189 WALLPAPER_INFO
190 };
191
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -0700192 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800193 * Observes the wallpaper for changes and notifies all IWallpaperServiceCallbacks
194 * that the wallpaper has changed. The CREATE is triggered when there is no
195 * wallpaper set and is created for the first time. The CLOSE_WRITE is triggered
Christopher Tate190e8532016-07-11 11:35:34 -0700196 * every time the wallpaper is changed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800197 */
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800198 private class WallpaperObserver extends FileObserver {
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700199
Christopher Tatebe132e62016-02-10 12:59:49 -0800200 final int mUserId;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800201 final WallpaperData mWallpaper;
202 final File mWallpaperDir;
203 final File mWallpaperFile;
Christopher Tatebe132e62016-02-10 12:59:49 -0800204 final File mWallpaperLockFile;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800205
206 public WallpaperObserver(WallpaperData wallpaper) {
207 super(getWallpaperDir(wallpaper.userId).getAbsolutePath(),
Christopher Tateda058e22014-10-08 14:51:09 -0700208 CLOSE_WRITE | MOVED_TO | DELETE | DELETE_SELF);
Christopher Tatebe132e62016-02-10 12:59:49 -0800209 mUserId = wallpaper.userId;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800210 mWallpaperDir = getWallpaperDir(wallpaper.userId);
211 mWallpaper = wallpaper;
212 mWallpaperFile = new File(mWallpaperDir, WALLPAPER);
Christopher Tatebe132e62016-02-10 12:59:49 -0800213 mWallpaperLockFile = new File(mWallpaperDir, WALLPAPER_LOCK_ORIG);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800214 }
215
Christopher Tatebe132e62016-02-10 12:59:49 -0800216 private WallpaperData dataForEvent(boolean sysChanged, boolean lockChanged) {
217 WallpaperData wallpaper = null;
218 synchronized (mLock) {
219 if (lockChanged) {
220 wallpaper = mLockWallpaperMap.get(mUserId);
221 }
222 if (wallpaper == null) {
223 // no lock-specific wallpaper exists, or sys case, handled together
224 wallpaper = mWallpaperMap.get(mUserId);
225 }
226 }
227 return (wallpaper != null) ? wallpaper : mWallpaper;
228 }
229
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800230 @Override
231 public void onEvent(int event, String path) {
232 if (path == null) {
233 return;
234 }
Christopher Tated7faf532016-02-25 12:43:38 -0800235 final boolean moved = (event == MOVED_TO);
236 final boolean written = (event == CLOSE_WRITE || moved);
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800237 final File changedFile = new File(mWallpaperDir, path);
238
Christopher Tatebe132e62016-02-10 12:59:49 -0800239 // System and system+lock changes happen on the system wallpaper input file;
240 // lock-only changes happen on the dedicated lock wallpaper input file
241 final boolean sysWallpaperChanged = (mWallpaperFile.equals(changedFile));
242 final boolean lockWallpaperChanged = (mWallpaperLockFile.equals(changedFile));
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700243 int notifyColorsWhich = 0;
Christopher Tatebe132e62016-02-10 12:59:49 -0800244 WallpaperData wallpaper = dataForEvent(sysWallpaperChanged, lockWallpaperChanged);
245
246 if (DEBUG) {
247 Slog.v(TAG, "Wallpaper file change: evt=" + event
248 + " path=" + path
249 + " sys=" + sysWallpaperChanged
250 + " lock=" + lockWallpaperChanged
251 + " imagePending=" + wallpaper.imageWallpaperPending
252 + " whichPending=0x" + Integer.toHexString(wallpaper.whichPending)
253 + " written=" + written);
254 }
Christopher Tate8347b632016-04-29 18:59:18 -0700255
256 if (moved && lockWallpaperChanged) {
257 // We just migrated sys -> lock to preserve imagery for an impending
Christopher Tatefa7d97f2016-06-30 12:21:57 -0700258 // new system-only wallpaper. Tell keyguard about it and make sure it
259 // has the right SELinux label.
Christopher Tate8347b632016-04-29 18:59:18 -0700260 if (DEBUG) {
261 Slog.i(TAG, "Sys -> lock MOVED_TO");
262 }
Christopher Tatefa7d97f2016-06-30 12:21:57 -0700263 SELinux.restorecon(changedFile);
Christopher Tate8347b632016-04-29 18:59:18 -0700264 notifyLockWallpaperChanged();
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700265 notifyWallpaperColorsChanged(wallpaper, FLAG_LOCK);
Christopher Tate8347b632016-04-29 18:59:18 -0700266 return;
267 }
268
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800269 synchronized (mLock) {
Christopher Tatebe132e62016-02-10 12:59:49 -0800270 if (sysWallpaperChanged || lockWallpaperChanged) {
271 notifyCallbacksLocked(wallpaper);
272 if (wallpaper.wallpaperComponent == null
Christopher Tateda058e22014-10-08 14:51:09 -0700273 || event != CLOSE_WRITE // includes the MOVED_TO case
Christopher Tatebe132e62016-02-10 12:59:49 -0800274 || wallpaper.imageWallpaperPending) {
Christopher Tateda058e22014-10-08 14:51:09 -0700275 if (written) {
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800276 // The image source has finished writing the source image,
277 // so we now produce the crop rect (in the background), and
278 // only publish the new displayable (sub)image as a result
279 // of that work.
Christopher Tatebe132e62016-02-10 12:59:49 -0800280 if (DEBUG) {
281 Slog.v(TAG, "Wallpaper written; generating crop");
282 }
Christopher Tateebadfb12016-07-25 14:50:08 -0700283 SELinux.restorecon(changedFile);
Christopher Tated7faf532016-02-25 12:43:38 -0800284 if (moved) {
285 // This is a restore, so generate the crop using any just-restored new
286 // crop guidelines, making sure to preserve our local dimension hints.
Christopher Tatefa7d97f2016-06-30 12:21:57 -0700287 // We also make sure to reapply the correct SELinux label.
Christopher Tated7faf532016-02-25 12:43:38 -0800288 if (DEBUG) {
289 Slog.v(TAG, "moved-to, therefore restore; reloading metadata");
290 }
291 loadSettingsLocked(wallpaper.userId, true);
292 }
Christopher Tatebe132e62016-02-10 12:59:49 -0800293 generateCrop(wallpaper);
294 if (DEBUG) {
295 Slog.v(TAG, "Crop done; invoking completion callback");
296 }
297 wallpaper.imageWallpaperPending = false;
Christopher Tatebe132e62016-02-10 12:59:49 -0800298 if (sysWallpaperChanged) {
299 // If this was the system wallpaper, rebind...
300 bindWallpaperComponentLocked(mImageWallpaper, true,
301 false, wallpaper, null);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700302 notifyColorsWhich |= FLAG_SYSTEM;
Christopher Tatebe132e62016-02-10 12:59:49 -0800303 }
304 if (lockWallpaperChanged
Christopher Tateedf7d042016-03-29 18:24:25 -0700305 || (wallpaper.whichPending & FLAG_LOCK) != 0) {
Christopher Tatebe132e62016-02-10 12:59:49 -0800306 if (DEBUG) {
Christopher Tatedb27b842016-02-25 14:39:17 -0800307 Slog.i(TAG, "Lock-relevant wallpaper changed");
Christopher Tatebe132e62016-02-10 12:59:49 -0800308 }
Christopher Tatedb27b842016-02-25 14:39:17 -0800309 // either a lock-only wallpaper commit or a system+lock event.
310 // if it's system-plus-lock we need to wipe the lock bookkeeping;
311 // we're falling back to displaying the system wallpaper there.
312 if (!lockWallpaperChanged) {
313 mLockWallpaperMap.remove(wallpaper.userId);
314 }
315 // and in any case, tell keyguard about it
Christopher Tate8347b632016-04-29 18:59:18 -0700316 notifyLockWallpaperChanged();
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700317 notifyColorsWhich |= FLAG_LOCK;
Christopher Tatebe132e62016-02-10 12:59:49 -0800318 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700319
Christopher Tatedb27b842016-02-25 14:39:17 -0800320 saveSettingsLocked(wallpaper.userId);
Christopher Tate8efbe0d2017-08-29 16:50:13 -0700321
322 // Publish completion *after* we've persisted the changes
323 if (wallpaper.setComplete != null) {
324 try {
325 wallpaper.setComplete.onWallpaperChanged();
326 } catch (RemoteException e) {
327 // if this fails we don't really care; the setting app may just
328 // have crashed and that sort of thing is a fact of life.
329 }
330 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700331 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800332 }
333 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800334 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700335
336 // Outside of the lock since it will synchronize itself
337 if (notifyColorsWhich != 0) {
338 notifyWallpaperColorsChanged(wallpaper, notifyColorsWhich);
339 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800340 }
341 }
342
wilsonshiha282bf72018-11-30 12:48:05 +0800343 private void notifyLockWallpaperChanged() {
Christopher Tate8347b632016-04-29 18:59:18 -0700344 final IWallpaperManagerCallback cb = mKeyguardListener;
345 if (cb != null) {
346 try {
347 cb.onWallpaperChanged();
348 } catch (RemoteException e) {
349 // Oh well it went away; no big deal
350 }
351 }
352 }
353
Lucas Dupin50ba9912017-07-14 11:55:05 -0700354 private void notifyWallpaperColorsChanged(@NonNull WallpaperData wallpaper, int which) {
wilsonshih36597d42018-12-05 18:56:39 +0800355 if (wallpaper.connection != null) {
356 wallpaper.connection.forEachDisplayConnector(connector -> {
357 notifyWallpaperColorsChangedOnDisplay(wallpaper, which, connector.mDisplayId);
358 });
359 } else { // Lock wallpaper does not have WallpaperConnection.
360 notifyWallpaperColorsChangedOnDisplay(wallpaper, which, DEFAULT_DISPLAY);
361 }
362 }
363
364 private RemoteCallbackList<IWallpaperManagerCallback> getWallpaperCallbacks(int userId,
365 int displayId) {
366 RemoteCallbackList<IWallpaperManagerCallback> listeners = null;
367 final SparseArray<RemoteCallbackList<IWallpaperManagerCallback>> displayListeners =
368 mColorsChangedListeners.get(userId);
369 if (displayListeners != null) {
370 listeners = displayListeners.get(displayId);
371 }
372 return listeners;
373 }
374
375 private void notifyWallpaperColorsChangedOnDisplay(@NonNull WallpaperData wallpaper, int which,
376 int displayId) {
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700377 boolean needsExtraction;
378 synchronized (mLock) {
Lucas Dupin50ba9912017-07-14 11:55:05 -0700379 final RemoteCallbackList<IWallpaperManagerCallback> currentUserColorListeners =
wilsonshih36597d42018-12-05 18:56:39 +0800380 getWallpaperCallbacks(wallpaper.userId, displayId);
Lucas Dupin50ba9912017-07-14 11:55:05 -0700381 final RemoteCallbackList<IWallpaperManagerCallback> userAllColorListeners =
wilsonshih36597d42018-12-05 18:56:39 +0800382 getWallpaperCallbacks(UserHandle.USER_ALL, displayId);
Lucas Dupin50ba9912017-07-14 11:55:05 -0700383 // No-op until someone is listening to it.
384 if (emptyCallbackList(currentUserColorListeners) &&
385 emptyCallbackList(userAllColorListeners)) {
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700386 return;
Lucas Dupin50ba9912017-07-14 11:55:05 -0700387 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700388
389 if (DEBUG) {
wilsonshih36597d42018-12-05 18:56:39 +0800390 Slog.v(TAG, "notifyWallpaperColorsChangedOnDisplay " + which);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700391 }
392
393 needsExtraction = wallpaper.primaryColors == null;
394 }
395
Lucas Dupin75ec3792017-06-29 14:07:18 -0700396 // Let's notify the current values, it's fine if it's null, it just means
397 // that we don't know yet.
wilsonshih36597d42018-12-05 18:56:39 +0800398 notifyColorListeners(wallpaper.primaryColors, which, wallpaper.userId, displayId);
Lucas Dupin75ec3792017-06-29 14:07:18 -0700399
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700400 if (needsExtraction) {
401 extractColors(wallpaper);
Lucas Dupin50ba9912017-07-14 11:55:05 -0700402 synchronized (mLock) {
403 // Don't need to notify if nothing changed.
404 if (wallpaper.primaryColors == null) {
405 return;
406 }
407 }
wilsonshih36597d42018-12-05 18:56:39 +0800408 notifyColorListeners(wallpaper.primaryColors, which, wallpaper.userId, displayId);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700409 }
Lucas Dupin75ec3792017-06-29 14:07:18 -0700410 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700411
Lucas Dupin50ba9912017-07-14 11:55:05 -0700412 private static <T extends IInterface> boolean emptyCallbackList(RemoteCallbackList<T> list) {
413 return (list == null || list.getRegisteredCallbackCount() == 0);
414 }
415
416 private void notifyColorListeners(@NonNull WallpaperColors wallpaperColors, int which,
wilsonshih36597d42018-12-05 18:56:39 +0800417 int userId, int displayId) {
Lucas Dupin75ec3792017-06-29 14:07:18 -0700418 final IWallpaperManagerCallback keyguardListener;
Lucas Dupinfb3ab2a2017-08-08 14:17:30 -0400419 final ArrayList<IWallpaperManagerCallback> colorListeners = new ArrayList<>();
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700420 synchronized (mLock) {
Lucas Dupinfb3ab2a2017-08-08 14:17:30 -0400421 final RemoteCallbackList<IWallpaperManagerCallback> currentUserColorListeners =
wilsonshih36597d42018-12-05 18:56:39 +0800422 getWallpaperCallbacks(userId, displayId);
Lucas Dupinfb3ab2a2017-08-08 14:17:30 -0400423 final RemoteCallbackList<IWallpaperManagerCallback> userAllColorListeners =
wilsonshih36597d42018-12-05 18:56:39 +0800424 getWallpaperCallbacks(UserHandle.USER_ALL, displayId);
Lucas Dupin75ec3792017-06-29 14:07:18 -0700425 keyguardListener = mKeyguardListener;
Lucas Dupinfb3ab2a2017-08-08 14:17:30 -0400426
427 if (currentUserColorListeners != null) {
428 final int count = currentUserColorListeners.beginBroadcast();
429 for (int i = 0; i < count; i++) {
430 colorListeners.add(currentUserColorListeners.getBroadcastItem(i));
431 }
432 currentUserColorListeners.finishBroadcast();
433 }
434
435 if (userAllColorListeners != null) {
436 final int count = userAllColorListeners.beginBroadcast();
437 for (int i = 0; i < count; i++) {
438 colorListeners.add(userAllColorListeners.getBroadcastItem(i));
439 }
440 userAllColorListeners.finishBroadcast();
441 }
Lucas Dupin75ec3792017-06-29 14:07:18 -0700442 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700443
Lucas Dupinfb3ab2a2017-08-08 14:17:30 -0400444 final int count = colorListeners.size();
445 for (int i = 0; i < count; i++) {
446 try {
447 colorListeners.get(i).onWallpaperColorsChanged(wallpaperColors, which, userId);
448 } catch (RemoteException e) {
449 // Callback is gone, it's not necessary to unregister it since
450 // RemoteCallbackList#getBroadcastItem will take care of it.
Lucas Dupin75ec3792017-06-29 14:07:18 -0700451 }
452 }
453
wilsonshih36597d42018-12-05 18:56:39 +0800454 // Only shows Keyguard on default display
455 if (keyguardListener != null && displayId == DEFAULT_DISPLAY) {
Lucas Dupin75ec3792017-06-29 14:07:18 -0700456 try {
Lucas Dupin50ba9912017-07-14 11:55:05 -0700457 keyguardListener.onWallpaperColorsChanged(wallpaperColors, which, userId);
Lucas Dupin75ec3792017-06-29 14:07:18 -0700458 } catch (RemoteException e) {
459 // Oh well it went away; no big deal
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700460 }
461 }
462 }
463
Lucas Dupinbcae5852017-05-03 12:42:58 -0700464 /**
465 * We can easily extract colors from an ImageWallpaper since it's only a bitmap.
Lucas Dupin284836b2017-06-23 15:28:41 -0700466 * In this case, using the crop is more than enough. Live wallpapers are just ignored.
Lucas Dupinbcae5852017-05-03 12:42:58 -0700467 *
468 * @param wallpaper a wallpaper representation
469 */
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700470 private void extractColors(WallpaperData wallpaper) {
471 String cropFile = null;
wilsonshih31d70a12019-01-14 12:42:35 +0800472 boolean defaultImageWallpaper = false;
Lucas Dupin284836b2017-06-23 15:28:41 -0700473 int wallpaperId;
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700474
wilsonshih36597d42018-12-05 18:56:39 +0800475 if (wallpaper.equals(mFallbackWallpaper)) {
476 extractDefaultImageWallpaperColors();
477 return;
478 }
479
Lucas Dupinbcae5852017-05-03 12:42:58 -0700480 synchronized (mLock) {
Lucas Dupin284836b2017-06-23 15:28:41 -0700481 // Not having a wallpaperComponent means it's a lock screen wallpaper.
482 final boolean imageWallpaper = mImageWallpaper.equals(wallpaper.wallpaperComponent)
Lucas Dupinbcae5852017-05-03 12:42:58 -0700483 || wallpaper.wallpaperComponent == null;
Lucas Dupin284836b2017-06-23 15:28:41 -0700484 if (imageWallpaper && wallpaper.cropFile != null && wallpaper.cropFile.exists()) {
485 cropFile = wallpaper.cropFile.getAbsolutePath();
wilsonshih31d70a12019-01-14 12:42:35 +0800486 } else if (imageWallpaper && !wallpaper.cropExists() && !wallpaper.sourceExists()) {
487 defaultImageWallpaper = true;
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700488 }
489 wallpaperId = wallpaper.wallpaperId;
490 }
491
Lucas Dupin84b89d92017-05-09 12:16:19 -0700492 WallpaperColors colors = null;
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700493 if (cropFile != null) {
Lucas Dupin84b89d92017-05-09 12:16:19 -0700494 Bitmap bitmap = BitmapFactory.decodeFile(cropFile);
Lucas Dupin284836b2017-06-23 15:28:41 -0700495 if (bitmap != null) {
Lucas Dupinb5e50532018-05-24 16:33:14 +0000496 colors = WallpaperColors.fromBitmap(bitmap);
Lucas Dupin284836b2017-06-23 15:28:41 -0700497 bitmap.recycle();
498 }
wilsonshih31d70a12019-01-14 12:42:35 +0800499 } else if (defaultImageWallpaper) {
500 // There is no crop and source file because this is default image wallpaper.
501 try (final InputStream is =
502 WallpaperManager.openDefaultWallpaper(mContext, FLAG_SYSTEM)) {
503 if (is != null) {
504 try {
505 final BitmapFactory.Options options = new BitmapFactory.Options();
506 final Bitmap bitmap = BitmapFactory.decodeStream(is, null, options);
507 if (bitmap != null) {
508 colors = WallpaperColors.fromBitmap(bitmap);
509 bitmap.recycle();
510 }
511 } catch (OutOfMemoryError e) {
512 Slog.w(TAG, "Can't decode default wallpaper stream", e);
513 }
514 }
515 } catch (IOException e) {
516 Slog.w(TAG, "Can't close default wallpaper stream", e);
517 }
Lucas Dupinbcae5852017-05-03 12:42:58 -0700518 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700519
Lucas Dupin84b89d92017-05-09 12:16:19 -0700520 if (colors == null) {
Lucas Dupinbcae5852017-05-03 12:42:58 -0700521 Slog.w(TAG, "Cannot extract colors because wallpaper could not be read.");
522 return;
523 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700524
Lucas Dupinbcae5852017-05-03 12:42:58 -0700525 synchronized (mLock) {
526 if (wallpaper.wallpaperId == wallpaperId) {
Lucas Dupin84b89d92017-05-09 12:16:19 -0700527 wallpaper.primaryColors = colors;
Lucas Dupin75ec3792017-06-29 14:07:18 -0700528 // Now that we have the colors, let's save them into the xml
529 // to avoid having to run this again.
530 saveSettingsLocked(wallpaper.userId);
Lucas Dupinbcae5852017-05-03 12:42:58 -0700531 } else {
532 Slog.w(TAG, "Not setting primary colors since wallpaper changed");
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700533 }
534 }
535 }
536
wilsonshih36597d42018-12-05 18:56:39 +0800537 private void extractDefaultImageWallpaperColors() {
538 synchronized (mLock) {
539 if (mFallbackWallpaper.primaryColors != null) return;
540 }
541
542 if (DEBUG) Slog.d(TAG, "Extract default image wallpaper colors");
543 WallpaperColors colors = null;
544 final InputStream is = WallpaperManager.openDefaultWallpaper(mContext, FLAG_SYSTEM);
545 if (is != null) {
546 try {
547 final BitmapFactory.Options options = new BitmapFactory.Options();
548 final Bitmap bitmap = BitmapFactory.decodeStream(is, null, options);
549 if (bitmap != null) {
550 colors = WallpaperColors.fromBitmap(bitmap);
551 bitmap.recycle();
552 }
553 } catch (OutOfMemoryError e) {
554 Slog.w(TAG, "Can't decode default wallpaper stream", e);
555 } finally {
556 IoUtils.closeQuietly(is);
557 }
558 }
559
560 if (colors == null) {
561 Slog.e(TAG, "Extract default image wallpaper colors failed");
562 return;
563 }
564
565 synchronized (mLock) {
566 mFallbackWallpaper.primaryColors = colors;
567 }
568 }
569
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800570 /**
571 * Once a new wallpaper has been written via setWallpaper(...), it needs to be cropped
572 * for display.
573 */
574 private void generateCrop(WallpaperData wallpaper) {
575 boolean success = false;
Christopher Tate1a96b632016-03-22 15:25:42 -0700576
wilsonshih81e10a72018-11-15 10:54:21 +0800577 // Only generate crop for default display.
wilsonshiha282bf72018-11-30 12:48:05 +0800578 final DisplayData wpData = getDisplayDataOrCreate(DEFAULT_DISPLAY);
Christopher Tate1a96b632016-03-22 15:25:42 -0700579 Rect cropHint = new Rect(wallpaper.cropHint);
Christopher Tatebe132e62016-02-10 12:59:49 -0800580
581 if (DEBUG) {
582 Slog.v(TAG, "Generating crop for new wallpaper(s): 0x"
583 + Integer.toHexString(wallpaper.whichPending)
Christopher Tate1a96b632016-03-22 15:25:42 -0700584 + " to " + wallpaper.cropFile.getName()
585 + " crop=(" + cropHint.width() + 'x' + cropHint.height()
wilsonshih81e10a72018-11-15 10:54:21 +0800586 + ") dim=(" + wpData.mWidth + 'x' + wpData.mHeight + ')');
Christopher Tatebe132e62016-02-10 12:59:49 -0800587 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800588
589 // Analyse the source; needed in multiple cases
590 BitmapFactory.Options options = new BitmapFactory.Options();
591 options.inJustDecodeBounds = true;
592 BitmapFactory.decodeFile(wallpaper.wallpaperFile.getAbsolutePath(), options);
Christopher Tate1a96b632016-03-22 15:25:42 -0700593 if (options.outWidth <= 0 || options.outHeight <= 0) {
Joe LaPennac298b162016-05-02 15:25:50 -0700594 Slog.w(TAG, "Invalid wallpaper data");
Christopher Tate1a96b632016-03-22 15:25:42 -0700595 success = false;
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800596 } else {
Christopher Tate1a96b632016-03-22 15:25:42 -0700597 boolean needCrop = false;
598 boolean needScale = false;
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800599
Christopher Tate1a96b632016-03-22 15:25:42 -0700600 // Empty crop means use the full image
601 if (cropHint.isEmpty()) {
602 cropHint.left = cropHint.top = 0;
603 cropHint.right = options.outWidth;
604 cropHint.bottom = options.outHeight;
605 } else {
606 // force the crop rect to lie within the measured bounds
607 cropHint.offset(
608 (cropHint.right > options.outWidth ? options.outWidth - cropHint.right : 0),
609 (cropHint.bottom > options.outHeight ? options.outHeight - cropHint.bottom : 0));
610
Adrian Roos5c97ff22016-08-31 10:25:38 -0700611 // If the crop hint was larger than the image we just overshot. Patch things up.
612 if (cropHint.left < 0) {
613 cropHint.left = 0;
614 }
615 if (cropHint.top < 0) {
616 cropHint.top = 0;
617 }
618
Christopher Tate1a96b632016-03-22 15:25:42 -0700619 // Don't bother cropping if what we're left with is identity
Christopher Tateebadfb12016-07-25 14:50:08 -0700620 needCrop = (options.outHeight > cropHint.height()
Adrian Roos5c97ff22016-08-31 10:25:38 -0700621 || options.outWidth > cropHint.width());
Christopher Tate1a96b632016-03-22 15:25:42 -0700622 }
623
624 // scale if the crop height winds up not matching the recommended metrics
wilsonshih81e10a72018-11-15 10:54:21 +0800625 needScale = (wpData.mHeight != cropHint.height());
Christopher Tate1a96b632016-03-22 15:25:42 -0700626
Valentin Iftime3047bb12018-12-28 17:02:19 +0100627 //make sure screen aspect ratio is preserved if width is scaled under screen size
628 if (needScale) {
629 final DisplayInfo displayInfo = new DisplayInfo();
630 mDisplayManager.getDisplay(DEFAULT_DISPLAY).getDisplayInfo(displayInfo);
631 final float scaleByHeight = (float) wpData.mHeight / (float) cropHint.height();
632 final int newWidth = (int) (cropHint.width() * scaleByHeight);
633 if (newWidth < displayInfo.logicalWidth) {
634 final float screenAspectRatio =
635 (float) displayInfo.logicalHeight / (float) displayInfo.logicalWidth;
636 cropHint.bottom = (int) (cropHint.width() * screenAspectRatio);
637 needCrop = true;
638 }
639 }
640
Christopher Tate1a96b632016-03-22 15:25:42 -0700641 if (DEBUG) {
642 Slog.v(TAG, "crop: w=" + cropHint.width() + " h=" + cropHint.height());
wilsonshih81e10a72018-11-15 10:54:21 +0800643 Slog.v(TAG, "dims: w=" + wpData.mWidth + " h=" + wpData.mHeight);
Christopher Tate1a96b632016-03-22 15:25:42 -0700644 Slog.v(TAG, "meas: w=" + options.outWidth + " h=" + options.outHeight);
645 Slog.v(TAG, "crop?=" + needCrop + " scale?=" + needScale);
646 }
647
648 if (!needCrop && !needScale) {
649 // Simple case: the nominal crop fits what we want, so we take
650 // the whole thing and just copy the image file directly.
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800651 if (DEBUG) {
Christopher Tate1a96b632016-03-22 15:25:42 -0700652 Slog.v(TAG, "Null crop of new wallpaper; copying");
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800653 }
Christopher Tate1a96b632016-03-22 15:25:42 -0700654 success = FileUtils.copyFile(wallpaper.wallpaperFile, wallpaper.cropFile);
655 if (!success) {
656 wallpaper.cropFile.delete();
657 // TODO: fall back to default wallpaper in this case
658 }
659 } else {
660 // Fancy case: crop and scale. First, we decode and scale down if appropriate.
661 FileOutputStream f = null;
662 BufferedOutputStream bos = null;
663 try {
664 BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(
665 wallpaper.wallpaperFile.getAbsolutePath(), false);
666
667 // This actually downsamples only by powers of two, but that's okay; we do
668 // a proper scaling blit later. This is to minimize transient RAM use.
669 // We calculate the largest power-of-two under the actual ratio rather than
670 // just let the decode take care of it because we also want to remap where the
671 // cropHint rectangle lies in the decoded [super]rect.
672 final BitmapFactory.Options scaler;
wilsonshih81e10a72018-11-15 10:54:21 +0800673 final int actualScale = cropHint.height() / wpData.mHeight;
Christopher Tate1a96b632016-03-22 15:25:42 -0700674 int scale = 1;
675 while (2*scale < actualScale) {
676 scale *= 2;
677 }
678 if (scale > 1) {
679 scaler = new BitmapFactory.Options();
680 scaler.inSampleSize = scale;
681 if (DEBUG) {
682 Slog.v(TAG, "Downsampling cropped rect with scale " + scale);
683 }
684 } else {
685 scaler = null;
686 }
687 Bitmap cropped = decoder.decodeRegion(cropHint, scaler);
688 decoder.recycle();
689
690 if (cropped == null) {
691 Slog.e(TAG, "Could not decode new wallpaper");
692 } else {
693 // We've got the extracted crop; now we want to scale it properly to
694 // the desired rectangle. That's a height-biased operation: make it
695 // fit the hinted height, and accept whatever width we end up with.
696 cropHint.offsetTo(0, 0);
697 cropHint.right /= scale; // adjust by downsampling factor
698 cropHint.bottom /= scale;
wilsonshih81e10a72018-11-15 10:54:21 +0800699 final float heightR =
700 ((float) wpData.mHeight) / ((float) cropHint.height());
Christopher Tate1a96b632016-03-22 15:25:42 -0700701 if (DEBUG) {
702 Slog.v(TAG, "scale " + heightR + ", extracting " + cropHint);
703 }
704 final int destWidth = (int)(cropHint.width() * heightR);
705 final Bitmap finalCrop = Bitmap.createScaledBitmap(cropped,
wilsonshih81e10a72018-11-15 10:54:21 +0800706 destWidth, wpData.mHeight, true);
Christopher Tate1a96b632016-03-22 15:25:42 -0700707 if (DEBUG) {
708 Slog.v(TAG, "Final extract:");
wilsonshih81e10a72018-11-15 10:54:21 +0800709 Slog.v(TAG, " dims: w=" + wpData.mWidth
710 + " h=" + wpData.mHeight);
Christopher Tate1a96b632016-03-22 15:25:42 -0700711 Slog.v(TAG, " out: w=" + finalCrop.getWidth()
712 + " h=" + finalCrop.getHeight());
713 }
714
715 f = new FileOutputStream(wallpaper.cropFile);
716 bos = new BufferedOutputStream(f, 32*1024);
Christopher Tatec484f542016-05-11 14:31:34 -0700717 finalCrop.compress(Bitmap.CompressFormat.JPEG, 100, bos);
Christopher Tate1a96b632016-03-22 15:25:42 -0700718 bos.flush(); // don't rely on the implicit flush-at-close when noting success
719 success = true;
720 }
721 } catch (Exception e) {
722 if (DEBUG) {
723 Slog.e(TAG, "Error decoding crop", e);
724 }
725 } finally {
726 IoUtils.closeQuietly(bos);
727 IoUtils.closeQuietly(f);
728 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800729 }
730 }
731
732 if (!success) {
733 Slog.e(TAG, "Unable to apply new wallpaper");
734 wallpaper.cropFile.delete();
735 }
736
737 if (wallpaper.cropFile.exists()) {
738 boolean didRestorecon = SELinux.restorecon(wallpaper.cropFile.getAbsoluteFile());
739 if (DEBUG) {
740 Slog.v(TAG, "restorecon() of crop file returned " + didRestorecon);
741 }
742 }
743 }
744
wilsonshiha282bf72018-11-30 12:48:05 +0800745 private final Context mContext;
746 private final IWindowManager mIWindowManager;
747 private final IPackageManager mIPackageManager;
748 private final MyPackageMonitor mMonitor;
749 private final AppOpsManager mAppOpsManager;
wilsonshihde93f492018-11-01 21:23:40 +0800750
751 private final DisplayManager mDisplayManager;
752 private final DisplayManager.DisplayListener mDisplayListener =
753 new DisplayManager.DisplayListener() {
754
755 @Override
756 public void onDisplayAdded(int displayId) {
757 synchronized (mLock) {
758 if (mLastWallpaper != null) {
wilsonshiha282bf72018-11-30 12:48:05 +0800759 if (supportsMultiDisplay(mLastWallpaper.connection)) {
760 final WallpaperConnection.DisplayConnector connector =
761 mLastWallpaper.connection.getDisplayConnectorOrCreate(displayId);
762 if (connector == null) return;
763 connector.connectLocked(mLastWallpaper.connection, mLastWallpaper);
764 return;
765 }
766 // System wallpaper does not support multiple displays, attach this display to
767 // the fallback wallpaper.
768 if (mFallbackWallpaper != null) {
769 final WallpaperConnection.DisplayConnector connector = mFallbackWallpaper
770 .connection.getDisplayConnectorOrCreate(displayId);
771 if (connector == null) return;
772 connector.connectLocked(mFallbackWallpaper.connection, mFallbackWallpaper);
773 } else {
774 Slog.w(TAG, "No wallpaper can be added to the new display");
775 }
wilsonshihde93f492018-11-01 21:23:40 +0800776 }
777 }
778 }
779
780 @Override
781 public void onDisplayRemoved(int displayId) {
782 synchronized (mLock) {
783 if (mLastWallpaper != null) {
wilsonshiha282bf72018-11-30 12:48:05 +0800784 WallpaperData targetWallpaper = null;
785 if (mLastWallpaper.connection.containsDisplay(displayId)) {
786 targetWallpaper = mLastWallpaper;
787 } else if (mFallbackWallpaper.connection.containsDisplay(displayId)) {
788 targetWallpaper = mFallbackWallpaper;
789 }
790 if (targetWallpaper == null) return;
791 WallpaperConnection.DisplayConnector connector =
792 targetWallpaper.connection.getDisplayConnectorOrCreate(displayId);
wilsonshihde93f492018-11-01 21:23:40 +0800793 if (connector == null) return;
794 connector.disconnectLocked();
wilsonshiha282bf72018-11-30 12:48:05 +0800795 targetWallpaper.connection.removeDisplayConnector(displayId);
796 removeDisplayData(displayId);
wilsonshihde93f492018-11-01 21:23:40 +0800797 }
wilsonshih36597d42018-12-05 18:56:39 +0800798 for (int i = mColorsChangedListeners.size() - 1; i >= 0; i--) {
799 final SparseArray<RemoteCallbackList<IWallpaperManagerCallback>> callbacks =
800 mColorsChangedListeners.valueAt(i);
801 callbacks.delete(displayId);
802 }
wilsonshihde93f492018-11-01 21:23:40 +0800803 }
804 }
805
806 @Override
807 public void onDisplayChanged(int displayId) {
wilsonshihde93f492018-11-01 21:23:40 +0800808 }
809 };
810
Lucas Dupin50ba9912017-07-14 11:55:05 -0700811 /**
812 * Map of color listeners per user id.
wilsonshih36597d42018-12-05 18:56:39 +0800813 * The first key will be the id of a user or UserHandle.USER_ALL - for wildcard listeners.
814 * The secondary key will be the display id, which means which display the listener is
815 * interested in.
Lucas Dupin50ba9912017-07-14 11:55:05 -0700816 */
wilsonshih36597d42018-12-05 18:56:39 +0800817 private final SparseArray<SparseArray<RemoteCallbackList<IWallpaperManagerCallback>>>
wilsonshiha282bf72018-11-30 12:48:05 +0800818 mColorsChangedListeners;
819 private WallpaperData mLastWallpaper;
820 private IWallpaperManagerCallback mKeyguardListener;
821 private boolean mWaitingForUnlock;
822 private boolean mShuttingDown;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800823
Justin Koh29c30162014-09-05 17:10:10 -0700824 /**
Christopher Tatead3c2592016-01-20 18:13:17 -0800825 * ID of the current wallpaper, changed every time anything sets a wallpaper.
826 * This is used for external detection of wallpaper update activity.
827 */
wilsonshiha282bf72018-11-30 12:48:05 +0800828 private int mWallpaperId;
Christopher Tatead3c2592016-01-20 18:13:17 -0800829
830 /**
Justin Koh29c30162014-09-05 17:10:10 -0700831 * Name of the component used to display bitmap wallpapers from either the gallery or
832 * built-in wallpapers.
833 */
wilsonshiha282bf72018-11-30 12:48:05 +0800834 private final ComponentName mImageWallpaper;
Justin Koh29c30162014-09-05 17:10:10 -0700835
Christopher Tate2a6c55f2017-03-31 12:28:30 -0700836 /**
837 * Name of the default wallpaper component; might be different from mImageWallpaper
838 */
wilsonshiha282bf72018-11-30 12:48:05 +0800839 private final ComponentName mDefaultWallpaperComponent;
Christopher Tate2a6c55f2017-03-31 12:28:30 -0700840
wilsonshiha282bf72018-11-30 12:48:05 +0800841 private final SparseArray<WallpaperData> mWallpaperMap = new SparseArray<WallpaperData>();
842 private final SparseArray<WallpaperData> mLockWallpaperMap = new SparseArray<WallpaperData>();
Dianne Hackborn07213e62011-08-24 20:05:39 -0700843
wilsonshiha282bf72018-11-30 12:48:05 +0800844 private SparseArray<DisplayData> mDisplayDatas = new SparseArray<>();
845
846 private WallpaperData mFallbackWallpaper;
847
848 private final SparseBooleanArray mUserRestorecon = new SparseBooleanArray();
849 private int mCurrentUserId = UserHandle.USER_NULL;
850 private boolean mInAmbientMode;
Dianne Hackborn07213e62011-08-24 20:05:39 -0700851
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800852 static class WallpaperData {
853
854 int userId;
855
Christopher Tatebe132e62016-02-10 12:59:49 -0800856 final File wallpaperFile; // source image
857 final File cropFile; // eventual destination
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800858
859 /**
Christopher Tatebe132e62016-02-10 12:59:49 -0800860 * True while the client is writing a new wallpaper
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800861 */
862 boolean imageWallpaperPending;
863
864 /**
Christopher Tatebe132e62016-02-10 12:59:49 -0800865 * Which new wallpapers are being written; mirrors the 'which'
866 * selector bit field to setWallpaper().
867 */
868 int whichPending;
869
870 /**
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800871 * Callback once the set + crop is finished
872 */
873 IWallpaperManagerCallback setComplete;
874
875 /**
Christopher Tated7faf532016-02-25 12:43:38 -0800876 * Is the OS allowed to back up this wallpaper imagery?
877 */
878 boolean allowBackup;
879
880 /**
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800881 * Resource name if using a picture from the wallpaper gallery
882 */
883 String name = "";
884
885 /**
886 * The component name of the currently set live wallpaper.
887 */
888 ComponentName wallpaperComponent;
889
890 /**
891 * The component name of the wallpaper that should be set next.
892 */
893 ComponentName nextWallpaperComponent;
894
Christopher Tatead3c2592016-01-20 18:13:17 -0800895 /**
896 * The ID of this wallpaper
897 */
898 int wallpaperId;
899
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700900 /**
901 * Primary colors histogram
902 */
903 WallpaperColors primaryColors;
904
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800905 WallpaperConnection connection;
906 long lastDiedTime;
907 boolean wallpaperUpdating;
908 WallpaperObserver wallpaperObserver;
909
910 /**
911 * List of callbacks registered they should each be notified when the wallpaper is changed.
912 */
913 private RemoteCallbackList<IWallpaperManagerCallback> callbacks
914 = new RemoteCallbackList<IWallpaperManagerCallback>();
915
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800916 /**
917 * The crop hint supplied for displaying a subset of the source image
918 */
919 final Rect cropHint = new Rect(0, 0, 0, 0);
920
Christopher Tatebe132e62016-02-10 12:59:49 -0800921 WallpaperData(int userId, String inputFileName, String cropFileName) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800922 this.userId = userId;
Christopher Tatebe132e62016-02-10 12:59:49 -0800923 final File wallpaperDir = getWallpaperDir(userId);
924 wallpaperFile = new File(wallpaperDir, inputFileName);
925 cropFile = new File(wallpaperDir, cropFileName);
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800926 }
927
Christopher Tatebe132e62016-02-10 12:59:49 -0800928 // Called during initialization of a given user's wallpaper bookkeeping
Christopher Tate41297ff2016-03-10 16:46:15 -0800929 boolean cropExists() {
930 return cropFile.exists();
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800931 }
Christopher Tate2a6c55f2017-03-31 12:28:30 -0700932
933 boolean sourceExists() {
934 return wallpaperFile.exists();
935 }
wilsonshiha282bf72018-11-30 12:48:05 +0800936 }
wilsonshih81e10a72018-11-15 10:54:21 +0800937
wilsonshiha282bf72018-11-30 12:48:05 +0800938 private static final class DisplayData {
939 int mWidth = -1;
940 int mHeight = -1;
941 final Rect mPadding = new Rect(0, 0, 0, 0);
942 final int mDisplayId;
943
944 DisplayData(int displayId) {
945 mDisplayId = displayId;
wilsonshih81e10a72018-11-15 10:54:21 +0800946 }
947 }
948
wilsonshiha282bf72018-11-30 12:48:05 +0800949 private void removeDisplayData(int displayId) {
950 mDisplayDatas.remove(displayId);
951 }
952
953 private DisplayData getDisplayDataOrCreate(int displayId) {
954 DisplayData wpdData = mDisplayDatas.get(displayId);
wilsonshih81e10a72018-11-15 10:54:21 +0800955 if (wpdData == null) {
wilsonshiha282bf72018-11-30 12:48:05 +0800956 wpdData = new DisplayData(displayId);
wilsonshih81e10a72018-11-15 10:54:21 +0800957 ensureSaneWallpaperDisplaySize(wpdData, displayId);
wilsonshiha282bf72018-11-30 12:48:05 +0800958 mDisplayDatas.append(displayId, wpdData);
wilsonshih81e10a72018-11-15 10:54:21 +0800959 }
960 return wpdData;
961 }
962
wilsonshiha282bf72018-11-30 12:48:05 +0800963 private void ensureSaneWallpaperDisplaySize(DisplayData wpdData, int displayId) {
wilsonshih81e10a72018-11-15 10:54:21 +0800964 // We always want to have some reasonable width hint.
965 final int baseSize = getMaximumSizeDimension(displayId);
966 if (wpdData.mWidth < baseSize) {
967 wpdData.mWidth = baseSize;
968 }
969 if (wpdData.mHeight < baseSize) {
970 wpdData.mHeight = baseSize;
971 }
972 }
973
974 private int getMaximumSizeDimension(int displayId) {
975 Display display = mDisplayManager.getDisplay(displayId);
wilsonshiha282bf72018-11-30 12:48:05 +0800976 if (display == null) {
977 Slog.w(TAG, "Invalid displayId=" + displayId + " " + Debug.getCallers(4));
978 display = mDisplayManager.getDisplay(DEFAULT_DISPLAY);
979 }
wilsonshih81e10a72018-11-15 10:54:21 +0800980 return display.getMaximumSizeDimension();
981 }
982
wilsonshiha282bf72018-11-30 12:48:05 +0800983 void forEachDisplayData(Consumer<DisplayData> action) {
984 for (int i = mDisplayDatas.size() - 1; i >= 0; i--) {
985 final DisplayData wpdData = mDisplayDatas.valueAt(i);
wilsonshih81e10a72018-11-15 10:54:21 +0800986 action.accept(wpdData);
987 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800988 }
989
Christopher Tatead3c2592016-01-20 18:13:17 -0800990 int makeWallpaperIdLocked() {
991 do {
992 ++mWallpaperId;
993 } while (mWallpaperId == 0);
994 return mWallpaperId;
995 }
996
wilsonshiha282bf72018-11-30 12:48:05 +0800997 private boolean supportsMultiDisplay(WallpaperConnection connection) {
998 if (connection != null) {
999 return connection.mInfo == null // This is image wallpaper
1000 || connection.mInfo.supportsMultipleDisplays();
1001 }
1002 return false;
1003 }
1004
1005 private void updateFallbackConnection() {
1006 if (mLastWallpaper == null || mFallbackWallpaper == null) return;
1007 final WallpaperConnection systemConnection = mLastWallpaper.connection;
1008 final WallpaperConnection fallbackConnection = mFallbackWallpaper.connection;
wilsonshih78268c32018-12-18 20:48:28 +08001009 if (fallbackConnection == null) {
1010 Slog.w(TAG, "Fallback wallpaper connection has not been created yet!!");
1011 return;
1012 }
wilsonshih507ada52019-01-19 11:22:09 +08001013 if (supportsMultiDisplay(systemConnection)) {
1014 if (fallbackConnection.mDisplayConnector.size() != 0) {
1015 fallbackConnection.forEachDisplayConnector(connector -> {
1016 if (connector.mEngine != null) {
1017 connector.disconnectLocked();
1018 }
1019 });
1020 fallbackConnection.mDisplayConnector.clear();
1021 }
wilsonshiha282bf72018-11-30 12:48:05 +08001022 } else {
1023 fallbackConnection.appendConnectorWithCondition(display ->
1024 fallbackConnection.isUsableDisplay(display)
1025 && display.getDisplayId() != DEFAULT_DISPLAY
1026 && !fallbackConnection.containsDisplay(display.getDisplayId()));
1027 fallbackConnection.forEachDisplayConnector(connector -> {
1028 if (connector.mEngine == null) {
1029 connector.connectLocked(fallbackConnection, mFallbackWallpaper);
1030 }
1031 });
1032 }
1033 }
1034
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001035 class WallpaperConnection extends IWallpaperConnection.Stub
1036 implements ServiceConnection {
Adrian Roosc3f915e2016-09-06 11:40:53 -07001037
wilsonshihde93f492018-11-01 21:23:40 +08001038 /**
1039 * Collect needed info for a display.
1040 */
1041 private final class DisplayConnector {
1042 final int mDisplayId;
1043 final Binder mToken = new Binder();
1044 IWallpaperEngine mEngine;
1045 boolean mDimensionsChanged;
1046 boolean mPaddingChanged;
1047
1048 DisplayConnector(int displayId) {
1049 mDisplayId = displayId;
1050 }
1051
1052 void ensureStatusHandled() {
wilsonshiha282bf72018-11-30 12:48:05 +08001053 final DisplayData wpdData = getDisplayDataOrCreate(mDisplayId);
wilsonshihde93f492018-11-01 21:23:40 +08001054 if (mDimensionsChanged) {
1055 try {
wilsonshih81e10a72018-11-15 10:54:21 +08001056 mEngine.setDesiredSize(wpdData.mWidth, wpdData.mHeight);
wilsonshihde93f492018-11-01 21:23:40 +08001057 } catch (RemoteException e) {
1058 Slog.w(TAG, "Failed to set wallpaper dimensions", e);
1059 }
1060 mDimensionsChanged = false;
1061 }
1062 if (mPaddingChanged) {
1063 try {
wilsonshih81e10a72018-11-15 10:54:21 +08001064 mEngine.setDisplayPadding(wpdData.mPadding);
wilsonshihde93f492018-11-01 21:23:40 +08001065 } catch (RemoteException e) {
1066 Slog.w(TAG, "Failed to set wallpaper padding", e);
1067 }
1068 mPaddingChanged = false;
1069 }
1070 }
1071
1072 void connectLocked(WallpaperConnection connection, WallpaperData wallpaper) {
wilsonshih674a4a02018-12-19 11:47:25 +08001073 if (connection.mService == null) {
1074 Slog.w(TAG, "WallpaperService is not connected yet");
1075 return;
1076 }
wilsonshihde93f492018-11-01 21:23:40 +08001077 if (DEBUG) Slog.v(TAG, "Adding window token: " + mToken);
1078 try {
1079 mIWindowManager.addWindowToken(mToken, TYPE_WALLPAPER, mDisplayId);
1080 } catch (RemoteException e) {
1081 Slog.e(TAG, "Failed add wallpaper window token on display " + mDisplayId, e);
1082 return;
1083 }
1084
wilsonshiha282bf72018-11-30 12:48:05 +08001085 final DisplayData wpdData = getDisplayDataOrCreate(mDisplayId);
wilsonshihde93f492018-11-01 21:23:40 +08001086 try {
wilsonshihde93f492018-11-01 21:23:40 +08001087 connection.mService.attach(connection, mToken, TYPE_WALLPAPER, false,
wilsonshih81e10a72018-11-15 10:54:21 +08001088 wpdData.mWidth, wpdData.mHeight,
1089 wpdData.mPadding, mDisplayId);
wilsonshihde93f492018-11-01 21:23:40 +08001090 } catch (RemoteException e) {
1091 Slog.w(TAG, "Failed attaching wallpaper on display", e);
wilsonshih674a4a02018-12-19 11:47:25 +08001092 if (wallpaper != null && !wallpaper.wallpaperUpdating
wilsonshih81e10a72018-11-15 10:54:21 +08001093 && connection.getConnectedEngineSize() == 0) {
wilsonshihde93f492018-11-01 21:23:40 +08001094 bindWallpaperComponentLocked(null /* componentName */, false /* force */,
1095 false /* fromUser */, wallpaper, null /* reply */);
1096 }
1097 }
1098 }
1099
1100 void disconnectLocked() {
1101 if (DEBUG) Slog.v(TAG, "Removing window token: " + mToken);
1102 try {
1103 mIWindowManager.removeWindowToken(mToken, mDisplayId);
1104 } catch (RemoteException e) {
1105 }
1106 try {
1107 if (mEngine != null) {
1108 mEngine.destroy();
1109 }
1110 } catch (RemoteException e) {
1111 }
1112 mEngine = null;
1113 }
1114 }
1115
1116 /**
1117 * A map for each display.
1118 * Use {@link #getDisplayConnectorOrCreate(int displayId)} to ensure the display is usable.
1119 */
1120 private SparseArray<DisplayConnector> mDisplayConnector = new SparseArray<>();
1121
Adrian Roosc3f915e2016-09-06 11:40:53 -07001122 /** Time in milliseconds until we expect the wallpaper to reconnect (unless we're in the
1123 * middle of an update). If exceeded, the wallpaper gets reset to the system default. */
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001124 private static final long WALLPAPER_RECONNECT_TIMEOUT_MS = 10000;
Adrian Roosc3f915e2016-09-06 11:40:53 -07001125
Dianne Hackborneb034652009-09-07 00:49:58 -07001126 final WallpaperInfo mInfo;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001127 IWallpaperService mService;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001128 WallpaperData mWallpaper;
wilsonshihde93f492018-11-01 21:23:40 +08001129 final int mClientUid;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001130 IRemoteCallback mReply;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001131
Adrian Roosc3f915e2016-09-06 11:40:53 -07001132 private Runnable mResetRunnable = () -> {
1133 synchronized (mLock) {
Christopher Tate762dfd12016-10-10 17:44:48 -07001134 if (mShuttingDown) {
1135 // Don't expect wallpaper services to relaunch during shutdown
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001136 if (DEBUG_LIVE) {
Christopher Tate762dfd12016-10-10 17:44:48 -07001137 Slog.i(TAG, "Ignoring relaunch timeout during shutdown");
1138 }
1139 return;
1140 }
1141
Adrian Roosc3f915e2016-09-06 11:40:53 -07001142 if (!mWallpaper.wallpaperUpdating
1143 && mWallpaper.userId == mCurrentUserId) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001144 Slog.w(TAG, "Wallpaper reconnect timed out for " + mWallpaper.wallpaperComponent
1145 + ", reverting to built-in wallpaper!");
Adrian Roosc3f915e2016-09-06 11:40:53 -07001146 clearWallpaperLocked(true, FLAG_SYSTEM, mWallpaper.userId,
1147 null);
1148 }
1149 }
1150 };
1151
wilsonshihde93f492018-11-01 21:23:40 +08001152 WallpaperConnection(WallpaperInfo info, WallpaperData wallpaper, int clientUid) {
Dianne Hackborneb034652009-09-07 00:49:58 -07001153 mInfo = info;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001154 mWallpaper = wallpaper;
wilsonshihde93f492018-11-01 21:23:40 +08001155 mClientUid = clientUid;
1156 initDisplayState();
1157 }
1158
1159 private void initDisplayState() {
wilsonshiha282bf72018-11-30 12:48:05 +08001160 // Do not initialize fallback wallpaper
1161 if (!mWallpaper.equals(mFallbackWallpaper)) {
1162 if (supportsMultiDisplay(this)) {
1163 // The system wallpaper is image wallpaper or it can supports multiple displays.
1164 appendConnectorWithCondition(this::isUsableDisplay);
1165 } else {
1166 // The system wallpaper does not support multiple displays, so just attach it on
1167 // default display.
1168 mDisplayConnector.append(DEFAULT_DISPLAY,
1169 new DisplayConnector(DEFAULT_DISPLAY));
wilsonshihde93f492018-11-01 21:23:40 +08001170 }
1171 }
1172 }
1173
wilsonshiha282bf72018-11-30 12:48:05 +08001174 private void appendConnectorWithCondition(Predicate<Display> tester) {
1175 final Display[] displays = mDisplayManager.getDisplays();
1176 for (Display display : displays) {
1177 if (tester.test(display)) {
1178 final int displayId = display.getDisplayId();
wilsonshih674a4a02018-12-19 11:47:25 +08001179 final DisplayConnector connector = mDisplayConnector.get(displayId);
1180 if (connector == null) {
1181 mDisplayConnector.append(displayId,
1182 new DisplayConnector(displayId));
1183 }
wilsonshiha282bf72018-11-30 12:48:05 +08001184 }
1185 }
1186 }
1187
wilsonshihde93f492018-11-01 21:23:40 +08001188 private boolean isUsableDisplay(Display display) {
1189 return display != null && display.hasAccess(mClientUid)
wilsonshihde93f492018-11-01 21:23:40 +08001190 && (display.supportsSystemDecorations()
1191 || display.getDisplayId() == DEFAULT_DISPLAY);
1192 }
1193
1194 void forEachDisplayConnector(Consumer<DisplayConnector> action) {
1195 for (int i = mDisplayConnector.size() - 1; i >= 0; i--) {
wilsonshih81e10a72018-11-15 10:54:21 +08001196 final DisplayConnector connector = mDisplayConnector.valueAt(i);
wilsonshihde93f492018-11-01 21:23:40 +08001197 action.accept(connector);
1198 }
1199 }
1200
wilsonshih81e10a72018-11-15 10:54:21 +08001201 int getConnectedEngineSize() {
1202 int engineSize = 0;
1203 for (int i = mDisplayConnector.size() - 1; i >= 0; i--) {
1204 final DisplayConnector connector = mDisplayConnector.valueAt(i);
1205 if (connector.mEngine != null) engineSize++;
1206 }
1207 return engineSize;
1208 }
1209
wilsonshihde93f492018-11-01 21:23:40 +08001210 DisplayConnector getDisplayConnectorOrCreate(int displayId) {
1211 DisplayConnector connector = mDisplayConnector.get(displayId);
1212 if (connector == null) {
1213 final Display display = mDisplayManager.getDisplay(displayId);
1214 if (isUsableDisplay(display)) {
1215 connector = new DisplayConnector(displayId);
1216 mDisplayConnector.append(displayId, connector);
1217 }
1218 }
1219 return connector;
1220 }
1221
wilsonshiha282bf72018-11-30 12:48:05 +08001222 boolean containsDisplay(int displayId) {
1223 return mDisplayConnector.get(displayId) != null;
1224 }
1225
wilsonshihde93f492018-11-01 21:23:40 +08001226 void removeDisplayConnector(int displayId) {
1227 final DisplayConnector connector = mDisplayConnector.get(displayId);
1228 if (connector != null) {
1229 mDisplayConnector.remove(displayId);
1230 }
Dianne Hackborneb034652009-09-07 00:49:58 -07001231 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001232
1233 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001234 public void onServiceConnected(ComponentName name, IBinder service) {
1235 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001236 if (mWallpaper.connection == this) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001237 mService = IWallpaperService.Stub.asInterface(service);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001238 attachServiceLocked(this, mWallpaper);
Dianne Hackborneb034652009-09-07 00:49:58 -07001239 // XXX should probably do saveSettingsLocked() later
1240 // when we have an engine, but I'm not sure about
1241 // locking there and anyway we always need to be able to
1242 // recover if there is something wrong.
wilsonshiha282bf72018-11-30 12:48:05 +08001243 if (!mWallpaper.equals(mFallbackWallpaper)) {
1244 saveSettingsLocked(mWallpaper.userId);
1245 }
Adrian Roosc3f915e2016-09-06 11:40:53 -07001246 FgThread.getHandler().removeCallbacks(mResetRunnable);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001247 }
1248 }
1249 }
1250
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001251 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001252 public void onServiceDisconnected(ComponentName name) {
1253 synchronized (mLock) {
Christopher Tatec349e59f2017-05-05 17:37:43 -07001254 Slog.w(TAG, "Wallpaper service gone: " + name);
1255 if (!Objects.equals(name, mWallpaper.wallpaperComponent)) {
1256 Slog.e(TAG, "Does not match expected wallpaper component "
1257 + mWallpaper.wallpaperComponent);
1258 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001259 mService = null;
wilsonshihde93f492018-11-01 21:23:40 +08001260 forEachDisplayConnector(connector -> connector.mEngine = null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001261 if (mWallpaper.connection == this) {
Christopher Tatec349e59f2017-05-05 17:37:43 -07001262 // There is an inherent ordering race between this callback and the
1263 // package monitor that receives notice that a package is being updated,
1264 // so we cannot quite trust at this moment that we know for sure that
1265 // this is not an update. If we think this is a genuine non-update
1266 // wallpaper outage, we do our "wait for reset" work as a continuation,
1267 // a short time in the future, specifically to allow any pending package
1268 // update message on this same looper thread to be processed.
1269 if (!mWallpaper.wallpaperUpdating) {
1270 mContext.getMainThreadHandler().postDelayed(() -> processDisconnect(this),
1271 1000);
1272 }
1273 }
1274 }
1275 }
1276
Tetsutoki Shiozawa06919212018-02-02 14:18:43 +09001277 public void scheduleTimeoutLocked() {
1278 // If we didn't reset it right away, do so after we couldn't connect to
1279 // it for an extended amount of time to avoid having a black wallpaper.
1280 final Handler fgHandler = FgThread.getHandler();
1281 fgHandler.removeCallbacks(mResetRunnable);
1282 fgHandler.postDelayed(mResetRunnable, WALLPAPER_RECONNECT_TIMEOUT_MS);
1283 if (DEBUG_LIVE) {
wilsonshihde93f492018-11-01 21:23:40 +08001284 Slog.i(TAG,
1285 "Started wallpaper reconnect timeout for " + mWallpaper.wallpaperComponent);
Tetsutoki Shiozawa06919212018-02-02 14:18:43 +09001286 }
1287 }
1288
Christopher Tatec349e59f2017-05-05 17:37:43 -07001289 private void processDisconnect(final ServiceConnection connection) {
1290 synchronized (mLock) {
1291 // The wallpaper disappeared. If this isn't a system-default one, track
1292 // crashes and fall back to default if it continues to misbehave.
1293 if (connection == mWallpaper.connection) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001294 final ComponentName wpService = mWallpaper.wallpaperComponent;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001295 if (!mWallpaper.wallpaperUpdating
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001296 && mWallpaper.userId == mCurrentUserId
1297 && !Objects.equals(mDefaultWallpaperComponent, wpService)
1298 && !Objects.equals(mImageWallpaper, wpService)) {
Selim Cinekebebadb2014-03-05 22:17:26 +01001299 // There is a race condition which causes
1300 // {@link #mWallpaper.wallpaperUpdating} to be false even if it is
1301 // currently updating since the broadcast notifying us is async.
1302 // This race is overcome by the general rule that we only reset the
1303 // wallpaper if its service was shut down twice
1304 // during {@link #MIN_WALLPAPER_CRASH_TIME} millis.
1305 if (mWallpaper.lastDiedTime != 0
1306 && mWallpaper.lastDiedTime + MIN_WALLPAPER_CRASH_TIME
Christopher Tatec349e59f2017-05-05 17:37:43 -07001307 > SystemClock.uptimeMillis()) {
Selim Cinekebebadb2014-03-05 22:17:26 +01001308 Slog.w(TAG, "Reverting to built-in wallpaper!");
Christopher Tateedf7d042016-03-29 18:24:25 -07001309 clearWallpaperLocked(true, FLAG_SYSTEM, mWallpaper.userId, null);
Selim Cinekebebadb2014-03-05 22:17:26 +01001310 } else {
1311 mWallpaper.lastDiedTime = SystemClock.uptimeMillis();
Adrian Roosc3f915e2016-09-06 11:40:53 -07001312
Tetsutoki Shiozawa06919212018-02-02 14:18:43 +09001313 clearWallpaperComponentLocked(mWallpaper);
1314 if (bindWallpaperComponentLocked(
1315 wpService, false, false, mWallpaper, null)) {
1316 mWallpaper.connection.scheduleTimeoutLocked();
1317 } else {
1318 Slog.w(TAG, "Reverting to built-in wallpaper!");
1319 clearWallpaperLocked(true, FLAG_SYSTEM, mWallpaper.userId, null);
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001320 }
Selim Cinekebebadb2014-03-05 22:17:26 +01001321 }
Christopher Tatec349e59f2017-05-05 17:37:43 -07001322 final String flattened = wpService.flattenToString();
Filip Gruszczynski5dcc3ac2014-10-13 15:51:39 -07001323 EventLog.writeEvent(EventLogTags.WP_WALLPAPER_CRASHED,
Filip Gruszczynski5a589432014-10-14 12:06:06 -07001324 flattened.substring(0, Math.min(flattened.length(),
1325 MAX_WALLPAPER_COMPONENT_LOG_LENGTH)));
Dianne Hackborn0cd48872009-08-13 18:51:59 -07001326 }
Christopher Tatec349e59f2017-05-05 17:37:43 -07001327 } else {
1328 if (DEBUG_LIVE) {
1329 Slog.i(TAG, "Wallpaper changed during disconnect tracking; ignoring");
1330 }
Dianne Hackborn0cd48872009-08-13 18:51:59 -07001331 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001332 }
1333 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001334
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07001335 /**
1336 * Called by a live wallpaper if its colors have changed.
1337 * @param primaryColors representation of wallpaper primary colors
wilsonshih36597d42018-12-05 18:56:39 +08001338 * @param displayId for which display
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07001339 */
1340 @Override
wilsonshih36597d42018-12-05 18:56:39 +08001341 public void onWallpaperColorsChanged(WallpaperColors primaryColors, int displayId) {
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07001342 int which;
1343 synchronized (mLock) {
1344 // Do not broadcast changes on ImageWallpaper since it's handled
1345 // internally by this class.
1346 if (mImageWallpaper.equals(mWallpaper.wallpaperComponent)) {
1347 return;
1348 }
1349
1350 mWallpaper.primaryColors = primaryColors;
1351
1352 // Live wallpapers always are system wallpapers.
1353 which = FLAG_SYSTEM;
wilsonshih36597d42018-12-05 18:56:39 +08001354 // It's also the lock screen wallpaper when we don't have a bitmap in there.
1355 if (displayId == DEFAULT_DISPLAY) {
1356 final WallpaperData lockedWallpaper = mLockWallpaperMap.get(mWallpaper.userId);
1357 if (lockedWallpaper == null) {
1358 which |= FLAG_LOCK;
1359 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07001360 }
1361 }
1362 if (which != 0) {
wilsonshih36597d42018-12-05 18:56:39 +08001363 notifyWallpaperColorsChangedOnDisplay(mWallpaper, which, displayId);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07001364 }
1365 }
1366
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001367 @Override
wilsonshihde93f492018-11-01 21:23:40 +08001368 public void attachEngine(IWallpaperEngine engine, int displayId) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001369 synchronized (mLock) {
wilsonshihde93f492018-11-01 21:23:40 +08001370 final DisplayConnector connector = getDisplayConnectorOrCreate(displayId);
1371 if (connector == null) {
Michael Wright5203a8b2013-10-03 14:16:42 -07001372 try {
wilsonshihde93f492018-11-01 21:23:40 +08001373 engine.destroy();
Michael Wright5203a8b2013-10-03 14:16:42 -07001374 } catch (RemoteException e) {
wilsonshihde93f492018-11-01 21:23:40 +08001375 Slog.w(TAG, "Failed to destroy engine", e);
Michael Wright5203a8b2013-10-03 14:16:42 -07001376 }
wilsonshihde93f492018-11-01 21:23:40 +08001377 return;
Michael Wright5203a8b2013-10-03 14:16:42 -07001378 }
wilsonshihde93f492018-11-01 21:23:40 +08001379 connector.mEngine = engine;
1380 connector.ensureStatusHandled();
1381
1382 // TODO(multi-display) TBD.
1383 if (mInfo != null && mInfo.supportsAmbientMode() && displayId == DEFAULT_DISPLAY) {
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001384 try {
Lucas Dupin4c8c3272018-11-06 17:47:48 -08001385 connector.mEngine.setInAmbientMode(mInAmbientMode, 0L /* duration */);
Lucas Dupin7517b5d2017-08-22 12:51:25 -07001386 } catch (RemoteException e) {
1387 Slog.w(TAG, "Failed to set ambient mode state", e);
1388 }
1389 }
wilsonshih36597d42018-12-05 18:56:39 +08001390 try {
1391 // This will trigger onComputeColors in the wallpaper engine.
1392 // It's fine to be locked in here since the binder is oneway.
1393 connector.mEngine.requestWallpaperColors();
1394 } catch (RemoteException e) {
1395 Slog.w(TAG, "Failed to request wallpaper colors", e);
Lucas Dupin50ba9912017-07-14 11:55:05 -07001396 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001397 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001398 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001399
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001400 @Override
1401 public void engineShown(IWallpaperEngine engine) {
1402 synchronized (mLock) {
1403 if (mReply != null) {
1404 long ident = Binder.clearCallingIdentity();
1405 try {
1406 mReply.sendResult(null);
1407 } catch (RemoteException e) {
1408 Binder.restoreCallingIdentity(ident);
1409 }
1410 mReply = null;
1411 }
1412 }
1413 }
1414
1415 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001416 public ParcelFileDescriptor setWallpaper(String name) {
1417 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001418 if (mWallpaper.connection == this) {
Christopher Tatead3c2592016-01-20 18:13:17 -08001419 return updateWallpaperBitmapLocked(name, mWallpaper, null);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001420 }
1421 return null;
1422 }
1423 }
1424 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001425
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001426 class MyPackageMonitor extends PackageMonitor {
1427 @Override
1428 public void onPackageUpdateFinished(String packageName, int uid) {
1429 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -07001430 if (mCurrentUserId != getChangingUserId()) {
1431 return;
1432 }
1433 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
1434 if (wallpaper != null) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001435 final ComponentName wpService = wallpaper.wallpaperComponent;
1436 if (wpService != null && wpService.getPackageName().equals(packageName)) {
1437 if (DEBUG_LIVE) {
1438 Slog.i(TAG, "Wallpaper " + wpService + " update has finished");
1439 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001440 wallpaper.wallpaperUpdating = false;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001441 clearWallpaperComponentLocked(wallpaper);
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001442 if (!bindWallpaperComponentLocked(wpService, false, false,
Dianne Hackbornc72fc672012-09-20 13:12:03 -07001443 wallpaper, null)) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001444 Slog.w(TAG, "Wallpaper " + wpService
1445 + " no longer available; reverting to default");
Christopher Tateedf7d042016-03-29 18:24:25 -07001446 clearWallpaperLocked(false, FLAG_SYSTEM, wallpaper.userId, null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001447 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001448 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001449 }
1450 }
1451 }
1452
1453 @Override
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001454 public void onPackageModified(String packageName) {
1455 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -07001456 if (mCurrentUserId != getChangingUserId()) {
1457 return;
1458 }
1459 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
1460 if (wallpaper != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001461 if (wallpaper.wallpaperComponent == null
1462 || !wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -07001463 return;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001464 }
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001465 doPackagesChangedLocked(true, wallpaper);
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001466 }
1467 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001468 }
1469
1470 @Override
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001471 public void onPackageUpdateStarted(String packageName, int uid) {
1472 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -07001473 if (mCurrentUserId != getChangingUserId()) {
1474 return;
1475 }
1476 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
1477 if (wallpaper != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001478 if (wallpaper.wallpaperComponent != null
1479 && wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001480 if (DEBUG_LIVE) {
1481 Slog.i(TAG, "Wallpaper service " + wallpaper.wallpaperComponent
1482 + " is updating");
1483 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001484 wallpaper.wallpaperUpdating = true;
Adrian Roosc3f915e2016-09-06 11:40:53 -07001485 if (wallpaper.connection != null) {
1486 FgThread.getHandler().removeCallbacks(
1487 wallpaper.connection.mResetRunnable);
1488 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001489 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001490 }
1491 }
1492 }
1493
1494 @Override
1495 public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001496 synchronized (mLock) {
1497 boolean changed = false;
Dianne Hackbornc72fc672012-09-20 13:12:03 -07001498 if (mCurrentUserId != getChangingUserId()) {
1499 return false;
1500 }
1501 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
1502 if (wallpaper != null) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001503 boolean res = doPackagesChangedLocked(doit, wallpaper);
1504 changed |= res;
1505 }
1506 return changed;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001507 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001508 }
1509
1510 @Override
1511 public void onSomePackagesChanged() {
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001512 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -07001513 if (mCurrentUserId != getChangingUserId()) {
1514 return;
1515 }
1516 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
1517 if (wallpaper != null) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001518 doPackagesChangedLocked(true, wallpaper);
1519 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001520 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001521 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001522
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001523 boolean doPackagesChangedLocked(boolean doit, WallpaperData wallpaper) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001524 boolean changed = false;
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001525 if (wallpaper.wallpaperComponent != null) {
1526 int change = isPackageDisappearing(wallpaper.wallpaperComponent
1527 .getPackageName());
1528 if (change == PACKAGE_PERMANENT_CHANGE
1529 || change == PACKAGE_TEMPORARY_CHANGE) {
1530 changed = true;
1531 if (doit) {
1532 Slog.w(TAG, "Wallpaper uninstalled, removing: "
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001533 + wallpaper.wallpaperComponent);
Christopher Tateedf7d042016-03-29 18:24:25 -07001534 clearWallpaperLocked(false, FLAG_SYSTEM, wallpaper.userId, null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001535 }
1536 }
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001537 }
1538 if (wallpaper.nextWallpaperComponent != null) {
1539 int change = isPackageDisappearing(wallpaper.nextWallpaperComponent
1540 .getPackageName());
1541 if (change == PACKAGE_PERMANENT_CHANGE
1542 || change == PACKAGE_TEMPORARY_CHANGE) {
1543 wallpaper.nextWallpaperComponent = null;
1544 }
1545 }
1546 if (wallpaper.wallpaperComponent != null
1547 && isPackageModified(wallpaper.wallpaperComponent.getPackageName())) {
1548 try {
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001549 mContext.getPackageManager().getServiceInfo(wallpaper.wallpaperComponent,
1550 PackageManager.MATCH_DIRECT_BOOT_AWARE
1551 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001552 } catch (NameNotFoundException e) {
1553 Slog.w(TAG, "Wallpaper component gone, removing: "
1554 + wallpaper.wallpaperComponent);
Christopher Tateedf7d042016-03-29 18:24:25 -07001555 clearWallpaperLocked(false, FLAG_SYSTEM, wallpaper.userId, null);
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001556 }
1557 }
1558 if (wallpaper.nextWallpaperComponent != null
1559 && isPackageModified(wallpaper.nextWallpaperComponent.getPackageName())) {
1560 try {
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001561 mContext.getPackageManager().getServiceInfo(wallpaper.nextWallpaperComponent,
1562 PackageManager.MATCH_DIRECT_BOOT_AWARE
1563 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001564 } catch (NameNotFoundException e) {
1565 wallpaper.nextWallpaperComponent = null;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001566 }
1567 }
1568 return changed;
1569 }
1570 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001571
Dianne Hackborn8cc6a502009-08-05 21:29:42 -07001572 public WallpaperManagerService(Context context) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001573 if (DEBUG) Slog.v(TAG, "WallpaperService startup");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001574 mContext = context;
Christopher Tate762dfd12016-10-10 17:44:48 -07001575 mShuttingDown = false;
Justin Koh29c30162014-09-05 17:10:10 -07001576 mImageWallpaper = ComponentName.unflattenFromString(
1577 context.getResources().getString(R.string.image_wallpaper_component));
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001578 mDefaultWallpaperComponent = WallpaperManager.getDefaultWallpaperComponent(context);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001579 mIWindowManager = IWindowManager.Stub.asInterface(
1580 ServiceManager.getService(Context.WINDOW_SERVICE));
Amith Yamasani4e2820c2012-08-28 22:17:23 -07001581 mIPackageManager = AppGlobals.getPackageManager();
Benjamin Franzf3ece362015-02-11 10:51:10 +00001582 mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
wilsonshihde93f492018-11-01 21:23:40 +08001583 mDisplayManager = mContext.getSystemService(DisplayManager.class);
1584 mDisplayManager.registerDisplayListener(mDisplayListener, null /* handler */);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001585 mMonitor = new MyPackageMonitor();
Jaekyun Seokad7d90f2018-04-04 01:57:18 +09001586 mColorsChangedListeners = new SparseArray<>();
1587 }
1588
1589 void initialize() {
1590 mMonitor.register(mContext, null, UserHandle.ALL, true);
Xiaohui Chen233d94c2015-07-30 15:08:00 -07001591 getWallpaperDir(UserHandle.USER_SYSTEM).mkdirs();
Christopher Tatef717b932017-09-11 15:52:54 -07001592
1593 // Initialize state from the persistent store, then guarantee that the
1594 // WallpaperData for the system imagery is instantiated & active, creating
1595 // it from defaults if necessary.
Christopher Tated7faf532016-02-25 12:43:38 -08001596 loadSettingsLocked(UserHandle.USER_SYSTEM, false);
Christopher Tatef717b932017-09-11 15:52:54 -07001597 getWallpaperSafeLocked(UserHandle.USER_SYSTEM, FLAG_SYSTEM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001598 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001599
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001600 private static File getWallpaperDir(int userId) {
Amith Yamasani61f57372012-08-31 12:12:28 -07001601 return Environment.getUserSystemDirectory(userId);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001602 }
1603
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001604 @Override
1605 protected void finalize() throws Throwable {
1606 super.finalize();
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001607 for (int i = 0; i < mWallpaperMap.size(); i++) {
1608 WallpaperData wallpaper = mWallpaperMap.valueAt(i);
1609 wallpaper.wallpaperObserver.stopWatching();
1610 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001611 }
Amith Yamasani13593602012-03-22 16:16:17 -07001612
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001613 void systemReady() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001614 if (DEBUG) Slog.v(TAG, "systemReady");
Jaekyun Seokad7d90f2018-04-04 01:57:18 +09001615 initialize();
1616
Xiaohui Chen233d94c2015-07-30 15:08:00 -07001617 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.USER_SYSTEM);
Christopher Tate2cdd3f22016-03-14 17:36:16 -07001618 // If we think we're going to be using the system image wallpaper imagery, make
1619 // sure we have something to render
1620 if (mImageWallpaper.equals(wallpaper.nextWallpaperComponent)) {
1621 // No crop file? Make sure we've finished the processing sequence if necessary
1622 if (!wallpaper.cropExists()) {
1623 if (DEBUG) {
1624 Slog.i(TAG, "No crop; regenerating from source");
1625 }
1626 generateCrop(wallpaper);
1627 }
1628 // Still nothing? Fall back to default.
1629 if (!wallpaper.cropExists()) {
1630 if (DEBUG) {
1631 Slog.i(TAG, "Unable to regenerate crop; resetting");
1632 }
Christopher Tateedf7d042016-03-29 18:24:25 -07001633 clearWallpaperLocked(false, FLAG_SYSTEM, UserHandle.USER_SYSTEM, null);
Christopher Tate2cdd3f22016-03-14 17:36:16 -07001634 }
1635 } else {
1636 if (DEBUG) {
1637 Slog.i(TAG, "Nondefault wallpaper component; gracefully ignoring");
1638 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001639 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001640
Amith Yamasani13593602012-03-22 16:16:17 -07001641 IntentFilter userFilter = new IntentFilter();
Amith Yamasani13593602012-03-22 16:16:17 -07001642 userFilter.addAction(Intent.ACTION_USER_REMOVED);
1643 mContext.registerReceiver(new BroadcastReceiver() {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001644 @Override
Amith Yamasani13593602012-03-22 16:16:17 -07001645 public void onReceive(Context context, Intent intent) {
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001646 final String action = intent.getAction();
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001647 if (Intent.ACTION_USER_REMOVED.equals(action)) {
Amith Yamasani756901d2012-10-12 12:30:07 -07001648 onRemoveUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
1649 UserHandle.USER_NULL));
Amith Yamasani13593602012-03-22 16:16:17 -07001650 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001651 }
Amith Yamasani13593602012-03-22 16:16:17 -07001652 }, userFilter);
Amith Yamasani756901d2012-10-12 12:30:07 -07001653
Christopher Tate762dfd12016-10-10 17:44:48 -07001654 final IntentFilter shutdownFilter = new IntentFilter(Intent.ACTION_SHUTDOWN);
1655 mContext.registerReceiver(new BroadcastReceiver() {
1656 @Override
1657 public void onReceive(Context context, Intent intent) {
1658 if (Intent.ACTION_SHUTDOWN.equals(intent.getAction())) {
1659 if (DEBUG) {
1660 Slog.i(TAG, "Shutting down");
1661 }
1662 synchronized (mLock) {
1663 mShuttingDown = true;
1664 }
1665 }
1666 }
1667 }, shutdownFilter);
1668
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001669 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001670 ActivityManager.getService().registerUserSwitchObserver(
Sudheer Shanka2c4522c2016-08-27 20:53:28 -07001671 new UserSwitchObserver() {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001672 @Override
1673 public void onUserSwitching(int newUserId, IRemoteCallback reply) {
1674 switchUser(newUserId, reply);
1675 }
Fyodor Kupolov0b77ef92016-06-20 17:16:52 -07001676 }, TAG);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001677 } catch (RemoteException e) {
Fyodor Kupolov0b77ef92016-06-20 17:16:52 -07001678 e.rethrowAsRuntimeException();
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001679 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001680 }
1681
Amith Yamasani09e9cdc2013-11-06 14:54:50 -08001682 /** Called by SystemBackupAgent */
1683 public String getName() {
1684 // Verify caller is the system
1685 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
1686 throw new RuntimeException("getName() can only be called from the system process");
1687 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001688 synchronized (mLock) {
1689 return mWallpaperMap.get(0).name;
1690 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001691 }
1692
Christopher Tatebe132e62016-02-10 12:59:49 -08001693 void stopObserver(WallpaperData wallpaper) {
1694 if (wallpaper != null) {
1695 if (wallpaper.wallpaperObserver != null) {
1696 wallpaper.wallpaperObserver.stopWatching();
1697 wallpaper.wallpaperObserver = null;
Amith Yamasani13593602012-03-22 16:16:17 -07001698 }
Amith Yamasani756901d2012-10-12 12:30:07 -07001699 }
1700 }
1701
Christopher Tatebe132e62016-02-10 12:59:49 -08001702 void stopObserversLocked(int userId) {
1703 stopObserver(mWallpaperMap.get(userId));
1704 stopObserver(mLockWallpaperMap.get(userId));
1705 mWallpaperMap.remove(userId);
1706 mLockWallpaperMap.remove(userId);
1707 }
1708
Daichi Hirono4bbf8522017-12-06 10:34:18 +09001709 @Override
1710 public void onBootPhase(int phase) {
1711 if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
1712 systemReady();
1713 } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
1714 switchUser(UserHandle.USER_SYSTEM, null);
1715 }
1716 }
1717
1718 @Override
1719 public void onUnlockUser(final int userId) {
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001720 synchronized (mLock) {
Christopher Tate38a5dc32016-07-20 15:10:18 -07001721 if (mCurrentUserId == userId) {
1722 if (mWaitingForUnlock) {
wilsonshiha47fcc92018-04-26 14:27:38 +08001723 // the desired wallpaper is not direct-boot aware, load it now
1724 final WallpaperData systemWallpaper =
1725 getWallpaperSafeLocked(userId, FLAG_SYSTEM);
1726 switchWallpaper(systemWallpaper, null);
Christopher Tate38a5dc32016-07-20 15:10:18 -07001727 }
Christopher Tate190e8532016-07-11 11:35:34 -07001728
1729 // Make sure that the SELinux labeling of all the relevant files is correct.
1730 // This corrects for mislabeling bugs that might have arisen from move-to
1731 // operations involving the wallpaper files. This isn't timing-critical,
1732 // so we do it in the background to avoid holding up the user unlock operation.
wilsonshiha282bf72018-11-30 12:48:05 +08001733 if (!mUserRestorecon.get(userId)) {
1734 mUserRestorecon.put(userId, true);
Christopher Tate38a5dc32016-07-20 15:10:18 -07001735 Runnable relabeler = new Runnable() {
1736 @Override
1737 public void run() {
1738 final File wallpaperDir = getWallpaperDir(userId);
1739 for (String filename : sPerUserFiles) {
1740 File f = new File(wallpaperDir, filename);
1741 if (f.exists()) {
1742 SELinux.restorecon(f);
1743 }
Christopher Tate190e8532016-07-11 11:35:34 -07001744 }
1745 }
Christopher Tate38a5dc32016-07-20 15:10:18 -07001746 };
1747 BackgroundThread.getHandler().post(relabeler);
1748 }
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001749 }
1750 }
1751 }
1752
Amith Yamasani756901d2012-10-12 12:30:07 -07001753 void onRemoveUser(int userId) {
1754 if (userId < 1) return;
Christopher Tatebe132e62016-02-10 12:59:49 -08001755
1756 final File wallpaperDir = getWallpaperDir(userId);
Amith Yamasani756901d2012-10-12 12:30:07 -07001757 synchronized (mLock) {
Christopher Tatebe132e62016-02-10 12:59:49 -08001758 stopObserversLocked(userId);
1759 for (String filename : sPerUserFiles) {
1760 new File(wallpaperDir, filename).delete();
1761 }
wilsonshiha282bf72018-11-30 12:48:05 +08001762 mUserRestorecon.delete(userId);
Amith Yamasani13593602012-03-22 16:16:17 -07001763 }
1764 }
1765
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001766 void switchUser(int userId, IRemoteCallback reply) {
Lucas Dupin9272d452017-09-14 14:15:42 -07001767 final WallpaperData systemWallpaper;
1768 final WallpaperData lockWallpaper;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001769 synchronized (mLock) {
Jaekyun Seokad7d90f2018-04-04 01:57:18 +09001770 if (mCurrentUserId == userId) {
1771 return;
1772 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001773 mCurrentUserId = userId;
Lucas Dupin50ba9912017-07-14 11:55:05 -07001774 systemWallpaper = getWallpaperSafeLocked(userId, FLAG_SYSTEM);
Lucas Dupin9272d452017-09-14 14:15:42 -07001775 final WallpaperData tmpLockWallpaper = mLockWallpaperMap.get(userId);
1776 lockWallpaper = tmpLockWallpaper == null ? systemWallpaper : tmpLockWallpaper;
Lucas Dupin50ba9912017-07-14 11:55:05 -07001777 // Not started watching yet, in case wallpaper data was loaded for other reasons.
1778 if (systemWallpaper.wallpaperObserver == null) {
1779 systemWallpaper.wallpaperObserver = new WallpaperObserver(systemWallpaper);
1780 systemWallpaper.wallpaperObserver.startWatching();
1781 }
1782 switchWallpaper(systemWallpaper, reply);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001783 }
Lucas Dupin9272d452017-09-14 14:15:42 -07001784
1785 // Offload color extraction to another thread since switchUser will be called
1786 // from the main thread.
1787 FgThread.getHandler().post(() -> {
1788 notifyWallpaperColorsChanged(systemWallpaper, FLAG_SYSTEM);
1789 notifyWallpaperColorsChanged(lockWallpaper, FLAG_LOCK);
wilsonshih36597d42018-12-05 18:56:39 +08001790 notifyWallpaperColorsChanged(mFallbackWallpaper, FLAG_SYSTEM);
Lucas Dupin9272d452017-09-14 14:15:42 -07001791 });
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001792 }
1793
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001794 void switchWallpaper(WallpaperData wallpaper, IRemoteCallback reply) {
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001795 synchronized (mLock) {
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001796 mWaitingForUnlock = false;
1797 final ComponentName cname = wallpaper.wallpaperComponent != null ?
1798 wallpaper.wallpaperComponent : wallpaper.nextWallpaperComponent;
1799 if (!bindWallpaperComponentLocked(cname, true, false, wallpaper, reply)) {
1800 // We failed to bind the desired wallpaper, but that might
1801 // happen if the wallpaper isn't direct-boot aware
1802 ServiceInfo si = null;
1803 try {
1804 si = mIPackageManager.getServiceInfo(cname,
1805 PackageManager.MATCH_DIRECT_BOOT_UNAWARE, wallpaper.userId);
1806 } catch (RemoteException ignored) {
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001807 }
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001808
1809 if (si == null) {
1810 Slog.w(TAG, "Failure starting previous wallpaper; clearing");
1811 clearWallpaperLocked(false, FLAG_SYSTEM, wallpaper.userId, reply);
1812 } else {
1813 Slog.w(TAG, "Wallpaper isn't direct boot aware; using fallback until unlocked");
1814 // We might end up persisting the current wallpaper data
1815 // while locked, so pretend like the component was actually
1816 // bound into place
1817 wallpaper.wallpaperComponent = wallpaper.nextWallpaperComponent;
1818 final WallpaperData fallback = new WallpaperData(wallpaper.userId,
1819 WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP);
wilsonshih81e10a72018-11-15 10:54:21 +08001820 ensureSaneWallpaperData(fallback, DEFAULT_DISPLAY);
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001821 bindWallpaperComponentLocked(mImageWallpaper, true, false, fallback, reply);
1822 mWaitingForUnlock = true;
1823 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001824 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001825 }
1826 }
1827
Christopher Tatebe132e62016-02-10 12:59:49 -08001828 @Override
1829 public void clearWallpaper(String callingPackage, int which, int userId) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001830 if (DEBUG) Slog.v(TAG, "clearWallpaper");
Benjamin Franzf3ece362015-02-11 10:51:10 +00001831 checkPermission(android.Manifest.permission.SET_WALLPAPER);
Christopher Tate98d609c2016-05-18 17:31:58 -07001832 if (!isWallpaperSupported(callingPackage) || !isSetWallpaperAllowed(callingPackage)) {
Benjamin Franzf3ece362015-02-11 10:51:10 +00001833 return;
1834 }
Christopher Tatee409f0e2016-03-21 14:53:15 -07001835 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
1836 Binder.getCallingUid(), userId, false, true, "clearWallpaper", null);
Christopher Tatebe132e62016-02-10 12:59:49 -08001837
Lucas Dupin41f69422017-05-03 15:26:22 -07001838 WallpaperData data = null;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001839 synchronized (mLock) {
Christopher Tatebe132e62016-02-10 12:59:49 -08001840 clearWallpaperLocked(false, which, userId, null);
Lucas Dupin41f69422017-05-03 15:26:22 -07001841
1842 if (which == FLAG_LOCK) {
1843 data = mLockWallpaperMap.get(userId);
1844 }
1845 if (which == FLAG_SYSTEM || data == null) {
1846 data = mWallpaperMap.get(userId);
1847 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001848 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07001849
1850 // When clearing a wallpaper, broadcast new valid colors
Lucas Dupin41f69422017-05-03 15:26:22 -07001851 if (data != null) {
1852 notifyWallpaperColorsChanged(data, which);
wilsonshih36597d42018-12-05 18:56:39 +08001853 notifyWallpaperColorsChanged(mFallbackWallpaper, FLAG_SYSTEM);
Lucas Dupin41f69422017-05-03 15:26:22 -07001854 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001855 }
1856
Christopher Tatebe132e62016-02-10 12:59:49 -08001857 void clearWallpaperLocked(boolean defaultFailed, int which, int userId, IRemoteCallback reply) {
Christopher Tateedf7d042016-03-29 18:24:25 -07001858 if (which != FLAG_SYSTEM && which != FLAG_LOCK) {
Christopher Tate105540d2018-03-21 13:03:09 -07001859 throw new IllegalArgumentException("Must specify exactly one kind of wallpaper to clear");
Christopher Tatebe132e62016-02-10 12:59:49 -08001860 }
1861
1862 WallpaperData wallpaper = null;
Christopher Tateedf7d042016-03-29 18:24:25 -07001863 if (which == FLAG_LOCK) {
Christopher Tatebe132e62016-02-10 12:59:49 -08001864 wallpaper = mLockWallpaperMap.get(userId);
1865 if (wallpaper == null) {
1866 // It's already gone; we're done.
Christopher Tate79a24572016-03-02 14:42:44 -08001867 if (DEBUG) {
1868 Slog.i(TAG, "Lock wallpaper already cleared");
1869 }
Christopher Tatebe132e62016-02-10 12:59:49 -08001870 return;
1871 }
1872 } else {
1873 wallpaper = mWallpaperMap.get(userId);
1874 if (wallpaper == null) {
1875 // Might need to bring it in the first time to establish our rewrite
Christopher Tated7faf532016-02-25 12:43:38 -08001876 loadSettingsLocked(userId, false);
Christopher Tatebe132e62016-02-10 12:59:49 -08001877 wallpaper = mWallpaperMap.get(userId);
1878 }
1879 }
Benjamin Franzf3ece362015-02-11 10:51:10 +00001880 if (wallpaper == null) {
1881 return;
1882 }
Christopher Tatebe132e62016-02-10 12:59:49 -08001883
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001884 final long ident = Binder.clearCallingIdentity();
1885 try {
Christopher Tatebe132e62016-02-10 12:59:49 -08001886 if (wallpaper.wallpaperFile.exists()) {
1887 wallpaper.wallpaperFile.delete();
1888 wallpaper.cropFile.delete();
Christopher Tateedf7d042016-03-29 18:24:25 -07001889 if (which == FLAG_LOCK) {
Christopher Tate79a24572016-03-02 14:42:44 -08001890 mLockWallpaperMap.remove(userId);
Christopher Tatebe132e62016-02-10 12:59:49 -08001891 final IWallpaperManagerCallback cb = mKeyguardListener;
1892 if (cb != null) {
Christopher Tate79a24572016-03-02 14:42:44 -08001893 if (DEBUG) {
1894 Slog.i(TAG, "Notifying keyguard of lock wallpaper clear");
1895 }
Christopher Tatebe132e62016-02-10 12:59:49 -08001896 try {
1897 cb.onWallpaperChanged();
1898 } catch (RemoteException e) {
1899 // Oh well it went away; no big deal
1900 }
1901 }
Christopher Tate79a24572016-03-02 14:42:44 -08001902 saveSettingsLocked(userId);
Christopher Tatebe132e62016-02-10 12:59:49 -08001903 return;
1904 }
1905 }
1906
Christopher Tateecd827a2014-09-05 17:42:34 -07001907 RuntimeException e = null;
1908 try {
Lucas Dupin75ec3792017-06-29 14:07:18 -07001909 wallpaper.primaryColors = null;
Christopher Tateecd827a2014-09-05 17:42:34 -07001910 wallpaper.imageWallpaperPending = false;
1911 if (userId != mCurrentUserId) return;
1912 if (bindWallpaperComponentLocked(defaultFailed
1913 ? mImageWallpaper
1914 : null, true, false, wallpaper, reply)) {
1915 return;
1916 }
1917 } catch (IllegalArgumentException e1) {
1918 e = e1;
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001919 }
Christopher Tateecd827a2014-09-05 17:42:34 -07001920
1921 // This can happen if the default wallpaper component doesn't
1922 // exist. This should be a system configuration problem, but
1923 // let's not let it crash the system and just live with no
1924 // wallpaper.
1925 Slog.e(TAG, "Default wallpaper component not found!", e);
1926 clearWallpaperComponentLocked(wallpaper);
1927 if (reply != null) {
1928 try {
1929 reply.sendResult(null);
1930 } catch (RemoteException e1) {
1931 }
1932 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001933 } finally {
1934 Binder.restoreCallingIdentity(ident);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001935 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001936 }
1937
1938 public boolean hasNamedWallpaper(String name) {
1939 synchronized (mLock) {
Amith Yamasani6474c4c2012-10-04 14:55:42 -07001940 List<UserInfo> users;
1941 long ident = Binder.clearCallingIdentity();
1942 try {
1943 users = ((UserManager) mContext.getSystemService(Context.USER_SERVICE)).getUsers();
1944 } finally {
1945 Binder.restoreCallingIdentity(ident);
1946 }
1947 for (UserInfo user: users) {
Benjamin Franzf3ece362015-02-11 10:51:10 +00001948 // ignore managed profiles
1949 if (user.isManagedProfile()) {
1950 continue;
1951 }
Amith Yamasani6474c4c2012-10-04 14:55:42 -07001952 WallpaperData wd = mWallpaperMap.get(user.id);
1953 if (wd == null) {
1954 // User hasn't started yet, so load her settings to peek at the wallpaper
Christopher Tated7faf532016-02-25 12:43:38 -08001955 loadSettingsLocked(user.id, false);
Amith Yamasani6474c4c2012-10-04 14:55:42 -07001956 wd = mWallpaperMap.get(user.id);
1957 }
1958 if (wd != null && name.equals(wd.name)) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001959 return true;
1960 }
1961 }
1962 }
1963 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001964 }
1965
wilsonshih81e10a72018-11-15 10:54:21 +08001966 private boolean isValidDisplay(int displayId) {
1967 return mDisplayManager.getDisplay(displayId) != null;
1968 }
1969
1970 /**
1971 * Sets the dimension hint for the wallpaper. These hints indicate the desired
1972 * minimum width and height for the wallpaper in a particular display.
1973 */
1974 public void setDimensionHints(int width, int height, String callingPackage, int displayId)
Benjamin Franzf3ece362015-02-11 10:51:10 +00001975 throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001976 checkPermission(android.Manifest.permission.SET_WALLPAPER_HINTS);
Benjamin Franzf3ece362015-02-11 10:51:10 +00001977 if (!isWallpaperSupported(callingPackage)) {
1978 return;
1979 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001980 synchronized (mLock) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001981 int userId = UserHandle.getCallingUserId();
Christopher Tateedf7d042016-03-29 18:24:25 -07001982 WallpaperData wallpaper = getWallpaperSafeLocked(userId, FLAG_SYSTEM);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001983 if (width <= 0 || height <= 0) {
1984 throw new IllegalArgumentException("width and height must be > 0");
1985 }
1986
wilsonshih81e10a72018-11-15 10:54:21 +08001987 if (!isValidDisplay(displayId)) {
1988 throw new IllegalArgumentException("Cannot find display with id=" + displayId);
1989 }
1990
wilsonshiha282bf72018-11-30 12:48:05 +08001991 final DisplayData wpdData = getDisplayDataOrCreate(displayId);
wilsonshih81e10a72018-11-15 10:54:21 +08001992 if (width != wpdData.mWidth || height != wpdData.mHeight) {
1993 wpdData.mWidth = width;
1994 wpdData.mHeight = height;
1995 if (displayId == DEFAULT_DISPLAY) saveSettingsLocked(userId);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001996 if (mCurrentUserId != userId) return; // Don't change the properties now
1997 if (wallpaper.connection != null) {
wilsonshih81e10a72018-11-15 10:54:21 +08001998 final WallpaperConnection.DisplayConnector connector = wallpaper.connection
1999 .getDisplayConnectorOrCreate(displayId);
2000 final IWallpaperEngine engine = connector != null ? connector.mEngine : null;
wilsonshihde93f492018-11-01 21:23:40 +08002001 if (engine != null) {
Dianne Hackborn284ac932009-08-28 10:34:25 -07002002 try {
wilsonshihde93f492018-11-01 21:23:40 +08002003 engine.setDesiredSize(width, height);
Dianne Hackborn284ac932009-08-28 10:34:25 -07002004 } catch (RemoteException e) {
2005 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002006 notifyCallbacksLocked(wallpaper);
wilsonshih81e10a72018-11-15 10:54:21 +08002007 } else if (wallpaper.connection.mService != null && connector != null) {
Michael Wright5203a8b2013-10-03 14:16:42 -07002008 // We've attached to the service but the engine hasn't attached back to us
2009 // yet. This means it will be created with the previous dimensions, so we
2010 // need to update it to the new dimensions once it attaches.
wilsonshih81e10a72018-11-15 10:54:21 +08002011 connector.mDimensionsChanged = true;
Dianne Hackborn284ac932009-08-28 10:34:25 -07002012 }
2013 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002014 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002015 }
2016 }
2017
wilsonshih81e10a72018-11-15 10:54:21 +08002018 /**
2019 * Returns the desired minimum width for the wallpaper in a particular display.
2020 */
2021 public int getWidthHint(int displayId) throws RemoteException {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002022 synchronized (mLock) {
wilsonshih81e10a72018-11-15 10:54:21 +08002023 if (!isValidDisplay(displayId)) {
2024 throw new IllegalArgumentException("Cannot find display with id=" + displayId);
2025 }
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07002026 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.getCallingUserId());
Benjamin Franzf3ece362015-02-11 10:51:10 +00002027 if (wallpaper != null) {
wilsonshiha282bf72018-11-30 12:48:05 +08002028 final DisplayData wpdData = getDisplayDataOrCreate(displayId);
wilsonshih81e10a72018-11-15 10:54:21 +08002029 return wpdData.mWidth;
Benjamin Franzf3ece362015-02-11 10:51:10 +00002030 } else {
2031 return 0;
2032 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002033 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002034 }
2035
wilsonshih81e10a72018-11-15 10:54:21 +08002036 /**
2037 * Returns the desired minimum height for the wallpaper in a particular display.
2038 */
2039 public int getHeightHint(int displayId) throws RemoteException {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002040 synchronized (mLock) {
wilsonshih81e10a72018-11-15 10:54:21 +08002041 if (!isValidDisplay(displayId)) {
2042 throw new IllegalArgumentException("Cannot find display with id=" + displayId);
2043 }
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07002044 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.getCallingUserId());
Benjamin Franzf3ece362015-02-11 10:51:10 +00002045 if (wallpaper != null) {
wilsonshiha282bf72018-11-30 12:48:05 +08002046 final DisplayData wpdData = getDisplayDataOrCreate(displayId);
wilsonshih81e10a72018-11-15 10:54:21 +08002047 return wpdData.mHeight;
Benjamin Franzf3ece362015-02-11 10:51:10 +00002048 } else {
2049 return 0;
2050 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002051 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002052 }
2053
wilsonshih81e10a72018-11-15 10:54:21 +08002054 /**
2055 * Sets extra padding that we would like the wallpaper to have outside of the display.
2056 */
2057 public void setDisplayPadding(Rect padding, String callingPackage, int displayId) {
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002058 checkPermission(android.Manifest.permission.SET_WALLPAPER_HINTS);
Benjamin Franzf3ece362015-02-11 10:51:10 +00002059 if (!isWallpaperSupported(callingPackage)) {
2060 return;
2061 }
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002062 synchronized (mLock) {
wilsonshih81e10a72018-11-15 10:54:21 +08002063 if (!isValidDisplay(displayId)) {
2064 throw new IllegalArgumentException("Cannot find display with id=" + displayId);
2065 }
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002066 int userId = UserHandle.getCallingUserId();
Christopher Tateedf7d042016-03-29 18:24:25 -07002067 WallpaperData wallpaper = getWallpaperSafeLocked(userId, FLAG_SYSTEM);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002068 if (padding.left < 0 || padding.top < 0 || padding.right < 0 || padding.bottom < 0) {
2069 throw new IllegalArgumentException("padding must be positive: " + padding);
2070 }
2071
wilsonshiha282bf72018-11-30 12:48:05 +08002072 final DisplayData wpdData = getDisplayDataOrCreate(displayId);
wilsonshih81e10a72018-11-15 10:54:21 +08002073 if (!padding.equals(wpdData.mPadding)) {
2074 wpdData.mPadding.set(padding);
2075 if (displayId == DEFAULT_DISPLAY) saveSettingsLocked(userId);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002076 if (mCurrentUserId != userId) return; // Don't change the properties now
2077 if (wallpaper.connection != null) {
wilsonshih81e10a72018-11-15 10:54:21 +08002078 final WallpaperConnection.DisplayConnector connector = wallpaper.connection
2079 .getDisplayConnectorOrCreate(displayId);
2080 final IWallpaperEngine engine = connector != null ? connector.mEngine : null;
wilsonshihde93f492018-11-01 21:23:40 +08002081 if (engine != null) {
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002082 try {
wilsonshihde93f492018-11-01 21:23:40 +08002083 engine.setDisplayPadding(padding);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002084 } catch (RemoteException e) {
2085 }
2086 notifyCallbacksLocked(wallpaper);
wilsonshih81e10a72018-11-15 10:54:21 +08002087 } else if (wallpaper.connection.mService != null && connector != null) {
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002088 // We've attached to the service but the engine hasn't attached back to us
2089 // yet. This means it will be created with the previous dimensions, so we
2090 // need to update it to the new dimensions once it attaches.
wilsonshih81e10a72018-11-15 10:54:21 +08002091 connector.mPaddingChanged = true;
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002092 }
2093 }
2094 }
2095 }
2096 }
2097
Christopher Tate93252de2017-06-15 14:48:41 -07002098 private void enforceCallingOrSelfPermissionAndAppOp(String permission, final String callingPkg,
2099 final int callingUid, String message) {
2100 mContext.enforceCallingOrSelfPermission(permission, message);
2101
2102 final String opName = AppOpsManager.permissionToOp(permission);
2103 if (opName != null) {
2104 final int appOpMode = mAppOpsManager.noteOp(opName, callingUid, callingPkg);
2105 if (appOpMode != AppOpsManager.MODE_ALLOWED) {
2106 throw new SecurityException(
2107 message + ": " + callingPkg + " is not allowed to " + permission);
2108 }
2109 }
2110 }
2111
Yorke Leedcd93cc2016-01-08 14:12:55 -08002112 @Override
Christopher Tate93252de2017-06-15 14:48:41 -07002113 public ParcelFileDescriptor getWallpaper(String callingPkg, IWallpaperManagerCallback cb,
2114 final int which, Bundle outParams, int wallpaperUserId) {
Christopher Tate8a71c482017-08-14 16:45:03 -07002115 final int hasPrivilege = mContext.checkCallingOrSelfPermission(
2116 android.Manifest.permission.READ_WALLPAPER_INTERNAL);
2117 if (hasPrivilege != PackageManager.PERMISSION_GRANTED) {
2118 enforceCallingOrSelfPermissionAndAppOp(android.Manifest.permission.READ_EXTERNAL_STORAGE,
2119 callingPkg, Binder.getCallingUid(), "read wallpaper");
2120 }
Christopher Tate93252de2017-06-15 14:48:41 -07002121
Christopher Tatee409f0e2016-03-21 14:53:15 -07002122 wallpaperUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
2123 Binder.getCallingUid(), wallpaperUserId, false, true, "getWallpaper", null);
Christopher Tatebe132e62016-02-10 12:59:49 -08002124
Christopher Tateedf7d042016-03-29 18:24:25 -07002125 if (which != FLAG_SYSTEM && which != FLAG_LOCK) {
Christopher Tatebe132e62016-02-10 12:59:49 -08002126 throw new IllegalArgumentException("Must specify exactly one kind of wallpaper to read");
2127 }
2128
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002129 synchronized (mLock) {
Vadim Tryshev8cde0792016-02-19 17:02:15 -08002130 final SparseArray<WallpaperData> whichSet =
Christopher Tateedf7d042016-03-29 18:24:25 -07002131 (which == FLAG_LOCK) ? mLockWallpaperMap : mWallpaperMap;
Vadim Tryshev8cde0792016-02-19 17:02:15 -08002132 WallpaperData wallpaper = whichSet.get(wallpaperUserId);
2133 if (wallpaper == null) {
Christopher Tatef717b932017-09-11 15:52:54 -07002134 // There is no established wallpaper imagery of this type (expected
2135 // only for lock wallpapers; a system WallpaperData is established at
2136 // user switch)
2137 return null;
Benjamin Franzf3ece362015-02-11 10:51:10 +00002138 }
wilsonshih81e10a72018-11-15 10:54:21 +08002139 // Only for default display.
wilsonshiha282bf72018-11-30 12:48:05 +08002140 final DisplayData wpdData = getDisplayDataOrCreate(DEFAULT_DISPLAY);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002141 try {
Dianne Hackborn284ac932009-08-28 10:34:25 -07002142 if (outParams != null) {
wilsonshih81e10a72018-11-15 10:54:21 +08002143 outParams.putInt("width", wpdData.mWidth);
2144 outParams.putInt("height", wpdData.mHeight);
Dianne Hackborn284ac932009-08-28 10:34:25 -07002145 }
Christopher Tateea6724a2016-02-18 18:39:19 -08002146 if (cb != null) {
2147 wallpaper.callbacks.register(cb);
2148 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08002149 if (!wallpaper.cropFile.exists()) {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002150 return null;
2151 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08002152 return ParcelFileDescriptor.open(wallpaper.cropFile, MODE_READ_ONLY);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002153 } catch (FileNotFoundException e) {
2154 /* Shouldn't happen as we check to see if the file exists */
Joe Onorato8a9b2202010-02-26 18:56:32 -08002155 Slog.w(TAG, "Error getting wallpaper", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002156 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002157 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002158 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002159 }
2160
Christopher Tatee409f0e2016-03-21 14:53:15 -07002161 @Override
Jorim Jaggie31f6b82016-07-01 16:15:09 -07002162 public WallpaperInfo getWallpaperInfo(int userId) {
2163 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
Christopher Tatef717b932017-09-11 15:52:54 -07002164 Binder.getCallingUid(), userId, false, true, "getWallpaperInfo", null);
Dianne Hackborneb034652009-09-07 00:49:58 -07002165 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002166 WallpaperData wallpaper = mWallpaperMap.get(userId);
Benjamin Franzf3ece362015-02-11 10:51:10 +00002167 if (wallpaper != null && wallpaper.connection != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002168 return wallpaper.connection.mInfo;
Dianne Hackborneb034652009-09-07 00:49:58 -07002169 }
2170 return null;
2171 }
2172 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002173
Christopher Tatead3c2592016-01-20 18:13:17 -08002174 @Override
Christopher Tatee409f0e2016-03-21 14:53:15 -07002175 public int getWallpaperIdForUser(int which, int userId) {
2176 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
2177 Binder.getCallingUid(), userId, false, true, "getWallpaperIdForUser", null);
2178
Christopher Tateedf7d042016-03-29 18:24:25 -07002179 if (which != FLAG_SYSTEM && which != FLAG_LOCK) {
Christopher Tatee409f0e2016-03-21 14:53:15 -07002180 throw new IllegalArgumentException("Must specify exactly one kind of wallpaper");
2181 }
2182
2183 final SparseArray<WallpaperData> map =
Christopher Tateedf7d042016-03-29 18:24:25 -07002184 (which == FLAG_LOCK) ? mLockWallpaperMap : mWallpaperMap;
Christopher Tatee409f0e2016-03-21 14:53:15 -07002185 synchronized (mLock) {
2186 WallpaperData wallpaper = map.get(userId);
2187 if (wallpaper != null) {
2188 return wallpaper.wallpaperId;
2189 }
2190 }
2191 return -1;
2192 }
2193
2194 @Override
wilsonshih36597d42018-12-05 18:56:39 +08002195 public void registerWallpaperColorsCallback(IWallpaperManagerCallback cb, int userId,
2196 int displayId) {
Lucas Dupin50ba9912017-07-14 11:55:05 -07002197 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
2198 userId, true, true, "registerWallpaperColorsCallback", null);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002199 synchronized (mLock) {
wilsonshih36597d42018-12-05 18:56:39 +08002200 SparseArray<RemoteCallbackList<IWallpaperManagerCallback>>
2201 userDisplayColorsChangedListeners = mColorsChangedListeners.get(userId);
2202 if (userDisplayColorsChangedListeners == null) {
2203 userDisplayColorsChangedListeners = new SparseArray<>();
2204 mColorsChangedListeners.put(userId, userDisplayColorsChangedListeners);
Lucas Dupin50ba9912017-07-14 11:55:05 -07002205 }
wilsonshih36597d42018-12-05 18:56:39 +08002206 RemoteCallbackList<IWallpaperManagerCallback> displayChangedListeners =
2207 userDisplayColorsChangedListeners.get(displayId);
2208 if (displayChangedListeners == null) {
2209 displayChangedListeners = new RemoteCallbackList<>();
2210 userDisplayColorsChangedListeners.put(displayId, displayChangedListeners);
2211 }
2212 displayChangedListeners.register(cb);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002213 }
2214 }
2215
2216 @Override
wilsonshih36597d42018-12-05 18:56:39 +08002217 public void unregisterWallpaperColorsCallback(IWallpaperManagerCallback cb, int userId,
2218 int displayId) {
Lucas Dupin50ba9912017-07-14 11:55:05 -07002219 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
2220 userId, true, true, "unregisterWallpaperColorsCallback", null);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002221 synchronized (mLock) {
wilsonshih36597d42018-12-05 18:56:39 +08002222 SparseArray<RemoteCallbackList<IWallpaperManagerCallback>>
2223 userDisplayColorsChangedListeners = mColorsChangedListeners.get(userId);
2224 if (userDisplayColorsChangedListeners != null) {
2225 RemoteCallbackList<IWallpaperManagerCallback> displayChangedListeners =
2226 userDisplayColorsChangedListeners.get(displayId);
2227 if (displayChangedListeners != null) {
2228 displayChangedListeners.unregister(cb);
2229 }
Lucas Dupin50ba9912017-07-14 11:55:05 -07002230 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002231 }
2232 }
2233
Lucas Dupin4c8c3272018-11-06 17:47:48 -08002234 /**
wilsonshih36597d42018-12-05 18:56:39 +08002235 * TODO(multi-display) Extends this method with specific display.
Lucas Dupin4c8c3272018-11-06 17:47:48 -08002236 * Propagate ambient state to wallpaper engine.
2237 *
2238 * @param inAmbientMode {@code true} when in ambient mode, {@code false} otherwise.
2239 * @param animationDuration Duration of the animation, or 0 when immediate.
2240 */
2241 public void setInAmbientMode(boolean inAmbientMode, long animationDuration) {
Lucas Dupin7517b5d2017-08-22 12:51:25 -07002242 final IWallpaperEngine engine;
2243 synchronized (mLock) {
Lucas Dupin4c8c3272018-11-06 17:47:48 -08002244 mInAmbientMode = inAmbientMode;
Lucas Dupin7517b5d2017-08-22 12:51:25 -07002245 final WallpaperData data = mWallpaperMap.get(mCurrentUserId);
Lucas Dupin98897ce2019-02-06 20:43:36 +00002246 final boolean hasConnection = data != null && data.connection != null;
2247 final WallpaperInfo info = hasConnection ? data.connection.mInfo : null;
2248
Ahan Wu723a80e2018-11-07 20:39:32 +08002249 // The wallpaper info is null for image wallpaper, also use the engine in this case.
Lucas Dupin98897ce2019-02-06 20:43:36 +00002250 if (hasConnection && (info == null && isAodImageWallpaperEnabled()
2251 || info != null && info.supportsAmbientMode())) {
wilsonshih36597d42018-12-05 18:56:39 +08002252 // TODO(multi-display) Extends this method with specific display.
wilsonshihde93f492018-11-01 21:23:40 +08002253 engine = data.connection.getDisplayConnectorOrCreate(DEFAULT_DISPLAY).mEngine;
Lucas Dupin7517b5d2017-08-22 12:51:25 -07002254 } else {
2255 engine = null;
2256 }
2257 }
2258
2259 if (engine != null) {
2260 try {
Lucas Dupin4c8c3272018-11-06 17:47:48 -08002261 engine.setInAmbientMode(inAmbientMode, animationDuration);
Lucas Dupin7517b5d2017-08-22 12:51:25 -07002262 } catch (RemoteException e) {
2263 // Cannot talk to wallpaper engine.
2264 }
2265 }
2266 }
2267
Ahan Wu723a80e2018-11-07 20:39:32 +08002268 private boolean isAodImageWallpaperEnabled() {
2269 return FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.AOD_IMAGEWALLPAPER_ENABLED);
2270 }
2271
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002272 @Override
Christopher Tatebe132e62016-02-10 12:59:49 -08002273 public boolean setLockWallpaperCallback(IWallpaperManagerCallback cb) {
2274 checkPermission(android.Manifest.permission.INTERNAL_SYSTEM_WINDOW);
2275 synchronized (mLock) {
2276 mKeyguardListener = cb;
2277 }
2278 return true;
2279 }
2280
2281 @Override
wilsonshih36597d42018-12-05 18:56:39 +08002282 public WallpaperColors getWallpaperColors(int which, int userId, int displayId)
2283 throws RemoteException {
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002284 if (which != FLAG_LOCK && which != FLAG_SYSTEM) {
2285 throw new IllegalArgumentException("which should be either FLAG_LOCK or FLAG_SYSTEM");
2286 }
Lucas Dupin50ba9912017-07-14 11:55:05 -07002287 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
2288 userId, false, true, "getWallpaperColors", null);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002289
2290 WallpaperData wallpaperData = null;
2291 boolean shouldExtract;
2292
2293 synchronized (mLock) {
2294 if (which == FLAG_LOCK) {
Lucas Dupin50ba9912017-07-14 11:55:05 -07002295 wallpaperData = mLockWallpaperMap.get(userId);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002296 }
2297
2298 // Try to get the system wallpaper anyway since it might
2299 // also be the lock screen wallpaper
2300 if (wallpaperData == null) {
wilsonshih36597d42018-12-05 18:56:39 +08002301 wallpaperData = findWallpaperAtDisplay(userId, displayId);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002302 }
2303
2304 if (wallpaperData == null) {
2305 return null;
2306 }
2307 shouldExtract = wallpaperData.primaryColors == null;
2308 }
2309
2310 if (shouldExtract) {
2311 extractColors(wallpaperData);
2312 }
2313
2314 synchronized (mLock) {
Lucas Dupin4b4c5302018-06-24 18:22:10 -07002315 return wallpaperData.primaryColors;
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002316 }
2317 }
2318
wilsonshih36597d42018-12-05 18:56:39 +08002319 private WallpaperData findWallpaperAtDisplay(int userId, int displayId) {
2320 if (mFallbackWallpaper != null && mFallbackWallpaper.connection != null
2321 && mFallbackWallpaper.connection.containsDisplay(displayId)) {
2322 return mFallbackWallpaper;
2323 } else {
2324 return mWallpaperMap.get(userId);
2325 }
2326 }
2327
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002328 @Override
Christopher Tate1e1e2e02016-01-25 15:34:36 -08002329 public ParcelFileDescriptor setWallpaper(String name, String callingPackage,
Christopher Tated7faf532016-02-25 12:43:38 -08002330 Rect cropHint, boolean allowBackup, Bundle extras, int which,
Jorim Jaggi6c902d02016-08-18 10:44:54 -07002331 IWallpaperManagerCallback completion, int userId) {
2332 userId = ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,
2333 false /* all */, true /* full */, "changing wallpaper", null /* pkg */);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002334 checkPermission(android.Manifest.permission.SET_WALLPAPER);
Christopher Tatead3c2592016-01-20 18:13:17 -08002335
Christopher Tateedf7d042016-03-29 18:24:25 -07002336 if ((which & (FLAG_LOCK|FLAG_SYSTEM)) == 0) {
Christopher Tate98d609c2016-05-18 17:31:58 -07002337 final String msg = "Must specify a valid wallpaper category to set";
2338 Slog.e(TAG, msg);
2339 throw new IllegalArgumentException(msg);
Christopher Tatead3c2592016-01-20 18:13:17 -08002340 }
2341
Christopher Tate98d609c2016-05-18 17:31:58 -07002342 if (!isWallpaperSupported(callingPackage) || !isSetWallpaperAllowed(callingPackage)) {
Benjamin Franzf3ece362015-02-11 10:51:10 +00002343 return null;
2344 }
Christopher Tatead3c2592016-01-20 18:13:17 -08002345
Christopher Tate1e1e2e02016-01-25 15:34:36 -08002346 // "null" means the no-op crop, preserving the full input image
2347 if (cropHint == null) {
2348 cropHint = new Rect(0, 0, 0, 0);
2349 } else {
2350 if (cropHint.isEmpty()
2351 || cropHint.left < 0
2352 || cropHint.top < 0) {
Christopher Tate98d609c2016-05-18 17:31:58 -07002353 throw new IllegalArgumentException("Invalid crop rect supplied: " + cropHint);
Christopher Tate1e1e2e02016-01-25 15:34:36 -08002354 }
2355 }
2356
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002357 synchronized (mLock) {
Christopher Tatebe132e62016-02-10 12:59:49 -08002358 if (DEBUG) Slog.v(TAG, "setWallpaper which=0x" + Integer.toHexString(which));
2359 WallpaperData wallpaper;
2360
Christopher Tate8347b632016-04-29 18:59:18 -07002361 /* If we're setting system but not lock, and lock is currently sharing the system
2362 * wallpaper, we need to migrate that image over to being lock-only before
2363 * the caller here writes new bitmap data.
2364 */
2365 if (which == FLAG_SYSTEM && mLockWallpaperMap.get(userId) == null) {
2366 if (DEBUG) {
2367 Slog.i(TAG, "Migrating system->lock to preserve");
2368 }
2369 migrateSystemToLockWallpaperLocked(userId);
2370 }
2371
Christopher Tatebe132e62016-02-10 12:59:49 -08002372 wallpaper = getWallpaperSafeLocked(userId, which);
Dianne Hackborn0cd48872009-08-13 18:51:59 -07002373 final long ident = Binder.clearCallingIdentity();
2374 try {
Christopher Tatead3c2592016-01-20 18:13:17 -08002375 ParcelFileDescriptor pfd = updateWallpaperBitmapLocked(name, wallpaper, extras);
Dianne Hackborn0cd48872009-08-13 18:51:59 -07002376 if (pfd != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002377 wallpaper.imageWallpaperPending = true;
Christopher Tatebe132e62016-02-10 12:59:49 -08002378 wallpaper.whichPending = which;
Christopher Tate1e1e2e02016-01-25 15:34:36 -08002379 wallpaper.setComplete = completion;
2380 wallpaper.cropHint.set(cropHint);
Christopher Tatec613c632016-08-12 14:13:02 -07002381 wallpaper.allowBackup = allowBackup;
Dianne Hackborn0cd48872009-08-13 18:51:59 -07002382 }
2383 return pfd;
2384 } finally {
2385 Binder.restoreCallingIdentity(ident);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002386 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002387 }
2388 }
2389
Christopher Tate8347b632016-04-29 18:59:18 -07002390 private void migrateSystemToLockWallpaperLocked(int userId) {
2391 WallpaperData sysWP = mWallpaperMap.get(userId);
2392 if (sysWP == null) {
2393 if (DEBUG) {
2394 Slog.i(TAG, "No system wallpaper? Not tracking for lock-only");
2395 }
2396 return;
2397 }
2398
2399 // We know a-priori that there is no lock-only wallpaper currently
2400 WallpaperData lockWP = new WallpaperData(userId,
2401 WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP);
2402 lockWP.wallpaperId = sysWP.wallpaperId;
2403 lockWP.cropHint.set(sysWP.cropHint);
Christopher Tateedd8dc82016-10-12 15:17:58 -07002404 lockWP.allowBackup = sysWP.allowBackup;
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002405 lockWP.primaryColors = sysWP.primaryColors;
Christopher Tate8347b632016-04-29 18:59:18 -07002406
2407 // Migrate the bitmap files outright; no need to copy
2408 try {
2409 Os.rename(sysWP.wallpaperFile.getAbsolutePath(), lockWP.wallpaperFile.getAbsolutePath());
2410 Os.rename(sysWP.cropFile.getAbsolutePath(), lockWP.cropFile.getAbsolutePath());
2411 } catch (ErrnoException e) {
2412 Slog.e(TAG, "Can't migrate system wallpaper: " + e.getMessage());
2413 lockWP.wallpaperFile.delete();
2414 lockWP.cropFile.delete();
2415 return;
2416 }
2417
2418 mLockWallpaperMap.put(userId, lockWP);
2419 }
2420
Christopher Tatead3c2592016-01-20 18:13:17 -08002421 ParcelFileDescriptor updateWallpaperBitmapLocked(String name, WallpaperData wallpaper,
2422 Bundle extras) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002423 if (name == null) name = "";
2424 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002425 File dir = getWallpaperDir(wallpaper.userId);
2426 if (!dir.exists()) {
2427 dir.mkdir();
Dianne Hackbornebac48c2011-11-29 18:01:50 -08002428 FileUtils.setPermissions(
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002429 dir.getPath(),
Dianne Hackbornebac48c2011-11-29 18:01:50 -08002430 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
2431 -1, -1);
2432 }
Christopher Tatebe132e62016-02-10 12:59:49 -08002433 ParcelFileDescriptor fd = ParcelFileDescriptor.open(wallpaper.wallpaperFile,
Christopher Tate90f86ba2014-09-11 12:37:19 -07002434 MODE_CREATE|MODE_READ_WRITE|MODE_TRUNCATE);
Christopher Tatebe132e62016-02-10 12:59:49 -08002435 if (!SELinux.restorecon(wallpaper.wallpaperFile)) {
rpcraig554cb0c2012-07-05 06:41:43 -04002436 return null;
2437 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002438 wallpaper.name = name;
Christopher Tatead3c2592016-01-20 18:13:17 -08002439 wallpaper.wallpaperId = makeWallpaperIdLocked();
2440 if (extras != null) {
2441 extras.putInt(WallpaperManager.EXTRA_NEW_WALLPAPER_ID, wallpaper.wallpaperId);
2442 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002443 // Nullify field to require new computation
2444 wallpaper.primaryColors = null;
Christopher Tatead3c2592016-01-20 18:13:17 -08002445 if (DEBUG) {
2446 Slog.v(TAG, "updateWallpaperBitmapLocked() : id=" + wallpaper.wallpaperId
Christopher Tatebe132e62016-02-10 12:59:49 -08002447 + " name=" + name + " file=" + wallpaper.wallpaperFile.getName());
Christopher Tatead3c2592016-01-20 18:13:17 -08002448 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002449 return fd;
2450 } catch (FileNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002451 Slog.w(TAG, "Error setting wallpaper", e);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002452 }
2453 return null;
2454 }
2455
Christopher Tated57d17c2016-03-25 13:41:46 -07002456 @Override
Adrian Roos40ea0832016-07-14 14:19:55 -07002457 public void setWallpaperComponentChecked(ComponentName name, String callingPackage,
2458 int userId) {
2459
Christopher Tate98d609c2016-05-18 17:31:58 -07002460 if (isWallpaperSupported(callingPackage) && isSetWallpaperAllowed(callingPackage)) {
Adrian Roos40ea0832016-07-14 14:19:55 -07002461 setWallpaperComponent(name, userId);
Benjamin Franzf3ece362015-02-11 10:51:10 +00002462 }
2463 }
2464
2465 // ToDo: Remove this version of the function
Christopher Tated57d17c2016-03-25 13:41:46 -07002466 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002467 public void setWallpaperComponent(ComponentName name) {
Adrian Roos40ea0832016-07-14 14:19:55 -07002468 setWallpaperComponent(name, UserHandle.getCallingUserId());
2469 }
2470
2471 private void setWallpaperComponent(ComponentName name, int userId) {
2472 userId = ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,
2473 false /* all */, true /* full */, "changing live wallpaper", null /* pkg */);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002474 checkPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT);
Adrian Roos40ea0832016-07-14 14:19:55 -07002475
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002476 int which = FLAG_SYSTEM;
2477 boolean shouldNotifyColors = false;
2478 WallpaperData wallpaper;
2479
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002480 synchronized (mLock) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002481 if (DEBUG) Slog.v(TAG, "setWallpaperComponent name=" + name);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002482 wallpaper = mWallpaperMap.get(userId);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002483 if (wallpaper == null) {
2484 throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
2485 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002486 final long ident = Binder.clearCallingIdentity();
Christopher Tate7cd00102016-12-19 14:38:44 -08002487
2488 // Live wallpapers can't be specified for keyguard. If we're using a static
2489 // system+lock image currently, migrate the system wallpaper to be a lock-only
2490 // image as part of making a different live component active as the system
2491 // wallpaper.
2492 if (mImageWallpaper.equals(wallpaper.wallpaperComponent)) {
2493 if (mLockWallpaperMap.get(userId) == null) {
2494 // We're using the static imagery and there is no lock-specific image in place,
2495 // therefore it's a shared system+lock image that we need to migrate.
2496 migrateSystemToLockWallpaperLocked(userId);
2497 }
2498 }
2499
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002500 // New live wallpaper is also a lock wallpaper if nothing is set
2501 if (mLockWallpaperMap.get(userId) == null) {
2502 which |= FLAG_LOCK;
2503 }
2504
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002505 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002506 wallpaper.imageWallpaperPending = false;
Lucas Dupin50ba9912017-07-14 11:55:05 -07002507 boolean same = changingToSame(name, wallpaper);
Christopher Tated57d17c2016-03-25 13:41:46 -07002508 if (bindWallpaperComponentLocked(name, false, true, wallpaper, null)) {
Lucas Dupin50ba9912017-07-14 11:55:05 -07002509 if (!same) {
2510 wallpaper.primaryColors = null;
2511 }
Christopher Tated57d17c2016-03-25 13:41:46 -07002512 wallpaper.wallpaperId = makeWallpaperIdLocked();
Sunny Goyal0572e182016-03-31 11:05:51 -07002513 notifyCallbacksLocked(wallpaper);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002514 shouldNotifyColors = true;
Christopher Tated57d17c2016-03-25 13:41:46 -07002515 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002516 } finally {
2517 Binder.restoreCallingIdentity(ident);
2518 }
2519 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002520
2521 if (shouldNotifyColors) {
2522 notifyWallpaperColorsChanged(wallpaper, which);
wilsonshih36597d42018-12-05 18:56:39 +08002523 notifyWallpaperColorsChanged(mFallbackWallpaper, FLAG_SYSTEM);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002524 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002525 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01002526
Lucas Dupin50ba9912017-07-14 11:55:05 -07002527 private boolean changingToSame(ComponentName componentName, WallpaperData wallpaper) {
2528 if (wallpaper.connection != null) {
2529 if (wallpaper.wallpaperComponent == null) {
2530 if (componentName == null) {
2531 if (DEBUG) Slog.v(TAG, "changingToSame: still using default");
2532 // Still using default wallpaper.
2533 return true;
2534 }
2535 } else if (wallpaper.wallpaperComponent.equals(componentName)) {
2536 // Changing to same wallpaper.
2537 if (DEBUG) Slog.v(TAG, "same wallpaper");
2538 return true;
2539 }
2540 }
2541 return false;
2542 }
2543
wilsonshiha282bf72018-11-30 12:48:05 +08002544 private boolean bindWallpaperComponentLocked(ComponentName componentName, boolean force,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002545 boolean fromUser, WallpaperData wallpaper, IRemoteCallback reply) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07002546 if (DEBUG_LIVE) {
2547 Slog.v(TAG, "bindWallpaperComponentLocked: componentName=" + componentName);
2548 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002549 // Has the component changed?
Lucas Dupin50ba9912017-07-14 11:55:05 -07002550 if (!force && changingToSame(componentName, wallpaper)) {
2551 return true;
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002552 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01002553
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002554 try {
Mike Clerona428b2c2009-11-15 22:53:08 -08002555 if (componentName == null) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07002556 componentName = mDefaultWallpaperComponent;
Mike Clerona428b2c2009-11-15 22:53:08 -08002557 if (componentName == null) {
Mike Cleron322b6ee2009-11-12 07:45:47 -08002558 // Fall back to static image wallpaper
Justin Koh29c30162014-09-05 17:10:10 -07002559 componentName = mImageWallpaper;
Mike Cleron322b6ee2009-11-12 07:45:47 -08002560 //clearWallpaperComponentLocked();
2561 //return;
Christopher Tate2a6c55f2017-03-31 12:28:30 -07002562 if (DEBUG_LIVE) Slog.v(TAG, "No default component; using image wallpaper");
Mike Cleron322b6ee2009-11-12 07:45:47 -08002563 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002564 }
Amith Yamasani4e2820c2012-08-28 22:17:23 -07002565 int serviceUserId = wallpaper.userId;
2566 ServiceInfo si = mIPackageManager.getServiceInfo(componentName,
2567 PackageManager.GET_META_DATA | PackageManager.GET_PERMISSIONS, serviceUserId);
Christopher Tate90952202013-09-08 13:01:28 -07002568 if (si == null) {
2569 // The wallpaper component we're trying to use doesn't exist
2570 Slog.w(TAG, "Attempted wallpaper " + componentName + " is unavailable");
2571 return false;
2572 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002573 if (!android.Manifest.permission.BIND_WALLPAPER.equals(si.permission)) {
Lucas Dupin4c8c3272018-11-06 17:47:48 -08002574 String msg = "Selected service does not have "
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002575 + android.Manifest.permission.BIND_WALLPAPER
Dianne Hackborn80b902f2011-09-15 15:15:27 -07002576 + ": " + componentName;
2577 if (fromUser) {
2578 throw new SecurityException(msg);
2579 }
2580 Slog.w(TAG, msg);
2581 return false;
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002582 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01002583
Dianne Hackborneb034652009-09-07 00:49:58 -07002584 WallpaperInfo wi = null;
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01002585
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002586 Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
Justin Koh29c30162014-09-05 17:10:10 -07002587 if (componentName != null && !componentName.equals(mImageWallpaper)) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002588 // Make sure the selected service is actually a wallpaper service.
Amith Yamasani4e2820c2012-08-28 22:17:23 -07002589 List<ResolveInfo> ris =
2590 mIPackageManager.queryIntentServices(intent,
2591 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
Jeff Sharkeyd5896632016-03-04 16:16:00 -07002592 PackageManager.GET_META_DATA, serviceUserId).getList();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002593 for (int i=0; i<ris.size(); i++) {
2594 ServiceInfo rsi = ris.get(i).serviceInfo;
2595 if (rsi.name.equals(si.name) &&
2596 rsi.packageName.equals(si.packageName)) {
Dianne Hackborneb034652009-09-07 00:49:58 -07002597 try {
2598 wi = new WallpaperInfo(mContext, ris.get(i));
2599 } catch (XmlPullParserException e) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -07002600 if (fromUser) {
2601 throw new IllegalArgumentException(e);
2602 }
2603 Slog.w(TAG, e);
2604 return false;
Dianne Hackborneb034652009-09-07 00:49:58 -07002605 } catch (IOException e) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -07002606 if (fromUser) {
2607 throw new IllegalArgumentException(e);
2608 }
2609 Slog.w(TAG, e);
2610 return false;
Dianne Hackborneb034652009-09-07 00:49:58 -07002611 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002612 break;
2613 }
2614 }
Dianne Hackborneb034652009-09-07 00:49:58 -07002615 if (wi == null) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -07002616 String msg = "Selected service is not a wallpaper: "
2617 + componentName;
2618 if (fromUser) {
2619 throw new SecurityException(msg);
2620 }
2621 Slog.w(TAG, msg);
2622 return false;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002623 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002624 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01002625
Lucas Dupin4c8c3272018-11-06 17:47:48 -08002626 if (wi != null && wi.supportsAmbientMode()) {
2627 final int hasPrivilege = mIPackageManager.checkPermission(
2628 android.Manifest.permission.AMBIENT_WALLPAPER, wi.getPackageName(),
2629 serviceUserId);
2630 if (hasPrivilege != PackageManager.PERMISSION_GRANTED) {
2631 String msg = "Selected service does not have "
2632 + android.Manifest.permission.AMBIENT_WALLPAPER
2633 + ": " + componentName;
2634 if (fromUser) {
2635 throw new SecurityException(msg);
2636 }
2637 Slog.w(TAG, msg);
2638 return false;
2639 }
2640 }
2641
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002642 // Bind the service!
Joe Onorato8a9b2202010-02-26 18:56:32 -08002643 if (DEBUG) Slog.v(TAG, "Binding to:" + componentName);
wilsonshihde93f492018-11-01 21:23:40 +08002644 final int componentUid = mIPackageManager.getPackageUid(componentName.getPackageName(),
2645 MATCH_DIRECT_BOOT_AUTO, wallpaper.userId);
2646 WallpaperConnection newConn = new WallpaperConnection(wi, wallpaper, componentUid);
Mike Clerona428b2c2009-11-15 22:53:08 -08002647 intent.setComponent(componentName);
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07002648 intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
2649 com.android.internal.R.string.wallpaper_binding_label);
Dianne Hackborn41203752012-08-31 14:05:51 -07002650 intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivityAsUser(
Dianne Hackborneb034652009-09-07 00:49:58 -07002651 mContext, 0,
2652 Intent.createChooser(new Intent(Intent.ACTION_SET_WALLPAPER),
2653 mContext.getText(com.android.internal.R.string.chooser_wallpaper)),
Dianne Hackborn41203752012-08-31 14:05:51 -07002654 0, null, new UserHandle(serviceUserId)));
Dianne Hackbornc8230512013-07-13 21:32:12 -07002655 if (!mContext.bindServiceAsUser(intent, newConn,
Dianne Hackbornd69e4c12015-04-24 09:54:54 -07002656 Context.BIND_AUTO_CREATE | Context.BIND_SHOWING_UI
2657 | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
Amith Yamasani27b89e62013-01-16 12:30:11 -08002658 new UserHandle(serviceUserId))) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -07002659 String msg = "Unable to bind service: "
2660 + componentName;
2661 if (fromUser) {
2662 throw new IllegalArgumentException(msg);
2663 }
2664 Slog.w(TAG, msg);
2665 return false;
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002666 }
wilsonshiha282bf72018-11-30 12:48:05 +08002667 if (wallpaper.userId == mCurrentUserId && mLastWallpaper != null
2668 && !wallpaper.equals(mFallbackWallpaper)) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002669 detachWallpaperLocked(mLastWallpaper);
2670 }
2671 wallpaper.wallpaperComponent = componentName;
2672 wallpaper.connection = newConn;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002673 newConn.mReply = reply;
wilsonshiha282bf72018-11-30 12:48:05 +08002674 if (wallpaper.userId == mCurrentUserId && !wallpaper.equals(mFallbackWallpaper)) {
wilsonshihde93f492018-11-01 21:23:40 +08002675 mLastWallpaper = wallpaper;
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002676 }
wilsonshiha282bf72018-11-30 12:48:05 +08002677 updateFallbackConnection();
Amith Yamasani4e2820c2012-08-28 22:17:23 -07002678 } catch (RemoteException e) {
2679 String msg = "Remote exception for " + componentName + "\n" + e;
Dianne Hackborn80b902f2011-09-15 15:15:27 -07002680 if (fromUser) {
2681 throw new IllegalArgumentException(msg);
2682 }
2683 Slog.w(TAG, msg);
2684 return false;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002685 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -07002686 return true;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002687 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002688
wilsonshiha282bf72018-11-30 12:48:05 +08002689 private void detachWallpaperLocked(WallpaperData wallpaper) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002690 if (wallpaper.connection != null) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002691 if (wallpaper.connection.mReply != null) {
2692 try {
2693 wallpaper.connection.mReply.sendResult(null);
2694 } catch (RemoteException e) {
2695 }
2696 wallpaper.connection.mReply = null;
2697 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002698 mContext.unbindService(wallpaper.connection);
wilsonshiha282bf72018-11-30 12:48:05 +08002699 wallpaper.connection.forEachDisplayConnector(
2700 WallpaperConnection.DisplayConnector::disconnectLocked);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002701 wallpaper.connection.mService = null;
wilsonshihde93f492018-11-01 21:23:40 +08002702 wallpaper.connection.mDisplayConnector.clear();
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002703 wallpaper.connection = null;
wilsonshihde93f492018-11-01 21:23:40 +08002704 if (wallpaper == mLastWallpaper) mLastWallpaper = null;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002705 }
2706 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002707
wilsonshiha282bf72018-11-30 12:48:05 +08002708 private void clearWallpaperComponentLocked(WallpaperData wallpaper) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002709 wallpaper.wallpaperComponent = null;
2710 detachWallpaperLocked(wallpaper);
2711 }
2712
wilsonshiha282bf72018-11-30 12:48:05 +08002713 private void attachServiceLocked(WallpaperConnection conn, WallpaperData wallpaper) {
wilsonshihde93f492018-11-01 21:23:40 +08002714 conn.forEachDisplayConnector(connector-> connector.connectLocked(conn, wallpaper));
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002715 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002716
2717 private void notifyCallbacksLocked(WallpaperData wallpaper) {
2718 final int n = wallpaper.callbacks.beginBroadcast();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002719 for (int i = 0; i < n; i++) {
2720 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002721 wallpaper.callbacks.getBroadcastItem(i).onWallpaperChanged();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002722 } catch (RemoteException e) {
2723
2724 // The RemoteCallbackList will take care of removing
2725 // the dead object for us.
2726 }
2727 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002728 wallpaper.callbacks.finishBroadcast();
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002729
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002730 final Intent intent = new Intent(Intent.ACTION_WALLPAPER_CHANGED);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07002731 mContext.sendBroadcastAsUser(intent, new UserHandle(mCurrentUserId));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002732 }
2733
2734 private void checkPermission(String permission) {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002735 if (PackageManager.PERMISSION_GRANTED!= mContext.checkCallingOrSelfPermission(permission)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002736 throw new SecurityException("Access denied to process: " + Binder.getCallingPid()
2737 + ", must have permission " + permission);
2738 }
2739 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002740
Benjamin Franzf3ece362015-02-11 10:51:10 +00002741 /**
2742 * Certain user types do not support wallpapers (e.g. managed profiles). The check is
2743 * implemented through through the OP_WRITE_WALLPAPER AppOp.
2744 */
2745 public boolean isWallpaperSupported(String callingPackage) {
2746 return mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_WRITE_WALLPAPER, Binder.getCallingUid(),
2747 callingPackage) == AppOpsManager.MODE_ALLOWED;
2748 }
2749
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01002750 @Override
Christopher Tate98d609c2016-05-18 17:31:58 -07002751 public boolean isSetWallpaperAllowed(String callingPackage) {
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01002752 final PackageManager pm = mContext.getPackageManager();
2753 String[] uidPackages = pm.getPackagesForUid(Binder.getCallingUid());
2754 boolean uidMatchPackage = Arrays.asList(uidPackages).contains(callingPackage);
2755 if (!uidMatchPackage) {
2756 return false; // callingPackage was faked.
2757 }
2758
2759 final DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
2760 if (dpm.isDeviceOwnerApp(callingPackage) || dpm.isProfileOwnerApp(callingPackage)) {
2761 return true;
2762 }
2763 final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
2764 return !um.hasUserRestriction(UserManager.DISALLOW_SET_WALLPAPER);
2765 }
2766
Christopher Tated7faf532016-02-25 12:43:38 -08002767 @Override
Christopher Tate61722662016-08-10 16:13:14 -07002768 public boolean isWallpaperBackupEligible(int which, int userId) {
Christopher Tated7faf532016-02-25 12:43:38 -08002769 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
2770 throw new SecurityException("Only the system may call isWallpaperBackupEligible");
2771 }
2772
Christopher Tate61722662016-08-10 16:13:14 -07002773 WallpaperData wallpaper = (which == FLAG_LOCK)
Christopher Tatef7d1b5d2016-08-19 11:21:07 -07002774 ? mLockWallpaperMap.get(userId)
2775 : mWallpaperMap.get(userId);
Christopher Tated7faf532016-02-25 12:43:38 -08002776 return (wallpaper != null) ? wallpaper.allowBackup : false;
2777 }
2778
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002779 private static JournaledFile makeJournaledFile(int userId) {
Amith Yamasani61f57372012-08-31 12:12:28 -07002780 final String base = new File(getWallpaperDir(userId), WALLPAPER_INFO).getAbsolutePath();
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002781 return new JournaledFile(new File(base), new File(base + ".tmp"));
2782 }
2783
Christopher Tatedb27b842016-02-25 14:39:17 -08002784 private void saveSettingsLocked(int userId) {
2785 JournaledFile journal = makeJournaledFile(userId);
2786 FileOutputStream fstream = null;
2787 BufferedOutputStream stream = null;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002788 try {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002789 XmlSerializer out = new FastXmlSerializer();
Christopher Tatedb27b842016-02-25 14:39:17 -08002790 fstream = new FileOutputStream(journal.chooseForWrite(), false);
2791 stream = new BufferedOutputStream(fstream);
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01002792 out.setOutput(stream, StandardCharsets.UTF_8.name());
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002793 out.startDocument(null, true);
2794
Christopher Tatedb27b842016-02-25 14:39:17 -08002795 WallpaperData wallpaper;
Christopher Tate1e1e2e02016-01-25 15:34:36 -08002796
Christopher Tatedb27b842016-02-25 14:39:17 -08002797 wallpaper = mWallpaperMap.get(userId);
2798 if (wallpaper != null) {
2799 writeWallpaperAttributes(out, "wp", wallpaper);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002800 }
Christopher Tatedb27b842016-02-25 14:39:17 -08002801 wallpaper = mLockWallpaperMap.get(userId);
2802 if (wallpaper != null) {
2803 writeWallpaperAttributes(out, "kwp", wallpaper);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002804 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002805
2806 out.endDocument();
Christopher Tatedb27b842016-02-25 14:39:17 -08002807
2808 stream.flush(); // also flushes fstream
2809 FileUtils.sync(fstream);
2810 stream.close(); // also closes fstream
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002811 journal.commit();
2812 } catch (IOException e) {
Christopher Tatead3c2592016-01-20 18:13:17 -08002813 IoUtils.closeQuietly(stream);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002814 journal.rollback();
2815 }
2816 }
2817
Christopher Tatedb27b842016-02-25 14:39:17 -08002818 private void writeWallpaperAttributes(XmlSerializer out, String tag, WallpaperData wallpaper)
2819 throws IllegalArgumentException, IllegalStateException, IOException {
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002820 if (DEBUG) {
Christopher Tatef717b932017-09-11 15:52:54 -07002821 Slog.v(TAG, "writeWallpaperAttributes id=" + wallpaper.wallpaperId);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002822 }
wilsonshiha282bf72018-11-30 12:48:05 +08002823 final DisplayData wpdData = getDisplayDataOrCreate(DEFAULT_DISPLAY);
Christopher Tatedb27b842016-02-25 14:39:17 -08002824 out.startTag(null, tag);
2825 out.attribute(null, "id", Integer.toString(wallpaper.wallpaperId));
wilsonshih81e10a72018-11-15 10:54:21 +08002826 out.attribute(null, "width", Integer.toString(wpdData.mWidth));
2827 out.attribute(null, "height", Integer.toString(wpdData.mHeight));
Christopher Tatedb27b842016-02-25 14:39:17 -08002828
2829 out.attribute(null, "cropLeft", Integer.toString(wallpaper.cropHint.left));
2830 out.attribute(null, "cropTop", Integer.toString(wallpaper.cropHint.top));
2831 out.attribute(null, "cropRight", Integer.toString(wallpaper.cropHint.right));
2832 out.attribute(null, "cropBottom", Integer.toString(wallpaper.cropHint.bottom));
2833
wilsonshih81e10a72018-11-15 10:54:21 +08002834 if (wpdData.mPadding.left != 0) {
2835 out.attribute(null, "paddingLeft", Integer.toString(wpdData.mPadding.left));
Christopher Tatedb27b842016-02-25 14:39:17 -08002836 }
wilsonshih81e10a72018-11-15 10:54:21 +08002837 if (wpdData.mPadding.top != 0) {
2838 out.attribute(null, "paddingTop", Integer.toString(wpdData.mPadding.top));
Christopher Tatedb27b842016-02-25 14:39:17 -08002839 }
wilsonshih81e10a72018-11-15 10:54:21 +08002840 if (wpdData.mPadding.right != 0) {
2841 out.attribute(null, "paddingRight", Integer.toString(wpdData.mPadding.right));
Christopher Tatedb27b842016-02-25 14:39:17 -08002842 }
wilsonshih81e10a72018-11-15 10:54:21 +08002843 if (wpdData.mPadding.bottom != 0) {
2844 out.attribute(null, "paddingBottom", Integer.toString(wpdData.mPadding.bottom));
Christopher Tatedb27b842016-02-25 14:39:17 -08002845 }
2846
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002847 if (wallpaper.primaryColors != null) {
Lucas Dupin84b89d92017-05-09 12:16:19 -07002848 int colorsCount = wallpaper.primaryColors.getMainColors().size();
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002849 out.attribute(null, "colorsCount", Integer.toString(colorsCount));
2850 if (colorsCount > 0) {
2851 for (int i = 0; i < colorsCount; i++) {
Lucas Dupin84b89d92017-05-09 12:16:19 -07002852 final Color wc = wallpaper.primaryColors.getMainColors().get(i);
2853 out.attribute(null, "colorValue"+i, Integer.toString(wc.toArgb()));
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002854 }
2855 }
Lucas Dupin75ec3792017-06-29 14:07:18 -07002856 out.attribute(null, "colorHints",
Lucas Dupin84b89d92017-05-09 12:16:19 -07002857 Integer.toString(wallpaper.primaryColors.getColorHints()));
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002858 }
2859
Christopher Tatedb27b842016-02-25 14:39:17 -08002860 out.attribute(null, "name", wallpaper.name);
2861 if (wallpaper.wallpaperComponent != null
2862 && !wallpaper.wallpaperComponent.equals(mImageWallpaper)) {
2863 out.attribute(null, "component",
2864 wallpaper.wallpaperComponent.flattenToShortString());
2865 }
Christopher Tated7faf532016-02-25 12:43:38 -08002866
2867 if (wallpaper.allowBackup) {
2868 out.attribute(null, "backup", "true");
2869 }
2870
Christopher Tatedb27b842016-02-25 14:39:17 -08002871 out.endTag(null, tag);
2872 }
2873
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002874 private void migrateFromOld() {
Christopher Tate9f224432017-08-01 16:32:49 -07002875 // Pre-N, what existed is the one we're now using as the display crop
2876 File preNWallpaper = new File(getWallpaperDir(0), WALLPAPER_CROP);
2877 // In the very-long-ago, imagery lived with the settings app
2878 File originalWallpaper = new File(WallpaperBackupHelper.WALLPAPER_IMAGE_KEY);
2879 File newWallpaper = new File(getWallpaperDir(0), WALLPAPER);
2880
2881 // Migrations from earlier wallpaper image storage schemas
2882 if (preNWallpaper.exists()) {
2883 if (!newWallpaper.exists()) {
2884 // we've got the 'wallpaper' crop file but not the nominal source image,
2885 // so do the simple "just take everything" straight copy of legacy data
2886 if (DEBUG) {
2887 Slog.i(TAG, "Migrating wallpaper schema");
2888 }
2889 FileUtils.copyFile(preNWallpaper, newWallpaper);
2890 } // else we're in the usual modern case: both source & crop exist
2891 } else if (originalWallpaper.exists()) {
2892 // VERY old schema; make sure things exist and are in the right place
2893 if (DEBUG) {
2894 Slog.i(TAG, "Migrating antique wallpaper schema");
2895 }
2896 File oldInfo = new File(WallpaperBackupHelper.WALLPAPER_INFO_KEY);
2897 if (oldInfo.exists()) {
2898 File newInfo = new File(getWallpaperDir(0), WALLPAPER_INFO);
2899 oldInfo.renameTo(newInfo);
2900 }
2901
2902 FileUtils.copyFile(originalWallpaper, preNWallpaper);
2903 originalWallpaper.renameTo(newWallpaper);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002904 }
2905 }
2906
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002907 private int getAttributeInt(XmlPullParser parser, String name, int defValue) {
2908 String value = parser.getAttributeValue(null, name);
2909 if (value == null) {
2910 return defValue;
2911 }
2912 return Integer.parseInt(value);
2913 }
2914
Xiaohui Chenac531942015-05-13 13:20:52 -07002915 /**
2916 * Sometimes it is expected the wallpaper map may not have a user's data. E.g. This could
2917 * happen during user switch. The async user switch observer may not have received
2918 * the event yet. We use this safe method when we don't care about this ordering and just
2919 * want to update the data. The data is going to be applied when the user switch observer
2920 * is eventually executed.
Christopher Tatef717b932017-09-11 15:52:54 -07002921 *
2922 * Important: this method loads settings to initialize the given user's wallpaper data if
2923 * there is no current in-memory state.
Xiaohui Chenac531942015-05-13 13:20:52 -07002924 */
Christopher Tatebe132e62016-02-10 12:59:49 -08002925 private WallpaperData getWallpaperSafeLocked(int userId, int which) {
2926 // We're setting either just system (work with the system wallpaper),
2927 // both (also work with the system wallpaper), or just the lock
2928 // wallpaper (update against the existing lock wallpaper if any).
2929 // Combined or just-system operations use the 'system' WallpaperData
2930 // for this use; lock-only operations use the dedicated one.
2931 final SparseArray<WallpaperData> whichSet =
Christopher Tateedf7d042016-03-29 18:24:25 -07002932 (which == FLAG_LOCK) ? mLockWallpaperMap : mWallpaperMap;
Christopher Tatebe132e62016-02-10 12:59:49 -08002933 WallpaperData wallpaper = whichSet.get(userId);
Xiaohui Chenac531942015-05-13 13:20:52 -07002934 if (wallpaper == null) {
Christopher Tatebe132e62016-02-10 12:59:49 -08002935 // common case, this is the first lookup post-boot of the system or
2936 // unified lock, so we bring up the saved state lazily now and recheck.
Christopher Tated7faf532016-02-25 12:43:38 -08002937 loadSettingsLocked(userId, false);
Christopher Tatebe132e62016-02-10 12:59:49 -08002938 wallpaper = whichSet.get(userId);
2939 // if it's still null here, this is a lock-only operation and there is not
2940 // yet a lock-only wallpaper set for this user, so we need to establish
2941 // it now.
2942 if (wallpaper == null) {
Christopher Tateedf7d042016-03-29 18:24:25 -07002943 if (which == FLAG_LOCK) {
Christopher Tatebe132e62016-02-10 12:59:49 -08002944 wallpaper = new WallpaperData(userId,
2945 WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP);
2946 mLockWallpaperMap.put(userId, wallpaper);
wilsonshih81e10a72018-11-15 10:54:21 +08002947 ensureSaneWallpaperData(wallpaper, DEFAULT_DISPLAY);
Christopher Tatebe132e62016-02-10 12:59:49 -08002948 } else {
2949 // sanity fallback: we're in bad shape, but establishing a known
2950 // valid system+lock WallpaperData will keep us from dying.
2951 Slog.wtf(TAG, "Didn't find wallpaper in non-lock case!");
2952 wallpaper = new WallpaperData(userId, WALLPAPER, WALLPAPER_CROP);
2953 mWallpaperMap.put(userId, wallpaper);
wilsonshih81e10a72018-11-15 10:54:21 +08002954 ensureSaneWallpaperData(wallpaper, DEFAULT_DISPLAY);
Christopher Tatebe132e62016-02-10 12:59:49 -08002955 }
2956 }
Xiaohui Chenac531942015-05-13 13:20:52 -07002957 }
2958 return wallpaper;
2959 }
2960
Christopher Tated7faf532016-02-25 12:43:38 -08002961 private void loadSettingsLocked(int userId, boolean keepDimensionHints) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002962 JournaledFile journal = makeJournaledFile(userId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002963 FileInputStream stream = null;
2964 File file = journal.chooseForRead();
Christopher Tate9f224432017-08-01 16:32:49 -07002965
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002966 WallpaperData wallpaper = mWallpaperMap.get(userId);
2967 if (wallpaper == null) {
Christopher Tate9f224432017-08-01 16:32:49 -07002968 // Do this once per boot
2969 migrateFromOld();
2970
Christopher Tatebe132e62016-02-10 12:59:49 -08002971 wallpaper = new WallpaperData(userId, WALLPAPER, WALLPAPER_CROP);
Christopher Tated7faf532016-02-25 12:43:38 -08002972 wallpaper.allowBackup = true;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002973 mWallpaperMap.put(userId, wallpaper);
Christopher Tate41297ff2016-03-10 16:46:15 -08002974 if (!wallpaper.cropExists()) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07002975 if (wallpaper.sourceExists()) {
2976 generateCrop(wallpaper);
2977 } else {
2978 Slog.i(TAG, "No static wallpaper imagery; defaults will be shown");
2979 }
Christopher Tate41297ff2016-03-10 16:46:15 -08002980 }
wilsonshiha282bf72018-11-30 12:48:05 +08002981 initializeFallbackWallpaper();
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002982 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002983 boolean success = false;
wilsonshiha282bf72018-11-30 12:48:05 +08002984 final DisplayData wpdData = getDisplayDataOrCreate(DEFAULT_DISPLAY);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002985 try {
2986 stream = new FileInputStream(file);
2987 XmlPullParser parser = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01002988 parser.setInput(stream, StandardCharsets.UTF_8.name());
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002989
2990 int type;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002991 do {
2992 type = parser.next();
2993 if (type == XmlPullParser.START_TAG) {
2994 String tag = parser.getName();
2995 if ("wp".equals(tag)) {
Christopher Tatebe132e62016-02-10 12:59:49 -08002996 // Common to system + lock wallpapers
Christopher Tated7faf532016-02-25 12:43:38 -08002997 parseWallpaperAttributes(parser, wallpaper, keepDimensionHints);
Christopher Tatead3c2592016-01-20 18:13:17 -08002998
Christopher Tatebe132e62016-02-10 12:59:49 -08002999 // A system wallpaper might also be a live wallpaper
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07003000 String comp = parser.getAttributeValue(null, "component");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003001 wallpaper.nextWallpaperComponent = comp != null
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07003002 ? ComponentName.unflattenFromString(comp)
3003 : null;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003004 if (wallpaper.nextWallpaperComponent == null
3005 || "android".equals(wallpaper.nextWallpaperComponent
3006 .getPackageName())) {
Justin Koh29c30162014-09-05 17:10:10 -07003007 wallpaper.nextWallpaperComponent = mImageWallpaper;
Dianne Hackborn9ea31632011-08-05 14:43:50 -07003008 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01003009
Mike Clerona428b2c2009-11-15 22:53:08 -08003010 if (DEBUG) {
wilsonshih81e10a72018-11-15 10:54:21 +08003011 Slog.v(TAG, "mWidth:" + wpdData.mWidth);
3012 Slog.v(TAG, "mHeight:" + wpdData.mHeight);
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003013 Slog.v(TAG, "cropRect:" + wallpaper.cropHint);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07003014 Slog.v(TAG, "primaryColors:" + wallpaper.primaryColors);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003015 Slog.v(TAG, "mName:" + wallpaper.name);
3016 Slog.v(TAG, "mNextWallpaperComponent:"
3017 + wallpaper.nextWallpaperComponent);
Mike Clerona428b2c2009-11-15 22:53:08 -08003018 }
Christopher Tatebe132e62016-02-10 12:59:49 -08003019 } else if ("kwp".equals(tag)) {
3020 // keyguard-specific wallpaper for this user
3021 WallpaperData lockWallpaper = mLockWallpaperMap.get(userId);
3022 if (lockWallpaper == null) {
3023 lockWallpaper = new WallpaperData(userId,
3024 WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP);
3025 mLockWallpaperMap.put(userId, lockWallpaper);
3026 }
Christopher Tated7faf532016-02-25 12:43:38 -08003027 parseWallpaperAttributes(parser, lockWallpaper, false);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003028 }
3029 }
3030 } while (type != XmlPullParser.END_DOCUMENT);
3031 success = true;
Dianne Hackborn13579ed2012-11-28 18:05:36 -08003032 } catch (FileNotFoundException e) {
3033 Slog.w(TAG, "no current wallpaper -- first boot?");
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003034 } catch (NullPointerException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003035 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003036 } catch (NumberFormatException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003037 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003038 } catch (XmlPullParserException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003039 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003040 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003041 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003042 } catch (IndexOutOfBoundsException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003043 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003044 }
Christopher Tatead3c2592016-01-20 18:13:17 -08003045 IoUtils.closeQuietly(stream);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003046
3047 if (!success) {
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003048 wallpaper.cropHint.set(0, 0, 0, 0);
wilsonshih81e10a72018-11-15 10:54:21 +08003049 wpdData.mPadding.set(0, 0, 0, 0);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003050 wallpaper.name = "";
Adrian Roosc28e3a92016-04-14 10:47:52 -07003051
3052 mLockWallpaperMap.remove(userId);
Christopher Tatead3c2592016-01-20 18:13:17 -08003053 } else {
3054 if (wallpaper.wallpaperId <= 0) {
3055 wallpaper.wallpaperId = makeWallpaperIdLocked();
3056 if (DEBUG) {
3057 Slog.w(TAG, "Didn't set wallpaper id in loadSettingsLocked(" + userId
3058 + "); now " + wallpaper.wallpaperId);
3059 }
3060 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003061 }
Dianne Hackborn44bc17c2011-04-20 18:18:51 -07003062
wilsonshihd9173df2018-11-29 11:52:15 +08003063 ensureSaneWallpaperDisplaySize(wpdData, DEFAULT_DISPLAY);
wilsonshih81e10a72018-11-15 10:54:21 +08003064 ensureSaneWallpaperData(wallpaper, DEFAULT_DISPLAY);
Adrian Roosc28e3a92016-04-14 10:47:52 -07003065 WallpaperData lockWallpaper = mLockWallpaperMap.get(userId);
3066 if (lockWallpaper != null) {
wilsonshih81e10a72018-11-15 10:54:21 +08003067 ensureSaneWallpaperData(lockWallpaper, DEFAULT_DISPLAY);
Adrian Roosc28e3a92016-04-14 10:47:52 -07003068 }
3069 }
3070
wilsonshiha282bf72018-11-30 12:48:05 +08003071 private void initializeFallbackWallpaper() {
3072 if (mFallbackWallpaper == null) {
3073 if (DEBUG) Slog.d(TAG, "Initialize fallback wallpaper");
3074 mFallbackWallpaper = new WallpaperData(
3075 UserHandle.USER_SYSTEM, WALLPAPER, WALLPAPER_CROP);
3076 mFallbackWallpaper.allowBackup = false;
3077 mFallbackWallpaper.wallpaperId = makeWallpaperIdLocked();
3078 bindWallpaperComponentLocked(mImageWallpaper, true, false, mFallbackWallpaper, null);
3079 }
3080 }
3081
wilsonshih81e10a72018-11-15 10:54:21 +08003082 private void ensureSaneWallpaperData(WallpaperData wallpaper, int displayId) {
wilsonshiha282bf72018-11-30 12:48:05 +08003083 final DisplayData size = getDisplayDataOrCreate(displayId);
wilsonshih81e10a72018-11-15 10:54:21 +08003084
3085 if (displayId == DEFAULT_DISPLAY) {
3086 // crop, if not previously specified
3087 if (wallpaper.cropHint.width() <= 0
3088 || wallpaper.cropHint.height() <= 0) {
3089 wallpaper.cropHint.set(0, 0, size.mWidth, size.mHeight);
3090 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003091 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003092 }
3093
Christopher Tated7faf532016-02-25 12:43:38 -08003094 private void parseWallpaperAttributes(XmlPullParser parser, WallpaperData wallpaper,
3095 boolean keepDimensionHints) {
Christopher Tatebe132e62016-02-10 12:59:49 -08003096 final String idString = parser.getAttributeValue(null, "id");
3097 if (idString != null) {
3098 final int id = wallpaper.wallpaperId = Integer.parseInt(idString);
3099 if (id > mWallpaperId) {
3100 mWallpaperId = id;
3101 }
3102 } else {
3103 wallpaper.wallpaperId = makeWallpaperIdLocked();
3104 }
3105
wilsonshiha282bf72018-11-30 12:48:05 +08003106 final DisplayData wpData = getDisplayDataOrCreate(DEFAULT_DISPLAY);
wilsonshih81e10a72018-11-15 10:54:21 +08003107
Christopher Tated7faf532016-02-25 12:43:38 -08003108 if (!keepDimensionHints) {
wilsonshih81e10a72018-11-15 10:54:21 +08003109 wpData.mWidth = Integer.parseInt(parser.getAttributeValue(null, "width"));
3110 wpData.mHeight = Integer.parseInt(parser.getAttributeValue(null, "height"));
Christopher Tated7faf532016-02-25 12:43:38 -08003111 }
Christopher Tatebe132e62016-02-10 12:59:49 -08003112 wallpaper.cropHint.left = getAttributeInt(parser, "cropLeft", 0);
3113 wallpaper.cropHint.top = getAttributeInt(parser, "cropTop", 0);
3114 wallpaper.cropHint.right = getAttributeInt(parser, "cropRight", 0);
3115 wallpaper.cropHint.bottom = getAttributeInt(parser, "cropBottom", 0);
wilsonshih81e10a72018-11-15 10:54:21 +08003116 wpData.mPadding.left = getAttributeInt(parser, "paddingLeft", 0);
3117 wpData.mPadding.top = getAttributeInt(parser, "paddingTop", 0);
3118 wpData.mPadding.right = getAttributeInt(parser, "paddingRight", 0);
3119 wpData.mPadding.bottom = getAttributeInt(parser, "paddingBottom", 0);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07003120 int colorsCount = getAttributeInt(parser, "colorsCount", 0);
3121 if (colorsCount > 0) {
Lucas Dupin84b89d92017-05-09 12:16:19 -07003122 Color primary = null, secondary = null, tertiary = null;
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07003123 for (int i = 0; i < colorsCount; i++) {
Lucas Dupin84b89d92017-05-09 12:16:19 -07003124 Color color = Color.valueOf(getAttributeInt(parser, "colorValue" + i, 0));
3125 if (i == 0) {
3126 primary = color;
3127 } else if (i == 1) {
3128 secondary = color;
3129 } else if (i == 2) {
3130 tertiary = color;
3131 } else {
3132 break;
3133 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07003134 }
Lucas Dupin84b89d92017-05-09 12:16:19 -07003135 int colorHints = getAttributeInt(parser, "colorHints", 0);
3136 wallpaper.primaryColors = new WallpaperColors(primary, secondary, tertiary, colorHints);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07003137 }
Christopher Tatebe132e62016-02-10 12:59:49 -08003138 wallpaper.name = parser.getAttributeValue(null, "name");
Christopher Tated7faf532016-02-25 12:43:38 -08003139 wallpaper.allowBackup = "true".equals(parser.getAttributeValue(null, "backup"));
Christopher Tatebe132e62016-02-10 12:59:49 -08003140 }
3141
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07003142 // Called by SystemBackupAgent after files are restored to disk.
Amith Yamasani09e9cdc2013-11-06 14:54:50 -08003143 public void settingsRestored() {
3144 // Verify caller is the system
3145 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
3146 throw new RuntimeException("settingsRestored() can only be called from the system process");
3147 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003148 // TODO: If necessary, make it work for secondary users as well. This currently assumes
3149 // restores only to the primary user
Joe Onorato8a9b2202010-02-26 18:56:32 -08003150 if (DEBUG) Slog.v(TAG, "settingsRestored");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003151 WallpaperData wallpaper = null;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003152 boolean success = false;
3153 synchronized (mLock) {
Christopher Tated7faf532016-02-25 12:43:38 -08003154 loadSettingsLocked(UserHandle.USER_SYSTEM, false);
Christopher Tatedb27b842016-02-25 14:39:17 -08003155 wallpaper = mWallpaperMap.get(UserHandle.USER_SYSTEM);
Christopher Tatead3c2592016-01-20 18:13:17 -08003156 wallpaper.wallpaperId = makeWallpaperIdLocked(); // always bump id at restore
Christopher Tated7faf532016-02-25 12:43:38 -08003157 wallpaper.allowBackup = true; // by definition if it was restored
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003158 if (wallpaper.nextWallpaperComponent != null
Justin Koh29c30162014-09-05 17:10:10 -07003159 && !wallpaper.nextWallpaperComponent.equals(mImageWallpaper)) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003160 if (!bindWallpaperComponentLocked(wallpaper.nextWallpaperComponent, false, false,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07003161 wallpaper, null)) {
Christopher Tatee3ab4d02009-12-16 14:03:31 -08003162 // No such live wallpaper or other failure; fall back to the default
3163 // live wallpaper (since the profile being restored indicated that the
3164 // user had selected a live rather than static one).
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07003165 bindWallpaperComponentLocked(null, false, false, wallpaper, null);
Christopher Tatee3ab4d02009-12-16 14:03:31 -08003166 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003167 success = true;
3168 } else {
Mike Clerona428b2c2009-11-15 22:53:08 -08003169 // If there's a wallpaper name, we use that. If that can't be loaded, then we
3170 // use the default.
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003171 if ("".equals(wallpaper.name)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003172 if (DEBUG) Slog.v(TAG, "settingsRestored: name is empty");
Mike Clerona428b2c2009-11-15 22:53:08 -08003173 success = true;
3174 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003175 if (DEBUG) Slog.v(TAG, "settingsRestored: attempting to restore named resource");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003176 success = restoreNamedResourceLocked(wallpaper);
Mike Clerona428b2c2009-11-15 22:53:08 -08003177 }
Christopher Tatead3c2592016-01-20 18:13:17 -08003178 if (DEBUG) Slog.v(TAG, "settingsRestored: success=" + success
3179 + " id=" + wallpaper.wallpaperId);
Mike Clerona428b2c2009-11-15 22:53:08 -08003180 if (success) {
wilsonshih81e10a72018-11-15 10:54:21 +08003181 generateCrop(wallpaper); // based on the new image + metadata
Christopher Tate41297ff2016-03-10 16:46:15 -08003182 bindWallpaperComponentLocked(wallpaper.nextWallpaperComponent, true, false,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07003183 wallpaper, null);
Mike Clerona428b2c2009-11-15 22:53:08 -08003184 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003185 }
3186 }
3187
3188 if (!success) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003189 Slog.e(TAG, "Failed to restore wallpaper: '" + wallpaper.name + "'");
3190 wallpaper.name = "";
Christopher Tatedb27b842016-02-25 14:39:17 -08003191 getWallpaperDir(UserHandle.USER_SYSTEM).delete();
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003192 }
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07003193
3194 synchronized (mLock) {
Christopher Tatedb27b842016-02-25 14:39:17 -08003195 saveSettingsLocked(UserHandle.USER_SYSTEM);
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07003196 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003197 }
3198
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003199 // Restore the named resource bitmap to both source + crop files
wilsonshiha282bf72018-11-30 12:48:05 +08003200 private boolean restoreNamedResourceLocked(WallpaperData wallpaper) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003201 if (wallpaper.name.length() > 4 && "res:".equals(wallpaper.name.substring(0, 4))) {
3202 String resName = wallpaper.name.substring(4);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003203
3204 String pkg = null;
3205 int colon = resName.indexOf(':');
3206 if (colon > 0) {
3207 pkg = resName.substring(0, colon);
3208 }
3209
3210 String ident = null;
3211 int slash = resName.lastIndexOf('/');
3212 if (slash > 0) {
3213 ident = resName.substring(slash+1);
3214 }
3215
3216 String type = null;
3217 if (colon > 0 && slash > 0 && (slash-colon) > 1) {
3218 type = resName.substring(colon+1, slash);
3219 }
3220
3221 if (pkg != null && ident != null && type != null) {
3222 int resId = -1;
3223 InputStream res = null;
3224 FileOutputStream fos = null;
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003225 FileOutputStream cos = null;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003226 try {
3227 Context c = mContext.createPackageContext(pkg, Context.CONTEXT_RESTRICTED);
3228 Resources r = c.getResources();
3229 resId = r.getIdentifier(resName, null, null);
3230 if (resId == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003231 Slog.e(TAG, "couldn't resolve identifier pkg=" + pkg + " type=" + type
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003232 + " ident=" + ident);
3233 return false;
3234 }
3235
3236 res = r.openRawResource(resId);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003237 if (wallpaper.wallpaperFile.exists()) {
3238 wallpaper.wallpaperFile.delete();
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003239 wallpaper.cropFile.delete();
Dianne Hackborn1afd1c92010-03-18 22:47:17 -07003240 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003241 fos = new FileOutputStream(wallpaper.wallpaperFile);
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003242 cos = new FileOutputStream(wallpaper.cropFile);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003243
3244 byte[] buffer = new byte[32768];
3245 int amt;
3246 while ((amt=res.read(buffer)) > 0) {
3247 fos.write(buffer, 0, amt);
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003248 cos.write(buffer, 0, amt);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003249 }
3250 // mWallpaperObserver will notice the close and send the change broadcast
3251
Joe Onorato8a9b2202010-02-26 18:56:32 -08003252 Slog.v(TAG, "Restored wallpaper: " + resName);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003253 return true;
3254 } catch (NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003255 Slog.e(TAG, "Package name " + pkg + " not found");
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003256 } catch (Resources.NotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003257 Slog.e(TAG, "Resource not found: " + resId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003258 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003259 Slog.e(TAG, "IOException while restoring wallpaper ", e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003260 } finally {
Christopher Tatead3c2592016-01-20 18:13:17 -08003261 IoUtils.closeQuietly(res);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003262 if (fos != null) {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07003263 FileUtils.sync(fos);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003264 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003265 if (cos != null) {
3266 FileUtils.sync(cos);
3267 }
3268 IoUtils.closeQuietly(fos);
3269 IoUtils.closeQuietly(cos);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003270 }
3271 }
3272 }
3273 return false;
3274 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003275
Dianne Hackborneb034652009-09-07 00:49:58 -07003276 @Override
3277 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06003278 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Dianne Hackborneb034652009-09-07 00:49:58 -07003279
3280 synchronized (mLock) {
Adrian Roosc28e3a92016-04-14 10:47:52 -07003281 pw.println("System wallpaper state:");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003282 for (int i = 0; i < mWallpaperMap.size(); i++) {
3283 WallpaperData wallpaper = mWallpaperMap.valueAt(i);
Christopher Tatead3c2592016-01-20 18:13:17 -08003284 pw.print(" User "); pw.print(wallpaper.userId);
wilsonshiha282bf72018-11-30 12:48:05 +08003285 pw.print(": id="); pw.println(wallpaper.wallpaperId);
3286 pw.println(" Display state:");
3287 forEachDisplayData(wpSize -> {
wilsonshih81e10a72018-11-15 10:54:21 +08003288 pw.print(" displayId=");
3289 pw.println(wpSize.mDisplayId);
3290 pw.print(" mWidth=");
3291 pw.print(wpSize.mWidth);
3292 pw.print(" mHeight=");
3293 pw.println(wpSize.mHeight);
3294 pw.print(" mPadding="); pw.println(wpSize.mPadding);
3295 });
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003296 pw.print(" mCropHint="); pw.println(wallpaper.cropHint);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07003297 pw.print(" mName="); pw.println(wallpaper.name);
Bryan Mawhinney0fa54f42017-07-06 17:09:37 +01003298 pw.print(" mAllowBackup="); pw.println(wallpaper.allowBackup);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07003299 pw.print(" mWallpaperComponent="); pw.println(wallpaper.wallpaperComponent);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003300 if (wallpaper.connection != null) {
3301 WallpaperConnection conn = wallpaper.connection;
3302 pw.print(" Wallpaper connection ");
3303 pw.print(conn);
3304 pw.println(":");
3305 if (conn.mInfo != null) {
3306 pw.print(" mInfo.component=");
3307 pw.println(conn.mInfo.getComponent());
3308 }
wilsonshihde93f492018-11-01 21:23:40 +08003309 conn.forEachDisplayConnector(connector -> {
wilsonshiha282bf72018-11-30 12:48:05 +08003310 pw.print(" mDisplayId=");
wilsonshihde93f492018-11-01 21:23:40 +08003311 pw.println(connector.mDisplayId);
wilsonshiha282bf72018-11-30 12:48:05 +08003312 pw.print(" mToken=");
wilsonshihde93f492018-11-01 21:23:40 +08003313 pw.println(connector.mToken);
wilsonshiha282bf72018-11-30 12:48:05 +08003314 pw.print(" mEngine=");
wilsonshihde93f492018-11-01 21:23:40 +08003315 pw.println(connector.mEngine);
3316 });
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003317 pw.print(" mService=");
3318 pw.println(conn.mService);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003319 pw.print(" mLastDiedTime=");
3320 pw.println(wallpaper.lastDiedTime - SystemClock.uptimeMillis());
3321 }
Dianne Hackborneb034652009-09-07 00:49:58 -07003322 }
Adrian Roosc28e3a92016-04-14 10:47:52 -07003323 pw.println("Lock wallpaper state:");
3324 for (int i = 0; i < mLockWallpaperMap.size(); i++) {
3325 WallpaperData wallpaper = mLockWallpaperMap.valueAt(i);
3326 pw.print(" User "); pw.print(wallpaper.userId);
wilsonshih81e10a72018-11-15 10:54:21 +08003327 pw.print(": id="); pw.println(wallpaper.wallpaperId);
Adrian Roosc28e3a92016-04-14 10:47:52 -07003328 pw.print(" mCropHint="); pw.println(wallpaper.cropHint);
Adrian Roosc28e3a92016-04-14 10:47:52 -07003329 pw.print(" mName="); pw.println(wallpaper.name);
Bryan Mawhinney0fa54f42017-07-06 17:09:37 +01003330 pw.print(" mAllowBackup="); pw.println(wallpaper.allowBackup);
Adrian Roosc28e3a92016-04-14 10:47:52 -07003331 }
wilsonshiha282bf72018-11-30 12:48:05 +08003332 pw.println("Fallback wallpaper state:");
3333 pw.print(" User "); pw.print(mFallbackWallpaper.userId);
3334 pw.print(": id="); pw.println(mFallbackWallpaper.wallpaperId);
3335 pw.print(" mCropHint="); pw.println(mFallbackWallpaper.cropHint);
3336 pw.print(" mName="); pw.println(mFallbackWallpaper.name);
3337 pw.print(" mAllowBackup="); pw.println(mFallbackWallpaper.allowBackup);
3338 if (mFallbackWallpaper.connection != null) {
3339 WallpaperConnection conn = mFallbackWallpaper.connection;
3340 pw.print(" Fallback Wallpaper connection ");
3341 pw.print(conn);
3342 pw.println(":");
3343 if (conn.mInfo != null) {
3344 pw.print(" mInfo.component=");
3345 pw.println(conn.mInfo.getComponent());
3346 }
3347 conn.forEachDisplayConnector(connector -> {
3348 pw.print(" mDisplayId=");
3349 pw.println(connector.mDisplayId);
3350 pw.print(" mToken=");
3351 pw.println(connector.mToken);
3352 pw.print(" mEngine=");
3353 pw.println(connector.mEngine);
3354 });
3355 pw.print(" mService=");
3356 pw.println(conn.mService);
3357 pw.print(" mLastDiedTime=");
3358 pw.println(mFallbackWallpaper.lastDiedTime - SystemClock.uptimeMillis());
3359 }
Dianne Hackborneb034652009-09-07 00:49:58 -07003360 }
3361 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003362}