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