blob: 5d50aa8223542d18ddf701439875306da566d422 [file] [log] [blame]
Igor Murashkinc073ba52013-02-26 14:32:34 -08001/*
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
Igor Murashkinc073ba52013-02-26 14:32:34 -080032#include <camera/Camera.h>
33
34#include <system/camera_metadata.h>
35
36namespace android {
37
38namespace {
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:
48 DeathNotifier() {
49 }
50
Mark Salyzyn7b73e712014-06-09 16:28:21 -070051 virtual void binderDied(const wp<IBinder>& /*who*/) {
Igor Murashkinc073ba52013-02-26 14:32:34 -080052 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
67template <typename TCam, typename TCamTraits>
68const 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
92template <typename TCam, typename TCamTraits>
93sp<TCam> CameraBase<TCam, TCamTraits>::connect(int cameraId,
Svetoslav Ganov280405a2015-05-12 02:19:27 +000094 const String16& clientPackageName,
Igor Murashkinc073ba52013-02-26 14:32:34 -080095 int clientUid)
96{
97 ALOGV("%s: connect", __FUNCTION__);
98 sp<TCam> c = new TCam(cameraId);
99 sp<TCamCallbacks> cl = c;
Ruben Brunk0f61d8f2013-08-08 13:07:18 -0700100 status_t status = NO_ERROR;
Igor Murashkinc073ba52013-02-26 14:32:34 -0800101 const sp<ICameraService>& cs = getCameraService();
Ruben Brunk0f61d8f2013-08-08 13:07:18 -0700102
Igor Murashkinc073ba52013-02-26 14:32:34 -0800103 if (cs != 0) {
Ruben Brunk0f61d8f2013-08-08 13:07:18 -0700104 TCamConnectService fnConnectService = TCamTraits::fnConnectService;
Svetoslav Ganov280405a2015-05-12 02:19:27 +0000105 status = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid,
Ruben Brunk0f61d8f2013-08-08 13:07:18 -0700106 /*out*/ c->mCamera);
Igor Murashkinc073ba52013-02-26 14:32:34 -0800107 }
Ruben Brunk0f61d8f2013-08-08 13:07:18 -0700108 if (status == OK && c->mCamera != 0) {
Marco Nelissen06b46062014-11-14 07:58:25 -0800109 IInterface::asBinder(c->mCamera)->linkToDeath(c);
Igor Murashkinc073ba52013-02-26 14:32:34 -0800110 c->mStatus = NO_ERROR;
111 } else {
Ruben Brunk0f61d8f2013-08-08 13:07:18 -0700112 ALOGW("An error occurred while connecting to camera: %d", cameraId);
Igor Murashkinc073ba52013-02-26 14:32:34 -0800113 c.clear();
114 }
115 return c;
116}
117
118template <typename TCam, typename TCamTraits>
119void CameraBase<TCam, TCamTraits>::disconnect()
120{
121 ALOGV("%s: disconnect", __FUNCTION__);
122 if (mCamera != 0) {
123 mCamera->disconnect();
Marco Nelissen06b46062014-11-14 07:58:25 -0800124 IInterface::asBinder(mCamera)->unlinkToDeath(this);
Igor Murashkinc073ba52013-02-26 14:32:34 -0800125 mCamera = 0;
126 }
127 ALOGV("%s: disconnect (done)", __FUNCTION__);
128}
129
130template <typename TCam, typename TCamTraits>
131CameraBase<TCam, TCamTraits>::CameraBase(int cameraId) :
132 mStatus(UNKNOWN_ERROR),
133 mCameraId(cameraId)
134{
135}
136
137template <typename TCam, typename TCamTraits>
138CameraBase<TCam, TCamTraits>::~CameraBase()
139{
140}
141
142template <typename TCam, typename TCamTraits>
143sp<typename TCamTraits::TCamUser> CameraBase<TCam, TCamTraits>::remote()
144{
145 return mCamera;
146}
147
148template <typename TCam, typename TCamTraits>
149status_t CameraBase<TCam, TCamTraits>::getStatus()
150{
151 return mStatus;
152}
153
154template <typename TCam, typename TCamTraits>
Mark Salyzyn7b73e712014-06-09 16:28:21 -0700155void CameraBase<TCam, TCamTraits>::binderDied(const wp<IBinder>& /*who*/) {
Igor Murashkinc073ba52013-02-26 14:32:34 -0800156 ALOGW("mediaserver's remote binder Camera object died");
157 notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_SERVER_DIED, /*ext2*/0);
158}
159
160template <typename TCam, typename TCamTraits>
161void CameraBase<TCam, TCamTraits>::setListener(const sp<TCamListener>& listener)
162{
163 Mutex::Autolock _l(mLock);
164 mListener = listener;
165}
166
167// callback from camera service
168template <typename TCam, typename TCamTraits>
169void 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
Igor Murashkinc073ba52013-02-26 14:32:34 -0800183template <typename TCam, typename TCamTraits>
184int 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
195template <typename TCam, typename TCamTraits>
196status_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
Igor Murashkinbfc99152013-02-27 12:55:20 -0800203template <typename TCam, typename TCamTraits>
204status_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
211template <typename TCam, typename TCamTraits>
212status_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
Igor Murashkinc073ba52013-02-26 14:32:34 -0800219template class CameraBase<Camera>;
220
221} // namespace android