1 /* 2 * Copyright (C) 2021 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.displayhash; 18 19 import android.annotation.CurrentTimeMillisLong; 20 import android.annotation.NonNull; 21 import android.annotation.SystemApi; 22 import android.graphics.Rect; 23 import android.os.Parcel; 24 import android.os.Parcelable; 25 26 import com.android.internal.util.AnnotationValidations; 27 28 /** 29 * The DisplayHash used to validate information about what was present on screen. 30 */ 31 public final class DisplayHash implements Parcelable { 32 /** 33 * The timestamp when the hash was generated. 34 */ 35 @CurrentTimeMillisLong 36 private final long mTimeMillis; 37 38 /** 39 * The bounds of the requested area to generate the hash. This is in window space passed in 40 * by the client. 41 */ 42 @NonNull 43 private final Rect mBoundsInWindow; 44 45 /** 46 * The selected hash algorithm that generated the image hash. 47 */ 48 @NonNull 49 private final String mHashAlgorithm; 50 51 /** 52 * The image hash generated when creating the DisplayHash. 53 */ 54 @NonNull 55 private final byte[] mImageHash; 56 57 /** 58 * The hmac generated by the system and used to verify whether this token was generated by 59 * the system. 60 */ 61 @NonNull 62 private final byte[] mHmac; 63 64 /** 65 * Creates a new DisplayHash. 66 * 67 * @param timeMillis The timestamp when the hash was generated. 68 * @param boundsInWindow The bounds of the requested area to generate the hash. This is 69 * in window space passed in by the client. 70 * @param hashAlgorithm The selected hash algorithm that generated the image hash. 71 * @param imageHash The image hash generated when creating the DisplayHash. 72 * @param hmac The hmac generated by the system and used to verify whether this 73 * token was generated by 74 * the system. This should only be accessed by a system process. 75 * @hide 76 */ 77 @SystemApi DisplayHash(@urrentTimeMillisLong long timeMillis, @NonNull Rect boundsInWindow, @NonNull String hashAlgorithm, @NonNull byte[] imageHash, @NonNull byte[] hmac)78 public DisplayHash(@CurrentTimeMillisLong long timeMillis, @NonNull Rect boundsInWindow, 79 @NonNull String hashAlgorithm, @NonNull byte[] imageHash, @NonNull byte[] hmac) { 80 mTimeMillis = timeMillis; 81 mBoundsInWindow = boundsInWindow; 82 AnnotationValidations.validate(NonNull.class, null, mBoundsInWindow); 83 mHashAlgorithm = hashAlgorithm; 84 AnnotationValidations.validate(NonNull.class, null, mHashAlgorithm); 85 mImageHash = imageHash; 86 AnnotationValidations.validate(NonNull.class, null, mImageHash); 87 mHmac = hmac; 88 AnnotationValidations.validate(NonNull.class, null, mHmac); 89 } 90 91 /** 92 * The timestamp when the hash was generated. 93 * 94 * @hide 95 */ 96 @SystemApi 97 @CurrentTimeMillisLong getTimeMillis()98 public long getTimeMillis() { 99 return mTimeMillis; 100 } 101 102 /** 103 * The bounds of the requested area to to generate the hash. This is in window space passed in 104 * by the client. 105 * 106 * @hide 107 */ 108 @SystemApi 109 @NonNull getBoundsInWindow()110 public Rect getBoundsInWindow() { 111 return mBoundsInWindow; 112 } 113 114 /** 115 * The selected hash algorithm that generated the image hash. 116 * 117 * @hide 118 */ 119 @SystemApi 120 @NonNull getHashAlgorithm()121 public String getHashAlgorithm() { 122 return mHashAlgorithm; 123 } 124 125 /** 126 * The image hash generated when creating the DisplayHash. 127 * 128 * @hide 129 */ 130 @SystemApi 131 @NonNull getImageHash()132 public byte[] getImageHash() { 133 return mImageHash; 134 } 135 136 /** 137 * The hmac generated by the system and used to verify whether this token was generated by 138 * the system. This should only be accessed by a system process. 139 * 140 * @hide 141 */ 142 @SystemApi 143 @NonNull getHmac()144 public byte[] getHmac() { 145 return mHmac; 146 } 147 148 /** @hide **/ 149 @Override toString()150 public String toString() { 151 return "DisplayHash { " 152 + "timeMillis = " + mTimeMillis + ", " 153 + "boundsInWindow = " + mBoundsInWindow + ", " 154 + "hashAlgorithm = " + mHashAlgorithm + ", " 155 + "imageHash = " + byteArrayToString(mImageHash) + ", " 156 + "hmac = " + byteArrayToString(mHmac) 157 + " }"; 158 } 159 byteArrayToString(byte[] byteArray)160 private String byteArrayToString(byte[] byteArray) { 161 if (byteArray == null) { 162 return "null"; 163 } 164 int iMax = byteArray.length - 1; 165 if (iMax == -1) { 166 return "[]"; 167 } 168 169 StringBuilder b = new StringBuilder(); 170 b.append('['); 171 for (int i = 0; ; i++) { 172 String formatted = String.format("%02X", byteArray[i] & 0xFF); 173 b.append(formatted); 174 if (i == iMax) { 175 return b.append(']').toString(); 176 } 177 b.append(", "); 178 } 179 } 180 181 /** @hide **/ 182 @SystemApi 183 @Override writeToParcel(@onNull Parcel dest, int flags)184 public void writeToParcel(@NonNull Parcel dest, int flags) { 185 dest.writeLong(mTimeMillis); 186 dest.writeTypedObject(mBoundsInWindow, flags); 187 dest.writeString(mHashAlgorithm); 188 dest.writeByteArray(mImageHash); 189 dest.writeByteArray(mHmac); 190 } 191 192 /** @hide **/ 193 @SystemApi 194 @Override describeContents()195 public int describeContents() { 196 return 0; 197 } 198 DisplayHash(@onNull Parcel in)199 private DisplayHash(@NonNull Parcel in) { 200 mTimeMillis = in.readLong(); 201 Rect boundsInWindow = in.readTypedObject(Rect.CREATOR); 202 String hashAlgorithm = in.readString(); 203 byte[] imageHash = in.createByteArray(); 204 byte[] hmac = in.createByteArray(); 205 206 mBoundsInWindow = boundsInWindow; 207 AnnotationValidations.validate(NonNull.class, null, mBoundsInWindow); 208 mHashAlgorithm = hashAlgorithm; 209 AnnotationValidations.validate(NonNull.class, null, mHashAlgorithm); 210 mImageHash = imageHash; 211 AnnotationValidations.validate(NonNull.class, null, mImageHash); 212 mHmac = hmac; 213 AnnotationValidations.validate(NonNull.class, null, mHmac); 214 } 215 216 @NonNull 217 public static final Parcelable.Creator<DisplayHash> CREATOR = 218 new Parcelable.Creator<DisplayHash>() { 219 @Override 220 public DisplayHash[] newArray(int size) { 221 return new DisplayHash[size]; 222 } 223 224 @Override 225 public DisplayHash createFromParcel(@NonNull Parcel in) { 226 return new DisplayHash(in); 227 } 228 }; 229 } 230