依据Android P版本剖析

createCaptureRequest时序图:

依据Android Camera2_preview&capture_request流程剖析

一般情况下,openCamera()之后会履行回调办法Onopened(),在这个办法中,会履行createCaptureSession(),同时也会履行createCaptureRequest(),都是由CameraDeviceImpl实现的。

1 CameraDeviceImpl.createCaptureRequest()

@Override
public CaptureRequest.Builder createCaptureRequest(int templateType)
    throws CameraAccessException {
  synchronized(mInterfaceLock) {
    checkIfCameraClosedOrInError();
​
    CameraMetadataNative templatedRequest = null;
​
    // 会依据传入的templateType创立对应的CameraMetadata数据,其间封装了对应Camera1中需求装备的setParameter参数
    templatedRequest = mRemoteDevice.createDefaultRequest(templateType);
​
    // If app target SDK is older than O, or it's not a still capture template, enableZsl
    // must be false in the default request.
    if (mAppTargetSdkVersion < Build.VERSION_CODES.O ||
        templateType != TEMPLATE_STILL_CAPTURE) {
      overrideEnableZsl(templatedRequest, false);
     }
​
    // 在创立Builder目标的时分,传入的参数为CameraMetadataNative目标
    CaptureRequest.Builder builder = new CaptureRequest.Builder(
        templatedRequest, /*reprocess*/false, CameraCaptureSession.SESSION_ID_NONE,
        getId(), /*physicalCameraIdSet*/ null);
​
    return builder;
   }
}

依据templateType创立对应的新的Capture request,参数templateType代表了恳求类型,例如templateType = CameraDevice.TEMPLATE_PREVIEW,回来类型为CaptureRequest.Builder,为建造者模型,所以需求经过build()办法创立真实的request;

参数templateType代表了恳求类型,恳求类型一共分为六种:

  • TEMPLATE_PREVIEW : 创立预览的恳求
  • TEMPLATE_STILL_CAPTURE: 创立一个适合于静态图画捕获的恳求,图画质量优先于帧速率
  • TEMPLATE_RECORD : 创立视频录制的恳求
  • TEMPLATE_VIDEO_SNAPSHOT : 创立视视频录制时截屏的恳求
  • TEMPLATE_ZERO_SHUTTER_LAG : 创立一个适用于零快门延迟的恳求。在不影响预览帧率的情况下最大化图画质量
  • TEMPLATE_MANUAL : 创立一个基本捕获恳求,这种恳求中一切的主动控制都是禁用的(主动曝光,主动白平衡、主动焦点)

1.1 mRemoteDevice.createDefaultRequest(templateType)

由于mRemoteDevice的类型为ICameraDeviceUser,在Framework中表现为CameraDeviceClient,所以直接剖析CameraDeviceClient::createDefaultRequest()办法:

// Create a request object from a template.
binder::Status CameraDeviceClient::createDefaultRequest(int templateId,
    /*out*/
    hardware::camera2::impl::CameraMetadataNative* request)
{
  ATRACE_CALL();
  ALOGV("%s (templateId = 0x%x)", __FUNCTION__, templateId);
​
  binder::Status res;
  if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
​
  Mutex::Autolock icl(mBinderSerializationLock);
​
  if (!mDevice.get()) {
    return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
   }
​
  CameraMetadata metadata;
  status_t err;
  if ( (err = mDevice->createDefaultRequest(templateId, &metadata) ) == OK &&
    request != NULL) {
​
    // 保存CameraMetadata目标的camera_metadata_t变量
    request->swap(metadata);
   } else if (err == BAD_VALUE) {
    res = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
        "Camera %s: Template ID %d is invalid or not supported: %s (%d)",
        mCameraIdStr.string(), templateId, strerror(-err), err);
​
   } else {
    res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
        "Camera %s: Error creating default request for template %d: %s (%d)",
        mCameraIdStr.string(), templateId, strerror(-err), err);
   }
  return res;
}

调用了Camera3Device::createDefaultRequest()办法;

status_t Camera3Device::createDefaultRequest(int templateId,
    CameraMetadata *request) {
  ATRACE_CALL();
  ALOGV("%s: for template %d", __FUNCTION__, templateId);
​
  if (templateId <= 0 || templateId >= CAMERA3_TEMPLATE_COUNT) {
    android_errorWriteWithInfoLog(CameraService::SN_EVENT_LOG_ID, "26866110",
        IPCThreadState::self()->getCallingUid(), nullptr, 0);
    return BAD_VALUE;
   }
​
  Mutex::Autolock il(mInterfaceLock);
​
   {
    Mutex::Autolock l(mLock);
    switch (mStatus) {
      case STATUS_ERROR:
        CLOGE("Device has encountered a serious error");
        return INVALID_OPERATION;
      case STATUS_UNINITIALIZED:
        CLOGE("Device is not initialized!");
        return INVALID_OPERATION;
      case STATUS_UNCONFIGURED:
      case STATUS_CONFIGURED:
      case STATUS_ACTIVE:
        // OK
        break;
      default:
        SET_ERR_L("Unexpected status: %d", mStatus);
        return INVALID_OPERATION;
     }
​
    if (!mRequestTemplateCache[templateId].isEmpty()) {
      *request = mRequestTemplateCache[templateId];
      mLastTemplateId = templateId;
      return OK;
     }
   }
​
  camera_metadata_t *rawRequest;
  status_t res = mInterface->constructDefaultRequestSettings(
       (camera3_request_template_t) templateId, &rawRequest);
​
   {
    Mutex::Autolock l(mLock);
    if (res == BAD_VALUE) {
      ALOGI("%s: template %d is not supported on this camera device",
         __FUNCTION__, templateId);
      return res;
     } else if (res != OK) {
      CLOGE("Unable to construct request template %d: %s (%d)",
          templateId, strerror(-res), res);
      return res;
     }
​
    set_camera_metadata_vendor_id(rawRequest, mVendorTagId);
    // 在一块逻辑中,将创立好的rawRequest保存到mRequestTemplateCache中,即保存到request(mRequestTemplateCache类型)中,这样就创立好了对应的
    mRequestTemplateCache[templateId].acquire(rawRequest);
​
    *request = mRequestTemplateCache[templateId];
    mLastTemplateId = templateId;
   }
  return OK;
}

