From 969bfd43744a88109d369089f9ee1313211ac9e1 Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Sat, 1 May 2021 00:18:55 +0200 Subject: [PATCH] Serialize clean-up configuration This avoids to pass each option as individual parameter and parse them manually (it's still "manual" in the Parcelable implementation). Refs #824 Reviewed-by: Yu-Chen Lin --- .../java/com/genymobile/scrcpy/CleanUp.java | 138 +++++++++++++++--- .../java/com/genymobile/scrcpy/Server.java | 2 +- 2 files changed, 119 insertions(+), 21 deletions(-) diff --git a/server/src/main/java/com/genymobile/scrcpy/CleanUp.java b/server/src/main/java/com/genymobile/scrcpy/CleanUp.java index ccdc9fd8..ec61a1c0 100644 --- a/server/src/main/java/com/genymobile/scrcpy/CleanUp.java +++ b/server/src/main/java/com/genymobile/scrcpy/CleanUp.java @@ -3,6 +3,10 @@ package com.genymobile.scrcpy; import com.genymobile.scrcpy.wrappers.ContentProvider; import com.genymobile.scrcpy.wrappers.ServiceManager; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Base64; + import java.io.File; import java.io.IOException; @@ -15,25 +19,123 @@ public final class CleanUp { 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 + public static class Config implements Parcelable { + + public static final Creator CREATOR = new Creator() { + @Override + public Config createFromParcel(Parcel in) { + return new Config(in); + } + + @Override + public Config[] newArray(int size) { + return new Config[size]; + } + }; + + private static final int FLAG_DISABLE_SHOW_TOUCHES = 1; + private static final int FLAG_RESTORE_NORMAL_POWER_MODE = 2; + private static final int FLAG_POWER_OFF_SCREEN = 4; + + private int displayId; + + // Restore the value (between 0 and 7), -1 to not restore + // + private int restoreStayOn = -1; + + private boolean disableShowTouches; + private boolean restoreNormalPowerMode; + private boolean powerOffScreen; + + public Config() { + // Default constructor, the fields are initialized by CleanUp.configure() + } + + protected Config(Parcel in) { + displayId = in.readInt(); + restoreStayOn = in.readInt(); + byte options = in.readByte(); + disableShowTouches = (options & FLAG_DISABLE_SHOW_TOUCHES) != 0; + restoreNormalPowerMode = (options & FLAG_RESTORE_NORMAL_POWER_MODE) != 0; + powerOffScreen = (options & FLAG_POWER_OFF_SCREEN) != 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(displayId); + dest.writeInt(restoreStayOn); + byte options = 0; + if (disableShowTouches) { + options |= FLAG_DISABLE_SHOW_TOUCHES; + } + if (restoreNormalPowerMode) { + options |= FLAG_RESTORE_NORMAL_POWER_MODE; + } + if (powerOffScreen) { + options |= FLAG_POWER_OFF_SCREEN; + } + dest.writeByte(options); + } + + private boolean hasWork() { + return disableShowTouches || restoreStayOn != -1 || restoreNormalPowerMode || powerOffScreen; + } + + @Override + public int describeContents() { + return 0; + } + + byte[] serialize() { + Parcel parcel = Parcel.obtain(); + writeToParcel(parcel, 0); + byte[] bytes = parcel.marshall(); + parcel.recycle(); + return bytes; + } + + static Config deserialize(byte[] bytes) { + Parcel parcel = Parcel.obtain(); + parcel.unmarshall(bytes, 0, bytes.length); + parcel.setDataPosition(0); + return CREATOR.createFromParcel(parcel); + } + + static Config fromBase64(String base64) { + byte[] bytes = Base64.decode(base64, Base64.NO_WRAP); + return deserialize(bytes); + } + + String toBase64() { + byte[] bytes = serialize(); + return Base64.encodeToString(bytes, Base64.NO_WRAP); + } + } + private CleanUp() { // not instantiable } - public static void configure(boolean disableShowTouches, int restoreStayOn, boolean restoreNormalPowerMode, boolean powerOffScreen, int displayId) + public static void configure(int displayId, int restoreStayOn, boolean disableShowTouches, boolean restoreNormalPowerMode, boolean powerOffScreen) throws IOException { - boolean needProcess = disableShowTouches || restoreStayOn != -1 || restoreNormalPowerMode || powerOffScreen; - if (needProcess) { - startProcess(disableShowTouches, restoreStayOn, restoreNormalPowerMode, powerOffScreen, displayId); + Config config = new Config(); + config.displayId = displayId; + config.disableShowTouches = disableShowTouches; + config.restoreStayOn = restoreStayOn; + config.restoreNormalPowerMode = restoreNormalPowerMode; + config.powerOffScreen = powerOffScreen; + + if (config.hasWork()) { + startProcess(config); } else { // There is no additional clean up to do when scrcpy dies unlinkSelf(); } } - private static void startProcess(boolean disableShowTouches, int restoreStayOn, boolean restoreNormalPowerMode, boolean powerOffScreen, - int displayId) throws IOException { - String[] cmd = {"app_process", "/", CleanUp.class.getName(), String.valueOf(disableShowTouches), String.valueOf( - restoreStayOn), String.valueOf(restoreNormalPowerMode), String.valueOf(powerOffScreen), String.valueOf(displayId)}; + private static void startProcess(Config config) throws IOException { + String[] cmd = {"app_process", "/", CleanUp.class.getName(), config.toBase64()}; ProcessBuilder builder = new ProcessBuilder(cmd); builder.environment().put("CLASSPATH", SERVER_PATH); @@ -60,31 +162,27 @@ public final class CleanUp { Ln.i("Cleaning up"); - boolean disableShowTouches = Boolean.parseBoolean(args[0]); - int restoreStayOn = Integer.parseInt(args[1]); - boolean restoreNormalPowerMode = Boolean.parseBoolean(args[2]); - boolean powerOffScreen = Boolean.parseBoolean(args[3]); - int displayId = Integer.parseInt(args[4]); + Config config = Config.fromBase64(args[0]); - if (disableShowTouches || restoreStayOn != -1) { + if (config.disableShowTouches || config.restoreStayOn != -1) { ServiceManager serviceManager = new ServiceManager(); try (ContentProvider settings = serviceManager.getActivityManager().createSettingsProvider()) { - if (disableShowTouches) { + if (config.disableShowTouches) { Ln.i("Disabling \"show touches\""); settings.putValue(ContentProvider.TABLE_SYSTEM, "show_touches", "0"); } - if (restoreStayOn != -1) { + if (config.restoreStayOn != -1) { Ln.i("Restoring \"stay awake\""); - settings.putValue(ContentProvider.TABLE_GLOBAL, "stay_on_while_plugged_in", String.valueOf(restoreStayOn)); + settings.putValue(ContentProvider.TABLE_GLOBAL, "stay_on_while_plugged_in", String.valueOf(config.restoreStayOn)); } } } if (Device.isScreenOn()) { - if (powerOffScreen) { + if (config.powerOffScreen) { Ln.i("Power off screen"); - Device.powerOffScreen(displayId); - } else if (restoreNormalPowerMode) { + Device.powerOffScreen(config.displayId); + } else if (config.restoreNormalPowerMode) { Ln.i("Restoring normal power mode"); Device.setScreenPowerMode(Device.POWER_MODE_NORMAL); } diff --git a/server/src/main/java/com/genymobile/scrcpy/Server.java b/server/src/main/java/com/genymobile/scrcpy/Server.java index 674f314b..fdd9db88 100644 --- a/server/src/main/java/com/genymobile/scrcpy/Server.java +++ b/server/src/main/java/com/genymobile/scrcpy/Server.java @@ -50,7 +50,7 @@ public final class Server { } } - CleanUp.configure(mustDisableShowTouchesOnCleanUp, restoreStayOn, true, options.getPowerOffScreenOnClose(), options.getDisplayId()); + CleanUp.configure(options.getDisplayId(), restoreStayOn, mustDisableShowTouchesOnCleanUp, true, options.getPowerOffScreenOnClose()); boolean tunnelForward = options.isTunnelForward();