From 70c2207c34cf0e6b3b383b1b1500ff5385aa51a6 Mon Sep 17 00:00:00 2001 From: Eino-Ville Talvala Date: Tue, 27 Aug 2013 12:09:04 -0700 Subject: Camera2: Immutable metadata Make all camera metadata immutable once created; requests are created using CameraRequest.Builder. - Separate CameraMetadata implementation from interface - Implement deep copying of metadata - Requests/results/properties have-a native implementation Bug: 10360518 Change-Id: Ia6300c237219d39f70c63156fa9ca666d951a36e --- .../integration/CameraBinderTest.java | 3 +- .../integration/CameraDeviceBinderTest.java | 53 +++++----- .../unit/CameraMetadataTest.java | 112 ++++----------------- 3 files changed, 49 insertions(+), 119 deletions(-) (limited to 'media/tests/MediaFrameworkTest') 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 624bbaa..1b7faec 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,7 @@ import android.hardware.IProCameraUser; import android.hardware.camera2.CameraMetadata; import android.hardware.camera2.ICameraDeviceCallbacks; import android.hardware.camera2.ICameraDeviceUser; +import android.hardware.camera2.impl.CameraMetadataNative; import android.hardware.camera2.utils.BinderHolder; import android.hardware.camera2.utils.CameraBinderDecorator; import android.os.Binder; @@ -155,7 +156,7 @@ public class CameraBinderTest extends AndroidTestCase { } @Override - public void onResultReceived(int frameId, CameraMetadata result) throws RemoteException { + public void onResultReceived(int frameId, CameraMetadataNative result) throws RemoteException { } } 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 2f271bb..56d73c0 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.CameraProperties; import android.hardware.camera2.CaptureRequest; import android.hardware.camera2.ICameraDeviceCallbacks; import android.hardware.camera2.ICameraDeviceUser; +import android.hardware.camera2.impl.CameraMetadataNative; import android.hardware.camera2.utils.BinderHolder; import android.os.RemoteException; import android.test.AndroidTestCase; @@ -62,13 +63,13 @@ public class CameraDeviceBinderTest extends AndroidTestCase { } @Override - public void onResultReceived(int frameId, CameraMetadata result) throws RemoteException { + public void onResultReceived(int frameId, CameraMetadataNative result) throws RemoteException { } } - class IsMetadataNotEmpty extends ArgumentMatcher { + class IsMetadataNotEmpty extends ArgumentMatcher { public boolean matches(Object obj) { - return !((CameraMetadata) obj).isEmpty(); + return !((CameraMetadataNative) obj).isEmpty(); } } @@ -78,20 +79,17 @@ public class CameraDeviceBinderTest extends AndroidTestCase { mSurface = new Surface(mSurfaceTexture); } - private CaptureRequest createDefaultRequest(boolean needStream) throws Exception { - CameraMetadata metadata = new CameraMetadata(); + private CaptureRequest.Builder createDefaultBuilder(boolean needStream) throws Exception { + CameraMetadataNative metadata = new CameraMetadataNative(); assertTrue(metadata.isEmpty()); - CaptureRequest request = new CaptureRequest(); - assertTrue(request.isEmpty()); - int status = mCameraUser.createDefaultRequest(TEMPLATE_PREVIEW, /* out */metadata); assertEquals(CameraBinderTestUtils.NO_ERROR, status); assertFalse(metadata.isEmpty()); - request.swap(metadata); + CaptureRequest.Builder request = new CaptureRequest.Builder(metadata); assertFalse(request.isEmpty()); - assertTrue(metadata.isEmpty()); + assertFalse(metadata.isEmpty()); if (needStream) { int streamId = mCameraUser.createStream(/* ignored */10, /* ignored */20, /* ignored */30, mSurface); @@ -150,14 +148,13 @@ public class CameraDeviceBinderTest extends AndroidTestCase { @SmallTest public void testCreateDefaultRequest() throws Exception { - CameraMetadata metadata = new CameraMetadata(); + CameraMetadataNative metadata = new CameraMetadataNative(); assertTrue(metadata.isEmpty()); int status = mCameraUser.createDefaultRequest(TEMPLATE_PREVIEW, /* out */metadata); assertEquals(CameraBinderTestUtils.NO_ERROR, status); assertFalse(metadata.isEmpty()); - metadata.close(); } @SmallTest @@ -208,37 +205,39 @@ public class CameraDeviceBinderTest extends AndroidTestCase { @SmallTest public void testSubmitBadRequest() throws Exception { - CaptureRequest request = createDefaultRequest(/* needStream */false); - int status = mCameraUser.submitRequest(request, /* streaming */false); + CaptureRequest.Builder builder = createDefaultBuilder(/* needStream */false); + CaptureRequest request1 = builder.build(); + int status = mCameraUser.submitRequest(request1, /* streaming */false); assertEquals("Expected submitRequest to return BAD_VALUE " + "since we had 0 surface targets set.", CameraBinderTestUtils.BAD_VALUE, status); - request.addTarget(mSurface); - status = mCameraUser.submitRequest(request, /* streaming */false); + builder.addTarget(mSurface); + CaptureRequest request2 = builder.build(); + status = mCameraUser.submitRequest(request2, /* streaming */false); assertEquals("Expected submitRequest to return BAD_VALUE since " + "the target surface wasn't registered with createStream.", CameraBinderTestUtils.BAD_VALUE, status); - - request.close(); } @SmallTest public void testSubmitGoodRequest() throws Exception { - CaptureRequest request = createDefaultRequest(/* needStream */true); + CaptureRequest.Builder builder = createDefaultBuilder(/* needStream */true); + CaptureRequest request = builder.build(); // Submit valid request twice. int requestId1 = submitCameraRequest(request, /* streaming */false); int requestId2 = submitCameraRequest(request, /* streaming */false); assertNotSame("Request IDs should be unique for multiple requests", requestId1, requestId2); - request.close(); } @SmallTest public void testSubmitStreamingRequest() throws Exception { - CaptureRequest request = createDefaultRequest(/* needStream */true); + CaptureRequest.Builder builder = createDefaultBuilder(/* needStream */true); + + CaptureRequest request = builder.build(); // Submit valid request once (non-streaming), and another time // (streaming) @@ -260,12 +259,11 @@ public class CameraDeviceBinderTest extends AndroidTestCase { assertEquals("Streaming request IDs should be cancellable", CameraBinderTestUtils.NO_ERROR, status); - request.close(); } @SmallTest public void testCameraInfo() throws RemoteException { - CameraMetadata info = new CameraMetadata(); + CameraMetadataNative info = new CameraMetadataNative(); int status = mCameraUser.getCameraInfo(/*out*/info); assertEquals(CameraBinderTestUtils.NO_ERROR, status); @@ -276,8 +274,8 @@ public class CameraDeviceBinderTest extends AndroidTestCase { @SmallTest public void testWaitUntilIdle() throws Exception { - CaptureRequest request = createDefaultRequest(/* needStream */true); - int requestIdStreaming = submitCameraRequest(request, /* streaming */true); + CaptureRequest.Builder builder = createDefaultBuilder(/* needStream */true); + int requestIdStreaming = submitCameraRequest(builder.build(), /* streaming */true); // Test Bad case first: waitUntilIdle when there is active repeating request int status = mCameraUser.waitUntilIdle(); @@ -294,7 +292,7 @@ public class CameraDeviceBinderTest extends AndroidTestCase { @SmallTest public void testCaptureResultCallbacks() throws Exception { IsMetadataNotEmpty matcher = new IsMetadataNotEmpty(); - CaptureRequest request = createDefaultRequest(/* needStream */true); + CaptureRequest request = createDefaultBuilder(/* needStream */true).build(); // Test both single request and streaming request. int requestId1 = submitCameraRequest(request, /* streaming */false); @@ -307,7 +305,6 @@ public class CameraDeviceBinderTest extends AndroidTestCase { .onResultReceived( eq(streamingId), argThat(matcher)); - request.close(); } @SmallTest @@ -319,7 +316,7 @@ public class CameraDeviceBinderTest extends AndroidTestCase { assertEquals(CameraBinderTestUtils.NO_ERROR, status); // Then set up a stream - CaptureRequest request = createDefaultRequest(/* needStream */true); + CaptureRequest request = createDefaultBuilder(/* needStream */true).build(); // Flush should still be a no-op, really status = mCameraUser.flush(); diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java index ecf01d9..874e078 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java @@ -23,8 +23,9 @@ import android.graphics.Rect; import android.hardware.camera2.CameraMetadata; import android.hardware.camera2.Rational; import android.hardware.camera2.Size; +import android.hardware.camera2.impl.CameraMetadataNative; -import static android.hardware.camera2.CameraMetadata.*; +import static android.hardware.camera2.impl.CameraMetadataNative.*; import java.lang.reflect.Array; import java.nio.ByteBuffer; @@ -42,7 +43,7 @@ import static org.junit.Assert.assertArrayEquals; */ public class CameraMetadataTest extends junit.framework.TestCase { - CameraMetadata mMetadata; + CameraMetadataNative mMetadata; Parcel mParcel; // Sections @@ -62,13 +63,12 @@ public class CameraMetadataTest extends junit.framework.TestCase { @Override public void setUp() { - mMetadata = new CameraMetadata(); + mMetadata = new CameraMetadataNative(); mParcel = Parcel.obtain(); } @Override public void tearDown() throws Exception { - mMetadata.close(); mMetadata = null; mParcel.recycle(); @@ -82,115 +82,47 @@ public class CameraMetadataTest extends junit.framework.TestCase { } @SmallTest - public void testClose() throws Exception { - mMetadata.isEmpty(); // no throw - - assertFalse(mMetadata.isClosed()); - - mMetadata.close(); - - assertTrue(mMetadata.isClosed()); - - // OK: second close should not throw - mMetadata.close(); - - assertTrue(mMetadata.isClosed()); - - // All other calls after close should throw IllegalStateException - - try { - mMetadata.isEmpty(); - fail("Unreachable -- isEmpty after close should throw IllegalStateException"); - } catch (IllegalStateException e) { - // good: we expect calling this method after close to fail - } - - try { - mMetadata.getEntryCount(); - fail("Unreachable -- getEntryCount after close should throw IllegalStateException"); - } catch (IllegalStateException e) { - // good: we expect calling this method after close to fail - } - - - try { - mMetadata.swap(mMetadata); - fail("Unreachable -- swap after close should throw IllegalStateException"); - } catch (IllegalStateException e) { - // good: we expect calling this method after close to fail - } - - try { - mMetadata.readFromParcel(mParcel); - fail("Unreachable -- readFromParcel after close should throw IllegalStateException"); - } catch (IllegalStateException e) { - // good: we expect calling this method after close to fail - } - - try { - mMetadata.writeToParcel(mParcel, /*flags*/0); - fail("Unreachable -- writeToParcel after close should throw IllegalStateException"); - } catch (IllegalStateException e) { - // good: we expect calling this method after close to fail - } - - try { - mMetadata.readValues(/*tag*/0); - fail("Unreachable -- readValues after close should throw IllegalStateException"); - } catch (IllegalStateException e) { - // good: we expect calling this method after close to fail - } - - try { - mMetadata.writeValues(/*tag*/0, /*source*/new byte[] { 1,2,3 }); - fail("Unreachable -- readValues after close should throw IllegalStateException"); - } catch (IllegalStateException e) { - // good: we expect calling this method after close to fail - } - } - - @SmallTest public void testGetTagFromKey() { // Test success assertEquals(ANDROID_COLOR_CORRECTION_MODE, - CameraMetadata.getTag("android.colorCorrection.mode")); + CameraMetadataNative.getTag("android.colorCorrection.mode")); assertEquals(ANDROID_COLOR_CORRECTION_TRANSFORM, - CameraMetadata.getTag("android.colorCorrection.transform")); + CameraMetadataNative.getTag("android.colorCorrection.transform")); assertEquals(ANDROID_CONTROL_AE_ANTIBANDING_MODE, - CameraMetadata.getTag("android.control.aeAntibandingMode")); + CameraMetadataNative.getTag("android.control.aeAntibandingMode")); assertEquals(ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION, - CameraMetadata.getTag("android.control.aeExposureCompensation")); + CameraMetadataNative.getTag("android.control.aeExposureCompensation")); // Test failures try { - CameraMetadata.getTag(null); + CameraMetadataNative.getTag(null); fail("A null key should throw NPE"); } catch(NullPointerException e) { } try { - CameraMetadata.getTag("android.control"); + CameraMetadataNative.getTag("android.control"); fail("A section name only should not be a valid key"); } catch(IllegalArgumentException e) { } try { - CameraMetadata.getTag("android.control.thisTagNameIsFakeAndDoesNotExist"); + CameraMetadataNative.getTag("android.control.thisTagNameIsFakeAndDoesNotExist"); fail("A valid section with an invalid tag name should not be a valid key"); } catch(IllegalArgumentException e) { } try { - CameraMetadata.getTag("android"); + CameraMetadataNative.getTag("android"); fail("A namespace name only should not be a valid key"); } catch(IllegalArgumentException e) { } try { - CameraMetadata.getTag("this.key.is.definitely.invalid"); + CameraMetadataNative.getTag("this.key.is.definitely.invalid"); fail("A completely fake key name should not be valid"); } catch(IllegalArgumentException e) { } @@ -198,14 +130,14 @@ public class CameraMetadataTest extends junit.framework.TestCase { @SmallTest public void testGetTypeFromTag() { - assertEquals(TYPE_BYTE, CameraMetadata.getNativeType(ANDROID_COLOR_CORRECTION_MODE)); - assertEquals(TYPE_FLOAT, CameraMetadata.getNativeType(ANDROID_COLOR_CORRECTION_TRANSFORM)); - assertEquals(TYPE_BYTE, CameraMetadata.getNativeType(ANDROID_CONTROL_AE_ANTIBANDING_MODE)); + assertEquals(TYPE_BYTE, CameraMetadataNative.getNativeType(ANDROID_COLOR_CORRECTION_MODE)); + assertEquals(TYPE_FLOAT, CameraMetadataNative.getNativeType(ANDROID_COLOR_CORRECTION_TRANSFORM)); + assertEquals(TYPE_BYTE, CameraMetadataNative.getNativeType(ANDROID_CONTROL_AE_ANTIBANDING_MODE)); assertEquals(TYPE_INT32, - CameraMetadata.getNativeType(ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION)); + CameraMetadataNative.getNativeType(ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION)); try { - CameraMetadata.getNativeType(0xDEADF00D); + CameraMetadataNative.getNativeType(0xDEADF00D); fail("No type should exist for invalid tag 0xDEADF00D"); } catch(IllegalArgumentException e) { } @@ -454,7 +386,7 @@ public class CameraMetadataTest extends junit.framework.TestCase { @SmallTest public void testReadWriteEnumWithCustomValues() { - CameraMetadata.registerEnumValues(AeAntibandingMode.class, new int[] { + CameraMetadataNative.registerEnumValues(AeAntibandingMode.class, new int[] { 0, 10, 20, @@ -475,7 +407,7 @@ public class CameraMetadataTest extends junit.framework.TestCase { Key aeAntibandingModeKey = new Key("android.control.aeAvailableAntibandingModes", AeAntibandingMode[].class); - byte[] aeAntibandingModeValues = mMetadata.readValues(CameraMetadata + byte[] aeAntibandingModeValues = mMetadata.readValues(CameraMetadataNative .getTag("android.control.aeAvailableAntibandingModes")); byte[] expectedValues = new byte[] { 0, 10, 20, 30 }; assertArrayEquals(expectedValues, aeAntibandingModeValues); @@ -485,7 +417,7 @@ public class CameraMetadataTest extends junit.framework.TestCase { * Stranger cases that don't use byte enums */ // int (n) - CameraMetadata.registerEnumValues(AvailableFormat.class, new int[] { + CameraMetadataNative.registerEnumValues(AvailableFormat.class, new int[] { 0x20, 0x32315659, 0x11, @@ -505,7 +437,7 @@ public class CameraMetadataTest extends junit.framework.TestCase { Key availableFormatsKey = new Key("android.scaler.availableFormats", AeAntibandingMode.class); - byte[] availableFormatValues = mMetadata.readValues(CameraMetadata + byte[] availableFormatValues = mMetadata.readValues(CameraMetadataNative .getTag(availableFormatsKey.getName())); int[] expectedIntValues = new int[] { -- cgit v1.1