blob: e53fde96e844ef759dd4927df8b04cd7204029f8 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Amith Yamasani09e9cdc2013-11-06 14:54:50 -080017package com.android.server.wallpaper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080018
Christopher Tateedf7d042016-03-29 18:24:25 -070019import static android.app.WallpaperManager.FLAG_LOCK;
Jeff Sharkey1cab76a2016-04-12 18:23:31 -060020import static android.app.WallpaperManager.FLAG_SYSTEM;
wilsonshihde93f492018-11-01 21:23:40 +080021import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AUTO;
Jeff Sharkey1cab76a2016-04-12 18:23:31 -060022import static android.os.ParcelFileDescriptor.MODE_CREATE;
23import static android.os.ParcelFileDescriptor.MODE_READ_ONLY;
24import static android.os.ParcelFileDescriptor.MODE_READ_WRITE;
25import static android.os.ParcelFileDescriptor.MODE_TRUNCATE;
Wale Ogunwaleac2561e2016-11-01 15:43:46 -070026import static android.view.Display.DEFAULT_DISPLAY;
27import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
Christopher Tate111bd4a2009-06-24 17:29:38 -070028
Lucas Dupin50ba9912017-07-14 11:55:05 -070029import android.annotation.NonNull;
Christopher Tatee409f0e2016-03-21 14:53:15 -070030import android.app.ActivityManager;
Amith Yamasani4e2820c2012-08-28 22:17:23 -070031import android.app.AppGlobals;
Benjamin Franzf3ece362015-02-11 10:51:10 +000032import android.app.AppOpsManager;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070033import android.app.IWallpaperManager;
34import android.app.IWallpaperManagerCallback;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070035import android.app.PendingIntent;
Sudheer Shanka2c4522c2016-08-27 20:53:28 -070036import android.app.UserSwitchObserver;
Lucas Dupin75ec3792017-06-29 14:07:18 -070037import android.app.WallpaperColors;
Dianne Hackborneb034652009-09-07 00:49:58 -070038import android.app.WallpaperInfo;
Jeff Sharkey28f08772014-04-16 09:41:58 -070039import android.app.WallpaperManager;
Oleksandr Peletskyif2519812016-01-26 20:16:06 +010040import android.app.admin.DevicePolicyManager;
Amith Yamasani37ce3a82012-02-06 12:04:42 -080041import android.app.backup.WallpaperBackupHelper;
Amith Yamasani13593602012-03-22 16:16:17 -070042import android.content.BroadcastReceiver;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070043import android.content.ComponentName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044import android.content.Context;
45import android.content.Intent;
Amith Yamasani13593602012-03-22 16:16:17 -070046import android.content.IntentFilter;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070047import android.content.ServiceConnection;
Amith Yamasani4e2820c2012-08-28 22:17:23 -070048import android.content.pm.IPackageManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049import android.content.pm.PackageManager;
Jeff Sharkey1cab76a2016-04-12 18:23:31 -060050import android.content.pm.PackageManager.NameNotFoundException;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070051import android.content.pm.ResolveInfo;
52import android.content.pm.ServiceInfo;
Amith Yamasani6474c4c2012-10-04 14:55:42 -070053import android.content.pm.UserInfo;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070054import android.content.res.Resources;
Christopher Tate1e1e2e02016-01-25 15:34:36 -080055import android.graphics.Bitmap;
56import android.graphics.BitmapFactory;
57import android.graphics.BitmapRegionDecoder;
Lucas Dupinea1fb1e2017-04-05 17:39:44 -070058import android.graphics.Color;
Dianne Hackborn067e5f62014-09-07 23:14:30 -070059import android.graphics.Rect;
wilsonshihde93f492018-11-01 21:23:40 +080060import android.hardware.display.DisplayManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061import android.os.Binder;
Dianne Hackborn284ac932009-08-28 10:34:25 -070062import android.os.Bundle;
wilsonshiha282bf72018-11-30 12:48:05 +080063import android.os.Debug;
Amith Yamasani13593602012-03-22 16:16:17 -070064import android.os.Environment;
Jeff Sharkey1cab76a2016-04-12 18:23:31 -060065import android.os.FileObserver;
Dianne Hackborn8bdf5932010-10-15 12:54:40 -070066import android.os.FileUtils;
Christopher Tatec349e59f2017-05-05 17:37:43 -070067import android.os.Handler;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070068import android.os.IBinder;
Lucas Dupin50ba9912017-07-14 11:55:05 -070069import android.os.IInterface;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -070070import android.os.IRemoteCallback;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071import android.os.ParcelFileDescriptor;
Lucas Dupin75ec3792017-06-29 14:07:18 -070072import android.os.Process;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073import android.os.RemoteCallbackList;
Jeff Sharkey1cab76a2016-04-12 18:23:31 -060074import android.os.RemoteException;
rpcraig554cb0c2012-07-05 06:41:43 -040075import android.os.SELinux;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070076import android.os.ServiceManager;
Dianne Hackborn0cd48872009-08-13 18:51:59 -070077import android.os.SystemClock;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070078import android.os.UserHandle;
Amith Yamasani6474c4c2012-10-04 14:55:42 -070079import android.os.UserManager;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070080import android.service.wallpaper.IWallpaperConnection;
81import android.service.wallpaper.IWallpaperEngine;
82import android.service.wallpaper.IWallpaperService;
83import android.service.wallpaper.WallpaperService;
Christopher Tate8347b632016-04-29 18:59:18 -070084import android.system.ErrnoException;
85import android.system.Os;
Filip Gruszczynski5dcc3ac2014-10-13 15:51:39 -070086import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -080087import android.util.Slog;
Amith Yamasani37ce3a82012-02-06 12:04:42 -080088import android.util.SparseArray;
wilsonshiha282bf72018-11-30 12:48:05 +080089import android.util.SparseBooleanArray;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070090import android.util.Xml;
Dianne Hackborn44bc17c2011-04-20 18:18:51 -070091import android.view.Display;
Valentin Iftime3047bb12018-12-28 17:02:19 +010092import android.view.DisplayInfo;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070093import android.view.IWindowManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094
Jeff Sharkey1cab76a2016-04-12 18:23:31 -060095import com.android.internal.R;
96import com.android.internal.content.PackageMonitor;
Christopher Tate190e8532016-07-11 11:35:34 -070097import com.android.internal.os.BackgroundThread;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060098import com.android.internal.util.DumpUtils;
Jeff Sharkey1cab76a2016-04-12 18:23:31 -060099import com.android.internal.util.FastXmlSerializer;
100import com.android.internal.util.JournaledFile;
101import com.android.server.EventLogTags;
Adrian Roosc3f915e2016-09-06 11:40:53 -0700102import com.android.server.FgThread;
Andrii Kuliandd989612019-02-21 12:13:28 -0800103import com.android.server.LocalServices;
Jeff Sharkey1cab76a2016-04-12 18:23:31 -0600104import com.android.server.SystemService;
Andrii Kuliandd989612019-02-21 12:13:28 -0800105import com.android.server.wm.WindowManagerInternal;
Jeff Sharkey1cab76a2016-04-12 18:23:31 -0600106
107import libcore.io.IoUtils;
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700108
109import org.xmlpull.v1.XmlPullParser;
110import org.xmlpull.v1.XmlPullParserException;
111import org.xmlpull.v1.XmlSerializer;
112
Jeff Sharkey1cab76a2016-04-12 18:23:31 -0600113import java.io.BufferedOutputStream;
114import java.io.File;
115import java.io.FileDescriptor;
116import java.io.FileInputStream;
117import java.io.FileNotFoundException;
118import java.io.FileOutputStream;
119import java.io.IOException;
120import java.io.InputStream;
121import java.io.PrintWriter;
122import java.nio.charset.StandardCharsets;
Lucas Dupinfb3ab2a2017-08-08 14:17:30 -0400123import java.util.ArrayList;
Jeff Sharkey1cab76a2016-04-12 18:23:31 -0600124import java.util.Arrays;
125import java.util.List;
Christopher Tate2a6c55f2017-03-31 12:28:30 -0700126import java.util.Objects;
wilsonshihde93f492018-11-01 21:23:40 +0800127import java.util.function.Consumer;
wilsonshiha282bf72018-11-30 12:48:05 +0800128import java.util.function.Predicate;
Christopher Tatead3c2592016-01-20 18:13:17 -0800129
Daichi Hirono4bbf8522017-12-06 10:34:18 +0900130public class WallpaperManagerService extends IWallpaperManager.Stub
131 implements IWallpaperManagerService {
wilsonshiha282bf72018-11-30 12:48:05 +0800132 private static final String TAG = "WallpaperManagerService";
133 private static final boolean DEBUG = false;
134 private static final boolean DEBUG_LIVE = true;
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700135
Jeff Sharkey1cab76a2016-04-12 18:23:31 -0600136 public static class Lifecycle extends SystemService {
Daichi Hirono4bbf8522017-12-06 10:34:18 +0900137 private IWallpaperManagerService mService;
Jeff Sharkey1cab76a2016-04-12 18:23:31 -0600138
139 public Lifecycle(Context context) {
140 super(context);
141 }
142
143 @Override
144 public void onStart() {
Daichi Hirono4bbf8522017-12-06 10:34:18 +0900145 try {
146 final Class<? extends IWallpaperManagerService> klass =
147 (Class<? extends IWallpaperManagerService>)Class.forName(
148 getContext().getResources().getString(
149 R.string.config_wallpaperManagerServiceName));
150 mService = klass.getConstructor(Context.class).newInstance(getContext());
151 publishBinderService(Context.WALLPAPER_SERVICE, mService);
152 } catch (Exception exp) {
153 Slog.wtf(TAG, "Failed to instantiate WallpaperManagerService", exp);
154 }
Jeff Sharkey1cab76a2016-04-12 18:23:31 -0600155 }
156
157 @Override
158 public void onBootPhase(int phase) {
Daichi Hirono4bbf8522017-12-06 10:34:18 +0900159 if (mService != null) {
160 mService.onBootPhase(phase);
Jeff Sharkey1cab76a2016-04-12 18:23:31 -0600161 }
162 }
163
164 @Override
165 public void onUnlockUser(int userHandle) {
Daichi Hirono4bbf8522017-12-06 10:34:18 +0900166 if (mService != null) {
167 mService.onUnlockUser(userHandle);
168 }
Jeff Sharkey1cab76a2016-04-12 18:23:31 -0600169 }
170 }
171
wilsonshiha282bf72018-11-30 12:48:05 +0800172 private final Object mLock = new Object();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800173
Dianne Hackborn0cd48872009-08-13 18:51:59 -0700174 /**
175 * Minimum time between crashes of a wallpaper service for us to consider
176 * restarting it vs. just reverting to the static wallpaper.
177 */
wilsonshiha282bf72018-11-30 12:48:05 +0800178 private static final long MIN_WALLPAPER_CRASH_TIME = 10000;
179 private static final int MAX_WALLPAPER_COMPONENT_LOG_LENGTH = 128;
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800180 static final String WALLPAPER = "wallpaper_orig";
181 static final String WALLPAPER_CROP = "wallpaper";
Christopher Tatebe132e62016-02-10 12:59:49 -0800182 static final String WALLPAPER_LOCK_ORIG = "wallpaper_lock_orig";
183 static final String WALLPAPER_LOCK_CROP = "wallpaper_lock";
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800184 static final String WALLPAPER_INFO = "wallpaper_info.xml";
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -0700185
Christopher Tatebe132e62016-02-10 12:59:49 -0800186 // All the various per-user state files we need to be aware of
wilsonshiha282bf72018-11-30 12:48:05 +0800187 private static final String[] sPerUserFiles = new String[] {
Christopher Tatebe132e62016-02-10 12:59:49 -0800188 WALLPAPER, WALLPAPER_CROP,
189 WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP,
190 WALLPAPER_INFO
191 };
192
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -0700193 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194 * Observes the wallpaper for changes and notifies all IWallpaperServiceCallbacks
195 * that the wallpaper has changed. The CREATE is triggered when there is no
196 * wallpaper set and is created for the first time. The CLOSE_WRITE is triggered
Christopher Tate190e8532016-07-11 11:35:34 -0700197 * every time the wallpaper is changed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800198 */
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800199 private class WallpaperObserver extends FileObserver {
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700200
Christopher Tatebe132e62016-02-10 12:59:49 -0800201 final int mUserId;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800202 final WallpaperData mWallpaper;
203 final File mWallpaperDir;
204 final File mWallpaperFile;
Christopher Tatebe132e62016-02-10 12:59:49 -0800205 final File mWallpaperLockFile;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800206
207 public WallpaperObserver(WallpaperData wallpaper) {
208 super(getWallpaperDir(wallpaper.userId).getAbsolutePath(),
Christopher Tateda058e22014-10-08 14:51:09 -0700209 CLOSE_WRITE | MOVED_TO | DELETE | DELETE_SELF);
Christopher Tatebe132e62016-02-10 12:59:49 -0800210 mUserId = wallpaper.userId;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800211 mWallpaperDir = getWallpaperDir(wallpaper.userId);
212 mWallpaper = wallpaper;
213 mWallpaperFile = new File(mWallpaperDir, WALLPAPER);
Christopher Tatebe132e62016-02-10 12:59:49 -0800214 mWallpaperLockFile = new File(mWallpaperDir, WALLPAPER_LOCK_ORIG);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800215 }
216
Christopher Tatebe132e62016-02-10 12:59:49 -0800217 private WallpaperData dataForEvent(boolean sysChanged, boolean lockChanged) {
218 WallpaperData wallpaper = null;
219 synchronized (mLock) {
220 if (lockChanged) {
221 wallpaper = mLockWallpaperMap.get(mUserId);
222 }
223 if (wallpaper == null) {
224 // no lock-specific wallpaper exists, or sys case, handled together
225 wallpaper = mWallpaperMap.get(mUserId);
226 }
227 }
228 return (wallpaper != null) ? wallpaper : mWallpaper;
229 }
230
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800231 @Override
232 public void onEvent(int event, String path) {
233 if (path == null) {
234 return;
235 }
Christopher Tated7faf532016-02-25 12:43:38 -0800236 final boolean moved = (event == MOVED_TO);
237 final boolean written = (event == CLOSE_WRITE || moved);
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800238 final File changedFile = new File(mWallpaperDir, path);
239
Christopher Tatebe132e62016-02-10 12:59:49 -0800240 // System and system+lock changes happen on the system wallpaper input file;
241 // lock-only changes happen on the dedicated lock wallpaper input file
242 final boolean sysWallpaperChanged = (mWallpaperFile.equals(changedFile));
243 final boolean lockWallpaperChanged = (mWallpaperLockFile.equals(changedFile));
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700244 int notifyColorsWhich = 0;
Christopher Tatebe132e62016-02-10 12:59:49 -0800245 WallpaperData wallpaper = dataForEvent(sysWallpaperChanged, lockWallpaperChanged);
246
247 if (DEBUG) {
248 Slog.v(TAG, "Wallpaper file change: evt=" + event
249 + " path=" + path
250 + " sys=" + sysWallpaperChanged
251 + " lock=" + lockWallpaperChanged
252 + " imagePending=" + wallpaper.imageWallpaperPending
253 + " whichPending=0x" + Integer.toHexString(wallpaper.whichPending)
254 + " written=" + written);
255 }
Christopher Tate8347b632016-04-29 18:59:18 -0700256
257 if (moved && lockWallpaperChanged) {
258 // We just migrated sys -> lock to preserve imagery for an impending
Christopher Tatefa7d97f2016-06-30 12:21:57 -0700259 // new system-only wallpaper. Tell keyguard about it and make sure it
260 // has the right SELinux label.
Christopher Tate8347b632016-04-29 18:59:18 -0700261 if (DEBUG) {
262 Slog.i(TAG, "Sys -> lock MOVED_TO");
263 }
Christopher Tatefa7d97f2016-06-30 12:21:57 -0700264 SELinux.restorecon(changedFile);
Christopher Tate8347b632016-04-29 18:59:18 -0700265 notifyLockWallpaperChanged();
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700266 notifyWallpaperColorsChanged(wallpaper, FLAG_LOCK);
Christopher Tate8347b632016-04-29 18:59:18 -0700267 return;
268 }
269
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800270 synchronized (mLock) {
Christopher Tatebe132e62016-02-10 12:59:49 -0800271 if (sysWallpaperChanged || lockWallpaperChanged) {
272 notifyCallbacksLocked(wallpaper);
273 if (wallpaper.wallpaperComponent == null
Christopher Tateda058e22014-10-08 14:51:09 -0700274 || event != CLOSE_WRITE // includes the MOVED_TO case
Christopher Tatebe132e62016-02-10 12:59:49 -0800275 || wallpaper.imageWallpaperPending) {
Christopher Tateda058e22014-10-08 14:51:09 -0700276 if (written) {
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800277 // The image source has finished writing the source image,
278 // so we now produce the crop rect (in the background), and
279 // only publish the new displayable (sub)image as a result
280 // of that work.
Christopher Tatebe132e62016-02-10 12:59:49 -0800281 if (DEBUG) {
282 Slog.v(TAG, "Wallpaper written; generating crop");
283 }
Christopher Tateebadfb12016-07-25 14:50:08 -0700284 SELinux.restorecon(changedFile);
Christopher Tated7faf532016-02-25 12:43:38 -0800285 if (moved) {
286 // This is a restore, so generate the crop using any just-restored new
287 // crop guidelines, making sure to preserve our local dimension hints.
Christopher Tatefa7d97f2016-06-30 12:21:57 -0700288 // We also make sure to reapply the correct SELinux label.
Christopher Tated7faf532016-02-25 12:43:38 -0800289 if (DEBUG) {
290 Slog.v(TAG, "moved-to, therefore restore; reloading metadata");
291 }
292 loadSettingsLocked(wallpaper.userId, true);
293 }
Christopher Tatebe132e62016-02-10 12:59:49 -0800294 generateCrop(wallpaper);
295 if (DEBUG) {
296 Slog.v(TAG, "Crop done; invoking completion callback");
297 }
298 wallpaper.imageWallpaperPending = false;
Christopher Tatebe132e62016-02-10 12:59:49 -0800299 if (sysWallpaperChanged) {
300 // If this was the system wallpaper, rebind...
301 bindWallpaperComponentLocked(mImageWallpaper, true,
302 false, wallpaper, null);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700303 notifyColorsWhich |= FLAG_SYSTEM;
Christopher Tatebe132e62016-02-10 12:59:49 -0800304 }
305 if (lockWallpaperChanged
Christopher Tateedf7d042016-03-29 18:24:25 -0700306 || (wallpaper.whichPending & FLAG_LOCK) != 0) {
Christopher Tatebe132e62016-02-10 12:59:49 -0800307 if (DEBUG) {
Christopher Tatedb27b842016-02-25 14:39:17 -0800308 Slog.i(TAG, "Lock-relevant wallpaper changed");
Christopher Tatebe132e62016-02-10 12:59:49 -0800309 }
Christopher Tatedb27b842016-02-25 14:39:17 -0800310 // either a lock-only wallpaper commit or a system+lock event.
311 // if it's system-plus-lock we need to wipe the lock bookkeeping;
312 // we're falling back to displaying the system wallpaper there.
313 if (!lockWallpaperChanged) {
314 mLockWallpaperMap.remove(wallpaper.userId);
315 }
316 // and in any case, tell keyguard about it
Christopher Tate8347b632016-04-29 18:59:18 -0700317 notifyLockWallpaperChanged();
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700318 notifyColorsWhich |= FLAG_LOCK;
Christopher Tatebe132e62016-02-10 12:59:49 -0800319 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700320
Christopher Tatedb27b842016-02-25 14:39:17 -0800321 saveSettingsLocked(wallpaper.userId);
Christopher Tate8efbe0d2017-08-29 16:50:13 -0700322
323 // Publish completion *after* we've persisted the changes
324 if (wallpaper.setComplete != null) {
325 try {
326 wallpaper.setComplete.onWallpaperChanged();
327 } catch (RemoteException e) {
328 // if this fails we don't really care; the setting app may just
329 // have crashed and that sort of thing is a fact of life.
330 }
331 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700332 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800333 }
334 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800335 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700336
337 // Outside of the lock since it will synchronize itself
338 if (notifyColorsWhich != 0) {
339 notifyWallpaperColorsChanged(wallpaper, notifyColorsWhich);
340 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800341 }
342 }
343
wilsonshiha282bf72018-11-30 12:48:05 +0800344 private void notifyLockWallpaperChanged() {
Christopher Tate8347b632016-04-29 18:59:18 -0700345 final IWallpaperManagerCallback cb = mKeyguardListener;
346 if (cb != null) {
347 try {
348 cb.onWallpaperChanged();
349 } catch (RemoteException e) {
350 // Oh well it went away; no big deal
351 }
352 }
353 }
354
Lucas Dupin50ba9912017-07-14 11:55:05 -0700355 private void notifyWallpaperColorsChanged(@NonNull WallpaperData wallpaper, int which) {
wilsonshih36597d42018-12-05 18:56:39 +0800356 if (wallpaper.connection != null) {
357 wallpaper.connection.forEachDisplayConnector(connector -> {
358 notifyWallpaperColorsChangedOnDisplay(wallpaper, which, connector.mDisplayId);
359 });
360 } else { // Lock wallpaper does not have WallpaperConnection.
361 notifyWallpaperColorsChangedOnDisplay(wallpaper, which, DEFAULT_DISPLAY);
362 }
363 }
364
365 private RemoteCallbackList<IWallpaperManagerCallback> getWallpaperCallbacks(int userId,
366 int displayId) {
367 RemoteCallbackList<IWallpaperManagerCallback> listeners = null;
368 final SparseArray<RemoteCallbackList<IWallpaperManagerCallback>> displayListeners =
369 mColorsChangedListeners.get(userId);
370 if (displayListeners != null) {
371 listeners = displayListeners.get(displayId);
372 }
373 return listeners;
374 }
375
376 private void notifyWallpaperColorsChangedOnDisplay(@NonNull WallpaperData wallpaper, int which,
377 int displayId) {
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700378 boolean needsExtraction;
379 synchronized (mLock) {
Lucas Dupin50ba9912017-07-14 11:55:05 -0700380 final RemoteCallbackList<IWallpaperManagerCallback> currentUserColorListeners =
wilsonshih36597d42018-12-05 18:56:39 +0800381 getWallpaperCallbacks(wallpaper.userId, displayId);
Lucas Dupin50ba9912017-07-14 11:55:05 -0700382 final RemoteCallbackList<IWallpaperManagerCallback> userAllColorListeners =
wilsonshih36597d42018-12-05 18:56:39 +0800383 getWallpaperCallbacks(UserHandle.USER_ALL, displayId);
Lucas Dupin50ba9912017-07-14 11:55:05 -0700384 // No-op until someone is listening to it.
385 if (emptyCallbackList(currentUserColorListeners) &&
386 emptyCallbackList(userAllColorListeners)) {
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700387 return;
Lucas Dupin50ba9912017-07-14 11:55:05 -0700388 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700389
390 if (DEBUG) {
wilsonshih36597d42018-12-05 18:56:39 +0800391 Slog.v(TAG, "notifyWallpaperColorsChangedOnDisplay " + which);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700392 }
393
394 needsExtraction = wallpaper.primaryColors == null;
395 }
396
Lucas Dupin75ec3792017-06-29 14:07:18 -0700397 // Let's notify the current values, it's fine if it's null, it just means
398 // that we don't know yet.
wilsonshih36597d42018-12-05 18:56:39 +0800399 notifyColorListeners(wallpaper.primaryColors, which, wallpaper.userId, displayId);
Lucas Dupin75ec3792017-06-29 14:07:18 -0700400
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700401 if (needsExtraction) {
402 extractColors(wallpaper);
Lucas Dupin50ba9912017-07-14 11:55:05 -0700403 synchronized (mLock) {
404 // Don't need to notify if nothing changed.
405 if (wallpaper.primaryColors == null) {
406 return;
407 }
408 }
wilsonshih36597d42018-12-05 18:56:39 +0800409 notifyColorListeners(wallpaper.primaryColors, which, wallpaper.userId, displayId);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700410 }
Lucas Dupin75ec3792017-06-29 14:07:18 -0700411 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700412
Lucas Dupin50ba9912017-07-14 11:55:05 -0700413 private static <T extends IInterface> boolean emptyCallbackList(RemoteCallbackList<T> list) {
414 return (list == null || list.getRegisteredCallbackCount() == 0);
415 }
416
417 private void notifyColorListeners(@NonNull WallpaperColors wallpaperColors, int which,
wilsonshih36597d42018-12-05 18:56:39 +0800418 int userId, int displayId) {
Lucas Dupin75ec3792017-06-29 14:07:18 -0700419 final IWallpaperManagerCallback keyguardListener;
Lucas Dupinfb3ab2a2017-08-08 14:17:30 -0400420 final ArrayList<IWallpaperManagerCallback> colorListeners = new ArrayList<>();
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700421 synchronized (mLock) {
Lucas Dupinfb3ab2a2017-08-08 14:17:30 -0400422 final RemoteCallbackList<IWallpaperManagerCallback> currentUserColorListeners =
wilsonshih36597d42018-12-05 18:56:39 +0800423 getWallpaperCallbacks(userId, displayId);
Lucas Dupinfb3ab2a2017-08-08 14:17:30 -0400424 final RemoteCallbackList<IWallpaperManagerCallback> userAllColorListeners =
wilsonshih36597d42018-12-05 18:56:39 +0800425 getWallpaperCallbacks(UserHandle.USER_ALL, displayId);
Lucas Dupin75ec3792017-06-29 14:07:18 -0700426 keyguardListener = mKeyguardListener;
Lucas Dupinfb3ab2a2017-08-08 14:17:30 -0400427
428 if (currentUserColorListeners != null) {
429 final int count = currentUserColorListeners.beginBroadcast();
430 for (int i = 0; i < count; i++) {
431 colorListeners.add(currentUserColorListeners.getBroadcastItem(i));
432 }
433 currentUserColorListeners.finishBroadcast();
434 }
435
436 if (userAllColorListeners != null) {
437 final int count = userAllColorListeners.beginBroadcast();
438 for (int i = 0; i < count; i++) {
439 colorListeners.add(userAllColorListeners.getBroadcastItem(i));
440 }
441 userAllColorListeners.finishBroadcast();
442 }
Lucas Dupin75ec3792017-06-29 14:07:18 -0700443 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700444
Lucas Dupinfb3ab2a2017-08-08 14:17:30 -0400445 final int count = colorListeners.size();
446 for (int i = 0; i < count; i++) {
447 try {
448 colorListeners.get(i).onWallpaperColorsChanged(wallpaperColors, which, userId);
449 } catch (RemoteException e) {
450 // Callback is gone, it's not necessary to unregister it since
451 // RemoteCallbackList#getBroadcastItem will take care of it.
Lucas Dupin75ec3792017-06-29 14:07:18 -0700452 }
453 }
454
wilsonshih36597d42018-12-05 18:56:39 +0800455 // Only shows Keyguard on default display
456 if (keyguardListener != null && displayId == DEFAULT_DISPLAY) {
Lucas Dupin75ec3792017-06-29 14:07:18 -0700457 try {
Lucas Dupin50ba9912017-07-14 11:55:05 -0700458 keyguardListener.onWallpaperColorsChanged(wallpaperColors, which, userId);
Lucas Dupin75ec3792017-06-29 14:07:18 -0700459 } catch (RemoteException e) {
460 // Oh well it went away; no big deal
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700461 }
462 }
463 }
464
Lucas Dupinbcae5852017-05-03 12:42:58 -0700465 /**
466 * We can easily extract colors from an ImageWallpaper since it's only a bitmap.
Lucas Dupin284836b2017-06-23 15:28:41 -0700467 * In this case, using the crop is more than enough. Live wallpapers are just ignored.
Lucas Dupinbcae5852017-05-03 12:42:58 -0700468 *
469 * @param wallpaper a wallpaper representation
470 */
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700471 private void extractColors(WallpaperData wallpaper) {
472 String cropFile = null;
wilsonshih31d70a12019-01-14 12:42:35 +0800473 boolean defaultImageWallpaper = false;
Lucas Dupin284836b2017-06-23 15:28:41 -0700474 int wallpaperId;
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700475
wilsonshih36597d42018-12-05 18:56:39 +0800476 if (wallpaper.equals(mFallbackWallpaper)) {
wilsonshihfa24e4f2019-02-22 10:29:19 +0800477 synchronized (mLock) {
478 if (mFallbackWallpaper.primaryColors != null) return;
479 }
480 final WallpaperColors colors = extractDefaultImageWallpaperColors();
481 synchronized (mLock) {
482 mFallbackWallpaper.primaryColors = colors;
483 }
wilsonshih36597d42018-12-05 18:56:39 +0800484 return;
485 }
486
Lucas Dupinbcae5852017-05-03 12:42:58 -0700487 synchronized (mLock) {
Lucas Dupin284836b2017-06-23 15:28:41 -0700488 // Not having a wallpaperComponent means it's a lock screen wallpaper.
489 final boolean imageWallpaper = mImageWallpaper.equals(wallpaper.wallpaperComponent)
Lucas Dupinbcae5852017-05-03 12:42:58 -0700490 || wallpaper.wallpaperComponent == null;
Lucas Dupin284836b2017-06-23 15:28:41 -0700491 if (imageWallpaper && wallpaper.cropFile != null && wallpaper.cropFile.exists()) {
492 cropFile = wallpaper.cropFile.getAbsolutePath();
wilsonshih31d70a12019-01-14 12:42:35 +0800493 } else if (imageWallpaper && !wallpaper.cropExists() && !wallpaper.sourceExists()) {
494 defaultImageWallpaper = true;
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700495 }
496 wallpaperId = wallpaper.wallpaperId;
497 }
498
Lucas Dupin84b89d92017-05-09 12:16:19 -0700499 WallpaperColors colors = null;
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700500 if (cropFile != null) {
Lucas Dupin84b89d92017-05-09 12:16:19 -0700501 Bitmap bitmap = BitmapFactory.decodeFile(cropFile);
Lucas Dupin284836b2017-06-23 15:28:41 -0700502 if (bitmap != null) {
Lucas Dupinb5e50532018-05-24 16:33:14 +0000503 colors = WallpaperColors.fromBitmap(bitmap);
Lucas Dupin284836b2017-06-23 15:28:41 -0700504 bitmap.recycle();
505 }
wilsonshih31d70a12019-01-14 12:42:35 +0800506 } else if (defaultImageWallpaper) {
507 // There is no crop and source file because this is default image wallpaper.
wilsonshihfa24e4f2019-02-22 10:29:19 +0800508 colors = extractDefaultImageWallpaperColors();
Lucas Dupinbcae5852017-05-03 12:42:58 -0700509 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700510
Lucas Dupin84b89d92017-05-09 12:16:19 -0700511 if (colors == null) {
Lucas Dupinbcae5852017-05-03 12:42:58 -0700512 Slog.w(TAG, "Cannot extract colors because wallpaper could not be read.");
513 return;
514 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700515
Lucas Dupinbcae5852017-05-03 12:42:58 -0700516 synchronized (mLock) {
517 if (wallpaper.wallpaperId == wallpaperId) {
Lucas Dupin84b89d92017-05-09 12:16:19 -0700518 wallpaper.primaryColors = colors;
Lucas Dupin75ec3792017-06-29 14:07:18 -0700519 // Now that we have the colors, let's save them into the xml
520 // to avoid having to run this again.
521 saveSettingsLocked(wallpaper.userId);
Lucas Dupinbcae5852017-05-03 12:42:58 -0700522 } else {
523 Slog.w(TAG, "Not setting primary colors since wallpaper changed");
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700524 }
525 }
526 }
527
wilsonshihfa24e4f2019-02-22 10:29:19 +0800528 private WallpaperColors extractDefaultImageWallpaperColors() {
529 if (DEBUG) Slog.d(TAG, "Extract default image wallpaper colors");
530
wilsonshih36597d42018-12-05 18:56:39 +0800531 synchronized (mLock) {
wilsonshihfa24e4f2019-02-22 10:29:19 +0800532 if (mCacheDefaultImageWallpaperColors != null) return mCacheDefaultImageWallpaperColors;
wilsonshih36597d42018-12-05 18:56:39 +0800533 }
534
wilsonshih36597d42018-12-05 18:56:39 +0800535 WallpaperColors colors = null;
wilsonshihfa24e4f2019-02-22 10:29:19 +0800536 try (InputStream is = WallpaperManager.openDefaultWallpaper(mContext, FLAG_SYSTEM)) {
537 if (is == null) {
538 Slog.w(TAG, "Can't open default wallpaper stream");
539 return null;
wilsonshih36597d42018-12-05 18:56:39 +0800540 }
wilsonshihfa24e4f2019-02-22 10:29:19 +0800541
542 final BitmapFactory.Options options = new BitmapFactory.Options();
543 final Bitmap bitmap = BitmapFactory.decodeStream(is, null, options);
544 if (bitmap != null) {
545 colors = WallpaperColors.fromBitmap(bitmap);
546 bitmap.recycle();
547 }
548 } catch (OutOfMemoryError e) {
549 Slog.w(TAG, "Can't decode default wallpaper stream", e);
550 } catch (IOException e) {
551 Slog.w(TAG, "Can't close default wallpaper stream", e);
wilsonshih36597d42018-12-05 18:56:39 +0800552 }
553
554 if (colors == null) {
555 Slog.e(TAG, "Extract default image wallpaper colors failed");
wilsonshihfa24e4f2019-02-22 10:29:19 +0800556 } else {
557 synchronized (mLock) {
558 mCacheDefaultImageWallpaperColors = colors;
559 }
wilsonshih36597d42018-12-05 18:56:39 +0800560 }
561
wilsonshihfa24e4f2019-02-22 10:29:19 +0800562 return colors;
wilsonshih36597d42018-12-05 18:56:39 +0800563 }
564
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800565 /**
566 * Once a new wallpaper has been written via setWallpaper(...), it needs to be cropped
567 * for display.
568 */
569 private void generateCrop(WallpaperData wallpaper) {
570 boolean success = false;
Christopher Tate1a96b632016-03-22 15:25:42 -0700571
wilsonshih81e10a72018-11-15 10:54:21 +0800572 // Only generate crop for default display.
wilsonshiha282bf72018-11-30 12:48:05 +0800573 final DisplayData wpData = getDisplayDataOrCreate(DEFAULT_DISPLAY);
Christopher Tate1a96b632016-03-22 15:25:42 -0700574 Rect cropHint = new Rect(wallpaper.cropHint);
Christopher Tatebe132e62016-02-10 12:59:49 -0800575
576 if (DEBUG) {
577 Slog.v(TAG, "Generating crop for new wallpaper(s): 0x"
578 + Integer.toHexString(wallpaper.whichPending)
Christopher Tate1a96b632016-03-22 15:25:42 -0700579 + " to " + wallpaper.cropFile.getName()
580 + " crop=(" + cropHint.width() + 'x' + cropHint.height()
wilsonshih81e10a72018-11-15 10:54:21 +0800581 + ") dim=(" + wpData.mWidth + 'x' + wpData.mHeight + ')');
Christopher Tatebe132e62016-02-10 12:59:49 -0800582 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800583
584 // Analyse the source; needed in multiple cases
585 BitmapFactory.Options options = new BitmapFactory.Options();
586 options.inJustDecodeBounds = true;
587 BitmapFactory.decodeFile(wallpaper.wallpaperFile.getAbsolutePath(), options);
Christopher Tate1a96b632016-03-22 15:25:42 -0700588 if (options.outWidth <= 0 || options.outHeight <= 0) {
Joe LaPennac298b162016-05-02 15:25:50 -0700589 Slog.w(TAG, "Invalid wallpaper data");
Christopher Tate1a96b632016-03-22 15:25:42 -0700590 success = false;
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800591 } else {
Christopher Tate1a96b632016-03-22 15:25:42 -0700592 boolean needCrop = false;
593 boolean needScale = false;
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800594
Christopher Tate1a96b632016-03-22 15:25:42 -0700595 // Empty crop means use the full image
596 if (cropHint.isEmpty()) {
597 cropHint.left = cropHint.top = 0;
598 cropHint.right = options.outWidth;
599 cropHint.bottom = options.outHeight;
600 } else {
601 // force the crop rect to lie within the measured bounds
602 cropHint.offset(
603 (cropHint.right > options.outWidth ? options.outWidth - cropHint.right : 0),
604 (cropHint.bottom > options.outHeight ? options.outHeight - cropHint.bottom : 0));
605
Adrian Roos5c97ff22016-08-31 10:25:38 -0700606 // If the crop hint was larger than the image we just overshot. Patch things up.
607 if (cropHint.left < 0) {
608 cropHint.left = 0;
609 }
610 if (cropHint.top < 0) {
611 cropHint.top = 0;
612 }
613
Christopher Tate1a96b632016-03-22 15:25:42 -0700614 // Don't bother cropping if what we're left with is identity
Christopher Tateebadfb12016-07-25 14:50:08 -0700615 needCrop = (options.outHeight > cropHint.height()
Adrian Roos5c97ff22016-08-31 10:25:38 -0700616 || options.outWidth > cropHint.width());
Christopher Tate1a96b632016-03-22 15:25:42 -0700617 }
618
619 // scale if the crop height winds up not matching the recommended metrics
wilsonshih81e10a72018-11-15 10:54:21 +0800620 needScale = (wpData.mHeight != cropHint.height());
Christopher Tate1a96b632016-03-22 15:25:42 -0700621
Valentin Iftime3047bb12018-12-28 17:02:19 +0100622 //make sure screen aspect ratio is preserved if width is scaled under screen size
623 if (needScale) {
624 final DisplayInfo displayInfo = new DisplayInfo();
625 mDisplayManager.getDisplay(DEFAULT_DISPLAY).getDisplayInfo(displayInfo);
626 final float scaleByHeight = (float) wpData.mHeight / (float) cropHint.height();
627 final int newWidth = (int) (cropHint.width() * scaleByHeight);
628 if (newWidth < displayInfo.logicalWidth) {
629 final float screenAspectRatio =
630 (float) displayInfo.logicalHeight / (float) displayInfo.logicalWidth;
631 cropHint.bottom = (int) (cropHint.width() * screenAspectRatio);
632 needCrop = true;
633 }
634 }
635
Christopher Tate1a96b632016-03-22 15:25:42 -0700636 if (DEBUG) {
637 Slog.v(TAG, "crop: w=" + cropHint.width() + " h=" + cropHint.height());
wilsonshih81e10a72018-11-15 10:54:21 +0800638 Slog.v(TAG, "dims: w=" + wpData.mWidth + " h=" + wpData.mHeight);
Christopher Tate1a96b632016-03-22 15:25:42 -0700639 Slog.v(TAG, "meas: w=" + options.outWidth + " h=" + options.outHeight);
640 Slog.v(TAG, "crop?=" + needCrop + " scale?=" + needScale);
641 }
642
643 if (!needCrop && !needScale) {
644 // Simple case: the nominal crop fits what we want, so we take
645 // the whole thing and just copy the image file directly.
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800646 if (DEBUG) {
Christopher Tate1a96b632016-03-22 15:25:42 -0700647 Slog.v(TAG, "Null crop of new wallpaper; copying");
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800648 }
Christopher Tate1a96b632016-03-22 15:25:42 -0700649 success = FileUtils.copyFile(wallpaper.wallpaperFile, wallpaper.cropFile);
650 if (!success) {
651 wallpaper.cropFile.delete();
652 // TODO: fall back to default wallpaper in this case
653 }
654 } else {
655 // Fancy case: crop and scale. First, we decode and scale down if appropriate.
656 FileOutputStream f = null;
657 BufferedOutputStream bos = null;
658 try {
659 BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(
660 wallpaper.wallpaperFile.getAbsolutePath(), false);
661
662 // This actually downsamples only by powers of two, but that's okay; we do
663 // a proper scaling blit later. This is to minimize transient RAM use.
664 // We calculate the largest power-of-two under the actual ratio rather than
665 // just let the decode take care of it because we also want to remap where the
666 // cropHint rectangle lies in the decoded [super]rect.
667 final BitmapFactory.Options scaler;
wilsonshih81e10a72018-11-15 10:54:21 +0800668 final int actualScale = cropHint.height() / wpData.mHeight;
Christopher Tate1a96b632016-03-22 15:25:42 -0700669 int scale = 1;
670 while (2*scale < actualScale) {
671 scale *= 2;
672 }
673 if (scale > 1) {
674 scaler = new BitmapFactory.Options();
675 scaler.inSampleSize = scale;
676 if (DEBUG) {
677 Slog.v(TAG, "Downsampling cropped rect with scale " + scale);
678 }
679 } else {
680 scaler = null;
681 }
682 Bitmap cropped = decoder.decodeRegion(cropHint, scaler);
683 decoder.recycle();
684
685 if (cropped == null) {
686 Slog.e(TAG, "Could not decode new wallpaper");
687 } else {
688 // We've got the extracted crop; now we want to scale it properly to
689 // the desired rectangle. That's a height-biased operation: make it
690 // fit the hinted height, and accept whatever width we end up with.
691 cropHint.offsetTo(0, 0);
692 cropHint.right /= scale; // adjust by downsampling factor
693 cropHint.bottom /= scale;
wilsonshih81e10a72018-11-15 10:54:21 +0800694 final float heightR =
695 ((float) wpData.mHeight) / ((float) cropHint.height());
Christopher Tate1a96b632016-03-22 15:25:42 -0700696 if (DEBUG) {
697 Slog.v(TAG, "scale " + heightR + ", extracting " + cropHint);
698 }
699 final int destWidth = (int)(cropHint.width() * heightR);
700 final Bitmap finalCrop = Bitmap.createScaledBitmap(cropped,
wilsonshih81e10a72018-11-15 10:54:21 +0800701 destWidth, wpData.mHeight, true);
Christopher Tate1a96b632016-03-22 15:25:42 -0700702 if (DEBUG) {
703 Slog.v(TAG, "Final extract:");
wilsonshih81e10a72018-11-15 10:54:21 +0800704 Slog.v(TAG, " dims: w=" + wpData.mWidth
705 + " h=" + wpData.mHeight);
Christopher Tate1a96b632016-03-22 15:25:42 -0700706 Slog.v(TAG, " out: w=" + finalCrop.getWidth()
707 + " h=" + finalCrop.getHeight());
708 }
709
710 f = new FileOutputStream(wallpaper.cropFile);
711 bos = new BufferedOutputStream(f, 32*1024);
Christopher Tatec484f542016-05-11 14:31:34 -0700712 finalCrop.compress(Bitmap.CompressFormat.JPEG, 100, bos);
Christopher Tate1a96b632016-03-22 15:25:42 -0700713 bos.flush(); // don't rely on the implicit flush-at-close when noting success
714 success = true;
715 }
716 } catch (Exception e) {
717 if (DEBUG) {
718 Slog.e(TAG, "Error decoding crop", e);
719 }
720 } finally {
721 IoUtils.closeQuietly(bos);
722 IoUtils.closeQuietly(f);
723 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800724 }
725 }
726
727 if (!success) {
728 Slog.e(TAG, "Unable to apply new wallpaper");
729 wallpaper.cropFile.delete();
730 }
731
732 if (wallpaper.cropFile.exists()) {
733 boolean didRestorecon = SELinux.restorecon(wallpaper.cropFile.getAbsoluteFile());
734 if (DEBUG) {
735 Slog.v(TAG, "restorecon() of crop file returned " + didRestorecon);
736 }
737 }
738 }
739
wilsonshiha282bf72018-11-30 12:48:05 +0800740 private final Context mContext;
741 private final IWindowManager mIWindowManager;
Andrii Kuliandd989612019-02-21 12:13:28 -0800742 private final WindowManagerInternal mWindowManagerInternal;
wilsonshiha282bf72018-11-30 12:48:05 +0800743 private final IPackageManager mIPackageManager;
744 private final MyPackageMonitor mMonitor;
745 private final AppOpsManager mAppOpsManager;
wilsonshihde93f492018-11-01 21:23:40 +0800746
747 private final DisplayManager mDisplayManager;
748 private final DisplayManager.DisplayListener mDisplayListener =
749 new DisplayManager.DisplayListener() {
750
751 @Override
752 public void onDisplayAdded(int displayId) {
wilsonshihde93f492018-11-01 21:23:40 +0800753 }
754
755 @Override
756 public void onDisplayRemoved(int displayId) {
757 synchronized (mLock) {
758 if (mLastWallpaper != null) {
wilsonshiha282bf72018-11-30 12:48:05 +0800759 WallpaperData targetWallpaper = null;
760 if (mLastWallpaper.connection.containsDisplay(displayId)) {
761 targetWallpaper = mLastWallpaper;
762 } else if (mFallbackWallpaper.connection.containsDisplay(displayId)) {
763 targetWallpaper = mFallbackWallpaper;
764 }
765 if (targetWallpaper == null) return;
766 WallpaperConnection.DisplayConnector connector =
767 targetWallpaper.connection.getDisplayConnectorOrCreate(displayId);
wilsonshihde93f492018-11-01 21:23:40 +0800768 if (connector == null) return;
769 connector.disconnectLocked();
wilsonshiha282bf72018-11-30 12:48:05 +0800770 targetWallpaper.connection.removeDisplayConnector(displayId);
771 removeDisplayData(displayId);
wilsonshihde93f492018-11-01 21:23:40 +0800772 }
wilsonshih36597d42018-12-05 18:56:39 +0800773 for (int i = mColorsChangedListeners.size() - 1; i >= 0; i--) {
774 final SparseArray<RemoteCallbackList<IWallpaperManagerCallback>> callbacks =
775 mColorsChangedListeners.valueAt(i);
776 callbacks.delete(displayId);
777 }
wilsonshihde93f492018-11-01 21:23:40 +0800778 }
779 }
780
781 @Override
782 public void onDisplayChanged(int displayId) {
wilsonshihde93f492018-11-01 21:23:40 +0800783 }
784 };
785
Lucas Dupin50ba9912017-07-14 11:55:05 -0700786 /**
787 * Map of color listeners per user id.
wilsonshih36597d42018-12-05 18:56:39 +0800788 * The first key will be the id of a user or UserHandle.USER_ALL - for wildcard listeners.
789 * The secondary key will be the display id, which means which display the listener is
790 * interested in.
Lucas Dupin50ba9912017-07-14 11:55:05 -0700791 */
wilsonshih36597d42018-12-05 18:56:39 +0800792 private final SparseArray<SparseArray<RemoteCallbackList<IWallpaperManagerCallback>>>
wilsonshiha282bf72018-11-30 12:48:05 +0800793 mColorsChangedListeners;
794 private WallpaperData mLastWallpaper;
795 private IWallpaperManagerCallback mKeyguardListener;
796 private boolean mWaitingForUnlock;
797 private boolean mShuttingDown;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800798
Justin Koh29c30162014-09-05 17:10:10 -0700799 /**
Christopher Tatead3c2592016-01-20 18:13:17 -0800800 * ID of the current wallpaper, changed every time anything sets a wallpaper.
801 * This is used for external detection of wallpaper update activity.
802 */
wilsonshiha282bf72018-11-30 12:48:05 +0800803 private int mWallpaperId;
Christopher Tatead3c2592016-01-20 18:13:17 -0800804
805 /**
Justin Koh29c30162014-09-05 17:10:10 -0700806 * Name of the component used to display bitmap wallpapers from either the gallery or
807 * built-in wallpapers.
808 */
wilsonshiha282bf72018-11-30 12:48:05 +0800809 private final ComponentName mImageWallpaper;
Justin Koh29c30162014-09-05 17:10:10 -0700810
Christopher Tate2a6c55f2017-03-31 12:28:30 -0700811 /**
wilsonshihfa24e4f2019-02-22 10:29:19 +0800812 * Default image wallpaper shall never changed after system service started, caching it when we
813 * first read the image file.
814 */
815 private WallpaperColors mCacheDefaultImageWallpaperColors;
816
817 /**
Christopher Tate2a6c55f2017-03-31 12:28:30 -0700818 * Name of the default wallpaper component; might be different from mImageWallpaper
819 */
wilsonshiha282bf72018-11-30 12:48:05 +0800820 private final ComponentName mDefaultWallpaperComponent;
Christopher Tate2a6c55f2017-03-31 12:28:30 -0700821
wilsonshiha282bf72018-11-30 12:48:05 +0800822 private final SparseArray<WallpaperData> mWallpaperMap = new SparseArray<WallpaperData>();
823 private final SparseArray<WallpaperData> mLockWallpaperMap = new SparseArray<WallpaperData>();
Dianne Hackborn07213e62011-08-24 20:05:39 -0700824
wilsonshiha282bf72018-11-30 12:48:05 +0800825 private SparseArray<DisplayData> mDisplayDatas = new SparseArray<>();
826
827 private WallpaperData mFallbackWallpaper;
828
829 private final SparseBooleanArray mUserRestorecon = new SparseBooleanArray();
830 private int mCurrentUserId = UserHandle.USER_NULL;
831 private boolean mInAmbientMode;
Dianne Hackborn07213e62011-08-24 20:05:39 -0700832
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800833 static class WallpaperData {
834
835 int userId;
836
Christopher Tatebe132e62016-02-10 12:59:49 -0800837 final File wallpaperFile; // source image
838 final File cropFile; // eventual destination
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800839
840 /**
Christopher Tatebe132e62016-02-10 12:59:49 -0800841 * True while the client is writing a new wallpaper
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800842 */
843 boolean imageWallpaperPending;
844
845 /**
Christopher Tatebe132e62016-02-10 12:59:49 -0800846 * Which new wallpapers are being written; mirrors the 'which'
847 * selector bit field to setWallpaper().
848 */
849 int whichPending;
850
851 /**
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800852 * Callback once the set + crop is finished
853 */
854 IWallpaperManagerCallback setComplete;
855
856 /**
Christopher Tated7faf532016-02-25 12:43:38 -0800857 * Is the OS allowed to back up this wallpaper imagery?
858 */
859 boolean allowBackup;
860
861 /**
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800862 * Resource name if using a picture from the wallpaper gallery
863 */
864 String name = "";
865
866 /**
867 * The component name of the currently set live wallpaper.
868 */
869 ComponentName wallpaperComponent;
870
871 /**
872 * The component name of the wallpaper that should be set next.
873 */
874 ComponentName nextWallpaperComponent;
875
Christopher Tatead3c2592016-01-20 18:13:17 -0800876 /**
877 * The ID of this wallpaper
878 */
879 int wallpaperId;
880
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700881 /**
882 * Primary colors histogram
883 */
884 WallpaperColors primaryColors;
885
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800886 WallpaperConnection connection;
887 long lastDiedTime;
888 boolean wallpaperUpdating;
889 WallpaperObserver wallpaperObserver;
890
891 /**
892 * List of callbacks registered they should each be notified when the wallpaper is changed.
893 */
894 private RemoteCallbackList<IWallpaperManagerCallback> callbacks
895 = new RemoteCallbackList<IWallpaperManagerCallback>();
896
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800897 /**
898 * The crop hint supplied for displaying a subset of the source image
899 */
900 final Rect cropHint = new Rect(0, 0, 0, 0);
901
Christopher Tatebe132e62016-02-10 12:59:49 -0800902 WallpaperData(int userId, String inputFileName, String cropFileName) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800903 this.userId = userId;
Christopher Tatebe132e62016-02-10 12:59:49 -0800904 final File wallpaperDir = getWallpaperDir(userId);
905 wallpaperFile = new File(wallpaperDir, inputFileName);
906 cropFile = new File(wallpaperDir, cropFileName);
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800907 }
908
Christopher Tatebe132e62016-02-10 12:59:49 -0800909 // Called during initialization of a given user's wallpaper bookkeeping
Christopher Tate41297ff2016-03-10 16:46:15 -0800910 boolean cropExists() {
911 return cropFile.exists();
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800912 }
Christopher Tate2a6c55f2017-03-31 12:28:30 -0700913
914 boolean sourceExists() {
915 return wallpaperFile.exists();
916 }
wilsonshiha282bf72018-11-30 12:48:05 +0800917 }
wilsonshih81e10a72018-11-15 10:54:21 +0800918
wilsonshiha282bf72018-11-30 12:48:05 +0800919 private static final class DisplayData {
920 int mWidth = -1;
921 int mHeight = -1;
922 final Rect mPadding = new Rect(0, 0, 0, 0);
923 final int mDisplayId;
924
925 DisplayData(int displayId) {
926 mDisplayId = displayId;
wilsonshih81e10a72018-11-15 10:54:21 +0800927 }
928 }
929
wilsonshiha282bf72018-11-30 12:48:05 +0800930 private void removeDisplayData(int displayId) {
931 mDisplayDatas.remove(displayId);
932 }
933
934 private DisplayData getDisplayDataOrCreate(int displayId) {
935 DisplayData wpdData = mDisplayDatas.get(displayId);
wilsonshih81e10a72018-11-15 10:54:21 +0800936 if (wpdData == null) {
wilsonshiha282bf72018-11-30 12:48:05 +0800937 wpdData = new DisplayData(displayId);
wilsonshih81e10a72018-11-15 10:54:21 +0800938 ensureSaneWallpaperDisplaySize(wpdData, displayId);
wilsonshiha282bf72018-11-30 12:48:05 +0800939 mDisplayDatas.append(displayId, wpdData);
wilsonshih81e10a72018-11-15 10:54:21 +0800940 }
941 return wpdData;
942 }
943
wilsonshiha282bf72018-11-30 12:48:05 +0800944 private void ensureSaneWallpaperDisplaySize(DisplayData wpdData, int displayId) {
wilsonshih81e10a72018-11-15 10:54:21 +0800945 // We always want to have some reasonable width hint.
946 final int baseSize = getMaximumSizeDimension(displayId);
947 if (wpdData.mWidth < baseSize) {
948 wpdData.mWidth = baseSize;
949 }
950 if (wpdData.mHeight < baseSize) {
951 wpdData.mHeight = baseSize;
952 }
953 }
954
955 private int getMaximumSizeDimension(int displayId) {
956 Display display = mDisplayManager.getDisplay(displayId);
wilsonshiha282bf72018-11-30 12:48:05 +0800957 if (display == null) {
958 Slog.w(TAG, "Invalid displayId=" + displayId + " " + Debug.getCallers(4));
959 display = mDisplayManager.getDisplay(DEFAULT_DISPLAY);
960 }
wilsonshih81e10a72018-11-15 10:54:21 +0800961 return display.getMaximumSizeDimension();
962 }
963
wilsonshiha282bf72018-11-30 12:48:05 +0800964 void forEachDisplayData(Consumer<DisplayData> action) {
965 for (int i = mDisplayDatas.size() - 1; i >= 0; i--) {
966 final DisplayData wpdData = mDisplayDatas.valueAt(i);
wilsonshih81e10a72018-11-15 10:54:21 +0800967 action.accept(wpdData);
968 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800969 }
970
Christopher Tatead3c2592016-01-20 18:13:17 -0800971 int makeWallpaperIdLocked() {
972 do {
973 ++mWallpaperId;
974 } while (mWallpaperId == 0);
975 return mWallpaperId;
976 }
977
wilsonshiha282bf72018-11-30 12:48:05 +0800978 private boolean supportsMultiDisplay(WallpaperConnection connection) {
979 if (connection != null) {
980 return connection.mInfo == null // This is image wallpaper
981 || connection.mInfo.supportsMultipleDisplays();
982 }
983 return false;
984 }
985
986 private void updateFallbackConnection() {
987 if (mLastWallpaper == null || mFallbackWallpaper == null) return;
988 final WallpaperConnection systemConnection = mLastWallpaper.connection;
989 final WallpaperConnection fallbackConnection = mFallbackWallpaper.connection;
wilsonshih78268c32018-12-18 20:48:28 +0800990 if (fallbackConnection == null) {
991 Slog.w(TAG, "Fallback wallpaper connection has not been created yet!!");
992 return;
993 }
wilsonshih507ada52019-01-19 11:22:09 +0800994 if (supportsMultiDisplay(systemConnection)) {
995 if (fallbackConnection.mDisplayConnector.size() != 0) {
996 fallbackConnection.forEachDisplayConnector(connector -> {
997 if (connector.mEngine != null) {
998 connector.disconnectLocked();
999 }
1000 });
1001 fallbackConnection.mDisplayConnector.clear();
1002 }
wilsonshiha282bf72018-11-30 12:48:05 +08001003 } else {
1004 fallbackConnection.appendConnectorWithCondition(display ->
1005 fallbackConnection.isUsableDisplay(display)
1006 && display.getDisplayId() != DEFAULT_DISPLAY
1007 && !fallbackConnection.containsDisplay(display.getDisplayId()));
1008 fallbackConnection.forEachDisplayConnector(connector -> {
1009 if (connector.mEngine == null) {
1010 connector.connectLocked(fallbackConnection, mFallbackWallpaper);
1011 }
1012 });
1013 }
1014 }
1015
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001016 class WallpaperConnection extends IWallpaperConnection.Stub
1017 implements ServiceConnection {
Adrian Roosc3f915e2016-09-06 11:40:53 -07001018
wilsonshihde93f492018-11-01 21:23:40 +08001019 /**
1020 * Collect needed info for a display.
1021 */
1022 private final class DisplayConnector {
1023 final int mDisplayId;
1024 final Binder mToken = new Binder();
1025 IWallpaperEngine mEngine;
1026 boolean mDimensionsChanged;
1027 boolean mPaddingChanged;
1028
1029 DisplayConnector(int displayId) {
1030 mDisplayId = displayId;
1031 }
1032
1033 void ensureStatusHandled() {
wilsonshiha282bf72018-11-30 12:48:05 +08001034 final DisplayData wpdData = getDisplayDataOrCreate(mDisplayId);
wilsonshihde93f492018-11-01 21:23:40 +08001035 if (mDimensionsChanged) {
1036 try {
wilsonshih81e10a72018-11-15 10:54:21 +08001037 mEngine.setDesiredSize(wpdData.mWidth, wpdData.mHeight);
wilsonshihde93f492018-11-01 21:23:40 +08001038 } catch (RemoteException e) {
1039 Slog.w(TAG, "Failed to set wallpaper dimensions", e);
1040 }
1041 mDimensionsChanged = false;
1042 }
1043 if (mPaddingChanged) {
1044 try {
wilsonshih81e10a72018-11-15 10:54:21 +08001045 mEngine.setDisplayPadding(wpdData.mPadding);
wilsonshihde93f492018-11-01 21:23:40 +08001046 } catch (RemoteException e) {
1047 Slog.w(TAG, "Failed to set wallpaper padding", e);
1048 }
1049 mPaddingChanged = false;
1050 }
1051 }
1052
1053 void connectLocked(WallpaperConnection connection, WallpaperData wallpaper) {
wilsonshih674a4a02018-12-19 11:47:25 +08001054 if (connection.mService == null) {
1055 Slog.w(TAG, "WallpaperService is not connected yet");
1056 return;
1057 }
wilsonshihde93f492018-11-01 21:23:40 +08001058 if (DEBUG) Slog.v(TAG, "Adding window token: " + mToken);
1059 try {
1060 mIWindowManager.addWindowToken(mToken, TYPE_WALLPAPER, mDisplayId);
1061 } catch (RemoteException e) {
1062 Slog.e(TAG, "Failed add wallpaper window token on display " + mDisplayId, e);
1063 return;
1064 }
1065
wilsonshiha282bf72018-11-30 12:48:05 +08001066 final DisplayData wpdData = getDisplayDataOrCreate(mDisplayId);
wilsonshihde93f492018-11-01 21:23:40 +08001067 try {
wilsonshihde93f492018-11-01 21:23:40 +08001068 connection.mService.attach(connection, mToken, TYPE_WALLPAPER, false,
wilsonshih81e10a72018-11-15 10:54:21 +08001069 wpdData.mWidth, wpdData.mHeight,
1070 wpdData.mPadding, mDisplayId);
wilsonshihde93f492018-11-01 21:23:40 +08001071 } catch (RemoteException e) {
1072 Slog.w(TAG, "Failed attaching wallpaper on display", e);
wilsonshih674a4a02018-12-19 11:47:25 +08001073 if (wallpaper != null && !wallpaper.wallpaperUpdating
wilsonshih81e10a72018-11-15 10:54:21 +08001074 && connection.getConnectedEngineSize() == 0) {
wilsonshihde93f492018-11-01 21:23:40 +08001075 bindWallpaperComponentLocked(null /* componentName */, false /* force */,
1076 false /* fromUser */, wallpaper, null /* reply */);
1077 }
1078 }
1079 }
1080
1081 void disconnectLocked() {
1082 if (DEBUG) Slog.v(TAG, "Removing window token: " + mToken);
1083 try {
1084 mIWindowManager.removeWindowToken(mToken, mDisplayId);
1085 } catch (RemoteException e) {
1086 }
1087 try {
1088 if (mEngine != null) {
1089 mEngine.destroy();
1090 }
1091 } catch (RemoteException e) {
1092 }
1093 mEngine = null;
1094 }
1095 }
1096
1097 /**
1098 * A map for each display.
1099 * Use {@link #getDisplayConnectorOrCreate(int displayId)} to ensure the display is usable.
1100 */
1101 private SparseArray<DisplayConnector> mDisplayConnector = new SparseArray<>();
1102
Adrian Roosc3f915e2016-09-06 11:40:53 -07001103 /** Time in milliseconds until we expect the wallpaper to reconnect (unless we're in the
1104 * middle of an update). If exceeded, the wallpaper gets reset to the system default. */
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001105 private static final long WALLPAPER_RECONNECT_TIMEOUT_MS = 10000;
Adrian Roosc3f915e2016-09-06 11:40:53 -07001106
Dianne Hackborneb034652009-09-07 00:49:58 -07001107 final WallpaperInfo mInfo;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001108 IWallpaperService mService;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001109 WallpaperData mWallpaper;
wilsonshihde93f492018-11-01 21:23:40 +08001110 final int mClientUid;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001111 IRemoteCallback mReply;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001112
Adrian Roosc3f915e2016-09-06 11:40:53 -07001113 private Runnable mResetRunnable = () -> {
1114 synchronized (mLock) {
Christopher Tate762dfd12016-10-10 17:44:48 -07001115 if (mShuttingDown) {
1116 // Don't expect wallpaper services to relaunch during shutdown
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001117 if (DEBUG_LIVE) {
Christopher Tate762dfd12016-10-10 17:44:48 -07001118 Slog.i(TAG, "Ignoring relaunch timeout during shutdown");
1119 }
1120 return;
1121 }
1122
Adrian Roosc3f915e2016-09-06 11:40:53 -07001123 if (!mWallpaper.wallpaperUpdating
1124 && mWallpaper.userId == mCurrentUserId) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001125 Slog.w(TAG, "Wallpaper reconnect timed out for " + mWallpaper.wallpaperComponent
1126 + ", reverting to built-in wallpaper!");
Adrian Roosc3f915e2016-09-06 11:40:53 -07001127 clearWallpaperLocked(true, FLAG_SYSTEM, mWallpaper.userId,
1128 null);
1129 }
1130 }
1131 };
1132
wilsonshihde93f492018-11-01 21:23:40 +08001133 WallpaperConnection(WallpaperInfo info, WallpaperData wallpaper, int clientUid) {
Dianne Hackborneb034652009-09-07 00:49:58 -07001134 mInfo = info;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001135 mWallpaper = wallpaper;
wilsonshihde93f492018-11-01 21:23:40 +08001136 mClientUid = clientUid;
1137 initDisplayState();
1138 }
1139
1140 private void initDisplayState() {
wilsonshiha282bf72018-11-30 12:48:05 +08001141 // Do not initialize fallback wallpaper
1142 if (!mWallpaper.equals(mFallbackWallpaper)) {
1143 if (supportsMultiDisplay(this)) {
1144 // The system wallpaper is image wallpaper or it can supports multiple displays.
1145 appendConnectorWithCondition(this::isUsableDisplay);
1146 } else {
1147 // The system wallpaper does not support multiple displays, so just attach it on
1148 // default display.
1149 mDisplayConnector.append(DEFAULT_DISPLAY,
1150 new DisplayConnector(DEFAULT_DISPLAY));
wilsonshihde93f492018-11-01 21:23:40 +08001151 }
1152 }
1153 }
1154
wilsonshiha282bf72018-11-30 12:48:05 +08001155 private void appendConnectorWithCondition(Predicate<Display> tester) {
1156 final Display[] displays = mDisplayManager.getDisplays();
1157 for (Display display : displays) {
1158 if (tester.test(display)) {
1159 final int displayId = display.getDisplayId();
wilsonshih674a4a02018-12-19 11:47:25 +08001160 final DisplayConnector connector = mDisplayConnector.get(displayId);
1161 if (connector == null) {
1162 mDisplayConnector.append(displayId,
1163 new DisplayConnector(displayId));
1164 }
wilsonshiha282bf72018-11-30 12:48:05 +08001165 }
1166 }
1167 }
1168
wilsonshihde93f492018-11-01 21:23:40 +08001169 private boolean isUsableDisplay(Display display) {
Andrii Kuliandd989612019-02-21 12:13:28 -08001170 if (display == null || !display.hasAccess(mClientUid)) {
1171 return false;
1172 }
1173 final int displayId = display.getDisplayId();
1174 return displayId == DEFAULT_DISPLAY
1175 || mWindowManagerInternal.shouldShowSystemDecorOnDisplay(displayId);
wilsonshihde93f492018-11-01 21:23:40 +08001176 }
1177
1178 void forEachDisplayConnector(Consumer<DisplayConnector> action) {
1179 for (int i = mDisplayConnector.size() - 1; i >= 0; i--) {
wilsonshih81e10a72018-11-15 10:54:21 +08001180 final DisplayConnector connector = mDisplayConnector.valueAt(i);
wilsonshihde93f492018-11-01 21:23:40 +08001181 action.accept(connector);
1182 }
1183 }
1184
wilsonshih81e10a72018-11-15 10:54:21 +08001185 int getConnectedEngineSize() {
1186 int engineSize = 0;
1187 for (int i = mDisplayConnector.size() - 1; i >= 0; i--) {
1188 final DisplayConnector connector = mDisplayConnector.valueAt(i);
1189 if (connector.mEngine != null) engineSize++;
1190 }
1191 return engineSize;
1192 }
1193
wilsonshihde93f492018-11-01 21:23:40 +08001194 DisplayConnector getDisplayConnectorOrCreate(int displayId) {
1195 DisplayConnector connector = mDisplayConnector.get(displayId);
1196 if (connector == null) {
1197 final Display display = mDisplayManager.getDisplay(displayId);
1198 if (isUsableDisplay(display)) {
1199 connector = new DisplayConnector(displayId);
1200 mDisplayConnector.append(displayId, connector);
1201 }
1202 }
1203 return connector;
1204 }
1205
wilsonshiha282bf72018-11-30 12:48:05 +08001206 boolean containsDisplay(int displayId) {
1207 return mDisplayConnector.get(displayId) != null;
1208 }
1209
wilsonshihde93f492018-11-01 21:23:40 +08001210 void removeDisplayConnector(int displayId) {
1211 final DisplayConnector connector = mDisplayConnector.get(displayId);
1212 if (connector != null) {
1213 mDisplayConnector.remove(displayId);
1214 }
Dianne Hackborneb034652009-09-07 00:49:58 -07001215 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001216
1217 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001218 public void onServiceConnected(ComponentName name, IBinder service) {
1219 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001220 if (mWallpaper.connection == this) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001221 mService = IWallpaperService.Stub.asInterface(service);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001222 attachServiceLocked(this, mWallpaper);
Dianne Hackborneb034652009-09-07 00:49:58 -07001223 // XXX should probably do saveSettingsLocked() later
1224 // when we have an engine, but I'm not sure about
1225 // locking there and anyway we always need to be able to
1226 // recover if there is something wrong.
wilsonshiha282bf72018-11-30 12:48:05 +08001227 if (!mWallpaper.equals(mFallbackWallpaper)) {
1228 saveSettingsLocked(mWallpaper.userId);
1229 }
Adrian Roosc3f915e2016-09-06 11:40:53 -07001230 FgThread.getHandler().removeCallbacks(mResetRunnable);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001231 }
1232 }
1233 }
1234
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001235 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001236 public void onServiceDisconnected(ComponentName name) {
1237 synchronized (mLock) {
Christopher Tatec349e59f2017-05-05 17:37:43 -07001238 Slog.w(TAG, "Wallpaper service gone: " + name);
1239 if (!Objects.equals(name, mWallpaper.wallpaperComponent)) {
1240 Slog.e(TAG, "Does not match expected wallpaper component "
1241 + mWallpaper.wallpaperComponent);
1242 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001243 mService = null;
wilsonshihde93f492018-11-01 21:23:40 +08001244 forEachDisplayConnector(connector -> connector.mEngine = null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001245 if (mWallpaper.connection == this) {
Christopher Tatec349e59f2017-05-05 17:37:43 -07001246 // There is an inherent ordering race between this callback and the
1247 // package monitor that receives notice that a package is being updated,
1248 // so we cannot quite trust at this moment that we know for sure that
1249 // this is not an update. If we think this is a genuine non-update
1250 // wallpaper outage, we do our "wait for reset" work as a continuation,
1251 // a short time in the future, specifically to allow any pending package
1252 // update message on this same looper thread to be processed.
1253 if (!mWallpaper.wallpaperUpdating) {
1254 mContext.getMainThreadHandler().postDelayed(() -> processDisconnect(this),
1255 1000);
1256 }
1257 }
1258 }
1259 }
1260
Tetsutoki Shiozawa06919212018-02-02 14:18:43 +09001261 public void scheduleTimeoutLocked() {
1262 // If we didn't reset it right away, do so after we couldn't connect to
1263 // it for an extended amount of time to avoid having a black wallpaper.
1264 final Handler fgHandler = FgThread.getHandler();
1265 fgHandler.removeCallbacks(mResetRunnable);
1266 fgHandler.postDelayed(mResetRunnable, WALLPAPER_RECONNECT_TIMEOUT_MS);
1267 if (DEBUG_LIVE) {
wilsonshihde93f492018-11-01 21:23:40 +08001268 Slog.i(TAG,
1269 "Started wallpaper reconnect timeout for " + mWallpaper.wallpaperComponent);
Tetsutoki Shiozawa06919212018-02-02 14:18:43 +09001270 }
1271 }
1272
Christopher Tatec349e59f2017-05-05 17:37:43 -07001273 private void processDisconnect(final ServiceConnection connection) {
1274 synchronized (mLock) {
1275 // The wallpaper disappeared. If this isn't a system-default one, track
1276 // crashes and fall back to default if it continues to misbehave.
1277 if (connection == mWallpaper.connection) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001278 final ComponentName wpService = mWallpaper.wallpaperComponent;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001279 if (!mWallpaper.wallpaperUpdating
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001280 && mWallpaper.userId == mCurrentUserId
1281 && !Objects.equals(mDefaultWallpaperComponent, wpService)
1282 && !Objects.equals(mImageWallpaper, wpService)) {
Selim Cinekebebadb2014-03-05 22:17:26 +01001283 // There is a race condition which causes
1284 // {@link #mWallpaper.wallpaperUpdating} to be false even if it is
1285 // currently updating since the broadcast notifying us is async.
1286 // This race is overcome by the general rule that we only reset the
1287 // wallpaper if its service was shut down twice
1288 // during {@link #MIN_WALLPAPER_CRASH_TIME} millis.
1289 if (mWallpaper.lastDiedTime != 0
1290 && mWallpaper.lastDiedTime + MIN_WALLPAPER_CRASH_TIME
Christopher Tatec349e59f2017-05-05 17:37:43 -07001291 > SystemClock.uptimeMillis()) {
Selim Cinekebebadb2014-03-05 22:17:26 +01001292 Slog.w(TAG, "Reverting to built-in wallpaper!");
Christopher Tateedf7d042016-03-29 18:24:25 -07001293 clearWallpaperLocked(true, FLAG_SYSTEM, mWallpaper.userId, null);
Selim Cinekebebadb2014-03-05 22:17:26 +01001294 } else {
1295 mWallpaper.lastDiedTime = SystemClock.uptimeMillis();
Adrian Roosc3f915e2016-09-06 11:40:53 -07001296
Tetsutoki Shiozawa06919212018-02-02 14:18:43 +09001297 clearWallpaperComponentLocked(mWallpaper);
1298 if (bindWallpaperComponentLocked(
1299 wpService, false, false, mWallpaper, null)) {
1300 mWallpaper.connection.scheduleTimeoutLocked();
1301 } else {
1302 Slog.w(TAG, "Reverting to built-in wallpaper!");
1303 clearWallpaperLocked(true, FLAG_SYSTEM, mWallpaper.userId, null);
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001304 }
Selim Cinekebebadb2014-03-05 22:17:26 +01001305 }
Christopher Tatec349e59f2017-05-05 17:37:43 -07001306 final String flattened = wpService.flattenToString();
Filip Gruszczynski5dcc3ac2014-10-13 15:51:39 -07001307 EventLog.writeEvent(EventLogTags.WP_WALLPAPER_CRASHED,
Filip Gruszczynski5a589432014-10-14 12:06:06 -07001308 flattened.substring(0, Math.min(flattened.length(),
1309 MAX_WALLPAPER_COMPONENT_LOG_LENGTH)));
Dianne Hackborn0cd48872009-08-13 18:51:59 -07001310 }
Christopher Tatec349e59f2017-05-05 17:37:43 -07001311 } else {
1312 if (DEBUG_LIVE) {
1313 Slog.i(TAG, "Wallpaper changed during disconnect tracking; ignoring");
1314 }
Dianne Hackborn0cd48872009-08-13 18:51:59 -07001315 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001316 }
1317 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001318
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07001319 /**
1320 * Called by a live wallpaper if its colors have changed.
1321 * @param primaryColors representation of wallpaper primary colors
wilsonshih36597d42018-12-05 18:56:39 +08001322 * @param displayId for which display
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07001323 */
1324 @Override
wilsonshih36597d42018-12-05 18:56:39 +08001325 public void onWallpaperColorsChanged(WallpaperColors primaryColors, int displayId) {
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07001326 int which;
1327 synchronized (mLock) {
1328 // Do not broadcast changes on ImageWallpaper since it's handled
1329 // internally by this class.
1330 if (mImageWallpaper.equals(mWallpaper.wallpaperComponent)) {
1331 return;
1332 }
1333
1334 mWallpaper.primaryColors = primaryColors;
1335
1336 // Live wallpapers always are system wallpapers.
1337 which = FLAG_SYSTEM;
wilsonshih36597d42018-12-05 18:56:39 +08001338 // It's also the lock screen wallpaper when we don't have a bitmap in there.
1339 if (displayId == DEFAULT_DISPLAY) {
1340 final WallpaperData lockedWallpaper = mLockWallpaperMap.get(mWallpaper.userId);
1341 if (lockedWallpaper == null) {
1342 which |= FLAG_LOCK;
1343 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07001344 }
1345 }
1346 if (which != 0) {
wilsonshih36597d42018-12-05 18:56:39 +08001347 notifyWallpaperColorsChangedOnDisplay(mWallpaper, which, displayId);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07001348 }
1349 }
1350
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001351 @Override
wilsonshihde93f492018-11-01 21:23:40 +08001352 public void attachEngine(IWallpaperEngine engine, int displayId) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001353 synchronized (mLock) {
wilsonshihde93f492018-11-01 21:23:40 +08001354 final DisplayConnector connector = getDisplayConnectorOrCreate(displayId);
1355 if (connector == null) {
Michael Wright5203a8b2013-10-03 14:16:42 -07001356 try {
wilsonshihde93f492018-11-01 21:23:40 +08001357 engine.destroy();
Michael Wright5203a8b2013-10-03 14:16:42 -07001358 } catch (RemoteException e) {
wilsonshihde93f492018-11-01 21:23:40 +08001359 Slog.w(TAG, "Failed to destroy engine", e);
Michael Wright5203a8b2013-10-03 14:16:42 -07001360 }
wilsonshihde93f492018-11-01 21:23:40 +08001361 return;
Michael Wright5203a8b2013-10-03 14:16:42 -07001362 }
wilsonshihde93f492018-11-01 21:23:40 +08001363 connector.mEngine = engine;
1364 connector.ensureStatusHandled();
1365
1366 // TODO(multi-display) TBD.
1367 if (mInfo != null && mInfo.supportsAmbientMode() && displayId == DEFAULT_DISPLAY) {
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001368 try {
Lucas Dupin4c8c3272018-11-06 17:47:48 -08001369 connector.mEngine.setInAmbientMode(mInAmbientMode, 0L /* duration */);
Lucas Dupin7517b5d2017-08-22 12:51:25 -07001370 } catch (RemoteException e) {
1371 Slog.w(TAG, "Failed to set ambient mode state", e);
1372 }
1373 }
wilsonshih36597d42018-12-05 18:56:39 +08001374 try {
1375 // This will trigger onComputeColors in the wallpaper engine.
1376 // It's fine to be locked in here since the binder is oneway.
1377 connector.mEngine.requestWallpaperColors();
1378 } catch (RemoteException e) {
1379 Slog.w(TAG, "Failed to request wallpaper colors", e);
Lucas Dupin50ba9912017-07-14 11:55:05 -07001380 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001381 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001382 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001383
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001384 @Override
1385 public void engineShown(IWallpaperEngine engine) {
1386 synchronized (mLock) {
1387 if (mReply != null) {
1388 long ident = Binder.clearCallingIdentity();
1389 try {
1390 mReply.sendResult(null);
1391 } catch (RemoteException e) {
1392 Binder.restoreCallingIdentity(ident);
1393 }
1394 mReply = null;
1395 }
1396 }
1397 }
1398
1399 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001400 public ParcelFileDescriptor setWallpaper(String name) {
1401 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001402 if (mWallpaper.connection == this) {
Christopher Tatead3c2592016-01-20 18:13:17 -08001403 return updateWallpaperBitmapLocked(name, mWallpaper, null);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001404 }
1405 return null;
1406 }
1407 }
1408 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001409
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001410 class MyPackageMonitor extends PackageMonitor {
1411 @Override
1412 public void onPackageUpdateFinished(String packageName, int uid) {
1413 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -07001414 if (mCurrentUserId != getChangingUserId()) {
1415 return;
1416 }
1417 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
1418 if (wallpaper != null) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001419 final ComponentName wpService = wallpaper.wallpaperComponent;
1420 if (wpService != null && wpService.getPackageName().equals(packageName)) {
1421 if (DEBUG_LIVE) {
1422 Slog.i(TAG, "Wallpaper " + wpService + " update has finished");
1423 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001424 wallpaper.wallpaperUpdating = false;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001425 clearWallpaperComponentLocked(wallpaper);
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001426 if (!bindWallpaperComponentLocked(wpService, false, false,
Dianne Hackbornc72fc672012-09-20 13:12:03 -07001427 wallpaper, null)) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001428 Slog.w(TAG, "Wallpaper " + wpService
1429 + " no longer available; reverting to default");
Christopher Tateedf7d042016-03-29 18:24:25 -07001430 clearWallpaperLocked(false, FLAG_SYSTEM, wallpaper.userId, null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001431 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001432 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001433 }
1434 }
1435 }
1436
1437 @Override
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001438 public void onPackageModified(String packageName) {
1439 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -07001440 if (mCurrentUserId != getChangingUserId()) {
1441 return;
1442 }
1443 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
1444 if (wallpaper != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001445 if (wallpaper.wallpaperComponent == null
1446 || !wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -07001447 return;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001448 }
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001449 doPackagesChangedLocked(true, wallpaper);
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001450 }
1451 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001452 }
1453
1454 @Override
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001455 public void onPackageUpdateStarted(String packageName, int uid) {
1456 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -07001457 if (mCurrentUserId != getChangingUserId()) {
1458 return;
1459 }
1460 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
1461 if (wallpaper != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001462 if (wallpaper.wallpaperComponent != null
1463 && wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001464 if (DEBUG_LIVE) {
1465 Slog.i(TAG, "Wallpaper service " + wallpaper.wallpaperComponent
1466 + " is updating");
1467 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001468 wallpaper.wallpaperUpdating = true;
Adrian Roosc3f915e2016-09-06 11:40:53 -07001469 if (wallpaper.connection != null) {
1470 FgThread.getHandler().removeCallbacks(
1471 wallpaper.connection.mResetRunnable);
1472 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001473 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001474 }
1475 }
1476 }
1477
1478 @Override
1479 public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001480 synchronized (mLock) {
1481 boolean changed = false;
Dianne Hackbornc72fc672012-09-20 13:12:03 -07001482 if (mCurrentUserId != getChangingUserId()) {
1483 return false;
1484 }
1485 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
1486 if (wallpaper != null) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001487 boolean res = doPackagesChangedLocked(doit, wallpaper);
1488 changed |= res;
1489 }
1490 return changed;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001491 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001492 }
1493
1494 @Override
1495 public void onSomePackagesChanged() {
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001496 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -07001497 if (mCurrentUserId != getChangingUserId()) {
1498 return;
1499 }
1500 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
1501 if (wallpaper != null) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001502 doPackagesChangedLocked(true, wallpaper);
1503 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001504 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001505 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001506
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001507 boolean doPackagesChangedLocked(boolean doit, WallpaperData wallpaper) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001508 boolean changed = false;
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001509 if (wallpaper.wallpaperComponent != null) {
1510 int change = isPackageDisappearing(wallpaper.wallpaperComponent
1511 .getPackageName());
1512 if (change == PACKAGE_PERMANENT_CHANGE
1513 || change == PACKAGE_TEMPORARY_CHANGE) {
1514 changed = true;
1515 if (doit) {
1516 Slog.w(TAG, "Wallpaper uninstalled, removing: "
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001517 + wallpaper.wallpaperComponent);
Christopher Tateedf7d042016-03-29 18:24:25 -07001518 clearWallpaperLocked(false, FLAG_SYSTEM, wallpaper.userId, null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001519 }
1520 }
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001521 }
1522 if (wallpaper.nextWallpaperComponent != null) {
1523 int change = isPackageDisappearing(wallpaper.nextWallpaperComponent
1524 .getPackageName());
1525 if (change == PACKAGE_PERMANENT_CHANGE
1526 || change == PACKAGE_TEMPORARY_CHANGE) {
1527 wallpaper.nextWallpaperComponent = null;
1528 }
1529 }
1530 if (wallpaper.wallpaperComponent != null
1531 && isPackageModified(wallpaper.wallpaperComponent.getPackageName())) {
1532 try {
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001533 mContext.getPackageManager().getServiceInfo(wallpaper.wallpaperComponent,
1534 PackageManager.MATCH_DIRECT_BOOT_AWARE
1535 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001536 } catch (NameNotFoundException e) {
1537 Slog.w(TAG, "Wallpaper component gone, removing: "
1538 + wallpaper.wallpaperComponent);
Christopher Tateedf7d042016-03-29 18:24:25 -07001539 clearWallpaperLocked(false, FLAG_SYSTEM, wallpaper.userId, null);
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001540 }
1541 }
1542 if (wallpaper.nextWallpaperComponent != null
1543 && isPackageModified(wallpaper.nextWallpaperComponent.getPackageName())) {
1544 try {
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001545 mContext.getPackageManager().getServiceInfo(wallpaper.nextWallpaperComponent,
1546 PackageManager.MATCH_DIRECT_BOOT_AWARE
1547 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001548 } catch (NameNotFoundException e) {
1549 wallpaper.nextWallpaperComponent = null;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001550 }
1551 }
1552 return changed;
1553 }
1554 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001555
Dianne Hackborn8cc6a502009-08-05 21:29:42 -07001556 public WallpaperManagerService(Context context) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001557 if (DEBUG) Slog.v(TAG, "WallpaperService startup");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001558 mContext = context;
Christopher Tate762dfd12016-10-10 17:44:48 -07001559 mShuttingDown = false;
Justin Koh29c30162014-09-05 17:10:10 -07001560 mImageWallpaper = ComponentName.unflattenFromString(
1561 context.getResources().getString(R.string.image_wallpaper_component));
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001562 mDefaultWallpaperComponent = WallpaperManager.getDefaultWallpaperComponent(context);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001563 mIWindowManager = IWindowManager.Stub.asInterface(
1564 ServiceManager.getService(Context.WINDOW_SERVICE));
Andrii Kuliandd989612019-02-21 12:13:28 -08001565 mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
Amith Yamasani4e2820c2012-08-28 22:17:23 -07001566 mIPackageManager = AppGlobals.getPackageManager();
Benjamin Franzf3ece362015-02-11 10:51:10 +00001567 mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
wilsonshihde93f492018-11-01 21:23:40 +08001568 mDisplayManager = mContext.getSystemService(DisplayManager.class);
1569 mDisplayManager.registerDisplayListener(mDisplayListener, null /* handler */);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001570 mMonitor = new MyPackageMonitor();
Jaekyun Seokad7d90f2018-04-04 01:57:18 +09001571 mColorsChangedListeners = new SparseArray<>();
wilsonshih643bf132019-02-27 12:49:19 +08001572
1573 LocalServices.addService(WallpaperManagerInternal.class, new LocalService());
1574 }
1575
1576 private final class LocalService extends WallpaperManagerInternal {
1577 @Override
1578 public void onDisplayReady(int displayId) {
1579 onDisplayReadyInternal(displayId);
1580 }
Jaekyun Seokad7d90f2018-04-04 01:57:18 +09001581 }
1582
1583 void initialize() {
1584 mMonitor.register(mContext, null, UserHandle.ALL, true);
Xiaohui Chen233d94c2015-07-30 15:08:00 -07001585 getWallpaperDir(UserHandle.USER_SYSTEM).mkdirs();
Christopher Tatef717b932017-09-11 15:52:54 -07001586
1587 // Initialize state from the persistent store, then guarantee that the
1588 // WallpaperData for the system imagery is instantiated & active, creating
1589 // it from defaults if necessary.
Christopher Tated7faf532016-02-25 12:43:38 -08001590 loadSettingsLocked(UserHandle.USER_SYSTEM, false);
Christopher Tatef717b932017-09-11 15:52:54 -07001591 getWallpaperSafeLocked(UserHandle.USER_SYSTEM, FLAG_SYSTEM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001592 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001593
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001594 private static File getWallpaperDir(int userId) {
Amith Yamasani61f57372012-08-31 12:12:28 -07001595 return Environment.getUserSystemDirectory(userId);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001596 }
1597
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001598 @Override
1599 protected void finalize() throws Throwable {
1600 super.finalize();
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001601 for (int i = 0; i < mWallpaperMap.size(); i++) {
1602 WallpaperData wallpaper = mWallpaperMap.valueAt(i);
1603 wallpaper.wallpaperObserver.stopWatching();
1604 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001605 }
Amith Yamasani13593602012-03-22 16:16:17 -07001606
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001607 void systemReady() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001608 if (DEBUG) Slog.v(TAG, "systemReady");
Jaekyun Seokad7d90f2018-04-04 01:57:18 +09001609 initialize();
1610
Xiaohui Chen233d94c2015-07-30 15:08:00 -07001611 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.USER_SYSTEM);
Christopher Tate2cdd3f22016-03-14 17:36:16 -07001612 // If we think we're going to be using the system image wallpaper imagery, make
1613 // sure we have something to render
1614 if (mImageWallpaper.equals(wallpaper.nextWallpaperComponent)) {
1615 // No crop file? Make sure we've finished the processing sequence if necessary
1616 if (!wallpaper.cropExists()) {
1617 if (DEBUG) {
1618 Slog.i(TAG, "No crop; regenerating from source");
1619 }
1620 generateCrop(wallpaper);
1621 }
1622 // Still nothing? Fall back to default.
1623 if (!wallpaper.cropExists()) {
1624 if (DEBUG) {
1625 Slog.i(TAG, "Unable to regenerate crop; resetting");
1626 }
Christopher Tateedf7d042016-03-29 18:24:25 -07001627 clearWallpaperLocked(false, FLAG_SYSTEM, UserHandle.USER_SYSTEM, null);
Christopher Tate2cdd3f22016-03-14 17:36:16 -07001628 }
1629 } else {
1630 if (DEBUG) {
1631 Slog.i(TAG, "Nondefault wallpaper component; gracefully ignoring");
1632 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001633 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001634
Amith Yamasani13593602012-03-22 16:16:17 -07001635 IntentFilter userFilter = new IntentFilter();
Amith Yamasani13593602012-03-22 16:16:17 -07001636 userFilter.addAction(Intent.ACTION_USER_REMOVED);
1637 mContext.registerReceiver(new BroadcastReceiver() {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001638 @Override
Amith Yamasani13593602012-03-22 16:16:17 -07001639 public void onReceive(Context context, Intent intent) {
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001640 final String action = intent.getAction();
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001641 if (Intent.ACTION_USER_REMOVED.equals(action)) {
Amith Yamasani756901d2012-10-12 12:30:07 -07001642 onRemoveUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
1643 UserHandle.USER_NULL));
Amith Yamasani13593602012-03-22 16:16:17 -07001644 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001645 }
Amith Yamasani13593602012-03-22 16:16:17 -07001646 }, userFilter);
Amith Yamasani756901d2012-10-12 12:30:07 -07001647
Christopher Tate762dfd12016-10-10 17:44:48 -07001648 final IntentFilter shutdownFilter = new IntentFilter(Intent.ACTION_SHUTDOWN);
1649 mContext.registerReceiver(new BroadcastReceiver() {
1650 @Override
1651 public void onReceive(Context context, Intent intent) {
1652 if (Intent.ACTION_SHUTDOWN.equals(intent.getAction())) {
1653 if (DEBUG) {
1654 Slog.i(TAG, "Shutting down");
1655 }
1656 synchronized (mLock) {
1657 mShuttingDown = true;
1658 }
1659 }
1660 }
1661 }, shutdownFilter);
1662
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001663 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001664 ActivityManager.getService().registerUserSwitchObserver(
Sudheer Shanka2c4522c2016-08-27 20:53:28 -07001665 new UserSwitchObserver() {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001666 @Override
1667 public void onUserSwitching(int newUserId, IRemoteCallback reply) {
1668 switchUser(newUserId, reply);
1669 }
Fyodor Kupolov0b77ef92016-06-20 17:16:52 -07001670 }, TAG);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001671 } catch (RemoteException e) {
Fyodor Kupolov0b77ef92016-06-20 17:16:52 -07001672 e.rethrowAsRuntimeException();
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001673 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001674 }
1675
Amith Yamasani09e9cdc2013-11-06 14:54:50 -08001676 /** Called by SystemBackupAgent */
1677 public String getName() {
1678 // Verify caller is the system
1679 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
1680 throw new RuntimeException("getName() can only be called from the system process");
1681 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001682 synchronized (mLock) {
1683 return mWallpaperMap.get(0).name;
1684 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001685 }
1686
Christopher Tatebe132e62016-02-10 12:59:49 -08001687 void stopObserver(WallpaperData wallpaper) {
1688 if (wallpaper != null) {
1689 if (wallpaper.wallpaperObserver != null) {
1690 wallpaper.wallpaperObserver.stopWatching();
1691 wallpaper.wallpaperObserver = null;
Amith Yamasani13593602012-03-22 16:16:17 -07001692 }
Amith Yamasani756901d2012-10-12 12:30:07 -07001693 }
1694 }
1695
Christopher Tatebe132e62016-02-10 12:59:49 -08001696 void stopObserversLocked(int userId) {
1697 stopObserver(mWallpaperMap.get(userId));
1698 stopObserver(mLockWallpaperMap.get(userId));
1699 mWallpaperMap.remove(userId);
1700 mLockWallpaperMap.remove(userId);
1701 }
1702
Daichi Hirono4bbf8522017-12-06 10:34:18 +09001703 @Override
1704 public void onBootPhase(int phase) {
1705 if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
1706 systemReady();
1707 } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
1708 switchUser(UserHandle.USER_SYSTEM, null);
1709 }
1710 }
1711
1712 @Override
1713 public void onUnlockUser(final int userId) {
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001714 synchronized (mLock) {
Christopher Tate38a5dc32016-07-20 15:10:18 -07001715 if (mCurrentUserId == userId) {
1716 if (mWaitingForUnlock) {
wilsonshiha47fcc92018-04-26 14:27:38 +08001717 // the desired wallpaper is not direct-boot aware, load it now
1718 final WallpaperData systemWallpaper =
1719 getWallpaperSafeLocked(userId, FLAG_SYSTEM);
1720 switchWallpaper(systemWallpaper, null);
Christopher Tate38a5dc32016-07-20 15:10:18 -07001721 }
Christopher Tate190e8532016-07-11 11:35:34 -07001722
1723 // Make sure that the SELinux labeling of all the relevant files is correct.
1724 // This corrects for mislabeling bugs that might have arisen from move-to
1725 // operations involving the wallpaper files. This isn't timing-critical,
1726 // so we do it in the background to avoid holding up the user unlock operation.
wilsonshiha282bf72018-11-30 12:48:05 +08001727 if (!mUserRestorecon.get(userId)) {
1728 mUserRestorecon.put(userId, true);
Christopher Tate38a5dc32016-07-20 15:10:18 -07001729 Runnable relabeler = new Runnable() {
1730 @Override
1731 public void run() {
1732 final File wallpaperDir = getWallpaperDir(userId);
1733 for (String filename : sPerUserFiles) {
1734 File f = new File(wallpaperDir, filename);
1735 if (f.exists()) {
1736 SELinux.restorecon(f);
1737 }
Christopher Tate190e8532016-07-11 11:35:34 -07001738 }
1739 }
Christopher Tate38a5dc32016-07-20 15:10:18 -07001740 };
1741 BackgroundThread.getHandler().post(relabeler);
1742 }
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001743 }
1744 }
1745 }
1746
Amith Yamasani756901d2012-10-12 12:30:07 -07001747 void onRemoveUser(int userId) {
1748 if (userId < 1) return;
Christopher Tatebe132e62016-02-10 12:59:49 -08001749
1750 final File wallpaperDir = getWallpaperDir(userId);
Amith Yamasani756901d2012-10-12 12:30:07 -07001751 synchronized (mLock) {
Christopher Tatebe132e62016-02-10 12:59:49 -08001752 stopObserversLocked(userId);
1753 for (String filename : sPerUserFiles) {
1754 new File(wallpaperDir, filename).delete();
1755 }
wilsonshiha282bf72018-11-30 12:48:05 +08001756 mUserRestorecon.delete(userId);
Amith Yamasani13593602012-03-22 16:16:17 -07001757 }
1758 }
1759
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001760 void switchUser(int userId, IRemoteCallback reply) {
Lucas Dupin9272d452017-09-14 14:15:42 -07001761 final WallpaperData systemWallpaper;
1762 final WallpaperData lockWallpaper;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001763 synchronized (mLock) {
Jaekyun Seokad7d90f2018-04-04 01:57:18 +09001764 if (mCurrentUserId == userId) {
1765 return;
1766 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001767 mCurrentUserId = userId;
Lucas Dupin50ba9912017-07-14 11:55:05 -07001768 systemWallpaper = getWallpaperSafeLocked(userId, FLAG_SYSTEM);
Lucas Dupin9272d452017-09-14 14:15:42 -07001769 final WallpaperData tmpLockWallpaper = mLockWallpaperMap.get(userId);
1770 lockWallpaper = tmpLockWallpaper == null ? systemWallpaper : tmpLockWallpaper;
Lucas Dupin50ba9912017-07-14 11:55:05 -07001771 // Not started watching yet, in case wallpaper data was loaded for other reasons.
1772 if (systemWallpaper.wallpaperObserver == null) {
1773 systemWallpaper.wallpaperObserver = new WallpaperObserver(systemWallpaper);
1774 systemWallpaper.wallpaperObserver.startWatching();
1775 }
1776 switchWallpaper(systemWallpaper, reply);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001777 }
Lucas Dupin9272d452017-09-14 14:15:42 -07001778
1779 // Offload color extraction to another thread since switchUser will be called
1780 // from the main thread.
1781 FgThread.getHandler().post(() -> {
1782 notifyWallpaperColorsChanged(systemWallpaper, FLAG_SYSTEM);
1783 notifyWallpaperColorsChanged(lockWallpaper, FLAG_LOCK);
wilsonshih36597d42018-12-05 18:56:39 +08001784 notifyWallpaperColorsChanged(mFallbackWallpaper, FLAG_SYSTEM);
Lucas Dupin9272d452017-09-14 14:15:42 -07001785 });
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001786 }
1787
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001788 void switchWallpaper(WallpaperData wallpaper, IRemoteCallback reply) {
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001789 synchronized (mLock) {
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001790 mWaitingForUnlock = false;
1791 final ComponentName cname = wallpaper.wallpaperComponent != null ?
1792 wallpaper.wallpaperComponent : wallpaper.nextWallpaperComponent;
1793 if (!bindWallpaperComponentLocked(cname, true, false, wallpaper, reply)) {
1794 // We failed to bind the desired wallpaper, but that might
1795 // happen if the wallpaper isn't direct-boot aware
1796 ServiceInfo si = null;
1797 try {
1798 si = mIPackageManager.getServiceInfo(cname,
1799 PackageManager.MATCH_DIRECT_BOOT_UNAWARE, wallpaper.userId);
1800 } catch (RemoteException ignored) {
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001801 }
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001802
1803 if (si == null) {
1804 Slog.w(TAG, "Failure starting previous wallpaper; clearing");
1805 clearWallpaperLocked(false, FLAG_SYSTEM, wallpaper.userId, reply);
1806 } else {
1807 Slog.w(TAG, "Wallpaper isn't direct boot aware; using fallback until unlocked");
1808 // We might end up persisting the current wallpaper data
1809 // while locked, so pretend like the component was actually
1810 // bound into place
1811 wallpaper.wallpaperComponent = wallpaper.nextWallpaperComponent;
1812 final WallpaperData fallback = new WallpaperData(wallpaper.userId,
1813 WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP);
wilsonshih81e10a72018-11-15 10:54:21 +08001814 ensureSaneWallpaperData(fallback, DEFAULT_DISPLAY);
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001815 bindWallpaperComponentLocked(mImageWallpaper, true, false, fallback, reply);
1816 mWaitingForUnlock = true;
1817 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001818 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001819 }
1820 }
1821
Christopher Tatebe132e62016-02-10 12:59:49 -08001822 @Override
1823 public void clearWallpaper(String callingPackage, int which, int userId) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001824 if (DEBUG) Slog.v(TAG, "clearWallpaper");
Benjamin Franzf3ece362015-02-11 10:51:10 +00001825 checkPermission(android.Manifest.permission.SET_WALLPAPER);
Christopher Tate98d609c2016-05-18 17:31:58 -07001826 if (!isWallpaperSupported(callingPackage) || !isSetWallpaperAllowed(callingPackage)) {
Benjamin Franzf3ece362015-02-11 10:51:10 +00001827 return;
1828 }
Christopher Tatee409f0e2016-03-21 14:53:15 -07001829 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
1830 Binder.getCallingUid(), userId, false, true, "clearWallpaper", null);
Christopher Tatebe132e62016-02-10 12:59:49 -08001831
Lucas Dupin41f69422017-05-03 15:26:22 -07001832 WallpaperData data = null;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001833 synchronized (mLock) {
Christopher Tatebe132e62016-02-10 12:59:49 -08001834 clearWallpaperLocked(false, which, userId, null);
Lucas Dupin41f69422017-05-03 15:26:22 -07001835
1836 if (which == FLAG_LOCK) {
1837 data = mLockWallpaperMap.get(userId);
1838 }
1839 if (which == FLAG_SYSTEM || data == null) {
1840 data = mWallpaperMap.get(userId);
1841 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001842 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07001843
1844 // When clearing a wallpaper, broadcast new valid colors
Lucas Dupin41f69422017-05-03 15:26:22 -07001845 if (data != null) {
1846 notifyWallpaperColorsChanged(data, which);
wilsonshih36597d42018-12-05 18:56:39 +08001847 notifyWallpaperColorsChanged(mFallbackWallpaper, FLAG_SYSTEM);
Lucas Dupin41f69422017-05-03 15:26:22 -07001848 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001849 }
1850
Christopher Tatebe132e62016-02-10 12:59:49 -08001851 void clearWallpaperLocked(boolean defaultFailed, int which, int userId, IRemoteCallback reply) {
Christopher Tateedf7d042016-03-29 18:24:25 -07001852 if (which != FLAG_SYSTEM && which != FLAG_LOCK) {
Christopher Tate105540d2018-03-21 13:03:09 -07001853 throw new IllegalArgumentException("Must specify exactly one kind of wallpaper to clear");
Christopher Tatebe132e62016-02-10 12:59:49 -08001854 }
1855
1856 WallpaperData wallpaper = null;
Christopher Tateedf7d042016-03-29 18:24:25 -07001857 if (which == FLAG_LOCK) {
Christopher Tatebe132e62016-02-10 12:59:49 -08001858 wallpaper = mLockWallpaperMap.get(userId);
1859 if (wallpaper == null) {
1860 // It's already gone; we're done.
Christopher Tate79a24572016-03-02 14:42:44 -08001861 if (DEBUG) {
1862 Slog.i(TAG, "Lock wallpaper already cleared");
1863 }
Christopher Tatebe132e62016-02-10 12:59:49 -08001864 return;
1865 }
1866 } else {
1867 wallpaper = mWallpaperMap.get(userId);
1868 if (wallpaper == null) {
1869 // Might need to bring it in the first time to establish our rewrite
Christopher Tated7faf532016-02-25 12:43:38 -08001870 loadSettingsLocked(userId, false);
Christopher Tatebe132e62016-02-10 12:59:49 -08001871 wallpaper = mWallpaperMap.get(userId);
1872 }
1873 }
Benjamin Franzf3ece362015-02-11 10:51:10 +00001874 if (wallpaper == null) {
1875 return;
1876 }
Christopher Tatebe132e62016-02-10 12:59:49 -08001877
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001878 final long ident = Binder.clearCallingIdentity();
1879 try {
Christopher Tatebe132e62016-02-10 12:59:49 -08001880 if (wallpaper.wallpaperFile.exists()) {
1881 wallpaper.wallpaperFile.delete();
1882 wallpaper.cropFile.delete();
Christopher Tateedf7d042016-03-29 18:24:25 -07001883 if (which == FLAG_LOCK) {
Christopher Tate79a24572016-03-02 14:42:44 -08001884 mLockWallpaperMap.remove(userId);
Christopher Tatebe132e62016-02-10 12:59:49 -08001885 final IWallpaperManagerCallback cb = mKeyguardListener;
1886 if (cb != null) {
Christopher Tate79a24572016-03-02 14:42:44 -08001887 if (DEBUG) {
1888 Slog.i(TAG, "Notifying keyguard of lock wallpaper clear");
1889 }
Christopher Tatebe132e62016-02-10 12:59:49 -08001890 try {
1891 cb.onWallpaperChanged();
1892 } catch (RemoteException e) {
1893 // Oh well it went away; no big deal
1894 }
1895 }
Christopher Tate79a24572016-03-02 14:42:44 -08001896 saveSettingsLocked(userId);
Christopher Tatebe132e62016-02-10 12:59:49 -08001897 return;
1898 }
1899 }
1900
Christopher Tateecd827a2014-09-05 17:42:34 -07001901 RuntimeException e = null;
1902 try {
Lucas Dupin75ec3792017-06-29 14:07:18 -07001903 wallpaper.primaryColors = null;
Christopher Tateecd827a2014-09-05 17:42:34 -07001904 wallpaper.imageWallpaperPending = false;
1905 if (userId != mCurrentUserId) return;
1906 if (bindWallpaperComponentLocked(defaultFailed
1907 ? mImageWallpaper
1908 : null, true, false, wallpaper, reply)) {
1909 return;
1910 }
1911 } catch (IllegalArgumentException e1) {
1912 e = e1;
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001913 }
Christopher Tateecd827a2014-09-05 17:42:34 -07001914
1915 // This can happen if the default wallpaper component doesn't
1916 // exist. This should be a system configuration problem, but
1917 // let's not let it crash the system and just live with no
1918 // wallpaper.
1919 Slog.e(TAG, "Default wallpaper component not found!", e);
1920 clearWallpaperComponentLocked(wallpaper);
1921 if (reply != null) {
1922 try {
1923 reply.sendResult(null);
1924 } catch (RemoteException e1) {
1925 }
1926 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001927 } finally {
1928 Binder.restoreCallingIdentity(ident);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001929 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001930 }
1931
1932 public boolean hasNamedWallpaper(String name) {
1933 synchronized (mLock) {
Amith Yamasani6474c4c2012-10-04 14:55:42 -07001934 List<UserInfo> users;
1935 long ident = Binder.clearCallingIdentity();
1936 try {
1937 users = ((UserManager) mContext.getSystemService(Context.USER_SERVICE)).getUsers();
1938 } finally {
1939 Binder.restoreCallingIdentity(ident);
1940 }
1941 for (UserInfo user: users) {
Benjamin Franzf3ece362015-02-11 10:51:10 +00001942 // ignore managed profiles
1943 if (user.isManagedProfile()) {
1944 continue;
1945 }
Amith Yamasani6474c4c2012-10-04 14:55:42 -07001946 WallpaperData wd = mWallpaperMap.get(user.id);
1947 if (wd == null) {
1948 // User hasn't started yet, so load her settings to peek at the wallpaper
Christopher Tated7faf532016-02-25 12:43:38 -08001949 loadSettingsLocked(user.id, false);
Amith Yamasani6474c4c2012-10-04 14:55:42 -07001950 wd = mWallpaperMap.get(user.id);
1951 }
1952 if (wd != null && name.equals(wd.name)) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001953 return true;
1954 }
1955 }
1956 }
1957 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001958 }
1959
wilsonshih81e10a72018-11-15 10:54:21 +08001960 private boolean isValidDisplay(int displayId) {
1961 return mDisplayManager.getDisplay(displayId) != null;
1962 }
1963
1964 /**
1965 * Sets the dimension hint for the wallpaper. These hints indicate the desired
1966 * minimum width and height for the wallpaper in a particular display.
1967 */
1968 public void setDimensionHints(int width, int height, String callingPackage, int displayId)
Benjamin Franzf3ece362015-02-11 10:51:10 +00001969 throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001970 checkPermission(android.Manifest.permission.SET_WALLPAPER_HINTS);
Benjamin Franzf3ece362015-02-11 10:51:10 +00001971 if (!isWallpaperSupported(callingPackage)) {
1972 return;
1973 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001974 synchronized (mLock) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001975 int userId = UserHandle.getCallingUserId();
Christopher Tateedf7d042016-03-29 18:24:25 -07001976 WallpaperData wallpaper = getWallpaperSafeLocked(userId, FLAG_SYSTEM);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001977 if (width <= 0 || height <= 0) {
1978 throw new IllegalArgumentException("width and height must be > 0");
1979 }
1980
wilsonshih81e10a72018-11-15 10:54:21 +08001981 if (!isValidDisplay(displayId)) {
1982 throw new IllegalArgumentException("Cannot find display with id=" + displayId);
1983 }
1984
wilsonshiha282bf72018-11-30 12:48:05 +08001985 final DisplayData wpdData = getDisplayDataOrCreate(displayId);
wilsonshih81e10a72018-11-15 10:54:21 +08001986 if (width != wpdData.mWidth || height != wpdData.mHeight) {
1987 wpdData.mWidth = width;
1988 wpdData.mHeight = height;
1989 if (displayId == DEFAULT_DISPLAY) saveSettingsLocked(userId);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001990 if (mCurrentUserId != userId) return; // Don't change the properties now
1991 if (wallpaper.connection != null) {
wilsonshih81e10a72018-11-15 10:54:21 +08001992 final WallpaperConnection.DisplayConnector connector = wallpaper.connection
1993 .getDisplayConnectorOrCreate(displayId);
1994 final IWallpaperEngine engine = connector != null ? connector.mEngine : null;
wilsonshihde93f492018-11-01 21:23:40 +08001995 if (engine != null) {
Dianne Hackborn284ac932009-08-28 10:34:25 -07001996 try {
wilsonshihde93f492018-11-01 21:23:40 +08001997 engine.setDesiredSize(width, height);
Dianne Hackborn284ac932009-08-28 10:34:25 -07001998 } catch (RemoteException e) {
1999 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002000 notifyCallbacksLocked(wallpaper);
wilsonshih81e10a72018-11-15 10:54:21 +08002001 } else if (wallpaper.connection.mService != null && connector != null) {
Michael Wright5203a8b2013-10-03 14:16:42 -07002002 // We've attached to the service but the engine hasn't attached back to us
2003 // yet. This means it will be created with the previous dimensions, so we
2004 // need to update it to the new dimensions once it attaches.
wilsonshih81e10a72018-11-15 10:54:21 +08002005 connector.mDimensionsChanged = true;
Dianne Hackborn284ac932009-08-28 10:34:25 -07002006 }
2007 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002008 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002009 }
2010 }
2011
wilsonshih81e10a72018-11-15 10:54:21 +08002012 /**
2013 * Returns the desired minimum width for the wallpaper in a particular display.
2014 */
2015 public int getWidthHint(int displayId) throws RemoteException {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002016 synchronized (mLock) {
wilsonshih81e10a72018-11-15 10:54:21 +08002017 if (!isValidDisplay(displayId)) {
2018 throw new IllegalArgumentException("Cannot find display with id=" + displayId);
2019 }
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07002020 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.getCallingUserId());
Benjamin Franzf3ece362015-02-11 10:51:10 +00002021 if (wallpaper != null) {
wilsonshiha282bf72018-11-30 12:48:05 +08002022 final DisplayData wpdData = getDisplayDataOrCreate(displayId);
wilsonshih81e10a72018-11-15 10:54:21 +08002023 return wpdData.mWidth;
Benjamin Franzf3ece362015-02-11 10:51:10 +00002024 } else {
2025 return 0;
2026 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002027 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002028 }
2029
wilsonshih81e10a72018-11-15 10:54:21 +08002030 /**
2031 * Returns the desired minimum height for the wallpaper in a particular display.
2032 */
2033 public int getHeightHint(int displayId) throws RemoteException {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002034 synchronized (mLock) {
wilsonshih81e10a72018-11-15 10:54:21 +08002035 if (!isValidDisplay(displayId)) {
2036 throw new IllegalArgumentException("Cannot find display with id=" + displayId);
2037 }
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07002038 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.getCallingUserId());
Benjamin Franzf3ece362015-02-11 10:51:10 +00002039 if (wallpaper != null) {
wilsonshiha282bf72018-11-30 12:48:05 +08002040 final DisplayData wpdData = getDisplayDataOrCreate(displayId);
wilsonshih81e10a72018-11-15 10:54:21 +08002041 return wpdData.mHeight;
Benjamin Franzf3ece362015-02-11 10:51:10 +00002042 } else {
2043 return 0;
2044 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002045 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002046 }
2047
wilsonshih81e10a72018-11-15 10:54:21 +08002048 /**
2049 * Sets extra padding that we would like the wallpaper to have outside of the display.
2050 */
2051 public void setDisplayPadding(Rect padding, String callingPackage, int displayId) {
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002052 checkPermission(android.Manifest.permission.SET_WALLPAPER_HINTS);
Benjamin Franzf3ece362015-02-11 10:51:10 +00002053 if (!isWallpaperSupported(callingPackage)) {
2054 return;
2055 }
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002056 synchronized (mLock) {
wilsonshih81e10a72018-11-15 10:54:21 +08002057 if (!isValidDisplay(displayId)) {
2058 throw new IllegalArgumentException("Cannot find display with id=" + displayId);
2059 }
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002060 int userId = UserHandle.getCallingUserId();
Christopher Tateedf7d042016-03-29 18:24:25 -07002061 WallpaperData wallpaper = getWallpaperSafeLocked(userId, FLAG_SYSTEM);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002062 if (padding.left < 0 || padding.top < 0 || padding.right < 0 || padding.bottom < 0) {
2063 throw new IllegalArgumentException("padding must be positive: " + padding);
2064 }
2065
wilsonshiha282bf72018-11-30 12:48:05 +08002066 final DisplayData wpdData = getDisplayDataOrCreate(displayId);
wilsonshih81e10a72018-11-15 10:54:21 +08002067 if (!padding.equals(wpdData.mPadding)) {
2068 wpdData.mPadding.set(padding);
2069 if (displayId == DEFAULT_DISPLAY) saveSettingsLocked(userId);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002070 if (mCurrentUserId != userId) return; // Don't change the properties now
2071 if (wallpaper.connection != null) {
wilsonshih81e10a72018-11-15 10:54:21 +08002072 final WallpaperConnection.DisplayConnector connector = wallpaper.connection
2073 .getDisplayConnectorOrCreate(displayId);
2074 final IWallpaperEngine engine = connector != null ? connector.mEngine : null;
wilsonshihde93f492018-11-01 21:23:40 +08002075 if (engine != null) {
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002076 try {
wilsonshihde93f492018-11-01 21:23:40 +08002077 engine.setDisplayPadding(padding);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002078 } catch (RemoteException e) {
2079 }
2080 notifyCallbacksLocked(wallpaper);
wilsonshih81e10a72018-11-15 10:54:21 +08002081 } else if (wallpaper.connection.mService != null && connector != null) {
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002082 // We've attached to the service but the engine hasn't attached back to us
2083 // yet. This means it will be created with the previous dimensions, so we
2084 // need to update it to the new dimensions once it attaches.
wilsonshih81e10a72018-11-15 10:54:21 +08002085 connector.mPaddingChanged = true;
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002086 }
2087 }
2088 }
2089 }
2090 }
2091
Christopher Tate93252de2017-06-15 14:48:41 -07002092 private void enforceCallingOrSelfPermissionAndAppOp(String permission, final String callingPkg,
2093 final int callingUid, String message) {
2094 mContext.enforceCallingOrSelfPermission(permission, message);
2095
2096 final String opName = AppOpsManager.permissionToOp(permission);
2097 if (opName != null) {
2098 final int appOpMode = mAppOpsManager.noteOp(opName, callingUid, callingPkg);
2099 if (appOpMode != AppOpsManager.MODE_ALLOWED) {
2100 throw new SecurityException(
2101 message + ": " + callingPkg + " is not allowed to " + permission);
2102 }
2103 }
2104 }
2105
Yorke Leedcd93cc2016-01-08 14:12:55 -08002106 @Override
Christopher Tate93252de2017-06-15 14:48:41 -07002107 public ParcelFileDescriptor getWallpaper(String callingPkg, IWallpaperManagerCallback cb,
2108 final int which, Bundle outParams, int wallpaperUserId) {
Christopher Tate8a71c482017-08-14 16:45:03 -07002109 final int hasPrivilege = mContext.checkCallingOrSelfPermission(
2110 android.Manifest.permission.READ_WALLPAPER_INTERNAL);
2111 if (hasPrivilege != PackageManager.PERMISSION_GRANTED) {
2112 enforceCallingOrSelfPermissionAndAppOp(android.Manifest.permission.READ_EXTERNAL_STORAGE,
2113 callingPkg, Binder.getCallingUid(), "read wallpaper");
2114 }
Christopher Tate93252de2017-06-15 14:48:41 -07002115
Christopher Tatee409f0e2016-03-21 14:53:15 -07002116 wallpaperUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
2117 Binder.getCallingUid(), wallpaperUserId, false, true, "getWallpaper", null);
Christopher Tatebe132e62016-02-10 12:59:49 -08002118
Christopher Tateedf7d042016-03-29 18:24:25 -07002119 if (which != FLAG_SYSTEM && which != FLAG_LOCK) {
Christopher Tatebe132e62016-02-10 12:59:49 -08002120 throw new IllegalArgumentException("Must specify exactly one kind of wallpaper to read");
2121 }
2122
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002123 synchronized (mLock) {
Vadim Tryshev8cde0792016-02-19 17:02:15 -08002124 final SparseArray<WallpaperData> whichSet =
Christopher Tateedf7d042016-03-29 18:24:25 -07002125 (which == FLAG_LOCK) ? mLockWallpaperMap : mWallpaperMap;
Vadim Tryshev8cde0792016-02-19 17:02:15 -08002126 WallpaperData wallpaper = whichSet.get(wallpaperUserId);
2127 if (wallpaper == null) {
Christopher Tatef717b932017-09-11 15:52:54 -07002128 // There is no established wallpaper imagery of this type (expected
2129 // only for lock wallpapers; a system WallpaperData is established at
2130 // user switch)
2131 return null;
Benjamin Franzf3ece362015-02-11 10:51:10 +00002132 }
wilsonshih81e10a72018-11-15 10:54:21 +08002133 // Only for default display.
wilsonshiha282bf72018-11-30 12:48:05 +08002134 final DisplayData wpdData = getDisplayDataOrCreate(DEFAULT_DISPLAY);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002135 try {
Dianne Hackborn284ac932009-08-28 10:34:25 -07002136 if (outParams != null) {
wilsonshih81e10a72018-11-15 10:54:21 +08002137 outParams.putInt("width", wpdData.mWidth);
2138 outParams.putInt("height", wpdData.mHeight);
Dianne Hackborn284ac932009-08-28 10:34:25 -07002139 }
Christopher Tateea6724a2016-02-18 18:39:19 -08002140 if (cb != null) {
2141 wallpaper.callbacks.register(cb);
2142 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08002143 if (!wallpaper.cropFile.exists()) {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002144 return null;
2145 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08002146 return ParcelFileDescriptor.open(wallpaper.cropFile, MODE_READ_ONLY);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002147 } catch (FileNotFoundException e) {
2148 /* Shouldn't happen as we check to see if the file exists */
Joe Onorato8a9b2202010-02-26 18:56:32 -08002149 Slog.w(TAG, "Error getting wallpaper", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002150 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002151 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002152 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002153 }
2154
Christopher Tatee409f0e2016-03-21 14:53:15 -07002155 @Override
Jorim Jaggie31f6b82016-07-01 16:15:09 -07002156 public WallpaperInfo getWallpaperInfo(int userId) {
2157 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
Christopher Tatef717b932017-09-11 15:52:54 -07002158 Binder.getCallingUid(), userId, false, true, "getWallpaperInfo", null);
Dianne Hackborneb034652009-09-07 00:49:58 -07002159 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002160 WallpaperData wallpaper = mWallpaperMap.get(userId);
Benjamin Franzf3ece362015-02-11 10:51:10 +00002161 if (wallpaper != null && wallpaper.connection != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002162 return wallpaper.connection.mInfo;
Dianne Hackborneb034652009-09-07 00:49:58 -07002163 }
2164 return null;
2165 }
2166 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002167
Christopher Tatead3c2592016-01-20 18:13:17 -08002168 @Override
Christopher Tatee409f0e2016-03-21 14:53:15 -07002169 public int getWallpaperIdForUser(int which, int userId) {
2170 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
2171 Binder.getCallingUid(), userId, false, true, "getWallpaperIdForUser", null);
2172
Christopher Tateedf7d042016-03-29 18:24:25 -07002173 if (which != FLAG_SYSTEM && which != FLAG_LOCK) {
Christopher Tatee409f0e2016-03-21 14:53:15 -07002174 throw new IllegalArgumentException("Must specify exactly one kind of wallpaper");
2175 }
2176
2177 final SparseArray<WallpaperData> map =
Christopher Tateedf7d042016-03-29 18:24:25 -07002178 (which == FLAG_LOCK) ? mLockWallpaperMap : mWallpaperMap;
Christopher Tatee409f0e2016-03-21 14:53:15 -07002179 synchronized (mLock) {
2180 WallpaperData wallpaper = map.get(userId);
2181 if (wallpaper != null) {
2182 return wallpaper.wallpaperId;
2183 }
2184 }
2185 return -1;
2186 }
2187
2188 @Override
wilsonshih36597d42018-12-05 18:56:39 +08002189 public void registerWallpaperColorsCallback(IWallpaperManagerCallback cb, int userId,
2190 int displayId) {
Lucas Dupin50ba9912017-07-14 11:55:05 -07002191 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
2192 userId, true, true, "registerWallpaperColorsCallback", null);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002193 synchronized (mLock) {
wilsonshih36597d42018-12-05 18:56:39 +08002194 SparseArray<RemoteCallbackList<IWallpaperManagerCallback>>
2195 userDisplayColorsChangedListeners = mColorsChangedListeners.get(userId);
2196 if (userDisplayColorsChangedListeners == null) {
2197 userDisplayColorsChangedListeners = new SparseArray<>();
2198 mColorsChangedListeners.put(userId, userDisplayColorsChangedListeners);
Lucas Dupin50ba9912017-07-14 11:55:05 -07002199 }
wilsonshih36597d42018-12-05 18:56:39 +08002200 RemoteCallbackList<IWallpaperManagerCallback> displayChangedListeners =
2201 userDisplayColorsChangedListeners.get(displayId);
2202 if (displayChangedListeners == null) {
2203 displayChangedListeners = new RemoteCallbackList<>();
2204 userDisplayColorsChangedListeners.put(displayId, displayChangedListeners);
2205 }
2206 displayChangedListeners.register(cb);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002207 }
2208 }
2209
2210 @Override
wilsonshih36597d42018-12-05 18:56:39 +08002211 public void unregisterWallpaperColorsCallback(IWallpaperManagerCallback cb, int userId,
2212 int displayId) {
Lucas Dupin50ba9912017-07-14 11:55:05 -07002213 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
2214 userId, true, true, "unregisterWallpaperColorsCallback", null);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002215 synchronized (mLock) {
wilsonshih36597d42018-12-05 18:56:39 +08002216 SparseArray<RemoteCallbackList<IWallpaperManagerCallback>>
2217 userDisplayColorsChangedListeners = mColorsChangedListeners.get(userId);
2218 if (userDisplayColorsChangedListeners != null) {
2219 RemoteCallbackList<IWallpaperManagerCallback> displayChangedListeners =
2220 userDisplayColorsChangedListeners.get(displayId);
2221 if (displayChangedListeners != null) {
2222 displayChangedListeners.unregister(cb);
2223 }
Lucas Dupin50ba9912017-07-14 11:55:05 -07002224 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002225 }
2226 }
2227
Lucas Dupin4c8c3272018-11-06 17:47:48 -08002228 /**
wilsonshih36597d42018-12-05 18:56:39 +08002229 * TODO(multi-display) Extends this method with specific display.
Lucas Dupin4c8c3272018-11-06 17:47:48 -08002230 * Propagate ambient state to wallpaper engine.
2231 *
2232 * @param inAmbientMode {@code true} when in ambient mode, {@code false} otherwise.
2233 * @param animationDuration Duration of the animation, or 0 when immediate.
2234 */
2235 public void setInAmbientMode(boolean inAmbientMode, long animationDuration) {
Lucas Dupin7517b5d2017-08-22 12:51:25 -07002236 final IWallpaperEngine engine;
2237 synchronized (mLock) {
Lucas Dupin4c8c3272018-11-06 17:47:48 -08002238 mInAmbientMode = inAmbientMode;
Lucas Dupin7517b5d2017-08-22 12:51:25 -07002239 final WallpaperData data = mWallpaperMap.get(mCurrentUserId);
Ahan Wu723a80e2018-11-07 20:39:32 +08002240 // The wallpaper info is null for image wallpaper, also use the engine in this case.
Ahan Wu67e7f102019-01-14 20:38:14 +08002241 if (data != null && data.connection != null && (data.connection.mInfo == null
2242 || data.connection.mInfo.supportsAmbientMode())) {
wilsonshih36597d42018-12-05 18:56:39 +08002243 // TODO(multi-display) Extends this method with specific display.
wilsonshihde93f492018-11-01 21:23:40 +08002244 engine = data.connection.getDisplayConnectorOrCreate(DEFAULT_DISPLAY).mEngine;
Lucas Dupin7517b5d2017-08-22 12:51:25 -07002245 } else {
2246 engine = null;
2247 }
2248 }
2249
2250 if (engine != null) {
2251 try {
Lucas Dupin4c8c3272018-11-06 17:47:48 -08002252 engine.setInAmbientMode(inAmbientMode, animationDuration);
Lucas Dupin7517b5d2017-08-22 12:51:25 -07002253 } catch (RemoteException e) {
2254 // Cannot talk to wallpaper engine.
2255 }
2256 }
2257 }
2258
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002259 @Override
Christopher Tatebe132e62016-02-10 12:59:49 -08002260 public boolean setLockWallpaperCallback(IWallpaperManagerCallback cb) {
2261 checkPermission(android.Manifest.permission.INTERNAL_SYSTEM_WINDOW);
2262 synchronized (mLock) {
2263 mKeyguardListener = cb;
2264 }
2265 return true;
2266 }
2267
2268 @Override
wilsonshih36597d42018-12-05 18:56:39 +08002269 public WallpaperColors getWallpaperColors(int which, int userId, int displayId)
2270 throws RemoteException {
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002271 if (which != FLAG_LOCK && which != FLAG_SYSTEM) {
2272 throw new IllegalArgumentException("which should be either FLAG_LOCK or FLAG_SYSTEM");
2273 }
Lucas Dupin50ba9912017-07-14 11:55:05 -07002274 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
2275 userId, false, true, "getWallpaperColors", null);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002276
2277 WallpaperData wallpaperData = null;
2278 boolean shouldExtract;
2279
2280 synchronized (mLock) {
2281 if (which == FLAG_LOCK) {
Lucas Dupin50ba9912017-07-14 11:55:05 -07002282 wallpaperData = mLockWallpaperMap.get(userId);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002283 }
2284
2285 // Try to get the system wallpaper anyway since it might
2286 // also be the lock screen wallpaper
2287 if (wallpaperData == null) {
wilsonshih36597d42018-12-05 18:56:39 +08002288 wallpaperData = findWallpaperAtDisplay(userId, displayId);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002289 }
2290
2291 if (wallpaperData == null) {
2292 return null;
2293 }
2294 shouldExtract = wallpaperData.primaryColors == null;
2295 }
2296
2297 if (shouldExtract) {
2298 extractColors(wallpaperData);
2299 }
2300
2301 synchronized (mLock) {
Lucas Dupin4b4c5302018-06-24 18:22:10 -07002302 return wallpaperData.primaryColors;
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002303 }
2304 }
2305
wilsonshih36597d42018-12-05 18:56:39 +08002306 private WallpaperData findWallpaperAtDisplay(int userId, int displayId) {
2307 if (mFallbackWallpaper != null && mFallbackWallpaper.connection != null
2308 && mFallbackWallpaper.connection.containsDisplay(displayId)) {
2309 return mFallbackWallpaper;
2310 } else {
2311 return mWallpaperMap.get(userId);
2312 }
2313 }
2314
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002315 @Override
Christopher Tate1e1e2e02016-01-25 15:34:36 -08002316 public ParcelFileDescriptor setWallpaper(String name, String callingPackage,
Christopher Tated7faf532016-02-25 12:43:38 -08002317 Rect cropHint, boolean allowBackup, Bundle extras, int which,
Jorim Jaggi6c902d02016-08-18 10:44:54 -07002318 IWallpaperManagerCallback completion, int userId) {
2319 userId = ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,
2320 false /* all */, true /* full */, "changing wallpaper", null /* pkg */);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002321 checkPermission(android.Manifest.permission.SET_WALLPAPER);
Christopher Tatead3c2592016-01-20 18:13:17 -08002322
Christopher Tateedf7d042016-03-29 18:24:25 -07002323 if ((which & (FLAG_LOCK|FLAG_SYSTEM)) == 0) {
Christopher Tate98d609c2016-05-18 17:31:58 -07002324 final String msg = "Must specify a valid wallpaper category to set";
2325 Slog.e(TAG, msg);
2326 throw new IllegalArgumentException(msg);
Christopher Tatead3c2592016-01-20 18:13:17 -08002327 }
2328
Christopher Tate98d609c2016-05-18 17:31:58 -07002329 if (!isWallpaperSupported(callingPackage) || !isSetWallpaperAllowed(callingPackage)) {
Benjamin Franzf3ece362015-02-11 10:51:10 +00002330 return null;
2331 }
Christopher Tatead3c2592016-01-20 18:13:17 -08002332
Christopher Tate1e1e2e02016-01-25 15:34:36 -08002333 // "null" means the no-op crop, preserving the full input image
2334 if (cropHint == null) {
2335 cropHint = new Rect(0, 0, 0, 0);
2336 } else {
2337 if (cropHint.isEmpty()
2338 || cropHint.left < 0
2339 || cropHint.top < 0) {
Christopher Tate98d609c2016-05-18 17:31:58 -07002340 throw new IllegalArgumentException("Invalid crop rect supplied: " + cropHint);
Christopher Tate1e1e2e02016-01-25 15:34:36 -08002341 }
2342 }
2343
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002344 synchronized (mLock) {
Christopher Tatebe132e62016-02-10 12:59:49 -08002345 if (DEBUG) Slog.v(TAG, "setWallpaper which=0x" + Integer.toHexString(which));
2346 WallpaperData wallpaper;
2347
Christopher Tate8347b632016-04-29 18:59:18 -07002348 /* If we're setting system but not lock, and lock is currently sharing the system
2349 * wallpaper, we need to migrate that image over to being lock-only before
2350 * the caller here writes new bitmap data.
2351 */
2352 if (which == FLAG_SYSTEM && mLockWallpaperMap.get(userId) == null) {
2353 if (DEBUG) {
2354 Slog.i(TAG, "Migrating system->lock to preserve");
2355 }
2356 migrateSystemToLockWallpaperLocked(userId);
2357 }
2358
Christopher Tatebe132e62016-02-10 12:59:49 -08002359 wallpaper = getWallpaperSafeLocked(userId, which);
Dianne Hackborn0cd48872009-08-13 18:51:59 -07002360 final long ident = Binder.clearCallingIdentity();
2361 try {
Christopher Tatead3c2592016-01-20 18:13:17 -08002362 ParcelFileDescriptor pfd = updateWallpaperBitmapLocked(name, wallpaper, extras);
Dianne Hackborn0cd48872009-08-13 18:51:59 -07002363 if (pfd != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002364 wallpaper.imageWallpaperPending = true;
Christopher Tatebe132e62016-02-10 12:59:49 -08002365 wallpaper.whichPending = which;
Christopher Tate1e1e2e02016-01-25 15:34:36 -08002366 wallpaper.setComplete = completion;
2367 wallpaper.cropHint.set(cropHint);
Christopher Tatec613c632016-08-12 14:13:02 -07002368 wallpaper.allowBackup = allowBackup;
Dianne Hackborn0cd48872009-08-13 18:51:59 -07002369 }
2370 return pfd;
2371 } finally {
2372 Binder.restoreCallingIdentity(ident);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002373 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002374 }
2375 }
2376
Christopher Tate8347b632016-04-29 18:59:18 -07002377 private void migrateSystemToLockWallpaperLocked(int userId) {
2378 WallpaperData sysWP = mWallpaperMap.get(userId);
2379 if (sysWP == null) {
2380 if (DEBUG) {
2381 Slog.i(TAG, "No system wallpaper? Not tracking for lock-only");
2382 }
2383 return;
2384 }
2385
2386 // We know a-priori that there is no lock-only wallpaper currently
2387 WallpaperData lockWP = new WallpaperData(userId,
2388 WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP);
2389 lockWP.wallpaperId = sysWP.wallpaperId;
2390 lockWP.cropHint.set(sysWP.cropHint);
Christopher Tateedd8dc82016-10-12 15:17:58 -07002391 lockWP.allowBackup = sysWP.allowBackup;
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002392 lockWP.primaryColors = sysWP.primaryColors;
Christopher Tate8347b632016-04-29 18:59:18 -07002393
2394 // Migrate the bitmap files outright; no need to copy
2395 try {
2396 Os.rename(sysWP.wallpaperFile.getAbsolutePath(), lockWP.wallpaperFile.getAbsolutePath());
2397 Os.rename(sysWP.cropFile.getAbsolutePath(), lockWP.cropFile.getAbsolutePath());
2398 } catch (ErrnoException e) {
2399 Slog.e(TAG, "Can't migrate system wallpaper: " + e.getMessage());
2400 lockWP.wallpaperFile.delete();
2401 lockWP.cropFile.delete();
2402 return;
2403 }
2404
2405 mLockWallpaperMap.put(userId, lockWP);
2406 }
2407
Christopher Tatead3c2592016-01-20 18:13:17 -08002408 ParcelFileDescriptor updateWallpaperBitmapLocked(String name, WallpaperData wallpaper,
2409 Bundle extras) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002410 if (name == null) name = "";
2411 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002412 File dir = getWallpaperDir(wallpaper.userId);
2413 if (!dir.exists()) {
2414 dir.mkdir();
Dianne Hackbornebac48c2011-11-29 18:01:50 -08002415 FileUtils.setPermissions(
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002416 dir.getPath(),
Dianne Hackbornebac48c2011-11-29 18:01:50 -08002417 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
2418 -1, -1);
2419 }
Christopher Tatebe132e62016-02-10 12:59:49 -08002420 ParcelFileDescriptor fd = ParcelFileDescriptor.open(wallpaper.wallpaperFile,
Christopher Tate90f86ba2014-09-11 12:37:19 -07002421 MODE_CREATE|MODE_READ_WRITE|MODE_TRUNCATE);
Christopher Tatebe132e62016-02-10 12:59:49 -08002422 if (!SELinux.restorecon(wallpaper.wallpaperFile)) {
rpcraig554cb0c2012-07-05 06:41:43 -04002423 return null;
2424 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002425 wallpaper.name = name;
Christopher Tatead3c2592016-01-20 18:13:17 -08002426 wallpaper.wallpaperId = makeWallpaperIdLocked();
2427 if (extras != null) {
2428 extras.putInt(WallpaperManager.EXTRA_NEW_WALLPAPER_ID, wallpaper.wallpaperId);
2429 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002430 // Nullify field to require new computation
2431 wallpaper.primaryColors = null;
Christopher Tatead3c2592016-01-20 18:13:17 -08002432 if (DEBUG) {
2433 Slog.v(TAG, "updateWallpaperBitmapLocked() : id=" + wallpaper.wallpaperId
Christopher Tatebe132e62016-02-10 12:59:49 -08002434 + " name=" + name + " file=" + wallpaper.wallpaperFile.getName());
Christopher Tatead3c2592016-01-20 18:13:17 -08002435 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002436 return fd;
2437 } catch (FileNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002438 Slog.w(TAG, "Error setting wallpaper", e);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002439 }
2440 return null;
2441 }
2442
Christopher Tated57d17c2016-03-25 13:41:46 -07002443 @Override
Adrian Roos40ea0832016-07-14 14:19:55 -07002444 public void setWallpaperComponentChecked(ComponentName name, String callingPackage,
2445 int userId) {
2446
Christopher Tate98d609c2016-05-18 17:31:58 -07002447 if (isWallpaperSupported(callingPackage) && isSetWallpaperAllowed(callingPackage)) {
Adrian Roos40ea0832016-07-14 14:19:55 -07002448 setWallpaperComponent(name, userId);
Benjamin Franzf3ece362015-02-11 10:51:10 +00002449 }
2450 }
2451
2452 // ToDo: Remove this version of the function
Christopher Tated57d17c2016-03-25 13:41:46 -07002453 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002454 public void setWallpaperComponent(ComponentName name) {
Adrian Roos40ea0832016-07-14 14:19:55 -07002455 setWallpaperComponent(name, UserHandle.getCallingUserId());
2456 }
2457
2458 private void setWallpaperComponent(ComponentName name, int userId) {
2459 userId = ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,
2460 false /* all */, true /* full */, "changing live wallpaper", null /* pkg */);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002461 checkPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT);
Adrian Roos40ea0832016-07-14 14:19:55 -07002462
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002463 int which = FLAG_SYSTEM;
2464 boolean shouldNotifyColors = false;
2465 WallpaperData wallpaper;
2466
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002467 synchronized (mLock) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002468 if (DEBUG) Slog.v(TAG, "setWallpaperComponent name=" + name);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002469 wallpaper = mWallpaperMap.get(userId);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002470 if (wallpaper == null) {
2471 throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
2472 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002473 final long ident = Binder.clearCallingIdentity();
Christopher Tate7cd00102016-12-19 14:38:44 -08002474
2475 // Live wallpapers can't be specified for keyguard. If we're using a static
2476 // system+lock image currently, migrate the system wallpaper to be a lock-only
2477 // image as part of making a different live component active as the system
2478 // wallpaper.
2479 if (mImageWallpaper.equals(wallpaper.wallpaperComponent)) {
2480 if (mLockWallpaperMap.get(userId) == null) {
2481 // We're using the static imagery and there is no lock-specific image in place,
2482 // therefore it's a shared system+lock image that we need to migrate.
2483 migrateSystemToLockWallpaperLocked(userId);
2484 }
2485 }
2486
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002487 // New live wallpaper is also a lock wallpaper if nothing is set
2488 if (mLockWallpaperMap.get(userId) == null) {
2489 which |= FLAG_LOCK;
2490 }
2491
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002492 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002493 wallpaper.imageWallpaperPending = false;
Lucas Dupin50ba9912017-07-14 11:55:05 -07002494 boolean same = changingToSame(name, wallpaper);
Christopher Tated57d17c2016-03-25 13:41:46 -07002495 if (bindWallpaperComponentLocked(name, false, true, wallpaper, null)) {
Lucas Dupin50ba9912017-07-14 11:55:05 -07002496 if (!same) {
2497 wallpaper.primaryColors = null;
2498 }
Christopher Tated57d17c2016-03-25 13:41:46 -07002499 wallpaper.wallpaperId = makeWallpaperIdLocked();
Sunny Goyal0572e182016-03-31 11:05:51 -07002500 notifyCallbacksLocked(wallpaper);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002501 shouldNotifyColors = true;
Christopher Tated57d17c2016-03-25 13:41:46 -07002502 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002503 } finally {
2504 Binder.restoreCallingIdentity(ident);
2505 }
2506 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002507
2508 if (shouldNotifyColors) {
2509 notifyWallpaperColorsChanged(wallpaper, which);
wilsonshih36597d42018-12-05 18:56:39 +08002510 notifyWallpaperColorsChanged(mFallbackWallpaper, FLAG_SYSTEM);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002511 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002512 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01002513
Lucas Dupin50ba9912017-07-14 11:55:05 -07002514 private boolean changingToSame(ComponentName componentName, WallpaperData wallpaper) {
2515 if (wallpaper.connection != null) {
2516 if (wallpaper.wallpaperComponent == null) {
2517 if (componentName == null) {
2518 if (DEBUG) Slog.v(TAG, "changingToSame: still using default");
2519 // Still using default wallpaper.
2520 return true;
2521 }
2522 } else if (wallpaper.wallpaperComponent.equals(componentName)) {
2523 // Changing to same wallpaper.
2524 if (DEBUG) Slog.v(TAG, "same wallpaper");
2525 return true;
2526 }
2527 }
2528 return false;
2529 }
2530
wilsonshiha282bf72018-11-30 12:48:05 +08002531 private boolean bindWallpaperComponentLocked(ComponentName componentName, boolean force,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002532 boolean fromUser, WallpaperData wallpaper, IRemoteCallback reply) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07002533 if (DEBUG_LIVE) {
2534 Slog.v(TAG, "bindWallpaperComponentLocked: componentName=" + componentName);
2535 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002536 // Has the component changed?
Lucas Dupin50ba9912017-07-14 11:55:05 -07002537 if (!force && changingToSame(componentName, wallpaper)) {
2538 return true;
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002539 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01002540
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002541 try {
Mike Clerona428b2c2009-11-15 22:53:08 -08002542 if (componentName == null) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07002543 componentName = mDefaultWallpaperComponent;
Mike Clerona428b2c2009-11-15 22:53:08 -08002544 if (componentName == null) {
Mike Cleron322b6ee2009-11-12 07:45:47 -08002545 // Fall back to static image wallpaper
Justin Koh29c30162014-09-05 17:10:10 -07002546 componentName = mImageWallpaper;
Mike Cleron322b6ee2009-11-12 07:45:47 -08002547 //clearWallpaperComponentLocked();
2548 //return;
Christopher Tate2a6c55f2017-03-31 12:28:30 -07002549 if (DEBUG_LIVE) Slog.v(TAG, "No default component; using image wallpaper");
Mike Cleron322b6ee2009-11-12 07:45:47 -08002550 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002551 }
Amith Yamasani4e2820c2012-08-28 22:17:23 -07002552 int serviceUserId = wallpaper.userId;
2553 ServiceInfo si = mIPackageManager.getServiceInfo(componentName,
2554 PackageManager.GET_META_DATA | PackageManager.GET_PERMISSIONS, serviceUserId);
Christopher Tate90952202013-09-08 13:01:28 -07002555 if (si == null) {
2556 // The wallpaper component we're trying to use doesn't exist
2557 Slog.w(TAG, "Attempted wallpaper " + componentName + " is unavailable");
2558 return false;
2559 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002560 if (!android.Manifest.permission.BIND_WALLPAPER.equals(si.permission)) {
Lucas Dupin4c8c3272018-11-06 17:47:48 -08002561 String msg = "Selected service does not have "
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002562 + android.Manifest.permission.BIND_WALLPAPER
Dianne Hackborn80b902f2011-09-15 15:15:27 -07002563 + ": " + componentName;
2564 if (fromUser) {
2565 throw new SecurityException(msg);
2566 }
2567 Slog.w(TAG, msg);
2568 return false;
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002569 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01002570
Dianne Hackborneb034652009-09-07 00:49:58 -07002571 WallpaperInfo wi = null;
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01002572
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002573 Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
Justin Koh29c30162014-09-05 17:10:10 -07002574 if (componentName != null && !componentName.equals(mImageWallpaper)) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002575 // Make sure the selected service is actually a wallpaper service.
Amith Yamasani4e2820c2012-08-28 22:17:23 -07002576 List<ResolveInfo> ris =
2577 mIPackageManager.queryIntentServices(intent,
2578 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
Jeff Sharkeyd5896632016-03-04 16:16:00 -07002579 PackageManager.GET_META_DATA, serviceUserId).getList();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002580 for (int i=0; i<ris.size(); i++) {
2581 ServiceInfo rsi = ris.get(i).serviceInfo;
2582 if (rsi.name.equals(si.name) &&
2583 rsi.packageName.equals(si.packageName)) {
Dianne Hackborneb034652009-09-07 00:49:58 -07002584 try {
2585 wi = new WallpaperInfo(mContext, ris.get(i));
2586 } catch (XmlPullParserException e) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -07002587 if (fromUser) {
2588 throw new IllegalArgumentException(e);
2589 }
2590 Slog.w(TAG, e);
2591 return false;
Dianne Hackborneb034652009-09-07 00:49:58 -07002592 } catch (IOException e) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -07002593 if (fromUser) {
2594 throw new IllegalArgumentException(e);
2595 }
2596 Slog.w(TAG, e);
2597 return false;
Dianne Hackborneb034652009-09-07 00:49:58 -07002598 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002599 break;
2600 }
2601 }
Dianne Hackborneb034652009-09-07 00:49:58 -07002602 if (wi == null) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -07002603 String msg = "Selected service is not a wallpaper: "
2604 + componentName;
2605 if (fromUser) {
2606 throw new SecurityException(msg);
2607 }
2608 Slog.w(TAG, msg);
2609 return false;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002610 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002611 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01002612
Lucas Dupin4c8c3272018-11-06 17:47:48 -08002613 if (wi != null && wi.supportsAmbientMode()) {
2614 final int hasPrivilege = mIPackageManager.checkPermission(
2615 android.Manifest.permission.AMBIENT_WALLPAPER, wi.getPackageName(),
2616 serviceUserId);
2617 if (hasPrivilege != PackageManager.PERMISSION_GRANTED) {
2618 String msg = "Selected service does not have "
2619 + android.Manifest.permission.AMBIENT_WALLPAPER
2620 + ": " + componentName;
2621 if (fromUser) {
2622 throw new SecurityException(msg);
2623 }
2624 Slog.w(TAG, msg);
2625 return false;
2626 }
2627 }
2628
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002629 // Bind the service!
Joe Onorato8a9b2202010-02-26 18:56:32 -08002630 if (DEBUG) Slog.v(TAG, "Binding to:" + componentName);
wilsonshihde93f492018-11-01 21:23:40 +08002631 final int componentUid = mIPackageManager.getPackageUid(componentName.getPackageName(),
2632 MATCH_DIRECT_BOOT_AUTO, wallpaper.userId);
2633 WallpaperConnection newConn = new WallpaperConnection(wi, wallpaper, componentUid);
Mike Clerona428b2c2009-11-15 22:53:08 -08002634 intent.setComponent(componentName);
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07002635 intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
2636 com.android.internal.R.string.wallpaper_binding_label);
Dianne Hackborn41203752012-08-31 14:05:51 -07002637 intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivityAsUser(
Dianne Hackborneb034652009-09-07 00:49:58 -07002638 mContext, 0,
2639 Intent.createChooser(new Intent(Intent.ACTION_SET_WALLPAPER),
2640 mContext.getText(com.android.internal.R.string.chooser_wallpaper)),
Dianne Hackborn41203752012-08-31 14:05:51 -07002641 0, null, new UserHandle(serviceUserId)));
Dianne Hackbornc8230512013-07-13 21:32:12 -07002642 if (!mContext.bindServiceAsUser(intent, newConn,
Dianne Hackbornd69e4c12015-04-24 09:54:54 -07002643 Context.BIND_AUTO_CREATE | Context.BIND_SHOWING_UI
2644 | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
Amith Yamasani27b89e62013-01-16 12:30:11 -08002645 new UserHandle(serviceUserId))) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -07002646 String msg = "Unable to bind service: "
2647 + componentName;
2648 if (fromUser) {
2649 throw new IllegalArgumentException(msg);
2650 }
2651 Slog.w(TAG, msg);
2652 return false;
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002653 }
wilsonshiha282bf72018-11-30 12:48:05 +08002654 if (wallpaper.userId == mCurrentUserId && mLastWallpaper != null
2655 && !wallpaper.equals(mFallbackWallpaper)) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002656 detachWallpaperLocked(mLastWallpaper);
2657 }
2658 wallpaper.wallpaperComponent = componentName;
2659 wallpaper.connection = newConn;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002660 newConn.mReply = reply;
wilsonshiha282bf72018-11-30 12:48:05 +08002661 if (wallpaper.userId == mCurrentUserId && !wallpaper.equals(mFallbackWallpaper)) {
wilsonshihde93f492018-11-01 21:23:40 +08002662 mLastWallpaper = wallpaper;
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002663 }
wilsonshiha282bf72018-11-30 12:48:05 +08002664 updateFallbackConnection();
Amith Yamasani4e2820c2012-08-28 22:17:23 -07002665 } catch (RemoteException e) {
2666 String msg = "Remote exception for " + componentName + "\n" + e;
Dianne Hackborn80b902f2011-09-15 15:15:27 -07002667 if (fromUser) {
2668 throw new IllegalArgumentException(msg);
2669 }
2670 Slog.w(TAG, msg);
2671 return false;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002672 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -07002673 return true;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002674 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002675
wilsonshiha282bf72018-11-30 12:48:05 +08002676 private void detachWallpaperLocked(WallpaperData wallpaper) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002677 if (wallpaper.connection != null) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002678 if (wallpaper.connection.mReply != null) {
2679 try {
2680 wallpaper.connection.mReply.sendResult(null);
2681 } catch (RemoteException e) {
2682 }
2683 wallpaper.connection.mReply = null;
2684 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002685 mContext.unbindService(wallpaper.connection);
wilsonshiha282bf72018-11-30 12:48:05 +08002686 wallpaper.connection.forEachDisplayConnector(
2687 WallpaperConnection.DisplayConnector::disconnectLocked);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002688 wallpaper.connection.mService = null;
wilsonshihde93f492018-11-01 21:23:40 +08002689 wallpaper.connection.mDisplayConnector.clear();
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002690 wallpaper.connection = null;
wilsonshihde93f492018-11-01 21:23:40 +08002691 if (wallpaper == mLastWallpaper) mLastWallpaper = null;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002692 }
2693 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002694
wilsonshiha282bf72018-11-30 12:48:05 +08002695 private void clearWallpaperComponentLocked(WallpaperData wallpaper) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002696 wallpaper.wallpaperComponent = null;
2697 detachWallpaperLocked(wallpaper);
2698 }
2699
wilsonshiha282bf72018-11-30 12:48:05 +08002700 private void attachServiceLocked(WallpaperConnection conn, WallpaperData wallpaper) {
wilsonshihde93f492018-11-01 21:23:40 +08002701 conn.forEachDisplayConnector(connector-> connector.connectLocked(conn, wallpaper));
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002702 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002703
2704 private void notifyCallbacksLocked(WallpaperData wallpaper) {
2705 final int n = wallpaper.callbacks.beginBroadcast();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002706 for (int i = 0; i < n; i++) {
2707 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002708 wallpaper.callbacks.getBroadcastItem(i).onWallpaperChanged();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002709 } catch (RemoteException e) {
2710
2711 // The RemoteCallbackList will take care of removing
2712 // the dead object for us.
2713 }
2714 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002715 wallpaper.callbacks.finishBroadcast();
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002716
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002717 final Intent intent = new Intent(Intent.ACTION_WALLPAPER_CHANGED);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07002718 mContext.sendBroadcastAsUser(intent, new UserHandle(mCurrentUserId));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002719 }
2720
2721 private void checkPermission(String permission) {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002722 if (PackageManager.PERMISSION_GRANTED!= mContext.checkCallingOrSelfPermission(permission)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002723 throw new SecurityException("Access denied to process: " + Binder.getCallingPid()
2724 + ", must have permission " + permission);
2725 }
2726 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002727
Benjamin Franzf3ece362015-02-11 10:51:10 +00002728 /**
2729 * Certain user types do not support wallpapers (e.g. managed profiles). The check is
2730 * implemented through through the OP_WRITE_WALLPAPER AppOp.
2731 */
2732 public boolean isWallpaperSupported(String callingPackage) {
2733 return mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_WRITE_WALLPAPER, Binder.getCallingUid(),
2734 callingPackage) == AppOpsManager.MODE_ALLOWED;
2735 }
2736
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01002737 @Override
Christopher Tate98d609c2016-05-18 17:31:58 -07002738 public boolean isSetWallpaperAllowed(String callingPackage) {
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01002739 final PackageManager pm = mContext.getPackageManager();
2740 String[] uidPackages = pm.getPackagesForUid(Binder.getCallingUid());
2741 boolean uidMatchPackage = Arrays.asList(uidPackages).contains(callingPackage);
2742 if (!uidMatchPackage) {
2743 return false; // callingPackage was faked.
2744 }
2745
2746 final DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
2747 if (dpm.isDeviceOwnerApp(callingPackage) || dpm.isProfileOwnerApp(callingPackage)) {
2748 return true;
2749 }
2750 final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
2751 return !um.hasUserRestriction(UserManager.DISALLOW_SET_WALLPAPER);
2752 }
2753
Christopher Tated7faf532016-02-25 12:43:38 -08002754 @Override
Christopher Tate61722662016-08-10 16:13:14 -07002755 public boolean isWallpaperBackupEligible(int which, int userId) {
Christopher Tated7faf532016-02-25 12:43:38 -08002756 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
2757 throw new SecurityException("Only the system may call isWallpaperBackupEligible");
2758 }
2759
Christopher Tate61722662016-08-10 16:13:14 -07002760 WallpaperData wallpaper = (which == FLAG_LOCK)
Christopher Tatef7d1b5d2016-08-19 11:21:07 -07002761 ? mLockWallpaperMap.get(userId)
2762 : mWallpaperMap.get(userId);
Christopher Tated7faf532016-02-25 12:43:38 -08002763 return (wallpaper != null) ? wallpaper.allowBackup : false;
2764 }
2765
wilsonshih643bf132019-02-27 12:49:19 +08002766 private void onDisplayReadyInternal(int displayId) {
2767 synchronized (mLock) {
2768 if (mLastWallpaper == null) {
2769 return;
2770 }
2771 if (supportsMultiDisplay(mLastWallpaper.connection)) {
2772 final WallpaperConnection.DisplayConnector connector =
2773 mLastWallpaper.connection.getDisplayConnectorOrCreate(displayId);
2774 if (connector == null) return;
2775 connector.connectLocked(mLastWallpaper.connection, mLastWallpaper);
2776 return;
2777 }
2778 // System wallpaper does not support multiple displays, attach this display to
2779 // the fallback wallpaper.
2780 if (mFallbackWallpaper != null) {
2781 final WallpaperConnection.DisplayConnector connector = mFallbackWallpaper
2782 .connection.getDisplayConnectorOrCreate(displayId);
2783 if (connector == null) return;
2784 connector.connectLocked(mFallbackWallpaper.connection, mFallbackWallpaper);
2785 } else {
2786 Slog.w(TAG, "No wallpaper can be added to the new display");
2787 }
2788 }
2789 }
2790
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002791 private static JournaledFile makeJournaledFile(int userId) {
Amith Yamasani61f57372012-08-31 12:12:28 -07002792 final String base = new File(getWallpaperDir(userId), WALLPAPER_INFO).getAbsolutePath();
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002793 return new JournaledFile(new File(base), new File(base + ".tmp"));
2794 }
2795
Christopher Tatedb27b842016-02-25 14:39:17 -08002796 private void saveSettingsLocked(int userId) {
2797 JournaledFile journal = makeJournaledFile(userId);
2798 FileOutputStream fstream = null;
2799 BufferedOutputStream stream = null;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002800 try {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002801 XmlSerializer out = new FastXmlSerializer();
Christopher Tatedb27b842016-02-25 14:39:17 -08002802 fstream = new FileOutputStream(journal.chooseForWrite(), false);
2803 stream = new BufferedOutputStream(fstream);
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01002804 out.setOutput(stream, StandardCharsets.UTF_8.name());
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002805 out.startDocument(null, true);
2806
Christopher Tatedb27b842016-02-25 14:39:17 -08002807 WallpaperData wallpaper;
Christopher Tate1e1e2e02016-01-25 15:34:36 -08002808
Christopher Tatedb27b842016-02-25 14:39:17 -08002809 wallpaper = mWallpaperMap.get(userId);
2810 if (wallpaper != null) {
2811 writeWallpaperAttributes(out, "wp", wallpaper);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002812 }
Christopher Tatedb27b842016-02-25 14:39:17 -08002813 wallpaper = mLockWallpaperMap.get(userId);
2814 if (wallpaper != null) {
2815 writeWallpaperAttributes(out, "kwp", wallpaper);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002816 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002817
2818 out.endDocument();
Christopher Tatedb27b842016-02-25 14:39:17 -08002819
2820 stream.flush(); // also flushes fstream
2821 FileUtils.sync(fstream);
2822 stream.close(); // also closes fstream
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002823 journal.commit();
2824 } catch (IOException e) {
Christopher Tatead3c2592016-01-20 18:13:17 -08002825 IoUtils.closeQuietly(stream);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002826 journal.rollback();
2827 }
2828 }
2829
Christopher Tatedb27b842016-02-25 14:39:17 -08002830 private void writeWallpaperAttributes(XmlSerializer out, String tag, WallpaperData wallpaper)
2831 throws IllegalArgumentException, IllegalStateException, IOException {
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002832 if (DEBUG) {
Christopher Tatef717b932017-09-11 15:52:54 -07002833 Slog.v(TAG, "writeWallpaperAttributes id=" + wallpaper.wallpaperId);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002834 }
wilsonshiha282bf72018-11-30 12:48:05 +08002835 final DisplayData wpdData = getDisplayDataOrCreate(DEFAULT_DISPLAY);
Christopher Tatedb27b842016-02-25 14:39:17 -08002836 out.startTag(null, tag);
2837 out.attribute(null, "id", Integer.toString(wallpaper.wallpaperId));
wilsonshih81e10a72018-11-15 10:54:21 +08002838 out.attribute(null, "width", Integer.toString(wpdData.mWidth));
2839 out.attribute(null, "height", Integer.toString(wpdData.mHeight));
Christopher Tatedb27b842016-02-25 14:39:17 -08002840
2841 out.attribute(null, "cropLeft", Integer.toString(wallpaper.cropHint.left));
2842 out.attribute(null, "cropTop", Integer.toString(wallpaper.cropHint.top));
2843 out.attribute(null, "cropRight", Integer.toString(wallpaper.cropHint.right));
2844 out.attribute(null, "cropBottom", Integer.toString(wallpaper.cropHint.bottom));
2845
wilsonshih81e10a72018-11-15 10:54:21 +08002846 if (wpdData.mPadding.left != 0) {
2847 out.attribute(null, "paddingLeft", Integer.toString(wpdData.mPadding.left));
Christopher Tatedb27b842016-02-25 14:39:17 -08002848 }
wilsonshih81e10a72018-11-15 10:54:21 +08002849 if (wpdData.mPadding.top != 0) {
2850 out.attribute(null, "paddingTop", Integer.toString(wpdData.mPadding.top));
Christopher Tatedb27b842016-02-25 14:39:17 -08002851 }
wilsonshih81e10a72018-11-15 10:54:21 +08002852 if (wpdData.mPadding.right != 0) {
2853 out.attribute(null, "paddingRight", Integer.toString(wpdData.mPadding.right));
Christopher Tatedb27b842016-02-25 14:39:17 -08002854 }
wilsonshih81e10a72018-11-15 10:54:21 +08002855 if (wpdData.mPadding.bottom != 0) {
2856 out.attribute(null, "paddingBottom", Integer.toString(wpdData.mPadding.bottom));
Christopher Tatedb27b842016-02-25 14:39:17 -08002857 }
2858
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002859 if (wallpaper.primaryColors != null) {
Lucas Dupin84b89d92017-05-09 12:16:19 -07002860 int colorsCount = wallpaper.primaryColors.getMainColors().size();
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002861 out.attribute(null, "colorsCount", Integer.toString(colorsCount));
2862 if (colorsCount > 0) {
2863 for (int i = 0; i < colorsCount; i++) {
Lucas Dupin84b89d92017-05-09 12:16:19 -07002864 final Color wc = wallpaper.primaryColors.getMainColors().get(i);
2865 out.attribute(null, "colorValue"+i, Integer.toString(wc.toArgb()));
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002866 }
2867 }
Lucas Dupin75ec3792017-06-29 14:07:18 -07002868 out.attribute(null, "colorHints",
Lucas Dupin84b89d92017-05-09 12:16:19 -07002869 Integer.toString(wallpaper.primaryColors.getColorHints()));
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002870 }
2871
Christopher Tatedb27b842016-02-25 14:39:17 -08002872 out.attribute(null, "name", wallpaper.name);
2873 if (wallpaper.wallpaperComponent != null
2874 && !wallpaper.wallpaperComponent.equals(mImageWallpaper)) {
2875 out.attribute(null, "component",
2876 wallpaper.wallpaperComponent.flattenToShortString());
2877 }
Christopher Tated7faf532016-02-25 12:43:38 -08002878
2879 if (wallpaper.allowBackup) {
2880 out.attribute(null, "backup", "true");
2881 }
2882
Christopher Tatedb27b842016-02-25 14:39:17 -08002883 out.endTag(null, tag);
2884 }
2885
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002886 private void migrateFromOld() {
Christopher Tate9f224432017-08-01 16:32:49 -07002887 // Pre-N, what existed is the one we're now using as the display crop
2888 File preNWallpaper = new File(getWallpaperDir(0), WALLPAPER_CROP);
2889 // In the very-long-ago, imagery lived with the settings app
2890 File originalWallpaper = new File(WallpaperBackupHelper.WALLPAPER_IMAGE_KEY);
2891 File newWallpaper = new File(getWallpaperDir(0), WALLPAPER);
2892
2893 // Migrations from earlier wallpaper image storage schemas
2894 if (preNWallpaper.exists()) {
2895 if (!newWallpaper.exists()) {
2896 // we've got the 'wallpaper' crop file but not the nominal source image,
2897 // so do the simple "just take everything" straight copy of legacy data
2898 if (DEBUG) {
2899 Slog.i(TAG, "Migrating wallpaper schema");
2900 }
2901 FileUtils.copyFile(preNWallpaper, newWallpaper);
2902 } // else we're in the usual modern case: both source & crop exist
2903 } else if (originalWallpaper.exists()) {
2904 // VERY old schema; make sure things exist and are in the right place
2905 if (DEBUG) {
2906 Slog.i(TAG, "Migrating antique wallpaper schema");
2907 }
2908 File oldInfo = new File(WallpaperBackupHelper.WALLPAPER_INFO_KEY);
2909 if (oldInfo.exists()) {
2910 File newInfo = new File(getWallpaperDir(0), WALLPAPER_INFO);
2911 oldInfo.renameTo(newInfo);
2912 }
2913
2914 FileUtils.copyFile(originalWallpaper, preNWallpaper);
2915 originalWallpaper.renameTo(newWallpaper);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002916 }
2917 }
2918
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002919 private int getAttributeInt(XmlPullParser parser, String name, int defValue) {
2920 String value = parser.getAttributeValue(null, name);
2921 if (value == null) {
2922 return defValue;
2923 }
2924 return Integer.parseInt(value);
2925 }
2926
Xiaohui Chenac531942015-05-13 13:20:52 -07002927 /**
2928 * Sometimes it is expected the wallpaper map may not have a user's data. E.g. This could
2929 * happen during user switch. The async user switch observer may not have received
2930 * the event yet. We use this safe method when we don't care about this ordering and just
2931 * want to update the data. The data is going to be applied when the user switch observer
2932 * is eventually executed.
Christopher Tatef717b932017-09-11 15:52:54 -07002933 *
2934 * Important: this method loads settings to initialize the given user's wallpaper data if
2935 * there is no current in-memory state.
Xiaohui Chenac531942015-05-13 13:20:52 -07002936 */
Christopher Tatebe132e62016-02-10 12:59:49 -08002937 private WallpaperData getWallpaperSafeLocked(int userId, int which) {
2938 // We're setting either just system (work with the system wallpaper),
2939 // both (also work with the system wallpaper), or just the lock
2940 // wallpaper (update against the existing lock wallpaper if any).
2941 // Combined or just-system operations use the 'system' WallpaperData
2942 // for this use; lock-only operations use the dedicated one.
2943 final SparseArray<WallpaperData> whichSet =
Christopher Tateedf7d042016-03-29 18:24:25 -07002944 (which == FLAG_LOCK) ? mLockWallpaperMap : mWallpaperMap;
Christopher Tatebe132e62016-02-10 12:59:49 -08002945 WallpaperData wallpaper = whichSet.get(userId);
Xiaohui Chenac531942015-05-13 13:20:52 -07002946 if (wallpaper == null) {
Christopher Tatebe132e62016-02-10 12:59:49 -08002947 // common case, this is the first lookup post-boot of the system or
2948 // unified lock, so we bring up the saved state lazily now and recheck.
Christopher Tated7faf532016-02-25 12:43:38 -08002949 loadSettingsLocked(userId, false);
Christopher Tatebe132e62016-02-10 12:59:49 -08002950 wallpaper = whichSet.get(userId);
2951 // if it's still null here, this is a lock-only operation and there is not
2952 // yet a lock-only wallpaper set for this user, so we need to establish
2953 // it now.
2954 if (wallpaper == null) {
Christopher Tateedf7d042016-03-29 18:24:25 -07002955 if (which == FLAG_LOCK) {
Christopher Tatebe132e62016-02-10 12:59:49 -08002956 wallpaper = new WallpaperData(userId,
2957 WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP);
2958 mLockWallpaperMap.put(userId, wallpaper);
wilsonshih81e10a72018-11-15 10:54:21 +08002959 ensureSaneWallpaperData(wallpaper, DEFAULT_DISPLAY);
Christopher Tatebe132e62016-02-10 12:59:49 -08002960 } else {
2961 // sanity fallback: we're in bad shape, but establishing a known
2962 // valid system+lock WallpaperData will keep us from dying.
2963 Slog.wtf(TAG, "Didn't find wallpaper in non-lock case!");
2964 wallpaper = new WallpaperData(userId, WALLPAPER, WALLPAPER_CROP);
2965 mWallpaperMap.put(userId, wallpaper);
wilsonshih81e10a72018-11-15 10:54:21 +08002966 ensureSaneWallpaperData(wallpaper, DEFAULT_DISPLAY);
Christopher Tatebe132e62016-02-10 12:59:49 -08002967 }
2968 }
Xiaohui Chenac531942015-05-13 13:20:52 -07002969 }
2970 return wallpaper;
2971 }
2972
Christopher Tated7faf532016-02-25 12:43:38 -08002973 private void loadSettingsLocked(int userId, boolean keepDimensionHints) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002974 JournaledFile journal = makeJournaledFile(userId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002975 FileInputStream stream = null;
2976 File file = journal.chooseForRead();
Christopher Tate9f224432017-08-01 16:32:49 -07002977
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002978 WallpaperData wallpaper = mWallpaperMap.get(userId);
2979 if (wallpaper == null) {
Christopher Tate9f224432017-08-01 16:32:49 -07002980 // Do this once per boot
2981 migrateFromOld();
2982
Christopher Tatebe132e62016-02-10 12:59:49 -08002983 wallpaper = new WallpaperData(userId, WALLPAPER, WALLPAPER_CROP);
Christopher Tated7faf532016-02-25 12:43:38 -08002984 wallpaper.allowBackup = true;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002985 mWallpaperMap.put(userId, wallpaper);
Christopher Tate41297ff2016-03-10 16:46:15 -08002986 if (!wallpaper.cropExists()) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07002987 if (wallpaper.sourceExists()) {
2988 generateCrop(wallpaper);
2989 } else {
2990 Slog.i(TAG, "No static wallpaper imagery; defaults will be shown");
2991 }
Christopher Tate41297ff2016-03-10 16:46:15 -08002992 }
wilsonshiha282bf72018-11-30 12:48:05 +08002993 initializeFallbackWallpaper();
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002994 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002995 boolean success = false;
wilsonshiha282bf72018-11-30 12:48:05 +08002996 final DisplayData wpdData = getDisplayDataOrCreate(DEFAULT_DISPLAY);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002997 try {
2998 stream = new FileInputStream(file);
2999 XmlPullParser parser = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01003000 parser.setInput(stream, StandardCharsets.UTF_8.name());
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003001
3002 int type;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003003 do {
3004 type = parser.next();
3005 if (type == XmlPullParser.START_TAG) {
3006 String tag = parser.getName();
3007 if ("wp".equals(tag)) {
Christopher Tatebe132e62016-02-10 12:59:49 -08003008 // Common to system + lock wallpapers
Christopher Tated7faf532016-02-25 12:43:38 -08003009 parseWallpaperAttributes(parser, wallpaper, keepDimensionHints);
Christopher Tatead3c2592016-01-20 18:13:17 -08003010
Christopher Tatebe132e62016-02-10 12:59:49 -08003011 // A system wallpaper might also be a live wallpaper
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07003012 String comp = parser.getAttributeValue(null, "component");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003013 wallpaper.nextWallpaperComponent = comp != null
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07003014 ? ComponentName.unflattenFromString(comp)
3015 : null;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003016 if (wallpaper.nextWallpaperComponent == null
3017 || "android".equals(wallpaper.nextWallpaperComponent
3018 .getPackageName())) {
Justin Koh29c30162014-09-05 17:10:10 -07003019 wallpaper.nextWallpaperComponent = mImageWallpaper;
Dianne Hackborn9ea31632011-08-05 14:43:50 -07003020 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01003021
Mike Clerona428b2c2009-11-15 22:53:08 -08003022 if (DEBUG) {
wilsonshih81e10a72018-11-15 10:54:21 +08003023 Slog.v(TAG, "mWidth:" + wpdData.mWidth);
3024 Slog.v(TAG, "mHeight:" + wpdData.mHeight);
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003025 Slog.v(TAG, "cropRect:" + wallpaper.cropHint);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07003026 Slog.v(TAG, "primaryColors:" + wallpaper.primaryColors);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003027 Slog.v(TAG, "mName:" + wallpaper.name);
3028 Slog.v(TAG, "mNextWallpaperComponent:"
3029 + wallpaper.nextWallpaperComponent);
Mike Clerona428b2c2009-11-15 22:53:08 -08003030 }
Christopher Tatebe132e62016-02-10 12:59:49 -08003031 } else if ("kwp".equals(tag)) {
3032 // keyguard-specific wallpaper for this user
3033 WallpaperData lockWallpaper = mLockWallpaperMap.get(userId);
3034 if (lockWallpaper == null) {
3035 lockWallpaper = new WallpaperData(userId,
3036 WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP);
3037 mLockWallpaperMap.put(userId, lockWallpaper);
3038 }
Christopher Tated7faf532016-02-25 12:43:38 -08003039 parseWallpaperAttributes(parser, lockWallpaper, false);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003040 }
3041 }
3042 } while (type != XmlPullParser.END_DOCUMENT);
3043 success = true;
Dianne Hackborn13579ed2012-11-28 18:05:36 -08003044 } catch (FileNotFoundException e) {
3045 Slog.w(TAG, "no current wallpaper -- first boot?");
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003046 } catch (NullPointerException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003047 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003048 } catch (NumberFormatException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003049 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003050 } catch (XmlPullParserException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003051 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003052 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003053 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003054 } catch (IndexOutOfBoundsException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003055 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003056 }
Christopher Tatead3c2592016-01-20 18:13:17 -08003057 IoUtils.closeQuietly(stream);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003058
3059 if (!success) {
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003060 wallpaper.cropHint.set(0, 0, 0, 0);
wilsonshih81e10a72018-11-15 10:54:21 +08003061 wpdData.mPadding.set(0, 0, 0, 0);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003062 wallpaper.name = "";
Adrian Roosc28e3a92016-04-14 10:47:52 -07003063
3064 mLockWallpaperMap.remove(userId);
Christopher Tatead3c2592016-01-20 18:13:17 -08003065 } else {
3066 if (wallpaper.wallpaperId <= 0) {
3067 wallpaper.wallpaperId = makeWallpaperIdLocked();
3068 if (DEBUG) {
3069 Slog.w(TAG, "Didn't set wallpaper id in loadSettingsLocked(" + userId
3070 + "); now " + wallpaper.wallpaperId);
3071 }
3072 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003073 }
Dianne Hackborn44bc17c2011-04-20 18:18:51 -07003074
wilsonshihd9173df2018-11-29 11:52:15 +08003075 ensureSaneWallpaperDisplaySize(wpdData, DEFAULT_DISPLAY);
wilsonshih81e10a72018-11-15 10:54:21 +08003076 ensureSaneWallpaperData(wallpaper, DEFAULT_DISPLAY);
Adrian Roosc28e3a92016-04-14 10:47:52 -07003077 WallpaperData lockWallpaper = mLockWallpaperMap.get(userId);
3078 if (lockWallpaper != null) {
wilsonshih81e10a72018-11-15 10:54:21 +08003079 ensureSaneWallpaperData(lockWallpaper, DEFAULT_DISPLAY);
Adrian Roosc28e3a92016-04-14 10:47:52 -07003080 }
3081 }
3082
wilsonshiha282bf72018-11-30 12:48:05 +08003083 private void initializeFallbackWallpaper() {
3084 if (mFallbackWallpaper == null) {
3085 if (DEBUG) Slog.d(TAG, "Initialize fallback wallpaper");
3086 mFallbackWallpaper = new WallpaperData(
3087 UserHandle.USER_SYSTEM, WALLPAPER, WALLPAPER_CROP);
3088 mFallbackWallpaper.allowBackup = false;
3089 mFallbackWallpaper.wallpaperId = makeWallpaperIdLocked();
3090 bindWallpaperComponentLocked(mImageWallpaper, true, false, mFallbackWallpaper, null);
3091 }
3092 }
3093
wilsonshih81e10a72018-11-15 10:54:21 +08003094 private void ensureSaneWallpaperData(WallpaperData wallpaper, int displayId) {
wilsonshiha282bf72018-11-30 12:48:05 +08003095 final DisplayData size = getDisplayDataOrCreate(displayId);
wilsonshih81e10a72018-11-15 10:54:21 +08003096
3097 if (displayId == DEFAULT_DISPLAY) {
3098 // crop, if not previously specified
3099 if (wallpaper.cropHint.width() <= 0
3100 || wallpaper.cropHint.height() <= 0) {
3101 wallpaper.cropHint.set(0, 0, size.mWidth, size.mHeight);
3102 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003103 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003104 }
3105
Christopher Tated7faf532016-02-25 12:43:38 -08003106 private void parseWallpaperAttributes(XmlPullParser parser, WallpaperData wallpaper,
3107 boolean keepDimensionHints) {
Christopher Tatebe132e62016-02-10 12:59:49 -08003108 final String idString = parser.getAttributeValue(null, "id");
3109 if (idString != null) {
3110 final int id = wallpaper.wallpaperId = Integer.parseInt(idString);
3111 if (id > mWallpaperId) {
3112 mWallpaperId = id;
3113 }
3114 } else {
3115 wallpaper.wallpaperId = makeWallpaperIdLocked();
3116 }
3117
wilsonshiha282bf72018-11-30 12:48:05 +08003118 final DisplayData wpData = getDisplayDataOrCreate(DEFAULT_DISPLAY);
wilsonshih81e10a72018-11-15 10:54:21 +08003119
Christopher Tated7faf532016-02-25 12:43:38 -08003120 if (!keepDimensionHints) {
wilsonshih81e10a72018-11-15 10:54:21 +08003121 wpData.mWidth = Integer.parseInt(parser.getAttributeValue(null, "width"));
3122 wpData.mHeight = Integer.parseInt(parser.getAttributeValue(null, "height"));
Christopher Tated7faf532016-02-25 12:43:38 -08003123 }
Christopher Tatebe132e62016-02-10 12:59:49 -08003124 wallpaper.cropHint.left = getAttributeInt(parser, "cropLeft", 0);
3125 wallpaper.cropHint.top = getAttributeInt(parser, "cropTop", 0);
3126 wallpaper.cropHint.right = getAttributeInt(parser, "cropRight", 0);
3127 wallpaper.cropHint.bottom = getAttributeInt(parser, "cropBottom", 0);
wilsonshih81e10a72018-11-15 10:54:21 +08003128 wpData.mPadding.left = getAttributeInt(parser, "paddingLeft", 0);
3129 wpData.mPadding.top = getAttributeInt(parser, "paddingTop", 0);
3130 wpData.mPadding.right = getAttributeInt(parser, "paddingRight", 0);
3131 wpData.mPadding.bottom = getAttributeInt(parser, "paddingBottom", 0);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07003132 int colorsCount = getAttributeInt(parser, "colorsCount", 0);
3133 if (colorsCount > 0) {
Lucas Dupin84b89d92017-05-09 12:16:19 -07003134 Color primary = null, secondary = null, tertiary = null;
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07003135 for (int i = 0; i < colorsCount; i++) {
Lucas Dupin84b89d92017-05-09 12:16:19 -07003136 Color color = Color.valueOf(getAttributeInt(parser, "colorValue" + i, 0));
3137 if (i == 0) {
3138 primary = color;
3139 } else if (i == 1) {
3140 secondary = color;
3141 } else if (i == 2) {
3142 tertiary = color;
3143 } else {
3144 break;
3145 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07003146 }
Lucas Dupin84b89d92017-05-09 12:16:19 -07003147 int colorHints = getAttributeInt(parser, "colorHints", 0);
3148 wallpaper.primaryColors = new WallpaperColors(primary, secondary, tertiary, colorHints);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07003149 }
Christopher Tatebe132e62016-02-10 12:59:49 -08003150 wallpaper.name = parser.getAttributeValue(null, "name");
Christopher Tated7faf532016-02-25 12:43:38 -08003151 wallpaper.allowBackup = "true".equals(parser.getAttributeValue(null, "backup"));
Christopher Tatebe132e62016-02-10 12:59:49 -08003152 }
3153
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07003154 // Called by SystemBackupAgent after files are restored to disk.
Amith Yamasani09e9cdc2013-11-06 14:54:50 -08003155 public void settingsRestored() {
3156 // Verify caller is the system
3157 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
3158 throw new RuntimeException("settingsRestored() can only be called from the system process");
3159 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003160 // TODO: If necessary, make it work for secondary users as well. This currently assumes
3161 // restores only to the primary user
Joe Onorato8a9b2202010-02-26 18:56:32 -08003162 if (DEBUG) Slog.v(TAG, "settingsRestored");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003163 WallpaperData wallpaper = null;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003164 boolean success = false;
3165 synchronized (mLock) {
Christopher Tated7faf532016-02-25 12:43:38 -08003166 loadSettingsLocked(UserHandle.USER_SYSTEM, false);
Christopher Tatedb27b842016-02-25 14:39:17 -08003167 wallpaper = mWallpaperMap.get(UserHandle.USER_SYSTEM);
Christopher Tatead3c2592016-01-20 18:13:17 -08003168 wallpaper.wallpaperId = makeWallpaperIdLocked(); // always bump id at restore
Christopher Tated7faf532016-02-25 12:43:38 -08003169 wallpaper.allowBackup = true; // by definition if it was restored
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003170 if (wallpaper.nextWallpaperComponent != null
Justin Koh29c30162014-09-05 17:10:10 -07003171 && !wallpaper.nextWallpaperComponent.equals(mImageWallpaper)) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003172 if (!bindWallpaperComponentLocked(wallpaper.nextWallpaperComponent, false, false,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07003173 wallpaper, null)) {
Christopher Tatee3ab4d02009-12-16 14:03:31 -08003174 // No such live wallpaper or other failure; fall back to the default
3175 // live wallpaper (since the profile being restored indicated that the
3176 // user had selected a live rather than static one).
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07003177 bindWallpaperComponentLocked(null, false, false, wallpaper, null);
Christopher Tatee3ab4d02009-12-16 14:03:31 -08003178 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003179 success = true;
3180 } else {
Mike Clerona428b2c2009-11-15 22:53:08 -08003181 // If there's a wallpaper name, we use that. If that can't be loaded, then we
3182 // use the default.
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003183 if ("".equals(wallpaper.name)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003184 if (DEBUG) Slog.v(TAG, "settingsRestored: name is empty");
Mike Clerona428b2c2009-11-15 22:53:08 -08003185 success = true;
3186 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003187 if (DEBUG) Slog.v(TAG, "settingsRestored: attempting to restore named resource");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003188 success = restoreNamedResourceLocked(wallpaper);
Mike Clerona428b2c2009-11-15 22:53:08 -08003189 }
Christopher Tatead3c2592016-01-20 18:13:17 -08003190 if (DEBUG) Slog.v(TAG, "settingsRestored: success=" + success
3191 + " id=" + wallpaper.wallpaperId);
Mike Clerona428b2c2009-11-15 22:53:08 -08003192 if (success) {
wilsonshih81e10a72018-11-15 10:54:21 +08003193 generateCrop(wallpaper); // based on the new image + metadata
Christopher Tate41297ff2016-03-10 16:46:15 -08003194 bindWallpaperComponentLocked(wallpaper.nextWallpaperComponent, true, false,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07003195 wallpaper, null);
Mike Clerona428b2c2009-11-15 22:53:08 -08003196 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003197 }
3198 }
3199
3200 if (!success) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003201 Slog.e(TAG, "Failed to restore wallpaper: '" + wallpaper.name + "'");
3202 wallpaper.name = "";
Christopher Tatedb27b842016-02-25 14:39:17 -08003203 getWallpaperDir(UserHandle.USER_SYSTEM).delete();
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003204 }
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07003205
3206 synchronized (mLock) {
Christopher Tatedb27b842016-02-25 14:39:17 -08003207 saveSettingsLocked(UserHandle.USER_SYSTEM);
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07003208 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003209 }
3210
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003211 // Restore the named resource bitmap to both source + crop files
wilsonshiha282bf72018-11-30 12:48:05 +08003212 private boolean restoreNamedResourceLocked(WallpaperData wallpaper) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003213 if (wallpaper.name.length() > 4 && "res:".equals(wallpaper.name.substring(0, 4))) {
3214 String resName = wallpaper.name.substring(4);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003215
3216 String pkg = null;
3217 int colon = resName.indexOf(':');
3218 if (colon > 0) {
3219 pkg = resName.substring(0, colon);
3220 }
3221
3222 String ident = null;
3223 int slash = resName.lastIndexOf('/');
3224 if (slash > 0) {
3225 ident = resName.substring(slash+1);
3226 }
3227
3228 String type = null;
3229 if (colon > 0 && slash > 0 && (slash-colon) > 1) {
3230 type = resName.substring(colon+1, slash);
3231 }
3232
3233 if (pkg != null && ident != null && type != null) {
3234 int resId = -1;
3235 InputStream res = null;
3236 FileOutputStream fos = null;
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003237 FileOutputStream cos = null;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003238 try {
3239 Context c = mContext.createPackageContext(pkg, Context.CONTEXT_RESTRICTED);
3240 Resources r = c.getResources();
3241 resId = r.getIdentifier(resName, null, null);
3242 if (resId == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003243 Slog.e(TAG, "couldn't resolve identifier pkg=" + pkg + " type=" + type
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003244 + " ident=" + ident);
3245 return false;
3246 }
3247
3248 res = r.openRawResource(resId);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003249 if (wallpaper.wallpaperFile.exists()) {
3250 wallpaper.wallpaperFile.delete();
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003251 wallpaper.cropFile.delete();
Dianne Hackborn1afd1c92010-03-18 22:47:17 -07003252 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003253 fos = new FileOutputStream(wallpaper.wallpaperFile);
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003254 cos = new FileOutputStream(wallpaper.cropFile);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003255
3256 byte[] buffer = new byte[32768];
3257 int amt;
3258 while ((amt=res.read(buffer)) > 0) {
3259 fos.write(buffer, 0, amt);
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003260 cos.write(buffer, 0, amt);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003261 }
3262 // mWallpaperObserver will notice the close and send the change broadcast
3263
Joe Onorato8a9b2202010-02-26 18:56:32 -08003264 Slog.v(TAG, "Restored wallpaper: " + resName);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003265 return true;
3266 } catch (NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003267 Slog.e(TAG, "Package name " + pkg + " not found");
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003268 } catch (Resources.NotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003269 Slog.e(TAG, "Resource not found: " + resId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003270 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003271 Slog.e(TAG, "IOException while restoring wallpaper ", e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003272 } finally {
Christopher Tatead3c2592016-01-20 18:13:17 -08003273 IoUtils.closeQuietly(res);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003274 if (fos != null) {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07003275 FileUtils.sync(fos);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003276 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003277 if (cos != null) {
3278 FileUtils.sync(cos);
3279 }
3280 IoUtils.closeQuietly(fos);
3281 IoUtils.closeQuietly(cos);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003282 }
3283 }
3284 }
3285 return false;
3286 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003287
Dianne Hackborneb034652009-09-07 00:49:58 -07003288 @Override
3289 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06003290 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Dianne Hackborneb034652009-09-07 00:49:58 -07003291
3292 synchronized (mLock) {
Adrian Roosc28e3a92016-04-14 10:47:52 -07003293 pw.println("System wallpaper state:");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003294 for (int i = 0; i < mWallpaperMap.size(); i++) {
3295 WallpaperData wallpaper = mWallpaperMap.valueAt(i);
Christopher Tatead3c2592016-01-20 18:13:17 -08003296 pw.print(" User "); pw.print(wallpaper.userId);
wilsonshiha282bf72018-11-30 12:48:05 +08003297 pw.print(": id="); pw.println(wallpaper.wallpaperId);
3298 pw.println(" Display state:");
3299 forEachDisplayData(wpSize -> {
wilsonshih81e10a72018-11-15 10:54:21 +08003300 pw.print(" displayId=");
3301 pw.println(wpSize.mDisplayId);
3302 pw.print(" mWidth=");
3303 pw.print(wpSize.mWidth);
3304 pw.print(" mHeight=");
3305 pw.println(wpSize.mHeight);
3306 pw.print(" mPadding="); pw.println(wpSize.mPadding);
3307 });
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003308 pw.print(" mCropHint="); pw.println(wallpaper.cropHint);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07003309 pw.print(" mName="); pw.println(wallpaper.name);
Bryan Mawhinney0fa54f42017-07-06 17:09:37 +01003310 pw.print(" mAllowBackup="); pw.println(wallpaper.allowBackup);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07003311 pw.print(" mWallpaperComponent="); pw.println(wallpaper.wallpaperComponent);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003312 if (wallpaper.connection != null) {
3313 WallpaperConnection conn = wallpaper.connection;
3314 pw.print(" Wallpaper connection ");
3315 pw.print(conn);
3316 pw.println(":");
3317 if (conn.mInfo != null) {
3318 pw.print(" mInfo.component=");
3319 pw.println(conn.mInfo.getComponent());
3320 }
wilsonshihde93f492018-11-01 21:23:40 +08003321 conn.forEachDisplayConnector(connector -> {
wilsonshiha282bf72018-11-30 12:48:05 +08003322 pw.print(" mDisplayId=");
wilsonshihde93f492018-11-01 21:23:40 +08003323 pw.println(connector.mDisplayId);
wilsonshiha282bf72018-11-30 12:48:05 +08003324 pw.print(" mToken=");
wilsonshihde93f492018-11-01 21:23:40 +08003325 pw.println(connector.mToken);
wilsonshiha282bf72018-11-30 12:48:05 +08003326 pw.print(" mEngine=");
wilsonshihde93f492018-11-01 21:23:40 +08003327 pw.println(connector.mEngine);
3328 });
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003329 pw.print(" mService=");
3330 pw.println(conn.mService);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003331 pw.print(" mLastDiedTime=");
3332 pw.println(wallpaper.lastDiedTime - SystemClock.uptimeMillis());
3333 }
Dianne Hackborneb034652009-09-07 00:49:58 -07003334 }
Adrian Roosc28e3a92016-04-14 10:47:52 -07003335 pw.println("Lock wallpaper state:");
3336 for (int i = 0; i < mLockWallpaperMap.size(); i++) {
3337 WallpaperData wallpaper = mLockWallpaperMap.valueAt(i);
3338 pw.print(" User "); pw.print(wallpaper.userId);
wilsonshih81e10a72018-11-15 10:54:21 +08003339 pw.print(": id="); pw.println(wallpaper.wallpaperId);
Adrian Roosc28e3a92016-04-14 10:47:52 -07003340 pw.print(" mCropHint="); pw.println(wallpaper.cropHint);
Adrian Roosc28e3a92016-04-14 10:47:52 -07003341 pw.print(" mName="); pw.println(wallpaper.name);
Bryan Mawhinney0fa54f42017-07-06 17:09:37 +01003342 pw.print(" mAllowBackup="); pw.println(wallpaper.allowBackup);
Adrian Roosc28e3a92016-04-14 10:47:52 -07003343 }
wilsonshiha282bf72018-11-30 12:48:05 +08003344 pw.println("Fallback wallpaper state:");
3345 pw.print(" User "); pw.print(mFallbackWallpaper.userId);
3346 pw.print(": id="); pw.println(mFallbackWallpaper.wallpaperId);
3347 pw.print(" mCropHint="); pw.println(mFallbackWallpaper.cropHint);
3348 pw.print(" mName="); pw.println(mFallbackWallpaper.name);
3349 pw.print(" mAllowBackup="); pw.println(mFallbackWallpaper.allowBackup);
3350 if (mFallbackWallpaper.connection != null) {
3351 WallpaperConnection conn = mFallbackWallpaper.connection;
3352 pw.print(" Fallback Wallpaper connection ");
3353 pw.print(conn);
3354 pw.println(":");
3355 if (conn.mInfo != null) {
3356 pw.print(" mInfo.component=");
3357 pw.println(conn.mInfo.getComponent());
3358 }
3359 conn.forEachDisplayConnector(connector -> {
3360 pw.print(" mDisplayId=");
3361 pw.println(connector.mDisplayId);
3362 pw.print(" mToken=");
3363 pw.println(connector.mToken);
3364 pw.print(" mEngine=");
3365 pw.println(connector.mEngine);
3366 });
3367 pw.print(" mService=");
3368 pw.println(conn.mService);
3369 pw.print(" mLastDiedTime=");
3370 pw.println(mFallbackWallpaper.lastDiedTime - SystemClock.uptimeMillis());
3371 }
Dianne Hackborneb034652009-09-07 00:49:58 -07003372 }
3373 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003374}