mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2026-10-22 16:17:27 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
36191781ed | ||
|
|
61b6a49669 | ||
|
|
e97845e46e | ||
|
|
6bba68207d | ||
|
|
0e17cccc06 | ||
|
|
918e922e40 | ||
|
|
a08854ddfd | ||
|
|
eb6f15c2b7 | ||
|
|
2cd9e31684 | ||
|
|
791d6624e2 | ||
|
|
af41021271 |
No files matched your search
+4
-1
@@ -1,6 +1,9 @@
|
|||||||
#built application files
|
# built application files
|
||||||
*.apk
|
*.apk
|
||||||
*.ap_
|
*.ap_
|
||||||
|
*.aab
|
||||||
|
output.json
|
||||||
|
out/
|
||||||
|
|
||||||
# files for the dex VM
|
# files for the dex VM
|
||||||
*.dex
|
*.dex
|
||||||
|
|||||||
+2
-2
@@ -8,8 +8,8 @@ android {
|
|||||||
minSdkVersion 16
|
minSdkVersion 16
|
||||||
targetSdkVersion 28
|
targetSdkVersion 28
|
||||||
|
|
||||||
versionName "5.8.1"
|
versionName "5.8.2"
|
||||||
versionCode = 166
|
versionCode = 167
|
||||||
}
|
}
|
||||||
|
|
||||||
flavorDimensions "root"
|
flavorDimensions "root"
|
||||||
|
|||||||
@@ -834,8 +834,12 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle a synthetic back button event that some Android OS versions
|
// Handle a synthetic back button event that some Android OS versions
|
||||||
// create as a result of a right-click.
|
// create as a result of a right-click. This event WILL repeat if
|
||||||
if (event.getSource() == InputDevice.SOURCE_MOUSE && event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
|
// the right mouse button is held down, so we ignore those.
|
||||||
|
if ((event.getSource() == InputDevice.SOURCE_MOUSE ||
|
||||||
|
event.getSource() == InputDevice.SOURCE_MOUSE_RELATIVE) &&
|
||||||
|
event.getKeyCode() == KeyEvent.KEYCODE_BACK &&
|
||||||
|
event.getRepeatCount() == 0) {
|
||||||
conn.sendMouseButtonDown(MouseButtonPacket.BUTTON_RIGHT);
|
conn.sendMouseButtonDown(MouseButtonPacket.BUTTON_RIGHT);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -885,7 +889,9 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
|
|
||||||
// Handle a synthetic back button event that some Android OS versions
|
// Handle a synthetic back button event that some Android OS versions
|
||||||
// create as a result of a right-click.
|
// create as a result of a right-click.
|
||||||
if (event.getSource() == InputDevice.SOURCE_MOUSE && event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
|
if ((event.getSource() == InputDevice.SOURCE_MOUSE ||
|
||||||
|
event.getSource() == InputDevice.SOURCE_MOUSE_RELATIVE) &&
|
||||||
|
event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
|
||||||
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_RIGHT);
|
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_RIGHT);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -953,6 +959,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
{
|
{
|
||||||
// This case is for mice
|
// This case is for mice
|
||||||
if (event.getSource() == InputDevice.SOURCE_MOUSE ||
|
if (event.getSource() == InputDevice.SOURCE_MOUSE ||
|
||||||
|
event.getSource() == InputDevice.SOURCE_MOUSE_RELATIVE ||
|
||||||
(event.getPointerCount() >= 1 &&
|
(event.getPointerCount() >= 1 &&
|
||||||
event.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE))
|
event.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE))
|
||||||
{
|
{
|
||||||
@@ -968,6 +975,13 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
byte vScrollClicks = (byte) event.getAxisValue(MotionEvent.AXIS_VSCROLL);
|
byte vScrollClicks = (byte) event.getAxisValue(MotionEvent.AXIS_VSCROLL);
|
||||||
conn.sendMouseScroll(vScrollClicks);
|
conn.sendMouseScroll(vScrollClicks);
|
||||||
}
|
}
|
||||||
|
else if (event.getActionMasked() == MotionEvent.ACTION_HOVER_ENTER ||
|
||||||
|
event.getActionMasked() == MotionEvent.ACTION_HOVER_EXIT) {
|
||||||
|
// On some devices (Galaxy S8 without Oreo pointer capture), we can
|
||||||
|
// get spurious ACTION_HOVER_ENTER events when right clicking with
|
||||||
|
// incorrect X and Y coordinates. Just eat this event without processing it.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if ((changedButtons & MotionEvent.BUTTON_PRIMARY) != 0) {
|
if ((changedButtons & MotionEvent.BUTTON_PRIMARY) != 0) {
|
||||||
if ((event.getButtonState() & MotionEvent.BUTTON_PRIMARY) != 0) {
|
if ((event.getButtonState() & MotionEvent.BUTTON_PRIMARY) != 0) {
|
||||||
@@ -1014,12 +1028,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
lastMouseY = (int)event.getY();
|
lastMouseY = (int)event.getY();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// First process the history
|
// Don't process the history. We just want the current position now.
|
||||||
for (int i = 0; i < event.getHistorySize(); i++) {
|
|
||||||
updateMousePosition((int)event.getHistoricalX(i), (int)event.getHistoricalY(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now process the current values
|
|
||||||
updateMousePosition((int)event.getX(), (int)event.getY());
|
updateMousePosition((int)event.getX(), (int)event.getY());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import android.content.Context;
|
|||||||
import android.hardware.input.InputManager;
|
import android.hardware.input.InputManager;
|
||||||
import android.hardware.usb.UsbDevice;
|
import android.hardware.usb.UsbDevice;
|
||||||
import android.hardware.usb.UsbManager;
|
import android.hardware.usb.UsbManager;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
import android.view.InputDevice;
|
import android.view.InputDevice;
|
||||||
@@ -22,6 +23,7 @@ import com.limelight.preferences.PreferenceConfiguration;
|
|||||||
import com.limelight.ui.GameGestures;
|
import com.limelight.ui.GameGestures;
|
||||||
import com.limelight.utils.Vector2d;
|
import com.limelight.utils.Vector2d;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
|
|
||||||
@@ -308,6 +310,79 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
|||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isExternal(InputDevice dev) {
|
||||||
|
try {
|
||||||
|
// Landroid/view/InputDevice;->isExternal()Z is on the light graylist in Android P
|
||||||
|
return (Boolean)dev.getClass().getMethod("isExternal").invoke(dev);
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (ClassCastException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Answer true if we don't know
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean shouldIgnoreBack(InputDevice dev) {
|
||||||
|
String devName = dev.getName();
|
||||||
|
|
||||||
|
// The Serval has a Select button but the framework doesn't
|
||||||
|
// know about that because it uses a non-standard scancode.
|
||||||
|
if (devName.contains("Razer Serval")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Classify this device as a remote by name if it has no joystick axes
|
||||||
|
if (getMotionRangeForJoystickAxis(dev, MotionEvent.AXIS_X) == null &&
|
||||||
|
getMotionRangeForJoystickAxis(dev, MotionEvent.AXIS_Y) == null &&
|
||||||
|
devName.toLowerCase().contains("remote")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, dynamically try to determine whether we should allow this
|
||||||
|
// 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)) {
|
||||||
|
InputManager im = (InputManager) activityContext.getSystemService(Context.INPUT_SERVICE);
|
||||||
|
|
||||||
|
boolean foundInternalGamepad = false;
|
||||||
|
boolean foundInternalSelect = false;
|
||||||
|
for (int id : im.getInputDeviceIds()) {
|
||||||
|
InputDevice currentDev = im.getInputDevice(id);
|
||||||
|
|
||||||
|
// Ignore external devices
|
||||||
|
if (currentDev == null || isExternal(currentDev)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note that we are explicitly NOT excluding the current device we're examining here,
|
||||||
|
// since the other gamepad buttons may be on our current device and that's fine.
|
||||||
|
boolean[] keys = currentDev.hasKeys(KeyEvent.KEYCODE_BUTTON_SELECT, KeyEvent.KEYCODE_BUTTON_A);
|
||||||
|
if (keys[0]) {
|
||||||
|
foundInternalSelect = true;
|
||||||
|
}
|
||||||
|
if (keys[1]) {
|
||||||
|
foundInternalGamepad = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow the back button to function for navigation if we either:
|
||||||
|
// a) have no internal gamepad (most phones)
|
||||||
|
// b) have an internal gamepad but also have an internal select button (GPD XD)
|
||||||
|
// but not:
|
||||||
|
// c) have an internal gamepad but no internal select button (NVIDIA SHIELD Portable)
|
||||||
|
return !foundInternalGamepad || foundInternalSelect;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private InputDeviceContext createInputDeviceContextForDevice(InputDevice dev) {
|
private InputDeviceContext createInputDeviceContextForDevice(InputDevice dev) {
|
||||||
InputDeviceContext context = new InputDeviceContext();
|
InputDeviceContext context = new InputDeviceContext();
|
||||||
String devName = dev.getName();
|
String devName = dev.getName();
|
||||||
@@ -440,6 +515,8 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context.ignoreBack = shouldIgnoreBack(dev);
|
||||||
|
|
||||||
if (devName != null) {
|
if (devName != null) {
|
||||||
// For the Nexus Player (and probably other ATV devices), we should
|
// For the Nexus Player (and probably other ATV devices), we should
|
||||||
// use the back button as start since it doesn't have a start/menu button
|
// use the back button as start since it doesn't have a start/menu button
|
||||||
@@ -459,30 +536,15 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
|||||||
// so we increase the deadzone on them to minimize this
|
// so we increase the deadzone on them to minimize this
|
||||||
context.triggerDeadzone = 0.30f;
|
context.triggerDeadzone = 0.30f;
|
||||||
}
|
}
|
||||||
// Classify this device as a remote by name
|
|
||||||
else if (devName.toLowerCase().contains("remote")) {
|
|
||||||
// It's only a remote if it doesn't any sticks
|
|
||||||
if (!context.hasJoystickAxes) {
|
|
||||||
context.ignoreBack = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// SHIELD controllers will use small stick deadzones
|
// SHIELD controllers will use small stick deadzones
|
||||||
else if (devName.contains("SHIELD")) {
|
else if (devName.contains("SHIELD")) {
|
||||||
context.leftStickDeadzoneRadius = 0.07f;
|
context.leftStickDeadzoneRadius = 0.07f;
|
||||||
context.rightStickDeadzoneRadius = 0.07f;
|
context.rightStickDeadzoneRadius = 0.07f;
|
||||||
}
|
}
|
||||||
// Samsung's face buttons appear as a non-virtual button so we'll explicitly ignore
|
|
||||||
// back presses on this device. The Goodix buttons on the Nokia 6 also appear
|
|
||||||
// non-virtual so we'll ignore those too.
|
|
||||||
else if (devName.equals("sec_touchscreen") || devName.equals("sec_touchkey") ||
|
|
||||||
devName.equals("goodix_fp")) {
|
|
||||||
context.ignoreBack = true;
|
|
||||||
}
|
|
||||||
// The Serval has a couple of unknown buttons that are start and select. It also has
|
// The Serval has a couple of unknown buttons that are start and select. It also has
|
||||||
// a back button which we want to ignore since there's already a select button.
|
// a back button which we want to ignore since there's already a select button.
|
||||||
else if (devName.contains("Razer Serval")) {
|
else if (devName.contains("Razer Serval")) {
|
||||||
context.isServal = true;
|
context.isServal = true;
|
||||||
context.ignoreBack = true;
|
|
||||||
}
|
}
|
||||||
// The Xbox One S Bluetooth controller has some mappings that need fixing up.
|
// The Xbox One S Bluetooth controller has some mappings that need fixing up.
|
||||||
// However, Microsoft released a firmware update with no change to VID/PID
|
// However, Microsoft released a firmware update with no change to VID/PID
|
||||||
|
|||||||
+10
-2
@@ -43,11 +43,19 @@ public class AndroidNativePointerCaptureProvider extends InputCaptureProvider {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float getRelativeAxisX(MotionEvent event) {
|
public float getRelativeAxisX(MotionEvent event) {
|
||||||
return event.getX();
|
float x = event.getX();
|
||||||
|
for (int i = 0; i < event.getHistorySize(); i++) {
|
||||||
|
x += event.getHistoricalX(i);
|
||||||
|
}
|
||||||
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float getRelativeAxisY(MotionEvent event) {
|
public float getRelativeAxisY(MotionEvent event) {
|
||||||
return event.getY();
|
float y = event.getY();
|
||||||
|
for (int i = 0; i < event.getHistorySize(); i++) {
|
||||||
|
y += event.getHistoricalY(i);
|
||||||
|
}
|
||||||
|
return y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -131,8 +131,8 @@ public class MediaCodecHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sony ATVs have broken MediaTek codecs (decoder hangs after rendering the first frame).
|
// Sony ATVs have broken MediaTek codecs (decoder hangs after rendering the first frame).
|
||||||
// I know the Fire TV 2 works, so I'll just whitelist Amazon devices which seem
|
// I know the Fire TV 2 and 3 works, so I'll just whitelist Amazon devices which seem
|
||||||
// to actually be tested. Ugh...
|
// to actually be tested.
|
||||||
if (Build.MANUFACTURER.equalsIgnoreCase("Amazon")) {
|
if (Build.MANUFACTURER.equalsIgnoreCase("Amazon")) {
|
||||||
whitelistedHevcDecoders.add("omx.mtk");
|
whitelistedHevcDecoders.add("omx.mtk");
|
||||||
whitelistedHevcDecoders.add("omx.amlogic");
|
whitelistedHevcDecoders.add("omx.amlogic");
|
||||||
@@ -166,6 +166,10 @@ public class MediaCodecHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isPowerVR(String glRenderer) {
|
||||||
|
return glRenderer.toLowerCase().contains("powervr");
|
||||||
|
}
|
||||||
|
|
||||||
private static String getAdrenoVersionString(String glRenderer) {
|
private static String getAdrenoVersionString(String glRenderer) {
|
||||||
glRenderer = glRenderer.toLowerCase().trim();
|
glRenderer = glRenderer.toLowerCase().trim();
|
||||||
|
|
||||||
@@ -259,6 +263,18 @@ public class MediaCodecHelper {
|
|||||||
else {
|
else {
|
||||||
blacklistedDecoderPrefixes.add("OMX.qcom.video.decoder.hevc");
|
blacklistedDecoderPrefixes.add("OMX.qcom.video.decoder.hevc");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Older MediaTek SoCs have issues with HEVC rendering but the newer chips with
|
||||||
|
// PowerVR GPUs have good HEVC support.
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && isPowerVR(glRenderer)) {
|
||||||
|
LimeLog.info("Added omx.mtk to HEVC decoders based on PowerVR GPU");
|
||||||
|
whitelistedHevcDecoders.add("omx.mtk");
|
||||||
|
|
||||||
|
// This SoC (MT8176 in GPD XD+) supports AVC RFI too, but the maxNumReferenceFrames setting
|
||||||
|
// required to make it work adds a huge amount of latency.
|
||||||
|
LimeLog.info("Added omx.mtk to RFI list for HEVC");
|
||||||
|
refFrameInvalidationHevcPrefixes.add("omx.mtk");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
initialized = true;
|
initialized = true;
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@ buildscript {
|
|||||||
google()
|
google()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:3.2.0-alpha17'
|
classpath 'com.android.tools.build:gradle:3.2.0-alpha18'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -1,9 +1,9 @@
|
|||||||
This file serves to document some of the decoder errata when using MediaCodec hardware decoders on certain devices.
|
This file serves to document some of the decoder errata when using MediaCodec hardware decoders on certain devices.
|
||||||
|
|
||||||
1. num_ref_frames is set to 16 by NVENC which causes decoders to allocate 16+ buffers. This can cause an error or lag on some devices.
|
1. num_ref_frames is set to 16 by NVENC which causes decoders to allocate 16+ buffers. This can cause an error or lag on some devices.
|
||||||
- Affected decoders: TI OMAP4, Allwinner A20
|
- Affected decoders: TI OMAP4 crashes, Allwinner A20, MT8176 lags (HEVC not affected)
|
||||||
|
|
||||||
2. Some decoders have a huge per-frame latency with the unmodified SPS sent from NVENC. Setting max_dec_frame_buffering fixes this latency issue.
|
2. Some H.264 decoders have a huge per-frame latency with the unmodified SPS sent from NVENC. Setting max_dec_frame_buffering=1 fixes this latency issue.
|
||||||
- Affected decoders: NVIDIA Tegra 3 and 4, Broadcom VideoCore IV
|
- Affected decoders: NVIDIA Tegra 3 and 4, Broadcom VideoCore IV
|
||||||
|
|
||||||
3. Some decoders strictly require that you pass BUFFER_FLAG_CODEC_CONFIG and crash upon the IDR frame if you don't
|
3. Some decoders strictly require that you pass BUFFER_FLAG_CODEC_CONFIG and crash upon the IDR frame if you don't
|
||||||
|
|||||||
Reference in new issue
Block a user