1 /* 2 * Copyright (C) 2023 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 17 package com.android.server.wallpaper; 18 19 import static android.app.Flags.liveWallpaperContentHandling; 20 import static android.app.WallpaperManager.FLAG_LOCK; 21 import static android.app.WallpaperManager.ORIENTATION_UNKNOWN; 22 23 import static com.android.server.wallpaper.WallpaperUtils.WALLPAPER; 24 import static com.android.server.wallpaper.WallpaperUtils.WALLPAPER_CROP; 25 import static com.android.server.wallpaper.WallpaperUtils.WALLPAPER_LOCK_CROP; 26 import static com.android.server.wallpaper.WallpaperUtils.WALLPAPER_LOCK_ORIG; 27 import static com.android.server.wallpaper.WallpaperUtils.getWallpaperDir; 28 29 import android.annotation.NonNull; 30 import android.app.IWallpaperManagerCallback; 31 import android.app.WallpaperColors; 32 import android.app.WallpaperManager.ScreenOrientation; 33 import android.app.WallpaperManager.SetWallpaperFlags; 34 import android.app.wallpaper.WallpaperDescription; 35 import android.content.ComponentName; 36 import android.graphics.Rect; 37 import android.os.RemoteCallbackList; 38 import android.util.SparseArray; 39 40 import java.io.File; 41 42 /** 43 * The main wallpaper data model, used internally by the {@link WallpaperManagerService}. <br> 44 * An instance of this class contains all the information about a wallpaper. 45 */ 46 class WallpaperData { 47 48 final int userId; 49 50 /** 51 * True while the client is writing a new wallpaper 52 */ 53 boolean imageWallpaperPending; 54 55 /** 56 * Which wallpaper is set. Flag values are from {@link SetWallpaperFlags}. 57 */ 58 int mWhich; 59 60 /** 61 * True if the system wallpaper was also used for lock screen before this wallpaper was set. 62 * This is needed to update state after setting the wallpaper. 63 */ 64 boolean mSystemWasBoth; 65 66 /** 67 * Callback once the set + crop is finished 68 */ 69 IWallpaperManagerCallback setComplete; 70 71 /** 72 * Is the OS allowed to back up this wallpaper imagery? 73 */ 74 boolean allowBackup; 75 76 /** 77 * Resource name if using a picture from the wallpaper gallery 78 */ 79 String name = ""; 80 81 /** 82 * The component name of the currently set live wallpaper. 83 * 84 * @deprecated 85 */ 86 private ComponentName mWallpaperComponent; 87 88 // TODO(b/347235611) Remove this field 89 /** 90 * The component name of the wallpaper that should be set next. 91 * 92 * @deprecated 93 */ 94 ComponentName nextWallpaperComponent; 95 96 /** 97 * The ID of this wallpaper 98 */ 99 int wallpaperId; 100 101 /** 102 * Primary colors histogram 103 */ 104 WallpaperColors primaryColors; 105 106 /** 107 * If the wallpaper was set from a foreground app (instead of from a background service). 108 */ 109 public boolean fromForegroundApp; 110 111 WallpaperManagerService.WallpaperConnection connection; 112 long lastDiedTime; 113 boolean wallpaperUpdating; 114 WallpaperManagerService.WallpaperObserver wallpaperObserver; 115 116 /** 117 * The dim amount to be applied to the wallpaper. 118 */ 119 float mWallpaperDimAmount = 0.0f; 120 121 /** 122 * A map to keep track of the dimming set by different applications. The key is the calling 123 * UID and the value is the dim amount. 124 */ 125 SparseArray<Float> mUidToDimAmount = new SparseArray<>(); 126 127 /** 128 * Whether we need to extract the wallpaper colors again to calculate the dark hints 129 * after dimming is applied. 130 */ 131 boolean mIsColorExtractedFromDim; 132 133 /** 134 * List of callbacks registered they should each be notified when the wallpaper is changed. 135 */ 136 RemoteCallbackList<IWallpaperManagerCallback> callbacks = new RemoteCallbackList<>(); 137 138 /** 139 * Defines which part of the {@link #getWallpaperFile()} image is in the {@link #getCropFile()}. 140 */ 141 final Rect cropHint = new Rect(0, 0, 0, 0); 142 143 /** 144 * How much the crop is sub-sampled. A value > 1 means that the image quality was reduced. 145 * This is the ratio between the cropHint height and the actual {@link #getCropFile()} height. 146 */ 147 float mSampleSize = 1f; 148 149 // Describes the context of a call to WallpaperManagerService#bindWallpaperComponentLocked 150 enum BindSource { 151 UNKNOWN, 152 CONNECT_LOCKED, 153 CONNECTION_TRY_TO_REBIND, 154 FALLBACK_DEFAULT_MISSING, 155 INITIALIZE_FALLBACK, 156 PACKAGE_UPDATE_FINISHED, 157 RESTORE_SETTINGS_LIVE_FAILURE, 158 RESTORE_SETTINGS_LIVE_SUCCESS, 159 RESTORE_SETTINGS_STATIC, 160 SET_LIVE, 161 SET_LIVE_TO_CLEAR, 162 SET_STATIC, 163 SWITCH_WALLPAPER_FAILURE, 164 SWITCH_WALLPAPER_SWITCH_USER, 165 SWITCH_WALLPAPER_UNLOCK_USER, 166 } 167 168 // Context in which this wallpaper was bound. Intended for use in resolving b/301073479 but may 169 // be useful after the issue is resolved as well. 170 BindSource mBindSource = BindSource.UNKNOWN; 171 172 // map of which -> File 173 private final SparseArray<File> mWallpaperFiles = new SparseArray<>(); 174 private final SparseArray<File> mCropFiles = new SparseArray<>(); 175 176 /** 177 * Mapping of {@link ScreenOrientation} -> crop hint. The crop hints are relative to the 178 * original image stored in {@link #getWallpaperFile()}. 179 * Only used when multi crop flag is enabled. 180 */ 181 SparseArray<Rect> mCropHints = new SparseArray<>(); 182 183 /** 184 * The phone orientation when the wallpaper was set. Only relevant for image wallpapers 185 */ 186 int mOrientationWhenSet = ORIENTATION_UNKNOWN; 187 188 /** Description of the current wallpaper */ 189 private WallpaperDescription mDescription = new WallpaperDescription.Builder().build(); 190 WallpaperData(int userId, @SetWallpaperFlags int wallpaperType)191 WallpaperData(int userId, @SetWallpaperFlags int wallpaperType) { 192 this.userId = userId; 193 this.mWhich = wallpaperType; 194 } 195 196 /** 197 * Copies the essential properties of a WallpaperData to a new instance, including the id and 198 * WallpaperConnection, usually in preparation for migrating a system+lock wallpaper to system- 199 * or lock-only. NB: the source object retains the pointer to the connection and it is the 200 * caller's responsibility to set this to null or otherwise be sure the connection is not shared 201 * between WallpaperData instances. 202 * 203 * @param source WallpaperData object to copy 204 */ WallpaperData(WallpaperData source)205 WallpaperData(WallpaperData source) { 206 this.userId = source.userId; 207 this.mWallpaperComponent = source.mWallpaperComponent; 208 this.mWhich = source.mWhich; 209 this.wallpaperId = source.wallpaperId; 210 this.cropHint.set(source.cropHint); 211 if (source.mCropHints != null) { 212 this.mCropHints = source.mCropHints.clone(); 213 } 214 this.allowBackup = source.allowBackup; 215 this.primaryColors = source.primaryColors; 216 this.mWallpaperDimAmount = source.mWallpaperDimAmount; 217 this.connection = source.connection; 218 if (liveWallpaperContentHandling()) { 219 this.setDescription(source.getDescription()); 220 } 221 if (this.connection != null) { 222 this.connection.mWallpaper = this; 223 } 224 } 225 getWallpaperFile()226 File getWallpaperFile() { 227 String fileName = mWhich == FLAG_LOCK ? WALLPAPER_LOCK_ORIG : WALLPAPER; 228 return getFile(mWallpaperFiles, fileName); 229 } 230 getCropFile()231 File getCropFile() { 232 String fileName = mWhich == FLAG_LOCK ? WALLPAPER_LOCK_CROP : WALLPAPER_CROP; 233 return getFile(mCropFiles, fileName); 234 } 235 getFile(SparseArray<File> map, String fileName)236 private File getFile(SparseArray<File> map, String fileName) { 237 File result = map.get(mWhich); 238 if (result == null) { 239 result = new File(getWallpaperDir(userId), fileName); 240 map.put(userId, result); 241 } 242 return result; 243 } 244 getComponent()245 @NonNull ComponentName getComponent() { 246 if (liveWallpaperContentHandling()) { 247 return mDescription.getComponent(); 248 } else { 249 return mWallpaperComponent; 250 } 251 } 252 setComponent(@onNull ComponentName componentName)253 void setComponent(@NonNull ComponentName componentName) { 254 if (liveWallpaperContentHandling()) { 255 throw new IllegalStateException( 256 "Use \"setDescription\" when content handling is enabled"); 257 } 258 this.mWallpaperComponent = componentName; 259 } 260 getDescription()261 @NonNull WallpaperDescription getDescription() { 262 return mDescription; 263 } 264 setDescription(@onNull WallpaperDescription description)265 void setDescription(@NonNull WallpaperDescription description) { 266 if (!liveWallpaperContentHandling()) { 267 throw new IllegalStateException( 268 "Use \"setContent\" when content handling is disabled"); 269 } 270 if (description == null) { 271 throw new IllegalArgumentException("WallpaperDescription must not be null"); 272 } 273 if (description.getComponent() == null) { 274 throw new IllegalArgumentException("WallpaperDescription component must not be null"); 275 } 276 this.mDescription = description; 277 } 278 279 @Override toString()280 public String toString() { 281 StringBuilder out = new StringBuilder(defaultString(this)); 282 out.append(", id: "); 283 out.append(wallpaperId); 284 out.append(", which: "); 285 out.append(mWhich); 286 out.append(", file mod: "); 287 out.append(getWallpaperFile() != null ? getWallpaperFile().lastModified() : "null"); 288 if (connection == null) { 289 out.append(", no connection"); 290 } else { 291 out.append(", info: "); 292 out.append(connection.mInfo); 293 out.append(", engine(s):"); 294 connection.forEachDisplayConnector(connector -> { 295 if (connector.mEngine != null) { 296 out.append(" "); 297 out.append(defaultString(connector.mEngine)); 298 } else { 299 out.append(" null"); 300 } 301 }); 302 } 303 return out.toString(); 304 } 305 defaultString(Object o)306 private static String defaultString(Object o) { 307 return o.getClass().getSimpleName() + "@" + Integer.toHexString(o.hashCode()); 308 } 309 310 // Called during initialization of a given user's wallpaper bookkeeping cropExists()311 boolean cropExists() { 312 return getCropFile().exists(); 313 } 314 sourceExists()315 boolean sourceExists() { 316 return getWallpaperFile().exists(); 317 } 318 } 319