Compare commits

..

7 Commits

Author SHA1 Message Date
Romain Vimont
dedbc3f8cd Recover on invalid camera FPS ranges
Some devices may provide invalid ranges, causing an
IllegalArgumentException "lower must be less than or equal to upper".

Catch the exception to list the cameras anyway.

Refs #4403 <https://github.com/Genymobile/scrcpy/issues/4403>
2023-11-05 15:14:04 +01:00
Romain Vimont
ad8ced5b1e Log physical cameras 2023-11-05 12:16:14 +01:00
Romain Vimont
36b17ee068 Simplify --list-cameras ouptut
Remove --video-source=camera from the output of --list-cameras (this is
implicit).
2023-11-05 11:52:33 +01:00
Romain Vimont
4e4ddc499f Return the FakeContext as application context
This avoids getApplicationContext() to return null and cause
NullPointerException.

Fixes #4392 <https://github.com/Genymobile/scrcpy/issues/4392#issuecomment-1792806080>
2023-11-03 19:07:15 +01:00
Romain Vimont
8d76b3e06d Fill application context for camera
Using the camera fails on some devices without a proper application
context.

Fixes #4392 <https://github.com/Genymobile/scrcpy/issues/4392>
2023-11-03 19:07:08 +01:00
Romain Vimont
85a0b935c9 Always assign a system context as base context
FakeContext used ActivityThread.getSystemContext() as base context only
in some cases, because it caused problems on some devices:
 - warnings on Xiaomi devices [1], which are now fixed by
   b8c5853aa6
 - issues related to Looper [2], which are solved by just calling
   Looper.prepare*()

Therefore, we can now always assign a base context, which simplifies and
helps to solve camera issues on some devices (#4392).

[1] <https://github.com/Genymobile/scrcpy/issues/4015#issuecomment-1595382142>
[2] <https://github.com/Genymobile/scrcpy/issues/3805#issuecomment-1596148031>

Fixes #4392 <https://github.com/Genymobile/scrcpy/issues/4392>
2023-11-03 19:05:50 +01:00
Romain Vimont
8c3e2bae7b Simplify Application instantiation
The constructor is public.
2023-11-03 19:05:28 +01:00

View File

@@ -3,14 +3,17 @@ package com.genymobile.scrcpy;
import com.genymobile.scrcpy.wrappers.DisplayManager;
import com.genymobile.scrcpy.wrappers.ServiceManager;
import android.annotation.TargetApi;
import android.graphics.Rect;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.MediaCodec;
import android.os.Build;
import android.util.Range;
import java.util.Arrays;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;
@@ -84,6 +87,7 @@ public final class LogUtils {
}
}
@TargetApi(Build.VERSION_CODES.P)
public static String buildCameraListMessage(boolean includeSizes) {
StringBuilder builder = new StringBuilder("List of cameras:");
CameraManager cameraManager = ServiceManager.getCameraManager();
@@ -93,19 +97,35 @@ public final class LogUtils {
builder.append("\n (none)");
} else {
for (String id : cameraIds) {
builder.append("\n --video-source=camera --camera-id=").append(id);
builder.append("\n --camera-id=").append(id);
CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(id);
int facing = characteristics.get(CameraCharacteristics.LENS_FACING);
builder.append(" (").append(getCameraFacingName(facing)).append(", ");
Rect activeSize = characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
builder.append(activeSize.width()).append("x").append(activeSize.height()).append(", ");
builder.append(activeSize.width()).append("x").append(activeSize.height());
// Capture frame rates for low-FPS mode are the same for every resolution
Range<Integer>[] lowFpsRanges = characteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES);
SortedSet<Integer> uniqueLowFps = getUniqueSet(lowFpsRanges);
builder.append("fps=").append(uniqueLowFps).append(')');
try {
// Capture frame rates for low-FPS mode are the same for every resolution
Range<Integer>[] lowFpsRanges = characteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES);
SortedSet<Integer> uniqueLowFps = getUniqueSet(lowFpsRanges);
builder.append(", fps=").append(uniqueLowFps);
} catch (Exception e) {
// Some devices may provide invalid ranges, causing an IllegalArgumentException "lower must be less than or equal to upper"
Ln.w("Could not get available frame rates for camera " + id, e);
}
builder.append(')');
int[] capabilities = characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
if (Arrays.asList(capabilities).contains(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA)) {
builder.append("\n Logical multi-camera, backed by physical cameras:");
for (String phyId : characteristics.getPhysicalCameraIds()) {
CameraCharacteristics phyCharacteristics = cameraManager.getCameraCharacteristics(phyId);
appendPhysicalCamera(builder, phyId, phyCharacteristics);
}
}
if (includeSizes) {
StreamConfigurationMap configs = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
@@ -134,6 +154,13 @@ public final class LogUtils {
return builder.toString();
}
private static void appendPhysicalCamera(StringBuilder builder, String id, CameraCharacteristics characteristics) {
builder.append("\n --camera-id=").append(id).append(" (");
Rect activeSize = characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
builder.append(activeSize.width()).append("x").append(activeSize.height()).append(")");
}
private static SortedSet<Integer> getUniqueSet(Range<Integer>[] ranges) {
SortedSet<Integer> set = new TreeSet<>();
for (Range<Integer> range : ranges) {