创立CameraMetadataNative目标,内在是创立CameraMetadata目标(CameraMetadata.cpp),对CameraMetadataNative目标的操作本质上都是操作CameraMetadata目标,即camera_metadata_t * metadata;

至此咱们就创立了CameraMetadata目标,其办理着一块buffer,buffer中保存的是某个场景预览、录像或摄影的默认metadata;

1.2 new CaptureRequest.Builder

    CaptureRequest.Builder builder = new CaptureRequest.Builder(
        templatedRequest, /*reprocess*/false, CameraCaptureSession.SESSION_ID_NONE,
        getId(), /*physicalCameraIdSet*/ null);
public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>
    implements Parcelable {
  
  private final ArraySet<Surface> mSurfaceSet = new ArraySet<Surface>();
  
  /**
   * Clone from source capture request.
   *
   * Used by the Builder to create an immutable copy.
   */
  @SuppressWarnings("unchecked")
  private CaptureRequest(CaptureRequest source) {
    mLogicalCameraId = new String(source.mLogicalCameraId);
    for (Map.Entry<String, CameraMetadataNative> entry :
        source.mPhysicalCameraSettings.entrySet()) {
      mPhysicalCameraSettings.put(new String(entry.getKey()),
          new CameraMetadataNative(entry.getValue()));
     }
    mLogicalCameraSettings = mPhysicalCameraSettings.get(mLogicalCameraId);
    setNativeInstance(mLogicalCameraSettings);
    mSurfaceSet.addAll(source.mSurfaceSet);
    mIsReprocess = source.mIsReprocess;
    mIsPartOfCHSRequestList = source.mIsPartOfCHSRequestList;
    mReprocessableSessionId = source.mReprocessableSessionId;
    mUserTag = source.mUserTag;
   }
  
  /**
   * Take ownership of passed-in settings.
   *
   * Used by the Builder to create a mutable CaptureRequest.
   *
   * @param settings Settings for this capture request.
   * @param isReprocess Indicates whether to create a reprocess capture request. {@code true}
   *           to create a reprocess capture request. {@code false} to create a regular
   *           capture request.
   * @param reprocessableSessionId The ID of the camera capture session this capture is created
   *                for. This is used to validate if the application submits a
   *                reprocess capture request to the same session where
   *                the {@link TotalCaptureResult}, used to create the reprocess
   *                capture, came from.
   * @param logicalCameraId Camera Id of the actively open camera that instantiates the
   *             Builder.
   *
   * @param physicalCameraIdSet A set of physical camera ids that can be used to customize
   *               the request for a specific physical camera.
   *
   * @throws IllegalArgumentException If creating a reprocess capture request with an invalid
   *                  reprocessableSessionId, or multiple physical cameras.
   *
   * @see CameraDevice#createReprocessCaptureRequest
   */
  private CaptureRequest(CameraMetadataNative settings, boolean isReprocess,
      int reprocessableSessionId, String logicalCameraId, Set<String> physicalCameraIdSet) {
​
    // isReprocess这个值在new CaptureRequest.Builder的时分传入的是false,所以该流程不履行
    if ((physicalCameraIdSet != null) && isReprocess) {
      throw new IllegalArgumentException("Create a reprocess capture request with " +
          "with more than one physical camera is not supported!");
     }
​
    mLogicalCameraId = logicalCameraId;
    mLogicalCameraSettings = CameraMetadataNative.move(settings);
    mPhysicalCameraSettings.put(mLogicalCameraId, mLogicalCameraSettings);
​
    // physicalCameraIdSet CaptureRequest.Builder的时分传入的是null,所以该流程不履行
    if (physicalCameraIdSet != null) {
      for (String physicalId : physicalCameraIdSet) {
        mPhysicalCameraSettings.put(physicalId, new CameraMetadataNative(
              mLogicalCameraSettings));
       }
     }
​
    setNativeInstance(mLogicalCameraSettings);
    mIsReprocess = isReprocess;
    if (isReprocess) {
      if (reprocessableSessionId == CameraCaptureSession.SESSION_ID_NONE) {
        throw new IllegalArgumentException("Create a reprocess capture request with an " +
            "invalid session ID: " + reprocessableSessionId);
       }
      mReprocessableSessionId = reprocessableSessionId;
     } else {
      mReprocessableSessionId = CameraCaptureSession.SESSION_ID_NONE;
     }
   }
  
  /**
   * A builder for capture requests.
   *
   * <p>To obtain a builder instance, use the
   * {@link CameraDevice#createCaptureRequest} method, which initializes the
   * request fields to one of the templates defined in {@link CameraDevice}.
   *
   * @see CameraDevice#createCaptureRequest
   * @see CameraDevice#TEMPLATE_PREVIEW
   * @see CameraDevice#TEMPLATE_RECORD
   * @see CameraDevice#TEMPLATE_STILL_CAPTURE
   * @see CameraDevice#TEMPLATE_VIDEO_SNAPSHOT
   * @see CameraDevice#TEMPLATE_MANUAL
   */
  public final static class Builder {
​
    private final CaptureRequest mRequest;
​
    /**
     * Initialize the builder using the template; the request takes
     * ownership of the template.
     *
     * @param template Template settings for this capture request.
     * @param reprocess Indicates whether to create a reprocess capture request. {@code true}
     *          to create a reprocess capture request. {@code false} to create a regular
     *          capture request.
     * @param reprocessableSessionId The ID of the camera capture session this capture is
     *                created for. This is used to validate if the application
     *                submits a reprocess capture request to the same session
     *                where the {@link TotalCaptureResult}, used to create the
     *                reprocess capture, came from.
     * @param logicalCameraId Camera Id of the actively open camera that instantiates the
     *             Builder.
     * @param physicalCameraIdSet A set of physical camera ids that can be used to customize
     *               the request for a specific physical camera.
     *
     * @throws IllegalArgumentException If creating a reprocess capture request with an invalid
     *                  reprocessableSessionId.
     * @hide
     */
    public Builder(CameraMetadataNative template, boolean reprocess,
        int reprocessableSessionId, String logicalCameraId,
        Set<String> physicalCameraIdSet) {
      mRequest = new CaptureRequest(template, reprocess, reprocessableSessionId,
          logicalCameraId, physicalCameraIdSet);
     }
    
    ……
    
    /**
     * Build a request using the current target Surfaces and settings.
     * <p>Note that, although it is possible to create a {@code CaptureRequest} with no target
     * {@link Surface}s, passing such a request into {@link CameraCaptureSession#capture},
     * {@link CameraCaptureSession#captureBurst},
     * {@link CameraCaptureSession#setRepeatingBurst}, or
     * {@link CameraCaptureSession#setRepeatingRequest} will cause that method to throw an
     * {@link IllegalArgumentException}.</p>
     *
     * @return A new capture request instance, ready for submission to the
     * camera device.
     */
    @NonNull
    public CaptureRequest build() {
      return new CaptureRequest(mRequest);
     }
    
    /**
     * <p>Add a surface to the list of targets for this request</p>
     *
     * <p>The Surface added must be one of the surfaces included in the most
     * recent call to {@link CameraDevice#createCaptureSession}, when the
     * request is given to the camera device.</p>
     *
     * <p>Adding a target more than once has no effect.</p>
     *
     * @param outputTarget Surface to use as an output target for this request
     */
    public void addTarget(@NonNull Surface outputTarget) {
      mRequest.mSurfaceSet.add(outputTarget);
     }
    
    ……
   }
}

