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.ext.services.displayhash;
18 
19 import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_INVALID_HASH_ALGORITHM;
20 import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_UNKNOWN;
21 
22 import static org.junit.Assert.assertEquals;
23 import static org.junit.Assert.assertNotNull;
24 import static org.junit.Assert.assertNull;
25 
26 import android.graphics.Rect;
27 import android.hardware.HardwareBuffer;
28 import android.view.displayhash.DisplayHash;
29 import android.view.displayhash.DisplayHashResultCallback;
30 import android.view.displayhash.VerifiedDisplayHash;
31 
32 import androidx.annotation.NonNull;
33 import androidx.test.filters.SdkSuppress;
34 
35 import org.junit.Before;
36 import org.junit.Test;
37 
38 import java.util.concurrent.CountDownLatch;
39 import java.util.concurrent.TimeUnit;
40 
41 @SdkSuppress(minSdkVersion = 31, codeName = "S")
42 public class DisplayHashingServiceImplTest {
43     private final DisplayHashingServiceImpl mService = new DisplayHashingServiceImpl();
44 
45     private final byte[] mSalt = "SALT".getBytes();
46     private final String mHashAlgorithm = "PHASH";
47     private final HardwareBuffer mBuffer = HardwareBuffer.create(10, 10,
48             HardwareBuffer.RGBX_8888, 1, HardwareBuffer.USAGE_CPU_READ_RARELY);
49     private final Rect mBounds = new Rect(0, 0, 10, 10);
50 
51     private SyncDisplayHashResultCallback mDisplayHashResultCallback;
52 
53     @Before
54     public void setUp() throws Exception {
55         mService.onCreate();
56         mService.setImageHashManager(new MockImageHashManager());
57         mDisplayHashResultCallback = new SyncDisplayHashResultCallback();
58     }
59 
60     @Test
61     public void testOnGenerateAndOnVerifyDisplayHash() {
62         mService.onGenerateDisplayHash(mSalt, mBuffer, mBounds, mHashAlgorithm,
63                 mDisplayHashResultCallback);
64         DisplayHash DisplayHash = mDisplayHashResultCallback.getDisplayHash();
65         assertNotNull(DisplayHash);
66 
67         VerifiedDisplayHash verifiedDisplayHash = mService.onVerifyDisplayHash(mSalt,
68                 DisplayHash);
69         assertNotNull(verifiedDisplayHash);
70 
71         assertEquals(DisplayHash.getBoundsInWindow(), verifiedDisplayHash.getBoundsInWindow());
72         assertEquals(DisplayHash.getHashAlgorithm(), verifiedDisplayHash.getHashAlgorithm());
73         assertEquals(DisplayHash.getTimeMillis(), verifiedDisplayHash.getTimeMillis());
74         assertEquals(DisplayHash.getImageHash(), verifiedDisplayHash.getImageHash());
75     }
76 
77     @Test
78     public void testOnGenerateDisplayHash_nullSalt() {
79         mService.onGenerateDisplayHash(null, mBuffer, mBounds, mHashAlgorithm,
80                 mDisplayHashResultCallback);
81         int errorCode = mDisplayHashResultCallback.getError();
82         assertEquals(DISPLAY_HASH_ERROR_UNKNOWN, errorCode);
83     }
84 
85     @Test
86     public void testOnGenerateDisplayHash_invalidHashAlgorithm() {
87         mService.onGenerateDisplayHash(mSalt, mBuffer, mBounds, null /* hashAlgorithm */,
88                 mDisplayHashResultCallback);
89         int errorCode = mDisplayHashResultCallback.getError();
90         assertEquals(DISPLAY_HASH_ERROR_INVALID_HASH_ALGORITHM, errorCode);
91 
92         mDisplayHashResultCallback.reset();
93         mService.onGenerateDisplayHash(mSalt, mBuffer, mBounds, "fake hash",
94                 mDisplayHashResultCallback);
95         errorCode = mDisplayHashResultCallback.getError();
96         assertEquals(DISPLAY_HASH_ERROR_INVALID_HASH_ALGORITHM, errorCode);
97     }
98 
99     @Test
100     public void testOnGenerateDisplayHash_nullBuffer() {
101         mService.onGenerateDisplayHash(mSalt, null /* buffer */, mBounds, mHashAlgorithm,
102                 mDisplayHashResultCallback);
103         int errorCode = mDisplayHashResultCallback.getError();
104         assertEquals(DISPLAY_HASH_ERROR_UNKNOWN, errorCode);
105     }
106 
107     @Test
108     public void testOnVerifyDisplayHash_nullSalt() {
109         mService.onGenerateDisplayHash(mSalt, mBuffer, mBounds, mHashAlgorithm,
110                 mDisplayHashResultCallback);
111         DisplayHash DisplayHash = mDisplayHashResultCallback.getDisplayHash();
112         assertNotNull(DisplayHash);
113 
114         VerifiedDisplayHash verifiedDisplayHash = mService.onVerifyDisplayHash(null /* salt */,
115                 DisplayHash);
116         assertNull(verifiedDisplayHash);
117     }
118 
119     @Test
120     public void testOnVerifyDisplayHash_nullDisplayHash() {
121         mService.onGenerateDisplayHash(mSalt, mBuffer, mBounds, mHashAlgorithm,
122                 mDisplayHashResultCallback);
123         DisplayHash DisplayHash = mDisplayHashResultCallback.getDisplayHash();
124         assertNotNull(DisplayHash);
125 
126         VerifiedDisplayHash verifiedDisplayHash = mService.onVerifyDisplayHash(mSalt,
127                 null /* DisplayHash */);
128         assertNull(verifiedDisplayHash);
129     }
130 
131     @Test
132     public void testOnGetIntervalBetweenRequestsMillis() {
133         int intervalBetweenRequests = mService.onGetIntervalBetweenRequestsMillis();
134         assertEquals(10000, intervalBetweenRequests);
135     }
136 
137     private static class SyncDisplayHashResultCallback implements DisplayHashResultCallback {
138         private static final int DISPLAY_HASH_WAIT_TIME_S = 1;
139         private DisplayHash mDisplayHash;
140         private int mError;
141         private CountDownLatch mCountDownLatch = new CountDownLatch(1);
142 
143         public void reset() {
144             mCountDownLatch = new CountDownLatch(1);
145         }
146 
147         public DisplayHash getDisplayHash() {
148             try {
149                 mCountDownLatch.await(DISPLAY_HASH_WAIT_TIME_S, TimeUnit.SECONDS);
150             } catch (Exception e) {
151             }
152             return mDisplayHash;
153         }
154 
155         public int getError() {
156             try {
157                 mCountDownLatch.await(DISPLAY_HASH_WAIT_TIME_S, TimeUnit.SECONDS);
158             } catch (Exception e) {
159             }
160             return mError;
161         }
162 
163         @Override
164         public void onDisplayHashResult(@NonNull DisplayHash displayHash) {
165             mDisplayHash = displayHash;
166             mCountDownLatch.countDown();
167         }
168 
169         @Override
170         public void onDisplayHashError(int errorCode) {
171             mError = errorCode;
172             mCountDownLatch.countDown();
173         }
174     }
175 }
176