Home | History | Annotate | Download | only in camera
      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