| Igor Murashkin | e7ee763 | 2013-06-11 18:10:18 -0700 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright (C) 2013 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 | #define LOG_TAG "CameraDeviceClient" | 
 | 18 | #define ATRACE_TAG ATRACE_TAG_CAMERA | 
| Jianing Wei | cb0652e | 2014-03-12 18:29:36 -0700 | [diff] [blame] | 19 | //#define LOG_NDEBUG 0 | 
| Igor Murashkin | e7ee763 | 2013-06-11 18:10:18 -0700 | [diff] [blame] | 20 |  | 
| Eino-Ville Talvala | 7b82efe | 2013-07-25 17:12:35 -0700 | [diff] [blame] | 21 | #include <cutils/properties.h> | 
| Igor Murashkin | e7ee763 | 2013-06-11 18:10:18 -0700 | [diff] [blame] | 22 | #include <utils/Log.h> | 
 | 23 | #include <utils/Trace.h> | 
| Igor Murashkin | e7ee763 | 2013-06-11 18:10:18 -0700 | [diff] [blame] | 24 | #include <gui/Surface.h> | 
| Eino-Ville Talvala | 7b82efe | 2013-07-25 17:12:35 -0700 | [diff] [blame] | 25 | #include <camera/camera2/CaptureRequest.h> | 
| Ruben Brunk | 5698d44 | 2014-06-18 10:39:40 -0700 | [diff] [blame] | 26 | #include <camera/CameraUtils.h> | 
| Eino-Ville Talvala | 7b82efe | 2013-07-25 17:12:35 -0700 | [diff] [blame] | 27 |  | 
 | 28 | #include "common/CameraDeviceBase.h" | 
 | 29 | #include "api2/CameraDeviceClient.h" | 
 | 30 |  | 
 | 31 |  | 
