blob: 9908b3657121bb60e1f28d41ff19f63386369950 [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;
Jeff Sharkey859856d2019-03-25 11:44:11 -060080import android.os.storage.StorageManager;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070081import android.service.wallpaper.IWallpaperConnection;
82import android.service.wallpaper.IWallpaperEngine;
83import android.service.wallpaper.IWallpaperService;
84import android.service.wallpaper.WallpaperService;
Christopher Tate8347b632016-04-29 18:59:18 -070085import android.system.ErrnoException;
86import android.system.Os;
Filip Gruszczynski5dcc3ac2014-10-13 15:51:39 -070087import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -080088import android.util.Slog;
Amith Yamasani37ce3a82012-02-06 12:04:42 -080089import android.util.SparseArray;
wilsonshiha282bf72018-11-30 12:48:05 +080090import android.util.SparseBooleanArray;
Joe Onorato9bb8fd72009-07-28 18:24:51 -070091import android.util.Xml;
Dianne Hackborn44bc17c2011-04-20 18:18:51 -070092import android.view.Display;
Valentin Iftime3047bb12018-12-28 17:02:19 +010093import android.view.DisplayInfo;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070094import android.view.IWindowManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095
Jeff Sharkey1cab76a2016-04-12 18:23:31 -060096import com.android.internal.R;
97import com.android.internal.content.PackageMonitor;
Christopher Tate190e8532016-07-11 11:35:34 -070098import com.android.internal.os.BackgroundThread;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060099import com.android.internal.util.DumpUtils;
Jeff Sharkey1cab76a2016-04-12 18:23:31 -0600100import com.android.internal.util.FastXmlSerializer;
101import com.android.internal.util.JournaledFile;
102import com.android.server.EventLogTags;
Adrian Roosc3f915e2016-09-06 11:40:53 -0700103import com.android.server.FgThread;
Andrii Kuliandd989612019-02-21 12:13:28 -0800104import com.android.server.LocalServices;
Jeff Sharkey1cab76a2016-04-12 18:23:31 -0600105import com.android.server.SystemService;
Andrii Kuliandd989612019-02-21 12:13:28 -0800106import com.android.server.wm.WindowManagerInternal;
Jeff Sharkey1cab76a2016-04-12 18:23:31 -0600107
108import libcore.io.IoUtils;
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700109
110import org.xmlpull.v1.XmlPullParser;
111import org.xmlpull.v1.XmlPullParserException;
112import org.xmlpull.v1.XmlSerializer;
113
Jeff Sharkey1cab76a2016-04-12 18:23:31 -0600114import java.io.BufferedOutputStream;
115import java.io.File;
116import java.io.FileDescriptor;
117import java.io.FileInputStream;
118import java.io.FileNotFoundException;
119import java.io.FileOutputStream;
120import java.io.IOException;
121import java.io.InputStream;
122import java.io.PrintWriter;
123import java.nio.charset.StandardCharsets;
Lucas Dupinfb3ab2a2017-08-08 14:17:30 -0400124import java.util.ArrayList;
Jeff Sharkey1cab76a2016-04-12 18:23:31 -0600125import java.util.Arrays;
126import java.util.List;
Christopher Tate2a6c55f2017-03-31 12:28:30 -0700127import java.util.Objects;
wilsonshihde93f492018-11-01 21:23:40 +0800128import java.util.function.Consumer;
wilsonshiha282bf72018-11-30 12:48:05 +0800129import java.util.function.Predicate;
Christopher Tatead3c2592016-01-20 18:13:17 -0800130
Daichi Hirono4bbf8522017-12-06 10:34:18 +0900131public class WallpaperManagerService extends IWallpaperManager.Stub
132 implements IWallpaperManagerService {
wilsonshiha282bf72018-11-30 12:48:05 +0800133 private static final String TAG = "WallpaperManagerService";
134 private static final boolean DEBUG = false;
135 private static final boolean DEBUG_LIVE = true;
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700136
Jeff Sharkey1cab76a2016-04-12 18:23:31 -0600137 public static class Lifecycle extends SystemService {
Daichi Hirono4bbf8522017-12-06 10:34:18 +0900138 private IWallpaperManagerService mService;
Jeff Sharkey1cab76a2016-04-12 18:23:31 -0600139
140 public Lifecycle(Context context) {
141 super(context);
142 }
143
144 @Override
145 public void onStart() {
Daichi Hirono4bbf8522017-12-06 10:34:18 +0900146 try {
147 final Class<? extends IWallpaperManagerService> klass =
148 (Class<? extends IWallpaperManagerService>)Class.forName(
149 getContext().getResources().getString(
150 R.string.config_wallpaperManagerServiceName));
151 mService = klass.getConstructor(Context.class).newInstance(getContext());
152 publishBinderService(Context.WALLPAPER_SERVICE, mService);
153 } catch (Exception exp) {
154 Slog.wtf(TAG, "Failed to instantiate WallpaperManagerService", exp);
155 }
Jeff Sharkey1cab76a2016-04-12 18:23:31 -0600156 }
157
158 @Override
159 public void onBootPhase(int phase) {
Daichi Hirono4bbf8522017-12-06 10:34:18 +0900160 if (mService != null) {
161 mService.onBootPhase(phase);
Jeff Sharkey1cab76a2016-04-12 18:23:31 -0600162 }
163 }
164
165 @Override
166 public void onUnlockUser(int userHandle) {
Daichi Hirono4bbf8522017-12-06 10:34:18 +0900167 if (mService != null) {
168 mService.onUnlockUser(userHandle);
169 }
Jeff Sharkey1cab76a2016-04-12 18:23:31 -0600170 }
171 }
172
wilsonshiha282bf72018-11-30 12:48:05 +0800173 private final Object mLock = new Object();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800174
Dianne Hackborn0cd48872009-08-13 18:51:59 -0700175 /**
176 * Minimum time between crashes of a wallpaper service for us to consider
177 * restarting it vs. just reverting to the static wallpaper.
178 */
wilsonshiha282bf72018-11-30 12:48:05 +0800179 private static final long MIN_WALLPAPER_CRASH_TIME = 10000;
180 private static final int MAX_WALLPAPER_COMPONENT_LOG_LENGTH = 128;
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800181 static final String WALLPAPER = "wallpaper_orig";
182 static final String WALLPAPER_CROP = "wallpaper";
Christopher Tatebe132e62016-02-10 12:59:49 -0800183 static final String WALLPAPER_LOCK_ORIG = "wallpaper_lock_orig";
184 static final String WALLPAPER_LOCK_CROP = "wallpaper_lock";
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800185 static final String WALLPAPER_INFO = "wallpaper_info.xml";
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -0700186
Christopher Tatebe132e62016-02-10 12:59:49 -0800187 // All the various per-user state files we need to be aware of
wilsonshiha282bf72018-11-30 12:48:05 +0800188 private static final String[] sPerUserFiles = new String[] {
Christopher Tatebe132e62016-02-10 12:59:49 -0800189 WALLPAPER, WALLPAPER_CROP,
190 WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP,
191 WALLPAPER_INFO
192 };
193
Dianne Hackbornbce0cbb2012-10-05 11:06:53 -0700194 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195 * Observes the wallpaper for changes and notifies all IWallpaperServiceCallbacks
196 * that the wallpaper has changed. The CREATE is triggered when there is no
197 * wallpaper set and is created for the first time. The CLOSE_WRITE is triggered
Christopher Tate190e8532016-07-11 11:35:34 -0700198 * every time the wallpaper is changed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800199 */
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800200 private class WallpaperObserver extends FileObserver {
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700201
Christopher Tatebe132e62016-02-10 12:59:49 -0800202 final int mUserId;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800203 final WallpaperData mWallpaper;
204 final File mWallpaperDir;
205 final File mWallpaperFile;
Christopher Tatebe132e62016-02-10 12:59:49 -0800206 final File mWallpaperLockFile;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800207
208 public WallpaperObserver(WallpaperData wallpaper) {
209 super(getWallpaperDir(wallpaper.userId).getAbsolutePath(),
Christopher Tateda058e22014-10-08 14:51:09 -0700210 CLOSE_WRITE | MOVED_TO | DELETE | DELETE_SELF);
Christopher Tatebe132e62016-02-10 12:59:49 -0800211 mUserId = wallpaper.userId;
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800212 mWallpaperDir = getWallpaperDir(wallpaper.userId);
213 mWallpaper = wallpaper;
214 mWallpaperFile = new File(mWallpaperDir, WALLPAPER);
Christopher Tatebe132e62016-02-10 12:59:49 -0800215 mWallpaperLockFile = new File(mWallpaperDir, WALLPAPER_LOCK_ORIG);
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800216 }
217
Christopher Tatebe132e62016-02-10 12:59:49 -0800218 private WallpaperData dataForEvent(boolean sysChanged, boolean lockChanged) {
219 WallpaperData wallpaper = null;
220 synchronized (mLock) {
221 if (lockChanged) {
222 wallpaper = mLockWallpaperMap.get(mUserId);
223 }
224 if (wallpaper == null) {
225 // no lock-specific wallpaper exists, or sys case, handled together
226 wallpaper = mWallpaperMap.get(mUserId);
227 }
228 }
229 return (wallpaper != null) ? wallpaper : mWallpaper;
230 }
231
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800232 @Override
233 public void onEvent(int event, String path) {
234 if (path == null) {
235 return;
236 }
Christopher Tated7faf532016-02-25 12:43:38 -0800237 final boolean moved = (event == MOVED_TO);
238 final boolean written = (event == CLOSE_WRITE || moved);
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800239 final File changedFile = new File(mWallpaperDir, path);
240
Christopher Tatebe132e62016-02-10 12:59:49 -0800241 // System and system+lock changes happen on the system wallpaper input file;
242 // lock-only changes happen on the dedicated lock wallpaper input file
243 final boolean sysWallpaperChanged = (mWallpaperFile.equals(changedFile));
244 final boolean lockWallpaperChanged = (mWallpaperLockFile.equals(changedFile));
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700245 int notifyColorsWhich = 0;
Christopher Tatebe132e62016-02-10 12:59:49 -0800246 WallpaperData wallpaper = dataForEvent(sysWallpaperChanged, lockWallpaperChanged);
247
248 if (DEBUG) {
249 Slog.v(TAG, "Wallpaper file change: evt=" + event
250 + " path=" + path
251 + " sys=" + sysWallpaperChanged
252 + " lock=" + lockWallpaperChanged
253 + " imagePending=" + wallpaper.imageWallpaperPending
254 + " whichPending=0x" + Integer.toHexString(wallpaper.whichPending)
255 + " written=" + written);
256 }
Christopher Tate8347b632016-04-29 18:59:18 -0700257
258 if (moved && lockWallpaperChanged) {
259 // We just migrated sys -> lock to preserve imagery for an impending
Christopher Tatefa7d97f2016-06-30 12:21:57 -0700260 // new system-only wallpaper. Tell keyguard about it and make sure it
261 // has the right SELinux label.
Christopher Tate8347b632016-04-29 18:59:18 -0700262 if (DEBUG) {
263 Slog.i(TAG, "Sys -> lock MOVED_TO");
264 }
Christopher Tatefa7d97f2016-06-30 12:21:57 -0700265 SELinux.restorecon(changedFile);
Christopher Tate8347b632016-04-29 18:59:18 -0700266 notifyLockWallpaperChanged();
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700267 notifyWallpaperColorsChanged(wallpaper, FLAG_LOCK);
Christopher Tate8347b632016-04-29 18:59:18 -0700268 return;
269 }
270
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800271 synchronized (mLock) {
Christopher Tatebe132e62016-02-10 12:59:49 -0800272 if (sysWallpaperChanged || lockWallpaperChanged) {
273 notifyCallbacksLocked(wallpaper);
274 if (wallpaper.wallpaperComponent == null
Christopher Tateda058e22014-10-08 14:51:09 -0700275 || event != CLOSE_WRITE // includes the MOVED_TO case
Christopher Tatebe132e62016-02-10 12:59:49 -0800276 || wallpaper.imageWallpaperPending) {
Christopher Tateda058e22014-10-08 14:51:09 -0700277 if (written) {
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800278 // The image source has finished writing the source image,
279 // so we now produce the crop rect (in the background), and
280 // only publish the new displayable (sub)image as a result
281 // of that work.
Christopher Tatebe132e62016-02-10 12:59:49 -0800282 if (DEBUG) {
283 Slog.v(TAG, "Wallpaper written; generating crop");
284 }
Christopher Tateebadfb12016-07-25 14:50:08 -0700285 SELinux.restorecon(changedFile);
Christopher Tated7faf532016-02-25 12:43:38 -0800286 if (moved) {
287 // This is a restore, so generate the crop using any just-restored new
288 // crop guidelines, making sure to preserve our local dimension hints.
Christopher Tatefa7d97f2016-06-30 12:21:57 -0700289 // We also make sure to reapply the correct SELinux label.
Christopher Tated7faf532016-02-25 12:43:38 -0800290 if (DEBUG) {
291 Slog.v(TAG, "moved-to, therefore restore; reloading metadata");
292 }
293 loadSettingsLocked(wallpaper.userId, true);
294 }
Christopher Tatebe132e62016-02-10 12:59:49 -0800295 generateCrop(wallpaper);
296 if (DEBUG) {
297 Slog.v(TAG, "Crop done; invoking completion callback");
298 }
299 wallpaper.imageWallpaperPending = false;
Christopher Tatebe132e62016-02-10 12:59:49 -0800300 if (sysWallpaperChanged) {
301 // If this was the system wallpaper, rebind...
302 bindWallpaperComponentLocked(mImageWallpaper, true,
303 false, wallpaper, null);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700304 notifyColorsWhich |= FLAG_SYSTEM;
Christopher Tatebe132e62016-02-10 12:59:49 -0800305 }
306 if (lockWallpaperChanged
Christopher Tateedf7d042016-03-29 18:24:25 -0700307 || (wallpaper.whichPending & FLAG_LOCK) != 0) {
Christopher Tatebe132e62016-02-10 12:59:49 -0800308 if (DEBUG) {
Christopher Tatedb27b842016-02-25 14:39:17 -0800309 Slog.i(TAG, "Lock-relevant wallpaper changed");
Christopher Tatebe132e62016-02-10 12:59:49 -0800310 }
Christopher Tatedb27b842016-02-25 14:39:17 -0800311 // either a lock-only wallpaper commit or a system+lock event.
312 // if it's system-plus-lock we need to wipe the lock bookkeeping;
313 // we're falling back to displaying the system wallpaper there.
314 if (!lockWallpaperChanged) {
315 mLockWallpaperMap.remove(wallpaper.userId);
316 }
317 // and in any case, tell keyguard about it
Christopher Tate8347b632016-04-29 18:59:18 -0700318 notifyLockWallpaperChanged();
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700319 notifyColorsWhich |= FLAG_LOCK;
Christopher Tatebe132e62016-02-10 12:59:49 -0800320 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700321
Christopher Tatedb27b842016-02-25 14:39:17 -0800322 saveSettingsLocked(wallpaper.userId);
Christopher Tate8efbe0d2017-08-29 16:50:13 -0700323
324 // Publish completion *after* we've persisted the changes
325 if (wallpaper.setComplete != null) {
326 try {
327 wallpaper.setComplete.onWallpaperChanged();
328 } catch (RemoteException e) {
329 // if this fails we don't really care; the setting app may just
330 // have crashed and that sort of thing is a fact of life.
331 }
332 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -0700333 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800334 }
335 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800336 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700337
338 // Outside of the lock since it will synchronize itself
339 if (notifyColorsWhich != 0) {
340 notifyWallpaperColorsChanged(wallpaper, notifyColorsWhich);
341 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800342 }
343 }
344
wilsonshiha282bf72018-11-30 12:48:05 +0800345 private void notifyLockWallpaperChanged() {
Christopher Tate8347b632016-04-29 18:59:18 -0700346 final IWallpaperManagerCallback cb = mKeyguardListener;
347 if (cb != null) {
348 try {
349 cb.onWallpaperChanged();
350 } catch (RemoteException e) {
351 // Oh well it went away; no big deal
352 }
353 }
354 }
355
Lucas Dupin50ba9912017-07-14 11:55:05 -0700356 private void notifyWallpaperColorsChanged(@NonNull WallpaperData wallpaper, int which) {
wilsonshih36597d42018-12-05 18:56:39 +0800357 if (wallpaper.connection != null) {
358 wallpaper.connection.forEachDisplayConnector(connector -> {
359 notifyWallpaperColorsChangedOnDisplay(wallpaper, which, connector.mDisplayId);
360 });
361 } else { // Lock wallpaper does not have WallpaperConnection.
362 notifyWallpaperColorsChangedOnDisplay(wallpaper, which, DEFAULT_DISPLAY);
363 }
364 }
365
366 private RemoteCallbackList<IWallpaperManagerCallback> getWallpaperCallbacks(int userId,
367 int displayId) {
368 RemoteCallbackList<IWallpaperManagerCallback> listeners = null;
369 final SparseArray<RemoteCallbackList<IWallpaperManagerCallback>> displayListeners =
370 mColorsChangedListeners.get(userId);
371 if (displayListeners != null) {
372 listeners = displayListeners.get(displayId);
373 }
374 return listeners;
375 }
376
377 private void notifyWallpaperColorsChangedOnDisplay(@NonNull WallpaperData wallpaper, int which,
378 int displayId) {
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700379 boolean needsExtraction;
380 synchronized (mLock) {
Lucas Dupin50ba9912017-07-14 11:55:05 -0700381 final RemoteCallbackList<IWallpaperManagerCallback> currentUserColorListeners =
wilsonshih36597d42018-12-05 18:56:39 +0800382 getWallpaperCallbacks(wallpaper.userId, displayId);
Lucas Dupin50ba9912017-07-14 11:55:05 -0700383 final RemoteCallbackList<IWallpaperManagerCallback> userAllColorListeners =
wilsonshih36597d42018-12-05 18:56:39 +0800384 getWallpaperCallbacks(UserHandle.USER_ALL, displayId);
Lucas Dupin50ba9912017-07-14 11:55:05 -0700385 // No-op until someone is listening to it.
386 if (emptyCallbackList(currentUserColorListeners) &&
387 emptyCallbackList(userAllColorListeners)) {
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700388 return;
Lucas Dupin50ba9912017-07-14 11:55:05 -0700389 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700390
391 if (DEBUG) {
wilsonshih36597d42018-12-05 18:56:39 +0800392 Slog.v(TAG, "notifyWallpaperColorsChangedOnDisplay " + which);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700393 }
394
395 needsExtraction = wallpaper.primaryColors == null;
396 }
397
Lucas Dupin75ec3792017-06-29 14:07:18 -0700398 // Let's notify the current values, it's fine if it's null, it just means
399 // that we don't know yet.
wilsonshih36597d42018-12-05 18:56:39 +0800400 notifyColorListeners(wallpaper.primaryColors, which, wallpaper.userId, displayId);
Lucas Dupin75ec3792017-06-29 14:07:18 -0700401
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700402 if (needsExtraction) {
403 extractColors(wallpaper);
Lucas Dupin50ba9912017-07-14 11:55:05 -0700404 synchronized (mLock) {
405 // Don't need to notify if nothing changed.
406 if (wallpaper.primaryColors == null) {
407 return;
408 }
409 }
wilsonshih36597d42018-12-05 18:56:39 +0800410 notifyColorListeners(wallpaper.primaryColors, which, wallpaper.userId, displayId);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700411 }
Lucas Dupin75ec3792017-06-29 14:07:18 -0700412 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700413
Lucas Dupin50ba9912017-07-14 11:55:05 -0700414 private static <T extends IInterface> boolean emptyCallbackList(RemoteCallbackList<T> list) {
415 return (list == null || list.getRegisteredCallbackCount() == 0);
416 }
417
418 private void notifyColorListeners(@NonNull WallpaperColors wallpaperColors, int which,
wilsonshih36597d42018-12-05 18:56:39 +0800419 int userId, int displayId) {
Lucas Dupin75ec3792017-06-29 14:07:18 -0700420 final IWallpaperManagerCallback keyguardListener;
Lucas Dupinfb3ab2a2017-08-08 14:17:30 -0400421 final ArrayList<IWallpaperManagerCallback> colorListeners = new ArrayList<>();
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700422 synchronized (mLock) {
Lucas Dupinfb3ab2a2017-08-08 14:17:30 -0400423 final RemoteCallbackList<IWallpaperManagerCallback> currentUserColorListeners =
wilsonshih36597d42018-12-05 18:56:39 +0800424 getWallpaperCallbacks(userId, displayId);
Lucas Dupinfb3ab2a2017-08-08 14:17:30 -0400425 final RemoteCallbackList<IWallpaperManagerCallback> userAllColorListeners =
wilsonshih36597d42018-12-05 18:56:39 +0800426 getWallpaperCallbacks(UserHandle.USER_ALL, displayId);
Lucas Dupin75ec3792017-06-29 14:07:18 -0700427 keyguardListener = mKeyguardListener;
Lucas Dupinfb3ab2a2017-08-08 14:17:30 -0400428
429 if (currentUserColorListeners != null) {
430 final int count = currentUserColorListeners.beginBroadcast();
431 for (int i = 0; i < count; i++) {
432 colorListeners.add(currentUserColorListeners.getBroadcastItem(i));
433 }
434 currentUserColorListeners.finishBroadcast();
435 }
436
437 if (userAllColorListeners != null) {
438 final int count = userAllColorListeners.beginBroadcast();
439 for (int i = 0; i < count; i++) {
440 colorListeners.add(userAllColorListeners.getBroadcastItem(i));
441 }
442 userAllColorListeners.finishBroadcast();
443 }
Lucas Dupin75ec3792017-06-29 14:07:18 -0700444 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700445
Lucas Dupinfb3ab2a2017-08-08 14:17:30 -0400446 final int count = colorListeners.size();
447 for (int i = 0; i < count; i++) {
448 try {
449 colorListeners.get(i).onWallpaperColorsChanged(wallpaperColors, which, userId);
450 } catch (RemoteException e) {
451 // Callback is gone, it's not necessary to unregister it since
452 // RemoteCallbackList#getBroadcastItem will take care of it.
Lucas Dupin75ec3792017-06-29 14:07:18 -0700453 }
454 }
455
wilsonshih36597d42018-12-05 18:56:39 +0800456 // Only shows Keyguard on default display
457 if (keyguardListener != null && displayId == DEFAULT_DISPLAY) {
Lucas Dupin75ec3792017-06-29 14:07:18 -0700458 try {
Lucas Dupin50ba9912017-07-14 11:55:05 -0700459 keyguardListener.onWallpaperColorsChanged(wallpaperColors, which, userId);
Lucas Dupin75ec3792017-06-29 14:07:18 -0700460 } catch (RemoteException e) {
461 // Oh well it went away; no big deal
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700462 }
463 }
464 }
465
Lucas Dupinbcae5852017-05-03 12:42:58 -0700466 /**
467 * We can easily extract colors from an ImageWallpaper since it's only a bitmap.
Lucas Dupin284836b2017-06-23 15:28:41 -0700468 * In this case, using the crop is more than enough. Live wallpapers are just ignored.
Lucas Dupinbcae5852017-05-03 12:42:58 -0700469 *
470 * @param wallpaper a wallpaper representation
471 */
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700472 private void extractColors(WallpaperData wallpaper) {
473 String cropFile = null;
wilsonshih31d70a12019-01-14 12:42:35 +0800474 boolean defaultImageWallpaper = false;
Lucas Dupin284836b2017-06-23 15:28:41 -0700475 int wallpaperId;
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700476
wilsonshih36597d42018-12-05 18:56:39 +0800477 if (wallpaper.equals(mFallbackWallpaper)) {
wilsonshihfa24e4f2019-02-22 10:29:19 +0800478 synchronized (mLock) {
479 if (mFallbackWallpaper.primaryColors != null) return;
480 }
481 final WallpaperColors colors = extractDefaultImageWallpaperColors();
482 synchronized (mLock) {
483 mFallbackWallpaper.primaryColors = colors;
484 }
wilsonshih36597d42018-12-05 18:56:39 +0800485 return;
486 }
487
Lucas Dupinbcae5852017-05-03 12:42:58 -0700488 synchronized (mLock) {
Lucas Dupin284836b2017-06-23 15:28:41 -0700489 // Not having a wallpaperComponent means it's a lock screen wallpaper.
490 final boolean imageWallpaper = mImageWallpaper.equals(wallpaper.wallpaperComponent)
Lucas Dupinbcae5852017-05-03 12:42:58 -0700491 || wallpaper.wallpaperComponent == null;
Lucas Dupin284836b2017-06-23 15:28:41 -0700492 if (imageWallpaper && wallpaper.cropFile != null && wallpaper.cropFile.exists()) {
493 cropFile = wallpaper.cropFile.getAbsolutePath();
wilsonshih31d70a12019-01-14 12:42:35 +0800494 } else if (imageWallpaper && !wallpaper.cropExists() && !wallpaper.sourceExists()) {
495 defaultImageWallpaper = true;
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700496 }
497 wallpaperId = wallpaper.wallpaperId;
498 }
499
Lucas Dupin84b89d92017-05-09 12:16:19 -0700500 WallpaperColors colors = null;
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700501 if (cropFile != null) {
Lucas Dupin84b89d92017-05-09 12:16:19 -0700502 Bitmap bitmap = BitmapFactory.decodeFile(cropFile);
Lucas Dupin284836b2017-06-23 15:28:41 -0700503 if (bitmap != null) {
Lucas Dupinb5e50532018-05-24 16:33:14 +0000504 colors = WallpaperColors.fromBitmap(bitmap);
Lucas Dupin284836b2017-06-23 15:28:41 -0700505 bitmap.recycle();
506 }
wilsonshih31d70a12019-01-14 12:42:35 +0800507 } else if (defaultImageWallpaper) {
508 // There is no crop and source file because this is default image wallpaper.
wilsonshihfa24e4f2019-02-22 10:29:19 +0800509 colors = extractDefaultImageWallpaperColors();
Lucas Dupinbcae5852017-05-03 12:42:58 -0700510 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700511
Lucas Dupin84b89d92017-05-09 12:16:19 -0700512 if (colors == null) {
Lucas Dupinbcae5852017-05-03 12:42:58 -0700513 Slog.w(TAG, "Cannot extract colors because wallpaper could not be read.");
514 return;
515 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700516
Lucas Dupinbcae5852017-05-03 12:42:58 -0700517 synchronized (mLock) {
518 if (wallpaper.wallpaperId == wallpaperId) {
Lucas Dupin84b89d92017-05-09 12:16:19 -0700519 wallpaper.primaryColors = colors;
Lucas Dupin75ec3792017-06-29 14:07:18 -0700520 // Now that we have the colors, let's save them into the xml
521 // to avoid having to run this again.
522 saveSettingsLocked(wallpaper.userId);
Lucas Dupinbcae5852017-05-03 12:42:58 -0700523 } else {
524 Slog.w(TAG, "Not setting primary colors since wallpaper changed");
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700525 }
526 }
527 }
528
wilsonshihfa24e4f2019-02-22 10:29:19 +0800529 private WallpaperColors extractDefaultImageWallpaperColors() {
530 if (DEBUG) Slog.d(TAG, "Extract default image wallpaper colors");
531
wilsonshih36597d42018-12-05 18:56:39 +0800532 synchronized (mLock) {
wilsonshihfa24e4f2019-02-22 10:29:19 +0800533 if (mCacheDefaultImageWallpaperColors != null) return mCacheDefaultImageWallpaperColors;
wilsonshih36597d42018-12-05 18:56:39 +0800534 }
535
wilsonshih36597d42018-12-05 18:56:39 +0800536 WallpaperColors colors = null;
wilsonshihfa24e4f2019-02-22 10:29:19 +0800537 try (InputStream is = WallpaperManager.openDefaultWallpaper(mContext, FLAG_SYSTEM)) {
538 if (is == null) {
539 Slog.w(TAG, "Can't open default wallpaper stream");
540 return null;
wilsonshih36597d42018-12-05 18:56:39 +0800541 }
wilsonshihfa24e4f2019-02-22 10:29:19 +0800542
543 final BitmapFactory.Options options = new BitmapFactory.Options();
544 final Bitmap bitmap = BitmapFactory.decodeStream(is, null, options);
545 if (bitmap != null) {
546 colors = WallpaperColors.fromBitmap(bitmap);
547 bitmap.recycle();
548 }
549 } catch (OutOfMemoryError e) {
550 Slog.w(TAG, "Can't decode default wallpaper stream", e);
551 } catch (IOException e) {
552 Slog.w(TAG, "Can't close default wallpaper stream", e);
wilsonshih36597d42018-12-05 18:56:39 +0800553 }
554
555 if (colors == null) {
556 Slog.e(TAG, "Extract default image wallpaper colors failed");
wilsonshihfa24e4f2019-02-22 10:29:19 +0800557 } else {
558 synchronized (mLock) {
559 mCacheDefaultImageWallpaperColors = colors;
560 }
wilsonshih36597d42018-12-05 18:56:39 +0800561 }
562
wilsonshihfa24e4f2019-02-22 10:29:19 +0800563 return colors;
wilsonshih36597d42018-12-05 18:56:39 +0800564 }
565
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800566 /**
567 * Once a new wallpaper has been written via setWallpaper(...), it needs to be cropped
568 * for display.
569 */
570 private void generateCrop(WallpaperData wallpaper) {
571 boolean success = false;
Christopher Tate1a96b632016-03-22 15:25:42 -0700572
wilsonshih81e10a72018-11-15 10:54:21 +0800573 // Only generate crop for default display.
wilsonshiha282bf72018-11-30 12:48:05 +0800574 final DisplayData wpData = getDisplayDataOrCreate(DEFAULT_DISPLAY);
Christopher Tate1a96b632016-03-22 15:25:42 -0700575 Rect cropHint = new Rect(wallpaper.cropHint);
Christopher Tatebe132e62016-02-10 12:59:49 -0800576
577 if (DEBUG) {
578 Slog.v(TAG, "Generating crop for new wallpaper(s): 0x"
579 + Integer.toHexString(wallpaper.whichPending)
Christopher Tate1a96b632016-03-22 15:25:42 -0700580 + " to " + wallpaper.cropFile.getName()
581 + " crop=(" + cropHint.width() + 'x' + cropHint.height()
wilsonshih81e10a72018-11-15 10:54:21 +0800582 + ") dim=(" + wpData.mWidth + 'x' + wpData.mHeight + ')');
Christopher Tatebe132e62016-02-10 12:59:49 -0800583 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800584
585 // Analyse the source; needed in multiple cases
586 BitmapFactory.Options options = new BitmapFactory.Options();
587 options.inJustDecodeBounds = true;
588 BitmapFactory.decodeFile(wallpaper.wallpaperFile.getAbsolutePath(), options);
Christopher Tate1a96b632016-03-22 15:25:42 -0700589 if (options.outWidth <= 0 || options.outHeight <= 0) {
Joe LaPennac298b162016-05-02 15:25:50 -0700590 Slog.w(TAG, "Invalid wallpaper data");
Christopher Tate1a96b632016-03-22 15:25:42 -0700591 success = false;
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800592 } else {
Christopher Tate1a96b632016-03-22 15:25:42 -0700593 boolean needCrop = false;
594 boolean needScale = false;
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800595
Christopher Tate1a96b632016-03-22 15:25:42 -0700596 // Empty crop means use the full image
597 if (cropHint.isEmpty()) {
598 cropHint.left = cropHint.top = 0;
599 cropHint.right = options.outWidth;
600 cropHint.bottom = options.outHeight;
601 } else {
602 // force the crop rect to lie within the measured bounds
603 cropHint.offset(
604 (cropHint.right > options.outWidth ? options.outWidth - cropHint.right : 0),
605 (cropHint.bottom > options.outHeight ? options.outHeight - cropHint.bottom : 0));
606
Adrian Roos5c97ff22016-08-31 10:25:38 -0700607 // If the crop hint was larger than the image we just overshot. Patch things up.
608 if (cropHint.left < 0) {
609 cropHint.left = 0;
610 }
611 if (cropHint.top < 0) {
612 cropHint.top = 0;
613 }
614
Christopher Tate1a96b632016-03-22 15:25:42 -0700615 // Don't bother cropping if what we're left with is identity
Christopher Tateebadfb12016-07-25 14:50:08 -0700616 needCrop = (options.outHeight > cropHint.height()
Adrian Roos5c97ff22016-08-31 10:25:38 -0700617 || options.outWidth > cropHint.width());
Christopher Tate1a96b632016-03-22 15:25:42 -0700618 }
619
620 // scale if the crop height winds up not matching the recommended metrics
wilsonshih81e10a72018-11-15 10:54:21 +0800621 needScale = (wpData.mHeight != cropHint.height());
Christopher Tate1a96b632016-03-22 15:25:42 -0700622
Valentin Iftime3047bb12018-12-28 17:02:19 +0100623 //make sure screen aspect ratio is preserved if width is scaled under screen size
624 if (needScale) {
625 final DisplayInfo displayInfo = new DisplayInfo();
626 mDisplayManager.getDisplay(DEFAULT_DISPLAY).getDisplayInfo(displayInfo);
627 final float scaleByHeight = (float) wpData.mHeight / (float) cropHint.height();
628 final int newWidth = (int) (cropHint.width() * scaleByHeight);
629 if (newWidth < displayInfo.logicalWidth) {
630 final float screenAspectRatio =
631 (float) displayInfo.logicalHeight / (float) displayInfo.logicalWidth;
632 cropHint.bottom = (int) (cropHint.width() * screenAspectRatio);
633 needCrop = true;
634 }
635 }
636
Christopher Tate1a96b632016-03-22 15:25:42 -0700637 if (DEBUG) {
638 Slog.v(TAG, "crop: w=" + cropHint.width() + " h=" + cropHint.height());
wilsonshih81e10a72018-11-15 10:54:21 +0800639 Slog.v(TAG, "dims: w=" + wpData.mWidth + " h=" + wpData.mHeight);
Christopher Tate1a96b632016-03-22 15:25:42 -0700640 Slog.v(TAG, "meas: w=" + options.outWidth + " h=" + options.outHeight);
641 Slog.v(TAG, "crop?=" + needCrop + " scale?=" + needScale);
642 }
643
644 if (!needCrop && !needScale) {
645 // Simple case: the nominal crop fits what we want, so we take
646 // the whole thing and just copy the image file directly.
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800647 if (DEBUG) {
Christopher Tate1a96b632016-03-22 15:25:42 -0700648 Slog.v(TAG, "Null crop of new wallpaper; copying");
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800649 }
Christopher Tate1a96b632016-03-22 15:25:42 -0700650 success = FileUtils.copyFile(wallpaper.wallpaperFile, wallpaper.cropFile);
651 if (!success) {
652 wallpaper.cropFile.delete();
653 // TODO: fall back to default wallpaper in this case
654 }
655 } else {
656 // Fancy case: crop and scale. First, we decode and scale down if appropriate.
657 FileOutputStream f = null;
658 BufferedOutputStream bos = null;
659 try {
660 BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(
661 wallpaper.wallpaperFile.getAbsolutePath(), false);
662
663 // This actually downsamples only by powers of two, but that's okay; we do
664 // a proper scaling blit later. This is to minimize transient RAM use.
665 // We calculate the largest power-of-two under the actual ratio rather than
666 // just let the decode take care of it because we also want to remap where the
667 // cropHint rectangle lies in the decoded [super]rect.
668 final BitmapFactory.Options scaler;
wilsonshih81e10a72018-11-15 10:54:21 +0800669 final int actualScale = cropHint.height() / wpData.mHeight;
Christopher Tate1a96b632016-03-22 15:25:42 -0700670 int scale = 1;
671 while (2*scale < actualScale) {
672 scale *= 2;
673 }
674 if (scale > 1) {
675 scaler = new BitmapFactory.Options();
676 scaler.inSampleSize = scale;
677 if (DEBUG) {
678 Slog.v(TAG, "Downsampling cropped rect with scale " + scale);
679 }
680 } else {
681 scaler = null;
682 }
683 Bitmap cropped = decoder.decodeRegion(cropHint, scaler);
684 decoder.recycle();
685
686 if (cropped == null) {
687 Slog.e(TAG, "Could not decode new wallpaper");
688 } else {
689 // We've got the extracted crop; now we want to scale it properly to
690 // the desired rectangle. That's a height-biased operation: make it
691 // fit the hinted height, and accept whatever width we end up with.
692 cropHint.offsetTo(0, 0);
693 cropHint.right /= scale; // adjust by downsampling factor
694 cropHint.bottom /= scale;
wilsonshih81e10a72018-11-15 10:54:21 +0800695 final float heightR =
696 ((float) wpData.mHeight) / ((float) cropHint.height());
Christopher Tate1a96b632016-03-22 15:25:42 -0700697 if (DEBUG) {
698 Slog.v(TAG, "scale " + heightR + ", extracting " + cropHint);
699 }
700 final int destWidth = (int)(cropHint.width() * heightR);
701 final Bitmap finalCrop = Bitmap.createScaledBitmap(cropped,
wilsonshih81e10a72018-11-15 10:54:21 +0800702 destWidth, wpData.mHeight, true);
Christopher Tate1a96b632016-03-22 15:25:42 -0700703 if (DEBUG) {
704 Slog.v(TAG, "Final extract:");
wilsonshih81e10a72018-11-15 10:54:21 +0800705 Slog.v(TAG, " dims: w=" + wpData.mWidth
706 + " h=" + wpData.mHeight);
Christopher Tate1a96b632016-03-22 15:25:42 -0700707 Slog.v(TAG, " out: w=" + finalCrop.getWidth()
708 + " h=" + finalCrop.getHeight());
709 }
710
711 f = new FileOutputStream(wallpaper.cropFile);
712 bos = new BufferedOutputStream(f, 32*1024);
Christopher Tatec484f542016-05-11 14:31:34 -0700713 finalCrop.compress(Bitmap.CompressFormat.JPEG, 100, bos);
Christopher Tate1a96b632016-03-22 15:25:42 -0700714 bos.flush(); // don't rely on the implicit flush-at-close when noting success
715 success = true;
716 }
717 } catch (Exception e) {
718 if (DEBUG) {
719 Slog.e(TAG, "Error decoding crop", e);
720 }
721 } finally {
722 IoUtils.closeQuietly(bos);
723 IoUtils.closeQuietly(f);
724 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800725 }
726 }
727
728 if (!success) {
729 Slog.e(TAG, "Unable to apply new wallpaper");
730 wallpaper.cropFile.delete();
731 }
732
733 if (wallpaper.cropFile.exists()) {
734 boolean didRestorecon = SELinux.restorecon(wallpaper.cropFile.getAbsoluteFile());
735 if (DEBUG) {
736 Slog.v(TAG, "restorecon() of crop file returned " + didRestorecon);
737 }
738 }
739 }
740
wilsonshiha282bf72018-11-30 12:48:05 +0800741 private final Context mContext;
742 private final IWindowManager mIWindowManager;
Andrii Kuliandd989612019-02-21 12:13:28 -0800743 private final WindowManagerInternal mWindowManagerInternal;
wilsonshiha282bf72018-11-30 12:48:05 +0800744 private final IPackageManager mIPackageManager;
745 private final MyPackageMonitor mMonitor;
746 private final AppOpsManager mAppOpsManager;
wilsonshihde93f492018-11-01 21:23:40 +0800747
748 private final DisplayManager mDisplayManager;
749 private final DisplayManager.DisplayListener mDisplayListener =
750 new DisplayManager.DisplayListener() {
751
752 @Override
753 public void onDisplayAdded(int displayId) {
wilsonshihde93f492018-11-01 21:23:40 +0800754 }
755
756 @Override
757 public void onDisplayRemoved(int displayId) {
758 synchronized (mLock) {
759 if (mLastWallpaper != null) {
wilsonshiha282bf72018-11-30 12:48:05 +0800760 WallpaperData targetWallpaper = null;
761 if (mLastWallpaper.connection.containsDisplay(displayId)) {
762 targetWallpaper = mLastWallpaper;
763 } else if (mFallbackWallpaper.connection.containsDisplay(displayId)) {
764 targetWallpaper = mFallbackWallpaper;
765 }
766 if (targetWallpaper == null) return;
767 WallpaperConnection.DisplayConnector connector =
768 targetWallpaper.connection.getDisplayConnectorOrCreate(displayId);
wilsonshihde93f492018-11-01 21:23:40 +0800769 if (connector == null) return;
770 connector.disconnectLocked();
wilsonshiha282bf72018-11-30 12:48:05 +0800771 targetWallpaper.connection.removeDisplayConnector(displayId);
772 removeDisplayData(displayId);
wilsonshihde93f492018-11-01 21:23:40 +0800773 }
wilsonshih36597d42018-12-05 18:56:39 +0800774 for (int i = mColorsChangedListeners.size() - 1; i >= 0; i--) {
775 final SparseArray<RemoteCallbackList<IWallpaperManagerCallback>> callbacks =
776 mColorsChangedListeners.valueAt(i);
777 callbacks.delete(displayId);
778 }
wilsonshihde93f492018-11-01 21:23:40 +0800779 }
780 }
781
782 @Override
783 public void onDisplayChanged(int displayId) {
wilsonshihde93f492018-11-01 21:23:40 +0800784 }
785 };
786
Lucas Dupin50ba9912017-07-14 11:55:05 -0700787 /**
788 * Map of color listeners per user id.
wilsonshih36597d42018-12-05 18:56:39 +0800789 * The first key will be the id of a user or UserHandle.USER_ALL - for wildcard listeners.
790 * The secondary key will be the display id, which means which display the listener is
791 * interested in.
Lucas Dupin50ba9912017-07-14 11:55:05 -0700792 */
wilsonshih36597d42018-12-05 18:56:39 +0800793 private final SparseArray<SparseArray<RemoteCallbackList<IWallpaperManagerCallback>>>
wilsonshiha282bf72018-11-30 12:48:05 +0800794 mColorsChangedListeners;
795 private WallpaperData mLastWallpaper;
796 private IWallpaperManagerCallback mKeyguardListener;
797 private boolean mWaitingForUnlock;
798 private boolean mShuttingDown;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800799
Justin Koh29c30162014-09-05 17:10:10 -0700800 /**
Christopher Tatead3c2592016-01-20 18:13:17 -0800801 * ID of the current wallpaper, changed every time anything sets a wallpaper.
802 * This is used for external detection of wallpaper update activity.
803 */
wilsonshiha282bf72018-11-30 12:48:05 +0800804 private int mWallpaperId;
Christopher Tatead3c2592016-01-20 18:13:17 -0800805
806 /**
Justin Koh29c30162014-09-05 17:10:10 -0700807 * Name of the component used to display bitmap wallpapers from either the gallery or
808 * built-in wallpapers.
809 */
wilsonshiha282bf72018-11-30 12:48:05 +0800810 private final ComponentName mImageWallpaper;
Justin Koh29c30162014-09-05 17:10:10 -0700811
Christopher Tate2a6c55f2017-03-31 12:28:30 -0700812 /**
wilsonshihfa24e4f2019-02-22 10:29:19 +0800813 * Default image wallpaper shall never changed after system service started, caching it when we
814 * first read the image file.
815 */
816 private WallpaperColors mCacheDefaultImageWallpaperColors;
817
818 /**
Christopher Tate2a6c55f2017-03-31 12:28:30 -0700819 * Name of the default wallpaper component; might be different from mImageWallpaper
820 */
wilsonshiha282bf72018-11-30 12:48:05 +0800821 private final ComponentName mDefaultWallpaperComponent;
Christopher Tate2a6c55f2017-03-31 12:28:30 -0700822
wilsonshiha282bf72018-11-30 12:48:05 +0800823 private final SparseArray<WallpaperData> mWallpaperMap = new SparseArray<WallpaperData>();
824 private final SparseArray<WallpaperData> mLockWallpaperMap = new SparseArray<WallpaperData>();
Dianne Hackborn07213e62011-08-24 20:05:39 -0700825
wilsonshiha282bf72018-11-30 12:48:05 +0800826 private SparseArray<DisplayData> mDisplayDatas = new SparseArray<>();
827
828 private WallpaperData mFallbackWallpaper;
829
830 private final SparseBooleanArray mUserRestorecon = new SparseBooleanArray();
831 private int mCurrentUserId = UserHandle.USER_NULL;
832 private boolean mInAmbientMode;
Dianne Hackborn07213e62011-08-24 20:05:39 -0700833
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800834 static class WallpaperData {
835
836 int userId;
837
Christopher Tatebe132e62016-02-10 12:59:49 -0800838 final File wallpaperFile; // source image
839 final File cropFile; // eventual destination
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800840
841 /**
Christopher Tatebe132e62016-02-10 12:59:49 -0800842 * True while the client is writing a new wallpaper
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800843 */
844 boolean imageWallpaperPending;
845
846 /**
Christopher Tatebe132e62016-02-10 12:59:49 -0800847 * Which new wallpapers are being written; mirrors the 'which'
848 * selector bit field to setWallpaper().
849 */
850 int whichPending;
851
852 /**
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800853 * Callback once the set + crop is finished
854 */
855 IWallpaperManagerCallback setComplete;
856
857 /**
Christopher Tated7faf532016-02-25 12:43:38 -0800858 * Is the OS allowed to back up this wallpaper imagery?
859 */
860 boolean allowBackup;
861
862 /**
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800863 * Resource name if using a picture from the wallpaper gallery
864 */
865 String name = "";
866
867 /**
868 * The component name of the currently set live wallpaper.
869 */
870 ComponentName wallpaperComponent;
871
872 /**
873 * The component name of the wallpaper that should be set next.
874 */
875 ComponentName nextWallpaperComponent;
876
Christopher Tatead3c2592016-01-20 18:13:17 -0800877 /**
878 * The ID of this wallpaper
879 */
880 int wallpaperId;
881
Lucas Dupinea1fb1e2017-04-05 17:39:44 -0700882 /**
883 * Primary colors histogram
884 */
885 WallpaperColors primaryColors;
886
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800887 WallpaperConnection connection;
888 long lastDiedTime;
889 boolean wallpaperUpdating;
890 WallpaperObserver wallpaperObserver;
891
892 /**
893 * List of callbacks registered they should each be notified when the wallpaper is changed.
894 */
895 private RemoteCallbackList<IWallpaperManagerCallback> callbacks
896 = new RemoteCallbackList<IWallpaperManagerCallback>();
897
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800898 /**
899 * The crop hint supplied for displaying a subset of the source image
900 */
901 final Rect cropHint = new Rect(0, 0, 0, 0);
902
Christopher Tatebe132e62016-02-10 12:59:49 -0800903 WallpaperData(int userId, String inputFileName, String cropFileName) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800904 this.userId = userId;
Christopher Tatebe132e62016-02-10 12:59:49 -0800905 final File wallpaperDir = getWallpaperDir(userId);
906 wallpaperFile = new File(wallpaperDir, inputFileName);
907 cropFile = new File(wallpaperDir, cropFileName);
Christopher Tate1e1e2e02016-01-25 15:34:36 -0800908 }
909
Christopher Tatebe132e62016-02-10 12:59:49 -0800910 // Called during initialization of a given user's wallpaper bookkeeping
Christopher Tate41297ff2016-03-10 16:46:15 -0800911 boolean cropExists() {
912 return cropFile.exists();
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800913 }
Christopher Tate2a6c55f2017-03-31 12:28:30 -0700914
915 boolean sourceExists() {
916 return wallpaperFile.exists();
917 }
wilsonshiha282bf72018-11-30 12:48:05 +0800918 }
wilsonshih81e10a72018-11-15 10:54:21 +0800919
wilsonshiha282bf72018-11-30 12:48:05 +0800920 private static final class DisplayData {
921 int mWidth = -1;
922 int mHeight = -1;
923 final Rect mPadding = new Rect(0, 0, 0, 0);
924 final int mDisplayId;
925
926 DisplayData(int displayId) {
927 mDisplayId = displayId;
wilsonshih81e10a72018-11-15 10:54:21 +0800928 }
929 }
930
wilsonshiha282bf72018-11-30 12:48:05 +0800931 private void removeDisplayData(int displayId) {
932 mDisplayDatas.remove(displayId);
933 }
934
935 private DisplayData getDisplayDataOrCreate(int displayId) {
936 DisplayData wpdData = mDisplayDatas.get(displayId);
wilsonshih81e10a72018-11-15 10:54:21 +0800937 if (wpdData == null) {
wilsonshiha282bf72018-11-30 12:48:05 +0800938 wpdData = new DisplayData(displayId);
wilsonshih81e10a72018-11-15 10:54:21 +0800939 ensureSaneWallpaperDisplaySize(wpdData, displayId);
wilsonshiha282bf72018-11-30 12:48:05 +0800940 mDisplayDatas.append(displayId, wpdData);
wilsonshih81e10a72018-11-15 10:54:21 +0800941 }
942 return wpdData;
943 }
944
wilsonshiha282bf72018-11-30 12:48:05 +0800945 private void ensureSaneWallpaperDisplaySize(DisplayData wpdData, int displayId) {
wilsonshih81e10a72018-11-15 10:54:21 +0800946 // We always want to have some reasonable width hint.
947 final int baseSize = getMaximumSizeDimension(displayId);
948 if (wpdData.mWidth < baseSize) {
949 wpdData.mWidth = baseSize;
950 }
951 if (wpdData.mHeight < baseSize) {
952 wpdData.mHeight = baseSize;
953 }
954 }
955
956 private int getMaximumSizeDimension(int displayId) {
957 Display display = mDisplayManager.getDisplay(displayId);
wilsonshiha282bf72018-11-30 12:48:05 +0800958 if (display == null) {
959 Slog.w(TAG, "Invalid displayId=" + displayId + " " + Debug.getCallers(4));
960 display = mDisplayManager.getDisplay(DEFAULT_DISPLAY);
961 }
wilsonshih81e10a72018-11-15 10:54:21 +0800962 return display.getMaximumSizeDimension();
963 }
964
wilsonshiha282bf72018-11-30 12:48:05 +0800965 void forEachDisplayData(Consumer<DisplayData> action) {
966 for (int i = mDisplayDatas.size() - 1; i >= 0; i--) {
967 final DisplayData wpdData = mDisplayDatas.valueAt(i);
wilsonshih81e10a72018-11-15 10:54:21 +0800968 action.accept(wpdData);
969 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -0800970 }
971
Christopher Tatead3c2592016-01-20 18:13:17 -0800972 int makeWallpaperIdLocked() {
973 do {
974 ++mWallpaperId;
975 } while (mWallpaperId == 0);
976 return mWallpaperId;
977 }
978
wilsonshiha282bf72018-11-30 12:48:05 +0800979 private boolean supportsMultiDisplay(WallpaperConnection connection) {
980 if (connection != null) {
981 return connection.mInfo == null // This is image wallpaper
982 || connection.mInfo.supportsMultipleDisplays();
983 }
984 return false;
985 }
986
987 private void updateFallbackConnection() {
988 if (mLastWallpaper == null || mFallbackWallpaper == null) return;
989 final WallpaperConnection systemConnection = mLastWallpaper.connection;
990 final WallpaperConnection fallbackConnection = mFallbackWallpaper.connection;
wilsonshih78268c32018-12-18 20:48:28 +0800991 if (fallbackConnection == null) {
992 Slog.w(TAG, "Fallback wallpaper connection has not been created yet!!");
993 return;
994 }
wilsonshih507ada52019-01-19 11:22:09 +0800995 if (supportsMultiDisplay(systemConnection)) {
996 if (fallbackConnection.mDisplayConnector.size() != 0) {
997 fallbackConnection.forEachDisplayConnector(connector -> {
998 if (connector.mEngine != null) {
999 connector.disconnectLocked();
1000 }
1001 });
1002 fallbackConnection.mDisplayConnector.clear();
1003 }
wilsonshiha282bf72018-11-30 12:48:05 +08001004 } else {
1005 fallbackConnection.appendConnectorWithCondition(display ->
1006 fallbackConnection.isUsableDisplay(display)
1007 && display.getDisplayId() != DEFAULT_DISPLAY
1008 && !fallbackConnection.containsDisplay(display.getDisplayId()));
1009 fallbackConnection.forEachDisplayConnector(connector -> {
1010 if (connector.mEngine == null) {
1011 connector.connectLocked(fallbackConnection, mFallbackWallpaper);
1012 }
1013 });
1014 }
1015 }
1016
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001017 class WallpaperConnection extends IWallpaperConnection.Stub
1018 implements ServiceConnection {
Adrian Roosc3f915e2016-09-06 11:40:53 -07001019
wilsonshihde93f492018-11-01 21:23:40 +08001020 /**
1021 * Collect needed info for a display.
1022 */
1023 private final class DisplayConnector {
1024 final int mDisplayId;
1025 final Binder mToken = new Binder();
1026 IWallpaperEngine mEngine;
1027 boolean mDimensionsChanged;
1028 boolean mPaddingChanged;
1029
1030 DisplayConnector(int displayId) {
1031 mDisplayId = displayId;
1032 }
1033
1034 void ensureStatusHandled() {
wilsonshiha282bf72018-11-30 12:48:05 +08001035 final DisplayData wpdData = getDisplayDataOrCreate(mDisplayId);
wilsonshihde93f492018-11-01 21:23:40 +08001036 if (mDimensionsChanged) {
1037 try {
wilsonshih81e10a72018-11-15 10:54:21 +08001038 mEngine.setDesiredSize(wpdData.mWidth, wpdData.mHeight);
wilsonshihde93f492018-11-01 21:23:40 +08001039 } catch (RemoteException e) {
1040 Slog.w(TAG, "Failed to set wallpaper dimensions", e);
1041 }
1042 mDimensionsChanged = false;
1043 }
1044 if (mPaddingChanged) {
1045 try {
wilsonshih81e10a72018-11-15 10:54:21 +08001046 mEngine.setDisplayPadding(wpdData.mPadding);
wilsonshihde93f492018-11-01 21:23:40 +08001047 } catch (RemoteException e) {
1048 Slog.w(TAG, "Failed to set wallpaper padding", e);
1049 }
1050 mPaddingChanged = false;
1051 }
1052 }
1053
1054 void connectLocked(WallpaperConnection connection, WallpaperData wallpaper) {
wilsonshih674a4a02018-12-19 11:47:25 +08001055 if (connection.mService == null) {
1056 Slog.w(TAG, "WallpaperService is not connected yet");
1057 return;
1058 }
wilsonshihde93f492018-11-01 21:23:40 +08001059 if (DEBUG) Slog.v(TAG, "Adding window token: " + mToken);
1060 try {
1061 mIWindowManager.addWindowToken(mToken, TYPE_WALLPAPER, mDisplayId);
1062 } catch (RemoteException e) {
1063 Slog.e(TAG, "Failed add wallpaper window token on display " + mDisplayId, e);
1064 return;
1065 }
1066
wilsonshiha282bf72018-11-30 12:48:05 +08001067 final DisplayData wpdData = getDisplayDataOrCreate(mDisplayId);
wilsonshihde93f492018-11-01 21:23:40 +08001068 try {
wilsonshihde93f492018-11-01 21:23:40 +08001069 connection.mService.attach(connection, mToken, TYPE_WALLPAPER, false,
wilsonshih81e10a72018-11-15 10:54:21 +08001070 wpdData.mWidth, wpdData.mHeight,
1071 wpdData.mPadding, mDisplayId);
wilsonshihde93f492018-11-01 21:23:40 +08001072 } catch (RemoteException e) {
1073 Slog.w(TAG, "Failed attaching wallpaper on display", e);
wilsonshih674a4a02018-12-19 11:47:25 +08001074 if (wallpaper != null && !wallpaper.wallpaperUpdating
wilsonshih81e10a72018-11-15 10:54:21 +08001075 && connection.getConnectedEngineSize() == 0) {
wilsonshihde93f492018-11-01 21:23:40 +08001076 bindWallpaperComponentLocked(null /* componentName */, false /* force */,
1077 false /* fromUser */, wallpaper, null /* reply */);
1078 }
1079 }
1080 }
1081
1082 void disconnectLocked() {
1083 if (DEBUG) Slog.v(TAG, "Removing window token: " + mToken);
1084 try {
1085 mIWindowManager.removeWindowToken(mToken, mDisplayId);
1086 } catch (RemoteException e) {
1087 }
1088 try {
1089 if (mEngine != null) {
1090 mEngine.destroy();
1091 }
1092 } catch (RemoteException e) {
1093 }
1094 mEngine = null;
1095 }
1096 }
1097
1098 /**
1099 * A map for each display.
1100 * Use {@link #getDisplayConnectorOrCreate(int displayId)} to ensure the display is usable.
1101 */
1102 private SparseArray<DisplayConnector> mDisplayConnector = new SparseArray<>();
1103
Adrian Roosc3f915e2016-09-06 11:40:53 -07001104 /** Time in milliseconds until we expect the wallpaper to reconnect (unless we're in the
1105 * middle of an update). If exceeded, the wallpaper gets reset to the system default. */
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001106 private static final long WALLPAPER_RECONNECT_TIMEOUT_MS = 10000;
Adrian Roosc3f915e2016-09-06 11:40:53 -07001107
Dianne Hackborneb034652009-09-07 00:49:58 -07001108 final WallpaperInfo mInfo;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001109 IWallpaperService mService;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001110 WallpaperData mWallpaper;
wilsonshihde93f492018-11-01 21:23:40 +08001111 final int mClientUid;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001112 IRemoteCallback mReply;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001113
Adrian Roosc3f915e2016-09-06 11:40:53 -07001114 private Runnable mResetRunnable = () -> {
1115 synchronized (mLock) {
Christopher Tate762dfd12016-10-10 17:44:48 -07001116 if (mShuttingDown) {
1117 // Don't expect wallpaper services to relaunch during shutdown
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001118 if (DEBUG_LIVE) {
Christopher Tate762dfd12016-10-10 17:44:48 -07001119 Slog.i(TAG, "Ignoring relaunch timeout during shutdown");
1120 }
1121 return;
1122 }
1123
Adrian Roosc3f915e2016-09-06 11:40:53 -07001124 if (!mWallpaper.wallpaperUpdating
1125 && mWallpaper.userId == mCurrentUserId) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001126 Slog.w(TAG, "Wallpaper reconnect timed out for " + mWallpaper.wallpaperComponent
1127 + ", reverting to built-in wallpaper!");
Adrian Roosc3f915e2016-09-06 11:40:53 -07001128 clearWallpaperLocked(true, FLAG_SYSTEM, mWallpaper.userId,
1129 null);
1130 }
1131 }
1132 };
1133
wilsonshihde93f492018-11-01 21:23:40 +08001134 WallpaperConnection(WallpaperInfo info, WallpaperData wallpaper, int clientUid) {
Dianne Hackborneb034652009-09-07 00:49:58 -07001135 mInfo = info;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001136 mWallpaper = wallpaper;
wilsonshihde93f492018-11-01 21:23:40 +08001137 mClientUid = clientUid;
1138 initDisplayState();
1139 }
1140
1141 private void initDisplayState() {
wilsonshiha282bf72018-11-30 12:48:05 +08001142 // Do not initialize fallback wallpaper
1143 if (!mWallpaper.equals(mFallbackWallpaper)) {
1144 if (supportsMultiDisplay(this)) {
1145 // The system wallpaper is image wallpaper or it can supports multiple displays.
1146 appendConnectorWithCondition(this::isUsableDisplay);
1147 } else {
1148 // The system wallpaper does not support multiple displays, so just attach it on
1149 // default display.
1150 mDisplayConnector.append(DEFAULT_DISPLAY,
1151 new DisplayConnector(DEFAULT_DISPLAY));
wilsonshihde93f492018-11-01 21:23:40 +08001152 }
1153 }
1154 }
1155
wilsonshiha282bf72018-11-30 12:48:05 +08001156 private void appendConnectorWithCondition(Predicate<Display> tester) {
1157 final Display[] displays = mDisplayManager.getDisplays();
1158 for (Display display : displays) {
1159 if (tester.test(display)) {
1160 final int displayId = display.getDisplayId();
wilsonshih674a4a02018-12-19 11:47:25 +08001161 final DisplayConnector connector = mDisplayConnector.get(displayId);
1162 if (connector == null) {
1163 mDisplayConnector.append(displayId,
1164 new DisplayConnector(displayId));
1165 }
wilsonshiha282bf72018-11-30 12:48:05 +08001166 }
1167 }
1168 }
1169
wilsonshihde93f492018-11-01 21:23:40 +08001170 private boolean isUsableDisplay(Display display) {
Andrii Kuliandd989612019-02-21 12:13:28 -08001171 if (display == null || !display.hasAccess(mClientUid)) {
1172 return false;
1173 }
1174 final int displayId = display.getDisplayId();
1175 return displayId == DEFAULT_DISPLAY
1176 || mWindowManagerInternal.shouldShowSystemDecorOnDisplay(displayId);
wilsonshihde93f492018-11-01 21:23:40 +08001177 }
1178
1179 void forEachDisplayConnector(Consumer<DisplayConnector> action) {
1180 for (int i = mDisplayConnector.size() - 1; i >= 0; i--) {
wilsonshih81e10a72018-11-15 10:54:21 +08001181 final DisplayConnector connector = mDisplayConnector.valueAt(i);
wilsonshihde93f492018-11-01 21:23:40 +08001182 action.accept(connector);
1183 }
1184 }
1185
wilsonshih81e10a72018-11-15 10:54:21 +08001186 int getConnectedEngineSize() {
1187 int engineSize = 0;
1188 for (int i = mDisplayConnector.size() - 1; i >= 0; i--) {
1189 final DisplayConnector connector = mDisplayConnector.valueAt(i);
1190 if (connector.mEngine != null) engineSize++;
1191 }
1192 return engineSize;
1193 }
1194
wilsonshihde93f492018-11-01 21:23:40 +08001195 DisplayConnector getDisplayConnectorOrCreate(int displayId) {
1196 DisplayConnector connector = mDisplayConnector.get(displayId);
1197 if (connector == null) {
1198 final Display display = mDisplayManager.getDisplay(displayId);
1199 if (isUsableDisplay(display)) {
1200 connector = new DisplayConnector(displayId);
1201 mDisplayConnector.append(displayId, connector);
1202 }
1203 }
1204 return connector;
1205 }
1206
wilsonshiha282bf72018-11-30 12:48:05 +08001207 boolean containsDisplay(int displayId) {
1208 return mDisplayConnector.get(displayId) != null;
1209 }
1210
wilsonshihde93f492018-11-01 21:23:40 +08001211 void removeDisplayConnector(int displayId) {
1212 final DisplayConnector connector = mDisplayConnector.get(displayId);
1213 if (connector != null) {
1214 mDisplayConnector.remove(displayId);
1215 }
Dianne Hackborneb034652009-09-07 00:49:58 -07001216 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001217
1218 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001219 public void onServiceConnected(ComponentName name, IBinder service) {
1220 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001221 if (mWallpaper.connection == this) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001222 mService = IWallpaperService.Stub.asInterface(service);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001223 attachServiceLocked(this, mWallpaper);
Dianne Hackborneb034652009-09-07 00:49:58 -07001224 // XXX should probably do saveSettingsLocked() later
1225 // when we have an engine, but I'm not sure about
1226 // locking there and anyway we always need to be able to
1227 // recover if there is something wrong.
wilsonshiha282bf72018-11-30 12:48:05 +08001228 if (!mWallpaper.equals(mFallbackWallpaper)) {
1229 saveSettingsLocked(mWallpaper.userId);
1230 }
Adrian Roosc3f915e2016-09-06 11:40:53 -07001231 FgThread.getHandler().removeCallbacks(mResetRunnable);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001232 }
1233 }
1234 }
1235
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001236 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001237 public void onServiceDisconnected(ComponentName name) {
1238 synchronized (mLock) {
Christopher Tatec349e59f2017-05-05 17:37:43 -07001239 Slog.w(TAG, "Wallpaper service gone: " + name);
1240 if (!Objects.equals(name, mWallpaper.wallpaperComponent)) {
1241 Slog.e(TAG, "Does not match expected wallpaper component "
1242 + mWallpaper.wallpaperComponent);
1243 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001244 mService = null;
wilsonshihde93f492018-11-01 21:23:40 +08001245 forEachDisplayConnector(connector -> connector.mEngine = null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001246 if (mWallpaper.connection == this) {
Christopher Tatec349e59f2017-05-05 17:37:43 -07001247 // There is an inherent ordering race between this callback and the
1248 // package monitor that receives notice that a package is being updated,
1249 // so we cannot quite trust at this moment that we know for sure that
1250 // this is not an update. If we think this is a genuine non-update
1251 // wallpaper outage, we do our "wait for reset" work as a continuation,
1252 // a short time in the future, specifically to allow any pending package
1253 // update message on this same looper thread to be processed.
1254 if (!mWallpaper.wallpaperUpdating) {
1255 mContext.getMainThreadHandler().postDelayed(() -> processDisconnect(this),
1256 1000);
1257 }
1258 }
1259 }
1260 }
1261
Tetsutoki Shiozawa06919212018-02-02 14:18:43 +09001262 public void scheduleTimeoutLocked() {
1263 // If we didn't reset it right away, do so after we couldn't connect to
1264 // it for an extended amount of time to avoid having a black wallpaper.
1265 final Handler fgHandler = FgThread.getHandler();
1266 fgHandler.removeCallbacks(mResetRunnable);
1267 fgHandler.postDelayed(mResetRunnable, WALLPAPER_RECONNECT_TIMEOUT_MS);
1268 if (DEBUG_LIVE) {
wilsonshihde93f492018-11-01 21:23:40 +08001269 Slog.i(TAG,
1270 "Started wallpaper reconnect timeout for " + mWallpaper.wallpaperComponent);
Tetsutoki Shiozawa06919212018-02-02 14:18:43 +09001271 }
1272 }
1273
Christopher Tatec349e59f2017-05-05 17:37:43 -07001274 private void processDisconnect(final ServiceConnection connection) {
1275 synchronized (mLock) {
1276 // The wallpaper disappeared. If this isn't a system-default one, track
1277 // crashes and fall back to default if it continues to misbehave.
1278 if (connection == mWallpaper.connection) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001279 final ComponentName wpService = mWallpaper.wallpaperComponent;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001280 if (!mWallpaper.wallpaperUpdating
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001281 && mWallpaper.userId == mCurrentUserId
1282 && !Objects.equals(mDefaultWallpaperComponent, wpService)
1283 && !Objects.equals(mImageWallpaper, wpService)) {
Selim Cinekebebadb2014-03-05 22:17:26 +01001284 // There is a race condition which causes
1285 // {@link #mWallpaper.wallpaperUpdating} to be false even if it is
1286 // currently updating since the broadcast notifying us is async.
1287 // This race is overcome by the general rule that we only reset the
1288 // wallpaper if its service was shut down twice
1289 // during {@link #MIN_WALLPAPER_CRASH_TIME} millis.
1290 if (mWallpaper.lastDiedTime != 0
1291 && mWallpaper.lastDiedTime + MIN_WALLPAPER_CRASH_TIME
Christopher Tatec349e59f2017-05-05 17:37:43 -07001292 > SystemClock.uptimeMillis()) {
Selim Cinekebebadb2014-03-05 22:17:26 +01001293 Slog.w(TAG, "Reverting to built-in wallpaper!");
Christopher Tateedf7d042016-03-29 18:24:25 -07001294 clearWallpaperLocked(true, FLAG_SYSTEM, mWallpaper.userId, null);
Selim Cinekebebadb2014-03-05 22:17:26 +01001295 } else {
1296 mWallpaper.lastDiedTime = SystemClock.uptimeMillis();
Adrian Roosc3f915e2016-09-06 11:40:53 -07001297
Tetsutoki Shiozawa06919212018-02-02 14:18:43 +09001298 clearWallpaperComponentLocked(mWallpaper);
1299 if (bindWallpaperComponentLocked(
1300 wpService, false, false, mWallpaper, null)) {
1301 mWallpaper.connection.scheduleTimeoutLocked();
1302 } else {
1303 Slog.w(TAG, "Reverting to built-in wallpaper!");
1304 clearWallpaperLocked(true, FLAG_SYSTEM, mWallpaper.userId, null);
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001305 }
Selim Cinekebebadb2014-03-05 22:17:26 +01001306 }
Christopher Tatec349e59f2017-05-05 17:37:43 -07001307 final String flattened = wpService.flattenToString();
Filip Gruszczynski5dcc3ac2014-10-13 15:51:39 -07001308 EventLog.writeEvent(EventLogTags.WP_WALLPAPER_CRASHED,
Filip Gruszczynski5a589432014-10-14 12:06:06 -07001309 flattened.substring(0, Math.min(flattened.length(),
1310 MAX_WALLPAPER_COMPONENT_LOG_LENGTH)));
Dianne Hackborn0cd48872009-08-13 18:51:59 -07001311 }
Christopher Tatec349e59f2017-05-05 17:37:43 -07001312 } else {
1313 if (DEBUG_LIVE) {
1314 Slog.i(TAG, "Wallpaper changed during disconnect tracking; ignoring");
1315 }
Dianne Hackborn0cd48872009-08-13 18:51:59 -07001316 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001317 }
1318 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001319
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07001320 /**
1321 * Called by a live wallpaper if its colors have changed.
1322 * @param primaryColors representation of wallpaper primary colors
wilsonshih36597d42018-12-05 18:56:39 +08001323 * @param displayId for which display
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07001324 */
1325 @Override
wilsonshih36597d42018-12-05 18:56:39 +08001326 public void onWallpaperColorsChanged(WallpaperColors primaryColors, int displayId) {
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07001327 int which;
1328 synchronized (mLock) {
1329 // Do not broadcast changes on ImageWallpaper since it's handled
1330 // internally by this class.
1331 if (mImageWallpaper.equals(mWallpaper.wallpaperComponent)) {
1332 return;
1333 }
1334
1335 mWallpaper.primaryColors = primaryColors;
1336
1337 // Live wallpapers always are system wallpapers.
1338 which = FLAG_SYSTEM;
wilsonshih36597d42018-12-05 18:56:39 +08001339 // It's also the lock screen wallpaper when we don't have a bitmap in there.
1340 if (displayId == DEFAULT_DISPLAY) {
1341 final WallpaperData lockedWallpaper = mLockWallpaperMap.get(mWallpaper.userId);
1342 if (lockedWallpaper == null) {
1343 which |= FLAG_LOCK;
1344 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07001345 }
1346 }
1347 if (which != 0) {
wilsonshih36597d42018-12-05 18:56:39 +08001348 notifyWallpaperColorsChangedOnDisplay(mWallpaper, which, displayId);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07001349 }
1350 }
1351
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001352 @Override
wilsonshihde93f492018-11-01 21:23:40 +08001353 public void attachEngine(IWallpaperEngine engine, int displayId) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001354 synchronized (mLock) {
wilsonshihde93f492018-11-01 21:23:40 +08001355 final DisplayConnector connector = getDisplayConnectorOrCreate(displayId);
1356 if (connector == null) {
Michael Wright5203a8b2013-10-03 14:16:42 -07001357 try {
wilsonshihde93f492018-11-01 21:23:40 +08001358 engine.destroy();
Michael Wright5203a8b2013-10-03 14:16:42 -07001359 } catch (RemoteException e) {
wilsonshihde93f492018-11-01 21:23:40 +08001360 Slog.w(TAG, "Failed to destroy engine", e);
Michael Wright5203a8b2013-10-03 14:16:42 -07001361 }
wilsonshihde93f492018-11-01 21:23:40 +08001362 return;
Michael Wright5203a8b2013-10-03 14:16:42 -07001363 }
wilsonshihde93f492018-11-01 21:23:40 +08001364 connector.mEngine = engine;
1365 connector.ensureStatusHandled();
1366
1367 // TODO(multi-display) TBD.
1368 if (mInfo != null && mInfo.supportsAmbientMode() && displayId == DEFAULT_DISPLAY) {
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001369 try {
Lucas Dupin4c8c3272018-11-06 17:47:48 -08001370 connector.mEngine.setInAmbientMode(mInAmbientMode, 0L /* duration */);
Lucas Dupin7517b5d2017-08-22 12:51:25 -07001371 } catch (RemoteException e) {
1372 Slog.w(TAG, "Failed to set ambient mode state", e);
1373 }
1374 }
wilsonshih36597d42018-12-05 18:56:39 +08001375 try {
1376 // This will trigger onComputeColors in the wallpaper engine.
1377 // It's fine to be locked in here since the binder is oneway.
1378 connector.mEngine.requestWallpaperColors();
1379 } catch (RemoteException e) {
1380 Slog.w(TAG, "Failed to request wallpaper colors", e);
Lucas Dupin50ba9912017-07-14 11:55:05 -07001381 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001382 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001383 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001384
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001385 @Override
1386 public void engineShown(IWallpaperEngine engine) {
1387 synchronized (mLock) {
1388 if (mReply != null) {
1389 long ident = Binder.clearCallingIdentity();
1390 try {
1391 mReply.sendResult(null);
1392 } catch (RemoteException e) {
1393 Binder.restoreCallingIdentity(ident);
1394 }
1395 mReply = null;
1396 }
1397 }
1398 }
1399
1400 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001401 public ParcelFileDescriptor setWallpaper(String name) {
1402 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001403 if (mWallpaper.connection == this) {
Christopher Tatead3c2592016-01-20 18:13:17 -08001404 return updateWallpaperBitmapLocked(name, mWallpaper, null);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001405 }
1406 return null;
1407 }
1408 }
1409 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001410
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001411 class MyPackageMonitor extends PackageMonitor {
1412 @Override
1413 public void onPackageUpdateFinished(String packageName, int uid) {
1414 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -07001415 if (mCurrentUserId != getChangingUserId()) {
1416 return;
1417 }
1418 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
1419 if (wallpaper != null) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001420 final ComponentName wpService = wallpaper.wallpaperComponent;
1421 if (wpService != null && wpService.getPackageName().equals(packageName)) {
1422 if (DEBUG_LIVE) {
1423 Slog.i(TAG, "Wallpaper " + wpService + " update has finished");
1424 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001425 wallpaper.wallpaperUpdating = false;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001426 clearWallpaperComponentLocked(wallpaper);
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001427 if (!bindWallpaperComponentLocked(wpService, false, false,
Dianne Hackbornc72fc672012-09-20 13:12:03 -07001428 wallpaper, null)) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001429 Slog.w(TAG, "Wallpaper " + wpService
1430 + " no longer available; reverting to default");
Christopher Tateedf7d042016-03-29 18:24:25 -07001431 clearWallpaperLocked(false, FLAG_SYSTEM, wallpaper.userId, null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001432 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001433 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001434 }
1435 }
1436 }
1437
1438 @Override
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001439 public void onPackageModified(String packageName) {
1440 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -07001441 if (mCurrentUserId != getChangingUserId()) {
1442 return;
1443 }
1444 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
1445 if (wallpaper != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001446 if (wallpaper.wallpaperComponent == null
1447 || !wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -07001448 return;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001449 }
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001450 doPackagesChangedLocked(true, wallpaper);
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001451 }
1452 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001453 }
1454
1455 @Override
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001456 public void onPackageUpdateStarted(String packageName, int uid) {
1457 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -07001458 if (mCurrentUserId != getChangingUserId()) {
1459 return;
1460 }
1461 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
1462 if (wallpaper != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001463 if (wallpaper.wallpaperComponent != null
1464 && wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001465 if (DEBUG_LIVE) {
1466 Slog.i(TAG, "Wallpaper service " + wallpaper.wallpaperComponent
1467 + " is updating");
1468 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001469 wallpaper.wallpaperUpdating = true;
Adrian Roosc3f915e2016-09-06 11:40:53 -07001470 if (wallpaper.connection != null) {
1471 FgThread.getHandler().removeCallbacks(
1472 wallpaper.connection.mResetRunnable);
1473 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001474 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001475 }
1476 }
1477 }
1478
1479 @Override
1480 public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001481 synchronized (mLock) {
1482 boolean changed = false;
Dianne Hackbornc72fc672012-09-20 13:12:03 -07001483 if (mCurrentUserId != getChangingUserId()) {
1484 return false;
1485 }
1486 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
1487 if (wallpaper != null) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001488 boolean res = doPackagesChangedLocked(doit, wallpaper);
1489 changed |= res;
1490 }
1491 return changed;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001492 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001493 }
1494
1495 @Override
1496 public void onSomePackagesChanged() {
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001497 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -07001498 if (mCurrentUserId != getChangingUserId()) {
1499 return;
1500 }
1501 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
1502 if (wallpaper != null) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001503 doPackagesChangedLocked(true, wallpaper);
1504 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001505 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001506 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001507
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001508 boolean doPackagesChangedLocked(boolean doit, WallpaperData wallpaper) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001509 boolean changed = false;
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001510 if (wallpaper.wallpaperComponent != null) {
1511 int change = isPackageDisappearing(wallpaper.wallpaperComponent
1512 .getPackageName());
1513 if (change == PACKAGE_PERMANENT_CHANGE
1514 || change == PACKAGE_TEMPORARY_CHANGE) {
1515 changed = true;
1516 if (doit) {
1517 Slog.w(TAG, "Wallpaper uninstalled, removing: "
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001518 + wallpaper.wallpaperComponent);
Christopher Tateedf7d042016-03-29 18:24:25 -07001519 clearWallpaperLocked(false, FLAG_SYSTEM, wallpaper.userId, null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001520 }
1521 }
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001522 }
1523 if (wallpaper.nextWallpaperComponent != null) {
1524 int change = isPackageDisappearing(wallpaper.nextWallpaperComponent
1525 .getPackageName());
1526 if (change == PACKAGE_PERMANENT_CHANGE
1527 || change == PACKAGE_TEMPORARY_CHANGE) {
1528 wallpaper.nextWallpaperComponent = null;
1529 }
1530 }
1531 if (wallpaper.wallpaperComponent != null
1532 && isPackageModified(wallpaper.wallpaperComponent.getPackageName())) {
1533 try {
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001534 mContext.getPackageManager().getServiceInfo(wallpaper.wallpaperComponent,
1535 PackageManager.MATCH_DIRECT_BOOT_AWARE
1536 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001537 } catch (NameNotFoundException e) {
1538 Slog.w(TAG, "Wallpaper component gone, removing: "
1539 + wallpaper.wallpaperComponent);
Christopher Tateedf7d042016-03-29 18:24:25 -07001540 clearWallpaperLocked(false, FLAG_SYSTEM, wallpaper.userId, null);
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001541 }
1542 }
1543 if (wallpaper.nextWallpaperComponent != null
1544 && isPackageModified(wallpaper.nextWallpaperComponent.getPackageName())) {
1545 try {
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001546 mContext.getPackageManager().getServiceInfo(wallpaper.nextWallpaperComponent,
1547 PackageManager.MATCH_DIRECT_BOOT_AWARE
1548 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001549 } catch (NameNotFoundException e) {
1550 wallpaper.nextWallpaperComponent = null;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001551 }
1552 }
1553 return changed;
1554 }
1555 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001556
Dianne Hackborn8cc6a502009-08-05 21:29:42 -07001557 public WallpaperManagerService(Context context) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001558 if (DEBUG) Slog.v(TAG, "WallpaperService startup");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001559 mContext = context;
Christopher Tate762dfd12016-10-10 17:44:48 -07001560 mShuttingDown = false;
Justin Koh29c30162014-09-05 17:10:10 -07001561 mImageWallpaper = ComponentName.unflattenFromString(
1562 context.getResources().getString(R.string.image_wallpaper_component));
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001563 mDefaultWallpaperComponent = WallpaperManager.getDefaultWallpaperComponent(context);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001564 mIWindowManager = IWindowManager.Stub.asInterface(
1565 ServiceManager.getService(Context.WINDOW_SERVICE));
Andrii Kuliandd989612019-02-21 12:13:28 -08001566 mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
Amith Yamasani4e2820c2012-08-28 22:17:23 -07001567 mIPackageManager = AppGlobals.getPackageManager();
Benjamin Franzf3ece362015-02-11 10:51:10 +00001568 mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
wilsonshihde93f492018-11-01 21:23:40 +08001569 mDisplayManager = mContext.getSystemService(DisplayManager.class);
1570 mDisplayManager.registerDisplayListener(mDisplayListener, null /* handler */);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001571 mMonitor = new MyPackageMonitor();
Jaekyun Seokad7d90f2018-04-04 01:57:18 +09001572 mColorsChangedListeners = new SparseArray<>();
wilsonshih643bf132019-02-27 12:49:19 +08001573
1574 LocalServices.addService(WallpaperManagerInternal.class, new LocalService());
1575 }
1576
1577 private final class LocalService extends WallpaperManagerInternal {
1578 @Override
1579 public void onDisplayReady(int displayId) {
1580 onDisplayReadyInternal(displayId);
1581 }
Jaekyun Seokad7d90f2018-04-04 01:57:18 +09001582 }
1583
1584 void initialize() {
1585 mMonitor.register(mContext, null, UserHandle.ALL, true);
Xiaohui Chen233d94c2015-07-30 15:08:00 -07001586 getWallpaperDir(UserHandle.USER_SYSTEM).mkdirs();
Christopher Tatef717b932017-09-11 15:52:54 -07001587
1588 // Initialize state from the persistent store, then guarantee that the
1589 // WallpaperData for the system imagery is instantiated & active, creating
1590 // it from defaults if necessary.
Christopher Tated7faf532016-02-25 12:43:38 -08001591 loadSettingsLocked(UserHandle.USER_SYSTEM, false);
Christopher Tatef717b932017-09-11 15:52:54 -07001592 getWallpaperSafeLocked(UserHandle.USER_SYSTEM, FLAG_SYSTEM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001593 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001594
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001595 private static File getWallpaperDir(int userId) {
Amith Yamasani61f57372012-08-31 12:12:28 -07001596 return Environment.getUserSystemDirectory(userId);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001597 }
1598
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001599 @Override
1600 protected void finalize() throws Throwable {
1601 super.finalize();
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001602 for (int i = 0; i < mWallpaperMap.size(); i++) {
1603 WallpaperData wallpaper = mWallpaperMap.valueAt(i);
1604 wallpaper.wallpaperObserver.stopWatching();
1605 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001606 }
Amith Yamasani13593602012-03-22 16:16:17 -07001607
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001608 void systemReady() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001609 if (DEBUG) Slog.v(TAG, "systemReady");
Jaekyun Seokad7d90f2018-04-04 01:57:18 +09001610 initialize();
1611
Xiaohui Chen233d94c2015-07-30 15:08:00 -07001612 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.USER_SYSTEM);
Christopher Tate2cdd3f22016-03-14 17:36:16 -07001613 // If we think we're going to be using the system image wallpaper imagery, make
1614 // sure we have something to render
1615 if (mImageWallpaper.equals(wallpaper.nextWallpaperComponent)) {
1616 // No crop file? Make sure we've finished the processing sequence if necessary
1617 if (!wallpaper.cropExists()) {
1618 if (DEBUG) {
1619 Slog.i(TAG, "No crop; regenerating from source");
1620 }
1621 generateCrop(wallpaper);
1622 }
1623 // Still nothing? Fall back to default.
1624 if (!wallpaper.cropExists()) {
1625 if (DEBUG) {
1626 Slog.i(TAG, "Unable to regenerate crop; resetting");
1627 }
Christopher Tateedf7d042016-03-29 18:24:25 -07001628 clearWallpaperLocked(false, FLAG_SYSTEM, UserHandle.USER_SYSTEM, null);
Christopher Tate2cdd3f22016-03-14 17:36:16 -07001629 }
1630 } else {
1631 if (DEBUG) {
1632 Slog.i(TAG, "Nondefault wallpaper component; gracefully ignoring");
1633 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001634 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001635
Amith Yamasani13593602012-03-22 16:16:17 -07001636 IntentFilter userFilter = new IntentFilter();
Amith Yamasani13593602012-03-22 16:16:17 -07001637 userFilter.addAction(Intent.ACTION_USER_REMOVED);
1638 mContext.registerReceiver(new BroadcastReceiver() {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001639 @Override
Amith Yamasani13593602012-03-22 16:16:17 -07001640 public void onReceive(Context context, Intent intent) {
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001641 final String action = intent.getAction();
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001642 if (Intent.ACTION_USER_REMOVED.equals(action)) {
Amith Yamasani756901d2012-10-12 12:30:07 -07001643 onRemoveUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
1644 UserHandle.USER_NULL));
Amith Yamasani13593602012-03-22 16:16:17 -07001645 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001646 }
Amith Yamasani13593602012-03-22 16:16:17 -07001647 }, userFilter);
Amith Yamasani756901d2012-10-12 12:30:07 -07001648
Christopher Tate762dfd12016-10-10 17:44:48 -07001649 final IntentFilter shutdownFilter = new IntentFilter(Intent.ACTION_SHUTDOWN);
1650 mContext.registerReceiver(new BroadcastReceiver() {
1651 @Override
1652 public void onReceive(Context context, Intent intent) {
1653 if (Intent.ACTION_SHUTDOWN.equals(intent.getAction())) {
1654 if (DEBUG) {
1655 Slog.i(TAG, "Shutting down");
1656 }
1657 synchronized (mLock) {
1658 mShuttingDown = true;
1659 }
1660 }
1661 }
1662 }, shutdownFilter);
1663
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001664 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001665 ActivityManager.getService().registerUserSwitchObserver(
Sudheer Shanka2c4522c2016-08-27 20:53:28 -07001666 new UserSwitchObserver() {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001667 @Override
1668 public void onUserSwitching(int newUserId, IRemoteCallback reply) {
1669 switchUser(newUserId, reply);
1670 }
Fyodor Kupolov0b77ef92016-06-20 17:16:52 -07001671 }, TAG);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001672 } catch (RemoteException e) {
Fyodor Kupolov0b77ef92016-06-20 17:16:52 -07001673 e.rethrowAsRuntimeException();
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001674 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001675 }
1676
Amith Yamasani09e9cdc2013-11-06 14:54:50 -08001677 /** Called by SystemBackupAgent */
1678 public String getName() {
1679 // Verify caller is the system
1680 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
1681 throw new RuntimeException("getName() can only be called from the system process");
1682 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001683 synchronized (mLock) {
1684 return mWallpaperMap.get(0).name;
1685 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001686 }
1687
Christopher Tatebe132e62016-02-10 12:59:49 -08001688 void stopObserver(WallpaperData wallpaper) {
1689 if (wallpaper != null) {
1690 if (wallpaper.wallpaperObserver != null) {
1691 wallpaper.wallpaperObserver.stopWatching();
1692 wallpaper.wallpaperObserver = null;
Amith Yamasani13593602012-03-22 16:16:17 -07001693 }
Amith Yamasani756901d2012-10-12 12:30:07 -07001694 }
1695 }
1696
Christopher Tatebe132e62016-02-10 12:59:49 -08001697 void stopObserversLocked(int userId) {
1698 stopObserver(mWallpaperMap.get(userId));
1699 stopObserver(mLockWallpaperMap.get(userId));
1700 mWallpaperMap.remove(userId);
1701 mLockWallpaperMap.remove(userId);
1702 }
1703
Daichi Hirono4bbf8522017-12-06 10:34:18 +09001704 @Override
1705 public void onBootPhase(int phase) {
1706 if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
1707 systemReady();
1708 } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
1709 switchUser(UserHandle.USER_SYSTEM, null);
1710 }
1711 }
1712
1713 @Override
1714 public void onUnlockUser(final int userId) {
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001715 synchronized (mLock) {
Christopher Tate38a5dc32016-07-20 15:10:18 -07001716 if (mCurrentUserId == userId) {
1717 if (mWaitingForUnlock) {
wilsonshiha47fcc92018-04-26 14:27:38 +08001718 // the desired wallpaper is not direct-boot aware, load it now
1719 final WallpaperData systemWallpaper =
1720 getWallpaperSafeLocked(userId, FLAG_SYSTEM);
1721 switchWallpaper(systemWallpaper, null);
Ahan Wu96dbbb92019-03-29 15:26:22 +08001722 notifyCallbacksLocked(systemWallpaper);
Christopher Tate38a5dc32016-07-20 15:10:18 -07001723 }
Christopher Tate190e8532016-07-11 11:35:34 -07001724
1725 // Make sure that the SELinux labeling of all the relevant files is correct.
1726 // This corrects for mislabeling bugs that might have arisen from move-to
1727 // operations involving the wallpaper files. This isn't timing-critical,
1728 // so we do it in the background to avoid holding up the user unlock operation.
wilsonshiha282bf72018-11-30 12:48:05 +08001729 if (!mUserRestorecon.get(userId)) {
1730 mUserRestorecon.put(userId, true);
Christopher Tate38a5dc32016-07-20 15:10:18 -07001731 Runnable relabeler = new Runnable() {
1732 @Override
1733 public void run() {
1734 final File wallpaperDir = getWallpaperDir(userId);
1735 for (String filename : sPerUserFiles) {
1736 File f = new File(wallpaperDir, filename);
1737 if (f.exists()) {
1738 SELinux.restorecon(f);
1739 }
Christopher Tate190e8532016-07-11 11:35:34 -07001740 }
1741 }
Christopher Tate38a5dc32016-07-20 15:10:18 -07001742 };
1743 BackgroundThread.getHandler().post(relabeler);
1744 }
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001745 }
1746 }
1747 }
1748
Amith Yamasani756901d2012-10-12 12:30:07 -07001749 void onRemoveUser(int userId) {
1750 if (userId < 1) return;
Christopher Tatebe132e62016-02-10 12:59:49 -08001751
1752 final File wallpaperDir = getWallpaperDir(userId);
Amith Yamasani756901d2012-10-12 12:30:07 -07001753 synchronized (mLock) {
Christopher Tatebe132e62016-02-10 12:59:49 -08001754 stopObserversLocked(userId);
1755 for (String filename : sPerUserFiles) {
1756 new File(wallpaperDir, filename).delete();
1757 }
wilsonshiha282bf72018-11-30 12:48:05 +08001758 mUserRestorecon.delete(userId);
Amith Yamasani13593602012-03-22 16:16:17 -07001759 }
1760 }
1761
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001762 void switchUser(int userId, IRemoteCallback reply) {
Lucas Dupin9272d452017-09-14 14:15:42 -07001763 final WallpaperData systemWallpaper;
1764 final WallpaperData lockWallpaper;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001765 synchronized (mLock) {
Jaekyun Seokad7d90f2018-04-04 01:57:18 +09001766 if (mCurrentUserId == userId) {
1767 return;
1768 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001769 mCurrentUserId = userId;
Lucas Dupin50ba9912017-07-14 11:55:05 -07001770 systemWallpaper = getWallpaperSafeLocked(userId, FLAG_SYSTEM);
Lucas Dupin9272d452017-09-14 14:15:42 -07001771 final WallpaperData tmpLockWallpaper = mLockWallpaperMap.get(userId);
1772 lockWallpaper = tmpLockWallpaper == null ? systemWallpaper : tmpLockWallpaper;
Lucas Dupin50ba9912017-07-14 11:55:05 -07001773 // Not started watching yet, in case wallpaper data was loaded for other reasons.
1774 if (systemWallpaper.wallpaperObserver == null) {
1775 systemWallpaper.wallpaperObserver = new WallpaperObserver(systemWallpaper);
1776 systemWallpaper.wallpaperObserver.startWatching();
1777 }
1778 switchWallpaper(systemWallpaper, reply);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001779 }
Lucas Dupin9272d452017-09-14 14:15:42 -07001780
1781 // Offload color extraction to another thread since switchUser will be called
1782 // from the main thread.
1783 FgThread.getHandler().post(() -> {
1784 notifyWallpaperColorsChanged(systemWallpaper, FLAG_SYSTEM);
1785 notifyWallpaperColorsChanged(lockWallpaper, FLAG_LOCK);
wilsonshih36597d42018-12-05 18:56:39 +08001786 notifyWallpaperColorsChanged(mFallbackWallpaper, FLAG_SYSTEM);
Lucas Dupin9272d452017-09-14 14:15:42 -07001787 });
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001788 }
1789
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001790 void switchWallpaper(WallpaperData wallpaper, IRemoteCallback reply) {
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001791 synchronized (mLock) {
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001792 mWaitingForUnlock = false;
1793 final ComponentName cname = wallpaper.wallpaperComponent != null ?
1794 wallpaper.wallpaperComponent : wallpaper.nextWallpaperComponent;
1795 if (!bindWallpaperComponentLocked(cname, true, false, wallpaper, reply)) {
1796 // We failed to bind the desired wallpaper, but that might
1797 // happen if the wallpaper isn't direct-boot aware
1798 ServiceInfo si = null;
1799 try {
1800 si = mIPackageManager.getServiceInfo(cname,
1801 PackageManager.MATCH_DIRECT_BOOT_UNAWARE, wallpaper.userId);
1802 } catch (RemoteException ignored) {
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001803 }
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001804
1805 if (si == null) {
1806 Slog.w(TAG, "Failure starting previous wallpaper; clearing");
1807 clearWallpaperLocked(false, FLAG_SYSTEM, wallpaper.userId, reply);
1808 } else {
1809 Slog.w(TAG, "Wallpaper isn't direct boot aware; using fallback until unlocked");
1810 // We might end up persisting the current wallpaper data
1811 // while locked, so pretend like the component was actually
1812 // bound into place
1813 wallpaper.wallpaperComponent = wallpaper.nextWallpaperComponent;
1814 final WallpaperData fallback = new WallpaperData(wallpaper.userId,
1815 WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP);
wilsonshih81e10a72018-11-15 10:54:21 +08001816 ensureSaneWallpaperData(fallback, DEFAULT_DISPLAY);
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001817 bindWallpaperComponentLocked(mImageWallpaper, true, false, fallback, reply);
1818 mWaitingForUnlock = true;
1819 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001820 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001821 }
1822 }
1823
Christopher Tatebe132e62016-02-10 12:59:49 -08001824 @Override
1825 public void clearWallpaper(String callingPackage, int which, int userId) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001826 if (DEBUG) Slog.v(TAG, "clearWallpaper");
Benjamin Franzf3ece362015-02-11 10:51:10 +00001827 checkPermission(android.Manifest.permission.SET_WALLPAPER);
Christopher Tate98d609c2016-05-18 17:31:58 -07001828 if (!isWallpaperSupported(callingPackage) || !isSetWallpaperAllowed(callingPackage)) {
Benjamin Franzf3ece362015-02-11 10:51:10 +00001829 return;
1830 }
Christopher Tatee409f0e2016-03-21 14:53:15 -07001831 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
1832 Binder.getCallingUid(), userId, false, true, "clearWallpaper", null);
Christopher Tatebe132e62016-02-10 12:59:49 -08001833
Lucas Dupin41f69422017-05-03 15:26:22 -07001834 WallpaperData data = null;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001835 synchronized (mLock) {
Christopher Tatebe132e62016-02-10 12:59:49 -08001836 clearWallpaperLocked(false, which, userId, null);
Lucas Dupin41f69422017-05-03 15:26:22 -07001837
1838 if (which == FLAG_LOCK) {
1839 data = mLockWallpaperMap.get(userId);
1840 }
1841 if (which == FLAG_SYSTEM || data == null) {
1842 data = mWallpaperMap.get(userId);
1843 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001844 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07001845
1846 // When clearing a wallpaper, broadcast new valid colors
Lucas Dupin41f69422017-05-03 15:26:22 -07001847 if (data != null) {
1848 notifyWallpaperColorsChanged(data, which);
wilsonshih36597d42018-12-05 18:56:39 +08001849 notifyWallpaperColorsChanged(mFallbackWallpaper, FLAG_SYSTEM);
Lucas Dupin41f69422017-05-03 15:26:22 -07001850 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001851 }
1852
Christopher Tatebe132e62016-02-10 12:59:49 -08001853 void clearWallpaperLocked(boolean defaultFailed, int which, int userId, IRemoteCallback reply) {
Christopher Tateedf7d042016-03-29 18:24:25 -07001854 if (which != FLAG_SYSTEM && which != FLAG_LOCK) {
Christopher Tate105540d2018-03-21 13:03:09 -07001855 throw new IllegalArgumentException("Must specify exactly one kind of wallpaper to clear");
Christopher Tatebe132e62016-02-10 12:59:49 -08001856 }
1857
1858 WallpaperData wallpaper = null;
Christopher Tateedf7d042016-03-29 18:24:25 -07001859 if (which == FLAG_LOCK) {
Christopher Tatebe132e62016-02-10 12:59:49 -08001860 wallpaper = mLockWallpaperMap.get(userId);
1861 if (wallpaper == null) {
1862 // It's already gone; we're done.
Christopher Tate79a24572016-03-02 14:42:44 -08001863 if (DEBUG) {
1864 Slog.i(TAG, "Lock wallpaper already cleared");
1865 }
Christopher Tatebe132e62016-02-10 12:59:49 -08001866 return;
1867 }
1868 } else {
1869 wallpaper = mWallpaperMap.get(userId);
1870 if (wallpaper == null) {
1871 // Might need to bring it in the first time to establish our rewrite
Christopher Tated7faf532016-02-25 12:43:38 -08001872 loadSettingsLocked(userId, false);
Christopher Tatebe132e62016-02-10 12:59:49 -08001873 wallpaper = mWallpaperMap.get(userId);
1874 }
1875 }
Benjamin Franzf3ece362015-02-11 10:51:10 +00001876 if (wallpaper == null) {
1877 return;
1878 }
Christopher Tatebe132e62016-02-10 12:59:49 -08001879
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001880 final long ident = Binder.clearCallingIdentity();
1881 try {
Christopher Tatebe132e62016-02-10 12:59:49 -08001882 if (wallpaper.wallpaperFile.exists()) {
1883 wallpaper.wallpaperFile.delete();
1884 wallpaper.cropFile.delete();
Christopher Tateedf7d042016-03-29 18:24:25 -07001885 if (which == FLAG_LOCK) {
Christopher Tate79a24572016-03-02 14:42:44 -08001886 mLockWallpaperMap.remove(userId);
Christopher Tatebe132e62016-02-10 12:59:49 -08001887 final IWallpaperManagerCallback cb = mKeyguardListener;
1888 if (cb != null) {
Christopher Tate79a24572016-03-02 14:42:44 -08001889 if (DEBUG) {
1890 Slog.i(TAG, "Notifying keyguard of lock wallpaper clear");
1891 }
Christopher Tatebe132e62016-02-10 12:59:49 -08001892 try {
1893 cb.onWallpaperChanged();
1894 } catch (RemoteException e) {
1895 // Oh well it went away; no big deal
1896 }
1897 }
Christopher Tate79a24572016-03-02 14:42:44 -08001898 saveSettingsLocked(userId);
Christopher Tatebe132e62016-02-10 12:59:49 -08001899 return;
1900 }
1901 }
1902
Christopher Tateecd827a2014-09-05 17:42:34 -07001903 RuntimeException e = null;
1904 try {
Lucas Dupin75ec3792017-06-29 14:07:18 -07001905 wallpaper.primaryColors = null;
Christopher Tateecd827a2014-09-05 17:42:34 -07001906 wallpaper.imageWallpaperPending = false;
1907 if (userId != mCurrentUserId) return;
1908 if (bindWallpaperComponentLocked(defaultFailed
1909 ? mImageWallpaper
1910 : null, true, false, wallpaper, reply)) {
1911 return;
1912 }
1913 } catch (IllegalArgumentException e1) {
1914 e = e1;
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001915 }
Christopher Tateecd827a2014-09-05 17:42:34 -07001916
1917 // This can happen if the default wallpaper component doesn't
1918 // exist. This should be a system configuration problem, but
1919 // let's not let it crash the system and just live with no
1920 // wallpaper.
1921 Slog.e(TAG, "Default wallpaper component not found!", e);
1922 clearWallpaperComponentLocked(wallpaper);
1923 if (reply != null) {
1924 try {
1925 reply.sendResult(null);
1926 } catch (RemoteException e1) {
1927 }
1928 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001929 } finally {
1930 Binder.restoreCallingIdentity(ident);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001931 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001932 }
1933
1934 public boolean hasNamedWallpaper(String name) {
1935 synchronized (mLock) {
Amith Yamasani6474c4c2012-10-04 14:55:42 -07001936 List<UserInfo> users;
1937 long ident = Binder.clearCallingIdentity();
1938 try {
1939 users = ((UserManager) mContext.getSystemService(Context.USER_SERVICE)).getUsers();
1940 } finally {
1941 Binder.restoreCallingIdentity(ident);
1942 }
1943 for (UserInfo user: users) {
Benjamin Franzf3ece362015-02-11 10:51:10 +00001944 // ignore managed profiles
1945 if (user.isManagedProfile()) {
1946 continue;
1947 }
Amith Yamasani6474c4c2012-10-04 14:55:42 -07001948 WallpaperData wd = mWallpaperMap.get(user.id);
1949 if (wd == null) {
1950 // User hasn't started yet, so load her settings to peek at the wallpaper
Christopher Tated7faf532016-02-25 12:43:38 -08001951 loadSettingsLocked(user.id, false);
Amith Yamasani6474c4c2012-10-04 14:55:42 -07001952 wd = mWallpaperMap.get(user.id);
1953 }
1954 if (wd != null && name.equals(wd.name)) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001955 return true;
1956 }
1957 }
1958 }
1959 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001960 }
1961
wilsonshih81e10a72018-11-15 10:54:21 +08001962 private boolean isValidDisplay(int displayId) {
1963 return mDisplayManager.getDisplay(displayId) != null;
1964 }
1965
1966 /**
1967 * Sets the dimension hint for the wallpaper. These hints indicate the desired
1968 * minimum width and height for the wallpaper in a particular display.
1969 */
1970 public void setDimensionHints(int width, int height, String callingPackage, int displayId)
Benjamin Franzf3ece362015-02-11 10:51:10 +00001971 throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001972 checkPermission(android.Manifest.permission.SET_WALLPAPER_HINTS);
Benjamin Franzf3ece362015-02-11 10:51:10 +00001973 if (!isWallpaperSupported(callingPackage)) {
1974 return;
1975 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001976 synchronized (mLock) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001977 int userId = UserHandle.getCallingUserId();
Christopher Tateedf7d042016-03-29 18:24:25 -07001978 WallpaperData wallpaper = getWallpaperSafeLocked(userId, FLAG_SYSTEM);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001979 if (width <= 0 || height <= 0) {
1980 throw new IllegalArgumentException("width and height must be > 0");
1981 }
1982
wilsonshih81e10a72018-11-15 10:54:21 +08001983 if (!isValidDisplay(displayId)) {
1984 throw new IllegalArgumentException("Cannot find display with id=" + displayId);
1985 }
1986
wilsonshiha282bf72018-11-30 12:48:05 +08001987 final DisplayData wpdData = getDisplayDataOrCreate(displayId);
wilsonshih81e10a72018-11-15 10:54:21 +08001988 if (width != wpdData.mWidth || height != wpdData.mHeight) {
1989 wpdData.mWidth = width;
1990 wpdData.mHeight = height;
1991 if (displayId == DEFAULT_DISPLAY) saveSettingsLocked(userId);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001992 if (mCurrentUserId != userId) return; // Don't change the properties now
1993 if (wallpaper.connection != null) {
wilsonshih81e10a72018-11-15 10:54:21 +08001994 final WallpaperConnection.DisplayConnector connector = wallpaper.connection
1995 .getDisplayConnectorOrCreate(displayId);
1996 final IWallpaperEngine engine = connector != null ? connector.mEngine : null;
wilsonshihde93f492018-11-01 21:23:40 +08001997 if (engine != null) {
Dianne Hackborn284ac932009-08-28 10:34:25 -07001998 try {
wilsonshihde93f492018-11-01 21:23:40 +08001999 engine.setDesiredSize(width, height);
Dianne Hackborn284ac932009-08-28 10:34:25 -07002000 } catch (RemoteException e) {
2001 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002002 notifyCallbacksLocked(wallpaper);
wilsonshih81e10a72018-11-15 10:54:21 +08002003 } else if (wallpaper.connection.mService != null && connector != null) {
Michael Wright5203a8b2013-10-03 14:16:42 -07002004 // We've attached to the service but the engine hasn't attached back to us
2005 // yet. This means it will be created with the previous dimensions, so we
2006 // need to update it to the new dimensions once it attaches.
wilsonshih81e10a72018-11-15 10:54:21 +08002007 connector.mDimensionsChanged = true;
Dianne Hackborn284ac932009-08-28 10:34:25 -07002008 }
2009 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002010 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002011 }
2012 }
2013
wilsonshih81e10a72018-11-15 10:54:21 +08002014 /**
2015 * Returns the desired minimum width for the wallpaper in a particular display.
2016 */
2017 public int getWidthHint(int displayId) throws RemoteException {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002018 synchronized (mLock) {
wilsonshih81e10a72018-11-15 10:54:21 +08002019 if (!isValidDisplay(displayId)) {
2020 throw new IllegalArgumentException("Cannot find display with id=" + displayId);
2021 }
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07002022 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.getCallingUserId());
Benjamin Franzf3ece362015-02-11 10:51:10 +00002023 if (wallpaper != null) {
wilsonshiha282bf72018-11-30 12:48:05 +08002024 final DisplayData wpdData = getDisplayDataOrCreate(displayId);
wilsonshih81e10a72018-11-15 10:54:21 +08002025 return wpdData.mWidth;
Benjamin Franzf3ece362015-02-11 10:51:10 +00002026 } else {
2027 return 0;
2028 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002029 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002030 }
2031
wilsonshih81e10a72018-11-15 10:54:21 +08002032 /**
2033 * Returns the desired minimum height for the wallpaper in a particular display.
2034 */
2035 public int getHeightHint(int displayId) throws RemoteException {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002036 synchronized (mLock) {
wilsonshih81e10a72018-11-15 10:54:21 +08002037 if (!isValidDisplay(displayId)) {
2038 throw new IllegalArgumentException("Cannot find display with id=" + displayId);
2039 }
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07002040 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.getCallingUserId());
Benjamin Franzf3ece362015-02-11 10:51:10 +00002041 if (wallpaper != null) {
wilsonshiha282bf72018-11-30 12:48:05 +08002042 final DisplayData wpdData = getDisplayDataOrCreate(displayId);
wilsonshih81e10a72018-11-15 10:54:21 +08002043 return wpdData.mHeight;
Benjamin Franzf3ece362015-02-11 10:51:10 +00002044 } else {
2045 return 0;
2046 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002047 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002048 }
2049
wilsonshih81e10a72018-11-15 10:54:21 +08002050 /**
2051 * Sets extra padding that we would like the wallpaper to have outside of the display.
2052 */
2053 public void setDisplayPadding(Rect padding, String callingPackage, int displayId) {
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002054 checkPermission(android.Manifest.permission.SET_WALLPAPER_HINTS);
Benjamin Franzf3ece362015-02-11 10:51:10 +00002055 if (!isWallpaperSupported(callingPackage)) {
2056 return;
2057 }
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002058 synchronized (mLock) {
wilsonshih81e10a72018-11-15 10:54:21 +08002059 if (!isValidDisplay(displayId)) {
2060 throw new IllegalArgumentException("Cannot find display with id=" + displayId);
2061 }
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002062 int userId = UserHandle.getCallingUserId();
Christopher Tateedf7d042016-03-29 18:24:25 -07002063 WallpaperData wallpaper = getWallpaperSafeLocked(userId, FLAG_SYSTEM);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002064 if (padding.left < 0 || padding.top < 0 || padding.right < 0 || padding.bottom < 0) {
2065 throw new IllegalArgumentException("padding must be positive: " + padding);
2066 }
2067
wilsonshiha282bf72018-11-30 12:48:05 +08002068 final DisplayData wpdData = getDisplayDataOrCreate(displayId);
wilsonshih81e10a72018-11-15 10:54:21 +08002069 if (!padding.equals(wpdData.mPadding)) {
2070 wpdData.mPadding.set(padding);
2071 if (displayId == DEFAULT_DISPLAY) saveSettingsLocked(userId);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002072 if (mCurrentUserId != userId) return; // Don't change the properties now
2073 if (wallpaper.connection != null) {
wilsonshih81e10a72018-11-15 10:54:21 +08002074 final WallpaperConnection.DisplayConnector connector = wallpaper.connection
2075 .getDisplayConnectorOrCreate(displayId);
2076 final IWallpaperEngine engine = connector != null ? connector.mEngine : null;
wilsonshihde93f492018-11-01 21:23:40 +08002077 if (engine != null) {
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002078 try {
wilsonshihde93f492018-11-01 21:23:40 +08002079 engine.setDisplayPadding(padding);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002080 } catch (RemoteException e) {
2081 }
2082 notifyCallbacksLocked(wallpaper);
wilsonshih81e10a72018-11-15 10:54:21 +08002083 } else if (wallpaper.connection.mService != null && connector != null) {
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002084 // We've attached to the service but the engine hasn't attached back to us
2085 // yet. This means it will be created with the previous dimensions, so we
2086 // need to update it to the new dimensions once it attaches.
wilsonshih81e10a72018-11-15 10:54:21 +08002087 connector.mPaddingChanged = true;
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002088 }
2089 }
2090 }
2091 }
2092 }
2093
Yorke Leedcd93cc2016-01-08 14:12:55 -08002094 @Override
Christopher Tate93252de2017-06-15 14:48:41 -07002095 public ParcelFileDescriptor getWallpaper(String callingPkg, IWallpaperManagerCallback cb,
2096 final int which, Bundle outParams, int wallpaperUserId) {
Christopher Tate8a71c482017-08-14 16:45:03 -07002097 final int hasPrivilege = mContext.checkCallingOrSelfPermission(
2098 android.Manifest.permission.READ_WALLPAPER_INTERNAL);
2099 if (hasPrivilege != PackageManager.PERMISSION_GRANTED) {
Jeff Sharkey859856d2019-03-25 11:44:11 -06002100 mContext.getSystemService(StorageManager.class).checkPermissionReadImages(true,
2101 Binder.getCallingPid(), Binder.getCallingUid(), callingPkg);
Christopher Tate8a71c482017-08-14 16:45:03 -07002102 }
Christopher Tate93252de2017-06-15 14:48:41 -07002103
Christopher Tatee409f0e2016-03-21 14:53:15 -07002104 wallpaperUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
2105 Binder.getCallingUid(), wallpaperUserId, false, true, "getWallpaper", null);
Christopher Tatebe132e62016-02-10 12:59:49 -08002106
Christopher Tateedf7d042016-03-29 18:24:25 -07002107 if (which != FLAG_SYSTEM && which != FLAG_LOCK) {
Christopher Tatebe132e62016-02-10 12:59:49 -08002108 throw new IllegalArgumentException("Must specify exactly one kind of wallpaper to read");
2109 }
2110
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002111 synchronized (mLock) {
Vadim Tryshev8cde0792016-02-19 17:02:15 -08002112 final SparseArray<WallpaperData> whichSet =
Christopher Tateedf7d042016-03-29 18:24:25 -07002113 (which == FLAG_LOCK) ? mLockWallpaperMap : mWallpaperMap;
Vadim Tryshev8cde0792016-02-19 17:02:15 -08002114 WallpaperData wallpaper = whichSet.get(wallpaperUserId);
2115 if (wallpaper == null) {
Christopher Tatef717b932017-09-11 15:52:54 -07002116 // There is no established wallpaper imagery of this type (expected
2117 // only for lock wallpapers; a system WallpaperData is established at
2118 // user switch)
2119 return null;
Benjamin Franzf3ece362015-02-11 10:51:10 +00002120 }
wilsonshih81e10a72018-11-15 10:54:21 +08002121 // Only for default display.
wilsonshiha282bf72018-11-30 12:48:05 +08002122 final DisplayData wpdData = getDisplayDataOrCreate(DEFAULT_DISPLAY);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002123 try {
Dianne Hackborn284ac932009-08-28 10:34:25 -07002124 if (outParams != null) {
wilsonshih81e10a72018-11-15 10:54:21 +08002125 outParams.putInt("width", wpdData.mWidth);
2126 outParams.putInt("height", wpdData.mHeight);
Dianne Hackborn284ac932009-08-28 10:34:25 -07002127 }
Christopher Tateea6724a2016-02-18 18:39:19 -08002128 if (cb != null) {
2129 wallpaper.callbacks.register(cb);
2130 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08002131 if (!wallpaper.cropFile.exists()) {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002132 return null;
2133 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08002134 return ParcelFileDescriptor.open(wallpaper.cropFile, MODE_READ_ONLY);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002135 } catch (FileNotFoundException e) {
2136 /* Shouldn't happen as we check to see if the file exists */
Joe Onorato8a9b2202010-02-26 18:56:32 -08002137 Slog.w(TAG, "Error getting wallpaper", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002138 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002139 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002140 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002141 }
2142
Christopher Tatee409f0e2016-03-21 14:53:15 -07002143 @Override
Jorim Jaggie31f6b82016-07-01 16:15:09 -07002144 public WallpaperInfo getWallpaperInfo(int userId) {
2145 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
Christopher Tatef717b932017-09-11 15:52:54 -07002146 Binder.getCallingUid(), userId, false, true, "getWallpaperInfo", null);
Dianne Hackborneb034652009-09-07 00:49:58 -07002147 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002148 WallpaperData wallpaper = mWallpaperMap.get(userId);
Benjamin Franzf3ece362015-02-11 10:51:10 +00002149 if (wallpaper != null && wallpaper.connection != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002150 return wallpaper.connection.mInfo;
Dianne Hackborneb034652009-09-07 00:49:58 -07002151 }
2152 return null;
2153 }
2154 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002155
Christopher Tatead3c2592016-01-20 18:13:17 -08002156 @Override
Christopher Tatee409f0e2016-03-21 14:53:15 -07002157 public int getWallpaperIdForUser(int which, int userId) {
2158 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
2159 Binder.getCallingUid(), userId, false, true, "getWallpaperIdForUser", null);
2160
Christopher Tateedf7d042016-03-29 18:24:25 -07002161 if (which != FLAG_SYSTEM && which != FLAG_LOCK) {
Christopher Tatee409f0e2016-03-21 14:53:15 -07002162 throw new IllegalArgumentException("Must specify exactly one kind of wallpaper");
2163 }
2164
2165 final SparseArray<WallpaperData> map =
Christopher Tateedf7d042016-03-29 18:24:25 -07002166 (which == FLAG_LOCK) ? mLockWallpaperMap : mWallpaperMap;
Christopher Tatee409f0e2016-03-21 14:53:15 -07002167 synchronized (mLock) {
2168 WallpaperData wallpaper = map.get(userId);
2169 if (wallpaper != null) {
2170 return wallpaper.wallpaperId;
2171 }
2172 }
2173 return -1;
2174 }
2175
2176 @Override
wilsonshih36597d42018-12-05 18:56:39 +08002177 public void registerWallpaperColorsCallback(IWallpaperManagerCallback cb, int userId,
2178 int displayId) {
Lucas Dupin50ba9912017-07-14 11:55:05 -07002179 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
2180 userId, true, true, "registerWallpaperColorsCallback", null);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002181 synchronized (mLock) {
wilsonshih36597d42018-12-05 18:56:39 +08002182 SparseArray<RemoteCallbackList<IWallpaperManagerCallback>>
2183 userDisplayColorsChangedListeners = mColorsChangedListeners.get(userId);
2184 if (userDisplayColorsChangedListeners == null) {
2185 userDisplayColorsChangedListeners = new SparseArray<>();
2186 mColorsChangedListeners.put(userId, userDisplayColorsChangedListeners);
Lucas Dupin50ba9912017-07-14 11:55:05 -07002187 }
wilsonshih36597d42018-12-05 18:56:39 +08002188 RemoteCallbackList<IWallpaperManagerCallback> displayChangedListeners =
2189 userDisplayColorsChangedListeners.get(displayId);
2190 if (displayChangedListeners == null) {
2191 displayChangedListeners = new RemoteCallbackList<>();
2192 userDisplayColorsChangedListeners.put(displayId, displayChangedListeners);
2193 }
2194 displayChangedListeners.register(cb);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002195 }
2196 }
2197
2198 @Override
wilsonshih36597d42018-12-05 18:56:39 +08002199 public void unregisterWallpaperColorsCallback(IWallpaperManagerCallback cb, int userId,
2200 int displayId) {
Lucas Dupin50ba9912017-07-14 11:55:05 -07002201 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
2202 userId, true, true, "unregisterWallpaperColorsCallback", null);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002203 synchronized (mLock) {
wilsonshih36597d42018-12-05 18:56:39 +08002204 SparseArray<RemoteCallbackList<IWallpaperManagerCallback>>
2205 userDisplayColorsChangedListeners = mColorsChangedListeners.get(userId);
2206 if (userDisplayColorsChangedListeners != null) {
2207 RemoteCallbackList<IWallpaperManagerCallback> displayChangedListeners =
2208 userDisplayColorsChangedListeners.get(displayId);
2209 if (displayChangedListeners != null) {
2210 displayChangedListeners.unregister(cb);
2211 }
Lucas Dupin50ba9912017-07-14 11:55:05 -07002212 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002213 }
2214 }
2215
Lucas Dupin4c8c3272018-11-06 17:47:48 -08002216 /**
wilsonshih36597d42018-12-05 18:56:39 +08002217 * TODO(multi-display) Extends this method with specific display.
Lucas Dupin4c8c3272018-11-06 17:47:48 -08002218 * Propagate ambient state to wallpaper engine.
2219 *
2220 * @param inAmbientMode {@code true} when in ambient mode, {@code false} otherwise.
2221 * @param animationDuration Duration of the animation, or 0 when immediate.
2222 */
2223 public void setInAmbientMode(boolean inAmbientMode, long animationDuration) {
Lucas Dupin7517b5d2017-08-22 12:51:25 -07002224 final IWallpaperEngine engine;
2225 synchronized (mLock) {
Lucas Dupin4c8c3272018-11-06 17:47:48 -08002226 mInAmbientMode = inAmbientMode;
Lucas Dupin7517b5d2017-08-22 12:51:25 -07002227 final WallpaperData data = mWallpaperMap.get(mCurrentUserId);
Ahan Wu723a80e2018-11-07 20:39:32 +08002228 // The wallpaper info is null for image wallpaper, also use the engine in this case.
Ahan Wu67e7f102019-01-14 20:38:14 +08002229 if (data != null && data.connection != null && (data.connection.mInfo == null
2230 || data.connection.mInfo.supportsAmbientMode())) {
wilsonshih36597d42018-12-05 18:56:39 +08002231 // TODO(multi-display) Extends this method with specific display.
wilsonshihde93f492018-11-01 21:23:40 +08002232 engine = data.connection.getDisplayConnectorOrCreate(DEFAULT_DISPLAY).mEngine;
Lucas Dupin7517b5d2017-08-22 12:51:25 -07002233 } else {
2234 engine = null;
2235 }
2236 }
2237
2238 if (engine != null) {
2239 try {
Lucas Dupin4c8c3272018-11-06 17:47:48 -08002240 engine.setInAmbientMode(inAmbientMode, animationDuration);
Lucas Dupin7517b5d2017-08-22 12:51:25 -07002241 } catch (RemoteException e) {
2242 // Cannot talk to wallpaper engine.
2243 }
2244 }
2245 }
2246
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002247 @Override
Christopher Tatebe132e62016-02-10 12:59:49 -08002248 public boolean setLockWallpaperCallback(IWallpaperManagerCallback cb) {
2249 checkPermission(android.Manifest.permission.INTERNAL_SYSTEM_WINDOW);
2250 synchronized (mLock) {
2251 mKeyguardListener = cb;
2252 }
2253 return true;
2254 }
2255
2256 @Override
wilsonshih36597d42018-12-05 18:56:39 +08002257 public WallpaperColors getWallpaperColors(int which, int userId, int displayId)
2258 throws RemoteException {
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002259 if (which != FLAG_LOCK && which != FLAG_SYSTEM) {
2260 throw new IllegalArgumentException("which should be either FLAG_LOCK or FLAG_SYSTEM");
2261 }
Lucas Dupin50ba9912017-07-14 11:55:05 -07002262 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
2263 userId, false, true, "getWallpaperColors", null);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002264
2265 WallpaperData wallpaperData = null;
2266 boolean shouldExtract;
2267
2268 synchronized (mLock) {
2269 if (which == FLAG_LOCK) {
Lucas Dupin50ba9912017-07-14 11:55:05 -07002270 wallpaperData = mLockWallpaperMap.get(userId);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002271 }
2272
2273 // Try to get the system wallpaper anyway since it might
2274 // also be the lock screen wallpaper
2275 if (wallpaperData == null) {
wilsonshih36597d42018-12-05 18:56:39 +08002276 wallpaperData = findWallpaperAtDisplay(userId, displayId);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002277 }
2278
2279 if (wallpaperData == null) {
2280 return null;
2281 }
2282 shouldExtract = wallpaperData.primaryColors == null;
2283 }
2284
2285 if (shouldExtract) {
2286 extractColors(wallpaperData);
2287 }
2288
2289 synchronized (mLock) {
Lucas Dupin4b4c5302018-06-24 18:22:10 -07002290 return wallpaperData.primaryColors;
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002291 }
2292 }
2293
wilsonshih36597d42018-12-05 18:56:39 +08002294 private WallpaperData findWallpaperAtDisplay(int userId, int displayId) {
2295 if (mFallbackWallpaper != null && mFallbackWallpaper.connection != null
2296 && mFallbackWallpaper.connection.containsDisplay(displayId)) {
2297 return mFallbackWallpaper;
2298 } else {
2299 return mWallpaperMap.get(userId);
2300 }
2301 }
2302
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002303 @Override
Christopher Tate1e1e2e02016-01-25 15:34:36 -08002304 public ParcelFileDescriptor setWallpaper(String name, String callingPackage,
Christopher Tated7faf532016-02-25 12:43:38 -08002305 Rect cropHint, boolean allowBackup, Bundle extras, int which,
Jorim Jaggi6c902d02016-08-18 10:44:54 -07002306 IWallpaperManagerCallback completion, int userId) {
2307 userId = ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,
2308 false /* all */, true /* full */, "changing wallpaper", null /* pkg */);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002309 checkPermission(android.Manifest.permission.SET_WALLPAPER);
Christopher Tatead3c2592016-01-20 18:13:17 -08002310
Christopher Tateedf7d042016-03-29 18:24:25 -07002311 if ((which & (FLAG_LOCK|FLAG_SYSTEM)) == 0) {
Christopher Tate98d609c2016-05-18 17:31:58 -07002312 final String msg = "Must specify a valid wallpaper category to set";
2313 Slog.e(TAG, msg);
2314 throw new IllegalArgumentException(msg);
Christopher Tatead3c2592016-01-20 18:13:17 -08002315 }
2316
Christopher Tate98d609c2016-05-18 17:31:58 -07002317 if (!isWallpaperSupported(callingPackage) || !isSetWallpaperAllowed(callingPackage)) {
Benjamin Franzf3ece362015-02-11 10:51:10 +00002318 return null;
2319 }
Christopher Tatead3c2592016-01-20 18:13:17 -08002320
Christopher Tate1e1e2e02016-01-25 15:34:36 -08002321 // "null" means the no-op crop, preserving the full input image
2322 if (cropHint == null) {
2323 cropHint = new Rect(0, 0, 0, 0);
2324 } else {
2325 if (cropHint.isEmpty()
2326 || cropHint.left < 0
2327 || cropHint.top < 0) {
Christopher Tate98d609c2016-05-18 17:31:58 -07002328 throw new IllegalArgumentException("Invalid crop rect supplied: " + cropHint);
Christopher Tate1e1e2e02016-01-25 15:34:36 -08002329 }
2330 }
2331
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002332 synchronized (mLock) {
Christopher Tatebe132e62016-02-10 12:59:49 -08002333 if (DEBUG) Slog.v(TAG, "setWallpaper which=0x" + Integer.toHexString(which));
2334 WallpaperData wallpaper;
2335
Christopher Tate8347b632016-04-29 18:59:18 -07002336 /* If we're setting system but not lock, and lock is currently sharing the system
2337 * wallpaper, we need to migrate that image over to being lock-only before
2338 * the caller here writes new bitmap data.
2339 */
2340 if (which == FLAG_SYSTEM && mLockWallpaperMap.get(userId) == null) {
2341 if (DEBUG) {
2342 Slog.i(TAG, "Migrating system->lock to preserve");
2343 }
2344 migrateSystemToLockWallpaperLocked(userId);
2345 }
2346
Christopher Tatebe132e62016-02-10 12:59:49 -08002347 wallpaper = getWallpaperSafeLocked(userId, which);
Dianne Hackborn0cd48872009-08-13 18:51:59 -07002348 final long ident = Binder.clearCallingIdentity();
2349 try {
Christopher Tatead3c2592016-01-20 18:13:17 -08002350 ParcelFileDescriptor pfd = updateWallpaperBitmapLocked(name, wallpaper, extras);
Dianne Hackborn0cd48872009-08-13 18:51:59 -07002351 if (pfd != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002352 wallpaper.imageWallpaperPending = true;
Christopher Tatebe132e62016-02-10 12:59:49 -08002353 wallpaper.whichPending = which;
Christopher Tate1e1e2e02016-01-25 15:34:36 -08002354 wallpaper.setComplete = completion;
2355 wallpaper.cropHint.set(cropHint);
Christopher Tatec613c632016-08-12 14:13:02 -07002356 wallpaper.allowBackup = allowBackup;
Dianne Hackborn0cd48872009-08-13 18:51:59 -07002357 }
2358 return pfd;
2359 } finally {
2360 Binder.restoreCallingIdentity(ident);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002361 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002362 }
2363 }
2364
Christopher Tate8347b632016-04-29 18:59:18 -07002365 private void migrateSystemToLockWallpaperLocked(int userId) {
2366 WallpaperData sysWP = mWallpaperMap.get(userId);
2367 if (sysWP == null) {
2368 if (DEBUG) {
2369 Slog.i(TAG, "No system wallpaper? Not tracking for lock-only");
2370 }
2371 return;
2372 }
2373
2374 // We know a-priori that there is no lock-only wallpaper currently
2375 WallpaperData lockWP = new WallpaperData(userId,
2376 WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP);
2377 lockWP.wallpaperId = sysWP.wallpaperId;
2378 lockWP.cropHint.set(sysWP.cropHint);
Christopher Tateedd8dc82016-10-12 15:17:58 -07002379 lockWP.allowBackup = sysWP.allowBackup;
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002380 lockWP.primaryColors = sysWP.primaryColors;
Christopher Tate8347b632016-04-29 18:59:18 -07002381
2382 // Migrate the bitmap files outright; no need to copy
2383 try {
2384 Os.rename(sysWP.wallpaperFile.getAbsolutePath(), lockWP.wallpaperFile.getAbsolutePath());
2385 Os.rename(sysWP.cropFile.getAbsolutePath(), lockWP.cropFile.getAbsolutePath());
2386 } catch (ErrnoException e) {
2387 Slog.e(TAG, "Can't migrate system wallpaper: " + e.getMessage());
2388 lockWP.wallpaperFile.delete();
2389 lockWP.cropFile.delete();
2390 return;
2391 }
2392
2393 mLockWallpaperMap.put(userId, lockWP);
2394 }
2395
Christopher Tatead3c2592016-01-20 18:13:17 -08002396 ParcelFileDescriptor updateWallpaperBitmapLocked(String name, WallpaperData wallpaper,
2397 Bundle extras) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002398 if (name == null) name = "";
2399 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002400 File dir = getWallpaperDir(wallpaper.userId);
2401 if (!dir.exists()) {
2402 dir.mkdir();
Dianne Hackbornebac48c2011-11-29 18:01:50 -08002403 FileUtils.setPermissions(
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002404 dir.getPath(),
Dianne Hackbornebac48c2011-11-29 18:01:50 -08002405 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
2406 -1, -1);
2407 }
Christopher Tatebe132e62016-02-10 12:59:49 -08002408 ParcelFileDescriptor fd = ParcelFileDescriptor.open(wallpaper.wallpaperFile,
Christopher Tate90f86ba2014-09-11 12:37:19 -07002409 MODE_CREATE|MODE_READ_WRITE|MODE_TRUNCATE);
Christopher Tatebe132e62016-02-10 12:59:49 -08002410 if (!SELinux.restorecon(wallpaper.wallpaperFile)) {
rpcraig554cb0c2012-07-05 06:41:43 -04002411 return null;
2412 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002413 wallpaper.name = name;
Christopher Tatead3c2592016-01-20 18:13:17 -08002414 wallpaper.wallpaperId = makeWallpaperIdLocked();
2415 if (extras != null) {
2416 extras.putInt(WallpaperManager.EXTRA_NEW_WALLPAPER_ID, wallpaper.wallpaperId);
2417 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002418 // Nullify field to require new computation
2419 wallpaper.primaryColors = null;
Christopher Tatead3c2592016-01-20 18:13:17 -08002420 if (DEBUG) {
2421 Slog.v(TAG, "updateWallpaperBitmapLocked() : id=" + wallpaper.wallpaperId
Christopher Tatebe132e62016-02-10 12:59:49 -08002422 + " name=" + name + " file=" + wallpaper.wallpaperFile.getName());
Christopher Tatead3c2592016-01-20 18:13:17 -08002423 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002424 return fd;
2425 } catch (FileNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002426 Slog.w(TAG, "Error setting wallpaper", e);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002427 }
2428 return null;
2429 }
2430
Christopher Tated57d17c2016-03-25 13:41:46 -07002431 @Override
Adrian Roos40ea0832016-07-14 14:19:55 -07002432 public void setWallpaperComponentChecked(ComponentName name, String callingPackage,
2433 int userId) {
2434
Christopher Tate98d609c2016-05-18 17:31:58 -07002435 if (isWallpaperSupported(callingPackage) && isSetWallpaperAllowed(callingPackage)) {
Adrian Roos40ea0832016-07-14 14:19:55 -07002436 setWallpaperComponent(name, userId);
Benjamin Franzf3ece362015-02-11 10:51:10 +00002437 }
2438 }
2439
2440 // ToDo: Remove this version of the function
Christopher Tated57d17c2016-03-25 13:41:46 -07002441 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002442 public void setWallpaperComponent(ComponentName name) {
Adrian Roos40ea0832016-07-14 14:19:55 -07002443 setWallpaperComponent(name, UserHandle.getCallingUserId());
2444 }
2445
2446 private void setWallpaperComponent(ComponentName name, int userId) {
2447 userId = ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,
2448 false /* all */, true /* full */, "changing live wallpaper", null /* pkg */);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002449 checkPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT);
Adrian Roos40ea0832016-07-14 14:19:55 -07002450
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002451 int which = FLAG_SYSTEM;
2452 boolean shouldNotifyColors = false;
2453 WallpaperData wallpaper;
2454
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002455 synchronized (mLock) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002456 if (DEBUG) Slog.v(TAG, "setWallpaperComponent name=" + name);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002457 wallpaper = mWallpaperMap.get(userId);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002458 if (wallpaper == null) {
2459 throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
2460 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002461 final long ident = Binder.clearCallingIdentity();
Christopher Tate7cd00102016-12-19 14:38:44 -08002462
2463 // Live wallpapers can't be specified for keyguard. If we're using a static
2464 // system+lock image currently, migrate the system wallpaper to be a lock-only
2465 // image as part of making a different live component active as the system
2466 // wallpaper.
2467 if (mImageWallpaper.equals(wallpaper.wallpaperComponent)) {
2468 if (mLockWallpaperMap.get(userId) == null) {
2469 // We're using the static imagery and there is no lock-specific image in place,
2470 // therefore it's a shared system+lock image that we need to migrate.
2471 migrateSystemToLockWallpaperLocked(userId);
2472 }
2473 }
2474
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002475 // New live wallpaper is also a lock wallpaper if nothing is set
2476 if (mLockWallpaperMap.get(userId) == null) {
2477 which |= FLAG_LOCK;
2478 }
2479
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002480 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002481 wallpaper.imageWallpaperPending = false;
Lucas Dupin50ba9912017-07-14 11:55:05 -07002482 boolean same = changingToSame(name, wallpaper);
Christopher Tated57d17c2016-03-25 13:41:46 -07002483 if (bindWallpaperComponentLocked(name, false, true, wallpaper, null)) {
Lucas Dupin50ba9912017-07-14 11:55:05 -07002484 if (!same) {
2485 wallpaper.primaryColors = null;
2486 }
Christopher Tated57d17c2016-03-25 13:41:46 -07002487 wallpaper.wallpaperId = makeWallpaperIdLocked();
Sunny Goyal0572e182016-03-31 11:05:51 -07002488 notifyCallbacksLocked(wallpaper);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002489 shouldNotifyColors = true;
Christopher Tated57d17c2016-03-25 13:41:46 -07002490 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002491 } finally {
2492 Binder.restoreCallingIdentity(ident);
2493 }
2494 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002495
2496 if (shouldNotifyColors) {
2497 notifyWallpaperColorsChanged(wallpaper, which);
wilsonshih36597d42018-12-05 18:56:39 +08002498 notifyWallpaperColorsChanged(mFallbackWallpaper, FLAG_SYSTEM);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002499 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002500 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01002501
Lucas Dupin50ba9912017-07-14 11:55:05 -07002502 private boolean changingToSame(ComponentName componentName, WallpaperData wallpaper) {
2503 if (wallpaper.connection != null) {
2504 if (wallpaper.wallpaperComponent == null) {
2505 if (componentName == null) {
2506 if (DEBUG) Slog.v(TAG, "changingToSame: still using default");
2507 // Still using default wallpaper.
2508 return true;
2509 }
2510 } else if (wallpaper.wallpaperComponent.equals(componentName)) {
2511 // Changing to same wallpaper.
2512 if (DEBUG) Slog.v(TAG, "same wallpaper");
2513 return true;
2514 }
2515 }
2516 return false;
2517 }
2518
wilsonshiha282bf72018-11-30 12:48:05 +08002519 private boolean bindWallpaperComponentLocked(ComponentName componentName, boolean force,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002520 boolean fromUser, WallpaperData wallpaper, IRemoteCallback reply) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07002521 if (DEBUG_LIVE) {
2522 Slog.v(TAG, "bindWallpaperComponentLocked: componentName=" + componentName);
2523 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002524 // Has the component changed?
Lucas Dupin50ba9912017-07-14 11:55:05 -07002525 if (!force && changingToSame(componentName, wallpaper)) {
2526 return true;
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002527 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01002528
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002529 try {
Mike Clerona428b2c2009-11-15 22:53:08 -08002530 if (componentName == null) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07002531 componentName = mDefaultWallpaperComponent;
Mike Clerona428b2c2009-11-15 22:53:08 -08002532 if (componentName == null) {
Mike Cleron322b6ee2009-11-12 07:45:47 -08002533 // Fall back to static image wallpaper
Justin Koh29c30162014-09-05 17:10:10 -07002534 componentName = mImageWallpaper;
Mike Cleron322b6ee2009-11-12 07:45:47 -08002535 //clearWallpaperComponentLocked();
2536 //return;
Christopher Tate2a6c55f2017-03-31 12:28:30 -07002537 if (DEBUG_LIVE) Slog.v(TAG, "No default component; using image wallpaper");
Mike Cleron322b6ee2009-11-12 07:45:47 -08002538 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002539 }
Amith Yamasani4e2820c2012-08-28 22:17:23 -07002540 int serviceUserId = wallpaper.userId;
2541 ServiceInfo si = mIPackageManager.getServiceInfo(componentName,
2542 PackageManager.GET_META_DATA | PackageManager.GET_PERMISSIONS, serviceUserId);
Christopher Tate90952202013-09-08 13:01:28 -07002543 if (si == null) {
2544 // The wallpaper component we're trying to use doesn't exist
2545 Slog.w(TAG, "Attempted wallpaper " + componentName + " is unavailable");
2546 return false;
2547 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002548 if (!android.Manifest.permission.BIND_WALLPAPER.equals(si.permission)) {
Lucas Dupin4c8c3272018-11-06 17:47:48 -08002549 String msg = "Selected service does not have "
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002550 + android.Manifest.permission.BIND_WALLPAPER
Dianne Hackborn80b902f2011-09-15 15:15:27 -07002551 + ": " + componentName;
2552 if (fromUser) {
2553 throw new SecurityException(msg);
2554 }
2555 Slog.w(TAG, msg);
2556 return false;
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002557 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01002558
Dianne Hackborneb034652009-09-07 00:49:58 -07002559 WallpaperInfo wi = null;
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01002560
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002561 Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
Justin Koh29c30162014-09-05 17:10:10 -07002562 if (componentName != null && !componentName.equals(mImageWallpaper)) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002563 // Make sure the selected service is actually a wallpaper service.
Amith Yamasani4e2820c2012-08-28 22:17:23 -07002564 List<ResolveInfo> ris =
2565 mIPackageManager.queryIntentServices(intent,
2566 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
Jeff Sharkeyd5896632016-03-04 16:16:00 -07002567 PackageManager.GET_META_DATA, serviceUserId).getList();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002568 for (int i=0; i<ris.size(); i++) {
2569 ServiceInfo rsi = ris.get(i).serviceInfo;
2570 if (rsi.name.equals(si.name) &&
2571 rsi.packageName.equals(si.packageName)) {
Dianne Hackborneb034652009-09-07 00:49:58 -07002572 try {
2573 wi = new WallpaperInfo(mContext, ris.get(i));
2574 } catch (XmlPullParserException e) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -07002575 if (fromUser) {
2576 throw new IllegalArgumentException(e);
2577 }
2578 Slog.w(TAG, e);
2579 return false;
Dianne Hackborneb034652009-09-07 00:49:58 -07002580 } catch (IOException e) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -07002581 if (fromUser) {
2582 throw new IllegalArgumentException(e);
2583 }
2584 Slog.w(TAG, e);
2585 return false;
Dianne Hackborneb034652009-09-07 00:49:58 -07002586 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002587 break;
2588 }
2589 }
Dianne Hackborneb034652009-09-07 00:49:58 -07002590 if (wi == null) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -07002591 String msg = "Selected service is not a wallpaper: "
2592 + componentName;
2593 if (fromUser) {
2594 throw new SecurityException(msg);
2595 }
2596 Slog.w(TAG, msg);
2597 return false;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002598 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002599 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01002600
Lucas Dupin4c8c3272018-11-06 17:47:48 -08002601 if (wi != null && wi.supportsAmbientMode()) {
2602 final int hasPrivilege = mIPackageManager.checkPermission(
2603 android.Manifest.permission.AMBIENT_WALLPAPER, wi.getPackageName(),
2604 serviceUserId);
2605 if (hasPrivilege != PackageManager.PERMISSION_GRANTED) {
2606 String msg = "Selected service does not have "
2607 + android.Manifest.permission.AMBIENT_WALLPAPER
2608 + ": " + componentName;
2609 if (fromUser) {
2610 throw new SecurityException(msg);
2611 }
2612 Slog.w(TAG, msg);
2613 return false;
2614 }
2615 }
2616
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002617 // Bind the service!
Joe Onorato8a9b2202010-02-26 18:56:32 -08002618 if (DEBUG) Slog.v(TAG, "Binding to:" + componentName);
wilsonshihde93f492018-11-01 21:23:40 +08002619 final int componentUid = mIPackageManager.getPackageUid(componentName.getPackageName(),
2620 MATCH_DIRECT_BOOT_AUTO, wallpaper.userId);
2621 WallpaperConnection newConn = new WallpaperConnection(wi, wallpaper, componentUid);
Mike Clerona428b2c2009-11-15 22:53:08 -08002622 intent.setComponent(componentName);
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07002623 intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
2624 com.android.internal.R.string.wallpaper_binding_label);
Dianne Hackborn41203752012-08-31 14:05:51 -07002625 intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivityAsUser(
Dianne Hackborneb034652009-09-07 00:49:58 -07002626 mContext, 0,
2627 Intent.createChooser(new Intent(Intent.ACTION_SET_WALLPAPER),
2628 mContext.getText(com.android.internal.R.string.chooser_wallpaper)),
Dianne Hackborn41203752012-08-31 14:05:51 -07002629 0, null, new UserHandle(serviceUserId)));
Dianne Hackbornc8230512013-07-13 21:32:12 -07002630 if (!mContext.bindServiceAsUser(intent, newConn,
Dianne Hackbornd69e4c12015-04-24 09:54:54 -07002631 Context.BIND_AUTO_CREATE | Context.BIND_SHOWING_UI
Amith Yamasanic45a9902019-04-05 16:29:30 -07002632 | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE
2633 | Context.BIND_INCLUDE_CAPABILITIES,
Amith Yamasani27b89e62013-01-16 12:30:11 -08002634 new UserHandle(serviceUserId))) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -07002635 String msg = "Unable to bind service: "
2636 + componentName;
2637 if (fromUser) {
2638 throw new IllegalArgumentException(msg);
2639 }
2640 Slog.w(TAG, msg);
2641 return false;
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002642 }
wilsonshiha282bf72018-11-30 12:48:05 +08002643 if (wallpaper.userId == mCurrentUserId && mLastWallpaper != null
2644 && !wallpaper.equals(mFallbackWallpaper)) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002645 detachWallpaperLocked(mLastWallpaper);
2646 }
2647 wallpaper.wallpaperComponent = componentName;
2648 wallpaper.connection = newConn;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002649 newConn.mReply = reply;
wilsonshiha282bf72018-11-30 12:48:05 +08002650 if (wallpaper.userId == mCurrentUserId && !wallpaper.equals(mFallbackWallpaper)) {
wilsonshihde93f492018-11-01 21:23:40 +08002651 mLastWallpaper = wallpaper;
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002652 }
wilsonshiha282bf72018-11-30 12:48:05 +08002653 updateFallbackConnection();
Amith Yamasani4e2820c2012-08-28 22:17:23 -07002654 } catch (RemoteException e) {
2655 String msg = "Remote exception for " + componentName + "\n" + e;
Dianne Hackborn80b902f2011-09-15 15:15:27 -07002656 if (fromUser) {
2657 throw new IllegalArgumentException(msg);
2658 }
2659 Slog.w(TAG, msg);
2660 return false;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002661 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -07002662 return true;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002663 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002664
wilsonshiha282bf72018-11-30 12:48:05 +08002665 private void detachWallpaperLocked(WallpaperData wallpaper) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002666 if (wallpaper.connection != null) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002667 if (wallpaper.connection.mReply != null) {
2668 try {
2669 wallpaper.connection.mReply.sendResult(null);
2670 } catch (RemoteException e) {
2671 }
2672 wallpaper.connection.mReply = null;
2673 }
wilsonshihb72ff9c2019-03-21 17:27:02 +08002674 try {
Keun young Parke3d2fea2019-03-29 17:42:32 -07002675 // It can be null if user switching happens before service connection.
2676 if (wallpaper.connection.mService != null) {
2677 wallpaper.connection.mService.detach();
2678 }
wilsonshihb72ff9c2019-03-21 17:27:02 +08002679 } catch (RemoteException e) {
2680 Slog.w(TAG, "Failed detaching wallpaper service ", e);
2681 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002682 mContext.unbindService(wallpaper.connection);
wilsonshiha282bf72018-11-30 12:48:05 +08002683 wallpaper.connection.forEachDisplayConnector(
2684 WallpaperConnection.DisplayConnector::disconnectLocked);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002685 wallpaper.connection.mService = null;
wilsonshihde93f492018-11-01 21:23:40 +08002686 wallpaper.connection.mDisplayConnector.clear();
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002687 wallpaper.connection = null;
wilsonshihde93f492018-11-01 21:23:40 +08002688 if (wallpaper == mLastWallpaper) mLastWallpaper = null;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002689 }
2690 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002691
wilsonshiha282bf72018-11-30 12:48:05 +08002692 private void clearWallpaperComponentLocked(WallpaperData wallpaper) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002693 wallpaper.wallpaperComponent = null;
2694 detachWallpaperLocked(wallpaper);
2695 }
2696
wilsonshiha282bf72018-11-30 12:48:05 +08002697 private void attachServiceLocked(WallpaperConnection conn, WallpaperData wallpaper) {
wilsonshihde93f492018-11-01 21:23:40 +08002698 conn.forEachDisplayConnector(connector-> connector.connectLocked(conn, wallpaper));
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002699 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002700
2701 private void notifyCallbacksLocked(WallpaperData wallpaper) {
2702 final int n = wallpaper.callbacks.beginBroadcast();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002703 for (int i = 0; i < n; i++) {
2704 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002705 wallpaper.callbacks.getBroadcastItem(i).onWallpaperChanged();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002706 } catch (RemoteException e) {
2707
2708 // The RemoteCallbackList will take care of removing
2709 // the dead object for us.
2710 }
2711 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002712 wallpaper.callbacks.finishBroadcast();
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002713
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002714 final Intent intent = new Intent(Intent.ACTION_WALLPAPER_CHANGED);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07002715 mContext.sendBroadcastAsUser(intent, new UserHandle(mCurrentUserId));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002716 }
2717
2718 private void checkPermission(String permission) {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002719 if (PackageManager.PERMISSION_GRANTED!= mContext.checkCallingOrSelfPermission(permission)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002720 throw new SecurityException("Access denied to process: " + Binder.getCallingPid()
2721 + ", must have permission " + permission);
2722 }
2723 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002724
Benjamin Franzf3ece362015-02-11 10:51:10 +00002725 /**
2726 * Certain user types do not support wallpapers (e.g. managed profiles). The check is
2727 * implemented through through the OP_WRITE_WALLPAPER AppOp.
2728 */
2729 public boolean isWallpaperSupported(String callingPackage) {
2730 return mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_WRITE_WALLPAPER, Binder.getCallingUid(),
2731 callingPackage) == AppOpsManager.MODE_ALLOWED;
2732 }
2733
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01002734 @Override
Christopher Tate98d609c2016-05-18 17:31:58 -07002735 public boolean isSetWallpaperAllowed(String callingPackage) {
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01002736 final PackageManager pm = mContext.getPackageManager();
2737 String[] uidPackages = pm.getPackagesForUid(Binder.getCallingUid());
2738 boolean uidMatchPackage = Arrays.asList(uidPackages).contains(callingPackage);
2739 if (!uidMatchPackage) {
2740 return false; // callingPackage was faked.
2741 }
2742
2743 final DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
2744 if (dpm.isDeviceOwnerApp(callingPackage) || dpm.isProfileOwnerApp(callingPackage)) {
2745 return true;
2746 }
2747 final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
2748 return !um.hasUserRestriction(UserManager.DISALLOW_SET_WALLPAPER);
2749 }
2750
Christopher Tated7faf532016-02-25 12:43:38 -08002751 @Override
Christopher Tate61722662016-08-10 16:13:14 -07002752 public boolean isWallpaperBackupEligible(int which, int userId) {
Christopher Tated7faf532016-02-25 12:43:38 -08002753 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
2754 throw new SecurityException("Only the system may call isWallpaperBackupEligible");
2755 }
2756
Christopher Tate61722662016-08-10 16:13:14 -07002757 WallpaperData wallpaper = (which == FLAG_LOCK)
Christopher Tatef7d1b5d2016-08-19 11:21:07 -07002758 ? mLockWallpaperMap.get(userId)
2759 : mWallpaperMap.get(userId);
Christopher Tated7faf532016-02-25 12:43:38 -08002760 return (wallpaper != null) ? wallpaper.allowBackup : false;
2761 }
2762
wilsonshih643bf132019-02-27 12:49:19 +08002763 private void onDisplayReadyInternal(int displayId) {
2764 synchronized (mLock) {
2765 if (mLastWallpaper == null) {
2766 return;
2767 }
2768 if (supportsMultiDisplay(mLastWallpaper.connection)) {
2769 final WallpaperConnection.DisplayConnector connector =
2770 mLastWallpaper.connection.getDisplayConnectorOrCreate(displayId);
2771 if (connector == null) return;
2772 connector.connectLocked(mLastWallpaper.connection, mLastWallpaper);
2773 return;
2774 }
2775 // System wallpaper does not support multiple displays, attach this display to
2776 // the fallback wallpaper.
2777 if (mFallbackWallpaper != null) {
2778 final WallpaperConnection.DisplayConnector connector = mFallbackWallpaper
2779 .connection.getDisplayConnectorOrCreate(displayId);
2780 if (connector == null) return;
2781 connector.connectLocked(mFallbackWallpaper.connection, mFallbackWallpaper);
2782 } else {
2783 Slog.w(TAG, "No wallpaper can be added to the new display");
2784 }
2785 }
2786 }
2787
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002788 private static JournaledFile makeJournaledFile(int userId) {
Amith Yamasani61f57372012-08-31 12:12:28 -07002789 final String base = new File(getWallpaperDir(userId), WALLPAPER_INFO).getAbsolutePath();
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002790 return new JournaledFile(new File(base), new File(base + ".tmp"));
2791 }
2792
Christopher Tatedb27b842016-02-25 14:39:17 -08002793 private void saveSettingsLocked(int userId) {
2794 JournaledFile journal = makeJournaledFile(userId);
2795 FileOutputStream fstream = null;
2796 BufferedOutputStream stream = null;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002797 try {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002798 XmlSerializer out = new FastXmlSerializer();
Christopher Tatedb27b842016-02-25 14:39:17 -08002799 fstream = new FileOutputStream(journal.chooseForWrite(), false);
2800 stream = new BufferedOutputStream(fstream);
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01002801 out.setOutput(stream, StandardCharsets.UTF_8.name());
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002802 out.startDocument(null, true);
2803
Christopher Tatedb27b842016-02-25 14:39:17 -08002804 WallpaperData wallpaper;
Christopher Tate1e1e2e02016-01-25 15:34:36 -08002805
Christopher Tatedb27b842016-02-25 14:39:17 -08002806 wallpaper = mWallpaperMap.get(userId);
2807 if (wallpaper != null) {
2808 writeWallpaperAttributes(out, "wp", wallpaper);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002809 }
Christopher Tatedb27b842016-02-25 14:39:17 -08002810 wallpaper = mLockWallpaperMap.get(userId);
2811 if (wallpaper != null) {
2812 writeWallpaperAttributes(out, "kwp", wallpaper);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002813 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002814
2815 out.endDocument();
Christopher Tatedb27b842016-02-25 14:39:17 -08002816
2817 stream.flush(); // also flushes fstream
2818 FileUtils.sync(fstream);
2819 stream.close(); // also closes fstream
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002820 journal.commit();
2821 } catch (IOException e) {
Christopher Tatead3c2592016-01-20 18:13:17 -08002822 IoUtils.closeQuietly(stream);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002823 journal.rollback();
2824 }
2825 }
2826
Christopher Tatedb27b842016-02-25 14:39:17 -08002827 private void writeWallpaperAttributes(XmlSerializer out, String tag, WallpaperData wallpaper)
2828 throws IllegalArgumentException, IllegalStateException, IOException {
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002829 if (DEBUG) {
Christopher Tatef717b932017-09-11 15:52:54 -07002830 Slog.v(TAG, "writeWallpaperAttributes id=" + wallpaper.wallpaperId);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002831 }
wilsonshiha282bf72018-11-30 12:48:05 +08002832 final DisplayData wpdData = getDisplayDataOrCreate(DEFAULT_DISPLAY);
Christopher Tatedb27b842016-02-25 14:39:17 -08002833 out.startTag(null, tag);
2834 out.attribute(null, "id", Integer.toString(wallpaper.wallpaperId));
wilsonshih81e10a72018-11-15 10:54:21 +08002835 out.attribute(null, "width", Integer.toString(wpdData.mWidth));
2836 out.attribute(null, "height", Integer.toString(wpdData.mHeight));
Christopher Tatedb27b842016-02-25 14:39:17 -08002837
2838 out.attribute(null, "cropLeft", Integer.toString(wallpaper.cropHint.left));
2839 out.attribute(null, "cropTop", Integer.toString(wallpaper.cropHint.top));
2840 out.attribute(null, "cropRight", Integer.toString(wallpaper.cropHint.right));
2841 out.attribute(null, "cropBottom", Integer.toString(wallpaper.cropHint.bottom));
2842
wilsonshih81e10a72018-11-15 10:54:21 +08002843 if (wpdData.mPadding.left != 0) {
2844 out.attribute(null, "paddingLeft", Integer.toString(wpdData.mPadding.left));
Christopher Tatedb27b842016-02-25 14:39:17 -08002845 }
wilsonshih81e10a72018-11-15 10:54:21 +08002846 if (wpdData.mPadding.top != 0) {
2847 out.attribute(null, "paddingTop", Integer.toString(wpdData.mPadding.top));
Christopher Tatedb27b842016-02-25 14:39:17 -08002848 }
wilsonshih81e10a72018-11-15 10:54:21 +08002849 if (wpdData.mPadding.right != 0) {
2850 out.attribute(null, "paddingRight", Integer.toString(wpdData.mPadding.right));
Christopher Tatedb27b842016-02-25 14:39:17 -08002851 }
wilsonshih81e10a72018-11-15 10:54:21 +08002852 if (wpdData.mPadding.bottom != 0) {
2853 out.attribute(null, "paddingBottom", Integer.toString(wpdData.mPadding.bottom));
Christopher Tatedb27b842016-02-25 14:39:17 -08002854 }
2855
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002856 if (wallpaper.primaryColors != null) {
Lucas Dupin84b89d92017-05-09 12:16:19 -07002857 int colorsCount = wallpaper.primaryColors.getMainColors().size();
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002858 out.attribute(null, "colorsCount", Integer.toString(colorsCount));
2859 if (colorsCount > 0) {
2860 for (int i = 0; i < colorsCount; i++) {
Lucas Dupin84b89d92017-05-09 12:16:19 -07002861 final Color wc = wallpaper.primaryColors.getMainColors().get(i);
2862 out.attribute(null, "colorValue"+i, Integer.toString(wc.toArgb()));
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002863 }
2864 }
Lucas Dupin75ec3792017-06-29 14:07:18 -07002865 out.attribute(null, "colorHints",
Lucas Dupin84b89d92017-05-09 12:16:19 -07002866 Integer.toString(wallpaper.primaryColors.getColorHints()));
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002867 }
2868
Christopher Tatedb27b842016-02-25 14:39:17 -08002869 out.attribute(null, "name", wallpaper.name);
2870 if (wallpaper.wallpaperComponent != null
2871 && !wallpaper.wallpaperComponent.equals(mImageWallpaper)) {
2872 out.attribute(null, "component",
2873 wallpaper.wallpaperComponent.flattenToShortString());
2874 }
Christopher Tated7faf532016-02-25 12:43:38 -08002875
2876 if (wallpaper.allowBackup) {
2877 out.attribute(null, "backup", "true");
2878 }
2879
Christopher Tatedb27b842016-02-25 14:39:17 -08002880 out.endTag(null, tag);
2881 }
2882
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002883 private void migrateFromOld() {
Christopher Tate9f224432017-08-01 16:32:49 -07002884 // Pre-N, what existed is the one we're now using as the display crop
2885 File preNWallpaper = new File(getWallpaperDir(0), WALLPAPER_CROP);
2886 // In the very-long-ago, imagery lived with the settings app
2887 File originalWallpaper = new File(WallpaperBackupHelper.WALLPAPER_IMAGE_KEY);
2888 File newWallpaper = new File(getWallpaperDir(0), WALLPAPER);
2889
2890 // Migrations from earlier wallpaper image storage schemas
2891 if (preNWallpaper.exists()) {
2892 if (!newWallpaper.exists()) {
2893 // we've got the 'wallpaper' crop file but not the nominal source image,
2894 // so do the simple "just take everything" straight copy of legacy data
2895 if (DEBUG) {
2896 Slog.i(TAG, "Migrating wallpaper schema");
2897 }
2898 FileUtils.copyFile(preNWallpaper, newWallpaper);
2899 } // else we're in the usual modern case: both source & crop exist
2900 } else if (originalWallpaper.exists()) {
2901 // VERY old schema; make sure things exist and are in the right place
2902 if (DEBUG) {
2903 Slog.i(TAG, "Migrating antique wallpaper schema");
2904 }
2905 File oldInfo = new File(WallpaperBackupHelper.WALLPAPER_INFO_KEY);
2906 if (oldInfo.exists()) {
2907 File newInfo = new File(getWallpaperDir(0), WALLPAPER_INFO);
2908 oldInfo.renameTo(newInfo);
2909 }
2910
2911 FileUtils.copyFile(originalWallpaper, preNWallpaper);
2912 originalWallpaper.renameTo(newWallpaper);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002913 }
2914 }
2915
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002916 private int getAttributeInt(XmlPullParser parser, String name, int defValue) {
2917 String value = parser.getAttributeValue(null, name);
2918 if (value == null) {
2919 return defValue;
2920 }
2921 return Integer.parseInt(value);
2922 }
2923
Xiaohui Chenac531942015-05-13 13:20:52 -07002924 /**
2925 * Sometimes it is expected the wallpaper map may not have a user's data. E.g. This could
2926 * happen during user switch. The async user switch observer may not have received
2927 * the event yet. We use this safe method when we don't care about this ordering and just
2928 * want to update the data. The data is going to be applied when the user switch observer
2929 * is eventually executed.
Christopher Tatef717b932017-09-11 15:52:54 -07002930 *
2931 * Important: this method loads settings to initialize the given user's wallpaper data if
2932 * there is no current in-memory state.
Xiaohui Chenac531942015-05-13 13:20:52 -07002933 */
Christopher Tatebe132e62016-02-10 12:59:49 -08002934 private WallpaperData getWallpaperSafeLocked(int userId, int which) {
2935 // We're setting either just system (work with the system wallpaper),
2936 // both (also work with the system wallpaper), or just the lock
2937 // wallpaper (update against the existing lock wallpaper if any).
2938 // Combined or just-system operations use the 'system' WallpaperData
2939 // for this use; lock-only operations use the dedicated one.
2940 final SparseArray<WallpaperData> whichSet =
Christopher Tateedf7d042016-03-29 18:24:25 -07002941 (which == FLAG_LOCK) ? mLockWallpaperMap : mWallpaperMap;
Christopher Tatebe132e62016-02-10 12:59:49 -08002942 WallpaperData wallpaper = whichSet.get(userId);
Xiaohui Chenac531942015-05-13 13:20:52 -07002943 if (wallpaper == null) {
Christopher Tatebe132e62016-02-10 12:59:49 -08002944 // common case, this is the first lookup post-boot of the system or
2945 // unified lock, so we bring up the saved state lazily now and recheck.
Christopher Tated7faf532016-02-25 12:43:38 -08002946 loadSettingsLocked(userId, false);
Christopher Tatebe132e62016-02-10 12:59:49 -08002947 wallpaper = whichSet.get(userId);
2948 // if it's still null here, this is a lock-only operation and there is not
2949 // yet a lock-only wallpaper set for this user, so we need to establish
2950 // it now.
2951 if (wallpaper == null) {
Christopher Tateedf7d042016-03-29 18:24:25 -07002952 if (which == FLAG_LOCK) {
Christopher Tatebe132e62016-02-10 12:59:49 -08002953 wallpaper = new WallpaperData(userId,
2954 WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP);
2955 mLockWallpaperMap.put(userId, wallpaper);
wilsonshih81e10a72018-11-15 10:54:21 +08002956 ensureSaneWallpaperData(wallpaper, DEFAULT_DISPLAY);
Christopher Tatebe132e62016-02-10 12:59:49 -08002957 } else {
2958 // sanity fallback: we're in bad shape, but establishing a known
2959 // valid system+lock WallpaperData will keep us from dying.
2960 Slog.wtf(TAG, "Didn't find wallpaper in non-lock case!");
2961 wallpaper = new WallpaperData(userId, WALLPAPER, WALLPAPER_CROP);
2962 mWallpaperMap.put(userId, wallpaper);
wilsonshih81e10a72018-11-15 10:54:21 +08002963 ensureSaneWallpaperData(wallpaper, DEFAULT_DISPLAY);
Christopher Tatebe132e62016-02-10 12:59:49 -08002964 }
2965 }
Xiaohui Chenac531942015-05-13 13:20:52 -07002966 }
2967 return wallpaper;
2968 }
2969
Christopher Tated7faf532016-02-25 12:43:38 -08002970 private void loadSettingsLocked(int userId, boolean keepDimensionHints) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002971 JournaledFile journal = makeJournaledFile(userId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002972 FileInputStream stream = null;
2973 File file = journal.chooseForRead();
Christopher Tate9f224432017-08-01 16:32:49 -07002974
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002975 WallpaperData wallpaper = mWallpaperMap.get(userId);
2976 if (wallpaper == null) {
Christopher Tate9f224432017-08-01 16:32:49 -07002977 // Do this once per boot
2978 migrateFromOld();
2979
Christopher Tatebe132e62016-02-10 12:59:49 -08002980 wallpaper = new WallpaperData(userId, WALLPAPER, WALLPAPER_CROP);
Christopher Tated7faf532016-02-25 12:43:38 -08002981 wallpaper.allowBackup = true;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002982 mWallpaperMap.put(userId, wallpaper);
Christopher Tate41297ff2016-03-10 16:46:15 -08002983 if (!wallpaper.cropExists()) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07002984 if (wallpaper.sourceExists()) {
2985 generateCrop(wallpaper);
2986 } else {
2987 Slog.i(TAG, "No static wallpaper imagery; defaults will be shown");
2988 }
Christopher Tate41297ff2016-03-10 16:46:15 -08002989 }
wilsonshiha282bf72018-11-30 12:48:05 +08002990 initializeFallbackWallpaper();
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002991 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002992 boolean success = false;
wilsonshiha282bf72018-11-30 12:48:05 +08002993 final DisplayData wpdData = getDisplayDataOrCreate(DEFAULT_DISPLAY);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002994 try {
2995 stream = new FileInputStream(file);
2996 XmlPullParser parser = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01002997 parser.setInput(stream, StandardCharsets.UTF_8.name());
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002998
2999 int type;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003000 do {
3001 type = parser.next();
3002 if (type == XmlPullParser.START_TAG) {
3003 String tag = parser.getName();
3004 if ("wp".equals(tag)) {
Christopher Tatebe132e62016-02-10 12:59:49 -08003005 // Common to system + lock wallpapers
Christopher Tated7faf532016-02-25 12:43:38 -08003006 parseWallpaperAttributes(parser, wallpaper, keepDimensionHints);
Christopher Tatead3c2592016-01-20 18:13:17 -08003007
Christopher Tatebe132e62016-02-10 12:59:49 -08003008 // A system wallpaper might also be a live wallpaper
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07003009 String comp = parser.getAttributeValue(null, "component");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003010 wallpaper.nextWallpaperComponent = comp != null
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07003011 ? ComponentName.unflattenFromString(comp)
3012 : null;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003013 if (wallpaper.nextWallpaperComponent == null
3014 || "android".equals(wallpaper.nextWallpaperComponent
3015 .getPackageName())) {
Justin Koh29c30162014-09-05 17:10:10 -07003016 wallpaper.nextWallpaperComponent = mImageWallpaper;
Dianne Hackborn9ea31632011-08-05 14:43:50 -07003017 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01003018
Mike Clerona428b2c2009-11-15 22:53:08 -08003019 if (DEBUG) {
wilsonshih81e10a72018-11-15 10:54:21 +08003020 Slog.v(TAG, "mWidth:" + wpdData.mWidth);
3021 Slog.v(TAG, "mHeight:" + wpdData.mHeight);
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003022 Slog.v(TAG, "cropRect:" + wallpaper.cropHint);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07003023 Slog.v(TAG, "primaryColors:" + wallpaper.primaryColors);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003024 Slog.v(TAG, "mName:" + wallpaper.name);
3025 Slog.v(TAG, "mNextWallpaperComponent:"
3026 + wallpaper.nextWallpaperComponent);
Mike Clerona428b2c2009-11-15 22:53:08 -08003027 }
Christopher Tatebe132e62016-02-10 12:59:49 -08003028 } else if ("kwp".equals(tag)) {
3029 // keyguard-specific wallpaper for this user
3030 WallpaperData lockWallpaper = mLockWallpaperMap.get(userId);
3031 if (lockWallpaper == null) {
3032 lockWallpaper = new WallpaperData(userId,
3033 WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP);
3034 mLockWallpaperMap.put(userId, lockWallpaper);
3035 }
Christopher Tated7faf532016-02-25 12:43:38 -08003036 parseWallpaperAttributes(parser, lockWallpaper, false);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003037 }
3038 }
3039 } while (type != XmlPullParser.END_DOCUMENT);
3040 success = true;
Dianne Hackborn13579ed2012-11-28 18:05:36 -08003041 } catch (FileNotFoundException e) {
3042 Slog.w(TAG, "no current wallpaper -- first boot?");
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003043 } catch (NullPointerException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003044 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003045 } catch (NumberFormatException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003046 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003047 } catch (XmlPullParserException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003048 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003049 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003050 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003051 } catch (IndexOutOfBoundsException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003052 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003053 }
Christopher Tatead3c2592016-01-20 18:13:17 -08003054 IoUtils.closeQuietly(stream);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003055
3056 if (!success) {
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003057 wallpaper.cropHint.set(0, 0, 0, 0);
wilsonshih81e10a72018-11-15 10:54:21 +08003058 wpdData.mPadding.set(0, 0, 0, 0);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003059 wallpaper.name = "";
Adrian Roosc28e3a92016-04-14 10:47:52 -07003060
3061 mLockWallpaperMap.remove(userId);
Christopher Tatead3c2592016-01-20 18:13:17 -08003062 } else {
3063 if (wallpaper.wallpaperId <= 0) {
3064 wallpaper.wallpaperId = makeWallpaperIdLocked();
3065 if (DEBUG) {
3066 Slog.w(TAG, "Didn't set wallpaper id in loadSettingsLocked(" + userId
3067 + "); now " + wallpaper.wallpaperId);
3068 }
3069 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003070 }
Dianne Hackborn44bc17c2011-04-20 18:18:51 -07003071
wilsonshihd9173df2018-11-29 11:52:15 +08003072 ensureSaneWallpaperDisplaySize(wpdData, DEFAULT_DISPLAY);
wilsonshih81e10a72018-11-15 10:54:21 +08003073 ensureSaneWallpaperData(wallpaper, DEFAULT_DISPLAY);
Adrian Roosc28e3a92016-04-14 10:47:52 -07003074 WallpaperData lockWallpaper = mLockWallpaperMap.get(userId);
3075 if (lockWallpaper != null) {
wilsonshih81e10a72018-11-15 10:54:21 +08003076 ensureSaneWallpaperData(lockWallpaper, DEFAULT_DISPLAY);
Adrian Roosc28e3a92016-04-14 10:47:52 -07003077 }
3078 }
3079
wilsonshiha282bf72018-11-30 12:48:05 +08003080 private void initializeFallbackWallpaper() {
3081 if (mFallbackWallpaper == null) {
3082 if (DEBUG) Slog.d(TAG, "Initialize fallback wallpaper");
3083 mFallbackWallpaper = new WallpaperData(
3084 UserHandle.USER_SYSTEM, WALLPAPER, WALLPAPER_CROP);
3085 mFallbackWallpaper.allowBackup = false;
3086 mFallbackWallpaper.wallpaperId = makeWallpaperIdLocked();
3087 bindWallpaperComponentLocked(mImageWallpaper, true, false, mFallbackWallpaper, null);
3088 }
3089 }
3090
wilsonshih81e10a72018-11-15 10:54:21 +08003091 private void ensureSaneWallpaperData(WallpaperData wallpaper, int displayId) {
wilsonshiha282bf72018-11-30 12:48:05 +08003092 final DisplayData size = getDisplayDataOrCreate(displayId);
wilsonshih81e10a72018-11-15 10:54:21 +08003093
3094 if (displayId == DEFAULT_DISPLAY) {
3095 // crop, if not previously specified
3096 if (wallpaper.cropHint.width() <= 0
3097 || wallpaper.cropHint.height() <= 0) {
3098 wallpaper.cropHint.set(0, 0, size.mWidth, size.mHeight);
3099 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003100 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003101 }
3102
Christopher Tated7faf532016-02-25 12:43:38 -08003103 private void parseWallpaperAttributes(XmlPullParser parser, WallpaperData wallpaper,
3104 boolean keepDimensionHints) {
Christopher Tatebe132e62016-02-10 12:59:49 -08003105 final String idString = parser.getAttributeValue(null, "id");
3106 if (idString != null) {
3107 final int id = wallpaper.wallpaperId = Integer.parseInt(idString);
3108 if (id > mWallpaperId) {
3109 mWallpaperId = id;
3110 }
3111 } else {
3112 wallpaper.wallpaperId = makeWallpaperIdLocked();
3113 }
3114
wilsonshiha282bf72018-11-30 12:48:05 +08003115 final DisplayData wpData = getDisplayDataOrCreate(DEFAULT_DISPLAY);
wilsonshih81e10a72018-11-15 10:54:21 +08003116
Christopher Tated7faf532016-02-25 12:43:38 -08003117 if (!keepDimensionHints) {
wilsonshih81e10a72018-11-15 10:54:21 +08003118 wpData.mWidth = Integer.parseInt(parser.getAttributeValue(null, "width"));
3119 wpData.mHeight = Integer.parseInt(parser.getAttributeValue(null, "height"));
Christopher Tated7faf532016-02-25 12:43:38 -08003120 }
Christopher Tatebe132e62016-02-10 12:59:49 -08003121 wallpaper.cropHint.left = getAttributeInt(parser, "cropLeft", 0);
3122 wallpaper.cropHint.top = getAttributeInt(parser, "cropTop", 0);
3123 wallpaper.cropHint.right = getAttributeInt(parser, "cropRight", 0);
3124 wallpaper.cropHint.bottom = getAttributeInt(parser, "cropBottom", 0);
wilsonshih81e10a72018-11-15 10:54:21 +08003125 wpData.mPadding.left = getAttributeInt(parser, "paddingLeft", 0);
3126 wpData.mPadding.top = getAttributeInt(parser, "paddingTop", 0);
3127 wpData.mPadding.right = getAttributeInt(parser, "paddingRight", 0);
3128 wpData.mPadding.bottom = getAttributeInt(parser, "paddingBottom", 0);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07003129 int colorsCount = getAttributeInt(parser, "colorsCount", 0);
3130 if (colorsCount > 0) {
Lucas Dupin84b89d92017-05-09 12:16:19 -07003131 Color primary = null, secondary = null, tertiary = null;
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07003132 for (int i = 0; i < colorsCount; i++) {
Lucas Dupin84b89d92017-05-09 12:16:19 -07003133 Color color = Color.valueOf(getAttributeInt(parser, "colorValue" + i, 0));
3134 if (i == 0) {
3135 primary = color;
3136 } else if (i == 1) {
3137 secondary = color;
3138 } else if (i == 2) {
3139 tertiary = color;
3140 } else {
3141 break;
3142 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07003143 }
Lucas Dupin84b89d92017-05-09 12:16:19 -07003144 int colorHints = getAttributeInt(parser, "colorHints", 0);
3145 wallpaper.primaryColors = new WallpaperColors(primary, secondary, tertiary, colorHints);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07003146 }
Christopher Tatebe132e62016-02-10 12:59:49 -08003147 wallpaper.name = parser.getAttributeValue(null, "name");
Christopher Tated7faf532016-02-25 12:43:38 -08003148 wallpaper.allowBackup = "true".equals(parser.getAttributeValue(null, "backup"));
Christopher Tatebe132e62016-02-10 12:59:49 -08003149 }
3150
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07003151 // Called by SystemBackupAgent after files are restored to disk.
Amith Yamasani09e9cdc2013-11-06 14:54:50 -08003152 public void settingsRestored() {
3153 // Verify caller is the system
3154 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
3155 throw new RuntimeException("settingsRestored() can only be called from the system process");
3156 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003157 // TODO: If necessary, make it work for secondary users as well. This currently assumes
3158 // restores only to the primary user
Joe Onorato8a9b2202010-02-26 18:56:32 -08003159 if (DEBUG) Slog.v(TAG, "settingsRestored");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003160 WallpaperData wallpaper = null;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003161 boolean success = false;
3162 synchronized (mLock) {
Christopher Tated7faf532016-02-25 12:43:38 -08003163 loadSettingsLocked(UserHandle.USER_SYSTEM, false);
Christopher Tatedb27b842016-02-25 14:39:17 -08003164 wallpaper = mWallpaperMap.get(UserHandle.USER_SYSTEM);
Christopher Tatead3c2592016-01-20 18:13:17 -08003165 wallpaper.wallpaperId = makeWallpaperIdLocked(); // always bump id at restore
Christopher Tated7faf532016-02-25 12:43:38 -08003166 wallpaper.allowBackup = true; // by definition if it was restored
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003167 if (wallpaper.nextWallpaperComponent != null
Justin Koh29c30162014-09-05 17:10:10 -07003168 && !wallpaper.nextWallpaperComponent.equals(mImageWallpaper)) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003169 if (!bindWallpaperComponentLocked(wallpaper.nextWallpaperComponent, false, false,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07003170 wallpaper, null)) {
Christopher Tatee3ab4d02009-12-16 14:03:31 -08003171 // No such live wallpaper or other failure; fall back to the default
3172 // live wallpaper (since the profile being restored indicated that the
3173 // user had selected a live rather than static one).
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07003174 bindWallpaperComponentLocked(null, false, false, wallpaper, null);
Christopher Tatee3ab4d02009-12-16 14:03:31 -08003175 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003176 success = true;
3177 } else {
Mike Clerona428b2c2009-11-15 22:53:08 -08003178 // If there's a wallpaper name, we use that. If that can't be loaded, then we
3179 // use the default.
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003180 if ("".equals(wallpaper.name)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003181 if (DEBUG) Slog.v(TAG, "settingsRestored: name is empty");
Mike Clerona428b2c2009-11-15 22:53:08 -08003182 success = true;
3183 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003184 if (DEBUG) Slog.v(TAG, "settingsRestored: attempting to restore named resource");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003185 success = restoreNamedResourceLocked(wallpaper);
Mike Clerona428b2c2009-11-15 22:53:08 -08003186 }
Christopher Tatead3c2592016-01-20 18:13:17 -08003187 if (DEBUG) Slog.v(TAG, "settingsRestored: success=" + success
3188 + " id=" + wallpaper.wallpaperId);
Mike Clerona428b2c2009-11-15 22:53:08 -08003189 if (success) {
wilsonshih81e10a72018-11-15 10:54:21 +08003190 generateCrop(wallpaper); // based on the new image + metadata
Christopher Tate41297ff2016-03-10 16:46:15 -08003191 bindWallpaperComponentLocked(wallpaper.nextWallpaperComponent, true, false,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07003192 wallpaper, null);
Mike Clerona428b2c2009-11-15 22:53:08 -08003193 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003194 }
3195 }
3196
3197 if (!success) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003198 Slog.e(TAG, "Failed to restore wallpaper: '" + wallpaper.name + "'");
3199 wallpaper.name = "";
Christopher Tatedb27b842016-02-25 14:39:17 -08003200 getWallpaperDir(UserHandle.USER_SYSTEM).delete();
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003201 }
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07003202
3203 synchronized (mLock) {
Christopher Tatedb27b842016-02-25 14:39:17 -08003204 saveSettingsLocked(UserHandle.USER_SYSTEM);
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07003205 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003206 }
3207
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003208 // Restore the named resource bitmap to both source + crop files
wilsonshiha282bf72018-11-30 12:48:05 +08003209 private boolean restoreNamedResourceLocked(WallpaperData wallpaper) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003210 if (wallpaper.name.length() > 4 && "res:".equals(wallpaper.name.substring(0, 4))) {
3211 String resName = wallpaper.name.substring(4);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003212
3213 String pkg = null;
3214 int colon = resName.indexOf(':');
3215 if (colon > 0) {
3216 pkg = resName.substring(0, colon);
3217 }
3218
3219 String ident = null;
3220 int slash = resName.lastIndexOf('/');
3221 if (slash > 0) {
3222 ident = resName.substring(slash+1);
3223 }
3224
3225 String type = null;
3226 if (colon > 0 && slash > 0 && (slash-colon) > 1) {
3227 type = resName.substring(colon+1, slash);
3228 }
3229
3230 if (pkg != null && ident != null && type != null) {
3231 int resId = -1;
3232 InputStream res = null;
3233 FileOutputStream fos = null;
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003234 FileOutputStream cos = null;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003235 try {
3236 Context c = mContext.createPackageContext(pkg, Context.CONTEXT_RESTRICTED);
3237 Resources r = c.getResources();
3238 resId = r.getIdentifier(resName, null, null);
3239 if (resId == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003240 Slog.e(TAG, "couldn't resolve identifier pkg=" + pkg + " type=" + type
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003241 + " ident=" + ident);
3242 return false;
3243 }
3244
3245 res = r.openRawResource(resId);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003246 if (wallpaper.wallpaperFile.exists()) {
3247 wallpaper.wallpaperFile.delete();
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003248 wallpaper.cropFile.delete();
Dianne Hackborn1afd1c92010-03-18 22:47:17 -07003249 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003250 fos = new FileOutputStream(wallpaper.wallpaperFile);
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003251 cos = new FileOutputStream(wallpaper.cropFile);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003252
3253 byte[] buffer = new byte[32768];
3254 int amt;
3255 while ((amt=res.read(buffer)) > 0) {
3256 fos.write(buffer, 0, amt);
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003257 cos.write(buffer, 0, amt);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003258 }
3259 // mWallpaperObserver will notice the close and send the change broadcast
3260
Joe Onorato8a9b2202010-02-26 18:56:32 -08003261 Slog.v(TAG, "Restored wallpaper: " + resName);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003262 return true;
3263 } catch (NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003264 Slog.e(TAG, "Package name " + pkg + " not found");
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003265 } catch (Resources.NotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003266 Slog.e(TAG, "Resource not found: " + resId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003267 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003268 Slog.e(TAG, "IOException while restoring wallpaper ", e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003269 } finally {
Christopher Tatead3c2592016-01-20 18:13:17 -08003270 IoUtils.closeQuietly(res);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003271 if (fos != null) {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07003272 FileUtils.sync(fos);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003273 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003274 if (cos != null) {
3275 FileUtils.sync(cos);
3276 }
3277 IoUtils.closeQuietly(fos);
3278 IoUtils.closeQuietly(cos);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003279 }
3280 }
3281 }
3282 return false;
3283 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003284
Dianne Hackborneb034652009-09-07 00:49:58 -07003285 @Override
3286 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06003287 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Dianne Hackborneb034652009-09-07 00:49:58 -07003288
3289 synchronized (mLock) {
Adrian Roosc28e3a92016-04-14 10:47:52 -07003290 pw.println("System wallpaper state:");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003291 for (int i = 0; i < mWallpaperMap.size(); i++) {
3292 WallpaperData wallpaper = mWallpaperMap.valueAt(i);
Christopher Tatead3c2592016-01-20 18:13:17 -08003293 pw.print(" User "); pw.print(wallpaper.userId);
wilsonshiha282bf72018-11-30 12:48:05 +08003294 pw.print(": id="); pw.println(wallpaper.wallpaperId);
3295 pw.println(" Display state:");
3296 forEachDisplayData(wpSize -> {
wilsonshih81e10a72018-11-15 10:54:21 +08003297 pw.print(" displayId=");
3298 pw.println(wpSize.mDisplayId);
3299 pw.print(" mWidth=");
3300 pw.print(wpSize.mWidth);
3301 pw.print(" mHeight=");
3302 pw.println(wpSize.mHeight);
3303 pw.print(" mPadding="); pw.println(wpSize.mPadding);
3304 });
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003305 pw.print(" mCropHint="); pw.println(wallpaper.cropHint);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07003306 pw.print(" mName="); pw.println(wallpaper.name);
Bryan Mawhinney0fa54f42017-07-06 17:09:37 +01003307 pw.print(" mAllowBackup="); pw.println(wallpaper.allowBackup);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07003308 pw.print(" mWallpaperComponent="); pw.println(wallpaper.wallpaperComponent);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003309 if (wallpaper.connection != null) {
3310 WallpaperConnection conn = wallpaper.connection;
3311 pw.print(" Wallpaper connection ");
3312 pw.print(conn);
3313 pw.println(":");
3314 if (conn.mInfo != null) {
3315 pw.print(" mInfo.component=");
3316 pw.println(conn.mInfo.getComponent());
3317 }
wilsonshihde93f492018-11-01 21:23:40 +08003318 conn.forEachDisplayConnector(connector -> {
wilsonshiha282bf72018-11-30 12:48:05 +08003319 pw.print(" mDisplayId=");
wilsonshihde93f492018-11-01 21:23:40 +08003320 pw.println(connector.mDisplayId);
wilsonshiha282bf72018-11-30 12:48:05 +08003321 pw.print(" mToken=");
wilsonshihde93f492018-11-01 21:23:40 +08003322 pw.println(connector.mToken);
wilsonshiha282bf72018-11-30 12:48:05 +08003323 pw.print(" mEngine=");
wilsonshihde93f492018-11-01 21:23:40 +08003324 pw.println(connector.mEngine);
3325 });
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003326 pw.print(" mService=");
3327 pw.println(conn.mService);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003328 pw.print(" mLastDiedTime=");
3329 pw.println(wallpaper.lastDiedTime - SystemClock.uptimeMillis());
3330 }
Dianne Hackborneb034652009-09-07 00:49:58 -07003331 }
Adrian Roosc28e3a92016-04-14 10:47:52 -07003332 pw.println("Lock wallpaper state:");
3333 for (int i = 0; i < mLockWallpaperMap.size(); i++) {
3334 WallpaperData wallpaper = mLockWallpaperMap.valueAt(i);
3335 pw.print(" User "); pw.print(wallpaper.userId);
wilsonshih81e10a72018-11-15 10:54:21 +08003336 pw.print(": id="); pw.println(wallpaper.wallpaperId);
Adrian Roosc28e3a92016-04-14 10:47:52 -07003337 pw.print(" mCropHint="); pw.println(wallpaper.cropHint);
Adrian Roosc28e3a92016-04-14 10:47:52 -07003338 pw.print(" mName="); pw.println(wallpaper.name);
Bryan Mawhinney0fa54f42017-07-06 17:09:37 +01003339 pw.print(" mAllowBackup="); pw.println(wallpaper.allowBackup);
Adrian Roosc28e3a92016-04-14 10:47:52 -07003340 }
wilsonshiha282bf72018-11-30 12:48:05 +08003341 pw.println("Fallback wallpaper state:");
3342 pw.print(" User "); pw.print(mFallbackWallpaper.userId);
3343 pw.print(": id="); pw.println(mFallbackWallpaper.wallpaperId);
3344 pw.print(" mCropHint="); pw.println(mFallbackWallpaper.cropHint);
3345 pw.print(" mName="); pw.println(mFallbackWallpaper.name);
3346 pw.print(" mAllowBackup="); pw.println(mFallbackWallpaper.allowBackup);
3347 if (mFallbackWallpaper.connection != null) {
3348 WallpaperConnection conn = mFallbackWallpaper.connection;
3349 pw.print(" Fallback Wallpaper connection ");
3350 pw.print(conn);
3351 pw.println(":");
3352 if (conn.mInfo != null) {
3353 pw.print(" mInfo.component=");
3354 pw.println(conn.mInfo.getComponent());
3355 }
3356 conn.forEachDisplayConnector(connector -> {
3357 pw.print(" mDisplayId=");
3358 pw.println(connector.mDisplayId);
3359 pw.print(" mToken=");
3360 pw.println(connector.mToken);
3361 pw.print(" mEngine=");
3362 pw.println(connector.mEngine);
3363 });
3364 pw.print(" mService=");
3365 pw.println(conn.mService);
3366 pw.print(" mLastDiedTime=");
3367 pw.println(mFallbackWallpaper.lastDiedTime - SystemClock.uptimeMillis());
3368 }
Dianne Hackborneb034652009-09-07 00:49:58 -07003369 }
3370 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003371}