1 /* 2 ** 3 ** Copyright 2013, The Android Open Source Project 4 ** 5 ** Licensed under the Apache License, Version 2.0 (the "License"); 6 ** you may not use this file except in compliance with the License. 7 ** You may obtain a copy of the License at 8 ** 9 ** http://www.apache.org/licenses/LICENSE-2.0 10 ** 11 ** Unless required by applicable law or agreed to in writing, software 12 ** distributed under the License is distributed on an "AS IS" BASIS, 13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 ** See the License for the specific language governing permissions and 15 ** limitations under the License. 16 */ 17 18 //#define LOG_NDEBUG 0 19 #define LOG_TAG "IProCameraUser" 20 #include <utils/Log.h> 21 #include <stdint.h> 22 #include <sys/types.h> 23 #include <binder/Parcel.h> 24 #include <camera/IProCameraUser.h> 25 #include <gui/IGraphicBufferProducer.h> 26 #include <gui/Surface.h> 27 #include <system/camera_metadata.h> 28 29 namespace android { 30 31 typedef Parcel::WritableBlob WritableBlob; 32 typedef Parcel::ReadableBlob ReadableBlob; 33 34 enum { 35 DISCONNECT = IBinder::FIRST_CALL_TRANSACTION, 36 CONNECT, 37 EXCLUSIVE_TRY_LOCK, 38 EXCLUSIVE_LOCK, 39 EXCLUSIVE_UNLOCK, 40 HAS_EXCLUSIVE_LOCK, 41 SUBMIT_REQUEST, 42 CANCEL_REQUEST, 43 DELETE_STREAM, 44 CREATE_STREAM, 45 CREATE_DEFAULT_REQUEST, 46 GET_CAMERA_INFO, 47 }; 48 49 /** 50 * Caller becomes the owner of the new metadata 51 * 'const Parcel' doesnt prevent us from calling the read functions. 52 * which is interesting since it changes the internal state 53 * 54 * NULL can be returned when no metadata was sent, OR if there was an issue 55 * unpacking the serialized data (i.e. bad parcel or invalid structure). 56 */ 57 void readMetadata(const Parcel& data, camera_metadata_t** out) { 58 59 status_t err = OK; 60 61 camera_metadata_t* metadata = NULL; 62 63 if (out) { 64 *out = NULL; 65 } 66 67 // arg0 = metadataSize (int32) 68 int32_t metadataSizeTmp = -1; 69 if ((err = data.readInt32(&metadataSizeTmp)) != OK) { 70 ALOGE("%s: Failed to read metadata size (error %d %s)", 71 __FUNCTION__, err, strerror(-err)); 72 return; 73 } 74 const size_t metadataSize = static_cast<size_t>(metadataSizeTmp); 75 76 if (metadataSize == 0) { 77 return; 78 } 79 80 // NOTE: this doesn't make sense to me. shouldnt the blob 81 // know how big it is? why do we have to specify the size 82 // to Parcel::readBlob ? 83 84 ReadableBlob blob; 85 // arg1 = metadata (blob) 86 do { 87 if ((err = data.readBlob(metadataSize, &blob)) != OK) { 88 ALOGE("%s: Failed to read metadata blob (sized %d). Possible " 89 " serialization bug. Error %d %s", 90 __FUNCTION__, metadataSize, err, strerror(-err)); 91 break; 92 } 93 const camera_metadata_t* tmp = 94 reinterpret_cast<const camera_metadata_t*>(blob.data()); 95 96 metadata = allocate_copy_camera_metadata_checked(tmp, metadataSize); 97 } while(0); 98 blob.release(); 99 100 if (out) { 101 *out = metadata; 102 } else if (metadata != NULL) { 103 free_camera_metadata(metadata); 104 } 105 } 106 107 /** 108 * Caller retains ownership of metadata 109 * - Write 2 (int32 + blob) args in the current position 110 */ 111 void writeMetadata(Parcel& data, camera_metadata_t* metadata) { 112 // arg0 = metadataSize (int32) 113 114 if (metadata == NULL) { 115 data.writeInt32(0); 116 return; 117 } 118 119 const size_t metadataSize = get_camera_metadata_compact_size(metadata); 120 data.writeInt32(static_cast<int32_t>(metadataSize)); 121 122 // arg1 = metadata (blob) 123 WritableBlob blob; 124 { 125 data.writeBlob(metadataSize, &blob); 126 copy_camera_metadata(blob.data(), metadataSize, metadata); 127 128 IF_ALOGV() { 129 if (validate_camera_metadata_structure( 130 (const camera_metadata_t*)blob.data(), 131 &metadataSize) != OK) { 132 ALOGV("%s: Failed to validate metadata %p after writing blob", 133 __FUNCTION__, blob.data()); 134 } else { 135 ALOGV("%s: Metadata written to blob. Validation success", 136 __FUNCTION__); 137 } 138 } 139 140 // Not too big of a problem since receiving side does hard validation 141 if (validate_camera_metadata_structure(metadata, &metadataSize) != OK) { 142 ALOGW("%s: Failed to validate metadata %p before writing blob", 143 __FUNCTION__, metadata); 144 } 145 146 } 147 blob.release(); 148 } 149 150 class BpProCameraUser: public BpInterface<IProCameraUser> 151 { 152 public: 153 BpProCameraUser(const sp<IBinder>& impl) 154 : BpInterface<IProCameraUser>(impl) 155 { 156 } 157 158 // disconnect from camera service 159 void disconnect() 160 { 161 ALOGV("disconnect"); 162 Parcel data, reply; 163 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor()); 164 remote()->transact(DISCONNECT, data, &reply); 165 } 166 167 virtual status_t connect(const sp<IProCameraCallbacks>& cameraClient) 168 { 169 Parcel data, reply; 170 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor()); 171 data.writeStrongBinder(cameraClient->asBinder()); 172 remote()->transact(CONNECT, data, &reply); 173 return reply.readInt32(); 174 } 175 176 /* Shared ProCameraUser */ 177 178 virtual status_t exclusiveTryLock() 179 { 180 Parcel data, reply; 181 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor()); 182 remote()->transact(EXCLUSIVE_TRY_LOCK, data, &reply); 183 return reply.readInt32(); 184 } 185 virtual status_t exclusiveLock() 186 { 187 Parcel data, reply; 188 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor()); 189 remote()->transact(EXCLUSIVE_LOCK, data, &reply); 190 return reply.readInt32(); 191 } 192 193 virtual status_t exclusiveUnlock() 194 { 195 Parcel data, reply; 196 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor()); 197 remote()->transact(EXCLUSIVE_UNLOCK, data, &reply); 198 return reply.readInt32(); 199 } 200 201 virtual bool hasExclusiveLock() 202 { 203 Parcel data, reply; 204 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor()); 205 remote()->transact(HAS_EXCLUSIVE_LOCK, data, &reply); 206 return !!reply.readInt32(); 207 } 208 209 virtual int submitRequest(camera_metadata_t* metadata, bool streaming) 210 { 211 212 Parcel data, reply; 213 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor()); 214 215 // arg0+arg1 216 writeMetadata(data, metadata); 217 218 // arg2 = streaming (bool) 219 data.writeInt32(streaming); 220 221 remote()->transact(SUBMIT_REQUEST, data, &reply); 222 return reply.readInt32(); 223 } 224 225 virtual status_t cancelRequest(int requestId) 226 { 227 Parcel data, reply; 228 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor()); 229 data.writeInt32(requestId); 230 231 remote()->transact(CANCEL_REQUEST, data, &reply); 232 return reply.readInt32(); 233 } 234 235 virtual status_t deleteStream(int streamId) 236 { 237 Parcel data, reply; 238 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor()); 239 data.writeInt32(streamId); 240 241 remote()->transact(DELETE_STREAM, data, &reply); 242 return reply.readInt32(); 243 } 244 245 virtual status_t createStream(int width, int height, int format, 246 const sp<IGraphicBufferProducer>& bufferProducer, 247 /*out*/ 248 int* streamId) 249 { 250 Parcel data, reply; 251 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor()); 252 data.writeInt32(width); 253 data.writeInt32(height); 254 data.writeInt32(format); 255 256 sp<IBinder> b(bufferProducer->asBinder()); 257 data.writeStrongBinder(b); 258 259 remote()->transact(CREATE_STREAM, data, &reply); 260 261 int sId = reply.readInt32(); 262 if (streamId) { 263 *streamId = sId; 264 } 265 return reply.readInt32(); 266 } 267 268 // Create a request object from a template. 269 virtual status_t createDefaultRequest(int templateId, 270 /*out*/ 271 camera_metadata** request) 272 { 273 Parcel data, reply; 274 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor()); 275 data.writeInt32(templateId); 276 remote()->transact(CREATE_DEFAULT_REQUEST, data, &reply); 277 readMetadata(reply, /*out*/request); 278 return reply.readInt32(); 279 } 280 281 282 virtual status_t getCameraInfo(int cameraId, camera_metadata** info) 283 { 284 Parcel data, reply; 285 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor()); 286 data.writeInt32(cameraId); 287 remote()->transact(GET_CAMERA_INFO, data, &reply); 288 readMetadata(reply, /*out*/info); 289 return reply.readInt32(); 290 } 291 292 293 private: 294 295 296 }; 297 298 IMPLEMENT_META_INTERFACE(ProCameraUser, "android.hardware.IProCameraUser"); 299 300 // ---------------------------------------------------------------------- 301 302 status_t BnProCameraUser::onTransact( 303 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) 304 { 305 switch(code) { 306 case DISCONNECT: { 307 ALOGV("DISCONNECT"); 308 CHECK_INTERFACE(IProCameraUser, data, reply); 309 disconnect(); 310 return NO_ERROR; 311 } break; 312 case CONNECT: { 313 CHECK_INTERFACE(IProCameraUser, data, reply); 314 sp<IProCameraCallbacks> cameraClient = 315 interface_cast<IProCameraCallbacks>(data.readStrongBinder()); 316 reply->writeInt32(connect(cameraClient)); 317 return NO_ERROR; 318 } break; 319 320 /* Shared ProCameraUser */ 321 case EXCLUSIVE_TRY_LOCK: { 322 CHECK_INTERFACE(IProCameraUser, data, reply); 323 reply->writeInt32(exclusiveTryLock()); 324 return NO_ERROR; 325 } break; 326 case EXCLUSIVE_LOCK: { 327 CHECK_INTERFACE(IProCameraUser, data, reply); 328 reply->writeInt32(exclusiveLock()); 329 return NO_ERROR; 330 } break; 331 case EXCLUSIVE_UNLOCK: { 332 CHECK_INTERFACE(IProCameraUser, data, reply); 333 reply->writeInt32(exclusiveUnlock()); 334 return NO_ERROR; 335 } break; 336 case HAS_EXCLUSIVE_LOCK: { 337 CHECK_INTERFACE(IProCameraUser, data, reply); 338 reply->writeInt32(hasExclusiveLock()); 339 return NO_ERROR; 340 } break; 341 case SUBMIT_REQUEST: { 342 CHECK_INTERFACE(IProCameraUser, data, reply); 343 camera_metadata_t* metadata; 344 readMetadata(data, /*out*/&metadata); 345 346 // arg2 = streaming (bool) 347 bool streaming = data.readInt32(); 348 349 // return code: requestId (int32) 350 reply->writeInt32(submitRequest(metadata, streaming)); 351 352 return NO_ERROR; 353 } break; 354 case CANCEL_REQUEST: { 355 CHECK_INTERFACE(IProCameraUser, data, reply); 356 int requestId = data.readInt32(); 357 reply->writeInt32(cancelRequest(requestId)); 358 return NO_ERROR; 359 } break; 360 case DELETE_STREAM: { 361 CHECK_INTERFACE(IProCameraUser, data, reply); 362 int streamId = data.readInt32(); 363 reply->writeInt32(deleteStream(streamId)); 364 return NO_ERROR; 365 } break; 366 case CREATE_STREAM: { 367 CHECK_INTERFACE(IProCameraUser, data, reply); 368 int width, height, format; 369 370 width = data.readInt32(); 371 height = data.readInt32(); 372 format = data.readInt32(); 373 374 sp<IGraphicBufferProducer> bp = 375 interface_cast<IGraphicBufferProducer>(data.readStrongBinder()); 376 377 int streamId = -1; 378 status_t ret; 379 ret = createStream(width, height, format, bp, &streamId); 380 381 reply->writeInt32(streamId); 382 reply->writeInt32(ret); 383 384 return NO_ERROR; 385 } break; 386 387 case CREATE_DEFAULT_REQUEST: { 388 CHECK_INTERFACE(IProCameraUser, data, reply); 389 390 int templateId = data.readInt32(); 391 392 camera_metadata_t* request = NULL; 393 status_t ret; 394 ret = createDefaultRequest(templateId, &request); 395 396 writeMetadata(*reply, request); 397 reply->writeInt32(ret); 398 399 free_camera_metadata(request); 400 401 return NO_ERROR; 402 } break; 403 case GET_CAMERA_INFO: { 404 CHECK_INTERFACE(IProCameraUser, data, reply); 405 406 int cameraId = data.readInt32(); 407 408 camera_metadata_t* info = NULL; 409 status_t ret; 410 ret = getCameraInfo(cameraId, &info); 411 412 writeMetadata(*reply, info); 413 reply->writeInt32(ret); 414 415 free_camera_metadata(info); 416 417 return NO_ERROR; 418 } break; 419 default: 420 return BBinder::onTransact(code, data, reply, flags); 421 } 422 } 423 424 // ---------------------------------------------------------------------------- 425 426 }; // namespace android 427