1 /* 2 * Copyright (C) 2021 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.wm; 18 19 import android.hardware.display.DisplayManagerInternal; 20 import android.util.ArraySet; 21 import android.util.Slog; 22 import android.util.SparseArray; 23 import android.view.DisplayInfo; 24 25 import java.util.ArrayList; 26 import java.util.List; 27 import java.util.Set; 28 29 /** 30 * Maintains a map of possible {@link DisplayInfo} for displays and states that may be encountered 31 * on a device. This is not guaranteed to include all possible device states for all displays. 32 * 33 * By 'possible', this class only handles device states for displays and display groups it is 34 * currently aware of. It can not handle all eventual states the system may enter, for example, if 35 * an external display is added, or a new display is added to the group. 36 */ 37 public class PossibleDisplayInfoMapper { 38 private static final String TAG = "PossibleDisplayInfoMapper"; 39 private static final boolean DEBUG = false; 40 41 private final DisplayManagerInternal mDisplayManagerInternal; 42 43 /** 44 * Map of all logical displays, indexed by logical display id. 45 * Each logical display has multiple entries, one for each device state. 46 * 47 * Emptied and re-calculated when a display is added, removed, or changed. 48 */ 49 private final SparseArray<Set<DisplayInfo>> mDisplayInfos = new SparseArray<>(); 50 PossibleDisplayInfoMapper(DisplayManagerInternal displayManagerInternal)51 PossibleDisplayInfoMapper(DisplayManagerInternal displayManagerInternal) { 52 mDisplayManagerInternal = displayManagerInternal; 53 } 54 55 56 /** 57 * Returns, for the given displayId, a list of unique display infos. List contains each 58 * supported device state. 59 * <p>List contents are guaranteed to be unique, but returned as a list rather than a set to 60 * minimize copies needed to make an iteraable data structure. 61 */ getPossibleDisplayInfos(int displayId)62 public List<DisplayInfo> getPossibleDisplayInfos(int displayId) { 63 // Update display infos before returning, since any cached values would have been removed 64 // in response to any display event. This model avoids re-computing the cache for every 65 // display change event (which occurs extremely frequently in the normal usage of the 66 // device). 67 updatePossibleDisplayInfos(displayId); 68 if (!mDisplayInfos.contains(displayId)) { 69 return new ArrayList<>(); 70 } 71 return List.copyOf(mDisplayInfos.get(displayId)); 72 } 73 74 /** 75 * Updates the possible {@link DisplayInfo}s for the given display, by saving the DisplayInfo 76 * across supported device states. 77 */ updatePossibleDisplayInfos(int displayId)78 public void updatePossibleDisplayInfos(int displayId) { 79 Set<DisplayInfo> displayInfos = mDisplayManagerInternal.getPossibleDisplayInfo(displayId); 80 if (DEBUG) { 81 Slog.v(TAG, "updatePossibleDisplayInfos, given DisplayInfo " 82 + displayInfos.size() + " on display " + displayId); 83 } 84 updateDisplayInfos(displayInfos); 85 } 86 87 /** 88 * For the given displayId, removes all possible {@link DisplayInfo}. 89 */ removePossibleDisplayInfos(int displayId)90 public void removePossibleDisplayInfos(int displayId) { 91 if (DEBUG && mDisplayInfos.get(displayId) != null) { 92 Slog.v(TAG, "onDisplayRemoved, remove all DisplayInfo (" + mDisplayInfos.get( 93 displayId).size() + ") with id " + displayId); 94 } 95 mDisplayInfos.remove(displayId); 96 } 97 updateDisplayInfos(Set<DisplayInfo> displayInfos)98 private void updateDisplayInfos(Set<DisplayInfo> displayInfos) { 99 // Empty out cache before re-computing. 100 mDisplayInfos.clear(); 101 // Iterate over each logical display layout for the current state. 102 for (DisplayInfo di : displayInfos) { 103 // Combine all results under the logical display id. 104 Set<DisplayInfo> priorDisplayInfos = mDisplayInfos.get(di.displayId, new ArraySet<>()); 105 priorDisplayInfos.add(di); 106 mDisplayInfos.put(di.displayId, priorDisplayInfos); 107 } 108 } 109 } 110