Use explicit constants for Android versions

Who remembers code names? This avoids to check the mapping every time.
This commit is contained in:
Romain Vimont 2024-10-20 13:01:52 +02:00
parent e33be3d288
commit 3acffaae57
23 changed files with 108 additions and 62 deletions

View File

@ -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;
}

View File

@ -4,7 +4,6 @@ import android.annotation.TargetApi;
import android.content.AttributionSource;
import android.content.Context;
import android.content.ContextWrapper;
import android.os.Build;
import android.os.Process;
public final class FakeContext extends ContextWrapper {
@ -32,7 +31,7 @@ public final class FakeContext extends ContextWrapper {
return PACKAGE_NAME;
}
@TargetApi(Build.VERSION_CODES.S)
@TargetApi(AndroidVersions.API_31_ANDROID_12)
@Override
public AttributionSource getAttributionSource() {
AttributionSource.Builder builder = new AttributionSource.Builder(Process.SHELL_UID);

View File

@ -121,7 +121,7 @@ public final class Server {
}
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");
throw new ConfigurationException("Camera mirroring is not supported");
}

View File

@ -52,7 +52,7 @@ public final class Workarounds {
}
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(),
// which requires a non-null ConfigurationController.
// 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")
public static AudioRecord createAudioRecord(int source, int sampleRate, int channelConfig, int channels, int channelMask, int encoding) throws
AudioCaptureException {
@ -226,7 +226,7 @@ public final class Workarounds {
int[] session = new int[]{AudioManager.AUDIO_SESSION_ID_GENERATE};
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,
// Object /*AudioAttributes*/ attributes,
// int[] sampleRate, int channelMask, int channelIndexMask, int audioFormat,
@ -252,7 +252,7 @@ public final class Workarounds {
Method getParcelMethod = attributionSourceState.getClass().getDeclaredMethod("getParcel");
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,
// Object /*AudioAttributes*/ attributes,
// int[] sampleRate, int channelMask, int channelIndexMask, int audioFormat,

View File

@ -1,5 +1,6 @@
package com.genymobile.scrcpy.audio;
import com.genymobile.scrcpy.AndroidVersions;
import com.genymobile.scrcpy.FakeContext;
import com.genymobile.scrcpy.Workarounds;
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"})
private static AudioRecord createAudioRecord(int audioSource) {
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
builder.setContext(FakeContext.get());
}
@ -117,7 +118,7 @@ public class AudioDirectCapture implements AudioCapture {
@Override
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");
throw new AudioCaptureException();
}
@ -125,7 +126,7 @@ public class AudioDirectCapture implements AudioCapture {
@Override
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();
try {
tryStartRecording(5, 100);
@ -146,7 +147,7 @@ public class AudioDirectCapture implements AudioCapture {
}
@Override
@TargetApi(Build.VERSION_CODES.N)
@TargetApi(AndroidVersions.API_24_ANDROID_7_0)
public int read(ByteBuffer outDirectBuffer, MediaCodec.BufferInfo outBufferInfo) {
return reader.read(outDirectBuffer, outBufferInfo);
}

View File

@ -1,5 +1,6 @@
package com.genymobile.scrcpy.audio;
import com.genymobile.scrcpy.AndroidVersions;
import com.genymobile.scrcpy.AsyncProcessor;
import com.genymobile.scrcpy.device.ConfigurationException;
import com.genymobile.scrcpy.device.Streamer;
@ -93,7 +94,7 @@ public final class AudioEncoder implements AsyncProcessor {
return format;
}
@TargetApi(Build.VERSION_CODES.N)
@TargetApi(AndroidVersions.API_24_ANDROID_7_0)
private void inputThread(MediaCodec mediaCodec, AudioCapture capture) throws IOException, InterruptedException {
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 {
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");
streamer.writeDisableStream(false);
return;
@ -314,7 +315,7 @@ public final class AudioEncoder implements AsyncProcessor {
}
private final class EncoderCallback extends MediaCodec.Callback {
@TargetApi(Build.VERSION_CODES.N)
@TargetApi(AndroidVersions.API_24_ANDROID_7_0)
@Override
public void onInputBufferAvailable(MediaCodec codec, int index) {
try {

View File

@ -1,5 +1,6 @@
package com.genymobile.scrcpy.audio;
import com.genymobile.scrcpy.AndroidVersions;
import com.genymobile.scrcpy.FakeContext;
import com.genymobile.scrcpy.util.Ln;
@ -108,7 +109,7 @@ public final class AudioPlaybackCapture implements AudioCapture {
@Override
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");
throw new AudioCaptureException();
}
@ -130,7 +131,7 @@ public final class AudioPlaybackCapture implements AudioCapture {
}
@Override
@TargetApi(Build.VERSION_CODES.N)
@TargetApi(AndroidVersions.API_24_ANDROID_7_0)
public int read(ByteBuffer outDirectBuffer, MediaCodec.BufferInfo outBufferInfo) {
return reader.read(outDirectBuffer, outBufferInfo);
}

View File

@ -1,5 +1,6 @@
package com.genymobile.scrcpy.audio;
import com.genymobile.scrcpy.AndroidVersions;
import com.genymobile.scrcpy.AsyncProcessor;
import com.genymobile.scrcpy.device.Streamer;
import com.genymobile.scrcpy.util.IO;
@ -24,7 +25,7 @@ public final class AudioRawRecorder implements AsyncProcessor {
}
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");
streamer.writeDisableStream(false);
return;

View File

@ -1,12 +1,12 @@
package com.genymobile.scrcpy.audio;
import com.genymobile.scrcpy.AndroidVersions;
import com.genymobile.scrcpy.util.Ln;
import android.annotation.TargetApi;
import android.media.AudioRecord;
import android.media.AudioTimestamp;
import android.media.MediaCodec;
import android.os.Build;
import java.nio.ByteBuffer;
@ -26,7 +26,7 @@ public class AudioRecordReader {
this.recorder = recorder;
}
@TargetApi(Build.VERSION_CODES.N)
@TargetApi(AndroidVersions.API_24_ANDROID_7_0)
public int read(ByteBuffer outDirectBuffer, MediaCodec.BufferInfo outBufferInfo) {
int r = recorder.read(outDirectBuffer, AudioConfig.MAX_READ_SIZE);
if (r <= 0) {

View File

@ -1,5 +1,6 @@
package com.genymobile.scrcpy.control;
import com.genymobile.scrcpy.AndroidVersions;
import com.genymobile.scrcpy.AsyncProcessor;
import com.genymobile.scrcpy.CleanUp;
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>
*/
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 (actionButton == buttons) {
// First button pressed: ACTION_DOWN
@ -423,7 +424,7 @@ public class Controller implements AsyncProcessor {
private void getClipboard(int copyKey) {
// 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;
// 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);
@ -448,7 +449,7 @@ public class Controller implements AsyncProcessor {
}
// 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);
}

View File

@ -1,5 +1,6 @@
package com.genymobile.scrcpy.control;
import com.genymobile.scrcpy.AndroidVersions;
import com.genymobile.scrcpy.util.Ln;
import com.genymobile.scrcpy.util.StringUtils;
@ -38,7 +39,7 @@ public final class UhidManager {
public UhidManager(DeviceMessageSender 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");
thread.start();
queue = thread.getLooper().getQueue();
@ -71,7 +72,7 @@ public final class UhidManager {
}
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) -> {
try {
buffer.clear();
@ -97,7 +98,7 @@ public final class UhidManager {
}
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);
}
}

View File

@ -1,5 +1,6 @@
package com.genymobile.scrcpy.device;
import com.genymobile.scrcpy.AndroidVersions;
import com.genymobile.scrcpy.Options;
import com.genymobile.scrcpy.util.Ln;
import com.genymobile.scrcpy.util.LogUtils;
@ -104,7 +105,7 @@ public final class Device {
}
}, 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() {
@Override
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");
}
// main display or any display on Android >= Q
supportsInputEvents = displayId == 0 || Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q;
// main display or any display on Android >= 10
supportsInputEvents = displayId == 0 || Build.VERSION.SDK_INT >= AndroidVersions.API_29_ANDROID_10;
if (!supportsInputEvents) {
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) {
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() {
@ -323,10 +324,10 @@ public final class Device {
* @param mode one of the {@code POWER_MODE_*} constants
*/
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
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE
&& Build.VERSION.SDK_INT >= AndroidVersions.API_34_ANDROID_14
&& Build.BRAND.equalsIgnoreCase("honor")
&& SurfaceControl.hasGetBuildInDisplayMethod()) {
// Workaround for Honor devices with Android 14:
@ -338,7 +339,7 @@ public final class Device {
if (applyToMultiPhysicalDisplays) {
// On Android 14, these internal methods have been moved to DisplayControl
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
long[] physicalDisplayIds = useDisplayControl ? DisplayControl.getPhysicalDisplayIds() : SurfaceControl.getPhysicalDisplayIds();

View File

@ -1,5 +1,6 @@
package com.genymobile.scrcpy.util;
import com.genymobile.scrcpy.AndroidVersions;
import com.genymobile.scrcpy.BuildConfig;
import android.os.Build;
@ -31,7 +32,7 @@ public final class IO {
}
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()) {
write(fd, from);
}

View File

@ -1,5 +1,6 @@
package com.genymobile.scrcpy.util;
import com.genymobile.scrcpy.AndroidVersions;
import com.genymobile.scrcpy.wrappers.ContentProvider;
import com.genymobile.scrcpy.wrappers.ServiceManager;
@ -34,7 +35,7 @@ public final class Settings {
}
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>
try (ContentProvider provider = ServiceManager.getActivityManager().createSettingsProvider()) {
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 {
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>
try (ContentProvider provider = ServiceManager.getActivityManager().createSettingsProvider()) {
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 {
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>
try (ContentProvider provider = ServiceManager.getActivityManager().createSettingsProvider()) {
String oldValue = provider.getValue(table, key);

View File

@ -1,5 +1,6 @@
package com.genymobile.scrcpy.video;
import com.genymobile.scrcpy.AndroidVersions;
import com.genymobile.scrcpy.device.Size;
import com.genymobile.scrcpy.util.HandlerExecutor;
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.StreamConfigurationMap;
import android.media.MediaCodec;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Range;
@ -118,7 +118,7 @@ public class CameraCapture extends SurfaceCapture {
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)
throws CameraAccessException {
if (explicitSize != null) {
@ -242,7 +242,7 @@ public class CameraCapture extends SurfaceCapture {
}
@SuppressLint("MissingPermission")
@TargetApi(Build.VERSION_CODES.S)
@TargetApi(AndroidVersions.API_31_ANDROID_12)
private CameraDevice openCamera(String id) throws CameraAccessException, InterruptedException {
CompletableFuture<CameraDevice> future = new CompletableFuture<>();
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 {
CompletableFuture<CameraCaptureSession> future = new CompletableFuture<>();
OutputConfiguration outputConfig = new OutputConfiguration(surface);
@ -328,7 +328,7 @@ public class CameraCapture extends SurfaceCapture {
return requestBuilder.build();
}
@TargetApi(Build.VERSION_CODES.S)
@TargetApi(AndroidVersions.API_31_ANDROID_12)
private void setRepeatingRequest(CameraCaptureSession session, CaptureRequest request) throws CameraAccessException, InterruptedException {
CameraCaptureSession.CaptureCallback callback = new CameraCaptureSession.CaptureCallback() {
@Override

View File

@ -1,5 +1,6 @@
package com.genymobile.scrcpy.video;
import com.genymobile.scrcpy.AndroidVersions;
import com.genymobile.scrcpy.device.Device;
import com.genymobile.scrcpy.device.Size;
import com.genymobile.scrcpy.util.Ln;
@ -103,8 +104,8 @@ public class ScreenCapture extends SurfaceCapture implements Device.RotationList
private static IBinder createDisplay() throws Exception {
// 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".
boolean secure = Build.VERSION.SDK_INT < Build.VERSION_CODES.R || (Build.VERSION.SDK_INT == Build.VERSION_CODES.R && !"S".equals(
Build.VERSION.CODENAME));
boolean secure = Build.VERSION.SDK_INT < AndroidVersions.API_30_ANDROID_11 || (Build.VERSION.SDK_INT == AndroidVersions.API_30_ANDROID_11
&& !"S".equals(Build.VERSION.CODENAME));
return SurfaceControl.createDisplay("scrcpy", secure);
}

View File

@ -1,5 +1,6 @@
package com.genymobile.scrcpy.video;
import com.genymobile.scrcpy.AndroidVersions;
import com.genymobile.scrcpy.AsyncProcessor;
import com.genymobile.scrcpy.device.ConfigurationException;
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
format.setInteger(MediaFormat.KEY_FRAME_RATE, 60);
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_I_FRAME_INTERVAL, DEFAULT_I_FRAME_INTERVAL);

View File

@ -1,5 +1,6 @@
package com.genymobile.scrcpy.wrappers;
import com.genymobile.scrcpy.AndroidVersions;
import com.genymobile.scrcpy.FakeContext;
import com.genymobile.scrcpy.util.Ln;
@ -7,7 +8,6 @@ import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Intent;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.IInterface;
@ -63,7 +63,7 @@ public final class ActivityManager {
return removeContentProviderExternalMethod;
}
@TargetApi(Build.VERSION_CODES.Q)
@TargetApi(AndroidVersions.API_29_ANDROID_10)
private ContentProvider getContentProviderExternal(String name, IBinder token) {
try {
Method method = getGetContentProviderExternalMethod();

View File

@ -1,5 +1,6 @@
package com.genymobile.scrcpy.wrappers;
import com.genymobile.scrcpy.AndroidVersions;
import com.genymobile.scrcpy.FakeContext;
import com.genymobile.scrcpy.util.Ln;
@ -36,7 +37,7 @@ public final class ClipboardManager {
private Method getGetPrimaryClipMethod() throws NoSuchMethodException {
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);
return getPrimaryClipMethod;
}
@ -99,7 +100,7 @@ public final class ClipboardManager {
private Method getSetPrimaryClipMethod() throws NoSuchMethodException {
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);
return setPrimaryClipMethod;
}
@ -137,7 +138,7 @@ public final class ClipboardManager {
}
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);
}
@ -161,7 +162,7 @@ public final class ClipboardManager {
}
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);
return;
}
@ -210,7 +211,7 @@ public final class ClipboardManager {
private static void addPrimaryClipChangedListener(Method method, int methodVersion, IInterface manager, IOnPrimaryClipChangedListener listener)
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);
return;
}
@ -230,7 +231,7 @@ public final class ClipboardManager {
private Method getAddPrimaryClipChangedListener() throws NoSuchMethodException {
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()
.getMethod("addPrimaryClipChangedListener", IOnPrimaryClipChangedListener.class, String.class);
} else {

View File

@ -1,5 +1,6 @@
package com.genymobile.scrcpy.wrappers;
import com.genymobile.scrcpy.AndroidVersions;
import com.genymobile.scrcpy.FakeContext;
import com.genymobile.scrcpy.util.Ln;
import com.genymobile.scrcpy.util.SettingsException;
@ -51,7 +52,7 @@ public final class ContentProvider implements Closeable {
@SuppressLint("PrivateApi")
private Method getCallMethod() throws NoSuchMethodException {
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);
callMethodVersion = 0;
} else {
@ -79,7 +80,7 @@ public final class ContentProvider implements Closeable {
Method method = getCallMethod();
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};
} else {
switch (callMethodVersion) {

View File

@ -1,16 +1,16 @@
package com.genymobile.scrcpy.wrappers;
import com.genymobile.scrcpy.AndroidVersions;
import com.genymobile.scrcpy.util.Ln;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.os.Build;
import android.os.IBinder;
import java.lang.reflect.Method;
@SuppressLint({"PrivateApi", "SoonBlockedPrivateApi", "BlockedPrivateApi"})
@TargetApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
@TargetApi(AndroidVersions.API_34_ANDROID_14)
public final class DisplayControl {
private static final Class<?> CLASS;

View File

@ -1,5 +1,6 @@
package com.genymobile.scrcpy.wrappers;
import com.genymobile.scrcpy.AndroidVersions;
import com.genymobile.scrcpy.util.Ln;
import android.annotation.SuppressLint;
@ -24,7 +25,7 @@ public final class PowerManager {
private Method getIsScreenOnMethod() throws NoSuchMethodException {
if (isScreenOnMethod == null) {
@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);
}
return isScreenOnMethod;

View File

@ -1,5 +1,6 @@
package com.genymobile.scrcpy.wrappers;
import com.genymobile.scrcpy.AndroidVersions;
import com.genymobile.scrcpy.util.Ln;
import android.annotation.SuppressLint;
@ -83,9 +84,9 @@ public final class SurfaceControl {
private static Method getGetBuiltInDisplayMethod() throws NoSuchMethodException {
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>
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);
} else {
getBuiltInDisplayMethod = CLASS.getMethod("getInternalDisplayToken");
@ -106,7 +107,7 @@ public final class SurfaceControl {
public static IBinder getBuiltInDisplay() {
try {
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)
return (IBinder) method.invoke(null, 0);
}