1 /*
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 
17 package android.view;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.os.Parcel;
22 import android.os.Parcelable;
23 
24 /** Display identifier that is stable across reboots.
25  *
26  * @hide
27  */
28 public 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.
35      * @return The {@link Physical} address.
36      * @see SurfaceControl#getPhysicalDisplayIds
37      */
38     @NonNull
fromPhysicalDisplayId(long physicalDisplayId)39     public static Physical fromPhysicalDisplayId(long physicalDisplayId) {
40         return new Physical(physicalDisplayId);
41     }
42 
43     /**
44      * 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
fromPortAndModel(byte port, Long model)51     public static Physical fromPortAndModel(byte port, Long model) {
52         return new Physical(port, model);
53     }
54 
55     /**
56      * 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
fromMacAddress(String macAddress)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.
73      * 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.
75      */
76     public static final class Physical extends DisplayAddress {
77         private static final long UNKNOWN_MODEL = 0;
78         private static final int MODEL_SHIFT = 8;
79 
80         private final long mPhysicalDisplayId;
81 
82         /**
83          * 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          */
getPhysicalDisplayId()88         public long getPhysicalDisplayId() {
89             return mPhysicalDisplayId;
90         }
91 
92         /**
93          * Physical port to which the display is connected.
94          *
95          * @return A port in the range [0, 255] interpreted as signed.
96          */
getPort()97         public byte getPort() {
98             return (byte) mPhysicalDisplayId;
99         }
100 
101         /**
102          * Model identifier unique across manufacturers.
103          *
104          * @return A positive integer, or {@code null} if the model cannot be identified.
105          */
106         @Nullable
getModel()107         public Long getModel() {
108             final long model = mPhysicalDisplayId >>> MODEL_SHIFT;
109             return model == UNKNOWN_MODEL ? null : model;
110         }
111 
112         @Override
equals(Object other)113         public boolean equals(Object other) {
114             return other instanceof Physical
115                     && mPhysicalDisplayId == ((Physical) other).mPhysicalDisplayId;
116         }
117 
118         @Override
toString()119         public String toString() {
120             final StringBuilder builder = new StringBuilder("{")
121                     .append("port=").append(Byte.toUnsignedInt(getPort()));
122 
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();
129         }
130 
131         @Override
hashCode()132         public int hashCode() {
133             return Long.hashCode(mPhysicalDisplayId);
134         }
135 
136         @Override
writeToParcel(Parcel out, int flags)137         public void writeToParcel(Parcel out, int flags) {
138             out.writeLong(mPhysicalDisplayId);
139         }
140 
Physical(long physicalDisplayId)141         private Physical(long physicalDisplayId) {
142             mPhysicalDisplayId = physicalDisplayId;
143         }
144 
Physical(byte port, Long model)145         private Physical(byte port, Long model) {
146             mPhysicalDisplayId = Byte.toUnsignedLong(port)
147                     | (model == null ? UNKNOWN_MODEL : (model << MODEL_SHIFT));
148         }
149 
150         public static final @NonNull Parcelable.Creator<Physical> CREATOR =
151                 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
equals(Object other)171         public boolean equals(Object other) {
172             return other instanceof Network && mMacAddress.equals(((Network) other).mMacAddress);
173         }
174 
175         @Override
toString()176         public String toString() {
177             return mMacAddress;
178         }
179 
180         @Override
hashCode()181         public int hashCode() {
182             return mMacAddress.hashCode();
183         }
184 
185         @Override
writeToParcel(Parcel out, int flags)186         public void writeToParcel(Parcel out, int flags) {
187             out.writeString(mMacAddress);
188         }
189 
Network(String macAddress)190         private Network(String macAddress) {
191             mMacAddress = macAddress;
192         }
193 
194         public static final @NonNull Parcelable.Creator<Network> CREATOR =
195                 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
describeContents()209     public int describeContents() {
210         return 0;
211     }
212 }
213