Compare commits

..

7 Commits

Author SHA1 Message Date
4d98160984 Use DisplayManagerGlobal instance
Use the client instance to communicate with the DisplayManager server.

Fixes #3446 <https://github.com/Genymobile/scrcpy/issues/3446>
2022-08-16 23:52:08 +02:00
d23b3e88a4 Replace '%g' by '%f' as printf format
For some reason, '%g' does not work correctly with MinGW.

Refs #3369 <https://github.com/Genymobile/scrcpy/pull/3369>
PR #3399 <https://github.com/Genymobile/scrcpy/pull/3399>
2022-08-03 23:25:09 +02:00
a47848f304 Detect Windows using _WIN32 in network util
For consistency, always use _WIN32 instead of a mix of __WINDOWS__ and
_WIN32.
2022-07-27 14:54:27 +02:00
db8c1ce8e1 Fix protocol documentation in comments
Flags were in the correct order in the schema, but their description
were reversed.
2022-07-20 11:41:04 +02:00
4aeb78ece2 Add missing allocation failure check 2022-07-19 12:17:02 +02:00
396e4bd925 Add missing LOG_OOM() on malloc failure 2022-07-19 12:15:06 +02:00
7f2f5950f2 Remove useless dependencies reference
There is no libs/ directory with local jar files.
2022-06-20 21:23:05 +02:00
15 changed files with 30 additions and 263 deletions

View File

@ -401,6 +401,7 @@ sc_adb_list_devices(struct sc_intr *intr, unsigned flags,
#define BUFSIZE 65536
char *buf = malloc(BUFSIZE);
if (!buf) {
LOG_OOM();
return false;
}
@ -434,7 +435,6 @@ sc_adb_list_devices(struct sc_intr *intr, unsigned flags,
"Please report an issue.");
return false;
}
#undef BUFSIZE
// It is parsed as a NUL-terminated string
buf[r] = '\0';
@ -713,95 +713,3 @@ sc_adb_get_device_ip(struct sc_intr *intr, const char *serial, unsigned flags) {
return sc_adb_parse_device_ip(buf);
}
char *
sc_adb_get_installed_apk_path(struct sc_intr *intr, const char *serial,
unsigned flags) {
assert(serial);
const char *const argv[] =
SC_ADB_COMMAND("-s", serial, "shell", "pm", "list", "package", "-f",
SC_ANDROID_PACKAGE);
sc_pipe pout;
sc_pid pid = sc_adb_execute_p(argv, flags, &pout);
if (pid == SC_PROCESS_NONE) {
LOGD("Could not execute \"pm list packages\"");
return NULL;
}
// "pm list packages -f <package>" output should contain only one line, so
// the output should be short
char buf[1024];
ssize_t r = sc_pipe_read_all_intr(intr, pid, pout, buf, sizeof(buf) - 1);
sc_pipe_close(pout);
bool ok = process_check_success_intr(intr, pid, "pm list packages", flags);
if (!ok) {
return NULL;
}
if (r == -1) {
return NULL;
}
assert((size_t) r < sizeof(buf));
if (r == sizeof(buf) - 1) {
// The implementation assumes that the output of "pm list packages"
// fits in the buffer in a single pass
LOGW("Result of \"pm list package\" does not fit in 1Kb. "
"Please report an issue.");
return NULL;
}
// It is parsed as a NUL-terminated string
buf[r] = '\0';
return sc_adb_parse_installed_apk_path(buf);
}
char *
sc_adb_get_installed_apk_version(struct sc_intr *intr, const char *serial,
unsigned flags) {
assert(serial);
const char *const argv[] =
SC_ADB_COMMAND("-s", serial, "shell", "dumpsys", "package",
SC_ANDROID_PACKAGE);
sc_pipe pout;
sc_pid pid = sc_adb_execute_p(argv, flags, &pout);
if (pid == SC_PROCESS_NONE) {
LOGD("Could not execute \"dumpsys package\"");
return NULL;
}
// "dumpsys package" output can be huge (e.g. 16k), but versionName is at
// the beginning, typically in the first 1024 bytes (64k should be enough
// for the whole output anyway)
#define BUFSIZE 65536
char *buf = malloc(BUFSIZE);
if (!buf) {
return false;
}
ssize_t r = sc_pipe_read_all_intr(intr, pid, pout, buf, BUFSIZE - 1);
sc_pipe_close(pout);
bool ok = process_check_success_intr(intr, pid, "dumpsys package", flags);
if (!ok) {
return NULL;
}
if (r == -1) {
return NULL;
}
assert((size_t) r < BUFSIZE);
#undef BUFSIZE
// if r == sizeof(buf), then the output is truncated, but we don't care,
// versionName is at the beginning in practice, and is unlikely to be
// truncated at 64k
// It is parsed as a NUL-terminated string
buf[r] = '\0';
return sc_adb_parse_installed_apk_version(buf);
}

