blob: d6389a183bc90765dd4329fe5266478f4d9dac92 [file] [log] [blame]
Igor Murashkin985fd302013-02-20 18:24:43 -08001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "ProCamera2Client"
18#define ATRACE_TAG ATRACE_TAG_CAMERA
19//#define LOG_NDEBUG 0
20
21#include <utils/Log.h>
22#include <utils/Trace.h>
23
24#include <cutils/properties.h>
25#include <gui/Surface.h>
26#include <gui/Surface.h>
27#include "camera2/Parameters.h"
28#include "ProCamera2Client.h"
29
30namespace android {
31using namespace camera2;
32
33static int getCallingPid() {
34 return IPCThreadState::self()->getCallingPid();
35}
36
37static int getCallingUid() {
38 return IPCThreadState::self()->getCallingUid();
39}
40
41// Interface used by CameraService
42
43ProCamera2Client::ProCamera2Client(const sp<CameraService>& cameraService,
44 const sp<IProCameraCallbacks>& remoteCallback,
45 int cameraId,
46 int cameraFacing,
47 int clientPid,
48 int servicePid):
49 ProClient(cameraService, remoteCallback,
50 cameraId, cameraFacing, clientPid, servicePid),
51 mSharedCameraCallbacks(remoteCallback)
52{
53 ATRACE_CALL();
54 ALOGI("ProCamera %d: Opened", cameraId);
55
56 mDevice = new Camera2Device(cameraId);
57
58 mExclusiveLock = false;
59}
60
61status_t ProCamera2Client::checkPid(const char* checkLocation) const {
62 int callingPid = getCallingPid();
63 if (callingPid == mClientPid) return NO_ERROR;
64
65 ALOGE("%s: attempt to use a locked camera from a different process"
66 " (old pid %d, new pid %d)", checkLocation, mClientPid, callingPid);
67 return PERMISSION_DENIED;
68}
69
70status_t ProCamera2Client::initialize(camera_module_t *module)
71{
72 ATRACE_CALL();
73 ALOGV("%s: Initializing client for camera %d", __FUNCTION__, mCameraId);
74 status_t res;
75
76 res = mDevice->initialize(module);
77 if (res != OK) {
78 ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
79 __FUNCTION__, mCameraId, strerror(-res), res);
80 return NO_INIT;
81 }
82
83 res = mDevice->setNotifyCallback(this);
84
85 return OK;
86}
87
88ProCamera2Client::~ProCamera2Client() {
89 ATRACE_CALL();
90
91 mDestructionStarted = true;
92
93 disconnect();
94
95 ALOGI("ProCamera %d: Closed", mCameraId);
96}
97
98status_t ProCamera2Client::exclusiveTryLock() {
99 ATRACE_CALL();
100 ALOGV("%s", __FUNCTION__);
101
102 Mutex::Autolock icl(mIProCameraUserLock);
103 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
104
105 if (!mExclusiveLock) {
106 mExclusiveLock = true;
107
108 if (mRemoteCallback != NULL) {
109 mRemoteCallback->onLockStatusChanged(
110 IProCameraCallbacks::LOCK_ACQUIRED);
111 }
112
113 ALOGV("%s: exclusive lock acquired", __FUNCTION__);
114
115 return OK;
116 }
117
118 // TODO: have a PERMISSION_DENIED case for when someone else owns the lock
119
120 // don't allow recursive locking
121 ALOGW("%s: exclusive lock already exists - recursive locking is not"
122 "allowed", __FUNCTION__);
123
124 return ALREADY_EXISTS;
125}
126
127status_t ProCamera2Client::exclusiveLock() {
128 ATRACE_CALL();
129 ALOGV("%s", __FUNCTION__);
130
131 Mutex::Autolock icl(mIProCameraUserLock);
132 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
133
134 /**
135 * TODO: this should asynchronously 'wait' until the lock becomes available
136 * if another client already has an exclusive lock.
137 *
138 * once we have proper sharing support this will need to do
139 * more than just return immediately
140 */
141 if (!mExclusiveLock) {
142 mExclusiveLock = true;
143
144 if (mRemoteCallback != NULL) {
145 mRemoteCallback->onLockStatusChanged(IProCameraCallbacks::LOCK_ACQUIRED);
146 }
147
148 ALOGV("%s: exclusive lock acquired", __FUNCTION__);
149
150 return OK;
151 }
152
153 // don't allow recursive locking
154 ALOGW("%s: exclusive lock already exists - recursive locking is not allowed"
155 , __FUNCTION__);
156 return ALREADY_EXISTS;
157}
158
159status_t ProCamera2Client::exclusiveUnlock() {
160 ATRACE_CALL();
161 ALOGV("%s", __FUNCTION__);
162
163 Mutex::Autolock icl(mIProCameraUserLock);
164 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
165
166 // don't allow unlocking if we have no lock
167 if (!mExclusiveLock) {
168 ALOGW("%s: cannot unlock, no lock was held in the first place",
169 __FUNCTION__);
170 return BAD_VALUE;
171 }
172
173 mExclusiveLock = false;
174 if (mRemoteCallback != NULL ) {
175 mRemoteCallback->onLockStatusChanged(
176 IProCameraCallbacks::LOCK_RELEASED);
177 }
178 ALOGV("%s: exclusive lock released", __FUNCTION__);
179
180 return OK;
181}
182
183bool ProCamera2Client::hasExclusiveLock() {
184 return mExclusiveLock;
185}
186
187status_t ProCamera2Client::submitRequest(camera_metadata_t* request,
188 bool streaming) {
189 ATRACE_CALL();
190 ALOGV("%s", __FUNCTION__);
191
192 Mutex::Autolock icl(mIProCameraUserLock);
193 if (!mExclusiveLock) {
194 return PERMISSION_DENIED;
195 }
196
197 ALOGE("%s: not fully implemented yet", __FUNCTION__);
198 free_camera_metadata(request);
199 return OK;
200}
201
202status_t ProCamera2Client::cancelRequest(int requestId) {
203 ATRACE_CALL();
204 ALOGV("%s", __FUNCTION__);
205
206 Mutex::Autolock icl(mIProCameraUserLock);
207 if (!mExclusiveLock) {
208 return PERMISSION_DENIED;
209 }
210
211 ALOGE("%s: not fully implemented yet", __FUNCTION__);
212 return OK;
213}
214
215status_t ProCamera2Client::requestStream(int streamId) {
216 ALOGE("%s: not implemented yet", __FUNCTION__);
217
218 return INVALID_OPERATION;
219}
220
221status_t ProCamera2Client::cancelStream(int streamId) {
222 ALOGE("%s: not implemented yet", __FUNCTION__);
223
224 return INVALID_OPERATION;
225}
226
227status_t ProCamera2Client::createStream(int width, int height, int format,
228 const sp<Surface>& surface,
229 /*out*/
230 int* streamId) {
231 ALOGE("%s: not implemented yet", __FUNCTION__);
232
233 return INVALID_OPERATION;
234}
235
236status_t ProCamera2Client::createDefaultRequest(int templateId,
237 /*out*/
238 camera_metadata** request) {
239 ALOGE("%s: not implemented yet", __FUNCTION__);
240
241 return INVALID_OPERATION;
242}
243
244
245
246
247
248status_t ProCamera2Client::dump(int fd, const Vector<String16>& args) {
249 String8 result;
250 result.appendFormat("ProCamera2Client[%d] (%p) PID: %d, dump:\n",
251 mCameraId,
252 getRemoteCallback()->asBinder().get(),
253 mClientPid);
254 result.append(" State: ");
255
256 // TODO: print dynamic/request section from most recent requests
257
258#define CASE_APPEND_ENUM(x) case x: result.append(#x "\n"); break;
259
260 result = " Device dump:\n";
261 write(fd, result.string(), result.size());
262
263 status_t res = mDevice->dump(fd, args);
264 if (res != OK) {
265 result = String8::format(" Error dumping device: %s (%d)",
266 strerror(-res), res);
267 write(fd, result.string(), result.size());
268 }
269
270#undef CASE_APPEND_ENUM
271 return NO_ERROR;
272}
273
274// IProCameraUser interface
275
276void ProCamera2Client::disconnect() {
277 ATRACE_CALL();
278 Mutex::Autolock icl(mIProCameraUserLock);
279 status_t res;
280
281 // Allow both client and the media server to disconnect at all times
282 int callingPid = getCallingPid();
283 if (callingPid != mClientPid && callingPid != mServicePid) return;
284
285 if (mDevice == 0) return;
286
287 ALOGV("Camera %d: Shutting down", mCameraId);
288 ALOGV("Camera %d: Waiting for threads", mCameraId);
289 ALOGV("Camera %d: Disconnecting device", mCameraId);
290
291 mDevice->disconnect();
292
293 mDevice.clear();
294
295 ProClient::disconnect();
296}
297
298status_t ProCamera2Client::connect(const sp<IProCameraCallbacks>& client) {
299 ATRACE_CALL();
300 ALOGV("%s: E", __FUNCTION__);
301 Mutex::Autolock icl(mIProCameraUserLock);
302
303 if (mClientPid != 0 && getCallingPid() != mClientPid) {
304 ALOGE("%s: Camera %d: Connection attempt from pid %d; "
305 "current locked to pid %d", __FUNCTION__,
306 mCameraId, getCallingPid(), mClientPid);
307 return BAD_VALUE;
308 }
309
310 mClientPid = getCallingPid();
311
312 mRemoteCallback = client;
313 mSharedCameraCallbacks = client;
314
315 return OK;
316}
317
318/** Device-related methods */
319
320void ProCamera2Client::notifyError(int errorCode, int arg1, int arg2) {
321 ALOGE("Error condition %d reported by HAL, arguments %d, %d", errorCode,
322 arg1, arg2);
323}
324
325void ProCamera2Client::notifyShutter(int frameNumber, nsecs_t timestamp) {
326 ALOGV("%s: Shutter notification for frame %d at time %lld", __FUNCTION__,
327 frameNumber, timestamp);
328}
329
330void ProCamera2Client::notifyAutoFocus(uint8_t newState, int triggerId) {
331 ALOGV("%s: Autofocus state now %d, last trigger %d",
332 __FUNCTION__, newState, triggerId);
333
334 SharedCameraCallbacks::Lock l(mSharedCameraCallbacks);
335 if (l.mRemoteCallback != 0) {
336 l.mRemoteCallback->notifyCallback(CAMERA_MSG_FOCUS_MOVE,
337 1, 0);
338 }
339 if (l.mRemoteCallback != 0) {
340 l.mRemoteCallback->notifyCallback(CAMERA_MSG_FOCUS,
341 1, 0);
342 }
343}
344
345void ProCamera2Client::notifyAutoExposure(uint8_t newState, int triggerId) {
346 ALOGV("%s: Autoexposure state now %d, last trigger %d",
347 __FUNCTION__, newState, triggerId);
348}
349
350void ProCamera2Client::notifyAutoWhitebalance(uint8_t newState, int triggerId) {
351 ALOGV("%s: Auto-whitebalance state now %d, last trigger %d",
352 __FUNCTION__, newState, triggerId);
353}
354
355int ProCamera2Client::getCameraId() const {
356 return mCameraId;
357}
358
359const sp<Camera2Device>& ProCamera2Client::getCameraDevice() {
360 return mDevice;
361}
362
363const sp<CameraService>& ProCamera2Client::getCameraService() {
364 return mCameraService;
365}
366
367ProCamera2Client::SharedCameraCallbacks::Lock::Lock(
368 SharedCameraCallbacks &client):
369 mRemoteCallback(client.mRemoteCallback),
370 mSharedClient(client) {
371 mSharedClient.mRemoteCallbackLock.lock();
372}
373
374ProCamera2Client::SharedCameraCallbacks::Lock::~Lock() {
375 mSharedClient.mRemoteCallbackLock.unlock();
376}
377
378ProCamera2Client::SharedCameraCallbacks::SharedCameraCallbacks
379 (const sp<IProCameraCallbacks>&client):
380 mRemoteCallback(client) {
381}
382
383ProCamera2Client::SharedCameraCallbacks&
384 ProCamera2Client::SharedCameraCallbacks::operator=(
385 const sp<IProCameraCallbacks>&client) {
386 Mutex::Autolock l(mRemoteCallbackLock);
387 mRemoteCallback = client;
388 return *this;
389}
390
391void ProCamera2Client::SharedCameraCallbacks::clear() {
392 Mutex::Autolock l(mRemoteCallbackLock);
393 mRemoteCallback.clear();
394}
395
396} // namespace android