blob: e3a2065838d1481ae29a977ec03ceb1547d0d615 [file] [log] [blame]
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.wm;
import android.hardware.display.DisplayManagerInternal;
import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseArray;
import android.view.DisplayInfo;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* Maintains a map of possible {@link DisplayInfo} for displays and states that may be encountered
* on a device. This is not guaranteed to include all possible device states for all displays.
*
* By 'possible', this class only handles device states for displays and display groups it is
* currently aware of. It can not handle all eventual states the system may enter, for example, if
* an external display is added, or a new display is added to the group.
*/
public class PossibleDisplayInfoMapper {
private static final String TAG = "PossibleDisplayInfoMapper";
private static final boolean DEBUG = false;
private final DisplayManagerInternal mDisplayManagerInternal;
/**
* Map of all logical displays, indexed by logical display id.
* Each logical display has multiple entries, one for each device state.
*
* Emptied and re-calculated when a display is added, removed, or changed.
*/
private final SparseArray<Set<DisplayInfo>> mDisplayInfos = new SparseArray<>();
PossibleDisplayInfoMapper(DisplayManagerInternal displayManagerInternal) {
mDisplayManagerInternal = displayManagerInternal;
}
/**
* Returns, for the given displayId, a list of unique display infos. List contains each
* supported device state.
* <p>List contents are guaranteed to be unique, but returned as a list rather than a set to
* minimize copies needed to make an iteraable data structure.
*/
public List<DisplayInfo> getPossibleDisplayInfos(int displayId) {
// Update display infos before returning, since any cached values would have been removed
// in response to any display event. This model avoids re-computing the cache for every
// display change event (which occurs extremely frequently in the normal usage of the
// device).
updatePossibleDisplayInfos(displayId);
if (!mDisplayInfos.contains(displayId)) {
return new ArrayList<>();
}
return List.copyOf(mDisplayInfos.get(displayId));
}
/**
* Updates the possible {@link DisplayInfo}s for the given display, by saving the DisplayInfo
* across supported device states.
*/
public void updatePossibleDisplayInfos(int displayId) {
Set<DisplayInfo> displayInfos = mDisplayManagerInternal.getPossibleDisplayInfo(displayId);
if (DEBUG) {
Slog.v(TAG, "updatePossibleDisplayInfos, given DisplayInfo "
+ displayInfos.size() + " on display " + displayId);
}
updateDisplayInfos(displayInfos);
}
/**
* For the given displayId, removes all possible {@link DisplayInfo}.
*/
public void removePossibleDisplayInfos(int displayId) {
if (DEBUG && mDisplayInfos.get(displayId) != null) {
Slog.v(TAG, "onDisplayRemoved, remove all DisplayInfo (" + mDisplayInfos.get(
displayId).size() + ") with id " + displayId);
}
mDisplayInfos.remove(displayId);
}
private void updateDisplayInfos(Set<DisplayInfo> displayInfos) {
// Empty out cache before re-computing.
mDisplayInfos.clear();
// Iterate over each logical display layout for the current state.
for (DisplayInfo di : displayInfos) {
// Combine all results under the logical display id.
Set<DisplayInfo> priorDisplayInfos = mDisplayInfos.get(di.displayId, new ArraySet<>());
priorDisplayInfos.add(di);
mDisplayInfos.put(di.displayId, priorDisplayInfos);
}
}
}