最终createCaptureRequest()办法回来的便是CaptureRequest.Builder目标;

然后履行build()办法就能够创立一个CaptureRequest类型实例;

2 addTarget()

build()履行完成之后,紧接着会调用CaptureRequest.Builder.addTarget()办法;

public void addTarget(@NonNull Surface outputTarget) {
  mRequest.mSurfaceSet.add(outputTarget);
}

这个办法主要是用于承认哪些surface需求作为CaptureRequest.Builder的目标;

这个mSurfaceSet会在后续setRepeatingRequest()过程中与create session中绑定的SurfaceList进行一一对比;

3 setRepeatingRequest()

在createCaptureRequest()履行完成,同时createCaptureSession()也成功履行后,会履行onConfigured()回调办法,就能够在该回调办法中履行CameraCaptureSessionImpl.setRepeatingRequest()办法发送恳求;

一般情况下,createCaptureRequest()传入的参数为Preview,假如想在openCamera之后就开启preview画面的话,就需求履行setRepeatingRequest()办法,不然RequestThread判别没有request,所以不会上报camera数据;

@Override
public int setRepeatingRequest(CaptureRequest request, CaptureCallback callback,
                Handler handler) throws CameraAccessException {
  // 这个主要是对request进行判空和重复恳求异常处理
  checkRepeatingRequest(request);
​
  synchronized (mDeviceImpl.mInterfaceLock) {
    checkNotClosed();
​
    handler = checkHandler(handler, callback);
​
    if (DEBUG) {
      Log.v(TAG, mIdString + "setRepeatingRequest - request " + request + ", callback " +
          callback + " handler" + " " + handler);
     }
​
    return addPendingSequence(mDeviceImpl.setRepeatingRequest(request,
        createCaptureCallbackProxy(handler, callback), mDeviceExecutor));
   }
}

第一个参数request,这个便是经过build()办法创立的request,标识当时capture恳求的特点,是恳求一个camera还是多个camera,是否复用之前的恳求等;

第二个参数callback,这个是捕捉回调,这个可认为null;

