• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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.server.wm.scvh;
18 
19 import static android.server.wm.BuildUtils.HW_TIMEOUT_MULTIPLIER;
20 
21 import static org.junit.Assert.assertTrue;
22 
23 import android.app.Service;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.os.Handler;
27 import android.os.IBinder;
28 import android.os.Looper;
29 import android.server.wm.CtsWindowInfoUtils;
30 import android.server.wm.shared.ICrossProcessSurfaceControlViewHostTestService;
31 import android.view.Display;
32 import android.view.MotionEvent;
33 import android.view.SurfaceControlViewHost;
34 import android.view.View;
35 import android.view.WindowManager;
36 
37 import androidx.annotation.Nullable;
38 
39 import java.util.concurrent.CountDownLatch;
40 import java.util.concurrent.TimeUnit;
41 
42 public class CrossProcessSurfaceControlViewHostTestService extends Service {
43     private final ICrossProcessSurfaceControlViewHostTestService mBinder = new ServiceImpl();
44     private Handler mHandler;
45 
46     class MotionRecordingView extends View {
47         boolean mGotEvent = false;
48         boolean mGotObscuredEvent = false;
49 
50         private CountDownLatch mReceivedTouchLatch = new CountDownLatch(1);
51 
MotionRecordingView(Context c)52         MotionRecordingView(Context c) {
53             super(c);
54         }
55 
onTouchEvent(MotionEvent e)56         public boolean onTouchEvent(MotionEvent e) {
57             super.onTouchEvent(e);
58             synchronized (this) {
59                 mGotEvent = true;
60                 if ((e.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
61                     mGotObscuredEvent = true;
62                 }
63             }
64             mReceivedTouchLatch.countDown();
65             return true;
66         }
67 
gotEvent()68         boolean gotEvent() {
69             synchronized (this) {
70                 return mGotEvent;
71             }
72         }
73 
gotObscuredTouch()74         boolean gotObscuredTouch() {
75             synchronized (this) {
76                 return mGotObscuredEvent;
77             }
78         }
79 
waitOnEvent()80         void waitOnEvent() {
81             try {
82                 mReceivedTouchLatch.await(HW_TIMEOUT_MULTIPLIER * 5L, TimeUnit.SECONDS);
83             } catch (InterruptedException e) {
84             }
85         }
86     }
87 
88     @Override
onCreate()89     public void onCreate() {
90         mHandler = new Handler(Looper.getMainLooper());
91     }
92 
93     @Nullable
94     @Override
onBind(Intent intent)95     public IBinder onBind(Intent intent) {
96         return mBinder.asBinder();
97     }
98 
getDefaultDisplay()99     Display getDefaultDisplay() {
100         WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
101         return wm.getDefaultDisplay();
102     }
103 
104     SurfaceControlViewHost mSurfaceControlViewHost;
105     MotionRecordingView mView;
106 
createSurfacePackage(IBinder hostInputToken)107     SurfaceControlViewHost.SurfacePackage createSurfacePackage(IBinder hostInputToken) {
108         mView = new MotionRecordingView(this);
109         mSurfaceControlViewHost = new SurfaceControlViewHost(this, getDefaultDisplay(),
110                 hostInputToken);
111         mSurfaceControlViewHost.setView(mView, 100, 100);
112         return mSurfaceControlViewHost.getSurfacePackage();
113     }
114 
115     private class ServiceImpl extends ICrossProcessSurfaceControlViewHostTestService.Stub {
drainHandler()116         private void drainHandler() {
117             final CountDownLatch latch = new CountDownLatch(1);
118             mHandler.post(latch::countDown);
119             try {
120                 assertTrue("Failed to wait for handler to drain",
121                         latch.await(HW_TIMEOUT_MULTIPLIER * 1L, TimeUnit.SECONDS));
122             } catch (Exception e) {
123             }
124         }
125 
126         @Override
getSurfacePackage(IBinder hostInputToken)127         public SurfaceControlViewHost.SurfacePackage getSurfacePackage(IBinder hostInputToken) {
128             final CountDownLatch latch = new CountDownLatch(1);
129             mHandler.post(() -> {
130                 createSurfacePackage(hostInputToken);
131                 mView.getViewTreeObserver().registerFrameCommitCallback(latch::countDown);
132                 mView.invalidate();
133             });
134             try {
135                 assertTrue("Failed to wait for frame to draw",
136                         latch.await(HW_TIMEOUT_MULTIPLIER * 1L, TimeUnit.SECONDS));
137             } catch (Exception e) {
138                 return null;
139             }
140             return mSurfaceControlViewHost.getSurfacePackage();
141         }
142 
143         @Override
getViewIsTouched()144         public boolean getViewIsTouched() {
145             drainHandler();
146             mView.waitOnEvent();
147             return mView.gotEvent();
148         }
149 
150         @Override
getViewIsTouchedAndObscured()151         public boolean getViewIsTouchedAndObscured() {
152             return getViewIsTouched() && mView.gotObscuredTouch();
153         }
154 
155         @Override
getWindowToken()156         public IBinder getWindowToken() {
157             return mView.getWindowToken();
158         }
159 
160         @Override
waitForFocus(boolean waitForFocus)161         public boolean waitForFocus(boolean waitForFocus) {
162             return CtsWindowInfoUtils.waitForWindowFocus(mView, waitForFocus);
163         }
164 
165     }
166 }
167