1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.cts.verifier.sensors; 17 18 // ---------------------------------------------------------------------- 19 20 import android.content.Context; 21 import android.hardware.Camera; 22 import android.util.AttributeSet; 23 import android.util.Log; 24 import android.view.SurfaceHolder; 25 import android.view.SurfaceView; 26 import android.view.ViewGroup; 27 28 import java.io.IOException; 29 import java.lang.Math; 30 31 import com.android.cts.verifier.sensors.RVCVRecordActivity; 32 import com.android.cts.verifier.sensors.RVCVRecordActivity.RecordProcedureControllerCallback; 33 34 /** Camera preview class */ 35 public class RVCVCameraPreview extends SurfaceView implements SurfaceHolder.Callback { 36 private static final String TAG = "RVCVCameraPreview"; 37 private static final boolean LOCAL_LOGD = true; 38 39 private SurfaceHolder mHolder; 40 private Camera mCamera; 41 private float mAspect; 42 private int mRotation; 43 private boolean mCheckStartTest = false; 44 private boolean mPreviewStarted = false; 45 46 private RVCVRecordActivity.RecordProcedureControllerCallback mRecordProcedureControllerCallback; 47 48 /** 49 * Constructor 50 * @param context Activity context 51 */ 52 public RVCVCameraPreview(Context context) { 53 super(context); 54 mCamera = null; 55 initSurface(); 56 } 57 58 /** 59 * Constructor 60 * @param context Activity context 61 * @param attrs 62 */ 63 public RVCVCameraPreview(Context context, AttributeSet attrs) { 64 super(context, attrs); 65 } 66 67 public void init(Camera camera, float aspectRatio, int rotation) { 68 this.mCamera = camera; 69 mAspect = aspectRatio; 70 mRotation = rotation; 71 initSurface(); 72 } 73 74 private void initSurface() { 75 // Install a SurfaceHolder.Callback so we get notified when the 76 // underlying surface is created and destroyed. 77 mHolder = getHolder(); 78 mHolder.addCallback(this); 79 80 // deprecated 81 // TODO: update this code to match new API level. 82 mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 83 } 84 85 /** 86 * SurfaceHolder.Callback 87 * Surface is created, it is OK to start the camera preview now. 88 */ 89 public void surfaceCreated(SurfaceHolder holder) { 90 // The Surface has been created, now tell the camera where to draw the preview. 91 92 if (mCamera == null) { 93 // preview camera does not exist 94 return; 95 } 96 } 97 /** 98 * SurfaceHolder.Callback 99 */ 100 public void surfaceDestroyed(SurfaceHolder holder) { 101 // empty. Take care of releasing the Camera preview in your activity. 102 } 103 104 /** 105 * SurfaceHolder.Callback 106 * Restart camera preview if surface changed 107 */ 108 public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 109 110 if (mHolder.getSurface() == null || mCamera == null){ 111 // preview surface or camera does not exist 112 return; 113 } 114 if (adjustLayoutParamsIfNeeded()) { 115 // Wait on next surfaceChanged() call before proceeding 116 Log.d(TAG, "Waiting on surface change before starting preview"); 117 return; 118 } 119 120 if (mPreviewStarted) { 121 Log.w(TAG, "Re-starting camera preview"); 122 if (mCheckStartTest && mRecordProcedureControllerCallback != null) { 123 mRecordProcedureControllerCallback.stopRecordProcedureController(); 124 } 125 mCamera.stopPreview(); 126 mPreviewStarted = false; 127 } 128 mCheckStartTest = false; 129 130 mCamera.setDisplayOrientation(mRotation); 131 try { 132 mCamera.setPreviewDisplay(holder); 133 mCamera.startPreview(); 134 mPreviewStarted = true; 135 if (mRecordProcedureControllerCallback != null) { 136 mCheckStartTest = true; 137 mRecordProcedureControllerCallback.startRecordProcedureController(); 138 } 139 } catch (IOException e) { 140 if (LOCAL_LOGD) Log.d(TAG, "Error when starting camera preview: " + e.getMessage()); 141 } 142 } 143 144 /** 145 * Resize the layout to more closely match the desired aspect ratio, if necessary. 146 * 147 * @return true if we updated the layout params, false if the params look good 148 */ 149 private boolean adjustLayoutParamsIfNeeded() { 150 ViewGroup.LayoutParams layoutParams = getLayoutParams(); 151 int curWidth = getWidth(); 152 int curHeight = getHeight(); 153 float curAspect = (float)curHeight / (float)curWidth; 154 float aspectDelta = Math.abs(mAspect - curAspect); 155 if ((aspectDelta / mAspect) >= 0.01) { 156 if (curAspect > mAspect) { 157 layoutParams.height = (int)Math.round(curWidth * mAspect); 158 layoutParams.width = curWidth; 159 } else { 160 layoutParams.height = curHeight; 161 layoutParams.width = (int)Math.round(curHeight / mAspect); 162 } 163 164 if (layoutParams.height != curHeight || layoutParams.width != curWidth) { 165 Log.d(TAG, String.format("Layout (%d, %d) -> (%d, %d)", curWidth, curHeight, 166 layoutParams.width, layoutParams.height)); 167 setLayoutParams(layoutParams); 168 return true; 169 } 170 } 171 return false; 172 } 173 174 public void setRecordProcedureControllerCallback( 175 RVCVRecordActivity.RecordProcedureControllerCallback callback) { 176 mRecordProcedureControllerCallback = callback; 177 } 178 } 179