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