Dianne Hackborn | 4c62fc0 | 2009-08-08 20:40:27 -0700 | [diff] [blame] | 1 | /* |
| 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 Hackborn | ba39839 | 2011-08-01 16:11:57 -0700 | [diff] [blame] | 17 | package com.android.systemui; |
Dianne Hackborn | 4c62fc0 | 2009-08-08 20:40:27 -0700 | [diff] [blame] | 18 | |
| 19 | import android.app.WallpaperManager; |
Chet Haase | c61d70e | 2012-10-10 15:41:57 -0700 | [diff] [blame] | 20 | import android.content.ComponentCallbacks2; |
Romain Guy | 407ec78 | 2011-08-24 17:06:58 -0700 | [diff] [blame] | 21 | import android.graphics.Bitmap; |
Dianne Hackborn | 4c62fc0 | 2009-08-08 20:40:27 -0700 | [diff] [blame] | 22 | import android.graphics.Canvas; |
Dianne Hackborn | 759a39e | 2009-08-09 17:20:27 -0700 | [diff] [blame] | 23 | import android.graphics.Rect; |
Michael Jurka | 824a4b5 | 2013-12-18 17:10:16 +0100 | [diff] [blame] | 24 | import android.graphics.RectF; |
Mathias Agopian | e2d034c | 2009-09-23 21:06:17 -0700 | [diff] [blame] | 25 | import android.graphics.Region.Op; |
Adrian Roos | 7e9dec2 | 2016-04-13 17:43:45 -0700 | [diff] [blame] | 26 | import android.os.AsyncTask; |
Lucas Dupin | 41c25ce | 2018-03-27 09:50:19 -0700 | [diff] [blame] | 27 | import android.os.Handler; |
Jorim Jaggi | c5887ea | 2016-05-13 18:21:48 -0700 | [diff] [blame] | 28 | import android.os.Trace; |
Dianne Hackborn | 4c62fc0 | 2009-08-08 20:40:27 -0700 | [diff] [blame] | 29 | import android.service.wallpaper.WallpaperService; |
Dianne Hackborn | c9dbbe2 | 2009-11-11 22:50:37 -0800 | [diff] [blame] | 30 | import android.util.Log; |
Michael Jurka | 824a4b5 | 2013-12-18 17:10:16 +0100 | [diff] [blame] | 31 | import android.view.Display; |
Adrian Roos | 9b9947d | 2015-06-09 16:46:05 -0700 | [diff] [blame] | 32 | import android.view.DisplayInfo; |
Lucas Dupin | 41c25ce | 2018-03-27 09:50:19 -0700 | [diff] [blame] | 33 | import android.view.Surface; |
Dianne Hackborn | 4c62fc0 | 2009-08-08 20:40:27 -0700 | [diff] [blame] | 34 | import android.view.SurfaceHolder; |
Chet Haase | 2f20081 | 2012-10-11 12:49:08 -0700 | [diff] [blame] | 35 | import android.view.WindowManager; |
Romain Guy | 407ec78 | 2011-08-24 17:06:58 -0700 | [diff] [blame] | 36 | |
Adrian Roos | ab6edbf | 2015-07-07 17:29:15 -0700 | [diff] [blame] | 37 | import java.io.FileDescriptor; |
Romain Guy | 407ec78 | 2011-08-24 17:06:58 -0700 | [diff] [blame] | 38 | import java.io.IOException; |
Adrian Roos | ab6edbf | 2015-07-07 17:29:15 -0700 | [diff] [blame] | 39 | import java.io.PrintWriter; |
Dianne Hackborn | 4c62fc0 | 2009-08-08 20:40:27 -0700 | [diff] [blame] | 40 | |
| 41 | /** |
| 42 | * Default built-in wallpaper that simply shows a static image. |
| 43 | */ |
Romain Guy | 407ec78 | 2011-08-24 17:06:58 -0700 | [diff] [blame] | 44 | @SuppressWarnings({"UnusedDeclaration"}) |
Dianne Hackborn | 4c62fc0 | 2009-08-08 20:40:27 -0700 | [diff] [blame] | 45 | public class ImageWallpaper extends WallpaperService { |
Jeff Brown | fa2e504 | 2011-01-23 13:14:23 -0800 | [diff] [blame] | 46 | private static final String TAG = "ImageWallpaper"; |
Romain Guy | 407ec78 | 2011-08-24 17:06:58 -0700 | [diff] [blame] | 47 | private static final String GL_LOG_TAG = "ImageWallpaperGL"; |
Jeff Brown | fa2e504 | 2011-01-23 13:14:23 -0800 | [diff] [blame] | 48 | private static final boolean DEBUG = false; |
Romain Guy | 043a6b1 | 2011-09-27 15:37:54 -0700 | [diff] [blame] | 49 | private static final String PROPERTY_KERNEL_QEMU = "ro.kernel.qemu"; |
Lucas Dupin | 41c25ce | 2018-03-27 09:50:19 -0700 | [diff] [blame] | 50 | private static final long DELAY_FORGET_WALLPAPER = 5000; |
Jeff Brown | fa2e504 | 2011-01-23 13:14:23 -0800 | [diff] [blame] | 51 | |
Lucas Dupin | 049978e | 2017-10-02 11:38:13 -0700 | [diff] [blame] | 52 | private WallpaperManager mWallpaperManager; |
| 53 | private DrawableEngine mEngine; |
Dianne Hackborn | 759a39e | 2009-08-09 17:20:27 -0700 | [diff] [blame] | 54 | |
Romain Guy | ef654bd | 2009-08-11 19:12:17 -0700 | [diff] [blame] | 55 | @Override |
| 56 | public void onCreate() { |
| 57 | super.onCreate(); |
Lucas Dupin | 049978e | 2017-10-02 11:38:13 -0700 | [diff] [blame] | 58 | mWallpaperManager = getSystemService(WallpaperManager.class); |
Romain Guy | ef654bd | 2009-08-11 19:12:17 -0700 | [diff] [blame] | 59 | } |
| 60 | |
Chet Haase | c61d70e | 2012-10-10 15:41:57 -0700 | [diff] [blame] | 61 | @Override |
| 62 | public void onTrimMemory(int level) { |
| 63 | if (mEngine != null) { |
| 64 | mEngine.trimMemory(level); |
| 65 | } |
| 66 | } |
| 67 | |
Craig Mautner | b1ef369 | 2012-11-16 17:31:04 -0800 | [diff] [blame] | 68 | @Override |
Romain Guy | ef654bd | 2009-08-11 19:12:17 -0700 | [diff] [blame] | 69 | public Engine onCreateEngine() { |
Chet Haase | c61d70e | 2012-10-10 15:41:57 -0700 | [diff] [blame] | 70 | mEngine = new DrawableEngine(); |
| 71 | return mEngine; |
Romain Guy | ef654bd | 2009-08-11 19:12:17 -0700 | [diff] [blame] | 72 | } |
| 73 | |
| 74 | class DrawableEngine extends Engine { |
Lucas Dupin | 41c25ce | 2018-03-27 09:50:19 -0700 | [diff] [blame] | 75 | private final Runnable mUnloadWallpaperCallback = () -> { |
| 76 | unloadWallpaper(false /* forgetSize */); |
| 77 | }; |
| 78 | |
Romain Guy | 407ec78 | 2011-08-24 17:06:58 -0700 | [diff] [blame] | 79 | Bitmap mBackground; |
Michael Jurka | 824a4b5 | 2013-12-18 17:10:16 +0100 | [diff] [blame] | 80 | int mBackgroundWidth = -1, mBackgroundHeight = -1; |
Chet Haase | 5f0d976 | 2012-10-18 12:01:34 -0700 | [diff] [blame] | 81 | int mLastSurfaceWidth = -1, mLastSurfaceHeight = -1; |
Chet Haase | 2f20081 | 2012-10-11 12:49:08 -0700 | [diff] [blame] | 82 | int mLastRotation = -1; |
Lucas Dupin | 049978e | 2017-10-02 11:38:13 -0700 | [diff] [blame] | 83 | float mXOffset = 0f; |
| 84 | float mYOffset = 0f; |
Michael Jurka | 824a4b5 | 2013-12-18 17:10:16 +0100 | [diff] [blame] | 85 | float mScale = 1f; |
Romain Guy | ef654bd | 2009-08-11 19:12:17 -0700 | [diff] [blame] | 86 | |
Adrian Roos | 9b9947d | 2015-06-09 16:46:05 -0700 | [diff] [blame] | 87 | private Display mDefaultDisplay; |
| 88 | private final DisplayInfo mTmpDisplayInfo = new DisplayInfo(); |
| 89 | |
Jeff Brown | fa2e504 | 2011-01-23 13:14:23 -0800 | [diff] [blame] | 90 | boolean mVisible = true; |
Jeff Brown | fa2e504 | 2011-01-23 13:14:23 -0800 | [diff] [blame] | 91 | boolean mOffsetsChanged; |
| 92 | int mLastXTranslation; |
| 93 | int mLastYTranslation; |
| 94 | |
Adrian Roos | ab6edbf | 2015-07-07 17:29:15 -0700 | [diff] [blame] | 95 | private int mRotationAtLastSurfaceSizeUpdate = -1; |
| 96 | private int mDisplayWidthAtLastSurfaceSizeUpdate = -1; |
| 97 | private int mDisplayHeightAtLastSurfaceSizeUpdate = -1; |
| 98 | |
Adrian Roos | 30a7dfa | 2015-07-17 12:29:53 -0700 | [diff] [blame] | 99 | private int mLastRequestedWidth = -1; |
| 100 | private int mLastRequestedHeight = -1; |
Adrian Roos | 7e9dec2 | 2016-04-13 17:43:45 -0700 | [diff] [blame] | 101 | private AsyncTask<Void, Void, Bitmap> mLoader; |
| 102 | private boolean mNeedsDrawAfterLoadingWallpaper; |
Adrian Roos | 53560f1 | 2016-04-28 15:22:29 -0700 | [diff] [blame] | 103 | private boolean mSurfaceValid; |
Lucas Dupin | 049978e | 2017-10-02 11:38:13 -0700 | [diff] [blame] | 104 | private boolean mSurfaceRedrawNeeded; |
Adrian Roos | 30a7dfa | 2015-07-17 12:29:53 -0700 | [diff] [blame] | 105 | |
Lucas Dupin | 049978e | 2017-10-02 11:38:13 -0700 | [diff] [blame] | 106 | DrawableEngine() { |
Jeff Sharkey | 35be756 | 2012-04-18 19:16:15 -0700 | [diff] [blame] | 107 | super(); |
| 108 | setFixedSizeAllowed(true); |
| 109 | } |
| 110 | |
Lucas Dupin | 049978e | 2017-10-02 11:38:13 -0700 | [diff] [blame] | 111 | void trimMemory(int level) { |
Jorim Jaggi | ed0e1a6 | 2016-05-13 17:45:41 -0700 | [diff] [blame] | 112 | if (level >= ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW |
| 113 | && level <= ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL |
| 114 | && mBackground != null) { |
Chet Haase | 5f0d976 | 2012-10-18 12:01:34 -0700 | [diff] [blame] | 115 | if (DEBUG) { |
| 116 | Log.d(TAG, "trimMemory"); |
| 117 | } |
Adrian Roos | 45febbb | 2016-10-11 13:41:27 -0700 | [diff] [blame] | 118 | unloadWallpaper(true /* forgetSize */); |
Chet Haase | c61d70e | 2012-10-10 15:41:57 -0700 | [diff] [blame] | 119 | } |
| 120 | } |
| 121 | |
Dianne Hackborn | 4c62fc0 | 2009-08-08 20:40:27 -0700 | [diff] [blame] | 122 | @Override |
Dianne Hackborn | 759a39e | 2009-08-09 17:20:27 -0700 | [diff] [blame] | 123 | public void onCreate(SurfaceHolder surfaceHolder) { |
Jeff Brown | 30bc34f | 2011-01-25 12:56:56 -0800 | [diff] [blame] | 124 | if (DEBUG) { |
| 125 | Log.d(TAG, "onCreate"); |
| 126 | } |
| 127 | |
Dianne Hackborn | 759a39e | 2009-08-09 17:20:27 -0700 | [diff] [blame] | 128 | super.onCreate(surfaceHolder); |
John Spurlock | 209bede | 2013-07-17 12:23:27 -0400 | [diff] [blame] | 129 | |
Lucas Dupin | 049978e | 2017-10-02 11:38:13 -0700 | [diff] [blame] | 130 | //noinspection ConstantConditions |
Adrian Roos | 9b9947d | 2015-06-09 16:46:05 -0700 | [diff] [blame] | 131 | mDefaultDisplay = getSystemService(WindowManager.class).getDefaultDisplay(); |
Chet Haase | a8e5a2b | 2011-10-28 13:18:16 -0700 | [diff] [blame] | 132 | setOffsetNotificationsEnabled(false); |
Adrian Roos | 7e9dec2 | 2016-04-13 17:43:45 -0700 | [diff] [blame] | 133 | |
| 134 | updateSurfaceSize(surfaceHolder, getDefaultDisplayInfo(), false /* forDraw */); |
Dianne Hackborn | 4c62fc0 | 2009-08-08 20:40:27 -0700 | [diff] [blame] | 135 | } |
| 136 | |
| 137 | @Override |
Dianne Hackborn | 284ac93 | 2009-08-28 10:34:25 -0700 | [diff] [blame] | 138 | public void onDestroy() { |
| 139 | super.onDestroy(); |
jshe32X | 7670b2b | 2013-10-24 12:57:09 +0800 | [diff] [blame] | 140 | mBackground = null; |
Adrian Roos | 45febbb | 2016-10-11 13:41:27 -0700 | [diff] [blame] | 141 | unloadWallpaper(true /* forgetSize */); |
Dianne Hackborn | 284ac93 | 2009-08-28 10:34:25 -0700 | [diff] [blame] | 142 | } |
| 143 | |
Adrian Roos | 7e9dec2 | 2016-04-13 17:43:45 -0700 | [diff] [blame] | 144 | boolean updateSurfaceSize(SurfaceHolder surfaceHolder, DisplayInfo displayInfo, |
| 145 | boolean forDraw) { |
| 146 | boolean hasWallpaper = true; |
| 147 | |
Michael Jurka | 824a4b5 | 2013-12-18 17:10:16 +0100 | [diff] [blame] | 148 | // 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 Dupin | 049978e | 2017-10-02 11:38:13 -0700 | [diff] [blame] | 151 | loadWallpaper(forDraw); |
Adrian Roos | 7e9dec2 | 2016-04-13 17:43:45 -0700 | [diff] [blame] | 152 | if (DEBUG) { |
| 153 | Log.d(TAG, "Reloading, redoing updateSurfaceSize later."); |
Michael Jurka | 824a4b5 | 2013-12-18 17:10:16 +0100 | [diff] [blame] | 154 | } |
Adrian Roos | 7e9dec2 | 2016-04-13 17:43:45 -0700 | [diff] [blame] | 155 | hasWallpaper = false; |
Michael Jurka | 824a4b5 | 2013-12-18 17:10:16 +0100 | [diff] [blame] | 156 | } |
| 157 | |
| 158 | // Force the wallpaper to cover the screen in both dimensions |
Adrian Roos | 9b9947d | 2015-06-09 16:46:05 -0700 | [diff] [blame] | 159 | int surfaceWidth = Math.max(displayInfo.logicalWidth, mBackgroundWidth); |
| 160 | int surfaceHeight = Math.max(displayInfo.logicalHeight, mBackgroundHeight); |
Michael Jurka | 824a4b5 | 2013-12-18 17:10:16 +0100 | [diff] [blame] | 161 | |
Lucas Dupin | 049978e | 2017-10-02 11:38:13 -0700 | [diff] [blame] | 162 | // 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 Roos | 7e9dec2 | 2016-04-13 17:43:45 -0700 | [diff] [blame] | 169 | return hasWallpaper; |
Dianne Hackborn | ac1471a | 2011-02-03 13:46:06 -0800 | [diff] [blame] | 170 | } |
| 171 | |
| 172 | @Override |
Dianne Hackborn | 759a39e | 2009-08-09 17:20:27 -0700 | [diff] [blame] | 173 | public void onVisibilityChanged(boolean visible) { |
Jeff Brown | 30bc34f | 2011-01-25 12:56:56 -0800 | [diff] [blame] | 174 | if (DEBUG) { |
Chet Haase | 2f20081 | 2012-10-11 12:49:08 -0700 | [diff] [blame] | 175 | Log.d(TAG, "onVisibilityChanged: mVisible, visible=" + mVisible + ", " + visible); |
Jeff Brown | 30bc34f | 2011-01-25 12:56:56 -0800 | [diff] [blame] | 176 | } |
| 177 | |
Craig Mautner | b1ef369 | 2012-11-16 17:31:04 -0800 | [diff] [blame] | 178 | if (mVisible != visible) { |
| 179 | if (DEBUG) { |
| 180 | Log.d(TAG, "Visibility changed to visible=" + visible); |
Jeff Brown | 30bc34f | 2011-01-25 12:56:56 -0800 | [diff] [blame] | 181 | } |
Craig Mautner | b1ef369 | 2012-11-16 17:31:04 -0800 | [diff] [blame] | 182 | mVisible = visible; |
longyu.huang | 6b53fd2 | 2015-05-06 01:46:23 -0700 | [diff] [blame] | 183 | if (visible) { |
| 184 | drawFrame(); |
| 185 | } |
Jeff Brown | fa2e504 | 2011-01-23 13:14:23 -0800 | [diff] [blame] | 186 | } |
Dianne Hackborn | 759a39e | 2009-08-09 17:20:27 -0700 | [diff] [blame] | 187 | } |
Jeff Brown | fa2e504 | 2011-01-23 13:14:23 -0800 | [diff] [blame] | 188 | |
Dianne Hackborn | 759a39e | 2009-08-09 17:20:27 -0700 | [diff] [blame] | 189 | @Override |
Dianne Hackborn | 72c82ab | 2009-08-11 21:13:54 -0700 | [diff] [blame] | 190 | public void onOffsetsChanged(float xOffset, float yOffset, |
Marco Nelissen | bf6956b | 2009-11-09 15:21:13 -0800 | [diff] [blame] | 191 | float xOffsetStep, float yOffsetStep, |
Dianne Hackborn | 72c82ab | 2009-08-11 21:13:54 -0700 | [diff] [blame] | 192 | int xPixels, int yPixels) { |
Jeff Brown | 30bc34f | 2011-01-25 12:56:56 -0800 | [diff] [blame] | 193 | if (DEBUG) { |
| 194 | Log.d(TAG, "onOffsetsChanged: xOffset=" + xOffset + ", yOffset=" + yOffset |
| 195 | + ", xOffsetStep=" + xOffsetStep + ", yOffsetStep=" + yOffsetStep |
| 196 | + ", xPixels=" + xPixels + ", yPixels=" + yPixels); |
| 197 | } |
| 198 | |
Craig Mautner | b1ef369 | 2012-11-16 17:31:04 -0800 | [diff] [blame] | 199 | if (mXOffset != xOffset || mYOffset != yOffset) { |
| 200 | if (DEBUG) { |
| 201 | Log.d(TAG, "Offsets changed to (" + xOffset + "," + yOffset + ")."); |
Jeff Brown | fa2e504 | 2011-01-23 13:14:23 -0800 | [diff] [blame] | 202 | } |
Craig Mautner | b1ef369 | 2012-11-16 17:31:04 -0800 | [diff] [blame] | 203 | mXOffset = xOffset; |
| 204 | mYOffset = yOffset; |
| 205 | mOffsetsChanged = true; |
Jeff Brown | fa2e504 | 2011-01-23 13:14:23 -0800 | [diff] [blame] | 206 | } |
Craig Mautner | b1ef369 | 2012-11-16 17:31:04 -0800 | [diff] [blame] | 207 | drawFrame(); |
Dianne Hackborn | 72c82ab | 2009-08-11 21:13:54 -0700 | [diff] [blame] | 208 | } |
| 209 | |
| 210 | @Override |
Dianne Hackborn | 4c62fc0 | 2009-08-08 20:40:27 -0700 | [diff] [blame] | 211 | public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) { |
Jeff Brown | 30bc34f | 2011-01-25 12:56:56 -0800 | [diff] [blame] | 212 | if (DEBUG) { |
| 213 | Log.d(TAG, "onSurfaceChanged: width=" + width + ", height=" + height); |
| 214 | } |
| 215 | |
Dianne Hackborn | 4c62fc0 | 2009-08-08 20:40:27 -0700 | [diff] [blame] | 216 | super.onSurfaceChanged(holder, format, width, height); |
Jeff Brown | 30bc34f | 2011-01-25 12:56:56 -0800 | [diff] [blame] | 217 | |
Craig Mautner | b1ef369 | 2012-11-16 17:31:04 -0800 | [diff] [blame] | 218 | drawFrame(); |
Dianne Hackborn | 4c62fc0 | 2009-08-08 20:40:27 -0700 | [diff] [blame] | 219 | } |
| 220 | |
Craig Mautner | fb729c7 | 2012-10-01 09:39:43 -0700 | [diff] [blame] | 221 | @Override |
Chet Haase | 2f20081 | 2012-10-11 12:49:08 -0700 | [diff] [blame] | 222 | public void onSurfaceDestroyed(SurfaceHolder holder) { |
| 223 | super.onSurfaceDestroyed(holder); |
Adrian Roos | 53560f1 | 2016-04-28 15:22:29 -0700 | [diff] [blame] | 224 | if (DEBUG) { |
| 225 | Log.i(TAG, "onSurfaceDestroyed"); |
| 226 | } |
| 227 | |
Chet Haase | 5f0d976 | 2012-10-18 12:01:34 -0700 | [diff] [blame] | 228 | mLastSurfaceWidth = mLastSurfaceHeight = -1; |
Adrian Roos | 53560f1 | 2016-04-28 15:22:29 -0700 | [diff] [blame] | 229 | mSurfaceValid = false; |
Chet Haase | 2f20081 | 2012-10-11 12:49:08 -0700 | [diff] [blame] | 230 | } |
| 231 | |
| 232 | @Override |
| 233 | public void onSurfaceCreated(SurfaceHolder holder) { |
| 234 | super.onSurfaceCreated(holder); |
Adrian Roos | 53560f1 | 2016-04-28 15:22:29 -0700 | [diff] [blame] | 235 | if (DEBUG) { |
| 236 | Log.i(TAG, "onSurfaceCreated"); |
| 237 | } |
| 238 | |
Chet Haase | 5f0d976 | 2012-10-18 12:01:34 -0700 | [diff] [blame] | 239 | mLastSurfaceWidth = mLastSurfaceHeight = -1; |
Adrian Roos | 53560f1 | 2016-04-28 15:22:29 -0700 | [diff] [blame] | 240 | mSurfaceValid = true; |
Chet Haase | 2f20081 | 2012-10-11 12:49:08 -0700 | [diff] [blame] | 241 | } |
| 242 | |
| 243 | @Override |
Craig Mautner | fb729c7 | 2012-10-01 09:39:43 -0700 | [diff] [blame] | 244 | public void onSurfaceRedrawNeeded(SurfaceHolder holder) { |
| 245 | if (DEBUG) { |
Chet Haase | 2f20081 | 2012-10-11 12:49:08 -0700 | [diff] [blame] | 246 | Log.d(TAG, "onSurfaceRedrawNeeded"); |
Craig Mautner | fb729c7 | 2012-10-01 09:39:43 -0700 | [diff] [blame] | 247 | } |
| 248 | super.onSurfaceRedrawNeeded(holder); |
Lucas Dupin | 049978e | 2017-10-02 11:38:13 -0700 | [diff] [blame] | 249 | // 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 Mautner | b1ef369 | 2012-11-16 17:31:04 -0800 | [diff] [blame] | 256 | drawFrame(); |
Craig Mautner | fb729c7 | 2012-10-01 09:39:43 -0700 | [diff] [blame] | 257 | } |
| 258 | |
Adrian Roos | 9b9947d | 2015-06-09 16:46:05 -0700 | [diff] [blame] | 259 | private DisplayInfo getDefaultDisplayInfo() { |
| 260 | mDefaultDisplay.getDisplayInfo(mTmpDisplayInfo); |
| 261 | return mTmpDisplayInfo; |
Michael Jurka | 824a4b5 | 2013-12-18 17:10:16 +0100 | [diff] [blame] | 262 | } |
| 263 | |
Craig Mautner | b1ef369 | 2012-11-16 17:31:04 -0800 | [diff] [blame] | 264 | void drawFrame() { |
Adrian Roos | 53560f1 | 2016-04-28 15:22:29 -0700 | [diff] [blame] | 265 | if (!mSurfaceValid) { |
| 266 | return; |
| 267 | } |
Adrian Roos | 2acaeda | 2014-11-12 18:02:42 +0100 | [diff] [blame] | 268 | try { |
Jorim Jaggi | c5887ea | 2016-05-13 18:21:48 -0700 | [diff] [blame] | 269 | Trace.traceBegin(Trace.TRACE_TAG_VIEW, "drawWallpaper"); |
Adrian Roos | 9b9947d | 2015-06-09 16:46:05 -0700 | [diff] [blame] | 270 | DisplayInfo displayInfo = getDefaultDisplayInfo(); |
| 271 | int newRotation = displayInfo.rotation; |
Michael Jurka | 824a4b5 | 2013-12-18 17:10:16 +0100 | [diff] [blame] | 272 | |
Adrian Roos | 2acaeda | 2014-11-12 18:02:42 +0100 | [diff] [blame] | 273 | // 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 Roos | 7e9dec2 | 2016-04-13 17:43:45 -0700 | [diff] [blame] | 278 | if (!updateSurfaceSize(getSurfaceHolder(), displayInfo, true /* forDraw */)) { |
| 279 | return; // had to reload wallpaper, will retry later |
| 280 | } |
Adrian Roos | ab6edbf | 2015-07-07 17:29:15 -0700 | [diff] [blame] | 281 | mRotationAtLastSurfaceSizeUpdate = newRotation; |
| 282 | mDisplayWidthAtLastSurfaceSizeUpdate = displayInfo.logicalWidth; |
| 283 | mDisplayHeightAtLastSurfaceSizeUpdate = displayInfo.logicalHeight; |
Chet Haase | 2f20081 | 2012-10-11 12:49:08 -0700 | [diff] [blame] | 284 | } |
Adrian Roos | 2acaeda | 2014-11-12 18:02:42 +0100 | [diff] [blame] | 285 | 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 Haase | 2f20081 | 2012-10-11 12:49:08 -0700 | [diff] [blame] | 291 | |
Lucas Dupin | 049978e | 2017-10-02 11:38:13 -0700 | [diff] [blame] | 292 | boolean redrawNeeded = surfaceDimensionsChanged || newRotation != mLastRotation |
| 293 | || mSurfaceRedrawNeeded; |
Adrian Roos | 2acaeda | 2014-11-12 18:02:42 +0100 | [diff] [blame] | 294 | if (!redrawNeeded && !mOffsetsChanged) { |
Chet Haase | 5f0d976 | 2012-10-18 12:01:34 -0700 | [diff] [blame] | 295 | if (DEBUG) { |
Adrian Roos | 2acaeda | 2014-11-12 18:02:42 +0100 | [diff] [blame] | 296 | Log.d(TAG, "Suppressed drawFrame since redraw is not needed " |
| 297 | + "and offsets have not changed."); |
Chet Haase | 5f0d976 | 2012-10-18 12:01:34 -0700 | [diff] [blame] | 298 | } |
| 299 | return; |
| 300 | } |
Adrian Roos | 2acaeda | 2014-11-12 18:02:42 +0100 | [diff] [blame] | 301 | mLastRotation = newRotation; |
Lucas Dupin | 049978e | 2017-10-02 11:38:13 -0700 | [diff] [blame] | 302 | mSurfaceRedrawNeeded = false; |
Adrian Roos | 2acaeda | 2014-11-12 18:02:42 +0100 | [diff] [blame] | 303 | |
Adrian Roos | 7e9dec2 | 2016-04-13 17:43:45 -0700 | [diff] [blame] | 304 | // Load bitmap if it is not yet loaded |
| 305 | if (mBackground == null) { |
Lucas Dupin | 049978e | 2017-10-02 11:38:13 -0700 | [diff] [blame] | 306 | loadWallpaper(true); |
Adrian Roos | 2acaeda | 2014-11-12 18:02:42 +0100 | [diff] [blame] | 307 | if (DEBUG) { |
Adrian Roos | 7e9dec2 | 2016-04-13 17:43:45 -0700 | [diff] [blame] | 308 | Log.d(TAG, "Reloading, resuming draw later"); |
Chet Haase | 5f0d976 | 2012-10-18 12:01:34 -0700 | [diff] [blame] | 309 | } |
Adrian Roos | 7e9dec2 | 2016-04-13 17:43:45 -0700 | [diff] [blame] | 310 | return; |
Chet Haase | 5f0d976 | 2012-10-18 12:01:34 -0700 | [diff] [blame] | 311 | } |
Chet Haase | 2f20081 | 2012-10-11 12:49:08 -0700 | [diff] [blame] | 312 | |
Lucas Dupin | 049978e | 2017-10-02 11:38:13 -0700 | [diff] [blame] | 313 | // Left align the scaled image |
Adrian Roos | 2acaeda | 2014-11-12 18:02:42 +0100 | [diff] [blame] | 314 | mScale = Math.max(1f, Math.max(dw / (float) mBackground.getWidth(), |
| 315 | dh / (float) mBackground.getHeight())); |
Lucas Dupin | 049978e | 2017-10-02 11:38:13 -0700 | [diff] [blame] | 316 | 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 Brown | 033f63a | 2011-01-23 22:01:49 -0800 | [diff] [blame] | 320 | |
Adrian Roos | 2acaeda | 2014-11-12 18:02:42 +0100 | [diff] [blame] | 321 | mOffsetsChanged = false; |
Adrian Roos | 2acaeda | 2014-11-12 18:02:42 +0100 | [diff] [blame] | 322 | if (surfaceDimensionsChanged) { |
| 323 | mLastSurfaceWidth = dw; |
| 324 | mLastSurfaceHeight = dh; |
Jeff Brown | 033f63a | 2011-01-23 22:01:49 -0800 | [diff] [blame] | 325 | } |
Adrian Roos | 2acaeda | 2014-11-12 18:02:42 +0100 | [diff] [blame] | 326 | 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 Brown | 033f63a | 2011-01-23 22:01:49 -0800 | [diff] [blame] | 335 | |
Adrian Roos | 2acaeda | 2014-11-12 18:02:42 +0100 | [diff] [blame] | 336 | if (DEBUG) { |
| 337 | Log.d(TAG, "Redrawing wallpaper"); |
| 338 | } |
Wim Vander Schelden | 9549c06 | 2013-02-07 15:51:51 +0000 | [diff] [blame] | 339 | |
Lucas Dupin | 049978e | 2017-10-02 11:38:13 -0700 | [diff] [blame] | 340 | drawWallpaperWithCanvas(sh, availw, availh, xPixels, yPixels); |
Lucas Dupin | 41c25ce | 2018-03-27 09:50:19 -0700 | [diff] [blame] | 341 | scheduleUnloadWallpaper(); |
Adrian Roos | 2acaeda | 2014-11-12 18:02:42 +0100 | [diff] [blame] | 342 | } finally { |
Jorim Jaggi | c5887ea | 2016-05-13 18:21:48 -0700 | [diff] [blame] | 343 | Trace.traceEnd(Trace.TRACE_TAG_VIEW); |
Dianne Hackborn | 759a39e | 2009-08-09 17:20:27 -0700 | [diff] [blame] | 344 | } |
Dianne Hackborn | 759a39e | 2009-08-09 17:20:27 -0700 | [diff] [blame] | 345 | } |
Romain Guy | ef654bd | 2009-08-11 19:12:17 -0700 | [diff] [blame] | 346 | |
Adrian Roos | 7e9dec2 | 2016-04-13 17:43:45 -0700 | [diff] [blame] | 347 | /** |
| 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 Roos | 45febbb | 2016-10-11 13:41:27 -0700 | [diff] [blame] | 353 | * |
| 354 | * If {@param needsReset} is set also clears the cache in WallpaperManager first. |
Adrian Roos | 7e9dec2 | 2016-04-13 17:43:45 -0700 | [diff] [blame] | 355 | */ |
Lucas Dupin | 049978e | 2017-10-02 11:38:13 -0700 | [diff] [blame] | 356 | private void loadWallpaper(boolean needsDraw) { |
Adrian Roos | 7e9dec2 | 2016-04-13 17:43:45 -0700 | [diff] [blame] | 357 | mNeedsDrawAfterLoadingWallpaper |= needsDraw; |
| 358 | if (mLoader != null) { |
Lucas Dupin | 049978e | 2017-10-02 11:38:13 -0700 | [diff] [blame] | 359 | if (DEBUG) { |
| 360 | Log.d(TAG, "Skipping loadWallpaper, already in flight "); |
Dianne Hackborn | c9dbbe2 | 2009-11-11 22:50:37 -0800 | [diff] [blame] | 361 | } |
Lucas Dupin | 049978e | 2017-10-02 11:38:13 -0700 | [diff] [blame] | 362 | return; |
Romain Guy | ef654bd | 2009-08-11 19:12:17 -0700 | [diff] [blame] | 363 | } |
Adrian Roos | 7e9dec2 | 2016-04-13 17:43:45 -0700 | [diff] [blame] | 364 | mLoader = new AsyncTask<Void, Void, Bitmap>() { |
| 365 | @Override |
| 366 | protected Bitmap doInBackground(Void... params) { |
| 367 | Throwable exception; |
| 368 | try { |
Lucas Dupin | 049978e | 2017-10-02 11:38:13 -0700 | [diff] [blame] | 369 | return mWallpaperManager.getBitmap(true /* hardware */); |
Adrian Roos | 7e9dec2 | 2016-04-13 17:43:45 -0700 | [diff] [blame] | 370 | } catch (RuntimeException | OutOfMemoryError e) { |
| 371 | exception = e; |
| 372 | } |
| 373 | |
Adrian Roos | 45febbb | 2016-10-11 13:41:27 -0700 | [diff] [blame] | 374 | if (isCancelled()) { |
| 375 | return null; |
| 376 | } |
| 377 | |
Lucas Dupin | 049978e | 2017-10-02 11:38:13 -0700 | [diff] [blame] | 378 | // 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 Roos | 7e9dec2 | 2016-04-13 17:43:45 -0700 | [diff] [blame] | 388 | |
Lucas Dupin | 049978e | 2017-10-02 11:38:13 -0700 | [diff] [blame] | 389 | if (isCancelled()) { |
| 390 | return null; |
| 391 | } |
Adrian Roos | 45febbb | 2016-10-11 13:41:27 -0700 | [diff] [blame] | 392 | |
Lucas Dupin | 049978e | 2017-10-02 11:38:13 -0700 | [diff] [blame] | 393 | try { |
| 394 | return mWallpaperManager.getBitmap(true /* hardware */); |
| 395 | } catch (RuntimeException | OutOfMemoryError e) { |
| 396 | Log.w(TAG, "Unable to load default wallpaper!", e); |
Adrian Roos | 7e9dec2 | 2016-04-13 17:43:45 -0700 | [diff] [blame] | 397 | } |
| 398 | return null; |
| 399 | } |
| 400 | |
| 401 | @Override |
| 402 | protected void onPostExecute(Bitmap b) { |
Lucas Dupin | 049978e | 2017-10-02 11:38:13 -0700 | [diff] [blame] | 403 | updateBitmap(b); |
Adrian Roos | 7e9dec2 | 2016-04-13 17:43:45 -0700 | [diff] [blame] | 404 | |
Adrian Roos | 7e9dec2 | 2016-04-13 17:43:45 -0700 | [diff] [blame] | 405 | if (mNeedsDrawAfterLoadingWallpaper) { |
| 406 | drawFrame(); |
| 407 | } |
| 408 | |
| 409 | mLoader = null; |
| 410 | mNeedsDrawAfterLoadingWallpaper = false; |
| 411 | } |
| 412 | }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); |
Romain Guy | 407ec78 | 2011-08-24 17:06:58 -0700 | [diff] [blame] | 413 | } |
| 414 | |
Lucas Dupin | 049978e | 2017-10-02 11:38:13 -0700 | [diff] [blame] | 415 | 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 Roos | 45febbb | 2016-10-11 13:41:27 -0700 | [diff] [blame] | 433 | 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 Dupin | 41c25ce | 2018-03-27 09:50:19 -0700 | [diff] [blame] | 444 | final Surface surface = getSurfaceHolder().getSurface(); |
| 445 | surface.hwuiDestroy(); |
| 446 | |
Lucas Dupin | 61df45c | 2018-04-07 11:08:15 -0700 | [diff] [blame] | 447 | mWallpaperManager.forgetLoadedWallpaper(); |
Adrian Roos | 45febbb | 2016-10-11 13:41:27 -0700 | [diff] [blame] | 448 | } |
| 449 | |
Lucas Dupin | 41c25ce | 2018-03-27 09:50:19 -0700 | [diff] [blame] | 450 | private void scheduleUnloadWallpaper() { |
| 451 | Handler handler = getMainThreadHandler(); |
| 452 | handler.removeCallbacks(mUnloadWallpaperCallback); |
| 453 | handler.postDelayed(mUnloadWallpaperCallback, DELAY_FORGET_WALLPAPER); |
| 454 | } |
| 455 | |
Adrian Roos | ab6edbf | 2015-07-07 17:29:15 -0700 | [diff] [blame] | 456 | @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 Roos | ab6edbf | 2015-07-07 17:29:15 -0700 | [diff] [blame] | 473 | 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 Roos | 30a7dfa | 2015-07-17 12:29:53 -0700 | [diff] [blame] | 479 | out.print(prefix); out.print(" mLastRequestedWidth="); out.print(mLastRequestedWidth); |
| 480 | out.print(" mLastRequestedHeight="); out.println(mLastRequestedHeight); |
| 481 | |
Adrian Roos | ab6edbf | 2015-07-07 17:29:15 -0700 | [diff] [blame] | 482 | 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 Jurka | 824a4b5 | 2013-12-18 17:10:16 +0100 | [diff] [blame] | 489 | private void drawWallpaperWithCanvas(SurfaceHolder sh, int w, int h, int left, int top) { |
Lucas Dupin | 049978e | 2017-10-02 11:38:13 -0700 | [diff] [blame] | 490 | Canvas c = sh.lockHardwareCanvas(); |
Romain Guy | 407ec78 | 2011-08-24 17:06:58 -0700 | [diff] [blame] | 491 | if (c != null) { |
| 492 | try { |
| 493 | if (DEBUG) { |
Michael Jurka | 824a4b5 | 2013-12-18 17:10:16 +0100 | [diff] [blame] | 494 | Log.d(TAG, "Redrawing: left=" + left + ", top=" + top); |
Romain Guy | 407ec78 | 2011-08-24 17:06:58 -0700 | [diff] [blame] | 495 | } |
| 496 | |
Michael Jurka | 824a4b5 | 2013-12-18 17:10:16 +0100 | [diff] [blame] | 497 | final float right = left + mBackground.getWidth() * mScale; |
| 498 | final float bottom = top + mBackground.getHeight() * mScale; |
Romain Guy | 407ec78 | 2011-08-24 17:06:58 -0700 | [diff] [blame] | 499 | if (w < 0 || h < 0) { |
| 500 | c.save(Canvas.CLIP_SAVE_FLAG); |
Michael Jurka | 824a4b5 | 2013-12-18 17:10:16 +0100 | [diff] [blame] | 501 | c.clipRect(left, top, right, bottom, |
Chet Haase | 5f0d976 | 2012-10-18 12:01:34 -0700 | [diff] [blame] | 502 | Op.DIFFERENCE); |
Romain Guy | 407ec78 | 2011-08-24 17:06:58 -0700 | [diff] [blame] | 503 | c.drawColor(0xff000000); |
| 504 | c.restore(); |
| 505 | } |
| 506 | if (mBackground != null) { |
Michael Jurka | 824a4b5 | 2013-12-18 17:10:16 +0100 | [diff] [blame] | 507 | RectF dest = new RectF(left, top, right, bottom); |
Lucas Dupin | ba13095 | 2017-12-14 14:50:11 -0800 | [diff] [blame] | 508 | Log.i(TAG, "Redrawing in rect: " + dest + " with surface size: " |
| 509 | + mLastRequestedWidth + "x" + mLastRequestedHeight); |
Michael Jurka | 824a4b5 | 2013-12-18 17:10:16 +0100 | [diff] [blame] | 510 | c.drawBitmap(mBackground, null, dest, null); |
Romain Guy | 407ec78 | 2011-08-24 17:06:58 -0700 | [diff] [blame] | 511 | } |
| 512 | } finally { |
| 513 | sh.unlockCanvasAndPost(c); |
| 514 | } |
| 515 | } |
| 516 | } |
Dianne Hackborn | 4c62fc0 | 2009-08-08 20:40:27 -0700 | [diff] [blame] | 517 | } |
| 518 | } |