Introduces Android API level linting, fixes all current API lint errors.
This CL attempts to annotate accesses on >16 API levels using as small scopes as possible. The TargetApi notations mean "yes, I know I'm accessing a higher API and I take responsibility for gating the call on Android API level". The Encoder/Decoder classes are annotated on the whole class, but they're only accessed through JNI; we should annotate on method level otherwise and preferably on private methods. This patch also fixes some compiler-level deprecation warnings (i.e. -Xlint:deprecation), but probably not all of them. BUG=webrtc:5063 R=henrika@webrtc.org, kjellander@webrtc.org, magjed@webrtc.org Review URL: https://codereview.webrtc.org/1412673008 . Cr-Commit-Position: refs/heads/master@{#10624}
This commit is contained in:
@ -27,7 +27,9 @@
|
||||
|
||||
package org.webrtc;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
|
||||
import android.graphics.ImageFormat;
|
||||
import android.hardware.camera2.CameraCharacteristics;
|
||||
import android.hardware.camera2.CameraManager;
|
||||
@ -45,6 +47,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@TargetApi(21)
|
||||
public class Camera2Enumerator implements CameraEnumerationAndroid.Enumerator {
|
||||
private final static String TAG = "Camera2Enumerator";
|
||||
private final static double NANO_SECONDS_PER_SECOND = 1.0e9;
|
||||
|
@ -29,7 +29,6 @@ package org.webrtc;
|
||||
|
||||
import static java.lang.Math.abs;
|
||||
import static java.lang.Math.ceil;
|
||||
import android.hardware.Camera;
|
||||
import android.graphics.ImageFormat;
|
||||
|
||||
import org.json.JSONArray;
|
||||
@ -127,8 +126,8 @@ public class CameraEnumerationAndroid {
|
||||
|
||||
// Returns device names that can be used to create a new VideoCapturerAndroid.
|
||||
public static String[] getDeviceNames() {
|
||||
String[] names = new String[Camera.getNumberOfCameras()];
|
||||
for (int i = 0; i < Camera.getNumberOfCameras(); ++i) {
|
||||
String[] names = new String[android.hardware.Camera.getNumberOfCameras()];
|
||||
for (int i = 0; i < android.hardware.Camera.getNumberOfCameras(); ++i) {
|
||||
names[i] = getDeviceName(i);
|
||||
}
|
||||
return names;
|
||||
@ -136,22 +135,22 @@ public class CameraEnumerationAndroid {
|
||||
|
||||
// Returns number of cameras on device.
|
||||
public static int getDeviceCount() {
|
||||
return Camera.getNumberOfCameras();
|
||||
return android.hardware.Camera.getNumberOfCameras();
|
||||
}
|
||||
|
||||
// Returns the name of the camera with camera index. Returns null if the
|
||||
// camera can not be used.
|
||||
public static String getDeviceName(int index) {
|
||||
Camera.CameraInfo info = new Camera.CameraInfo();
|
||||
android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
|
||||
try {
|
||||
Camera.getCameraInfo(index, info);
|
||||
android.hardware.Camera.getCameraInfo(index, info);
|
||||
} catch (Exception e) {
|
||||
Logging.e(TAG, "getCameraInfo failed on index " + index,e);
|
||||
return null;
|
||||
}
|
||||
|
||||
String facing =
|
||||
(info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) ? "front" : "back";
|
||||
(info.facing == android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT) ? "front" : "back";
|
||||
return "Camera " + index + ", Facing " + facing
|
||||
+ ", Orientation " + info.orientation;
|
||||
}
|
||||
@ -159,13 +158,13 @@ public class CameraEnumerationAndroid {
|
||||
// Returns the name of the front facing camera. Returns null if the
|
||||
// camera can not be used or does not exist.
|
||||
public static String getNameOfFrontFacingDevice() {
|
||||
return getNameOfDevice(Camera.CameraInfo.CAMERA_FACING_FRONT);
|
||||
return getNameOfDevice(android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT);
|
||||
}
|
||||
|
||||
// Returns the name of the back facing camera. Returns null if the
|
||||
// camera can not be used or does not exist.
|
||||
public static String getNameOfBackFacingDevice() {
|
||||
return getNameOfDevice(Camera.CameraInfo.CAMERA_FACING_BACK);
|
||||
return getNameOfDevice(android.hardware.Camera.CameraInfo.CAMERA_FACING_BACK);
|
||||
}
|
||||
|
||||
public static String getSupportedFormatsAsJson(int id) throws JSONException {
|
||||
@ -194,7 +193,8 @@ public class CameraEnumerationAndroid {
|
||||
}
|
||||
}
|
||||
|
||||
public static int[] getFramerateRange(Camera.Parameters parameters, final int framerate) {
|
||||
public static int[] getFramerateRange(android.hardware.Camera.Parameters parameters,
|
||||
final int framerate) {
|
||||
List<int[]> listFpsRange = parameters.getSupportedPreviewFpsRange();
|
||||
if (listFpsRange.isEmpty()) {
|
||||
Logging.w(TAG, "No supported preview fps range");
|
||||
@ -203,27 +203,28 @@ public class CameraEnumerationAndroid {
|
||||
return Collections.min(listFpsRange,
|
||||
new ClosestComparator<int[]>() {
|
||||
@Override int diff(int[] range) {
|
||||
return abs(framerate - range[Camera.Parameters.PREVIEW_FPS_MIN_INDEX])
|
||||
+ abs(framerate - range[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]);
|
||||
return abs(framerate - range[android.hardware.Camera.Parameters.PREVIEW_FPS_MIN_INDEX])
|
||||
+ abs(framerate - range[android.hardware.Camera.Parameters.PREVIEW_FPS_MAX_INDEX]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static Camera.Size getClosestSupportedSize(
|
||||
List<Camera.Size> supportedSizes, final int requestedWidth, final int requestedHeight) {
|
||||
public static android.hardware.Camera.Size getClosestSupportedSize(
|
||||
List<android.hardware.Camera.Size> supportedSizes, final int requestedWidth,
|
||||
final int requestedHeight) {
|
||||
return Collections.min(supportedSizes,
|
||||
new ClosestComparator<Camera.Size>() {
|
||||
@Override int diff(Camera.Size size) {
|
||||
new ClosestComparator<android.hardware.Camera.Size>() {
|
||||
@Override int diff(android.hardware.Camera.Size size) {
|
||||
return abs(requestedWidth - size.width) + abs(requestedHeight - size.height);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static String getNameOfDevice(int facing) {
|
||||
final Camera.CameraInfo info = new Camera.CameraInfo();
|
||||
for (int i = 0; i < Camera.getNumberOfCameras(); ++i) {
|
||||
final android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
|
||||
for (int i = 0; i < android.hardware.Camera.getNumberOfCameras(); ++i) {
|
||||
try {
|
||||
Camera.getCameraInfo(i, info);
|
||||
android.hardware.Camera.getCameraInfo(i, info);
|
||||
if (info.facing == facing) {
|
||||
return getDeviceName(i);
|
||||
}
|
||||
|
@ -27,7 +27,6 @@
|
||||
|
||||
package org.webrtc;
|
||||
|
||||
import android.hardware.Camera;
|
||||
import android.os.SystemClock;
|
||||
|
||||
import org.webrtc.CameraEnumerationAndroid.CaptureFormat;
|
||||
@ -60,11 +59,11 @@ public class CameraEnumerator implements CameraEnumerationAndroid.Enumerator {
|
||||
private List<CaptureFormat> enumerateFormats(int cameraId) {
|
||||
Logging.d(TAG, "Get supported formats for camera index " + cameraId + ".");
|
||||
final long startTimeMs = SystemClock.elapsedRealtime();
|
||||
final Camera.Parameters parameters;
|
||||
Camera camera = null;
|
||||
final android.hardware.Camera.Parameters parameters;
|
||||
android.hardware.Camera camera = null;
|
||||
try {
|
||||
Logging.d(TAG, "Opening camera with index " + cameraId);
|
||||
camera = Camera.open(cameraId);
|
||||
camera = android.hardware.Camera.open(cameraId);
|
||||
parameters = camera.getParameters();
|
||||
} catch (RuntimeException e) {
|
||||
Logging.e(TAG, "Open camera failed on camera index " + cameraId, e);
|
||||
@ -84,10 +83,10 @@ public class CameraEnumerator implements CameraEnumerationAndroid.Enumerator {
|
||||
// getSupportedPreviewFpsRange() returns a sorted list. Take the fps range
|
||||
// corresponding to the highest fps.
|
||||
final int[] range = listFpsRange.get(listFpsRange.size() - 1);
|
||||
minFps = range[Camera.Parameters.PREVIEW_FPS_MIN_INDEX];
|
||||
maxFps = range[Camera.Parameters.PREVIEW_FPS_MAX_INDEX];
|
||||
minFps = range[android.hardware.Camera.Parameters.PREVIEW_FPS_MIN_INDEX];
|
||||
maxFps = range[android.hardware.Camera.Parameters.PREVIEW_FPS_MAX_INDEX];
|
||||
}
|
||||
for (Camera.Size size : parameters.getSupportedPreviewSizes()) {
|
||||
for (android.hardware.Camera.Size size : parameters.getSupportedPreviewSizes()) {
|
||||
formatList.add(new CaptureFormat(size.width, size.height, minFps, maxFps));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
@ -29,8 +29,6 @@ package org.webrtc;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.SurfaceTexture;
|
||||
import android.hardware.Camera;
|
||||
import android.hardware.Camera.PreviewCallback;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.SystemClock;
|
||||
@ -68,20 +66,21 @@ import javax.microedition.khronos.egl.EGL10;
|
||||
// camera thread. The internal *OnCameraThread() methods must check |camera| for null to check if
|
||||
// the camera has been stopped.
|
||||
@SuppressWarnings("deprecation")
|
||||
public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallback,
|
||||
public class VideoCapturerAndroid extends VideoCapturer implements
|
||||
android.hardware.Camera.PreviewCallback,
|
||||
SurfaceTextureHelper.OnTextureFrameAvailableListener {
|
||||
private final static String TAG = "VideoCapturerAndroid";
|
||||
private final static int CAMERA_OBSERVER_PERIOD_MS = 2000;
|
||||
private final static int CAMERA_FREEZE_REPORT_TIMOUT_MS = 6000;
|
||||
|
||||
private Camera camera; // Only non-null while capturing.
|
||||
private android.hardware.Camera camera; // Only non-null while capturing.
|
||||
private HandlerThread cameraThread;
|
||||
private final Handler cameraThreadHandler;
|
||||
private Context applicationContext;
|
||||
// Synchronization lock for |id|.
|
||||
private final Object cameraIdLock = new Object();
|
||||
private int id;
|
||||
private Camera.CameraInfo info;
|
||||
private android.hardware.Camera.CameraInfo info;
|
||||
private final FramePool videoBuffers;
|
||||
private final CameraStatistics cameraStatistics;
|
||||
// Remember the requested format in case we want to switch cameras.
|
||||
@ -108,10 +107,10 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
|
||||
private int openCameraAttempts;
|
||||
|
||||
// Camera error callback.
|
||||
private final Camera.ErrorCallback cameraErrorCallback =
|
||||
new Camera.ErrorCallback() {
|
||||
private final android.hardware.Camera.ErrorCallback cameraErrorCallback =
|
||||
new android.hardware.Camera.ErrorCallback() {
|
||||
@Override
|
||||
public void onError(int error, Camera camera) {
|
||||
public void onError(int error, android.hardware.Camera camera) {
|
||||
String errorMessage;
|
||||
if (error == android.hardware.Camera.CAMERA_ERROR_SERVER_DIED) {
|
||||
errorMessage = "Camera server died!";
|
||||
@ -261,7 +260,7 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
|
||||
// Switch camera to the next valid camera id. This can only be called while
|
||||
// the camera is running.
|
||||
public void switchCamera(final CameraSwitchHandler handler) {
|
||||
if (Camera.getNumberOfCameras() < 2) {
|
||||
if (android.hardware.Camera.getNumberOfCameras() < 2) {
|
||||
if (handler != null) {
|
||||
handler.onCameraSwitchError("No camera to switch to.");
|
||||
}
|
||||
@ -292,7 +291,8 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
|
||||
pendingCameraSwitch = false;
|
||||
}
|
||||
if (handler != null) {
|
||||
handler.onCameraSwitchDone(info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT);
|
||||
handler.onCameraSwitchDone(
|
||||
info.facing == android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -375,13 +375,13 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
|
||||
// found. If |deviceName| is empty, the first available device is used.
|
||||
private static int lookupDeviceName(String deviceName) {
|
||||
Logging.d(TAG, "lookupDeviceName: " + deviceName);
|
||||
if (deviceName == null || Camera.getNumberOfCameras() == 0) {
|
||||
if (deviceName == null || android.hardware.Camera.getNumberOfCameras() == 0) {
|
||||
return -1;
|
||||
}
|
||||
if (deviceName.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
for (int i = 0; i < Camera.getNumberOfCameras(); ++i) {
|
||||
for (int i = 0; i < android.hardware.Camera.getNumberOfCameras(); ++i) {
|
||||
if (deviceName.equals(CameraEnumerationAndroid.getDeviceName(i))) {
|
||||
return i;
|
||||
}
|
||||
@ -461,9 +461,9 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
|
||||
if (eventsHandler != null) {
|
||||
eventsHandler.onCameraOpening(id);
|
||||
}
|
||||
camera = Camera.open(id);
|
||||
info = new Camera.CameraInfo();
|
||||
Camera.getCameraInfo(id, info);
|
||||
camera = android.hardware.Camera.open(id);
|
||||
info = new android.hardware.Camera.CameraInfo();
|
||||
android.hardware.Camera.getCameraInfo(id, info);
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
openCameraAttempts++;
|
||||
@ -525,14 +525,15 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
|
||||
requestedFramerate = framerate;
|
||||
|
||||
// Find closest supported format for |width| x |height| @ |framerate|.
|
||||
final Camera.Parameters parameters = camera.getParameters();
|
||||
final android.hardware.Camera.Parameters parameters = camera.getParameters();
|
||||
final int[] range = CameraEnumerationAndroid.getFramerateRange(parameters, framerate * 1000);
|
||||
final Camera.Size previewSize = CameraEnumerationAndroid.getClosestSupportedSize(
|
||||
parameters.getSupportedPreviewSizes(), width, height);
|
||||
final android.hardware.Camera.Size previewSize =
|
||||
CameraEnumerationAndroid.getClosestSupportedSize(
|
||||
parameters.getSupportedPreviewSizes(), width, height);
|
||||
final CaptureFormat captureFormat = new CaptureFormat(
|
||||
previewSize.width, previewSize.height,
|
||||
range[Camera.Parameters.PREVIEW_FPS_MIN_INDEX],
|
||||
range[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]);
|
||||
range[android.hardware.Camera.Parameters.PREVIEW_FPS_MIN_INDEX],
|
||||
range[android.hardware.Camera.Parameters.PREVIEW_FPS_MAX_INDEX]);
|
||||
|
||||
// Check if we are already using this capture format, then we don't need to do anything.
|
||||
if (captureFormat.equals(this.captureFormat)) {
|
||||
@ -554,8 +555,9 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
|
||||
parameters.setPreviewFormat(captureFormat.imageFormat);
|
||||
// Picture size is for taking pictures and not for preview/video, but we need to set it anyway
|
||||
// as a workaround for an aspect ratio problem on Nexus 7.
|
||||
final Camera.Size pictureSize = CameraEnumerationAndroid.getClosestSupportedSize(
|
||||
parameters.getSupportedPictureSizes(), width, height);
|
||||
final android.hardware.Camera.Size pictureSize =
|
||||
CameraEnumerationAndroid.getClosestSupportedSize(
|
||||
parameters.getSupportedPictureSizes(), width, height);
|
||||
parameters.setPictureSize(pictureSize.width, pictureSize.height);
|
||||
|
||||
// Temporarily stop preview if it's already running.
|
||||
@ -572,8 +574,8 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
|
||||
this.captureFormat = captureFormat;
|
||||
|
||||
List<String> focusModes = parameters.getSupportedFocusModes();
|
||||
if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
|
||||
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
|
||||
if (focusModes.contains(android.hardware.Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
|
||||
parameters.setFocusMode(android.hardware.Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
|
||||
}
|
||||
|
||||
camera.setParameters(parameters);
|
||||
@ -637,7 +639,7 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
|
||||
Logging.d(TAG, "switchCameraOnCameraThread");
|
||||
stopCaptureOnCameraThread();
|
||||
synchronized (cameraIdLock) {
|
||||
id = (id + 1) % Camera.getNumberOfCameras();
|
||||
id = (id + 1) % android.hardware.Camera.getNumberOfCameras();
|
||||
}
|
||||
dropNextFrame = true;
|
||||
startCaptureOnCameraThread(requestedWidth, requestedHeight, requestedFramerate, frameObserver,
|
||||
@ -699,7 +701,7 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
|
||||
|
||||
private int getFrameOrientation() {
|
||||
int rotation = getDeviceOrientation();
|
||||
if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
|
||||
if (info.facing == android.hardware.Camera.CameraInfo.CAMERA_FACING_BACK) {
|
||||
rotation = 360 - rotation;
|
||||
}
|
||||
return (info.orientation + rotation) % 360;
|
||||
@ -707,7 +709,7 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
|
||||
|
||||
// Called on cameraThread so must not "synchronized".
|
||||
@Override
|
||||
public void onPreviewFrame(byte[] data, Camera callbackCamera) {
|
||||
public void onPreviewFrame(byte[] data, android.hardware.Camera callbackCamera) {
|
||||
checkIsOnCameraThread();
|
||||
if (camera == null) {
|
||||
return;
|
||||
@ -752,7 +754,7 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
|
||||
}
|
||||
|
||||
int rotation = getFrameOrientation();
|
||||
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
|
||||
if (info.facing == android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT) {
|
||||
// Undo the mirror that the OS "helps" us with.
|
||||
// http://developer.android.com/reference/android/hardware/Camera.html#setDisplayOrientation(int)
|
||||
transformMatrix =
|
||||
@ -784,7 +786,7 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
|
||||
// keeping the buffers alive and for finding the corresponding ByteBuffer given a timestamp.
|
||||
private final Map<Long, ByteBuffer> pendingBuffers = new HashMap<Long, ByteBuffer>();
|
||||
private int frameSize = 0;
|
||||
private Camera camera;
|
||||
private android.hardware.Camera camera;
|
||||
|
||||
public FramePool(Thread thread) {
|
||||
this.thread = thread;
|
||||
@ -797,7 +799,7 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
|
||||
}
|
||||
|
||||
// Discards previous queued buffers and adds new callback buffers to camera.
|
||||
public void queueCameraBuffers(int frameSize, Camera camera) {
|
||||
public void queueCameraBuffers(int frameSize, android.hardware.Camera camera) {
|
||||
checkIsOnValidThread();
|
||||
this.camera = camera;
|
||||
this.frameSize = frameSize;
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
package org.webrtc;
|
||||
|
||||
import android.graphics.SurfaceTexture;
|
||||
import android.media.MediaCodec;
|
||||
import android.media.MediaCodecInfo;
|
||||
import android.media.MediaCodecInfo.CodecCapabilities;
|
||||
@ -48,6 +49,7 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
// Java-side of peerconnection_jni.cc:MediaCodecVideoDecoder.
|
||||
// This class is an implementation detail of the Java PeerConnection API.
|
||||
@SuppressWarnings("deprecation")
|
||||
public class MediaCodecVideoDecoder {
|
||||
// This class is constructed, operated, and destroyed by its C++ incarnation,
|
||||
// so the class and its methods have non-public visibility. The API this
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
package org.webrtc;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.media.MediaCodec;
|
||||
import android.media.MediaCodecInfo.CodecCapabilities;
|
||||
import android.media.MediaCodecInfo;
|
||||
@ -44,6 +45,8 @@ import java.util.concurrent.CountDownLatch;
|
||||
|
||||
// Java-side of peerconnection_jni.cc:MediaCodecVideoEncoder.
|
||||
// This class is an implementation detail of the Java PeerConnection API.
|
||||
@TargetApi(19)
|
||||
@SuppressWarnings("deprecation")
|
||||
public class MediaCodecVideoEncoder {
|
||||
// This class is constructed, operated, and destroyed by its C++ incarnation,
|
||||
// so the class and its methods have non-public visibility. The API this
|
||||
|
@ -227,6 +227,12 @@
|
||||
'libjingle_peerconnection_so',
|
||||
],
|
||||
'variables': {
|
||||
# Designate as Chromium code and point to our lint settings to
|
||||
# enable linting of the WebRTC code (this is the only way to make
|
||||
# lint_action invoke the Android linter).
|
||||
'android_manifest_path': '<(webrtc_root)/build/android/AndroidManifest.xml',
|
||||
'suppressions_file': '<(webrtc_root)/build/android/suppressions.xml',
|
||||
'chromium_code': 1,
|
||||
'java_in_dir': 'app/webrtc/java',
|
||||
'webrtc_base_dir': '<(webrtc_root)/base',
|
||||
'webrtc_modules_dir': '<(webrtc_root)/modules',
|
||||
|
14
webrtc/build/android/AndroidManifest.xml
Normal file
14
webrtc/build/android/AndroidManifest.xml
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
This is a dummy manifest which is required by:
|
||||
1. aapt when generating R.java in java.gypi:
|
||||
Nothing in the manifest is used, but it is still required by aapt.
|
||||
2. lint: [min|target]SdkVersion are required by lint and should
|
||||
be kept up-to-date.
|
||||
-->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="dummy.package">
|
||||
|
||||
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="23" />
|
||||
|
||||
</manifest>
|
23
webrtc/build/android/suppressions.xml
Normal file
23
webrtc/build/android/suppressions.xml
Normal file
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<lint>
|
||||
<!-- These lint settings is for the Android linter that gets run by
|
||||
lint_action.gypi on compile of WebRTC java code. All WebRTC java code
|
||||
should lint cleanly for the issues below. -->
|
||||
<!-- TODO(phoglund): make work with suppress.py or remove printout referring
|
||||
to suppress.py. -->
|
||||
<issue id="NewApi"></issue>
|
||||
|
||||
<issue id="Locale" severity="ignore"/>
|
||||
<issue id="SdCardPath" severity="ignore"/>
|
||||
<issue id="UseValueOf" severity="ignore"/>
|
||||
<issue id="InlinedApi" severity="ignore"/>
|
||||
<issue id="DefaultLocale" severity="ignore"/>
|
||||
<issue id="Assert" severity="ignore"/>
|
||||
<issue id="UseSparseArrays" severity="ignore"/>
|
||||
|
||||
<!-- These are just from the dummy AndroidManifest.xml we use for linting.
|
||||
It's in the same directory as this file. -->
|
||||
<issue id="MissingApplicationIcon" severity="ignore"/>
|
||||
<issue id="AllowBackup" severity="ignore"/>
|
||||
<issue id="MissingVersion" severity="ignore"/>
|
||||
</lint>
|
@ -7,7 +7,7 @@
|
||||
<uses-feature android:name="android.hardware.camera" />
|
||||
<uses-feature android:name="android.hardware.camera.autofocus" />
|
||||
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
|
||||
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="21" />
|
||||
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="21" />
|
||||
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
package org.webrtc.voiceengine;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.media.audiofx.AcousticEchoCanceler;
|
||||
import android.media.audiofx.AudioEffect;
|
||||
import android.media.audiofx.AudioEffect.Descriptor;
|
||||
@ -119,6 +120,7 @@ class WebRtcAudioEffects {
|
||||
|
||||
// Returns true if the platform AEC should be excluded based on its UUID.
|
||||
// AudioEffect.queryEffects() can throw IllegalStateException.
|
||||
@TargetApi(18)
|
||||
private static boolean isAcousticEchoCancelerExcludedByUUID() {
|
||||
for (Descriptor d : AudioEffect.queryEffects()) {
|
||||
if (d.type.equals(AudioEffect.EFFECT_TYPE_AEC) &&
|
||||
@ -131,6 +133,7 @@ class WebRtcAudioEffects {
|
||||
|
||||
// Returns true if the platform AGC should be excluded based on its UUID.
|
||||
// AudioEffect.queryEffects() can throw IllegalStateException.
|
||||
@TargetApi(18)
|
||||
private static boolean isAutomaticGainControlExcludedByUUID() {
|
||||
for (Descriptor d : AudioEffect.queryEffects()) {
|
||||
if (d.type.equals(AudioEffect.EFFECT_TYPE_AGC) &&
|
||||
@ -143,6 +146,7 @@ class WebRtcAudioEffects {
|
||||
|
||||
// Returns true if the platform NS should be excluded based on its UUID.
|
||||
// AudioEffect.queryEffects() can throw IllegalStateException.
|
||||
@TargetApi(18)
|
||||
private static boolean isNoiseSuppressorExcludedByUUID() {
|
||||
for (Descriptor d : AudioEffect.queryEffects()) {
|
||||
if (d.type.equals(AudioEffect.EFFECT_TYPE_NS) &&
|
||||
@ -368,7 +372,11 @@ class WebRtcAudioEffects {
|
||||
// AudioEffect.Descriptor array that are actually not available on the device.
|
||||
// As an example: Samsung Galaxy S6 includes an AGC in the descriptor but
|
||||
// AutomaticGainControl.isAvailable() returns false.
|
||||
@TargetApi(18)
|
||||
private boolean effectTypeIsVoIP(UUID type) {
|
||||
if (!WebRtcAudioUtils.runningOnJellyBeanMR2OrHigher())
|
||||
return false;
|
||||
|
||||
return (AudioEffect.EFFECT_TYPE_AEC.equals(type)
|
||||
&& isAcousticEchoCancelerSupported())
|
||||
|| (AudioEffect.EFFECT_TYPE_AGC.equals(type)
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
package org.webrtc.voiceengine;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.media.AudioFormat;
|
||||
@ -189,20 +190,26 @@ public class WebRtcAudioManager {
|
||||
// No overrides available. Deliver best possible estimate based on default
|
||||
// Android AudioManager APIs.
|
||||
final int sampleRateHz;
|
||||
if (!WebRtcAudioUtils.runningOnJellyBeanMR1OrHigher()) {
|
||||
sampleRateHz = WebRtcAudioUtils.getDefaultSampleRateHz();
|
||||
if (WebRtcAudioUtils.runningOnJellyBeanMR1OrHigher()) {
|
||||
sampleRateHz = getSampleRateOnJellyBeanMR10OrHigher();
|
||||
} else {
|
||||
String sampleRateString = audioManager.getProperty(
|
||||
AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE);
|
||||
sampleRateHz = (sampleRateString == null)
|
||||
? WebRtcAudioUtils.getDefaultSampleRateHz()
|
||||
: Integer.parseInt(sampleRateString);
|
||||
sampleRateHz = WebRtcAudioUtils.getDefaultSampleRateHz();
|
||||
}
|
||||
Logging.d(TAG, "Sample rate is set to " + sampleRateHz + " Hz");
|
||||
return sampleRateHz;
|
||||
}
|
||||
|
||||
@TargetApi(17)
|
||||
private int getSampleRateOnJellyBeanMR10OrHigher() {
|
||||
String sampleRateString = audioManager.getProperty(
|
||||
AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE);
|
||||
return (sampleRateString == null)
|
||||
? WebRtcAudioUtils.getDefaultSampleRateHz()
|
||||
: Integer.parseInt(sampleRateString);
|
||||
}
|
||||
|
||||
// Returns the native output buffer size for low-latency output streams.
|
||||
@TargetApi(17)
|
||||
private int getLowLatencyOutputFramesPerBuffer() {
|
||||
assertTrue(isLowLatencyOutputSupported());
|
||||
if (!WebRtcAudioUtils.runningOnJellyBeanMR1OrHigher()) {
|
||||
|
@ -13,6 +13,7 @@ package org.webrtc.voiceengine;
|
||||
import java.lang.Thread;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.media.AudioFormat;
|
||||
import android.media.AudioManager;
|
||||
@ -90,13 +91,9 @@ class WebRtcAudioTrack {
|
||||
assertTrue(sizeInBytes <= byteBuffer.remaining());
|
||||
int bytesWritten = 0;
|
||||
if (WebRtcAudioUtils.runningOnLollipopOrHigher()) {
|
||||
bytesWritten = audioTrack.write(byteBuffer,
|
||||
sizeInBytes,
|
||||
AudioTrack.WRITE_BLOCKING);
|
||||
bytesWritten = writeOnLollipop(audioTrack, byteBuffer, sizeInBytes);
|
||||
} else {
|
||||
bytesWritten = audioTrack.write(byteBuffer.array(),
|
||||
byteBuffer.arrayOffset(),
|
||||
sizeInBytes);
|
||||
bytesWritten = writePreLollipop(audioTrack, byteBuffer, sizeInBytes);
|
||||
}
|
||||
if (bytesWritten != sizeInBytes) {
|
||||
Logging.e(TAG, "AudioTrack.write failed: " + bytesWritten);
|
||||
@ -123,6 +120,15 @@ class WebRtcAudioTrack {
|
||||
audioTrack.flush();
|
||||
}
|
||||
|
||||
@TargetApi(21)
|
||||
private int writeOnLollipop(AudioTrack audioTrack, ByteBuffer byteBuffer, int sizeInBytes) {
|
||||
return audioTrack.write(byteBuffer, sizeInBytes, AudioTrack.WRITE_BLOCKING);
|
||||
}
|
||||
|
||||
private int writePreLollipop(AudioTrack audioTrack, ByteBuffer byteBuffer, int sizeInBytes) {
|
||||
return audioTrack.write(byteBuffer.array(), byteBuffer.arrayOffset(), sizeInBytes);
|
||||
}
|
||||
|
||||
public void joinThread() {
|
||||
keepAlive = false;
|
||||
while (isAlive()) {
|
||||
@ -224,16 +230,21 @@ class WebRtcAudioTrack {
|
||||
private boolean setStreamVolume(int volume) {
|
||||
Logging.d(TAG, "setStreamVolume(" + volume + ")");
|
||||
assertTrue(audioManager != null);
|
||||
if (WebRtcAudioUtils.runningOnLollipopOrHigher()) {
|
||||
if (audioManager.isVolumeFixed()) {
|
||||
Logging.e(TAG, "The device implements a fixed volume policy.");
|
||||
return false;
|
||||
}
|
||||
if (isVolumeFixed()) {
|
||||
Logging.e(TAG, "The device implements a fixed volume policy.");
|
||||
return false;
|
||||
}
|
||||
audioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL, volume, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
@TargetApi(21)
|
||||
private boolean isVolumeFixed() {
|
||||
if (!WebRtcAudioUtils.runningOnLollipopOrHigher())
|
||||
return false;
|
||||
return audioManager.isVolumeFixed();
|
||||
}
|
||||
|
||||
/** Get current volume level for a phone call audio stream. */
|
||||
private int getStreamVolume() {
|
||||
Logging.d(TAG, "getStreamVolume");
|
||||
|
@ -144,6 +144,11 @@ public final class WebRtcAudioUtils {
|
||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1;
|
||||
}
|
||||
|
||||
public static boolean runningOnJellyBeanMR2OrHigher() {
|
||||
// July 24, 2013: Android 4.3. API Level 18.
|
||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2;
|
||||
}
|
||||
|
||||
public static boolean runningOnLollipopOrHigher() {
|
||||
// API Level 21.
|
||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
|
||||
|
Reference in New Issue
Block a user