change: execute server as root and create secure display
change: AID_GRAPHICS -> AID_SYSTEM add: fllag --root to launch server as root cleanup: phantom whitespace change: eliminate ambiguous description add: autocompletion for --root change: use getPackageName method rather than fixed constant for `--root` case change: at least try audio when running as AID_SYSTEM on older versions fixups: PACKAGE_SHELL constant where necessary, DRY cleanup: usage of PACKAGE_NAME + PACKAGE_SHELL
This commit is contained in:
parent
1ee46970e3
commit
7b1ac46ab0
13 changed files with 36 additions and 5 deletions
|
@ -53,6 +53,7 @@ _scrcpy() {
|
|||
--record-format=
|
||||
--render-driver=
|
||||
--require-audio
|
||||
--root
|
||||
--rotation=
|
||||
-s --serial=
|
||||
-S --turn-screen-off
|
||||
|
|
|
@ -59,6 +59,7 @@ arguments=(
|
|||
'--record-format=[Force recording format]:format:(mp4 mkv)'
|
||||
'--render-driver=[Request SDL to use the given render driver]:driver name:(direct3d opengl opengles2 opengles metal software)'
|
||||
'--require-audio=[Make scrcpy fail if audio is enabled but does not work]'
|
||||
'--root[Launch the server as root]'
|
||||
'--rotation=[Set the initial display rotation]:rotation values:(0 1 2 3)'
|
||||
{-s,--serial=}'[The device serial number \(mandatory for multiple devices only\)]:serial:($("${ADB-adb}" devices | awk '\''$2 == "device" {print $1}'\''))'
|
||||
{-S,--turn-screen-off}'[Turn the device screen off immediately]'
|
||||
|
|
|
@ -79,6 +79,7 @@ enum {
|
|||
OPT_AUDIO_SOURCE,
|
||||
OPT_KILL_ADB_ON_CLOSE,
|
||||
OPT_TIME_LIMIT,
|
||||
OPT_ROOT,
|
||||
};
|
||||
|
||||
struct sc_option {
|
||||
|
@ -535,6 +536,11 @@ static const struct sc_option options[] = {
|
|||
"Possible values are 0, 1, 2 and 3. Each increment adds a 90 "
|
||||
"degrees rotation counterclockwise.",
|
||||
},
|
||||
{
|
||||
.longopt_id = OPT_ROOT,
|
||||
.longopt = "root",
|
||||
.text = "Launch the server as root (disabled by default).",
|
||||
},
|
||||
{
|
||||
.shortopt = 's',
|
||||
.longopt = "serial",
|
||||
|
@ -1977,6 +1983,9 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
|
|||
return false;
|
||||
}
|
||||
break;
|
||||
case OPT_ROOT:
|
||||
opts->root = true;
|
||||
break;
|
||||
default:
|
||||
// getopt prints the error message on stderr
|
||||
return false;
|
||||
|
|
|
@ -82,4 +82,5 @@ const struct scrcpy_options scrcpy_options_default = {
|
|||
.list_encoders = false,
|
||||
.list_displays = false,
|
||||
.kill_adb_on_close = false,
|
||||
.root = false,
|
||||
};
|
||||
|
|
|
@ -182,6 +182,7 @@ struct scrcpy_options {
|
|||
bool list_encoders;
|
||||
bool list_displays;
|
||||
bool kill_adb_on_close;
|
||||
bool root;
|
||||
};
|
||||
|
||||
extern const struct scrcpy_options scrcpy_options_default;
|
||||
|
|
|
@ -380,6 +380,7 @@ scrcpy(struct scrcpy_options *options) {
|
|||
.list_encoders = options->list_encoders,
|
||||
.list_displays = options->list_displays,
|
||||
.kill_adb_on_close = options->kill_adb_on_close,
|
||||
.root = options->root,
|
||||
};
|
||||
|
||||
static const struct sc_server_callbacks cbs = {
|
||||
|
|
|
@ -194,6 +194,13 @@ execute_server(struct sc_server *server,
|
|||
cmd[count++] = "-s";
|
||||
cmd[count++] = serial;
|
||||
cmd[count++] = "shell";
|
||||
|
||||
if (params->root) {
|
||||
cmd[count++] = "su";
|
||||
cmd[count++] = "1000"; // AID_SYSTEM, AID_GRAPHICS is also supported for FLAG_SECURE but lacks other perms
|
||||
cmd[count++] = "-c";
|
||||
}
|
||||
|
||||
cmd[count++] = "CLASSPATH=" SC_DEVICE_SERVER_PATH;
|
||||
cmd[count++] = "app_process";
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ struct sc_server_params {
|
|||
bool list_encoders;
|
||||
bool list_displays;
|
||||
bool kill_adb_on_close;
|
||||
bool root;
|
||||
};
|
||||
|
||||
struct sc_server {
|
||||
|
|
|
@ -74,12 +74,12 @@ public final class AudioCapture {
|
|||
Intent intent = new Intent(Intent.ACTION_MAIN);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.addCategory(Intent.CATEGORY_LAUNCHER);
|
||||
intent.setComponent(new ComponentName(FakeContext.PACKAGE_NAME, "com.android.shell.HeapDumpActivity"));
|
||||
intent.setComponent(new ComponentName(FakeContext.PACKAGE_SHELL, "com.android.shell.HeapDumpActivity"));
|
||||
ServiceManager.getActivityManager().startActivityAsUserWithFeature(intent);
|
||||
}
|
||||
|
||||
private static void stopWorkaroundAndroid11() {
|
||||
ServiceManager.getActivityManager().forceStopPackage(FakeContext.PACKAGE_NAME);
|
||||
ServiceManager.getActivityManager().forceStopPackage(FakeContext.PACKAGE_SHELL);
|
||||
}
|
||||
|
||||
private void tryStartRecording(int attempts, int delayMs) throws AudioCaptureForegroundException {
|
||||
|
|
|
@ -7,6 +7,7 @@ import android.os.Build;
|
|||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.Looper;
|
||||
import android.system.Os;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
@ -170,7 +171,7 @@ public final class AudioEncoder implements AsyncProcessor {
|
|||
|
||||
@TargetApi(Build.VERSION_CODES.M)
|
||||
public void encode() throws IOException, ConfigurationException, AudioCaptureForegroundException {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
|
||||
if ((Os.getuid() == 2000) && (Build.VERSION.SDK_INT < Build.VERSION_CODES.R)) {
|
||||
Ln.w("Audio disabled: it is not supported before Android 11");
|
||||
streamer.writeDisableStream(false);
|
||||
return;
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.genymobile.scrcpy;
|
|||
|
||||
import android.media.MediaCodec;
|
||||
import android.os.Build;
|
||||
import android.system.Os;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
@ -22,7 +23,7 @@ public final class AudioRawRecorder implements AsyncProcessor {
|
|||
}
|
||||
|
||||
private void record() throws IOException, AudioCaptureForegroundException {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
|
||||
if ((Os.getuid() == 2000) && (Build.VERSION.SDK_INT < Build.VERSION_CODES.R)) {
|
||||
Ln.w("Audio disabled: it is not supported before Android 11");
|
||||
streamer.writeDisableStream(false);
|
||||
return;
|
||||
|
|
|
@ -5,10 +5,12 @@ import android.content.AttributionSource;
|
|||
import android.content.MutableContextWrapper;
|
||||
import android.os.Build;
|
||||
import android.os.Process;
|
||||
import android.system.Os;
|
||||
|
||||
public final class FakeContext extends MutableContextWrapper {
|
||||
|
||||
public static final String PACKAGE_NAME = "com.android.shell";
|
||||
public static final String PACKAGE_NAME = Os.getuid() == 1000 ? "android" : "com.android.shell";
|
||||
public static final String PACKAGE_SHELL = "com.android.shell";
|
||||
public static final int ROOT_UID = 0; // Like android.os.Process.ROOT_UID, but before API 29
|
||||
|
||||
private static final FakeContext INSTANCE = new FakeContext();
|
||||
|
@ -31,6 +33,7 @@ public final class FakeContext extends MutableContextWrapper {
|
|||
return PACKAGE_NAME;
|
||||
}
|
||||
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.S)
|
||||
@Override
|
||||
public AttributionSource getAttributionSource() {
|
||||
|
|
|
@ -11,6 +11,7 @@ import android.os.IBinder;
|
|||
import android.os.Looper;
|
||||
import android.os.SystemClock;
|
||||
import android.view.Surface;
|
||||
import android.system.Os;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
@ -269,6 +270,9 @@ public class ScreenEncoder implements Device.RotationListener, Device.FoldListen
|
|||
// On Android 12 preview, SDK_INT is still R (not S), but CODENAME is "S".
|
||||
boolean secure = Build.VERSION.SDK_INT < Build.VERSION_CODES.R || (Build.VERSION.SDK_INT == Build.VERSION_CODES.R && !"S"
|
||||
.equals(Build.VERSION.CODENAME));
|
||||
if (Os.getuid() < 2000) {
|
||||
secure = true;
|
||||
}
|
||||
return SurfaceControl.createDisplay("scrcpy", secure);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue