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.view.Display.DEFAULT_DISPLAY;
20 
21 import android.graphics.Rect;
22 import android.hardware.display.DisplayManager;
23 import android.os.Binder;
24 import android.os.Debug;
25 import android.util.Slog;
26 import android.util.SparseArray;
27 import android.view.Display;
28 import android.view.DisplayInfo;
29 
30 import com.android.server.wm.WindowManagerInternal;
31 
32 import java.util.function.Consumer;
33 
34 /**
35  * Internal class used to store all the display data relevant to the wallpapers
36  */
37 class WallpaperDisplayHelper {
38 
39     static final class DisplayData {
40         int mWidth = -1;
41         int mHeight = -1;
42         final Rect mPadding = new Rect(0, 0, 0, 0);
43         final int mDisplayId;
DisplayData(int displayId)44         DisplayData(int displayId) {
45             mDisplayId = displayId;
46         }
47     }
48 
49     private static final String TAG = WallpaperDisplayHelper.class.getSimpleName();
50     private final SparseArray<DisplayData> mDisplayDatas = new SparseArray<>();
51     private final DisplayManager mDisplayManager;
52     private final WindowManagerInternal mWindowManagerInternal;
53 
WallpaperDisplayHelper( DisplayManager displayManager, WindowManagerInternal windowManagerInternal)54     WallpaperDisplayHelper(
55             DisplayManager displayManager,
56             WindowManagerInternal windowManagerInternal) {
57         mDisplayManager = displayManager;
58         mWindowManagerInternal = windowManagerInternal;
59     }
60 
getDisplayDataOrCreate(int displayId)61     DisplayData getDisplayDataOrCreate(int displayId) {
62         DisplayData wpdData = mDisplayDatas.get(displayId);
63         if (wpdData == null) {
64             wpdData = new DisplayData(displayId);
65             ensureSaneWallpaperDisplaySize(wpdData, displayId);
66             mDisplayDatas.append(displayId, wpdData);
67         }
68         return wpdData;
69     }
70 
removeDisplayData(int displayId)71     void removeDisplayData(int displayId) {
72         mDisplayDatas.remove(displayId);
73     }
74 
ensureSaneWallpaperDisplaySize(DisplayData wpdData, int displayId)75     void ensureSaneWallpaperDisplaySize(DisplayData wpdData, int displayId) {
76         // We always want to have some reasonable width hint.
77         final int baseSize = getMaximumSizeDimension(displayId);
78         if (wpdData.mWidth < baseSize) {
79             wpdData.mWidth = baseSize;
80         }
81         if (wpdData.mHeight < baseSize) {
82             wpdData.mHeight = baseSize;
83         }
84     }
85 
getMaximumSizeDimension(int displayId)86     int getMaximumSizeDimension(int displayId) {
87         Display display = mDisplayManager.getDisplay(displayId);
88         if (display == null) {
89             Slog.w(TAG, "Invalid displayId=" + displayId + " " + Debug.getCallers(4));
90             display = mDisplayManager.getDisplay(DEFAULT_DISPLAY);
91         }
92         return display.getMaximumSizeDimension();
93     }
94 
forEachDisplayData(Consumer<DisplayData> action)95     void forEachDisplayData(Consumer<DisplayData> action) {
96         for (int i = mDisplayDatas.size() - 1; i >= 0; i--) {
97             final DisplayData wpdData = mDisplayDatas.valueAt(i);
98             action.accept(wpdData);
99         }
100     }
101 
getDisplays()102     Display[] getDisplays() {
103         return mDisplayManager.getDisplays();
104     }
105 
getDisplayInfo(int displayId)106     DisplayInfo getDisplayInfo(int displayId) {
107         final DisplayInfo displayInfo = new DisplayInfo();
108         mDisplayManager.getDisplay(displayId).getDisplayInfo(displayInfo);
109         return displayInfo;
110     }
111 
isUsableDisplay(int displayId, int clientUid)112     boolean isUsableDisplay(int displayId, int clientUid) {
113         return isUsableDisplay(mDisplayManager.getDisplay(displayId), clientUid);
114     }
115 
isUsableDisplay(Display display, int clientUid)116     boolean isUsableDisplay(Display display, int clientUid) {
117         if (display == null || !display.hasAccess(clientUid)) {
118             return false;
119         }
120         final int displayId = display.getDisplayId();
121         if (displayId == DEFAULT_DISPLAY) {
122             return true;
123         }
124 
125         final long ident = Binder.clearCallingIdentity();
126         try {
127             return mWindowManagerInternal.shouldShowSystemDecorOnDisplay(displayId);
128         } finally {
129             Binder.restoreCallingIdentity(ident);
130         }
131     }
132 
isValidDisplay(int displayId)133     boolean isValidDisplay(int displayId) {
134         return mDisplayManager.getDisplay(displayId) != null;
135     }
136 }
137