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 static com.android.window.flags.Flags.multiCrop; 22 23 import android.app.WallpaperManager; 24 import android.content.res.Resources; 25 import android.graphics.Point; 26 import android.graphics.Rect; 27 import android.hardware.display.DisplayManager; 28 import android.os.Binder; 29 import android.os.Debug; 30 import android.util.Slog; 31 import android.util.SparseArray; 32 import android.view.Display; 33 import android.view.DisplayInfo; 34 import android.view.WindowManager; 35 36 import com.android.server.wm.WindowManagerInternal; 37 38 import java.util.function.Consumer; 39 40 /** 41 * Internal class used to store all the display data relevant to the wallpapers 42 */ 43 class WallpaperDisplayHelper { 44 45 static final class DisplayData { 46 int mWidth = -1; 47 int mHeight = -1; 48 final Rect mPadding = new Rect(0, 0, 0, 0); 49 final int mDisplayId; DisplayData(int displayId)50 DisplayData(int displayId) { 51 mDisplayId = displayId; 52 } 53 } 54 55 private static final String TAG = WallpaperDisplayHelper.class.getSimpleName(); 56 57 private final SparseArray<DisplayData> mDisplayDatas = new SparseArray<>(); 58 private final DisplayManager mDisplayManager; 59 private final WindowManagerInternal mWindowManagerInternal; 60 61 private final WallpaperDefaultDisplayInfo mDefaultDisplayInfo; 62 WallpaperDisplayHelper( DisplayManager displayManager, WindowManager windowManager, WindowManagerInternal windowManagerInternal, Resources resources)63 WallpaperDisplayHelper( 64 DisplayManager displayManager, 65 WindowManager windowManager, 66 WindowManagerInternal windowManagerInternal, 67 Resources resources) { 68 mDisplayManager = displayManager; 69 mWindowManagerInternal = windowManagerInternal; 70 if (!multiCrop()) { 71 mDefaultDisplayInfo = new WallpaperDefaultDisplayInfo(); 72 return; 73 } 74 mDefaultDisplayInfo = new WallpaperDefaultDisplayInfo(windowManager, resources); 75 } 76 getDisplayDataOrCreate(int displayId)77 DisplayData getDisplayDataOrCreate(int displayId) { 78 DisplayData wpdData = mDisplayDatas.get(displayId); 79 if (wpdData == null) { 80 wpdData = new DisplayData(displayId); 81 ensureSaneWallpaperDisplaySize(wpdData, displayId); 82 mDisplayDatas.append(displayId, wpdData); 83 } 84 return wpdData; 85 } 86 getDefaultDisplayCurrentOrientation()87 int getDefaultDisplayCurrentOrientation() { 88 Point displaySize = new Point(); 89 mDisplayManager.getDisplay(DEFAULT_DISPLAY).getSize(displaySize); 90 return WallpaperManager.getOrientation(displaySize); 91 } 92 removeDisplayData(int displayId)93 void removeDisplayData(int displayId) { 94 mDisplayDatas.remove(displayId); 95 } 96 ensureSaneWallpaperDisplaySize(DisplayData wpdData, int displayId)97 void ensureSaneWallpaperDisplaySize(DisplayData wpdData, int displayId) { 98 // We always want to have some reasonable width hint. 99 final int baseSize = getMaximumSizeDimension(displayId); 100 if (wpdData.mWidth < baseSize) { 101 wpdData.mWidth = baseSize; 102 } 103 if (wpdData.mHeight < baseSize) { 104 wpdData.mHeight = baseSize; 105 } 106 } 107 getMaximumSizeDimension(int displayId)108 int getMaximumSizeDimension(int displayId) { 109 Display display = mDisplayManager.getDisplay(displayId); 110 if (display == null) { 111 Slog.w(TAG, "Invalid displayId=" + displayId + " " + Debug.getCallers(4)); 112 display = mDisplayManager.getDisplay(DEFAULT_DISPLAY); 113 } 114 return display.getMaximumSizeDimension(); 115 } 116 forEachDisplayData(Consumer<DisplayData> action)117 void forEachDisplayData(Consumer<DisplayData> action) { 118 for (int i = mDisplayDatas.size() - 1; i >= 0; i--) { 119 final DisplayData wpdData = mDisplayDatas.valueAt(i); 120 action.accept(wpdData); 121 } 122 } 123 getDisplays()124 Display[] getDisplays() { 125 return mDisplayManager.getDisplays(); 126 } 127 getDisplayInfo(int displayId)128 DisplayInfo getDisplayInfo(int displayId) { 129 final DisplayInfo displayInfo = new DisplayInfo(); 130 mDisplayManager.getDisplay(displayId).getDisplayInfo(displayInfo); 131 return displayInfo; 132 } 133 isUsableDisplay(int displayId, int clientUid)134 boolean isUsableDisplay(int displayId, int clientUid) { 135 return isUsableDisplay(mDisplayManager.getDisplay(displayId), clientUid); 136 } 137 isUsableDisplay(Display display, int clientUid)138 boolean isUsableDisplay(Display display, int clientUid) { 139 if (display == null || !display.hasAccess(clientUid)) { 140 return false; 141 } 142 final int displayId = display.getDisplayId(); 143 if (displayId == DEFAULT_DISPLAY) { 144 return true; 145 } 146 147 final long ident = Binder.clearCallingIdentity(); 148 try { 149 return mWindowManagerInternal.isHomeSupportedOnDisplay(displayId); 150 } finally { 151 Binder.restoreCallingIdentity(ident); 152 } 153 } 154 isValidDisplay(int displayId)155 boolean isValidDisplay(int displayId) { 156 return mDisplayManager.getDisplay(displayId) != null; 157 } 158 getDefaultDisplaySizes()159 SparseArray<Point> getDefaultDisplaySizes() { 160 return mDefaultDisplayInfo.defaultDisplaySizes; 161 } 162 163 /** Return the number of pixel of the largest dimension of the default display */ getDefaultDisplayLargestDimension()164 int getDefaultDisplayLargestDimension() { 165 SparseArray<Point> defaultDisplaySizes = mDefaultDisplayInfo.defaultDisplaySizes; 166 int result = -1; 167 for (int i = 0; i < defaultDisplaySizes.size(); i++) { 168 Point size = defaultDisplaySizes.valueAt(i); 169 result = Math.max(result, Math.max(size.x, size.y)); 170 } 171 return result; 172 } 173 getDefaultDisplayInfo()174 public WallpaperDefaultDisplayInfo getDefaultDisplayInfo() { 175 return mDefaultDisplayInfo; 176 } 177 } 178