1 /* 2 * Copyright (C) 2020 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.car.input; 18 19 import static android.car.CarOccupantZoneManager.DisplayTypeEnum; 20 21 import android.annotation.CallbackExecutor; 22 import android.annotation.IntDef; 23 import android.annotation.NonNull; 24 import android.annotation.RequiresPermission; 25 import android.annotation.SystemApi; 26 import android.car.Car; 27 import android.car.CarManagerBase; 28 import android.car.CarOccupantZoneManager; 29 import android.car.builtin.util.Slogf; 30 import android.os.Handler; 31 import android.os.IBinder; 32 import android.os.RemoteException; 33 import android.util.SparseArray; 34 import android.view.KeyEvent; 35 36 import com.android.internal.annotations.GuardedBy; 37 38 import java.lang.annotation.ElementType; 39 import java.lang.annotation.Retention; 40 import java.lang.annotation.RetentionPolicy; 41 import java.lang.annotation.Target; 42 import java.lang.ref.WeakReference; 43 import java.util.List; 44 import java.util.Objects; 45 import java.util.concurrent.Executor; 46 47 /** 48 * This API allows capturing selected input events. 49 */ 50 public final class CarInputManager extends CarManagerBase { 51 52 private static final String TAG = CarInputManager.class.getSimpleName(); 53 54 private static final boolean DEBUG = false; 55 56 private static final String PERMISSION_FRAMEWORK_MONITOR_INPUT = 57 "android.permission.MONITOR_INPUT"; 58 59 /** 60 * Callback for capturing input events. 61 * <p> 62 * Events (key, rotary and custom input events) are associated with display types. 63 * Display types are defined in {@link android.car.CarOccupantZoneManager}. This manager only 64 * accepts the driver display types ({@link CarOccupantZoneManager#DISPLAY_TYPE_MAIN} and 65 * {@link CarOccupantZoneManager#DISPLAY_TYPE_INSTRUMENT_CLUSTER}). 66 * 67 * @hide 68 */ 69 @SystemApi 70 public interface CarInputCaptureCallback { 71 /** 72 * Key events were captured. 73 * 74 * @param targetDisplayType the display type associated with the events passed as parameter 75 * @param keyEvents the key events to process 76 */ onKeyEvents(@isplayTypeEnum int targetDisplayType, @NonNull List<KeyEvent> keyEvents)77 default void onKeyEvents(@DisplayTypeEnum int targetDisplayType, 78 @NonNull List<KeyEvent> keyEvents) {} 79 80 /** 81 * Rotary events were captured. 82 * 83 * @param targetDisplayType the display type associated with the events passed as parameter 84 * @param events the rotary events to process 85 */ onRotaryEvents(@isplayTypeEnum int targetDisplayType, @NonNull List<RotaryEvent> events)86 default void onRotaryEvents(@DisplayTypeEnum int targetDisplayType, 87 @NonNull List<RotaryEvent> events) {} 88 89 /** 90 * Capture state for the display has changed due to other client making requests or 91 * releasing capture. Client should check {@code activeInputTypes} for which input types 92 * are currently captured. 93 * 94 * @param targetDisplayType the display type associated with the events passed as parameter 95 * @param activeInputTypes the input types to watch 96 */ onCaptureStateChanged(@isplayTypeEnum int targetDisplayType, @NonNull @InputTypeEnum int[] activeInputTypes)97 default void onCaptureStateChanged(@DisplayTypeEnum int targetDisplayType, 98 @NonNull @InputTypeEnum int[] activeInputTypes) {} 99 100 /** 101 * Custom input events were captured. 102 * 103 * @param targetDisplayType the display type associated with the events passed as parameter 104 * @param events the custom input events to process 105 */ onCustomInputEvents(@isplayTypeEnum int targetDisplayType, @NonNull List<CustomInputEvent> events)106 default void onCustomInputEvents(@DisplayTypeEnum int targetDisplayType, 107 @NonNull List<CustomInputEvent> events) {} 108 } 109 110 /** 111 * Client will wait for grant if the request is failing due to higher priority client. 112 * 113 * @hide 114 */ 115 @SystemApi 116 public static final int CAPTURE_REQ_FLAGS_ALLOW_DELAYED_GRANT = 0x1; 117 118 /** 119 * Client wants to capture the keys for the whole display. This is only allowed to system 120 * process. 121 * 122 * @hide 123 */ 124 @SystemApi 125 public static final int CAPTURE_REQ_FLAGS_TAKE_ALL_EVENTS_FOR_DISPLAY = 0x2; 126 127 /** @hide */ 128 @IntDef(flag = true, prefix = {"CAPTURE_REQ_FLAGS_"}, value = { 129 CAPTURE_REQ_FLAGS_ALLOW_DELAYED_GRANT, 130 CAPTURE_REQ_FLAGS_TAKE_ALL_EVENTS_FOR_DISPLAY, 131 }) 132 @Retention(RetentionPolicy.SOURCE) 133 public @interface CaptureRequestFlags {} 134 135 /** 136 * This is special type to cover all INPUT_TYPE_*. This is used for clients using 137 * {@link #CAPTURE_REQ_FLAGS_TAKE_ALL_EVENTS_FOR_DISPLAY} flag. 138 * 139 * @hide 140 */ 141 @SystemApi 142 public static final int INPUT_TYPE_ALL_INPUTS = 1; 143 144 /** 145 * This covers rotary input device for navigation. 146 */ 147 public static final int INPUT_TYPE_ROTARY_NAVIGATION = 10; 148 149 /** 150 * Volume knob. 151 */ 152 public static final int INPUT_TYPE_ROTARY_VOLUME = 11; 153 154 /** 155 * This is the group of keys for DPAD. 156 * Included key events are: {@link KeyEvent#KEYCODE_DPAD_UP}, 157 * {@link KeyEvent#KEYCODE_DPAD_DOWN}, {@link KeyEvent#KEYCODE_DPAD_LEFT}, 158 * {@link KeyEvent#KEYCODE_DPAD_RIGHT}, {@link KeyEvent#KEYCODE_DPAD_CENTER}, 159 * {@link KeyEvent#KEYCODE_DPAD_DOWN_LEFT}, {@link KeyEvent#KEYCODE_DPAD_DOWN_RIGHT}, 160 * {@link KeyEvent#KEYCODE_DPAD_UP_LEFT}, {@link KeyEvent#KEYCODE_DPAD_UP_RIGHT} 161 */ 162 public static final int INPUT_TYPE_DPAD_KEYS = 100; 163 164 /** 165 * This is for all {@code KeyEvent#KEYCODE_NAVIGATE_*} keys and {@link KeyEvent#KEYCODE_BACK}. 166 */ 167 public static final int INPUT_TYPE_NAVIGATE_KEYS = 101; 168 169 /** 170 * This is for all {@code KeyEvent#KEYCODE_SYSTEM_NAVIGATE_*} keys. 171 */ 172 public static final int INPUT_TYPE_SYSTEM_NAVIGATE_KEYS = 102; 173 174 /** 175 * This is for {@code HW_CUSTOM_INPUT} events. 176 */ 177 public static final int INPUT_TYPE_CUSTOM_INPUT_EVENT = 200; 178 179 /** 180 * This is for touch mode input type. 181 */ 182 public static final int INPUT_TYPE_TOUCH_SCREEN = 210; 183 184 /** 185 * This is for displays that don't support any input type 186 */ 187 public static final int INPUT_TYPE_NONE = -1; 188 189 /** @hide */ 190 @Retention(RetentionPolicy.SOURCE) 191 @IntDef(prefix = "INPUT_TYPE_", value = { 192 INPUT_TYPE_ALL_INPUTS, 193 INPUT_TYPE_ROTARY_NAVIGATION, 194 INPUT_TYPE_ROTARY_VOLUME, 195 INPUT_TYPE_DPAD_KEYS, 196 INPUT_TYPE_NAVIGATE_KEYS, 197 INPUT_TYPE_SYSTEM_NAVIGATE_KEYS, 198 INPUT_TYPE_CUSTOM_INPUT_EVENT, 199 INPUT_TYPE_TOUCH_SCREEN, 200 INPUT_TYPE_NONE, 201 }) 202 @Target({ElementType.TYPE_USE}) 203 public @interface InputTypeEnum {} 204 205 /** 206 * The client's request has succeeded and capture will start. 207 * 208 * @hide 209 */ 210 @SystemApi 211 public static final int INPUT_CAPTURE_RESPONSE_SUCCEEDED = 0; 212 213 /** 214 * The client's request has failed due to higher priority client already capturing. If priority 215 * for the clients are the same, last client making request will be allowed to capture. 216 * 217 * @hide 218 */ 219 @SystemApi 220 public static final int INPUT_CAPTURE_RESPONSE_FAILED = 1; 221 222 /** 223 * This is used when client has set {@link #CAPTURE_REQ_FLAGS_ALLOW_DELAYED_GRANT} in 224 * {@code requestFlags} and capturing is blocked due to existing higher priority client. 225 * When the higher priority client stops capturing, this client can capture events after 226 * getting @link CarInputCaptureCallback#onCaptureStateChanged(int, int[])} call. 227 * 228 * @hide 229 */ 230 @SystemApi 231 public static final int INPUT_CAPTURE_RESPONSE_DELAYED = 2; 232 233 /** @hide */ 234 @Retention(RetentionPolicy.SOURCE) 235 @IntDef(prefix = "INPUT_CAPTURE_RESPONSE_", value = { 236 INPUT_CAPTURE_RESPONSE_SUCCEEDED, 237 INPUT_CAPTURE_RESPONSE_FAILED, 238 INPUT_CAPTURE_RESPONSE_DELAYED 239 }) 240 @Target({ElementType.TYPE_USE}) 241 public @interface InputCaptureResponseEnum {} 242 243 private final ICarInput mService; 244 private final ICarInputCallback mServiceCallback = new ICarInputCallbackImpl(this); 245 246 private final Object mLock = new Object(); 247 248 @GuardedBy("mLock") 249 private final SparseArray<CallbackHolder> mCarInputCaptureCallbacks = new SparseArray<>(1); 250 251 /** 252 * @hide 253 */ CarInputManager(Car car, IBinder service)254 public CarInputManager(Car car, IBinder service) { 255 super(car); 256 mService = ICarInput.Stub.asInterface(service); 257 } 258 259 /** 260 * Requests capturing of input event for the specified display for all requested input types. 261 * 262 * <p>The request can fail if a high priority client is holding it. The client can set 263 * {@link #CAPTURE_REQ_FLAGS_ALLOW_DELAYED_GRANT} in {@code requestFlags} to wait for the 264 * current high priority client to release it. 265 * 266 * <p>If only some of the input types specified are available, the request will either: 267 * <ul> 268 * <li>fail, returning {@link #INPUT_CAPTURE_RESPONSE_FAILED}, or 269 * <li>be deferred, returning {@link #INPUT_CAPTURE_RESPONSE_DELAYED}, if the 270 * {@link #CAPTURE_REQ_FLAGS_ALLOW_DELAYED_GRANT} flag is used. 271 * </ul> 272 * 273 * <p> After {@link #INPUT_CAPTURE_RESPONSE_DELAYED} is returned, no input types are captured 274 * until the client receives a {@link CarInputCaptureCallback#onCaptureStateChanged(int, int[])} 275 * call with valid input types. 276 * 277 * <p> The targetDisplayType parameter must only contain driver display types (which are 278 * {@link CarOccupantZoneManager#DISPLAY_TYPE_MAIN} and 279 * {@link CarOccupantZoneManager#DISPLAY_TYPE_INSTRUMENT_CLUSTER}. 280 * 281 * <p>Callbacks are grouped and stacked per display types. Only the most recently 282 * registered callback will receive the incoming events for the associated display and input 283 * types. For instance, if two callbacks are registered against the same display type, on the 284 * same {@link CarInputManager} instance, then only the last registered callback will receive 285 * events, even if they were registered for different input event types. 286 * 287 * @throws SecurityException if caller doesn't have one of the following permissions granted: 288 * {@code android.car.permission.CAR_MONITOR_INPUT} nor 289 * {@code android.Manifest.permission.MONITOR_INPUT} 290 * @throws IllegalArgumentException if targetDisplayType parameter correspond to a non supported 291 * display type 292 * @throws IllegalArgumentException if inputTypes parameter contains invalid or non supported 293 * values 294 * @param targetDisplayType the display type to register callback for 295 * @param inputTypes the input type to register callback for 296 * @param requestFlags the capture request flag 297 * @param callback the callback to receive the input events 298 * @return the input capture response indicating if registration succeed, failed or delayed 299 * 300 * @hide 301 */ 302 @SystemApi 303 @RequiresPermission(anyOf = {PERMISSION_FRAMEWORK_MONITOR_INPUT, 304 Car.PERMISSION_CAR_MONITOR_INPUT}) 305 @InputCaptureResponseEnum requestInputEventCapture(@isplayTypeEnum int targetDisplayType, @NonNull @InputTypeEnum int[] inputTypes, @CaptureRequestFlags int requestFlags, @NonNull CarInputCaptureCallback callback)306 public int requestInputEventCapture(@DisplayTypeEnum int targetDisplayType, 307 @NonNull @InputTypeEnum int[] inputTypes, 308 @CaptureRequestFlags int requestFlags, 309 @NonNull CarInputCaptureCallback callback) { 310 Handler handler = getEventHandler(); 311 return requestInputEventCapture(targetDisplayType, inputTypes, requestFlags, handler::post, 312 callback); 313 } 314 315 /** 316 * Works just like {@link CarInputManager#requestInputEventCapture(int, int[], int, 317 * CarInputCaptureCallback)} except that callbacks are invoked using 318 * the executor passed as parameter. 319 * 320 * @throws SecurityException if caller doesn't have one of the following permissions granted: 321 * {@code android.car.permission.CAR_MONITOR_INPUT} nor 322 * {@code android.Manifest.permission.MONITOR_INPUT} 323 * @param targetDisplayType the display type to register callback against 324 * @param inputTypes the input type to register callback against 325 * @param requestFlags the capture request flag 326 * @param executor {@link Executor} to handle the callbacks 327 * @param callback the callback to receive the input events 328 * @return the input capture response indicating if registration succeed, failed or delayed 329 * @see CarInputManager#requestInputEventCapture(int, int[], int, CarInputCaptureCallback) 330 * 331 * @hide 332 */ 333 @SystemApi 334 @RequiresPermission(anyOf = {PERMISSION_FRAMEWORK_MONITOR_INPUT, 335 Car.PERMISSION_CAR_MONITOR_INPUT}) 336 @InputCaptureResponseEnum requestInputEventCapture(@isplayTypeEnum int targetDisplayType, @NonNull @InputTypeEnum int[] inputTypes, @CaptureRequestFlags int requestFlags, @NonNull @CallbackExecutor Executor executor, @NonNull CarInputCaptureCallback callback)337 public int requestInputEventCapture(@DisplayTypeEnum int targetDisplayType, 338 @NonNull @InputTypeEnum int[] inputTypes, 339 @CaptureRequestFlags int requestFlags, 340 @NonNull @CallbackExecutor Executor executor, 341 @NonNull CarInputCaptureCallback callback) { 342 Objects.requireNonNull(executor); 343 Objects.requireNonNull(callback); 344 345 synchronized (mLock) { 346 mCarInputCaptureCallbacks.put(targetDisplayType, 347 new CallbackHolder(callback, executor)); 348 } 349 try { 350 return mService.requestInputEventCapture(mServiceCallback, targetDisplayType, 351 inputTypes, requestFlags); 352 } catch (RemoteException e) { 353 return handleRemoteExceptionFromCarService(e, INPUT_CAPTURE_RESPONSE_FAILED); 354 } 355 } 356 357 /** 358 * Stops capturing of given display. 359 * 360 * @hide 361 */ 362 @SystemApi releaseInputEventCapture(@isplayTypeEnum int targetDisplayType)363 public void releaseInputEventCapture(@DisplayTypeEnum int targetDisplayType) { 364 CallbackHolder callbackHolder; 365 synchronized (mLock) { 366 callbackHolder = mCarInputCaptureCallbacks.get(targetDisplayType); 367 mCarInputCaptureCallbacks.delete(targetDisplayType); 368 } 369 if (callbackHolder == null) { 370 return; 371 } 372 try { 373 mService.releaseInputEventCapture(mServiceCallback, targetDisplayType); 374 } catch (RemoteException e) { 375 // ignore 376 } 377 } 378 379 /** 380 * Injects the {@link KeyEvent} passed as parameter against Car Input API. 381 * <p> 382 * The event parameter display id will be overridden accordingly to the display type also passed 383 * as parameter. 384 * 385 * @param event the key event to inject 386 * @param targetDisplayType the display type associated with the key event 387 * @throws RemoteException in case of failure when invoking car input service 388 * 389 * @hide 390 */ 391 @SystemApi 392 @RequiresPermission(android.Manifest.permission.INJECT_EVENTS) injectKeyEvent(@onNull KeyEvent event, @DisplayTypeEnum int targetDisplayType)393 public void injectKeyEvent(@NonNull KeyEvent event, @DisplayTypeEnum int targetDisplayType) { 394 try { 395 mService.injectKeyEvent(event, targetDisplayType); 396 } catch (RemoteException e) { 397 e.rethrowFromSystemServer(); 398 } 399 } 400 401 /** @hide */ 402 @Override onCarDisconnected()403 protected void onCarDisconnected() { 404 synchronized (mLock) { 405 mCarInputCaptureCallbacks.clear(); 406 } 407 } 408 getCallback(@isplayTypeEnum int targetDisplayType)409 private CallbackHolder getCallback(@DisplayTypeEnum int targetDisplayType) { 410 synchronized (mLock) { 411 return mCarInputCaptureCallbacks.get(targetDisplayType); 412 } 413 } 414 dispatchKeyEvents(@isplayTypeEnum int targetDisplayType, List<KeyEvent> keyEvents)415 private void dispatchKeyEvents(@DisplayTypeEnum int targetDisplayType, 416 List<KeyEvent> keyEvents) { 417 CallbackHolder callbackHolder = getCallback(targetDisplayType); 418 if (callbackHolder == null) { 419 return; 420 } 421 callbackHolder.mExecutor.execute(() -> { 422 callbackHolder.mCallback.onKeyEvents(targetDisplayType, keyEvents); 423 }); 424 } 425 dispatchRotaryEvents(@isplayTypeEnum int targetDisplayType, List<RotaryEvent> events)426 private void dispatchRotaryEvents(@DisplayTypeEnum int targetDisplayType, 427 List<RotaryEvent> events) { 428 CallbackHolder callbackHolder = getCallback(targetDisplayType); 429 if (callbackHolder == null) { 430 return; 431 } 432 callbackHolder.mExecutor.execute(() -> { 433 callbackHolder.mCallback.onRotaryEvents(targetDisplayType, events); 434 }); 435 } 436 dispatchOnCaptureStateChanged(@isplayTypeEnum int targetDisplayType, int[] activeInputTypes)437 private void dispatchOnCaptureStateChanged(@DisplayTypeEnum int targetDisplayType, 438 int[] activeInputTypes) { 439 CallbackHolder callbackHolder = getCallback(targetDisplayType); 440 if (callbackHolder == null) { 441 return; 442 } 443 callbackHolder.mExecutor.execute(() -> { 444 callbackHolder.mCallback.onCaptureStateChanged(targetDisplayType, activeInputTypes); 445 }); 446 } 447 dispatchCustomInputEvents(@isplayTypeEnum int targetDisplayType, List<CustomInputEvent> events)448 private void dispatchCustomInputEvents(@DisplayTypeEnum int targetDisplayType, 449 List<CustomInputEvent> events) { 450 CallbackHolder callbackHolder = getCallback(targetDisplayType); 451 if (callbackHolder == null) { 452 return; 453 } 454 callbackHolder.mExecutor.execute(() -> { 455 if (DEBUG) { 456 Slogf.d(TAG, "Firing events " + events + " on callback " 457 + callbackHolder.mCallback); 458 } 459 callbackHolder.mCallback.onCustomInputEvents(targetDisplayType, events); 460 }); 461 } 462 463 private static final class ICarInputCallbackImpl extends ICarInputCallback.Stub { 464 465 private final WeakReference<CarInputManager> mManager; 466 ICarInputCallbackImpl(CarInputManager manager)467 private ICarInputCallbackImpl(CarInputManager manager) { 468 mManager = new WeakReference<>(manager); 469 } 470 471 @Override onKeyEvents(@isplayTypeEnum int targetDisplayType, @NonNull List<KeyEvent> keyEvents)472 public void onKeyEvents(@DisplayTypeEnum int targetDisplayType, 473 @NonNull List<KeyEvent> keyEvents) { 474 CarInputManager manager = mManager.get(); 475 if (manager == null) { 476 return; 477 } 478 manager.dispatchKeyEvents(targetDisplayType, keyEvents); 479 } 480 481 @Override onRotaryEvents(@isplayTypeEnum int targetDisplayType, @NonNull List<RotaryEvent> events)482 public void onRotaryEvents(@DisplayTypeEnum int targetDisplayType, 483 @NonNull List<RotaryEvent> events) { 484 CarInputManager manager = mManager.get(); 485 if (manager == null) { 486 return; 487 } 488 manager.dispatchRotaryEvents(targetDisplayType, events); 489 } 490 491 @Override onCaptureStateChanged(@isplayTypeEnum int targetDisplayType, @NonNull @InputTypeEnum int[] activeInputTypes)492 public void onCaptureStateChanged(@DisplayTypeEnum int targetDisplayType, 493 @NonNull @InputTypeEnum int[] activeInputTypes) { 494 CarInputManager manager = mManager.get(); 495 if (manager == null) { 496 return; 497 } 498 manager.dispatchOnCaptureStateChanged(targetDisplayType, activeInputTypes); 499 } 500 501 @Override onCustomInputEvents(@isplayTypeEnum int targetDisplayType, @NonNull List<CustomInputEvent> events)502 public void onCustomInputEvents(@DisplayTypeEnum int targetDisplayType, 503 @NonNull List<CustomInputEvent> events) { 504 CarInputManager manager = mManager.get(); 505 if (manager == null) { 506 return; 507 } 508 manager.dispatchCustomInputEvents(targetDisplayType, events); 509 } 510 } 511 512 /** 513 * Class used to bind {@link CarInputCaptureCallback} and their associated {@link Executor}. 514 */ 515 private static final class CallbackHolder { 516 517 final CarInputCaptureCallback mCallback; 518 519 final Executor mExecutor; 520 CallbackHolder(CarInputCaptureCallback callback, Executor executor)521 CallbackHolder(CarInputCaptureCallback callback, Executor executor) { 522 mCallback = callback; 523 mExecutor = executor; 524 } 525 } 526 } 527