Use explicit constants for Android versions
Who remembers code names? This avoids to check the mapping every time.
This commit is contained in:
parent
e33be3d288
commit
3acffaae57
@ -0,0 +1,32 @@
|
|||||||
|
package com.genymobile.scrcpy;
|
||||||
|
|
||||||
|
import android.os.Build;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Android version code constants, done right.
|
||||||
|
* <p/>
|
||||||
|
* <a href="https://apilevels.com/">API levels</a>
|
||||||
|
*/
|
||||||
|
public final class AndroidVersions {
|
||||||
|
|
||||||
|
private AndroidVersions() {
|
||||||
|
// not instantiable
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final int API_20_ANDROID_4_4 = Build.VERSION_CODES.KITKAT_WATCH;
|
||||||
|
public static final int API_21_ANDROID_5_0 = Build.VERSION_CODES.LOLLIPOP;
|
||||||
|
public static final int API_22_ANDROID_5_1 = Build.VERSION_CODES.LOLLIPOP_MR1;
|
||||||
|
public static final int API_23_ANDROID_6_0 = Build.VERSION_CODES.M;
|
||||||
|
public static final int API_24_ANDROID_7_0 = Build.VERSION_CODES.N;
|
||||||
|
public static final int API_25_ANDROID_7_1 = Build.VERSION_CODES.N_MR1;
|
||||||
|
public static final int API_26_ANDROID_8_0 = Build.VERSION_CODES.O;
|
||||||
|
public static final int API_27_ANDROID_8_1 = Build.VERSION_CODES.O_MR1;
|
||||||
|
public static final int API_28_ANDROID_9 = Build.VERSION_CODES.P;
|
||||||
|
public static final int API_29_ANDROID_10 = Build.VERSION_CODES.Q;
|
||||||
|
public static final int API_30_ANDROID_11 = Build.VERSION_CODES.R;
|
||||||
|
public static final int API_31_ANDROID_12 = Build.VERSION_CODES.S;
|
||||||
|
public static final int API_32_ANDROID_12L = Build.VERSION_CODES.S_V2;
|
||||||
|
public static final int API_33_ANDROID_13 = Build.VERSION_CODES.TIRAMISU;
|
||||||
|
public static final int API_34_ANDROID_14 = Build.VERSION_CODES.UPSIDE_DOWN_CAKE;
|
||||||
|
|
||||||
|
}
|
@ -4,7 +4,6 @@ import android.annotation.TargetApi;
|
|||||||
import android.content.AttributionSource;
|
import android.content.AttributionSource;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.ContextWrapper;
|
import android.content.ContextWrapper;
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
|
|
||||||
public final class FakeContext extends ContextWrapper {
|
public final class FakeContext extends ContextWrapper {
|
||||||
@ -32,7 +31,7 @@ public final class FakeContext extends ContextWrapper {
|
|||||||
return PACKAGE_NAME;
|
return PACKAGE_NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.S)
|
@TargetApi(AndroidVersions.API_31_ANDROID_12)
|
||||||
@Override
|
@Override
|
||||||
public AttributionSource getAttributionSource() {
|
public AttributionSource getAttributionSource() {
|
||||||
AttributionSource.Builder builder = new AttributionSource.Builder(Process.SHELL_UID);
|
AttributionSource.Builder builder = new AttributionSource.Builder(Process.SHELL_UID);
|
||||||
|
@ -121,7 +121,7 @@ public final class Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void scrcpy(Options options) throws IOException, ConfigurationException {
|
private static void scrcpy(Options options) throws IOException, ConfigurationException {
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S && options.getVideoSource() == VideoSource.CAMERA) {
|
if (Build.VERSION.SDK_INT < AndroidVersions.API_31_ANDROID_12 && options.getVideoSource() == VideoSource.CAMERA) {
|
||||||
Ln.e("Camera mirroring is not supported before Android 12");
|
Ln.e("Camera mirroring is not supported before Android 12");
|
||||||
throw new ConfigurationException("Camera mirroring is not supported");
|
throw new ConfigurationException("Camera mirroring is not supported");
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ public final class Workarounds {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void apply() {
|
public static void apply() {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
if (Build.VERSION.SDK_INT >= AndroidVersions.API_31_ANDROID_12) {
|
||||||
// On some Samsung devices, DisplayManagerGlobal.getDisplayInfoLocked() calls ActivityThread.currentActivityThread().getConfiguration(),
|
// On some Samsung devices, DisplayManagerGlobal.getDisplayInfoLocked() calls ActivityThread.currentActivityThread().getConfiguration(),
|
||||||
// which requires a non-null ConfigurationController.
|
// which requires a non-null ConfigurationController.
|
||||||
// ConfigurationController was introduced in Android 12, so do not attempt to set it on lower versions.
|
// ConfigurationController was introduced in Android 12, so do not attempt to set it on lower versions.
|
||||||
@ -155,7 +155,7 @@ public final class Workarounds {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.R)
|
@TargetApi(AndroidVersions.API_30_ANDROID_11)
|
||||||
@SuppressLint("WrongConstant,MissingPermission")
|
@SuppressLint("WrongConstant,MissingPermission")
|
||||||
public static AudioRecord createAudioRecord(int source, int sampleRate, int channelConfig, int channels, int channelMask, int encoding) throws
|
public static AudioRecord createAudioRecord(int source, int sampleRate, int channelConfig, int channels, int channelMask, int encoding) throws
|
||||||
AudioCaptureException {
|
AudioCaptureException {
|
||||||
@ -226,7 +226,7 @@ public final class Workarounds {
|
|||||||
int[] session = new int[]{AudioManager.AUDIO_SESSION_ID_GENERATE};
|
int[] session = new int[]{AudioManager.AUDIO_SESSION_ID_GENERATE};
|
||||||
|
|
||||||
int initResult;
|
int initResult;
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
|
if (Build.VERSION.SDK_INT < AndroidVersions.API_31_ANDROID_12) {
|
||||||
// private native final int native_setup(Object audiorecord_this,
|
// private native final int native_setup(Object audiorecord_this,
|
||||||
// Object /*AudioAttributes*/ attributes,
|
// Object /*AudioAttributes*/ attributes,
|
||||||
// int[] sampleRate, int channelMask, int channelIndexMask, int audioFormat,
|
// int[] sampleRate, int channelMask, int channelIndexMask, int audioFormat,
|
||||||
@ -252,7 +252,7 @@ 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) {
|
if (Build.VERSION.SDK_INT < AndroidVersions.API_34_ANDROID_14) {
|
||||||
// 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,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.genymobile.scrcpy.audio;
|
package com.genymobile.scrcpy.audio;
|
||||||
|
|
||||||
|
import com.genymobile.scrcpy.AndroidVersions;
|
||||||
import com.genymobile.scrcpy.FakeContext;
|
import com.genymobile.scrcpy.FakeContext;
|
||||||
import com.genymobile.scrcpy.Workarounds;
|
import com.genymobile.scrcpy.Workarounds;
|
||||||
import com.genymobile.scrcpy.util.Ln;
|
import com.genymobile.scrcpy.util.Ln;
|
||||||
@ -45,11 +46,11 @@ public class AudioDirectCapture implements AudioCapture {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.M)
|
@TargetApi(AndroidVersions.API_23_ANDROID_6_0)
|
||||||
@SuppressLint({"WrongConstant", "MissingPermission"})
|
@SuppressLint({"WrongConstant", "MissingPermission"})
|
||||||
private static AudioRecord createAudioRecord(int audioSource) {
|
private static AudioRecord createAudioRecord(int audioSource) {
|
||||||
AudioRecord.Builder builder = new AudioRecord.Builder();
|
AudioRecord.Builder builder = new AudioRecord.Builder();
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
if (Build.VERSION.SDK_INT >= AndroidVersions.API_31_ANDROID_12) {
|
||||||
// On older APIs, Workarounds.fillAppInfo() must be called beforehand
|
// On older APIs, Workarounds.fillAppInfo() must be called beforehand
|
||||||
builder.setContext(FakeContext.get());
|
builder.setContext(FakeContext.get());
|
||||||
}
|
}
|
||||||
@ -117,7 +118,7 @@ public class AudioDirectCapture implements AudioCapture {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void checkCompatibility() throws AudioCaptureException {
|
public void checkCompatibility() throws AudioCaptureException {
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
|
if (Build.VERSION.SDK_INT < AndroidVersions.API_30_ANDROID_11) {
|
||||||
Ln.w("Audio disabled: it is not supported before Android 11");
|
Ln.w("Audio disabled: it is not supported before Android 11");
|
||||||
throw new AudioCaptureException();
|
throw new AudioCaptureException();
|
||||||
}
|
}
|
||||||
@ -125,7 +126,7 @@ public class AudioDirectCapture implements AudioCapture {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start() throws AudioCaptureException {
|
public void start() throws AudioCaptureException {
|
||||||
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.R) {
|
if (Build.VERSION.SDK_INT == AndroidVersions.API_30_ANDROID_11) {
|
||||||
startWorkaroundAndroid11();
|
startWorkaroundAndroid11();
|
||||||
try {
|
try {
|
||||||
tryStartRecording(5, 100);
|
tryStartRecording(5, 100);
|
||||||
@ -146,7 +147,7 @@ public class AudioDirectCapture implements AudioCapture {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@TargetApi(Build.VERSION_CODES.N)
|
@TargetApi(AndroidVersions.API_24_ANDROID_7_0)
|
||||||
public int read(ByteBuffer outDirectBuffer, MediaCodec.BufferInfo outBufferInfo) {
|
public int read(ByteBuffer outDirectBuffer, MediaCodec.BufferInfo outBufferInfo) {
|
||||||
return reader.read(outDirectBuffer, outBufferInfo);
|
return reader.read(outDirectBuffer, outBufferInfo);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.genymobile.scrcpy.audio;
|
package com.genymobile.scrcpy.audio;
|
||||||
|
|
||||||
|
import com.genymobile.scrcpy.AndroidVersions;
|
||||||
import com.genymobile.scrcpy.AsyncProcessor;
|
import com.genymobile.scrcpy.AsyncProcessor;
|
||||||
import com.genymobile.scrcpy.device.ConfigurationException;
|
import com.genymobile.scrcpy.device.ConfigurationException;
|
||||||
import com.genymobile.scrcpy.device.Streamer;
|
import com.genymobile.scrcpy.device.Streamer;
|
||||||
@ -93,7 +94,7 @@ public final class AudioEncoder implements AsyncProcessor {
|
|||||||
return format;
|
return format;
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.N)
|
@TargetApi(AndroidVersions.API_24_ANDROID_7_0)
|
||||||
private void inputThread(MediaCodec mediaCodec, AudioCapture capture) throws IOException, InterruptedException {
|
private void inputThread(MediaCodec mediaCodec, AudioCapture capture) throws IOException, InterruptedException {
|
||||||
final MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
|
final MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
|
||||||
|
|
||||||
@ -175,9 +176,9 @@ public final class AudioEncoder implements AsyncProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.M)
|
@TargetApi(AndroidVersions.API_23_ANDROID_6_0)
|
||||||
private void encode() throws IOException, ConfigurationException, AudioCaptureException {
|
private void encode() throws IOException, ConfigurationException, AudioCaptureException {
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
|
if (Build.VERSION.SDK_INT < AndroidVersions.API_30_ANDROID_11) {
|
||||||
Ln.w("Audio disabled: it is not supported before Android 11");
|
Ln.w("Audio disabled: it is not supported before Android 11");
|
||||||
streamer.writeDisableStream(false);
|
streamer.writeDisableStream(false);
|
||||||
return;
|
return;
|
||||||
@ -314,7 +315,7 @@ public final class AudioEncoder implements AsyncProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final class EncoderCallback extends MediaCodec.Callback {
|
private final class EncoderCallback extends MediaCodec.Callback {
|
||||||
@TargetApi(Build.VERSION_CODES.N)
|
@TargetApi(AndroidVersions.API_24_ANDROID_7_0)
|
||||||
@Override
|
@Override
|
||||||
public void onInputBufferAvailable(MediaCodec codec, int index) {
|
public void onInputBufferAvailable(MediaCodec codec, int index) {
|
||||||
try {
|
try {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.genymobile.scrcpy.audio;
|
package com.genymobile.scrcpy.audio;
|
||||||
|
|
||||||
|
import com.genymobile.scrcpy.AndroidVersions;
|
||||||
import com.genymobile.scrcpy.FakeContext;
|
import com.genymobile.scrcpy.FakeContext;
|
||||||
import com.genymobile.scrcpy.util.Ln;
|
import com.genymobile.scrcpy.util.Ln;
|
||||||
|
|
||||||
@ -108,7 +109,7 @@ public final class AudioPlaybackCapture implements AudioCapture {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void checkCompatibility() throws AudioCaptureException {
|
public void checkCompatibility() throws AudioCaptureException {
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
|
if (Build.VERSION.SDK_INT < AndroidVersions.API_33_ANDROID_13) {
|
||||||
Ln.w("Audio disabled: audio playback capture source not supported before Android 13");
|
Ln.w("Audio disabled: audio playback capture source not supported before Android 13");
|
||||||
throw new AudioCaptureException();
|
throw new AudioCaptureException();
|
||||||
}
|
}
|
||||||
@ -130,7 +131,7 @@ public final class AudioPlaybackCapture implements AudioCapture {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@TargetApi(Build.VERSION_CODES.N)
|
@TargetApi(AndroidVersions.API_24_ANDROID_7_0)
|
||||||
public int read(ByteBuffer outDirectBuffer, MediaCodec.BufferInfo outBufferInfo) {
|
public int read(ByteBuffer outDirectBuffer, MediaCodec.BufferInfo outBufferInfo) {
|
||||||
return reader.read(outDirectBuffer, outBufferInfo);
|
return reader.read(outDirectBuffer, outBufferInfo);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.genymobile.scrcpy.audio;
|
package com.genymobile.scrcpy.audio;
|
||||||
|
|
||||||
|
import com.genymobile.scrcpy.AndroidVersions;
|
||||||
import com.genymobile.scrcpy.AsyncProcessor;
|
import com.genymobile.scrcpy.AsyncProcessor;
|
||||||
import com.genymobile.scrcpy.device.Streamer;
|
import com.genymobile.scrcpy.device.Streamer;
|
||||||
import com.genymobile.scrcpy.util.IO;
|
import com.genymobile.scrcpy.util.IO;
|
||||||
@ -24,7 +25,7 @@ public final class AudioRawRecorder implements AsyncProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void record() throws IOException, AudioCaptureException {
|
private void record() throws IOException, AudioCaptureException {
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
|
if (Build.VERSION.SDK_INT < AndroidVersions.API_30_ANDROID_11) {
|
||||||
Ln.w("Audio disabled: it is not supported before Android 11");
|
Ln.w("Audio disabled: it is not supported before Android 11");
|
||||||
streamer.writeDisableStream(false);
|
streamer.writeDisableStream(false);
|
||||||
return;
|
return;
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
package com.genymobile.scrcpy.audio;
|
package com.genymobile.scrcpy.audio;
|
||||||
|
|
||||||
|
import com.genymobile.scrcpy.AndroidVersions;
|
||||||
import com.genymobile.scrcpy.util.Ln;
|
import com.genymobile.scrcpy.util.Ln;
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
import android.media.AudioRecord;
|
import android.media.AudioRecord;
|
||||||
import android.media.AudioTimestamp;
|
import android.media.AudioTimestamp;
|
||||||
import android.media.MediaCodec;
|
import android.media.MediaCodec;
|
||||||
import android.os.Build;
|
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ public class AudioRecordReader {
|
|||||||
this.recorder = recorder;
|
this.recorder = recorder;
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.N)
|
@TargetApi(AndroidVersions.API_24_ANDROID_7_0)
|
||||||
public int read(ByteBuffer outDirectBuffer, MediaCodec.BufferInfo outBufferInfo) {
|
public int read(ByteBuffer outDirectBuffer, MediaCodec.BufferInfo outBufferInfo) {
|
||||||
int r = recorder.read(outDirectBuffer, AudioConfig.MAX_READ_SIZE);
|
int r = recorder.read(outDirectBuffer, AudioConfig.MAX_READ_SIZE);
|
||||||
if (r <= 0) {
|
if (r <= 0) {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.genymobile.scrcpy.control;
|
package com.genymobile.scrcpy.control;
|
||||||
|
|
||||||
|
import com.genymobile.scrcpy.AndroidVersions;
|
||||||
import com.genymobile.scrcpy.AsyncProcessor;
|
import com.genymobile.scrcpy.AsyncProcessor;
|
||||||
import com.genymobile.scrcpy.CleanUp;
|
import com.genymobile.scrcpy.CleanUp;
|
||||||
import com.genymobile.scrcpy.device.Device;
|
import com.genymobile.scrcpy.device.Device;
|
||||||
@ -318,7 +319,7 @@ public class Controller implements AsyncProcessor {
|
|||||||
*
|
*
|
||||||
* Otherwise, Chrome does not work properly: <https://github.com/Genymobile/scrcpy/issues/3635>
|
* Otherwise, Chrome does not work properly: <https://github.com/Genymobile/scrcpy/issues/3635>
|
||||||
*/
|
*/
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && source == InputDevice.SOURCE_MOUSE) {
|
if (Build.VERSION.SDK_INT >= AndroidVersions.API_23_ANDROID_6_0 && source == InputDevice.SOURCE_MOUSE) {
|
||||||
if (action == MotionEvent.ACTION_DOWN) {
|
if (action == MotionEvent.ACTION_DOWN) {
|
||||||
if (actionButton == buttons) {
|
if (actionButton == buttons) {
|
||||||
// First button pressed: ACTION_DOWN
|
// First button pressed: ACTION_DOWN
|
||||||
@ -423,7 +424,7 @@ public class Controller implements AsyncProcessor {
|
|||||||
|
|
||||||
private void getClipboard(int copyKey) {
|
private void getClipboard(int copyKey) {
|
||||||
// On Android >= 7, press the COPY or CUT key if requested
|
// On Android >= 7, press the COPY or CUT key if requested
|
||||||
if (copyKey != ControlMessage.COPY_KEY_NONE && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && device.supportsInputEvents()) {
|
if (copyKey != ControlMessage.COPY_KEY_NONE && Build.VERSION.SDK_INT >= AndroidVersions.API_24_ANDROID_7_0 && device.supportsInputEvents()) {
|
||||||
int key = copyKey == ControlMessage.COPY_KEY_COPY ? KeyEvent.KEYCODE_COPY : KeyEvent.KEYCODE_CUT;
|
int key = copyKey == ControlMessage.COPY_KEY_COPY ? KeyEvent.KEYCODE_COPY : KeyEvent.KEYCODE_CUT;
|
||||||
// Wait until the event is finished, to ensure that the clipboard text we read just after is the correct one
|
// Wait until the event is finished, to ensure that the clipboard text we read just after is the correct one
|
||||||
device.pressReleaseKeycode(key, Device.INJECT_MODE_WAIT_FOR_FINISH);
|
device.pressReleaseKeycode(key, Device.INJECT_MODE_WAIT_FOR_FINISH);
|
||||||
@ -448,7 +449,7 @@ public class Controller implements AsyncProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// On Android >= 7, also press the PASTE key if requested
|
// On Android >= 7, also press the PASTE key if requested
|
||||||
if (paste && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && device.supportsInputEvents()) {
|
if (paste && Build.VERSION.SDK_INT >= AndroidVersions.API_24_ANDROID_7_0 && device.supportsInputEvents()) {
|
||||||
device.pressReleaseKeycode(KeyEvent.KEYCODE_PASTE, Device.INJECT_MODE_ASYNC);
|
device.pressReleaseKeycode(KeyEvent.KEYCODE_PASTE, Device.INJECT_MODE_ASYNC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.genymobile.scrcpy.control;
|
package com.genymobile.scrcpy.control;
|
||||||
|
|
||||||
|
import com.genymobile.scrcpy.AndroidVersions;
|
||||||
import com.genymobile.scrcpy.util.Ln;
|
import com.genymobile.scrcpy.util.Ln;
|
||||||
import com.genymobile.scrcpy.util.StringUtils;
|
import com.genymobile.scrcpy.util.StringUtils;
|
||||||
|
|
||||||
@ -38,7 +39,7 @@ public final class UhidManager {
|
|||||||
|
|
||||||
public UhidManager(DeviceMessageSender sender) {
|
public UhidManager(DeviceMessageSender sender) {
|
||||||
this.sender = sender;
|
this.sender = sender;
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT >= AndroidVersions.API_23_ANDROID_6_0) {
|
||||||
HandlerThread thread = new HandlerThread("UHidManager");
|
HandlerThread thread = new HandlerThread("UHidManager");
|
||||||
thread.start();
|
thread.start();
|
||||||
queue = thread.getLooper().getQueue();
|
queue = thread.getLooper().getQueue();
|
||||||
@ -71,7 +72,7 @@ public final class UhidManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void registerUhidListener(int id, FileDescriptor fd) {
|
private void registerUhidListener(int id, FileDescriptor fd) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT >= AndroidVersions.API_23_ANDROID_6_0) {
|
||||||
queue.addOnFileDescriptorEventListener(fd, MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT, (fd2, events) -> {
|
queue.addOnFileDescriptorEventListener(fd, MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT, (fd2, events) -> {
|
||||||
try {
|
try {
|
||||||
buffer.clear();
|
buffer.clear();
|
||||||
@ -97,7 +98,7 @@ public final class UhidManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void unregisterUhidListener(FileDescriptor fd) {
|
private void unregisterUhidListener(FileDescriptor fd) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT >= AndroidVersions.API_23_ANDROID_6_0) {
|
||||||
queue.removeOnFileDescriptorEventListener(fd);
|
queue.removeOnFileDescriptorEventListener(fd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.genymobile.scrcpy.device;
|
package com.genymobile.scrcpy.device;
|
||||||
|
|
||||||
|
import com.genymobile.scrcpy.AndroidVersions;
|
||||||
import com.genymobile.scrcpy.Options;
|
import com.genymobile.scrcpy.Options;
|
||||||
import com.genymobile.scrcpy.util.Ln;
|
import com.genymobile.scrcpy.util.Ln;
|
||||||
import com.genymobile.scrcpy.util.LogUtils;
|
import com.genymobile.scrcpy.util.LogUtils;
|
||||||
@ -104,7 +105,7 @@ public final class Device {
|
|||||||
}
|
}
|
||||||
}, displayId);
|
}, displayId);
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
if (Build.VERSION.SDK_INT >= AndroidVersions.API_29_ANDROID_10) {
|
||||||
ServiceManager.getWindowManager().registerDisplayFoldListener(new IDisplayFoldListener.Stub() {
|
ServiceManager.getWindowManager().registerDisplayFoldListener(new IDisplayFoldListener.Stub() {
|
||||||
@Override
|
@Override
|
||||||
public void onDisplayFoldChanged(int displayId, boolean folded) {
|
public void onDisplayFoldChanged(int displayId, boolean folded) {
|
||||||
@ -161,8 +162,8 @@ public final class Device {
|
|||||||
Ln.w("Display doesn't have FLAG_SUPPORTS_PROTECTED_BUFFERS flag, mirroring can be restricted");
|
Ln.w("Display doesn't have FLAG_SUPPORTS_PROTECTED_BUFFERS flag, mirroring can be restricted");
|
||||||
}
|
}
|
||||||
|
|
||||||
// main display or any display on Android >= Q
|
// main display or any display on Android >= 10
|
||||||
supportsInputEvents = displayId == 0 || Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q;
|
supportsInputEvents = displayId == 0 || Build.VERSION.SDK_INT >= AndroidVersions.API_29_ANDROID_10;
|
||||||
if (!supportsInputEvents) {
|
if (!supportsInputEvents) {
|
||||||
Ln.w("Input events are not supported for secondary displays before Android 10");
|
Ln.w("Input events are not supported for secondary displays before Android 10");
|
||||||
}
|
}
|
||||||
@ -215,7 +216,7 @@ public final class Device {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean supportsInputEvents(int displayId) {
|
public static boolean supportsInputEvents(int displayId) {
|
||||||
return displayId == 0 || Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q;
|
return displayId == 0 || Build.VERSION.SDK_INT >= AndroidVersions.API_29_ANDROID_10;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean supportsInputEvents() {
|
public boolean supportsInputEvents() {
|
||||||
@ -323,10 +324,10 @@ public final class Device {
|
|||||||
* @param mode one of the {@code POWER_MODE_*} constants
|
* @param mode one of the {@code POWER_MODE_*} constants
|
||||||
*/
|
*/
|
||||||
public static boolean setScreenPowerMode(int mode) {
|
public static boolean setScreenPowerMode(int mode) {
|
||||||
boolean applyToMultiPhysicalDisplays = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q;
|
boolean applyToMultiPhysicalDisplays = Build.VERSION.SDK_INT >= AndroidVersions.API_29_ANDROID_10;
|
||||||
|
|
||||||
if (applyToMultiPhysicalDisplays
|
if (applyToMultiPhysicalDisplays
|
||||||
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE
|
&& Build.VERSION.SDK_INT >= AndroidVersions.API_34_ANDROID_14
|
||||||
&& Build.BRAND.equalsIgnoreCase("honor")
|
&& Build.BRAND.equalsIgnoreCase("honor")
|
||||||
&& SurfaceControl.hasGetBuildInDisplayMethod()) {
|
&& SurfaceControl.hasGetBuildInDisplayMethod()) {
|
||||||
// Workaround for Honor devices with Android 14:
|
// Workaround for Honor devices with Android 14:
|
||||||
@ -338,7 +339,7 @@ public final class Device {
|
|||||||
if (applyToMultiPhysicalDisplays) {
|
if (applyToMultiPhysicalDisplays) {
|
||||||
// On Android 14, these internal methods have been moved to DisplayControl
|
// On Android 14, these internal methods have been moved to DisplayControl
|
||||||
boolean useDisplayControl =
|
boolean useDisplayControl =
|
||||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE && !SurfaceControl.hasGetPhysicalDisplayIdsMethod();
|
Build.VERSION.SDK_INT >= AndroidVersions.API_34_ANDROID_14 && !SurfaceControl.hasGetPhysicalDisplayIdsMethod();
|
||||||
|
|
||||||
// Change the power mode for all physical displays
|
// Change the power mode for all physical displays
|
||||||
long[] physicalDisplayIds = useDisplayControl ? DisplayControl.getPhysicalDisplayIds() : SurfaceControl.getPhysicalDisplayIds();
|
long[] physicalDisplayIds = useDisplayControl ? DisplayControl.getPhysicalDisplayIds() : SurfaceControl.getPhysicalDisplayIds();
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.genymobile.scrcpy.util;
|
package com.genymobile.scrcpy.util;
|
||||||
|
|
||||||
|
import com.genymobile.scrcpy.AndroidVersions;
|
||||||
import com.genymobile.scrcpy.BuildConfig;
|
import com.genymobile.scrcpy.BuildConfig;
|
||||||
|
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
@ -31,7 +32,7 @@ public final class IO {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void writeFully(FileDescriptor fd, ByteBuffer from) throws IOException {
|
public static void writeFully(FileDescriptor fd, ByteBuffer from) throws IOException {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT >= AndroidVersions.API_23_ANDROID_6_0) {
|
||||||
while (from.hasRemaining()) {
|
while (from.hasRemaining()) {
|
||||||
write(fd, from);
|
write(fd, from);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.genymobile.scrcpy.util;
|
package com.genymobile.scrcpy.util;
|
||||||
|
|
||||||
|
import com.genymobile.scrcpy.AndroidVersions;
|
||||||
import com.genymobile.scrcpy.wrappers.ContentProvider;
|
import com.genymobile.scrcpy.wrappers.ContentProvider;
|
||||||
import com.genymobile.scrcpy.wrappers.ServiceManager;
|
import com.genymobile.scrcpy.wrappers.ServiceManager;
|
||||||
|
|
||||||
@ -34,7 +35,7 @@ public final class Settings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String getValue(String table, String key) throws SettingsException {
|
public static String getValue(String table, String key) throws SettingsException {
|
||||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) {
|
if (Build.VERSION.SDK_INT <= AndroidVersions.API_30_ANDROID_11) {
|
||||||
// on Android >= 12, it always fails: <https://github.com/Genymobile/scrcpy/issues/2788>
|
// on Android >= 12, it always fails: <https://github.com/Genymobile/scrcpy/issues/2788>
|
||||||
try (ContentProvider provider = ServiceManager.getActivityManager().createSettingsProvider()) {
|
try (ContentProvider provider = ServiceManager.getActivityManager().createSettingsProvider()) {
|
||||||
return provider.getValue(table, key);
|
return provider.getValue(table, key);
|
||||||
@ -47,7 +48,7 @@ public final class Settings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void putValue(String table, String key, String value) throws SettingsException {
|
public static void putValue(String table, String key, String value) throws SettingsException {
|
||||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) {
|
if (Build.VERSION.SDK_INT <= AndroidVersions.API_30_ANDROID_11) {
|
||||||
// on Android >= 12, it always fails: <https://github.com/Genymobile/scrcpy/issues/2788>
|
// on Android >= 12, it always fails: <https://github.com/Genymobile/scrcpy/issues/2788>
|
||||||
try (ContentProvider provider = ServiceManager.getActivityManager().createSettingsProvider()) {
|
try (ContentProvider provider = ServiceManager.getActivityManager().createSettingsProvider()) {
|
||||||
provider.putValue(table, key, value);
|
provider.putValue(table, key, value);
|
||||||
@ -60,7 +61,7 @@ public final class Settings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String getAndPutValue(String table, String key, String value) throws SettingsException {
|
public static String getAndPutValue(String table, String key, String value) throws SettingsException {
|
||||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) {
|
if (Build.VERSION.SDK_INT <= AndroidVersions.API_30_ANDROID_11) {
|
||||||
// on Android >= 12, it always fails: <https://github.com/Genymobile/scrcpy/issues/2788>
|
// on Android >= 12, it always fails: <https://github.com/Genymobile/scrcpy/issues/2788>
|
||||||
try (ContentProvider provider = ServiceManager.getActivityManager().createSettingsProvider()) {
|
try (ContentProvider provider = ServiceManager.getActivityManager().createSettingsProvider()) {
|
||||||
String oldValue = provider.getValue(table, key);
|
String oldValue = provider.getValue(table, key);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.genymobile.scrcpy.video;
|
package com.genymobile.scrcpy.video;
|
||||||
|
|
||||||
|
import com.genymobile.scrcpy.AndroidVersions;
|
||||||
import com.genymobile.scrcpy.device.Size;
|
import com.genymobile.scrcpy.device.Size;
|
||||||
import com.genymobile.scrcpy.util.HandlerExecutor;
|
import com.genymobile.scrcpy.util.HandlerExecutor;
|
||||||
import com.genymobile.scrcpy.util.Ln;
|
import com.genymobile.scrcpy.util.Ln;
|
||||||
@ -20,7 +21,6 @@ import android.hardware.camera2.params.OutputConfiguration;
|
|||||||
import android.hardware.camera2.params.SessionConfiguration;
|
import android.hardware.camera2.params.SessionConfiguration;
|
||||||
import android.hardware.camera2.params.StreamConfigurationMap;
|
import android.hardware.camera2.params.StreamConfigurationMap;
|
||||||
import android.media.MediaCodec;
|
import android.media.MediaCodec;
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.HandlerThread;
|
import android.os.HandlerThread;
|
||||||
import android.util.Range;
|
import android.util.Range;
|
||||||
@ -118,7 +118,7 @@ public class CameraCapture extends SurfaceCapture {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.N)
|
@TargetApi(AndroidVersions.API_24_ANDROID_7_0)
|
||||||
private static Size selectSize(String cameraId, Size explicitSize, int maxSize, CameraAspectRatio aspectRatio, boolean highSpeed)
|
private static Size selectSize(String cameraId, Size explicitSize, int maxSize, CameraAspectRatio aspectRatio, boolean highSpeed)
|
||||||
throws CameraAccessException {
|
throws CameraAccessException {
|
||||||
if (explicitSize != null) {
|
if (explicitSize != null) {
|
||||||
@ -242,7 +242,7 @@ public class CameraCapture extends SurfaceCapture {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("MissingPermission")
|
@SuppressLint("MissingPermission")
|
||||||
@TargetApi(Build.VERSION_CODES.S)
|
@TargetApi(AndroidVersions.API_31_ANDROID_12)
|
||||||
private CameraDevice openCamera(String id) throws CameraAccessException, InterruptedException {
|
private CameraDevice openCamera(String id) throws CameraAccessException, InterruptedException {
|
||||||
CompletableFuture<CameraDevice> future = new CompletableFuture<>();
|
CompletableFuture<CameraDevice> future = new CompletableFuture<>();
|
||||||
ServiceManager.getCameraManager().openCamera(id, new CameraDevice.StateCallback() {
|
ServiceManager.getCameraManager().openCamera(id, new CameraDevice.StateCallback() {
|
||||||
@ -289,7 +289,7 @@ public class CameraCapture extends SurfaceCapture {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.S)
|
@TargetApi(AndroidVersions.API_31_ANDROID_12)
|
||||||
private CameraCaptureSession createCaptureSession(CameraDevice camera, Surface surface) throws CameraAccessException, InterruptedException {
|
private CameraCaptureSession createCaptureSession(CameraDevice camera, Surface surface) throws CameraAccessException, InterruptedException {
|
||||||
CompletableFuture<CameraCaptureSession> future = new CompletableFuture<>();
|
CompletableFuture<CameraCaptureSession> future = new CompletableFuture<>();
|
||||||
OutputConfiguration outputConfig = new OutputConfiguration(surface);
|
OutputConfiguration outputConfig = new OutputConfiguration(surface);
|
||||||
@ -328,7 +328,7 @@ public class CameraCapture extends SurfaceCapture {
|
|||||||
return requestBuilder.build();
|
return requestBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.S)
|
@TargetApi(AndroidVersions.API_31_ANDROID_12)
|
||||||
private void setRepeatingRequest(CameraCaptureSession session, CaptureRequest request) throws CameraAccessException, InterruptedException {
|
private void setRepeatingRequest(CameraCaptureSession session, CaptureRequest request) throws CameraAccessException, InterruptedException {
|
||||||
CameraCaptureSession.CaptureCallback callback = new CameraCaptureSession.CaptureCallback() {
|
CameraCaptureSession.CaptureCallback callback = new CameraCaptureSession.CaptureCallback() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.genymobile.scrcpy.video;
|
package com.genymobile.scrcpy.video;
|
||||||
|
|
||||||
|
import com.genymobile.scrcpy.AndroidVersions;
|
||||||
import com.genymobile.scrcpy.device.Device;
|
import com.genymobile.scrcpy.device.Device;
|
||||||
import com.genymobile.scrcpy.device.Size;
|
import com.genymobile.scrcpy.device.Size;
|
||||||
import com.genymobile.scrcpy.util.Ln;
|
import com.genymobile.scrcpy.util.Ln;
|
||||||
@ -103,8 +104,8 @@ public class ScreenCapture extends SurfaceCapture implements Device.RotationList
|
|||||||
private static IBinder createDisplay() throws Exception {
|
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 < AndroidVersions.API_30_ANDROID_11 || (Build.VERSION.SDK_INT == AndroidVersions.API_30_ANDROID_11
|
||||||
Build.VERSION.CODENAME));
|
&& !"S".equals(Build.VERSION.CODENAME));
|
||||||
return SurfaceControl.createDisplay("scrcpy", secure);
|
return SurfaceControl.createDisplay("scrcpy", secure);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.genymobile.scrcpy.video;
|
package com.genymobile.scrcpy.video;
|
||||||
|
|
||||||
|
import com.genymobile.scrcpy.AndroidVersions;
|
||||||
import com.genymobile.scrcpy.AsyncProcessor;
|
import com.genymobile.scrcpy.AsyncProcessor;
|
||||||
import com.genymobile.scrcpy.device.ConfigurationException;
|
import com.genymobile.scrcpy.device.ConfigurationException;
|
||||||
import com.genymobile.scrcpy.device.Size;
|
import com.genymobile.scrcpy.device.Size;
|
||||||
@ -238,7 +239,7 @@ public class SurfaceEncoder implements AsyncProcessor {
|
|||||||
// must be present to configure the encoder, but does not impact the actual frame rate, which is variable
|
// must be present to configure the encoder, but does not impact the actual frame rate, which is variable
|
||||||
format.setInteger(MediaFormat.KEY_FRAME_RATE, 60);
|
format.setInteger(MediaFormat.KEY_FRAME_RATE, 60);
|
||||||
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
|
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
if (Build.VERSION.SDK_INT >= AndroidVersions.API_24_ANDROID_7_0) {
|
||||||
format.setInteger(MediaFormat.KEY_COLOR_RANGE, MediaFormat.COLOR_RANGE_LIMITED);
|
format.setInteger(MediaFormat.KEY_COLOR_RANGE, MediaFormat.COLOR_RANGE_LIMITED);
|
||||||
}
|
}
|
||||||
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, DEFAULT_I_FRAME_INTERVAL);
|
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, DEFAULT_I_FRAME_INTERVAL);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.genymobile.scrcpy.wrappers;
|
package com.genymobile.scrcpy.wrappers;
|
||||||
|
|
||||||
|
import com.genymobile.scrcpy.AndroidVersions;
|
||||||
import com.genymobile.scrcpy.FakeContext;
|
import com.genymobile.scrcpy.FakeContext;
|
||||||
import com.genymobile.scrcpy.util.Ln;
|
import com.genymobile.scrcpy.util.Ln;
|
||||||
|
|
||||||
@ -7,7 +8,6 @@ import android.annotation.SuppressLint;
|
|||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.IInterface;
|
import android.os.IInterface;
|
||||||
@ -63,7 +63,7 @@ public final class ActivityManager {
|
|||||||
return removeContentProviderExternalMethod;
|
return removeContentProviderExternalMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.Q)
|
@TargetApi(AndroidVersions.API_29_ANDROID_10)
|
||||||
private ContentProvider getContentProviderExternal(String name, IBinder token) {
|
private ContentProvider getContentProviderExternal(String name, IBinder token) {
|
||||||
try {
|
try {
|
||||||
Method method = getGetContentProviderExternalMethod();
|
Method method = getGetContentProviderExternalMethod();
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.genymobile.scrcpy.wrappers;
|
package com.genymobile.scrcpy.wrappers;
|
||||||
|
|
||||||
|
import com.genymobile.scrcpy.AndroidVersions;
|
||||||
import com.genymobile.scrcpy.FakeContext;
|
import com.genymobile.scrcpy.FakeContext;
|
||||||
import com.genymobile.scrcpy.util.Ln;
|
import com.genymobile.scrcpy.util.Ln;
|
||||||
|
|
||||||
@ -36,7 +37,7 @@ public final class ClipboardManager {
|
|||||||
|
|
||||||
private Method getGetPrimaryClipMethod() throws NoSuchMethodException {
|
private Method getGetPrimaryClipMethod() throws NoSuchMethodException {
|
||||||
if (getPrimaryClipMethod == null) {
|
if (getPrimaryClipMethod == null) {
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
|
if (Build.VERSION.SDK_INT < AndroidVersions.API_29_ANDROID_10) {
|
||||||
getPrimaryClipMethod = manager.getClass().getMethod("getPrimaryClip", String.class);
|
getPrimaryClipMethod = manager.getClass().getMethod("getPrimaryClip", String.class);
|
||||||
return getPrimaryClipMethod;
|
return getPrimaryClipMethod;
|
||||||
}
|
}
|
||||||
@ -99,7 +100,7 @@ public final class ClipboardManager {
|
|||||||
|
|
||||||
private Method getSetPrimaryClipMethod() throws NoSuchMethodException {
|
private Method getSetPrimaryClipMethod() throws NoSuchMethodException {
|
||||||
if (setPrimaryClipMethod == null) {
|
if (setPrimaryClipMethod == null) {
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
|
if (Build.VERSION.SDK_INT < AndroidVersions.API_29_ANDROID_10) {
|
||||||
setPrimaryClipMethod = manager.getClass().getMethod("setPrimaryClip", ClipData.class, String.class);
|
setPrimaryClipMethod = manager.getClass().getMethod("setPrimaryClip", ClipData.class, String.class);
|
||||||
return setPrimaryClipMethod;
|
return setPrimaryClipMethod;
|
||||||
}
|
}
|
||||||
@ -137,7 +138,7 @@ public final class ClipboardManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static ClipData getPrimaryClip(Method method, int methodVersion, IInterface manager) throws ReflectiveOperationException {
|
private static ClipData getPrimaryClip(Method method, int methodVersion, IInterface manager) throws ReflectiveOperationException {
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
|
if (Build.VERSION.SDK_INT < AndroidVersions.API_29_ANDROID_10) {
|
||||||
return (ClipData) method.invoke(manager, FakeContext.PACKAGE_NAME);
|
return (ClipData) method.invoke(manager, FakeContext.PACKAGE_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,7 +162,7 @@ public final class ClipboardManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void setPrimaryClip(Method method, int methodVersion, IInterface manager, ClipData clipData) throws ReflectiveOperationException {
|
private static void setPrimaryClip(Method method, int methodVersion, IInterface manager, ClipData clipData) throws ReflectiveOperationException {
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
|
if (Build.VERSION.SDK_INT < AndroidVersions.API_29_ANDROID_10) {
|
||||||
method.invoke(manager, clipData, FakeContext.PACKAGE_NAME);
|
method.invoke(manager, clipData, FakeContext.PACKAGE_NAME);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -210,7 +211,7 @@ public final class ClipboardManager {
|
|||||||
|
|
||||||
private static void addPrimaryClipChangedListener(Method method, int methodVersion, IInterface manager, IOnPrimaryClipChangedListener listener)
|
private static void addPrimaryClipChangedListener(Method method, int methodVersion, IInterface manager, IOnPrimaryClipChangedListener listener)
|
||||||
throws ReflectiveOperationException {
|
throws ReflectiveOperationException {
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
|
if (Build.VERSION.SDK_INT < AndroidVersions.API_29_ANDROID_10) {
|
||||||
method.invoke(manager, listener, FakeContext.PACKAGE_NAME);
|
method.invoke(manager, listener, FakeContext.PACKAGE_NAME);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -230,7 +231,7 @@ public final class ClipboardManager {
|
|||||||
|
|
||||||
private Method getAddPrimaryClipChangedListener() throws NoSuchMethodException {
|
private Method getAddPrimaryClipChangedListener() throws NoSuchMethodException {
|
||||||
if (addPrimaryClipChangedListener == null) {
|
if (addPrimaryClipChangedListener == null) {
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
|
if (Build.VERSION.SDK_INT < AndroidVersions.API_29_ANDROID_10) {
|
||||||
addPrimaryClipChangedListener = manager.getClass()
|
addPrimaryClipChangedListener = manager.getClass()
|
||||||
.getMethod("addPrimaryClipChangedListener", IOnPrimaryClipChangedListener.class, String.class);
|
.getMethod("addPrimaryClipChangedListener", IOnPrimaryClipChangedListener.class, String.class);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.genymobile.scrcpy.wrappers;
|
package com.genymobile.scrcpy.wrappers;
|
||||||
|
|
||||||
|
import com.genymobile.scrcpy.AndroidVersions;
|
||||||
import com.genymobile.scrcpy.FakeContext;
|
import com.genymobile.scrcpy.FakeContext;
|
||||||
import com.genymobile.scrcpy.util.Ln;
|
import com.genymobile.scrcpy.util.Ln;
|
||||||
import com.genymobile.scrcpy.util.SettingsException;
|
import com.genymobile.scrcpy.util.SettingsException;
|
||||||
@ -51,7 +52,7 @@ public final class ContentProvider implements Closeable {
|
|||||||
@SuppressLint("PrivateApi")
|
@SuppressLint("PrivateApi")
|
||||||
private Method getCallMethod() throws NoSuchMethodException {
|
private Method getCallMethod() throws NoSuchMethodException {
|
||||||
if (callMethod == null) {
|
if (callMethod == null) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
if (Build.VERSION.SDK_INT >= AndroidVersions.API_31_ANDROID_12) {
|
||||||
callMethod = provider.getClass().getMethod("call", AttributionSource.class, String.class, String.class, String.class, Bundle.class);
|
callMethod = provider.getClass().getMethod("call", AttributionSource.class, String.class, String.class, String.class, Bundle.class);
|
||||||
callMethodVersion = 0;
|
callMethodVersion = 0;
|
||||||
} else {
|
} else {
|
||||||
@ -79,7 +80,7 @@ public final class ContentProvider implements Closeable {
|
|||||||
Method method = getCallMethod();
|
Method method = getCallMethod();
|
||||||
Object[] args;
|
Object[] args;
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && callMethodVersion == 0) {
|
if (Build.VERSION.SDK_INT >= AndroidVersions.API_31_ANDROID_12 && callMethodVersion == 0) {
|
||||||
args = new Object[]{FakeContext.get().getAttributionSource(), "settings", callMethod, arg, extras};
|
args = new Object[]{FakeContext.get().getAttributionSource(), "settings", callMethod, arg, extras};
|
||||||
} else {
|
} else {
|
||||||
switch (callMethodVersion) {
|
switch (callMethodVersion) {
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
package com.genymobile.scrcpy.wrappers;
|
package com.genymobile.scrcpy.wrappers;
|
||||||
|
|
||||||
|
import com.genymobile.scrcpy.AndroidVersions;
|
||||||
import com.genymobile.scrcpy.util.Ln;
|
import com.genymobile.scrcpy.util.Ln;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
import android.os.Build;
|
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
@SuppressLint({"PrivateApi", "SoonBlockedPrivateApi", "BlockedPrivateApi"})
|
@SuppressLint({"PrivateApi", "SoonBlockedPrivateApi", "BlockedPrivateApi"})
|
||||||
@TargetApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
|
@TargetApi(AndroidVersions.API_34_ANDROID_14)
|
||||||
public final class DisplayControl {
|
public final class DisplayControl {
|
||||||
|
|
||||||
private static final Class<?> CLASS;
|
private static final Class<?> CLASS;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.genymobile.scrcpy.wrappers;
|
package com.genymobile.scrcpy.wrappers;
|
||||||
|
|
||||||
|
import com.genymobile.scrcpy.AndroidVersions;
|
||||||
import com.genymobile.scrcpy.util.Ln;
|
import com.genymobile.scrcpy.util.Ln;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
@ -24,7 +25,7 @@ public final class PowerManager {
|
|||||||
private Method getIsScreenOnMethod() throws NoSuchMethodException {
|
private Method getIsScreenOnMethod() throws NoSuchMethodException {
|
||||||
if (isScreenOnMethod == null) {
|
if (isScreenOnMethod == null) {
|
||||||
@SuppressLint("ObsoleteSdkInt") // we may lower minSdkVersion in the future
|
@SuppressLint("ObsoleteSdkInt") // we may lower minSdkVersion in the future
|
||||||
String methodName = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH ? "isInteractive" : "isScreenOn";
|
String methodName = Build.VERSION.SDK_INT >= AndroidVersions.API_20_ANDROID_4_4 ? "isInteractive" : "isScreenOn";
|
||||||
isScreenOnMethod = manager.getClass().getMethod(methodName);
|
isScreenOnMethod = manager.getClass().getMethod(methodName);
|
||||||
}
|
}
|
||||||
return isScreenOnMethod;
|
return isScreenOnMethod;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.genymobile.scrcpy.wrappers;
|
package com.genymobile.scrcpy.wrappers;
|
||||||
|
|
||||||
|
import com.genymobile.scrcpy.AndroidVersions;
|
||||||
import com.genymobile.scrcpy.util.Ln;
|
import com.genymobile.scrcpy.util.Ln;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
@ -83,9 +84,9 @@ public final class SurfaceControl {
|
|||||||
|
|
||||||
private static Method getGetBuiltInDisplayMethod() throws NoSuchMethodException {
|
private static Method getGetBuiltInDisplayMethod() throws NoSuchMethodException {
|
||||||
if (getBuiltInDisplayMethod == null) {
|
if (getBuiltInDisplayMethod == null) {
|
||||||
// the method signature has changed in Android Q
|
// the method signature has changed in Android 10
|
||||||
// <https://github.com/Genymobile/scrcpy/issues/586>
|
// <https://github.com/Genymobile/scrcpy/issues/586>
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
|
if (Build.VERSION.SDK_INT < AndroidVersions.API_29_ANDROID_10) {
|
||||||
getBuiltInDisplayMethod = CLASS.getMethod("getBuiltInDisplay", int.class);
|
getBuiltInDisplayMethod = CLASS.getMethod("getBuiltInDisplay", int.class);
|
||||||
} else {
|
} else {
|
||||||
getBuiltInDisplayMethod = CLASS.getMethod("getInternalDisplayToken");
|
getBuiltInDisplayMethod = CLASS.getMethod("getInternalDisplayToken");
|
||||||
@ -106,7 +107,7 @@ public final class SurfaceControl {
|
|||||||
public static IBinder getBuiltInDisplay() {
|
public static IBinder getBuiltInDisplay() {
|
||||||
try {
|
try {
|
||||||
Method method = getGetBuiltInDisplayMethod();
|
Method method = getGetBuiltInDisplayMethod();
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
|
if (Build.VERSION.SDK_INT < AndroidVersions.API_29_ANDROID_10) {
|
||||||
// call getBuiltInDisplay(0)
|
// call getBuiltInDisplay(0)
|
||||||
return (IBinder) method.invoke(null, 0);
|
return (IBinder) method.invoke(null, 0);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user