blob: 134a4a3182fcd4a0952560ae709056476fc4631a [file] [log] [blame]
Igor Murashkin634a5152013-02-20 17:15:11 -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 "ProCamera"
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/ProCamera.h>
29#include <camera/ICameraService.h>
30#include <camera/IProCameraUser.h>
31#include <camera/IProCameraCallbacks.h>
32
33#include <gui/IGraphicBufferProducer.h>
34#include <gui/Surface.h>
35
36namespace android {
37
38// client singleton for camera service binder interface
39Mutex ProCamera::mLock;
40sp<ICameraService> ProCamera::mCameraService;
41sp<ProCamera::DeathNotifier> ProCamera::mDeathNotifier;
42
43// establish binder interface to camera service
44const sp<ICameraService>& ProCamera::getCameraService()
45{
46 Mutex::Autolock _l(mLock);
47 if (mCameraService.get() == 0) {
48 sp<IServiceManager> sm = defaultServiceManager();
49 sp<IBinder> binder;
50 do {
51 binder = sm->getService(String16("media.camera"));
52 if (binder != 0)
53 break;
54 ALOGW("CameraService not published, waiting...");
55 usleep(500000); // 0.5 s
56 } while(true);
57 if (mDeathNotifier == NULL) {
58 mDeathNotifier = new DeathNotifier();
59 }
60 binder->linkToDeath(mDeathNotifier);
61 mCameraService = interface_cast<ICameraService>(binder);
62 }
63 ALOGE_IF(mCameraService==0, "no CameraService!?");
64 return mCameraService;
65}
66
67sp<ProCamera> ProCamera::connect(int cameraId)
68{
69 ALOGV("connect");
70 sp<ProCamera> c = new ProCamera();
71 sp<IProCameraCallbacks> cl = c;
72 const sp<ICameraService>& cs = getCameraService();
73 if (cs != 0) {
74 c->mCamera = cs->connect(cl, cameraId);
75 }
76 if (c->mCamera != 0) {
77 c->mCamera->asBinder()->linkToDeath(c);
78 c->mStatus = NO_ERROR;
79 } else {
80 c.clear();
81 }
82 return c;
83}
84
85void ProCamera::disconnect()
86{
87 ALOGV("disconnect");
88 if (mCamera != 0) {
89 mCamera->disconnect();
90 mCamera->asBinder()->unlinkToDeath(this);
91 mCamera = 0;
92 }
93}
94
95ProCamera::ProCamera()
96{
97}
98
99ProCamera::~ProCamera()
100{
101
102}
103
104sp<IProCameraUser> ProCamera::remote()
105{
106 return mCamera;
107}
108
109void ProCamera::binderDied(const wp<IBinder>& who) {
110 ALOGW("IProCameraUser died");
111 notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_SERVER_DIED, 0);
112}
113
114void ProCamera::DeathNotifier::binderDied(const wp<IBinder>& who) {
115 ALOGV("binderDied");
116 Mutex::Autolock _l(ProCamera::mLock);
117 ProCamera::mCameraService.clear();
118 ALOGW("Camera service died!");
119}
120
121
122// callback from camera service
123void ProCamera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2)
124{
125 sp<ProCameraListener> listener;
126 {
127 Mutex::Autolock _l(mLock);
128 listener = mListener;
129 }
130 if (listener != NULL) {
131 listener->notify(msgType, ext1, ext2);
132 }
133}
134
135// callback from camera service when frame or image is ready
136void ProCamera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr,
137 camera_frame_metadata_t *metadata)
138{
139 sp<ProCameraListener> listener;
140 {
141 Mutex::Autolock _l(mLock);
142 listener = mListener;
143 }
144 if (listener != NULL) {
145 listener->postData(msgType, dataPtr, metadata);
146 }
147}
148
149// callback from camera service when timestamped frame is ready
150void ProCamera::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType,
151 const sp<IMemory>& dataPtr)
152{
153 sp<ProCameraListener> listener;
154 {
155 Mutex::Autolock _l(mLock);
156 listener = mListener;
157 }
158 if (listener != NULL) {
159 listener->postDataTimestamp(timestamp, msgType, dataPtr);
160 } else {
161 ALOGW("No listener was set. Drop a recording frame.");
162 }
163}
164
165/* IProCameraUser's implementation */
166
167status_t ProCamera::exclusiveTryLock()
168{
169 sp <IProCameraUser> c = mCamera;
170 if (c == 0) return NO_INIT;
171
172 return c->exclusiveTryLock();
173}
174status_t ProCamera::exclusiveLock()
175{
176 sp <IProCameraUser> c = mCamera;
177 if (c == 0) return NO_INIT;
178
179 return c->exclusiveLock();
180}
181status_t ProCamera::exclusiveUnlock()
182{
183 sp <IProCameraUser> c = mCamera;
184 if (c == 0) return NO_INIT;
185
186 return c->exclusiveUnlock();
187}
188bool ProCamera::hasExclusiveLock()
189{
190 sp <IProCameraUser> c = mCamera;
191 if (c == 0) return NO_INIT;
192
193 return c->hasExclusiveLock();
194}
195
196// Note that the callee gets a copy of the metadata.
197int ProCamera::submitRequest(const struct camera_metadata* metadata,
198 bool streaming)
199{
200 sp <IProCameraUser> c = mCamera;
201 if (c == 0) return NO_INIT;
202
203 return c->submitRequest(const_cast<struct camera_metadata*>(metadata),
204 streaming);
205}
206
207status_t ProCamera::cancelRequest(int requestId)
208{
209 sp <IProCameraUser> c = mCamera;
210 if (c == 0) return NO_INIT;
211
212 return c->cancelRequest(requestId);
213}
214
215status_t ProCamera::requestStream(int streamId)
216{
217 sp <IProCameraUser> c = mCamera;
218 if (c == 0) return NO_INIT;
219
220 return c->requestStream(streamId);
221}
222status_t ProCamera::cancelStream(int streamId)
223{
224 sp <IProCameraUser> c = mCamera;
225 if (c == 0) return NO_INIT;
226
227 return c->cancelStream(streamId);
228}
229
230}; // namespace android