Guest User

Andrpid exposure raws dualcam

a guest
Oct 3rd, 2018
148
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 77.06 KB | None | 0 0
  1. package com.example.android.camera2raw_exp_fin;
  2.  
  3. import android.Manifest;
  4. import android.app.Activity;
  5. import android.app.AlertDialog;
  6. import android.app.Dialog;
  7. import android.app.DialogFragment;
  8. import android.app.Fragment;
  9. import android.content.Context;
  10. import android.content.DialogInterface;
  11. import android.content.pm.PackageManager;
  12. import android.graphics.ImageFormat;
  13. import android.graphics.Matrix;
  14. import android.graphics.Point;
  15. import android.graphics.RectF;
  16. import android.graphics.SurfaceTexture;
  17. import android.hardware.SensorManager;
  18. import android.hardware.camera2.CameraAccessException;
  19. import android.hardware.camera2.CameraCaptureSession;
  20. import android.hardware.camera2.CameraCharacteristics;
  21. import android.hardware.camera2.CameraDevice;
  22. import android.hardware.camera2.CameraManager;
  23. import android.hardware.camera2.CameraMetadata;
  24. import android.hardware.camera2.CaptureFailure;
  25. import android.hardware.camera2.CaptureRequest;
  26. import android.hardware.camera2.CaptureResult;
  27. import android.hardware.camera2.DngCreator;
  28. import android.hardware.camera2.TotalCaptureResult;
  29. import android.hardware.camera2.params.StreamConfigurationMap;
  30. import android.media.Image;
  31. import android.media.ImageReader;
  32. import android.media.MediaScannerConnection;
  33. import android.net.Uri;
  34. import android.os.AsyncTask;
  35. import android.os.Bundle;
  36. import android.os.Environment;
  37. import android.os.Handler;
  38. import android.os.HandlerThread;
  39. import android.os.Looper;
  40. import android.os.Message;
  41. import android.os.SystemClock;
  42. import android.support.v13.app.FragmentCompat;
  43. import android.support.v4.app.ActivityCompat;
  44. import android.util.Log;
  45. import android.util.Size;
  46. import android.util.SparseIntArray;
  47. import android.view.LayoutInflater;
  48. import android.view.OrientationEventListener;
  49. import android.view.Surface;
  50. import android.view.TextureView;
  51. import android.view.View;
  52. import android.view.ViewGroup;
  53. import android.widget.EditText;
  54. import android.widget.Toast;
  55.  
  56. import com.example.android.camera2raw_exp.R;
  57.  
  58. import java.io.File;
  59. import java.io.FileOutputStream;
  60. import java.io.IOException;
  61. import java.io.OutputStream;
  62. import java.nio.ByteBuffer;
  63. import java.text.SimpleDateFormat;
  64. import java.util.ArrayList;
  65. import java.util.Arrays;
  66. import java.util.Collections;
  67. import java.util.Comparator;
  68. import java.util.Date;
  69. import java.util.List;
  70. import java.util.Locale;
  71. import java.util.Map;
  72. import java.util.TreeMap;
  73. import java.util.concurrent.Semaphore;
  74. import java.util.concurrent.TimeUnit;
  75. import java.util.concurrent.atomic.AtomicInteger;
  76.  
  77. import java.util.Random;
  78.  
  79. import static android.os.SystemClock.sleep;
  80.  
  81. /**
  82.  * A fragment that demonstrates use of the Camera2 API to capture RAW and JPEG photos.
  83.  * <p/>
  84.  * In this example, the lifecycle of a single request to take a photo is:
  85.  * <ul>
  86.  * <li>
  87.  * The user presses the "Picture" button, resulting in a call to {@link #takePicture()}.
  88.  * </li>
  89.  * <li>
  90.  * {@link #takePicture()} initiates a pre-capture sequence that triggers the camera's built-in
  91.  * auto-focus, auto-exposure, and auto-white-balance algorithms (aka. "3A") to run.
  92.  * </li>
  93.  * <li>
  94.  * When the pre-capture sequence has finished, a {@link CaptureRequest} with a monotonically
  95.  * increasing request ID set by calls to {@link CaptureRequest.Builder#setTag(Object)} is sent to
  96.  * the camera to begin the JPEG and RAW capture sequence, and an
  97.  * {@link ImageSaver.ImageSaverBuilder} is stored for this request in the
  98.  * {@link #mJpegResultQueue} and {@link #mRawResultQueue}.
  99.  * </li>
  100.  * <li>
  101.  * As {@link CaptureResult}s and {@link Image}s become available via callbacks in a background
  102.  * thread, a {@link ImageSaver.ImageSaverBuilder} is looked up by the request ID in
  103.  * {@link #mJpegResultQueue} and {@link #mRawResultQueue} and updated.
  104.  * </li>
  105.  * <li>
  106.  * When all of the necessary results to save an image are available, the an {@link ImageSaver} is
  107.  * constructed by the {@link ImageSaver.ImageSaverBuilder} and passed to a separate background
  108.  * thread to save to a file.
  109.  * </li>
  110.  * </ul>
  111.  */
  112. public class Camera2RawFragment extends Fragment
  113.         implements View.OnClickListener, FragmentCompat.OnRequestPermissionsResultCallback {
  114.  
  115.     /**
  116.      * Conversion from screen rotation to JPEG orientation.
  117.      */
  118.     private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
  119.  
  120.     static {
  121.         ORIENTATIONS.append(Surface.ROTATION_0, 0);
  122.         ORIENTATIONS.append(Surface.ROTATION_90, 90);
  123.         ORIENTATIONS.append(Surface.ROTATION_180, 180);
  124.         ORIENTATIONS.append(Surface.ROTATION_270, 270);
  125.     }
  126.  
  127.     /**
  128.      * Request code for camera permissions.
  129.      */
  130.     private static final int REQUEST_CAMERA_PERMISSIONS = 1;
  131.  
  132.     /**
  133.      * Permissions required to take a picture.
  134.      */
  135.     private static final String[] CAMERA_PERMISSIONS = {
  136.             Manifest.permission.CAMERA,
  137.             Manifest.permission.READ_EXTERNAL_STORAGE,
  138.             Manifest.permission.WRITE_EXTERNAL_STORAGE,
  139.     };
  140.  
  141.     /**
  142.      * Timeout for the pre-capture sequence.
  143.      */
  144.     private static final long PRECAPTURE_TIMEOUT_MS = 1000;
  145.  
  146.     /**
  147.      * Tolerance when comparing aspect ratios.
  148.      */
  149.     private static final double ASPECT_RATIO_TOLERANCE = 0.005;
  150.  
  151.     /**
  152.      * Max preview width that is guaranteed by Camera2 API
  153.      */
  154.     private static final int MAX_PREVIEW_WIDTH = 1920;
  155.  
  156.     /**
  157.      * Max preview height that is guaranteed by Camera2 API
  158.      */
  159.     private static final int MAX_PREVIEW_HEIGHT = 1080;
  160.  
  161.     /**
  162.      * Tag for the {@link Log}.
  163.      */
  164.     private static final String TAG = "Camera2RawFragment";
  165.  
  166.     /**
  167.      * Camera state: Device is closed.
  168.      */
  169.     private static final int STATE_CLOSED = 0;
  170.  
  171.     /**
  172.      * Camera state: Device is opened, but is not capturing.
  173.      */
  174.     private static final int STATE_OPENED = 1;
  175.  
  176.     /**
  177.      * Camera state: Showing camera preview.
  178.      */
  179.     private static final int STATE_PREVIEW = 2;
  180.  
  181.     /**
  182.      * Camera state: Waiting for 3A convergence before capturing a photo.
  183.      */
  184.     private static final int STATE_WAITING_FOR_3A_CONVERGENCE = 3;
  185.  
  186.     /**
  187.      * An {@link OrientationEventListener} used to determine when device rotation has occurred.
  188.      * This is mainly necessary for when the device is rotated by 180 degrees, in which case
  189.      * onCreate or onConfigurationChanged is not called as the view dimensions remain the same,
  190.      * but the orientation of the has changed, and thus the preview rotation must be updated.
  191.      */
  192.     private OrientationEventListener mOrientationListener;
  193.     public EditText Exposure;
  194.     public EditText Exposure2;
  195.     public EditText ISO;
  196.     public EditText Step;
  197.     Random rn = new Random();
  198.     public long epsilon =  rn.nextInt(9) + 1;
  199.     public long temp = 31250000 + (100000* epsilon);
  200.     public long temp2 = 31250000 + (100000 * epsilon);
  201.     public int stepcount=0;//after-edit
  202.     int skip3A=0;
  203.     /**
  204.      * {@link TextureView.SurfaceTextureListener} handles several lifecycle events of a
  205.      * {@link TextureView}.
  206.      */
  207.     private final TextureView.SurfaceTextureListener mSurfaceTextureListener
  208.             = new TextureView.SurfaceTextureListener() {
  209.  
  210.         @Override
  211.         public void onSurfaceTextureAvailable(SurfaceTexture texture, int width, int height) {
  212.             configureTransform(width, height);
  213.         }
  214.  
  215.         @Override
  216.         public void onSurfaceTextureSizeChanged(SurfaceTexture texture, int width, int height) {
  217.             configureTransform(width, height);
  218.         }
  219.  
  220.         @Override
  221.         public boolean onSurfaceTextureDestroyed(SurfaceTexture texture) {
  222.             synchronized (mCameraStateLock) {
  223.                 mPreviewSize = null;
  224.             }
  225.             return true;
  226.         }
  227.  
  228.         @Override
  229.         public void onSurfaceTextureUpdated(SurfaceTexture texture) {
  230.         }
  231.  
  232.     };
  233.  
  234.     /**
  235.      * An {@link AutoFitTextureView} for camera preview.
  236.      */
  237.     private AutoFitTextureView mTextureView;
  238.  
  239.     /**
  240.      * An additional thread for running tasks that shouldn't block the UI.  This is used for all
  241.      * callbacks from the {@link CameraDevice} and {@link CameraCaptureSession}s.
  242.      */
  243.     private HandlerThread mBackgroundThread;
  244.  
  245.     /**
  246.      * A counter for tracking corresponding {@link CaptureRequest}s and {@link CaptureResult}s
  247.      * across the {@link CameraCaptureSession} capture callbacks.
  248.      */
  249.     private final AtomicInteger mRequestCounter = new AtomicInteger();
  250.  
  251.     /**
  252.      * A {@link Semaphore} to prevent the app from exiting before closing the camera.
  253.      */
  254.     private final Semaphore mCameraOpenCloseLock = new Semaphore(1);
  255.  
  256.     /**
  257.      * A lock protecting camera state.
  258.      */
  259.     private final Object mCameraStateLock = new Object();
  260.  
  261.     // *********************************************************************************************
  262.     // State protected by mCameraStateLock.
  263.     //
  264.     // The following state is used across both the UI and background threads.  Methods with "Locked"
  265.     // in the name expect mCameraStateLock to be held while calling.
  266.  
  267.     /**
  268.      * ID of the current {@link CameraDevice}.
  269.      */
  270.     private String mCameraId;
  271.     String CID="0";
  272.  
  273.  
  274.     /**
  275.      * A {@link CameraCaptureSession } for camera preview.
  276.      */
  277.     private CameraCaptureSession mCaptureSession;
  278.  
  279.     /**
  280.      * A reference to the open {@link CameraDevice}.
  281.      */
  282.     private CameraDevice mCameraDevice;
  283.  
  284.     /**
  285.      * The {@link Size} of camera preview.
  286.      */
  287.     private Size mPreviewSize;
  288.  
  289.     /**
  290.      * The {@link CameraCharacteristics} for the currently configured camera device.
  291.      */
  292.     private CameraCharacteristics mCharacteristics;
  293.  
  294.     /**
  295.      * A {@link Handler} for running tasks in the background.
  296.      */
  297.     private Handler mBackgroundHandler;
  298.  
  299.     /**
  300.      * A reference counted holder wrapping the {@link ImageReader} that handles JPEG image
  301.      * captures. This is used to allow us to clean up the {@link ImageReader} when all background
  302.      * tasks using its {@link Image}s have completed.
  303.      */
  304.     private RefCountedAutoCloseable<ImageReader> mJpegImageReader;
  305.  
  306.     /**
  307.      * A reference counted holder wrapping the {@link ImageReader} that handles RAW image captures.
  308.      * This is used to allow us to clean up the {@link ImageReader} when all background tasks using
  309.      * its {@link Image}s have completed.
  310.      */
  311.     private RefCountedAutoCloseable<ImageReader> mRawImageReader;
  312.  
  313.     /**
  314.      * Whether or not the currently configured camera device is fixed-focus.
  315.      */
  316.     private boolean mNoAFRun = false;
  317.  
  318.     /**
  319.      * Number of pending user requests to capture a photo.
  320.      */
  321.     private int mPendingUserCaptures = 0;
  322.  
  323.     /**
  324.      * Request ID to {@link ImageSaver.ImageSaverBuilder} mapping for in-progress JPEG captures.
  325.      */
  326.     private final TreeMap<Integer, ImageSaver.ImageSaverBuilder> mJpegResultQueue = new TreeMap<>();
  327.  
  328.     /**
  329.      * Request ID to {@link ImageSaver.ImageSaverBuilder} mapping for in-progress RAW captures.
  330.      */
  331.     private final TreeMap<Integer, ImageSaver.ImageSaverBuilder> mRawResultQueue = new TreeMap<>();
  332.  
  333.     /**
  334.      * {@link CaptureRequest.Builder} for the camera preview
  335.      */
  336.     private CaptureRequest.Builder mPreviewRequestBuilder;
  337.  
  338.     /**
  339.      * The state of the camera device.
  340.      *
  341.      * @see #mPreCaptureCallback
  342.      */
  343.     private int mState = STATE_CLOSED;
  344.  
  345.     /**
  346.      * Timer to use with pre-capture sequence to ensure a timely capture if 3A convergence is
  347.      * taking too long.
  348.      */
  349.     private long mCaptureTimer;
  350.  
  351.     //**********************************************************************************************
  352.  
  353.     /**
  354.      * {@link CameraDevice.StateCallback} is called when the currently active {@link CameraDevice}
  355.      * changes its state.
  356.      */
  357.     private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
  358.  
  359.         @Override
  360.         public void onOpened(CameraDevice cameraDevice) {
  361.             // This method is called when the camera is opened.  We start camera preview here if
  362.             // the TextureView displaying this has been set up.
  363.             synchronized (mCameraStateLock) {
  364.                 mState = STATE_OPENED;
  365.                 mCameraOpenCloseLock.release();
  366.                 mCameraDevice = cameraDevice;
  367.  
  368.                 // Start the preview session if the TextureView has been set up already.
  369.                 if (mPreviewSize != null && mTextureView.isAvailable()) {
  370.                     createCameraPreviewSessionLocked();
  371.                 }
  372.             }
  373.         }
  374.  
  375.         @Override
  376.         public void onDisconnected(CameraDevice cameraDevice) {
  377.             synchronized (mCameraStateLock) {
  378.                 mState = STATE_CLOSED;
  379.                 mCameraOpenCloseLock.release();
  380.                 cameraDevice.close();
  381.                 mCameraDevice = null;
  382.             }
  383.         }
  384.  
  385.         @Override
  386.         public void onError(CameraDevice cameraDevice, int error) {
  387.             Log.e(TAG, "Received camera device error: " + error);
  388.             synchronized (mCameraStateLock) {
  389.                 mState = STATE_CLOSED;
  390.                 mCameraOpenCloseLock.release();
  391.                 cameraDevice.close();
  392.                 mCameraDevice = null;
  393.             }
  394.             Activity activity = getActivity();
  395.             if (null != activity) {
  396.                 activity.finish();
  397.             }
  398.         }
  399.  
  400.     };
  401.  
  402.     /**
  403.      * This a callback object for the {@link ImageReader}. "onImageAvailable" will be called when a
  404.      * JPEG image is ready to be saved.
  405.      */
  406.     private final ImageReader.OnImageAvailableListener mOnJpegImageAvailableListener
  407.             = new ImageReader.OnImageAvailableListener() {
  408.  
  409.         @Override
  410.         public void onImageAvailable(ImageReader reader) {
  411.             dequeueAndSaveImage(mJpegResultQueue, mJpegImageReader);
  412.         }
  413.  
  414.     };
  415.  
  416.     /**
  417.      * This a callback object for the {@link ImageReader}. "onImageAvailable" will be called when a
  418.      * RAW image is ready to be saved.
  419.      */
  420.     private final ImageReader.OnImageAvailableListener mOnRawImageAvailableListener
  421.             = new ImageReader.OnImageAvailableListener() {
  422.  
  423.         @Override
  424.         public void onImageAvailable(ImageReader reader) {
  425.             dequeueAndSaveImage(mRawResultQueue, mRawImageReader);
  426.         }
  427.  
  428.     };
  429.  
  430.     /**
  431.      * A {@link CameraCaptureSession.CaptureCallback} that handles events for the preview and
  432.      * pre-capture sequence.
  433.      */
  434.     private CameraCaptureSession.CaptureCallback mPreCaptureCallback
  435.             = new CameraCaptureSession.CaptureCallback() {
  436.  
  437.         private void process(CaptureResult result) {
  438.             synchronized (mCameraStateLock) {
  439.                 switch (mState) {
  440.                     case STATE_PREVIEW: {
  441.                         // We have nothing to do when the camera preview is running normally.
  442.                         break;
  443.                     }
  444.                     case STATE_WAITING_FOR_3A_CONVERGENCE: {
  445.                         boolean readyToCapture = true;
  446.                         if (!mNoAFRun) {
  447.                             Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);
  448.                             if (afState == null) {
  449.                                 break;
  450.                             }
  451.  
  452.                             // If auto-focus has reached locked state, we are ready to capture
  453.                             readyToCapture =
  454.                                     (afState == CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED ||
  455.                                             afState == CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED);
  456.                         }
  457.  
  458.                         // If we are running on an non-legacy device, we should also wait until
  459.                         // auto-exposure and auto-white-balance have converged as well before
  460.                         // taking a picture.
  461.                         if (!isLegacyLocked()) {
  462.                             Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
  463.                             Integer awbState = result.get(CaptureResult.CONTROL_AWB_STATE);
  464.                             if (aeState == null || awbState == null) {
  465.                                 break;
  466.                             }
  467.  
  468.                             readyToCapture = readyToCapture &&
  469.                                     aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED &&
  470.                                     awbState == CaptureResult.CONTROL_AWB_STATE_CONVERGED;
  471.                         }
  472.  
  473.                         // If we haven't finished the pre-capture sequence but have hit our maximum
  474.                         // wait timeout, too bad! Begin capture anyway.
  475.                         if (!readyToCapture && hitTimeoutLocked()) {
  476.                             Log.w(TAG, "Timed out waiting for pre-capture sequence to complete.");
  477.                             readyToCapture = true;
  478.                         }
  479.  
  480.                         if (readyToCapture && mPendingUserCaptures > 0) {
  481.                             // Capture once for each user tap of the "Picture" button.
  482.                             while (mPendingUserCaptures > 0) {
  483.                                 captureStillPictureLocked();
  484.                                 mPendingUserCaptures--;
  485.                             }
  486.                             // After this, the camera will go back to the normal state of preview.
  487.                             mState = STATE_PREVIEW;
  488.                         }
  489.                     }
  490.                 }
  491.             }
  492.         }
  493.  
  494.         @Override
  495.         public void onCaptureProgressed(CameraCaptureSession session, CaptureRequest request,
  496.                                         CaptureResult partialResult) {
  497.             process(partialResult);
  498.         }
  499.  
  500.         @Override
  501.         public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
  502.                                        TotalCaptureResult result) {
  503.             process(result);
  504.         }
  505.  
  506.     };
  507.  
  508.     /**
  509.      * A {@link CameraCaptureSession.CaptureCallback} that handles the still JPEG and RAW capture
  510.      * request.
  511.      */
  512.     private final CameraCaptureSession.CaptureCallback mCaptureCallback
  513.             = new CameraCaptureSession.CaptureCallback() {
  514.         @Override
  515.         public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request,
  516.                                      long timestamp, long frameNumber) {
  517.             String currentDateTime = generateTimestamp();
  518.             File rawFile = new File(Environment.
  519.                     getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM),
  520.                     "RAW_" + currentDateTime + ".dng");
  521.             File jpegFile = new File(Environment.
  522.                     getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM),
  523.                     "JPEG_" + currentDateTime + ".jpg");
  524.  
  525.             // Look up the ImageSaverBuilder for this request and update it with the file name
  526.             // based on the capture start time.
  527.             ImageSaver.ImageSaverBuilder jpegBuilder;
  528.             ImageSaver.ImageSaverBuilder rawBuilder;
  529.             int requestId = (int) request.getTag();
  530.             synchronized (mCameraStateLock) {
  531.                 jpegBuilder = mJpegResultQueue.get(requestId);
  532.                 rawBuilder = mRawResultQueue.get(requestId);
  533.             }
  534.  
  535.             if (jpegBuilder != null) jpegBuilder.setFile(jpegFile);
  536.             if (rawBuilder != null) rawBuilder.setFile(rawFile);
  537.         }
  538.  
  539.         @Override
  540.         public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
  541.                                        TotalCaptureResult result) {
  542.  
  543.  
  544.             int requestId = (int) request.getTag();
  545.             ImageSaver.ImageSaverBuilder jpegBuilder;
  546.             ImageSaver.ImageSaverBuilder rawBuilder;
  547.             StringBuilder sb = new StringBuilder();
  548.  
  549.             // Look up the ImageSaverBuilder for this request and update it with the CaptureResult
  550.             synchronized (mCameraStateLock) {
  551.                 jpegBuilder = mJpegResultQueue.get(requestId);
  552.                 rawBuilder = mRawResultQueue.get(requestId);
  553.  
  554.                 if (jpegBuilder != null) {
  555.                     jpegBuilder.setResult(result);
  556.                     sb.append("Saving JPEG as: ");
  557.                     sb.append(jpegBuilder.getSaveLocation());
  558.                 }
  559.                 if (rawBuilder != null) {
  560.                     rawBuilder.setResult(result);
  561.                     if (jpegBuilder != null) sb.append(", ");
  562.                     sb.append("Saving RAW as: ");
  563.                     sb.append(rawBuilder.getSaveLocation());
  564.                 }
  565.  
  566.                 // If we have all the results necessary, save the image to a file in the background.
  567.                 handleCompletionLocked(requestId, jpegBuilder, mJpegResultQueue);
  568.                 handleCompletionLocked(requestId, rawBuilder, mRawResultQueue);
  569.  
  570.                 finishedCaptureLocked();
  571.             }
  572.  
  573.             Toast.makeText(getActivity(), "Saved !!!",
  574.                     Toast.LENGTH_SHORT).show();
  575.          
  576.  
  577.  
  578.         }
  579.  
  580.         @Override
  581.         public void onCaptureFailed(CameraCaptureSession session, CaptureRequest request,
  582.                                     CaptureFailure failure) {
  583.             int requestId = (int) request.getTag();
  584.             synchronized (mCameraStateLock) {
  585.                 mJpegResultQueue.remove(requestId);
  586.                 mRawResultQueue.remove(requestId);
  587.                 finishedCaptureLocked();
  588.             }
  589.             showToast("Capture failed!");
  590.         }
  591.  
  592.     };
  593.  
  594.     /**
  595.      * A {@link Handler} for showing {@link Toast}s on the UI thread.
  596.      */
  597.     private final Handler mMessageHandler = new Handler(Looper.getMainLooper()) {
  598.         @Override
  599.         public void handleMessage(Message msg) {
  600.             Activity activity = getActivity();
  601.             if (activity != null) {
  602.                 Toast.makeText(activity, (String) msg.obj, Toast.LENGTH_SHORT).show();
  603.             }
  604.         }
  605.     };
  606.  
  607.     public static Camera2RawFragment newInstance() {
  608.         return new Camera2RawFragment();
  609.     }
  610.  
  611.     @Override
  612.     public View onCreateView(LayoutInflater inflater, ViewGroup container,
  613.                              Bundle savedInstanceState) {
  614.         return inflater.inflate(R.layout.fragment_camera2_basic, container, false);
  615.     }
  616.  
  617.     @Override
  618.     public void onViewCreated(final View view, Bundle savedInstanceState) {
  619.         view.findViewById(R.id.picture).setOnClickListener(this);
  620.         //view.findViewById(R.id.info).setOnClickListener(this);
  621.         mTextureView = (AutoFitTextureView) view.findViewById(R.id.texture);
  622.         //Exposure and ISO values
  623.         Exposure = (EditText) view.findViewById(R.id.expo);
  624.         Exposure2 = (EditText) view.findViewById(R.id.expo2);
  625.         ISO = (EditText) view.findViewById(R.id.iso);
  626.         Step = (EditText) view.findViewById(R.id.step);
  627.         Step.setBackground(null);
  628.         Exposure.setBackground(null);
  629.         Exposure2.setBackground(null);
  630.  
  631.  
  632.         // Setup a new OrientationEventListener.  This is used to handle rotation events like a
  633.         // 180 degree rotation that do not normally trigger a call to onCreate to do view re-layout
  634.         // or otherwise cause the preview TextureView's size to change.
  635.         mOrientationListener = new OrientationEventListener(getActivity(),
  636.                 SensorManager.SENSOR_DELAY_NORMAL) {
  637.             @Override
  638.             public void onOrientationChanged(int orientation) {
  639.                 if (mTextureView != null && mTextureView.isAvailable()) {
  640.                     configureTransform(mTextureView.getWidth(), mTextureView.getHeight());
  641.                 }
  642.             }
  643.         };
  644.     }
  645.  
  646.     @Override
  647.     public void onResume() {
  648.         super.onResume();
  649.         startBackgroundThread();
  650.         openCamera();
  651.  
  652.  
  653.         // When the screen is turned off and turned back on, the SurfaceTexture is already
  654.         // available, and "onSurfaceTextureAvailable" will not be called. In that case, we should
  655.         // configure the preview bounds here (otherwise, we wait until the surface is ready in
  656.         // the SurfaceTextureListener).
  657.         if (mTextureView.isAvailable()) {
  658.             configureTransform(mTextureView.getWidth(), mTextureView.getHeight());
  659.         } else {
  660.             mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
  661.         }
  662.         if (mOrientationListener != null && mOrientationListener.canDetectOrientation()) {
  663.             mOrientationListener.enable();
  664.         }
  665.     }
  666.  
  667.     @Override
  668.     public void onPause() {
  669.         if (mOrientationListener != null) {
  670.             mOrientationListener.disable();
  671.         }
  672.         closeCamera();
  673.         stopBackgroundThread();
  674.         super.onPause();
  675.     }
  676.  
  677.     @Override
  678.     public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
  679.         if (requestCode == REQUEST_CAMERA_PERMISSIONS) {
  680.             for (int result : grantResults) {
  681.                 if (result != PackageManager.PERMISSION_GRANTED) {
  682.                     showMissingPermissionError();
  683.                     return;
  684.                 }
  685.             }
  686.         } else {
  687.             super.onRequestPermissionsResult(requestCode, permissions, grantResults);
  688.         }
  689.     }
  690.  
  691.     @Override
  692.     public void onClick(View view) {
  693.         switch (view.getId()) {
  694.             case R.id.picture: {
  695.                 takePicture();
  696.  
  697.                 //Toast.makeText(getActivity(), "Waiting" ,
  698.                        // Toast.LENGTH_LONG).show();
  699.  
  700.                 //if (Integer.parseInt(Exposure.getText().toString())>1){
  701.                   //  Toast.makeText(getActivity(), "Waiting" + Integer.parseInt(Exposure.getText().toString()),
  702.                     //        Toast.LENGTH_SHORT).show();
  703.                 //sleep((long) (Integer.parseInt(Exposure.getText().toString()) * 1000 + 100));}
  704.                 //sleep((int)(parse(Exposure.getText().toString()))*1000);
  705.                 //sleep(2000);
  706.  
  707.  
  708.                 sleep(1650); // This time depends on expo and saving since we are closing
  709.                 closeCamera();
  710.                 //stopBackgroundThread();
  711.                 CID="2";
  712.                 //startBackgroundThread();
  713.                 openCamera();
  714.                 //stepcount--;
  715.                 skip3A=1;
  716.                 sleep(125); // This time is proportional to exposure value
  717.                 takePicture();
  718.                 skip3A=0;
  719.  
  720.  
  721.  
  722.                 break;
  723.             }
  724.             case R.id.info: {
  725.                 Activity activity = getActivity();
  726.                 if (null != activity) {
  727.                     new AlertDialog.Builder(activity)
  728.                             .setMessage(R.string.intro_message)
  729.                             .setPositiveButton(android.R.string.ok, null)
  730.                             .show();
  731.                 }
  732.                 break;
  733.             }
  734.         }
  735.     }
  736.  
  737.     /**
  738.      * Sets up state related to camera that is needed before opening a {@link CameraDevice}.
  739.      */
  740.     private boolean setUpCameraOutputs() {
  741.         Activity activity = getActivity();
  742.         CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
  743.         if (manager == null) {
  744.             ErrorDialog.buildErrorDialog("This device doesn't support Camera2 API.").
  745.                     show(getFragmentManager(), "dialog");
  746.             return false;
  747.         }
  748.         try {
  749.             // Find a CameraDevice that supports RAW captures, and configure state.
  750.             //for (String cameraId : manager.getCameraIdList()) {
  751.             String cameraId=CID;
  752.             {
  753.                 CameraCharacteristics characteristics
  754.                         = manager.getCameraCharacteristics(cameraId);
  755.  
  756.                 // We only use a camera that supports RAW in this sample.
  757.                 if (!contains(characteristics.get(
  758.                                 CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES),
  759.                         CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW)) {
  760.                     //continue;
  761.                 }
  762.  
  763.                 StreamConfigurationMap map = characteristics.get(
  764.                         CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
  765.  
  766.                 // For still image captures, we use the largest available size.
  767.                 Size largestJpeg = Collections.max(
  768.                         Arrays.asList(map.getOutputSizes(ImageFormat.JPEG)),
  769.                         new CompareSizesByArea());
  770.  
  771.                 Size largestRaw = Collections.max(
  772.                         Arrays.asList(map.getOutputSizes(ImageFormat.RAW_SENSOR)),
  773.                         new CompareSizesByArea());
  774.  
  775.                 synchronized (mCameraStateLock) {
  776.                     // Set up ImageReaders for JPEG and RAW outputs.  Place these in a reference
  777.                     // counted wrapper to ensure they are only closed when all background tasks
  778.                     // using them are finished.
  779.                     if (mJpegImageReader == null || mJpegImageReader.getAndRetain() == null) {
  780.                         mJpegImageReader = new RefCountedAutoCloseable<>(
  781.                                 ImageReader.newInstance(largestJpeg.getWidth(),
  782.                                         largestJpeg.getHeight(), ImageFormat.JPEG, /*maxImages*/5));
  783.                     }
  784.                     mJpegImageReader.get().setOnImageAvailableListener(
  785.                             mOnJpegImageAvailableListener, mBackgroundHandler);
  786.  
  787.                     if (mRawImageReader == null || mRawImageReader.getAndRetain() == null) {
  788.                         mRawImageReader = new RefCountedAutoCloseable<>(
  789.                                 ImageReader.newInstance(largestRaw.getWidth(),
  790.                                         largestRaw.getHeight(), ImageFormat.RAW_SENSOR, /*maxImages*/ 5));
  791.                     }
  792.                     mRawImageReader.get().setOnImageAvailableListener(
  793.                             mOnRawImageAvailableListener, mBackgroundHandler);
  794.  
  795.                     mCharacteristics = characteristics;
  796.                     mCameraId = cameraId;
  797.                 }
  798.                 return true;
  799.             }
  800.         } catch (CameraAccessException e) {
  801.             e.printStackTrace();
  802.         }
  803.  
  804.         // If we found no suitable cameras for capturing RAW, warn the user.
  805.         ErrorDialog.buildErrorDialog("This device doesn't support capturing RAW photos").
  806.                 show(getFragmentManager(), "dialog");
  807.         return false;
  808.     }
  809.  
  810.     /**
  811.      * Opens the camera specified by {@link #mCameraId}.
  812.      */
  813.     @SuppressWarnings("MissingPermission")
  814.     private void openCamera() {
  815.         if (!setUpCameraOutputs()) {
  816.             return;
  817.         }
  818.         if (!hasAllPermissionsGranted()) {
  819.             requestCameraPermissions();
  820.             return;
  821.         }
  822.  
  823.         Activity activity = getActivity();
  824.         CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
  825.         try {
  826.             // Wait for any previously running session to finish.
  827.             if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
  828.                 throw new RuntimeException("Time out waiting to lock camera opening.");
  829.             }
  830.  
  831.             String cameraId;
  832.             Handler backgroundHandler;
  833.             synchronized (mCameraStateLock) {
  834.                 cameraId = mCameraId;
  835.                 backgroundHandler = mBackgroundHandler;
  836.             }
  837.  
  838.             // Attempt to open the camera. mStateCallback will be called on the background handler's
  839.             // thread when this succeeds or fails.
  840.             manager.openCamera(cameraId, mStateCallback, backgroundHandler);
  841.         } catch (CameraAccessException e) {
  842.             e.printStackTrace();
  843.         } catch (InterruptedException e) {
  844.             throw new RuntimeException("Interrupted while trying to lock camera opening.", e);
  845.         }
  846.     }
  847.  
  848.     /**
  849.      * Requests permissions necessary to use camera and save pictures.
  850.      */
  851.     private void requestCameraPermissions() {
  852.         if (shouldShowRationale()) {
  853.             PermissionConfirmationDialog.newInstance().show(getChildFragmentManager(), "dialog");
  854.         } else {
  855.             FragmentCompat.requestPermissions(this, CAMERA_PERMISSIONS, REQUEST_CAMERA_PERMISSIONS);
  856.         }
  857.     }
  858.  
  859.     /**
  860.      * Tells whether all the necessary permissions are granted to this app.
  861.      *
  862.      * @return True if all the required permissions are granted.
  863.      */
  864.     private boolean hasAllPermissionsGranted() {
  865.         for (String permission : CAMERA_PERMISSIONS) {
  866.             if (ActivityCompat.checkSelfPermission(getActivity(), permission)
  867.                     != PackageManager.PERMISSION_GRANTED) {
  868.                 return false;
  869.             }
  870.         }
  871.         return true;
  872.     }
  873.  
  874.     /**
  875.      * Gets whether you should show UI with rationale for requesting the permissions.
  876.      *
  877.      * @return True if the UI should be shown.
  878.      */
  879.     private boolean shouldShowRationale() {
  880.         for (String permission : CAMERA_PERMISSIONS) {
  881.             if (FragmentCompat.shouldShowRequestPermissionRationale(this, permission)) {
  882.                 return true;
  883.             }
  884.         }
  885.         return false;
  886.     }
  887.  
  888.     /**
  889.      * Shows that this app really needs the permission and finishes the app.
  890.      */
  891.     private void showMissingPermissionError() {
  892.         Activity activity = getActivity();
  893.         if (activity != null) {
  894.             Toast.makeText(activity, R.string.request_permission, Toast.LENGTH_SHORT).show();
  895.             activity.finish();
  896.         }
  897.     }
  898.  
  899.     /**
  900.      * Closes the current {@link CameraDevice}.
  901.      */
  902.     private void closeCamera() {
  903.         try {
  904.             mCameraOpenCloseLock.acquire();
  905.             synchronized (mCameraStateLock) {
  906.  
  907.                 // Reset state and clean up resources used by the camera.
  908.                 // Note: After calling this, the ImageReaders will be closed after any background
  909.                 // tasks saving Images from these readers have been completed.
  910.                 mPendingUserCaptures = 0;
  911.                 mState = STATE_CLOSED;
  912.                 if (null != mCaptureSession) {
  913.                     mCaptureSession.close();
  914.                     mCaptureSession = null;
  915.                 }
  916.                 if (null != mCameraDevice) {
  917.                     mCameraDevice.close();
  918.                     mCameraDevice = null;
  919.                 }
  920.                 if (null != mJpegImageReader) {
  921.                     mJpegImageReader.close();
  922.                     mJpegImageReader = null;
  923.                 }
  924.                 if (null != mRawImageReader) {
  925.                     mRawImageReader.close();
  926.                     mRawImageReader = null;
  927.                 }
  928.             }
  929.         } catch (InterruptedException e) {
  930.             throw new RuntimeException("Interrupted while trying to lock camera closing.", e);
  931.         } finally {
  932.             mCameraOpenCloseLock.release();
  933.         }
  934.     }
  935.  
  936.     /**
  937.      * Starts a background thread and its {@link Handler}.
  938.      */
  939.     private void startBackgroundThread() {
  940.         mBackgroundThread = new HandlerThread("CameraBackground");
  941.         mBackgroundThread.start();
  942.         synchronized (mCameraStateLock) {
  943.             mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
  944.         }
  945.     }
  946.  
  947.     /**
  948.      * Stops the background thread and its {@link Handler}.
  949.      */
  950.     private void stopBackgroundThread() {
  951.         mBackgroundThread.quitSafely();
  952.         try {
  953.             mBackgroundThread.join();
  954.             mBackgroundThread = null;
  955.             synchronized (mCameraStateLock) {
  956.                 mBackgroundHandler = null;
  957.             }
  958.         } catch (InterruptedException e) {
  959.             e.printStackTrace();
  960.         }
  961.     }
  962.  
  963.     /**
  964.      * Creates a new {@link CameraCaptureSession} for camera preview.
  965.      * <p/>
  966.      * Call this only with {@link #mCameraStateLock} held.
  967.      */
  968.     private void createCameraPreviewSessionLocked() {
  969.         try {
  970.             SurfaceTexture texture = mTextureView.getSurfaceTexture();
  971.             // We configure the size of default buffer to be the size of camera preview we want.
  972.             texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
  973.  
  974.             // This is the output Surface we need to start preview.
  975.             Surface surface = new Surface(texture);
  976.  
  977.             // We set up a CaptureRequest.Builder with the output Surface.
  978.             mPreviewRequestBuilder
  979.                     = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
  980.             mPreviewRequestBuilder.addTarget(surface);
  981.  
  982.             // Here, we create a CameraCaptureSession for camera preview.
  983.             mCameraDevice.createCaptureSession(Arrays.asList(surface,
  984.                             mJpegImageReader.get().getSurface(),
  985.                             mRawImageReader.get().getSurface()), new CameraCaptureSession.StateCallback() {
  986.                         @Override
  987.                         public void onConfigured(CameraCaptureSession cameraCaptureSession) {
  988.                             synchronized (mCameraStateLock) {
  989.                                 // The camera is already closed
  990.                                 if (null == mCameraDevice) {
  991.                                     return;
  992.                                 }
  993.  
  994.                                 try {
  995.                                     setup3AControlsLocked(mPreviewRequestBuilder);
  996.                                     // Finally, we start displaying the camera preview.
  997.                                     cameraCaptureSession.setRepeatingRequest(
  998.                                             mPreviewRequestBuilder.build(),
  999.                                             mPreCaptureCallback, mBackgroundHandler);
  1000.                                     mState = STATE_PREVIEW;
  1001.                                 } catch (CameraAccessException | IllegalStateException e) {
  1002.                                     e.printStackTrace();
  1003.                                     return;
  1004.                                 }
  1005.                                 // When the session is ready, we start displaying the preview.
  1006.                                 mCaptureSession = cameraCaptureSession;
  1007.                             }
  1008.                         }
  1009.  
  1010.                         @Override
  1011.                         public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
  1012.                             showToast("Failed to configure camera.");
  1013.                         }
  1014.                     }, mBackgroundHandler
  1015.             );
  1016.         } catch (CameraAccessException e) {
  1017.             e.printStackTrace();
  1018.         }
  1019.     }
  1020.  
  1021.     // Enter exposure values in fraction values (seconds)
  1022.     double parse(String ratio) {
  1023.         if (ratio.contains("/")) {
  1024.             String[] rat = ratio.split("/");
  1025.             return Double.parseDouble(rat[0]) / Double.parseDouble(rat[1]);
  1026.         } else {
  1027.             return Double.parseDouble(ratio);
  1028.         }
  1029.     }
  1030.  
  1031.  
  1032.     /**
  1033.      * Configure the given {@link CaptureRequest.Builder} to use auto-focus, auto-exposure, and
  1034.      * auto-white-balance controls if available.
  1035.      * <p/>
  1036.      * Call this only with {@link #mCameraStateLock} held.
  1037.      *
  1038.      * @param builder the builder to configure.
  1039.      */
  1040.  
  1041.  
  1042.  
  1043.     private void setup3AControlsLocked(CaptureRequest.Builder builder) {
  1044.  
  1045.       if (skip3A==0) {
  1046.  
  1047.           /*
  1048.  
  1049.           // Enable auto-magical 3A run by camera device
  1050.           builder.set(CaptureRequest.CONTROL_MODE,
  1051.                   CaptureRequest.CONTROL_MODE_AUTO);
  1052.  
  1053.           Float minFocusDist =
  1054.                   mCharacteristics.get(CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE);
  1055.  
  1056.           // If MINIMUM_FOCUS_DISTANCE is 0, lens is fixed-focus and we need to skip the AF run.
  1057.           mNoAFRun = (minFocusDist == null || minFocusDist == 0);
  1058.  
  1059.           if (!mNoAFRun) {
  1060.               // If there is a "continuous picture" mode available, use it, otherwise default to AUTO.
  1061.               if (contains(mCharacteristics.get(
  1062.                       CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES),
  1063.                       CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE)) {
  1064.                   builder.set(CaptureRequest.CONTROL_AF_MODE,
  1065.                           CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
  1066.               } else {
  1067.                   builder.set(CaptureRequest.CONTROL_AF_MODE,
  1068.                           CaptureRequest.CONTROL_AF_MODE_AUTO);
  1069.               }
  1070.           }
  1071.  
  1072.           // If there is an auto-magical flash control mode available, use it, otherwise default to
  1073.           // the "on" mode, which is guaranteed to always be available.
  1074.           if (contains(mCharacteristics.get(
  1075.                   CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES),
  1076.                   CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH)) {
  1077.               builder.set(CaptureRequest.CONTROL_AE_MODE,
  1078.                       CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
  1079.           } else {
  1080.               builder.set(CaptureRequest.CONTROL_AE_MODE,
  1081.                       CaptureRequest.CONTROL_AE_MODE_ON);
  1082.           }
  1083.  
  1084.           // If there is an auto-magical white balance control mode available, use it.
  1085.           if (contains(mCharacteristics.get(
  1086.                   CameraCharacteristics.CONTROL_AWB_AVAILABLE_MODES),
  1087.                   CaptureRequest.CONTROL_AWB_MODE_AUTO)) {
  1088.               // Allow AWB to run auto-magically if this device supports this
  1089.               builder.set(CaptureRequest.CONTROL_AWB_MODE,
  1090.                       CaptureRequest.CONTROL_AWB_MODE_AUTO);
  1091.           }
  1092.           */
  1093.  
  1094.           // Restore fixed controls
  1095.           //builder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_MODE_OFF);
  1096.           builder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_OFF);// AF Fixed
  1097.           builder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF);// AE Fixed
  1098.           builder.set(CaptureRequest.CONTROL_AWB_MODE, CaptureRequest.CONTROL_AWB_MODE_OFF);// AWB Fixed
  1099.  
  1100.           // Signal Exposure and Sensitivity Change
  1101.           Toast.makeText(getActivity(), "Snapshot :" + (stepcount),
  1102.                   Toast.LENGTH_SHORT).show();
  1103.  
  1104.           if (stepcount < 2) {
  1105.  
  1106.  
  1107.               Long E1 = (long) (parse(Exposure.getText().toString()) * 1000000000L);
  1108.               Toast.makeText(getActivity(), "EV :" + E1,
  1109.                       Toast.LENGTH_SHORT).show();
  1110.               //builder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, Long.parseLong(Exposure.getText().toString()) );
  1111.               builder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, E1);
  1112.               builder.set(CaptureRequest.SENSOR_SENSITIVITY, Integer.parseInt(ISO.getText().toString()));
  1113.  
  1114.  
  1115.               stepcount++;
  1116.           } else {
  1117.  
  1118.               Long E2 = (long) (parse(Exposure2.getText().toString()) * 1000000000L);
  1119.               Toast.makeText(getActivity(), "EV :" + E2,
  1120.                       Toast.LENGTH_SHORT).show();
  1121.               //builder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, Long.parseLong(Exposure2.getText().toString()) );
  1122.               builder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, E2);
  1123.               builder.set(CaptureRequest.SENSOR_SENSITIVITY, Integer.parseInt(ISO.getText().toString()));
  1124.  
  1125.               stepcount = 1;
  1126.  
  1127.  
  1128.           }
  1129.       }
  1130.  
  1131.     }
  1132.  
  1133.     /**
  1134.      * Configure the necessary {@link android.graphics.Matrix} transformation to `mTextureView`,
  1135.      * and start/restart the preview capture session if necessary.
  1136.      * <p/>
  1137.      * This method should be called after the camera state has been initialized in
  1138.      * setUpCameraOutputs.
  1139.      *
  1140.      * @param viewWidth  The width of `mTextureView`
  1141.      * @param viewHeight The height of `mTextureView`
  1142.      */
  1143.     private void configureTransform(int viewWidth, int viewHeight) {
  1144.         Activity activity = getActivity();
  1145.         synchronized (mCameraStateLock) {
  1146.             if (null == mTextureView || null == activity) {
  1147.                 return;
  1148.             }
  1149.  
  1150.             StreamConfigurationMap map = mCharacteristics.get(
  1151.                     CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
  1152.  
  1153.             // For still image captures, we always use the largest available size.
  1154.             Size largestJpeg = Collections.max(Arrays.asList(map.getOutputSizes(ImageFormat.JPEG)),
  1155.                     new CompareSizesByArea());
  1156.  
  1157.             // Find the rotation of the device relative to the native device orientation.
  1158.             int deviceRotation = activity.getWindowManager().getDefaultDisplay().getRotation();
  1159.             Point displaySize = new Point();
  1160.             activity.getWindowManager().getDefaultDisplay().getSize(displaySize);
  1161.  
  1162.             // Find the rotation of the device relative to the camera sensor's orientation.
  1163.             int totalRotation = sensorToDeviceRotation(mCharacteristics, deviceRotation);
  1164.  
  1165.             // Swap the view dimensions for calculation as needed if they are rotated relative to
  1166.             // the sensor.
  1167.             boolean swappedDimensions = totalRotation == 90 || totalRotation == 270;
  1168.             int rotatedViewWidth = viewWidth;
  1169.             int rotatedViewHeight = viewHeight;
  1170.             int maxPreviewWidth = displaySize.x;
  1171.             int maxPreviewHeight = displaySize.y;
  1172.  
  1173.             if (swappedDimensions) {
  1174.                 rotatedViewWidth = viewHeight;
  1175.                 rotatedViewHeight = viewWidth;
  1176.                 maxPreviewWidth = displaySize.y;
  1177.                 maxPreviewHeight = displaySize.x;
  1178.             }
  1179.  
  1180.             // Preview should not be larger than display size and 1080p.
  1181.             if (maxPreviewWidth > MAX_PREVIEW_WIDTH) {
  1182.                 maxPreviewWidth = MAX_PREVIEW_WIDTH;
  1183.             }
  1184.  
  1185.             if (maxPreviewHeight > MAX_PREVIEW_HEIGHT) {
  1186.                 maxPreviewHeight = MAX_PREVIEW_HEIGHT;
  1187.             }
  1188.  
  1189.             // Find the best preview size for these view dimensions and configured JPEG size.
  1190.             Size previewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class),
  1191.                     rotatedViewWidth, rotatedViewHeight, maxPreviewWidth, maxPreviewHeight,
  1192.                     largestJpeg);
  1193.  
  1194.             if (swappedDimensions) {
  1195.                 mTextureView.setAspectRatio(
  1196.                         previewSize.getHeight(), previewSize.getWidth());
  1197.             } else {
  1198.                 mTextureView.setAspectRatio(
  1199.                         previewSize.getWidth(), previewSize.getHeight());
  1200.             }
  1201.  
  1202.             // Find rotation of device in degrees (reverse device orientation for front-facing
  1203.             // cameras).
  1204.             int rotation = (mCharacteristics.get(CameraCharacteristics.LENS_FACING) ==
  1205.                     CameraCharacteristics.LENS_FACING_FRONT) ?
  1206.                     (360 + ORIENTATIONS.get(deviceRotation)) % 360 :
  1207.                     (360 - ORIENTATIONS.get(deviceRotation)) % 360;
  1208.  
  1209.             Matrix matrix = new Matrix();
  1210.             RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
  1211.             RectF bufferRect = new RectF(0, 0, previewSize.getHeight(), previewSize.getWidth());
  1212.             float centerX = viewRect.centerX();
  1213.             float centerY = viewRect.centerY();
  1214.  
  1215.             // Initially, output stream images from the Camera2 API will be rotated to the native
  1216.             // device orientation from the sensor's orientation, and the TextureView will default to
  1217.             // scaling these buffers to fill it's view bounds.  If the aspect ratios and relative
  1218.             // orientations are correct, this is fine.
  1219.             //
  1220.             // However, if the device orientation has been rotated relative to its native
  1221.             // orientation so that the TextureView's dimensions are swapped relative to the
  1222.             // native device orientation, we must do the following to ensure the output stream
  1223.             // images are not incorrectly scaled by the TextureView:
  1224.             //   - Undo the scale-to-fill from the output buffer's dimensions (i.e. its dimensions
  1225.             //     in the native device orientation) to the TextureView's dimension.
  1226.             //   - Apply a scale-to-fill from the output buffer's rotated dimensions
  1227.             //     (i.e. its dimensions in the current device orientation) to the TextureView's
  1228.             //     dimensions.
  1229.             //   - Apply the rotation from the native device orientation to the current device
  1230.             //     rotation.
  1231.             if (Surface.ROTATION_90 == deviceRotation || Surface.ROTATION_270 == deviceRotation) {
  1232.                 bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
  1233.                 matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
  1234.                 float scale = Math.max(
  1235.                         (float) viewHeight / previewSize.getHeight(),
  1236.                         (float) viewWidth / previewSize.getWidth());
  1237.                 matrix.postScale(scale, scale, centerX, centerY);
  1238.  
  1239.             }
  1240.             matrix.postRotate(rotation, centerX, centerY);
  1241.  
  1242.             mTextureView.setTransform(matrix);
  1243.  
  1244.             // Start or restart the active capture session if the preview was initialized or
  1245.             // if its aspect ratio changed significantly.
  1246.             if (mPreviewSize == null || !checkAspectsEqual(previewSize, mPreviewSize)) {
  1247.                 mPreviewSize = previewSize;
  1248.                 if (mState != STATE_CLOSED) {
  1249.                     createCameraPreviewSessionLocked();
  1250.                 }
  1251.             }
  1252.         }
  1253.     }
  1254.  
  1255.     /**
  1256.      * Initiate a still image capture.
  1257.      * <p/>
  1258.      * This function sends a capture request that initiates a pre-capture sequence in our state
  1259.      * machine that waits for auto-focus to finish, ending in a "locked" state where the lens is no
  1260.      * longer moving, waits for auto-exposure to choose a good exposure value, and waits for
  1261.      * auto-white-balance to converge.
  1262.      */
  1263.     private void takePicture() {
  1264.         synchronized (mCameraStateLock) {
  1265.             mPendingUserCaptures++;
  1266.  
  1267.             // If we already triggered a pre-capture sequence, or are in a state where we cannot
  1268.             // do this, return immediately.
  1269.             if (mState != STATE_PREVIEW) {
  1270.                 return;
  1271.             }
  1272.  
  1273.             try {
  1274.                 // Trigger an auto-focus run if camera is capable. If the camera is already focused,
  1275.                 // this should do nothing.
  1276.                 if (!mNoAFRun) {
  1277.                     mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
  1278.                             CameraMetadata.CONTROL_AF_TRIGGER_START);
  1279.                 }
  1280.  
  1281.                 // If this is not a legacy device, we can also trigger an auto-exposure metering
  1282.                 // run.
  1283.                 if (!isLegacyLocked()) {
  1284.                     // Tell the camera to lock focus.
  1285.                     mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
  1286.                             CameraMetadata.CONTROL_AE_PRECAPTURE_TRIGGER_START);
  1287.                 }
  1288.  
  1289.                 // Update state machine to wait for auto-focus, auto-exposure, and
  1290.                 // auto-white-balance (aka. "3A") to converge.
  1291.                 mState = STATE_WAITING_FOR_3A_CONVERGENCE;
  1292.  
  1293.                 // Start a timer for the pre-capture sequence.
  1294.                 startTimerLocked();
  1295.  
  1296.                 // Replace the existing repeating request with one with updated 3A triggers.
  1297.                 mCaptureSession.capture(mPreviewRequestBuilder.build(), mPreCaptureCallback,
  1298.                         mBackgroundHandler);
  1299.             } catch (CameraAccessException e) {
  1300.                 e.printStackTrace();
  1301.             }
  1302.         }
  1303.     }
  1304.  
  1305.     /**
  1306.      * Send a capture request to the camera device that initiates a capture targeting the JPEG and
  1307.      * RAW outputs.
  1308.      * <p/>
  1309.      * Call this only with {@link #mCameraStateLock} held.
  1310.      */
  1311.     private void captureStillPictureLocked() {
  1312.         try {
  1313.             final Activity activity = getActivity();
  1314.             if (null == activity || null == mCameraDevice) {
  1315.                 return;
  1316.             }
  1317.             // This is the CaptureRequest.Builder that we use to take a picture.
  1318.             final CaptureRequest.Builder captureBuilder =
  1319.                     mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
  1320.  
  1321.             captureBuilder.addTarget(mJpegImageReader.get().getSurface());
  1322.             captureBuilder.addTarget(mRawImageReader.get().getSurface());
  1323.  
  1324.             // Use the same AE and AF modes as the preview.
  1325.             setup3AControlsLocked(captureBuilder);
  1326.  
  1327.             // Set orientation.
  1328.             int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
  1329.             captureBuilder.set(CaptureRequest.JPEG_ORIENTATION,
  1330.                     sensorToDeviceRotation(mCharacteristics, rotation));
  1331.  
  1332.             // Set request tag to easily track results in callbacks.
  1333.             captureBuilder.setTag(mRequestCounter.getAndIncrement());
  1334.  
  1335.             CaptureRequest request = captureBuilder.build();
  1336.  
  1337.             // Create an ImageSaverBuilder in which to collect results, and add it to the queue
  1338.             // of active requests.
  1339.             ImageSaver.ImageSaverBuilder jpegBuilder = new ImageSaver.ImageSaverBuilder(activity)
  1340.                     .setCharacteristics(mCharacteristics);
  1341.             ImageSaver.ImageSaverBuilder rawBuilder = new ImageSaver.ImageSaverBuilder(activity)
  1342.                     .setCharacteristics(mCharacteristics);
  1343.  
  1344.             mJpegResultQueue.put((int) request.getTag(), jpegBuilder);
  1345.             mRawResultQueue.put((int) request.getTag(), rawBuilder);
  1346.  
  1347.             mCaptureSession.capture(request, mCaptureCallback, mBackgroundHandler);
  1348.  
  1349.         } catch (CameraAccessException e) {
  1350.             e.printStackTrace();
  1351.         }
  1352.     }
  1353.  
  1354.     /**
  1355.      * Called after a RAW/JPEG capture has completed; resets the AF trigger state for the
  1356.      * pre-capture sequence.
  1357.      * <p/>
  1358.      * Call this only with {@link #mCameraStateLock} held.
  1359.      */
  1360.     private void finishedCaptureLocked() {
  1361.         try {
  1362.             // Reset the auto-focus trigger in case AF didn't run quickly enough.
  1363.             if (!mNoAFRun) {
  1364.                 mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
  1365.                         CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
  1366.  
  1367.                 mCaptureSession.capture(mPreviewRequestBuilder.build(), mPreCaptureCallback,
  1368.                         mBackgroundHandler);
  1369.  
  1370.                 mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
  1371.                         CameraMetadata.CONTROL_AF_TRIGGER_IDLE);
  1372.             }
  1373.         } catch (CameraAccessException e) {
  1374.             e.printStackTrace();
  1375.         }
  1376.     }
  1377.  
  1378.     /**
  1379.      * Retrieve the next {@link Image} from a reference counted {@link ImageReader}, retaining
  1380.      * that {@link ImageReader} until that {@link Image} is no longer in use, and set this
  1381.      * {@link Image} as the result for the next request in the queue of pending requests.  If
  1382.      * all necessary information is available, begin saving the image to a file in a background
  1383.      * thread.
  1384.      *
  1385.      * @param pendingQueue the currently active requests.
  1386.      * @param reader       a reference counted wrapper containing an {@link ImageReader} from which
  1387.      *                     to acquire an image.
  1388.      */
  1389.     private void dequeueAndSaveImage(TreeMap<Integer, ImageSaver.ImageSaverBuilder> pendingQueue,
  1390.                                      RefCountedAutoCloseable<ImageReader> reader) {
  1391.         synchronized (mCameraStateLock) {
  1392.             Map.Entry<Integer, ImageSaver.ImageSaverBuilder> entry =
  1393.                     pendingQueue.firstEntry();
  1394.             ImageSaver.ImageSaverBuilder builder = entry.getValue();
  1395.  
  1396.             // Increment reference count to prevent ImageReader from being closed while we
  1397.             // are saving its Images in a background thread (otherwise their resources may
  1398.             // be freed while we are writing to a file).
  1399.             if (reader == null || reader.getAndRetain() == null) {
  1400.                 Log.e(TAG, "Paused the activity before we could save the image," +
  1401.                         " ImageReader already closed.");
  1402.                 pendingQueue.remove(entry.getKey());
  1403.                 return;
  1404.             }
  1405.  
  1406.             Image image;
  1407.             try {
  1408.                 image = reader.get().acquireNextImage();
  1409.             } catch (IllegalStateException e) {
  1410.                 Log.e(TAG, "Too many images queued for saving, dropping image for request: " +
  1411.                         entry.getKey());
  1412.                 pendingQueue.remove(entry.getKey());
  1413.                 return;
  1414.             }
  1415.  
  1416.             builder.setRefCountedReader(reader).setImage(image);
  1417.  
  1418.             handleCompletionLocked(entry.getKey(), builder, pendingQueue);
  1419.         }
  1420.     }
  1421.  
  1422.     /**
  1423.      * Runnable that saves an {@link Image} into the specified {@link File}, and updates
  1424.      * {@link android.provider.MediaStore} to include the resulting file.
  1425.      * <p/>
  1426.      * This can be constructed through an {@link ImageSaverBuilder} as the necessary image and
  1427.      * result information becomes available.
  1428.      */
  1429.     private static class ImageSaver implements Runnable {
  1430.  
  1431.         /**
  1432.          * The image to save.
  1433.          */
  1434.         private final Image mImage;
  1435.         /**
  1436.          * The file we save the image into.
  1437.          */
  1438.         private final File mFile;
  1439.  
  1440.         /**
  1441.          * The CaptureResult for this image capture.
  1442.          */
  1443.         private final CaptureResult mCaptureResult;
  1444.  
  1445.         /**
  1446.          * The CameraCharacteristics for this camera device.
  1447.          */
  1448.         private final CameraCharacteristics mCharacteristics;
  1449.  
  1450.         /**
  1451.          * The Context to use when updating MediaStore with the saved images.
  1452.          */
  1453.         private final Context mContext;
  1454.  
  1455.         /**
  1456.          * A reference counted wrapper for the ImageReader that owns the given image.
  1457.          */
  1458.         private final RefCountedAutoCloseable<ImageReader> mReader;
  1459.  
  1460.         private ImageSaver(Image image, File file, CaptureResult result,
  1461.                            CameraCharacteristics characteristics, Context context,
  1462.                            RefCountedAutoCloseable<ImageReader> reader) {
  1463.             mImage = image;
  1464.             mFile = file;
  1465.             mCaptureResult = result;
  1466.             mCharacteristics = characteristics;
  1467.             mContext = context;
  1468.             mReader = reader;
  1469.         }
  1470.  
  1471.         @Override
  1472.         public void run() {
  1473.             boolean success = false;
  1474.             int format = mImage.getFormat();
  1475.             switch (format) {
  1476.                 case ImageFormat.JPEG: {
  1477.                     ByteBuffer buffer = mImage.getPlanes()[0].getBuffer();
  1478.                     byte[] bytes = new byte[buffer.remaining()];
  1479.                     buffer.get(bytes);
  1480.                     FileOutputStream output = null;
  1481.                     try {
  1482.                         output = new FileOutputStream(mFile);
  1483.                         output.write(bytes);
  1484.                         success = true;
  1485.                     } catch (IOException e) {
  1486.                         e.printStackTrace();
  1487.                     } finally {
  1488.                         mImage.close();
  1489.                         closeOutput(output);
  1490.                     }
  1491.                     break;
  1492.                 }
  1493.                 case ImageFormat.RAW_SENSOR: {
  1494.                     DngCreator dngCreator = new DngCreator(mCharacteristics, mCaptureResult);
  1495.                     FileOutputStream output = null;
  1496.                     try {
  1497.                         output = new FileOutputStream(mFile);
  1498.                         dngCreator.writeImage(output, mImage);
  1499.                         success = true;
  1500.                     } catch (IOException e) {
  1501.                         e.printStackTrace();
  1502.                     } finally {
  1503.                         mImage.close();
  1504.                         closeOutput(output);
  1505.                     }
  1506.                     break;
  1507.                 }
  1508.                 default: {
  1509.                     Log.e(TAG, "Cannot save image, unexpected image format:" + format);
  1510.                     break;
  1511.                 }
  1512.             }
  1513.  
  1514.             // Decrement reference count to allow ImageReader to be closed to free up resources.
  1515.             mReader.close();
  1516.  
  1517.             // If saving the file succeeded, update MediaStore.
  1518.             if (success) {
  1519.                 MediaScannerConnection.scanFile(mContext, new String[]{mFile.getPath()},
  1520.                 /*mimeTypes*/null, new MediaScannerConnection.MediaScannerConnectionClient() {
  1521.                     @Override
  1522.                     public void onMediaScannerConnected() {
  1523.                         // Do nothing
  1524.                     }
  1525.  
  1526.                     @Override
  1527.                     public void onScanCompleted(String path, Uri uri) {
  1528.                         Log.i(TAG, "Scanned " + path + ":");
  1529.                         Log.i(TAG, "-> uri=" + uri);
  1530.                     }
  1531.                 });
  1532.             }
  1533.         }
  1534.  
  1535.         /**
  1536.          * Builder class for constructing {@link ImageSaver}s.
  1537.          * <p/>
  1538.          * This class is thread safe.
  1539.          */
  1540.         public static class ImageSaverBuilder {
  1541.             private Image mImage;
  1542.             private File mFile;
  1543.             private CaptureResult mCaptureResult;
  1544.             private CameraCharacteristics mCharacteristics;
  1545.             private Context mContext;
  1546.             private RefCountedAutoCloseable<ImageReader> mReader;
  1547.  
  1548.             /**
  1549.              * Construct a new ImageSaverBuilder using the given {@link Context}.
  1550.              *
  1551.              * @param context a {@link Context} to for accessing the
  1552.              *                {@link android.provider.MediaStore}.
  1553.              */
  1554.             public ImageSaverBuilder(final Context context) {
  1555.                 mContext = context;
  1556.             }
  1557.  
  1558.             public synchronized ImageSaverBuilder setRefCountedReader(
  1559.                     RefCountedAutoCloseable<ImageReader> reader) {
  1560.                 if (reader == null) throw new NullPointerException();
  1561.  
  1562.                 mReader = reader;
  1563.                 return this;
  1564.             }
  1565.  
  1566.             public synchronized ImageSaverBuilder setImage(final Image image) {
  1567.                 if (image == null) throw new NullPointerException();
  1568.                 mImage = image;
  1569.                 return this;
  1570.             }
  1571.  
  1572.             public synchronized ImageSaverBuilder setFile(final File file) {
  1573.                 if (file == null) throw new NullPointerException();
  1574.                 mFile = file;
  1575.                 return this;
  1576.             }
  1577.  
  1578.             public synchronized ImageSaverBuilder setResult(final CaptureResult result) {
  1579.                 if (result == null) throw new NullPointerException();
  1580.                 mCaptureResult = result;
  1581.                 return this;
  1582.             }
  1583.  
  1584.             public synchronized ImageSaverBuilder setCharacteristics(
  1585.                     final CameraCharacteristics characteristics) {
  1586.                 if (characteristics == null) throw new NullPointerException();
  1587.                 mCharacteristics = characteristics;
  1588.                 return this;
  1589.             }
  1590.  
  1591.             public synchronized ImageSaver buildIfComplete() {
  1592.                 if (!isComplete()) {
  1593.                     return null;
  1594.                 }
  1595.                 return new ImageSaver(mImage, mFile, mCaptureResult, mCharacteristics, mContext,
  1596.                         mReader);
  1597.             }
  1598.  
  1599.             public synchronized String getSaveLocation() {
  1600.                 return (mFile == null) ? "Unknown" : mFile.toString();
  1601.             }
  1602.  
  1603.             private boolean isComplete() {
  1604.                 return mImage != null && mFile != null && mCaptureResult != null
  1605.                         && mCharacteristics != null;
  1606.             }
  1607.         }
  1608.     }
  1609.  
  1610.     // Utility classes and methods:
  1611.     // *********************************************************************************************
  1612.  
  1613.     /**
  1614.      * Comparator based on area of the given {@link Size} objects.
  1615.      */
  1616.     static class CompareSizesByArea implements Comparator<Size> {
  1617.  
  1618.         @Override
  1619.         public int compare(Size lhs, Size rhs) {
  1620.             // We cast here to ensure the multiplications won't overflow
  1621.             return Long.signum((long) lhs.getWidth() * lhs.getHeight() -
  1622.                     (long) rhs.getWidth() * rhs.getHeight());
  1623.         }
  1624.  
  1625.     }
  1626.  
  1627.     /**
  1628.      * A dialog fragment for displaying non-recoverable errors; this {@ling Activity} will be
  1629.      * finished once the dialog has been acknowledged by the user.
  1630.      */
  1631.     public static class ErrorDialog extends DialogFragment {
  1632.  
  1633.         private String mErrorMessage;
  1634.  
  1635.         public ErrorDialog() {
  1636.             mErrorMessage = "Unknown error occurred!";
  1637.         }
  1638.  
  1639.         // Build a dialog with a custom message (Fragments require default constructor).
  1640.         public static ErrorDialog buildErrorDialog(String errorMessage) {
  1641.             ErrorDialog dialog = new ErrorDialog();
  1642.             dialog.mErrorMessage = errorMessage;
  1643.             return dialog;
  1644.         }
  1645.  
  1646.         @Override
  1647.         public Dialog onCreateDialog(Bundle savedInstanceState) {
  1648.             final Activity activity = getActivity();
  1649.             return new AlertDialog.Builder(activity)
  1650.                     .setMessage(mErrorMessage)
  1651.                     .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
  1652.                         @Override
  1653.                         public void onClick(DialogInterface dialogInterface, int i) {
  1654.                             activity.finish();
  1655.                         }
  1656.                     })
  1657.                     .create();
  1658.         }
  1659.     }
  1660.  
  1661.     /**
  1662.      * A wrapper for an {@link AutoCloseable} object that implements reference counting to allow
  1663.      * for resource management.
  1664.      */
  1665.     public static class RefCountedAutoCloseable<T extends AutoCloseable> implements AutoCloseable {
  1666.         private T mObject;
  1667.         private long mRefCount = 0;
  1668.  
  1669.         /**
  1670.          * Wrap the given object.
  1671.          *
  1672.          * @param object an object to wrap.
  1673.          */
  1674.         public RefCountedAutoCloseable(T object) {
  1675.             if (object == null) throw new NullPointerException();
  1676.             mObject = object;
  1677.         }
  1678.  
  1679.         /**
  1680.          * Increment the reference count and return the wrapped object.
  1681.          *
  1682.          * @return the wrapped object, or null if the object has been released.
  1683.          */
  1684.         public synchronized T getAndRetain() {
  1685.             if (mRefCount < 0) {
  1686.                 return null;
  1687.             }
  1688.             mRefCount++;
  1689.             return mObject;
  1690.         }
  1691.  
  1692.         /**
  1693.          * Return the wrapped object.
  1694.          *
  1695.          * @return the wrapped object, or null if the object has been released.
  1696.          */
  1697.         public synchronized T get() {
  1698.             return mObject;
  1699.         }
  1700.  
  1701.         /**
  1702.          * Decrement the reference count and release the wrapped object if there are no other
  1703.          * users retaining this object.
  1704.          */
  1705.         @Override
  1706.         public synchronized void close() {
  1707.             if (mRefCount >= 0) {
  1708.                 mRefCount--;
  1709.                 if (mRefCount < 0) {
  1710.                     try {
  1711.                         mObject.close();
  1712.                     } catch (Exception e) {
  1713.                         throw new RuntimeException(e);
  1714.                     } finally {
  1715.                         mObject = null;
  1716.                     }
  1717.                 }
  1718.             }
  1719.         }
  1720.     }
  1721.  
  1722.     /**
  1723.      * Given {@code choices} of {@code Size}s supported by a camera, choose the smallest one that
  1724.      * is at least as large as the respective texture view size, and that is at most as large as the
  1725.      * respective max size, and whose aspect ratio matches with the specified value. If such size
  1726.      * doesn't exist, choose the largest one that is at most as large as the respective max size,
  1727.      * and whose aspect ratio matches with the specified value.
  1728.      *
  1729.      * @param choices           The list of sizes that the camera supports for the intended output
  1730.      *                          class
  1731.      * @param textureViewWidth  The width of the texture view relative to sensor coordinate
  1732.      * @param textureViewHeight The height of the texture view relative to sensor coordinate
  1733.      * @param maxWidth          The maximum width that can be chosen
  1734.      * @param maxHeight         The maximum height that can be chosen
  1735.      * @param aspectRatio       The aspect ratio
  1736.      * @return The optimal {@code Size}, or an arbitrary one if none were big enough
  1737.      */
  1738.     private static Size chooseOptimalSize(Size[] choices, int textureViewWidth,
  1739.             int textureViewHeight, int maxWidth, int maxHeight, Size aspectRatio) {
  1740.         // Collect the supported resolutions that are at least as big as the preview Surface
  1741.         List<Size> bigEnough = new ArrayList<>();
  1742.         // Collect the supported resolutions that are smaller than the preview Surface
  1743.         List<Size> notBigEnough = new ArrayList<>();
  1744.         int w = aspectRatio.getWidth();
  1745.         int h = aspectRatio.getHeight();
  1746.         for (Size option : choices) {
  1747.             if (option.getWidth() <= maxWidth && option.getHeight() <= maxHeight &&
  1748.                     option.getHeight() == option.getWidth() * h / w) {
  1749.                 if (option.getWidth() >= textureViewWidth &&
  1750.                     option.getHeight() >= textureViewHeight) {
  1751.                     bigEnough.add(option);
  1752.                 } else {
  1753.                     notBigEnough.add(option);
  1754.                 }
  1755.             }
  1756.         }
  1757.  
  1758.         // Pick the smallest of those big enough. If there is no one big enough, pick the
  1759.         // largest of those not big enough.
  1760.         if (bigEnough.size() > 0) {
  1761.             return Collections.min(bigEnough, new CompareSizesByArea());
  1762.         } else if (notBigEnough.size() > 0) {
  1763.             return Collections.max(notBigEnough, new CompareSizesByArea());
  1764.         } else {
  1765.             Log.e(TAG, "Couldn't find any suitable preview size");
  1766.             return choices[0];
  1767.         }
  1768.     }
  1769.  
  1770.     /**
  1771.      * Generate a string containing a formatted timestamp with the current date and time.
  1772.      *
  1773.      * @return a {@link String} representing a time.
  1774.      */
  1775.     private static String generateTimestamp() {
  1776.         SimpleDateFormat sdf = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss_SSS", Locale.US);
  1777.         return sdf.format(new Date());
  1778.     }
  1779.  
  1780.     /**
  1781.      * Cleanup the given {@link OutputStream}.
  1782.      *
  1783.      * @param outputStream the stream to close.
  1784.      */
  1785.     private static void closeOutput(OutputStream outputStream) {
  1786.         if (null != outputStream) {
  1787.             try {
  1788.                 outputStream.close();
  1789.             } catch (IOException e) {
  1790.                 e.printStackTrace();
  1791.             }
  1792.         }
  1793.     }
  1794.  
  1795.     /**
  1796.      * Return true if the given array contains the given integer.
  1797.      *
  1798.      * @param modes array to check.
  1799.      * @param mode  integer to get for.
  1800.      * @return true if the array contains the given integer, otherwise false.
  1801.      */
  1802.     private static boolean contains(int[] modes, int mode) {
  1803.         if (modes == null) {
  1804.             return false;
  1805.         }
  1806.         for (int i : modes) {
  1807.             if (i == mode) {
  1808.                 return true;
  1809.             }
  1810.         }
  1811.         return false;
  1812.     }
  1813.  
  1814.     /**
  1815.      * Return true if the two given {@link Size}s have the same aspect ratio.
  1816.      *
  1817.      * @param a first {@link Size} to compare.
  1818.      * @param b second {@link Size} to compare.
  1819.      * @return true if the sizes have the same aspect ratio, otherwise false.
  1820.      */
  1821.     private static boolean checkAspectsEqual(Size a, Size b) {
  1822.         double aAspect = a.getWidth() / (double) a.getHeight();
  1823.         double bAspect = b.getWidth() / (double) b.getHeight();
  1824.         return Math.abs(aAspect - bAspect) <= ASPECT_RATIO_TOLERANCE;
  1825.     }
  1826.  
  1827.     /**
  1828.      * Rotation need to transform from the camera sensor orientation to the device's current
  1829.      * orientation.
  1830.      *
  1831.      * @param c                 the {@link CameraCharacteristics} to query for the camera sensor
  1832.      *                          orientation.
  1833.      * @param deviceOrientation the current device orientation relative to the native device
  1834.      *                          orientation.
  1835.      * @return the total rotation from the sensor orientation to the current device orientation.
  1836.      */
  1837.     private static int sensorToDeviceRotation(CameraCharacteristics c, int deviceOrientation) {
  1838.         int sensorOrientation = c.get(CameraCharacteristics.SENSOR_ORIENTATION);
  1839.  
  1840.         // Get device orientation in degrees
  1841.         deviceOrientation = ORIENTATIONS.get(deviceOrientation);
  1842.  
  1843.         // Reverse device orientation for front-facing cameras
  1844.         if (c.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT) {
  1845.             deviceOrientation = -deviceOrientation;
  1846.         }
  1847.  
  1848.         // Calculate desired JPEG orientation relative to camera orientation to make
  1849.         // the image upright relative to the device orientation
  1850.         return (sensorOrientation - deviceOrientation + 360) % 360;
  1851.     }
  1852.  
  1853.     /**
  1854.      * Shows a {@link Toast} on the UI thread.
  1855.      *
  1856.      * @param text The message to show.
  1857.      */
  1858.     private void showToast(String text) {
  1859.         // We show a Toast by sending request message to mMessageHandler. This makes sure that the
  1860.         // Toast is shown on the UI thread.
  1861.         Message message = Message.obtain();
  1862.         message.obj = text;
  1863.         mMessageHandler.sendMessage(message);
  1864.     }
  1865.  
  1866.     /**
  1867.      * If the given request has been completed, remove it from the queue of active requests and
  1868.      * send an {@link ImageSaver} with the results from this request to a background thread to
  1869.      * save a file.
  1870.      * <p/>
  1871.      * Call this only with {@link #mCameraStateLock} held.
  1872.      *
  1873.      * @param requestId the ID of the {@link CaptureRequest} to handle.
  1874.      * @param builder   the {@link ImageSaver.ImageSaverBuilder} for this request.
  1875.      * @param queue     the queue to remove this request from, if completed.
  1876.      */
  1877.     private void handleCompletionLocked(int requestId, ImageSaver.ImageSaverBuilder builder,
  1878.                                         TreeMap<Integer, ImageSaver.ImageSaverBuilder> queue) {
  1879.         if (builder == null) return;
  1880.         ImageSaver saver = builder.buildIfComplete();
  1881.         if (saver != null) {
  1882.             queue.remove(requestId);
  1883.             AsyncTask.THREAD_POOL_EXECUTOR.execute(saver);
  1884.         }
  1885.     }
  1886.  
  1887.     /**
  1888.      * Check if we are using a device that only supports the LEGACY hardware level.
  1889.      * <p/>
  1890.      * Call this only with {@link #mCameraStateLock} held.
  1891.      *
  1892.      * @return true if this is a legacy device.
  1893.      */
  1894.     private boolean isLegacyLocked() {
  1895.         return mCharacteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL) ==
  1896.                 CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY;
  1897.     }
  1898.  
  1899.     /**
  1900.      * Start the timer for the pre-capture sequence.
  1901.      * <p/>
  1902.      * Call this only with {@link #mCameraStateLock} held.
  1903.      */
  1904.     private void startTimerLocked() {
  1905.         mCaptureTimer = SystemClock.elapsedRealtime();
  1906.     }
  1907.  
  1908.     /**
  1909.      * Check if the timer for the pre-capture sequence has been hit.
  1910.      * <p/>
  1911.      * Call this only with {@link #mCameraStateLock} held.
  1912.      *
  1913.      * @return true if the timeout occurred.
  1914.      */
  1915.     private boolean hitTimeoutLocked() {
  1916.         return (SystemClock.elapsedRealtime() - mCaptureTimer) > PRECAPTURE_TIMEOUT_MS;
  1917.     }
  1918.  
  1919.     /**
  1920.      * A dialog that explains about the necessary permissions.
  1921.      */
  1922.     public static class PermissionConfirmationDialog extends DialogFragment {
  1923.  
  1924.         public static PermissionConfirmationDialog newInstance() {
  1925.             return new PermissionConfirmationDialog();
  1926.         }
  1927.  
  1928.         @Override
  1929.         public Dialog onCreateDialog(Bundle savedInstanceState) {
  1930.             final Fragment parent = getParentFragment();
  1931.             return new AlertDialog.Builder(getActivity())
  1932.                     .setMessage(R.string.request_permission)
  1933.                     .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
  1934.                         @Override
  1935.                         public void onClick(DialogInterface dialog, int which) {
  1936.                             FragmentCompat.requestPermissions(parent, CAMERA_PERMISSIONS,
  1937.                                     REQUEST_CAMERA_PERMISSIONS);
  1938.                         }
  1939.                     })
  1940.                     .setNegativeButton(android.R.string.cancel,
  1941.                             new DialogInterface.OnClickListener() {
  1942.                                 @Override
  1943.                                 public void onClick(DialogInterface dialog, int which) {
  1944.                                     getActivity().finish();
  1945.                                 }
  1946.                             })
  1947.                     .create();
  1948.         }
  1949.  
  1950.     }
  1951. }
Add Comment
Please, Sign In to add comment