Marking CarInputManager methods with SystemApi

Test: atest CarServiceUnitTest
Bug: 159623196
Change-Id: I27e07b691167853000632db3c42324b8c855979c
diff --git a/car-lib/api/system-current.txt b/car-lib/api/system-current.txt
index 4406895..65d68d6 100644
--- a/car-lib/api/system-current.txt
+++ b/car-lib/api/system-current.txt
@@ -21,6 +21,7 @@
     field public static final String CAR_DEVICE_POLICY_SERVICE = "car_device_policy_service";
     field public static final String CAR_DRIVING_STATE_SERVICE = "drivingstate";
     field public static final String CAR_EXTRA_CLUSTER_ACTIVITY_STATE = "android.car.cluster.ClusterActivityState";
+    field public static final String CAR_INPUT_SERVICE = "android.car.input";
     field public static final String CAR_MEDIA_SERVICE = "car_media";
     field public static final String CAR_USER_SERVICE = "car_user_service";
     field public static final String CAR_WATCHDOG_SERVICE = "car_watchdog";
@@ -38,6 +39,7 @@
     field public static final String PERMISSION_CAR_DYNAMICS_STATE = "android.car.permission.CAR_DYNAMICS_STATE";
     field public static final String PERMISSION_CAR_ENGINE_DETAILED = "android.car.permission.CAR_ENGINE_DETAILED";
     field public static final String PERMISSION_CAR_INSTRUMENT_CLUSTER_CONTROL = "android.car.permission.CAR_INSTRUMENT_CLUSTER_CONTROL";
+    field public static final String PERMISSION_CAR_MONITOR_INPUT = "android.car.permission.CAR_MONITOR_INPUT";
     field public static final String PERMISSION_CAR_POWER = "android.car.permission.CAR_POWER";
     field public static final String PERMISSION_CAR_PROJECTION = "android.car.permission.CAR_PROJECTION";
     field public static final String PERMISSION_CAR_PROJECTION_STATUS = "android.car.permission.ACCESS_CAR_PROJECTION_STATUS";
@@ -831,6 +833,58 @@
     field @Deprecated public final int mTargetDisplay;
   }
 
