blob: b8a57bfe885a04748e5314b1fe12701149196156 [file] [log] [blame]
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001/*
2 * Copyright (C) 2009 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
Dianne Hackbornba398392011-08-01 16:11:57 -070017package com.android.systemui;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070018
19import android.app.WallpaperManager;
Chet Haasec61d70e2012-10-10 15:41:57 -070020import android.content.ComponentCallbacks2;
Romain Guy407ec782011-08-24 17:06:58 -070021import android.graphics.Bitmap;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070022import android.graphics.Canvas;
Dianne Hackborn759a39e2009-08-09 17:20:27 -070023import android.graphics.Rect;
Michael Jurka824a4b52013-12-18 17:10:16 +010024import android.graphics.RectF;
Mathias Agopiane2d034c2009-09-23 21:06:17 -070025import android.graphics.Region.Op;
Adrian Roos7e9dec22016-04-13 17:43:45 -070026import android.os.AsyncTask;
Lucas Dupin41c25ce2018-03-27 09:50:19 -070027import android.os.Handler;
Jorim Jaggic5887ea2016-05-13 18:21:48 -070028import android.os.Trace;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070029import android.service.wallpaper.WallpaperService;
Dianne Hackbornc9dbbe22009-11-11 22:50:37 -080030import android.util.Log;
Michael Jurka824a4b52013-12-18 17:10:16 +010031import android.view.Display;
Adrian Roos9b9947d2015-06-09 16:46:05 -070032import android.view.DisplayInfo;
Lucas Dupin41c25ce2018-03-27 09:50:19 -070033import android.view.Surface;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070034import android.view.SurfaceHolder;
Chet Haase2f200812012-10-11 12:49:08 -070035import android.view.WindowManager;
Romain Guy407ec782011-08-24 17:06:58 -070036
Adrian Roosab6edbf2015-07-07 17:29:15 -070037import java.io.FileDescriptor;
Romain Guy407ec782011-08-24 17:06:58 -070038import java.io.IOException;
Adrian Roosab6edbf2015-07-07 17:29:15 -070039import java.io.PrintWriter;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070040
41/**
42 * Default built-in wallpaper that simply shows a static image.
43 */
Romain Guy407ec782011-08-24 17:06:58 -070044@SuppressWarnings({"UnusedDeclaration"})
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070045public class ImageWallpaper extends WallpaperService {
Jeff Brownfa2e5042011-01-23 13:14:23 -080046 private static final String TAG = "ImageWallpaper";
Romain Guy407ec782011-08-24 17:06:58 -070047 private static final String GL_LOG_TAG = "ImageWallpaperGL";
Jeff Brownfa2e5042011-01-23 13:14:23 -080048 private static final boolean DEBUG = false;
Romain Guy043a6b12011-09-27 15:37:54 -070049 private static final String PROPERTY_KERNEL_QEMU = "ro.kernel.qemu";
Lucas Dupin41c25ce2018-03-27 09:50:19 -070050 private static final long DELAY_FORGET_WALLPAPER = 5000;
Jeff Brownfa2e5042011-01-23 13:14:23 -080051
Lucas Dupin049978e2017-10-02 11:38:13 -070052 private WallpaperManager mWallpaperManager;
53 private DrawableEngine mEngine;
Dianne Hackborn759a39e2009-08-09 17:20:27 -070054
Romain Guyef654bd2009-08-11 19:12:17 -070055 @Override
56 public void onCreate() {
57 super.onCreate();
Lucas Dupin049978e2017-10-02 11:38:13 -070058 mWallpaperManager = getSystemService(WallpaperManager.class);
Romain Guyef654bd2009-08-11 19:12:17 -070059 }
60
Chet Haasec61d70e2012-10-10 15:41:57 -070061 @Override
62 public void onTrimMemory(int level) {
63 if (mEngine != null) {
64 mEngine.trimMemory(level);
65 }
66 }
67
Craig Mautnerb1ef3692012-11-16 17:31:04 -080068 @Override
Romain Guyef654bd2009-08-11 19:12:17 -070069 public Engine onCreateEngine() {
Chet Haasec61d70e2012-10-10 15:41:57 -070070 mEngine = new DrawableEngine();
71 return mEngine;
Romain Guyef654bd2009-08-11 19:12:17 -070072 }
73
74 class DrawableEngine extends Engine {
Lucas Dupin41c25ce2018-03-27 09:50:19 -070075 private final Runnable mUnloadWallpaperCallback = () -> {
76 unloadWallpaper(false /* forgetSize */);
77 };
78
Romain Guy407ec782011-08-24 17:06:58 -070079 Bitmap mBackground;
Michael Jurka824a4b52013-12-18 17:10:16 +010080 int mBackgroundWidth = -1, mBackgroundHeight = -1;
Chet Haase5f0d9762012-10-18 12:01:34 -070081 int mLastSurfaceWidth = -1, mLastSurfaceHeight = -1;
Chet Haase2f200812012-10-11 12:49:08 -070082 int mLastRotation = -1;
Lucas Dupin049978e2017-10-02 11:38:13 -070083 float mXOffset = 0f;
84 float mYOffset = 0f;
Michael Jurka824a4b52013-12-18 17:10:16 +010085 float mScale = 1f;
Romain Guyef654bd2009-08-11 19:12:17 -070086
Adrian Roos9b9947d2015-06-09 16:46:05 -070087 private Display mDefaultDisplay;
88 private final DisplayInfo mTmpDisplayInfo = new DisplayInfo();
89
Jeff Brownfa2e5042011-01-23 13:14:23 -080090 boolean mVisible = true;
Jeff Brownfa2e5042011-01-23 13:14:23 -080091 boolean mOffsetsChanged;
92 int mLastXTranslation;
93 int mLastYTranslation;
94
Adrian Roosab6edbf2015-07-07 17:29:15 -070095 private int mRotationAtLastSurfaceSizeUpdate = -1;
96 private int mDisplayWidthAtLastSurfaceSizeUpdate = -1;
97 private int mDisplayHeightAtLastSurfaceSizeUpdate = -1;
98
Adrian Roos30a7dfa2015-07-17 12:29:53 -070099 private int mLastRequestedWidth = -1;
100 private int mLastRequestedHeight = -1;
Adrian Roos7e9dec22016-04-13 17:43:45 -0700101 private AsyncTask<Void, Void, Bitmap> mLoader;
102 private boolean mNeedsDrawAfterLoadingWallpaper;
Adrian Roos53560f12016-04-28 15:22:29 -0700103 private boolean mSurfaceValid;
Lucas Dupin049978e2017-10-02 11:38:13 -0700104 private boolean mSurfaceRedrawNeeded;
Adrian Roos30a7dfa2015-07-17 12:29:53 -0700105
Lucas Dupin049978e2017-10-02 11:38:13 -0700106 DrawableEngine() {
Jeff Sharkey35be7562012-04-18 19:16:15 -0700107 super();
108 setFixedSizeAllowed(true);
109 }
110
Lucas Dupin049978e2017-10-02 11:38:13 -0700111 void trimMemory(int level) {
Jorim Jaggied0e1a62016-05-13 17:45:41 -0700112 if (level >= ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW
113 && level <= ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL
114 && mBackground != null) {
Chet Haase5f0d9762012-10-18 12:01:34 -0700115 if (DEBUG) {
116 Log.d(TAG, "trimMemory");
117 }
Adrian Roos45febbb2016-10-11 13:41:27 -0700118 unloadWallpaper(true /* forgetSize */);
Chet Haasec61d70e2012-10-10 15:41:57 -0700119 }
120 }
121
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700122 @Override
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700123 public void onCreate(SurfaceHolder surfaceHolder) {
Jeff Brown30bc34f2011-01-25 12:56:56 -0800124 if (DEBUG) {
125 Log.d(TAG, "onCreate");
126 }
127
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700128 super.onCreate(surfaceHolder);
John Spurlock209bede2013-07-17 12:23:27 -0400129
Lucas Dupin049978e2017-10-02 11:38:13 -0700130 //noinspection ConstantConditions
Adrian Roos9b9947d2015-06-09 16:46:05 -0700131 mDefaultDisplay = getSystemService(WindowManager.class).getDefaultDisplay();
Chet Haasea8e5a2b2011-10-28 13:18:16 -0700132 setOffsetNotificationsEnabled(false);
Adrian Roos7e9dec22016-04-13 17:43:45 -0700133
134 updateSurfaceSize(surfaceHolder, getDefaultDisplayInfo(), false /* forDraw */);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700135 }
136
137 @Override
Dianne Hackborn284ac932009-08-28 10:34:25 -0700138 public void onDestroy() {
139 super.onDestroy();
jshe32X7670b2b2013-10-24 12:57:09 +0800140 mBackground = null;
Adrian Roos45febbb2016-10-11 13:41:27 -0700141 unloadWallpaper(true /* forgetSize */);
Dianne Hackborn284ac932009-08-28 10:34:25 -0700142 }
143
Adrian Roos7e9dec22016-04-13 17:43:45 -0700144 boolean updateSurfaceSize(SurfaceHolder surfaceHolder, DisplayInfo displayInfo,
145 boolean forDraw) {
146 boolean hasWallpaper = true;
147
Michael Jurka824a4b52013-12-18 17:10:16 +0100148 // Load background image dimensions, if we haven't saved them yet
149 if (mBackgroundWidth <= 0 || mBackgroundHeight <= 0) {
150 // Need to load the image to get dimensions
Lucas Dupin049978e2017-10-02 11:38:13 -0700151 loadWallpaper(forDraw);
Adrian Roos7e9dec22016-04-13 17:43:45 -0700152 if (DEBUG) {
153 Log.d(TAG, "Reloading, redoing updateSurfaceSize later.");
Michael Jurka824a4b52013-12-18 17:10:16 +0100154 }
Adrian Roos7e9dec22016-04-13 17:43:45 -0700155 hasWallpaper = false;
Michael Jurka824a4b52013-12-18 17:10:16 +0100156 }
157
158 // Force the wallpaper to cover the screen in both dimensions
Adrian Roos9b9947d2015-06-09 16:46:05 -0700159 int surfaceWidth = Math.max(displayInfo.logicalWidth, mBackgroundWidth);
160 int surfaceHeight = Math.max(displayInfo.logicalHeight, mBackgroundHeight);
Michael Jurka824a4b52013-12-18 17:10:16 +0100161
Lucas Dupin049978e2017-10-02 11:38:13 -0700162 // Used a fixed size surface, because we are special. We can do
163 // this because we know the current design of window animations doesn't
164 // cause this to break.
165 surfaceHolder.setFixedSize(surfaceWidth, surfaceHeight);
166 mLastRequestedWidth = surfaceWidth;
167 mLastRequestedHeight = surfaceHeight;
168
Adrian Roos7e9dec22016-04-13 17:43:45 -0700169 return hasWallpaper;
Dianne Hackbornac1471a2011-02-03 13:46:06 -0800170 }
171
172 @Override
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700173 public void onVisibilityChanged(boolean visible) {
Jeff Brown30bc34f2011-01-25 12:56:56 -0800174 if (DEBUG) {
Chet Haase2f200812012-10-11 12:49:08 -0700175 Log.d(TAG, "onVisibilityChanged: mVisible, visible=" + mVisible + ", " + visible);
Jeff Brown30bc34f2011-01-25 12:56:56 -0800176 }
177
Craig Mautnerb1ef3692012-11-16 17:31:04 -0800178 if (mVisible != visible) {
179 if (DEBUG) {
180 Log.d(TAG, "Visibility changed to visible=" + visible);
Jeff Brown30bc34f2011-01-25 12:56:56 -0800181 }
Craig Mautnerb1ef3692012-11-16 17:31:04 -0800182 mVisible = visible;
longyu.huang6b53fd22015-05-06 01:46:23 -0700183 if (visible) {
184 drawFrame();
185 }
Jeff Brownfa2e5042011-01-23 13:14:23 -0800186 }
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700187 }
Jeff Brownfa2e5042011-01-23 13:14:23 -0800188
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700189 @Override
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700190 public void onOffsetsChanged(float xOffset, float yOffset,
Marco Nelissenbf6956b2009-11-09 15:21:13 -0800191 float xOffsetStep, float yOffsetStep,
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700192 int xPixels, int yPixels) {
Jeff Brown30bc34f2011-01-25 12:56:56 -0800193 if (DEBUG) {
194 Log.d(TAG, "onOffsetsChanged: xOffset=" + xOffset + ", yOffset=" + yOffset
195 + ", xOffsetStep=" + xOffsetStep + ", yOffsetStep=" + yOffsetStep
196 + ", xPixels=" + xPixels + ", yPixels=" + yPixels);
197 }
198
Craig Mautnerb1ef3692012-11-16 17:31:04 -0800199 if (mXOffset != xOffset || mYOffset != yOffset) {
200 if (DEBUG) {
201 Log.d(TAG, "Offsets changed to (" + xOffset + "," + yOffset + ").");
Jeff Brownfa2e5042011-01-23 13:14:23 -0800202 }
Craig Mautnerb1ef3692012-11-16 17:31:04 -0800203 mXOffset = xOffset;
204 mYOffset = yOffset;
205 mOffsetsChanged = true;
Jeff Brownfa2e5042011-01-23 13:14:23 -0800206 }
Craig Mautnerb1ef3692012-11-16 17:31:04 -0800207 drawFrame();
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700208 }
209
210 @Override
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700211 public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Jeff Brown30bc34f2011-01-25 12:56:56 -0800212 if (DEBUG) {
213 Log.d(TAG, "onSurfaceChanged: width=" + width + ", height=" + height);
214 }
215
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700216 super.onSurfaceChanged(holder, format, width, height);
Jeff Brown30bc34f2011-01-25 12:56:56 -0800217
Craig Mautnerb1ef3692012-11-16 17:31:04 -0800218 drawFrame();
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700219 }
220
Craig Mautnerfb729c72012-10-01 09:39:43 -0700221 @Override
Chet Haase2f200812012-10-11 12:49:08 -0700222 public void onSurfaceDestroyed(SurfaceHolder holder) {
223 super.onSurfaceDestroyed(holder);
Adrian Roos53560f12016-04-28 15:22:29 -0700224 if (DEBUG) {
225 Log.i(TAG, "onSurfaceDestroyed");
226 }
227
Chet Haase5f0d9762012-10-18 12:01:34 -0700228 mLastSurfaceWidth = mLastSurfaceHeight = -1;
Adrian Roos53560f12016-04-28 15:22:29 -0700229 mSurfaceValid = false;
Chet Haase2f200812012-10-11 12:49:08 -0700230 }
231
232 @Override
233 public void onSurfaceCreated(SurfaceHolder holder) {
234 super.onSurfaceCreated(holder);
Adrian Roos53560f12016-04-28 15:22:29 -0700235 if (DEBUG) {
236 Log.i(TAG, "onSurfaceCreated");
237 }
238
Chet Haase5f0d9762012-10-18 12:01:34 -0700239 mLastSurfaceWidth = mLastSurfaceHeight = -1;
Adrian Roos53560f12016-04-28 15:22:29 -0700240 mSurfaceValid = true;
Chet Haase2f200812012-10-11 12:49:08 -0700241 }
242
243 @Override
Craig Mautnerfb729c72012-10-01 09:39:43 -0700244 public void onSurfaceRedrawNeeded(SurfaceHolder holder) {
245 if (DEBUG) {
Chet Haase2f200812012-10-11 12:49:08 -0700246 Log.d(TAG, "onSurfaceRedrawNeeded");
Craig Mautnerfb729c72012-10-01 09:39:43 -0700247 }
248 super.onSurfaceRedrawNeeded(holder);
Lucas Dupin049978e2017-10-02 11:38:13 -0700249 // At the end of this method we should have drawn into the surface.
250 // This means that the bitmap should be loaded synchronously if
251 // it was already unloaded.
252 if (mBackground == null) {
253 updateBitmap(mWallpaperManager.getBitmap(true /* hardware */));
254 }
255 mSurfaceRedrawNeeded = true;
Craig Mautnerb1ef3692012-11-16 17:31:04 -0800256 drawFrame();
Craig Mautnerfb729c72012-10-01 09:39:43 -0700257 }
258
Adrian Roos9b9947d2015-06-09 16:46:05 -0700259 private DisplayInfo getDefaultDisplayInfo() {
260 mDefaultDisplay.getDisplayInfo(mTmpDisplayInfo);
261 return mTmpDisplayInfo;
Michael Jurka824a4b52013-12-18 17:10:16 +0100262 }
263
Craig Mautnerb1ef3692012-11-16 17:31:04 -0800264 void drawFrame() {
Adrian Roos53560f12016-04-28 15:22:29 -0700265 if (!mSurfaceValid) {
266 return;
267 }
Adrian Roos2acaeda2014-11-12 18:02:42 +0100268 try {
Jorim Jaggic5887ea2016-05-13 18:21:48 -0700269 Trace.traceBegin(Trace.TRACE_TAG_VIEW, "drawWallpaper");
Adrian Roos9b9947d2015-06-09 16:46:05 -0700270 DisplayInfo displayInfo = getDefaultDisplayInfo();
271 int newRotation = displayInfo.rotation;
Michael Jurka824a4b52013-12-18 17:10:16 +0100272
Adrian Roos2acaeda2014-11-12 18:02:42 +0100273 // Sometimes a wallpaper is not large enough to cover the screen in one dimension.
274 // Call updateSurfaceSize -- it will only actually do the update if the dimensions
275 // should change
276 if (newRotation != mLastRotation) {
277 // Update surface size (if necessary)
Adrian Roos7e9dec22016-04-13 17:43:45 -0700278 if (!updateSurfaceSize(getSurfaceHolder(), displayInfo, true /* forDraw */)) {
279 return; // had to reload wallpaper, will retry later
280 }
Adrian Roosab6edbf2015-07-07 17:29:15 -0700281 mRotationAtLastSurfaceSizeUpdate = newRotation;
282 mDisplayWidthAtLastSurfaceSizeUpdate = displayInfo.logicalWidth;
283 mDisplayHeightAtLastSurfaceSizeUpdate = displayInfo.logicalHeight;
Chet Haase2f200812012-10-11 12:49:08 -0700284 }
Adrian Roos2acaeda2014-11-12 18:02:42 +0100285 SurfaceHolder sh = getSurfaceHolder();
286 final Rect frame = sh.getSurfaceFrame();
287 final int dw = frame.width();
288 final int dh = frame.height();
289 boolean surfaceDimensionsChanged = dw != mLastSurfaceWidth
290 || dh != mLastSurfaceHeight;
Chet Haase2f200812012-10-11 12:49:08 -0700291
Lucas Dupin049978e2017-10-02 11:38:13 -0700292 boolean redrawNeeded = surfaceDimensionsChanged || newRotation != mLastRotation
293 || mSurfaceRedrawNeeded;
Adrian Roos2acaeda2014-11-12 18:02:42 +0100294 if (!redrawNeeded && !mOffsetsChanged) {
Chet Haase5f0d9762012-10-18 12:01:34 -0700295 if (DEBUG) {
Adrian Roos2acaeda2014-11-12 18:02:42 +0100296 Log.d(TAG, "Suppressed drawFrame since redraw is not needed "
297 + "and offsets have not changed.");
Chet Haase5f0d9762012-10-18 12:01:34 -0700298 }
299 return;
300 }
Adrian Roos2acaeda2014-11-12 18:02:42 +0100301 mLastRotation = newRotation;
Lucas Dupin049978e2017-10-02 11:38:13 -0700302 mSurfaceRedrawNeeded = false;
Adrian Roos2acaeda2014-11-12 18:02:42 +0100303
Adrian Roos7e9dec22016-04-13 17:43:45 -0700304 // Load bitmap if it is not yet loaded
305 if (mBackground == null) {
Lucas Dupin049978e2017-10-02 11:38:13 -0700306 loadWallpaper(true);
Adrian Roos2acaeda2014-11-12 18:02:42 +0100307 if (DEBUG) {
Adrian Roos7e9dec22016-04-13 17:43:45 -0700308 Log.d(TAG, "Reloading, resuming draw later");
Chet Haase5f0d9762012-10-18 12:01:34 -0700309 }
Adrian Roos7e9dec22016-04-13 17:43:45 -0700310 return;
Chet Haase5f0d9762012-10-18 12:01:34 -0700311 }
Chet Haase2f200812012-10-11 12:49:08 -0700312
Lucas Dupin049978e2017-10-02 11:38:13 -0700313 // Left align the scaled image
Adrian Roos2acaeda2014-11-12 18:02:42 +0100314 mScale = Math.max(1f, Math.max(dw / (float) mBackground.getWidth(),
315 dh / (float) mBackground.getHeight()));
Lucas Dupin049978e2017-10-02 11:38:13 -0700316 final int availw = (int) (mBackground.getWidth() * mScale) - dw;
317 final int availh = (int) (mBackground.getHeight() * mScale) - dh;
318 int xPixels = (int) (availw * mXOffset);
319 int yPixels = (int) (availh * mYOffset);
Jeff Brown033f63a2011-01-23 22:01:49 -0800320
Adrian Roos2acaeda2014-11-12 18:02:42 +0100321 mOffsetsChanged = false;
Adrian Roos2acaeda2014-11-12 18:02:42 +0100322 if (surfaceDimensionsChanged) {
323 mLastSurfaceWidth = dw;
324 mLastSurfaceHeight = dh;
Jeff Brown033f63a2011-01-23 22:01:49 -0800325 }
Adrian Roos2acaeda2014-11-12 18:02:42 +0100326 if (!redrawNeeded && xPixels == mLastXTranslation && yPixels == mLastYTranslation) {
327 if (DEBUG) {
328 Log.d(TAG, "Suppressed drawFrame since the image has not "
329 + "actually moved an integral number of pixels.");
330 }
331 return;
332 }
333 mLastXTranslation = xPixels;
334 mLastYTranslation = yPixels;
Jeff Brown033f63a2011-01-23 22:01:49 -0800335
Adrian Roos2acaeda2014-11-12 18:02:42 +0100336 if (DEBUG) {
337 Log.d(TAG, "Redrawing wallpaper");
338 }
Wim Vander Schelden9549c062013-02-07 15:51:51 +0000339
Lucas Dupin049978e2017-10-02 11:38:13 -0700340 drawWallpaperWithCanvas(sh, availw, availh, xPixels, yPixels);
Lucas Dupin41c25ce2018-03-27 09:50:19 -0700341 scheduleUnloadWallpaper();
Adrian Roos2acaeda2014-11-12 18:02:42 +0100342 } finally {
Jorim Jaggic5887ea2016-05-13 18:21:48 -0700343 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700344 }
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700345 }
Romain Guyef654bd2009-08-11 19:12:17 -0700346
Adrian Roos7e9dec22016-04-13 17:43:45 -0700347 /**
348 * Loads the wallpaper on background thread and schedules updating the surface frame,
349 * and if {@param needsDraw} is set also draws a frame.
350 *
351 * If loading is already in-flight, subsequent loads are ignored (but needDraw is or-ed to
352 * the active request).
Adrian Roos45febbb2016-10-11 13:41:27 -0700353 *
354 * If {@param needsReset} is set also clears the cache in WallpaperManager first.
Adrian Roos7e9dec22016-04-13 17:43:45 -0700355 */
Lucas Dupin049978e2017-10-02 11:38:13 -0700356 private void loadWallpaper(boolean needsDraw) {
Adrian Roos7e9dec22016-04-13 17:43:45 -0700357 mNeedsDrawAfterLoadingWallpaper |= needsDraw;
358 if (mLoader != null) {
Lucas Dupin049978e2017-10-02 11:38:13 -0700359 if (DEBUG) {
360 Log.d(TAG, "Skipping loadWallpaper, already in flight ");
Dianne Hackbornc9dbbe22009-11-11 22:50:37 -0800361 }
Lucas Dupin049978e2017-10-02 11:38:13 -0700362 return;
Romain Guyef654bd2009-08-11 19:12:17 -0700363 }
Adrian Roos7e9dec22016-04-13 17:43:45 -0700364 mLoader = new AsyncTask<Void, Void, Bitmap>() {
365 @Override
366 protected Bitmap doInBackground(Void... params) {
367 Throwable exception;
368 try {
Lucas Dupin049978e2017-10-02 11:38:13 -0700369 return mWallpaperManager.getBitmap(true /* hardware */);
Adrian Roos7e9dec22016-04-13 17:43:45 -0700370 } catch (RuntimeException | OutOfMemoryError e) {
371 exception = e;
372 }
373
Adrian Roos45febbb2016-10-11 13:41:27 -0700374 if (isCancelled()) {
375 return null;
376 }
377
Lucas Dupin049978e2017-10-02 11:38:13 -0700378 // Note that if we do fail at this, and the default wallpaper can't
379 // be loaded, we will go into a cycle. Don't do a build where the
380 // default wallpaper can't be loaded.
381 Log.w(TAG, "Unable to load wallpaper!", exception);
382 try {
383 mWallpaperManager.clear();
384 } catch (IOException ex) {
385 // now we're really screwed.
386 Log.w(TAG, "Unable reset to default wallpaper!", ex);
387 }
Adrian Roos7e9dec22016-04-13 17:43:45 -0700388
Lucas Dupin049978e2017-10-02 11:38:13 -0700389 if (isCancelled()) {
390 return null;
391 }
Adrian Roos45febbb2016-10-11 13:41:27 -0700392
Lucas Dupin049978e2017-10-02 11:38:13 -0700393 try {
394 return mWallpaperManager.getBitmap(true /* hardware */);
395 } catch (RuntimeException | OutOfMemoryError e) {
396 Log.w(TAG, "Unable to load default wallpaper!", e);
Adrian Roos7e9dec22016-04-13 17:43:45 -0700397 }
398 return null;
399 }
400
401 @Override
402 protected void onPostExecute(Bitmap b) {
Lucas Dupin049978e2017-10-02 11:38:13 -0700403 updateBitmap(b);
Adrian Roos7e9dec22016-04-13 17:43:45 -0700404
Adrian Roos7e9dec22016-04-13 17:43:45 -0700405 if (mNeedsDrawAfterLoadingWallpaper) {
406 drawFrame();
407 }
408
409 mLoader = null;
410 mNeedsDrawAfterLoadingWallpaper = false;
411 }
412 }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
Romain Guy407ec782011-08-24 17:06:58 -0700413 }
414
Lucas Dupin049978e2017-10-02 11:38:13 -0700415 private void updateBitmap(Bitmap bitmap) {
416 mBackground = null;
417 mBackgroundWidth = -1;
418 mBackgroundHeight = -1;
419
420 if (bitmap != null) {
421 mBackground = bitmap;
422 mBackgroundWidth = mBackground.getWidth();
423 mBackgroundHeight = mBackground.getHeight();
424 }
425
426 if (DEBUG) {
427 Log.d(TAG, "Wallpaper loaded: " + mBackground);
428 }
429 updateSurfaceSize(getSurfaceHolder(), getDefaultDisplayInfo(),
430 false /* forDraw */);
431 }
432
Adrian Roos45febbb2016-10-11 13:41:27 -0700433 private void unloadWallpaper(boolean forgetSize) {
434 if (mLoader != null) {
435 mLoader.cancel(false);
436 mLoader = null;
437 }
438 mBackground = null;
439 if (forgetSize) {
440 mBackgroundWidth = -1;
441 mBackgroundHeight = -1;
442 }
443
Lucas Dupin41c25ce2018-03-27 09:50:19 -0700444 final Surface surface = getSurfaceHolder().getSurface();
445 surface.hwuiDestroy();
446
Lucas Dupin61df45c2018-04-07 11:08:15 -0700447 mWallpaperManager.forgetLoadedWallpaper();
Adrian Roos45febbb2016-10-11 13:41:27 -0700448 }
449
Lucas Dupin41c25ce2018-03-27 09:50:19 -0700450 private void scheduleUnloadWallpaper() {
451 Handler handler = getMainThreadHandler();
452 handler.removeCallbacks(mUnloadWallpaperCallback);
453 handler.postDelayed(mUnloadWallpaperCallback, DELAY_FORGET_WALLPAPER);
454 }
455
Adrian Roosab6edbf2015-07-07 17:29:15 -0700456 @Override
457 protected void dump(String prefix, FileDescriptor fd, PrintWriter out, String[] args) {
458 super.dump(prefix, fd, out, args);
459
460 out.print(prefix); out.println("ImageWallpaper.DrawableEngine:");
461 out.print(prefix); out.print(" mBackground="); out.print(mBackground);
462 out.print(" mBackgroundWidth="); out.print(mBackgroundWidth);
463 out.print(" mBackgroundHeight="); out.println(mBackgroundHeight);
464
465 out.print(prefix); out.print(" mLastRotation="); out.print(mLastRotation);
466 out.print(" mLastSurfaceWidth="); out.print(mLastSurfaceWidth);
467 out.print(" mLastSurfaceHeight="); out.println(mLastSurfaceHeight);
468
469 out.print(prefix); out.print(" mXOffset="); out.print(mXOffset);
470 out.print(" mYOffset="); out.println(mYOffset);
471
472 out.print(prefix); out.print(" mVisible="); out.print(mVisible);
Adrian Roosab6edbf2015-07-07 17:29:15 -0700473 out.print(" mOffsetsChanged="); out.println(mOffsetsChanged);
474
475 out.print(prefix); out.print(" mLastXTranslation="); out.print(mLastXTranslation);
476 out.print(" mLastYTranslation="); out.print(mLastYTranslation);
477 out.print(" mScale="); out.println(mScale);
478
Adrian Roos30a7dfa2015-07-17 12:29:53 -0700479 out.print(prefix); out.print(" mLastRequestedWidth="); out.print(mLastRequestedWidth);
480 out.print(" mLastRequestedHeight="); out.println(mLastRequestedHeight);
481
Adrian Roosab6edbf2015-07-07 17:29:15 -0700482 out.print(prefix); out.println(" DisplayInfo at last updateSurfaceSize:");
483 out.print(prefix);
484 out.print(" rotation="); out.print(mRotationAtLastSurfaceSizeUpdate);
485 out.print(" width="); out.print(mDisplayWidthAtLastSurfaceSizeUpdate);
486 out.print(" height="); out.println(mDisplayHeightAtLastSurfaceSizeUpdate);
487 }
488
Michael Jurka824a4b52013-12-18 17:10:16 +0100489 private void drawWallpaperWithCanvas(SurfaceHolder sh, int w, int h, int left, int top) {
Lucas Dupin049978e2017-10-02 11:38:13 -0700490 Canvas c = sh.lockHardwareCanvas();
Romain Guy407ec782011-08-24 17:06:58 -0700491 if (c != null) {
492 try {
493 if (DEBUG) {
Michael Jurka824a4b52013-12-18 17:10:16 +0100494 Log.d(TAG, "Redrawing: left=" + left + ", top=" + top);
Romain Guy407ec782011-08-24 17:06:58 -0700495 }
496
Michael Jurka824a4b52013-12-18 17:10:16 +0100497 final float right = left + mBackground.getWidth() * mScale;
498 final float bottom = top + mBackground.getHeight() * mScale;
Romain Guy407ec782011-08-24 17:06:58 -0700499 if (w < 0 || h < 0) {
500 c.save(Canvas.CLIP_SAVE_FLAG);
Michael Jurka824a4b52013-12-18 17:10:16 +0100501 c.clipRect(left, top, right, bottom,
Chet Haase5f0d9762012-10-18 12:01:34 -0700502 Op.DIFFERENCE);
Romain Guy407ec782011-08-24 17:06:58 -0700503 c.drawColor(0xff000000);
504 c.restore();
505 }
506 if (mBackground != null) {
Michael Jurka824a4b52013-12-18 17:10:16 +0100507 RectF dest = new RectF(left, top, right, bottom);
Lucas Dupinba130952017-12-14 14:50:11 -0800508 Log.i(TAG, "Redrawing in rect: " + dest + " with surface size: "
509 + mLastRequestedWidth + "x" + mLastRequestedHeight);
Michael Jurka824a4b52013-12-18 17:10:16 +0100510 c.drawBitmap(mBackground, null, dest, null);
Romain Guy407ec782011-08-24 17:06:58 -0700511 }
512 } finally {
513 sh.unlockCanvasAndPost(c);
514 }
515 }
516 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700517 }
518}