Replace layout stack option with better device id option.

This allows the correct geometry to be grabbed and the layout stack to be derived from the display info itself.
This commit is contained in:
Caleb Brown 2020-03-19 12:38:05 +11:00
commit 4afca06635
12 changed files with 58 additions and 34 deletions

View file

@ -41,8 +41,8 @@ scrcpy_print_usage(const char *arg0) {
" -h, --help\n" " -h, --help\n"
" Print this help.\n" " Print this help.\n"
"\n" "\n"
" --layer-stack value\n" " --display-id value\n"
" Specifies the Android layer stack to mirror\n" " Specifies the Android display to mirror\n"
" Default is 0\n" " Default is 0\n"
"\n" "\n"
" --max-fps value\n" " --max-fps value\n"
@ -264,14 +264,14 @@ parse_max_fps(const char *s, uint16_t *max_fps) {
} }
static bool static bool
parse_layer_stack(const char *s, uint16_t *layer_stack) { parse_display_id(const char *s, uint16_t *display_id) {
long value; long value;
bool ok = parse_integer_arg(s, &value, false, 0, 1000, "layer stack"); bool ok = parse_integer_arg(s, &value, false, 0, 1000, "display id");
if (!ok) { if (!ok) {
return false; return false;
} }
*layer_stack = (uint16_t) value; *display_id = (uint16_t) value;
return true; return true;
} }
@ -356,7 +356,7 @@ guess_record_format(const char *filename) {
#define OPT_WINDOW_HEIGHT 1010 #define OPT_WINDOW_HEIGHT 1010
#define OPT_WINDOW_BORDERLESS 1011 #define OPT_WINDOW_BORDERLESS 1011
#define OPT_MAX_FPS 1012 #define OPT_MAX_FPS 1012
#define OPT_LAYER_STACK 1013 #define OPT_DISPLAY_ID 1013
bool bool
scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) { scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
@ -367,7 +367,7 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
{"fullscreen", no_argument, NULL, 'f'}, {"fullscreen", no_argument, NULL, 'f'},
{"help", no_argument, NULL, 'h'}, {"help", no_argument, NULL, 'h'},
{"max-fps", required_argument, NULL, OPT_MAX_FPS}, {"max-fps", required_argument, NULL, OPT_MAX_FPS},
{"layer-stack", required_argument, NULL, OPT_LAYER_STACK}, {"display-id", required_argument, NULL, OPT_DISPLAY_ID},
{"max-size", required_argument, NULL, 'm'}, {"max-size", required_argument, NULL, 'm'},
{"no-control", no_argument, NULL, 'n'}, {"no-control", no_argument, NULL, 'n'},
{"no-display", no_argument, NULL, 'N'}, {"no-display", no_argument, NULL, 'N'},
@ -430,8 +430,8 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
return false; return false;
} }
break; break;
case OPT_LAYER_STACK: case OPT_DISPLAY_ID:
if (!parse_layer_stack(optarg, &opts->layer_stack)) { if (!parse_display_id(optarg, &opts->display_id)) {
return false; return false;
} }
break; break;

View file

@ -285,7 +285,7 @@ scrcpy(const struct scrcpy_options *options) {
.bit_rate = options->bit_rate, .bit_rate = options->bit_rate,
.max_fps = options->max_fps, .max_fps = options->max_fps,
.control = options->control, .control = options->control,
.layer_stack = options->layer_stack, .display_id = options->display_id,
}; };
if (!server_start(&server, options->serial, &params)) { if (!server_start(&server, options->serial, &params)) {
return false; return false;

View file

@ -32,7 +32,7 @@ struct scrcpy_options {
bool render_expired_frames; bool render_expired_frames;
bool prefer_text; bool prefer_text;
bool window_borderless; bool window_borderless;
uint16_t layer_stack; uint16_t display_id;
}; };
#define SCRCPY_OPTIONS_DEFAULT { \ #define SCRCPY_OPTIONS_DEFAULT { \
@ -59,7 +59,7 @@ struct scrcpy_options {
.render_expired_frames = false, \ .render_expired_frames = false, \
.prefer_text = false, \ .prefer_text = false, \
.window_borderless = false, \ .window_borderless = false, \
.layer_stack = 0, \ .display_id = 0, \
} }
bool bool

View file

