| /* |
| * Copyright (C) 2016 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.devcamera; |
| |
| import android.Manifest; |
| import android.content.Intent; |
| import android.content.pm.PackageManager; |
| import android.graphics.Color; |
| import android.hardware.camera2.CameraCharacteristics; |
| import android.hardware.camera2.CaptureResult; |
| import android.hardware.SensorManager; |
| import android.os.Bundle; |
| import android.app.Activity; |
| import android.os.Handler; |
| import android.os.HandlerThread; |
| import android.os.SystemClock; |
| import android.util.DisplayMetrics; |
| import android.util.Log; |
| import android.util.Size; |
| import android.view.Gravity; |
| import android.view.SurfaceHolder; |
| import android.view.SurfaceView; |
| import android.view.View; |
| import android.view.WindowManager; |
| import android.widget.Button; |
| import android.widget.FrameLayout; |
| import android.widget.LinearLayout; |
| import android.widget.TextView; |
| import android.widget.Toast; |
| import android.widget.ToggleButton; |
| |
| |
| /** |
| * A minimum camera app. |
| * To keep it simple: portrait mode only. |
| */ |
| public class DevCameraActivity extends Activity implements CameraInterface.MyCameraCallback, SurfaceHolder.Callback { |
| private static final String TAG = "DevCamera_UI"; |
| |
| private static final boolean LOG_FRAME_DATA = false; |
| private static final int AF_TRIGGER_HOLD_MILLIS = 4000; |
| private static final boolean STARTUP_FULL_YUV_ON = true; |
| private static final boolean START_WITH_FRONT_CAMERA = false; |
| |
| private static final int PERMISSIONS_REQUEST_CAMERA = 1; |
| private boolean mPermissionCheckActive = false; |
| |
| private SurfaceView mPreviewView; |
| private SurfaceHolder mPreviewHolder; |
| private PreviewOverlay mPreviewOverlay; |
| private FrameLayout mPreviewFrame; |
| |
| private TextView mLabel1; |
| private TextView mLabel2; |
| private ToggleButton mToggleFrontCam; // Use front camera |
| private ToggleButton mToggleYuvFull; // full YUV |
| private ToggleButton mToggleYuvVga; // VGA YUV |
| private ToggleButton mToggleRaw; // raw10 |
| private Button mButtonNoiseMode; // Noise reduction mode |
| private Button mButtonEdgeModeReprocess; // Edge mode |
| private Button mButtonNoiseModeReprocess; // Noise reduction mode for reprocessing |
| private Button mButtonEdgeMode; // Edge mode for reprocessing |
| private ToggleButton mToggleFace; // Face detection |
| private ToggleButton mToggleShow3A; // 3A info |
| private ToggleButton mToggleGyro; // Gyro |
| private ToggleButton mToggleBurstJpeg; |
| private ToggleButton mToggleSaveSdCard; |
| private LinearLayout mReprocessingGroup; |
| private Handler mMainHandler; |
| private CameraInterface mCamera; |
| |
| // Used for saving JPEGs. |
| private HandlerThread mUtilityThread; |
| private Handler mUtilityHandler; |
| |
| // send null for initialization |
| View.OnClickListener mTransferUiStateToCameraState = new View.OnClickListener() { |
| @Override |
| public void onClick(View view) { |
| // set capture flow. |
| if (view == mToggleYuvFull || view == mToggleYuvVga || view == mToggleRaw || |
| view == mButtonNoiseMode || view == mButtonEdgeMode || view == mToggleFace || view == null) |
| mCamera.setCaptureFlow( |
| mToggleYuvFull.isChecked(), |
| mToggleYuvVga.isChecked(), |
| mToggleRaw.isChecked(), |
| view == mButtonNoiseMode, /* cycle noise reduction mode */ |
| view == mButtonEdgeMode, /* cycle edge mode */ |
| mToggleFace.isChecked() |
| ); |
| // set reprocessing flow. |
| if (view == mButtonNoiseModeReprocess || view == mButtonEdgeModeReprocess || view == null) { |
| mCamera.setReprocessingFlow(view == mButtonNoiseModeReprocess, view == mButtonEdgeModeReprocess); |
| } |
| // set visibility of cluster of reprocessing controls. |
| int reprocessingViz = mToggleYuvFull.isChecked() && mCamera.isReprocessingAvailable() ? View.VISIBLE : View.GONE; |
| mReprocessingGroup.setVisibility(reprocessingViz); |
| |
| // if just turned off YUV1 stream, end burst. |
| if (view == mToggleYuvFull && !mToggleYuvFull.isChecked()) { |
| mToggleBurstJpeg.setChecked(false); |
| mCamera.setBurst(false); |
| } |
| |
| if (view == mToggleBurstJpeg) { |
| mCamera.setBurst(mToggleBurstJpeg.isChecked()); |
| } |
| |
| if (view == mToggleShow3A || view == null) { |
| mPreviewOverlay.show3AInfo(mToggleShow3A.isChecked()); |
| } |
| if (view == mToggleGyro || view == null) { |
| if (mToggleGyro.isChecked()) { |
| startGyroDisplay(); |
| } else { |
| stopGyroDisplay(); |
| } |
| } |
| } |
| }; |
| |
| @Override |
| protected void onCreate(Bundle savedInstanceState) { |
| Log.v(TAG, "onCreate"); |
| CameraTimer.t0 = SystemClock.elapsedRealtime(); |
| |
| if (checkPermissions()) { |
| // Go speed racer. |
| openCamera(START_WITH_FRONT_CAMERA); |
| } |
| |
| // Initialize UI. |
| setContentView(R.layout.activity_main); |
| mLabel1 = (TextView) findViewById(R.id.label1); |
| mLabel1.setText("Snappy initializing."); |
| mLabel2 = (TextView) findViewById(R.id.label2); |
| mLabel2.setText(" ..."); |
| Button mAfTriggerButton = (Button) findViewById(R.id.af_trigger); |
| mToggleFrontCam = (ToggleButton) findViewById(R.id.toggle_front_cam); |
| mToggleFrontCam.setChecked(START_WITH_FRONT_CAMERA); |
| mToggleYuvFull = (ToggleButton) findViewById(R.id.toggle_yuv_full); |
| mToggleYuvVga = (ToggleButton) findViewById(R.id.toggle_yuv_vga); |
| mToggleRaw = (ToggleButton) findViewById(R.id.toggle_raw); |
| mButtonNoiseMode = (Button) findViewById(R.id.button_noise); |
| mButtonEdgeMode = (Button) findViewById(R.id.button_edge); |
| mButtonNoiseModeReprocess = (Button) findViewById(R.id.button_noise_reprocess); |
| mButtonEdgeModeReprocess = (Button) findViewById(R.id.button_edge_reprocess); |
| |
| mToggleFace = (ToggleButton) findViewById(R.id.toggle_face); |
| mToggleShow3A = (ToggleButton) findViewById(R.id.toggle_show_3A); |
| mToggleGyro = (ToggleButton) findViewById(R.id.toggle_show_gyro); |
| Button mGetJpegButton = (Button) findViewById(R.id.jpeg_capture); |
| Button mGalleryButton = (Button) findViewById(R.id.gallery); |
| |
| mToggleBurstJpeg = (ToggleButton) findViewById(R.id.toggle_burst_jpeg); |
| mToggleSaveSdCard = (ToggleButton) findViewById(R.id.toggle_save_sdcard); |
| mReprocessingGroup = (LinearLayout) findViewById(R.id.reprocessing_controls); |
| mPreviewView = (SurfaceView) findViewById(R.id.preview_view); |
| mPreviewHolder = mPreviewView.getHolder(); |
| mPreviewHolder.addCallback(this); |
| mPreviewOverlay = (PreviewOverlay) findViewById(R.id.preview_overlay_view); |
| mPreviewFrame = (FrameLayout) findViewById(R.id.preview_frame); |
| |
| // Set UI listeners. |
| mAfTriggerButton.setOnClickListener(new View.OnClickListener() { |
| @Override |
| public void onClick(View view) { |
| doAFScan(); |
| } |
| }); |
| mGetJpegButton.setOnClickListener(new View.OnClickListener() { |
| @Override |
| public void onClick(View view) { |
| hitCaptureButton(); |
| } |
| }); |
| mGalleryButton.setOnClickListener(new View.OnClickListener() { |
| @Override |
| public void onClick(View view) { |
| launchPhotosViewer(); |
| } |
| }); |
| mToggleFrontCam.setOnClickListener(new View.OnClickListener() { |
| @Override |
| public void onClick(View view) { |
| Log.v(TAG, "switchCamera()"); |
| CameraTimer.t0 = SystemClock.elapsedRealtime(); |
| // ToggleButton isChecked state will determine which camera is started. |
| openCamera(mToggleFrontCam.isChecked()); |
| startCamera(); |
| } |
| }); |
| mToggleYuvFull.setOnClickListener(mTransferUiStateToCameraState); |
| mToggleYuvVga.setOnClickListener(mTransferUiStateToCameraState); |
| mToggleRaw.setOnClickListener(mTransferUiStateToCameraState); |
| mButtonNoiseMode.setOnClickListener(mTransferUiStateToCameraState); |
| mButtonEdgeMode.setOnClickListener(mTransferUiStateToCameraState); |
| mButtonNoiseModeReprocess.setOnClickListener(mTransferUiStateToCameraState); |
| mButtonEdgeModeReprocess.setOnClickListener(mTransferUiStateToCameraState); |
| mToggleFace.setOnClickListener(mTransferUiStateToCameraState); |
| mToggleShow3A.setOnClickListener(mTransferUiStateToCameraState); |
| mToggleGyro.setOnClickListener(mTransferUiStateToCameraState); |
| mToggleBurstJpeg.setOnClickListener(mTransferUiStateToCameraState); |
| mToggleSaveSdCard.setOnClickListener(mTransferUiStateToCameraState); |
| mToggleSaveSdCard.setChecked(true); |
| |
| mMainHandler = new Handler(this.getApplicationContext().getMainLooper()); |
| |
| // General utility thread for e.g. saving JPEGs. |
| mUtilityThread = new HandlerThread("UtilityThread"); |
| mUtilityThread.start(); |
| mUtilityHandler = new Handler(mUtilityThread.getLooper()); |
| |
| // --- PRINT REPORT --- |
| //CameraDeviceReport.printReport(this, false); |
| super.onCreate(savedInstanceState); |
| } |
| |
| // Open camera. No UI required. |
| private void openCamera(boolean frontCamera) { |
| // Close previous camera if required. |
| if (mCamera != null) { |
| mCamera.closeCamera(); |
| } |
| // --- SET UP CAMERA --- |
| mCamera = new Api2Camera(this, frontCamera); |
| mCamera.setCallback(this); |
| mCamera.openCamera(); |
| } |
| |
| // Initialize camera related UI and start camera; call openCamera first. |
| private void startCamera() { |
| // --- SET UP USER INTERFACE --- |
| mToggleYuvFull.setChecked(STARTUP_FULL_YUV_ON); |
| mToggleFace.setChecked(true); |
| mToggleRaw.setVisibility(mCamera.isRawAvailable() ? View.VISIBLE : View.GONE); |
| mToggleShow3A.setChecked(true); |
| mTransferUiStateToCameraState.onClick(null); |
| |
| // --- SET UP PREVIEW AND OPEN CAMERA --- |
| |
| if (mPreviewSurfaceValid) { |
| mCamera.startPreview(mPreviewHolder.getSurface()); |
| } else { |
| // Note that preview is rotated 90 degrees from camera. We just hard code this now. |
| Size previewSize = mCamera.getPreviewSize(); |
| // Render in top 12 x 9 of 16 x 9 display. |
| int renderHeight = 3 * displayHeight() / 4; |
| int renderWidth = renderHeight * previewSize.getHeight() / previewSize.getWidth(); |
| int renderPad = (displayWidth() - renderWidth) / 2; |
| |
| mPreviewFrame.setPadding(renderPad, 0, 0, 0); |
| mPreviewFrame.setLayoutParams(new LinearLayout.LayoutParams(renderWidth + renderPad, renderHeight)); |
| // setFixedSize() will trigger surfaceChanged() callback below, which will start preview. |
| mPreviewHolder.setFixedSize(previewSize.getHeight(), previewSize.getWidth()); |
| } |
| } |
| |
| boolean mPreviewSurfaceValid = false; |
| |
| @Override |
| public synchronized void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { |
| Log.v(TAG, String.format("surfaceChanged: format=%x w=%d h=%d", format, width, height)); |
| if (checkPermissions()) { |
| mPreviewSurfaceValid = true; |
| mCamera.startPreview(mPreviewHolder.getSurface()); |
| } |
| } |
| |
| Runnable mReturnToCafRunnable = new Runnable() { |
| @Override |
| public void run() { |
| mCamera.setCAF(); |
| } |
| }; |
| |
| private void doAFScan() { |
| mCamera.triggerAFScan(); |
| mMainHandler.removeCallbacks(mReturnToCafRunnable); |
| mMainHandler.postDelayed(mReturnToCafRunnable, AF_TRIGGER_HOLD_MILLIS); |
| } |
| |
| private int displayWidth() { |
| DisplayMetrics metrics = new DisplayMetrics(); |
| this.getWindowManager().getDefaultDisplay().getRealMetrics(metrics); |
| return metrics.widthPixels; |
| } |
| |
| private int displayHeight() { |
| DisplayMetrics metrics = new DisplayMetrics(); |
| this.getWindowManager().getDefaultDisplay().getRealMetrics(metrics); |
| return metrics.heightPixels; |
| } |
| |
| @Override |
| public void onStart() { |
| Log.v(TAG, "onStart"); |
| super.onStart(); |
| // Leave screen on. |
| getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); |
| |
| if (!checkPermissions()) return; |
| |
| // Can start camera now that we have the above initialized. |
| if (mCamera == null) { |
| openCamera(mToggleFrontCam.isChecked()); |
| } |
| startCamera(); |
| } |
| |
| private boolean checkPermissions() { |
| if (mPermissionCheckActive) return false; |
| |
| // Check for all runtime permissions |
| if ((checkSelfPermission(Manifest.permission.CAMERA) |
| != PackageManager.PERMISSION_GRANTED ) |
| || (checkSelfPermission(Manifest.permission.RECORD_AUDIO) |
| != PackageManager.PERMISSION_GRANTED) |
| || (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) |
| != PackageManager.PERMISSION_GRANTED)) { |
| Log.i(TAG, "Requested camera/video permissions"); |
| requestPermissions(new String[] { |
| Manifest.permission.CAMERA, |
| Manifest.permission.RECORD_AUDIO, |
| Manifest.permission.WRITE_EXTERNAL_STORAGE}, |
| PERMISSIONS_REQUEST_CAMERA); |
| mPermissionCheckActive = true; |
| return false; |
| } |
| |
| return true; |
| } |
| |
| @Override |
| public void onRequestPermissionsResult(int requestCode, String[] permissions, |
| int[] grantResults) { |
| mPermissionCheckActive = false; |
| if (requestCode == PERMISSIONS_REQUEST_CAMERA) { |
| for (int i = 0; i < grantResults.length; i++) { |
| if (grantResults[i] == PackageManager.PERMISSION_DENIED) { |
| Log.i(TAG, "At least one permission denied, can't continue: " + permissions[i]); |
| finish(); |
| return; |
| } |
| } |
| |
| Log.i(TAG, "All permissions granted"); |
| openCamera(mToggleFrontCam.isChecked()); |
| startCamera(); |
| } |
| } |
| |
| @Override |
| public void onStop() { |
| Log.v(TAG, "onStop"); |
| if (mCamera != null) { |
| mCamera.closeCamera(); |
| mCamera = null; |
| } |
| |
| // Cancel any pending AF operations. |
| mMainHandler.removeCallbacks(mReturnToCafRunnable); |
| stopGyroDisplay(); // No-op if not running. |
| super.onStop(); |
| } |
| |
| public void noCamera2Full() { |
| Toast toast = Toast.makeText(this, "WARNING: this camera does not support camera2 HARDWARE_LEVEL_FULL.", Toast.LENGTH_LONG); |
| toast.setGravity(Gravity.TOP, 0, 0); |
| toast.show(); |
| } |
| |
| @Override |
| public void setNoiseEdgeText(final String nrMode, final String edgeMode) { |
| mMainHandler.post(new Runnable() { |
| @Override |
| public void run() { |
| mButtonNoiseMode.setText(nrMode); |
| mButtonEdgeMode.setText(edgeMode); |
| } |
| }); |
| } |
| |
| @Override |
| public void setNoiseEdgeTextForReprocessing(final String nrMode, final String edgeMode) { |
| mMainHandler.post(new Runnable() { |
| @Override |
| public void run() { |
| mButtonNoiseModeReprocess.setText(nrMode); |
| mButtonEdgeModeReprocess.setText(edgeMode); |
| } |
| }); |
| } |
| |
| int mJpegCounter = 0; |
| long mJpegMillis = 0; |
| |
| @Override |
| public void jpegAvailable(final byte[] jpegData, final int x, final int y) { |
| Log.v(TAG, "JPEG returned, size = " + jpegData.length); |
| long now = SystemClock.elapsedRealtime(); |
| final long dt = mJpegMillis > 0 ? now - mJpegMillis : 0; |
| mJpegMillis = now; |
| |
| if (mToggleSaveSdCard.isChecked()) { |
| mUtilityHandler.post(new Runnable() { |
| @Override |
| public void run() { |
| final String result = MediaSaver.saveJpeg(getApplicationContext(), jpegData, getContentResolver()); |
| mMainHandler.post(new Runnable() { |
| @Override |
| public void run() { |
| fileNameToast(String.format("Saved %dx%d and %d bytes JPEG to %s in %d ms.", x, y, jpegData.length, result, dt)); |
| } |
| }); |
| |
| } |
| }); |
| } else { |
| mMainHandler.post(new Runnable() { |
| @Override |
| public void run() { |
| fileNameToast(String.format("Processing JPEG #%d %dx%d and %d bytes in %d ms.", ++mJpegCounter, x, y, jpegData.length, dt)); |
| } |
| }); |
| } |
| } |
| |
| @Override |
| public void receivedFirstFrame() { |
| mMainHandler.post(new Runnable() { |
| @Override |
| public void run() { |
| mPreviewView.setBackgroundColor(Color.TRANSPARENT); |
| } |
| }); |
| } |
| |
| Toast mToast; |
| |
| public void fileNameToast(String s) { |
| if (mToast != null) { |
| mToast.cancel(); |
| } |
| mToast = Toast.makeText(this, s, Toast.LENGTH_SHORT); |
| mToast.setGravity(Gravity.TOP, 0, 0); |
| mToast.show(); |
| } |
| |
| @Override |
| public void frameDataAvailable(final NormalizedFace[] faces, final float normExposure, final float normLens, float fps, int iso, final int afState, int aeState, int awbState) { |
| mMainHandler.post(new Runnable() { |
| @Override |
| public void run() { |
| mPreviewOverlay.setFrameData(faces, normExposure, normLens, afState); |
| } |
| }); |
| // Build info string. |
| String ae = aeStateToString(aeState); |
| String af = afStateToString(afState); |
| String awb = awbStateToString(awbState); |
| final String info = String.format(" %2.0f FPS%5d ISO AF:%s AE:%s AWB:%s", fps, iso, af, ae, awb); |
| mLastInfo = info; |
| |
| if (LOG_FRAME_DATA && faces != null) { |
| Log.v(TAG, "normExposure: " + normExposure); |
| Log.v(TAG, "normLens: " + normLens); |
| for (int i = 0; i < faces.length; ++i) { |
| Log.v(TAG, "Face getBounds: " + faces[i].bounds); |
| Log.v(TAG, "Face left eye: " + faces[i].leftEye); |
| Log.v(TAG, "Face right eye: " + faces[i].rightEye); |
| Log.v(TAG, "Face mouth: " + faces[i].mouth); |
| } |
| } |
| |
| // Status line |
| mMainHandler.post(new Runnable() { |
| @Override |
| public void run() { |
| mLabel1.setText(info); |
| } |
| }); |
| } |
| |
| Integer mTimeToFirstFrame = 0; |
| Integer mHalWaitTime = 0; |
| Float mDroppedFrameCount = 0f; |
| String mLastInfo; |
| |
| @Override |
| public void performanceDataAvailable(Integer timeToFirstFrame, Integer halWaitTime, Float droppedFrameCount) { |
| if (timeToFirstFrame != null) { |
| mTimeToFirstFrame = timeToFirstFrame; |
| } |
| if (halWaitTime != null) { |
| mHalWaitTime = halWaitTime; |
| } |
| if (droppedFrameCount != null) { |
| mDroppedFrameCount += droppedFrameCount; |
| } |
| mMainHandler.post(new Runnable() { |
| @Override |
| public void run() { |
| mLabel2.setText(String.format("TTP %dms HAL %dms Framedrops:%.2f", mTimeToFirstFrame, mHalWaitTime, mDroppedFrameCount)); |
| } |
| }); |
| } |
| |
| // Hit capture button. |
| private void hitCaptureButton() { |
| Log.v(TAG, "hitCaptureButton"); |
| mCamera.takePicture(); |
| } |
| |
| // Hit Photos button. |
| private void launchPhotosViewer() { |
| Intent intent = new Intent(android.content.Intent.ACTION_VIEW); |
| intent.setType("image/*"); |
| intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); |
| startActivity(intent); |
| } |
| |
| /********************************* |
| * Gyro graphics overlay update. * |
| *********************************/ |
| GyroOperations mGyroOperations; |
| |
| private void startGyroDisplay() { |
| |
| float[] fovs = mCamera.getFieldOfView(); |
| mPreviewOverlay.setFieldOfView(fovs[0], fovs[1]); |
| mPreviewOverlay.setFacingAndOrientation(mToggleFrontCam.isChecked() ? |
| CameraCharacteristics.LENS_FACING_FRONT : CameraCharacteristics.LENS_FACING_BACK, |
| mCamera.getOrientation()); |
| if (mGyroOperations == null) { |
| SensorManager sensorManager = (SensorManager) getSystemService(this.SENSOR_SERVICE); |
| mGyroOperations = new GyroOperations(sensorManager); |
| } |
| mGyroOperations.startListening( |
| new GyroListener() { |
| @Override |
| public void updateGyroAngles(float[] gyroAngles) { |
| mPreviewOverlay.setGyroAngles(gyroAngles); |
| } |
| } |
| ); |
| |
| mPreviewOverlay.showGyroGrid(true); |
| } |
| |
| private void stopGyroDisplay() { |
| if (mGyroOperations != null) { |
| mGyroOperations.stopListening(); |
| } |
| mPreviewOverlay.showGyroGrid(false); |
| } |
| |
| |
| /******************************************* |
| * SurfaceView callbacks just for logging. * |
| *******************************************/ |
| |
| @Override |
| public void surfaceCreated(SurfaceHolder holder) { |
| Log.v(TAG, "surfaceCreated"); |
| } |
| |
| @Override |
| public void surfaceDestroyed(SurfaceHolder holder) { |
| Log.v(TAG, "surfaceDestroyed"); |
| } |
| |
| /********************* |
| * UTILITY FUNCTIONS * |
| *********************/ |
| |
| private static String awbStateToString(int mode) { |
| switch (mode) { |
| case CaptureResult.CONTROL_AWB_STATE_INACTIVE: |
| return "inactive"; |
| case CaptureResult.CONTROL_AWB_STATE_SEARCHING: |
| return "searching"; |
| case CaptureResult.CONTROL_AWB_STATE_CONVERGED: |
| return "converged"; |
| case CaptureResult.CONTROL_AWB_STATE_LOCKED: |
| return "lock"; |
| default: |
| return "unknown " + Integer.toString(mode); |
| } |
| } |
| |
| private static String aeStateToString(int mode) { |
| switch (mode) { |
| case CaptureResult.CONTROL_AE_STATE_INACTIVE: |
| return "inactive"; |
| case CaptureResult.CONTROL_AE_STATE_SEARCHING: |
| return "searching"; |
| case CaptureResult.CONTROL_AE_STATE_PRECAPTURE: |
| return "precapture"; |
| case CaptureResult.CONTROL_AE_STATE_CONVERGED: |
| return "converged"; |
| case CaptureResult.CONTROL_AE_STATE_FLASH_REQUIRED: |
| return "flashReq"; |
| case CaptureResult.CONTROL_AE_STATE_LOCKED: |
| return "lock"; |
| default: |
| return "unknown " + Integer.toString(mode); |
| } |
| } |
| |
| private static String afStateToString(int mode) { |
| switch (mode) { |
| case CaptureResult.CONTROL_AF_STATE_INACTIVE: |
| return "inactive"; |
| case CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN: |
| return "passiveScan"; |
| case CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED: |
| return "passiveFocused"; |
| case CaptureResult.CONTROL_AF_STATE_PASSIVE_UNFOCUSED: |
| return "passiveUnfocused"; |
| case CaptureResult.CONTROL_AF_STATE_ACTIVE_SCAN: |
| return "activeScan"; |
| case CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED: |
| return "focusedLock"; |
| case CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED: |
| return "notFocusedLock"; |
| default: |
| return "unknown" + Integer.toString(mode); |
| } |
| } |
| |
| } |