| Igor Murashkin | e7ee763 | 2013-06-11 18:10:18 -0700 | [diff] [blame] | 32 |  | 
 | 33 | namespace android { | 
 | 34 | using namespace camera2; | 
 | 35 |  | 
 | 36 | CameraDeviceClientBase::CameraDeviceClientBase( | 
 | 37 |         const sp<CameraService>& cameraService, | 
 | 38 |         const sp<ICameraDeviceCallbacks>& remoteCallback, | 
 | 39 |         const String16& clientPackageName, | 
 | 40 |         int cameraId, | 
 | 41 |         int cameraFacing, | 
 | 42 |         int clientPid, | 
 | 43 |         uid_t clientUid, | 
 | 44 |         int servicePid) : | 
 | 45 |     BasicClient(cameraService, remoteCallback->asBinder(), clientPackageName, | 
 | 46 |                 cameraId, cameraFacing, clientPid, clientUid, servicePid), | 
 | 47 |     mRemoteCallback(remoteCallback) { | 
 | 48 | } | 
| Igor Murashkin | e7ee763 | 2013-06-11 18:10:18 -0700 | [diff] [blame] | 49 |  | 
 | 50 | // Interface used by CameraService | 
 | 51 |  | 
 | 52 | CameraDeviceClient::CameraDeviceClient(const sp<CameraService>& cameraService, | 
 | 53 |                                    const sp<ICameraDeviceCallbacks>& remoteCallback, | 
 | 54 |                                    const String16& clientPackageName, | 
 | 55 |                                    int cameraId, | 
 | 56 |                                    int cameraFacing, | 
 | 57 |                                    int clientPid, | 
 | 58 |                                    uid_t clientUid, | 
 | 59 |                                    int servicePid) : | 
 | 60 |     Camera2ClientBase(cameraService, remoteCallback, clientPackageName, | 
 | 61 |                 cameraId, cameraFacing, clientPid, clientUid, servicePid), | 
 | 62 |     mRequestIdCounter(0) { | 
 | 63 |  | 
 | 64 |     ATRACE_CALL(); | 
 | 65 |     ALOGI("CameraDeviceClient %d: Opened", cameraId); | 
 | 66 | } | 
 | 67 |  | 
 | 68 | status_t CameraDeviceClient::initialize(camera_module_t *module) | 
 | 69 | { | 
 | 70 |     ATRACE_CALL(); | 
 | 71 |     status_t res; | 
 | 72 |  | 
 | 73 |     res = Camera2ClientBase::initialize(module); | 
 | 74 |     if (res != OK) { | 
 | 75 |         return res; | 
 | 76 |     } | 
 | 77 |  | 
 | 78 |     String8 threadName; | 
| Eino-Ville Talvala | 7b82efe | 2013-07-25 17:12:35 -0700 | [diff] [blame] | 79 |     mFrameProcessor = new FrameProcessorBase(mDevice); | 
| Igor Murashkin | e7ee763 | 2013-06-11 18:10:18 -0700 | [diff] [blame] | 80 |     threadName = String8::format("CDU-%d-FrameProc", mCameraId); | 
 | 81 |     mFrameProcessor->run(threadName.string()); | 
 | 82 |  | 
 | 83 |     mFrameProcessor->registerListener(FRAME_PROCESSOR_LISTENER_MIN_ID, | 
 | 84 |                                       FRAME_PROCESSOR_LISTENER_MAX_ID, | 
| Eino-Ville Talvala | 184dfe4 | 2013-11-07 15:13:16 -0800 | [diff] [blame] | 85 |                                       /*listener*/this, | 
| Zhijun He | 25a0aef | 2014-06-25 11:40:02 -0700 | [diff] [blame] | 86 |                                       /*sendPartials*/true); | 
| Igor Murashkin | e7ee763 | 2013-06-11 18:10:18 -0700 | [diff] [blame] | 87 |  | 
 | 88 |     return OK; | 
 | 89 | } | 
 | 90 |  | 
 | 91 | CameraDeviceClient::~CameraDeviceClient() { | 
 | 92 | } | 
 | 93 |  | 
 | 94 | status_t CameraDeviceClient::submitRequest(sp<CaptureRequest> request, | 
| Jianing Wei | cb0652e | 2014-03-12 18:29:36 -0700 | [diff] [blame] | 95 |                                          bool streaming, | 
 | 96 |                                          /*out*/ | 
 | 97 |                                          int64_t* lastFrameNumber) { | 
 | 98 |     List<sp<CaptureRequest> > requestList; | 
 | 99 |     requestList.push_back(request); | 
 | 100 |     return submitRequestList(requestList, streaming, lastFrameNumber); | 
| Igor Murashkin | e7ee763 | 2013-06-11 18:10:18 -0700 | [diff] [blame] | 101 | } | 
 | 102 |  | 
| Jianing Wei | 90e59c9 | 2014-03-12 18:29:36 -0700 | [diff] [blame] | 103 | status_t CameraDeviceClient::submitRequestList(List<sp<CaptureRequest> > requests, | 
| Jianing Wei | cb0652e | 2014-03-12 18:29:36 -0700 | [diff] [blame] | 104 |                                                bool streaming, int64_t* lastFrameNumber) { | 
| Jianing Wei | 90e59c9 | 2014-03-12 18:29:36 -0700 | [diff] [blame] | 105 |     ATRACE_CALL(); | 
| Mark Salyzyn | 5046841 | 2014-06-18 16:33:43 -0700 | [diff] [blame] | 106 |     ALOGV("%s-start of function. Request list size %zu", __FUNCTION__, requests.size()); | 
| Jianing Wei | 90e59c9 | 2014-03-12 18:29:36 -0700 | [diff] [blame] | 107 |  | 
 | 108 |     status_t res; | 
 | 109 |     if ( (res = checkPid(__FUNCTION__) ) != OK) return res; | 
 | 110 |  | 
 | 111 |     Mutex::Autolock icl(mBinderSerializationLock); | 
 | 112 |  | 
 | 113 |     if (!mDevice.get()) return DEAD_OBJECT; | 
 | 114 |  | 
 | 115 |     if (requests.empty()) { | 
 | 116 |         ALOGE("%s: Camera %d: Sent null request. Rejecting request.", | 
 | 117 |               __FUNCTION__, mCameraId); | 
 | 118 |         return BAD_VALUE; | 
 | 119 |     } | 
 | 120 |  | 
 | 121 |     List<const CameraMetadata> metadataRequestList; | 
 | 122 |     int32_t requestId = mRequestIdCounter; | 
 | 123 |     uint32_t loopCounter = 0; | 
 | 124 |  | 
 | 125 |     for (List<sp<CaptureRequest> >::iterator it = requests.begin(); it != requests.end(); ++it) { | 
 | 126 |         sp<CaptureRequest> request = *it; | 
 | 127 |         if (request == 0) { | 
 | 128 |             ALOGE("%s: Camera %d: Sent null request.", | 
 | 129 |                     __FUNCTION__, mCameraId); | 
 | 130 |             return BAD_VALUE; | 
 | 131 |         } | 
 | 132 |  | 
 | 133 |         CameraMetadata metadata(request->mMetadata); | 
 | 134 |         if (metadata.isEmpty()) { | 
 | 135 |             ALOGE("%s: Camera %d: Sent empty metadata packet. Rejecting request.", | 
 | 136 |                    __FUNCTION__, mCameraId); | 
 | 137 |             return BAD_VALUE; | 
 | 138 |         } else if (request->mSurfaceList.isEmpty()) { | 
 | 139 |             ALOGE("%s: Camera %d: Requests must have at least one surface target. " | 
 | 140 |                   "Rejecting request.", __FUNCTION__, mCameraId); | 
 | 141 |             return BAD_VALUE; | 
 | 142 |         } | 
 | 143 |  | 
 | 144 |         if (!enforceRequestPermissions(metadata)) { | 
 | 145 |             // Callee logs | 
 | 146 |             return PERMISSION_DENIED; | 
 | 147 |         } | 
 | 148 |  | 
 | 149 |         /** | 
 | 150 |          * Write in the output stream IDs which we calculate from | 
 | 151 |          * the capture request's list of surface targets | 
 | 152 |          */ | 
 | 153 |         Vector<int32_t> outputStreamIds; | 
 | 154 |         outputStreamIds.setCapacity(request->mSurfaceList.size()); | 
| Jianing Wei | cb0652e | 2014-03-12 18:29:36 -0700 | [diff] [blame] | 155 |         for (size_t i = 0; i < request->mSurfaceList.size(); ++i) { | 
 | 156 |             sp<Surface> surface = request->mSurfaceList[i]; | 
| Jianing Wei | 90e59c9 | 2014-03-12 18:29:36 -0700 | [diff] [blame] | 157 |             if (surface == 0) continue; | 
 | 158 |  | 
 | 159 |             sp<IGraphicBufferProducer> gbp = surface->getIGraphicBufferProducer(); | 
 | 160 |             int idx = mStreamMap.indexOfKey(gbp->asBinder()); | 
 | 161 |  | 
 | 162 |             // Trying to submit request with surface that wasn't created | 
 | 163 |             if (idx == NAME_NOT_FOUND) { | 
 | 164 |                 ALOGE("%s: Camera %d: Tried to submit a request with a surface that" | 
 | 165 |                       " we have not called createStream on", | 
 | 166 |                       __FUNCTION__, mCameraId); | 
 | 167 |                 return BAD_VALUE; | 
 | 168 |             } | 
 | 169 |  | 
 | 170 |             int streamId = mStreamMap.valueAt(idx); | 
 | 171 |             outputStreamIds.push_back(streamId); | 
 | 172 |             ALOGV("%s: Camera %d: Appending output stream %d to request", | 
 | 173 |                   __FUNCTION__, mCameraId, streamId); | 
 | 174 |         } | 
 | 175 |  | 
 | 176 |         metadata.update(ANDROID_REQUEST_OUTPUT_STREAMS, &outputStreamIds[0], | 
 | 177 |                         outputStreamIds.size()); | 
 | 178 |  | 
 | 179 |         metadata.update(ANDROID_REQUEST_ID, &requestId, /*size*/1); | 
 | 180 |         loopCounter++; // loopCounter starts from 1 | 
| Mark Salyzyn | 5046841 | 2014-06-18 16:33:43 -0700 | [diff] [blame] | 181 |         ALOGV("%s: Camera %d: Creating request with ID %d (%d of %zu)", | 
| Jianing Wei | 90e59c9 | 2014-03-12 18:29:36 -0700 | [diff] [blame] | 182 |               __FUNCTION__, mCameraId, requestId, loopCounter, requests.size()); | 
 | 183 |  | 
 | 184 |         metadataRequestList.push_back(metadata); | 
 | 185 |     } | 
 | 186 |     mRequestIdCounter++; | 
 | 187 |  | 
 | 188 |     if (streaming) { | 
| Jianing Wei | cb0652e | 2014-03-12 18:29:36 -0700 | [diff] [blame] | 189 |         res = mDevice->setStreamingRequestList(metadataRequestList, lastFrameNumber); | 
| Jianing Wei | 90e59c9 | 2014-03-12 18:29:36 -0700 | [diff] [blame] | 190 |         if (res != OK) { | 
 | 191 |             ALOGE("%s: Camera %d:  Got error %d after trying to set streaming " | 
 | 192 |                   "request", __FUNCTION__, mCameraId, res); | 
 | 193 |         } else { | 
 | 194 |             mStreamingRequestList.push_back(requestId); | 
 | 195 |         } | 
 | 196 |     } else { | 
| Jianing Wei | cb0652e | 2014-03-12 18:29:36 -0700 | [diff] [blame] | 197 |         res = mDevice->captureList(metadataRequestList, lastFrameNumber); | 
| Jianing Wei | 90e59c9 | 2014-03-12 18:29:36 -0700 | [diff] [blame] | 198 |         if (res != OK) { | 
 | 199 |             ALOGE("%s: Camera %d: Got error %d after trying to set capture", | 
 | 200 |                 __FUNCTION__, mCameraId, res); | 
 | 201 |         } | 
| Jianing Wei | cb0652e | 2014-03-12 18:29:36 -0700 | [diff] [blame] | 202 |         ALOGV("%s: requestId = %d ", __FUNCTION__, requestId); | 
| Jianing Wei | 90e59c9 | 2014-03-12 18:29:36 -0700 | [diff] [blame] | 203 |     } | 
 | 204 |  | 
 | 205 |     ALOGV("%s: Camera %d: End of function", __FUNCTION__, mCameraId); | 
 | 206 |     if (res == OK) { | 
 | 207 |         return requestId; | 
 | 208 |     } | 
 | 209 |  | 
 | 210 |     return res; | 
 | 211 | } | 
 | 212 |  | 
| Jianing Wei | cb0652e | 2014-03-12 18:29:36 -0700 | [diff] [blame] | 213 | status_t CameraDeviceClient::cancelRequest(int requestId, int64_t* lastFrameNumber) { | 
| Igor Murashkin | e7ee763 | 2013-06-11 18:10:18 -0700 | [diff] [blame] | 214 |     ATRACE_CALL(); | 
 | 215 |     ALOGV("%s, requestId = %d", __FUNCTION__, requestId); | 
 | 216 |  | 
 | 217 |     status_t res; | 
 | 218 |  | 
 | 219 |     if ( (res = checkPid(__FUNCTION__) ) != OK) return res; | 
 | 220 |  | 
 | 221 |     Mutex::Autolock icl(mBinderSerializationLock); | 
 | 222 |  | 
 | 223 |     if (!mDevice.get()) return DEAD_OBJECT; | 
 | 224 |  | 
 | 225 |     Vector<int>::iterator it, end; | 
 | 226 |     for (it = mStreamingRequestList.begin(), end = mStreamingRequestList.end(); | 
 | 227 |          it != end; ++it) { | 
 | 228 |         if (*it == requestId) { | 
 | 229 |             break; | 
 | 230 |         } | 
 | 231 |     } | 
 | 232 |  | 
 | 233 |     if (it == end) { | 
 | 234 |         ALOGE("%s: Camera%d: Did not find request id %d in list of streaming " | 
 | 235 |               "requests", __FUNCTION__, mCameraId, requestId); | 
 | 236 |         return BAD_VALUE; | 
 | 237 |     } | 
 | 238 |  | 
| Jianing Wei | cb0652e | 2014-03-12 18:29:36 -0700 | [diff] [blame] | 239 |     res = mDevice->clearStreamingRequest(lastFrameNumber); | 
| Igor Murashkin | e7ee763 | 2013-06-11 18:10:18 -0700 | [diff] [blame] | 240 |  | 
 | 241 |     if (res == OK) { | 
 | 242 |         ALOGV("%s: Camera %d: Successfully cleared streaming request", | 
 | 243 |               __FUNCTION__, mCameraId); | 
 | 244 |         mStreamingRequestList.erase(it); | 
 | 245 |     } | 
 | 246 |  | 
 | 247 |     return res; | 
 | 248 | } | 
 | 249 |  | 
| Ruben Brunk | b2119af | 2014-05-09 19:57:56 -0700 | [diff] [blame] | 250 | status_t CameraDeviceClient::beginConfigure() { | 
 | 251 |     // TODO: Implement this. | 
 | 252 |     ALOGE("%s: Not implemented yet.", __FUNCTION__); | 
 | 253 |     return OK; | 
 | 254 | } | 
 | 255 |  | 
 | 256 | status_t CameraDeviceClient::endConfigure() { | 
 | 257 |     // TODO: Implement this. | 
 | 258 |     ALOGE("%s: Not implemented yet.", __FUNCTION__); | 
 | 259 |     return OK; | 
 | 260 | } | 
 | 261 |  | 
| Igor Murashkin | e7ee763 | 2013-06-11 18:10:18 -0700 | [diff] [blame] | 262 | status_t CameraDeviceClient::deleteStream(int streamId) { | 
 | 263 |     ATRACE_CALL(); | 
 | 264 |     ALOGV("%s (streamId = 0x%x)", __FUNCTION__, streamId); | 
 | 265 |  | 
 | 266 |     status_t res; | 
 | 267 |     if ( (res = checkPid(__FUNCTION__) ) != OK) return res; | 
 | 268 |  | 
 | 269 |     Mutex::Autolock icl(mBinderSerializationLock); | 
 | 270 |  | 
 | 271 |     if (!mDevice.get()) return DEAD_OBJECT; | 
 | 272 |  | 
 | 273 |     // Guard against trying to delete non-created streams | 
 | 274 |     ssize_t index = NAME_NOT_FOUND; | 
 | 275 |     for (size_t i = 0; i < mStreamMap.size(); ++i) { | 
 | 276 |         if (streamId == mStreamMap.valueAt(i)) { | 
 | 277 |             index = i; | 
 | 278 |             break; | 
 | 279 |         } | 
 | 280 |     } | 
 | 281 |  | 
 | 282 |     if (index == NAME_NOT_FOUND) { | 
 | 283 |         ALOGW("%s: Camera %d: Invalid stream ID (%d) specified, no stream " | 
 | 284 |               "created yet", __FUNCTION__, mCameraId, streamId); | 
 | 285 |         return BAD_VALUE; | 
 | 286 |     } | 
 | 287 |  | 
 | 288 |     // Also returns BAD_VALUE if stream ID was not valid | 
 | 289 |     res = mDevice->deleteStream(streamId); | 
 | 290 |  | 
 | 291 |     if (res == BAD_VALUE) { | 
 | 292 |         ALOGE("%s: Camera %d: Unexpected BAD_VALUE when deleting stream, but we" | 
 | 293 |               " already checked and the stream ID (%d) should be valid.", | 
 | 294 |               __FUNCTION__, mCameraId, streamId); | 
 | 295 |     } else if (res == OK) { | 
 | 296 |         mStreamMap.removeItemsAt(index); | 
 | 297 |  | 
| Igor Murashkin | e7ee763 | 2013-06-11 18:10:18 -0700 | [diff] [blame] | 298 |     } | 
 | 299 |  | 
 | 300 |     return res; | 
 | 301 | } | 
 | 302 |  | 
 | 303 | status_t CameraDeviceClient::createStream(int width, int height, int format, | 
 | 304 |                       const sp<IGraphicBufferProducer>& bufferProducer) | 
 | 305 | { | 
 | 306 |     ATRACE_CALL(); | 
 | 307 |     ALOGV("%s (w = %d, h = %d, f = 0x%x)", __FUNCTION__, width, height, format); | 
 | 308 |  | 
 | 309 |     status_t res; | 
 | 310 |     if ( (res = checkPid(__FUNCTION__) ) != OK) return res; | 
 | 311 |  | 
 | 312 |     Mutex::Autolock icl(mBinderSerializationLock); | 
 | 313 |  | 
| Yin-Chia Yeh | 89f14da | 2014-06-10 16:05:44 -0700 | [diff] [blame] | 314 |     if (bufferProducer == NULL) { | 
 | 315 |         ALOGE("%s: bufferProducer must not be null", __FUNCTION__); | 
 | 316 |         return BAD_VALUE; | 
 | 317 |     } | 
| Igor Murashkin | e7ee763 | 2013-06-11 18:10:18 -0700 | [diff] [blame] | 318 |     if (!mDevice.get()) return DEAD_OBJECT; | 
 | 319 |  | 
 | 320 |     // Don't create multiple streams for the same target surface | 
 | 321 |     { | 
 | 322 |         ssize_t index = mStreamMap.indexOfKey(bufferProducer->asBinder()); | 
 | 323 |         if (index != NAME_NOT_FOUND) { | 
 | 324 |             ALOGW("%s: Camera %d: Buffer producer already has a stream for it " | 
| Colin Cross | e5729fa | 2014-03-21 15:04:25 -0700 | [diff] [blame] | 325 |                   "(ID %zd)", | 
| Igor Murashkin | e7ee763 | 2013-06-11 18:10:18 -0700 | [diff] [blame] | 326 |                   __FUNCTION__, mCameraId, index); | 
 | 327 |             return ALREADY_EXISTS; | 
 | 328 |         } | 
 | 329 |     } | 
 | 330 |  | 
| Eino-Ville Talvala | 1da3b60 | 2013-09-26 15:28:55 -0700 | [diff] [blame] | 331 |     // HACK b/10949105 | 
 | 332 |     // Query consumer usage bits to set async operation mode for | 
 | 333 |     // GLConsumer using controlledByApp parameter. | 
 | 334 |     bool useAsync = false; | 
 | 335 |     int32_t consumerUsage; | 
 | 336 |     if ((res = bufferProducer->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, | 
 | 337 |             &consumerUsage)) != OK) { | 
 | 338 |         ALOGE("%s: Camera %d: Failed to query consumer usage", __FUNCTION__, | 
 | 339 |               mCameraId); | 
 | 340 |         return res; | 
 | 341 |     } | 
 | 342 |     if (consumerUsage & GraphicBuffer::USAGE_HW_TEXTURE) { | 
 | 343 |         ALOGW("%s: Camera %d: Forcing asynchronous mode for stream", | 
 | 344 |                 __FUNCTION__, mCameraId); | 
 | 345 |         useAsync = true; | 
 | 346 |     } | 
 | 347 |  | 
| Igor Murashkin | e7ee763 | 2013-06-11 18:10:18 -0700 | [diff] [blame] | 348 |     sp<IBinder> binder; | 
 | 349 |     sp<ANativeWindow> anw; | 
 | 350 |     if (bufferProducer != 0) { | 
 | 351 |         binder = bufferProducer->asBinder(); | 
| Eino-Ville Talvala | 1da3b60 | 2013-09-26 15:28:55 -0700 | [diff] [blame] | 352 |         anw = new Surface(bufferProducer, useAsync); | 
| Igor Murashkin | e7ee763 | 2013-06-11 18:10:18 -0700 | [diff] [blame] | 353 |     } | 
 | 354 |  | 
 | 355 |     // TODO: remove w,h,f since we are ignoring them | 
 | 356 |  | 
 | 357 |     if ((res = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, &width)) != OK) { | 
 | 358 |         ALOGE("%s: Camera %d: Failed to query Surface width", __FUNCTION__, | 
 | 359 |               mCameraId); | 
 | 360 |         return res; | 
 | 361 |     } | 
 | 362 |     if ((res = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, &height)) != OK) { | 
 | 363 |         ALOGE("%s: Camera %d: Failed to query Surface height", __FUNCTION__, | 
 | 364 |               mCameraId); | 
 | 365 |         return res; | 
 | 366 |     } | 
 | 367 |     if ((res = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &format)) != OK) { | 
 | 368 |         ALOGE("%s: Camera %d: Failed to query Surface format", __FUNCTION__, | 
 | 369 |               mCameraId); | 
 | 370 |         return res; | 
 | 371 |     } | 
 | 372 |  | 
 | 373 |     // FIXME: remove this override since the default format should be | 
 | 374 |     //       IMPLEMENTATION_DEFINED. b/9487482 | 
