Compare commits

..

2 commits
test ... master

Author SHA1 Message Date
54fb05837a
refine 2023-09-10 01:14:00 +08:00
85a9871082
virtual display 2023-09-08 17:51:14 +08:00
3 changed files with 34 additions and 43 deletions

View file

@ -552,9 +552,12 @@ static const struct sc_option options[] = {
.longopt_id = OPT_VIRTUAL_DISPLAY,
.longopt = "virtual-display",
.argdesc = "properties",
.optional_arg = true,
.text = "Start a new virtual display for your applications to "
"launch into. Requires Android version >= 10. "
"Display size and DPI may be specified. e.g. 1920x1080dpi300"
"Display size and DPI may be specified. e.g. 1920x1080dpi300\n"
"Comma separated extra launch arguments may be passed to am start.\n"
"e.g. 1920x1080dpi300,-a,android.intent.action.MAIN,-n,com.android.settings/.applications.ManageApplications"
},
{
.shortopt = 's',
@ -2005,7 +2008,7 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
opts->su_quirk = true;
break;
case OPT_VIRTUAL_DISPLAY:
opts->virtual_display_params = optarg;
opts->virtual_display_params = optarg ?: "";
break;
default:
// getopt prints the error message on stderr

View file

@ -3,13 +3,10 @@ package com.genymobile.scrcpy;
import android.annotation.TargetApi;
import android.content.AttributionSource;
import android.content.MutableContextWrapper;
import android.content.res.Resources;
import android.os.Build;
import android.os.Process;
import android.system.Os;
import java.lang.reflect.Constructor;
public final class FakeContext extends MutableContextWrapper {
public static final String PACKAGE_NAME = Os.getuid() == 1000 ? "android" : "com.android.shell";
@ -26,17 +23,6 @@ public final class FakeContext extends MutableContextWrapper {
super(null);
}
@Override
public Resources getResources() {
try {
Constructor<?> constructor = Class.forName("android.content.res.Resources").getDeclaredConstructor();
constructor.setAccessible(true);
return (Resources) constructor.newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public String getPackageName() {
return PACKAGE_NAME;

View file

@ -3,6 +3,7 @@ package com.genymobile.scrcpy.wrappers;
import com.genymobile.scrcpy.Command;
import com.genymobile.scrcpy.DisplayInfo;
import com.genymobile.scrcpy.FakeContext;
import com.genymobile.scrcpy.IO;
import com.genymobile.scrcpy.Ln;
import com.genymobile.scrcpy.Size;
@ -12,7 +13,10 @@ import android.os.Build;
import android.view.Display;
import android.view.Surface;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -25,47 +29,45 @@ public final class DisplayManager {
public VirtualDisplay createVirtualDisplay(String displayParams) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) throw new RuntimeException("requires android 10+");
final int VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 1 << 5;
final int VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH = 1 << 6;
final int VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT = 1 << 7;
final int VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL = 1 << 8;
final int VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS = 1 << 9;
final int VIRTUAL_DISPLAY_FLAG_TRUSTED = 1 << 10;
final int VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP = 1 << 11;
final int VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED = 1 << 12;
final int VIRTUAL_DISPLAY_FLAG_TOUCH_FEEDBACK_DISABLED = 1 << 13;
try {
if (displayParams == null || displayParams.isEmpty()) displayParams = "1920x1080dpi300";
String resolution = displayParams.toLowerCase().split("dpi")[0];
String[] displayParamsArray = displayParams.split(",");
String resolution = displayParamsArray[0].toLowerCase().split("dpi")[0];
int width = Integer.parseInt(resolution.split("x")[0]);
int height = Integer.parseInt(resolution.split("x")[1]);
int dpi = Integer.parseInt(displayParams.toLowerCase().split("dpi")[1]);
//MediaProjectionManager mediaProjectionManager = (MediaProjectionManager)Class.forName("android.media.projection.MediaProjectionManager").getConstructor(Class.forName("android.content.Context")).newInstance(FakeContext.get());
//Intent intent = mediaProjectionManager.createScreenCaptureIntent();
//ServiceManager.getActivityManager().startActivityAsUserWithFeature(intent);
int dpi = Integer.parseInt(displayParamsArray[0].toLowerCase().split("dpi")[1]);
android.hardware.display.DisplayManager displayManager = (android.hardware.display.DisplayManager)Class.forName("android.hardware.display.DisplayManager").getConstructor(Class.forName("android.content.Context")).newInstance(FakeContext.get());
SurfaceTexture surfaceTexture = new SurfaceTexture(false);
Surface surface = new Surface(surfaceTexture);
VirtualDisplay[] display = new VirtualDisplay[1];
display[0] = displayManager.createVirtualDisplay("test1", width, height, dpi, surface,
display[0] = displayManager.createVirtualDisplay("scrcpy", width, height, dpi, surface,
android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC
| android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR
| android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE
| VIRTUAL_DISPLAY_FLAG_TRUSTED
| VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED,
new VirtualDisplay.Callback() {
@Override
public void onStopped() {
super.onStopped();
surfaceTexture.release();
surface.release();
display[0].release();
}
}, null);
// start launcher or settings activity
| VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED);
Ln.i(String.format("Display: %d", display[0].getDisplay().getDisplayId()));
// start launcher
// TODO: replace shell commands with proper android framework api call
Command.exec("am", "start", "--user", "0", "--display", Integer.toString(display[0].getDisplay().getDisplayId()), "-a", "android.intent.action.MAIN", "-c", "android.intent.category.HOME", "-c", "android.intent.category.DEFAULT");
//Command.exec("am", "start", "--activity-single-top", "--display", Integer.toString(display.getDisplay().getDisplayId()), "com.android.settings");
String[] cmd;
if (displayParamsArray.length == 1) {
cmd = new String[]{"am", "start", "--user", "0", "--display", Integer.toString(display[0].getDisplay().getDisplayId()), "-a", "android.intent.action.MAIN", "-c", "android.intent.category.HOME", "-c", "android.intent.category.DEFAULT"};
}
else {
ArrayList<String> command = new ArrayList<>(Arrays.asList("am", "start", "--display", Integer.toString(display[0].getDisplay().getDisplayId())));
command.addAll(Arrays.asList(Arrays.copyOfRange(displayParamsArray, 1, displayParamsArray.length)));
cmd = command.toArray(new String[0]);
}
Process process = Runtime.getRuntime().exec(cmd);
String output = IO.toString(process.getInputStream());
String error = IO.toString(process.getErrorStream());
int exitCode = process.waitFor();
if (exitCode != 0) {
throw new IOException("Command " + Arrays.toString(cmd) + " returned with value " + exitCode);
}
Ln.i(String.format("stdout: %s\nstderr: %s", output.trim(), error.trim()));
return display[0];
} catch (Exception e) {
throw new AssertionError(e);