• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 package com.android.wallpaper.module;
17 
18 import static android.app.Flags.liveWallpaperContentHandling;
19 
20 import android.app.WallpaperManager;
21 import android.content.ComponentName;
22 import android.content.Context;
23 import android.graphics.Point;
24 import android.net.Uri;
25 
26 import androidx.annotation.Nullable;
27 
28 import com.android.wallpaper.config.BaseFlags;
29 import com.android.wallpaper.model.CreativeWallpaperInfo;
30 import com.android.wallpaper.model.CurrentWallpaperInfo;
31 import com.android.wallpaper.model.DefaultWallpaperInfo;
32 import com.android.wallpaper.model.LiveWallpaperInfo;
33 import com.android.wallpaper.model.LiveWallpaperMetadata;
34 import com.android.wallpaper.model.WallpaperInfo;
35 import com.android.wallpaper.model.WallpaperMetadata;
36 import com.android.wallpaper.module.WallpaperPreferences.PresentationMode;
37 import com.android.wallpaper.picker.customization.data.content.WallpaperClient;
38 import com.android.wallpaper.util.DisplayUtils;
39 
40 import java.util.HashMap;
41 import java.util.List;
42 
43 /**
44  * Default implementation of {@link CurrentWallpaperInfoFactory} which actually constructs
45  * {@link WallpaperInfo} instances representing the wallpapers currently set to the device.
46  */
47 public class DefaultCurrentWallpaperInfoFactory implements CurrentWallpaperInfoFactory {
48 
49     private final WallpaperRefresher mWallpaperRefresher;
50     private final LiveWallpaperInfoFactory mLiveWallpaperInfoFactory;
51 
52     // Cached copies of the currently-set WallpaperInfo(s) and presentation mode.
53     private WallpaperInfo mHomeWallpaper;
54     @Nullable
55     private WallpaperInfo mLockWallpaper;
56     @PresentationMode
57     private int mPresentationMode;
58 
DefaultCurrentWallpaperInfoFactory(WallpaperRefresher wallpaperRefresher, LiveWallpaperInfoFactory liveWallpaperInfoFactory)59     public DefaultCurrentWallpaperInfoFactory(WallpaperRefresher wallpaperRefresher,
60             LiveWallpaperInfoFactory liveWallpaperInfoFactory) {
61         mWallpaperRefresher = wallpaperRefresher;
62         mLiveWallpaperInfoFactory = liveWallpaperInfoFactory;
63     }
64 
65     @Override
createCurrentWallpaperInfos(Context context, boolean forceRefresh, WallpaperInfoCallback callback)66     public synchronized void createCurrentWallpaperInfos(Context context, boolean forceRefresh,
67             WallpaperInfoCallback callback) {
68 
69         BaseFlags flags = InjectorProvider.getInjector().getFlags();
70         final boolean isMultiCropEnabled = flags.isMultiCropEnabled();
71 
72         boolean isHomeWallpaperSynced  = homeWallpaperSynced(context);
73         boolean isLockWallpaperSynced  = lockWallpaperSynced(context);
74         if (!forceRefresh && isHomeWallpaperSynced && isLockWallpaperSynced
75                 && mPresentationMode != WallpaperPreferences.PRESENTATION_MODE_ROTATING) {
76             // Update wallpaper crop hints for static wallpaper even if home & lock wallpaper are
77             // considered synced because wallpaper info are considered synced as long as both are
78             // static
79             if (isMultiCropEnabled) {
80                 DisplayUtils displayUtils = InjectorProvider.getInjector().getDisplayUtils(context);
81                 WallpaperClient wallpaperClient = InjectorProvider.getInjector().getWallpaperClient(
82                         context);
83                 List<Point> displaySizes = displayUtils
84                         .getInternalDisplaySizes(/* allDimensions= */ true);
85                 if (mHomeWallpaper != null) {
86                     boolean isHomeWallpaperStatic = mHomeWallpaper.getWallpaperComponent() == null
87                             || mHomeWallpaper.getWallpaperComponent().getComponent() == null;
88                     if (isHomeWallpaperStatic) {
89                         mHomeWallpaper.setWallpaperCropHints(
90                                 wallpaperClient.getCurrentCropHints(displaySizes,
91                                         WallpaperManager.FLAG_SYSTEM));
92                     } else {
93                         mHomeWallpaper.setWallpaperCropHints(new HashMap<>());
94                     }
95                 }
96                 if (mLockWallpaper != null) {
97                     boolean isLockWallpaperStatic = mLockWallpaper.getWallpaperComponent() == null
98                             || mLockWallpaper.getWallpaperComponent().getComponent() == null;
99                     if (isLockWallpaperStatic) {
100                         mLockWallpaper.setWallpaperCropHints(
101                                 wallpaperClient.getCurrentCropHints(displaySizes,
102                                         WallpaperManager.FLAG_LOCK));
103                     } else {
104                         mLockWallpaper.setWallpaperCropHints(new HashMap<>());
105                     }
106                 }
107             } else {
108                 if (mHomeWallpaper != null) mHomeWallpaper.setWallpaperCropHints(null);
109                 if (mLockWallpaper != null) mLockWallpaper.setWallpaperCropHints(null);
110             }
111             callback.onWallpaperInfoCreated(mHomeWallpaper, mLockWallpaper, mPresentationMode);
112             return;
113         }
114 
115         // Clear cached copies if we are refreshing the currently-set WallpaperInfo(s) from the
116         // Refresher so that multiple calls to this method after a call with forceRefresh=true don't
117         // provide old cached copies.
118         if (forceRefresh) {
119             clearCurrentWallpaperInfos();
120         }
121 
122         mWallpaperRefresher.refresh(
123                 (homeWallpaperMetadata, lockWallpaperMetadata, presentationMode) -> {
124                     WallpaperInfo homeWallpaper;
125                     if (homeWallpaperMetadata instanceof LiveWallpaperMetadata) {
126                         homeWallpaper = mLiveWallpaperInfoFactory.getLiveWallpaperInfo(
127                                 homeWallpaperMetadata.getWallpaperComponent());
128                         if (liveWallpaperContentHandling()) {
129                             ((LiveWallpaperInfo) homeWallpaper).setWallpaperDescription(
130                                     ((LiveWallpaperMetadata) homeWallpaperMetadata)
131                                             .getDescription());
132                         }
133                         updateIfCreative(homeWallpaper, homeWallpaperMetadata);
134                     } else {
135                         Uri imageUri = homeWallpaperMetadata.getWallpaperImageUri();
136                         homeWallpaper = new CurrentWallpaperInfo(
137                                 homeWallpaperMetadata.getAttributions(),
138                                 homeWallpaperMetadata.getActionUrl(),
139                                 homeWallpaperMetadata.getCollectionId(),
140                                 WallpaperManager.FLAG_SYSTEM,
141                                 imageUri);
142                         if (isMultiCropEnabled) {
143                             homeWallpaper.setWallpaperCropHints(
144                                     homeWallpaperMetadata.getWallpaperCropHints());
145                         }
146                     }
147 
148                     WallpaperInfo lockWallpaper = null;
149 
150                     if (lockWallpaperMetadata != null) {
151 
152                         if (lockWallpaperMetadata instanceof LiveWallpaperMetadata) {
153                             lockWallpaper = mLiveWallpaperInfoFactory.getLiveWallpaperInfo(
154                                     lockWallpaperMetadata.getWallpaperComponent());
155                             if (liveWallpaperContentHandling()) {
156                                 ((LiveWallpaperInfo) lockWallpaper).setWallpaperDescription(
157                                         ((LiveWallpaperMetadata) lockWallpaperMetadata)
158                                                 .getDescription());
159                             }
160                             updateIfCreative(lockWallpaper, lockWallpaperMetadata);
161                         } else {
162                             if (isLockWallpaperBuiltIn(context)) {
163                                 lockWallpaper = new DefaultWallpaperInfo();
164                             } else {
165                                 Uri imageUri = lockWallpaperMetadata.getWallpaperImageUri();
166                                 lockWallpaper = new CurrentWallpaperInfo(
167                                         lockWallpaperMetadata.getAttributions(),
168                                         lockWallpaperMetadata.getActionUrl(),
169                                         lockWallpaperMetadata.getCollectionId(),
170                                         WallpaperManager.FLAG_LOCK,
171                                         imageUri);
172                             }
173 
174                             if (isMultiCropEnabled) {
175                                 lockWallpaper.setWallpaperCropHints(
176                                         lockWallpaperMetadata.getWallpaperCropHints());
177                             }
178                         }
179                     }
180 
181                     mHomeWallpaper = homeWallpaper;
182                     mLockWallpaper = lockWallpaper;
183                     mPresentationMode = presentationMode;
184 
185                     callback.onWallpaperInfoCreated(homeWallpaper, lockWallpaper, presentationMode);
186                 });
187     }
188 
updateIfCreative(WallpaperInfo info, WallpaperMetadata metadata)189     private void updateIfCreative(WallpaperInfo info, WallpaperMetadata metadata) {
190         if ((info instanceof CreativeWallpaperInfo)
191                 && (metadata instanceof LiveWallpaperMetadata)) {
192             ((CreativeWallpaperInfo) info).setConfigPreviewUri(
193                     ((LiveWallpaperMetadata) metadata).getPreviewUri());
194         }
195     }
196 
isLockWallpaperBuiltIn(Context context)197     private boolean isLockWallpaperBuiltIn(Context context) {
198         WallpaperManager manager =
199                 (WallpaperManager) context.getSystemService(Context.WALLPAPER_SERVICE);
200 
201         return manager.lockScreenWallpaperExists()
202                 && manager.getWallpaperInfo(WallpaperManager.FLAG_LOCK) == null
203                 && manager.getWallpaperFile(WallpaperManager.FLAG_LOCK) == null;
204     }
205 
206     /**
207      * We check 2 things in this function:
208      * 1. If mHomeWallpaper is null, the wallpaper is not initialized. Return false.
209      * 2. In the case when mHomeWallpaper is not null, we check if mHomeWallpaper is synced with the
210      *    one from the wallpaper manager.
211      */
homeWallpaperSynced(Context context)212     private boolean homeWallpaperSynced(Context context) {
213         if (mHomeWallpaper == null) {
214             return false;
215         }
216         return wallpaperSynced(context, mHomeWallpaper, WallpaperManager.FLAG_SYSTEM);
217     }
218 
219     /**
220      * mLockWallpaper can be null even after initialization. We only check the case if the
221      * lockscreen wallpaper is synced.
222      */
lockWallpaperSynced(Context context)223     private boolean lockWallpaperSynced(Context context) {
224         return wallpaperSynced(context, mLockWallpaper, WallpaperManager.FLAG_LOCK);
225     }
226 
227     /**
228      * Check if the given wallpaper info is synced with the one from the wallpaper manager. We only
229      * try to get the underlying ComponentName from both sides.
230      * If both are null, it means both are static image wallpapers, or both are not set,
231      * which we consider synced and return true.
232      * If only of the them is null, it means one is static image wallpaper and another is live
233      * wallpaper. We should return false.
234      * If both are not null, we check if the two ComponentName(s) are equal.
235      */
wallpaperSynced(Context context, @Nullable WallpaperInfo wallpaperInfo, int which)236     private boolean wallpaperSynced(Context context, @Nullable WallpaperInfo wallpaperInfo,
237             int which) {
238         android.app.WallpaperInfo currentWallpaperInfo = WallpaperManager.getInstance(context)
239                 .getWallpaperInfo(which);
240         ComponentName currentComponentName = currentWallpaperInfo != null
241                 ? currentWallpaperInfo.getComponent() : null;
242         android.app.WallpaperInfo info = wallpaperInfo != null
243                 ? wallpaperInfo.getWallpaperComponent() : null;
244         ComponentName homeComponentName = info != null
245                 ? info.getComponent() : null;
246         if (currentComponentName == null) {
247             // If both are null, it might not be synced for LOCK (param which is 2):
248             // When previous LOCK is default static then homeComponentName will be null, and current
249             // wallpaper is live for both home and lock then currentComponentName will be null.
250             if (homeComponentName == null) {
251                 return which != WallpaperManager.FLAG_LOCK;
252             } else {
253                 return false;
254             }
255         } else if (homeComponentName == null) {
256             // currentComponentName not null and homeComponentName null. It's not synced.
257             return false;
258         } else {
259             return currentComponentName.equals(homeComponentName);
260         }
261     }
262 
263     @Override
clearCurrentWallpaperInfos()264     public void clearCurrentWallpaperInfos() {
265         mHomeWallpaper = null;
266         mLockWallpaper = null;
267     }
268 }
269