| Igor Murashkin | 1581101 | 2013-07-29 12:25:59 -0700 | [diff] [blame] | 375 |     if (format >= HAL_PIXEL_FORMAT_RGBA_8888 && | 
 | 376 |         format <= HAL_PIXEL_FORMAT_BGRA_8888) { | 
| Igor Murashkin | e7ee763 | 2013-06-11 18:10:18 -0700 | [diff] [blame] | 377 |         ALOGW("%s: Camera %d: Overriding format 0x%x to IMPLEMENTATION_DEFINED", | 
 | 378 |               __FUNCTION__, mCameraId, format); | 
 | 379 |         format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED; | 
 | 380 |     } | 
 | 381 |  | 
 | 382 |     // TODO: add startConfigure/stopConfigure call to CameraDeviceBase | 
 | 383 |     // this will make it so Camera3Device doesn't call configure_streams | 
 | 384 |     // after each call, but only once we are done with all. | 
 | 385 |  | 
 | 386 |     int streamId = -1; | 
| Zhijun He | 28c9b6f | 2014-08-08 12:00:47 -0700 | [diff] [blame^] | 387 |     res = mDevice->createStream(anw, width, height, format, &streamId); | 
| Igor Murashkin | e7ee763 | 2013-06-11 18:10:18 -0700 | [diff] [blame] | 388 |  | 
 | 389 |     if (res == OK) { | 
 | 390 |         mStreamMap.add(bufferProducer->asBinder(), streamId); | 
 | 391 |  | 
 | 392 |         ALOGV("%s: Camera %d: Successfully created a new stream ID %d", | 
 | 393 |               __FUNCTION__, mCameraId, streamId); | 
| Igor Murashkin | f8b2a6f | 2013-09-17 17:03:28 -0700 | [diff] [blame] | 394 |  | 
 | 395 |         /** | 
 | 396 |          * Set the stream transform flags to automatically | 
 | 397 |          * rotate the camera stream for preview use cases. | 
 | 398 |          */ | 
 | 399 |         int32_t transform = 0; | 
 | 400 |         res = getRotationTransformLocked(&transform); | 
 | 401 |  | 
 | 402 |         if (res != OK) { | 
 | 403 |             // Error logged by getRotationTransformLocked. | 
 | 404 |             return res; | 
 | 405 |         } | 
 | 406 |  | 
 | 407 |         res = mDevice->setStreamTransform(streamId, transform); | 
 | 408 |         if (res != OK) { | 
 | 409 |             ALOGE("%s: Failed to set stream transform (stream id %d)", | 
 | 410 |                   __FUNCTION__, streamId); | 
 | 411 |             return res; | 
 | 412 |         } | 
 | 413 |  | 
| Igor Murashkin | e7ee763 | 2013-06-11 18:10:18 -0700 | [diff] [blame] | 414 |         return streamId; | 
 | 415 |     } | 
 | 416 |  | 
 | 417 |     return res; | 
 | 418 | } | 
 | 419 |  | 
 | 420 | // Create a request object from a template. | 
 | 421 | status_t CameraDeviceClient::createDefaultRequest(int templateId, | 
 | 422 |                                                   /*out*/ | 
 | 423 |                                                   CameraMetadata* request) | 
 | 424 | { | 
 | 425 |     ATRACE_CALL(); | 
 | 426 |     ALOGV("%s (templateId = 0x%x)", __FUNCTION__, templateId); | 
 | 427 |  | 
 | 428 |     status_t res; | 
 | 429 |     if ( (res = checkPid(__FUNCTION__) ) != OK) return res; | 
 | 430 |  | 
 | 431 |     Mutex::Autolock icl(mBinderSerializationLock); | 
 | 432 |  | 
 | 433 |     if (!mDevice.get()) return DEAD_OBJECT; | 
 | 434 |  | 
 | 435 |     CameraMetadata metadata; | 
 | 436 |     if ( (res = mDevice->createDefaultRequest(templateId, &metadata) ) == OK && | 
 | 437 |         request != NULL) { | 
 | 438 |  | 
 | 439 |         request->swap(metadata); | 
 | 440 |     } | 
 | 441 |  | 
 | 442 |     return res; | 
 | 443 | } | 
 | 444 |  | 
| Igor Murashkin | 099b457 | 2013-07-12 17:52:16 -0700 | [diff] [blame] | 445 | status_t CameraDeviceClient::getCameraInfo(/*out*/CameraMetadata* info) | 
| Igor Murashkin | e7ee763 | 2013-06-11 18:10:18 -0700 | [diff] [blame] | 446 | { | 
 | 447 |     ATRACE_CALL(); | 
 | 448 |     ALOGV("%s", __FUNCTION__); | 
 | 449 |  | 
 | 450 |     status_t res = OK; | 
 | 451 |  | 
| Igor Murashkin | e7ee763 | 2013-06-11 18:10:18 -0700 | [diff] [blame] | 452 |     if ( (res = checkPid(__FUNCTION__) ) != OK) return res; | 
 | 453 |  | 
 | 454 |     Mutex::Autolock icl(mBinderSerializationLock); | 
 | 455 |  | 
 | 456 |     if (!mDevice.get()) return DEAD_OBJECT; | 
 | 457 |  | 
| Igor Murashkin | 099b457 | 2013-07-12 17:52:16 -0700 | [diff] [blame] | 458 |     if (info != NULL) { | 
 | 459 |         *info = mDevice->info(); // static camera metadata | 
 | 460 |         // TODO: merge with device-specific camera metadata | 
 | 461 |     } | 
| Igor Murashkin | e7ee763 | 2013-06-11 18:10:18 -0700 | [diff] [blame] | 462 |  | 
 | 463 |     return res; | 
 | 464 | } | 
 | 465 |  | 
| Zhijun He | 2ab500c | 2013-07-23 08:02:53 -0700 | [diff] [blame] | 466 | status_t CameraDeviceClient::waitUntilIdle() | 
 | 467 | { | 
 | 468 |     ATRACE_CALL(); | 
 | 469 |     ALOGV("%s", __FUNCTION__); | 
 | 470 |  | 
 | 471 |     status_t res = OK; | 
 | 472 |     if ( (res = checkPid(__FUNCTION__) ) != OK) return res; | 
 | 473 |  | 
 | 474 |     Mutex::Autolock icl(mBinderSerializationLock); | 
 | 475 |  | 
 | 476 |     if (!mDevice.get()) return DEAD_OBJECT; | 
 | 477 |  | 
 | 478 |     // FIXME: Also need check repeating burst. | 
 | 479 |     if (!mStreamingRequestList.isEmpty()) { | 
 | 480 |         ALOGE("%s: Camera %d: Try to waitUntilIdle when there are active streaming requests", | 
 | 481 |               __FUNCTION__, mCameraId); | 
 | 482 |         return INVALID_OPERATION; | 
 | 483 |     } | 
 | 484 |     res = mDevice->waitUntilDrained(); | 
 | 485 |     ALOGV("%s Done", __FUNCTION__); | 
 | 486 |  | 
 | 487 |     return res; | 
 | 488 | } | 
 | 489 |  | 
| Jianing Wei | cb0652e | 2014-03-12 18:29:36 -0700 | [diff] [blame] | 490 | status_t CameraDeviceClient::flush(int64_t* lastFrameNumber) { | 
| Eino-Ville Talvala | abaa51d | 2013-08-14 11:37:00 -0700 | [diff] [blame] | 491 |     ATRACE_CALL(); | 
 | 492 |     ALOGV("%s", __FUNCTION__); | 
 | 493 |  | 
 | 494 |     status_t res = OK; | 
 | 495 |     if ( (res = checkPid(__FUNCTION__) ) != OK) return res; | 
 | 496 |  | 
 | 497 |     Mutex::Autolock icl(mBinderSerializationLock); | 
 | 498 |  | 
 | 499 |     if (!mDevice.get()) return DEAD_OBJECT; | 
 | 500 |  | 
| Jianing Wei | 3c76fa3 | 2014-04-21 11:34:34 -0700 | [diff] [blame] | 501 |     mStreamingRequestList.clear(); | 
| Jianing Wei | cb0652e | 2014-03-12 18:29:36 -0700 | [diff] [blame] | 502 |     return mDevice->flush(lastFrameNumber); | 
| Eino-Ville Talvala | abaa51d | 2013-08-14 11:37:00 -0700 | [diff] [blame] | 503 | } | 
 | 504 |  | 
