CameraBase.cpp revision f51fca277eb5b86bd0b2e3fc90ecb2b63089de29
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#include <cutils/properties.h> 24 25#include <android/hardware/ICameraService.h> 26 27#include <binder/IPCThreadState.h> 28#include <binder/IServiceManager.h> 29#include <binder/IMemory.h> 30 31#include <camera/CameraBase.h> 32 33// needed to instantiate 34#include <camera/Camera.h> 35 36#include <system/camera_metadata.h> 37 38namespace android { 39 40namespace hardware { 41 42status_t CameraInfo::writeToParcel(android::Parcel* parcel) const { 43 status_t res; 44 res = parcel->writeInt32(facing); 45 if (res != OK) return res; 46 res = parcel->writeInt32(orientation); 47 return res; 48} 49 50status_t CameraInfo::readFromParcel(const android::Parcel* parcel) { 51 status_t res; 52 res = parcel->readInt32(&facing); 53 if (res != OK) return res; 54 res = parcel->readInt32(&orientation); 55 return res; 56} 57 58status_t CameraStatus::writeToParcel(android::Parcel* parcel) const { 59 status_t res; 60 res = parcel->writeString8(cameraId); 61 if (res != OK) return res; 62 res = parcel->writeInt32(status); 63 return res; 64} 65 66status_t CameraStatus::readFromParcel(const android::Parcel* parcel) { 67 status_t res; 68 res = parcel->readString8(&cameraId); 69 if (res != OK) return res; 70 res = parcel->readInt32(&status); 71 return res; 72} 73 74} // namespace hardware 75 76namespace { 77 sp<::android::hardware::ICameraService> gCameraService; 78 const int kCameraServicePollDelay = 500000; // 0.5s 79 const char* kCameraServiceName = "media.camera"; 80 81 Mutex gLock; 82 83 class DeathNotifier : public IBinder::DeathRecipient 84 { 85 public: 86 DeathNotifier() { 87 } 88 89 virtual void binderDied(const wp<IBinder>& /*who*/) { 90 ALOGV("binderDied"); 91 Mutex::Autolock _l(gLock); 92 gCameraService.clear(); 93 ALOGW("Camera service died!"); 94 } 95 }; 96 97 sp<DeathNotifier> gDeathNotifier; 98}; // namespace anonymous 99 100/////////////////////////////////////////////////////////// 101// CameraBase definition 102/////////////////////////////////////////////////////////// 103 104// establish binder interface to camera service 105template <typename TCam, typename TCamTraits> 106const sp<::android::hardware::ICameraService>& CameraBase<TCam, TCamTraits>::getCameraService() 107{ 108 Mutex::Autolock _l(gLock); 109 if (gCameraService.get() == 0) { 110 char value[PROPERTY_VALUE_MAX]; 111 property_get("config.disable_cameraservice", value, "0"); 112 if (strncmp(value, "0", 2) != 0 && strncasecmp(value, "false", 6) != 0) { 113 return gCameraService; 114 } 115 116 sp<IServiceManager> sm = defaultServiceManager(); 117 sp<IBinder> binder; 118 do { 119 binder = sm->getService(String16(kCameraServiceName)); 120 if (binder != 0) { 121 break; 122 } 123 ALOGW("CameraService not published, waiting..."); 124 usleep(kCameraServicePollDelay); 125 } while(true); 126 if (gDeathNotifier == NULL) { 127 gDeathNotifier = new DeathNotifier(); 128 } 129 binder->linkToDeath(gDeathNotifier); 130 gCameraService = interface_cast<::android::hardware::ICameraService>(binder); 131 } 132 ALOGE_IF(gCameraService == 0, "no CameraService!?"); 133 return gCameraService; 134} 135 136template <typename TCam, typename TCamTraits> 137sp<TCam> CameraBase<TCam, TCamTraits>::connect(int cameraId, 138 const String16& clientPackageName, 139 int clientUid, int clientPid) 140{ 141 ALOGV("%s: connect", __FUNCTION__); 142 sp<TCam> c = new TCam(cameraId); 143 sp<TCamCallbacks> cl = c; 144 const sp<::android::hardware::ICameraService>& cs = getCameraService(); 145 146 binder::Status ret; 147 if (cs != nullptr) { 148 TCamConnectService fnConnectService = TCamTraits::fnConnectService; 149 ret = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid, 150 clientPid, /*out*/ &c->mCamera); 151 } 152 if (ret.isOk() && c->mCamera != nullptr) { 153 IInterface::asBinder(c->mCamera)->linkToDeath(c); 154 c->mStatus = NO_ERROR; 155 } else { 156 ALOGW("An error occurred while connecting to camera %d: %s", cameraId, 157 (cs == nullptr) ? "Service not available" : ret.toString8().string()); 158 c.clear(); 159 } 160 return c; 161} 162 163template <typename TCam, typename TCamTraits> 164void CameraBase<TCam, TCamTraits>::disconnect() 165{ 166 ALOGV("%s: disconnect", __FUNCTION__); 167 if (mCamera != 0) { 168 mCamera->disconnect(); 169 IInterface::asBinder(mCamera)->unlinkToDeath(this); 170 mCamera = 0; 171 } 172 ALOGV("%s: disconnect (done)", __FUNCTION__); 173} 174 175template <typename TCam, typename TCamTraits> 176CameraBase<TCam, TCamTraits>::CameraBase(int cameraId) : 177 mStatus(UNKNOWN_ERROR), 178 mCameraId(cameraId) 179{ 180} 181 182template <typename TCam, typename TCamTraits> 183CameraBase<TCam, TCamTraits>::~CameraBase() 184{ 185} 186 187template <typename TCam, typename TCamTraits> 188sp<typename TCamTraits::TCamUser> CameraBase<TCam, TCamTraits>::remote() 189{ 190 return mCamera; 191} 192 193template <typename TCam, typename TCamTraits> 194status_t CameraBase<TCam, TCamTraits>::getStatus() 195{ 196 return mStatus; 197} 198 199template <typename TCam, typename TCamTraits> 200void CameraBase<TCam, TCamTraits>::binderDied(const wp<IBinder>& /*who*/) { 201 ALOGW("mediaserver's remote binder Camera object died"); 202 notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_SERVER_DIED, /*ext2*/0); 203} 204 205template <typename TCam, typename TCamTraits> 206void CameraBase<TCam, TCamTraits>::setListener(const sp<TCamListener>& listener) 207{ 208 Mutex::Autolock _l(mLock); 209 mListener = listener; 210} 211 212// callback from camera service 213template <typename TCam, typename TCamTraits> 214void CameraBase<TCam, TCamTraits>::notifyCallback(int32_t msgType, 215 int32_t ext1, 216 int32_t ext2) 217{ 218 sp<TCamListener> listener; 219 { 220 Mutex::Autolock _l(mLock); 221 listener = mListener; 222 } 223 if (listener != NULL) { 224 listener->notify(msgType, ext1, ext2); 225 } 226} 227 228template <typename TCam, typename TCamTraits> 229int CameraBase<TCam, TCamTraits>::getNumberOfCameras() { 230 const sp<::android::hardware::ICameraService> cs = getCameraService(); 231 232 if (!cs.get()) { 233 // as required by the public Java APIs 234 return 0; 235 } 236 int32_t count; 237 binder::Status res = cs->getNumberOfCameras( 238 ::android::hardware::ICameraService::CAMERA_TYPE_BACKWARD_COMPATIBLE, 239 &count); 240 if (!res.isOk()) { 241 ALOGE("Error reading number of cameras: %s", 242 res.toString8().string()); 243 count = 0; 244 } 245 return count; 246} 247 248// this can be in BaseCamera but it should be an instance method 249template <typename TCam, typename TCamTraits> 250status_t CameraBase<TCam, TCamTraits>::getCameraInfo(int cameraId, 251 struct hardware::CameraInfo* cameraInfo) { 252 const sp<::android::hardware::ICameraService>& cs = getCameraService(); 253 if (cs == 0) return UNKNOWN_ERROR; 254 binder::Status res = cs->getCameraInfo(cameraId, cameraInfo); 255 return res.isOk() ? OK : res.serviceSpecificErrorCode(); 256} 257 258template class CameraBase<Camera>; 259 260} // namespace android 261