blob: b0f1e5d69be4006f3c4e07d2c3dc308d9eeb8e22 [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();
wilsonshih0d5792e2019-07-04 11:23:54 +08001175 if (displayId == DEFAULT_DISPLAY) {
1176 return true;
1177 }
1178
1179 final long ident = Binder.clearCallingIdentity();
1180 try {
1181 return mWindowManagerInternal.shouldShowSystemDecorOnDisplay(displayId);
1182 } finally {
1183 Binder.restoreCallingIdentity(ident);
1184 }
wilsonshihde93f492018-11-01 21:23:40 +08001185 }
1186
1187 void forEachDisplayConnector(Consumer<DisplayConnector> action) {
1188 for (int i = mDisplayConnector.size() - 1; i >= 0; i--) {
wilsonshih81e10a72018-11-15 10:54:21 +08001189 final DisplayConnector connector = mDisplayConnector.valueAt(i);
wilsonshihde93f492018-11-01 21:23:40 +08001190 action.accept(connector);
1191 }
1192 }
1193
wilsonshih81e10a72018-11-15 10:54:21 +08001194 int getConnectedEngineSize() {
1195 int engineSize = 0;
1196 for (int i = mDisplayConnector.size() - 1; i >= 0; i--) {
1197 final DisplayConnector connector = mDisplayConnector.valueAt(i);
1198 if (connector.mEngine != null) engineSize++;
1199 }
1200 return engineSize;
1201 }
1202
wilsonshihde93f492018-11-01 21:23:40 +08001203 DisplayConnector getDisplayConnectorOrCreate(int displayId) {
1204 DisplayConnector connector = mDisplayConnector.get(displayId);
1205 if (connector == null) {
1206 final Display display = mDisplayManager.getDisplay(displayId);
1207 if (isUsableDisplay(display)) {
1208 connector = new DisplayConnector(displayId);
1209 mDisplayConnector.append(displayId, connector);
1210 }
1211 }
1212 return connector;
1213 }
1214
wilsonshiha282bf72018-11-30 12:48:05 +08001215 boolean containsDisplay(int displayId) {
1216 return mDisplayConnector.get(displayId) != null;
1217 }
1218
wilsonshihde93f492018-11-01 21:23:40 +08001219 void removeDisplayConnector(int displayId) {
1220 final DisplayConnector connector = mDisplayConnector.get(displayId);
1221 if (connector != null) {
1222 mDisplayConnector.remove(displayId);
1223 }
Dianne Hackborneb034652009-09-07 00:49:58 -07001224 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001225
1226 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001227 public void onServiceConnected(ComponentName name, IBinder service) {
1228 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001229 if (mWallpaper.connection == this) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001230 mService = IWallpaperService.Stub.asInterface(service);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001231 attachServiceLocked(this, mWallpaper);
Dianne Hackborneb034652009-09-07 00:49:58 -07001232 // XXX should probably do saveSettingsLocked() later
1233 // when we have an engine, but I'm not sure about
1234 // locking there and anyway we always need to be able to
1235 // recover if there is something wrong.
wilsonshiha282bf72018-11-30 12:48:05 +08001236 if (!mWallpaper.equals(mFallbackWallpaper)) {
1237 saveSettingsLocked(mWallpaper.userId);
1238 }
Adrian Roosc3f915e2016-09-06 11:40:53 -07001239 FgThread.getHandler().removeCallbacks(mResetRunnable);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001240 }
1241 }
1242 }
1243
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001244 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001245 public void onServiceDisconnected(ComponentName name) {
1246 synchronized (mLock) {
Christopher Tatec349e59f2017-05-05 17:37:43 -07001247 Slog.w(TAG, "Wallpaper service gone: " + name);
1248 if (!Objects.equals(name, mWallpaper.wallpaperComponent)) {
1249 Slog.e(TAG, "Does not match expected wallpaper component "
1250 + mWallpaper.wallpaperComponent);
1251 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001252 mService = null;
wilsonshihde93f492018-11-01 21:23:40 +08001253 forEachDisplayConnector(connector -> connector.mEngine = null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001254 if (mWallpaper.connection == this) {
Christopher Tatec349e59f2017-05-05 17:37:43 -07001255 // There is an inherent ordering race between this callback and the
1256 // package monitor that receives notice that a package is being updated,
1257 // so we cannot quite trust at this moment that we know for sure that
1258 // this is not an update. If we think this is a genuine non-update
1259 // wallpaper outage, we do our "wait for reset" work as a continuation,
1260 // a short time in the future, specifically to allow any pending package
1261 // update message on this same looper thread to be processed.
1262 if (!mWallpaper.wallpaperUpdating) {
1263 mContext.getMainThreadHandler().postDelayed(() -> processDisconnect(this),
1264 1000);
1265 }
1266 }
1267 }
1268 }
1269
Tetsutoki Shiozawa06919212018-02-02 14:18:43 +09001270 public void scheduleTimeoutLocked() {
1271 // If we didn't reset it right away, do so after we couldn't connect to
1272 // it for an extended amount of time to avoid having a black wallpaper.
1273 final Handler fgHandler = FgThread.getHandler();
1274 fgHandler.removeCallbacks(mResetRunnable);
1275 fgHandler.postDelayed(mResetRunnable, WALLPAPER_RECONNECT_TIMEOUT_MS);
1276 if (DEBUG_LIVE) {
wilsonshihde93f492018-11-01 21:23:40 +08001277 Slog.i(TAG,
1278 "Started wallpaper reconnect timeout for " + mWallpaper.wallpaperComponent);
Tetsutoki Shiozawa06919212018-02-02 14:18:43 +09001279 }
1280 }
1281
Christopher Tatec349e59f2017-05-05 17:37:43 -07001282 private void processDisconnect(final ServiceConnection connection) {
1283 synchronized (mLock) {
1284 // The wallpaper disappeared. If this isn't a system-default one, track
1285 // crashes and fall back to default if it continues to misbehave.
1286 if (connection == mWallpaper.connection) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001287 final ComponentName wpService = mWallpaper.wallpaperComponent;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001288 if (!mWallpaper.wallpaperUpdating
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001289 && mWallpaper.userId == mCurrentUserId
1290 && !Objects.equals(mDefaultWallpaperComponent, wpService)
1291 && !Objects.equals(mImageWallpaper, wpService)) {
Selim Cinekebebadb2014-03-05 22:17:26 +01001292 // There is a race condition which causes
1293 // {@link #mWallpaper.wallpaperUpdating} to be false even if it is
1294 // currently updating since the broadcast notifying us is async.
1295 // This race is overcome by the general rule that we only reset the
1296 // wallpaper if its service was shut down twice
1297 // during {@link #MIN_WALLPAPER_CRASH_TIME} millis.
1298 if (mWallpaper.lastDiedTime != 0
1299 && mWallpaper.lastDiedTime + MIN_WALLPAPER_CRASH_TIME
Christopher Tatec349e59f2017-05-05 17:37:43 -07001300 > SystemClock.uptimeMillis()) {
Selim Cinekebebadb2014-03-05 22:17:26 +01001301 Slog.w(TAG, "Reverting to built-in wallpaper!");
Christopher Tateedf7d042016-03-29 18:24:25 -07001302 clearWallpaperLocked(true, FLAG_SYSTEM, mWallpaper.userId, null);
Selim Cinekebebadb2014-03-05 22:17:26 +01001303 } else {
1304 mWallpaper.lastDiedTime = SystemClock.uptimeMillis();
Adrian Roosc3f915e2016-09-06 11:40:53 -07001305
Tetsutoki Shiozawa06919212018-02-02 14:18:43 +09001306 clearWallpaperComponentLocked(mWallpaper);
1307 if (bindWallpaperComponentLocked(
1308 wpService, false, false, mWallpaper, null)) {
1309 mWallpaper.connection.scheduleTimeoutLocked();
1310 } else {
1311 Slog.w(TAG, "Reverting to built-in wallpaper!");
1312 clearWallpaperLocked(true, FLAG_SYSTEM, mWallpaper.userId, null);
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001313 }
Selim Cinekebebadb2014-03-05 22:17:26 +01001314 }
Christopher Tatec349e59f2017-05-05 17:37:43 -07001315 final String flattened = wpService.flattenToString();
Filip Gruszczynski5dcc3ac2014-10-13 15:51:39 -07001316 EventLog.writeEvent(EventLogTags.WP_WALLPAPER_CRASHED,
Filip Gruszczynski5a589432014-10-14 12:06:06 -07001317 flattened.substring(0, Math.min(flattened.length(),
1318 MAX_WALLPAPER_COMPONENT_LOG_LENGTH)));
Dianne Hackborn0cd48872009-08-13 18:51:59 -07001319 }
Christopher Tatec349e59f2017-05-05 17:37:43 -07001320 } else {
1321 if (DEBUG_LIVE) {
1322 Slog.i(TAG, "Wallpaper changed during disconnect tracking; ignoring");
1323 }
Dianne Hackborn0cd48872009-08-13 18:51:59 -07001324 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001325 }
1326 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001327
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07001328 /**
1329 * Called by a live wallpaper if its colors have changed.
1330 * @param primaryColors representation of wallpaper primary colors
wilsonshih36597d42018-12-05 18:56:39 +08001331 * @param displayId for which display
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07001332 */
1333 @Override
wilsonshih36597d42018-12-05 18:56:39 +08001334 public void onWallpaperColorsChanged(WallpaperColors primaryColors, int displayId) {
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07001335 int which;
1336 synchronized (mLock) {
1337 // Do not broadcast changes on ImageWallpaper since it's handled
1338 // internally by this class.
1339 if (mImageWallpaper.equals(mWallpaper.wallpaperComponent)) {
1340 return;
1341 }
1342
1343 mWallpaper.primaryColors = primaryColors;
1344
1345 // Live wallpapers always are system wallpapers.
1346 which = FLAG_SYSTEM;
wilsonshih36597d42018-12-05 18:56:39 +08001347 // It's also the lock screen wallpaper when we don't have a bitmap in there.
1348 if (displayId == DEFAULT_DISPLAY) {
1349 final WallpaperData lockedWallpaper = mLockWallpaperMap.get(mWallpaper.userId);
1350 if (lockedWallpaper == null) {
1351 which |= FLAG_LOCK;
1352 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07001353 }
1354 }
1355 if (which != 0) {
wilsonshih36597d42018-12-05 18:56:39 +08001356 notifyWallpaperColorsChangedOnDisplay(mWallpaper, which, displayId);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07001357 }
1358 }
1359
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001360 @Override
wilsonshihde93f492018-11-01 21:23:40 +08001361 public void attachEngine(IWallpaperEngine engine, int displayId) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001362 synchronized (mLock) {
wilsonshihde93f492018-11-01 21:23:40 +08001363 final DisplayConnector connector = getDisplayConnectorOrCreate(displayId);
1364 if (connector == null) {
Michael Wright5203a8b2013-10-03 14:16:42 -07001365 try {
wilsonshihde93f492018-11-01 21:23:40 +08001366 engine.destroy();
Michael Wright5203a8b2013-10-03 14:16:42 -07001367 } catch (RemoteException e) {
wilsonshihde93f492018-11-01 21:23:40 +08001368 Slog.w(TAG, "Failed to destroy engine", e);
Michael Wright5203a8b2013-10-03 14:16:42 -07001369 }
wilsonshihde93f492018-11-01 21:23:40 +08001370 return;
Michael Wright5203a8b2013-10-03 14:16:42 -07001371 }
wilsonshihde93f492018-11-01 21:23:40 +08001372 connector.mEngine = engine;
1373 connector.ensureStatusHandled();
1374
1375 // TODO(multi-display) TBD.
1376 if (mInfo != null && mInfo.supportsAmbientMode() && displayId == DEFAULT_DISPLAY) {
Dianne Hackborn067e5f62014-09-07 23:14:30 -07001377 try {
Lucas Dupin4c8c3272018-11-06 17:47:48 -08001378 connector.mEngine.setInAmbientMode(mInAmbientMode, 0L /* duration */);
Lucas Dupin7517b5d2017-08-22 12:51:25 -07001379 } catch (RemoteException e) {
1380 Slog.w(TAG, "Failed to set ambient mode state", e);
1381 }
1382 }
wilsonshih36597d42018-12-05 18:56:39 +08001383 try {
1384 // This will trigger onComputeColors in the wallpaper engine.
1385 // It's fine to be locked in here since the binder is oneway.
1386 connector.mEngine.requestWallpaperColors();
1387 } catch (RemoteException e) {
1388 Slog.w(TAG, "Failed to request wallpaper colors", e);
Lucas Dupin50ba9912017-07-14 11:55:05 -07001389 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001390 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001391 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001392
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001393 @Override
1394 public void engineShown(IWallpaperEngine engine) {
1395 synchronized (mLock) {
1396 if (mReply != null) {
1397 long ident = Binder.clearCallingIdentity();
1398 try {
1399 mReply.sendResult(null);
1400 } catch (RemoteException e) {
1401 Binder.restoreCallingIdentity(ident);
1402 }
1403 mReply = null;
1404 }
1405 }
1406 }
1407
1408 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001409 public ParcelFileDescriptor setWallpaper(String name) {
1410 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001411 if (mWallpaper.connection == this) {
Christopher Tatead3c2592016-01-20 18:13:17 -08001412 return updateWallpaperBitmapLocked(name, mWallpaper, null);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001413 }
1414 return null;
1415 }
1416 }
1417 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001418
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001419 class MyPackageMonitor extends PackageMonitor {
1420 @Override
1421 public void onPackageUpdateFinished(String packageName, int uid) {
1422 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -07001423 if (mCurrentUserId != getChangingUserId()) {
1424 return;
1425 }
1426 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
1427 if (wallpaper != null) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001428 final ComponentName wpService = wallpaper.wallpaperComponent;
1429 if (wpService != null && wpService.getPackageName().equals(packageName)) {
1430 if (DEBUG_LIVE) {
1431 Slog.i(TAG, "Wallpaper " + wpService + " update has finished");
1432 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001433 wallpaper.wallpaperUpdating = false;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001434 clearWallpaperComponentLocked(wallpaper);
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001435 if (!bindWallpaperComponentLocked(wpService, false, false,
Dianne Hackbornc72fc672012-09-20 13:12:03 -07001436 wallpaper, null)) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001437 Slog.w(TAG, "Wallpaper " + wpService
1438 + " no longer available; reverting to default");
Christopher Tateedf7d042016-03-29 18:24:25 -07001439 clearWallpaperLocked(false, FLAG_SYSTEM, wallpaper.userId, null);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001440 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001441 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001442 }
1443 }
1444 }
1445
1446 @Override
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001447 public void onPackageModified(String packageName) {
1448 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -07001449 if (mCurrentUserId != getChangingUserId()) {
1450 return;
1451 }
1452 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
1453 if (wallpaper != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001454 if (wallpaper.wallpaperComponent == null
1455 || !wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -07001456 return;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001457 }
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001458 doPackagesChangedLocked(true, wallpaper);
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001459 }
1460 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001461 }
1462
1463 @Override
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001464 public void onPackageUpdateStarted(String packageName, int uid) {
1465 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -07001466 if (mCurrentUserId != getChangingUserId()) {
1467 return;
1468 }
1469 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
1470 if (wallpaper != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001471 if (wallpaper.wallpaperComponent != null
1472 && wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001473 if (DEBUG_LIVE) {
1474 Slog.i(TAG, "Wallpaper service " + wallpaper.wallpaperComponent
1475 + " is updating");
1476 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001477 wallpaper.wallpaperUpdating = true;
Adrian Roosc3f915e2016-09-06 11:40:53 -07001478 if (wallpaper.connection != null) {
1479 FgThread.getHandler().removeCallbacks(
1480 wallpaper.connection.mResetRunnable);
1481 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001482 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001483 }
1484 }
1485 }
1486
1487 @Override
1488 public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001489 synchronized (mLock) {
1490 boolean changed = false;
Dianne Hackbornc72fc672012-09-20 13:12:03 -07001491 if (mCurrentUserId != getChangingUserId()) {
1492 return false;
1493 }
1494 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
1495 if (wallpaper != null) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001496 boolean res = doPackagesChangedLocked(doit, wallpaper);
1497 changed |= res;
1498 }
1499 return changed;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001500 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001501 }
1502
1503 @Override
1504 public void onSomePackagesChanged() {
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001505 synchronized (mLock) {
Dianne Hackbornc72fc672012-09-20 13:12:03 -07001506 if (mCurrentUserId != getChangingUserId()) {
1507 return;
1508 }
1509 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
1510 if (wallpaper != null) {
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001511 doPackagesChangedLocked(true, wallpaper);
1512 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001513 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001514 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001515
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001516 boolean doPackagesChangedLocked(boolean doit, WallpaperData wallpaper) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001517 boolean changed = false;
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001518 if (wallpaper.wallpaperComponent != null) {
1519 int change = isPackageDisappearing(wallpaper.wallpaperComponent
1520 .getPackageName());
1521 if (change == PACKAGE_PERMANENT_CHANGE
1522 || change == PACKAGE_TEMPORARY_CHANGE) {
1523 changed = true;
1524 if (doit) {
1525 Slog.w(TAG, "Wallpaper uninstalled, removing: "
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001526 + wallpaper.wallpaperComponent);
Christopher Tateedf7d042016-03-29 18:24:25 -07001527 clearWallpaperLocked(false, FLAG_SYSTEM, wallpaper.userId, null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001528 }
1529 }
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001530 }
1531 if (wallpaper.nextWallpaperComponent != null) {
1532 int change = isPackageDisappearing(wallpaper.nextWallpaperComponent
1533 .getPackageName());
1534 if (change == PACKAGE_PERMANENT_CHANGE
1535 || change == PACKAGE_TEMPORARY_CHANGE) {
1536 wallpaper.nextWallpaperComponent = null;
1537 }
1538 }
1539 if (wallpaper.wallpaperComponent != null
1540 && isPackageModified(wallpaper.wallpaperComponent.getPackageName())) {
1541 try {
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001542 mContext.getPackageManager().getServiceInfo(wallpaper.wallpaperComponent,
1543 PackageManager.MATCH_DIRECT_BOOT_AWARE
1544 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001545 } catch (NameNotFoundException e) {
1546 Slog.w(TAG, "Wallpaper component gone, removing: "
1547 + wallpaper.wallpaperComponent);
Christopher Tateedf7d042016-03-29 18:24:25 -07001548 clearWallpaperLocked(false, FLAG_SYSTEM, wallpaper.userId, null);
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001549 }
1550 }
1551 if (wallpaper.nextWallpaperComponent != null
1552 && isPackageModified(wallpaper.nextWallpaperComponent.getPackageName())) {
1553 try {
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001554 mContext.getPackageManager().getServiceInfo(wallpaper.nextWallpaperComponent,
1555 PackageManager.MATCH_DIRECT_BOOT_AWARE
1556 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
Dianne Hackbornd0d75032012-04-19 23:12:09 -07001557 } catch (NameNotFoundException e) {
1558 wallpaper.nextWallpaperComponent = null;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001559 }
1560 }
1561 return changed;
1562 }
1563 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001564
Dianne Hackborn8cc6a502009-08-05 21:29:42 -07001565 public WallpaperManagerService(Context context) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001566 if (DEBUG) Slog.v(TAG, "WallpaperService startup");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001567 mContext = context;
Christopher Tate762dfd12016-10-10 17:44:48 -07001568 mShuttingDown = false;
Justin Koh29c30162014-09-05 17:10:10 -07001569 mImageWallpaper = ComponentName.unflattenFromString(
1570 context.getResources().getString(R.string.image_wallpaper_component));
Christopher Tate2a6c55f2017-03-31 12:28:30 -07001571 mDefaultWallpaperComponent = WallpaperManager.getDefaultWallpaperComponent(context);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001572 mIWindowManager = IWindowManager.Stub.asInterface(
1573 ServiceManager.getService(Context.WINDOW_SERVICE));
Andrii Kuliandd989612019-02-21 12:13:28 -08001574 mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
Amith Yamasani4e2820c2012-08-28 22:17:23 -07001575 mIPackageManager = AppGlobals.getPackageManager();
Benjamin Franzf3ece362015-02-11 10:51:10 +00001576 mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
wilsonshihde93f492018-11-01 21:23:40 +08001577 mDisplayManager = mContext.getSystemService(DisplayManager.class);
1578 mDisplayManager.registerDisplayListener(mDisplayListener, null /* handler */);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001579 mMonitor = new MyPackageMonitor();
Jaekyun Seokad7d90f2018-04-04 01:57:18 +09001580 mColorsChangedListeners = new SparseArray<>();
wilsonshih643bf132019-02-27 12:49:19 +08001581
1582 LocalServices.addService(WallpaperManagerInternal.class, new LocalService());
1583 }
1584
1585 private final class LocalService extends WallpaperManagerInternal {
1586 @Override
1587 public void onDisplayReady(int displayId) {
1588 onDisplayReadyInternal(displayId);
1589 }
Jaekyun Seokad7d90f2018-04-04 01:57:18 +09001590 }
1591
1592 void initialize() {
1593 mMonitor.register(mContext, null, UserHandle.ALL, true);
Xiaohui Chen233d94c2015-07-30 15:08:00 -07001594 getWallpaperDir(UserHandle.USER_SYSTEM).mkdirs();
Christopher Tatef717b932017-09-11 15:52:54 -07001595
1596 // Initialize state from the persistent store, then guarantee that the
1597 // WallpaperData for the system imagery is instantiated & active, creating
1598 // it from defaults if necessary.
Christopher Tated7faf532016-02-25 12:43:38 -08001599 loadSettingsLocked(UserHandle.USER_SYSTEM, false);
Christopher Tatef717b932017-09-11 15:52:54 -07001600 getWallpaperSafeLocked(UserHandle.USER_SYSTEM, FLAG_SYSTEM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001601 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01001602
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001603 private static File getWallpaperDir(int userId) {
Amith Yamasani61f57372012-08-31 12:12:28 -07001604 return Environment.getUserSystemDirectory(userId);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001605 }
1606
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001607 @Override
1608 protected void finalize() throws Throwable {
1609 super.finalize();
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001610 for (int i = 0; i < mWallpaperMap.size(); i++) {
1611 WallpaperData wallpaper = mWallpaperMap.valueAt(i);
1612 wallpaper.wallpaperObserver.stopWatching();
1613 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001614 }
Amith Yamasani13593602012-03-22 16:16:17 -07001615
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001616 void systemReady() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001617 if (DEBUG) Slog.v(TAG, "systemReady");
Jaekyun Seokad7d90f2018-04-04 01:57:18 +09001618 initialize();
1619
Xiaohui Chen233d94c2015-07-30 15:08:00 -07001620 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.USER_SYSTEM);
Christopher Tate2cdd3f22016-03-14 17:36:16 -07001621 // If we think we're going to be using the system image wallpaper imagery, make
1622 // sure we have something to render
1623 if (mImageWallpaper.equals(wallpaper.nextWallpaperComponent)) {
1624 // No crop file? Make sure we've finished the processing sequence if necessary
1625 if (!wallpaper.cropExists()) {
1626 if (DEBUG) {
1627 Slog.i(TAG, "No crop; regenerating from source");
1628 }
1629 generateCrop(wallpaper);
1630 }
1631 // Still nothing? Fall back to default.
1632 if (!wallpaper.cropExists()) {
1633 if (DEBUG) {
1634 Slog.i(TAG, "Unable to regenerate crop; resetting");
1635 }
Christopher Tateedf7d042016-03-29 18:24:25 -07001636 clearWallpaperLocked(false, FLAG_SYSTEM, UserHandle.USER_SYSTEM, null);
Christopher Tate2cdd3f22016-03-14 17:36:16 -07001637 }
1638 } else {
1639 if (DEBUG) {
1640 Slog.i(TAG, "Nondefault wallpaper component; gracefully ignoring");
1641 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08001642 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001643
Amith Yamasani13593602012-03-22 16:16:17 -07001644 IntentFilter userFilter = new IntentFilter();
Amith Yamasani13593602012-03-22 16:16:17 -07001645 userFilter.addAction(Intent.ACTION_USER_REMOVED);
1646 mContext.registerReceiver(new BroadcastReceiver() {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001647 @Override
Amith Yamasani13593602012-03-22 16:16:17 -07001648 public void onReceive(Context context, Intent intent) {
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001649 final String action = intent.getAction();
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001650 if (Intent.ACTION_USER_REMOVED.equals(action)) {
Amith Yamasani756901d2012-10-12 12:30:07 -07001651 onRemoveUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
1652 UserHandle.USER_NULL));
Amith Yamasani13593602012-03-22 16:16:17 -07001653 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001654 }
Amith Yamasani13593602012-03-22 16:16:17 -07001655 }, userFilter);
Amith Yamasani756901d2012-10-12 12:30:07 -07001656
Christopher Tate762dfd12016-10-10 17:44:48 -07001657 final IntentFilter shutdownFilter = new IntentFilter(Intent.ACTION_SHUTDOWN);
1658 mContext.registerReceiver(new BroadcastReceiver() {
1659 @Override
1660 public void onReceive(Context context, Intent intent) {
1661 if (Intent.ACTION_SHUTDOWN.equals(intent.getAction())) {
1662 if (DEBUG) {
1663 Slog.i(TAG, "Shutting down");
1664 }
1665 synchronized (mLock) {
1666 mShuttingDown = true;
1667 }
1668 }
1669 }
1670 }, shutdownFilter);
1671
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001672 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001673 ActivityManager.getService().registerUserSwitchObserver(
Sudheer Shanka2c4522c2016-08-27 20:53:28 -07001674 new UserSwitchObserver() {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001675 @Override
1676 public void onUserSwitching(int newUserId, IRemoteCallback reply) {
1677 switchUser(newUserId, reply);
1678 }
Fyodor Kupolov0b77ef92016-06-20 17:16:52 -07001679 }, TAG);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001680 } catch (RemoteException e) {
Fyodor Kupolov0b77ef92016-06-20 17:16:52 -07001681 e.rethrowAsRuntimeException();
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001682 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001683 }
1684
Amith Yamasani09e9cdc2013-11-06 14:54:50 -08001685 /** Called by SystemBackupAgent */
1686 public String getName() {
1687 // Verify caller is the system
1688 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
1689 throw new RuntimeException("getName() can only be called from the system process");
1690 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001691 synchronized (mLock) {
1692 return mWallpaperMap.get(0).name;
1693 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001694 }
1695
Christopher Tatebe132e62016-02-10 12:59:49 -08001696 void stopObserver(WallpaperData wallpaper) {
1697 if (wallpaper != null) {
1698 if (wallpaper.wallpaperObserver != null) {
1699 wallpaper.wallpaperObserver.stopWatching();
1700 wallpaper.wallpaperObserver = null;
Amith Yamasani13593602012-03-22 16:16:17 -07001701 }
Amith Yamasani756901d2012-10-12 12:30:07 -07001702 }
1703 }
1704
Christopher Tatebe132e62016-02-10 12:59:49 -08001705 void stopObserversLocked(int userId) {
1706 stopObserver(mWallpaperMap.get(userId));
1707 stopObserver(mLockWallpaperMap.get(userId));
1708 mWallpaperMap.remove(userId);
1709 mLockWallpaperMap.remove(userId);
1710 }
1711
Daichi Hirono4bbf8522017-12-06 10:34:18 +09001712 @Override
1713 public void onBootPhase(int phase) {
1714 if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
1715 systemReady();
1716 } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
1717 switchUser(UserHandle.USER_SYSTEM, null);
1718 }
1719 }
1720
1721 @Override
1722 public void onUnlockUser(final int userId) {
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001723 synchronized (mLock) {
Christopher Tate38a5dc32016-07-20 15:10:18 -07001724 if (mCurrentUserId == userId) {
1725 if (mWaitingForUnlock) {
wilsonshiha47fcc92018-04-26 14:27:38 +08001726 // the desired wallpaper is not direct-boot aware, load it now
1727 final WallpaperData systemWallpaper =
1728 getWallpaperSafeLocked(userId, FLAG_SYSTEM);
1729 switchWallpaper(systemWallpaper, null);
Ahan Wu96dbbb92019-03-29 15:26:22 +08001730 notifyCallbacksLocked(systemWallpaper);
Christopher Tate38a5dc32016-07-20 15:10:18 -07001731 }
Christopher Tate190e8532016-07-11 11:35:34 -07001732
1733 // Make sure that the SELinux labeling of all the relevant files is correct.
1734 // This corrects for mislabeling bugs that might have arisen from move-to
1735 // operations involving the wallpaper files. This isn't timing-critical,
1736 // so we do it in the background to avoid holding up the user unlock operation.
wilsonshiha282bf72018-11-30 12:48:05 +08001737 if (!mUserRestorecon.get(userId)) {
1738 mUserRestorecon.put(userId, true);
Christopher Tate38a5dc32016-07-20 15:10:18 -07001739 Runnable relabeler = new Runnable() {
1740 @Override
1741 public void run() {
1742 final File wallpaperDir = getWallpaperDir(userId);
1743 for (String filename : sPerUserFiles) {
1744 File f = new File(wallpaperDir, filename);
1745 if (f.exists()) {
1746 SELinux.restorecon(f);
1747 }
Christopher Tate190e8532016-07-11 11:35:34 -07001748 }
1749 }
Christopher Tate38a5dc32016-07-20 15:10:18 -07001750 };
1751 BackgroundThread.getHandler().post(relabeler);
1752 }
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001753 }
1754 }
1755 }
1756
Amith Yamasani756901d2012-10-12 12:30:07 -07001757 void onRemoveUser(int userId) {
1758 if (userId < 1) return;
Christopher Tatebe132e62016-02-10 12:59:49 -08001759
1760 final File wallpaperDir = getWallpaperDir(userId);
Amith Yamasani756901d2012-10-12 12:30:07 -07001761 synchronized (mLock) {
Christopher Tatebe132e62016-02-10 12:59:49 -08001762 stopObserversLocked(userId);
1763 for (String filename : sPerUserFiles) {
1764 new File(wallpaperDir, filename).delete();
1765 }
wilsonshiha282bf72018-11-30 12:48:05 +08001766 mUserRestorecon.delete(userId);
Amith Yamasani13593602012-03-22 16:16:17 -07001767 }
1768 }
1769
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001770 void switchUser(int userId, IRemoteCallback reply) {
Lucas Dupin9272d452017-09-14 14:15:42 -07001771 final WallpaperData systemWallpaper;
1772 final WallpaperData lockWallpaper;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001773 synchronized (mLock) {
Jaekyun Seokad7d90f2018-04-04 01:57:18 +09001774 if (mCurrentUserId == userId) {
1775 return;
1776 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001777 mCurrentUserId = userId;
Lucas Dupin50ba9912017-07-14 11:55:05 -07001778 systemWallpaper = getWallpaperSafeLocked(userId, FLAG_SYSTEM);
Lucas Dupin9272d452017-09-14 14:15:42 -07001779 final WallpaperData tmpLockWallpaper = mLockWallpaperMap.get(userId);
1780 lockWallpaper = tmpLockWallpaper == null ? systemWallpaper : tmpLockWallpaper;
Lucas Dupin50ba9912017-07-14 11:55:05 -07001781 // Not started watching yet, in case wallpaper data was loaded for other reasons.
1782 if (systemWallpaper.wallpaperObserver == null) {
1783 systemWallpaper.wallpaperObserver = new WallpaperObserver(systemWallpaper);
1784 systemWallpaper.wallpaperObserver.startWatching();
1785 }
1786 switchWallpaper(systemWallpaper, reply);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001787 }
Lucas Dupin9272d452017-09-14 14:15:42 -07001788
1789 // Offload color extraction to another thread since switchUser will be called
1790 // from the main thread.
1791 FgThread.getHandler().post(() -> {
1792 notifyWallpaperColorsChanged(systemWallpaper, FLAG_SYSTEM);
1793 notifyWallpaperColorsChanged(lockWallpaper, FLAG_LOCK);
wilsonshih36597d42018-12-05 18:56:39 +08001794 notifyWallpaperColorsChanged(mFallbackWallpaper, FLAG_SYSTEM);
Lucas Dupin9272d452017-09-14 14:15:42 -07001795 });
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001796 }
1797
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001798 void switchWallpaper(WallpaperData wallpaper, IRemoteCallback reply) {
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001799 synchronized (mLock) {
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001800 mWaitingForUnlock = false;
1801 final ComponentName cname = wallpaper.wallpaperComponent != null ?
1802 wallpaper.wallpaperComponent : wallpaper.nextWallpaperComponent;
1803 if (!bindWallpaperComponentLocked(cname, true, false, wallpaper, reply)) {
1804 // We failed to bind the desired wallpaper, but that might
1805 // happen if the wallpaper isn't direct-boot aware
1806 ServiceInfo si = null;
1807 try {
1808 si = mIPackageManager.getServiceInfo(cname,
1809 PackageManager.MATCH_DIRECT_BOOT_UNAWARE, wallpaper.userId);
1810 } catch (RemoteException ignored) {
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001811 }
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001812
1813 if (si == null) {
1814 Slog.w(TAG, "Failure starting previous wallpaper; clearing");
1815 clearWallpaperLocked(false, FLAG_SYSTEM, wallpaper.userId, reply);
1816 } else {
1817 Slog.w(TAG, "Wallpaper isn't direct boot aware; using fallback until unlocked");
1818 // We might end up persisting the current wallpaper data
1819 // while locked, so pretend like the component was actually
1820 // bound into place
1821 wallpaper.wallpaperComponent = wallpaper.nextWallpaperComponent;
1822 final WallpaperData fallback = new WallpaperData(wallpaper.userId,
1823 WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP);
wilsonshih81e10a72018-11-15 10:54:21 +08001824 ensureSaneWallpaperData(fallback, DEFAULT_DISPLAY);
Jeff Sharkey1cab76a2016-04-12 18:23:31 -06001825 bindWallpaperComponentLocked(mImageWallpaper, true, false, fallback, reply);
1826 mWaitingForUnlock = true;
1827 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07001828 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001829 }
1830 }
1831
Christopher Tatebe132e62016-02-10 12:59:49 -08001832 @Override
1833 public void clearWallpaper(String callingPackage, int which, int userId) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001834 if (DEBUG) Slog.v(TAG, "clearWallpaper");
Benjamin Franzf3ece362015-02-11 10:51:10 +00001835 checkPermission(android.Manifest.permission.SET_WALLPAPER);
Christopher Tate98d609c2016-05-18 17:31:58 -07001836 if (!isWallpaperSupported(callingPackage) || !isSetWallpaperAllowed(callingPackage)) {
Benjamin Franzf3ece362015-02-11 10:51:10 +00001837 return;
1838 }
Christopher Tatee409f0e2016-03-21 14:53:15 -07001839 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
1840 Binder.getCallingUid(), userId, false, true, "clearWallpaper", null);
Christopher Tatebe132e62016-02-10 12:59:49 -08001841
Lucas Dupin41f69422017-05-03 15:26:22 -07001842 WallpaperData data = null;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001843 synchronized (mLock) {
Christopher Tatebe132e62016-02-10 12:59:49 -08001844 clearWallpaperLocked(false, which, userId, null);
Lucas Dupin41f69422017-05-03 15:26:22 -07001845
1846 if (which == FLAG_LOCK) {
1847 data = mLockWallpaperMap.get(userId);
1848 }
1849 if (which == FLAG_SYSTEM || data == null) {
1850 data = mWallpaperMap.get(userId);
1851 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001852 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07001853
1854 // When clearing a wallpaper, broadcast new valid colors
Lucas Dupin41f69422017-05-03 15:26:22 -07001855 if (data != null) {
1856 notifyWallpaperColorsChanged(data, which);
wilsonshih36597d42018-12-05 18:56:39 +08001857 notifyWallpaperColorsChanged(mFallbackWallpaper, FLAG_SYSTEM);
Lucas Dupin41f69422017-05-03 15:26:22 -07001858 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08001859 }
1860
Christopher Tatebe132e62016-02-10 12:59:49 -08001861 void clearWallpaperLocked(boolean defaultFailed, int which, int userId, IRemoteCallback reply) {
Christopher Tateedf7d042016-03-29 18:24:25 -07001862 if (which != FLAG_SYSTEM && which != FLAG_LOCK) {
Christopher Tate105540d2018-03-21 13:03:09 -07001863 throw new IllegalArgumentException("Must specify exactly one kind of wallpaper to clear");
Christopher Tatebe132e62016-02-10 12:59:49 -08001864 }
1865
1866 WallpaperData wallpaper = null;
Christopher Tateedf7d042016-03-29 18:24:25 -07001867 if (which == FLAG_LOCK) {
Christopher Tatebe132e62016-02-10 12:59:49 -08001868 wallpaper = mLockWallpaperMap.get(userId);
1869 if (wallpaper == null) {
1870 // It's already gone; we're done.
Christopher Tate79a24572016-03-02 14:42:44 -08001871 if (DEBUG) {
1872 Slog.i(TAG, "Lock wallpaper already cleared");
1873 }
Christopher Tatebe132e62016-02-10 12:59:49 -08001874 return;
1875 }
1876 } else {
1877 wallpaper = mWallpaperMap.get(userId);
1878 if (wallpaper == null) {
1879 // Might need to bring it in the first time to establish our rewrite
Christopher Tated7faf532016-02-25 12:43:38 -08001880 loadSettingsLocked(userId, false);
Christopher Tatebe132e62016-02-10 12:59:49 -08001881 wallpaper = mWallpaperMap.get(userId);
1882 }
1883 }
Benjamin Franzf3ece362015-02-11 10:51:10 +00001884 if (wallpaper == null) {
1885 return;
1886 }
Christopher Tatebe132e62016-02-10 12:59:49 -08001887
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001888 final long ident = Binder.clearCallingIdentity();
1889 try {
Christopher Tatebe132e62016-02-10 12:59:49 -08001890 if (wallpaper.wallpaperFile.exists()) {
1891 wallpaper.wallpaperFile.delete();
1892 wallpaper.cropFile.delete();
Christopher Tateedf7d042016-03-29 18:24:25 -07001893 if (which == FLAG_LOCK) {
Christopher Tate79a24572016-03-02 14:42:44 -08001894 mLockWallpaperMap.remove(userId);
Christopher Tatebe132e62016-02-10 12:59:49 -08001895 final IWallpaperManagerCallback cb = mKeyguardListener;
1896 if (cb != null) {
Christopher Tate79a24572016-03-02 14:42:44 -08001897 if (DEBUG) {
1898 Slog.i(TAG, "Notifying keyguard of lock wallpaper clear");
1899 }
Christopher Tatebe132e62016-02-10 12:59:49 -08001900 try {
1901 cb.onWallpaperChanged();
1902 } catch (RemoteException e) {
1903 // Oh well it went away; no big deal
1904 }
1905 }
Christopher Tate79a24572016-03-02 14:42:44 -08001906 saveSettingsLocked(userId);
Christopher Tatebe132e62016-02-10 12:59:49 -08001907 return;
1908 }
1909 }
1910
Christopher Tateecd827a2014-09-05 17:42:34 -07001911 RuntimeException e = null;
1912 try {
Lucas Dupin75ec3792017-06-29 14:07:18 -07001913 wallpaper.primaryColors = null;
Christopher Tateecd827a2014-09-05 17:42:34 -07001914 wallpaper.imageWallpaperPending = false;
1915 if (userId != mCurrentUserId) return;
1916 if (bindWallpaperComponentLocked(defaultFailed
1917 ? mImageWallpaper
1918 : null, true, false, wallpaper, reply)) {
1919 return;
1920 }
1921 } catch (IllegalArgumentException e1) {
1922 e = e1;
Dianne Hackborn80b902f2011-09-15 15:15:27 -07001923 }
Christopher Tateecd827a2014-09-05 17:42:34 -07001924
1925 // This can happen if the default wallpaper component doesn't
1926 // exist. This should be a system configuration problem, but
1927 // let's not let it crash the system and just live with no
1928 // wallpaper.
1929 Slog.e(TAG, "Default wallpaper component not found!", e);
1930 clearWallpaperComponentLocked(wallpaper);
1931 if (reply != null) {
1932 try {
1933 reply.sendResult(null);
1934 } catch (RemoteException e1) {
1935 }
1936 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001937 } finally {
1938 Binder.restoreCallingIdentity(ident);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001939 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001940 }
1941
1942 public boolean hasNamedWallpaper(String name) {
1943 synchronized (mLock) {
Amith Yamasani6474c4c2012-10-04 14:55:42 -07001944 List<UserInfo> users;
1945 long ident = Binder.clearCallingIdentity();
1946 try {
1947 users = ((UserManager) mContext.getSystemService(Context.USER_SERVICE)).getUsers();
1948 } finally {
1949 Binder.restoreCallingIdentity(ident);
1950 }
1951 for (UserInfo user: users) {
Benjamin Franzf3ece362015-02-11 10:51:10 +00001952 // ignore managed profiles
1953 if (user.isManagedProfile()) {
1954 continue;
1955 }
Amith Yamasani6474c4c2012-10-04 14:55:42 -07001956 WallpaperData wd = mWallpaperMap.get(user.id);
1957 if (wd == null) {
1958 // User hasn't started yet, so load her settings to peek at the wallpaper
Christopher Tated7faf532016-02-25 12:43:38 -08001959 loadSettingsLocked(user.id, false);
Amith Yamasani6474c4c2012-10-04 14:55:42 -07001960 wd = mWallpaperMap.get(user.id);
1961 }
1962 if (wd != null && name.equals(wd.name)) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001963 return true;
1964 }
1965 }
1966 }
1967 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001968 }
1969
wilsonshih81e10a72018-11-15 10:54:21 +08001970 private boolean isValidDisplay(int displayId) {
1971 return mDisplayManager.getDisplay(displayId) != null;
1972 }
1973
1974 /**
1975 * Sets the dimension hint for the wallpaper. These hints indicate the desired
1976 * minimum width and height for the wallpaper in a particular display.
1977 */
1978 public void setDimensionHints(int width, int height, String callingPackage, int displayId)
Benjamin Franzf3ece362015-02-11 10:51:10 +00001979 throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001980 checkPermission(android.Manifest.permission.SET_WALLPAPER_HINTS);
Benjamin Franzf3ece362015-02-11 10:51:10 +00001981 if (!isWallpaperSupported(callingPackage)) {
1982 return;
1983 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07001984 synchronized (mLock) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001985 int userId = UserHandle.getCallingUserId();
Christopher Tateedf7d042016-03-29 18:24:25 -07001986 WallpaperData wallpaper = getWallpaperSafeLocked(userId, FLAG_SYSTEM);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001987 if (width <= 0 || height <= 0) {
1988 throw new IllegalArgumentException("width and height must be > 0");
1989 }
1990
wilsonshih81e10a72018-11-15 10:54:21 +08001991 if (!isValidDisplay(displayId)) {
1992 throw new IllegalArgumentException("Cannot find display with id=" + displayId);
1993 }
1994
wilsonshiha282bf72018-11-30 12:48:05 +08001995 final DisplayData wpdData = getDisplayDataOrCreate(displayId);
wilsonshih81e10a72018-11-15 10:54:21 +08001996 if (width != wpdData.mWidth || height != wpdData.mHeight) {
1997 wpdData.mWidth = width;
1998 wpdData.mHeight = height;
1999 if (displayId == DEFAULT_DISPLAY) saveSettingsLocked(userId);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002000 if (mCurrentUserId != userId) return; // Don't change the properties now
2001 if (wallpaper.connection != null) {
wilsonshih81e10a72018-11-15 10:54:21 +08002002 final WallpaperConnection.DisplayConnector connector = wallpaper.connection
2003 .getDisplayConnectorOrCreate(displayId);
2004 final IWallpaperEngine engine = connector != null ? connector.mEngine : null;
wilsonshihde93f492018-11-01 21:23:40 +08002005 if (engine != null) {
Dianne Hackborn284ac932009-08-28 10:34:25 -07002006 try {
wilsonshihde93f492018-11-01 21:23:40 +08002007 engine.setDesiredSize(width, height);
Dianne Hackborn284ac932009-08-28 10:34:25 -07002008 } catch (RemoteException e) {
2009 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002010 notifyCallbacksLocked(wallpaper);
wilsonshih81e10a72018-11-15 10:54:21 +08002011 } else if (wallpaper.connection.mService != null && connector != null) {
Michael Wright5203a8b2013-10-03 14:16:42 -07002012 // We've attached to the service but the engine hasn't attached back to us
2013 // yet. This means it will be created with the previous dimensions, so we
2014 // need to update it to the new dimensions once it attaches.
wilsonshih81e10a72018-11-15 10:54:21 +08002015 connector.mDimensionsChanged = true;
Dianne Hackborn284ac932009-08-28 10:34:25 -07002016 }
2017 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002018 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002019 }
2020 }
2021
wilsonshih81e10a72018-11-15 10:54:21 +08002022 /**
2023 * Returns the desired minimum width for the wallpaper in a particular display.
2024 */
2025 public int getWidthHint(int displayId) throws RemoteException {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002026 synchronized (mLock) {
wilsonshih81e10a72018-11-15 10:54:21 +08002027 if (!isValidDisplay(displayId)) {
2028 throw new IllegalArgumentException("Cannot find display with id=" + displayId);
2029 }
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07002030 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.getCallingUserId());
Benjamin Franzf3ece362015-02-11 10:51:10 +00002031 if (wallpaper != null) {
wilsonshiha282bf72018-11-30 12:48:05 +08002032 final DisplayData wpdData = getDisplayDataOrCreate(displayId);
wilsonshih81e10a72018-11-15 10:54:21 +08002033 return wpdData.mWidth;
Benjamin Franzf3ece362015-02-11 10:51:10 +00002034 } else {
2035 return 0;
2036 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002037 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002038 }
2039
wilsonshih81e10a72018-11-15 10:54:21 +08002040 /**
2041 * Returns the desired minimum height for the wallpaper in a particular display.
2042 */
2043 public int getHeightHint(int displayId) throws RemoteException {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002044 synchronized (mLock) {
wilsonshih81e10a72018-11-15 10:54:21 +08002045 if (!isValidDisplay(displayId)) {
2046 throw new IllegalArgumentException("Cannot find display with id=" + displayId);
2047 }
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07002048 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.getCallingUserId());
Benjamin Franzf3ece362015-02-11 10:51:10 +00002049 if (wallpaper != null) {
wilsonshiha282bf72018-11-30 12:48:05 +08002050 final DisplayData wpdData = getDisplayDataOrCreate(displayId);
wilsonshih81e10a72018-11-15 10:54:21 +08002051 return wpdData.mHeight;
Benjamin Franzf3ece362015-02-11 10:51:10 +00002052 } else {
2053 return 0;
2054 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002055 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002056 }
2057
wilsonshih81e10a72018-11-15 10:54:21 +08002058 /**
2059 * Sets extra padding that we would like the wallpaper to have outside of the display.
2060 */
2061 public void setDisplayPadding(Rect padding, String callingPackage, int displayId) {
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002062 checkPermission(android.Manifest.permission.SET_WALLPAPER_HINTS);
Benjamin Franzf3ece362015-02-11 10:51:10 +00002063 if (!isWallpaperSupported(callingPackage)) {
2064 return;
2065 }
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002066 synchronized (mLock) {
wilsonshih81e10a72018-11-15 10:54:21 +08002067 if (!isValidDisplay(displayId)) {
2068 throw new IllegalArgumentException("Cannot find display with id=" + displayId);
2069 }
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002070 int userId = UserHandle.getCallingUserId();
Christopher Tateedf7d042016-03-29 18:24:25 -07002071 WallpaperData wallpaper = getWallpaperSafeLocked(userId, FLAG_SYSTEM);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002072 if (padding.left < 0 || padding.top < 0 || padding.right < 0 || padding.bottom < 0) {
2073 throw new IllegalArgumentException("padding must be positive: " + padding);
2074 }
2075
wilsonshiha282bf72018-11-30 12:48:05 +08002076 final DisplayData wpdData = getDisplayDataOrCreate(displayId);
wilsonshih81e10a72018-11-15 10:54:21 +08002077 if (!padding.equals(wpdData.mPadding)) {
2078 wpdData.mPadding.set(padding);
2079 if (displayId == DEFAULT_DISPLAY) saveSettingsLocked(userId);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002080 if (mCurrentUserId != userId) return; // Don't change the properties now
2081 if (wallpaper.connection != null) {
wilsonshih81e10a72018-11-15 10:54:21 +08002082 final WallpaperConnection.DisplayConnector connector = wallpaper.connection
2083 .getDisplayConnectorOrCreate(displayId);
2084 final IWallpaperEngine engine = connector != null ? connector.mEngine : null;
wilsonshihde93f492018-11-01 21:23:40 +08002085 if (engine != null) {
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002086 try {
wilsonshihde93f492018-11-01 21:23:40 +08002087 engine.setDisplayPadding(padding);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002088 } catch (RemoteException e) {
2089 }
2090 notifyCallbacksLocked(wallpaper);
wilsonshih81e10a72018-11-15 10:54:21 +08002091 } else if (wallpaper.connection.mService != null && connector != null) {
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002092 // We've attached to the service but the engine hasn't attached back to us
2093 // yet. This means it will be created with the previous dimensions, so we
2094 // need to update it to the new dimensions once it attaches.
wilsonshih81e10a72018-11-15 10:54:21 +08002095 connector.mPaddingChanged = true;
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002096 }
2097 }
2098 }
2099 }
2100 }
2101
Yorke Leedcd93cc2016-01-08 14:12:55 -08002102 @Override
Christopher Tate93252de2017-06-15 14:48:41 -07002103 public ParcelFileDescriptor getWallpaper(String callingPkg, IWallpaperManagerCallback cb,
2104 final int which, Bundle outParams, int wallpaperUserId) {
Christopher Tate8a71c482017-08-14 16:45:03 -07002105 final int hasPrivilege = mContext.checkCallingOrSelfPermission(
2106 android.Manifest.permission.READ_WALLPAPER_INTERNAL);
2107 if (hasPrivilege != PackageManager.PERMISSION_GRANTED) {
Jeff Sharkey859856d2019-03-25 11:44:11 -06002108 mContext.getSystemService(StorageManager.class).checkPermissionReadImages(true,
2109 Binder.getCallingPid(), Binder.getCallingUid(), callingPkg);
Christopher Tate8a71c482017-08-14 16:45:03 -07002110 }
Christopher Tate93252de2017-06-15 14:48:41 -07002111
Christopher Tatee409f0e2016-03-21 14:53:15 -07002112 wallpaperUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
2113 Binder.getCallingUid(), wallpaperUserId, false, true, "getWallpaper", null);
Christopher Tatebe132e62016-02-10 12:59:49 -08002114
Christopher Tateedf7d042016-03-29 18:24:25 -07002115 if (which != FLAG_SYSTEM && which != FLAG_LOCK) {
Christopher Tatebe132e62016-02-10 12:59:49 -08002116 throw new IllegalArgumentException("Must specify exactly one kind of wallpaper to read");
2117 }
2118
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002119 synchronized (mLock) {
Vadim Tryshev8cde0792016-02-19 17:02:15 -08002120 final SparseArray<WallpaperData> whichSet =
Christopher Tateedf7d042016-03-29 18:24:25 -07002121 (which == FLAG_LOCK) ? mLockWallpaperMap : mWallpaperMap;
Vadim Tryshev8cde0792016-02-19 17:02:15 -08002122 WallpaperData wallpaper = whichSet.get(wallpaperUserId);
2123 if (wallpaper == null) {
Christopher Tatef717b932017-09-11 15:52:54 -07002124 // There is no established wallpaper imagery of this type (expected
2125 // only for lock wallpapers; a system WallpaperData is established at
2126 // user switch)
2127 return null;
Benjamin Franzf3ece362015-02-11 10:51:10 +00002128 }
wilsonshih81e10a72018-11-15 10:54:21 +08002129 // Only for default display.
wilsonshiha282bf72018-11-30 12:48:05 +08002130 final DisplayData wpdData = getDisplayDataOrCreate(DEFAULT_DISPLAY);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002131 try {
Dianne Hackborn284ac932009-08-28 10:34:25 -07002132 if (outParams != null) {
wilsonshih81e10a72018-11-15 10:54:21 +08002133 outParams.putInt("width", wpdData.mWidth);
2134 outParams.putInt("height", wpdData.mHeight);
Dianne Hackborn284ac932009-08-28 10:34:25 -07002135 }
Christopher Tateea6724a2016-02-18 18:39:19 -08002136 if (cb != null) {
2137 wallpaper.callbacks.register(cb);
2138 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08002139 if (!wallpaper.cropFile.exists()) {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002140 return null;
2141 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08002142 return ParcelFileDescriptor.open(wallpaper.cropFile, MODE_READ_ONLY);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002143 } catch (FileNotFoundException e) {
2144 /* Shouldn't happen as we check to see if the file exists */
Joe Onorato8a9b2202010-02-26 18:56:32 -08002145 Slog.w(TAG, "Error getting wallpaper", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002146 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002147 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002148 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002149 }
2150
Christopher Tatee409f0e2016-03-21 14:53:15 -07002151 @Override
Jorim Jaggie31f6b82016-07-01 16:15:09 -07002152 public WallpaperInfo getWallpaperInfo(int userId) {
2153 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
Christopher Tatef717b932017-09-11 15:52:54 -07002154 Binder.getCallingUid(), userId, false, true, "getWallpaperInfo", null);
Dianne Hackborneb034652009-09-07 00:49:58 -07002155 synchronized (mLock) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002156 WallpaperData wallpaper = mWallpaperMap.get(userId);
Benjamin Franzf3ece362015-02-11 10:51:10 +00002157 if (wallpaper != null && wallpaper.connection != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002158 return wallpaper.connection.mInfo;
Dianne Hackborneb034652009-09-07 00:49:58 -07002159 }
2160 return null;
2161 }
2162 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002163
Christopher Tatead3c2592016-01-20 18:13:17 -08002164 @Override
Christopher Tatee409f0e2016-03-21 14:53:15 -07002165 public int getWallpaperIdForUser(int which, int userId) {
2166 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
2167 Binder.getCallingUid(), userId, false, true, "getWallpaperIdForUser", null);
2168
Christopher Tateedf7d042016-03-29 18:24:25 -07002169 if (which != FLAG_SYSTEM && which != FLAG_LOCK) {
Christopher Tatee409f0e2016-03-21 14:53:15 -07002170 throw new IllegalArgumentException("Must specify exactly one kind of wallpaper");
2171 }
2172
2173 final SparseArray<WallpaperData> map =
Christopher Tateedf7d042016-03-29 18:24:25 -07002174 (which == FLAG_LOCK) ? mLockWallpaperMap : mWallpaperMap;
Christopher Tatee409f0e2016-03-21 14:53:15 -07002175 synchronized (mLock) {
2176 WallpaperData wallpaper = map.get(userId);
2177 if (wallpaper != null) {
2178 return wallpaper.wallpaperId;
2179 }
2180 }
2181 return -1;
2182 }
2183
2184 @Override
wilsonshih36597d42018-12-05 18:56:39 +08002185 public void registerWallpaperColorsCallback(IWallpaperManagerCallback cb, int userId,
2186 int displayId) {
Lucas Dupin50ba9912017-07-14 11:55:05 -07002187 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
2188 userId, true, true, "registerWallpaperColorsCallback", null);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002189 synchronized (mLock) {
wilsonshih36597d42018-12-05 18:56:39 +08002190 SparseArray<RemoteCallbackList<IWallpaperManagerCallback>>
2191 userDisplayColorsChangedListeners = mColorsChangedListeners.get(userId);
2192 if (userDisplayColorsChangedListeners == null) {
2193 userDisplayColorsChangedListeners = new SparseArray<>();
2194 mColorsChangedListeners.put(userId, userDisplayColorsChangedListeners);
Lucas Dupin50ba9912017-07-14 11:55:05 -07002195 }
wilsonshih36597d42018-12-05 18:56:39 +08002196 RemoteCallbackList<IWallpaperManagerCallback> displayChangedListeners =
2197 userDisplayColorsChangedListeners.get(displayId);
2198 if (displayChangedListeners == null) {
2199 displayChangedListeners = new RemoteCallbackList<>();
2200 userDisplayColorsChangedListeners.put(displayId, displayChangedListeners);
2201 }
2202 displayChangedListeners.register(cb);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002203 }
2204 }
2205
2206 @Override
wilsonshih36597d42018-12-05 18:56:39 +08002207 public void unregisterWallpaperColorsCallback(IWallpaperManagerCallback cb, int userId,
2208 int displayId) {
Lucas Dupin50ba9912017-07-14 11:55:05 -07002209 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
2210 userId, true, true, "unregisterWallpaperColorsCallback", null);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002211 synchronized (mLock) {
wilsonshih36597d42018-12-05 18:56:39 +08002212 SparseArray<RemoteCallbackList<IWallpaperManagerCallback>>
2213 userDisplayColorsChangedListeners = mColorsChangedListeners.get(userId);
2214 if (userDisplayColorsChangedListeners != null) {
2215 RemoteCallbackList<IWallpaperManagerCallback> displayChangedListeners =
2216 userDisplayColorsChangedListeners.get(displayId);
2217 if (displayChangedListeners != null) {
2218 displayChangedListeners.unregister(cb);
2219 }
Lucas Dupin50ba9912017-07-14 11:55:05 -07002220 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002221 }
2222 }
2223
Lucas Dupin4c8c3272018-11-06 17:47:48 -08002224 /**
wilsonshih36597d42018-12-05 18:56:39 +08002225 * TODO(multi-display) Extends this method with specific display.
Lucas Dupin4c8c3272018-11-06 17:47:48 -08002226 * Propagate ambient state to wallpaper engine.
2227 *
2228 * @param inAmbientMode {@code true} when in ambient mode, {@code false} otherwise.
2229 * @param animationDuration Duration of the animation, or 0 when immediate.
2230 */
2231 public void setInAmbientMode(boolean inAmbientMode, long animationDuration) {
Lucas Dupin7517b5d2017-08-22 12:51:25 -07002232 final IWallpaperEngine engine;
2233 synchronized (mLock) {
Lucas Dupin4c8c3272018-11-06 17:47:48 -08002234 mInAmbientMode = inAmbientMode;
Lucas Dupin7517b5d2017-08-22 12:51:25 -07002235 final WallpaperData data = mWallpaperMap.get(mCurrentUserId);
Ahan Wu723a80e2018-11-07 20:39:32 +08002236 // The wallpaper info is null for image wallpaper, also use the engine in this case.
Ahan Wu67e7f102019-01-14 20:38:14 +08002237 if (data != null && data.connection != null && (data.connection.mInfo == null
2238 || data.connection.mInfo.supportsAmbientMode())) {
wilsonshih36597d42018-12-05 18:56:39 +08002239 // TODO(multi-display) Extends this method with specific display.
wilsonshihde93f492018-11-01 21:23:40 +08002240 engine = data.connection.getDisplayConnectorOrCreate(DEFAULT_DISPLAY).mEngine;
Lucas Dupin7517b5d2017-08-22 12:51:25 -07002241 } else {
2242 engine = null;
2243 }
2244 }
2245
2246 if (engine != null) {
2247 try {
Lucas Dupin4c8c3272018-11-06 17:47:48 -08002248 engine.setInAmbientMode(inAmbientMode, animationDuration);
Lucas Dupin7517b5d2017-08-22 12:51:25 -07002249 } catch (RemoteException e) {
2250 // Cannot talk to wallpaper engine.
2251 }
2252 }
2253 }
2254
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002255 @Override
Christopher Tatebe132e62016-02-10 12:59:49 -08002256 public boolean setLockWallpaperCallback(IWallpaperManagerCallback cb) {
2257 checkPermission(android.Manifest.permission.INTERNAL_SYSTEM_WINDOW);
2258 synchronized (mLock) {
2259 mKeyguardListener = cb;
2260 }
2261 return true;
2262 }
2263
2264 @Override
wilsonshih36597d42018-12-05 18:56:39 +08002265 public WallpaperColors getWallpaperColors(int which, int userId, int displayId)
2266 throws RemoteException {
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002267 if (which != FLAG_LOCK && which != FLAG_SYSTEM) {
2268 throw new IllegalArgumentException("which should be either FLAG_LOCK or FLAG_SYSTEM");
2269 }
Lucas Dupin50ba9912017-07-14 11:55:05 -07002270 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
2271 userId, false, true, "getWallpaperColors", null);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002272
2273 WallpaperData wallpaperData = null;
2274 boolean shouldExtract;
2275
2276 synchronized (mLock) {
2277 if (which == FLAG_LOCK) {
Lucas Dupin50ba9912017-07-14 11:55:05 -07002278 wallpaperData = mLockWallpaperMap.get(userId);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002279 }
2280
2281 // Try to get the system wallpaper anyway since it might
2282 // also be the lock screen wallpaper
2283 if (wallpaperData == null) {
wilsonshih36597d42018-12-05 18:56:39 +08002284 wallpaperData = findWallpaperAtDisplay(userId, displayId);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002285 }
2286
2287 if (wallpaperData == null) {
2288 return null;
2289 }
2290 shouldExtract = wallpaperData.primaryColors == null;
2291 }
2292
2293 if (shouldExtract) {
2294 extractColors(wallpaperData);
2295 }
2296
2297 synchronized (mLock) {
Lucas Dupin4b4c5302018-06-24 18:22:10 -07002298 return wallpaperData.primaryColors;
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002299 }
2300 }
2301
wilsonshih36597d42018-12-05 18:56:39 +08002302 private WallpaperData findWallpaperAtDisplay(int userId, int displayId) {
2303 if (mFallbackWallpaper != null && mFallbackWallpaper.connection != null
2304 && mFallbackWallpaper.connection.containsDisplay(displayId)) {
2305 return mFallbackWallpaper;
2306 } else {
2307 return mWallpaperMap.get(userId);
2308 }
2309 }
2310
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002311 @Override
Christopher Tate1e1e2e02016-01-25 15:34:36 -08002312 public ParcelFileDescriptor setWallpaper(String name, String callingPackage,
Christopher Tated7faf532016-02-25 12:43:38 -08002313 Rect cropHint, boolean allowBackup, Bundle extras, int which,
Jorim Jaggi6c902d02016-08-18 10:44:54 -07002314 IWallpaperManagerCallback completion, int userId) {
2315 userId = ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,
2316 false /* all */, true /* full */, "changing wallpaper", null /* pkg */);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002317 checkPermission(android.Manifest.permission.SET_WALLPAPER);
Christopher Tatead3c2592016-01-20 18:13:17 -08002318
Christopher Tateedf7d042016-03-29 18:24:25 -07002319 if ((which & (FLAG_LOCK|FLAG_SYSTEM)) == 0) {
Christopher Tate98d609c2016-05-18 17:31:58 -07002320 final String msg = "Must specify a valid wallpaper category to set";
2321 Slog.e(TAG, msg);
2322 throw new IllegalArgumentException(msg);
Christopher Tatead3c2592016-01-20 18:13:17 -08002323 }
2324
Christopher Tate98d609c2016-05-18 17:31:58 -07002325 if (!isWallpaperSupported(callingPackage) || !isSetWallpaperAllowed(callingPackage)) {
Benjamin Franzf3ece362015-02-11 10:51:10 +00002326 return null;
2327 }
Christopher Tatead3c2592016-01-20 18:13:17 -08002328
Christopher Tate1e1e2e02016-01-25 15:34:36 -08002329 // "null" means the no-op crop, preserving the full input image
2330 if (cropHint == null) {
2331 cropHint = new Rect(0, 0, 0, 0);
2332 } else {
2333 if (cropHint.isEmpty()
2334 || cropHint.left < 0
2335 || cropHint.top < 0) {
Christopher Tate98d609c2016-05-18 17:31:58 -07002336 throw new IllegalArgumentException("Invalid crop rect supplied: " + cropHint);
Christopher Tate1e1e2e02016-01-25 15:34:36 -08002337 }
2338 }
2339
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002340 synchronized (mLock) {
Christopher Tatebe132e62016-02-10 12:59:49 -08002341 if (DEBUG) Slog.v(TAG, "setWallpaper which=0x" + Integer.toHexString(which));
2342 WallpaperData wallpaper;
2343
Christopher Tate8347b632016-04-29 18:59:18 -07002344 /* If we're setting system but not lock, and lock is currently sharing the system
2345 * wallpaper, we need to migrate that image over to being lock-only before
2346 * the caller here writes new bitmap data.
2347 */
2348 if (which == FLAG_SYSTEM && mLockWallpaperMap.get(userId) == null) {
2349 if (DEBUG) {
2350 Slog.i(TAG, "Migrating system->lock to preserve");
2351 }
2352 migrateSystemToLockWallpaperLocked(userId);
2353 }
2354
Christopher Tatebe132e62016-02-10 12:59:49 -08002355 wallpaper = getWallpaperSafeLocked(userId, which);
Dianne Hackborn0cd48872009-08-13 18:51:59 -07002356 final long ident = Binder.clearCallingIdentity();
2357 try {
Christopher Tatead3c2592016-01-20 18:13:17 -08002358 ParcelFileDescriptor pfd = updateWallpaperBitmapLocked(name, wallpaper, extras);
Dianne Hackborn0cd48872009-08-13 18:51:59 -07002359 if (pfd != null) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002360 wallpaper.imageWallpaperPending = true;
Christopher Tatebe132e62016-02-10 12:59:49 -08002361 wallpaper.whichPending = which;
Christopher Tate1e1e2e02016-01-25 15:34:36 -08002362 wallpaper.setComplete = completion;
2363 wallpaper.cropHint.set(cropHint);
Christopher Tatec613c632016-08-12 14:13:02 -07002364 wallpaper.allowBackup = allowBackup;
Dianne Hackborn0cd48872009-08-13 18:51:59 -07002365 }
2366 return pfd;
2367 } finally {
2368 Binder.restoreCallingIdentity(ident);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002369 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002370 }
2371 }
2372
Christopher Tate8347b632016-04-29 18:59:18 -07002373 private void migrateSystemToLockWallpaperLocked(int userId) {
2374 WallpaperData sysWP = mWallpaperMap.get(userId);
2375 if (sysWP == null) {
2376 if (DEBUG) {
2377 Slog.i(TAG, "No system wallpaper? Not tracking for lock-only");
2378 }
2379 return;
2380 }
2381
2382 // We know a-priori that there is no lock-only wallpaper currently
2383 WallpaperData lockWP = new WallpaperData(userId,
2384 WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP);
2385 lockWP.wallpaperId = sysWP.wallpaperId;
2386 lockWP.cropHint.set(sysWP.cropHint);
Christopher Tateedd8dc82016-10-12 15:17:58 -07002387 lockWP.allowBackup = sysWP.allowBackup;
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002388 lockWP.primaryColors = sysWP.primaryColors;
Christopher Tate8347b632016-04-29 18:59:18 -07002389
2390 // Migrate the bitmap files outright; no need to copy
2391 try {
2392 Os.rename(sysWP.wallpaperFile.getAbsolutePath(), lockWP.wallpaperFile.getAbsolutePath());
2393 Os.rename(sysWP.cropFile.getAbsolutePath(), lockWP.cropFile.getAbsolutePath());
2394 } catch (ErrnoException e) {
2395 Slog.e(TAG, "Can't migrate system wallpaper: " + e.getMessage());
2396 lockWP.wallpaperFile.delete();
2397 lockWP.cropFile.delete();
2398 return;
2399 }
2400
2401 mLockWallpaperMap.put(userId, lockWP);
2402 }
2403
Christopher Tatead3c2592016-01-20 18:13:17 -08002404 ParcelFileDescriptor updateWallpaperBitmapLocked(String name, WallpaperData wallpaper,
2405 Bundle extras) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002406 if (name == null) name = "";
2407 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002408 File dir = getWallpaperDir(wallpaper.userId);
2409 if (!dir.exists()) {
2410 dir.mkdir();
Dianne Hackbornebac48c2011-11-29 18:01:50 -08002411 FileUtils.setPermissions(
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002412 dir.getPath(),
Dianne Hackbornebac48c2011-11-29 18:01:50 -08002413 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
2414 -1, -1);
2415 }
Christopher Tatebe132e62016-02-10 12:59:49 -08002416 ParcelFileDescriptor fd = ParcelFileDescriptor.open(wallpaper.wallpaperFile,
Christopher Tate90f86ba2014-09-11 12:37:19 -07002417 MODE_CREATE|MODE_READ_WRITE|MODE_TRUNCATE);
Christopher Tatebe132e62016-02-10 12:59:49 -08002418 if (!SELinux.restorecon(wallpaper.wallpaperFile)) {
rpcraig554cb0c2012-07-05 06:41:43 -04002419 return null;
2420 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002421 wallpaper.name = name;
Christopher Tatead3c2592016-01-20 18:13:17 -08002422 wallpaper.wallpaperId = makeWallpaperIdLocked();
2423 if (extras != null) {
2424 extras.putInt(WallpaperManager.EXTRA_NEW_WALLPAPER_ID, wallpaper.wallpaperId);
2425 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002426 // Nullify field to require new computation
2427 wallpaper.primaryColors = null;
Christopher Tatead3c2592016-01-20 18:13:17 -08002428 if (DEBUG) {
2429 Slog.v(TAG, "updateWallpaperBitmapLocked() : id=" + wallpaper.wallpaperId
Christopher Tatebe132e62016-02-10 12:59:49 -08002430 + " name=" + name + " file=" + wallpaper.wallpaperFile.getName());
Christopher Tatead3c2592016-01-20 18:13:17 -08002431 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002432 return fd;
2433 } catch (FileNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002434 Slog.w(TAG, "Error setting wallpaper", e);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002435 }
2436 return null;
2437 }
2438
Christopher Tated57d17c2016-03-25 13:41:46 -07002439 @Override
Adrian Roos40ea0832016-07-14 14:19:55 -07002440 public void setWallpaperComponentChecked(ComponentName name, String callingPackage,
2441 int userId) {
2442
Christopher Tate98d609c2016-05-18 17:31:58 -07002443 if (isWallpaperSupported(callingPackage) && isSetWallpaperAllowed(callingPackage)) {
Adrian Roos40ea0832016-07-14 14:19:55 -07002444 setWallpaperComponent(name, userId);
Benjamin Franzf3ece362015-02-11 10:51:10 +00002445 }
2446 }
2447
2448 // ToDo: Remove this version of the function
Christopher Tated57d17c2016-03-25 13:41:46 -07002449 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002450 public void setWallpaperComponent(ComponentName name) {
Adrian Roos40ea0832016-07-14 14:19:55 -07002451 setWallpaperComponent(name, UserHandle.getCallingUserId());
2452 }
2453
2454 private void setWallpaperComponent(ComponentName name, int userId) {
2455 userId = ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,
2456 false /* all */, true /* full */, "changing live wallpaper", null /* pkg */);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002457 checkPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT);
Adrian Roos40ea0832016-07-14 14:19:55 -07002458
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002459 int which = FLAG_SYSTEM;
2460 boolean shouldNotifyColors = false;
2461 WallpaperData wallpaper;
2462
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002463 synchronized (mLock) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002464 if (DEBUG) Slog.v(TAG, "setWallpaperComponent name=" + name);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002465 wallpaper = mWallpaperMap.get(userId);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002466 if (wallpaper == null) {
2467 throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
2468 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002469 final long ident = Binder.clearCallingIdentity();
Christopher Tate7cd00102016-12-19 14:38:44 -08002470
2471 // Live wallpapers can't be specified for keyguard. If we're using a static
2472 // system+lock image currently, migrate the system wallpaper to be a lock-only
2473 // image as part of making a different live component active as the system
2474 // wallpaper.
2475 if (mImageWallpaper.equals(wallpaper.wallpaperComponent)) {
2476 if (mLockWallpaperMap.get(userId) == null) {
2477 // We're using the static imagery and there is no lock-specific image in place,
2478 // therefore it's a shared system+lock image that we need to migrate.
2479 migrateSystemToLockWallpaperLocked(userId);
2480 }
2481 }
2482
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002483 // New live wallpaper is also a lock wallpaper if nothing is set
2484 if (mLockWallpaperMap.get(userId) == null) {
2485 which |= FLAG_LOCK;
2486 }
2487
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002488 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002489 wallpaper.imageWallpaperPending = false;
Lucas Dupin50ba9912017-07-14 11:55:05 -07002490 boolean same = changingToSame(name, wallpaper);
Christopher Tated57d17c2016-03-25 13:41:46 -07002491 if (bindWallpaperComponentLocked(name, false, true, wallpaper, null)) {
Lucas Dupin50ba9912017-07-14 11:55:05 -07002492 if (!same) {
2493 wallpaper.primaryColors = null;
2494 }
Christopher Tated57d17c2016-03-25 13:41:46 -07002495 wallpaper.wallpaperId = makeWallpaperIdLocked();
Sunny Goyal0572e182016-03-31 11:05:51 -07002496 notifyCallbacksLocked(wallpaper);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002497 shouldNotifyColors = true;
Christopher Tated57d17c2016-03-25 13:41:46 -07002498 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002499 } finally {
2500 Binder.restoreCallingIdentity(ident);
2501 }
2502 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002503
2504 if (shouldNotifyColors) {
2505 notifyWallpaperColorsChanged(wallpaper, which);
wilsonshih36597d42018-12-05 18:56:39 +08002506 notifyWallpaperColorsChanged(mFallbackWallpaper, FLAG_SYSTEM);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002507 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002508 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01002509
Lucas Dupin50ba9912017-07-14 11:55:05 -07002510 private boolean changingToSame(ComponentName componentName, WallpaperData wallpaper) {
2511 if (wallpaper.connection != null) {
2512 if (wallpaper.wallpaperComponent == null) {
2513 if (componentName == null) {
2514 if (DEBUG) Slog.v(TAG, "changingToSame: still using default");
2515 // Still using default wallpaper.
2516 return true;
2517 }
2518 } else if (wallpaper.wallpaperComponent.equals(componentName)) {
2519 // Changing to same wallpaper.
2520 if (DEBUG) Slog.v(TAG, "same wallpaper");
2521 return true;
2522 }
2523 }
2524 return false;
2525 }
2526
wilsonshiha282bf72018-11-30 12:48:05 +08002527 private boolean bindWallpaperComponentLocked(ComponentName componentName, boolean force,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002528 boolean fromUser, WallpaperData wallpaper, IRemoteCallback reply) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07002529 if (DEBUG_LIVE) {
2530 Slog.v(TAG, "bindWallpaperComponentLocked: componentName=" + componentName);
2531 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002532 // Has the component changed?
Lucas Dupin50ba9912017-07-14 11:55:05 -07002533 if (!force && changingToSame(componentName, wallpaper)) {
2534 return true;
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002535 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01002536
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002537 try {
Mike Clerona428b2c2009-11-15 22:53:08 -08002538 if (componentName == null) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07002539 componentName = mDefaultWallpaperComponent;
Mike Clerona428b2c2009-11-15 22:53:08 -08002540 if (componentName == null) {
Mike Cleron322b6ee2009-11-12 07:45:47 -08002541 // Fall back to static image wallpaper
Justin Koh29c30162014-09-05 17:10:10 -07002542 componentName = mImageWallpaper;
Mike Cleron322b6ee2009-11-12 07:45:47 -08002543 //clearWallpaperComponentLocked();
2544 //return;
Christopher Tate2a6c55f2017-03-31 12:28:30 -07002545 if (DEBUG_LIVE) Slog.v(TAG, "No default component; using image wallpaper");
Mike Cleron322b6ee2009-11-12 07:45:47 -08002546 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002547 }
Amith Yamasani4e2820c2012-08-28 22:17:23 -07002548 int serviceUserId = wallpaper.userId;
2549 ServiceInfo si = mIPackageManager.getServiceInfo(componentName,
2550 PackageManager.GET_META_DATA | PackageManager.GET_PERMISSIONS, serviceUserId);
Christopher Tate90952202013-09-08 13:01:28 -07002551 if (si == null) {
2552 // The wallpaper component we're trying to use doesn't exist
2553 Slog.w(TAG, "Attempted wallpaper " + componentName + " is unavailable");
2554 return false;
2555 }
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002556 if (!android.Manifest.permission.BIND_WALLPAPER.equals(si.permission)) {
Lucas Dupin4c8c3272018-11-06 17:47:48 -08002557 String msg = "Selected service does not have "
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002558 + android.Manifest.permission.BIND_WALLPAPER
Dianne Hackborn80b902f2011-09-15 15:15:27 -07002559 + ": " + componentName;
2560 if (fromUser) {
2561 throw new SecurityException(msg);
2562 }
2563 Slog.w(TAG, msg);
2564 return false;
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002565 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01002566
Dianne Hackborneb034652009-09-07 00:49:58 -07002567 WallpaperInfo wi = null;
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01002568
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002569 Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
Justin Koh29c30162014-09-05 17:10:10 -07002570 if (componentName != null && !componentName.equals(mImageWallpaper)) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002571 // Make sure the selected service is actually a wallpaper service.
Amith Yamasani4e2820c2012-08-28 22:17:23 -07002572 List<ResolveInfo> ris =
2573 mIPackageManager.queryIntentServices(intent,
2574 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
Jeff Sharkeyd5896632016-03-04 16:16:00 -07002575 PackageManager.GET_META_DATA, serviceUserId).getList();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002576 for (int i=0; i<ris.size(); i++) {
2577 ServiceInfo rsi = ris.get(i).serviceInfo;
2578 if (rsi.name.equals(si.name) &&
2579 rsi.packageName.equals(si.packageName)) {
Dianne Hackborneb034652009-09-07 00:49:58 -07002580 try {
2581 wi = new WallpaperInfo(mContext, ris.get(i));
2582 } catch (XmlPullParserException e) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -07002583 if (fromUser) {
2584 throw new IllegalArgumentException(e);
2585 }
2586 Slog.w(TAG, e);
2587 return false;
Dianne Hackborneb034652009-09-07 00:49:58 -07002588 } catch (IOException e) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -07002589 if (fromUser) {
2590 throw new IllegalArgumentException(e);
2591 }
2592 Slog.w(TAG, e);
2593 return false;
Dianne Hackborneb034652009-09-07 00:49:58 -07002594 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002595 break;
2596 }
2597 }
Dianne Hackborneb034652009-09-07 00:49:58 -07002598 if (wi == null) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -07002599 String msg = "Selected service is not a wallpaper: "
2600 + componentName;
2601 if (fromUser) {
2602 throw new SecurityException(msg);
2603 }
2604 Slog.w(TAG, msg);
2605 return false;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002606 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002607 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01002608
Lucas Dupin4c8c3272018-11-06 17:47:48 -08002609 if (wi != null && wi.supportsAmbientMode()) {
2610 final int hasPrivilege = mIPackageManager.checkPermission(
2611 android.Manifest.permission.AMBIENT_WALLPAPER, wi.getPackageName(),
2612 serviceUserId);
2613 if (hasPrivilege != PackageManager.PERMISSION_GRANTED) {
2614 String msg = "Selected service does not have "
2615 + android.Manifest.permission.AMBIENT_WALLPAPER
2616 + ": " + componentName;
2617 if (fromUser) {
2618 throw new SecurityException(msg);
2619 }
2620 Slog.w(TAG, msg);
2621 return false;
2622 }
2623 }
2624
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002625 // Bind the service!
Joe Onorato8a9b2202010-02-26 18:56:32 -08002626 if (DEBUG) Slog.v(TAG, "Binding to:" + componentName);
wilsonshihde93f492018-11-01 21:23:40 +08002627 final int componentUid = mIPackageManager.getPackageUid(componentName.getPackageName(),
2628 MATCH_DIRECT_BOOT_AUTO, wallpaper.userId);
2629 WallpaperConnection newConn = new WallpaperConnection(wi, wallpaper, componentUid);
Mike Clerona428b2c2009-11-15 22:53:08 -08002630 intent.setComponent(componentName);
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07002631 intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
2632 com.android.internal.R.string.wallpaper_binding_label);
Dianne Hackborn41203752012-08-31 14:05:51 -07002633 intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivityAsUser(
Dianne Hackborneb034652009-09-07 00:49:58 -07002634 mContext, 0,
2635 Intent.createChooser(new Intent(Intent.ACTION_SET_WALLPAPER),
2636 mContext.getText(com.android.internal.R.string.chooser_wallpaper)),
Dianne Hackborn41203752012-08-31 14:05:51 -07002637 0, null, new UserHandle(serviceUserId)));
Dianne Hackbornc8230512013-07-13 21:32:12 -07002638 if (!mContext.bindServiceAsUser(intent, newConn,
Dianne Hackbornd69e4c12015-04-24 09:54:54 -07002639 Context.BIND_AUTO_CREATE | Context.BIND_SHOWING_UI
Amith Yamasanic45a9902019-04-05 16:29:30 -07002640 | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE
2641 | Context.BIND_INCLUDE_CAPABILITIES,
Amith Yamasani27b89e62013-01-16 12:30:11 -08002642 new UserHandle(serviceUserId))) {
Dianne Hackborn80b902f2011-09-15 15:15:27 -07002643 String msg = "Unable to bind service: "
2644 + componentName;
2645 if (fromUser) {
2646 throw new IllegalArgumentException(msg);
2647 }
2648 Slog.w(TAG, msg);
2649 return false;
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002650 }
wilsonshiha282bf72018-11-30 12:48:05 +08002651 if (wallpaper.userId == mCurrentUserId && mLastWallpaper != null
2652 && !wallpaper.equals(mFallbackWallpaper)) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002653 detachWallpaperLocked(mLastWallpaper);
2654 }
2655 wallpaper.wallpaperComponent = componentName;
2656 wallpaper.connection = newConn;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002657 newConn.mReply = reply;
wilsonshiha282bf72018-11-30 12:48:05 +08002658 if (wallpaper.userId == mCurrentUserId && !wallpaper.equals(mFallbackWallpaper)) {
wilsonshihde93f492018-11-01 21:23:40 +08002659 mLastWallpaper = wallpaper;
Dianne Hackbornf21adf62009-08-13 10:20:21 -07002660 }
wilsonshiha282bf72018-11-30 12:48:05 +08002661 updateFallbackConnection();
Amith Yamasani4e2820c2012-08-28 22:17:23 -07002662 } catch (RemoteException e) {
2663 String msg = "Remote exception for " + componentName + "\n" + e;
Dianne Hackborn80b902f2011-09-15 15:15:27 -07002664 if (fromUser) {
2665 throw new IllegalArgumentException(msg);
2666 }
2667 Slog.w(TAG, msg);
2668 return false;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002669 }
Dianne Hackborn80b902f2011-09-15 15:15:27 -07002670 return true;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002671 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002672
wilsonshiha282bf72018-11-30 12:48:05 +08002673 private void detachWallpaperLocked(WallpaperData wallpaper) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002674 if (wallpaper.connection != null) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002675 if (wallpaper.connection.mReply != null) {
2676 try {
2677 wallpaper.connection.mReply.sendResult(null);
2678 } catch (RemoteException e) {
2679 }
2680 wallpaper.connection.mReply = null;
2681 }
wilsonshihb72ff9c2019-03-21 17:27:02 +08002682 try {
Keun young Parke3d2fea2019-03-29 17:42:32 -07002683 // It can be null if user switching happens before service connection.
2684 if (wallpaper.connection.mService != null) {
2685 wallpaper.connection.mService.detach();
2686 }
wilsonshihb72ff9c2019-03-21 17:27:02 +08002687 } catch (RemoteException e) {
2688 Slog.w(TAG, "Failed detaching wallpaper service ", e);
2689 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002690 mContext.unbindService(wallpaper.connection);
wilsonshiha282bf72018-11-30 12:48:05 +08002691 wallpaper.connection.forEachDisplayConnector(
2692 WallpaperConnection.DisplayConnector::disconnectLocked);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002693 wallpaper.connection.mService = null;
wilsonshihde93f492018-11-01 21:23:40 +08002694 wallpaper.connection.mDisplayConnector.clear();
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002695 wallpaper.connection = null;
wilsonshihde93f492018-11-01 21:23:40 +08002696 if (wallpaper == mLastWallpaper) mLastWallpaper = null;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002697 }
2698 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002699
wilsonshiha282bf72018-11-30 12:48:05 +08002700 private void clearWallpaperComponentLocked(WallpaperData wallpaper) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002701 wallpaper.wallpaperComponent = null;
2702 detachWallpaperLocked(wallpaper);
2703 }
2704
wilsonshiha282bf72018-11-30 12:48:05 +08002705 private void attachServiceLocked(WallpaperConnection conn, WallpaperData wallpaper) {
wilsonshihde93f492018-11-01 21:23:40 +08002706 conn.forEachDisplayConnector(connector-> connector.connectLocked(conn, wallpaper));
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002707 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002708
2709 private void notifyCallbacksLocked(WallpaperData wallpaper) {
2710 final int n = wallpaper.callbacks.beginBroadcast();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002711 for (int i = 0; i < n; i++) {
2712 try {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002713 wallpaper.callbacks.getBroadcastItem(i).onWallpaperChanged();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002714 } catch (RemoteException e) {
2715
2716 // The RemoteCallbackList will take care of removing
2717 // the dead object for us.
2718 }
2719 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002720 wallpaper.callbacks.finishBroadcast();
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002721
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002722 final Intent intent = new Intent(Intent.ACTION_WALLPAPER_CHANGED);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07002723 mContext.sendBroadcastAsUser(intent, new UserHandle(mCurrentUserId));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002724 }
2725
2726 private void checkPermission(String permission) {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002727 if (PackageManager.PERMISSION_GRANTED!= mContext.checkCallingOrSelfPermission(permission)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002728 throw new SecurityException("Access denied to process: " + Binder.getCallingPid()
2729 + ", must have permission " + permission);
2730 }
2731 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002732
Benjamin Franzf3ece362015-02-11 10:51:10 +00002733 /**
2734 * Certain user types do not support wallpapers (e.g. managed profiles). The check is
2735 * implemented through through the OP_WRITE_WALLPAPER AppOp.
2736 */
2737 public boolean isWallpaperSupported(String callingPackage) {
2738 return mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_WRITE_WALLPAPER, Binder.getCallingUid(),
2739 callingPackage) == AppOpsManager.MODE_ALLOWED;
2740 }
2741
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01002742 @Override
Christopher Tate98d609c2016-05-18 17:31:58 -07002743 public boolean isSetWallpaperAllowed(String callingPackage) {
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01002744 final PackageManager pm = mContext.getPackageManager();
2745 String[] uidPackages = pm.getPackagesForUid(Binder.getCallingUid());
2746 boolean uidMatchPackage = Arrays.asList(uidPackages).contains(callingPackage);
2747 if (!uidMatchPackage) {
2748 return false; // callingPackage was faked.
2749 }
2750
2751 final DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
2752 if (dpm.isDeviceOwnerApp(callingPackage) || dpm.isProfileOwnerApp(callingPackage)) {
2753 return true;
2754 }
2755 final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
2756 return !um.hasUserRestriction(UserManager.DISALLOW_SET_WALLPAPER);
2757 }
2758
Christopher Tated7faf532016-02-25 12:43:38 -08002759 @Override
Christopher Tate61722662016-08-10 16:13:14 -07002760 public boolean isWallpaperBackupEligible(int which, int userId) {
Christopher Tated7faf532016-02-25 12:43:38 -08002761 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
2762 throw new SecurityException("Only the system may call isWallpaperBackupEligible");
2763 }
2764
Christopher Tate61722662016-08-10 16:13:14 -07002765 WallpaperData wallpaper = (which == FLAG_LOCK)
Christopher Tatef7d1b5d2016-08-19 11:21:07 -07002766 ? mLockWallpaperMap.get(userId)
2767 : mWallpaperMap.get(userId);
Christopher Tated7faf532016-02-25 12:43:38 -08002768 return (wallpaper != null) ? wallpaper.allowBackup : false;
2769 }
2770
wilsonshih643bf132019-02-27 12:49:19 +08002771 private void onDisplayReadyInternal(int displayId) {
2772 synchronized (mLock) {
2773 if (mLastWallpaper == null) {
2774 return;
2775 }
2776 if (supportsMultiDisplay(mLastWallpaper.connection)) {
2777 final WallpaperConnection.DisplayConnector connector =
2778 mLastWallpaper.connection.getDisplayConnectorOrCreate(displayId);
2779 if (connector == null) return;
2780 connector.connectLocked(mLastWallpaper.connection, mLastWallpaper);
2781 return;
2782 }
2783 // System wallpaper does not support multiple displays, attach this display to
2784 // the fallback wallpaper.
2785 if (mFallbackWallpaper != null) {
2786 final WallpaperConnection.DisplayConnector connector = mFallbackWallpaper
2787 .connection.getDisplayConnectorOrCreate(displayId);
2788 if (connector == null) return;
2789 connector.connectLocked(mFallbackWallpaper.connection, mFallbackWallpaper);
2790 } else {
2791 Slog.w(TAG, "No wallpaper can be added to the new display");
2792 }
2793 }
2794 }
2795
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002796 private static JournaledFile makeJournaledFile(int userId) {
Amith Yamasani61f57372012-08-31 12:12:28 -07002797 final String base = new File(getWallpaperDir(userId), WALLPAPER_INFO).getAbsolutePath();
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002798 return new JournaledFile(new File(base), new File(base + ".tmp"));
2799 }
2800
Christopher Tatedb27b842016-02-25 14:39:17 -08002801 private void saveSettingsLocked(int userId) {
2802 JournaledFile journal = makeJournaledFile(userId);
2803 FileOutputStream fstream = null;
2804 BufferedOutputStream stream = null;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002805 try {
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002806 XmlSerializer out = new FastXmlSerializer();
Christopher Tatedb27b842016-02-25 14:39:17 -08002807 fstream = new FileOutputStream(journal.chooseForWrite(), false);
2808 stream = new BufferedOutputStream(fstream);
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01002809 out.setOutput(stream, StandardCharsets.UTF_8.name());
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002810 out.startDocument(null, true);
2811
Christopher Tatedb27b842016-02-25 14:39:17 -08002812 WallpaperData wallpaper;
Christopher Tate1e1e2e02016-01-25 15:34:36 -08002813
Christopher Tatedb27b842016-02-25 14:39:17 -08002814 wallpaper = mWallpaperMap.get(userId);
2815 if (wallpaper != null) {
2816 writeWallpaperAttributes(out, "wp", wallpaper);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002817 }
Christopher Tatedb27b842016-02-25 14:39:17 -08002818 wallpaper = mLockWallpaperMap.get(userId);
2819 if (wallpaper != null) {
2820 writeWallpaperAttributes(out, "kwp", wallpaper);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002821 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002822
2823 out.endDocument();
Christopher Tatedb27b842016-02-25 14:39:17 -08002824
2825 stream.flush(); // also flushes fstream
2826 FileUtils.sync(fstream);
2827 stream.close(); // also closes fstream
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002828 journal.commit();
2829 } catch (IOException e) {
Christopher Tatead3c2592016-01-20 18:13:17 -08002830 IoUtils.closeQuietly(stream);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002831 journal.rollback();
2832 }
2833 }
2834
Christopher Tatedb27b842016-02-25 14:39:17 -08002835 private void writeWallpaperAttributes(XmlSerializer out, String tag, WallpaperData wallpaper)
2836 throws IllegalArgumentException, IllegalStateException, IOException {
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002837 if (DEBUG) {
Christopher Tatef717b932017-09-11 15:52:54 -07002838 Slog.v(TAG, "writeWallpaperAttributes id=" + wallpaper.wallpaperId);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002839 }
wilsonshiha282bf72018-11-30 12:48:05 +08002840 final DisplayData wpdData = getDisplayDataOrCreate(DEFAULT_DISPLAY);
Christopher Tatedb27b842016-02-25 14:39:17 -08002841 out.startTag(null, tag);
2842 out.attribute(null, "id", Integer.toString(wallpaper.wallpaperId));
wilsonshih81e10a72018-11-15 10:54:21 +08002843 out.attribute(null, "width", Integer.toString(wpdData.mWidth));
2844 out.attribute(null, "height", Integer.toString(wpdData.mHeight));
Christopher Tatedb27b842016-02-25 14:39:17 -08002845
2846 out.attribute(null, "cropLeft", Integer.toString(wallpaper.cropHint.left));
2847 out.attribute(null, "cropTop", Integer.toString(wallpaper.cropHint.top));
2848 out.attribute(null, "cropRight", Integer.toString(wallpaper.cropHint.right));
2849 out.attribute(null, "cropBottom", Integer.toString(wallpaper.cropHint.bottom));
2850
wilsonshih81e10a72018-11-15 10:54:21 +08002851 if (wpdData.mPadding.left != 0) {
2852 out.attribute(null, "paddingLeft", Integer.toString(wpdData.mPadding.left));
Christopher Tatedb27b842016-02-25 14:39:17 -08002853 }
wilsonshih81e10a72018-11-15 10:54:21 +08002854 if (wpdData.mPadding.top != 0) {
2855 out.attribute(null, "paddingTop", Integer.toString(wpdData.mPadding.top));
Christopher Tatedb27b842016-02-25 14:39:17 -08002856 }
wilsonshih81e10a72018-11-15 10:54:21 +08002857 if (wpdData.mPadding.right != 0) {
2858 out.attribute(null, "paddingRight", Integer.toString(wpdData.mPadding.right));
Christopher Tatedb27b842016-02-25 14:39:17 -08002859 }
wilsonshih81e10a72018-11-15 10:54:21 +08002860 if (wpdData.mPadding.bottom != 0) {
2861 out.attribute(null, "paddingBottom", Integer.toString(wpdData.mPadding.bottom));
Christopher Tatedb27b842016-02-25 14:39:17 -08002862 }
2863
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002864 if (wallpaper.primaryColors != null) {
Lucas Dupin84b89d92017-05-09 12:16:19 -07002865 int colorsCount = wallpaper.primaryColors.getMainColors().size();
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002866 out.attribute(null, "colorsCount", Integer.toString(colorsCount));
2867 if (colorsCount > 0) {
2868 for (int i = 0; i < colorsCount; i++) {
Lucas Dupin84b89d92017-05-09 12:16:19 -07002869 final Color wc = wallpaper.primaryColors.getMainColors().get(i);
2870 out.attribute(null, "colorValue"+i, Integer.toString(wc.toArgb()));
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002871 }
2872 }
Lucas Dupin75ec3792017-06-29 14:07:18 -07002873 out.attribute(null, "colorHints",
Lucas Dupin84b89d92017-05-09 12:16:19 -07002874 Integer.toString(wallpaper.primaryColors.getColorHints()));
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07002875 }
2876
Christopher Tatedb27b842016-02-25 14:39:17 -08002877 out.attribute(null, "name", wallpaper.name);
2878 if (wallpaper.wallpaperComponent != null
2879 && !wallpaper.wallpaperComponent.equals(mImageWallpaper)) {
2880 out.attribute(null, "component",
2881 wallpaper.wallpaperComponent.flattenToShortString());
2882 }
Christopher Tated7faf532016-02-25 12:43:38 -08002883
2884 if (wallpaper.allowBackup) {
2885 out.attribute(null, "backup", "true");
2886 }
2887
Christopher Tatedb27b842016-02-25 14:39:17 -08002888 out.endTag(null, tag);
2889 }
2890
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002891 private void migrateFromOld() {
Christopher Tate9f224432017-08-01 16:32:49 -07002892 // Pre-N, what existed is the one we're now using as the display crop
2893 File preNWallpaper = new File(getWallpaperDir(0), WALLPAPER_CROP);
2894 // In the very-long-ago, imagery lived with the settings app
2895 File originalWallpaper = new File(WallpaperBackupHelper.WALLPAPER_IMAGE_KEY);
2896 File newWallpaper = new File(getWallpaperDir(0), WALLPAPER);
2897
2898 // Migrations from earlier wallpaper image storage schemas
2899 if (preNWallpaper.exists()) {
2900 if (!newWallpaper.exists()) {
2901 // we've got the 'wallpaper' crop file but not the nominal source image,
2902 // so do the simple "just take everything" straight copy of legacy data
2903 if (DEBUG) {
2904 Slog.i(TAG, "Migrating wallpaper schema");
2905 }
2906 FileUtils.copyFile(preNWallpaper, newWallpaper);
2907 } // else we're in the usual modern case: both source & crop exist
2908 } else if (originalWallpaper.exists()) {
2909 // VERY old schema; make sure things exist and are in the right place
2910 if (DEBUG) {
2911 Slog.i(TAG, "Migrating antique wallpaper schema");
2912 }
2913 File oldInfo = new File(WallpaperBackupHelper.WALLPAPER_INFO_KEY);
2914 if (oldInfo.exists()) {
2915 File newInfo = new File(getWallpaperDir(0), WALLPAPER_INFO);
2916 oldInfo.renameTo(newInfo);
2917 }
2918
2919 FileUtils.copyFile(originalWallpaper, preNWallpaper);
2920 originalWallpaper.renameTo(newWallpaper);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002921 }
2922 }
2923
Dianne Hackborn067e5f62014-09-07 23:14:30 -07002924 private int getAttributeInt(XmlPullParser parser, String name, int defValue) {
2925 String value = parser.getAttributeValue(null, name);
2926 if (value == null) {
2927 return defValue;
2928 }
2929 return Integer.parseInt(value);
2930 }
2931
Xiaohui Chenac531942015-05-13 13:20:52 -07002932 /**
2933 * Sometimes it is expected the wallpaper map may not have a user's data. E.g. This could
2934 * happen during user switch. The async user switch observer may not have received
2935 * the event yet. We use this safe method when we don't care about this ordering and just
2936 * want to update the data. The data is going to be applied when the user switch observer
2937 * is eventually executed.
Christopher Tatef717b932017-09-11 15:52:54 -07002938 *
2939 * Important: this method loads settings to initialize the given user's wallpaper data if
2940 * there is no current in-memory state.
Xiaohui Chenac531942015-05-13 13:20:52 -07002941 */
Christopher Tatebe132e62016-02-10 12:59:49 -08002942 private WallpaperData getWallpaperSafeLocked(int userId, int which) {
2943 // We're setting either just system (work with the system wallpaper),
2944 // both (also work with the system wallpaper), or just the lock
2945 // wallpaper (update against the existing lock wallpaper if any).
2946 // Combined or just-system operations use the 'system' WallpaperData
2947 // for this use; lock-only operations use the dedicated one.
2948 final SparseArray<WallpaperData> whichSet =
Christopher Tateedf7d042016-03-29 18:24:25 -07002949 (which == FLAG_LOCK) ? mLockWallpaperMap : mWallpaperMap;
Christopher Tatebe132e62016-02-10 12:59:49 -08002950 WallpaperData wallpaper = whichSet.get(userId);
Xiaohui Chenac531942015-05-13 13:20:52 -07002951 if (wallpaper == null) {
Christopher Tatebe132e62016-02-10 12:59:49 -08002952 // common case, this is the first lookup post-boot of the system or
2953 // unified lock, so we bring up the saved state lazily now and recheck.
Christopher Tated7faf532016-02-25 12:43:38 -08002954 loadSettingsLocked(userId, false);
Christopher Tatebe132e62016-02-10 12:59:49 -08002955 wallpaper = whichSet.get(userId);
2956 // if it's still null here, this is a lock-only operation and there is not
2957 // yet a lock-only wallpaper set for this user, so we need to establish
2958 // it now.
2959 if (wallpaper == null) {
Christopher Tateedf7d042016-03-29 18:24:25 -07002960 if (which == FLAG_LOCK) {
Christopher Tatebe132e62016-02-10 12:59:49 -08002961 wallpaper = new WallpaperData(userId,
2962 WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP);
2963 mLockWallpaperMap.put(userId, wallpaper);
wilsonshih81e10a72018-11-15 10:54:21 +08002964 ensureSaneWallpaperData(wallpaper, DEFAULT_DISPLAY);
Christopher Tatebe132e62016-02-10 12:59:49 -08002965 } else {
2966 // sanity fallback: we're in bad shape, but establishing a known
2967 // valid system+lock WallpaperData will keep us from dying.
2968 Slog.wtf(TAG, "Didn't find wallpaper in non-lock case!");
2969 wallpaper = new WallpaperData(userId, WALLPAPER, WALLPAPER_CROP);
2970 mWallpaperMap.put(userId, wallpaper);
wilsonshih81e10a72018-11-15 10:54:21 +08002971 ensureSaneWallpaperData(wallpaper, DEFAULT_DISPLAY);
Christopher Tatebe132e62016-02-10 12:59:49 -08002972 }
2973 }
Xiaohui Chenac531942015-05-13 13:20:52 -07002974 }
2975 return wallpaper;
2976 }
2977
Christopher Tated7faf532016-02-25 12:43:38 -08002978 private void loadSettingsLocked(int userId, boolean keepDimensionHints) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002979 JournaledFile journal = makeJournaledFile(userId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07002980 FileInputStream stream = null;
2981 File file = journal.chooseForRead();
Christopher Tate9f224432017-08-01 16:32:49 -07002982
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002983 WallpaperData wallpaper = mWallpaperMap.get(userId);
2984 if (wallpaper == null) {
Christopher Tate9f224432017-08-01 16:32:49 -07002985 // Do this once per boot
2986 migrateFromOld();
2987
Christopher Tatebe132e62016-02-10 12:59:49 -08002988 wallpaper = new WallpaperData(userId, WALLPAPER, WALLPAPER_CROP);
Christopher Tated7faf532016-02-25 12:43:38 -08002989 wallpaper.allowBackup = true;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002990 mWallpaperMap.put(userId, wallpaper);
Christopher Tate41297ff2016-03-10 16:46:15 -08002991 if (!wallpaper.cropExists()) {
Christopher Tate2a6c55f2017-03-31 12:28:30 -07002992 if (wallpaper.sourceExists()) {
2993 generateCrop(wallpaper);
2994 } else {
2995 Slog.i(TAG, "No static wallpaper imagery; defaults will be shown");
2996 }
Christopher Tate41297ff2016-03-10 16:46:15 -08002997 }
wilsonshiha282bf72018-11-30 12:48:05 +08002998 initializeFallbackWallpaper();
Amith Yamasani37ce3a82012-02-06 12:04:42 -08002999 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003000 boolean success = false;
wilsonshiha282bf72018-11-30 12:48:05 +08003001 final DisplayData wpdData = getDisplayDataOrCreate(DEFAULT_DISPLAY);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003002 try {
3003 stream = new FileInputStream(file);
3004 XmlPullParser parser = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01003005 parser.setInput(stream, StandardCharsets.UTF_8.name());
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003006
3007 int type;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003008 do {
3009 type = parser.next();
3010 if (type == XmlPullParser.START_TAG) {
3011 String tag = parser.getName();
3012 if ("wp".equals(tag)) {
Christopher Tatebe132e62016-02-10 12:59:49 -08003013 // Common to system + lock wallpapers
Christopher Tated7faf532016-02-25 12:43:38 -08003014 parseWallpaperAttributes(parser, wallpaper, keepDimensionHints);
Christopher Tatead3c2592016-01-20 18:13:17 -08003015
Christopher Tatebe132e62016-02-10 12:59:49 -08003016 // A system wallpaper might also be a live wallpaper
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07003017 String comp = parser.getAttributeValue(null, "component");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003018 wallpaper.nextWallpaperComponent = comp != null
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07003019 ? ComponentName.unflattenFromString(comp)
3020 : null;
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003021 if (wallpaper.nextWallpaperComponent == null
3022 || "android".equals(wallpaper.nextWallpaperComponent
3023 .getPackageName())) {
Justin Koh29c30162014-09-05 17:10:10 -07003024 wallpaper.nextWallpaperComponent = mImageWallpaper;
Dianne Hackborn9ea31632011-08-05 14:43:50 -07003025 }
Oleksandr Peletskyif2519812016-01-26 20:16:06 +01003026
Mike Clerona428b2c2009-11-15 22:53:08 -08003027 if (DEBUG) {
wilsonshih81e10a72018-11-15 10:54:21 +08003028 Slog.v(TAG, "mWidth:" + wpdData.mWidth);
3029 Slog.v(TAG, "mHeight:" + wpdData.mHeight);
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003030 Slog.v(TAG, "cropRect:" + wallpaper.cropHint);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07003031 Slog.v(TAG, "primaryColors:" + wallpaper.primaryColors);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003032 Slog.v(TAG, "mName:" + wallpaper.name);
3033 Slog.v(TAG, "mNextWallpaperComponent:"
3034 + wallpaper.nextWallpaperComponent);
Mike Clerona428b2c2009-11-15 22:53:08 -08003035 }
Christopher Tatebe132e62016-02-10 12:59:49 -08003036 } else if ("kwp".equals(tag)) {
3037 // keyguard-specific wallpaper for this user
3038 WallpaperData lockWallpaper = mLockWallpaperMap.get(userId);
3039 if (lockWallpaper == null) {
3040 lockWallpaper = new WallpaperData(userId,
3041 WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP);
3042 mLockWallpaperMap.put(userId, lockWallpaper);
3043 }
Christopher Tated7faf532016-02-25 12:43:38 -08003044 parseWallpaperAttributes(parser, lockWallpaper, false);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003045 }
3046 }
3047 } while (type != XmlPullParser.END_DOCUMENT);
3048 success = true;
Dianne Hackborn13579ed2012-11-28 18:05:36 -08003049 } catch (FileNotFoundException e) {
3050 Slog.w(TAG, "no current wallpaper -- first boot?");
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003051 } catch (NullPointerException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003052 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003053 } catch (NumberFormatException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003054 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003055 } catch (XmlPullParserException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003056 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003057 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003058 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003059 } catch (IndexOutOfBoundsException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003060 Slog.w(TAG, "failed parsing " + file + " " + e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003061 }
Christopher Tatead3c2592016-01-20 18:13:17 -08003062 IoUtils.closeQuietly(stream);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003063
3064 if (!success) {
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003065 wallpaper.cropHint.set(0, 0, 0, 0);
wilsonshih81e10a72018-11-15 10:54:21 +08003066 wpdData.mPadding.set(0, 0, 0, 0);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003067 wallpaper.name = "";
Adrian Roosc28e3a92016-04-14 10:47:52 -07003068
3069 mLockWallpaperMap.remove(userId);
Christopher Tatead3c2592016-01-20 18:13:17 -08003070 } else {
3071 if (wallpaper.wallpaperId <= 0) {
3072 wallpaper.wallpaperId = makeWallpaperIdLocked();
3073 if (DEBUG) {
3074 Slog.w(TAG, "Didn't set wallpaper id in loadSettingsLocked(" + userId
3075 + "); now " + wallpaper.wallpaperId);
3076 }
3077 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003078 }
Dianne Hackborn44bc17c2011-04-20 18:18:51 -07003079
wilsonshihd9173df2018-11-29 11:52:15 +08003080 ensureSaneWallpaperDisplaySize(wpdData, DEFAULT_DISPLAY);
wilsonshih81e10a72018-11-15 10:54:21 +08003081 ensureSaneWallpaperData(wallpaper, DEFAULT_DISPLAY);
Adrian Roosc28e3a92016-04-14 10:47:52 -07003082 WallpaperData lockWallpaper = mLockWallpaperMap.get(userId);
3083 if (lockWallpaper != null) {
wilsonshih81e10a72018-11-15 10:54:21 +08003084 ensureSaneWallpaperData(lockWallpaper, DEFAULT_DISPLAY);
Adrian Roosc28e3a92016-04-14 10:47:52 -07003085 }
3086 }
3087
wilsonshiha282bf72018-11-30 12:48:05 +08003088 private void initializeFallbackWallpaper() {
3089 if (mFallbackWallpaper == null) {
3090 if (DEBUG) Slog.d(TAG, "Initialize fallback wallpaper");
3091 mFallbackWallpaper = new WallpaperData(
3092 UserHandle.USER_SYSTEM, WALLPAPER, WALLPAPER_CROP);
3093 mFallbackWallpaper.allowBackup = false;
3094 mFallbackWallpaper.wallpaperId = makeWallpaperIdLocked();
3095 bindWallpaperComponentLocked(mImageWallpaper, true, false, mFallbackWallpaper, null);
3096 }
3097 }
3098
wilsonshih81e10a72018-11-15 10:54:21 +08003099 private void ensureSaneWallpaperData(WallpaperData wallpaper, int displayId) {
wilsonshiha282bf72018-11-30 12:48:05 +08003100 final DisplayData size = getDisplayDataOrCreate(displayId);
wilsonshih81e10a72018-11-15 10:54:21 +08003101
3102 if (displayId == DEFAULT_DISPLAY) {
3103 // crop, if not previously specified
3104 if (wallpaper.cropHint.width() <= 0
3105 || wallpaper.cropHint.height() <= 0) {
3106 wallpaper.cropHint.set(0, 0, size.mWidth, size.mHeight);
3107 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003108 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003109 }
3110
Christopher Tated7faf532016-02-25 12:43:38 -08003111 private void parseWallpaperAttributes(XmlPullParser parser, WallpaperData wallpaper,
3112 boolean keepDimensionHints) {
Christopher Tatebe132e62016-02-10 12:59:49 -08003113 final String idString = parser.getAttributeValue(null, "id");
3114 if (idString != null) {
3115 final int id = wallpaper.wallpaperId = Integer.parseInt(idString);
3116 if (id > mWallpaperId) {
3117 mWallpaperId = id;
3118 }
3119 } else {
3120 wallpaper.wallpaperId = makeWallpaperIdLocked();
3121 }
3122
wilsonshiha282bf72018-11-30 12:48:05 +08003123 final DisplayData wpData = getDisplayDataOrCreate(DEFAULT_DISPLAY);
wilsonshih81e10a72018-11-15 10:54:21 +08003124
Christopher Tated7faf532016-02-25 12:43:38 -08003125 if (!keepDimensionHints) {
wilsonshih81e10a72018-11-15 10:54:21 +08003126 wpData.mWidth = Integer.parseInt(parser.getAttributeValue(null, "width"));
3127 wpData.mHeight = Integer.parseInt(parser.getAttributeValue(null, "height"));
Christopher Tated7faf532016-02-25 12:43:38 -08003128 }
Christopher Tatebe132e62016-02-10 12:59:49 -08003129 wallpaper.cropHint.left = getAttributeInt(parser, "cropLeft", 0);
3130 wallpaper.cropHint.top = getAttributeInt(parser, "cropTop", 0);
3131 wallpaper.cropHint.right = getAttributeInt(parser, "cropRight", 0);
3132 wallpaper.cropHint.bottom = getAttributeInt(parser, "cropBottom", 0);
wilsonshih81e10a72018-11-15 10:54:21 +08003133 wpData.mPadding.left = getAttributeInt(parser, "paddingLeft", 0);
3134 wpData.mPadding.top = getAttributeInt(parser, "paddingTop", 0);
3135 wpData.mPadding.right = getAttributeInt(parser, "paddingRight", 0);
3136 wpData.mPadding.bottom = getAttributeInt(parser, "paddingBottom", 0);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07003137 int colorsCount = getAttributeInt(parser, "colorsCount", 0);
3138 if (colorsCount > 0) {
Lucas Dupin84b89d92017-05-09 12:16:19 -07003139 Color primary = null, secondary = null, tertiary = null;
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07003140 for (int i = 0; i < colorsCount; i++) {
Lucas Dupin84b89d92017-05-09 12:16:19 -07003141 Color color = Color.valueOf(getAttributeInt(parser, "colorValue" + i, 0));
3142 if (i == 0) {
3143 primary = color;
3144 } else if (i == 1) {
3145 secondary = color;
3146 } else if (i == 2) {
3147 tertiary = color;
3148 } else {
3149 break;
3150 }
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07003151 }
Lucas Dupin84b89d92017-05-09 12:16:19 -07003152 int colorHints = getAttributeInt(parser, "colorHints", 0);
3153 wallpaper.primaryColors = new WallpaperColors(primary, secondary, tertiary, colorHints);
Lucas Dupinea1fb1e2017-04-05 17:39:44 -07003154 }
Christopher Tatebe132e62016-02-10 12:59:49 -08003155 wallpaper.name = parser.getAttributeValue(null, "name");
Christopher Tated7faf532016-02-25 12:43:38 -08003156 wallpaper.allowBackup = "true".equals(parser.getAttributeValue(null, "backup"));
Christopher Tatebe132e62016-02-10 12:59:49 -08003157 }
3158
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07003159 // Called by SystemBackupAgent after files are restored to disk.
Amith Yamasani09e9cdc2013-11-06 14:54:50 -08003160 public void settingsRestored() {
3161 // Verify caller is the system
3162 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) {
3163 throw new RuntimeException("settingsRestored() can only be called from the system process");
3164 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003165 // TODO: If necessary, make it work for secondary users as well. This currently assumes
3166 // restores only to the primary user
Joe Onorato8a9b2202010-02-26 18:56:32 -08003167 if (DEBUG) Slog.v(TAG, "settingsRestored");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003168 WallpaperData wallpaper = null;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003169 boolean success = false;
3170 synchronized (mLock) {
Christopher Tated7faf532016-02-25 12:43:38 -08003171 loadSettingsLocked(UserHandle.USER_SYSTEM, false);
Christopher Tatedb27b842016-02-25 14:39:17 -08003172 wallpaper = mWallpaperMap.get(UserHandle.USER_SYSTEM);
Christopher Tatead3c2592016-01-20 18:13:17 -08003173 wallpaper.wallpaperId = makeWallpaperIdLocked(); // always bump id at restore
Christopher Tated7faf532016-02-25 12:43:38 -08003174 wallpaper.allowBackup = true; // by definition if it was restored
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003175 if (wallpaper.nextWallpaperComponent != null
Justin Koh29c30162014-09-05 17:10:10 -07003176 && !wallpaper.nextWallpaperComponent.equals(mImageWallpaper)) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003177 if (!bindWallpaperComponentLocked(wallpaper.nextWallpaperComponent, false, false,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07003178 wallpaper, null)) {
Christopher Tatee3ab4d02009-12-16 14:03:31 -08003179 // No such live wallpaper or other failure; fall back to the default
3180 // live wallpaper (since the profile being restored indicated that the
3181 // user had selected a live rather than static one).
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07003182 bindWallpaperComponentLocked(null, false, false, wallpaper, null);
Christopher Tatee3ab4d02009-12-16 14:03:31 -08003183 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003184 success = true;
3185 } else {
Mike Clerona428b2c2009-11-15 22:53:08 -08003186 // If there's a wallpaper name, we use that. If that can't be loaded, then we
3187 // use the default.
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003188 if ("".equals(wallpaper.name)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003189 if (DEBUG) Slog.v(TAG, "settingsRestored: name is empty");
Mike Clerona428b2c2009-11-15 22:53:08 -08003190 success = true;
3191 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003192 if (DEBUG) Slog.v(TAG, "settingsRestored: attempting to restore named resource");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003193 success = restoreNamedResourceLocked(wallpaper);
Mike Clerona428b2c2009-11-15 22:53:08 -08003194 }
Christopher Tatead3c2592016-01-20 18:13:17 -08003195 if (DEBUG) Slog.v(TAG, "settingsRestored: success=" + success
3196 + " id=" + wallpaper.wallpaperId);
Mike Clerona428b2c2009-11-15 22:53:08 -08003197 if (success) {
wilsonshih81e10a72018-11-15 10:54:21 +08003198 generateCrop(wallpaper); // based on the new image + metadata
Christopher Tate41297ff2016-03-10 16:46:15 -08003199 bindWallpaperComponentLocked(wallpaper.nextWallpaperComponent, true, false,
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07003200 wallpaper, null);
Mike Clerona428b2c2009-11-15 22:53:08 -08003201 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003202 }
3203 }
3204
3205 if (!success) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003206 Slog.e(TAG, "Failed to restore wallpaper: '" + wallpaper.name + "'");
3207 wallpaper.name = "";
Christopher Tatedb27b842016-02-25 14:39:17 -08003208 getWallpaperDir(UserHandle.USER_SYSTEM).delete();
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003209 }
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07003210
3211 synchronized (mLock) {
Christopher Tatedb27b842016-02-25 14:39:17 -08003212 saveSettingsLocked(UserHandle.USER_SYSTEM);
Brad Fitzpatrick194b19a2010-09-14 11:30:29 -07003213 }
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003214 }
3215
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003216 // Restore the named resource bitmap to both source + crop files
wilsonshiha282bf72018-11-30 12:48:05 +08003217 private boolean restoreNamedResourceLocked(WallpaperData wallpaper) {
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003218 if (wallpaper.name.length() > 4 && "res:".equals(wallpaper.name.substring(0, 4))) {
3219 String resName = wallpaper.name.substring(4);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003220
3221 String pkg = null;
3222 int colon = resName.indexOf(':');
3223 if (colon > 0) {
3224 pkg = resName.substring(0, colon);
3225 }
3226
3227 String ident = null;
3228 int slash = resName.lastIndexOf('/');
3229 if (slash > 0) {
3230 ident = resName.substring(slash+1);
3231 }
3232
3233 String type = null;
3234 if (colon > 0 && slash > 0 && (slash-colon) > 1) {
3235 type = resName.substring(colon+1, slash);
3236 }
3237
3238 if (pkg != null && ident != null && type != null) {
3239 int resId = -1;
3240 InputStream res = null;
3241 FileOutputStream fos = null;
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003242 FileOutputStream cos = null;
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003243 try {
3244 Context c = mContext.createPackageContext(pkg, Context.CONTEXT_RESTRICTED);
3245 Resources r = c.getResources();
3246 resId = r.getIdentifier(resName, null, null);
3247 if (resId == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003248 Slog.e(TAG, "couldn't resolve identifier pkg=" + pkg + " type=" + type
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003249 + " ident=" + ident);
3250 return false;
3251 }
3252
3253 res = r.openRawResource(resId);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003254 if (wallpaper.wallpaperFile.exists()) {
3255 wallpaper.wallpaperFile.delete();
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003256 wallpaper.cropFile.delete();
Dianne Hackborn1afd1c92010-03-18 22:47:17 -07003257 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003258 fos = new FileOutputStream(wallpaper.wallpaperFile);
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003259 cos = new FileOutputStream(wallpaper.cropFile);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003260
3261 byte[] buffer = new byte[32768];
3262 int amt;
3263 while ((amt=res.read(buffer)) > 0) {
3264 fos.write(buffer, 0, amt);
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003265 cos.write(buffer, 0, amt);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003266 }
3267 // mWallpaperObserver will notice the close and send the change broadcast
3268
Joe Onorato8a9b2202010-02-26 18:56:32 -08003269 Slog.v(TAG, "Restored wallpaper: " + resName);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003270 return true;
3271 } catch (NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003272 Slog.e(TAG, "Package name " + pkg + " not found");
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003273 } catch (Resources.NotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003274 Slog.e(TAG, "Resource not found: " + resId);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003275 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003276 Slog.e(TAG, "IOException while restoring wallpaper ", e);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003277 } finally {
Christopher Tatead3c2592016-01-20 18:13:17 -08003278 IoUtils.closeQuietly(res);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003279 if (fos != null) {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07003280 FileUtils.sync(fos);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003281 }
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003282 if (cos != null) {
3283 FileUtils.sync(cos);
3284 }
3285 IoUtils.closeQuietly(fos);
3286 IoUtils.closeQuietly(cos);
Joe Onorato9bb8fd72009-07-28 18:24:51 -07003287 }
3288 }
3289 }
3290 return false;
3291 }
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003292
Dianne Hackborneb034652009-09-07 00:49:58 -07003293 @Override
3294 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06003295 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Dianne Hackborneb034652009-09-07 00:49:58 -07003296
3297 synchronized (mLock) {
Adrian Roosc28e3a92016-04-14 10:47:52 -07003298 pw.println("System wallpaper state:");
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003299 for (int i = 0; i < mWallpaperMap.size(); i++) {
3300 WallpaperData wallpaper = mWallpaperMap.valueAt(i);
Christopher Tatead3c2592016-01-20 18:13:17 -08003301 pw.print(" User "); pw.print(wallpaper.userId);
wilsonshiha282bf72018-11-30 12:48:05 +08003302 pw.print(": id="); pw.println(wallpaper.wallpaperId);
3303 pw.println(" Display state:");
3304 forEachDisplayData(wpSize -> {
wilsonshih81e10a72018-11-15 10:54:21 +08003305 pw.print(" displayId=");
3306 pw.println(wpSize.mDisplayId);
3307 pw.print(" mWidth=");
3308 pw.print(wpSize.mWidth);
3309 pw.print(" mHeight=");
3310 pw.println(wpSize.mHeight);
3311 pw.print(" mPadding="); pw.println(wpSize.mPadding);
3312 });
Christopher Tate1e1e2e02016-01-25 15:34:36 -08003313 pw.print(" mCropHint="); pw.println(wallpaper.cropHint);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07003314 pw.print(" mName="); pw.println(wallpaper.name);
Bryan Mawhinney0fa54f42017-07-06 17:09:37 +01003315 pw.print(" mAllowBackup="); pw.println(wallpaper.allowBackup);
Dianne Hackborn067e5f62014-09-07 23:14:30 -07003316 pw.print(" mWallpaperComponent="); pw.println(wallpaper.wallpaperComponent);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003317 if (wallpaper.connection != null) {
3318 WallpaperConnection conn = wallpaper.connection;
3319 pw.print(" Wallpaper connection ");
3320 pw.print(conn);
3321 pw.println(":");
3322 if (conn.mInfo != null) {
3323 pw.print(" mInfo.component=");
3324 pw.println(conn.mInfo.getComponent());
3325 }
wilsonshihde93f492018-11-01 21:23:40 +08003326 conn.forEachDisplayConnector(connector -> {
wilsonshiha282bf72018-11-30 12:48:05 +08003327 pw.print(" mDisplayId=");
wilsonshihde93f492018-11-01 21:23:40 +08003328 pw.println(connector.mDisplayId);
wilsonshiha282bf72018-11-30 12:48:05 +08003329 pw.print(" mToken=");
wilsonshihde93f492018-11-01 21:23:40 +08003330 pw.println(connector.mToken);
wilsonshiha282bf72018-11-30 12:48:05 +08003331 pw.print(" mEngine=");
wilsonshihde93f492018-11-01 21:23:40 +08003332 pw.println(connector.mEngine);
3333 });
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003334 pw.print(" mService=");
3335 pw.println(conn.mService);
Amith Yamasani37ce3a82012-02-06 12:04:42 -08003336 pw.print(" mLastDiedTime=");
3337 pw.println(wallpaper.lastDiedTime - SystemClock.uptimeMillis());
3338 }
Dianne Hackborneb034652009-09-07 00:49:58 -07003339 }
Adrian Roosc28e3a92016-04-14 10:47:52 -07003340 pw.println("Lock wallpaper state:");
3341 for (int i = 0; i < mLockWallpaperMap.size(); i++) {
3342 WallpaperData wallpaper = mLockWallpaperMap.valueAt(i);
3343 pw.print(" User "); pw.print(wallpaper.userId);
wilsonshih81e10a72018-11-15 10:54:21 +08003344 pw.print(": id="); pw.println(wallpaper.wallpaperId);
Adrian Roosc28e3a92016-04-14 10:47:52 -07003345 pw.print(" mCropHint="); pw.println(wallpaper.cropHint);
Adrian Roosc28e3a92016-04-14 10:47:52 -07003346 pw.print(" mName="); pw.println(wallpaper.name);
Bryan Mawhinney0fa54f42017-07-06 17:09:37 +01003347 pw.print(" mAllowBackup="); pw.println(wallpaper.allowBackup);
Adrian Roosc28e3a92016-04-14 10:47:52 -07003348 }
wilsonshiha282bf72018-11-30 12:48:05 +08003349 pw.println("Fallback wallpaper state:");
3350 pw.print(" User "); pw.print(mFallbackWallpaper.userId);
3351 pw.print(": id="); pw.println(mFallbackWallpaper.wallpaperId);
3352 pw.print(" mCropHint="); pw.println(mFallbackWallpaper.cropHint);
3353 pw.print(" mName="); pw.println(mFallbackWallpaper.name);
3354 pw.print(" mAllowBackup="); pw.println(mFallbackWallpaper.allowBackup);
3355 if (mFallbackWallpaper.connection != null) {
3356 WallpaperConnection conn = mFallbackWallpaper.connection;
3357 pw.print(" Fallback Wallpaper connection ");
3358 pw.print(conn);
3359 pw.println(":");
3360 if (conn.mInfo != null) {
3361 pw.print(" mInfo.component=");
3362 pw.println(conn.mInfo.getComponent());
3363 }
3364 conn.forEachDisplayConnector(connector -> {
3365 pw.print(" mDisplayId=");
3366 pw.println(connector.mDisplayId);
3367 pw.print(" mToken=");
3368 pw.println(connector.mToken);
3369 pw.print(" mEngine=");
3370 pw.println(connector.mEngine);
3371 });
3372 pw.print(" mService=");
3373 pw.println(conn.mService);
3374 pw.print(" mLastDiedTime=");
3375 pw.println(mFallbackWallpaper.lastDiedTime - SystemClock.uptimeMillis());
3376 }
Dianne Hackborneb034652009-09-07 00:49:58 -07003377 }
3378 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003379}