• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
141         /**
142          * This method is meant to check to see if the ports match
143          * @param a1 Address to compare
144          * @param a2 Address to compare
145          *
146          * @return true if the arguments have the same port, and at least one does not specify
147          *         a model.
148          */
isPortMatch(DisplayAddress a1, DisplayAddress a2)149         public static boolean isPortMatch(DisplayAddress a1, DisplayAddress a2) {
150             // Both displays must be of type Physical
151             if (!(a1 instanceof Physical && a2 instanceof Physical)) {
152                 return false;
153             }
154             Physical p1 = (Physical) a1;
155             Physical p2 = (Physical) a2;
156 
157             // If both addresses specify a model, fallback to a basic match check (which
158             // also checks the port).
159             if (p1.getModel() != null && p2.getModel() != null) {
160                 return p1.equals(p2);
161             }
162             return p1.getPort() == p2.getPort();
163         }
164 
Physical(long physicalDisplayId)165         private Physical(long physicalDisplayId) {
166             mPhysicalDisplayId = physicalDisplayId;
167         }
168 
Physical(int port, Long model)169         private Physical(int port, Long model) {
170             if (port < 0 || port > 255) {
171                 throw new IllegalArgumentException("The port should be in the interval [0, 255]");
172             }
173             mPhysicalDisplayId = Integer.toUnsignedLong(port)
174                     | (model == null ? UNKNOWN_MODEL : (model << MODEL_SHIFT));
175         }
176 
177         public static final @NonNull Parcelable.Creator<Physical> CREATOR =
178                 new Parcelable.Creator<Physical>() {
179                     @Override
180                     public Physical createFromParcel(Parcel in) {
181                         return new Physical(in.readLong());
182                     }
183 
184                     @Override
185                     public Physical[] newArray(int size) {
186                         return new Physical[size];
187                     }
188                 };
189     }
190 
191     /**
192      * Address for a network-connected display.
193      */
194     public static final class Network extends DisplayAddress {
195         private final String mMacAddress;
196 
197         @Override
equals(@ullable Object other)198         public boolean equals(@Nullable Object other) {
199             return other instanceof Network && mMacAddress.equals(((Network) other).mMacAddress);
200         }
201 
202         @Override
toString()203         public String toString() {
204             return mMacAddress;
205         }
206 
207         @Override
hashCode()208         public int hashCode() {
209             return mMacAddress.hashCode();
210         }
211 
212         @Override
writeToParcel(Parcel out, int flags)213         public void writeToParcel(Parcel out, int flags) {
214             out.writeString(mMacAddress);
215         }
216 
Network(String macAddress)217         private Network(String macAddress) {
218             mMacAddress = macAddress;
219         }
220 
221         public static final @NonNull Parcelable.Creator<Network> CREATOR =
222                 new Parcelable.Creator<Network>() {
223                     @Override
224                     public Network createFromParcel(Parcel in) {
225                         return new Network(in.readString());
226                     }
227 
228                     @Override
229                     public Network[] newArray(int size) {
230                         return new Network[size];
231                     }
232                 };
233     }
234 
235     @Override
describeContents()236     public int describeContents() {
237         return 0;
238     }
239 }
240