public interface CaptureCallback {
  public static final int NO_FRAMES_CAPTURED = -1;
  public void onCaptureStarted(CameraDevice camera,
                 CaptureRequest request, long timestamp, long frameNumber);
  public void onCapturePartial(CameraDevice camera,
                 CaptureRequest request, CaptureResult result);
  public void onCaptureProgressed(CameraDevice camera,
                  CaptureRequest request, CaptureResult partialResult);
  public void onCaptureCompleted(CameraDevice camera,
                  CaptureRequest request, TotalCaptureResult result);
  public void onCaptureFailed(CameraDevice camera,
                CaptureRequest request, CaptureFailure failure);
  public void onCaptureSequenceCompleted(CameraDevice camera,
                      int sequenceId, long frameNumber);
  public void onCaptureSequenceAborted(CameraDevice camera,
                     int sequenceId);
  public void onCaptureBufferLost(CameraDevice camera,
                  CaptureRequest request, Surface target, long frameNumber);
}

第三个参数handler,这个和openCamera的handler是相同的,都是用于指定哪个线程需求履行callback;

private void checkRepeatingRequest(CaptureRequest request) {
  if (request == null) {
    throw new IllegalArgumentException("request must not be null");
   } else if (request.isReprocess()) {
    throw new IllegalArgumentException("repeating reprocess requests are not supported");
   }
}

最终回来addPendingSequence(),将本次调用时序加入到PendingSequence中;

/**
 * Notify the session that a pending capture sequence has just been queued.
 *
 * <p>During a shutdown/close, the session waits until all pending sessions are finished
 * before taking any further steps to shut down itself.</p>
 *
 * @see #finishPendingSequence
 */
private int addPendingSequence(int sequenceId) {
  mSequenceDrainer.taskStarted(sequenceId);
  return sequenceId;
}

其间在调用该办法的时分,传入的参数为mDeviceImpl.setRepeatingRequest(request, createCaptureCallbackProxy(handler, callback), mDeviceExecutor);

public int setRepeatingRequest(CaptureRequest request, CaptureCallback callback,
                Executor executor) throws CameraAccessException {
  List<CaptureRequest> requestList = new ArrayList<CaptureRequest>();
  requestList.add(request);
  return submitCaptureRequest(requestList, callback, executor, /*streaming*/true);
}

streaming = true是repeating的request,后面有用到;

将request加入到list中,然后submit request;

private int submitCaptureRequest(List<CaptureRequest> requestList, CaptureCallback callback,
                 Executor executor, boolean repeating) throws CameraAccessException {
​
  // Need a valid executor, or current thread needs to have a looper, if
  // callback is valid
  executor = checkExecutor(executor, callback);
​
  // Make sure that there all requests have at least 1 surface; all surfaces are non-null;
  // the surface isn't a physical stream surface for reprocessing request
  // 验证当时CaptureRequest列表中的request是否合理:中心便是验证与request绑定的Surface是否存在
  for (CaptureRequest request : requestList) {
    // request.getTargets():判别mSurfaceSet是否为空
    // public Collection<Surface> getTargets() {
    //   return Collections.unmodifiableCollection(mSurfaceSet);
    // }
    if (request.getTargets().isEmpty()) {
      throw new IllegalArgumentException(
          "Each request must have at least one Surface target");
     }
​
    for (Surface surface : request.getTargets()) {
      // 确保一切的request至少含有一个Surface,一切Surface非空
      if (surface == null) {
        throw new IllegalArgumentException("Null Surface targets are not allowed");
       }
​
      for (int i = 0; i < mConfiguredOutputs.size(); i++) {
        OutputConfiguration configuration = mConfiguredOutputs.valueAt(i);
        // 判别surface对应的request是否是重复恳求
        // public boolean isForPhysicalCamera() {
        //   return (mPhysicalCameraId != null);
        // }
        // 默认isForPhysicalCamera()回来成果为false,由于在封装surface成为configuration时,configuration目标的mPhysicalCameraId特点赋值为了null
        if (configuration.isForPhysicalCamera()
            && configuration.getSurfaces().contains(surface)) {
          // isReprocess 为 false,在界说Builder实例的时分传入的
          if (request.isReprocess()) {
            throw new IllegalArgumentException(
                "Reprocess request on physical stream is not allowed");
           }
         }
       }
     }
   }
​
  synchronized(mInterfaceLock) {
    checkIfCameraClosedOrInError();
    if (repeating) {
      stopRepeating();
     }
​
    // 一个实体类,用于界说成功提交捕获恳求时回来的状况信息,里面包含两个特点:mRequestId和mLastFrameNumber
    SubmitInfo requestInfo;
​
    // 将requestList转化为CaptureRequest数组
    CaptureRequest[] requestArray = requestList.toArray(new CaptureRequest[requestList.size()]);
    // 转化surface到streamIdx和surfaceIdx
    // Convert Surface to streamIdx and surfaceIdx
    for (CaptureRequest request : requestArray) {
      // 依据streamId转化surface
      request.convertSurfaceToStreamId(mConfiguredOutputs);
     }
​
    // 向底层发送恳求信息
    requestInfo = mRemoteDevice.submitRequestList(requestArray, repeating);
    if (DEBUG) {
      Log.v(TAG, "last frame number " + requestInfo.getLastFrameNumber());
     }
​
    for (CaptureRequest request : requestArray) {
      // 依据streamId康复surface
      request.recoverStreamIdToSurface();
     }
​
    if (callback != null) {
      mCaptureCallbackMap.put(requestInfo.getRequestId(),
          new CaptureCallbackHolder(
              callback, requestList, executor, repeating, mNextSessionId - 1));
     } else {
      if (DEBUG) {
        Log.d(TAG, "Listen for request " + requestInfo.getRequestId() + " is null");
       }
     }
​
    if (repeating) {
      if (mRepeatingRequestId != REQUEST_ID_NONE) {
        checkEarlyTriggerSequenceComplete(mRepeatingRequestId,
            requestInfo.getLastFrameNumber());
       }
      mRepeatingRequestId = requestInfo.getRequestId();
     } else {
      mRequestLastFrameNumbersList.add(
          new RequestLastFrameNumbersHolder(requestList, requestInfo));
     }
​
    if (mIdle) {
      mDeviceExecutor.execute(mCallOnActive);
     }
    mIdle = false;
​
    return requestInfo.getRequestId();
   }
}

3.1 验证当时CaptureRequest列表中的request

// 验证当时CaptureRequest列表中的request是否合理:中心便是验证与request绑定的Surface是否存在
for (CaptureRequest request : requestList) {
  if (request.getTargets().isEmpty()) {
    throw new IllegalArgumentException(
        "Each request must have at least one Surface target");
   }
​
  for (Surface surface : request.getTargets()) {
    // 确保一切的request至少含有一个Surface,一切Surface非空
    if (surface == null) {
      throw new IllegalArgumentException("Null Surface targets are not allowed");
     }
​
    for (int i = 0; i < mConfiguredOutputs.size(); i++) {
      OutputConfiguration configuration = mConfiguredOutputs.valueAt(i);
      // 判别surface对应的request是否是重复恳求
      if (configuration.isForPhysicalCamera()
          && configuration.getSurfaces().contains(surface)) {
        if (request.isReprocess()) {
          throw new IllegalArgumentException(
              "Reprocess request on physical stream is not allowed");
         }
       }
     }
   }
}

中心便是验证与request绑定的Surface是否存在,这个Surface便是经过addTarget的办法添到request中的surface,和createCaptureSession中传入的surfaces是不相同的;

3.2 底层发送恳求信息

SubmitInfo requestInfo;
​
// 将requestList转化为CaptureRequest数组
CaptureRequest[] requestArray = requestList.toArray(new CaptureRequest[requestList.size()]);
// 转化surface到streamIdx和surfaceIdx
// Convert Surface to streamIdx and surfaceIdx
for (CaptureRequest request : requestArray) {
  // 依据streamId转化surface
  request.convertSurfaceToStreamId(mConfiguredOutputs);
}
​
// 向底层发送恳求信息
requestInfo = mRemoteDevice.submitRequestList(requestArray, repeating);
if (DEBUG) {
  Log.v(TAG, "last frame number " + requestInfo.getLastFrameNumber());
}
​
for (CaptureRequest request : requestArray) {
  // 依据streamId康复surface
  request.recoverStreamIdToSurface();
}

这一逻辑是该办法的中心逻辑;

1.CaptureRequest.convertSurfaceToStreamId(mConfiguredOutputs)

/**
 * @hide
 */
public void convertSurfaceToStreamId(
    final SparseArray<OutputConfiguration> configuredOutputs) {
  synchronized (mSurfacesLock) {
    if (mSurfaceConverted) {
      Log.v(TAG, "Cannot convert already converted surfaces!");
      return;
     }
​
    mStreamIdxArray = new int[mSurfaceSet.size()];
    mSurfaceIdxArray = new int[mSurfaceSet.size()];
    int i = 0;
    for (Surface s : mSurfaceSet) {
      boolean streamFound = false;
      for (int j = 0; j < configuredOutputs.size(); ++j) {
        int streamId = configuredOutputs.keyAt(j);
        OutputConfiguration outConfig = configuredOutputs.valueAt(j);
        int surfaceId = 0;
        // 其实outConfig.getSurfaces()只能获取到一个surface,这个surface便是outconfig对应的surface
        for (Surface outSurface : outConfig.getSurfaces()) {
          if (s == outSurface) {
            streamFound = true;
            mStreamIdxArray[i] = streamId;
            mSurfaceIdxArray[i] = surfaceId;
            i++;
            break;
           }
          surfaceId++;
         }
        if (streamFound) {
          break;
         }
       }
​
      // 需求承认这一块的逻辑是否便是用于延时绑定surface的逻辑
      if (!streamFound) {
        // Check if we can match s by native object ID
        long reqSurfaceId = SurfaceUtils.getSurfaceId(s);
        for (int j = 0; j < configuredOutputs.size(); ++j) {
          int streamId = configuredOutputs.keyAt(j);
          OutputConfiguration outConfig = configuredOutputs.valueAt(j);
          int surfaceId = 0;
          for (Surface outSurface : outConfig.getSurfaces()) {
            if (reqSurfaceId == SurfaceUtils.getSurfaceId(outSurface)) {
              streamFound = true;
              mStreamIdxArray[i] = streamId;
              mSurfaceIdxArray[i] = surfaceId;
              i++;
              break;
             }
            surfaceId++;
           }
          if (streamFound) {
            break;
           }
         }
       }
​
      if (!streamFound) {
        mStreamIdxArray = null;
        mSurfaceIdxArray = null;
        throw new IllegalArgumentException(
            "CaptureRequest contains unconfigured Input/Output Surface!");
       }
     }
    mSurfaceConverted = true;
   }
}

将本地现已缓存的surface和stream记录在内存(mStreamIdxArray数组和mSurfaceIdxArray数组)中,并binder传输到camera service层中,经过mSurfaceConverted变量防止camera service端重复恳求;

2.CameraDeviceClient.submitRequestList(requestArray, repeating)

