Compare commits
2 Commits
issue4536
...
display_ma
Author | SHA1 | Date | |
---|---|---|---|
fdc58722b3 | |||
5a6b8310ca |
@ -1,3 +1,7 @@
|
|||||||
|
**This GitHub repo (<https://github.com/Genymobile/scrcpy>) is the only official
|
||||||
|
source for the project. Do not download releases from random websites, even if
|
||||||
|
their name contains `scrcpy`.**
|
||||||
|
|
||||||
# scrcpy (v2.3.1)
|
# scrcpy (v2.3.1)
|
||||||
|
|
||||||
<img src="app/data/icon.svg" width="128" height="128" alt="scrcpy" align="right" />
|
<img src="app/data/icon.svg" width="128" height="128" alt="scrcpy" align="right" />
|
||||||
|
@ -115,12 +115,13 @@ _scrcpy() {
|
|||||||
COMPREPLY=($(compgen -W 'front back external' -- "$cur"))
|
COMPREPLY=($(compgen -W 'front back external' -- "$cur"))
|
||||||
return
|
return
|
||||||
;;
|
;;
|
||||||
--orientation|--display-orientation)
|
--orientation
|
||||||
COMPREPLY=($(compgen -W '0 90 180 270 flip0 flip90 flip180 flip270' -- "$cur"))
|
--display-orientation)
|
||||||
|
COMPREPLY=($(compgen -> '0 90 180 270 flip0 flip90 flip180 flip270' -- "$cur"))
|
||||||
return
|
return
|
||||||
;;
|
;;
|
||||||
--record-orientation)
|
--record-orientation)
|
||||||
COMPREPLY=($(compgen -W '0 90 180 270' -- "$cur"))
|
COMPREPLY=($(compgen -> '0 90 180 270' -- "$cur"))
|
||||||
return
|
return
|
||||||
;;
|
;;
|
||||||
--lock-video-orientation)
|
--lock-video-orientation)
|
||||||
|
@ -124,7 +124,7 @@ Use USB device (if there is exactly one, like adb -d).
|
|||||||
Also see \fB\-e\fR (\fB\-\-select\-tcpip\fR).
|
Also see \fB\-e\fR (\fB\-\-select\-tcpip\fR).
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BI "\-\-disable\-screensaver"
|
.BI "\-\-disable-screensaver"
|
||||||
Disable screensaver while scrcpy is running.
|
Disable screensaver while scrcpy is running.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
@ -642,11 +642,7 @@ Enable/disable FPS counter (print frames/second in logs)
|
|||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B Ctrl+click-and-move
|
.B Ctrl+click-and-move
|
||||||
Pinch-to-zoom and rotate from the center of the screen
|
Pinch-to-zoom from the center of the screen
|
||||||
|
|
||||||
.TP
|
|
||||||
.B Shift+click-and-move
|
|
||||||
Tilt (slide vertically with two fingers)
|
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B Drag & drop APK file
|
.B Drag & drop APK file
|
||||||
|
@ -947,11 +947,7 @@ static const struct sc_shortcut shortcuts[] = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
.shortcuts = { "Ctrl+click-and-move" },
|
.shortcuts = { "Ctrl+click-and-move" },
|
||||||
.text = "Pinch-to-zoom and rotate from the center of the screen",
|
.text = "Pinch-to-zoom from the center of the screen",
|
||||||
},
|
|
||||||
{
|
|
||||||
.shortcuts = { "Shift+click-and-move" },
|
|
||||||
.text = "Tilt (slide vertically with two fingers)",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.shortcuts = { "Drag & drop APK file" },
|
.shortcuts = { "Drag & drop APK file" },
|
||||||
|
@ -76,8 +76,6 @@ sc_input_manager_init(struct sc_input_manager *im,
|
|||||||
im->sdl_shortcut_mods.count = shortcut_mods->count;
|
im->sdl_shortcut_mods.count = shortcut_mods->count;
|
||||||
|
|
||||||
im->vfinger_down = false;
|
im->vfinger_down = false;
|
||||||
im->vfinger_invert_x = false;
|
|
||||||
im->vfinger_invert_y = false;
|
|
||||||
|
|
||||||
im->last_keycode = SDLK_UNKNOWN;
|
im->last_keycode = SDLK_UNKNOWN;
|
||||||
im->last_mod = 0;
|
im->last_mod = 0;
|
||||||
@ -349,14 +347,9 @@ simulate_virtual_finger(struct sc_input_manager *im,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct sc_point
|
static struct sc_point
|
||||||
inverse_point(struct sc_point point, struct sc_size size,
|
inverse_point(struct sc_point point, struct sc_size size) {
|
||||||
bool invert_x, bool invert_y) {
|
point.x = size.width - point.x;
|
||||||
if (invert_x) {
|
point.y = size.height - point.y;
|
||||||
point.x = size.width - point.x;
|
|
||||||
}
|
|
||||||
if (invert_y) {
|
|
||||||
point.y = size.height - point.y;
|
|
||||||
}
|
|
||||||
return point;
|
return point;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -612,9 +605,7 @@ sc_input_manager_process_mouse_motion(struct sc_input_manager *im,
|
|||||||
struct sc_point mouse =
|
struct sc_point mouse =
|
||||||
sc_screen_convert_window_to_frame_coords(im->screen, event->x,
|
sc_screen_convert_window_to_frame_coords(im->screen, event->x,
|
||||||
event->y);
|
event->y);
|
||||||
struct sc_point vfinger = inverse_point(mouse, im->screen->frame_size,
|
struct sc_point vfinger = inverse_point(mouse, im->screen->frame_size);
|
||||||
im->vfinger_invert_x,
|
|
||||||
im->vfinger_invert_y);
|
|
||||||
simulate_virtual_finger(im, AMOTION_EVENT_ACTION_MOVE, vfinger);
|
simulate_virtual_finger(im, AMOTION_EVENT_ACTION_MOVE, vfinger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -735,7 +726,7 @@ sc_input_manager_process_mouse_button(struct sc_input_manager *im,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pinch-to-zoom, rotate and tilt simulation.
|
// Pinch-to-zoom simulation.
|
||||||
//
|
//
|
||||||
// If Ctrl is hold when the left-click button is pressed, then
|
// If Ctrl is hold when the left-click button is pressed, then
|
||||||
// pinch-to-zoom mode is enabled: on every mouse event until the left-click
|
// pinch-to-zoom mode is enabled: on every mouse event until the left-click
|
||||||
@ -744,29 +735,14 @@ sc_input_manager_process_mouse_button(struct sc_input_manager *im,
|
|||||||
//
|
//
|
||||||
// In other words, the center of the rotation/scaling is the center of the
|
// In other words, the center of the rotation/scaling is the center of the
|
||||||
// screen.
|
// screen.
|
||||||
//
|
#define CTRL_PRESSED (SDL_GetModState() & (KMOD_LCTRL | KMOD_RCTRL))
|
||||||
// To simulate a tilt gesture (a vertical slide with two fingers), Shift
|
|
||||||
// can be used instead of Ctrl. The "virtual finger" has a position
|
|
||||||
// inverted with respect to the vertical axis of symmetry in the middle of
|
|
||||||
// the screen.
|
|
||||||
const SDL_Keymod keymod = SDL_GetModState();
|
|
||||||
const bool ctrl_pressed = keymod & KMOD_CTRL;
|
|
||||||
const bool shift_pressed = keymod & KMOD_SHIFT;
|
|
||||||
if (event->button == SDL_BUTTON_LEFT &&
|
if (event->button == SDL_BUTTON_LEFT &&
|
||||||
((down && !im->vfinger_down &&
|
((down && !im->vfinger_down && CTRL_PRESSED) ||
|
||||||
((ctrl_pressed && !shift_pressed) ||
|
|
||||||
(!ctrl_pressed && shift_pressed))) ||
|
|
||||||
(!down && im->vfinger_down))) {
|
(!down && im->vfinger_down))) {
|
||||||
struct sc_point mouse =
|
struct sc_point mouse =
|
||||||
sc_screen_convert_window_to_frame_coords(im->screen, event->x,
|
sc_screen_convert_window_to_frame_coords(im->screen, event->x,
|
||||||
event->y);
|
event->y);
|
||||||
if (down) {
|
struct sc_point vfinger = inverse_point(mouse, im->screen->frame_size);
|
||||||
im->vfinger_invert_x = ctrl_pressed || shift_pressed;
|
|
||||||
im->vfinger_invert_y = ctrl_pressed;
|
|
||||||
}
|
|
||||||
struct sc_point vfinger = inverse_point(mouse, im->screen->frame_size,
|
|
||||||
im->vfinger_invert_x,
|
|
||||||
im->vfinger_invert_y);
|
|
||||||
enum android_motionevent_action action = down
|
enum android_motionevent_action action = down
|
||||||
? AMOTION_EVENT_ACTION_DOWN
|
? AMOTION_EVENT_ACTION_DOWN
|
||||||
: AMOTION_EVENT_ACTION_UP;
|
: AMOTION_EVENT_ACTION_UP;
|
||||||
|
@ -32,8 +32,6 @@ struct sc_input_manager {
|
|||||||
} sdl_shortcut_mods;
|
} sdl_shortcut_mods;
|
||||||
|
|
||||||
bool vfinger_down;
|
bool vfinger_down;
|
||||||
bool vfinger_invert_x;
|
|
||||||
bool vfinger_invert_y;
|
|
||||||
|
|
||||||
// Tracks the number of identical consecutive shortcut key down events.
|
// Tracks the number of identical consecutive shortcut key down events.
|
||||||
// Not to be confused with event->repeat, which counts the number of
|
// Not to be confused with event->repeat, which counts the number of
|
||||||
|
@ -85,7 +85,7 @@ way as <kbd>MOD</kbd>+<kbd>Shift</kbd>+<kbd>v</kbd>).
|
|||||||
To disable automatic clipboard synchronization, use
|
To disable automatic clipboard synchronization, use
|
||||||
`--no-clipboard-autosync`.
|
`--no-clipboard-autosync`.
|
||||||
|
|
||||||
## Pinch-to-zoom, rotate and tilt simulation
|
## Pinch-to-zoom
|
||||||
|
|
||||||
To simulate "pinch-to-zoom": <kbd>Ctrl</kbd>+_click-and-move_.
|
To simulate "pinch-to-zoom": <kbd>Ctrl</kbd>+_click-and-move_.
|
||||||
|
|
||||||
@ -93,12 +93,8 @@ More precisely, hold down <kbd>Ctrl</kbd> while pressing the left-click button.
|
|||||||
Until the left-click button is released, all mouse movements scale and rotate
|
Until the left-click button is released, all mouse movements scale and rotate
|
||||||
the content (if supported by the app) relative to the center of the screen.
|
the content (if supported by the app) relative to the center of the screen.
|
||||||
|
|
||||||
To simulate a tilt gesture: <kbd>Shift</kbd>+_click-and-move-up-or-down_.
|
|
||||||
|
|
||||||
Technically, _scrcpy_ generates additional touch events from a "virtual finger"
|
Technically, _scrcpy_ generates additional touch events from a "virtual finger"
|
||||||
at a location inverted through the center of the screen. When pressing
|
at a location inverted through the center of the screen.
|
||||||
<kbd>Ctrl</kbd> the x and y coordinates are inverted. Using <kbd>Shift</kbd>
|
|
||||||
only inverts x.
|
|
||||||
|
|
||||||
|
|
||||||
## Key repeat
|
## Key repeat
|
||||||
|
@ -49,8 +49,7 @@ _<kbd>[Super]</kbd> is typically the <kbd>Windows</kbd> or <kbd>Cmd</kbd> key._
|
|||||||
| Synchronize clipboards and paste⁵ | <kbd>MOD</kbd>+<kbd>v</kbd>
|
| Synchronize clipboards and paste⁵ | <kbd>MOD</kbd>+<kbd>v</kbd>
|
||||||
| Inject computer clipboard text | <kbd>MOD</kbd>+<kbd>Shift</kbd>+<kbd>v</kbd>
|
| Inject computer clipboard text | <kbd>MOD</kbd>+<kbd>Shift</kbd>+<kbd>v</kbd>
|
||||||
| Enable/disable FPS counter (on stdout) | <kbd>MOD</kbd>+<kbd>i</kbd>
|
| Enable/disable FPS counter (on stdout) | <kbd>MOD</kbd>+<kbd>i</kbd>
|
||||||
| Pinch-to-zoom/rotate | <kbd>Ctrl</kbd>+_click-and-move_
|
| Pinch-to-zoom | <kbd>Ctrl</kbd>+_click-and-move_
|
||||||
| Tilt (slide vertically with 2 fingers) | <kbd>Shift</kbd>+_click-and-move_
|
|
||||||
| Drag & drop APK file | Install APK from computer
|
| Drag & drop APK file | Install APK from computer
|
||||||
| Drag & drop non-APK file | [Push file to device](control.md#push-file-to-device)
|
| Drag & drop non-APK file | [Push file to device](control.md#push-file-to-device)
|
||||||
|
|
||||||
|
@ -153,14 +153,13 @@ public final class AudioCapture {
|
|||||||
previousRecorderTimestamp = timestamp.nanoTime;
|
previousRecorderTimestamp = timestamp.nanoTime;
|
||||||
} else {
|
} else {
|
||||||
if (nextPts == 0) {
|
if (nextPts == 0) {
|
||||||
Ln.w("Could not get initial audio timestamp");
|
Ln.w("Could not get any audio timestamp");
|
||||||
nextPts = System.nanoTime() / 1000;
|
|
||||||
}
|
}
|
||||||
// compute from previous timestamp and packet size
|
// compute from previous timestamp and packet size
|
||||||
pts = nextPts;
|
pts = nextPts;
|
||||||
}
|
}
|
||||||
|
|
||||||
long durationUs = r * 1000000L / (CHANNELS * BYTES_PER_SAMPLE * SAMPLE_RATE);
|
long durationUs = r * 1000000 / (CHANNELS * BYTES_PER_SAMPLE * SAMPLE_RATE);
|
||||||
nextPts = pts + durationUs;
|
nextPts = pts + durationUs;
|
||||||
|
|
||||||
if (previousPts != 0 && pts < previousPts + ONE_SAMPLE_US) {
|
if (previousPts != 0 && pts < previousPts + ONE_SAMPLE_US) {
|
||||||
|
@ -187,7 +187,5 @@ public final class CleanUp {
|
|||||||
Device.setScreenPowerMode(Device.POWER_MODE_NORMAL);
|
Device.setScreenPowerMode(Device.POWER_MODE_NORMAL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
System.exit(0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,11 +45,11 @@ public final class Device {
|
|||||||
void onClipboardTextChanged(String text);
|
void onClipboardTextChanged(String text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final Size deviceSize;
|
||||||
private final Rect crop;
|
private final Rect crop;
|
||||||
private int maxSize;
|
private int maxSize;
|
||||||
private final int lockVideoOrientation;
|
private final int lockVideoOrientation;
|
||||||
|
|
||||||
private Size deviceSize;
|
|
||||||
private ScreenInfo screenInfo;
|
private ScreenInfo screenInfo;
|
||||||
private RotationListener rotationListener;
|
private RotationListener rotationListener;
|
||||||
private FoldListener foldListener;
|
private FoldListener foldListener;
|
||||||
@ -116,8 +116,8 @@ public final class Device {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
deviceSize = displayInfo.getSize();
|
screenInfo = ScreenInfo.computeScreenInfo(displayInfo.getRotation(), displayInfo.getSize(), options.getCrop(),
|
||||||
screenInfo = ScreenInfo.computeScreenInfo(displayInfo.getRotation(), deviceSize, crop, maxSize, lockVideoOrientation);
|
options.getMaxSize(), options.getLockVideoOrientation());
|
||||||
// notify
|
// notify
|
||||||
if (foldListener != null) {
|
if (foldListener != null) {
|
||||||
foldListener.onFoldChanged(displayId, folded);
|
foldListener.onFoldChanged(displayId, folded);
|
||||||
@ -164,6 +164,10 @@ public final class Device {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getDisplayId() {
|
||||||
|
return displayId;
|
||||||
|
}
|
||||||
|
|
||||||
public synchronized void setMaxSize(int newMaxSize) {
|
public synchronized void setMaxSize(int newMaxSize) {
|
||||||
maxSize = newMaxSize;
|
maxSize = newMaxSize;
|
||||||
screenInfo = ScreenInfo.computeScreenInfo(screenInfo.getReverseVideoRotation(), deviceSize, crop, newMaxSize, lockVideoOrientation);
|
screenInfo = ScreenInfo.computeScreenInfo(screenInfo.getReverseVideoRotation(), deviceSize, crop, newMaxSize, lockVideoOrientation);
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
package com.genymobile.scrcpy;
|
package com.genymobile.scrcpy;
|
||||||
|
|
||||||
|
import com.genymobile.scrcpy.wrappers.ServiceManager;
|
||||||
import com.genymobile.scrcpy.wrappers.SurfaceControl;
|
import com.genymobile.scrcpy.wrappers.SurfaceControl;
|
||||||
|
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
|
import android.hardware.display.VirtualDisplay;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
@ -11,6 +13,7 @@ public class ScreenCapture extends SurfaceCapture implements Device.RotationList
|
|||||||
|
|
||||||
private final Device device;
|
private final Device device;
|
||||||
private IBinder display;
|
private IBinder display;
|
||||||
|
private VirtualDisplay virtualDisplay;
|
||||||
|
|
||||||
public ScreenCapture(Device device) {
|
public ScreenCapture(Device device) {
|
||||||
this.device = device;
|
this.device = device;
|
||||||
@ -34,9 +37,29 @@ public class ScreenCapture extends SurfaceCapture implements Device.RotationList
|
|||||||
|
|
||||||
if (display != null) {
|
if (display != null) {
|
||||||
SurfaceControl.destroyDisplay(display);
|
SurfaceControl.destroyDisplay(display);
|
||||||
|
display = null;
|
||||||
|
}
|
||||||
|
if (virtualDisplay != null) {
|
||||||
|
virtualDisplay.release();
|
||||||
|
virtualDisplay = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
display = createDisplay();
|
||||||
|
setDisplaySurface(display, surface, videoRotation, contentRect, unlockedVideoRect, layerStack);
|
||||||
|
Ln.d("Display: using SurfaceControl API");
|
||||||
|
} catch (Exception surfaceControlException) {
|
||||||
|
Rect videoRect = screenInfo.getVideoSize().toRect();
|
||||||
|
try {
|
||||||
|
virtualDisplay = ServiceManager.getDisplayManager()
|
||||||
|
.createVirtualDisplay("scrcpy", videoRect.width(), videoRect.height(), device.getDisplayId(), surface);
|
||||||
|
Ln.d("Display: using DisplayManager API");
|
||||||
|
} catch (Exception displayManagerException) {
|
||||||
|
Ln.e("Could not create display using SurfaceControl", surfaceControlException);
|
||||||
|
Ln.e("Could not create display using DisplayManager", displayManagerException);
|
||||||
|
throw new AssertionError("Could not create display");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
display = createDisplay();
|
|
||||||
setDisplaySurface(display, surface, videoRotation, contentRect, unlockedVideoRect, layerStack);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -69,7 +92,7 @@ public class ScreenCapture extends SurfaceCapture implements Device.RotationList
|
|||||||
requestReset();
|
requestReset();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IBinder createDisplay() {
|
private static IBinder createDisplay() throws Exception {
|
||||||
// Since Android 12 (preview), secure displays could not be created with shell permissions anymore.
|
// Since Android 12 (preview), secure displays could not be created with shell permissions anymore.
|
||||||
// On Android 12 preview, SDK_INT is still R (not S), but CODENAME is "S".
|
// 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(
|
boolean secure = Build.VERSION.SDK_INT < Build.VERSION_CODES.R || (Build.VERSION.SDK_INT == Build.VERSION_CODES.R && !"S".equals(
|
||||||
|
@ -285,28 +285,16 @@ public final class Workarounds {
|
|||||||
Method getParcelMethod = attributionSourceState.getClass().getDeclaredMethod("getParcel");
|
Method getParcelMethod = attributionSourceState.getClass().getDeclaredMethod("getParcel");
|
||||||
Parcel attributionSourceParcel = (Parcel) getParcelMethod.invoke(attributionSourceState);
|
Parcel attributionSourceParcel = (Parcel) getParcelMethod.invoke(attributionSourceState);
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
|
// private native int native_setup(Object audiorecordThis,
|
||||||
// private native int native_setup(Object audiorecordThis,
|
// Object /*AudioAttributes*/ attributes,
|
||||||
// Object /*AudioAttributes*/ attributes,
|
// int[] sampleRate, int channelMask, int channelIndexMask, int audioFormat,
|
||||||
// int[] sampleRate, int channelMask, int channelIndexMask, int audioFormat,
|
// int buffSizeInBytes, int[] sessionId, @NonNull Parcel attributionSource,
|
||||||
// int buffSizeInBytes, int[] sessionId, @NonNull Parcel attributionSource,
|
// long nativeRecordInJavaObj, int maxSharedAudioHistoryMs);
|
||||||
// long nativeRecordInJavaObj, int maxSharedAudioHistoryMs);
|
Method nativeSetupMethod = AudioRecord.class.getDeclaredMethod("native_setup", Object.class, Object.class, int[].class, int.class,
|
||||||
Method nativeSetupMethod = AudioRecord.class.getDeclaredMethod("native_setup", Object.class, Object.class, int[].class,
|
int.class, int.class, int.class, int[].class, Parcel.class, long.class, int.class);
|
||||||
int.class, int.class, int.class, int.class, int[].class, Parcel.class, long.class, int.class);
|
nativeSetupMethod.setAccessible(true);
|
||||||
nativeSetupMethod.setAccessible(true);
|
initResult = (int) nativeSetupMethod.invoke(audioRecord, new WeakReference<AudioRecord>(audioRecord), attributes, sampleRateArray,
|
||||||
initResult = (int) nativeSetupMethod.invoke(audioRecord, new WeakReference<AudioRecord>(audioRecord), attributes,
|
channelMask, channelIndexMask, audioRecord.getAudioFormat(), bufferSizeInBytes, session, attributionSourceParcel, 0L, 0);
|
||||||
sampleRateArray, channelMask, channelIndexMask, audioRecord.getAudioFormat(), bufferSizeInBytes, session,
|
|
||||||
attributionSourceParcel, 0L, 0);
|
|
||||||
} else {
|
|
||||||
// Android 14 added a new int parameter "halInputFlags"
|
|
||||||
// <https://github.com/aosp-mirror/platform_frameworks_base/commit/f6135d75db79b1d48fad3a3b3080d37be20a2313>
|
|
||||||
Method nativeSetupMethod = AudioRecord.class.getDeclaredMethod("native_setup", Object.class, Object.class, int[].class,
|
|
||||||
int.class, int.class, int.class, int.class, int[].class, Parcel.class, long.class, int.class, int.class);
|
|
||||||
nativeSetupMethod.setAccessible(true);
|
|
||||||
initResult = (int) nativeSetupMethod.invoke(audioRecord, new WeakReference<AudioRecord>(audioRecord), attributes,
|
|
||||||
sampleRateArray, channelMask, channelIndexMask, audioRecord.getAudioFormat(), bufferSizeInBytes, session,
|
|
||||||
attributionSourceParcel, 0L, 0, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,14 +41,8 @@ public final class ClipboardManager {
|
|||||||
getPrimaryClipMethod = manager.getClass().getMethod("getPrimaryClip", String.class, String.class, int.class, int.class);
|
getPrimaryClipMethod = manager.getClass().getMethod("getPrimaryClip", String.class, String.class, int.class, int.class);
|
||||||
getMethodVersion = 2;
|
getMethodVersion = 2;
|
||||||
} catch (NoSuchMethodException e3) {
|
} catch (NoSuchMethodException e3) {
|
||||||
try {
|
getPrimaryClipMethod = manager.getClass().getMethod("getPrimaryClip", String.class, int.class, String.class);
|
||||||
getPrimaryClipMethod = manager.getClass().getMethod("getPrimaryClip", String.class, int.class, String.class);
|
getMethodVersion = 3;
|
||||||
getMethodVersion = 3;
|
|
||||||
} catch (NoSuchMethodException e4) {
|
|
||||||
getPrimaryClipMethod = manager.getClass()
|
|
||||||
.getMethod("getPrimaryClip", String.class, String.class, int.class, int.class, boolean.class);
|
|
||||||
getMethodVersion = 4;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -93,11 +87,8 @@ public final class ClipboardManager {
|
|||||||
return (ClipData) method.invoke(manager, FakeContext.PACKAGE_NAME, null, FakeContext.ROOT_UID);
|
return (ClipData) method.invoke(manager, FakeContext.PACKAGE_NAME, null, FakeContext.ROOT_UID);
|
||||||
case 2:
|
case 2:
|
||||||
return (ClipData) method.invoke(manager, FakeContext.PACKAGE_NAME, null, FakeContext.ROOT_UID, 0);
|
return (ClipData) method.invoke(manager, FakeContext.PACKAGE_NAME, null, FakeContext.ROOT_UID, 0);
|
||||||
case 3:
|
|
||||||
return (ClipData) method.invoke(manager, FakeContext.PACKAGE_NAME, FakeContext.ROOT_UID, null);
|
|
||||||
default:
|
default:
|
||||||
// The last boolean parameter is "userOperate"
|
return (ClipData) method.invoke(manager, FakeContext.PACKAGE_NAME, FakeContext.ROOT_UID, null);
|
||||||
return (ClipData) method.invoke(manager, FakeContext.PACKAGE_NAME, null, FakeContext.ROOT_UID, 0, true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,14 +5,18 @@ import com.genymobile.scrcpy.DisplayInfo;
|
|||||||
import com.genymobile.scrcpy.Ln;
|
import com.genymobile.scrcpy.Ln;
|
||||||
import com.genymobile.scrcpy.Size;
|
import com.genymobile.scrcpy.Size;
|
||||||
|
|
||||||
|
import android.hardware.display.VirtualDisplay;
|
||||||
import android.view.Display;
|
import android.view.Display;
|
||||||
|
import android.view.Surface;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
public final class DisplayManager {
|
public final class DisplayManager {
|
||||||
private final Object manager; // instance of hidden class android.hardware.display.DisplayManagerGlobal
|
private final Object manager; // instance of hidden class android.hardware.display.DisplayManagerGlobal
|
||||||
|
private Method createVirtualDisplayMethod;
|
||||||
|
|
||||||
public DisplayManager(Object manager) {
|
public DisplayManager(Object manager) {
|
||||||
this.manager = manager;
|
this.manager = manager;
|
||||||
@ -94,4 +98,17 @@ public final class DisplayManager {
|
|||||||
throw new AssertionError(e);
|
throw new AssertionError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Method getCreateVirtualDisplayMethod() throws NoSuchMethodException {
|
||||||
|
if (createVirtualDisplayMethod == null) {
|
||||||
|
createVirtualDisplayMethod = android.hardware.display.DisplayManager.class
|
||||||
|
.getMethod("createVirtualDisplay", String.class, int.class, int.class, int.class, Surface.class);
|
||||||
|
}
|
||||||
|
return createVirtualDisplayMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VirtualDisplay createVirtualDisplay(String name, int width, int height, int displayIdToMirror, Surface surface) throws Exception {
|
||||||
|
Method method = getCreateVirtualDisplayMethod();
|
||||||
|
return (VirtualDisplay) method.invoke(null, name, width, height, displayIdToMirror, surface);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,12 +78,8 @@ public final class SurfaceControl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IBinder createDisplay(String name, boolean secure) {
|
public static IBinder createDisplay(String name, boolean secure) throws Exception {
|
||||||
try {
|
return (IBinder) CLASS.getMethod("createDisplay", String.class, boolean.class).invoke(null, name, secure);
|
||||||
return (IBinder) CLASS.getMethod("createDisplay", String.class, boolean.class).invoke(null, name, secure);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Method getGetBuiltInDisplayMethod() throws NoSuchMethodException {
|
private static Method getGetBuiltInDisplayMethod() throws NoSuchMethodException {
|
||||||
|
Reference in New Issue
Block a user