• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.display.layout;
18 
19 import static android.view.Display.DEFAULT_DISPLAY;
20 
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.util.Slog;
24 import android.view.DisplayAddress;
25 
26 import java.util.ArrayList;
27 import java.util.List;
28 
29 /**
30  * Holds a collection of {@link Display}s. A single instance of this class describes
31  * how to organize one or more DisplayDevices into LogicalDisplays for a particular device
32  * state. For example, there may be one instance of this class to describe display layout when
33  * a foldable device is folded, and a second instance for when the device is unfolded.
34  */
35 public class Layout {
36     private static final String TAG = "Layout";
37     private static int sNextNonDefaultDisplayId = DEFAULT_DISPLAY + 1;
38 
39     private final List<Display> mDisplays = new ArrayList<>(2);
40 
41     /**
42      *  @return The default display ID, or a new unique one to use.
43      */
assignDisplayIdLocked(boolean isDefault)44     public static int assignDisplayIdLocked(boolean isDefault) {
45         return isDefault ? DEFAULT_DISPLAY : sNextNonDefaultDisplayId++;
46     }
47 
48     @Override
toString()49     public String toString() {
50         return mDisplays.toString();
51     }
52 
53     /**
54      * Creates a simple 1:1 LogicalDisplay mapping for the specified DisplayDevice.
55      *
56      * @param address Address of the device.
57      * @param isDefault Indicates if the device is meant to be the default display.
58      * @return The new layout.
59      */
createDisplayLocked( @onNull DisplayAddress address, boolean isDefault, boolean isEnabled)60     public Display createDisplayLocked(
61             @NonNull DisplayAddress address, boolean isDefault, boolean isEnabled) {
62         if (contains(address)) {
63             Slog.w(TAG, "Attempting to add second definition for display-device: " + address);
64             return null;
65         }
66 
67         // See if we're dealing with the "default" display
68         if (isDefault && getById(DEFAULT_DISPLAY) != null) {
69             Slog.w(TAG, "Ignoring attempt to add a second default display: " + address);
70             return null;
71         }
72 
73         // Assign a logical display ID and create the new display.
74         // Note that the logical display ID is saved into the layout, so when switching between
75         // different layouts, a logical display can be destroyed and later recreated with the
76         // same logical display ID.
77         final int logicalDisplayId = assignDisplayIdLocked(isDefault);
78         final Display display = new Display(address, logicalDisplayId, isEnabled);
79 
80         mDisplays.add(display);
81         return display;
82     }
83 
84     /**
85      * @param id The ID of the display to remove.
86      */
removeDisplayLocked(int id)87     public void removeDisplayLocked(int id) {
88         Display display = getById(id);
89         if (display != null) {
90             mDisplays.remove(display);
91         }
92     }
93 
94     /**
95      * @param address The address to check.
96      *
97      * @return True if the specified address is used in this layout.
98      */
contains(@onNull DisplayAddress address)99     public boolean contains(@NonNull DisplayAddress address) {
100         final int size = mDisplays.size();
101         for (int i = 0; i < size; i++) {
102             if (address.equals(mDisplays.get(i).getAddress())) {
103                 return true;
104             }
105         }
106         return false;
107     }
108 
109     /**
110      * @param id The display ID to check.
111      *
112      * @return The display corresponding to the specified display ID.
113      */
114     @Nullable
getById(int id)115     public Display getById(int id) {
116         for (int i = 0; i < mDisplays.size(); i++) {
117             Display display = mDisplays.get(i);
118             if (id == display.getLogicalDisplayId()) {
119                 return display;
120             }
121         }
122         return null;
123     }
124 
125     /**
126      * @param address The display address to check.
127      *
128      * @return The display corresponding to the specified address.
129      */
130     @Nullable
getByAddress(@onNull DisplayAddress address)131     public Display getByAddress(@NonNull DisplayAddress address) {
132         for (int i = 0; i < mDisplays.size(); i++) {
133             Display display = mDisplays.get(i);
134             if (address.equals(display.getAddress())) {
135                 return display;
136             }
137         }
138         return null;
139     }
140 
141     /**
142      * @param index The index of the display to return.
143      *
144      * @return the display at the specified index.
145      */
getAt(int index)146     public Display getAt(int index) {
147         return mDisplays.get(index);
148     }
149 
150     /**
151      * @return The number of displays defined for this layout.
152      */
size()153     public int size() {
154         return mDisplays.size();
155     }
156 
157     /**
158      * Describes how a {@link LogicalDisplay} is built from {@link DisplayDevice}s.
159      */
160     public static class Display {
161         // Address of the display device to map to this display.
162         private final DisplayAddress mAddress;
163 
164         // Logical Display ID to apply to this display.
165         private final int mLogicalDisplayId;
166 
167         // Indicates that this display is not usable and should remain off.
168         private final boolean mIsEnabled;
169 
Display(@onNull DisplayAddress address, int logicalDisplayId, boolean isEnabled)170         Display(@NonNull DisplayAddress address, int logicalDisplayId, boolean isEnabled) {
171             mAddress = address;
172             mLogicalDisplayId = logicalDisplayId;
173             mIsEnabled = isEnabled;
174         }
175 
176         @Override
toString()177         public String toString() {
178             return "{addr: " + mAddress + ", dispId: " + mLogicalDisplayId
179                     + "(" + (mIsEnabled ? "ON" : "OFF") + ")}";
180         }
181 
getAddress()182         public DisplayAddress getAddress() {
183             return mAddress;
184         }
185 
getLogicalDisplayId()186         public int getLogicalDisplayId() {
187             return mLogicalDisplayId;
188         }
189 
isEnabled()190         public boolean isEnabled() {
191             return mIsEnabled;
192         }
193     }
194 }
195