blob: e0d9a4dd1df05c859eb56f0f987e215d34a42c32 [file] [log] [blame]
Dominik Laskowskidb845962019-01-27 21:20:00 -08001/*
2 * Copyright (C) 2019 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
17package android.view;
18
19import android.annotation.NonNull;
20import android.annotation.Nullable;
21import android.os.Parcel;
22import android.os.Parcelable;
23
24/** Display identifier that is stable across reboots.
25 *
26 * @hide
27 */
28public abstract class DisplayAddress implements Parcelable {
29 /**
30 * Creates an address for a physical display given its stable ID.
31 *
32 * A physical display ID is stable if the display can be identified using EDID information.
33 *
34 * @param physicalDisplayId A physical display ID.
Dominik Laskowski0de02a82019-04-17 16:45:16 -070035 * @return The {@link Physical} address.
Dominik Laskowskidb845962019-01-27 21:20:00 -080036 * @see SurfaceControl#getPhysicalDisplayIds
37 */
Dominik Laskowski0de02a82019-04-17 16:45:16 -070038 @NonNull
Dominik Laskowskidb845962019-01-27 21:20:00 -080039 public static Physical fromPhysicalDisplayId(long physicalDisplayId) {
Dominik Laskowski0de02a82019-04-17 16:45:16 -070040 return new Physical(physicalDisplayId);
Dominik Laskowskidb845962019-01-27 21:20:00 -080041 }
42
43 /**
Dominik Laskowski67cc7f82019-11-08 17:09:29 -080044 * Creates an address for a physical display given its port and model.
45 *
46 * @param port A port in the range [0, 255] interpreted as signed.
47 * @param model A positive integer, or {@code null} if the model cannot be identified.
48 * @return The {@link Physical} address.
49 */
50 @NonNull
51 public static Physical fromPortAndModel(byte port, Long model) {
52 return new Physical(port, model);
53 }
54
55 /**
Dominik Laskowskidb845962019-01-27 21:20:00 -080056 * Creates an address for a network display given its MAC address.
57 *
58 * @param macAddress A MAC address in colon notation.
59 * @return The {@link Network} address.
60 */
61 @NonNull
62 public static Network fromMacAddress(String macAddress) {
63 return new Network(macAddress);
64 }
65
66 /**
67 * Address for a physically connected display.
68 *
69 * A {@link Physical} address is represented by a 64-bit identifier combining the port and model
70 * of a display. The port, located in the least significant byte, uniquely identifies a physical
71 * connector on the device for display output like eDP or HDMI. The model, located in the upper
72 * bits, uniquely identifies a display model across manufacturers by encoding EDID information.
Dominik Laskowski0de02a82019-04-17 16:45:16 -070073 * While the port is always stable, the model may not be available if EDID identification is not
74 * supported by the platform, in which case the address is not unique.
Dominik Laskowskidb845962019-01-27 21:20:00 -080075 */
76 public static final class Physical extends DisplayAddress {
Dominik Laskowski0de02a82019-04-17 16:45:16 -070077 private static final long UNKNOWN_MODEL = 0;
78 private static final int MODEL_SHIFT = 8;
Dominik Laskowskidb845962019-01-27 21:20:00 -080079
80 private final long mPhysicalDisplayId;
81
82 /**
Dominik Laskowski67cc7f82019-11-08 17:09:29 -080083 * Stable display ID combining port and model.
84 *
85 * @return An ID in the range [0, 2^64) interpreted as signed.
86 * @see SurfaceControl#getPhysicalDisplayIds
87 */
88 public long getPhysicalDisplayId() {
89 return mPhysicalDisplayId;
90 }
91
92 /**
Dominik Laskowskidb845962019-01-27 21:20:00 -080093 * Physical port to which the display is connected.
Dominik Laskowski67cc7f82019-11-08 17:09:29 -080094 *
95 * @return A port in the range [0, 255] interpreted as signed.
Dominik Laskowskidb845962019-01-27 21:20:00 -080096 */
97 public byte getPort() {
98 return (byte) mPhysicalDisplayId;
99 }
100
101 /**
102 * Model identifier unique across manufacturers.
Dominik Laskowski0de02a82019-04-17 16:45:16 -0700103 *
Dominik Laskowski67cc7f82019-11-08 17:09:29 -0800104 * @return A positive integer, or {@code null} if the model cannot be identified.
Dominik Laskowskidb845962019-01-27 21:20:00 -0800105 */
Dominik Laskowski0de02a82019-04-17 16:45:16 -0700106 @Nullable
107 public Long getModel() {
108 final long model = mPhysicalDisplayId >>> MODEL_SHIFT;
109 return model == UNKNOWN_MODEL ? null : model;
Dominik Laskowskidb845962019-01-27 21:20:00 -0800110 }
111
112 @Override
113 public boolean equals(Object other) {
114 return other instanceof Physical
115 && mPhysicalDisplayId == ((Physical) other).mPhysicalDisplayId;
116 }
117
118 @Override
119 public String toString() {
Dominik Laskowski0de02a82019-04-17 16:45:16 -0700120 final StringBuilder builder = new StringBuilder("{")
Dominik Laskowski67cc7f82019-11-08 17:09:29 -0800121 .append("port=").append(Byte.toUnsignedInt(getPort()));
Dominik Laskowski0de02a82019-04-17 16:45:16 -0700122
123 final Long model = getModel();
124 if (model != null) {
125 builder.append(", model=0x").append(Long.toHexString(model));
126 }
127
128 return builder.append("}").toString();
Dominik Laskowskidb845962019-01-27 21:20:00 -0800129 }
130
131 @Override
132 public int hashCode() {
133 return Long.hashCode(mPhysicalDisplayId);
134 }
135
136 @Override
137 public void writeToParcel(Parcel out, int flags) {
138 out.writeLong(mPhysicalDisplayId);
139 }
140
141 private Physical(long physicalDisplayId) {
142 mPhysicalDisplayId = physicalDisplayId;
143 }
144
Dominik Laskowski67cc7f82019-11-08 17:09:29 -0800145 private Physical(byte port, Long model) {
146 mPhysicalDisplayId = Byte.toUnsignedLong(port)
147 | (model == null ? UNKNOWN_MODEL : (model << MODEL_SHIFT));
148 }
149
Dominik Laskowski0de02a82019-04-17 16:45:16 -0700150 public static final @NonNull Parcelable.Creator<Physical> CREATOR =
Dominik Laskowskidb845962019-01-27 21:20:00 -0800151 new Parcelable.Creator<Physical>() {
152 @Override
153 public Physical createFromParcel(Parcel in) {
154 return new Physical(in.readLong());
155 }
156
157 @Override
158 public Physical[] newArray(int size) {
159 return new Physical[size];
160 }
161 };
162 }
163
164 /**
165 * Address for a network-connected display.
166 */
167 public static final class Network extends DisplayAddress {
168 private final String mMacAddress;
169
170 @Override
171 public boolean equals(Object other) {
172 return other instanceof Network && mMacAddress.equals(((Network) other).mMacAddress);
173 }
174
175 @Override
176 public String toString() {
177 return mMacAddress;
178 }
179
180 @Override
181 public int hashCode() {
182 return mMacAddress.hashCode();
183 }
184
185 @Override
186 public void writeToParcel(Parcel out, int flags) {
187 out.writeString(mMacAddress);
188 }
189
190 private Network(String macAddress) {
191 mMacAddress = macAddress;
192 }
193
Dominik Laskowski0de02a82019-04-17 16:45:16 -0700194 public static final @NonNull Parcelable.Creator<Network> CREATOR =
Dominik Laskowskidb845962019-01-27 21:20:00 -0800195 new Parcelable.Creator<Network>() {
196 @Override
197 public Network createFromParcel(Parcel in) {
198 return new Network(in.readString());
199 }
200
201 @Override
202 public Network[] newArray(int size) {
203 return new Network[size];
204 }
205 };
206 }
207
208 @Override
209 public int describeContents() {
210 return 0;
211 }
212}