binder::Status CameraDeviceClient::submitRequestList(
    const std::vector<hardware::camera2::CaptureRequest>& requests,
    bool streaming,
    /*out*/
    hardware::camera2::utils::SubmitInfo *submitInfo) {
  ATRACE_CALL();
  ALOGV("%s-start of function. Request list size %zu", __FUNCTION__, requests.size());
  
  List<const CameraDeviceBase::PhysicalCameraSettingsList> metadataRequestList;
  std::list<const SurfaceMap> surfaceMapList;
​
  …………
    // 这个函数代码许多,前面许多履行都是在复用检索之前的缓存是否可用
    metadataRequestList.push_back(physicalSettingsList);
    surfaceMapList.push_back(surfaceMap);
   }
​
  // 从一步开始,经过setRepeatingRequest()办法传入的request就中止向下传递了,后续过程中需求重新装备新的CaptureRequest,这个创立过程就在Camera3Device::setUpRequestLocked()办法中表现
  // 预览的情况下传入的streaming是true
  // 摄影的情况下传入的streaming是false
  if (streaming) {
    err = mDevice->setStreamingRequestList(metadataRequestList, surfaceMapList,
        &(submitInfo->mLastFrameNumber));
    if (err != OK) {
      String8 msg = String8::format(
        "Camera %s:  Got error %s (%d) after trying to set streaming request",
        mCameraIdStr.string(), strerror(-err), err);
      ALOGE("%s: %s", __FUNCTION__, msg.string());
      res = STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION,
          msg.string());
     } else {
      Mutex::Autolock idLock(mStreamingRequestIdLock);
      mStreamingRequestId = submitInfo->mRequestId;
     }
   } else {
    err = mDevice->captureList(metadataRequestList, surfaceMapList,
        &(submitInfo->mLastFrameNumber));
    if (err != OK) {
      String8 msg = String8::format(
        "Camera %s: Got error %s (%d) after trying to submit capture request",
        mCameraIdStr.string(), strerror(-err), err);
      ALOGE("%s: %s", __FUNCTION__, msg.string());
      res = STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION,
          msg.string());
     }
    ALOGV("%s: requestId = %d ", __FUNCTION__, submitInfo->mRequestId);
   }
​
  ALOGV("%s: Camera %s: End of function", __FUNCTION__, mCameraIdStr.string());
  return res;
}

现在剖析preview情况;

3.mDevice->setStreamingRequestList

mDevice->setStreamingRequestList(metadataRequestList, surfaceMapList,
        &(submitInfo->mLastFrameNumber));
status_t Camera3Device::setStreamingRequestList(
    const List<const PhysicalCameraSettingsList> &requestsList,
    const std::list<const SurfaceMap> &surfaceMaps, int64_t *lastFrameNumber) {
  ATRACE_CALL();
​
  return submitRequestsHelper(requestsList, surfaceMaps, /*repeating*/true, lastFrameNumber);
}
status_t Camera3Device::submitRequestsHelper(
    const List<const PhysicalCameraSettingsList> &requests,
    const std::list<const SurfaceMap> &surfaceMaps,
    bool repeating,
    /*out*/
    int64_t *lastFrameNumber) {
  ATRACE_CALL();
  Mutex::Autolock il(mInterfaceLock);
  Mutex::Autolock l(mLock);
​
  status_t res = checkStatusOkToCaptureLocked();
  if (res != OK) {
    // error logged by previous call
    return res;
   }
​
  RequestList requestList;
​
  res = convertMetadataListToRequestListLocked(requests, surfaceMaps,
      repeating, /*out*/&requestList);
  if (res != OK) {
    // error logged by previous call
    return res;
   }
​
  // preview - true   capture - false
  if (repeating) {
    res = mRequestThread->setRepeatingRequests(requestList, lastFrameNumber);
   } else {
    res = mRequestThread->queueRequestList(requestList, lastFrameNumber);
   }
​
  if (res == OK) {
    // 履行等候直到 state 为 STATUS_ACTIVE
    waitUntilStateThenRelock(/*active*/true, kActiveTimeout);
    if (res != OK) {
      SET_ERR_L("Can't transition to active in %f seconds!",
          kActiveTimeout/1e9);
     }
    ALOGV("Camera %s: Capture request %" PRId32 " enqueued", mId.string(),
        (*(requestList.begin()))->mResultExtras.requestId);
   } else {
    CLOGE("Cannot queue request. Impossible.");
    return BAD_VALUE;
   }
​
  return res;
}

convertMetadataListToRequestListLocked();

status_t Camera3Device::convertMetadataListToRequestListLocked(
    const List<const PhysicalCameraSettingsList> &metadataList,
    const std::list<const SurfaceMap> &surfaceMaps,
    bool repeating,
    RequestList *requestList) {
  if (requestList == NULL) {
    CLOGE("requestList cannot be NULL.");
    return BAD_VALUE;
   }
​
  int32_t burstId = 0;
  List<const PhysicalCameraSettingsList>::const_iterator metadataIt = metadataList.begin();
  std::list<const SurfaceMap>::const_iterator surfaceMapIt = surfaceMaps.begin();
  for (; metadataIt != metadataList.end() && surfaceMapIt != surfaceMaps.end();
      ++metadataIt, ++surfaceMapIt) {
    sp<CaptureRequest> newRequest = setUpRequestLocked(*metadataIt, *surfaceMapIt);
    …………
​
    requestList->push_back(newRequest);
​
    ALOGV("%s: requestId = %" PRId32, __FUNCTION__, newRequest->mResultExtras.requestId);
   }
  …………
​
  return OK;
}

