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