| Igor Murashkin | e7ee763 | 2013-06-11 18:10:18 -0700 | [diff] [blame] | 505 | status_t CameraDeviceClient::dump(int fd, const Vector<String16>& args) { | 
 | 506 |     String8 result; | 
 | 507 |     result.appendFormat("CameraDeviceClient[%d] (%p) PID: %d, dump:\n", | 
 | 508 |             mCameraId, | 
 | 509 |             getRemoteCallback()->asBinder().get(), | 
 | 510 |             mClientPid); | 
 | 511 |     result.append("  State: "); | 
 | 512 |  | 
 | 513 |     // TODO: print dynamic/request section from most recent requests | 
 | 514 |     mFrameProcessor->dump(fd, args); | 
 | 515 |  | 
 | 516 |     return dumpDevice(fd, args); | 
 | 517 | } | 
 | 518 |  | 
| Jianing Wei | cb0652e | 2014-03-12 18:29:36 -0700 | [diff] [blame] | 519 | void CameraDeviceClient::notifyError(ICameraDeviceCallbacks::CameraErrorCode errorCode, | 
 | 520 |                                      const CaptureResultExtras& resultExtras) { | 
| Eino-Ville Talvala | f1e98d8 | 2013-09-06 09:32:43 -0700 | [diff] [blame] | 521 |     // Thread safe. Don't bother locking. | 
 | 522 |     sp<ICameraDeviceCallbacks> remoteCb = getRemoteCallback(); | 
 | 523 |  | 
 | 524 |     if (remoteCb != 0) { | 
| Jianing Wei | cb0652e | 2014-03-12 18:29:36 -0700 | [diff] [blame] | 525 |         remoteCb->onDeviceError(errorCode, resultExtras); | 
| Eino-Ville Talvala | f1e98d8 | 2013-09-06 09:32:43 -0700 | [diff] [blame] | 526 |     } | 
 | 527 | } | 
 | 528 |  | 
 | 529 | void CameraDeviceClient::notifyIdle() { | 
 | 530 |     // Thread safe. Don't bother locking. | 
 | 531 |     sp<ICameraDeviceCallbacks> remoteCb = getRemoteCallback(); | 
 | 532 |  | 
 | 533 |     if (remoteCb != 0) { | 
 | 534 |         remoteCb->onDeviceIdle(); | 
 | 535 |     } | 
 | 536 | } | 
 | 537 |  | 
| Jianing Wei | cb0652e | 2014-03-12 18:29:36 -0700 | [diff] [blame] | 538 | void CameraDeviceClient::notifyShutter(const CaptureResultExtras& resultExtras, | 
| Eino-Ville Talvala | f1e98d8 | 2013-09-06 09:32:43 -0700 | [diff] [blame] | 539 |         nsecs_t timestamp) { | 
 | 540 |     // Thread safe. Don't bother locking. | 
 | 541 |     sp<ICameraDeviceCallbacks> remoteCb = getRemoteCallback(); | 
 | 542 |     if (remoteCb != 0) { | 
| Jianing Wei | cb0652e | 2014-03-12 18:29:36 -0700 | [diff] [blame] | 543 |         remoteCb->onCaptureStarted(resultExtras, timestamp); | 
| Eino-Ville Talvala | f1e98d8 | 2013-09-06 09:32:43 -0700 | [diff] [blame] | 544 |     } | 
 | 545 | } | 
 | 546 |  | 
| Igor Murashkin | e7ee763 | 2013-06-11 18:10:18 -0700 | [diff] [blame] | 547 | // TODO: refactor the code below this with IProCameraUser. | 
 | 548 | // it's 100% copy-pasted, so lets not change it right now to make it easier. | 
 | 549 |  | 
 | 550 | void CameraDeviceClient::detachDevice() { | 
 | 551 |     if (mDevice == 0) return; | 
 | 552 |  | 
 | 553 |     ALOGV("Camera %d: Stopping processors", mCameraId); | 
 | 554 |  | 
 | 555 |     mFrameProcessor->removeListener(FRAME_PROCESSOR_LISTENER_MIN_ID, | 
 | 556 |                                     FRAME_PROCESSOR_LISTENER_MAX_ID, | 
 | 557 |                                     /*listener*/this); | 
 | 558 |     mFrameProcessor->requestExit(); | 
 | 559 |     ALOGV("Camera %d: Waiting for threads", mCameraId); | 
 | 560 |     mFrameProcessor->join(); | 
 | 561 |     ALOGV("Camera %d: Disconnecting device", mCameraId); | 
 | 562 |  | 
 | 563 |     // WORKAROUND: HAL refuses to disconnect while there's streams in flight | 
 | 564 |     { | 
 | 565 |         mDevice->clearStreamingRequest(); | 
 | 566 |  | 
 | 567 |         status_t code; | 
 | 568 |         if ((code = mDevice->waitUntilDrained()) != OK) { | 
 | 569 |             ALOGE("%s: waitUntilDrained failed with code 0x%x", __FUNCTION__, | 
 | 570 |                   code); | 
 | 571 |         } | 
 | 572 |     } | 
 | 573 |  | 
 | 574 |     Camera2ClientBase::detachDevice(); | 
 | 575 | } | 
 | 576 |  | 
 | 577 | /** Device-related methods */ | 
