public static void setBarcodeSceneMode(Camera.Parameters parameters) {
   if (Camera.Parameters.SCENE_MODE_BARCODE.equals(parameters.getSceneMode())) {
     Log.i(TAG, "Barcode scene mode already set");
     return;
   }
   String sceneMode =
       findSettableValue(
           "scene mode",
           parameters.getSupportedSceneModes(),
           Camera.Parameters.SCENE_MODE_BARCODE);
   if (sceneMode != null) {
     parameters.setSceneMode(sceneMode);
   }
 }
 @Override
 public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   boolean useFrontCamera = getArguments().getBoolean(FRONT_CAMERA, false);
   camera = getCameraInstance(useFrontCamera);
   if (camera == null) {
     return;
   }
   initScreenParams();
   parameters = camera.getParameters();
   zoomRatios = parameters.getZoomRatios();
   zoomIndex = minZoomIndex = 0;
   maxZoomIndex = parameters.getMaxZoom();
   previewSizes = buildPreviewSizesRatioMap(parameters.getSupportedPreviewSizes());
   pictureSizes = buildPictureSizesRatioMap(parameters.getSupportedPictureSizes());
   List<String> sceneModes = parameters.getSupportedSceneModes();
   if (sceneModes != null) {
     for (String mode : sceneModes) {
       if (mode.equals(Camera.Parameters.SCENE_MODE_HDR)) {
         supportedHDR = true;
         break;
       }
     }
   }
   // it returns false positive
   /*getActivity().getApplicationContext().getPackageManager()
   .hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);*/
   List<String> flashModes = parameters.getSupportedFlashModes();
   if (flashModes == null || flashModes.size() <= 1) {
     /* Device has no flash */
     supportedFlash = false;
   } else {
     supportedFlash = true;
   }
   if (CameraConst.DEBUG) {
     Timber.d("PictureSizesRatioMap:");
     for (Ratio r : pictureSizes.keySet()) {
       Timber.d(r.toString() + ":");
       for (Quality q : pictureSizes.get(r).keySet()) {
         Camera.Size size = pictureSizes.get(r).get(q);
         if (size != null) {
           Timber.d(q.toString() + ": " + size.width + "x" + size.height);
         }
       }
     }
   }
   expandParams(getArguments());
   initParams();
 }
    @Override
    protected Boolean doInBackground(Void... args) {
      if (opened) return true;

      try {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
          // Choose the first back-facing camera
          boolean cameraAvailable = false;
          final CameraInfo cameraInfo = new CameraInfo();
          int cameraId = 0;
          while (!cameraAvailable && cameraId < Camera.getNumberOfCameras()) {
            Camera.getCameraInfo(cameraId, cameraInfo);
            if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) cameraAvailable = true;
            else cameraId++;
          }
          if (!cameraAvailable) return false; // No back-facing camera available...
          camera = Camera.open(cameraId);
          cameraOrientation = cameraInfo.orientation;
        } else {
          camera = Camera.open();
          cameraOrientation = 90; // TODO Is this correct?
        }
        if (camera == null) return false; // No camera available...
        final Camera.Parameters params = camera.getParameters();

        // Set the maximum resolution based on the maximum heap size
        final int maxHeapSize =
            ((ActivityManager)
                    context.getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE))
                .getMemoryClass();
        final int maxResolution =
            Math.min(
                5 * 1024 * 1024,
                maxHeapSize
                    * 1024
                    * 1024
                    / 4
                    / 3); // Each image might take up to 33% of the maximum heap size and 5
                          // megapixels at most
        // System.err.println("max heap size: " + maxHeapSize);
        // System.err.println("max resolution: " + maxResolution);

        // Choose the biggest possible picture size within the limits and the corresponding preview
        // sizes with the same ratio
        pictureSize = null;
        previewSizes = new ArrayList<Size>();
        final List<Size> supportedPictureSizes = params.getSupportedPictureSizes();
        final List<Size> supportedPreviewSizes = params.getSupportedPreviewSizes();
        Collections.sort(supportedPictureSizes, Collections.reverseOrder(sizeComparator));
        for (Size supportedPictureSize : supportedPictureSizes) {
          for (Size supportedPreviewSize : supportedPreviewSizes) {
            if (supportedPictureSize.width * supportedPreviewSize.height
                    == supportedPictureSize.height * supportedPreviewSize.width
                && supportedPictureSize.width * supportedPictureSize.height <= maxResolution) {
              pictureSize = supportedPictureSize;
              previewSizes.add(supportedPreviewSize);
            }
          }
          if (pictureSize != null) break;
        }
        // System.err.println("Selected resolution: " + pictureSize.width + "x" +
        // pictureSize.height);
        Collections.sort(previewSizes, Collections.reverseOrder(sizeComparator));
        if (pictureSize
            == null) { // No picture size ratio and preview size ratio match (shouldn't happen...)
          releaseCamera();
          return false;
        }

        // Set parameters
        final List<String> supportedWhiteBalance = params.getSupportedWhiteBalance();
        final List<String> supportedFlashModes = params.getSupportedFlashModes();
        final List<String> supportedSceneModes = params.getSupportedSceneModes();
        final List<String> supportedFocusModes = params.getSupportedFocusModes();
        params.setPictureSize(pictureSize.width, pictureSize.height);
        params.setPreviewSize(previewSizes.get(0).width, previewSizes.get(0).height);
        if (supportedWhiteBalance != null
            && supportedWhiteBalance.contains(Camera.Parameters.WHITE_BALANCE_AUTO)) {
          params.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_AUTO);
        }
        if (supportedFlashModes != null
            && supportedFlashModes.contains(Camera.Parameters.FLASH_MODE_AUTO)) {
          params.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
        }
        if (supportedSceneModes != null
            && supportedSceneModes.contains(Camera.Parameters.SCENE_MODE_AUTO)) {
          params.setSceneMode(Camera.Parameters.SCENE_MODE_AUTO);
        }
        // TODO Decide the preferred focus mode order
        if (supportedFocusModes != null
            && supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
          params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
          autofocus = true;
        } else if (supportedFocusModes != null
            && supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
          params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
          autofocus = true;
        } else if (supportedFocusModes != null
            && supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
          params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
          autofocus = false;
        } else {
          autofocus = false;
        }
        camera.setParameters(params);
      } catch (Exception e) {
        releaseCamera();
        return false; // Some error while opening the camera...
      }

      opened = true;
      return true;
    }
  /**
   * Set the legacy parameters using the {@link LegacyRequest legacy request}.
   *
   * <p>The legacy request's parameters are changed as a side effect of calling this method.
   *
   * @param legacyRequest a non-{@code null} legacy request
   */
  public static void convertRequestMetadata(LegacyRequest legacyRequest) {
    CameraCharacteristics characteristics = legacyRequest.characteristics;
    CaptureRequest request = legacyRequest.captureRequest;
    Size previewSize = legacyRequest.previewSize;
    Camera.Parameters params = legacyRequest.parameters;

    Rect activeArray = characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);

    /*
     * scaler.cropRegion
     */
    ParameterUtils.ZoomData zoomData;
    {
      zoomData =
          ParameterUtils.convertScalerCropRegion(
              activeArray, request.get(SCALER_CROP_REGION), previewSize, params);

      if (params.isZoomSupported()) {
        params.setZoom(zoomData.zoomIndex);
      } else if (VERBOSE) {
        Log.v(TAG, "convertRequestToMetadata - zoom is not supported");
      }
    }

    /*
     * colorCorrection.*
     */
    // colorCorrection.aberrationMode
    {
      int aberrationMode =
          ParamsUtils.getOrDefault(
              request,
              COLOR_CORRECTION_ABERRATION_MODE,
              /*defaultValue*/ COLOR_CORRECTION_ABERRATION_MODE_FAST);

      if (aberrationMode != COLOR_CORRECTION_ABERRATION_MODE_FAST) {
        Log.w(
            TAG,
            "convertRequestToMetadata - Ignoring unsupported "
                + "colorCorrection.aberrationMode = "
                + aberrationMode);
      }
    }

    /*
     * control.ae*
     */
    // control.aeAntibandingMode
    {
      String legacyMode;
      Integer antiBandingMode = request.get(CONTROL_AE_ANTIBANDING_MODE);
      if (antiBandingMode != null) {
        legacyMode = convertAeAntiBandingModeToLegacy(antiBandingMode);
      } else {
        legacyMode =
            ListUtils.listSelectFirstFrom(
                params.getSupportedAntibanding(),
                new String[] {
                  Parameters.ANTIBANDING_AUTO,
                  Parameters.ANTIBANDING_OFF,
                  Parameters.ANTIBANDING_50HZ,
                  Parameters.ANTIBANDING_60HZ,
                });
      }

      if (legacyMode != null) {
        params.setAntibanding(legacyMode);
      }
    }

    /*
     * control.aeRegions, afRegions
     */
    {
      // aeRegions
      {
        // Use aeRegions if available, fall back to using awbRegions if present
        MeteringRectangle[] aeRegions = request.get(CONTROL_AE_REGIONS);
        if (request.get(CONTROL_AWB_REGIONS) != null) {
          Log.w(
              TAG,
              "convertRequestMetadata - control.awbRegions setting is not "
                  + "supported, ignoring value");
        }
        int maxNumMeteringAreas = params.getMaxNumMeteringAreas();
        List<Camera.Area> meteringAreaList =
            convertMeteringRegionsToLegacy(
                activeArray, zoomData, aeRegions, maxNumMeteringAreas, /*regionName*/ "AE");

        // WAR: for b/17252693, some devices can't handle params.setFocusAreas(null).
        if (maxNumMeteringAreas > 0) {
          params.setMeteringAreas(meteringAreaList);
        }
      }

      // afRegions
      {
        MeteringRectangle[] afRegions = request.get(CONTROL_AF_REGIONS);
        int maxNumFocusAreas = params.getMaxNumFocusAreas();
        List<Camera.Area> focusAreaList =
            convertMeteringRegionsToLegacy(
                activeArray, zoomData, afRegions, maxNumFocusAreas, /*regionName*/ "AF");

        // WAR: for b/17252693, some devices can't handle params.setFocusAreas(null).
        if (maxNumFocusAreas > 0) {
          params.setFocusAreas(focusAreaList);
        }
      }
    }

    // control.aeTargetFpsRange
    Range<Integer> aeFpsRange = request.get(CONTROL_AE_TARGET_FPS_RANGE);
    if (aeFpsRange != null) {
      int[] legacyFps = convertAeFpsRangeToLegacy(aeFpsRange);

      // TODO - Should we enforce that all HAL1 devices must include (30, 30) FPS range?
      boolean supported = false;
      for (int[] range : params.getSupportedPreviewFpsRange()) {
        if (legacyFps[0] == range[0] && legacyFps[1] == range[1]) {
          supported = true;
          break;
        }
      }
      if (supported) {
        params.setPreviewFpsRange(
            legacyFps[Camera.Parameters.PREVIEW_FPS_MIN_INDEX],
            legacyFps[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]);
      } else {
        Log.w(TAG, "Unsupported FPS range set [" + legacyFps[0] + "," + legacyFps[1] + "]");
      }
    }

    /*
     * control
     */

    // control.aeExposureCompensation
    {
      Range<Integer> compensationRange =
          characteristics.get(CameraCharacteristics.CONTROL_AE_COMPENSATION_RANGE);
      int compensation =
          ParamsUtils.getOrDefault(request, CONTROL_AE_EXPOSURE_COMPENSATION, /*defaultValue*/ 0);

      if (!compensationRange.contains(compensation)) {
        Log.w(
            TAG,
            "convertRequestMetadata - control.aeExposureCompensation "
                + "is out of range, ignoring value");
        compensation = 0;
      }

      params.setExposureCompensation(compensation);
    }

    // control.aeLock
    {
      Boolean aeLock =
          getIfSupported(
              request,
              CONTROL_AE_LOCK, /*defaultValue*/
              false,
              params.isAutoExposureLockSupported(),
              /*allowedValue*/ false);

      if (aeLock != null) {
        params.setAutoExposureLock(aeLock);
      }

      if (VERBOSE) {
        Log.v(TAG, "convertRequestToMetadata - control.aeLock set to " + aeLock);
      }

      // TODO: Don't add control.aeLock to availableRequestKeys if it's not supported
    }

    // control.aeMode, flash.mode
    mapAeAndFlashMode(request, /*out*/ params);

    // control.afMode
    {
      int afMode =
          ParamsUtils.getOrDefault(request, CONTROL_AF_MODE, /*defaultValue*/ CONTROL_AF_MODE_OFF);
      String focusMode =
          LegacyMetadataMapper.convertAfModeToLegacy(afMode, params.getSupportedFocusModes());

      if (focusMode != null) {
        params.setFocusMode(focusMode);
      }

      if (VERBOSE) {
        Log.v(
            TAG, "convertRequestToMetadata - control.afMode " + afMode + " mapped to " + focusMode);
      }
    }

    // control.awbMode
    {
      Integer awbMode =
          getIfSupported(
              request,
              CONTROL_AWB_MODE,
              /*defaultValue*/ CONTROL_AWB_MODE_AUTO,
              params.getSupportedWhiteBalance() != null,
              /*allowedValue*/ CONTROL_AWB_MODE_AUTO);

      String whiteBalanceMode = null;
      if (awbMode != null) { // null iff AWB is not supported by camera1 api
        whiteBalanceMode = convertAwbModeToLegacy(awbMode);
        params.setWhiteBalance(whiteBalanceMode);
      }

      if (VERBOSE) {
        Log.v(
            TAG,
            "convertRequestToMetadata - control.awbMode "
                + awbMode
                + " mapped to "
                + whiteBalanceMode);
      }
    }

    // control.awbLock
    {
      Boolean awbLock =
          getIfSupported(
              request,
              CONTROL_AWB_LOCK, /*defaultValue*/
              false,
              params.isAutoWhiteBalanceLockSupported(),
              /*allowedValue*/ false);

      if (awbLock != null) {
        params.setAutoWhiteBalanceLock(awbLock);
      }

      // TODO: Don't add control.awbLock to availableRequestKeys if it's not supported
    }

    // control.captureIntent
    {
      int captureIntent =
          ParamsUtils.getOrDefault(
              request, CONTROL_CAPTURE_INTENT, /*defaultValue*/ CONTROL_CAPTURE_INTENT_PREVIEW);

      captureIntent = filterSupportedCaptureIntent(captureIntent);

      params.setRecordingHint(
          captureIntent == CONTROL_CAPTURE_INTENT_VIDEO_RECORD
              || captureIntent == CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT);
    }

    // control.videoStabilizationMode
    {
      Integer stabMode =
          getIfSupported(
              request,
              CONTROL_VIDEO_STABILIZATION_MODE,
              /*defaultValue*/ CONTROL_VIDEO_STABILIZATION_MODE_OFF,
              params.isVideoStabilizationSupported(),
              /*allowedValue*/ CONTROL_VIDEO_STABILIZATION_MODE_OFF);

      if (stabMode != null) {
        params.setVideoStabilization(stabMode == CONTROL_VIDEO_STABILIZATION_MODE_ON);
      }
    }

    // lens.focusDistance
    {
      boolean infinityFocusSupported =
          ListUtils.listContains(params.getSupportedFocusModes(), Parameters.FOCUS_MODE_INFINITY);
      Float focusDistance =
          getIfSupported(
              request,
              LENS_FOCUS_DISTANCE,
              /*defaultValue*/ 0f,
              infinityFocusSupported, /*allowedValue*/
              0f);

      if (focusDistance == null || focusDistance != 0f) {
        Log.w(
            TAG,
            "convertRequestToMetadata - Ignoring android.lens.focusDistance "
                + infinityFocusSupported
                + ", only 0.0f is supported");
      }
    }

    // control.sceneMode, control.mode
    {
      // TODO: Map FACE_PRIORITY scene mode to face detection.

      if (params.getSupportedSceneModes() != null) {
        int controlMode =
            ParamsUtils.getOrDefault(request, CONTROL_MODE, /*defaultValue*/ CONTROL_MODE_AUTO);
        String modeToSet;
        switch (controlMode) {
          case CONTROL_MODE_USE_SCENE_MODE:
            {
              int sceneMode =
                  ParamsUtils.getOrDefault(
                      request, CONTROL_SCENE_MODE, /*defaultValue*/ CONTROL_SCENE_MODE_DISABLED);
              String legacySceneMode = LegacyMetadataMapper.convertSceneModeToLegacy(sceneMode);
              if (legacySceneMode != null) {
                modeToSet = legacySceneMode;
              } else {
                modeToSet = Parameters.SCENE_MODE_AUTO;
                Log.w(TAG, "Skipping unknown requested scene mode: " + sceneMode);
              }
              break;
            }
          case CONTROL_MODE_AUTO:
            {
              modeToSet = Parameters.SCENE_MODE_AUTO;
              break;
            }
          default:
            {
              Log.w(TAG, "Control mode " + controlMode + " is unsupported, defaulting to AUTO");
              modeToSet = Parameters.SCENE_MODE_AUTO;
            }
        }
        params.setSceneMode(modeToSet);
      }
    }

    // control.effectMode
    {
      if (params.getSupportedColorEffects() != null) {
        int effectMode =
            ParamsUtils.getOrDefault(
                request, CONTROL_EFFECT_MODE, /*defaultValue*/ CONTROL_EFFECT_MODE_OFF);
        String legacyEffectMode = LegacyMetadataMapper.convertEffectModeToLegacy(effectMode);
        if (legacyEffectMode != null) {
          params.setColorEffect(legacyEffectMode);
        } else {
          params.setColorEffect(Parameters.EFFECT_NONE);
          Log.w(TAG, "Skipping unknown requested effect mode: " + effectMode);
        }
      }
    }

    /*
     * sensor
     */

    // sensor.testPattern
    {
      int testPatternMode =
          ParamsUtils.getOrDefault(
              request, SENSOR_TEST_PATTERN_MODE, /*defaultValue*/ SENSOR_TEST_PATTERN_MODE_OFF);
      if (testPatternMode != SENSOR_TEST_PATTERN_MODE_OFF) {
        Log.w(
            TAG,
            "convertRequestToMetadata - ignoring sensor.testPatternMode "
                + testPatternMode
                + "; only OFF is supported");
      }
    }

    /*
     * jpeg.*
     */

    // jpeg.gpsLocation
    {
      Location location = request.get(JPEG_GPS_LOCATION);
      if (location != null) {
        if (checkForCompleteGpsData(location)) {
          params.setGpsAltitude(location.getAltitude());
          params.setGpsLatitude(location.getLatitude());
          params.setGpsLongitude(location.getLongitude());
          params.setGpsProcessingMethod(location.getProvider().toUpperCase());
          params.setGpsTimestamp(location.getTime());
        } else {
          Log.w(TAG, "Incomplete GPS parameters provided in location " + location);
        }
      } else {
        params.removeGpsData();
      }
    }

    // jpeg.orientation
    {
      Integer orientation = request.get(CaptureRequest.JPEG_ORIENTATION);
      params.setRotation(
          ParamsUtils.getOrDefault(
              request, JPEG_ORIENTATION, (orientation == null) ? 0 : orientation));
    }

    // jpeg.quality
    {
      params.setJpegQuality(
          0xFF & ParamsUtils.getOrDefault(request, JPEG_QUALITY, DEFAULT_JPEG_QUALITY));
    }

    // jpeg.thumbnailQuality
    {
      params.setJpegThumbnailQuality(
          0xFF & ParamsUtils.getOrDefault(request, JPEG_THUMBNAIL_QUALITY, DEFAULT_JPEG_QUALITY));
    }

    // jpeg.thumbnailSize
    {
      List<Camera.Size> sizes = params.getSupportedJpegThumbnailSizes();

      if (sizes != null && sizes.size() > 0) {
        Size s = request.get(JPEG_THUMBNAIL_SIZE);
        boolean invalidSize =
            (s == null) ? false : !ParameterUtils.containsSize(sizes, s.getWidth(), s.getHeight());
        if (invalidSize) {
          Log.w(TAG, "Invalid JPEG thumbnail size set " + s + ", skipping thumbnail...");
        }
        if (s == null || invalidSize) {
          // (0,0) = "no thumbnail" in Camera API 1
          params.setJpegThumbnailSize(/*width*/ 0, /*height*/ 0);
        } else {
          params.setJpegThumbnailSize(s.getWidth(), s.getHeight());
        }
      }
    }

    /*
     * noiseReduction.*
     */
    // noiseReduction.mode
    {
      int mode =
          ParamsUtils.getOrDefault(
              request, NOISE_REDUCTION_MODE, /*defaultValue*/ NOISE_REDUCTION_MODE_FAST);

      if (mode != NOISE_REDUCTION_MODE_FAST) {
        Log.w(
            TAG,
            "convertRequestToMetadata - Ignoring unsupported " + "noiseReduction.mode = " + mode);
      }
    }
  }