summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
Diffstat (limited to 'media')
-rw-r--r--media/java/android/media/ImageReader.java29
-rw-r--r--media/jni/android_media_ImageReader.cpp19
-rw-r--r--media/jni/android_media_MediaDrm.cpp16
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java26
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java11
5 files changed, 76 insertions, 25 deletions
diff --git a/media/java/android/media/ImageReader.java b/media/java/android/media/ImageReader.java
index 8ddc094..f3356c9 100644
--- a/media/java/android/media/ImageReader.java
+++ b/media/java/android/media/ImageReader.java
@@ -20,7 +20,6 @@ import android.graphics.ImageFormat;
import android.graphics.PixelFormat;
import android.os.Handler;
import android.os.Looper;
-import android.os.Message;
import android.view.Surface;
import java.lang.ref.WeakReference;
@@ -130,11 +129,26 @@ public final class ImageReader implements AutoCloseable {
}
/**
- * <p>Get the next Image from the ImageReader's queue. Returns {@code null}
- * if no new image is available.</p>
+ * <p>
+ * Get the next Image from the ImageReader's queue. Returns {@code null} if
+ * no new image is available.
+ * </p>
+ * <p>
+ * This operation will fail by throwing an
+ * {@link Surface.OutOfResourcesException OutOfResourcesException} if too
+ * many images have been acquired with {@link #getNextImage}. In particular
+ * a sequence of {@link #getNextImage} calls greater than {@link #getMaxImages}
+ * without calling {@link Image#close} or {@link #releaseImage} in-between
+ * will exhaust the underlying queue. At such a time,
+ * {@link Surface.OutOfResourcesException OutOfResourcesException} will be
+ * thrown until more images are released with {@link Image#close} or
+ * {@link #releaseImage}.
+ * </p>
*
* @return a new frame of image data, or {@code null} if no image data is
- * available.
+ * available.
+ * @throws Surface.OutOfResourcesException if too many images are currently
+ * acquired
*/
public Image getNextImage() {
SurfaceImage si = new SurfaceImage();
@@ -172,6 +186,8 @@ public final class ImageReader implements AutoCloseable {
* @param listener the listener that will be run
* @param handler The handler on which the listener should be invoked, or null
* if the listener should be invoked on the calling thread's looper.
+ *
+ * @throws IllegalArgumentException if no handler specified and the calling thread has no looper
*/
public void setImageAvailableListener(OnImageAvailableListener listener, Handler handler) {
mImageListener = listener;
@@ -260,8 +276,9 @@ public final class ImageReader implements AutoCloseable {
* Called from Native code when an Event happens.
*/
private static void postEventFromNative(Object selfRef) {
- WeakReference weakSelf = (WeakReference)selfRef;
- final ImageReader ir = (ImageReader)weakSelf.get();
+ @SuppressWarnings("unchecked")
+ WeakReference<ImageReader> weakSelf = (WeakReference<ImageReader>)selfRef;
+ final ImageReader ir = weakSelf.get();
if (ir == null) {
return;
}
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index cd589de..7d914d2 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -44,6 +44,9 @@
using namespace android;
+static const char* const OutOfResourcesException =
+ "android/view/Surface$OutOfResourcesException";
+
enum {
IMAGE_READER_MAX_NUM_PLANES = 3,
};
@@ -609,7 +612,8 @@ static void ImageReader_init(JNIEnv* env, jobject thiz, jobject weakThiz,
nativeFormat = Image_getPixelFormat(env, format);
sp<BufferQueue> bq = new BufferQueue();
- sp<CpuConsumer> consumer = new CpuConsumer(bq, true, maxImages);
+ sp<CpuConsumer> consumer = new CpuConsumer(bq, maxImages,
+ /*controlledByApp*/true);
// TODO: throw dvm exOutOfMemoryError?
if (consumer == NULL) {
jniThrowRuntimeException(env, "Failed to allocate native CpuConsumer");
@@ -702,7 +706,17 @@ static jboolean ImageReader_imageSetup(JNIEnv* env, jobject thiz,
status_t res = consumer->lockNextBuffer(buffer);
if (res != NO_ERROR) {
if (res != BAD_VALUE /*no buffers*/) {
- ALOGE("%s Fail to lockNextBuffer with error: %d ", __FUNCTION__, res);
+ if (res == NOT_ENOUGH_DATA) {
+ jniThrowException(env, OutOfResourcesException,
+ "Too many outstanding images, close existing images"
+ " to be able to acquire more.");
+ } else {
+ ALOGE("%s Fail to lockNextBuffer with error: %d ",
+ __FUNCTION__, res);
+ jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
+ "Unknown error (%d) when we tried to lock buffer.",
+ res);
+ }
}
return false;
}
@@ -714,6 +728,7 @@ static jboolean ImageReader_imageSetup(JNIEnv* env, jobject thiz,
ALOGE("crop left: %d, top = %d", lt.x, lt.y);
jniThrowException(env, "java/lang/UnsupportedOperationException",
"crop left top corner need to at origin");
+ return false;
}
// Check if the producer buffer configurations match what ImageReader configured.
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index 16a1e48..60142cd 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -753,7 +753,9 @@ static jbyteArray android_media_MediaDrm_provideKeyResponse(
status_t err = drm->provideKeyResponse(sessionId, response, keySetId);
- throwExceptionAsNecessary(env, err, "Failed to handle key response");
+ if (throwExceptionAsNecessary(env, err, "Failed to handle key response")) {
+ return NULL;
+ }
return VectorToJByteArray(env, keySetId);
}
@@ -1104,7 +1106,9 @@ static jbyteArray android_media_MediaDrm_encryptNative(
status_t err = drm->encrypt(sessionId, keyId, input, iv, output);
- throwExceptionAsNecessary(env, err, "Failed to encrypt");
+ if (throwExceptionAsNecessary(env, err, "Failed to encrypt")) {
+ return NULL;
+ }
return VectorToJByteArray(env, output);
}
@@ -1132,7 +1136,9 @@ static jbyteArray android_media_MediaDrm_decryptNative(
Vector<uint8_t> output;
status_t err = drm->decrypt(sessionId, keyId, input, iv, output);
- throwExceptionAsNecessary(env, err, "Failed to decrypt");
+ if (throwExceptionAsNecessary(env, err, "Failed to decrypt")) {
+ return NULL;
+ }
return VectorToJByteArray(env, output);
}
@@ -1160,7 +1166,9 @@ static jbyteArray android_media_MediaDrm_signNative(
status_t err = drm->sign(sessionId, keyId, message, signature);
- throwExceptionAsNecessary(env, err, "Failed to sign");
+ if (throwExceptionAsNecessary(env, err, "Failed to sign")) {
+ return NULL;
+ }
return VectorToJByteArray(env, signature);
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
index 9057f60..624bbaa 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
@@ -25,6 +25,8 @@ import android.hardware.IProCameraUser;
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.ICameraDeviceCallbacks;
import android.hardware.camera2.ICameraDeviceUser;
+import android.hardware.camera2.utils.BinderHolder;
+import android.hardware.camera2.utils.CameraBinderDecorator;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
@@ -109,9 +111,11 @@ public class CameraBinderTest extends AndroidTestCase {
String clientPackageName = getContext().getPackageName();
- ICamera cameraUser = mUtils.getCameraService().connect(dummyCallbacks, cameraId,
- clientPackageName,
- CameraBinderTestUtils.USE_CALLING_UID);
+ BinderHolder holder = new BinderHolder();
+ CameraBinderDecorator.newInstance(mUtils.getCameraService())
+ .connect(dummyCallbacks, cameraId, clientPackageName,
+ CameraBinderTestUtils.USE_CALLING_UID, holder);
+ ICamera cameraUser = ICamera.Stub.asInterface(holder.getBinder());
assertNotNull(String.format("Camera %s was null", cameraId), cameraUser);
Log.v(TAG, String.format("Camera %s connected", cameraId));
@@ -131,9 +135,11 @@ public class CameraBinderTest extends AndroidTestCase {
String clientPackageName = getContext().getPackageName();
- IProCameraUser cameraUser = mUtils.getCameraService().connectPro(dummyCallbacks,
- cameraId,
- clientPackageName, CameraBinderTestUtils.USE_CALLING_UID);
+ BinderHolder holder = new BinderHolder();
+ CameraBinderDecorator.newInstance(mUtils.getCameraService())
+ .connectPro(dummyCallbacks, cameraId,
+ clientPackageName, CameraBinderTestUtils.USE_CALLING_UID, holder);
+ IProCameraUser cameraUser = IProCameraUser.Stub.asInterface(holder.getBinder());
assertNotNull(String.format("Camera %s was null", cameraId), cameraUser);
Log.v(TAG, String.format("Camera %s connected", cameraId));
@@ -161,9 +167,11 @@ public class CameraBinderTest extends AndroidTestCase {
String clientPackageName = getContext().getPackageName();
- ICameraDeviceUser cameraUser = mUtils.getCameraService().connectDevice(dummyCallbacks,
- cameraId,
- clientPackageName, CameraBinderTestUtils.USE_CALLING_UID);
+ BinderHolder holder = new BinderHolder();
+ CameraBinderDecorator.newInstance(mUtils.getCameraService())
+ .connectDevice(dummyCallbacks, cameraId,
+ clientPackageName, CameraBinderTestUtils.USE_CALLING_UID, holder);
+ ICameraDeviceUser cameraUser = ICameraDeviceUser.Stub.asInterface(holder.getBinder());
assertNotNull(String.format("Camera %s was null", cameraId), cameraUser);
Log.v(TAG, String.format("Camera %s connected", cameraId));
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
index bdf14ff..5225e23 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
@@ -22,6 +22,7 @@ import android.hardware.camera2.CameraPropertiesKeys;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.ICameraDeviceCallbacks;
import android.hardware.camera2.ICameraDeviceUser;
+import android.hardware.camera2.utils.BinderHolder;
import android.os.RemoteException;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
@@ -39,8 +40,8 @@ public class CameraDeviceBinderTest extends AndroidTestCase {
private static String TAG = "CameraDeviceBinderTest";
// Number of streaming callbacks need to check.
private static int NUM_CALLBACKS_CHECKED = 10;
- // Wait for capture result timeout value: 1000ms
- private final static int WAIT_FOR_COMPLETE_TIMEOUT_MS = 1000;
+ // Wait for capture result timeout value: 1500ms
+ private final static int WAIT_FOR_COMPLETE_TIMEOUT_MS = 1500;
private int mCameraId;
private ICameraDeviceUser mCameraUser;
@@ -129,8 +130,10 @@ public class CameraDeviceBinderTest extends AndroidTestCase {
mMockCb = spy(dummyCallbacks);
- mCameraUser = mUtils.getCameraService().connectDevice(mMockCb, mCameraId,
- clientPackageName, CameraBinderTestUtils.USE_CALLING_UID);
+ BinderHolder holder = new BinderHolder();
+ mUtils.getCameraService().connectDevice(mMockCb, mCameraId,
+ clientPackageName, CameraBinderTestUtils.USE_CALLING_UID, holder);
+ mCameraUser = ICameraDeviceUser.Stub.asInterface(holder.getBinder());
assertNotNull(String.format("Camera %s was null", mCameraId), mCameraUser);
createDefaultSurface();