CameraBase.cpp revision 0f61d8f14aa368c9cd7076528e8096e10ed100a0
1c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin/* 2c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin** 3c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin** Copyright (C) 2013, The Android Open Source Project 4c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin** 5c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin** Licensed under the Apache License, Version 2.0 (the "License"); 6c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin** you may not use this file except in compliance with the License. 7c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin** You may obtain a copy of the License at 8c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin** 9c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin** http://www.apache.org/licenses/LICENSE-2.0 10c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin** 11c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin** Unless required by applicable law or agreed to in writing, software 12c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin** distributed under the License is distributed on an "AS IS" BASIS, 13c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin** See the License for the specific language governing permissions and 15c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin** limitations under the License. 16c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin*/ 17c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin 18c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin//#define LOG_NDEBUG 0 19c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin#define LOG_TAG "CameraBase" 20c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin#include <utils/Log.h> 21c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin#include <utils/threads.h> 22c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin#include <utils/Mutex.h> 23c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin 24c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin#include <binder/IPCThreadState.h> 25c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin#include <binder/IServiceManager.h> 26c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin#include <binder/IMemory.h> 27c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin 28c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin#include <camera/CameraBase.h> 29c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin#include <camera/ICameraService.h> 30c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin 31c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin// needed to instantiate 32c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin#include <camera/ProCamera.h> 33c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin#include <camera/Camera.h> 34c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin 35c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin#include <system/camera_metadata.h> 36c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin 37c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkinnamespace android { 38c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin 39c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkinnamespace { 40c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin sp<ICameraService> gCameraService; 41c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin const int kCameraServicePollDelay = 500000; // 0.5s 42c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin const char* kCameraServiceName = "media.camera"; 43c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin 44c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin Mutex gLock; 45c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin 46c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin class DeathNotifier : public IBinder::DeathRecipient 47c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin { 48c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin public: 49c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin DeathNotifier() { 50c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin } 51c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin 52c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin virtual void binderDied(const wp<IBinder>& who) { 53c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin ALOGV("binderDied"); 54c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin Mutex::Autolock _l(gLock); 55c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin gCameraService.clear(); 56c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin ALOGW("Camera service died!"); 57c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin } 58c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin }; 59c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin 60c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin sp<DeathNotifier> gDeathNotifier; 61c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin}; // namespace anonymous 62c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin 63c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin/////////////////////////////////////////////////////////// 64c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin// CameraBase definition 65c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin/////////////////////////////////////////////////////////// 66c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin 67c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin// establish binder interface to camera service 68c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkintemplate <typename TCam, typename TCamTraits> 69c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkinconst sp<ICameraService>& CameraBase<TCam, TCamTraits>::getCameraService() 70c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin{ 71c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin Mutex::Autolock _l(gLock); 72c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin if (gCameraService.get() == 0) { 73c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin sp<IServiceManager> sm = defaultServiceManager(); 74c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin sp<IBinder> binder; 75c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin do { 76c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin binder = sm->getService(String16(kCameraServiceName)); 77c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin if (binder != 0) { 78c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin break; 79c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin } 80c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin ALOGW("CameraService not published, waiting..."); 81c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin usleep(kCameraServicePollDelay); 82c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin } while(true); 83c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin if (gDeathNotifier == NULL) { 84c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin gDeathNotifier = new DeathNotifier(); 85c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin } 86c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin binder->linkToDeath(gDeathNotifier); 87c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin gCameraService = interface_cast<ICameraService>(binder); 88c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin } 89c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin ALOGE_IF(gCameraService == 0, "no CameraService!?"); 90c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin return gCameraService; 91c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin} 92c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin 93c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkintemplate <typename TCam, typename TCamTraits> 94c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkinsp<TCam> CameraBase<TCam, TCamTraits>::connect(int cameraId, 950f61d8f14aa368c9cd7076528e8096e10ed100a0Ruben Brunk const String16& clientPackageName, 96c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin int clientUid) 97c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin{ 98c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin ALOGV("%s: connect", __FUNCTION__); 99c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin sp<TCam> c = new TCam(cameraId); 100c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin sp<TCamCallbacks> cl = c; 1010f61d8f14aa368c9cd7076528e8096e10ed100a0Ruben Brunk status_t status = NO_ERROR; 102c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin const sp<ICameraService>& cs = getCameraService(); 1030f61d8f14aa368c9cd7076528e8096e10ed100a0Ruben Brunk 104c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin if (cs != 0) { 1050f61d8f14aa368c9cd7076528e8096e10ed100a0Ruben Brunk TCamConnectService fnConnectService = TCamTraits::fnConnectService; 1060f61d8f14aa368c9cd7076528e8096e10ed100a0Ruben Brunk status = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid, 1070f61d8f14aa368c9cd7076528e8096e10ed100a0Ruben Brunk /*out*/ c->mCamera); 108c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin } 1090f61d8f14aa368c9cd7076528e8096e10ed100a0Ruben Brunk if (status == OK && c->mCamera != 0) { 110c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin c->mCamera->asBinder()->linkToDeath(c); 111c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin c->mStatus = NO_ERROR; 112c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin } else { 1130f61d8f14aa368c9cd7076528e8096e10ed100a0Ruben Brunk ALOGW("An error occurred while connecting to camera: %d", cameraId); 114c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin c.clear(); 115c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin } 116c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin return c; 117c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin} 118c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin 119c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkintemplate <typename TCam, typename TCamTraits> 120c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkinvoid CameraBase<TCam, TCamTraits>::disconnect() 121c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin{ 122c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin ALOGV("%s: disconnect", __FUNCTION__); 123c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin if (mCamera != 0) { 124c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin mCamera->disconnect(); 125c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin mCamera->asBinder()->unlinkToDeath(this); 126c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin mCamera = 0; 127c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin } 128c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin ALOGV("%s: disconnect (done)", __FUNCTION__); 129c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin} 130c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin 131c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkintemplate <typename TCam, typename TCamTraits> 132c073ba525404f3416c2824c435d3d926a9892f1bIgor MurashkinCameraBase<TCam, TCamTraits>::CameraBase(int cameraId) : 133c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin mStatus(UNKNOWN_ERROR), 134c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin mCameraId(cameraId) 135c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin{ 136c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin} 137c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin 138c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkintemplate <typename TCam, typename TCamTraits> 139c073ba525404f3416c2824c435d3d926a9892f1bIgor MurashkinCameraBase<TCam, TCamTraits>::~CameraBase() 140c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin{ 141c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin} 142c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin 143c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkintemplate <typename TCam, typename TCamTraits> 144c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkinsp<typename TCamTraits::TCamUser> CameraBase<TCam, TCamTraits>::remote() 145c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin{ 146c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin return mCamera; 147c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin} 148c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin 149c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkintemplate <typename TCam, typename TCamTraits> 150c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkinstatus_t CameraBase<TCam, TCamTraits>::getStatus() 151c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin{ 152c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin return mStatus; 153c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin} 154c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin 155c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkintemplate <typename TCam, typename TCamTraits> 156c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkinvoid CameraBase<TCam, TCamTraits>::binderDied(const wp<IBinder>& who) { 157c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin ALOGW("mediaserver's remote binder Camera object died"); 158c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_SERVER_DIED, /*ext2*/0); 159c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin} 160c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin 161c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkintemplate <typename TCam, typename TCamTraits> 162c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkinvoid CameraBase<TCam, TCamTraits>::setListener(const sp<TCamListener>& listener) 163c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin{ 164c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin Mutex::Autolock _l(mLock); 165c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin mListener = listener; 166c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin} 167c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin 168c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin// callback from camera service 169c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkintemplate <typename TCam, typename TCamTraits> 170c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkinvoid CameraBase<TCam, TCamTraits>::notifyCallback(int32_t msgType, 171c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin int32_t ext1, 172c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin int32_t ext2) 173c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin{ 174c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin sp<TCamListener> listener; 175c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin { 176c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin Mutex::Autolock _l(mLock); 177c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin listener = mListener; 178c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin } 179c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin if (listener != NULL) { 180c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin listener->notify(msgType, ext1, ext2); 181c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin } 182c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin} 183c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin 184c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkintemplate <typename TCam, typename TCamTraits> 185c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkinint CameraBase<TCam, TCamTraits>::getNumberOfCameras() { 186c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin const sp<ICameraService> cs = getCameraService(); 187c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin 188c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin if (!cs.get()) { 189c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin // as required by the public Java APIs 190c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin return 0; 191c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin } 192c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin return cs->getNumberOfCameras(); 193c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin} 194c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin 195c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin// this can be in BaseCamera but it should be an instance method 196c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkintemplate <typename TCam, typename TCamTraits> 197c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkinstatus_t CameraBase<TCam, TCamTraits>::getCameraInfo(int cameraId, 198c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin struct CameraInfo* cameraInfo) { 199c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin const sp<ICameraService>& cs = getCameraService(); 200c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin if (cs == 0) return UNKNOWN_ERROR; 201c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin return cs->getCameraInfo(cameraId, cameraInfo); 202c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin} 203c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin 204bfc9915f482520eb9676c6d2dbf7f1ac078d937dIgor Murashkintemplate <typename TCam, typename TCamTraits> 205bfc9915f482520eb9676c6d2dbf7f1ac078d937dIgor Murashkinstatus_t CameraBase<TCam, TCamTraits>::addServiceListener( 206bfc9915f482520eb9676c6d2dbf7f1ac078d937dIgor Murashkin const sp<ICameraServiceListener>& listener) { 207bfc9915f482520eb9676c6d2dbf7f1ac078d937dIgor Murashkin const sp<ICameraService>& cs = getCameraService(); 208bfc9915f482520eb9676c6d2dbf7f1ac078d937dIgor Murashkin if (cs == 0) return UNKNOWN_ERROR; 209bfc9915f482520eb9676c6d2dbf7f1ac078d937dIgor Murashkin return cs->addListener(listener); 210bfc9915f482520eb9676c6d2dbf7f1ac078d937dIgor Murashkin} 211bfc9915f482520eb9676c6d2dbf7f1ac078d937dIgor Murashkin 212bfc9915f482520eb9676c6d2dbf7f1ac078d937dIgor Murashkintemplate <typename TCam, typename TCamTraits> 213bfc9915f482520eb9676c6d2dbf7f1ac078d937dIgor Murashkinstatus_t CameraBase<TCam, TCamTraits>::removeServiceListener( 214bfc9915f482520eb9676c6d2dbf7f1ac078d937dIgor Murashkin const sp<ICameraServiceListener>& listener) { 215bfc9915f482520eb9676c6d2dbf7f1ac078d937dIgor Murashkin const sp<ICameraService>& cs = getCameraService(); 216bfc9915f482520eb9676c6d2dbf7f1ac078d937dIgor Murashkin if (cs == 0) return UNKNOWN_ERROR; 217bfc9915f482520eb9676c6d2dbf7f1ac078d937dIgor Murashkin return cs->removeListener(listener); 218bfc9915f482520eb9676c6d2dbf7f1ac078d937dIgor Murashkin} 219bfc9915f482520eb9676c6d2dbf7f1ac078d937dIgor Murashkin 220c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkintemplate class CameraBase<ProCamera>; 221c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkintemplate class CameraBase<Camera>; 222c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin 223c073ba525404f3416c2824c435d3d926a9892f1bIgor Murashkin} // namespace android 224