| Jianing Wei | cb0652e | 2014-03-12 18:29:36 -0700 | [diff] [blame] | 578 | void CameraDeviceClient::onResultAvailable(const CaptureResult& result) { | 
| Igor Murashkin | e7ee763 | 2013-06-11 18:10:18 -0700 | [diff] [blame] | 579 |     ATRACE_CALL(); | 
 | 580 |     ALOGV("%s", __FUNCTION__); | 
 | 581 |  | 
| Igor Murashkin | 4fb55c1 | 2013-08-29 17:43:01 -0700 | [diff] [blame] | 582 |     // Thread-safe. No lock necessary. | 
 | 583 |     sp<ICameraDeviceCallbacks> remoteCb = mRemoteCallback; | 
 | 584 |     if (remoteCb != NULL) { | 
| Jianing Wei | cb0652e | 2014-03-12 18:29:36 -0700 | [diff] [blame] | 585 |         remoteCb->onResultReceived(result.mMetadata, result.mResultExtras); | 
| Igor Murashkin | e7ee763 | 2013-06-11 18:10:18 -0700 | [diff] [blame] | 586 |     } | 
| Igor Murashkin | e7ee763 | 2013-06-11 18:10:18 -0700 | [diff] [blame] | 587 | } | 
 | 588 |  | 
 | 589 | // TODO: move to Camera2ClientBase | 
 | 590 | bool CameraDeviceClient::enforceRequestPermissions(CameraMetadata& metadata) { | 
 | 591 |  | 
 | 592 |     const int pid = IPCThreadState::self()->getCallingPid(); | 
 | 593 |     const int selfPid = getpid(); | 
 | 594 |     camera_metadata_entry_t entry; | 
 | 595 |  | 
 | 596 |     /** | 
 | 597 |      * Mixin default important security values | 
 | 598 |      * - android.led.transmit = defaulted ON | 
 | 599 |      */ | 
 | 600 |     CameraMetadata staticInfo = mDevice->info(); | 
 | 601 |     entry = staticInfo.find(ANDROID_LED_AVAILABLE_LEDS); | 
 | 602 |     for(size_t i = 0; i < entry.count; ++i) { | 
 | 603 |         uint8_t led = entry.data.u8[i]; | 
 | 604 |  | 
 | 605 |         switch(led) { | 
 | 606 |             case ANDROID_LED_AVAILABLE_LEDS_TRANSMIT: { | 
 | 607 |                 uint8_t transmitDefault = ANDROID_LED_TRANSMIT_ON; | 
 | 608 |                 if (!metadata.exists(ANDROID_LED_TRANSMIT)) { | 
 | 609 |                     metadata.update(ANDROID_LED_TRANSMIT, | 
 | 610 |                                     &transmitDefault, 1); | 
 | 611 |                 } | 
 | 612 |                 break; | 
 | 613 |             } | 
 | 614 |         } | 
 | 615 |     } | 
 | 616 |  | 
 | 617 |     // We can do anything! | 
 | 618 |     if (pid == selfPid) { | 
 | 619 |         return true; | 
 | 620 |     } | 
 | 621 |  | 
 | 622 |     /** | 
 | 623 |      * Permission check special fields in the request | 
 | 624 |      * - android.led.transmit = android.permission.CAMERA_DISABLE_TRANSMIT | 
 | 625 |      */ | 
 | 626 |     entry = metadata.find(ANDROID_LED_TRANSMIT); | 
 | 627 |     if (entry.count > 0 && entry.data.u8[0] != ANDROID_LED_TRANSMIT_ON) { | 
 | 628 |         String16 permissionString = | 
 | 629 |             String16("android.permission.CAMERA_DISABLE_TRANSMIT_LED"); | 
 | 630 |         if (!checkCallingPermission(permissionString)) { | 
 | 631 |             const int uid = IPCThreadState::self()->getCallingUid(); | 
 | 632 |             ALOGE("Permission Denial: " | 
 | 633 |                   "can't disable transmit LED pid=%d, uid=%d", pid, uid); | 
 | 634 |             return false; | 
 | 635 |         } | 
 | 636 |     } | 
 | 637 |  | 
 | 638 |     return true; | 
 | 639 | } | 
 | 640 |  | 
| Igor Murashkin | f8b2a6f | 2013-09-17 17:03:28 -0700 | [diff] [blame] | 641 | status_t CameraDeviceClient::getRotationTransformLocked(int32_t* transform) { | 
 | 642 |     ALOGV("%s: begin", __FUNCTION__); | 
 | 643 |  | 
| Igor Murashkin | f8b2a6f | 2013-09-17 17:03:28 -0700 | [diff] [blame] | 644 |     const CameraMetadata& staticInfo = mDevice->info(); | 
| Ruben Brunk | 5698d44 | 2014-06-18 10:39:40 -0700 | [diff] [blame] | 645 |     return CameraUtils::getRotationTransform(staticInfo, transform); | 
| Igor Murashkin | f8b2a6f | 2013-09-17 17:03:28 -0700 | [diff] [blame] | 646 | } | 
 | 647 |  | 
| Igor Murashkin | e7ee763 | 2013-06-11 18:10:18 -0700 | [diff] [blame] | 648 | } // namespace android |