@ -124,12 +124,12 @@ execute_server(struct server *server, const struct server_params *params) {
char max_size_string[6]; char max_size_string[6];
char bit_rate_string[11]; char bit_rate_string[11];
char max_fps_string[6]; char max_fps_string[6];
char layer_stack_string[6]; char display_id_string[6];
sprintf(max_size_string, "%"PRIu16, params->max_size); sprintf(max_size_string, "%"PRIu16, params->max_size);
sprintf(bit_rate_string, "%"PRIu32, params->bit_rate); sprintf(bit_rate_string, "%"PRIu32, params->bit_rate);
sprintf(max_fps_string, "%"PRIu16, params->max_fps); sprintf(max_fps_string, "%"PRIu16, params->max_fps);
sprintf(layer_stack_string, "%"PRIu16, params->layer_stack); sprintf(display_id_string, "%"PRIu16, params->display_id);
const char *const cmd[] = { const char *const cmd[] = {
"shell", "shell",
"CLASSPATH=" DEVICE_SERVER_PATH, "CLASSPATH=" DEVICE_SERVER_PATH,
@ -149,7 +149,7 @@ execute_server(struct server *server, const struct server_params *params) {
params->crop ? params->crop : "-", params->crop ? params->crop : "-",
"true", // always send frame meta (packet boundaries + timestamp) "true", // always send frame meta (packet boundaries + timestamp)
params->control ? "true" : "false", params->control ? "true" : "false",
layer_stack_string display_id_string
}; };
#ifdef SERVER_DEBUGGER #ifdef SERVER_DEBUGGER
LOGI("Server debugger waiting for a client on device port " LOGI("Server debugger waiting for a client on device port "

View file

@ -37,7 +37,7 @@ struct server_params {
uint32_t bit_rate; uint32_t bit_rate;
uint16_t max_fps; uint16_t max_fps;
bool control; bool control;
uint16_t layer_stack; uint16_t display_id;
}; };
// init default values // init default values

View file

@ -26,7 +26,7 @@ public final class Device {
private RotationListener rotationListener; private RotationListener rotationListener;
public Device(Options options) { public Device(Options options) {
screenInfo = computeScreenInfo(options.getCrop(), options.getMaxSize()); screenInfo = computeScreenInfo(options.getDisplayId(), options.getCrop(), options.getMaxSize());
registerRotationWatcher(new IRotationWatcher.Stub() { registerRotationWatcher(new IRotationWatcher.Stub() {
@Override @Override
public void onRotationChanged(int rotation) throws RemoteException { public void onRotationChanged(int rotation) throws RemoteException {
@ -46,8 +46,8 @@ public final class Device {
return screenInfo; return screenInfo;
} }
private ScreenInfo computeScreenInfo(Rect crop, int maxSize) { private ScreenInfo computeScreenInfo(int displayId, Rect crop, int maxSize) {
DisplayInfo displayInfo = serviceManager.getDisplayManager().getDisplayInfo(); DisplayInfo displayInfo = serviceManager.getDisplayManager().getDisplayInfo(displayId);
boolean rotated = (displayInfo.getRotation() & 1) != 0; boolean rotated = (displayInfo.getRotation() & 1) != 0;
Size deviceSize = displayInfo.getSize(); Size deviceSize = displayInfo.getSize();
Rect contentRect = new Rect(0, 0, deviceSize.getWidth(), deviceSize.getHeight()); Rect contentRect = new Rect(0, 0, deviceSize.getWidth(), deviceSize.getHeight());
@ -64,7 +64,7 @@ public final class Device {
} }
Size videoSize = computeVideoSize(contentRect.width(), contentRect.height(), maxSize); Size videoSize = computeVideoSize(contentRect.width(), contentRect.height(), maxSize);
return new ScreenInfo(contentRect, videoSize, rotated); return new ScreenInfo(contentRect, videoSize, rotated, displayInfo.getLayerStack());
} }
private static String formatCrop(Rect rect) { private static String formatCrop(Rect rect) {

View file

@ -1,12 +1,20 @@
package com.genymobile.scrcpy; package com.genymobile.scrcpy;
public final class DisplayInfo { public final class DisplayInfo {
private final int displayId;
private final Size size; private final Size size;
private final int rotation; private final int rotation;
private final int layerStack;
public DisplayInfo(Size size, int rotation) { public DisplayInfo(int displayId, Size size, int rotation, int layerStack) {
this.displayId = displayId;
this.size = size; this.size = size;
this.rotation = rotation; this.rotation = rotation;
this.layerStack = layerStack;
}
public int getDisplayId() {
return displayId;
} }
public Size getSize() { public Size getSize() {
@ -16,5 +24,9 @@ public final class DisplayInfo {
public int getRotation() { public int getRotation() {
return rotation; return rotation;
} }
public int getLayerStack() {
return layerStack;
}
} }

View file

@ -10,7 +10,7 @@ public class Options {
private Rect crop; private Rect crop;
private boolean sendFrameMeta; // send PTS so that the client may record properly private boolean sendFrameMeta; // send PTS so that the client may record properly
private boolean control; private boolean control;
private int layerStack; private int displayId;
public int getMaxSize() { public int getMaxSize() {
return maxSize; return maxSize;
@ -68,11 +68,11 @@ public class Options {
this.control = control; this.control = control;
} }
public int getLayerStack() { public int getDisplayId() {
return layerStack; return displayId;
} }
public void setLayerStack(int layerStack) { public void setDisplayId(int displayId) {
this.layerStack = layerStack; this.displayId = displayId;
} }
} }

View file

@ -51,7 +51,7 @@ public class ScreenEncoder implements Device.RotationListener {
return rotationChanged.getAndSet(false); return rotationChanged.getAndSet(false);
} }
public void streamScreen(Device device, FileDescriptor fd, int layerStack) throws IOException { public void streamScreen(Device device, FileDescriptor fd) throws IOException {
Workarounds.prepareMainLooper(); Workarounds.prepareMainLooper();
Workarounds.fillAppInfo(); Workarounds.fillAppInfo();
@ -64,6 +64,7 @@ public class ScreenEncoder implements Device.RotationListener {
IBinder display = createDisplay(); IBinder display = createDisplay();
Rect contentRect = device.getScreenInfo().getContentRect(); Rect contentRect = device.getScreenInfo().getContentRect();
Rect videoRect = device.getScreenInfo().getVideoSize().toRect(); Rect videoRect = device.getScreenInfo().getVideoSize().toRect();
int layerStack = device.getScreenInfo().getLayerStack();
setSize(format, videoRect.width(), videoRect.height()); setSize(format, videoRect.width(), videoRect.height());
configure(codec, format); configure(codec, format);
Surface surface = codec.createInputSurface(); Surface surface = codec.createInputSurface();

View file

@ -6,11 +6,13 @@ public final class ScreenInfo {
private final Rect contentRect; // device size, possibly cropped private final Rect contentRect; // device size, possibly cropped
private final Size videoSize; private final Size videoSize;
private final boolean rotated; private final boolean rotated;
private final int layerStack;
public ScreenInfo(Rect contentRect, Size videoSize, boolean rotated) { public ScreenInfo(Rect contentRect, Size videoSize, boolean rotated, int layerStack) {
this.contentRect = contentRect; this.contentRect = contentRect;
this.videoSize = videoSize; this.videoSize = videoSize;
this.rotated = rotated; this.rotated = rotated;
this.layerStack = layerStack;
} }
public Rect getContentRect() { public Rect getContentRect() {
@ -21,11 +23,15 @@ public final class ScreenInfo {
return videoSize; return videoSize;
} }
public int getLayerStack() {
return layerStack;
}
public ScreenInfo withRotation(int rotation) { public ScreenInfo withRotation(int rotation) {
boolean newRotated = (rotation & 1) != 0; boolean newRotated = (rotation & 1) != 0;
if (rotated == newRotated) { if (rotated == newRotated) {
return this; return this;
} }
return new ScreenInfo(Device.flipRect(contentRect), videoSize.rotate(), newRotated); return new ScreenInfo(Device.flipRect(contentRect), videoSize.rotate(), newRotated, layerStack);
} }
} }

View file

@ -31,7 +31,7 @@ public final class Server {
try { try {
// synchronous // synchronous
screenEncoder.streamScreen(device, connection.getVideoFd(), options.getLayerStack()); screenEncoder.streamScreen(device, connection.getVideoFd());
} catch (IOException e) { } catch (IOException e) {
// this is expected on close // this is expected on close
Ln.d("Screen streaming stopped"); Ln.d("Screen streaming stopped");
@ -107,8 +107,8 @@ public final class Server {
boolean control = Boolean.parseBoolean(args[7]); boolean control = Boolean.parseBoolean(args[7]);
options.setControl(control); options.setControl(control);
int layerStack = Integer.parseInt(args[8]); int displayId = Integer.parseInt(args[8]);
options.setLayerStack(layerStack); options.setDisplayId(displayId);
return options; return options;
} }

View file

@ -13,14 +13,19 @@ public final class DisplayManager {
} }
public DisplayInfo getDisplayInfo() { public DisplayInfo getDisplayInfo() {
return getDisplayInfo(0);
}
public DisplayInfo getDisplayInfo(int displayId) {
try { try {
Object displayInfo = manager.getClass().getMethod("getDisplayInfo", int.class).invoke(manager, 0); Object displayInfo = manager.getClass().getMethod("getDisplayInfo", int.class).invoke(manager, displayId);
Class<?> cls = displayInfo.getClass(); Class<?> cls = displayInfo.getClass();
// width and height already take the rotation into account // width and height already take the rotation into account
int width = cls.getDeclaredField("logicalWidth").getInt(displayInfo); int width = cls.getDeclaredField("logicalWidth").getInt(displayInfo);
int height = cls.getDeclaredField("logicalHeight").getInt(displayInfo); int height = cls.getDeclaredField("logicalHeight").getInt(displayInfo);
int rotation = cls.getDeclaredField("rotation").getInt(displayInfo); int rotation = cls.getDeclaredField("rotation").getInt(displayInfo);
return new DisplayInfo(new Size(width, height), rotation); int layerStack = cls.getDeclaredField("layerStack").getInt(displayInfo);
return new DisplayInfo(displayId, new Size(width, height), rotation, layerStack);
} catch (Exception e) { } catch (Exception e) {
throw new AssertionError(e); throw new AssertionError(e);
} }