+  public final class CarInputManager {
+    method @RequiresPermission(android.Manifest.permission.INJECT_EVENTS) public void injectKeyEvent(@NonNull android.view.KeyEvent, int);
+    method public void releaseInputEventCapture(int);
+    method @RequiresPermission(android.car.Car.PERMISSION_CAR_MONITOR_INPUT) public int requestInputEventCapture(@NonNull android.car.input.CarInputManager.CarInputCaptureCallback, int, @NonNull int[], int);
+    field public static final int CAPTURE_REQ_FLAGS_ALLOW_DELAYED_GRANT = 1; // 0x1
+    field public static final int INPUT_CAPTURE_RESPONSE_DELAYED = 2; // 0x2
+    field public static final int INPUT_CAPTURE_RESPONSE_FAILED = 1; // 0x1
+    field public static final int INPUT_CAPTURE_RESPONSE_SUCCEEDED = 0; // 0x0
+    field public static final int INPUT_TYPE_CUSTOM_INPUT_EVENT = 200; // 0xc8
+    field public static final int INPUT_TYPE_ROTARY_NAVIGATION = 10; // 0xa
+  }
+
+  public static interface CarInputManager.CarInputCaptureCallback {
+    method public default void onCaptureStateChanged(int, @NonNull int[]);
+    method public default void onCustomInputEvents(int, @NonNull java.util.List<android.car.input.CustomInputEvent>);
+    method public default void onKeyEvents(int, @NonNull java.util.List<android.view.KeyEvent>);
+    method public default void onRotaryEvents(int, @NonNull java.util.List<android.car.input.RotaryEvent>);
+  }
+
+  public final class CustomInputEvent implements android.os.Parcelable {
+    ctor public CustomInputEvent(int, int, int);
+    method public int describeContents();
+    method public int getInputCode();
+    method public int getRepeatCounter();
+    method public int getTargetDisplayType();
+    method @NonNull public static String inputCodeToString(int);
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.car.input.CustomInputEvent> CREATOR;
+    field public static final int INPUT_CODE_F1 = 1001; // 0x3e9
+    field public static final int INPUT_CODE_F10 = 1010; // 0x3f2
+    field public static final int INPUT_CODE_F2 = 1002; // 0x3ea
+    field public static final int INPUT_CODE_F3 = 1003; // 0x3eb
+    field public static final int INPUT_CODE_F4 = 1004; // 0x3ec
+    field public static final int INPUT_CODE_F5 = 1005; // 0x3ed
+    field public static final int INPUT_CODE_F6 = 1006; // 0x3ee
+    field public static final int INPUT_CODE_F7 = 1007; // 0x3ef
+    field public static final int INPUT_CODE_F8 = 1008; // 0x3f0
+    field public static final int INPUT_CODE_F9 = 1009; // 0x3f1
+  }
+
+  public final class RotaryEvent implements android.os.Parcelable {
+    ctor public RotaryEvent(int, boolean, @NonNull long[]);
+    method public int describeContents();
+    method public int getInputType();
+    method public int getNumberOfClicks();
+    method public long getUptimeMillisForClick(int);
+    method @NonNull public long[] getUptimeMillisForClicks();
+    method public boolean isClockwise();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.car.input.RotaryEvent> CREATOR;
+  }
+
 }
 
 package android.car.media {
diff --git a/car-lib/api/system-lint-baseline.txt b/car-lib/api/system-lint-baseline.txt
index 0f151f2..b36f2ce 100644
--- a/car-lib/api/system-lint-baseline.txt
+++ b/car-lib/api/system-lint-baseline.txt
@@ -41,6 +41,8 @@
     Callbacks must be abstract class instead of interface to enable extension in future API levels: CarCabinEventCallback
 CallbackInterface: android.car.hardware.hvac.CarHvacManager.CarHvacEventCallback:
     Callbacks must be abstract class instead of interface to enable extension in future API levels: CarHvacEventCallback
+CallbackInterface: android.car.input.CarInputManager.CarInputCaptureCallback:
+    Callbacks must be abstract class instead of interface to enable extension in future API levels: CarInputCaptureCallback
 CallbackInterface: android.car.trust.CarTrustAgentEnrollmentManager.CarTrustAgentBleCallback:
     Callbacks must be abstract class instead of interface to enable extension in future API levels: CarTrustAgentBleCallback
 CallbackInterface: android.car.trust.CarTrustAgentEnrollmentManager.CarTrustAgentEnrollmentCallback:
@@ -77,6 +79,9 @@
     Registration methods should have overload that accepts delivery Executor: `registerCallback`
 ExecutorRegistration: android.car.hardware.hvac.CarHvacManager#registerCallback(android.car.hardware.hvac.CarHvacManager.CarHvacEventCallback):
     Registration methods should have overload that accepts delivery Executor: `registerCallback`
+ExecutorRegistration: android.car.input.CarInputManager#requestInputEventCapture(android.car.input.CarInputManager.CarInputCaptureCallback, int, int[], int):
+    Registration methods should have overload that accepts delivery Executor: `requestInputEventCapture`
+
 ExecutorRegistration: android.car.storagemonitoring.CarStorageMonitoringManager#registerListener(android.car.storagemonitoring.CarStorageMonitoringManager.IoStatsListener):
     Registration methods should have overload that accepts delivery Executor: `registerListener`
 ExecutorRegistration: android.car.trust.CarTrustAgentEnrollmentManager#setBleCallback(android.car.trust.CarTrustAgentEnrollmentManager.CarTrustAgentBleCallback):
@@ -144,6 +149,12 @@
 InternalField: android.car.input.CarInputHandlingService.InputFilter#mTargetDisplay:
     Internal field mTargetDisplay must not be exposed
 
+ListenerLast: android.car.input.CarInputManager#requestInputEventCapture(android.car.input.CarInputManager.CarInputCaptureCallback, int, int[], int) parameter #1:
+    Listeners should always be at end of argument list (method `requestInputEventCapture`)
+ListenerLast: android.car.input.CarInputManager#requestInputEventCapture(android.car.input.CarInputManager.CarInputCaptureCallback, int, int[], int) parameter #2:
+    Listeners should always be at end of argument list (method `requestInputEventCapture`)
+ListenerLast: android.car.input.CarInputManager#requestInputEventCapture(android.car.input.CarInputManager.CarInputCaptureCallback, int, int[], int) parameter #3:
+    Listeners should always be at end of argument list (method `requestInputEventCapture`)
 
 MinMaxConstant: android.car.diagnostic.IntegerSensorIndex#MAX_AIR_FLOW_RATE_FROM_MASS_AIR_FLOW_SENSOR:
     If min/max could change in future, make them dynamic methods: android.car.diagnostic.IntegerSensorIndex#MAX_AIR_FLOW_RATE_FROM_MASS_AIR_FLOW_SENSOR
diff --git a/car-lib/src/android/car/Car.java b/car-lib/src/android/car/Car.java
index 4468c95..5d9f128 100644
--- a/car-lib/src/android/car/Car.java
+++ b/car-lib/src/android/car/Car.java
@@ -336,6 +336,8 @@
     /**
      * @hide
      */
+    @MandatoryFeature
+    @SystemApi
     public static final String CAR_INPUT_SERVICE = "android.car.input";
 
     /**
@@ -711,10 +713,18 @@
     public static final String PERMISSION_USE_CAR_WATCHDOG =
             "android.car.permission.USE_CAR_WATCHDOG";
 
+    /**
+     * Permission necessary to monitor Car input events.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String PERMISSION_CAR_MONITOR_INPUT =
+            "android.car.permission.CAR_MONITOR_INPUT";
+
     /** Type of car connection: platform runs directly in car. */
     public static final int CONNECTION_TYPE_EMBEDDED = 5;
 
-
     /** @hide */
     @IntDef({CONNECTION_TYPE_EMBEDDED})
     @Retention(RetentionPolicy.SOURCE)
diff --git a/car-lib/src/android/car/input/CarInputManager.java b/car-lib/src/android/car/input/CarInputManager.java
index 84f582f..777d925 100644
--- a/car-lib/src/android/car/input/CarInputManager.java
+++ b/car-lib/src/android/car/input/CarInputManager.java
@@ -21,6 +21,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
 import android.car.Car;
 import android.car.CarManagerBase;
 import android.car.CarOccupantZoneManager;
@@ -44,6 +45,7 @@
  *
  * @hide
  */
+@SystemApi
 public final class CarInputManager extends CarManagerBase {
 
     private static final String TAG = CarInputManager.class.getSimpleName();
@@ -55,8 +57,7 @@
      * <p>
      * Events (key, rotary and custom input events) are associated with display types.
      * Display types are defined in {@link android.car.CarOccupantZoneManager}. This manager only
-     * accepts the driver display types. Currently it accepts driver's displays only (
-     * ({@link CarOccupantZoneManager#DISPLAY_TYPE_MAIN} and
+     * accepts the driver display types ({@link CarOccupantZoneManager#DISPLAY_TYPE_MAIN} and
      * {@link CarOccupantZoneManager#DISPLAY_TYPE_INSTRUMENT_CLUSTER}).
      */
     public interface CarInputCaptureCallback {
@@ -113,12 +114,12 @@
     public static final int CAPTURE_REQ_FLAGS_TAKE_ALL_EVENTS_FOR_DISPLAY = 0x2;
 
     /** @hide */
-    @IntDef(flag = true, prefix = { "CAPTURE_REQ_FLAGS_" }, value = {
+    @IntDef(flag = true, prefix = {"CAPTURE_REQ_FLAGS_"}, value = {
             CAPTURE_REQ_FLAGS_ALLOW_DELAYED_GRANT,
             CAPTURE_REQ_FLAGS_TAKE_ALL_EVENTS_FOR_DISPLAY,
     })
     @Retention(RetentionPolicy.SOURCE)
-    @interface CaptureRequestFlags {}
+    public @interface CaptureRequestFlags {}
 
     /**
      * This is special type to cover all INPUT_TYPE_*. This is used for clients using
@@ -148,16 +149,22 @@
      * {@link KeyEvent#KEYCODE_DPAD_RIGHT}, {@link KeyEvent#KEYCODE_DPAD_CENTER},
      * {@link KeyEvent#KEYCODE_DPAD_DOWN_LEFT}, {@link KeyEvent#KEYCODE_DPAD_DOWN_RIGHT},
      * {@link KeyEvent#KEYCODE_DPAD_UP_LEFT}, {@link KeyEvent#KEYCODE_DPAD_UP_RIGHT}
+     *
+     * @hide
      */
     public static final int INPUT_TYPE_DPAD_KEYS = 100;
 
     /**
      * This is for all {@code KeyEvent#KEYCODE_NAVIGATE_*} keys.
+     *
+     * @hide
      */
     public static final int INPUT_TYPE_NAVIGATE_KEYS = 101;
 
     /**
      * This is for all {@code KeyEvent#KEYCODE_SYSTEM_NAVIGATE_*} keys.
+     *
+     * @hide
      */
     public static final int INPUT_TYPE_SYSTEM_NAVIGATE_KEYS = 102;
 
@@ -244,11 +251,22 @@
      * until the client receives a {@link CarInputCaptureCallback#onCaptureStateChanged(int, int[])}
      * call with valid input types.
      *
-     * <p> The targetDisplayType parameter must represent a driver display type (
-     * {@link CarOccupantZoneManager#DISPLAY_TYPE_MAIN} or
+     * <p> The targetDisplayType parameter must only contain driver display types (which are
+     * {@link CarOccupantZoneManager#DISPLAY_TYPE_MAIN} and
      * {@link CarOccupantZoneManager#DISPLAY_TYPE_INSTRUMENT_CLUSTER}.
+     *
+     * <p>Callbacks are grouped and stacked per display and input types. Only the most recently
+     * registered callback will receive the incoming events for the associated display and input
+     * types.
+     *
+     * @throws SecurityException is caller doesn't have android.car.permission.CAR_MONITOR_INPUT
+     *                           permission granted
+     * @throws IllegalArgumentException if targetDisplayType parameter correspond to a non supported
+     *                                  display type
+     * @throws IllegalArgumentException if inputTypes parameter contains invalid or non supported
+     *                                  values
      */
-    @RequiresPermission(android.Manifest.permission.MONITOR_INPUT)
+    @RequiresPermission(Car.PERMISSION_CAR_MONITOR_INPUT)
     @InputCaptureResponseEnum
     public int requestInputEventCapture(@NonNull CarInputCaptureCallback callback,
             @DisplayTypeEnum int targetDisplayType,
@@ -289,12 +307,12 @@
      * The event parameter display id will be overridden accordingly to the display type also passed
      * as parameter.
      *
-     * @param event the event to inject
-     * @param targetDisplayType the display type associated with the event
+     * @param event the key event to inject
+     * @param targetDisplayType the display type associated with the key event
      * @throws RemoteException in case of failure when invoking car input service
      */
     @RequiresPermission(android.Manifest.permission.INJECT_EVENTS)
-    public void injectKeyEvent(KeyEvent event, @DisplayTypeEnum int targetDisplayType) {
+    public void injectKeyEvent(@NonNull KeyEvent event, @DisplayTypeEnum int targetDisplayType) {
         try {
             mService.injectKeyEvent(event, targetDisplayType);
         } catch (RemoteException e) {
@@ -302,6 +320,7 @@
         }
     }
 
+    /** @hide */
     @Override
     protected void onCarDisconnected() {
         synchronized (mLock) {
diff --git a/car-lib/src/android/car/input/CustomInputEvent.java b/car-lib/src/android/car/input/CustomInputEvent.java
index 129d8fa..fd5412c 100644
--- a/car-lib/src/android/car/input/CustomInputEvent.java
+++ b/car-lib/src/android/car/input/CustomInputEvent.java
@@ -17,6 +17,7 @@
 package android.car.input;
 
 import android.annotation.NonNull;
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -34,6 +35,7 @@
 //       input.
 // TODO(b/12219669): Check with INPUT_CODE_Fn constants should move to
 //     android/car/Constants/CommonConstants.java. If keeping these constants, than add unit tests.
+@SystemApi
 @DataClass(
         genEqualsHashCode = true,
         genAidl = true)
@@ -72,7 +74,7 @@
     //   Settings > Editor > Code Style > Formatter Control
     //@formatter:off
 
-
+    /** @hide */
     @android.annotation.IntDef(prefix = "INPUT_CODE_", value = {
             INPUT_CODE_F1,
             INPUT_CODE_F2,
@@ -91,6 +93,7 @@
     }
 
     @DataClass.Generated.Member
+    @NonNull
     public static String inputCodeToString(@InputCode int value) {
         switch (value) {
             case INPUT_CODE_F1:
@@ -314,3 +317,4 @@
     //@formatter:on
     // End of generated code
 }
+
diff --git a/car-lib/src/android/car/input/RotaryEvent.java b/car-lib/src/android/car/input/RotaryEvent.java
index a43e1e2..565f039 100644
--- a/car-lib/src/android/car/input/RotaryEvent.java
+++ b/car-lib/src/android/car/input/RotaryEvent.java
@@ -16,6 +16,7 @@
 package android.car.input;
 
 import android.annotation.NonNull;
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -31,6 +32,7 @@
  *
  * @hide
  */
+@SystemApi
 @DataClass(
         genEqualsHashCode = true,
         genAidl = true)
diff --git a/service/AndroidManifest.xml b/service/AndroidManifest.xml
index 1fe8c0c..e9755a5 100644
--- a/service/AndroidManifest.xml
+++ b/service/AndroidManifest.xml
@@ -780,6 +780,13 @@
          android:label="@string/car_permission_label_set_car_vendor_category_10"
          android:description="@string/car_permission_desc_set_car_vendor_category_10"/>
 
+    <!-- Allows an application to receive Car input events.
+        <p>Protection level: signature
+    -->
+    <permission android:name="android.car.permission.CAR_MONITOR_INPUT"
+                android:protectionLevel="signature"
+                android:label="@string/car_permission_label_monitor_input"
+                android:description="@string/car_permission_desc_monitor_input"/>
 
     <uses-permission android:name="android.permission.CALL_PHONE"/>
     <uses-permission android:name="android.permission.DEVICE_POWER"/>
diff --git a/service/res/values/strings.xml b/service/res/values/strings.xml
index 0b1c265..1d92934 100644
--- a/service/res/values/strings.xml
+++ b/service/res/values/strings.xml
@@ -465,6 +465,11 @@
     <!-- Permission text: apps control vendor properties in category 10 [CHAR LIMIT=NONE] -->
     <string name="car_permission_desc_set_car_vendor_category_10" translatable="false">Control vendor specific properties in category 10.</string>
 
+    <!-- Permission text: apps can receive car input events [CHAR LIMIT=NONE] -->
+    <string name="car_permission_label_monitor_input" translatable="false">receive car input events</string>
+    <!-- Permission text: apps can receive car input events [CHAR LIMIT=NONE] -->
+    <string name="car_permission_desc_monitor_input" translatable="false">Receive car input events</string>
+
     <!-- Permission text: enable or disable car's features [CHAR LIMIT=NONE] -->
     <string name="car_permission_label_control_car_features">Enable or disable car\u2019s features</string>
     <!-- Permission text: enable or disable car's features [CHAR LIMIT=NONE] -->
diff --git a/service/src/com/android/car/InputCaptureClientController.java b/service/src/com/android/car/InputCaptureClientController.java
index e33b0a5..ed55b24 100644
--- a/service/src/com/android/car/InputCaptureClientController.java
+++ b/service/src/com/android/car/InputCaptureClientController.java
@@ -21,6 +21,7 @@
 import static java.util.Map.entry;
 
 import android.annotation.NonNull;
+import android.car.Car;
 import android.car.CarOccupantZoneManager;
 import android.car.input.CarInputManager;
 import android.car.input.CustomInputEvent;
@@ -239,7 +240,7 @@
     public int requestInputEventCapture(ICarInputCallback callback,
             @DisplayTypeEnum int targetDisplayType,
             int[] inputTypes, int requestFlags) {
-        ICarImpl.assertPermission(mContext, android.Manifest.permission.MONITOR_INPUT);
+        ICarImpl.assertPermission(mContext, Car.PERMISSION_CAR_MONITOR_INPUT);
 
         Preconditions.checkArgument(SUPPORTED_DISPLAY_TYPES.contains(targetDisplayType),
                 "Display not supported yet:" + targetDisplayType);
diff --git a/tests/SampleCustomInputService/AndroidManifest.xml b/tests/SampleCustomInputService/AndroidManifest.xml
index d012ff4..596b0d6 100644
--- a/tests/SampleCustomInputService/AndroidManifest.xml
+++ b/tests/SampleCustomInputService/AndroidManifest.xml
@@ -25,7 +25,9 @@
     <!-- The following permissions are required in order to communicate against Car Input API -->
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"/>
     <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
-    <uses-permission android:name="android.permission.MONITOR_INPUT"/>
+    <!-- This permission is required to register against CarInputManager in order to receive
+         custom input events. -->
+    <uses-permission android:name="android.car.permission.CAR_MONITOR_INPUT"/>
     <!-- This permission is required to adjust car audio volume -->
     <uses-permission android:name="android.car.permission.CAR_CONTROL_AUDIO_VOLUME"/>
 
diff --git a/tests/carservice_test/AndroidManifest.xml b/tests/carservice_test/AndroidManifest.xml
index 198292b..6040c5b 100644
--- a/tests/carservice_test/AndroidManifest.xml
+++ b/tests/carservice_test/AndroidManifest.xml
@@ -28,6 +28,7 @@
     <uses-permission android:name="android.car.permission.CONTROL_APP_BLOCKING"/>
     <uses-permission android:name="android.car.permission.CAR_CONTROL_AUDIO_VOLUME"/>
     <uses-permission android:name="android.car.permission.CAR_CONTROL_AUDIO_SETTINGS"/>
+    <uses-permission android:name="android.car.permission.CAR_MONITOR_INPUT"/>
     <uses-permission android:name="android.car.permission.STORAGE_MONITORING"/>
     <uses-permission android:name="android.car.permission.READ_CAR_OCCUPANT_AWARENESS_STATE"/>