code: package freed.cam.apis.featuredetector;
  
  import android.content.Context;
  import android.graphics.ImageFormat;
  import android.hardware.camera2.CameraAccessException;
  import android.hardware.camera2.CameraCharacteristics;
  import android.hardware.camera2.CameraManager;
  import android.hardware.camera2.CaptureRequest;
  import android.hardware.camera2.CaptureResult;
  import android.hardware.camera2.params.StreamConfigurationMap;
  import android.os.Build;
  
  import java.lang.reflect.InvocationTargetException;
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.HashSet;
  import java.util.List;
  
  import camera2_hidden_keys.VendorKeyParser;
  import camera2_hidden_keys.qcom.CameraCharacteristicsQcom;
  import freed.FreedApplication;
  import freed.cam.apis.featuredetector.camera2.AeMeteringModeDetector;
  import freed.cam.apis.featuredetector.camera2.AeTargetFpsDetector;
  import freed.cam.apis.featuredetector.camera2.AntiBadindingModeDetector;
  import freed.cam.apis.featuredetector.camera2.ApertureDetector;
  import freed.cam.apis.featuredetector.camera2.AutoExposureModeDetector;
  import freed.cam.apis.featuredetector.camera2.AutoFocusModeDetector;
  import freed.cam.apis.featuredetector.camera2.AwbModesDetector;
  import freed.cam.apis.featuredetector.camera2.BaseParameter2Detector;
  import freed.cam.apis.featuredetector.camera2.CameraControlModeDetector;
  import freed.cam.apis.featuredetector.camera2.ColorCorrectionModeDetector;
  import freed.cam.apis.featuredetector.camera2.ColorModeDetector;
  import freed.cam.apis.featuredetector.camera2.DenoisParameterDetector;
  import freed.cam.apis.featuredetector.camera2.DistortionCorrectionDetector;
  import freed.cam.apis.featuredetector.camera2.EdgeModeDetector;
  import freed.cam.apis.featuredetector.camera2.EvDetector;
  import freed.cam.apis.featuredetector.camera2.ExposureTimeDetector;
  import freed.cam.apis.featuredetector.camera2.FaceModeDetector;
  import freed.cam.apis.featuredetector.camera2.FlashDetector;
  import freed.cam.apis.featuredetector.camera2.HotPixelModeDetector;
  import freed.cam.apis.featuredetector.camera2.IsoDetector;
  import freed.cam.apis.featuredetector.camera2.ManualFocusDetector;
  import freed.cam.apis.featuredetector.camera2.OisDetector;
  import freed.cam.apis.featuredetector.camera2.PictureFormatDetector;
  import freed.cam.apis.featuredetector.camera2.PictureSizeDetector;
  import freed.cam.apis.featuredetector.camera2.PostRawSensitivityBoostDetector;
  import freed.cam.apis.featuredetector.camera2.SaturationDetector;
  import freed.cam.apis.featuredetector.camera2.SceneModeDetector;
  import freed.cam.apis.featuredetector.camera2.ShadingModesDetector;
  import freed.cam.apis.featuredetector.camera2.SharpnessDetector;
  import freed.cam.apis.featuredetector.camera2.ToneMapModesDetector;
  import freed.cam.apis.featuredetector.camera2.VendorKeyDetector;
  import freed.cam.apis.featuredetector.camera2.VideoMediaProfilesDetector;
  import freed.cam.apis.featuredetector.camera2.VideoStabilizationModeDetector;
  import freed.cam.apis.featuredetector.camera2.debug.DumpQCFA;
  import freed.cam.apis.featuredetector.camera2.debug.DumpScalerStreamConfigurationMap;
  import freed.cam.apis.featuredetector.camera2.huawei.DualPrimaryCameraDetector;
  import freed.cam.apis.featuredetector.camera2.huawei.IsoExposureTimeDetector;
  import freed.cam.apis.featuredetector.camera2.huawei.Raw12bitDetector;
  import freed.cam.apis.featuredetector.camera2.huawei.SecondarySensorSizeDetector;
  import freed.cam.apis.featuredetector.camera2.huawei.WhitebalanceRangeDetector;
  import freed.cam.apis.featuredetector.camera2.qcom.HistogramSupportedDetector;
  import freed.cam.apis.featuredetector.camera2.qcom.MFNRDetector;
  import freed.cam.apis.featuredetector.camera2.qcom.QcomAeDetector;
  import freed.cam.apis.featuredetector.camera2.qcom.VideoHdr10Detector;
  import freed.cam.apis.featuredetector.camera2.xiaomi.ArcDistortionDetector;
  import freed.cam.apis.featuredetector.camera2.xiaomi.ProVideoLogDetector;
  import freed.cam.apis.featuredetector.camera2.xiaomi.SuperLowLightRawDetector;
  import freed.cam.apis.featuredetector.camera2.xiaomi.VideoRecordControl;
  import freed.cam.apis.featuredetector.camera2.xiaomi.XiaomiMfnrDetector;
  import freed.cam.ui.videoprofileeditor.MediaCodecInfoParser;
  import freed.settings.SettingKeys;
  import freed.settings.SettingsManager;
  import freed.utils.Log;
  
  
  /**
   * Created by troop on 23.01.2017.
   */
  
  @androidx.annotation.RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
  public class Camera2FeatureDetectorTask extends AbstractFeatureDetectorTask {
  
      private final String TAG = Camera2FeatureDetectorTask.class.getSimpleName();
      boolean hasCamera2Features;
  
      public int hwlvl = CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY;
      private CameraManager manager;
  
      public Camera2FeatureDetectorTask() {
          super();
      }
  
      @Override
      public List<Class> createParametersToCheckList() {
          List<Class> parameter2Detectors = new ArrayList<>();
          parameter2Detectors.add(FlashDetector.class);
          parameter2Detectors.add(SceneModeDetector.class);
          parameter2Detectors.add(AntiBadindingModeDetector.class);
          parameter2Detectors.add(ColorModeDetector.class);
          parameter2Detectors.add(EdgeModeDetector.class);
          parameter2Detectors.add(OisDetector.class);
          parameter2Detectors.add(AutoFocusModeDetector.class);
          parameter2Detectors.add(HotPixelModeDetector.class);
          parameter2Detectors.add(VideoStabilizationModeDetector.class);
          parameter2Detectors.add(DenoisParameterDetector.class);
          parameter2Detectors.add(PictureFormatDetector.class);
          parameter2Detectors.add(DistortionCorrectionDetector.class);
          parameter2Detectors.add(FaceModeDetector.class);
          parameter2Detectors.add(ArcDistortionDetector.class);
          parameter2Detectors.add(SuperLowLightRawDetector.class);
          parameter2Detectors.add(PictureSizeDetector.class);
          //call this after PictureSizes got detected. it depends on the picturesizes
          parameter2Detectors.add(VideoMediaProfilesDetector.class);
          parameter2Detectors.add(AutoExposureModeDetector.class);
          parameter2Detectors.add(ColorCorrectionModeDetector.class);
          parameter2Detectors.add(ToneMapModesDetector.class);
          parameter2Detectors.add(ShadingModesDetector.class);
          parameter2Detectors.add(AwbModesDetector.class);
          parameter2Detectors.add(CameraControlModeDetector.class);
          parameter2Detectors.add(AeTargetFpsDetector.class);
          parameter2Detectors.add(AeMeteringModeDetector.class);
          //N
          parameter2Detectors.add(PostRawSensitivityBoostDetector.class);
  
          //qcom
          parameter2Detectors.add(VideoHdr10Detector.class);
          parameter2Detectors.add(HistogramSupportedDetector.class);
          parameter2Detectors.add(MFNRDetector.class);
          //run this bevor exposuretime get detected
          parameter2Detectors.add(QcomAeDetector.class);
          //manuals
          parameter2Detectors.add(ApertureDetector.class);
          parameter2Detectors.add(EvDetector.class);
          parameter2Detectors.add(ExposureTimeDetector.class);
          parameter2Detectors.add(IsoDetector.class);
          parameter2Detectors.add(ManualFocusDetector.class);
          parameter2Detectors.add(SharpnessDetector.class);
          parameter2Detectors.add(SaturationDetector.class);
          //xiaomi
          parameter2Detectors.add(VideoRecordControl.class);
          parameter2Detectors.add(ProVideoLogDetector.class);
          parameter2Detectors.add(XiaomiMfnrDetector.class);
  
          //huawei
          parameter2Detectors.add(DualPrimaryCameraDetector.class);
          parameter2Detectors.add(IsoExposureTimeDetector.class);
          parameter2Detectors.add(Raw12bitDetector.class);
          parameter2Detectors.add(SecondarySensorSizeDetector.class);
          parameter2Detectors.add(WhitebalanceRangeDetector.class);
  
          //debug
          parameter2Detectors.add(DumpQCFA.class);
          parameter2Detectors.add(DumpScalerStreamConfigurationMap.class);
  
  
  
          return parameter2Detectors;
      }
  
      @Override
      public void preDetect() {
          new MediaCodecInfoParser().logMediaCodecInfos();
  
          settingsManager.setCamApi(SettingsManager.API_2);
          manager = (CameraManager) FreedApplication.getContext().getSystemService(Context.CAMERA_SERVICE);
      }
  
      @Override
      public List<String> findCameraIDs() {
          List<String> cameraids =new ArrayList<>();
          findCameraIds(manager, cameraids);
          return cameraids;
      }
  
      @Override
      public void checkCameraID(int id, List<String> cameraids, List<Class> parametersToDetect) {
          super.checkCameraID(id,cameraids,parametersToDetect);
          CameraCharacteristics characteristics = null;
          try {
              characteristics = manager.getCameraCharacteristics(cameraids.get(id));
          } catch (CameraAccessException e) {
              Log.WriteEx(e);
          }
          if (characteristics == null) {
              Log.e(TAG, "Failed to get Characteristics for camera id:" + id);
              return;
          }
          boolean front = characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT;
          settingsManager.setIsFrontCamera(front);
          VendorKeyParser vendorKeyParser = new VendorKeyParser();
          HashSet<String> vendorkeys = null;
          try {
              vendorKeyParser.readVendorKeys(characteristics,CaptureRequest.Key.class);
              vendorkeys = vendorKeyParser.getRequests();
              /*VendorKeyTestLog vendorKeyTestLog = new VendorKeyTestLog(vendorKeyParser,characteristics,null,null);
              vendorKeyTestLog.testKeys();*/
          } catch (NoSuchMethodException e) {
              e.printStackTrace();
          } catch (IllegalAccessException e) {
              e.printStackTrace();
          } catch (InvocationTargetException e) {
              e.printStackTrace();
          }
  
          hwlvl = characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
          //check first if a already checked cam have camera2features and if its now the front cam that dont have a camera2feature.
          //in that case set it to true
          //else it would override the already detected featureset from last cam and disable api2
          if (settingsManager.hasCamera2Features() && front) {
              hasCamera2Features = true;
              Log.d(TAG,"Front cam has no camera2 featureset, try to find supported things anyway");
          }
          else
              hasCamera2Features = true;
          settingsManager.setHasCamera2Features(hasCamera2Features);
  
          if (hasCamera2Features) {
  
              for (int i = 0; i < parametersToDetect.size(); i++) {
                  try {
                      BaseParameter2Detector parameter2Detector = getInstance(parametersToDetect.get(i));
                      if (parameter2Detector instanceof VendorKeyDetector) {
                          ((VendorKeyDetector) parameter2Detector).checkIfVendorKeyIsSupported(vendorkeys);
                      } else
                          parameter2Detector.checkIfSupported(characteristics);
                  } catch (NoSuchMethodException e) {
                      e.printStackTrace();
                  } catch (IllegalAccessException e) {
                      e.printStackTrace();
                  } catch (InvocationTargetException e) {
                      e.printStackTrace();
                  } catch (InstantiationException e) {
                      e.printStackTrace();
                  }
              }
  
              if (settingsManager.get(SettingKeys.M_FOCUS).isSupported()) {
                  settingsManager.get(SettingKeys.ZOOM_ON_MANUALFOCUS).setIsSupported(true);
                  settingsManager.get(SettingKeys.ZOOM_ON_MANUALFOCUS).set(true);
                  settingsManager.get(SettingKeys.ZOOM_ON_MANUALFOCUS_ZOOMFACTOR).setIsSupported(true);
                  String[] zoom = new String[]{"0", "10", "20", "30", "40", "50", "60", "70", "80", "90", "100"};
                  settingsManager.get(SettingKeys.ZOOM_ON_MANUALFOCUS_ZOOMFACTOR).setValues(zoom);
                  settingsManager.get(SettingKeys.ZOOM_ON_MANUALFOCUS_ZOOMFACTOR).set("50");
                  settingsManager.get(SettingKeys.ZOOM_ON_MANUALFOCUS_ZOOMDURATION).setIsSupported(true);
                  String[] duration = new String[]{"0", "1", "2", "3", "4", "5"};
                  settingsManager.get(SettingKeys.ZOOM_ON_MANUALFOCUS_ZOOMDURATION).setValues(duration);
                  settingsManager.get(SettingKeys.ZOOM_ON_MANUALFOCUS_ZOOMDURATION).set("1");
              }
  
              String[] templates = new String[]{"Preview","StillCapture","Record","VideoSnapshot","ZeroShutterLag","Manual"};
              settingsManager.get(SettingKeys.PREVIEW_TEMPLATE).setIsSupported(true);
              settingsManager.get(SettingKeys.PREVIEW_TEMPLATE).setValues(templates);
              settingsManager.get(SettingKeys.PREVIEW_TEMPLATE).set(templates[0]);
  
              settingsManager.get(SettingKeys.CAPTURE_TEMPLATE).setIsSupported(true);
              settingsManager.get(SettingKeys.CAPTURE_TEMPLATE).setValues(templates);
              settingsManager.get(SettingKeys.CAPTURE_TEMPLATE).set(templates[1]);
          }
      }
  
      @Override
      public void postDetect() {
          settingsManager.SetCurrentCamera(0);
          if (!hasCamera2Features || hwlvl == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY) {
              settingsManager.setCamApi(SettingsManager.API_1);
          }
      }
  
      public static boolean isKeySupported(HashSet<String> vendorkeys, CaptureRequest.Key key)
      {
          return vendorkeys != null && vendorkeys.contains(key.getName());
      }
  
      public static boolean isKeySupported(HashSet<String> vendorkeys, CameraCharacteristics.Key key)
      {
          return vendorkeys != null && vendorkeys.contains(key.getName());
      }
  
      public static boolean isKeySupported(HashSet<String> vendorkeys, CaptureResult.Key key)
      {
          return vendorkeys != null && vendorkeys.contains(key.getName());
      }
  
      private void findCameraIds(CameraManager manager, List<String> cameraids) {
          List<String> allcameraids = new ArrayList<>();
          List<String> nonlogicids = new ArrayList<>();
          String[] reportedids = null;
          try {
              reportedids = manager.getCameraIdList();
          } catch (CameraAccessException e) {
              e.printStackTrace();
          }
          for (int i = 0; i< 200; i++)
          {
              try {
                  CameraCharacteristics characteristics = manager.getCameraCharacteristics(String.valueOf(i));
  
                  if (characteristics != null) {
                      boolean raw = false;
                      boolean yuv = false;
                      boolean jpeg = false;
                      boolean logical = false;
                      allcameraids.add(String.valueOf(i));
                      StreamConfigurationMap smap = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
                      int[] outputformats =  smap.getOutputFormats();
                      try {
                          if(characteristics.get(CameraCharacteristicsQcom.is_logical_camera) != null) {
                              int logical_b = (int) characteristics.get(CameraCharacteristicsQcom.is_logical_camera);
                              Log.d(TAG, "logical id = " + logical_b);
                              if (logical_b > 5)
                                  logical = true;
                          }
                      }
                      catch (IllegalArgumentException ex)
                      {
                          Log.d(TAG, "CameraCharacteristicsQcom.is_logical_camera not supported");
                      }
                      catch (NullPointerException ex)
                      {
                          Log.d(TAG, "CameraCharacteristicsQcom.is_logical_camera not supported");
                      }
                      catch (Exception ex)
                      {
                          Log.d(TAG, "CameraCharacteristicsQcom.is_logical_camera not supported");
                      }
  
                      for(int outformat : outputformats)
                      {
                          switch (outformat)
                          {
                              case ImageFormat.RAW_SENSOR:
                              case ImageFormat.RAW10:
                              case ImageFormat.RAW12:
                                  raw = true;
                                  break;
                              case ImageFormat.JPEG:
                                  jpeg =true;
                                  break;
                                  case ImageFormat.YUV_420_888:
                                      yuv = true;
                                      break;
                          }
                      }
                      if (yuv && raw && jpeg && !logical)
                          nonlogicids.add(String.valueOf(i));
                  }
              }
              catch (IllegalArgumentException ex)
              {
              }
              catch (CameraAccessException ex)
              {
              }
              catch (Exception ex)
              {
              }
          }
          if (nonlogicids.size() >= reportedids.length || allcameraids.size() >= reportedids.length) {
              if (nonlogicids.size() == 0)
                  cameraids.addAll(allcameraids);
              else
                  cameraids.addAll(nonlogicids);
          }
          else
              cameraids.addAll(Arrays.asList(reportedids));
  
      }
  }
  