• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 package android.car.cluster.sample;
17 
18 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
19 
20 import static java.lang.Integer.parseInt;
21 
22 import android.app.ActivityOptions;
23 import android.car.CarNotConnectedException;
24 import android.car.cluster.ClusterActivityState;
25 import android.car.cluster.renderer.InstrumentClusterRenderingService;
26 import android.car.cluster.renderer.NavigationRenderer;
27 import android.car.navigation.CarNavigationInstrumentCluster;
28 import android.content.Intent;
29 import android.graphics.Rect;
30 import android.hardware.display.DisplayManager.DisplayListener;
31 import android.os.Binder;
32 import android.os.Bundle;
33 import android.os.IBinder;
34 import android.os.SystemClock;
35 import android.provider.Settings;
36 import android.provider.Settings.Global;
37 import android.util.Log;
38 import android.view.InputDevice;
39 import android.view.KeyEvent;
40 
41 import java.io.FileDescriptor;
42 import java.io.PrintWriter;
43 import java.util.Arrays;
44 
45 /**
46  * Dummy implementation of {@link SampleClusterServiceImpl} to log all interaction.
47  */
48 public class SampleClusterServiceImpl extends InstrumentClusterRenderingService {
49 
50     private static final String TAG = SampleClusterServiceImpl.class.getSimpleName();
51 
52     private Listener mListener;
53     private final Binder mLocalBinder = new LocalBinder();
54     static final String LOCAL_BINDING_ACTION = "local";
55 
56     private ClusterDisplayProvider mDisplayProvider;
57 
58     @Override
onBind(Intent intent)59     public IBinder onBind(Intent intent) {
60         Log.i(TAG, "onBind, intent: " + intent);
61         return (LOCAL_BINDING_ACTION.equals(intent.getAction()))
62                 ? mLocalBinder : super.onBind(intent);
63     }
64 
65     @Override
onCreate()66     public void onCreate() {
67         super.onCreate();
68         Log.i(TAG, "onCreate");
69 
70         mDisplayProvider = new ClusterDisplayProvider(this,
71                 new DisplayListener() {
72                     @Override
73                     public void onDisplayAdded(int displayId) {
74                         Log.i(TAG, "Cluster display found, displayId: " + displayId);
75                         doClusterDisplayConnected(displayId);
76                     }
77 
78                     @Override
79                     public void onDisplayRemoved(int displayId) {
80                         Log.w(TAG, "Cluster display has been removed");
81                     }
82 
83                     @Override
84                     public void onDisplayChanged(int displayId) {
85 
86                     }
87                 });
88     }
89 
doClusterDisplayConnected(int displayId)90     private void doClusterDisplayConnected(int displayId) {
91         ActivityOptions options = ActivityOptions.makeBasic();
92         options.setLaunchDisplayId(displayId);
93         Intent intent = new Intent(this, MainClusterActivity.class);
94         intent.setFlags(FLAG_ACTIVITY_NEW_TASK);
95         startActivity(intent, options.toBundle());
96     }
97 
98     @Override
onKeyEvent(KeyEvent keyEvent)99     protected void onKeyEvent(KeyEvent keyEvent) {
100         Log.i(TAG, "onKeyEvent, keyEvent: " + keyEvent + ", listener: " + mListener);
101         if (mListener != null) {
102             mListener.onKeyEvent(keyEvent);
103         }
104     }
105 
106     @Override
onDestroy()107     public void onDestroy() {
108         super.onDestroy();
109         Log.w(TAG, "onDestroy");
110     }
111 
registerListener(Listener listener)112     void registerListener(Listener listener) {
113         mListener = listener;
114     }
115 
unregisterListener()116     void unregisterListener() {
117         mListener = null;
118     }
119 
120     @Override
getNavigationRenderer()121     protected NavigationRenderer getNavigationRenderer() {
122         NavigationRenderer navigationRenderer = new NavigationRenderer() {
123             @Override
124             public CarNavigationInstrumentCluster getNavigationProperties() {
125                 Log.i(TAG, "getNavigationProperties");
126                 CarNavigationInstrumentCluster config =
127                         CarNavigationInstrumentCluster.createCluster(1000);
128                 Log.i(TAG, "getNavigationProperties, returns: " + config);
129                 return config;
130             }
131 
132             @Override
133             public void onEvent(int eventType, Bundle bundle) {
134                 StringBuilder bundleSummary = new StringBuilder();
135                 for (String key : bundle.keySet()) {
136                     bundleSummary.append(key);
137                     bundleSummary.append("=");
138                     bundleSummary.append(bundle.get(key));
139                     bundleSummary.append(" ");
140                 }
141                 Log.i(TAG, "onEvent(" + eventType + ", " + bundleSummary + ")");
142             }
143         };
144 
145         Log.i(TAG, "createNavigationRenderer, returns: " + navigationRenderer);
146         return navigationRenderer;
147     }
148 
149     class LocalBinder extends Binder {
getService()150         SampleClusterServiceImpl getService() {
151             // Return this instance of LocalService so clients can call public methods
152             return SampleClusterServiceImpl.this;
153         }
154     }
155 
156     interface Listener {
onKeyEvent(KeyEvent event)157         void onKeyEvent(KeyEvent event);
158     }
159 
160     @Override
dump(FileDescriptor fd, PrintWriter writer, String[] args)161     protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
162         if (args != null && args.length > 0) {
163             execShellCommand(args);
164         } else {
165 
166             if (args == null || args.length == 0) {
167                 writer.println("* dump " + getClass().getCanonicalName() + " *");
168                 writer.println("DisplayProvider: " + mDisplayProvider);
169             }
170         }
171     }
172 
emulateKeyEvent(int keyCode)173     private void emulateKeyEvent(int keyCode) {
174         Log.i(TAG, "emulateKeyEvent, keyCode: " + keyCode);
175         long downTime = SystemClock.uptimeMillis();
176         long eventTime = SystemClock.uptimeMillis();
177         KeyEvent event = obtainKeyEvent(keyCode, downTime, eventTime, KeyEvent.ACTION_DOWN);
178         onKeyEvent(event);
179 
180         eventTime = SystemClock.uptimeMillis();
181         event = obtainKeyEvent(keyCode, downTime, eventTime, KeyEvent.ACTION_UP);
182         onKeyEvent(event);
183     }
184 
obtainKeyEvent(int keyCode, long downTime, long eventTime, int action)185     private KeyEvent obtainKeyEvent(int keyCode, long downTime, long eventTime, int action) {
186         int scanCode = 0;
187         if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
188             scanCode = 108;
189         } else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
190             scanCode = 106;
191         }
192         return KeyEvent.obtain(
193                     downTime,
194                     eventTime,
195                     action,
196                     keyCode,
197                     0 /* repeat */,
198                     0 /* meta state */,
199                     0 /* deviceId*/,
200                     scanCode /* scancode */,
201                     KeyEvent.FLAG_FROM_SYSTEM /* flags */,
202                     InputDevice.SOURCE_KEYBOARD,
203                     null /* characters */);
204     }
205 
execShellCommand(String[] args)206     private void execShellCommand(String[] args) {
207         Log.i(TAG, "execShellCommand, args: " + Arrays.toString(args));
208 
209         String command = args[0];
210 
211         switch (command) {
212             case "injectKey": {
213                 if (args.length > 1) {
214                     emulateKeyEvent(parseInt(args[1]));
215                 } else {
216                     Log.i(TAG, "Not enough arguments");
217                 }
218                 break;
219             }
220             case "destroyOverlayDisplay": {
221                 Settings.Global.putString(getContentResolver(),
222                     Global.OVERLAY_DISPLAY_DEVICES, "");
223                 break;
224             }
225 
226             case "createOverlayDisplay": {
227                 if (args.length > 1) {
228                     Settings.Global.putString(getContentResolver(),
229                             Global.OVERLAY_DISPLAY_DEVICES, args[1]);
230                 } else {
231                     Log.i(TAG, "Not enough arguments, expected 2");
232                 }
233                 break;
234             }
235 
236             case "setUnobscuredArea": {
237                 if (args.length > 5) {
238                     Rect unobscuredArea = new Rect(parseInt(args[2]), parseInt(args[3]),
239                             parseInt(args[4]), parseInt(args[5]));
240                     try {
241                         setClusterActivityState(args[1],
242                                 ClusterActivityState.create(true, unobscuredArea).toBundle());
243                     } catch (CarNotConnectedException e) {
244                         Log.i(TAG, "Failed to set activity state.", e);
245                     }
246                 } else {
247                     Log.i(TAG, "wrong format, expected: category left top right bottom");
248                 }
249             }
250         }
251     }
252 
253 }
254