1 /*
2  * Copyright (C) 2023 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 com.android.server.wm;
18 
19 import static android.server.wm.ActivityManagerTestBase.createFullscreenActivityScenarioRule;
20 import static android.server.wm.BuildUtils.HW_TIMEOUT_MULTIPLIER;
21 
22 import static org.junit.Assert.assertFalse;
23 import static org.junit.Assert.assertTrue;
24 
25 import android.app.Activity;
26 import android.platform.test.annotations.Presubmit;
27 import android.util.Log;
28 import android.view.SurfaceControl;
29 import android.view.SurfaceControl.TrustedPresentationThresholds;
30 
31 import androidx.test.ext.junit.rules.ActivityScenarioRule;
32 
33 import org.junit.Before;
34 import org.junit.Rule;
35 import org.junit.Test;
36 
37 import java.util.concurrent.CountDownLatch;
38 import java.util.concurrent.TimeUnit;
39 import java.util.function.Consumer;
40 
41 /**
42  * TODO (b/287076178): Move these tests to
43  * {@link android.view.surfacecontrol.cts.TrustedPresentationCallbackTest} when API is made public
44  */
45 @Presubmit
46 public class TrustedPresentationCallbackTest {
47     private static final String TAG = "TrustedPresentationCallbackTest";
48     private static final int STABILITY_REQUIREMENT_MS = 500;
49     private static final long WAIT_TIME_MS = HW_TIMEOUT_MULTIPLIER * 2000L;
50 
51     private static final float FRACTION_VISIBLE = 0.1f;
52 
53     @Rule
54     public ActivityScenarioRule<TestActivity> mActivityRule = createFullscreenActivityScenarioRule(
55             TestActivity.class);
56 
57     private TestActivity mActivity;
58 
59     @Before
setup()60     public void setup() {
61         mActivityRule.getScenario().onActivity(activity -> mActivity = activity);
62     }
63 
64     @Test
testAddTrustedPresentationListenerOnWindow()65     public void testAddTrustedPresentationListenerOnWindow() throws InterruptedException {
66         boolean[] results = new boolean[1];
67         CountDownLatch receivedResults = new CountDownLatch(1);
68         TrustedPresentationThresholds thresholds = new TrustedPresentationThresholds(
69                 1 /* minAlpha */, FRACTION_VISIBLE, STABILITY_REQUIREMENT_MS);
70         SurfaceControl.Transaction t = new SurfaceControl.Transaction();
71         mActivity.getWindow().getRootSurfaceControl().addTrustedPresentationCallback(t, thresholds,
72                 Runnable::run, inTrustedPresentationState -> {
73                     Log.d(TAG, "onTrustedPresentationChanged " + inTrustedPresentationState);
74                     results[0] = inTrustedPresentationState;
75                     receivedResults.countDown();
76                 });
77         t.apply();
78 
79         assertTrue("Timed out waiting for results",
80                 receivedResults.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
81         assertTrue(results[0]);
82     }
83 
84     @Test
testRemoveTrustedPresentationListenerOnWindow()85     public void testRemoveTrustedPresentationListenerOnWindow() throws InterruptedException {
86         final Object resultsLock = new Object();
87         boolean[] results = new boolean[1];
88         boolean[] receivedResults = new boolean[1];
89         TrustedPresentationThresholds thresholds = new TrustedPresentationThresholds(
90                 1 /* minAlpha */, FRACTION_VISIBLE, STABILITY_REQUIREMENT_MS);
91         Consumer<Boolean> trustedPresentationCallback = inTrustedPresentationState -> {
92             synchronized (resultsLock) {
93                 results[0] = inTrustedPresentationState;
94                 receivedResults[0] = true;
95                 resultsLock.notify();
96             }
97         };
98         SurfaceControl.Transaction t = new SurfaceControl.Transaction();
99         mActivity.getWindow().getRootSurfaceControl().addTrustedPresentationCallback(t, thresholds,
100                 Runnable::run, trustedPresentationCallback);
101         t.apply();
102 
103         synchronized (resultsLock) {
104             if (!receivedResults[0]) {
105                 resultsLock.wait(WAIT_TIME_MS);
106             }
107             // Make sure we received the results and not just timed out
108             assertTrue("Timed out waiting for results", receivedResults[0]);
109             assertTrue(results[0]);
110 
111             // reset the state
112             receivedResults[0] = false;
113         }
114 
115         mActivity.getWindow().getRootSurfaceControl().removeTrustedPresentationCallback(t,
116                 trustedPresentationCallback);
117         t.apply();
118 
119         synchronized (resultsLock) {
120             if (!receivedResults[0]) {
121                 resultsLock.wait(WAIT_TIME_MS);
122             }
123             // Ensure we waited the full time and never received a notify on the result from the
124             // callback.
125             assertFalse("Should never have received a callback", receivedResults[0]);
126             // results shouldn't have changed.
127             assertTrue(results[0]);
128         }
129     }
130 
131     public static class TestActivity extends Activity {
132     }
133 }
134