From 17df15293fe9fbb55aab2a4ba75e91f0c2ef0e14 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sun, 17 Mar 2024 17:43:42 -0500 Subject: [PATCH] Drop support for Jelly Bean and KitKat NDK support for these is already gone --- app/build.gradle | 2 +- app/src/main/java/com/limelight/Game.java | 85 ++++------------ .../binding/audio/AndroidAudioRenderer.java | 94 +++++++----------- .../binding/input/ControllerHandler.java | 99 +++++++------------ .../input/driver/UsbDriverService.java | 32 +++--- .../input/driver/Xbox360WirelessDongle.java | 32 +++--- .../video/MediaCodecDecoderRenderer.java | 5 +- .../binding/video/MediaCodecHelper.java | 78 ++++++--------- .../computers/ComputerManagerService.java | 74 +++++++------- .../grid/assets/DiskAssetLoader.java | 10 +- .../com/limelight/nvstream/NvConnection.java | 2 +- .../com/limelight/nvstream/http/NvHTTP.java | 69 +------------ .../ConfirmDeleteOscPreference.java | 2 - .../preferences/LanguagePreference.java | 2 - .../limelight/preferences/StreamSettings.java | 79 +++++---------- .../preferences/WebLauncherPreference.java | 1 - .../com/limelight/ui/AdapterFragment.java | 2 +- .../java/com/limelight/ui/StreamView.java | 1 - .../java/com/limelight/utils/NetHelper.java | 2 +- app/src/main/jni/Application.mk | 4 +- 20 files changed, 218 insertions(+), 457 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 9d13f4be..9183ba70 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -8,7 +8,7 @@ android { namespace 'com.limelight' defaultConfig { - minSdk 16 + minSdk 21 targetSdk 34 versionName "12.1" diff --git a/app/src/main/java/com/limelight/Game.java b/app/src/main/java/com/limelight/Game.java index 42bc0c70..5d214508 100644 --- a/app/src/main/java/com/limelight/Game.java +++ b/app/src/main/java/com/limelight/Game.java @@ -195,14 +195,12 @@ public class Game extends Activity implements SurfaceHolder.Callback, // If we're going to use immersive mode, we want to have // the entire screen - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) { - getWindow().getDecorView().setSystemUiVisibility( - View.SYSTEM_UI_FLAG_LAYOUT_STABLE | - View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | - View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); + getWindow().getDecorView().setSystemUiVisibility( + View.SYSTEM_UI_FLAG_LAYOUT_STABLE | + View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | + View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); - getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN); - } + getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN); // Listen for UI visibility events getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(this); @@ -560,39 +558,19 @@ public class Game extends Activity implements SurfaceHolder.Callback, } if (desiredOrientation == Configuration.ORIENTATION_LANDSCAPE) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { - setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE); - } - else { - setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE); - } + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE); } else if (desiredOrientation == Configuration.ORIENTATION_PORTRAIT) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { - setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT); - } - else { - setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT); - } + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT); } else { // If we don't have a reason to lock to portrait or landscape, allow any orientation - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { - setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER); - } - else { - setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR); - } + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER); } } else { // For regular displays, we always request landscape - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { - setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE); - } - else { - setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE); - } + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE); } } @@ -920,7 +898,7 @@ public class Game extends Activity implements SurfaceHolder.Callback, displayRefreshRate = bestMode.getRefreshRate(); } // On L, we can at least tell the OS that we want a refresh rate - else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + else { float bestRefreshRate = display.getRefreshRate(); for (float candidate : display.getSupportedRefreshRates()) { LimeLog.info("Examining refresh rate: "+candidate); @@ -944,19 +922,12 @@ public class Game extends Activity implements SurfaceHolder.Callback, // Apply the refresh rate change getWindow().setAttributes(windowLayoutParams); } - else { - // Otherwise, the active display refresh rate is just - // whatever is currently in use. - displayRefreshRate = display.getRefreshRate(); - } - // From 4.4 to 5.1 we can't ask for a 4K display mode, so we'll + // Until Marshmallow, we can't ask for a 4K display mode, so we'll // need to hint the OS to provide one. boolean aspectRatioMatch = false; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && - Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP_MR1) { - // On KitKat and later (where we can use the whole screen via immersive mode), we'll - // calculate whether we need to scale by aspect ratio or not. If not, we'll use + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { + // We'll calculate whether we need to scale by aspect ratio. If not, we'll use // setFixedSize so we can handle 4K properly. The only known devices that have // >= 4K screens have exactly 4K screens, so we'll be able to hit this good path // on these devices. On Marshmallow, we can start changing to 4K manually but no @@ -1011,8 +982,8 @@ public class Game extends Activity implements SurfaceHolder.Callback, Game.this.getWindow().getDecorView().setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_STABLE); } - // Use immersive mode on 4.4+ or standard low profile on previous builds - else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + else { + // Use immersive mode Game.this.getWindow().getDecorView().setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | @@ -1021,11 +992,6 @@ public class Game extends Activity implements SurfaceHolder.Callback, View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); } - else { - Game.this.getWindow().getDecorView().setSystemUiVisibility( - View.SYSTEM_UI_FLAG_FULLSCREEN | - View.SYSTEM_UI_FLAG_LOW_PROFILE); - } } }; @@ -2214,13 +2180,11 @@ public class Game extends Activity implements SurfaceHolder.Callback, @SuppressLint("ClickableViewAccessibility") @Override public boolean onTouch(View view, MotionEvent event) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - if (event.getAction() == MotionEvent.ACTION_DOWN) { - // Tell the OS not to buffer input events for us - // - // NB: This is still needed even when we call the newer requestUnbufferedDispatch()! - view.requestUnbufferedDispatch(event); - } + if (event.getAction() == MotionEvent.ACTION_DOWN) { + // Tell the OS not to buffer input events for us + // + // NB: This is still needed even when we call the newer requestUnbufferedDispatch()! + view.requestUnbufferedDispatch(event); } return handleMotionEvent(view, event); @@ -2667,14 +2631,7 @@ public class Game extends Activity implements SurfaceHolder.Callback, if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) { hideSystemUi(2000); } - // This flag is only set on 4.4+ - else if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT && - (visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) { - hideSystemUi(2000); - } - // This flag is only set before 4.4+ - else if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.KITKAT && - (visibility & View.SYSTEM_UI_FLAG_LOW_PROFILE) == 0) { + else if ((visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) { hideSystemUi(2000); } } diff --git a/app/src/main/java/com/limelight/binding/audio/AndroidAudioRenderer.java b/app/src/main/java/com/limelight/binding/audio/AndroidAudioRenderer.java index 7c7776bc..dc25cc89 100644 --- a/app/src/main/java/com/limelight/binding/audio/AndroidAudioRenderer.java +++ b/app/src/main/java/com/limelight/binding/audio/AndroidAudioRenderer.java @@ -26,51 +26,41 @@ public class AndroidAudioRenderer implements AudioRenderer { } private AudioTrack createAudioTrack(int channelConfig, int sampleRate, int bufferSize, boolean lowLatency) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { - return new AudioTrack(AudioManager.STREAM_MUSIC, - sampleRate, - channelConfig, - AudioFormat.ENCODING_PCM_16BIT, - bufferSize, - AudioTrack.MODE_STREAM); + AudioAttributes.Builder attributesBuilder = new AudioAttributes.Builder() + .setUsage(AudioAttributes.USAGE_GAME); + AudioFormat format = new AudioFormat.Builder() + .setEncoding(AudioFormat.ENCODING_PCM_16BIT) + .setSampleRate(sampleRate) + .setChannelMask(channelConfig) + .build(); + + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { + // Use FLAG_LOW_LATENCY on L through N + if (lowLatency) { + attributesBuilder.setFlags(AudioAttributes.FLAG_LOW_LATENCY); + } + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + AudioTrack.Builder trackBuilder = new AudioTrack.Builder() + .setAudioFormat(format) + .setAudioAttributes(attributesBuilder.build()) + .setTransferMode(AudioTrack.MODE_STREAM) + .setBufferSizeInBytes(bufferSize); + + // Use PERFORMANCE_MODE_LOW_LATENCY on O and later + if (lowLatency) { + trackBuilder.setPerformanceMode(AudioTrack.PERFORMANCE_MODE_LOW_LATENCY); + } + + return trackBuilder.build(); } else { - AudioAttributes.Builder attributesBuilder = new AudioAttributes.Builder() - .setUsage(AudioAttributes.USAGE_GAME); - AudioFormat format = new AudioFormat.Builder() - .setEncoding(AudioFormat.ENCODING_PCM_16BIT) - .setSampleRate(sampleRate) - .setChannelMask(channelConfig) - .build(); - - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { - // Use FLAG_LOW_LATENCY on L through N - if (lowLatency) { - attributesBuilder.setFlags(AudioAttributes.FLAG_LOW_LATENCY); - } - } - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - AudioTrack.Builder trackBuilder = new AudioTrack.Builder() - .setAudioFormat(format) - .setAudioAttributes(attributesBuilder.build()) - .setTransferMode(AudioTrack.MODE_STREAM) - .setBufferSizeInBytes(bufferSize); - - // Use PERFORMANCE_MODE_LOW_LATENCY on O and later - if (lowLatency) { - trackBuilder.setPerformanceMode(AudioTrack.PERFORMANCE_MODE_LOW_LATENCY); - } - - return trackBuilder.build(); - } - else { - return new AudioTrack(attributesBuilder.build(), - format, - bufferSize, - AudioTrack.MODE_STREAM, - AudioManager.AUDIO_SESSION_ID_GENERATE); - } + return new AudioTrack(attributesBuilder.build(), + format, + bufferSize, + AudioTrack.MODE_STREAM, + AudioManager.AUDIO_SESSION_ID_GENERATE); } } @@ -91,20 +81,10 @@ public class AndroidAudioRenderer implements AudioRenderer { channelConfig = AudioFormat.CHANNEL_OUT_5POINT1; break; case 8: - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - // AudioFormat.CHANNEL_OUT_7POINT1_SURROUND isn't available until Android 6.0, - // yet the CHANNEL_OUT_SIDE_LEFT and CHANNEL_OUT_SIDE_RIGHT constants were added - // in 5.0, so just hardcode the constant so we can work on Lollipop. - channelConfig = 0x000018fc; // AudioFormat.CHANNEL_OUT_7POINT1_SURROUND - } - else { - // On KitKat and lower, creation of the AudioTrack will fail if we specify - // CHANNEL_OUT_SIDE_LEFT or CHANNEL_OUT_SIDE_RIGHT. That leaves us with - // the old CHANNEL_OUT_7POINT1 which uses left-of-center and right-of-center - // speakers instead of side-left and side-right. This non-standard layout - // is probably not what the user wants, but we don't really have a choice. - channelConfig = AudioFormat.CHANNEL_OUT_7POINT1; - } + // AudioFormat.CHANNEL_OUT_7POINT1_SURROUND isn't available until Android 6.0, + // yet the CHANNEL_OUT_SIDE_LEFT and CHANNEL_OUT_SIDE_RIGHT constants were added + // in 5.0, so just hardcode the constant so we can work on Lollipop. + channelConfig = 0x000018fc; // AudioFormat.CHANNEL_OUT_7POINT1_SURROUND break; default: LimeLog.severe("Decoder returned unhandled channel count"); diff --git a/app/src/main/java/com/limelight/binding/input/ControllerHandler.java b/app/src/main/java/com/limelight/binding/input/ControllerHandler.java index afe989f3..f7c8c0d1 100644 --- a/app/src/main/java/com/limelight/binding/input/ControllerHandler.java +++ b/app/src/main/java/com/limelight/binding/input/ControllerHandler.java @@ -666,7 +666,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD // back button to function for navigation. // // First, check if this is an internal device we're being called on. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && !isExternal(dev)) { + if (!isExternal(dev)) { InputManager im = (InputManager) activityContext.getSystemService(Context.INPUT_SERVICE); boolean foundInternalGamepad = false; @@ -712,10 +712,8 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD String devName = dev.getName(); LimeLog.info("Creating controller context for device: "+devName); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - LimeLog.info("Vendor ID: "+dev.getVendorId()); - LimeLog.info("Product ID: "+dev.getProductId()); - } + LimeLog.info("Vendor ID: " + dev.getVendorId()); + LimeLog.info("Product ID: "+dev.getProductId()); LimeLog.info(dev.toString()); context.inputDevice = dev; @@ -723,15 +721,13 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD context.id = dev.getId(); context.external = isExternal(dev); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - context.vendorId = dev.getVendorId(); - context.productId = dev.getProductId(); + context.vendorId = dev.getVendorId(); + context.productId = dev.getProductId(); - // These aren't always present in the Android key layout files, so they won't show up - // in our normal InputDevice.hasKeys() probing. - context.hasPaddles = MoonBridge.guessControllerHasPaddles(context.vendorId, context.productId); - context.hasShare = MoonBridge.guessControllerHasShareButton(context.vendorId, context.productId); - } + // These aren't always present in the Android key layout files, so they won't show up + // in our normal InputDevice.hasKeys() probing. + context.hasPaddles = MoonBridge.guessControllerHasPaddles(context.vendorId, context.productId); + context.hasShare = MoonBridge.guessControllerHasShareButton(context.vendorId, context.productId); // Try to use the InputDevice's associated vibrators first if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && hasQuadAmplitudeControlledRumbleVibrators(dev.getVibratorManager())) { @@ -790,11 +786,9 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD // Detect if the gamepad has Mode and Select buttons according to the Android key layouts. // We do this first because other codepaths below may override these defaults. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - boolean[] buttons = dev.hasKeys(KeyEvent.KEYCODE_BUTTON_MODE, KeyEvent.KEYCODE_BUTTON_SELECT, KeyEvent.KEYCODE_BACK, 0); - context.hasMode = buttons[0]; - context.hasSelect = buttons[1] || buttons[2]; - } + boolean[] buttons = dev.hasKeys(KeyEvent.KEYCODE_BUTTON_MODE, KeyEvent.KEYCODE_BUTTON_SELECT, KeyEvent.KEYCODE_BACK, 0); + context.hasMode = buttons[0]; + context.hasSelect = buttons[1] || buttons[2]; context.touchpadXRange = dev.getMotionRange(MotionEvent.AXIS_X, InputDevice.SOURCE_TOUCHPAD); context.touchpadYRange = dev.getMotionRange(MotionEvent.AXIS_Y, InputDevice.SOURCE_TOUCHPAD); @@ -844,22 +838,15 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD InputDevice.MotionRange rxRange = getMotionRangeForJoystickAxis(dev, MotionEvent.AXIS_RX); InputDevice.MotionRange ryRange = getMotionRangeForJoystickAxis(dev, MotionEvent.AXIS_RY); if (rxRange != null && ryRange != null && devName != null) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - if (dev.getVendorId() == 0x054c) { // Sony - if (dev.hasKeys(KeyEvent.KEYCODE_BUTTON_C)[0]) { - LimeLog.info("Detected non-standard DualShock 4 mapping"); - context.isNonStandardDualShock4 = true; - } - else { - LimeLog.info("Detected DualShock 4 (Linux standard mapping)"); - context.usesLinuxGamepadStandardFaceButtons = true; - } + if (dev.getVendorId() == 0x054c) { // Sony + if (dev.hasKeys(KeyEvent.KEYCODE_BUTTON_C)[0]) { + LimeLog.info("Detected non-standard DualShock 4 mapping"); + context.isNonStandardDualShock4 = true; + } else { + LimeLog.info("Detected DualShock 4 (Linux standard mapping)"); + context.usesLinuxGamepadStandardFaceButtons = true; } } - else if (!devName.contains("Xbox") && !devName.contains("XBox") && !devName.contains("X-Box")) { - LimeLog.info("Assuming non-standard DualShock 4 mapping on < 4.4"); - context.isNonStandardDualShock4 = true; - } if (context.isNonStandardDualShock4) { // The old DS4 driver uses RX and RY for triggers @@ -943,16 +930,12 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD } // The ADT-1 controller needs a similar fixup to the ASUS Gamepad - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - // The device name provided is just "Gamepad" which is pretty useless, so we - // use VID/PID instead - if (dev.getVendorId() == 0x18d1 && dev.getProductId() == 0x2c40) { - context.backIsStart = true; - context.modeIsSelect = true; - context.triggerDeadzone = 0.30f; - context.hasSelect = true; - context.hasMode = false; - } + if (dev.getVendorId() == 0x18d1 && dev.getProductId() == 0x2c40) { + context.backIsStart = true; + context.modeIsSelect = true; + context.triggerDeadzone = 0.30f; + context.hasSelect = true; + context.hasMode = false; } context.ignoreBack = shouldIgnoreBack(dev); @@ -962,16 +945,12 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD // use the back button as start since it doesn't have a start/menu button // on the controller if (devName.contains("ASUS Gamepad")) { - // We can only do this check on KitKat or higher, but it doesn't matter since ATV - // is Android 5.0 anyway - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - boolean[] hasStartKey = dev.hasKeys(KeyEvent.KEYCODE_BUTTON_START, KeyEvent.KEYCODE_MENU, 0); - if (!hasStartKey[0] && !hasStartKey[1]) { - context.backIsStart = true; - context.modeIsSelect = true; - context.hasSelect = true; - context.hasMode = false; - } + boolean[] hasStartKey = dev.hasKeys(KeyEvent.KEYCODE_BUTTON_START, KeyEvent.KEYCODE_MENU, 0); + if (!hasStartKey[0] && !hasStartKey[1]) { + context.backIsStart = true; + context.modeIsSelect = true; + context.hasSelect = true; + context.hasMode = false; } // The ASUS Gamepad has triggers that sit far forward and are prone to false presses @@ -1016,10 +995,8 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD // Thrustmaster Score A gamepad home button reports directly to android as // KEY_HOMEPAGE event on another event channel - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - if (dev.getVendorId() == 0x044f && dev.getProductId() == 0xb328) { - context.hasMode = false; - } + if (dev.getVendorId() == 0x044f && dev.getProductId() == 0xb328) { + context.hasMode = false; } LimeLog.info("Analog stick deadzone: "+context.leftStickDeadzoneRadius+" "+context.rightStickDeadzoneRadius); @@ -2048,15 +2025,12 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD .build(); vibrator.vibrate(VibrationEffect.createWaveform(new long[]{0, onTime, offTime}, 0), vibrationAttributes); } - else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + else { AudioAttributes audioAttributes = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_GAME) .build(); vibrator.vibrate(new long[]{0, onTime, offTime}, 0, audioAttributes); } - else { - vibrator.vibrate(new long[]{0, onTime, offTime}, 0); - } } public void handleRumble(short controllerNumber, short lowFreqMotor, short highFreqMotor) { @@ -3086,11 +3060,6 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD @Override public void sendControllerArrival() { - // Below KitKat we can't get enough information to report controller details accurately - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { - return; - } - byte type; switch (inputDevice.getVendorId()) { case 0x045e: // Microsoft diff --git a/app/src/main/java/com/limelight/binding/input/driver/UsbDriverService.java b/app/src/main/java/com/limelight/binding/input/driver/UsbDriverService.java index 2127bcef..f81221a5 100644 --- a/app/src/main/java/com/limelight/binding/input/driver/UsbDriverService.java +++ b/app/src/main/java/com/limelight/binding/input/driver/UsbDriverService.java @@ -211,28 +211,22 @@ public class UsbDriverService extends Service implements UsbDriverListener { } public static boolean isRecognizedInputDevice(UsbDevice device) { - // On KitKat and later, we can determine if this VID and PID combo - // matches an existing input device and defer to the built-in controller - // support in that case. Prior to KitKat, we'll always return true to be safe. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - for (int id : InputDevice.getDeviceIds()) { - InputDevice inputDev = InputDevice.getDevice(id); - if (inputDev == null) { - // Device was removed while looping - continue; - } - - if (inputDev.getVendorId() == device.getVendorId() && - inputDev.getProductId() == device.getProductId()) { - return true; - } + // Determine if this VID and PID combo matches an existing input device + // and defer to the built-in controller support in that case. + for (int id : InputDevice.getDeviceIds()) { + InputDevice inputDev = InputDevice.getDevice(id); + if (inputDev == null) { + // Device was removed while looping + continue; } - return false; - } - else { - return true; + if (inputDev.getVendorId() == device.getVendorId() && + inputDev.getProductId() == device.getProductId()) { + return true; + } } + + return false; } public static boolean kernelSupportsXboxOne() { diff --git a/app/src/main/java/com/limelight/binding/input/driver/Xbox360WirelessDongle.java b/app/src/main/java/com/limelight/binding/input/driver/Xbox360WirelessDongle.java index 632f1825..0aa311a6 100644 --- a/app/src/main/java/com/limelight/binding/input/driver/Xbox360WirelessDongle.java +++ b/app/src/main/java/com/limelight/binding/input/driver/Xbox360WirelessDongle.java @@ -89,28 +89,26 @@ public class Xbox360WirelessDongle extends AbstractController { public boolean start() { int controllerIndex = 0; - // On KitKat, there is a controller number associated with input devices. + // On Android, there is a controller number associated with input devices. // We can use this to approximate the likely controller number. This won't // be completely accurate because there's no guarantee the order of interfaces // matches the order that devices were enumerated by xpad, but it's probably // better than nothing. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - for (int id : InputDevice.getDeviceIds()) { - InputDevice inputDev = InputDevice.getDevice(id); - if (inputDev == null) { - // Device was removed while looping - continue; - } + for (int id : InputDevice.getDeviceIds()) { + InputDevice inputDev = InputDevice.getDevice(id); + if (inputDev == null) { + // Device was removed while looping + continue; + } - // Newer xpad versions use a special product ID (0x02a1) for controllers - // rather than copying the product ID of the dongle itself. - if (inputDev.getVendorId() == device.getVendorId() && - (inputDev.getProductId() == device.getProductId() || - inputDev.getProductId() == 0x02a1) && - inputDev.getControllerNumber() > 0) { - controllerIndex = inputDev.getControllerNumber() - 1; - break; - } + // Newer xpad versions use a special product ID (0x02a1) for controllers + // rather than copying the product ID of the dongle itself. + if (inputDev.getVendorId() == device.getVendorId() && + (inputDev.getProductId() == device.getProductId() || + inputDev.getProductId() == 0x02a1) && + inputDev.getControllerNumber() > 0) { + controllerIndex = inputDev.getControllerNumber() - 1; + break; } } diff --git a/app/src/main/java/com/limelight/binding/video/MediaCodecDecoderRenderer.java b/app/src/main/java/com/limelight/binding/video/MediaCodecDecoderRenderer.java index 9bda0e6b..d24ec0dc 100644 --- a/app/src/main/java/com/limelight/binding/video/MediaCodecDecoderRenderer.java +++ b/app/src/main/java/com/limelight/binding/video/MediaCodecDecoderRenderer.java @@ -471,9 +471,8 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C videoFormat.setInteger(MediaFormat.KEY_FRAME_RATE, refreshRate); } - // Adaptive playback can also be enabled by the whitelist on pre-KitKat devices - // so we don't fill these pre-KitKat - if (adaptivePlayback && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + // Populate keys for adaptive playback + if (adaptivePlayback) { videoFormat.setInteger(MediaFormat.KEY_MAX_WIDTH, initialWidth); videoFormat.setInteger(MediaFormat.KEY_MAX_HEIGHT, initialHeight); } diff --git a/app/src/main/java/com/limelight/binding/video/MediaCodecHelper.java b/app/src/main/java/com/limelight/binding/video/MediaCodecHelper.java index f6c86d6f..24d1f01a 100644 --- a/app/src/main/java/com/limelight/binding/video/MediaCodecHelper.java +++ b/app/src/main/java/com/limelight/binding/video/MediaCodecHelper.java @@ -596,45 +596,39 @@ public class MediaCodecHelper { public static boolean decoderSupportsFusedIdrFrame(MediaCodecInfo decoderInfo, String mimeType) { // If adaptive playback is supported, we can submit new CSD together with a keyframe - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - try { - if (decoderInfo.getCapabilitiesForType(mimeType). - isFeatureSupported(CodecCapabilities.FEATURE_AdaptivePlayback)) - { - LimeLog.info("Decoder supports fused IDR frames (FEATURE_AdaptivePlayback)"); - return true; - } - } catch (Exception e) { - // Tolerate buggy codecs - e.printStackTrace(); + try { + if (decoderInfo.getCapabilitiesForType(mimeType). + isFeatureSupported(CodecCapabilities.FEATURE_AdaptivePlayback)) { + LimeLog.info("Decoder supports fused IDR frames (FEATURE_AdaptivePlayback)"); + return true; } + } catch (Exception e) { + // Tolerate buggy codecs + e.printStackTrace(); } return false; } public static boolean decoderSupportsAdaptivePlayback(MediaCodecInfo decoderInfo, String mimeType) { - // Possibly enable adaptive playback on KitKat and above - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - if (isDecoderInList(blacklistedAdaptivePlaybackPrefixes, decoderInfo.getName())) { - LimeLog.info("Decoder blacklisted for adaptive playback"); - return false; - } - - try { - if (decoderInfo.getCapabilitiesForType(mimeType). - isFeatureSupported(CodecCapabilities.FEATURE_AdaptivePlayback)) - { - // This will make getCapabilities() return that adaptive playback is supported - LimeLog.info("Adaptive playback supported (FEATURE_AdaptivePlayback)"); - return true; - } - } catch (Exception e) { - // Tolerate buggy codecs - e.printStackTrace(); - } + if (isDecoderInList(blacklistedAdaptivePlaybackPrefixes, decoderInfo.getName())) { + LimeLog.info("Decoder blacklisted for adaptive playback"); + return false; } - + + try { + if (decoderInfo.getCapabilitiesForType(mimeType). + isFeatureSupported(CodecCapabilities.FEATURE_AdaptivePlayback)) + { + // This will make getCapabilities() return that adaptive playback is supported + LimeLog.info("Adaptive playback supported (FEATURE_AdaptivePlayback)"); + return true; + } + } catch (Exception e) { + // Tolerate buggy codecs + e.printStackTrace(); + } + return false; } @@ -709,13 +703,6 @@ public class MediaCodecHelper { } public static boolean decoderIsWhitelistedForHevc(MediaCodecInfo decoderInfo) { - // Google didn't have official support for HEVC (or more importantly, a CTS test) until - // Lollipop. I've seen some MediaTek devices on 4.4 crash when attempting to use HEVC, - // so I'm restricting HEVC usage to Lollipop and higher. - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { - return false; - } - // // Software decoders are terrible and we never want to use them. // We want to catch decoders like: @@ -784,17 +771,10 @@ public class MediaCodecHelper { @SuppressLint("NewApi") private static LinkedList getMediaCodecList() { LinkedList infoList = new LinkedList<>(); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS); - Collections.addAll(infoList, mcl.getCodecInfos()); - } - else { - for (int i = 0; i < MediaCodecList.getCodecCount(); i++) { - infoList.add(MediaCodecList.getCodecInfoAt(i)); - } - } - + + MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS); + Collections.addAll(infoList, mcl.getCodecInfos()); + return infoList; } diff --git a/app/src/main/java/com/limelight/computers/ComputerManagerService.java b/app/src/main/java/com/limelight/computers/ComputerManagerService.java index f8d77f9f..990a8953 100644 --- a/app/src/main/java/com/limelight/computers/ComputerManagerService.java +++ b/app/src/main/java/com/limelight/computers/ComputerManagerService.java @@ -341,57 +341,53 @@ public class ComputerManagerService extends Service { // Acquire the default network lock since we could be changing global process state defaultNetworkLock.lock(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - // On Lollipop or later, we can bind our process to the underlying interface - // to ensure our STUN request goes out on that interface or not at all (which is - // preferable to getting a VPN endpoint address back). - Network[] networks = connMgr.getAllNetworks(); - for (Network net : networks) { - NetworkCapabilities netCaps = connMgr.getNetworkCapabilities(net); - if (netCaps != null) { - if (!netCaps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) && - !netCaps.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) { - // This network looks like an underlying multicast-capable transport, - // so let's guess that it's probably where our mDNS response came from. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - if (connMgr.bindProcessToNetwork(net)) { - boundToNetwork = true; - break; - } - } - else if (ConnectivityManager.setProcessDefaultNetwork(net)) { + // On Lollipop or later, we can bind our process to the underlying interface + // to ensure our STUN request goes out on that interface or not at all (which is + // preferable to getting a VPN endpoint address back). + Network[] networks = connMgr.getAllNetworks(); + for (Network net : networks) { + NetworkCapabilities netCaps = connMgr.getNetworkCapabilities(net); + if (netCaps != null) { + if (!netCaps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) && + !netCaps.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) { + // This network looks like an underlying multicast-capable transport, + // so let's guess that it's probably where our mDNS response came from. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + if (connMgr.bindProcessToNetwork(net)) { boundToNetwork = true; break; } + } else if (ConnectivityManager.setProcessDefaultNetwork(net)) { + boundToNetwork = true; + break; } } } } - } - // Perform the STUN request if we're not on a VPN or if we bound to a network - if (!activeNetworkIsVpn || boundToNetwork) { - String stunResolvedAddress = NvConnection.findExternalAddressForMdns("stun.moonlight-stream.org", 3478); - if (stunResolvedAddress != null) { - // We don't know for sure what the external port is, so we will have to guess. - // When we contact the PC (if we haven't already), it will update the port. - details.remoteAddress = new ComputerDetails.AddressTuple(stunResolvedAddress, details.guessExternalPort()); + // Perform the STUN request if we're not on a VPN or if we bound to a network + if (!activeNetworkIsVpn || boundToNetwork) { + String stunResolvedAddress = NvConnection.findExternalAddressForMdns("stun.moonlight-stream.org", 3478); + if (stunResolvedAddress != null) { + // We don't know for sure what the external port is, so we will have to guess. + // When we contact the PC (if we haven't already), it will update the port. + details.remoteAddress = new ComputerDetails.AddressTuple(stunResolvedAddress, details.guessExternalPort()); + } } - } - // Unbind from the network - if (boundToNetwork) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - connMgr.bindProcessToNetwork(null); + // Unbind from the network + if (boundToNetwork) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + connMgr.bindProcessToNetwork(null); + } else { + ConnectivityManager.setProcessDefaultNetwork(null); + } } - else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - ConnectivityManager.setProcessDefaultNetwork(null); - } - } - // Unlock the network state - if (activeNetworkIsVpn) { - defaultNetworkLock.unlock(); + // Unlock the network state + if (activeNetworkIsVpn) { + defaultNetworkLock.unlock(); + } } } diff --git a/app/src/main/java/com/limelight/grid/assets/DiskAssetLoader.java b/app/src/main/java/com/limelight/grid/assets/DiskAssetLoader.java index 8cd63bdf..dc496a6b 100644 --- a/app/src/main/java/com/limelight/grid/assets/DiskAssetLoader.java +++ b/app/src/main/java/com/limelight/grid/assets/DiskAssetLoader.java @@ -28,14 +28,8 @@ public class DiskAssetLoader { public DiskAssetLoader(Context context) { this.cacheDir = context.getCacheDir(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - this.isLowRamDevice = - ((ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE)).isLowRamDevice(); - } - else { - // Use conservative low RAM behavior on very old devices - this.isLowRamDevice = true; - } + this.isLowRamDevice = + ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE)).isLowRamDevice(); } public boolean checkCacheExists(CachedAppAssetLoader.LoaderTuple tuple) { diff --git a/app/src/main/java/com/limelight/nvstream/NvConnection.java b/app/src/main/java/com/limelight/nvstream/NvConnection.java index f892e9f7..f29563f1 100644 --- a/app/src/main/java/com/limelight/nvstream/NvConnection.java +++ b/app/src/main/java/com/limelight/nvstream/NvConnection.java @@ -198,7 +198,7 @@ public class NvConnection { } } } - else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + else { NetworkInfo activeNetworkInfo = connMgr.getActiveNetworkInfo(); if (activeNetworkInfo != null) { switch (activeNetworkInfo.getType()) { diff --git a/app/src/main/java/com/limelight/nvstream/http/NvHTTP.java b/app/src/main/java/com/limelight/nvstream/http/NvHTTP.java index 775a35ea..c4dcb537 100644 --- a/app/src/main/java/com/limelight/nvstream/http/NvHTTP.java +++ b/app/src/main/java/com/limelight/nvstream/http/NvHTTP.java @@ -403,16 +403,7 @@ public class NvHTTP { try { SSLContext sc = SSLContext.getInstance("TLS"); sc.init(new KeyManager[] { keyManager }, new TrustManager[] { trustManager }, new SecureRandom()); - - // TLS 1.2 is not enabled by default prior to Android 5.0, so we'll need a custom - // SSLSocketFactory in order to connect to GFE 3.20.4 which requires TLSv1.2 or later. - // We don't just always use TLSv12SocketFactory because explicitly specifying TLS versions - // prevents later TLS versions from being negotiated even if client and server otherwise - // support them. - return client.newBuilder().sslSocketFactory( - Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? - sc.getSocketFactory() : new TLSv12SocketFactory(sc), - trustManager).build(); + return client.newBuilder().sslSocketFactory(sc.getSocketFactory(), trustManager).build(); } catch (NoSuchAlgorithmException | KeyManagementException e) { throw new RuntimeException(e); } @@ -814,62 +805,4 @@ public class NvHTTP { return true; } - - // Based on example code from https://blog.dev-area.net/2015/08/13/android-4-1-enable-tls-1-1-and-tls-1-2/ - private static class TLSv12SocketFactory extends SSLSocketFactory { - private SSLSocketFactory internalSSLSocketFactory; - - public TLSv12SocketFactory(SSLContext context) { - internalSSLSocketFactory = context.getSocketFactory(); - } - - @Override - public String[] getDefaultCipherSuites() { - return internalSSLSocketFactory.getDefaultCipherSuites(); - } - - @Override - public String[] getSupportedCipherSuites() { - return internalSSLSocketFactory.getSupportedCipherSuites(); - } - - @Override - public Socket createSocket() throws IOException { - return enableTLSv12OnSocket(internalSSLSocketFactory.createSocket()); - } - - @Override - public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { - return enableTLSv12OnSocket(internalSSLSocketFactory.createSocket(s, host, port, autoClose)); - } - - @Override - public Socket createSocket(String host, int port) throws IOException { - return enableTLSv12OnSocket(internalSSLSocketFactory.createSocket(host, port)); - } - - @Override - public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException { - return enableTLSv12OnSocket(internalSSLSocketFactory.createSocket(host, port, localHost, localPort)); - } - - @Override - public Socket createSocket(InetAddress host, int port) throws IOException { - return enableTLSv12OnSocket(internalSSLSocketFactory.createSocket(host, port)); - } - - @Override - public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { - return enableTLSv12OnSocket(internalSSLSocketFactory.createSocket(address, port, localAddress, localPort)); - } - - private Socket enableTLSv12OnSocket(Socket socket) { - if (socket instanceof SSLSocket) { - // TLS 1.2 is not enabled by default prior to Android 5.0. We must enable it - // explicitly to ensure we can communicate with GFE 3.20.4 which blocks TLS 1.0. - ((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.2"}); - } - return socket; - } - } } diff --git a/app/src/main/java/com/limelight/preferences/ConfirmDeleteOscPreference.java b/app/src/main/java/com/limelight/preferences/ConfirmDeleteOscPreference.java index 8c83457f..01f5c340 100644 --- a/app/src/main/java/com/limelight/preferences/ConfirmDeleteOscPreference.java +++ b/app/src/main/java/com/limelight/preferences/ConfirmDeleteOscPreference.java @@ -13,7 +13,6 @@ import com.limelight.R; import static com.limelight.binding.input.virtual_controller.VirtualControllerConfigurationLoader.OSC_PREFERENCE; public class ConfirmDeleteOscPreference extends DialogPreference { - @TargetApi(Build.VERSION_CODES.LOLLIPOP) public ConfirmDeleteOscPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } @@ -26,7 +25,6 @@ public class ConfirmDeleteOscPreference extends DialogPreference { super(context, attrs); } - @TargetApi(Build.VERSION_CODES.LOLLIPOP) public ConfirmDeleteOscPreference(Context context) { super(context); } diff --git a/app/src/main/java/com/limelight/preferences/LanguagePreference.java b/app/src/main/java/com/limelight/preferences/LanguagePreference.java index 2ce8fb2b..6549b015 100644 --- a/app/src/main/java/com/limelight/preferences/LanguagePreference.java +++ b/app/src/main/java/com/limelight/preferences/LanguagePreference.java @@ -11,12 +11,10 @@ import android.provider.Settings; import android.util.AttributeSet; public class LanguagePreference extends ListPreference { - @TargetApi(Build.VERSION_CODES.LOLLIPOP) public LanguagePreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } - @TargetApi(Build.VERSION_CODES.LOLLIPOP) public LanguagePreference(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } diff --git a/app/src/main/java/com/limelight/preferences/StreamSettings.java b/app/src/main/java/com/limelight/preferences/StreamSettings.java index f5bd2032..70701041 100644 --- a/app/src/main/java/com/limelight/preferences/StreamSettings.java +++ b/app/src/main/java/com/limelight/preferences/StreamSettings.java @@ -511,29 +511,15 @@ public class StreamSettings extends Activity { // Never remove 720p } } - else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { - // On Android 4.2 and later, we can get the true metrics via the - // getRealMetrics() function (unlike the lies that getWidth() and getHeight() - // tell to us). + else { + // We can get the true metrics via the getRealMetrics() function (unlike the lies + // that getWidth() and getHeight() tell to us). DisplayMetrics metrics = new DisplayMetrics(); display.getRealMetrics(metrics); int width = Math.max(metrics.widthPixels, metrics.heightPixels); int height = Math.min(metrics.widthPixels, metrics.heightPixels); addNativeResolutionEntries(width, height, false); } - else { - // On Android 4.1, we have to resort to reflection to invoke hidden APIs - // to get the real screen dimensions. - try { - Method getRawHeightFunc = Display.class.getMethod("getRawHeight"); - Method getRawWidthFunc = Display.class.getMethod("getRawWidth"); - int width = (Integer) getRawWidthFunc.invoke(display); - int height = (Integer) getRawHeightFunc.invoke(display); - addNativeResolutionEntries(Math.max(width, height), Math.min(width, height), false); - } catch (Exception e) { - e.printStackTrace(); - } - } if (!PreferenceConfiguration.readPreferences(this.getActivity()).unlockFps) { // We give some extra room in case the FPS is rounded down @@ -562,49 +548,29 @@ public class StreamSettings extends Activity { } addNativeFrameRateEntry(maxSupportedFps); - // Android L introduces proper 7.1 surround sound support. Remove the 7.1 option - // for earlier versions of Android to prevent AudioTrack initialization issues. - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { - LimeLog.info("Excluding 7.1 surround sound option based on OS"); - removeValue(PreferenceConfiguration.AUDIO_CONFIG_PREF_STRING, "71", new Runnable() { - @Override - public void run() { - setValue(PreferenceConfiguration.AUDIO_CONFIG_PREF_STRING, "51"); - } - }); - } - // Android L introduces the drop duplicate behavior of releaseOutputBuffer() // that the unlock FPS option relies on to not massively increase latency. - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { - LimeLog.info("Excluding unlock FPS toggle based on OS"); - PreferenceCategory category = - (PreferenceCategory) findPreference("category_advanced_settings"); - category.removePreference(findPreference("checkbox_unlock_fps")); - } - else { - findPreference(PreferenceConfiguration.UNLOCK_FPS_STRING).setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - // HACK: We need to let the preference change succeed before reinitializing to ensure - // it's reflected in the new layout. - final Handler h = new Handler(); - h.postDelayed(new Runnable() { - @Override - public void run() { - // Ensure the activity is still open when this timeout expires - StreamSettings settingsActivity = (StreamSettings)SettingsFragment.this.getActivity(); - if (settingsActivity != null) { - settingsActivity.reloadSettings(); - } + findPreference(PreferenceConfiguration.UNLOCK_FPS_STRING).setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + // HACK: We need to let the preference change succeed before reinitializing to ensure + // it's reflected in the new layout. + final Handler h = new Handler(); + h.postDelayed(new Runnable() { + @Override + public void run() { + // Ensure the activity is still open when this timeout expires + StreamSettings settingsActivity = (StreamSettings) SettingsFragment.this.getActivity(); + if (settingsActivity != null) { + settingsActivity.reloadSettings(); } - }, 500); + } + }, 500); - // Allow the original preference change to take place - return true; - } - }); - } + // Allow the original preference change to take place + return true; + } + }); // Remove HDR preference for devices below Nougat if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { @@ -623,6 +589,7 @@ public class StreamSettings extends Activity { for (int hdrType : hdrCaps.getSupportedHdrTypes()) { if (hdrType == Display.HdrCapabilities.HDR_TYPE_HDR10) { foundHdr10 = true; + break; } } } diff --git a/app/src/main/java/com/limelight/preferences/WebLauncherPreference.java b/app/src/main/java/com/limelight/preferences/WebLauncherPreference.java index 044c5ce3..d01a7b1e 100644 --- a/app/src/main/java/com/limelight/preferences/WebLauncherPreference.java +++ b/app/src/main/java/com/limelight/preferences/WebLauncherPreference.java @@ -21,7 +21,6 @@ public class WebLauncherPreference extends Preference { initialize(attrs); } - @TargetApi(Build.VERSION_CODES.LOLLIPOP) public WebLauncherPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); initialize(attrs); diff --git a/app/src/main/java/com/limelight/ui/AdapterFragment.java b/app/src/main/java/com/limelight/ui/AdapterFragment.java index 8076fa06..8e1c7b91 100644 --- a/app/src/main/java/com/limelight/ui/AdapterFragment.java +++ b/app/src/main/java/com/limelight/ui/AdapterFragment.java @@ -30,6 +30,6 @@ public class AdapterFragment extends Fragment { @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - callbacks.receiveAbsListView((AbsListView) getView().findViewById(R.id.fragmentView)); + callbacks.receiveAbsListView(getView().findViewById(R.id.fragmentView)); } } diff --git a/app/src/main/java/com/limelight/ui/StreamView.java b/app/src/main/java/com/limelight/ui/StreamView.java index 46d693b3..a11b4166 100644 --- a/app/src/main/java/com/limelight/ui/StreamView.java +++ b/app/src/main/java/com/limelight/ui/StreamView.java @@ -30,7 +30,6 @@ public class StreamView extends SurfaceView { super(context, attrs, defStyleAttr); } - @TargetApi(21) public StreamView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } diff --git a/app/src/main/java/com/limelight/utils/NetHelper.java b/app/src/main/java/com/limelight/utils/NetHelper.java index 4a6d7dc0..eb5512f8 100644 --- a/app/src/main/java/com/limelight/utils/NetHelper.java +++ b/app/src/main/java/com/limelight/utils/NetHelper.java @@ -20,7 +20,7 @@ public class NetHelper { } } } - else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + else { NetworkInfo activeNetworkInfo = connMgr.getActiveNetworkInfo(); if (activeNetworkInfo != null) { return activeNetworkInfo.getType() == ConnectivityManager.TYPE_VPN; diff --git a/app/src/main/jni/Application.mk b/app/src/main/jni/Application.mk index 32615607..f3ca2668 100644 --- a/app/src/main/jni/Application.mk +++ b/app/src/main/jni/Application.mk @@ -1,4 +1,4 @@ # Application.mk for Moonlight -# Our minimum version is Android 4.1 -APP_PLATFORM := android-16 +# Our minimum version is Android 5.0 +APP_PLATFORM := android-21