diff --git a/internal/android/android.go b/internal/android/android.go index a1820ea..17753f9 100644 --- a/internal/android/android.go +++ b/internal/android/android.go @@ -54,6 +54,33 @@ func EnsureDevice(ctx context.Context, serial, avdName string, stdout io.Writer) return nil } +// PrepareDevice keeps the device awake, wakes the screen, and dismisses a +// non-secure keyguard so the launched app stays in the foreground for the whole +// run. The fuzzer drives whatever is on screen, so a sleeping or locked device +// would have it explore system UI instead of the app. A secure lock +// (PIN/password) cannot be dismissed here and must be unlocked out of band. +func PrepareDevice(ctx context.Context, serial string) error { + adb, err := AdbBinary() + if err != nil { + return err + } + for _, shellCommand := range [][]string{ + {"svc", "power", "stayon", "true"}, + {"input", "keyevent", "KEYCODE_WAKEUP"}, + {"wm", "dismiss-keyguard"}, + } { + args := []string{} + if serial != "" { + args = append(args, "-s", serial) + } + args = append(append(args, "shell"), shellCommand...) + if err := exec.CommandContext(ctx, adb, args...).Run(); err != nil { + return fmt.Errorf("adb %s: %w", strings.Join(shellCommand, " "), err) + } + } + return nil +} + // AdbReverse sets up adb reverse forwarding for a local abstract socket. func AdbReverse(socket string, port int) error { adb, err := AdbBinary() diff --git a/internal/testrun/testrun.go b/internal/testrun/testrun.go index 1ffbdba..b0fc730 100644 --- a/internal/testrun/testrun.go +++ b/internal/testrun/testrun.go @@ -50,6 +50,9 @@ func Execute(ctx context.Context, options Options, stdout io.Writer) error { if err := android.EnsureDevice(ctx, options.Device, options.AVD, stdout); err != nil { return err } + if err := android.PrepareDevice(ctx, options.Device); err != nil { + return err + } case "ios": resolved, err := resolveIOSTarget(ctx, options, stdout) if err != nil {