1 /*
2  * Copyright (C) 2014 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.cts.verifier.projection;
18 
19 import android.app.Service;
20 import android.content.Intent;
21 import android.hardware.display.DisplayManager;
22 import android.hardware.display.VirtualDisplay;
23 import android.os.Handler;
24 import android.os.IBinder;
25 import android.os.Looper;
26 import android.os.RemoteException;
27 import android.util.Log;
28 import android.view.KeyEvent;
29 import android.view.MotionEvent;
30 import android.view.Surface;
31 
32 import com.android.cts.verifier.projection.cube.CubePresentation;
33 import com.android.cts.verifier.projection.list.ListPresentation;
34 import com.android.cts.verifier.projection.offscreen.OffscreenPresentation;
35 import com.android.cts.verifier.projection.touch.TouchPresentation;
36 import com.android.cts.verifier.projection.video.VideoPresentation;
37 import com.android.cts.verifier.projection.widgets.WidgetPresentation;
38 
39 /**
40  * Service to handle rendering of views on a virtual display and to forward input events to the
41  * display
42  */
43 public class ProjectionService extends Service {
44     private final String TAG = ProjectionService.class.getSimpleName();
45     private final String DISPLAY_NAME = "CtsVerifier Virtual Display";
46 
47     private Handler mUIHandler;
48 
createPresentation(int typeOrdinal)49     private ProjectedPresentation createPresentation(int typeOrdinal) {
50         ProjectionPresentationType type = ProjectionPresentationType.values()[typeOrdinal];
51         switch (type) {
52             case TUMBLING_CUBES:
53                 return new CubePresentation(ProjectionService.this, mDisplay.getDisplay());
54 
55             case BASIC_WIDGETS:
56                 return new WidgetPresentation(ProjectionService.this, mDisplay.getDisplay());
57 
58             case SCROLLING_LIST:
59                 return new ListPresentation(ProjectionService.this, mDisplay.getDisplay());
60 
61             case VIDEO_PLAYBACK:
62                 return new VideoPresentation(ProjectionService.this, mDisplay.getDisplay());
63 
64             case MULTI_TOUCH:
65                 return new TouchPresentation(ProjectionService.this, mDisplay.getDisplay());
66 
67             case OFFSCREEN:
68                 return new OffscreenPresentation(ProjectionService.this, mDisplay.getDisplay());
69         }
70 
71         return null;
72     }
73 
74     private class ProjectionServiceBinder extends IProjectionService.Stub {
75         @Override
startRendering(final Surface surface, final int width, final int height, final int density, final int viewType)76         public void startRendering(final Surface surface, final int width, final int height,
77                 final int density,
78                 final int viewType) throws RemoteException {
79             mUIHandler.post(new Runnable() {
80                 @Override
81                 public void run() {
82                     DisplayManager manager = (DisplayManager) getSystemService(DISPLAY_SERVICE);
83                     Log.i(TAG, "Surface " + surface.toString() + ": "
84                             + Boolean.toString(surface.isValid()));
85                     mDisplay = manager.createVirtualDisplay(DISPLAY_NAME, width, height, density,
86                             surface, 0);
87                     mPresentation = createPresentation(viewType);
88                     if (mPresentation == null) {
89                         return;
90                     }
91 
92                     mPresentation.show();
93                 }
94             });
95         }
96 
97         @Override
stopRendering()98         public void stopRendering() throws RemoteException {
99             mUIHandler.post(new Runnable() {
100 
101                 @Override
102                 public void run() {
103                     if (mPresentation != null) {
104                         mPresentation.dismiss();
105                         mPresentation = null;
106                     }
107                 }
108 
109             });
110         }
111 
112         @Override
onTouchEvent(final MotionEvent event)113         public void onTouchEvent(final MotionEvent event) throws RemoteException {
114             mUIHandler.post(new Runnable() {
115 
116                 @Override
117                 public void run() {
118                     if (mPresentation != null) {
119                         mPresentation.injectTouchEvent(event);
120                     }
121                 }
122 
123             });
124         }
125 
126         @Override
onKeyEvent(final KeyEvent event)127         public void onKeyEvent(final KeyEvent event) throws RemoteException {
128             mUIHandler.post(new Runnable() {
129 
130                 @Override
131                 public void run() {
132                     if (mPresentation != null) {
133                         mPresentation.injectKeyEvent(event);
134                     }
135                 }
136 
137             });
138         }
139     }
140 
141     private final IBinder mBinder = new ProjectionServiceBinder();
142     private VirtualDisplay mDisplay;
143     private ProjectedPresentation mPresentation;
144 
145     @Override
onBind(Intent intent)146     public IBinder onBind(Intent intent) {
147         Log.i(TAG, "onBind");
148         mUIHandler = new Handler(Looper.getMainLooper());
149         return mBinder;
150     }
151 }
152