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