该办法中调用了setUpRequestLocked();

sp<Camera3Device::CaptureRequest> Camera3Device::setUpRequestLocked(
    const PhysicalCameraSettingsList &request, const SurfaceMap &surfaceMap) {
  status_t res;
​
  if (mStatus == STATUS_UNCONFIGURED || mNeedConfig) {
    // This point should only be reached via API1 (API2 must explicitly call configureStreams)
    // so unilaterally select normal operating mode.
    res = filterParamsAndConfigureLocked(request.begin()->metadata,
        CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE);
    // Stream configuration failed. Client might try other configuraitons.
    if (res != OK) {
      CLOGE("Can't set up streams: %s (%d)", strerror(-res), res);
      return NULL;
     } else if (mStatus == STATUS_UNCONFIGURED) {
      // Stream configuration successfully configure to empty stream configuration.
      CLOGE("No streams configured");
      return NULL;
     }
   }
​
  // 经过PhysicalCameraSettings和Surface创立对应的request
  sp<CaptureRequest> newRequest = createCaptureRequest(request, surfaceMap);
  return newRequest;
}

mStatus和mNeedConfig这两个变量由于在履行configureStreamsLocked()的时分,将mStatus设置为了STATUS_CONFIGURED,mNeedConfig修改为了false;

但是在setUpRequestLocked()之前没有装备完成config,那就会履行filterParamsAndConfigureLocked()办法,而这个办法在上一节中现已讲解过,其中心便是调用configureStreamsLocked(),所以也会将mStatus和mNeedConfig两个变量的状况修改,然后再履行后续逻辑;

waitUntilStateThenRelock(/active/true, kActiveTimeout):履行等候直到 state 为 STATUS_ACTIVE;

status_t Camera3Device::waitUntilStateThenRelock(bool active, nsecs_t timeout) {
  status_t res = OK;
​
  size_t startIndex = 0;
  if (mStatusWaiters == 0) {
    // Clear the list of recent statuses if there are no existing threads waiting on updates to
    // this status list
    mRecentStatusUpdates.clear();
   } else {
    // If other threads are waiting on updates to this status list, set the position of the
    // first element that this list will check rather than clearing the list.
    startIndex = mRecentStatusUpdates.size();
   }
​
  mStatusWaiters++;
​
  bool stateSeen = false;
  do {
    if (active == (mStatus == STATUS_ACTIVE)) {
      // Desired state is current
      break;
     }
    …………
​
    // Encountered desired state since we began waiting
    for (size_t i = startIndex; i < mRecentStatusUpdates.size(); i++) {
      if (active == (mRecentStatusUpdates[i] == STATUS_ACTIVE) ) {
        stateSeen = true;
        break;
       }
     }
   } while (!stateSeen);
​
  mStatusWaiters--;
​
  return res;
}

该办法主要是为了防止在还没有将mStatus的状况值修改时,履行后续有依赖于mStatus的逻辑。该办法对应于上述的filterParamsAndConfigureLocked()办法,运用stateSeen变量控制该do-while循环;

status_t Camera3Device::RequestThread::setRepeatingRequests(
    const RequestList &requests,
    /*out*/
    int64_t *lastFrameNumber) {
  ATRACE_CALL();
  Mutex::Autolock l(mRequestLock);
  // 第一次进入为 null
  if (lastFrameNumber != NULL) {
    *lastFrameNumber = mRepeatingLastFrameNumber;
   }
  mRepeatingRequests.clear();
  // 最终将request经过insert()办法添加到mRepeatingRequests恳求行列中,mRepeatingRequests恳求行列是专门用于preview request的
  mRepeatingRequests.insert(mRepeatingRequests.begin(),
      requests.begin(), requests.end());
​
  unpauseForNewRequests();
​
  mRepeatingLastFrameNumber = hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES;
  return OK;
}

mRepeatingRequests变量界说:

Camera3Device.h

typedef List<sp<CaptureRequest> > RequestList;
/**
 * Thread for managing capture request submission to HAL device.
 */
