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 com.android.server.display.DisplayControl#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].
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(int port, Long model)51     public static Physical fromPortAndModel(int 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 com.android.server.display.DisplayControl#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].
96          */
getPort()97         public int getPort() {
98             return (int) (mPhysicalDisplayId & 0xFF);
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(@ullable Object other)113         public boolean equals(@Nullable 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(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(int port, Long model)145         private Physical(int port, Long model) {
146             if (port < 0 || port > 255) {
147                 throw new IllegalArgumentException("The port should be in the interval [0, 255]");
148             }
149             mPhysicalDisplayId = Integer.toUnsignedLong(port)
150                     | (model == null ? UNKNOWN_MODEL : (model << MODEL_SHIFT));
151         }
152 
153         public static final @NonNull Parcelable.Creator<Physical> CREATOR =
154                 new Parcelable.Creator<Physical>() {
155                     @Override
156                     public Physical createFromParcel(Parcel in) {
157                         return new Physical(in.readLong());
158                     }
159 
160                     @Override
161                     public Physical[] newArray(int size) {
162                         return new Physical[size];
163                     }
164                 };
165     }
166 
167     /**
168      * Address for a network-connected display.
169      */
170     public static final class Network extends DisplayAddress {
171         private final String mMacAddress;
172 
173         @Override
equals(@ullable Object other)174         public boolean equals(@Nullable Object other) {
175             return other instanceof Network && mMacAddress.equals(((Network) other).mMacAddress);
176         }
177 
178         @Override
toString()179         public String toString() {
180             return mMacAddress;
181         }
182 
183         @Override
hashCode()184         public int hashCode() {
185             return mMacAddress.hashCode();
186         }
187 
188         @Override
writeToParcel(Parcel out, int flags)189         public void writeToParcel(Parcel out, int flags) {
190             out.writeString(mMacAddress);
191         }
192 
Network(String macAddress)193         private Network(String macAddress) {
194             mMacAddress = macAddress;
195         }
196 
197         public static final @NonNull Parcelable.Creator<Network> CREATOR =
198                 new Parcelable.Creator<Network>() {
199                     @Override
200                     public Network createFromParcel(Parcel in) {
201                         return new Network(in.readString());
202                     }
203 
204                     @Override
205                     public Network[] newArray(int size) {
206                         return new Network[size];
207                     }
208                 };
209     }
210 
211     @Override
describeContents()212     public int describeContents() {
213         return 0;
214     }
215 }
216