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