class RequestThread : public Thread {
​
  public:
  ………… // 省掉// Used to prepare a batch of requests.
  struct NextRequest {
    sp<CaptureRequest>       captureRequest;
    camera3_capture_request_t    halRequest;
    Vector<camera3_stream_buffer_t> outputBuffers;
    bool              submitted;
   };
  ………… // 省掉const String8&   mId;    // The camera ID
  int        mStatusId; // The RequestThread's component ID for
  // status tracking
​
  Mutex       mRequestLock;
  Condition     mRequestSignal;
  RequestList    mRequestQueue;
  RequestList    mRepeatingRequests;
  // The next batch of requests being prepped for submission to the HAL, no longer
  // on the request queue. Read-only even with mRequestLock held, outside
  // of threadLoop
  Vector<NextRequest> mNextRequests;

将当时提交的CaptureRequest恳求放入之前的预览恳求行列中,告知HAL层有新的request恳求,HAL层衔接恳求开始作业,源源不断地输出信息到上层。

unpauseForNewRequests():

void Camera3Device::RequestThread::unpauseForNewRequests() {
  ATRACE_CALL();
  // With work to do, mark thread as unpaused.
  // If paused by request (setPaused), don't resume, to avoid
  // extra signaling/waiting overhead to waitUntilPaused
  mRequestSignal.signal();
  Mutex::Autolock p(mPauseLock);
  if (!mDoPause) {
    ALOGV("%s: RequestThread: Going active", __FUNCTION__);
    if (mPaused) {
      sp<StatusTracker> statusTracker = mStatusTracker.promote();
      if (statusTracker != 0) {
        statusTracker->markComponentActive(mStatusId);
       }
     }
    mPaused = false;
   }
}

调用unpauseForNewRequests()向相关线程发送信号,即RequestThread线程;

该办法触发了mRequestSignal的信号,它对应的是Camera3Device::RequestThread::waitForNextRequestLocked()中的 waitRelative() 动作,能够确保在预览的时分不断地捕获信息流,camera就不断处于预览的状况了;

4.CaptureRequest.recoverStreamIdToSurface()

/**
 * @hide
 */
public void recoverStreamIdToSurface() {
  synchronized (mSurfacesLock) {
    if (!mSurfaceConverted) {
      Log.v(TAG, "Cannot convert already converted surfaces!");
      return;
     }
​
    mStreamIdxArray = null;
    mSurfaceIdxArray = null;
    mSurfaceConverted = false;
   }
}

开释内存,康复Surface;

3.3 将回来恳求信息和 CaptureCallback 绑定

CameraDeviceImpl.java

/** map request IDs to callback/request data */
  private final SparseArray<CaptureCallbackHolder> mCaptureCallbackMap =
      new SparseArray<CaptureCallbackHolder>();
if (callback != null) {
  mCaptureCallbackMap.put(requestInfo.getRequestId(),
      new CaptureCallbackHolder(
          callback, requestList, executor, repeating, mNextSessionId - 1));
} else {
  if (DEBUG) {
    Log.d(TAG, "Listen for request " + requestInfo.getRequestId() + " is null");
   }
}
static class CaptureCallbackHolder {
​
  private final boolean mRepeating;
  private final CaptureCallback mCallback;
  private final List<CaptureRequest> mRequestList;
  private final Executor mExecutor;
  private final int mSessionId;
  /**
   * <p>Determine if the callback holder is for a constrained high speed request list that
   * expects batched capture results. Capture results will be batched if the request list
   * is interleaved with preview and video requests. Capture results won't be batched if the
   * request list only contains preview requests, or if the request doesn't belong to a
   * constrained high speed list.
   */
  private final boolean mHasBatchedOutputs;
​
  CaptureCallbackHolder(CaptureCallback callback, List<CaptureRequest> requestList,
             Executor executor, boolean repeating, int sessionId) {
    if (callback == null || executor == null) {
      throw new UnsupportedOperationException(
          "Must have a valid handler and a valid callback");
     }
    mRepeating = repeating;
    mExecutor = executor;
    mRequestList = new ArrayList<CaptureRequest>(requestList);
    mCallback = callback;
    mSessionId = sessionId;
​
    // Check whether this callback holder is for batched outputs.
    // The logic here should match createHighSpeedRequestList.
    boolean hasBatchedOutputs = true;
    for (int i = 0; i < requestList.size(); i++) {
      CaptureRequest request = requestList.get(i);
      if (!request.isPartOfCRequestList()) {
        hasBatchedOutputs = false;
        break;
       }
      if (i == 0) {
        Collection<Surface> targets = request.getTargets();
        if (targets.size() != 2) {
          hasBatchedOutputs = false;
          break;
         }
       }
     }
    mHasBatchedOutputs = hasBatchedOutputs;
   }
​
  public boolean isRepeating() {
    return mRepeating;
   }
​
  public CaptureCallback getCallback() {
    return mCallback;
   }
​
  public CaptureRequest getRequest(int subsequenceId) {
    if (subsequenceId >= mRequestList.size()) {
      throw new IllegalArgumentException(
          String.format(
              "Requested subsequenceId %d is larger than request list size %d.",
              subsequenceId, mRequestList.size()));
     } else {
      if (subsequenceId < 0) {
        throw new IllegalArgumentException(String.format(
            "Requested subsequenceId %d is negative", subsequenceId));
       } else {
        return mRequestList.get(subsequenceId);
       }
     }
   }
​
  public CaptureRequest getRequest() {
    return getRequest(0);
   }
​
  public Executor getExecutor() {
    return mExecutor;
   }
​
  public int getSessionId() {
    return mSessionId;
   }
​
  public int getRequestCount() {
    return mRequestList.size();
   }
​
  public boolean hasBatchedOutputs() {
    return mHasBatchedOutputs;
   }
}

requestInfo变量的类型为SubmitInfo;

public class SubmitInfo implements Parcelable {
​
  private int mRequestId;
  private long mLastFrameNumber;
​
  public SubmitInfo() {
    mRequestId = -1;
    mLastFrameNumber = ICameraDeviceUser.NO_IN_FLIGHT_REPEATING_FRAMES;
   }
​
  public SubmitInfo(int requestId, long lastFrameNumber) {
    mRequestId = requestId;
    mLastFrameNumber = lastFrameNumber;
   }
}

requestIinfo表示当时capture request的成果,将requestInfo.getRequestId()与CaptureCallbackHolder绑定,由于Camera 2架构支持发送多次CaptureRequest恳求,假如不运用这种绑定机制,后续的回调会造成严重的紊乱,乃至回调不上来,那么开发者无法持续运用了;

综上,至此在调用完mRepeatingRequests.insert()和unpauseForNewRequests()这两个办法之后,setRepeatingRequest()中心逻辑就基本上完毕了;

紧接着下来的便是RequestThread线程轮询处理逻辑;