| /* |
| * Copyright 2014 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 com.android.cts.verifier.sensors.sixdof.Renderer.RenderUtils; |
| |
| import android.annotation.TargetApi; |
| import android.content.Context; |
| import android.content.pm.ActivityInfo; |
| import android.content.res.Configuration; |
| import android.content.res.Resources; |
| import android.graphics.SurfaceTexture; |
| import android.hardware.camera2.CameraAccessException; |
| import android.hardware.camera2.CameraCaptureSession; |
| import android.hardware.camera2.CameraCharacteristics; |
| import android.hardware.camera2.CameraDevice; |
| import android.hardware.camera2.CameraManager; |
| import android.hardware.camera2.CaptureRequest; |
| import android.hardware.camera2.CaptureResult; |
| import android.hardware.camera2.TotalCaptureResult; |
| import android.os.Handler; |
| import android.os.HandlerThread; |
| import android.util.Log; |
| import android.util.Size; |
| import android.view.Display; |
| import android.view.Surface; |
| import android.view.WindowManager; |
| |
| import java.util.Arrays; |
| import java.util.concurrent.Semaphore; |
| import java.util.concurrent.TimeUnit; |
| |
| @TargetApi(21) |
| public class CameraStreamManager { |
| |
| private Context mContext; |
| private SurfaceTexture mSurfaceTextureToStreamTo; |
| private int mWidth; |
| private int mHeight; |
| |
| /** |
| * Tag for the {@link Log}. |
| */ |
| private static final String TAG = "Camera2BasicFragment"; |
| |
| /** |
| * ID of the current {@link CameraDevice}. |
| */ |
| private static final String CAMERA_ID = "0"; |
| |
| /** |
| * A {@link CameraCaptureSession } for camera preview. |
| */ |
| private CameraCaptureSession mCaptureSession; |
| |
| /** |
| * A reference to the opened {@link CameraDevice}. |
| */ |
| private CameraDevice mCameraDevice; |
| |
| /** |
| * The {@link android.util.Size} of camera preview. |
| */ |
| private Size mPreviewSize; |
| |
| /** |
| * {@link CameraDevice.StateCallback} is called when {@link CameraDevice} changes its state. |
| */ |
| private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() { |
| |
| @Override |
| public void onOpened(CameraDevice cameraDevice) { |
| // This method is called when the camera is opened. We start camera preview here. |
| mCameraOpenCloseLock.release(); |
| mCameraDevice = cameraDevice; |
| createCameraPreviewSession(); |
| } |
| |
| @Override |
| public void onDisconnected(CameraDevice cameraDevice) { |
| mCameraOpenCloseLock.release(); |
| cameraDevice.close(); |
| mCameraDevice = null; |
| } |
| |
| @Override |
| public void onError(CameraDevice cameraDevice, int error) { |
| mCameraOpenCloseLock.release(); |
| cameraDevice.close(); |
| mCameraDevice = null; |
| Log.e(TAG, "onError " + error); |
| } |
| |
| }; |
| |
| /** |
| * An additional thread for running tasks that shouldn't block the UI. |
| */ |
| private HandlerThread mBackgroundThread; |
| |
| /** |
| * A {@link Handler} for running tasks in the background. |
| */ |
| private Handler mBackgroundHandler; |
| |
| /** |
| * {@link CaptureRequest.Builder} for the camera preview |
| */ |
| private CaptureRequest.Builder mPreviewRequestBuilder; |
| |
| /** |
| * {@link CaptureRequest} generated by {@link #mPreviewRequestBuilder} |
| */ |
| private CaptureRequest mPreviewRequest; |
| |
| /** |
| * A {@link Semaphore} to prevent the app from exiting before closing the camera. |
| */ |
| private Semaphore mCameraOpenCloseLock = new Semaphore(1); |
| |
| /** |
| * A {@link CameraCaptureSession.CaptureCallback} that handles events related to JPEG capture. |
| */ |
| /** |
| * A {@link CameraCaptureSession.CaptureCallback} that handles events related to JPEG capture. |
| */ |
| private CameraCaptureSession.CaptureCallback mCaptureCallback |
| = new CameraCaptureSession.CaptureCallback() { |
| |
| @Override |
| public void onCaptureProgressed(CameraCaptureSession session, |
| CaptureRequest request, |
| CaptureResult partialResult) { |
| // Don't need to do anything here. |
| } |
| |
| @Override |
| public void onCaptureCompleted(CameraCaptureSession session, |
| CaptureRequest request, |
| TotalCaptureResult result) { |
| // Don't need to do anything here. |
| } |
| |
| }; |
| |
| public CameraStreamManager(Context context, SurfaceTexture textureToStreamTo, |
| int width, int height) { |
| mContext = context; |
| mSurfaceTextureToStreamTo = textureToStreamTo; |
| mWidth = width; |
| mHeight = height; |
| } |
| |
| public void onStartCameraStream() { |
| startBackgroundThread(); |
| openCamera(mWidth, mHeight); |
| } |
| |
| public void onStopCameraStream() { |
| closeCamera(); |
| stopBackgroundThread(); |
| } |
| |
| /** |
| * Sets up member variables related to camera. |
| * |
| * @param width The width of available size for camera preview |
| * @param height The height of available size for camera preview |
| */ |
| private void setUpCameraOutputs(int width, int height) { |
| // Danger, W.R.! Attempting to use too large a preview size could exceed the camera |
| // bus' bandwidth limitation, resulting in gorgeous previews but the storage of |
| // garbage capture data. |
| mPreviewSize = new Size(width, height); |
| } |
| |
| /** |
| * Opens the camera specified by {@link CameraStreamManager#CAMERA_ID}. |
| */ |
| private void openCamera(int width, int height) { |
| setUpCameraOutputs(width, height); |
| CameraManager manager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE); |
| try { |
| if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) { |
| throw new RuntimeException("Time out waiting to lock camera opening."); |
| } |
| manager.openCamera(CAMERA_ID, mStateCallback, mBackgroundHandler); |
| } catch (CameraAccessException e) { |
| e.printStackTrace(); |
| } catch (InterruptedException e) { |
| throw new RuntimeException("Interrupted while trying to lock camera opening.", e); |
| } |
| } |
| |
| /** |
| * Closes the current {@link CameraDevice}. |
| */ |
| private void closeCamera() { |
| try { |
| mCameraOpenCloseLock.acquire(); |
| if (null != mCaptureSession) { |
| mCaptureSession.close(); |
| mCaptureSession = null; |
| } |
| if (null != mCameraDevice) { |
| mCameraDevice.close(); |
| mCameraDevice = null; |
| } |
| } catch (InterruptedException e) { |
| throw new RuntimeException("Interrupted while trying to lock camera closing.", e); |
| } finally { |
| mCameraOpenCloseLock.release(); |
| } |
| } |
| |
| /** |
| * Starts a background thread and its {@link Handler}. |
| */ |
| private void startBackgroundThread() { |
| mBackgroundThread = new HandlerThread("CameraBackground"); |
| mBackgroundThread.start(); |
| mBackgroundHandler = new Handler(mBackgroundThread.getLooper()); |
| } |
| |
| /** |
| * Stops the background thread and its {@link Handler}. |
| */ |
| private void stopBackgroundThread() { |
| if (mBackgroundThread != null) { |
| mBackgroundThread.quitSafely(); |
| try { |
| mBackgroundThread.join(); |
| mBackgroundThread = null; |
| mBackgroundHandler = null; |
| } catch (InterruptedException e) { |
| e.printStackTrace(); |
| } |
| } |
| } |
| |
| /** |
| * Creates a new {@link CameraCaptureSession} for camera preview. |
| */ |
| private void createCameraPreviewSession() { |
| try { |
| assert mSurfaceTextureToStreamTo != null; |
| |
| // We configure the size of default buffer to be the size of camera preview we want. |
| mSurfaceTextureToStreamTo.setDefaultBufferSize(mPreviewSize.getWidth(), |
| mPreviewSize.getHeight()); |
| |
| // This is the output Surface we need to start preview. |
| Surface surface = new Surface(mSurfaceTextureToStreamTo); |
| |
| // We set up a CaptureRequest.Builder with the output Surface. |
| mPreviewRequestBuilder |
| = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); |
| mPreviewRequestBuilder.addTarget(surface); |
| |
| // Here, we create a CameraCaptureSession for camera preview. |
| mCameraDevice.createCaptureSession(Arrays.asList(surface), |
| new CameraCaptureSession.StateCallback() { |
| |
| @Override |
| public void onConfigured(CameraCaptureSession cameraCaptureSession) { |
| // The camera is already closed. |
| if (null == mCameraDevice) { |
| return; |
| } |
| |
| // When the session is ready, we start displaying the preview. |
| mCaptureSession = cameraCaptureSession; |
| try { |
| // Auto focus should be continuous for camera preview. |
| mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, |
| CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); |
| |
| // Finally, we start displaying the camera preview. |
| mPreviewRequest = mPreviewRequestBuilder.build(); |
| mCaptureSession.setRepeatingRequest(mPreviewRequest, |
| mCaptureCallback, mBackgroundHandler); |
| } catch (CameraAccessException e) { |
| e.printStackTrace(); |
| } |
| } |
| |
| @Override |
| public void onConfigureFailed( |
| CameraCaptureSession cameraCaptureSession) { |
| Log.e(TAG, "Camera configuration failed."); |
| } |
| }, null |
| ); |
| } catch (CameraAccessException e) { |
| e.printStackTrace(); |
| } |
| } |
| |
| public static int getRotation(Context context, int deviceRotation) { |
| // Get offset from the RGB camera. |
| CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE); |
| CameraCharacteristics characteristics = null; |
| try { |
| characteristics = manager.getCameraCharacteristics(CAMERA_ID + ""); |
| } catch (CameraAccessException e) { |
| e.printStackTrace(); |
| } |
| int toOrientate = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION); |
| |
| // Add RGB offset to current device rotation. |
| return toOrientate + deviceRotation; |
| } |
| } |