View File

@ -15,8 +15,6 @@
#define SC_ADB_SILENT (SC_ADB_NO_STDOUT | SC_ADB_NO_STDERR | SC_ADB_NO_LOGERR)
#define SC_ANDROID_PACKAGE "com.genymobile.scrcpy"
const char *
sc_adb_get_executable(void);
@ -116,18 +114,4 @@ sc_adb_getprop(struct sc_intr *intr, const char *serial, const char *prop,
char *
sc_adb_get_device_ip(struct sc_intr *intr, const char *serial, unsigned flags);
/**
* Return the path of the installed APK for com.genymobile.scrcpy (if any)
*/
char *
sc_adb_get_installed_apk_path(struct sc_intr *intr, const char *serial,
unsigned flags);
/**
* Return the version of the installed APK for com.genymobile.scrcpy (if any)
*/
char *
sc_adb_get_installed_apk_version(struct sc_intr *intr, const char *serial,
unsigned flags);
#endif

View File

@ -225,62 +225,3 @@ sc_adb_parse_device_ip(char *str) {
return NULL;
}
char *
sc_adb_parse_installed_apk_path(char *str) {
// str is expected to look like:
// "package:/data/app/.../base.apk=com.genymobile.scrcpy"
// ^^^^^^^^^^^^^^^^^^^^^^
// We want to extract the path (which may contain '=', even in practice)
if (strncmp(str, "package:", 8)) {
// Does not start with "package:"
return NULL;
}
char *s = str + 8;
size_t len = strcspn(s, " \r\n");
s[len] = '\0';
char *p = strrchr(s, '=');
if (!p) {
// No '=' found
return NULL;
}
// Truncate at the last '='
*p = '\0';
return strdup(s);
}
char *
sc_adb_parse_installed_apk_version(const char *str) {
// str is the (beginning of the) output of `dumpsys package`
// We want to extract the version string from a line starting with 4 spaces
// then `versionName=` then the version string.
#define VERSION_NAME_PREFIX "\n versionName="
char *s = strstr(str, VERSION_NAME_PREFIX);
if (!s) {
// Not found
return NULL;
}
s+= sizeof(VERSION_NAME_PREFIX) - 1;
size_t len = strspn(s, "0123456789.");
if (!len) {
LOGW("Unexpected version name with no value");
return NULL;
}
char *version = malloc(len + 1);
if (!version) {
return NULL;
}
memcpy(version, s, len);
version[len] = '\0';
return version;
}

View File

@ -27,24 +27,4 @@ sc_adb_parse_devices(char *str, struct sc_vec_adb_devices *out_vec);
char *
sc_adb_parse_device_ip(char *str);
/**
* Parse the package path from the output of
* `adb shell pm list packages -f <package>`
*
* The parameter must be a NUL-terminated string.
*
* Warning: this function modifies the buffer for optimization purposes.
*/
char *
sc_adb_parse_installed_apk_path(char *str);
/**
* Parse the package version from the output of
* `adb shell dumpsys package <package>`
*
* The parameter must be a NUL-terminated string.
*/
char *
sc_adb_parse_installed_apk_version(const char *str);
#endif

View File

@ -98,7 +98,7 @@ sc_clock_update(struct sc_clock *clock, sc_tick system, sc_tick stream) {
sc_clock_estimate(clock, &clock->slope, &clock->offset);
#ifndef SC_CLOCK_NDEBUG
LOGD("Clock estimation: %g * pts + %" PRItick,
LOGD("Clock estimation: %f * pts + %" PRItick,
clock->slope, clock->offset);
#endif
}

View File

@ -170,7 +170,7 @@ sc_control_msg_log(const struct sc_control_msg *msg) {
if (id == POINTER_ID_MOUSE || id == POINTER_ID_VIRTUAL_FINGER) {
// string pointer id
LOG_CMSG("touch [id=%s] %-4s position=%" PRIi32 ",%" PRIi32
" pressure=%g buttons=%06lx",
" pressure=%f buttons=%06lx",
id == POINTER_ID_MOUSE ? "mouse" : "vfinger",
MOTIONEVENT_ACTION_LABEL(action),
msg->inject_touch_event.position.point.x,
@ -180,7 +180,7 @@ sc_control_msg_log(const struct sc_control_msg *msg) {
} else {
// numeric pointer id
LOG_CMSG("touch [id=%" PRIu64_ "] %-4s position=%" PRIi32 ",%"
PRIi32 " pressure=%g buttons=%06lx",
PRIi32 " pressure=%f buttons=%06lx",
id,
MOTIONEVENT_ACTION_LABEL(action),
msg->inject_touch_event.position.point.x,

View File

@ -37,8 +37,8 @@ sc_demuxer_recv_packet(struct sc_demuxer *demuxer, AVPacket *packet) {
// CK...... ........ ........ ........ ........ ........ ........ ........
// ^^<------------------------------------------------------------------->
// || PTS
// | `- config packet
// `-- key frame
// | `- key frame
// `-- config packet
uint8_t header[SC_PACKET_HEADER_SIZE];
ssize_t r = net_recv_all(demuxer->socket, header, SC_PACKET_HEADER_SIZE);

View File

@ -160,8 +160,6 @@ execute_server(struct sc_server *server,
const char *serial = server->serial;
assert(serial);
fprintf(stderr, "=== [%s]\n", sc_adb_get_installed_apk_version(&server->intr, serial, 0));
const char *cmd[128];
unsigned count = 0;
cmd[count++] = sc_adb_get_executable();

View File

@ -23,6 +23,11 @@ read_string(libusb_device_handle *handle, uint8_t desc_index) {
// When non-negative, 'result' contains the number of bytes written
char *s = malloc(result + 1);
if (!s) {
LOG_OOM();
return NULL;
}
memcpy(s, buffer, result);
s[result] = '\0';
return s;

View File

@ -3,11 +3,10 @@
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <SDL2/SDL_platform.h>
#include "log.h"
#ifdef __WINDOWS__
#ifdef _WIN32
# include <ws2tcpip.h>
typedef int socklen_t;
typedef SOCKET sc_raw_socket;
@ -29,7 +28,7 @@
bool
net_init(void) {
#ifdef __WINDOWS__
#ifdef _WIN32
WSADATA wsa;
int res = WSAStartup(MAKEWORD(2, 2), &wsa) < 0;
if (res < 0) {
@ -42,14 +41,14 @@ net_init(void) {
void
net_cleanup(void) {
#ifdef __WINDOWS__
#ifdef _WIN32
WSACleanup();
#endif
}
static inline sc_socket
wrap(sc_raw_socket sock) {
#ifdef __WINDOWS__
#ifdef _WIN32
if (sock == INVALID_SOCKET) {
return SC_SOCKET_NONE;
}
@ -72,7 +71,7 @@ wrap(sc_raw_socket sock) {
static inline sc_raw_socket
unwrap(sc_socket socket) {
#ifdef __WINDOWS__
#ifdef _WIN32
if (socket == SC_SOCKET_NONE) {
return INVALID_SOCKET;
}
@ -248,7 +247,7 @@ net_interrupt(sc_socket socket) {
sc_raw_socket raw_sock = unwrap(socket);
#ifdef __WINDOWS__
#ifdef _WIN32
if (!atomic_flag_test_and_set(&socket->closed)) {
return !closesocket(raw_sock);
}
@ -262,7 +261,7 @@ bool
net_close(sc_socket socket) {
sc_raw_socket raw_sock = unwrap(socket);
#ifdef __WINDOWS__
#ifdef _WIN32
bool ret = true;
if (!atomic_flag_test_and_set(&socket->closed)) {
ret = !closesocket(raw_sock);

View File

@ -5,9 +5,8 @@
#include <stdbool.h>
#include <stdint.h>
#include <SDL2/SDL_platform.h>
#ifdef __WINDOWS__
#ifdef _WIN32
# include <winsock2.h>
# include <stdatomic.h>
@ -17,7 +16,7 @@
atomic_flag closed;
} *sc_socket;
#else // not __WINDOWS__
#else // not _WIN32
# include <sys/socket.h>
# define SC_SOCKET_NONE -1

View File

@ -241,54 +241,6 @@ static void test_get_ip_truncated(void) {
assert(!ip);
}
static void test_apk_path(void) {
char str[] = "package:/data/app/~~71mguyc6p-kNjQdNaNkToA==/com.genymobile."
"scrcpy-l6fiqqUSU7Ok7QLg-rIyJA==/base.apk=com.genymobile."
"scrcpy\n";
const char *expected = "/data/app/~~71mguyc6p-kNjQdNaNkToA==/com.genymobile"
".scrcpy-l6fiqqUSU7Ok7QLg-rIyJA==/base.apk";
char *path = sc_adb_parse_installed_apk_path(str);
assert(!strcmp(path, expected));
free(path);
}
static void test_apk_path_invalid(void) {
// Does not start with "package:"
char str[] = "garbage:/data/app/~~71mguyc6p-kNjQdNaNkToA==/com.genymobile."
"scrcpy-l6fiqqUSU7Ok7QLg-rIyJA==/base.apk=com.genymobile."
"scrcpy\n";
char *path = sc_adb_parse_installed_apk_path(str);
assert(!path);
}
static void test_apk_version(void) {
char str[] =
"Key Set Manager:\n"
" [com.genymobile.scrcpy]\n"
" Signing KeySets: 128\n"
"\n"
"Packages:\n"
" Package [com.genymobile.scrcpy] (89abcdef):\n"
" userId=12345\n"
" pkg=Package{012345 com.genymobile.scrcpy}\n"
" codePath=/data/app/~~abcdef==/com.genymobile.scrcpy-012345==\n"
" resourcePath=/data/app/~~abcdef==/com.genymobile.scrcpy-013245==\n"
" primaryCpuAbi=null\n"
" secondaryCpuAbi=null\n"
" versionCode=12400 minSdk=21 targetSdk=31\n"
" versionName=1.24\n"
" splits=[base]\n"
" apkSigningVersion=2\n"
" applicationInfo=ApplicationInfo{012345 com.genymobile.scrcpy}\n";
const char *expected = "1.24";
char *version = sc_adb_parse_installed_apk_version(str);
assert(!strcmp(version, expected));
free(version);
}
int main(int argc, char *argv[]) {
(void) argc;
(void) argv;
@ -311,9 +263,5 @@ int main(int argc, char *argv[]) {
test_get_ip_no_wlan_without_eol();
test_get_ip_truncated();
test_apk_path();
test_apk_path_invalid();
test_apk_version();
return 0;
}

View File

@ -19,7 +19,6 @@ android {
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
testImplementation 'junit:junit:4.13.1'
}

View File

@ -3,12 +3,10 @@ package com.genymobile.scrcpy.wrappers;
import com.genymobile.scrcpy.DisplayInfo;
import com.genymobile.scrcpy.Size;
import android.os.IInterface;
public final class DisplayManager {
private final IInterface manager;
private final Object manager; // instance of hidden class android.hardware.display.DisplayManagerGlobal
public DisplayManager(IInterface manager) {
public DisplayManager(Object manager) {
this.manager = manager;
}

View File

@ -50,6 +50,14 @@ public final class ServiceManager {
public DisplayManager getDisplayManager() {
if (displayManager == null) {
try {
Class<?> clazz = Class.forName("android.hardware.display.DisplayManagerGlobal");
Method getInstanceMethod = clazz.getDeclaredMethod("getInstance");
Object dmg = getInstanceMethod.invoke(null);
displayManager = new DisplayManager(dmg);
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
throw new AssertionError(e);
}
displayManager = new DisplayManager(getService("display", "android.hardware.display.IDisplayManager"));
}
return displayManager;