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