ProCamera.cpp revision bfb5d5ef5bae01efac171397260a7152782d92c7
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 "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
231