Compare commits
7 Commits
nosecurefl
...
device_sim
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
233f8e6cc4 | ||
|
|
9a7d351d67 | ||
|
|
d00ee640c0 | ||
|
|
ae6ec7a194 | ||
|
|
84f17fdeab | ||
|
|
1cde68a1fa | ||
|
|
45e7280148 |
@@ -186,7 +186,7 @@ Enable "show touches" on start, restore the initial value on exit.
|
|||||||
It only shows physical touches (not clicks from scrcpy).
|
It only shows physical touches (not clicks from scrcpy).
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BI "\-\-v4l2_sink " /dev/videoN
|
.BI "\-\-v4l2-sink " /dev/videoN
|
||||||
Output to v4l2loopback device.
|
Output to v4l2loopback device.
|
||||||
|
|
||||||
It requires to lock the video orientation (see --lock-video-orientation).
|
It requires to lock the video orientation (see --lock-video-orientation).
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ scrcpy_print_usage(const char *arg0) {
|
|||||||
" It only shows physical touches (not clicks from scrcpy).\n"
|
" It only shows physical touches (not clicks from scrcpy).\n"
|
||||||
"\n"
|
"\n"
|
||||||
#ifdef HAVE_V4L2
|
#ifdef HAVE_V4L2
|
||||||
" --v4l2_sink /dev/videoN\n"
|
" --v4l2-sink /dev/videoN\n"
|
||||||
" Output to v4l2loopback device.\n"
|
" Output to v4l2loopback device.\n"
|
||||||
" It requires to lock the video orientation (see\n"
|
" It requires to lock the video orientation (see\n"
|
||||||
" --lock-video-orientation).\n"
|
" --lock-video-orientation).\n"
|
||||||
@@ -726,7 +726,7 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
|
|||||||
{"stay-awake", no_argument, NULL, 'w'},
|
{"stay-awake", no_argument, NULL, 'w'},
|
||||||
{"turn-screen-off", no_argument, NULL, 'S'},
|
{"turn-screen-off", no_argument, NULL, 'S'},
|
||||||
#ifdef HAVE_V4L2
|
#ifdef HAVE_V4L2
|
||||||
{"v4l2_sink", required_argument, NULL, OPT_V4L2_SINK},
|
{"v4l2-sink", required_argument, NULL, OPT_V4L2_SINK},
|
||||||
#endif
|
#endif
|
||||||
{"verbosity", required_argument, NULL, 'V'},
|
{"verbosity", required_argument, NULL, 'V'},
|
||||||
{"version", no_argument, NULL, 'v'},
|
{"version", no_argument, NULL, 'v'},
|
||||||
@@ -926,7 +926,7 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
|
|||||||
#ifdef HAVE_V4L2
|
#ifdef HAVE_V4L2
|
||||||
if (!opts->display && !opts->record_filename && !opts->v4l2_device) {
|
if (!opts->display && !opts->record_filename && !opts->v4l2_device) {
|
||||||
LOGE("-N/--no-display requires either screen recording (-r/--record)"
|
LOGE("-N/--no-display requires either screen recording (-r/--record)"
|
||||||
" or sink to v4l2loopback device (--v4l2_sink)");
|
" or sink to v4l2loopback device (--v4l2-sink)");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -111,6 +111,8 @@ decoder_push(struct decoder *decoder, const AVPacket *packet) {
|
|||||||
// A frame lost should not make the whole pipeline fail. The error, if
|
// A frame lost should not make the whole pipeline fail. The error, if
|
||||||
// any, is already logged.
|
// any, is already logged.
|
||||||
(void) ok;
|
(void) ok;
|
||||||
|
|
||||||
|
av_frame_unref(decoder->frame);
|
||||||
} else if (ret != AVERROR(EAGAIN)) {
|
} else if (ret != AVERROR(EAGAIN)) {
|
||||||
LOGE("Could not receive video frame: %d", ret);
|
LOGE("Could not receive video frame: %d", ret);
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -92,11 +92,11 @@ encode_and_write_frame(struct sc_v4l2_sink *vs, const AVFrame *frame) {
|
|||||||
// A packet was received
|
// A packet was received
|
||||||
|
|
||||||
bool ok = write_packet(vs, packet);
|
bool ok = write_packet(vs, packet);
|
||||||
|
av_packet_unref(packet);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
LOGW("Could not send packet to v4l2 sink");
|
LOGW("Could not send packet to v4l2 sink");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
av_packet_unref(packet);
|
|
||||||
} else if (ret != AVERROR(EAGAIN)) {
|
} else if (ret != AVERROR(EAGAIN)) {
|
||||||
LOGE("Could not receive v4l2 video packet: %d", ret);
|
LOGE("Could not receive v4l2 video packet: %d", ret);
|
||||||
return false;
|
return false;
|
||||||
@@ -125,6 +125,7 @@ run_v4l2_sink(void *data) {
|
|||||||
|
|
||||||
video_buffer_consume(&vs->vb, vs->frame);
|
video_buffer_consume(&vs->vb, vs->frame);
|
||||||
bool ok = encode_and_write_frame(vs, vs->frame);
|
bool ok = encode_and_write_frame(vs, vs->frame);
|
||||||
|
av_frame_unref(vs->frame);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
LOGE("Could not send frame to v4l2 sink");
|
LOGE("Could not send frame to v4l2 sink");
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ public class Controller {
|
|||||||
public void control() throws IOException {
|
public void control() throws IOException {
|
||||||
// on start, power on the device
|
// on start, power on the device
|
||||||
if (!Device.isScreenOn()) {
|
if (!Device.isScreenOn()) {
|
||||||
device.injectKeycode(KeyEvent.KEYCODE_POWER);
|
device.pressReleaseKeycode(KeyEvent.KEYCODE_POWER);
|
||||||
|
|
||||||
// dirty hack
|
// dirty hack
|
||||||
// After POWER is injected, the device is powered on asynchronously.
|
// After POWER is injected, the device is powered on asynchronously.
|
||||||
@@ -273,7 +273,7 @@ public class Controller {
|
|||||||
if (keepPowerModeOff) {
|
if (keepPowerModeOff) {
|
||||||
schedulePowerModeOff();
|
schedulePowerModeOff();
|
||||||
}
|
}
|
||||||
return device.injectKeycode(KeyEvent.KEYCODE_POWER);
|
return device.pressReleaseKeycode(KeyEvent.KEYCODE_POWER);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean setClipboard(String text, boolean paste) {
|
private boolean setClipboard(String text, boolean paste) {
|
||||||
@@ -284,7 +284,7 @@ public class Controller {
|
|||||||
|
|
||||||
// On Android >= 7, also press the PASTE key if requested
|
// On Android >= 7, also press the PASTE key if requested
|
||||||
if (paste && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && device.supportsInputEvents()) {
|
if (paste && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && device.supportsInputEvents()) {
|
||||||
device.injectKeycode(KeyEvent.KEYCODE_PASTE);
|
device.pressReleaseKeycode(KeyEvent.KEYCODE_PASTE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ok;
|
return ok;
|
||||||
|
|||||||
@@ -164,54 +164,39 @@ public final class Device {
|
|||||||
return supportsInputEvents;
|
return supportsInputEvents;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean injectEvent(InputEvent inputEvent, int mode, int displayId) {
|
public static boolean injectEvent(InputEvent inputEvent, int displayId) {
|
||||||
if (!supportsInputEvents(displayId)) {
|
if (!supportsInputEvents(displayId)) {
|
||||||
return false;
|
throw new AssertionError("Could not inject input event if !supportsInputEvents()");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (displayId != 0 && !InputManager.setDisplayId(inputEvent, displayId)) {
|
if (displayId != 0 && !InputManager.setDisplayId(inputEvent, displayId)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return SERVICE_MANAGER.getInputManager().injectInputEvent(inputEvent, mode);
|
return SERVICE_MANAGER.getInputManager().injectInputEvent(inputEvent, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
|
||||||
}
|
|
||||||
|
|
||||||
public boolean injectEvent(InputEvent inputEvent, int mode) {
|
|
||||||
if (!supportsInputEvents()) {
|
|
||||||
throw new AssertionError("Could not inject input event if !supportsInputEvents()");
|
|
||||||
}
|
|
||||||
|
|
||||||
return injectEvent(inputEvent, mode, displayId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean injectEventOnDisplay(InputEvent event, int displayId) {
|
|
||||||
return injectEvent(event, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC, displayId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean injectEvent(InputEvent event) {
|
public boolean injectEvent(InputEvent event) {
|
||||||
return injectEvent(event, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
|
return injectEvent(event, displayId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean injectKeyEvent(int action, int keyCode, int repeat, int metaState, int displayId) {
|
public static boolean injectKeyEvent(int action, int keyCode, int repeat, int metaState, int displayId) {
|
||||||
long now = SystemClock.uptimeMillis();
|
long now = SystemClock.uptimeMillis();
|
||||||
KeyEvent event = new KeyEvent(now, now, action, keyCode, repeat, metaState, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0,
|
KeyEvent event = new KeyEvent(now, now, action, keyCode, repeat, metaState, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0,
|
||||||
InputDevice.SOURCE_KEYBOARD);
|
InputDevice.SOURCE_KEYBOARD);
|
||||||
return injectEventOnDisplay(event, displayId);
|
return injectEvent(event, displayId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean injectKeyEvent(int action, int keyCode, int repeat, int metaState) {
|
public boolean injectKeyEvent(int action, int keyCode, int repeat, int metaState) {
|
||||||
long now = SystemClock.uptimeMillis();
|
return injectKeyEvent(action, keyCode, repeat, metaState, displayId);
|
||||||
KeyEvent event = new KeyEvent(now, now, action, keyCode, repeat, metaState, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0,
|
|
||||||
InputDevice.SOURCE_KEYBOARD);
|
|
||||||
return injectEvent(event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean injectKeycode(int keyCode, int displayId) {
|
public static boolean pressReleaseKeycode(int keyCode, int displayId) {
|
||||||
return injectKeyEvent(KeyEvent.ACTION_DOWN, keyCode, 0, 0, displayId) && injectKeyEvent(KeyEvent.ACTION_UP, keyCode, 0, 0, displayId);
|
return injectKeyEvent(KeyEvent.ACTION_DOWN, keyCode, 0, 0, displayId) && injectKeyEvent(KeyEvent.ACTION_UP, keyCode, 0, 0, displayId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean injectKeycode(int keyCode) {
|
public boolean pressReleaseKeycode(int keyCode) {
|
||||||
return injectKeyEvent(KeyEvent.ACTION_DOWN, keyCode, 0, 0) && injectKeyEvent(KeyEvent.ACTION_UP, keyCode, 0, 0);
|
return pressReleaseKeycode(keyCode, displayId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isScreenOn() {
|
public static boolean isScreenOn() {
|
||||||
@@ -287,7 +272,7 @@ public final class Device {
|
|||||||
if (!isScreenOn()) {
|
if (!isScreenOn()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return injectKeycode(KeyEvent.KEYCODE_POWER, displayId);
|
return pressReleaseKeycode(KeyEvent.KEYCODE_POWER, displayId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user