Add inject-key command for CarInputService
- Running: $ adb shell cmd car_service inject-key [-d 1] [-t 2000] 219
- -d : display, 0 for main, 1 for cluster
- -t : delay (ms) between key down and key up events. Making this long like
2000 can trigger long press operation.
- last digit: key code to inject.
- Triggering assistant action looks like:
$ adb shell cmd car_service inject-key 219
Bug: 138391974
Test: Run commands and check correct case vs wrong params
Failing cases:
adb shell cmd car_service inject-key
adb shell cmd car_service inject-key -d 2
adb shell cmd car_service inject-key -d abc
adb shell cmd car_service inject-key -d 1 -t -1
adb shell cmd car_service inject-key -d 1 -t 10
adb shell cmd car_service inject-key 100 200
Working cases:
adb shell cmd car_service inject-key 219
adb shell cmd car_service inject-key -d 1 219
adb shell cmd car_service inject-key -t 2000 219
Change-Id: Ib00cf4be69bcd1843d1b03aab4e8addda4386e8e
diff --git a/service/src/com/android/car/ICarImpl.java b/service/src/com/android/car/ICarImpl.java
index 6ec1290..893fe3f 100644
--- a/service/src/com/android/car/ICarImpl.java
+++ b/service/src/com/android/car/ICarImpl.java
@@ -41,16 +41,19 @@
import android.os.ResultReceiver;
import android.os.ShellCallback;
import android.os.ShellCommand;
+import android.os.SystemClock;
import android.os.Trace;
import android.os.UserManager;
import android.util.Log;
import android.util.Slog;
import android.util.TimingsTraceLog;
+import android.view.KeyEvent;
import com.android.car.am.FixedActivityService;
import com.android.car.audio.CarAudioService;
import com.android.car.cluster.InstrumentClusterService;
import com.android.car.garagemode.GarageModeService;
+import com.android.car.hal.InputHalService;
import com.android.car.hal.VehicleHal;
import com.android.car.pm.CarPackageManagerService;
import com.android.car.stats.CarStatsService;
@@ -708,6 +711,7 @@
private static final String COMMAND_STOP_FIXED_ACTIVITY_MODE = "stop-fixed-activity-mode";
private static final String COMMAND_ENABLE_FEATURE = "enable-feature";
private static final String COMMAND_DISABLE_FEATURE = "disable-feature";
+ private static final String COMMAND_INJECT_KEY = "inject-key";
private static final String PARAM_DAY_MODE = "day";
private static final String PARAM_NIGHT_MODE = "night";
@@ -793,6 +797,12 @@
pw.println("\tdisable-feature featureName");
pw.println("\t Disable the requested feature. Change will happen after reboot");
pw.println("\t This requires root/su.");
+ pw.println("\tinject-key [-d display] [-t down_delay_ms] key_code");
+ pw.println("\t inject key down / up event to car service");
+ pw.println("\t display: 0 for main, 1 for cluster. If not specified, it will be 0.");
+ pw.println("\t down_delay_ms: delay from down to up key event. If not specified,");
+ pw.println("\t it will be 0");
+ pw.println("\t key_code: int key code defined in android KeyEvent");
}
private int dumpInvalidArguments(PrintWriter pw) {
@@ -948,6 +958,12 @@
}
handleEnableDisableFeature(args, writer, /* enable= */ false);
break;
+ case COMMAND_INJECT_KEY:
+ if (args.length < 2) {
+ return dumpInvalidArguments(writer);
+ }
+ handleInjectKey(args, writer);
+ break;
default:
writer.println("Unknown command: \"" + arg + "\"");
dumpHelp(writer);
@@ -1042,6 +1058,60 @@
Binder.restoreCallingIdentity(id);
}
+ private void handleInjectKey(String[] args, PrintWriter writer) {
+ int i = 1; // 0 is command itself
+ int display = InputHalService.DISPLAY_MAIN;
+ int delayMs = 0;
+ int keyCode = KeyEvent.KEYCODE_UNKNOWN;
+ try {
+ while (i < args.length) {
+ switch (args[i]) {
+ case "-d":
+ i++;
+ display = Integer.parseInt(args[i]);
+ break;
+ case "-t":
+ i++;
+ delayMs = Integer.parseInt(args[i]);
+ break;
+ default:
+ if (keyCode != KeyEvent.KEYCODE_UNKNOWN) {
+ throw new IllegalArgumentException("key_code already set:"
+ + keyCode);
+ }
+ keyCode = Integer.parseInt(args[i]);
+ }
+ i++;
+ }
+ } catch (Exception e) {
+ writer.println("Invalid args:" + e);
+ dumpHelp(writer);
+ return;
+ }
+ if (keyCode == KeyEvent.KEYCODE_UNKNOWN) {
+ writer.println("Missing key code or invalid keycode");
+ dumpHelp(writer);
+ return;
+ }
+ if (display != InputHalService.DISPLAY_MAIN
+ && display != InputHalService.DISPLAY_INSTRUMENT_CLUSTER) {
+ writer.println("Invalid display:" + display);
+ dumpHelp(writer);
+ return;
+ }
+ if (delayMs < 0) {
+ writer.println("Invalid delay:" + delayMs);
+ dumpHelp(writer);
+ return;
+ }
+ KeyEvent keyDown = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode);
+ mCarInputService.onKeyEvent(keyDown, display);
+ SystemClock.sleep(delayMs);
+ KeyEvent keyUp = new KeyEvent(KeyEvent.ACTION_UP, keyCode);
+ mCarInputService.onKeyEvent(keyUp, display);
+ writer.println("Succeeded");
+ }
+
private void forceDayNightMode(String arg, PrintWriter writer) {
int mode;
switch (arg) {