/* * Copyright 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.hardware.camera2.cts; import static android.hardware.camera2.cts.CameraTestUtils.*; import com.android.ex.camera2.blocking.BlockingSessionCallback; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.ImageFormat; import android.graphics.SurfaceTexture; import android.hardware.Camera; import android.hardware.cts.helpers.CameraUtils; import android.hardware.camera2.CameraCharacteristics; import android.hardware.camera2.CameraDevice; import android.hardware.camera2.CaptureRequest; import android.hardware.camera2.CaptureResult; import android.media.Image; import android.platform.test.annotations.Presubmit; import android.util.Log; import android.util.Size; import java.nio.ByteBuffer; import android.hardware.camera2.cts.Camera2SurfaceViewCtsActivity; import android.hardware.camera2.cts.CameraTestUtils.SimpleCaptureCallback; import android.hardware.camera2.cts.CameraTestUtils.SimpleImageReaderListener; import android.hardware.camera2.cts.testcases.Camera2SurfaceViewTestCase; import org.junit.runners.Parameterized; import org.junit.runner.RunWith; import org.junit.Test; /** * Quick-running test for very basic camera operation for all cameras * and both camera APIs. * * May not take more than a few seconds to run, to be suitable for quick * testing. */ @RunWith(Parameterized.class) public class FastBasicsTest extends Camera2SurfaceViewTestCase { private static final String TAG = "FastBasicsTest"; private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE); private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private static final int WAIT_FOR_FRAMES_TIMEOUT_MS = 3000; private static final int WAIT_FOR_PICTURE_TIMEOUT_MS = 8000; private static final int FRAMES_TO_WAIT_FOR_CAPTURE = 100; @Presubmit @Test public void testCamera2() throws Exception { String[] cameraIdsUnderTest = getCameraIdsUnderTest(); for (int i = 0; i < cameraIdsUnderTest.length; i++) { try { Log.i(TAG, "Testing camera2 API for camera device " + cameraIdsUnderTest[i]); if (!mAllStaticInfo.get(cameraIdsUnderTest[i]).isColorOutputSupported()) { Log.i(TAG, "Camera " + cameraIdsUnderTest[i] + " does not support color outputs, skipping"); continue; } openDevice(cameraIdsUnderTest[i]); camera2TestByCamera(); } finally { closeDevice(); } } } public void camera2TestByCamera() throws Exception { CaptureRequest.Builder previewRequest = mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); CaptureRequest.Builder stillCaptureRequest = mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); Size previewSize = mOrderedPreviewSizes.get(0); Size stillSize = mOrderedStillSizes.get(0); SimpleCaptureCallback resultListener = new SimpleCaptureCallback(); SimpleImageReaderListener imageListener = new SimpleImageReaderListener(); prepareStillCaptureAndStartPreview(previewRequest, stillCaptureRequest, previewSize, stillSize, resultListener, imageListener, false /*isHeic*/); CaptureResult result = resultListener.getCaptureResult(WAIT_FOR_FRAMES_TIMEOUT_MS); Long timestamp = result.get(CaptureResult.SENSOR_TIMESTAMP); assertNotNull("Can't read a capture result timestamp", timestamp); CaptureResult result2 = resultListener.getCaptureResult(WAIT_FOR_FRAMES_TIMEOUT_MS); Long timestamp2 = result2.get(CaptureResult.SENSOR_TIMESTAMP); assertNotNull("Can't read a capture result 2 timestamp", timestamp2); assertTrue("Bad timestamps", timestamp2 > timestamp); // If EnableZsl is supported, disable ZSL in order to compare preview and still timestamps. if (mStaticInfo.isEnableZslSupported()) { stillCaptureRequest.set(CaptureRequest.CONTROL_ENABLE_ZSL, false); } CaptureRequest capture = stillCaptureRequest.build(); mSession.capture(capture, resultListener, mHandler); CaptureResult stillResult = resultListener.getTotalCaptureResultForRequest(capture, FRAMES_TO_WAIT_FOR_CAPTURE); Long timestamp3 = stillResult.get(CaptureResult.SENSOR_TIMESTAMP); assertNotNull("Can't read a still capture result timestamp", timestamp3); assertTrue("Bad timestamps", timestamp3 > timestamp2); Image img = imageListener.getImage(WAIT_FOR_PICTURE_TIMEOUT_MS); ByteBuffer jpegBuffer = img.getPlanes()[0].getBuffer(); byte[] jpegData = new byte[jpegBuffer.remaining()]; jpegBuffer.get(jpegData); Bitmap b = BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length); assertNotNull("Unable to decode still capture JPEG", b); closeImageReader(); } private class Camera1Listener implements SurfaceTexture.OnFrameAvailableListener, Camera.PictureCallback { private Object mFrameSignal = new Object(); private boolean mGotFrame = false; public boolean waitForFrame() { synchronized(mFrameSignal) { boolean waited = false; while (!waited) { try { mFrameSignal.wait(WAIT_FOR_FRAMES_TIMEOUT_MS); waited = true; } catch (InterruptedException e) { } } return mGotFrame; } } public void onFrameAvailable(SurfaceTexture s) { synchronized(mFrameSignal) { mGotFrame = true; mFrameSignal.notifyAll(); } } private Object mPictureSignal = new Object(); private boolean mGotPicture = false; private byte[] mPictureData = null; public byte[] waitForPicture() { Log.i(TAG, "waitForPicture called"); synchronized(mPictureSignal) { boolean waited = false; while (!waited) { try { mPictureSignal.wait(WAIT_FOR_PICTURE_TIMEOUT_MS); waited = true; Log.i(TAG, "waitForPicture returned with mGotPicture = " + mGotPicture); } catch (InterruptedException e) { Log.e(TAG, "waitForPicture gets interrupted exception!"); } } return mPictureData; } } public void onPictureTaken(byte[] data, Camera camera) { Log.i(TAG, "onPictureTaken called"); synchronized(mPictureSignal) { mPictureData = data; mGotPicture = true; mPictureSignal.notifyAll(); } } } @Presubmit @Test public void testCamera1() throws Exception { int[] cameraIds = CameraUtils.deriveCameraIdsUnderTest(); for (int i : cameraIds) { Camera camera = null; try { Log.i(TAG, "Testing android.hardware.Camera API for camera device " + i); camera = Camera.open(i); Camera1Listener listener = new Camera1Listener(); SurfaceTexture st = new SurfaceTexture(/*random int*/ 5); st.setOnFrameAvailableListener(listener); camera.setPreviewTexture(st); camera.startPreview(); assertTrue("No preview received from camera", listener.waitForFrame()); camera.takePicture(null, null, listener); byte[] picture = listener.waitForPicture(); assertNotNull("No still picture received from camera", picture); Bitmap b = BitmapFactory.decodeByteArray(picture, 0, picture.length); assertNotNull("Still picture could not be decoded into Bitmap", b); } finally { if (camera != null) { camera.release(); } } } } }