diff options
Diffstat (limited to 'media')
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(); |