• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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