Compare commits
16 Commits
pr1944
...
legacy_pas
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
206abdb2c5 | ||
|
|
83082406d3 | ||
|
|
2edf192e3a | ||
|
|
d50ecf40b6 | ||
|
|
56d237f152 | ||
|
|
acc65f8c9d | ||
|
|
a65ebceac1 | ||
|
|
d662f73bdc | ||
|
|
1c44dc2259 | ||
|
|
02a882a0a2 | ||
|
|
cf7bf3148c | ||
|
|
ae758f99d6 | ||
|
|
bd9f656933 | ||
|
|
c243fd4c3f | ||
|
|
0bf110dd5c | ||
|
|
0c5e0a4f6d |
@@ -548,6 +548,10 @@ into the device clipboard. As a consequence, any Android application could read
|
|||||||
its content. You should avoid to paste sensitive content (like passwords) that
|
its content. You should avoid to paste sensitive content (like passwords) that
|
||||||
way.
|
way.
|
||||||
|
|
||||||
|
Some devices do not behave as expected when setting the device clipboard
|
||||||
|
programmatically. An option `--legacy-paste` is provided to change the behavior
|
||||||
|
of <kbd>Ctrl</kbd>+<kbd>v</kbd> and <kbd>MOD</kbd>+<kbd>v</kbd> to also inject
|
||||||
|
the computer clipboard text as a sequence of key events.
|
||||||
|
|
||||||
#### Pinch-to-zoom
|
#### Pinch-to-zoom
|
||||||
|
|
||||||
|
|||||||
14
app/scrcpy.1
14
app/scrcpy.1
@@ -68,6 +68,12 @@ Start in fullscreen.
|
|||||||
.B \-h, \-\-help
|
.B \-h, \-\-help
|
||||||
Print this help.
|
Print this help.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B \-\-legacy\-paste
|
||||||
|
Inject computer clipboard text as a sequence of key events on Ctrl+v (like MOD+Shift+v).
|
||||||
|
|
||||||
|
This is a workaround for some devices not behaving as expected when setting the device clipboard programmatically.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BI "\-\-lock\-video\-orientation " value
|
.BI "\-\-lock\-video\-orientation " value
|
||||||
Lock video orientation to \fIvalue\fR. Possible values are -1 (unlocked), 0, 1, 2 and 3. Natural device orientation is 0, and each increment adds a 90 degrees otation counterclockwise.
|
Lock video orientation to \fIvalue\fR. Possible values are -1 (unlocked), 0, 1, 2 and 3. Natural device orientation is 0, and each increment adds a 90 degrees otation counterclockwise.
|
||||||
@@ -92,14 +98,14 @@ Disable device control (mirror the device in read\-only).
|
|||||||
.B \-N, \-\-no\-display
|
.B \-N, \-\-no\-display
|
||||||
Do not display device (only when screen recording is enabled).
|
Do not display device (only when screen recording is enabled).
|
||||||
|
|
||||||
.TP
|
|
||||||
.B \-\-no\-mipmaps
|
|
||||||
If the renderer is OpenGL 3.0+ or OpenGL ES 2.0+, then mipmaps are automatically generated to improve downscaling quality. This option disables the generation of mipmaps.
|
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-\-no\-key\-repeat
|
.B \-\-no\-key\-repeat
|
||||||
Do not forward repeated key events when a key is held down.
|
Do not forward repeated key events when a key is held down.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B \-\-no\-mipmaps
|
||||||
|
If the renderer is OpenGL 3.0+ or OpenGL ES 2.0+, then mipmaps are automatically generated to improve downscaling quality. This option disables the generation of mipmaps.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BI "\-p, \-\-port " port[:port]
|
.BI "\-p, \-\-port " port[:port]
|
||||||
Set the TCP port (range) used by the client to listen.
|
Set the TCP port (range) used by the client to listen.
|
||||||
|
|||||||
@@ -63,6 +63,12 @@ scrcpy_print_usage(const char *arg0) {
|
|||||||
" -h, --help\n"
|
" -h, --help\n"
|
||||||
" Print this help.\n"
|
" Print this help.\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
" --legacy-paste\n"
|
||||||
|
" Inject computer clipboard text as a sequence of key events\n"
|
||||||
|
" on Ctrl+v (like MOD+Shift+v).\n"
|
||||||
|
" This is a workaround for some devices not behaving as\n"
|
||||||
|
" expected when setting the device clipboard programmatically.\n"
|
||||||
|
"\n"
|
||||||
" --lock-video-orientation value\n"
|
" --lock-video-orientation value\n"
|
||||||
" Lock video orientation to value.\n"
|
" Lock video orientation to value.\n"
|
||||||
" Possible values are -1 (unlocked), 0, 1, 2 and 3.\n"
|
" Possible values are -1 (unlocked), 0, 1, 2 and 3.\n"
|
||||||
@@ -87,14 +93,14 @@ scrcpy_print_usage(const char *arg0) {
|
|||||||
" Do not display device (only when screen recording is\n"
|
" Do not display device (only when screen recording is\n"
|
||||||
" enabled).\n"
|
" enabled).\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
" --no-key-repeat\n"
|
||||||
|
" Do not forward repeated key events when a key is held down.\n"
|
||||||
|
"\n"
|
||||||
" --no-mipmaps\n"
|
" --no-mipmaps\n"
|
||||||
" If the renderer is OpenGL 3.0+ or OpenGL ES 2.0+, then\n"
|
" If the renderer is OpenGL 3.0+ or OpenGL ES 2.0+, then\n"
|
||||||
" mipmaps are automatically generated to improve downscaling\n"
|
" mipmaps are automatically generated to improve downscaling\n"
|
||||||
" quality. This option disables the generation of mipmaps.\n"
|
" quality. This option disables the generation of mipmaps.\n"
|
||||||
"\n"
|
"\n"
|
||||||
" --no-key-repeat\n"
|
|
||||||
" Do not forward repeated key events when a key is held down.\n"
|
|
||||||
"\n"
|
|
||||||
" -p, --port port[:port]\n"
|
" -p, --port port[:port]\n"
|
||||||
" Set the TCP port (range) used by the client to listen.\n"
|
" Set the TCP port (range) used by the client to listen.\n"
|
||||||
" Default is %d:%d.\n"
|
" Default is %d:%d.\n"
|
||||||
@@ -651,6 +657,7 @@ guess_record_format(const char *filename) {
|
|||||||
#define OPT_DISABLE_SCREENSAVER 1020
|
#define OPT_DISABLE_SCREENSAVER 1020
|
||||||
#define OPT_SHORTCUT_MOD 1021
|
#define OPT_SHORTCUT_MOD 1021
|
||||||
#define OPT_NO_KEY_REPEAT 1022
|
#define OPT_NO_KEY_REPEAT 1022
|
||||||
|
#define OPT_LEGACY_PASTE 1023
|
||||||
|
|
||||||
bool
|
bool
|
||||||
scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
|
scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
|
||||||
@@ -666,14 +673,15 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
|
|||||||
OPT_FORCE_ADB_FORWARD},
|
OPT_FORCE_ADB_FORWARD},
|
||||||
{"fullscreen", no_argument, NULL, 'f'},
|
{"fullscreen", no_argument, NULL, 'f'},
|
||||||
{"help", no_argument, NULL, 'h'},
|
{"help", no_argument, NULL, 'h'},
|
||||||
|
{"legacy-paste", no_argument, NULL, OPT_LEGACY_PASTE},
|
||||||
{"lock-video-orientation", required_argument, NULL,
|
{"lock-video-orientation", required_argument, NULL,
|
||||||
OPT_LOCK_VIDEO_ORIENTATION},
|
OPT_LOCK_VIDEO_ORIENTATION},
|
||||||
{"max-fps", required_argument, NULL, OPT_MAX_FPS},
|
{"max-fps", required_argument, NULL, OPT_MAX_FPS},
|
||||||
{"max-size", required_argument, NULL, 'm'},
|
{"max-size", required_argument, NULL, 'm'},
|
||||||
{"no-control", no_argument, NULL, 'n'},
|
{"no-control", no_argument, NULL, 'n'},
|
||||||
{"no-display", no_argument, NULL, 'N'},
|
{"no-display", no_argument, NULL, 'N'},
|
||||||
{"no-mipmaps", no_argument, NULL, OPT_NO_MIPMAPS},
|
|
||||||
{"no-key-repeat", no_argument, NULL, OPT_NO_KEY_REPEAT},
|
{"no-key-repeat", no_argument, NULL, OPT_NO_KEY_REPEAT},
|
||||||
|
{"no-mipmaps", no_argument, NULL, OPT_NO_MIPMAPS},
|
||||||
{"port", required_argument, NULL, 'p'},
|
{"port", required_argument, NULL, 'p'},
|
||||||
{"prefer-text", no_argument, NULL, OPT_PREFER_TEXT},
|
{"prefer-text", no_argument, NULL, OPT_PREFER_TEXT},
|
||||||
{"push-target", required_argument, NULL, OPT_PUSH_TARGET},
|
{"push-target", required_argument, NULL, OPT_PUSH_TARGET},
|
||||||
@@ -856,6 +864,9 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case OPT_LEGACY_PASTE:
|
||||||
|
opts->legacy_paste = true;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
// getopt prints the error message on stderr
|
// getopt prints the error message on stderr
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ input_manager_init(struct input_manager *im,
|
|||||||
im->control = options->control;
|
im->control = options->control;
|
||||||
im->forward_key_repeat = options->forward_key_repeat;
|
im->forward_key_repeat = options->forward_key_repeat;
|
||||||
im->prefer_text = options->prefer_text;
|
im->prefer_text = options->prefer_text;
|
||||||
|
im->legacy_paste = options->legacy_paste;
|
||||||
|
|
||||||
const struct sc_shortcut_mods *shortcut_mods = &options->shortcut_mods;
|
const struct sc_shortcut_mods *shortcut_mods = &options->shortcut_mods;
|
||||||
assert(shortcut_mods->count);
|
assert(shortcut_mods->count);
|
||||||
@@ -440,7 +441,7 @@ input_manager_process_key(struct input_manager *im,
|
|||||||
return;
|
return;
|
||||||
case SDLK_v:
|
case SDLK_v:
|
||||||
if (control && !repeat && down) {
|
if (control && !repeat && down) {
|
||||||
if (shift) {
|
if (shift || im->legacy_paste) {
|
||||||
// inject the text as input events
|
// inject the text as input events
|
||||||
clipboard_paste(controller);
|
clipboard_paste(controller);
|
||||||
} else {
|
} else {
|
||||||
@@ -504,6 +505,11 @@ input_manager_process_key(struct input_manager *im,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ctrl && !shift && keycode == SDLK_v && down && !repeat) {
|
if (ctrl && !shift && keycode == SDLK_v && down && !repeat) {
|
||||||
|
if (im->legacy_paste) {
|
||||||
|
// inject the text as input events
|
||||||
|
clipboard_paste(controller);
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Synchronize the computer clipboard to the device clipboard before
|
// Synchronize the computer clipboard to the device clipboard before
|
||||||
// sending Ctrl+v, to allow seamless copy-paste.
|
// sending Ctrl+v, to allow seamless copy-paste.
|
||||||
set_device_clipboard(controller, false);
|
set_device_clipboard(controller, false);
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ struct input_manager {
|
|||||||
bool control;
|
bool control;
|
||||||
bool forward_key_repeat;
|
bool forward_key_repeat;
|
||||||
bool prefer_text;
|
bool prefer_text;
|
||||||
|
bool legacy_paste;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
unsigned data[SC_MAX_SHORTCUT_MODS];
|
unsigned data[SC_MAX_SHORTCUT_MODS];
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
#if defined (__WINDOWS__) && ! defined (WINDOWS_NOCONSOLE)
|
#if defined (__WINDOWS__) && ! defined (WINDOWS_NOCONSOLE)
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
fprintf(stderr, "Press any key to continue...\n");
|
fprintf(stderr, "Press Enter to continue...\n");
|
||||||
getchar();
|
getchar();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -361,12 +361,14 @@ recorder_push(struct recorder *recorder, const AVPacket *packet) {
|
|||||||
|
|
||||||
if (recorder->failed) {
|
if (recorder->failed) {
|
||||||
// reject any new packet (this will stop the stream)
|
// reject any new packet (this will stop the stream)
|
||||||
|
mutex_unlock(recorder->mutex);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct record_packet *rec = record_packet_new(packet);
|
struct record_packet *rec = record_packet_new(packet);
|
||||||
if (!rec) {
|
if (!rec) {
|
||||||
LOGC("Could not allocate record packet");
|
LOGC("Could not allocate record packet");
|
||||||
|
mutex_unlock(recorder->mutex);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ struct scrcpy_options {
|
|||||||
bool force_adb_forward;
|
bool force_adb_forward;
|
||||||
bool disable_screensaver;
|
bool disable_screensaver;
|
||||||
bool forward_key_repeat;
|
bool forward_key_repeat;
|
||||||
|
bool legacy_paste;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SCRCPY_OPTIONS_DEFAULT { \
|
#define SCRCPY_OPTIONS_DEFAULT { \
|
||||||
@@ -123,6 +124,7 @@ struct scrcpy_options {
|
|||||||
.force_adb_forward = false, \
|
.force_adb_forward = false, \
|
||||||
.disable_screensaver = false, \
|
.disable_screensaver = false, \
|
||||||
.forward_key_repeat = true, \
|
.forward_key_repeat = true, \
|
||||||
|
.legacy_paste = false, \
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ enable_tunnel_forward_any_port(struct server *server,
|
|||||||
|
|
||||||
if (port < port_range.last) {
|
if (port < port_range.last) {
|
||||||
LOGW("Could not forward port %" PRIu16", retrying on %" PRIu16,
|
LOGW("Could not forward port %" PRIu16", retrying on %" PRIu16,
|
||||||
port, port + 1);
|
port, (uint16_t) (port + 1));
|
||||||
port++;
|
port++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ struct video_buffer;
|
|||||||
|
|
||||||
struct stream {
|
struct stream {
|
||||||
socket_t socket;
|
socket_t socket;
|
||||||
struct video_buffer *video_buffer;
|
|
||||||
SDL_Thread *thread;
|
SDL_Thread *thread;
|
||||||
struct decoder *decoder;
|
struct decoder *decoder;
|
||||||
struct recorder *recorder;
|
struct recorder *recorder;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// for portability
|
// for portability (kill, readlink, strdup, strtok_r)
|
||||||
#define _POSIX_SOURCE // for kill()
|
#define _POSIX_C_SOURCE 200809L
|
||||||
#define _BSD_SOURCE // for readlink()
|
#define _BSD_SOURCE
|
||||||
|
|
||||||
// modern glibc will complain without this
|
// modern glibc will complain without this
|
||||||
#define _DEFAULT_SOURCE
|
#define _DEFAULT_SOURCE
|
||||||
|
|||||||
@@ -19,6 +19,9 @@ allprojects {
|
|||||||
google()
|
google()
|
||||||
jcenter()
|
jcenter()
|
||||||
}
|
}
|
||||||
|
tasks.withType(JavaCompile) {
|
||||||
|
options.compilerArgs << "-Xlint:deprecation"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
task clean(type: Delete) {
|
task clean(type: Delete) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
set -e
|
set -e
|
||||||
url="$1"
|
url="$1"
|
||||||
sum="$2"
|
sum="$2"
|
||||||
|
|||||||
2
run
2
run
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
# Run scrcpy generated in the specified BUILDDIR.
|
# Run scrcpy generated in the specified BUILDDIR.
|
||||||
#
|
#
|
||||||
# This provides the same feature as "ninja run", except that it is possible to
|
# This provides the same feature as "ninja run", except that it is possible to
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
SCRCPY_SERVER_PATH="$MESON_BUILD_ROOT/server/scrcpy-server" "$MESON_BUILD_ROOT/app/scrcpy"
|
SCRCPY_SERVER_PATH="$MESON_BUILD_ROOT/server/scrcpy-server" "$MESON_BUILD_ROOT/app/scrcpy"
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 29
|
compileSdkVersion 30
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "com.genymobile.scrcpy"
|
applicationId "com.genymobile.scrcpy"
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 29
|
targetSdkVersion 30
|
||||||
versionCode 19
|
versionCode 19
|
||||||
versionName "1.16"
|
versionName "1.16"
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
#
|
#
|
||||||
# This script generates the scrcpy binary "manually" (without gradle).
|
# This script generates the scrcpy binary "manually" (without gradle).
|
||||||
#
|
#
|
||||||
@@ -14,8 +14,8 @@ set -e
|
|||||||
SCRCPY_DEBUG=false
|
SCRCPY_DEBUG=false
|
||||||
SCRCPY_VERSION_NAME=1.16
|
SCRCPY_VERSION_NAME=1.16
|
||||||
|
|
||||||
PLATFORM=${ANDROID_PLATFORM:-29}
|
PLATFORM=${ANDROID_PLATFORM:-30}
|
||||||
BUILD_TOOLS=${ANDROID_BUILD_TOOLS:-29.0.2}
|
BUILD_TOOLS=${ANDROID_BUILD_TOOLS:-30.0.0}
|
||||||
|
|
||||||
BUILD_DIR="$(realpath ${BUILD_DIR:-build_manual})"
|
BUILD_DIR="$(realpath ${BUILD_DIR:-build_manual})"
|
||||||
CLASSES_DIR="$BUILD_DIR/classes"
|
CLASSES_DIR="$BUILD_DIR/classes"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
# Wrapper script to invoke gradle from meson
|
# Wrapper script to invoke gradle from meson
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
|||||||
@@ -78,7 +78,9 @@ public final class CleanUp {
|
|||||||
|
|
||||||
if (restoreNormalPowerMode) {
|
if (restoreNormalPowerMode) {
|
||||||
Ln.i("Restoring normal power mode");
|
Ln.i("Restoring normal power mode");
|
||||||
Device.setScreenPowerMode(Device.POWER_MODE_NORMAL);
|
if (Device.isScreenOn()) {
|
||||||
|
Device.setScreenPowerMode(Device.POWER_MODE_NORMAL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,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.injectKeycode(KeyEvent.KEYCODE_POWER);
|
||||||
|
|
||||||
// dirty hack
|
// dirty hack
|
||||||
@@ -105,13 +105,13 @@ public class Controller {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ControlMessage.TYPE_EXPAND_NOTIFICATION_PANEL:
|
case ControlMessage.TYPE_EXPAND_NOTIFICATION_PANEL:
|
||||||
device.expandNotificationPanel();
|
Device.expandNotificationPanel();
|
||||||
break;
|
break;
|
||||||
case ControlMessage.TYPE_COLLAPSE_NOTIFICATION_PANEL:
|
case ControlMessage.TYPE_COLLAPSE_NOTIFICATION_PANEL:
|
||||||
device.collapsePanels();
|
Device.collapsePanels();
|
||||||
break;
|
break;
|
||||||
case ControlMessage.TYPE_GET_CLIPBOARD:
|
case ControlMessage.TYPE_GET_CLIPBOARD:
|
||||||
String clipboardText = device.getClipboardText();
|
String clipboardText = Device.getClipboardText();
|
||||||
if (clipboardText != null) {
|
if (clipboardText != null) {
|
||||||
sender.pushClipboardText(clipboardText);
|
sender.pushClipboardText(clipboardText);
|
||||||
}
|
}
|
||||||
@@ -130,7 +130,7 @@ public class Controller {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ControlMessage.TYPE_ROTATE_DEVICE:
|
case ControlMessage.TYPE_ROTATE_DEVICE:
|
||||||
device.rotateDevice();
|
Device.rotateDevice();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// do nothing
|
// do nothing
|
||||||
@@ -248,7 +248,7 @@ public class Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean pressBackOrTurnScreenOn() {
|
private boolean pressBackOrTurnScreenOn() {
|
||||||
int keycode = device.isScreenOn() ? KeyEvent.KEYCODE_BACK : KeyEvent.KEYCODE_POWER;
|
int keycode = Device.isScreenOn() ? KeyEvent.KEYCODE_BACK : KeyEvent.KEYCODE_POWER;
|
||||||
if (keepPowerModeOff && keycode == KeyEvent.KEYCODE_POWER) {
|
if (keepPowerModeOff && keycode == KeyEvent.KEYCODE_POWER) {
|
||||||
schedulePowerModeOff();
|
schedulePowerModeOff();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ public final class Device {
|
|||||||
public static final int POWER_MODE_OFF = SurfaceControl.POWER_MODE_OFF;
|
public static final int POWER_MODE_OFF = SurfaceControl.POWER_MODE_OFF;
|
||||||
public static final int POWER_MODE_NORMAL = SurfaceControl.POWER_MODE_NORMAL;
|
public static final int POWER_MODE_NORMAL = SurfaceControl.POWER_MODE_NORMAL;
|
||||||
|
|
||||||
|
private static final ServiceManager SERVICE_MANAGER = new ServiceManager();
|
||||||
|
|
||||||
public interface RotationListener {
|
public interface RotationListener {
|
||||||
void onRotationChanged(int rotation);
|
void onRotationChanged(int rotation);
|
||||||
}
|
}
|
||||||
@@ -33,8 +35,6 @@ public final class Device {
|
|||||||
void onClipboardTextChanged(String text);
|
void onClipboardTextChanged(String text);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final ServiceManager serviceManager = new ServiceManager();
|
|
||||||
|
|
||||||
private ScreenInfo screenInfo;
|
private ScreenInfo screenInfo;
|
||||||
private RotationListener rotationListener;
|
private RotationListener rotationListener;
|
||||||
private ClipboardListener clipboardListener;
|
private ClipboardListener clipboardListener;
|
||||||
@@ -54,9 +54,9 @@ public final class Device {
|
|||||||
|
|
||||||
public Device(Options options) {
|
public Device(Options options) {
|
||||||
displayId = options.getDisplayId();
|
displayId = options.getDisplayId();
|
||||||
DisplayInfo displayInfo = serviceManager.getDisplayManager().getDisplayInfo(displayId);
|
DisplayInfo displayInfo = SERVICE_MANAGER.getDisplayManager().getDisplayInfo(displayId);
|
||||||
if (displayInfo == null) {
|
if (displayInfo == null) {
|
||||||
int[] displayIds = serviceManager.getDisplayManager().getDisplayIds();
|
int[] displayIds = SERVICE_MANAGER.getDisplayManager().getDisplayIds();
|
||||||
throw new InvalidDisplayIdException(displayId, displayIds);
|
throw new InvalidDisplayIdException(displayId, displayIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ public final class Device {
|
|||||||
screenInfo = ScreenInfo.computeScreenInfo(displayInfo, options.getCrop(), options.getMaxSize(), options.getLockedVideoOrientation());
|
screenInfo = ScreenInfo.computeScreenInfo(displayInfo, options.getCrop(), options.getMaxSize(), options.getLockedVideoOrientation());
|
||||||
layerStack = displayInfo.getLayerStack();
|
layerStack = displayInfo.getLayerStack();
|
||||||
|
|
||||||
serviceManager.getWindowManager().registerRotationWatcher(new IRotationWatcher.Stub() {
|
SERVICE_MANAGER.getWindowManager().registerRotationWatcher(new IRotationWatcher.Stub() {
|
||||||
@Override
|
@Override
|
||||||
public void onRotationChanged(int rotation) {
|
public void onRotationChanged(int rotation) {
|
||||||
synchronized (Device.this) {
|
synchronized (Device.this) {
|
||||||
@@ -81,7 +81,7 @@ public final class Device {
|
|||||||
|
|
||||||
if (options.getControl()) {
|
if (options.getControl()) {
|
||||||
// If control is enabled, synchronize Android clipboard to the computer automatically
|
// If control is enabled, synchronize Android clipboard to the computer automatically
|
||||||
ClipboardManager clipboardManager = serviceManager.getClipboardManager();
|
ClipboardManager clipboardManager = SERVICE_MANAGER.getClipboardManager();
|
||||||
if (clipboardManager != null) {
|
if (clipboardManager != null) {
|
||||||
clipboardManager.addPrimaryClipChangedListener(new IOnPrimaryClipChangedListener.Stub() {
|
clipboardManager.addPrimaryClipChangedListener(new IOnPrimaryClipChangedListener.Stub() {
|
||||||
@Override
|
@Override
|
||||||
@@ -166,7 +166,7 @@ public final class Device {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return serviceManager.getInputManager().injectInputEvent(inputEvent, mode);
|
return SERVICE_MANAGER.getInputManager().injectInputEvent(inputEvent, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean injectEvent(InputEvent event) {
|
public boolean injectEvent(InputEvent event) {
|
||||||
@@ -184,8 +184,8 @@ public final class Device {
|
|||||||
return injectKeyEvent(KeyEvent.ACTION_DOWN, keyCode, 0, 0) && injectKeyEvent(KeyEvent.ACTION_UP, keyCode, 0, 0);
|
return injectKeyEvent(KeyEvent.ACTION_DOWN, keyCode, 0, 0) && injectKeyEvent(KeyEvent.ACTION_UP, keyCode, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isScreenOn() {
|
public static boolean isScreenOn() {
|
||||||
return serviceManager.getPowerManager().isScreenOn();
|
return SERVICE_MANAGER.getPowerManager().isScreenOn();
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void setRotationListener(RotationListener rotationListener) {
|
public synchronized void setRotationListener(RotationListener rotationListener) {
|
||||||
@@ -196,16 +196,16 @@ public final class Device {
|
|||||||
this.clipboardListener = clipboardListener;
|
this.clipboardListener = clipboardListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void expandNotificationPanel() {
|
public static void expandNotificationPanel() {
|
||||||
serviceManager.getStatusBarManager().expandNotificationsPanel();
|
SERVICE_MANAGER.getStatusBarManager().expandNotificationsPanel();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void collapsePanels() {
|
public static void collapsePanels() {
|
||||||
serviceManager.getStatusBarManager().collapsePanels();
|
SERVICE_MANAGER.getStatusBarManager().collapsePanels();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getClipboardText() {
|
public static String getClipboardText() {
|
||||||
ClipboardManager clipboardManager = serviceManager.getClipboardManager();
|
ClipboardManager clipboardManager = SERVICE_MANAGER.getClipboardManager();
|
||||||
if (clipboardManager == null) {
|
if (clipboardManager == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -217,7 +217,7 @@ public final class Device {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean setClipboardText(String text) {
|
public boolean setClipboardText(String text) {
|
||||||
ClipboardManager clipboardManager = serviceManager.getClipboardManager();
|
ClipboardManager clipboardManager = SERVICE_MANAGER.getClipboardManager();
|
||||||
if (clipboardManager == null) {
|
if (clipboardManager == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -252,8 +252,8 @@ public final class Device {
|
|||||||
/**
|
/**
|
||||||
* Disable auto-rotation (if enabled), set the screen rotation and re-enable auto-rotation (if it was enabled).
|
* Disable auto-rotation (if enabled), set the screen rotation and re-enable auto-rotation (if it was enabled).
|
||||||
*/
|
*/
|
||||||
public void rotateDevice() {
|
public static void rotateDevice() {
|
||||||
WindowManager wm = serviceManager.getWindowManager();
|
WindowManager wm = SERVICE_MANAGER.getWindowManager();
|
||||||
|
|
||||||
boolean accelerometerRotation = !wm.isRotationFrozen();
|
boolean accelerometerRotation = !wm.isRotationFrozen();
|
||||||
|
|
||||||
@@ -270,7 +270,7 @@ public final class Device {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ContentProvider createSettingsProvider() {
|
public static ContentProvider createSettingsProvider() {
|
||||||
return serviceManager.getActivityManager().createSettingsProvider();
|
return SERVICE_MANAGER.getActivityManager().createSettingsProvider();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ public final class Server {
|
|||||||
boolean mustDisableShowTouchesOnCleanUp = false;
|
boolean mustDisableShowTouchesOnCleanUp = false;
|
||||||
int restoreStayOn = -1;
|
int restoreStayOn = -1;
|
||||||
if (options.getShowTouches() || options.getStayAwake()) {
|
if (options.getShowTouches() || options.getStayAwake()) {
|
||||||
try (ContentProvider settings = device.createSettingsProvider()) {
|
try (ContentProvider settings = Device.createSettingsProvider()) {
|
||||||
if (options.getShowTouches()) {
|
if (options.getShowTouches()) {
|
||||||
String oldValue = settings.getAndPutValue(ContentProvider.TABLE_SYSTEM, "show_touches", "1");
|
String oldValue = settings.getAndPutValue(ContentProvider.TABLE_SYSTEM, "show_touches", "1");
|
||||||
// If "show touches" was disabled, it must be disabled back on clean up
|
// If "show touches" was disabled, it must be disabled back on clean up
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ public final class Workarounds {
|
|||||||
// not instantiable
|
// not instantiable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public static void prepareMainLooper() {
|
public static void prepareMainLooper() {
|
||||||
// Some devices internally create a Handler when creating an input Surface, causing an exception:
|
// Some devices internally create a Handler when creating an input Surface, causing an exception:
|
||||||
// "Can't create handler inside thread that has not called Looper.prepare()"
|
// "Can't create handler inside thread that has not called Looper.prepare()"
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ public class ContentProvider implements Closeable {
|
|||||||
private final IBinder token;
|
private final IBinder token;
|
||||||
|
|
||||||
private Method callMethod;
|
private Method callMethod;
|
||||||
private boolean callMethodLegacy;
|
private int callMethodVersion;
|
||||||
|
|
||||||
ContentProvider(ActivityManager manager, Object provider, String name, IBinder token) {
|
ContentProvider(ActivityManager manager, Object provider, String name, IBinder token) {
|
||||||
this.manager = manager;
|
this.manager = manager;
|
||||||
@@ -46,12 +46,20 @@ public class ContentProvider implements Closeable {
|
|||||||
|
|
||||||
private Method getCallMethod() throws NoSuchMethodException {
|
private Method getCallMethod() throws NoSuchMethodException {
|
||||||
if (callMethod == null) {
|
if (callMethod == null) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
callMethod = provider.getClass().getMethod("call", String.class, String.class, String.class, String.class, Bundle.class);
|
callMethod = provider.getClass()
|
||||||
|
.getMethod("call", String.class, String.class, String.class, String.class, String.class, Bundle.class);
|
||||||
|
callMethodVersion = 0;
|
||||||
} catch (NoSuchMethodException e) {
|
} catch (NoSuchMethodException e) {
|
||||||
// old version
|
// old versions
|
||||||
callMethod = provider.getClass().getMethod("call", String.class, String.class, String.class, Bundle.class);
|
try {
|
||||||
callMethodLegacy = true;
|
callMethod = provider.getClass().getMethod("call", String.class, String.class, String.class, String.class, Bundle.class);
|
||||||
|
callMethodVersion = 1;
|
||||||
|
} catch (NoSuchMethodException e2) {
|
||||||
|
callMethod = provider.getClass().getMethod("call", String.class, String.class, String.class, Bundle.class);
|
||||||
|
callMethodVersion = 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return callMethod;
|
return callMethod;
|
||||||
@@ -61,10 +69,16 @@ public class ContentProvider implements Closeable {
|
|||||||
try {
|
try {
|
||||||
Method method = getCallMethod();
|
Method method = getCallMethod();
|
||||||
Object[] args;
|
Object[] args;
|
||||||
if (!callMethodLegacy) {
|
switch (callMethodVersion) {
|
||||||
args = new Object[]{ServiceManager.PACKAGE_NAME, "settings", callMethod, arg, extras};
|
case 0:
|
||||||
} else {
|
args = new Object[]{ServiceManager.PACKAGE_NAME, null, "settings", callMethod, arg, extras};
|
||||||
args = new Object[]{ServiceManager.PACKAGE_NAME, callMethod, arg, extras};
|
break;
|
||||||
|
case 1:
|
||||||
|
args = new Object[]{ServiceManager.PACKAGE_NAME, "settings", callMethod, arg, extras};
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
args = new Object[]{ServiceManager.PACKAGE_NAME, callMethod, arg, extras};
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return (Bundle) method.invoke(provider, args);
|
return (Bundle) method.invoke(provider, args);
|
||||||
} catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
|
} catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
|
||||||
|
|||||||
Reference in New Issue
Block a user