aboutsummaryrefslogtreecommitdiff
path: root/apps/TestingCamera
diff options
context:
space:
mode:
authorEino-Ville Talvala <etalvala@google.com>2013-02-19 17:38:58 -0800
committerEino-Ville Talvala <etalvala@google.com>2013-02-25 09:26:51 -0800
commit753ac7952bbb16004e5dd149dfdbfb70042827ff (patch)
treeede2b32cc0f5bbedd545cbe30f2bf0ceb70b4685 /apps/TestingCamera
parentb2409d280567130723fde8bc2922a43e2976b074 (diff)
downloadpdk-753ac7952bbb16004e5dd149dfdbfb70042827ff.tar.gz
TestingCamera: Add error handling, recording options
- Add new 'none' camera state to go to on errors - Handle failure to open camera - Register Camera.ErrorCallback and handle reported errors - Add checkbox to keep camera open when app goes to the background - Add checkbox to prevent camera handoff to MediaRecorder, to test media recorder's camera setup path. Bug: 8181262 Change-Id: I1766a69bd5ab841451e85aa4a4ad8104aa1bc8c1
Diffstat (limited to 'apps/TestingCamera')
-rw-r--r--apps/TestingCamera/res/layout/main.xml14
-rw-r--r--apps/TestingCamera/res/values/strings.xml2
-rw-r--r--apps/TestingCamera/src/com/android/testingcamera/TestingCamera.java198
3 files changed, 181 insertions, 33 deletions
diff --git a/apps/TestingCamera/res/layout/main.xml b/apps/TestingCamera/res/layout/main.xml
index 1b32057..9d6ec0a 100644
--- a/apps/TestingCamera/res/layout/main.xml
+++ b/apps/TestingCamera/res/layout/main.xml
@@ -86,6 +86,13 @@
android:layout_weight="1"
android:prompt="@string/camera_selection_prompt" />
+ <CheckBox
+ android:id="@+id/keep_open_checkbox"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/keep_open_prompt" />
+
<Button
android:id="@+id/info_button"
style="?android:attr/buttonStyleSmall"
@@ -305,6 +312,13 @@
android:textOff="@string/record_off_label"
android:textOn="@string/record_on_label" />
+ <CheckBox
+ android:id="@+id/record_handoff_checkbox"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/record_handoff_prompt" />
+
<ToggleButton
android:id="@+id/record_stabilization"
android:layout_width="fill_parent"
diff --git a/apps/TestingCamera/res/values/strings.xml b/apps/TestingCamera/res/values/strings.xml
index a4aa7f2..8acc5b3 100644
--- a/apps/TestingCamera/res/values/strings.xml
+++ b/apps/TestingCamera/res/values/strings.xml
@@ -51,4 +51,6 @@
<string name="callback_format_prompt">Preview callback format</string>
<string name="callbacks_on_label">Callbacks on</string>
<string name="callbacks_off_label">Callbacks off</string>
+ <string name="keep_open_prompt">Keep open on exit</string>
+ <string name="record_handoff_prompt">No camera recording handoff</string>
</resources>
diff --git a/apps/TestingCamera/src/com/android/testingcamera/TestingCamera.java b/apps/TestingCamera/src/com/android/testingcamera/TestingCamera.java
index cf232d9..44c6c77 100644
--- a/apps/TestingCamera/src/com/android/testingcamera/TestingCamera.java
+++ b/apps/TestingCamera/src/com/android/testingcamera/TestingCamera.java
@@ -23,6 +23,7 @@ import android.content.res.Resources;
import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
+import android.hardware.Camera.ErrorCallback;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.media.MediaScannerConnection;
@@ -39,6 +40,7 @@ import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
+import android.widget.CheckBox;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.Spinner;
@@ -68,7 +70,8 @@ import java.util.Set;
* exercised, and all information provided by the API to be shown.
*/
public class TestingCamera extends Activity
- implements SurfaceHolder.Callback, Camera.PreviewCallback {
+ implements SurfaceHolder.Callback, Camera.PreviewCallback,
+ Camera.ErrorCallback {
/** UI elements */
private SurfaceView mPreviewView;
@@ -79,6 +82,7 @@ public class TestingCamera extends Activity
private SurfaceHolder mCallbackHolder;
private Spinner mCameraSpinner;
+ private CheckBox mKeepOpenCheckBox;
private Button mInfoButton;
private Spinner mPreviewSizeSpinner;
private Spinner mPreviewFrameRateSpinner;
@@ -95,18 +99,20 @@ public class TestingCamera extends Activity
private Spinner mVideoRecordSizeSpinner;
private Spinner mVideoFrameRateSpinner;
private ToggleButton mRecordToggle;
+ private CheckBox mRecordHandoffCheckBox;
private ToggleButton mRecordStabilizationToggle;
private Spinner mCallbackFormatSpinner;
private ToggleButton mCallbackToggle;
private TextView mLogView;
+ private Set<View> mOpenOnlyControls = new HashSet<View>();
private Set<View> mPreviewOnlyControls = new HashSet<View>();
private SparseArray<String> mFormatNames;
/** Camera state */
- private int mCameraId = 0;
+ private int mCameraId;
private Camera mCamera;
private Camera.Parameters mParams;
private List<Camera.Size> mPreviewSizes;
@@ -150,12 +156,13 @@ public class TestingCamera extends Activity
private static final int CAMERA_RECORD = 4;
private int mState = CAMERA_UNINITIALIZED;
-
+ private static final int NO_CAMERA_ID = -1;
/** Misc variables */
private static final String TAG = "TestingCamera";
+
/** Activity lifecycle */
@Override
@@ -174,20 +181,27 @@ public class TestingCamera extends Activity
mCameraSpinner = (Spinner) findViewById(R.id.camera_spinner);
mCameraSpinner.setOnItemSelectedListener(mCameraSpinnerListener);
+ mKeepOpenCheckBox = (CheckBox) findViewById(R.id.keep_open_checkbox);
+
mInfoButton = (Button) findViewById(R.id.info_button);
mInfoButton.setOnClickListener(mInfoButtonListener);
+ mOpenOnlyControls.add(mInfoButton);
mPreviewSizeSpinner = (Spinner) findViewById(R.id.preview_size_spinner);
mPreviewSizeSpinner.setOnItemSelectedListener(mPreviewSizeListener);
+ mOpenOnlyControls.add(mPreviewSizeSpinner);
mPreviewFrameRateSpinner = (Spinner) findViewById(R.id.preview_frame_rate_spinner);
mPreviewFrameRateSpinner.setOnItemSelectedListener(mPreviewFrameRateListener);
+ mOpenOnlyControls.add(mPreviewFrameRateSpinner);
mPreviewToggle = (ToggleButton) findViewById(R.id.start_preview);
mPreviewToggle.setOnClickListener(mPreviewToggleListener);
+ mOpenOnlyControls.add(mPreviewToggle);
mAutofocusModeSpinner = (Spinner) findViewById(R.id.af_mode_spinner);
mAutofocusModeSpinner.setOnItemSelectedListener(mAutofocusModeListener);
+ mOpenOnlyControls.add(mAutofocusModeSpinner);
mAutofocusButton = (Button) findViewById(R.id.af_button);
mAutofocusButton.setOnClickListener(mAutofocusButtonListener);
@@ -201,12 +215,15 @@ public class TestingCamera extends Activity
mFlashModeSpinner = (Spinner) findViewById(R.id.flash_mode_spinner);
mFlashModeSpinner.setOnItemSelectedListener(mFlashModeListener);
+ mOpenOnlyControls.add(mFlashModeSpinner);
mExposureLockToggle = (ToggleButton) findViewById(R.id.exposure_lock);
mExposureLockToggle.setOnClickListener(mExposureLockToggleListener);
+ mOpenOnlyControls.add(mExposureLockToggle);
mSnapshotSizeSpinner = (Spinner) findViewById(R.id.snapshot_size_spinner);
mSnapshotSizeSpinner.setOnItemSelectedListener(mSnapshotSizeListener);
+ mOpenOnlyControls.add(mSnapshotSizeSpinner);
mTakePictureButton = (Button) findViewById(R.id.take_picture);
mTakePictureButton.setOnClickListener(mTakePictureListener);
@@ -214,29 +231,39 @@ public class TestingCamera extends Activity
mCamcorderProfileSpinner = (Spinner) findViewById(R.id.camcorder_profile_spinner);
mCamcorderProfileSpinner.setOnItemSelectedListener(mCamcorderProfileListener);
+ mOpenOnlyControls.add(mCamcorderProfileSpinner);
mVideoRecordSizeSpinner = (Spinner) findViewById(R.id.video_record_size_spinner);
mVideoRecordSizeSpinner.setOnItemSelectedListener(mVideoRecordSizeListener);
+ mOpenOnlyControls.add(mVideoRecordSizeSpinner);
mVideoFrameRateSpinner = (Spinner) findViewById(R.id.video_frame_rate_spinner);
mVideoFrameRateSpinner.setOnItemSelectedListener(mVideoFrameRateListener);
+ mOpenOnlyControls.add(mVideoFrameRateSpinner);
mRecordToggle = (ToggleButton) findViewById(R.id.start_record);
mRecordToggle.setOnClickListener(mRecordToggleListener);
mPreviewOnlyControls.add(mRecordToggle);
+ mRecordHandoffCheckBox = (CheckBox) findViewById(R.id.record_handoff_checkbox);
+
mRecordStabilizationToggle = (ToggleButton) findViewById(R.id.record_stabilization);
mRecordStabilizationToggle.setOnClickListener(mRecordStabilizationToggleListener);
+ mOpenOnlyControls.add(mRecordStabilizationToggle);
mCallbackFormatSpinner = (Spinner) findViewById(R.id.callback_format_spinner);
mCallbackFormatSpinner.setOnItemSelectedListener(mCallbackFormatListener);
+ mOpenOnlyControls.add(mCallbackFormatSpinner);
mCallbackToggle = (ToggleButton) findViewById(R.id.enable_callbacks);
mCallbackToggle.setOnClickListener(mCallbackToggleListener);
+ mOpenOnlyControls.add(mCallbackToggle);
mLogView = (TextView) findViewById(R.id.log);
mLogView.setMovementMethod(new ScrollingMovementMethod());
+ mOpenOnlyControls.addAll(mPreviewOnlyControls);
+
mFormatNames = new SparseArray<String>(7);
mFormatNames.append(ImageFormat.JPEG, "JPEG");
mFormatNames.append(ImageFormat.NV16, "NV16");
@@ -247,14 +274,22 @@ public class TestingCamera extends Activity
mFormatNames.append(ImageFormat.YV12, "YV12");
int numCameras = Camera.getNumberOfCameras();
- String[] cameraNames = new String[numCameras];
+ String[] cameraNames = new String[numCameras + 1];
+ cameraNames[0] = "None";
for (int i = 0; i < numCameras; i++) {
- cameraNames[i] = "Camera " + i;
+ cameraNames[i + 1] = "Camera " + i;
}
mCameraSpinner.setAdapter(
new ArrayAdapter<String>(this,
R.layout.spinner_item, cameraNames));
+ if (numCameras > 0) {
+ mCameraId = 0;
+ mCameraSpinner.setSelection(mCameraId + 1);
+ } else {
+ resetCamera();
+ mCameraSpinner.setSelection(0);
+ }
mRS = RenderScript.create(this);
}
@@ -262,7 +297,7 @@ public class TestingCamera extends Activity
@Override
public void onResume() {
super.onResume();
- log("onResume: Setting up camera");
+ log("onResume: Setting up");
mPreviewHolder = null;
setUpCamera();
}
@@ -270,9 +305,24 @@ public class TestingCamera extends Activity
@Override
public void onPause() {
super.onPause();
- log("onPause: Releasing camera");
- mCamera.release();
- mState = CAMERA_UNINITIALIZED;
+ if (mState == CAMERA_RECORD) {
+ stopRecording(false);
+ }
+ if (mKeepOpenCheckBox.isChecked()) {
+ log("onPause: Not releasing camera");
+
+ if (mState == CAMERA_PREVIEW) {
+ mCamera.stopPreview();
+ mState = CAMERA_OPEN;
+ }
+ } else {
+ log("onPause: Releasing camera");
+
+ if (mCamera != null) {
+ mCamera.release();
+ }
+ mState = CAMERA_UNINITIALIZED;
+ }
}
/** SurfaceHolder.Callback methods */
@@ -327,7 +377,14 @@ public class TestingCamera extends Activity
mPreviewHolder = null;
}
- /** UI controls enable/disable */
+ /** UI controls enable/disable for all open-only controls */
+ private void enableOpenOnlyControls(boolean enabled) {
+ for (View v : mOpenOnlyControls) {
+ v.setEnabled(enabled);
+ }
+ }
+
+ /** UI controls enable/disable for all preview-only controls */
private void enablePreviewOnlyControls(boolean enabled) {
for (View v : mPreviewOnlyControls) {
v.setEnabled(enabled);
@@ -341,8 +398,11 @@ public class TestingCamera extends Activity
@Override
public void onItemSelected(AdapterView<?> parent,
View view, int pos, long id) {
- if (mCameraId != pos) {
- mCameraId = pos;
+ int cameraId = pos - 1;
+ if (mCameraId != cameraId) {
+ resetCamera();
+ mCameraId = cameraId;
+ mPreviewToggle.setChecked(false);
setUpCamera();
}
}
@@ -356,10 +416,12 @@ public class TestingCamera extends Activity
private OnClickListener mInfoButtonListener = new OnClickListener() {
@Override
public void onClick(View v) {
- FragmentManager fm = getFragmentManager();
- InfoDialogFragment infoDialog = new InfoDialogFragment();
- infoDialog.updateInfo(mCameraId, mCamera);
- infoDialog.show(fm, "info_dialog_fragment");
+ if (mCameraId != NO_CAMERA_ID) {
+ FragmentManager fm = getFragmentManager();
+ InfoDialogFragment infoDialog = new InfoDialogFragment();
+ infoDialog.updateInfo(mCameraId, mCamera);
+ infoDialog.show(fm, "info_dialog_fragment");
+ }
}
};
@@ -756,17 +818,27 @@ public class TestingCamera extends Activity
// Internal methods
void setUpCamera() {
+ if (mCameraId == NO_CAMERA_ID) return;
+
log("Setting up camera " + mCameraId);
logIndent(1);
- if (mState >= CAMERA_OPEN) {
- log("Closing old camera");
- mCamera.release();
- mState = CAMERA_UNINITIALIZED;
+
+ if (mState < CAMERA_OPEN) {
+ log("Opening camera " + mCameraId);
+
+ try {
+ mCamera = Camera.open(mCameraId);
+ } catch (RuntimeException e) {
+ logE("Exception opening camera: " + e.getMessage());
+ resetCamera();
+ mCameraSpinner.setSelection(0);
+ logIndent(-1);
+ return;
+ }
+ mState = CAMERA_OPEN;
}
- log("Opening camera " + mCameraId);
- mCamera = Camera.open(mCameraId);
- mState = CAMERA_OPEN;
+ mCamera.setErrorCallback(this);
mParams = mCamera.getParameters();
// Set up preview size selection
@@ -817,9 +889,7 @@ public class TestingCamera extends Activity
logIndent(-1);
- mPreviewToggle.setEnabled(true);
- mPreviewToggle.setChecked(false);
- enablePreviewOnlyControls(false);
+ enableOpenOnlyControls(true);
resizePreview();
if (mPreviewToggle.isChecked()) {
@@ -828,10 +898,23 @@ public class TestingCamera extends Activity
mState = CAMERA_PREVIEW;
} else {
mState = CAMERA_OPEN;
+ enablePreviewOnlyControls(false);
}
logIndent(-1);
}
+ private void resetCamera() {
+ if (mState >= CAMERA_OPEN) {
+ log("Closing old camera");
+ mCamera.release();
+ }
+ mCamera = null;
+ mCameraId = NO_CAMERA_ID;
+ mState = CAMERA_UNINITIALIZED;
+
+ enableOpenOnlyControls(false);
+ }
+
private void updateAfModes(Parameters params) {
mAfModes = params.getSupportedFocusModes();
@@ -1183,6 +1266,26 @@ public class TestingCamera extends Activity
mCamera.addCallbackBuffer(data);
}
+ @Override
+ public void onError(int error, Camera camera) {
+ String errorName;
+ switch (error) {
+ case Camera.CAMERA_ERROR_SERVER_DIED:
+ errorName = "SERVER_DIED";
+ break;
+ case Camera.CAMERA_ERROR_UNKNOWN:
+ errorName = "UNKNOWN";
+ break;
+ default:
+ errorName = "?";
+ break;
+ }
+ logE("Camera error received: " + errorName + " (" + error + ")" );
+ logE("Shutting down camera");
+ resetCamera();
+ mCameraSpinner.setSelection(0);
+ }
+
static final int MEDIA_TYPE_IMAGE = 0;
static final int MEDIA_TYPE_VIDEO = 1;
@SuppressLint("SimpleDateFormat")
@@ -1258,14 +1361,26 @@ public class TestingCamera extends Activity
log("Starting recording");
logIndent(1);
log("Configuring MediaRecoder");
- mCamera.unlock();
+
+ mRecordHandoffCheckBox.setEnabled(false);
+ if (mRecordHandoffCheckBox.isChecked()) {
+ mCamera.release();
+ } else {
+ mCamera.unlock();
+ }
+
if (mRecorder != null) {
mRecorder.release();
}
+
mRecorder = new MediaRecorder();
mRecorder.setOnErrorListener(mRecordingErrorListener);
mRecorder.setOnInfoListener(mRecordingInfoListener);
- mRecorder.setCamera(mCamera);
+ if (!mRecordHandoffCheckBox.isChecked()) {
+ mRecorder.setCamera(mCamera);
+ }
+ mRecorder.setPreviewDisplay(mPreviewHolder.getSurface());
+
mRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mRecorder.setProfile(mCamcorderProfiles.get(mCamcorderProfile));
@@ -1302,9 +1417,18 @@ public class TestingCamera extends Activity
StringWriter writer = new StringWriter();
e.printStackTrace(new PrintWriter(writer));
logE("Exception starting MediaRecorder:\n" + writer.toString());
+ ready = false;
+ }
+ }
+
+ if (!ready) {
+ mRecordToggle.setChecked(false);
+ mRecordHandoffCheckBox.setEnabled(true);
+
+ if (mRecordHandoffCheckBox.isChecked()) {
+ mState = CAMERA_UNINITIALIZED;
+ setUpCamera();
}
- } else {
- mPreviewToggle.setChecked(false);
}
logIndent(-1);
}
@@ -1332,10 +1456,19 @@ public class TestingCamera extends Activity
private void stopRecording(boolean error) {
log("Stopping recording");
+ mRecordHandoffCheckBox.setEnabled(true);
+ mRecordToggle.setChecked(false);
if (mRecorder != null) {
mRecorder.stop();
- mCamera.lock();
- mState = CAMERA_PREVIEW;
+
+ if (mRecordHandoffCheckBox.isChecked()) {
+ mState = CAMERA_UNINITIALIZED;
+ setUpCamera();
+ } else {
+ mCamera.lock();
+ mState = CAMERA_PREVIEW;
+ }
+
if (!error) {
notifyMediaScannerOfFile(mRecordingFile, null);
} else {
@@ -1417,5 +1550,4 @@ public class TestingCamera extends Activity
}
}
}
-
}