Home | History | Annotate | Download | only in camera
      1 /*
      2 **
      3 ** Copyright (C) 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 "CameraBase"
     20 #include <utils/Log.h>
     21 #include <utils/threads.h>
     22 #include <utils/Mutex.h>
     23 
     24 #include <binder/IPCThreadState.h>
     25 #include <binder/IServiceManager.h>
     26 #include <binder/IMemory.h>
     27 
     28 #include <camera/CameraBase.h>
     29 #include <camera/ICameraService.h>
     30 
     31 // needed to instantiate
     32 #include <camera/ProCamera.h>
     33 #include <camera/Camera.h>
     34 
     35 #include <system/camera_metadata.h>
     36 
     37 namespace android {
     38 
     39 namespace {
     40     sp<ICameraService>        gCameraService;
     41     const int                 kCameraServicePollDelay = 500000; // 0.5s
     42     const char*               kCameraServiceName      = "media.camera";
     43 
     44     Mutex                     gLock;
     45 
     46     class DeathNotifier : public IBinder::DeathRecipient
     47     {
     48     public:
     49         DeathNotifier() {
     50         }
     51 
     52         virtual void binderDied(const wp<IBinder>& who) {
     53             ALOGV("binderDied");
     54             Mutex::Autolock _l(gLock);
     55             gCameraService.clear();
     56             ALOGW("Camera service died!");
     57         }
     58     };
     59 
     60     sp<DeathNotifier>         gDeathNotifier;
     61 }; // namespace anonymous
     62 
     63 ///////////////////////////////////////////////////////////
     64 // CameraBase definition
     65 ///////////////////////////////////////////////////////////
     66 
     67 // establish binder interface to camera service
     68 template <typename TCam, typename TCamTraits>
     69 const sp<ICameraService>& CameraBase<TCam, TCamTraits>::getCameraService()
     70 {
     71     Mutex::Autolock _l(gLock);
     72     if (gCameraService.get() == 0) {
     73         sp<IServiceManager> sm = defaultServiceManager();
     74         sp<IBinder> binder;
     75         do {
     76             binder = sm->getService(String16(kCameraServiceName));
     77             if (binder != 0) {
     78                 break;
     79             }
     80             ALOGW("CameraService not published, waiting...");
     81             usleep(kCameraServicePollDelay);
     82         } while(true);
     83         if (gDeathNotifier == NULL) {
     84             gDeathNotifier = new DeathNotifier();
     85         }
     86         binder->linkToDeath(gDeathNotifier);
     87         gCameraService = interface_cast<ICameraService>(binder);
     88     }
     89     ALOGE_IF(gCameraService == 0, "no CameraService!?");
     90     return gCameraService;
     91 }
     92 
     93 template <typename TCam, typename TCamTraits>
     94 sp<TCam> CameraBase<TCam, TCamTraits>::connect(int cameraId,
     95                                                const String16& clientPackageName,
     96                                                int clientUid)
     97 {
     98     ALOGV("%s: connect", __FUNCTION__);
     99     sp<TCam> c = new TCam(cameraId);
    100     sp<TCamCallbacks> cl = c;
    101     status_t status = NO_ERROR;
    102     const sp<ICameraService>& cs = getCameraService();
    103 
    104     if (cs != 0) {
    105         TCamConnectService fnConnectService = TCamTraits::fnConnectService;
    106         status = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid,
    107                                              /*out*/ c->mCamera);
    108     }
    109     if (status == OK && c->mCamera != 0) {
    110         c->mCamera->asBinder()->linkToDeath(c);
    111         c->mStatus = NO_ERROR;
    112     } else {
    113         ALOGW("An error occurred while connecting to camera: %d", cameraId);
    114         c.clear();
    115     }
    116     return c;
    117 }
    118 
    119 template <typename TCam, typename TCamTraits>
    120 void CameraBase<TCam, TCamTraits>::disconnect()
    121 {
    122     ALOGV("%s: disconnect", __FUNCTION__);
    123     if (mCamera != 0) {
    124         mCamera->disconnect();
    125         mCamera->asBinder()->unlinkToDeath(this);
    126         mCamera = 0;
    127     }
    128     ALOGV("%s: disconnect (done)", __FUNCTION__);
    129 }
    130 
    131 template <typename TCam, typename TCamTraits>
    132 CameraBase<TCam, TCamTraits>::CameraBase(int cameraId) :
    133     mStatus(UNKNOWN_ERROR),
    134     mCameraId(cameraId)
    135 {
    136 }
    137 
    138 template <typename TCam, typename TCamTraits>
    139 CameraBase<TCam, TCamTraits>::~CameraBase()
    140 {
    141 }
    142 
    143 template <typename TCam, typename TCamTraits>
    144 sp<typename TCamTraits::TCamUser> CameraBase<TCam, TCamTraits>::remote()
    145 {
    146     return mCamera;
    147 }
    148 
    149 template <typename TCam, typename TCamTraits>
    150 status_t CameraBase<TCam, TCamTraits>::getStatus()
    151 {
    152     return mStatus;
    153 }
    154 
    155 template <typename TCam, typename TCamTraits>
    156 void CameraBase<TCam, TCamTraits>::binderDied(const wp<IBinder>& who) {
    157     ALOGW("mediaserver's remote binder Camera object died");
    158     notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_SERVER_DIED, /*ext2*/0);
    159 }
    160 
    161 template <typename TCam, typename TCamTraits>
    162 void CameraBase<TCam, TCamTraits>::setListener(const sp<TCamListener>& listener)
    163 {
    164     Mutex::Autolock _l(mLock);
    165     mListener = listener;
    166 }
    167 
    168 // callback from camera service
    169 template <typename TCam, typename TCamTraits>
    170 void CameraBase<TCam, TCamTraits>::notifyCallback(int32_t msgType,
    171                                                   int32_t ext1,
    172                                                   int32_t ext2)
    173 {
    174     sp<TCamListener> listener;
    175     {
    176         Mutex::Autolock _l(mLock);
    177         listener = mListener;
    178     }
    179     if (listener != NULL) {
    180         listener->notify(msgType, ext1, ext2);
    181     }
    182 }
    183 
    184 template <typename TCam, typename TCamTraits>
    185 int CameraBase<TCam, TCamTraits>::getNumberOfCameras() {
    186     const sp<ICameraService> cs = getCameraService();
    187 
    188     if (!cs.get()) {
    189         // as required by the public Java APIs
    190         return 0;
    191     }
    192     return cs->getNumberOfCameras();
    193 }
    194 
    195 // this can be in BaseCamera but it should be an instance method
    196 template <typename TCam, typename TCamTraits>
    197 status_t CameraBase<TCam, TCamTraits>::getCameraInfo(int cameraId,
    198                                struct CameraInfo* cameraInfo) {
    199     const sp<ICameraService>& cs = getCameraService();
    200     if (cs == 0) return UNKNOWN_ERROR;
    201     return cs->getCameraInfo(cameraId, cameraInfo);
    202 }
    203 
    204 template <typename TCam, typename TCamTraits>
    205 status_t CameraBase<TCam, TCamTraits>::addServiceListener(
    206                             const sp<ICameraServiceListener>& listener) {
    207     const sp<ICameraService>& cs = getCameraService();
    208     if (cs == 0) return UNKNOWN_ERROR;
    209     return cs->addListener(listener);
    210 }
    211 
    212 template <typename TCam, typename TCamTraits>
    213 status_t CameraBase<TCam, TCamTraits>::removeServiceListener(
    214                             const sp<ICameraServiceListener>& listener) {
    215     const sp<ICameraService>& cs = getCameraService();
    216     if (cs == 0) return UNKNOWN_ERROR;
    217     return cs->removeListener(listener);
    218 }
    219 
    220 template class CameraBase<ProCamera>;
    221 template class CameraBase<Camera>;
    222 
    223 } // namespace android
    224