1/* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "ACameraCaptureSession.h" 18#include "ACameraMetadata.h" 19#include "ACaptureRequest.h" 20#include "utils.h" 21#include <CameraMetadata.h> 22#include <inttypes.h> 23#include <ndk_vendor/impl/ACameraDevice.h> 24#include <vector> 25 26using namespace android; 27 28namespace android { 29namespace acam { 30 31template<class T> 32camera_status_t CameraDevice::captureLocked( 33 sp<ACameraCaptureSession> session, 34 /*optional*/T* cbs, 35 int numRequests, 36 ACaptureRequest** requests, 37 /*optional*/int* captureSequenceId) { 38 return submitRequestsLocked( 39 session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/false); 40} 41 42template<class T> 43camera_status_t CameraDevice::setRepeatingRequestsLocked( 44 sp<ACameraCaptureSession> session, 45 /*optional*/T* cbs, 46 int numRequests, 47 ACaptureRequest** requests, 48 /*optional*/int* captureSequenceId) { 49 return submitRequestsLocked( 50 session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/true); 51} 52 53template<class T> 54camera_status_t CameraDevice::submitRequestsLocked( 55 sp<ACameraCaptureSession> session, 56 /*optional*/T* cbs, int numRequests, 57 ACaptureRequest** requests, 58 /*out*/int* captureSequenceId, 59 bool isRepeating) { 60 camera_status_t ret = checkCameraClosedOrErrorLocked(); 61 if (ret != ACAMERA_OK) { 62 ALOGE("Camera %s submit capture request failed! ret %d", getId(), ret); 63 return ret; 64 } 65 66 // Form two vectors of capture request, one for internal tracking 67 68 std::vector<::aidl::android::frameworks::cameraservice::device::CaptureRequest> requestList; 69 std::vector<sp<CaptureRequest>> requestsV; 70 requestsV.reserve(numRequests); 71 for (int i = 0; i < numRequests; i++) { 72 sp<CaptureRequest> req; 73 ret = allocateCaptureRequestLocked(requests[i], req); 74 // We need to call this method since after submitRequestList is called, 75 // the request metadata queue might have removed the capture request 76 // metadata. Therefore we simply add the metadata to its wrapper class, 77 // so that it can be retrieved later. 78 addRequestSettingsMetadata(requests[i], req); 79 if (ret != ACAMERA_OK) { 80 ALOGE("Convert capture request to internal format failure! ret %d", ret); 81 return ret; 82 } 83 if (req->mCaptureRequest.streamAndWindowIds.size() == 0) { 84 ALOGE("Capture request without output target cannot be submitted!"); 85 return ACAMERA_ERROR_INVALID_PARAMETER; 86 } 87 requestList.push_back(utils::convertToAidl(req.get())); 88 requestsV.push_back(req); 89 } 90 if (isRepeating) { 91 ret = stopRepeatingLocked(); 92 if (ret != ACAMERA_OK) { 93 ALOGE("Camera %s stop repeating failed! ret %d", getId(), ret); 94 return ret; 95 } 96 } 97 98 SubmitInfo info; 99 Status status; 100 ndk::ScopedAStatus remoteRet = mRemote->submitRequestList(requestList, isRepeating, &info); 101 if (!remoteRet.isOk()) { 102 if (remoteRet.getExceptionCode() == EX_SERVICE_SPECIFIC) { 103 Status errStatus = static_cast<Status>(remoteRet.getServiceSpecificError()); 104 ALOGE("%s: submitRequestList call failed: %s", 105 __FUNCTION__, toString(errStatus).c_str()); 106 return utils::convertFromAidl(errStatus); 107 } else { 108 ALOGE("%s: Transaction error for submitRequestList call: %d", __FUNCTION__, 109 remoteRet.getExceptionCode()); 110 return ACAMERA_ERROR_UNKNOWN; 111 } 112 } 113 114 int32_t sequenceId = info.requestId; 115 int64_t lastFrameNumber = info.lastFrameNumber; 116 if (sequenceId < 0) { 117 ALOGE("Camera %s submit request remote failure: ret %d", getId(), sequenceId); 118 return ACAMERA_ERROR_UNKNOWN; 119 } 120 121 CallbackHolder cbHolder(session, requestsV, isRepeating, cbs); 122 mSequenceCallbackMap.insert(std::make_pair(sequenceId, cbHolder)); 123 if (isRepeating) { 124 // stopRepeating above should have cleanup repeating sequence id 125 if (mRepeatingSequenceId != REQUEST_ID_NONE) { 126 setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE); 127 return ACAMERA_ERROR_CAMERA_DEVICE; 128 } 129 mRepeatingSequenceId = sequenceId; 130 } else { 131 mSequenceLastFrameNumberMap.insert(std::make_pair(sequenceId, lastFrameNumber)); 132 } 133 134 if (mIdle) { 135 sp<AMessage> msg = new AMessage(kWhatSessionStateCb, mHandler); 136 msg->setPointer(kContextKey, session->mUserSessionCallback.context); 137 msg->setObject(kSessionSpKey, session); 138 msg->setPointer(kCallbackFpKey, (void*) session->mUserSessionCallback.onActive); 139 postSessionMsgAndCleanup(msg); 140 } 141 mIdle = false; 142 mBusySession = session; 143 144 if (captureSequenceId) { 145 *captureSequenceId = sequenceId; 146 } 147 return ACAMERA_OK; 148} 149 150template<class T> 151camera_status_t CameraDevice::startStreamingLocked(ACameraCaptureSession* session, 152 /*optional*/T* callbacks, int numOutputWindows, 153 ANativeWindow** windows, /*optional*/int* captureSequenceId) { 154 camera_status_t ret = checkCameraClosedOrErrorLocked(); 155 if (ret != ACAMERA_OK) { 156 ALOGE("%s: camera is in closed or error state %d", __FUNCTION__, ret); 157 return ret; 158 } 159 utils::AidlCameraMetadata aidlMetadata; 160 ndk::ScopedAStatus remoteRet = mRemote->createDefaultRequest(utils::TemplateId::PREVIEW, 161 &aidlMetadata); 162 if (!remoteRet.isOk()) { 163 if (remoteRet.getExceptionCode() == EX_SERVICE_SPECIFIC) { 164 Status errStatus = static_cast<Status>(remoteRet.getServiceSpecificError()); 165 ALOGE("%s: submitRequestList call failed: %s", 166 __FUNCTION__, toString(errStatus).c_str()); 167 return utils::convertFromAidl(errStatus); 168 } else { 169 ALOGE("%s: Transaction error for submitRequestList call: %d", __FUNCTION__, 170 remoteRet.getExceptionCode()); 171 return ACAMERA_ERROR_UNKNOWN; 172 } 173 } 174 camera_metadata_t* rawPreviewRequest; 175 utils::cloneFromAidl(aidlMetadata, &rawPreviewRequest); 176 // ToDo: Check if the memory allocation can be freed automatically using either default_delete 177 // or ScopedAResource. 178 mPreviewRequest = new ACaptureRequest(); 179 mPreviewRequest->settings = new ACameraMetadata(rawPreviewRequest, 180 ACameraMetadata::ACM_REQUEST); 181 mPreviewRequest->targets = new ACameraOutputTargets(); 182 for (int i = 0; i < numOutputWindows ; i++) { 183 ACameraOutputTarget* outputTarget = nullptr; 184 ret = ACameraOutputTarget_create(windows[i], &outputTarget); 185 if (ret != ACAMERA_OK) { 186 ALOGE("%s: error while ACameraOutputTarget_create %d", __FUNCTION__, ret); 187 return ret; 188 } 189 ret = ACaptureRequest_addTarget(mPreviewRequest, outputTarget); 190 if (ret != ACAMERA_OK) { 191 ALOGE("%s: error while ACaptureRequest_addTarget %d", __FUNCTION__, ret); 192 return ret; 193 } 194 mPreviewRequestOutputs.push_back(outputTarget); 195 } 196 197 std::vector<sp<CaptureRequest>> requestsV; 198 sp<CaptureRequest> req; 199 ret = allocateCaptureRequestLocked(mPreviewRequest, req); 200 // We need to call this method since after submitRequestList is called, 201 // the request metadata queue might have removed the capture request 202 // metadata. Therefore we simply add the metadata to its wrapper class, 203 // so that it can be retrieved later. 204 addRequestSettingsMetadata(mPreviewRequest, req); 205 if (ret != ACAMERA_OK) { 206 ALOGE("Convert capture request to internal format failure! ret %d", ret); 207 return ret; 208 } 209 if (req->mCaptureRequest.streamAndWindowIds.size() == 0) { 210 ALOGE("Capture request without output target cannot be submitted!"); 211 return ACAMERA_ERROR_INVALID_PARAMETER; 212 } 213 requestsV.push_back(req); 214 // In shared session mode, if there are other active clients streaming then 215 // stoprepeating does not actually send request to HAL to cancel the request. 216 // Cameraservice will use this call to remove this client surfaces provided in its 217 // previous streaming request. If this is the only client for the shared camera device 218 // then camerservice will ask HAL to cancel the previous repeating request. 219 ret = stopRepeatingLocked(); 220 if (ret != ACAMERA_OK) { 221 ALOGE("Camera %s stop repeating failed! ret %d", getId(), ret); 222 return ret; 223 } 224 SubmitInfo info; 225 std::vector<int> streamIds; 226 std::vector<int> surfaceIds; 227 for (const auto& streamAndWindowId : req->mCaptureRequest.streamAndWindowIds) { 228 streamIds.push_back(streamAndWindowId.streamId); 229 surfaceIds.push_back(streamAndWindowId.windowId); 230 } 231 remoteRet = mRemote->startStreaming(streamIds, surfaceIds, &info); 232 if (!remoteRet.isOk()) { 233 if (remoteRet.getExceptionCode() == EX_SERVICE_SPECIFIC) { 234 Status errStatus = static_cast<Status>(remoteRet.getServiceSpecificError()); 235 ALOGE("%s: startStreaming call failed: %s", 236 __FUNCTION__, toString(errStatus).c_str()); 237 return utils::convertFromAidl(errStatus); 238 } else { 239 ALOGE("%s: Transaction error for startStreaming call: %d", __FUNCTION__, 240 remoteRet.getExceptionCode()); 241 return ACAMERA_ERROR_UNKNOWN; 242 } 243 } 244 245 int32_t sequenceId = info.requestId; 246 int64_t lastFrameNumber = info.lastFrameNumber; 247 if (sequenceId < 0) { 248 ALOGE("Camera %s submit request remote failure: ret %d", getId(), sequenceId); 249 return ACAMERA_ERROR_UNKNOWN; 250 } 251 CallbackHolder cbHolder(session, requestsV, true, callbacks); 252 mSequenceCallbackMap.insert(std::make_pair(sequenceId, cbHolder)); 253 // stopRepeating above should have cleanup repeating sequence id 254 if (mRepeatingSequenceId != REQUEST_ID_NONE) { 255 setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE); 256 return ACAMERA_ERROR_CAMERA_DEVICE; 257 } 258 mRepeatingSequenceId = sequenceId; 259 260 if (mIdle) { 261 sp<AMessage> msg = new AMessage(kWhatSessionStateCb, mHandler); 262 msg->setPointer(kContextKey, session->mUserSessionCallback.context); 263 msg->setObject(kSessionSpKey, session); 264 msg->setPointer(kCallbackFpKey, (void*) session->mUserSessionCallback.onActive); 265 postSessionMsgAndCleanup(msg); 266 } 267 mIdle = false; 268 mBusySession = session; 269 270 if (captureSequenceId) { 271 *captureSequenceId = sequenceId; 272 } 273 return ACAMERA_OK; 274} 275 276} // namespace acam 277} // namespace android 278