1 /*
2 * Copyright (C) 2012 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 "CameraClient"
18 //#define LOG_NDEBUG 0
19
20 #include <cutils/atomic.h>
21 #include <cutils/properties.h>
22 #include <gui/Surface.h>
23 #include <media/hardware/HardwareAPI.h>
24
25 #include "api1/CameraClient.h"
26 #include "device1/CameraHardwareInterface.h"
27 #include "CameraService.h"
28
29 namespace android {
30
31 #define LOG1(...) ALOGD_IF(gLogLevel >= 1, __VA_ARGS__);
32 #define LOG2(...) ALOGD_IF(gLogLevel >= 2, __VA_ARGS__);
33
getCallingPid()34 static int getCallingPid() {
35 return IPCThreadState::self()->getCallingPid();
36 }
37
CameraClient(const sp<CameraService> & cameraService,const sp<hardware::ICameraClient> & cameraClient,const String16 & clientPackageName,int cameraId,int cameraFacing,int clientPid,int clientUid,int servicePid,bool legacyMode)38 CameraClient::CameraClient(const sp<CameraService>& cameraService,
39 const sp<hardware::ICameraClient>& cameraClient,
40 const String16& clientPackageName,
41 int cameraId, int cameraFacing,
42 int clientPid, int clientUid,
43 int servicePid, bool legacyMode):
44 Client(cameraService, cameraClient, clientPackageName,
45 String8::format("%d", cameraId), cameraId, cameraFacing, clientPid,
46 clientUid, servicePid)
47 {
48 int callingPid = getCallingPid();
49 LOG1("CameraClient::CameraClient E (pid %d, id %d)", callingPid, cameraId);
50
51 mHardware = NULL;
52 mMsgEnabled = 0;
53 mSurface = 0;
54 mPreviewWindow = 0;
55 mDestructionStarted = false;
56
57 // Callback is disabled by default
58 mPreviewCallbackFlag = CAMERA_FRAME_CALLBACK_FLAG_NOOP;
59 mOrientation = getOrientation(0, mCameraFacing == CAMERA_FACING_FRONT);
60 mLegacyMode = legacyMode;
61 mPlayShutterSound = true;
62 LOG1("CameraClient::CameraClient X (pid %d, id %d)", callingPid, cameraId);
63 }
64
initialize(sp<CameraProviderManager> manager,const String8 &)65 status_t CameraClient::initialize(sp<CameraProviderManager> manager,
66 const String8& /*monitorTags*/) {
67 int callingPid = getCallingPid();
68 status_t res;
69
70 LOG1("CameraClient::initialize E (pid %d, id %d)", callingPid, mCameraId);
71
72 // Verify ops permissions
73 res = startCameraOps();
74 if (res != OK) {
75 return res;
76 }
77
78 char camera_device_name[10];
79 snprintf(camera_device_name, sizeof(camera_device_name), "%d", mCameraId);
80
81 mHardware = new CameraHardwareInterface(camera_device_name);
82 res = mHardware->initialize(manager);
83 if (res != OK) {
84 ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
85 __FUNCTION__, mCameraId, strerror(-res), res);
86 mHardware.clear();
87 return res;
88 }
89
90 mHardware->setCallbacks(notifyCallback,
91 dataCallback,
92 dataCallbackTimestamp,
93 handleCallbackTimestampBatch,
94 (void *)(uintptr_t)mCameraId);
95
96 // Enable zoom, error, focus, and metadata messages by default
97 enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS |
98 CAMERA_MSG_PREVIEW_METADATA | CAMERA_MSG_FOCUS_MOVE);
99
100 LOG1("CameraClient::initialize X (pid %d, id %d)", callingPid, mCameraId);
101 return OK;
102 }
103
104
105 // tear down the client
~CameraClient()106 CameraClient::~CameraClient() {
107 mDestructionStarted = true;
108 int callingPid = getCallingPid();
109 LOG1("CameraClient::~CameraClient E (pid %d, this %p)", callingPid, this);
110
111 disconnect();
112 LOG1("CameraClient::~CameraClient X (pid %d, this %p)", callingPid, this);
113 }
114
dump(int fd,const Vector<String16> & args)115 status_t CameraClient::dump(int fd, const Vector<String16>& args) {
116 return BasicClient::dump(fd, args);
117 }
118
dumpClient(int fd,const Vector<String16> & args)119 status_t CameraClient::dumpClient(int fd, const Vector<String16>& args) {
120 const size_t SIZE = 256;
121 char buffer[SIZE];
122
123 size_t len = snprintf(buffer, SIZE, "Client[%d] (%p) with UID %d\n",
124 mCameraId,
125 (getRemoteCallback() != NULL ?
126 IInterface::asBinder(getRemoteCallback()).get() : NULL),
127 mClientUid);
128 len = (len > SIZE - 1) ? SIZE - 1 : len;
129 write(fd, buffer, len);
130
131 len = snprintf(buffer, SIZE, "Latest set parameters:\n");
132 len = (len > SIZE - 1) ? SIZE - 1 : len;
133 write(fd, buffer, len);
134
135 mLatestSetParameters.dump(fd, args);
136
137 const char *enddump = "\n\n";
138 write(fd, enddump, strlen(enddump));
139
140 sp<CameraHardwareInterface> hardware = mHardware;
141 if (hardware != nullptr) {
142 return hardware->dump(fd, args);
143 }
144 ALOGI("%s: camera device closed already, skip dumping", __FUNCTION__);
145 return OK;
146 }
147
148 // ----------------------------------------------------------------------------
149
checkPid() const150 status_t CameraClient::checkPid() const {
151 int callingPid = getCallingPid();
152 if (callingPid == mClientPid) return NO_ERROR;
153
154 ALOGW("attempt to use a locked camera from a different process"
155 " (old pid %d, new pid %d)", mClientPid, callingPid);
156 return EBUSY;
157 }
158
checkPidAndHardware() const159 status_t CameraClient::checkPidAndHardware() const {
160 if (mHardware == 0) {
161 ALOGE("attempt to use a camera after disconnect() (pid %d)", getCallingPid());
162 return INVALID_OPERATION;
163 }
164 status_t result = checkPid();
165 if (result != NO_ERROR) return result;
166 return NO_ERROR;
167 }
168
lock()169 status_t CameraClient::lock() {
170 int callingPid = getCallingPid();
171 LOG1("lock (pid %d)", callingPid);
172 Mutex::Autolock lock(mLock);
173
174 // lock camera to this client if the the camera is unlocked
175 if (mClientPid == 0) {
176 mClientPid = callingPid;
177 return NO_ERROR;
178 }
179
180 // returns NO_ERROR if the client already owns the camera, EBUSY otherwise
181 return checkPid();
182 }
183
unlock()184 status_t CameraClient::unlock() {
185 int callingPid = getCallingPid();
186 LOG1("unlock (pid %d)", callingPid);
187 Mutex::Autolock lock(mLock);
188
189 // allow anyone to use camera (after they lock the camera)
190 status_t result = checkPid();
191 if (result == NO_ERROR) {
192 if (mHardware->recordingEnabled()) {
193 ALOGE("Not allowed to unlock camera during recording.");
194 return INVALID_OPERATION;
195 }
196 mClientPid = 0;
197 LOG1("clear mRemoteCallback (pid %d)", callingPid);
198 // we need to remove the reference to ICameraClient so that when the app
199 // goes away, the reference count goes to 0.
200 mRemoteCallback.clear();
201 }
202 return result;
203 }
204
205 // connect a new client to the camera
connect(const sp<hardware::ICameraClient> & client)206 status_t CameraClient::connect(const sp<hardware::ICameraClient>& client) {
207 int callingPid = getCallingPid();
208 LOG1("connect E (pid %d)", callingPid);
209 Mutex::Autolock lock(mLock);
210
211 if (mClientPid != 0 && checkPid() != NO_ERROR) {
212 ALOGW("Tried to connect to a locked camera (old pid %d, new pid %d)",
213 mClientPid, callingPid);
214 return EBUSY;
215 }
216
217 if (mRemoteCallback != 0 &&
218 (IInterface::asBinder(client) == IInterface::asBinder(mRemoteCallback))) {
219 LOG1("Connect to the same client");
220 return NO_ERROR;
221 }
222
223 mPreviewCallbackFlag = CAMERA_FRAME_CALLBACK_FLAG_NOOP;
224 mClientPid = callingPid;
225 mRemoteCallback = client;
226
227 LOG1("connect X (pid %d)", callingPid);
228 return NO_ERROR;
229 }
230
disconnectWindow(const sp<ANativeWindow> & window)231 static void disconnectWindow(const sp<ANativeWindow>& window) {
232 if (window != 0) {
233 status_t result = native_window_api_disconnect(window.get(),
234 NATIVE_WINDOW_API_CAMERA);
235 if (result != NO_ERROR) {
236 ALOGW("native_window_api_disconnect failed: %s (%d)", strerror(-result),
237 result);
238 }
239 }
240 }
241
disconnect()242 binder::Status CameraClient::disconnect() {
243 int callingPid = getCallingPid();
244 LOG1("disconnect E (pid %d)", callingPid);
245 Mutex::Autolock lock(mLock);
246
247 binder::Status res = binder::Status::ok();
248 // Allow both client and the cameraserver to disconnect at all times
249 if (callingPid != mClientPid && callingPid != mServicePid) {
250 ALOGW("different client - don't disconnect");
251 return res;
252 }
253
254 // Make sure disconnect() is done once and once only, whether it is called
255 // from the user directly, or called by the destructor.
256 if (mHardware == 0) return res;
257
258 LOG1("hardware teardown");
259 // Before destroying mHardware, we must make sure it's in the
260 // idle state.
261 // Turn off all messages.
262 disableMsgType(CAMERA_MSG_ALL_MSGS);
263 mHardware->stopPreview();
264 sCameraService->updateProxyDeviceState(
265 hardware::ICameraServiceProxy::CAMERA_STATE_IDLE,
266 mCameraIdStr, mCameraFacing, mClientPackageName,
267 hardware::ICameraServiceProxy::CAMERA_API_LEVEL_1);
268 mHardware->cancelPicture();
269 // Release the hardware resources.
270 mHardware->release();
271
272 // Release the held ANativeWindow resources.
273 if (mPreviewWindow != 0) {
274 disconnectWindow(mPreviewWindow);
275 mPreviewWindow = 0;
276 mHardware->setPreviewWindow(mPreviewWindow);
277 }
278 mHardware.clear();
279
280 CameraService::Client::disconnect();
281
282 LOG1("disconnect X (pid %d)", callingPid);
283
284 return res;
285 }
286
287 // ----------------------------------------------------------------------------
288
setPreviewWindow(const sp<IBinder> & binder,const sp<ANativeWindow> & window)289 status_t CameraClient::setPreviewWindow(const sp<IBinder>& binder,
290 const sp<ANativeWindow>& window) {
291 Mutex::Autolock lock(mLock);
292 status_t result = checkPidAndHardware();
293 if (result != NO_ERROR) return result;
294
295 // return if no change in surface.
296 if (binder == mSurface) {
297 return NO_ERROR;
298 }
299
300 if (window != 0) {
301 result = native_window_api_connect(window.get(), NATIVE_WINDOW_API_CAMERA);
302 if (result != NO_ERROR) {
303 ALOGE("native_window_api_connect failed: %s (%d)", strerror(-result),
304 result);
305 return result;
306 }
307 }
308
309 // If preview has been already started, register preview buffers now.
310 if (mHardware->previewEnabled()) {
311 if (window != 0) {
312 mHardware->setPreviewScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
313 mHardware->setPreviewTransform(mOrientation);
314 result = mHardware->setPreviewWindow(window);
315 }
316 }
317
318 if (result == NO_ERROR) {
319 // Everything has succeeded. Disconnect the old window and remember the
320 // new window.
321 disconnectWindow(mPreviewWindow);
322 mSurface = binder;
323 mPreviewWindow = window;
324 } else {
325 // Something went wrong after we connected to the new window, so
326 // disconnect here.
327 disconnectWindow(window);
328 }
329
330 return result;
331 }
332
333 // set the buffer consumer that the preview will use
setPreviewTarget(const sp<IGraphicBufferProducer> & bufferProducer)334 status_t CameraClient::setPreviewTarget(
335 const sp<IGraphicBufferProducer>& bufferProducer) {
336 LOG1("setPreviewTarget(%p) (pid %d)", bufferProducer.get(),
337 getCallingPid());
338
339 sp<IBinder> binder;
340 sp<ANativeWindow> window;
341 if (bufferProducer != 0) {
342 binder = IInterface::asBinder(bufferProducer);
343 // Using controlledByApp flag to ensure that the buffer queue remains in
344 // async mode for the old camera API, where many applications depend
345 // on that behavior.
346 window = new Surface(bufferProducer, /*controlledByApp*/ true);
347 }
348 return setPreviewWindow(binder, window);
349 }
350
351 // set the preview callback flag to affect how the received frames from
352 // preview are handled.
setPreviewCallbackFlag(int callback_flag)353 void CameraClient::setPreviewCallbackFlag(int callback_flag) {
354 LOG1("setPreviewCallbackFlag(%d) (pid %d)", callback_flag, getCallingPid());
355 Mutex::Autolock lock(mLock);
356 if (checkPidAndHardware() != NO_ERROR) return;
357
358 mPreviewCallbackFlag = callback_flag;
359 if (mPreviewCallbackFlag & CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK) {
360 enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
361 } else {
362 disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
363 }
364 }
365
setPreviewCallbackTarget(const sp<IGraphicBufferProducer> & callbackProducer)366 status_t CameraClient::setPreviewCallbackTarget(
367 const sp<IGraphicBufferProducer>& callbackProducer) {
368 (void)callbackProducer;
369 ALOGE("%s: Unimplemented!", __FUNCTION__);
370 return INVALID_OPERATION;
371 }
372
373 // start preview mode
startPreview()374 status_t CameraClient::startPreview() {
375 LOG1("startPreview (pid %d)", getCallingPid());
376 return startCameraMode(CAMERA_PREVIEW_MODE);
377 }
378
379 // start recording mode
startRecording()380 status_t CameraClient::startRecording() {
381 LOG1("startRecording (pid %d)", getCallingPid());
382 return startCameraMode(CAMERA_RECORDING_MODE);
383 }
384
385 // start preview or recording
startCameraMode(camera_mode mode)386 status_t CameraClient::startCameraMode(camera_mode mode) {
387 LOG1("startCameraMode(%d)", mode);
388 Mutex::Autolock lock(mLock);
389 status_t result = checkPidAndHardware();
390 if (result != NO_ERROR) return result;
391
392 switch(mode) {
393 case CAMERA_PREVIEW_MODE:
394 if (mSurface == 0 && mPreviewWindow == 0) {
395 LOG1("mSurface is not set yet.");
396 // still able to start preview in this case.
397 }
398 return startPreviewMode();
399 case CAMERA_RECORDING_MODE:
400 if (mSurface == 0 && mPreviewWindow == 0) {
401 ALOGE("mSurface or mPreviewWindow must be set before startRecordingMode.");
402 return INVALID_OPERATION;
403 }
404 return startRecordingMode();
405 default:
406 return UNKNOWN_ERROR;
407 }
408 }
409
startPreviewMode()410 status_t CameraClient::startPreviewMode() {
411 LOG1("startPreviewMode");
412 status_t result = NO_ERROR;
413
414 // if preview has been enabled, nothing needs to be done
415 if (mHardware->previewEnabled()) {
416 return NO_ERROR;
417 }
418
419 if (mPreviewWindow != 0) {
420 mHardware->setPreviewScalingMode(
421 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
422 mHardware->setPreviewTransform(mOrientation);
423 }
424 mHardware->setPreviewWindow(mPreviewWindow);
425 result = mHardware->startPreview();
426 if (result == NO_ERROR) {
427 sCameraService->updateProxyDeviceState(
428 hardware::ICameraServiceProxy::CAMERA_STATE_ACTIVE,
429 mCameraIdStr, mCameraFacing, mClientPackageName,
430 hardware::ICameraServiceProxy::CAMERA_API_LEVEL_1);
431 }
432 return result;
433 }
434
startRecordingMode()435 status_t CameraClient::startRecordingMode() {
436 LOG1("startRecordingMode");
437 status_t result = NO_ERROR;
438
439 // if recording has been enabled, nothing needs to be done
440 if (mHardware->recordingEnabled()) {
441 return NO_ERROR;
442 }
443
444 // if preview has not been started, start preview first
445 if (!mHardware->previewEnabled()) {
446 result = startPreviewMode();
447 if (result != NO_ERROR) {
448 return result;
449 }
450 }
451
452 // start recording mode
453 enableMsgType(CAMERA_MSG_VIDEO_FRAME);
454 sCameraService->playSound(CameraService::SOUND_RECORDING_START);
455 result = mHardware->startRecording();
456 if (result != NO_ERROR) {
457 ALOGE("mHardware->startRecording() failed with status %d", result);
458 }
459 return result;
460 }
461
462 // stop preview mode
stopPreview()463 void CameraClient::stopPreview() {
464 LOG1("stopPreview (pid %d)", getCallingPid());
465 Mutex::Autolock lock(mLock);
466 if (checkPidAndHardware() != NO_ERROR) return;
467
468
469 disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
470 mHardware->stopPreview();
471 sCameraService->updateProxyDeviceState(
472 hardware::ICameraServiceProxy::CAMERA_STATE_IDLE,
473 mCameraIdStr, mCameraFacing, mClientPackageName,
474 hardware::ICameraServiceProxy::CAMERA_API_LEVEL_1);
475 mPreviewBuffer.clear();
476 }
477
478 // stop recording mode
stopRecording()479 void CameraClient::stopRecording() {
480 LOG1("stopRecording (pid %d)", getCallingPid());
481 {
482 Mutex::Autolock lock(mLock);
483 if (checkPidAndHardware() != NO_ERROR) return;
484
485 disableMsgType(CAMERA_MSG_VIDEO_FRAME);
486 mHardware->stopRecording();
487 sCameraService->playSound(CameraService::SOUND_RECORDING_STOP);
488
489 mPreviewBuffer.clear();
490 }
491
492 {
493 Mutex::Autolock l(mAvailableCallbackBuffersLock);
494 if (!mAvailableCallbackBuffers.empty()) {
495 mAvailableCallbackBuffers.clear();
496 }
497 }
498 }
499
500 // release a recording frame
releaseRecordingFrame(const sp<IMemory> & mem)501 void CameraClient::releaseRecordingFrame(const sp<IMemory>& mem) {
502 Mutex::Autolock lock(mLock);
503 if (checkPidAndHardware() != NO_ERROR) return;
504 if (mem == nullptr) {
505 android_errorWriteWithInfoLog(CameraService::SN_EVENT_LOG_ID, "26164272",
506 IPCThreadState::self()->getCallingUid(), nullptr, 0);
507 return;
508 }
509
510 mHardware->releaseRecordingFrame(mem);
511 }
512
releaseRecordingFrameHandle(native_handle_t * handle)513 void CameraClient::releaseRecordingFrameHandle(native_handle_t *handle) {
514 if (handle == nullptr) return;
515 Mutex::Autolock lock(mLock);
516 sp<IMemory> dataPtr;
517 {
518 Mutex::Autolock l(mAvailableCallbackBuffersLock);
519 if (!mAvailableCallbackBuffers.empty()) {
520 dataPtr = mAvailableCallbackBuffers.back();
521 mAvailableCallbackBuffers.pop_back();
522 }
523 }
524
525 if (dataPtr == nullptr) {
526 ALOGE("%s: %d: No callback buffer available. Dropping a native handle.", __FUNCTION__,
527 __LINE__);
528 native_handle_close(handle);
529 native_handle_delete(handle);
530 return;
531 } else if (dataPtr->size() != sizeof(VideoNativeHandleMetadata)) {
532 ALOGE("%s: %d: Callback buffer size doesn't match VideoNativeHandleMetadata", __FUNCTION__,
533 __LINE__);
534 native_handle_close(handle);
535 native_handle_delete(handle);
536 return;
537 }
538
539 if (mHardware != nullptr) {
540 VideoNativeHandleMetadata *metadata = (VideoNativeHandleMetadata*)(dataPtr->pointer());
541 metadata->eType = kMetadataBufferTypeNativeHandleSource;
542 metadata->pHandle = handle;
543 mHardware->releaseRecordingFrame(dataPtr);
544 }
545 }
546
releaseRecordingFrameHandleBatch(const std::vector<native_handle_t * > & handles)547 void CameraClient::releaseRecordingFrameHandleBatch(const std::vector<native_handle_t*>& handles) {
548 Mutex::Autolock lock(mLock);
549 bool disconnected = (mHardware == nullptr);
550 size_t n = handles.size();
551 std::vector<sp<IMemory>> frames;
552 if (!disconnected) {
553 frames.reserve(n);
554 }
555 bool error = false;
556 for (auto& handle : handles) {
557 sp<IMemory> dataPtr;
558 {
559 Mutex::Autolock l(mAvailableCallbackBuffersLock);
560 if (!mAvailableCallbackBuffers.empty()) {
561 dataPtr = mAvailableCallbackBuffers.back();
562 mAvailableCallbackBuffers.pop_back();
563 }
564 }
565
566 if (dataPtr == nullptr) {
567 ALOGE("%s: %d: No callback buffer available. Dropping frames.", __FUNCTION__,
568 __LINE__);
569 error = true;
570 break;
571 } else if (dataPtr->size() != sizeof(VideoNativeHandleMetadata)) {
572 ALOGE("%s: %d: Callback buffer must be VideoNativeHandleMetadata", __FUNCTION__,
573 __LINE__);
574 error = true;
575 break;
576 }
577
578 if (!disconnected) {
579 VideoNativeHandleMetadata *metadata = (VideoNativeHandleMetadata*)(dataPtr->pointer());
580 metadata->eType = kMetadataBufferTypeNativeHandleSource;
581 metadata->pHandle = handle;
582 frames.push_back(dataPtr);
583 }
584 }
585
586 if (error) {
587 for (auto& handle : handles) {
588 native_handle_close(handle);
589 native_handle_delete(handle);
590 }
591 } else if (!disconnected) {
592 mHardware->releaseRecordingFrameBatch(frames);
593 }
594 return;
595 }
596
setVideoBufferMode(int32_t videoBufferMode)597 status_t CameraClient::setVideoBufferMode(int32_t videoBufferMode) {
598 LOG1("setVideoBufferMode: %d", videoBufferMode);
599 bool enableMetadataInBuffers = false;
600
601 if (videoBufferMode == VIDEO_BUFFER_MODE_DATA_CALLBACK_METADATA) {
602 enableMetadataInBuffers = true;
603 } else if (videoBufferMode != VIDEO_BUFFER_MODE_DATA_CALLBACK_YUV) {
604 ALOGE("%s: %d: videoBufferMode %d is not supported.", __FUNCTION__, __LINE__,
605 videoBufferMode);
606 return BAD_VALUE;
607 }
608
609 Mutex::Autolock lock(mLock);
610 if (checkPidAndHardware() != NO_ERROR) {
611 return UNKNOWN_ERROR;
612 }
613
614 return mHardware->storeMetaDataInBuffers(enableMetadataInBuffers);
615 }
616
previewEnabled()617 bool CameraClient::previewEnabled() {
618 LOG1("previewEnabled (pid %d)", getCallingPid());
619
620 Mutex::Autolock lock(mLock);
621 if (checkPidAndHardware() != NO_ERROR) return false;
622 return mHardware->previewEnabled();
623 }
624
recordingEnabled()625 bool CameraClient::recordingEnabled() {
626 LOG1("recordingEnabled (pid %d)", getCallingPid());
627
628 Mutex::Autolock lock(mLock);
629 if (checkPidAndHardware() != NO_ERROR) return false;
630 return mHardware->recordingEnabled();
631 }
632
autoFocus()633 status_t CameraClient::autoFocus() {
634 LOG1("autoFocus (pid %d)", getCallingPid());
635
636 Mutex::Autolock lock(mLock);
637 status_t result = checkPidAndHardware();
638 if (result != NO_ERROR) return result;
639
640 return mHardware->autoFocus();
641 }
642
cancelAutoFocus()643 status_t CameraClient::cancelAutoFocus() {
644 LOG1("cancelAutoFocus (pid %d)", getCallingPid());
645
646 Mutex::Autolock lock(mLock);
647 status_t result = checkPidAndHardware();
648 if (result != NO_ERROR) return result;
649
650 return mHardware->cancelAutoFocus();
651 }
652
653 // take a picture - image is returned in callback
takePicture(int msgType)654 status_t CameraClient::takePicture(int msgType) {
655 LOG1("takePicture (pid %d): 0x%x", getCallingPid(), msgType);
656
657 Mutex::Autolock lock(mLock);
658 status_t result = checkPidAndHardware();
659 if (result != NO_ERROR) return result;
660
661 if ((msgType & CAMERA_MSG_RAW_IMAGE) &&
662 (msgType & CAMERA_MSG_RAW_IMAGE_NOTIFY)) {
663 ALOGE("CAMERA_MSG_RAW_IMAGE and CAMERA_MSG_RAW_IMAGE_NOTIFY"
664 " cannot be both enabled");
665 return BAD_VALUE;
666 }
667
668 // We only accept picture related message types
669 // and ignore other types of messages for takePicture().
670 int picMsgType = msgType
671 & (CAMERA_MSG_SHUTTER |
672 CAMERA_MSG_POSTVIEW_FRAME |
673 CAMERA_MSG_RAW_IMAGE |
674 CAMERA_MSG_RAW_IMAGE_NOTIFY |
675 CAMERA_MSG_COMPRESSED_IMAGE);
676
677 enableMsgType(picMsgType);
678
679 return mHardware->takePicture();
680 }
681
682 // set preview/capture parameters - key/value pairs
setParameters(const String8 & params)683 status_t CameraClient::setParameters(const String8& params) {
684 LOG1("setParameters (pid %d) (%s)", getCallingPid(), params.string());
685
686 Mutex::Autolock lock(mLock);
687 status_t result = checkPidAndHardware();
688 if (result != NO_ERROR) return result;
689
690 mLatestSetParameters = CameraParameters(params);
691 CameraParameters p(params);
692 return mHardware->setParameters(p);
693 }
694
695 // get preview/capture parameters - key/value pairs
getParameters() const696 String8 CameraClient::getParameters() const {
697 Mutex::Autolock lock(mLock);
698 // The camera service can unconditionally get the parameters at all times
699 if (getCallingPid() != mServicePid && checkPidAndHardware() != NO_ERROR) return String8();
700
701 String8 params(mHardware->getParameters().flatten());
702 LOG1("getParameters (pid %d) (%s)", getCallingPid(), params.string());
703 return params;
704 }
705
706 // enable shutter sound
enableShutterSound(bool enable)707 status_t CameraClient::enableShutterSound(bool enable) {
708 LOG1("enableShutterSound (pid %d)", getCallingPid());
709
710 status_t result = checkPidAndHardware();
711 if (result != NO_ERROR) return result;
712
713 if (enable) {
714 mPlayShutterSound = true;
715 return OK;
716 }
717
718 // the camera2 api legacy mode can unconditionally disable the shutter sound
719 if (mLegacyMode) {
720 ALOGV("%s: Disable shutter sound in legacy mode", __FUNCTION__);
721 mPlayShutterSound = false;
722 return OK;
723 }
724
725 // Disabling shutter sound may not be allowed. In that case only
726 // allow the mediaserver process to disable the sound.
727 char value[PROPERTY_VALUE_MAX];
728 property_get("ro.camera.sound.forced", value, "0");
729 if (strcmp(value, "0") != 0) {
730 // Disabling shutter sound is not allowed. Deny if the current
731 // process is not mediaserver.
732 if (getCallingPid() != getpid()) {
733 ALOGE("Failed to disable shutter sound. Permission denied (pid %d)", getCallingPid());
734 return PERMISSION_DENIED;
735 }
736 }
737
738 mPlayShutterSound = false;
739 return OK;
740 }
741
sendCommand(int32_t cmd,int32_t arg1,int32_t arg2)742 status_t CameraClient::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) {
743 LOG1("sendCommand (pid %d)", getCallingPid());
744 int orientation;
745 Mutex::Autolock lock(mLock);
746 status_t result = checkPidAndHardware();
747 if (result != NO_ERROR) return result;
748
749 if (cmd == CAMERA_CMD_SET_DISPLAY_ORIENTATION) {
750 // Mirror the preview if the camera is front-facing.
751 orientation = getOrientation(arg1, mCameraFacing == CAMERA_FACING_FRONT);
752 if (orientation == -1) return BAD_VALUE;
753
754 if (mOrientation != orientation) {
755 mOrientation = orientation;
756 if (mPreviewWindow != 0) {
757 mHardware->setPreviewTransform(mOrientation);
758 }
759 }
760 return OK;
761 } else if (cmd == CAMERA_CMD_ENABLE_SHUTTER_SOUND) {
762 switch (arg1) {
763 case 0:
764 return enableShutterSound(false);
765 case 1:
766 return enableShutterSound(true);
767 default:
768 return BAD_VALUE;
769 }
770 return OK;
771 } else if (cmd == CAMERA_CMD_PLAY_RECORDING_SOUND) {
772 sCameraService->playSound(CameraService::SOUND_RECORDING_START);
773 } else if (cmd == CAMERA_CMD_SET_VIDEO_BUFFER_COUNT) {
774 // Silently ignore this command
775 return INVALID_OPERATION;
776 } else if (cmd == CAMERA_CMD_PING) {
777 // If mHardware is 0, checkPidAndHardware will return error.
778 return OK;
779 }
780
781 return mHardware->sendCommand(cmd, arg1, arg2);
782 }
783
784 // ----------------------------------------------------------------------------
785
enableMsgType(int32_t msgType)786 void CameraClient::enableMsgType(int32_t msgType) {
787 android_atomic_or(msgType, &mMsgEnabled);
788 mHardware->enableMsgType(msgType);
789 }
790
disableMsgType(int32_t msgType)791 void CameraClient::disableMsgType(int32_t msgType) {
792 android_atomic_and(~msgType, &mMsgEnabled);
793 mHardware->disableMsgType(msgType);
794 }
795
796 #define CHECK_MESSAGE_INTERVAL 10 // 10ms
lockIfMessageWanted(int32_t msgType)797 bool CameraClient::lockIfMessageWanted(int32_t msgType) {
798 int sleepCount = 0;
799 while (mMsgEnabled & msgType) {
800 if (mLock.tryLock() == NO_ERROR) {
801 if (sleepCount > 0) {
802 LOG1("lockIfMessageWanted(%d): waited for %d ms",
803 msgType, sleepCount * CHECK_MESSAGE_INTERVAL);
804 }
805
806 // If messages are no longer enabled after acquiring lock, release and drop message
807 if ((mMsgEnabled & msgType) == 0) {
808 mLock.unlock();
809 break;
810 }
811
812 return true;
813 }
814 if (sleepCount++ == 0) {
815 LOG1("lockIfMessageWanted(%d): enter sleep", msgType);
816 }
817 usleep(CHECK_MESSAGE_INTERVAL * 1000);
818 }
819 ALOGW("lockIfMessageWanted(%d): dropped unwanted message", msgType);
820 return false;
821 }
822
getClientFromCookie(void * user)823 sp<CameraClient> CameraClient::getClientFromCookie(void* user) {
824 String8 cameraId = String8::format("%d", (int)(intptr_t) user);
825 auto clientDescriptor = sCameraService->mActiveClientManager.get(cameraId);
826 if (clientDescriptor != nullptr) {
827 return sp<CameraClient>{
828 static_cast<CameraClient*>(clientDescriptor->getValue().get())};
829 }
830 return sp<CameraClient>{nullptr};
831 }
832
833 // Callback messages can be dispatched to internal handlers or pass to our
834 // client's callback functions, depending on the message type.
835 //
836 // notifyCallback:
837 // CAMERA_MSG_SHUTTER handleShutter
838 // (others) c->notifyCallback
839 // dataCallback:
840 // CAMERA_MSG_PREVIEW_FRAME handlePreviewData
841 // CAMERA_MSG_POSTVIEW_FRAME handlePostview
842 // CAMERA_MSG_RAW_IMAGE handleRawPicture
843 // CAMERA_MSG_COMPRESSED_IMAGE handleCompressedPicture
844 // (others) c->dataCallback
845 // dataCallbackTimestamp
846 // (others) c->dataCallbackTimestamp
847
notifyCallback(int32_t msgType,int32_t ext1,int32_t ext2,void * user)848 void CameraClient::notifyCallback(int32_t msgType, int32_t ext1,
849 int32_t ext2, void* user) {
850 LOG2("notifyCallback(%d)", msgType);
851
852 sp<CameraClient> client = getClientFromCookie(user);
853 if (client.get() == nullptr) return;
854
855 if (!client->lockIfMessageWanted(msgType)) return;
856
857 switch (msgType) {
858 case CAMERA_MSG_SHUTTER:
859 // ext1 is the dimension of the yuv picture.
860 client->handleShutter();
861 break;
862 default:
863 client->handleGenericNotify(msgType, ext1, ext2);
864 break;
865 }
866 }
867
dataCallback(int32_t msgType,const sp<IMemory> & dataPtr,camera_frame_metadata_t * metadata,void * user)868 void CameraClient::dataCallback(int32_t msgType,
869 const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata, void* user) {
870 LOG2("dataCallback(%d)", msgType);
871
872 sp<CameraClient> client = getClientFromCookie(user);
873 if (client.get() == nullptr) return;
874
875 if (!client->lockIfMessageWanted(msgType)) return;
876 if (dataPtr == 0 && metadata == NULL) {
877 ALOGE("Null data returned in data callback");
878 client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
879 return;
880 }
881
882 switch (msgType & ~CAMERA_MSG_PREVIEW_METADATA) {
883 case CAMERA_MSG_PREVIEW_FRAME:
884 client->handlePreviewData(msgType, dataPtr, metadata);
885 break;
886 case CAMERA_MSG_POSTVIEW_FRAME:
887 client->handlePostview(dataPtr);
888 break;
889 case CAMERA_MSG_RAW_IMAGE:
890 client->handleRawPicture(dataPtr);
891 break;
892 case CAMERA_MSG_COMPRESSED_IMAGE:
893 client->handleCompressedPicture(dataPtr);
894 break;
895 default:
896 client->handleGenericData(msgType, dataPtr, metadata);
897 break;
898 }
899 }
900
dataCallbackTimestamp(nsecs_t timestamp,int32_t msgType,const sp<IMemory> & dataPtr,void * user)901 void CameraClient::dataCallbackTimestamp(nsecs_t timestamp,
902 int32_t msgType, const sp<IMemory>& dataPtr, void* user) {
903 LOG2("dataCallbackTimestamp(%d)", msgType);
904
905 sp<CameraClient> client = getClientFromCookie(user);
906 if (client.get() == nullptr) return;
907
908 if (!client->lockIfMessageWanted(msgType)) return;
909
910 if (dataPtr == 0) {
911 ALOGE("Null data returned in data with timestamp callback");
912 client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
913 return;
914 }
915
916 client->handleGenericDataTimestamp(timestamp, msgType, dataPtr);
917 }
918
handleCallbackTimestampBatch(int32_t msgType,const std::vector<HandleTimestampMessage> & msgs,void * user)919 void CameraClient::handleCallbackTimestampBatch(
920 int32_t msgType, const std::vector<HandleTimestampMessage>& msgs, void* user) {
921 LOG2("dataCallbackTimestampBatch");
922 sp<CameraClient> client = getClientFromCookie(user);
923 if (client.get() == nullptr) return;
924 if (!client->lockIfMessageWanted(msgType)) return;
925
926 sp<hardware::ICameraClient> c = client->mRemoteCallback;
927 client->mLock.unlock();
928 if (c != 0 && msgs.size() > 0) {
929 size_t n = msgs.size();
930 std::vector<nsecs_t> timestamps;
931 std::vector<native_handle_t*> handles;
932 timestamps.reserve(n);
933 handles.reserve(n);
934 for (auto& msg : msgs) {
935 native_handle_t* handle = nullptr;
936 if (msg.dataPtr->size() != sizeof(VideoNativeHandleMetadata)) {
937 ALOGE("%s: dataPtr does not contain VideoNativeHandleMetadata!", __FUNCTION__);
938 return;
939 }
940 VideoNativeHandleMetadata *metadata =
941 (VideoNativeHandleMetadata*)(msg.dataPtr->pointer());
942 if (metadata->eType == kMetadataBufferTypeNativeHandleSource) {
943 handle = metadata->pHandle;
944 }
945
946 if (handle == nullptr) {
947 ALOGE("%s: VideoNativeHandleMetadata type mismatch or null handle passed!",
948 __FUNCTION__);
949 return;
950 }
951 {
952 Mutex::Autolock l(client->mAvailableCallbackBuffersLock);
953 client->mAvailableCallbackBuffers.push_back(msg.dataPtr);
954 }
955 timestamps.push_back(msg.timestamp);
956 handles.push_back(handle);
957 }
958 c->recordingFrameHandleCallbackTimestampBatch(timestamps, handles);
959 }
960 }
961
962 // snapshot taken callback
handleShutter(void)963 void CameraClient::handleShutter(void) {
964 if (mPlayShutterSound) {
965 sCameraService->playSound(CameraService::SOUND_SHUTTER);
966 }
967
968 sp<hardware::ICameraClient> c = mRemoteCallback;
969 if (c != 0) {
970 mLock.unlock();
971 c->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);
972 if (!lockIfMessageWanted(CAMERA_MSG_SHUTTER)) return;
973 }
974 disableMsgType(CAMERA_MSG_SHUTTER);
975
976 // Shutters only happen in response to takePicture, so mark device as
977 // idle now, until preview is restarted
978 sCameraService->updateProxyDeviceState(
979 hardware::ICameraServiceProxy::CAMERA_STATE_IDLE,
980 mCameraIdStr, mCameraFacing, mClientPackageName,
981 hardware::ICameraServiceProxy::CAMERA_API_LEVEL_1);
982
983 mLock.unlock();
984 }
985
986 // preview callback - frame buffer update
handlePreviewData(int32_t msgType,const sp<IMemory> & mem,camera_frame_metadata_t * metadata)987 void CameraClient::handlePreviewData(int32_t msgType,
988 const sp<IMemory>& mem,
989 camera_frame_metadata_t *metadata) {
990 ssize_t offset;
991 size_t size;
992 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
993
994 // local copy of the callback flags
995 int flags = mPreviewCallbackFlag;
996
997 // is callback enabled?
998 if (!(flags & CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
999 // If the enable bit is off, the copy-out and one-shot bits are ignored
1000 LOG2("frame callback is disabled");
1001 mLock.unlock();
1002 return;
1003 }
1004
1005 // hold a strong pointer to the client
1006 sp<hardware::ICameraClient> c = mRemoteCallback;
1007
1008 // clear callback flags if no client or one-shot mode
1009 if (c == 0 || (mPreviewCallbackFlag & CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK)) {
1010 LOG2("Disable preview callback");
1011 mPreviewCallbackFlag &= ~(CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
1012 CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
1013 CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK);
1014 disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
1015 }
1016
1017 if (c != 0) {
1018 // Is the received frame copied out or not?
1019 if (flags & CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
1020 LOG2("frame is copied");
1021 copyFrameAndPostCopiedFrame(msgType, c, heap, offset, size, metadata);
1022 } else {
1023 LOG2("frame is forwarded");
1024 mLock.unlock();
1025 c->dataCallback(msgType, mem, metadata);
1026 }
1027 } else {
1028 mLock.unlock();
1029 }
1030 }
1031
1032 // picture callback - postview image ready
handlePostview(const sp<IMemory> & mem)1033 void CameraClient::handlePostview(const sp<IMemory>& mem) {
1034 disableMsgType(CAMERA_MSG_POSTVIEW_FRAME);
1035
1036 sp<hardware::ICameraClient> c = mRemoteCallback;
1037 mLock.unlock();
1038 if (c != 0) {
1039 c->dataCallback(CAMERA_MSG_POSTVIEW_FRAME, mem, NULL);
1040 }
1041 }
1042
1043 // picture callback - raw image ready
handleRawPicture(const sp<IMemory> & mem)1044 void CameraClient::handleRawPicture(const sp<IMemory>& mem) {
1045 disableMsgType(CAMERA_MSG_RAW_IMAGE);
1046
1047 ssize_t offset;
1048 size_t size;
1049 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
1050
1051 sp<hardware::ICameraClient> c = mRemoteCallback;
1052 mLock.unlock();
1053 if (c != 0) {
1054 c->dataCallback(CAMERA_MSG_RAW_IMAGE, mem, NULL);
1055 }
1056 }
1057
1058 // picture callback - compressed picture ready
handleCompressedPicture(const sp<IMemory> & mem)1059 void CameraClient::handleCompressedPicture(const sp<IMemory>& mem) {
1060 disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);
1061
1062 sp<hardware::ICameraClient> c = mRemoteCallback;
1063 mLock.unlock();
1064 if (c != 0) {
1065 c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem, NULL);
1066 }
1067 }
1068
1069
handleGenericNotify(int32_t msgType,int32_t ext1,int32_t ext2)1070 void CameraClient::handleGenericNotify(int32_t msgType,
1071 int32_t ext1, int32_t ext2) {
1072 sp<hardware::ICameraClient> c = mRemoteCallback;
1073 mLock.unlock();
1074 if (c != 0) {
1075 c->notifyCallback(msgType, ext1, ext2);
1076 }
1077 }
1078
handleGenericData(int32_t msgType,const sp<IMemory> & dataPtr,camera_frame_metadata_t * metadata)1079 void CameraClient::handleGenericData(int32_t msgType,
1080 const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata) {
1081 sp<hardware::ICameraClient> c = mRemoteCallback;
1082 mLock.unlock();
1083 if (c != 0) {
1084 c->dataCallback(msgType, dataPtr, metadata);
1085 }
1086 }
1087
handleGenericDataTimestamp(nsecs_t timestamp,int32_t msgType,const sp<IMemory> & dataPtr)1088 void CameraClient::handleGenericDataTimestamp(nsecs_t timestamp,
1089 int32_t msgType, const sp<IMemory>& dataPtr) {
1090 sp<hardware::ICameraClient> c = mRemoteCallback;
1091 mLock.unlock();
1092 if (c != 0 && dataPtr != nullptr) {
1093 native_handle_t* handle = nullptr;
1094
1095 // Check if dataPtr contains a VideoNativeHandleMetadata.
1096 if (dataPtr->size() == sizeof(VideoNativeHandleMetadata)) {
1097 VideoNativeHandleMetadata *metadata =
1098 (VideoNativeHandleMetadata*)(dataPtr->pointer());
1099 if (metadata->eType == kMetadataBufferTypeNativeHandleSource) {
1100 handle = metadata->pHandle;
1101 }
1102 }
1103
1104 // If dataPtr contains a native handle, send it via recordingFrameHandleCallbackTimestamp.
1105 if (handle != nullptr) {
1106 {
1107 Mutex::Autolock l(mAvailableCallbackBuffersLock);
1108 mAvailableCallbackBuffers.push_back(dataPtr);
1109 }
1110 c->recordingFrameHandleCallbackTimestamp(timestamp, handle);
1111 } else {
1112 c->dataCallbackTimestamp(timestamp, msgType, dataPtr);
1113 }
1114 }
1115 }
1116
copyFrameAndPostCopiedFrame(int32_t msgType,const sp<hardware::ICameraClient> & client,const sp<IMemoryHeap> & heap,size_t offset,size_t size,camera_frame_metadata_t * metadata)1117 void CameraClient::copyFrameAndPostCopiedFrame(
1118 int32_t msgType, const sp<hardware::ICameraClient>& client,
1119 const sp<IMemoryHeap>& heap, size_t offset, size_t size,
1120 camera_frame_metadata_t *metadata) {
1121 LOG2("copyFrameAndPostCopiedFrame");
1122 // It is necessary to copy out of pmem before sending this to
1123 // the callback. For efficiency, reuse the same MemoryHeapBase
1124 // provided it's big enough. Don't allocate the memory or
1125 // perform the copy if there's no callback.
1126 // hold the preview lock while we grab a reference to the preview buffer
1127 sp<MemoryHeapBase> previewBuffer;
1128
1129 if (mPreviewBuffer == 0) {
1130 mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
1131 } else if (size > mPreviewBuffer->virtualSize()) {
1132 mPreviewBuffer.clear();
1133 mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
1134 }
1135 if (mPreviewBuffer == 0) {
1136 ALOGE("failed to allocate space for preview buffer");
1137 mLock.unlock();
1138 return;
1139 }
1140 previewBuffer = mPreviewBuffer;
1141
1142 void* previewBufferBase = previewBuffer->base();
1143 void* heapBase = heap->base();
1144
1145 if (heapBase == MAP_FAILED) {
1146 ALOGE("%s: Failed to mmap heap for preview frame.", __FUNCTION__);
1147 mLock.unlock();
1148 return;
1149 } else if (previewBufferBase == MAP_FAILED) {
1150 ALOGE("%s: Failed to mmap preview buffer for preview frame.", __FUNCTION__);
1151 mLock.unlock();
1152 return;
1153 }
1154
1155 memcpy(previewBufferBase, (uint8_t *) heapBase + offset, size);
1156
1157 sp<MemoryBase> frame = new MemoryBase(previewBuffer, 0, size);
1158 if (frame == 0) {
1159 ALOGE("failed to allocate space for frame callback");
1160 mLock.unlock();
1161 return;
1162 }
1163
1164 mLock.unlock();
1165 client->dataCallback(msgType, frame, metadata);
1166 }
1167
getOrientation(int degrees,bool mirror)1168 int CameraClient::getOrientation(int degrees, bool mirror) {
1169 if (!mirror) {
1170 if (degrees == 0) return 0;
1171 else if (degrees == 90) return HAL_TRANSFORM_ROT_90;
1172 else if (degrees == 180) return HAL_TRANSFORM_ROT_180;
1173 else if (degrees == 270) return HAL_TRANSFORM_ROT_270;
1174 } else { // Do mirror (horizontal flip)
1175 if (degrees == 0) { // FLIP_H and ROT_0
1176 return HAL_TRANSFORM_FLIP_H;
1177 } else if (degrees == 90) { // FLIP_H and ROT_90
1178 return HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_ROT_90;
1179 } else if (degrees == 180) { // FLIP_H and ROT_180
1180 return HAL_TRANSFORM_FLIP_V;
1181 } else if (degrees == 270) { // FLIP_H and ROT_270
1182 return HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90;
1183 }
1184 }
1185 ALOGE("Invalid setDisplayOrientation degrees=%d", degrees);
1186 return -1;
1187 }
1188
setVideoTarget(const sp<IGraphicBufferProducer> & bufferProducer)1189 status_t CameraClient::setVideoTarget(const sp<IGraphicBufferProducer>& bufferProducer) {
1190 (void)bufferProducer;
1191 ALOGE("%s: %d: CameraClient doesn't support setting a video target.", __FUNCTION__, __LINE__);
1192 return INVALID_OPERATION;
1193 }
1194
1195 }; // namespace android
1196