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 network display given its MAC address.
45      *
46      * @param macAddress A MAC address in colon notation.
47      * @return The {@link Network} address.
48      */
49     @NonNull
fromMacAddress(String macAddress)50     public static Network fromMacAddress(String macAddress) {
51         return new Network(macAddress);
52     }
53 
54     /**
55      * Address for a physically connected display.
56      *
57      * A {@link Physical} address is represented by a 64-bit identifier combining the port and model
58      * of a display. The port, located in the least significant byte, uniquely identifies a physical
59      * connector on the device for display output like eDP or HDMI. The model, located in the upper
60      * bits, uniquely identifies a display model across manufacturers by encoding EDID information.
61      * While the port is always stable, the model may not be available if EDID identification is not
62      * supported by the platform, in which case the address is not unique.
63      */
64     public static final class Physical extends DisplayAddress {
65         private static final long UNKNOWN_MODEL = 0;
66         private static final int MODEL_SHIFT = 8;
67         private static final int PORT_MASK = 0xFF;
68 
69         private final long mPhysicalDisplayId;
70 
71         /**
72          * Physical port to which the display is connected.
73          */
getPort()74         public byte getPort() {
75             return (byte) mPhysicalDisplayId;
76         }
77 
78         /**
79          * Model identifier unique across manufacturers.
80          *
81          * @return The model ID, or {@code null} if the model cannot be identified.
82          */
83         @Nullable
getModel()84         public Long getModel() {
85             final long model = mPhysicalDisplayId >>> MODEL_SHIFT;
86             return model == UNKNOWN_MODEL ? null : model;
87         }
88 
89         @Override
equals(Object other)90         public boolean equals(Object other) {
91             return other instanceof Physical
92                     && mPhysicalDisplayId == ((Physical) other).mPhysicalDisplayId;
93         }
94 
95         @Override
toString()96         public String toString() {
97             final StringBuilder builder = new StringBuilder("{")
98                     .append("port=").append(getPort() & PORT_MASK);
99 
100             final Long model = getModel();
101             if (model != null) {
102                 builder.append(", model=0x").append(Long.toHexString(model));
103             }
104 
105             return builder.append("}").toString();
106         }
107 
108         @Override
hashCode()109         public int hashCode() {
110             return Long.hashCode(mPhysicalDisplayId);
111         }
112 
113         @Override
writeToParcel(Parcel out, int flags)114         public void writeToParcel(Parcel out, int flags) {
115             out.writeLong(mPhysicalDisplayId);
116         }
117 
Physical(long physicalDisplayId)118         private Physical(long physicalDisplayId) {
119             mPhysicalDisplayId = physicalDisplayId;
120         }
121 
122         public static final @NonNull Parcelable.Creator<Physical> CREATOR =
123                 new Parcelable.Creator<Physical>() {
124                     @Override
125                     public Physical createFromParcel(Parcel in) {
126                         return new Physical(in.readLong());
127                     }
128 
129                     @Override
130                     public Physical[] newArray(int size) {
131                         return new Physical[size];
132                     }
133                 };
134     }
135 
136     /**
137      * Address for a network-connected display.
138      */
139     public static final class Network extends DisplayAddress {
140         private final String mMacAddress;
141 
142         @Override
equals(Object other)143         public boolean equals(Object other) {
144             return other instanceof Network && mMacAddress.equals(((Network) other).mMacAddress);
145         }
146 
147         @Override
toString()148         public String toString() {
149             return mMacAddress;
150         }
151 
152         @Override
hashCode()153         public int hashCode() {
154             return mMacAddress.hashCode();
155         }
156 
157         @Override
writeToParcel(Parcel out, int flags)158         public void writeToParcel(Parcel out, int flags) {
159             out.writeString(mMacAddress);
160         }
161 
Network(String macAddress)162         private Network(String macAddress) {
163             mMacAddress = macAddress;
164         }
165 
166         public static final @NonNull Parcelable.Creator<Network> CREATOR =
167                 new Parcelable.Creator<Network>() {
168                     @Override
169                     public Network createFromParcel(Parcel in) {
170                         return new Network(in.readString());
171                     }
172 
173                     @Override
174                     public Network[] newArray(int size) {
175                         return new Network[size];
176                     }
177                 };
178     }
179 
180     @Override
describeContents()181     public int describeContents() {
182         return 0;
183     }
184 }
185