Compare commits

..

2 Commits

Author SHA1 Message Date
db85211653 apk_version 2022-06-09 15:39:39 +02:00
c0e20c86d6 apk_path 2022-06-09 15:13:47 +02:00
18 changed files with 29 additions and 216 deletions

View File

@ -188,7 +188,7 @@ conf.set_quoted('SCRCPY_VERSION', meson.project_version())
# the prefix used during configuration (meson --prefix=PREFIX) # the prefix used during configuration (meson --prefix=PREFIX)
conf.set_quoted('PREFIX', get_option('prefix')) conf.set_quoted('PREFIX', get_option('prefix'))
# build a "portable" version (with scrcpy-server.apk accessible from the same # build a "portable" version (with scrcpy-server accessible from the same
# directory as the executable) # directory as the executable)
conf.set('PORTABLE', get_option('portable')) conf.set('PORTABLE', get_option('portable'))

View File

@ -329,17 +329,6 @@ sc_adb_install(struct sc_intr *intr, const char *serial, const char *local,
return process_check_success_intr(intr, pid, "adb install", flags); return process_check_success_intr(intr, pid, "adb install", flags);
} }
bool
sc_adb_uninstall(struct sc_intr *intr, const char *serial, const char *pkg,
unsigned flags) {
assert(serial);
const char *const argv[] =
SC_ADB_COMMAND("-s", serial, "uninstall", pkg);
sc_pid pid = sc_adb_execute(argv, flags);
return process_check_success_intr(intr, pid, "adb uninstall", flags);
}
bool bool
sc_adb_tcpip(struct sc_intr *intr, const char *serial, uint16_t port, sc_adb_tcpip(struct sc_intr *intr, const char *serial, uint16_t port,
unsigned flags) { unsigned flags) {
@ -798,12 +787,10 @@ sc_adb_get_installed_apk_version(struct sc_intr *intr, const char *serial,
bool ok = process_check_success_intr(intr, pid, "dumpsys package", flags); bool ok = process_check_success_intr(intr, pid, "dumpsys package", flags);
if (!ok) { if (!ok) {
free(buf);
return NULL; return NULL;
} }
if (r == -1) { if (r == -1) {
free(buf);
return NULL; return NULL;
} }
@ -816,7 +803,5 @@ sc_adb_get_installed_apk_version(struct sc_intr *intr, const char *serial,
// It is parsed as a NUL-terminated string // It is parsed as a NUL-terminated string
buf[r] = '\0'; buf[r] = '\0';
char *version = sc_adb_parse_installed_apk_version(buf); return sc_adb_parse_installed_apk_version(buf);
free(buf);
return version;
} }

View File

@ -66,10 +66,6 @@ bool
sc_adb_install(struct sc_intr *intr, const char *serial, const char *local, sc_adb_install(struct sc_intr *intr, const char *serial, const char *local,
unsigned flags); unsigned flags);
bool
sc_adb_uninstall(struct sc_intr *intr, const char *serial, const char *pkg,
unsigned flags);
/** /**
* Execute `adb tcpip <port>` * Execute `adb tcpip <port>`
*/ */

View File

@ -57,8 +57,6 @@
#define OPT_NO_CLEANUP 1037 #define OPT_NO_CLEANUP 1037
#define OPT_PRINT_FPS 1038 #define OPT_PRINT_FPS 1038
#define OPT_NO_POWER_ON 1039 #define OPT_NO_POWER_ON 1039
#define OPT_INSTALL 1040
#define OPT_REINSTALL 1041
struct sc_option { struct sc_option {
char shortopt; char shortopt;
@ -209,12 +207,6 @@ static const struct sc_option options[] = {
.longopt = "help", .longopt = "help",
.text = "Print this help.", .text = "Print this help.",
}, },
{
.longopt_id = OPT_INSTALL,
.longopt = "install",
.text = "Install the server (via 'adb install') instead of just "
"pushing it (via 'adb push').",
},
{ {
.longopt_id = OPT_LEGACY_PASTE, .longopt_id = OPT_LEGACY_PASTE,
.longopt = "legacy-paste", .longopt = "legacy-paste",
@ -386,13 +378,6 @@ static const struct sc_option options[] = {
.argdesc = "format", .argdesc = "format",
.text = "Force recording format (either mp4 or mkv).", .text = "Force recording format (either mp4 or mkv).",
}, },
{
.longopt_id = OPT_REINSTALL,
.longopt = "reinstall",
.text = "Reinstall the server (via 'adb install'), even if the correct "
"version is already installed.\n"
"Implies --install.",
},
{ {
.longopt_id = OPT_RENDER_DRIVER, .longopt_id = OPT_RENDER_DRIVER,
.longopt = "render-driver", .longopt = "render-driver",
@ -1625,13 +1610,6 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
case OPT_PRINT_FPS: case OPT_PRINT_FPS:
opts->start_fps_counter = true; opts->start_fps_counter = true;
break; break;
case OPT_INSTALL:
opts->install = true;
break;
case OPT_REINSTALL:
opts->install = true;
opts->reinstall = true;
break;
case OPT_OTG: case OPT_OTG:
#ifdef HAVE_USB #ifdef HAVE_USB
opts->otg = true; opts->otg = true;

View File

@ -65,6 +65,4 @@ const struct scrcpy_options scrcpy_options_default = {
.cleanup = true, .cleanup = true,
.start_fps_counter = false, .start_fps_counter = false,
.power_on = true, .power_on = true,
.install = false,
.reinstall = false,
}; };

View File

@ -140,8 +140,6 @@ struct scrcpy_options {
bool cleanup; bool cleanup;
bool start_fps_counter; bool start_fps_counter;
bool power_on; bool power_on;
bool install;
bool reinstall;
}; };
extern const struct scrcpy_options scrcpy_options_default; extern const struct scrcpy_options scrcpy_options_default;

View File

@ -325,8 +325,6 @@ scrcpy(struct scrcpy_options *options) {
.tcpip_dst = options->tcpip_dst, .tcpip_dst = options->tcpip_dst,
.cleanup = options->cleanup, .cleanup = options->cleanup,
.power_on = options->power_on, .power_on = options->power_on,
.install = options->install,
.reinstall = options->reinstall,
}; };
static const struct sc_server_callbacks cbs = { static const struct sc_server_callbacks cbs = {

View File

@ -14,11 +14,10 @@
#include "util/process_intr.h" #include "util/process_intr.h"
#include "util/str.h" #include "util/str.h"
#define SC_SERVER_FILENAME "scrcpy-server.apk" #define SC_SERVER_FILENAME "scrcpy-server"
#define SC_SERVER_PACKAGE "com.genymobile.scrcpy"
#define SC_SERVER_PATH_DEFAULT PREFIX "/share/scrcpy/" SC_SERVER_FILENAME #define SC_SERVER_PATH_DEFAULT PREFIX "/share/scrcpy/" SC_SERVER_FILENAME
#define SC_DEVICE_SERVER_PATH "/data/local/tmp/scrcpy-server.apk" #define SC_DEVICE_SERVER_PATH "/data/local/tmp/scrcpy-server.jar"
static char * static char *
get_server_path(void) { get_server_path(void) {
@ -105,10 +104,7 @@ error:
} }
static bool static bool
push_server(struct sc_intr *intr, const char *serial, bool install, push_server(struct sc_intr *intr, const char *serial) {
bool reinstall) {
assert(install || !reinstall); // reinstall implies install
char *server_path = get_server_path(); char *server_path = get_server_path();
if (!server_path) { if (!server_path) {
return false; return false;
@ -118,28 +114,7 @@ push_server(struct sc_intr *intr, const char *serial, bool install,
free(server_path); free(server_path);
return false; return false;
} }
bool ok; bool ok = sc_adb_push(intr, serial, server_path, SC_DEVICE_SERVER_PATH, 0);
if (install) {
char *version = sc_adb_get_installed_apk_version(intr, serial, 0);
bool same_version = version && !strcmp(version, SCRCPY_VERSION);
free(version);
if (!reinstall && same_version) {
LOGI("Server " SCRCPY_VERSION " already installed");
ok = true;
} else {
LOGI("Installing server " SCRCPY_VERSION);
// If a server with a different signature is installed, or if a
// newer server is already installed, we must uninstall it first.
ok = sc_adb_uninstall(intr, serial, SC_SERVER_PACKAGE,
SC_ADB_SILENT);
(void) ok; // expected to fail if it is not installed
ok = sc_adb_install(intr, serial, server_path, 0);
}
} else {
ok = sc_adb_push(intr, serial, server_path, SC_DEVICE_SERVER_PATH, 0);
}
free(server_path); free(server_path);
return ok; return ok;
} }
@ -177,38 +152,6 @@ sc_server_sleep(struct sc_server *server, sc_tick deadline) {
return !stopped; return !stopped;
} }
static char *
get_classpath_cmd(struct sc_intr *intr, const char *serial, bool install) {
if (!install) {
// In push mode, the path is known statically
char *cp = strdup("CLASSPATH=" SC_DEVICE_SERVER_PATH);
if (!cp) {
LOG_OOM();
}
return cp;
}
char *apk_path = sc_adb_get_installed_apk_path(intr, serial, 0);
if (!apk_path) {
LOGE("Could not get device apk path");
return NULL;
}
#define PREFIX_SIZE (sizeof("CLASSPATH=") - 1)
size_t len = strlen(apk_path);
char *cp = malloc(PREFIX_SIZE + len + 1);
if (!cp) {
LOG_OOM();
free(apk_path);
return NULL;
}
memcpy(cp, "CLASSPATH=", PREFIX_SIZE);
memcpy(cp + PREFIX_SIZE, apk_path, len + 1);
free(apk_path);
return cp;
}
static sc_pid static sc_pid
execute_server(struct sc_server *server, execute_server(struct sc_server *server,
const struct sc_server_params *params) { const struct sc_server_params *params) {
@ -217,12 +160,7 @@ execute_server(struct sc_server *server,
const char *serial = server->serial; const char *serial = server->serial;
assert(serial); assert(serial);
char *classpath = get_classpath_cmd(&server->intr, serial, params->install); fprintf(stderr, "=== [%s]\n", sc_adb_get_installed_apk_version(&server->intr, serial, 0));
if (!classpath) {
return SC_PROCESS_NONE;
}
LOGD("Using %s", classpath);
const char *cmd[128]; const char *cmd[128];
unsigned count = 0; unsigned count = 0;
@ -230,7 +168,7 @@ execute_server(struct sc_server *server,
cmd[count++] = "-s"; cmd[count++] = "-s";
cmd[count++] = serial; cmd[count++] = serial;
cmd[count++] = "shell"; cmd[count++] = "shell";
cmd[count++] = classpath; cmd[count++] = "CLASSPATH=" SC_DEVICE_SERVER_PATH;
cmd[count++] = "app_process"; cmd[count++] = "app_process";
#ifdef SERVER_DEBUGGER #ifdef SERVER_DEBUGGER
@ -316,8 +254,6 @@ execute_server(struct sc_server *server,
// By default, power_on is true // By default, power_on is true
ADD_PARAM("power_on=false"); ADD_PARAM("power_on=false");
} }
// TODO ADD_PARAM("install=…");
// The server must not rm in /data/local/tmp if installed
#undef ADD_PARAM #undef ADD_PARAM
@ -338,8 +274,6 @@ execute_server(struct sc_server *server,
pid = sc_adb_execute(cmd, 0); pid = sc_adb_execute(cmd, 0);
end: end:
free(classpath);
for (unsigned i = dyn_idx; i < count; ++i) { for (unsigned i = dyn_idx; i < count; ++i) {
free((char *) cmd[i]); free((char *) cmd[i]);
} }
@ -823,9 +757,8 @@ run_server(void *data) {
assert(serial); assert(serial);
LOGD("Device serial: %s", serial); LOGD("Device serial: %s", serial);
ok = push_server(&server->intr, serial, params->install, params->reinstall); ok = push_server(&server->intr, serial);
if (!ok) { if (!ok) {
LOGE("Failed to push server");
goto error_connection_failed; goto error_connection_failed;
} }

View File

@ -48,8 +48,6 @@ struct sc_server_params {
bool select_tcpip; bool select_tcpip;
bool cleanup; bool cleanup;
bool power_on; bool power_on;
bool install;
bool reinstall;
}; };
struct sc_server { struct sc_server {

2
run
View File

@ -21,5 +21,5 @@ then
fi fi
SCRCPY_ICON_PATH="app/data/icon.png" \ SCRCPY_ICON_PATH="app/data/icon.png" \
SCRCPY_SERVER_PATH="$BUILDDIR/server/scrcpy-server.apk" \ SCRCPY_SERVER_PATH="$BUILDDIR/server/scrcpy-server" \
"$BUILDDIR/app/scrcpy" "$@" "$BUILDDIR/app/scrcpy" "$@"

1
server/.gitignore vendored
View File

@ -6,4 +6,3 @@
/build /build
/captures /captures
.externalNativeBuild .externalNativeBuild
/keystore.properties

View File

@ -1,12 +0,0 @@
For an APK to be installable, it must be signed: <https://developer.android.com/training/articles/keystore>
For that purpose, create a keystore by executing this command:
keytool -genkey -v -keystore ~/.android/scrcpy.keystore -keyalg RSA -keysize 2048 -validity 10000 -alias scrcpy -dname cn=scrcpy
(Adapt ~/.android/scrcpy.keystore if you want to generate it to another location.)
Then create server/keystore.properties and edit its properties:
cp keystore.properties.sample keystore.properties
vim keystore.properties # fill the properties

View File

@ -10,31 +10,16 @@ android {
versionName "1.24" versionName "1.24"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
} }
signingConfigs {
release {
// to be defined in server/keystore.properties (see server/HOWTO_keystore.txt)
def keystorePropsFile = rootProject.file("server/keystore.properties")
if (keystorePropsFile.exists()) {
def props = new Properties()
props.load(new FileInputStream(keystorePropsFile))
storeFile rootProject.file(props['storeFile'])
storePassword props['storePassword']
keyAlias props['keyAlias']
keyPassword props['keyPassword']
}
}
}
buildTypes { buildTypes {
release { release {
minifyEnabled false minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
} }
} }
} }
dependencies { dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
testImplementation 'junit:junit:4.13.1' testImplementation 'junit:junit:4.13.1'
} }

View File

@ -14,42 +14,13 @@ set -e
SCRCPY_DEBUG=false SCRCPY_DEBUG=false
SCRCPY_VERSION_NAME=1.24 SCRCPY_VERSION_NAME=1.24
SERVER_DIR="$(realpath $(dirname "$0"))"
KEYSTORE_PROPERTIES_FILE="$SERVER_DIR/keystore.properties"
if [[ ! -f "$KEYSTORE_PROPERTIES_FILE" ]]
then
echo "The file '$KEYSTORE_PROPERTIES_FILE' does not exist." >&2
echo "Please read '$SERVER_DIR/HOWTO_keystore.txt'." >&2
exit 1
fi
declare -A props
while IFS='=' read -r key value
do
props["$key"]="$value"
done < "$KEYSTORE_PROPERTIES_FILE"
KEYSTORE_FILE=${props['storeFile']}
KEYSTORE_PASSWORD=${props['storePassword']}
KEYSTORE_KEY_ALIAS=${props['keyAlias']}
KEYSTORE_KEY_PASSWORD=${props['keyPassword']}
if [[ ! -f "$KEYSTORE_FILE" ]]
then
echo "Keystore '$KEYSTORE_FILE' (read from '$KEYSTORE_PROPERTIES_FILE')" \
"does not exist." >&2
echo "Please read '$SERVER_DIR/HOWTO_keystore.txt'." >&2
exit 2
fi
PLATFORM=${ANDROID_PLATFORM:-31} PLATFORM=${ANDROID_PLATFORM:-31}
BUILD_TOOLS=${ANDROID_BUILD_TOOLS:-31.0.0} BUILD_TOOLS=${ANDROID_BUILD_TOOLS:-31.0.0}
BUILD_TOOLS_DIR="$ANDROID_HOME/build-tools/$BUILD_TOOLS"
BUILD_DIR="$(realpath ${BUILD_DIR:-build_manual})" BUILD_DIR="$(realpath ${BUILD_DIR:-build_manual})"
CLASSES_DIR="$BUILD_DIR/classes" CLASSES_DIR="$BUILD_DIR/classes"
SERVER_BINARY=scrcpy-server.apk SERVER_DIR=$(dirname "$0")
SERVER_BINARY=scrcpy-server
ANDROID_JAR="$ANDROID_HOME/platforms/android-$PLATFORM/android.jar" ANDROID_JAR="$ANDROID_HOME/platforms/android-$PLATFORM/android.jar"
echo "Platform: android-$PLATFORM" echo "Platform: android-$PLATFORM"
@ -70,8 +41,9 @@ EOF
echo "Generating java from aidl..." echo "Generating java from aidl..."
cd "$SERVER_DIR/src/main/aidl" cd "$SERVER_DIR/src/main/aidl"
"$BUILD_TOOLS_DIR/aidl" -o"$CLASSES_DIR" android/view/IRotationWatcher.aidl "$ANDROID_HOME/build-tools/$BUILD_TOOLS/aidl" -o"$CLASSES_DIR" \
"$BUILD_TOOLS_DIR/aidl" -o"$CLASSES_DIR" \ android/view/IRotationWatcher.aidl
"$ANDROID_HOME/build-tools/$BUILD_TOOLS/aidl" -o"$CLASSES_DIR" \
android/content/IOnPrimaryClipChangedListener.aidl android/content/IOnPrimaryClipChangedListener.aidl
echo "Compiling java sources..." echo "Compiling java sources..."
@ -87,15 +59,20 @@ cd "$CLASSES_DIR"
if [[ $PLATFORM -lt 31 ]] if [[ $PLATFORM -lt 31 ]]
then then
# use dx # use dx
"$BUILD_TOOLS_DIR/dx" --dex --output "$BUILD_DIR/classes.dex" \ "$ANDROID_HOME/build-tools/$BUILD_TOOLS/dx" --dex \
--output "$BUILD_DIR/classes.dex" \
android/view/*.class \ android/view/*.class \
android/content/*.class \ android/content/*.class \
com/genymobile/scrcpy/*.class \ com/genymobile/scrcpy/*.class \
com/genymobile/scrcpy/wrappers/*.class com/genymobile/scrcpy/wrappers/*.class
echo "Archiving..."
cd "$BUILD_DIR" cd "$BUILD_DIR"
jar cvf "$SERVER_BINARY" classes.dex
rm -rf classes.dex classes
else else
# use d8 # use d8
"$BUILD_TOOLS_DIR/d8" --classpath "$ANDROID_JAR" \ "$ANDROID_HOME/build-tools/$BUILD_TOOLS/d8" --classpath "$ANDROID_JAR" \
--output "$BUILD_DIR/classes.zip" \ --output "$BUILD_DIR/classes.zip" \
android/view/*.class \ android/view/*.class \
android/content/*.class \ android/content/*.class \
@ -103,24 +80,8 @@ else
com/genymobile/scrcpy/wrappers/*.class com/genymobile/scrcpy/wrappers/*.class
cd "$BUILD_DIR" cd "$BUILD_DIR"
unzip -o classes.zip classes.dex # we need the inner classes.dex mv classes.zip "$SERVER_BINARY"
rm -rf classes
fi fi
echo "Packaging..."
# note: if a res directory exists, add: -S "$SERVER_DIR/src/main/res"
"$BUILD_TOOLS_DIR/aapt" package -f \
-M "$SERVER_DIR/src/main/AndroidManifest.xml" \
-I "$ANDROID_JAR" \
-F "$SERVER_BINARY.unaligned"
"$BUILD_TOOLS_DIR/aapt" add "$SERVER_BINARY.unaligned" classes.dex
"$BUILD_TOOLS_DIR/zipalign" -p 4 "$SERVER_BINARY.unaligned" "$SERVER_BINARY"
rm "$SERVER_BINARY.unaligned"
"$BUILD_TOOLS_DIR/apksigner" sign \
--ks "$KEYSTORE_FILE" \
--ks-pass "pass:$KEYSTORE_PASSWORD" \
--ks-key-alias "$KEYSTORE_KEY_ALIAS" \
--key-pass "pass:$KEYSTORE_KEY_PASSWORD" \
"$SERVER_BINARY"
echo "Server generated in $BUILD_DIR/$SERVER_BINARY" echo "Server generated in $BUILD_DIR/$SERVER_BINARY"

View File

@ -1,4 +0,0 @@
storeFile=/path/to/your/keystore
storePassword=PASSWORD
keyAlias=scrcpy
keyPassword=PASSWORD

View File

@ -6,7 +6,7 @@ if prebuilt_server == ''
# gradle is responsible for tracking source changes # gradle is responsible for tracking source changes
build_by_default: true, build_by_default: true,
build_always_stale: true, build_always_stale: true,
output: 'scrcpy-server.apk', output: 'scrcpy-server',
command: [find_program('./scripts/build-wrapper.sh'), meson.current_source_dir(), '@OUTPUT@', get_option('buildtype')], command: [find_program('./scripts/build-wrapper.sh'), meson.current_source_dir(), '@OUTPUT@', get_option('buildtype')],
console: true, console: true,
install: true, install: true,
@ -18,7 +18,7 @@ else
endif endif
custom_target('scrcpy-server-prebuilt', custom_target('scrcpy-server-prebuilt',
input: prebuilt_server, input: prebuilt_server,
output: 'scrcpy-server.apk', output: 'scrcpy-server',
command: ['cp', '@INPUT@', '@OUTPUT@'], command: ['cp', '@INPUT@', '@OUTPUT@'],
install: true, install: true,
install_dir: 'share/scrcpy') install_dir: 'share/scrcpy')

View File

@ -25,5 +25,5 @@ then
cp "$PROJECT_ROOT/build/outputs/apk/debug/server-debug.apk" "$OUTPUT" cp "$PROJECT_ROOT/build/outputs/apk/debug/server-debug.apk" "$OUTPUT"
else else
"$GRADLE" -p "$PROJECT_ROOT" assembleRelease "$GRADLE" -p "$PROJECT_ROOT" assembleRelease
cp "$PROJECT_ROOT/build/outputs/apk/release/server-release.apk" "$OUTPUT" cp "$PROJECT_ROOT/build/outputs/apk/release/server-release-unsigned.apk" "$OUTPUT"
fi fi

View File

@ -16,7 +16,7 @@ import java.io.IOException;
*/ */
public final class CleanUp { public final class CleanUp {
public static final String SERVER_PATH = "/data/local/tmp/scrcpy-server.apk"; public static final String SERVER_PATH = "/data/local/tmp/scrcpy-server.jar";
// A simple struct to be passed from the main process to the cleanup process // A simple struct to be passed from the main process to the cleanup process
public static class Config implements Parcelable { public static class Config implements Parcelable {