blob: e417b790d600a24ed6502eae1ec80f8eb7cb9b3a [file] [log] [blame]
James Dong8eb69d62011-03-17 11:48:13 -07001/*
2 * Copyright (C) 2010 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
Mathias Agopian65ab4712010-07-14 17:59:35 -070017#define LOG_TAG "CameraServiceTest"
18
19#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22#include <sys/types.h>
23#include <sys/wait.h>
24#include <unistd.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070025#include <camera/Camera.h>
26#include <camera/CameraParameters.h>
27#include <ui/GraphicBuffer.h>
28#include <camera/ICamera.h>
29#include <camera/ICameraClient.h>
30#include <camera/ICameraService.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070031#include <binder/IPCThreadState.h>
32#include <binder/IServiceManager.h>
33#include <binder/ProcessState.h>
34#include <utils/KeyedVector.h>
35#include <utils/Log.h>
36#include <utils/Vector.h>
37#include <utils/threads.h>
38
39using namespace android;
40
41//
42// Assertion and Logging utilities
43//
44#define INFO(...) \
45 do { \
46 printf(__VA_ARGS__); \
47 printf("\n"); \
Steve Blockb8a80522011-12-20 16:23:08 +000048 ALOGD(__VA_ARGS__); \
Mathias Agopian65ab4712010-07-14 17:59:35 -070049 } while(0)
50
51void assert_fail(const char *file, int line, const char *func, const char *expr) {
52 INFO("assertion failed at file %s, line %d, function %s:",
53 file, line, func);
54 INFO("%s", expr);
55 abort();
56}
57
58void assert_eq_fail(const char *file, int line, const char *func,
59 const char *expr, int actual) {
60 INFO("assertion failed at file %s, line %d, function %s:",
61 file, line, func);
62 INFO("(expected) %s != (actual) %d", expr, actual);
63 abort();
64}
65
66#define ASSERT(e) \
67 do { \
68 if (!(e)) \
69 assert_fail(__FILE__, __LINE__, __func__, #e); \
70 } while(0)
71
72#define ASSERT_EQ(expected, actual) \
73 do { \
74 int _x = (actual); \
75 if (_x != (expected)) \
76 assert_eq_fail(__FILE__, __LINE__, __func__, #expected, _x); \
77 } while(0)
78
79//
80// Holder service for pass objects between processes.
81//
82class IHolder : public IInterface {
83protected:
84 enum {
85 HOLDER_PUT = IBinder::FIRST_CALL_TRANSACTION,
86 HOLDER_GET,
87 HOLDER_CLEAR
88 };
89public:
90 DECLARE_META_INTERFACE(Holder);
91
92 virtual void put(sp<IBinder> obj) = 0;
93 virtual sp<IBinder> get() = 0;
94 virtual void clear() = 0;
95};
96
97class BnHolder : public BnInterface<IHolder> {
98 virtual status_t onTransact(uint32_t code,
99 const Parcel& data,
100 Parcel* reply,
101 uint32_t flags = 0);
102};
103
104class BpHolder : public BpInterface<IHolder> {
105public:
106 BpHolder(const sp<IBinder>& impl)
107 : BpInterface<IHolder>(impl) {
108 }
109
110 virtual void put(sp<IBinder> obj) {
111 Parcel data, reply;
112 data.writeStrongBinder(obj);
113 remote()->transact(HOLDER_PUT, data, &reply, IBinder::FLAG_ONEWAY);
114 }
115
116 virtual sp<IBinder> get() {
117 Parcel data, reply;
118 remote()->transact(HOLDER_GET, data, &reply);
119 return reply.readStrongBinder();
120 }
121
122 virtual void clear() {
123 Parcel data, reply;
124 remote()->transact(HOLDER_CLEAR, data, &reply);
125 }
126};
127
128IMPLEMENT_META_INTERFACE(Holder, "CameraServiceTest.Holder");
129
130status_t BnHolder::onTransact(
131 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
132 switch(code) {
133 case HOLDER_PUT: {
134 put(data.readStrongBinder());
135 return NO_ERROR;
136 } break;
137 case HOLDER_GET: {
138 reply->writeStrongBinder(get());
139 return NO_ERROR;
140 } break;
141 case HOLDER_CLEAR: {
142 clear();
143 return NO_ERROR;
144 } break;
145 default:
146 return BBinder::onTransact(code, data, reply, flags);
147 }
148}
149
150class HolderService : public BnHolder {
151 virtual void put(sp<IBinder> obj) {
152 mObj = obj;
153 }
154 virtual sp<IBinder> get() {
155 return mObj;
156 }
157 virtual void clear() {
158 mObj.clear();
159 }
160private:
161 sp<IBinder> mObj;
162};
163
164//
165// A mock CameraClient
166//
167class MCameraClient : public BnCameraClient {
168public:
169 virtual void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2);
170 virtual void dataCallback(int32_t msgType, const sp<IMemory>& data);
171 virtual void dataCallbackTimestamp(nsecs_t timestamp,
172 int32_t msgType, const sp<IMemory>& data);
173
174 // new functions
175 void clearStat();
176 enum OP { EQ, GE, LE, GT, LT };
177 void assertNotify(int32_t msgType, OP op, int count);
178 void assertData(int32_t msgType, OP op, int count);
179 void waitNotify(int32_t msgType, OP op, int count);
180 void waitData(int32_t msgType, OP op, int count);
181 void assertDataSize(int32_t msgType, OP op, int dataSize);
182
183 void setReleaser(ICamera *releaser) {
184 mReleaser = releaser;
185 }
186private:
187 Mutex mLock;
188 Condition mCond;
189 DefaultKeyedVector<int32_t, int> mNotifyCount;
190 DefaultKeyedVector<int32_t, int> mDataCount;
191 DefaultKeyedVector<int32_t, int> mDataSize;
192 bool test(OP op, int v1, int v2);
193 void assertTest(OP op, int v1, int v2);
194
195 ICamera *mReleaser;
196};
197
198void MCameraClient::clearStat() {
199 Mutex::Autolock _l(mLock);
200 mNotifyCount.clear();
201 mDataCount.clear();
202 mDataSize.clear();
203}
204
205bool MCameraClient::test(OP op, int v1, int v2) {
206 switch (op) {
207 case EQ: return v1 == v2;
208 case GT: return v1 > v2;
209 case LT: return v1 < v2;
210 case GE: return v1 >= v2;
211 case LE: return v1 <= v2;
212 default: ASSERT(0); break;
213 }
214 return false;
215}
216
217void MCameraClient::assertTest(OP op, int v1, int v2) {
218 if (!test(op, v1, v2)) {
Steve Block29357bc2012-01-06 19:20:56 +0000219 ALOGE("assertTest failed: op=%d, v1=%d, v2=%d", op, v1, v2);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700220 ASSERT(0);
221 }
222}
223
224void MCameraClient::assertNotify(int32_t msgType, OP op, int count) {
225 Mutex::Autolock _l(mLock);
226 int v = mNotifyCount.valueFor(msgType);
227 assertTest(op, v, count);
228}
229
230void MCameraClient::assertData(int32_t msgType, OP op, int count) {
231 Mutex::Autolock _l(mLock);
232 int v = mDataCount.valueFor(msgType);
233 assertTest(op, v, count);
234}
235
236void MCameraClient::assertDataSize(int32_t msgType, OP op, int dataSize) {
237 Mutex::Autolock _l(mLock);
238 int v = mDataSize.valueFor(msgType);
239 assertTest(op, v, dataSize);
240}
241
242void MCameraClient::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) {
243 INFO("%s", __func__);
244 Mutex::Autolock _l(mLock);
245 ssize_t i = mNotifyCount.indexOfKey(msgType);
246 if (i < 0) {
247 mNotifyCount.add(msgType, 1);
248 } else {
249 ++mNotifyCount.editValueAt(i);
250 }
251 mCond.signal();
252}
253
254void MCameraClient::dataCallback(int32_t msgType, const sp<IMemory>& data) {
255 INFO("%s", __func__);
256 int dataSize = data->size();
257 INFO("data type = %d, size = %d", msgType, dataSize);
258 Mutex::Autolock _l(mLock);
259 ssize_t i = mDataCount.indexOfKey(msgType);
260 if (i < 0) {
261 mDataCount.add(msgType, 1);
262 mDataSize.add(msgType, dataSize);
263 } else {
264 ++mDataCount.editValueAt(i);
265 mDataSize.editValueAt(i) = dataSize;
266 }
267 mCond.signal();
268
269 if (msgType == CAMERA_MSG_VIDEO_FRAME) {
270 ASSERT(mReleaser != NULL);
271 mReleaser->releaseRecordingFrame(data);
272 }
273}
274
275void MCameraClient::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType,
276 const sp<IMemory>& data) {
277 dataCallback(msgType, data);
278}
279
280void MCameraClient::waitNotify(int32_t msgType, OP op, int count) {
281 INFO("waitNotify: %d, %d, %d", msgType, op, count);
282 Mutex::Autolock _l(mLock);
283 while (true) {
284 int v = mNotifyCount.valueFor(msgType);
285 if (test(op, v, count)) {
286 break;
287 }
288 mCond.wait(mLock);
289 }
290}
291
292void MCameraClient::waitData(int32_t msgType, OP op, int count) {
293 INFO("waitData: %d, %d, %d", msgType, op, count);
294 Mutex::Autolock _l(mLock);
295 while (true) {
296 int v = mDataCount.valueFor(msgType);
297 if (test(op, v, count)) {
298 break;
299 }
300 mCond.wait(mLock);
301 }
302}
303
304//
305// A mock Surface
306//
307class MSurface : public BnSurface {
308public:
309 virtual status_t registerBuffers(const BufferHeap& buffers);
310 virtual void postBuffer(ssize_t offset);
311 virtual void unregisterBuffers();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700312 virtual sp<GraphicBuffer> requestBuffer(int bufferIdx, int usage);
313 virtual status_t setBufferCount(int bufferCount);
314
315 // new functions
316 void clearStat();
317 void waitUntil(int c0, int c1, int c2);
318
319private:
320 // check callback count
321 Condition mCond;
322 Mutex mLock;
323 int registerBuffersCount;
324 int postBufferCount;
325 int unregisterBuffersCount;
326};
327
328status_t MSurface::registerBuffers(const BufferHeap& buffers) {
329 INFO("%s", __func__);
330 Mutex::Autolock _l(mLock);
331 ++registerBuffersCount;
332 mCond.signal();
333 return NO_ERROR;
334}
335
336void MSurface::postBuffer(ssize_t offset) {
337 // INFO("%s", __func__);
338 Mutex::Autolock _l(mLock);
339 ++postBufferCount;
340 mCond.signal();
341}
342
343void MSurface::unregisterBuffers() {
344 INFO("%s", __func__);
345 Mutex::Autolock _l(mLock);
346 ++unregisterBuffersCount;
347 mCond.signal();
348}
349
350sp<GraphicBuffer> MSurface::requestBuffer(int bufferIdx, int usage) {
351 INFO("%s", __func__);
352 return NULL;
353}
354
355status_t MSurface::setBufferCount(int bufferCount) {
356 INFO("%s", __func__);
357 return NULL;
358}
359
360void MSurface::clearStat() {
361 Mutex::Autolock _l(mLock);
362 registerBuffersCount = 0;
363 postBufferCount = 0;
364 unregisterBuffersCount = 0;
365}
366
367void MSurface::waitUntil(int c0, int c1, int c2) {
368 INFO("waitUntil: %d %d %d", c0, c1, c2);
369 Mutex::Autolock _l(mLock);
370 while (true) {
371 if (registerBuffersCount >= c0 &&
372 postBufferCount >= c1 &&
373 unregisterBuffersCount >= c2) {
374 break;
375 }
376 mCond.wait(mLock);
377 }
378}
379
Mathias Agopian65ab4712010-07-14 17:59:35 -0700380//
381// Utilities to use the Holder service
382//
383sp<IHolder> getHolder() {
384 sp<IServiceManager> sm = defaultServiceManager();
385 ASSERT(sm != 0);
386 sp<IBinder> binder = sm->getService(String16("CameraServiceTest.Holder"));
387 ASSERT(binder != 0);
388 sp<IHolder> holder = interface_cast<IHolder>(binder);
389 ASSERT(holder != 0);
390 return holder;
391}
392
393void putTempObject(sp<IBinder> obj) {
394 INFO("%s", __func__);
395 getHolder()->put(obj);
396}
397
398sp<IBinder> getTempObject() {
399 INFO("%s", __func__);
400 return getHolder()->get();
401}
402
403void clearTempObject() {
404 INFO("%s", __func__);
405 getHolder()->clear();
406}
407
408//
409// Get a Camera Service
410//
411sp<ICameraService> getCameraService() {
412 sp<IServiceManager> sm = defaultServiceManager();
413 ASSERT(sm != 0);
414 sp<IBinder> binder = sm->getService(String16("media.camera"));
415 ASSERT(binder != 0);
416 sp<ICameraService> cs = interface_cast<ICameraService>(binder);
417 ASSERT(cs != 0);
418 return cs;
419}
420
421int getNumberOfCameras() {
422 sp<ICameraService> cs = getCameraService();
423 return cs->getNumberOfCameras();
424}
425
426//
427// Various Connect Tests
428//
429void testConnect(int cameraId) {
430 INFO("%s", __func__);
431 sp<ICameraService> cs = getCameraService();
432 sp<MCameraClient> cc = new MCameraClient();
433 sp<ICamera> c = cs->connect(cc, cameraId);
434 ASSERT(c != 0);
435 c->disconnect();
436}
437
438void testAllowConnectOnceOnly(int cameraId) {
439 INFO("%s", __func__);
440 sp<ICameraService> cs = getCameraService();
441 // Connect the first client.
442 sp<MCameraClient> cc = new MCameraClient();
443 sp<ICamera> c = cs->connect(cc, cameraId);
444 ASSERT(c != 0);
445 // Same client -- ok.
446 ASSERT(cs->connect(cc, cameraId) != 0);
447 // Different client -- not ok.
448 sp<MCameraClient> cc2 = new MCameraClient();
449 ASSERT(cs->connect(cc2, cameraId) == 0);
450 c->disconnect();
451}
452
453void testReconnectFailed() {
454 INFO("%s", __func__);
455 sp<ICamera> c = interface_cast<ICamera>(getTempObject());
456 sp<MCameraClient> cc = new MCameraClient();
457 ASSERT(c->connect(cc) != NO_ERROR);
458}
459
460void testReconnectSuccess() {
461 INFO("%s", __func__);
462 sp<ICamera> c = interface_cast<ICamera>(getTempObject());
463 sp<MCameraClient> cc = new MCameraClient();
464 ASSERT(c->connect(cc) == NO_ERROR);
465 c->disconnect();
466}
467
468void testLockFailed() {
469 INFO("%s", __func__);
470 sp<ICamera> c = interface_cast<ICamera>(getTempObject());
471 ASSERT(c->lock() != NO_ERROR);
472}
473
474void testLockUnlockSuccess() {
475 INFO("%s", __func__);
476 sp<ICamera> c = interface_cast<ICamera>(getTempObject());
477 ASSERT(c->lock() == NO_ERROR);
478 ASSERT(c->unlock() == NO_ERROR);
479}
480
481void testLockSuccess() {
482 INFO("%s", __func__);
483 sp<ICamera> c = interface_cast<ICamera>(getTempObject());
484 ASSERT(c->lock() == NO_ERROR);
485 c->disconnect();
486}
487
488//
489// Run the connect tests in another process.
490//
491const char *gExecutable;
492
493struct FunctionTableEntry {
494 const char *name;
495 void (*func)();
496};
497
498FunctionTableEntry function_table[] = {
499#define ENTRY(x) {#x, &x}
500 ENTRY(testReconnectFailed),
501 ENTRY(testReconnectSuccess),
502 ENTRY(testLockUnlockSuccess),
503 ENTRY(testLockFailed),
504 ENTRY(testLockSuccess),
505#undef ENTRY
506};
507
508void runFunction(const char *tag) {
509 INFO("runFunction: %s", tag);
510 int entries = sizeof(function_table) / sizeof(function_table[0]);
511 for (int i = 0; i < entries; i++) {
512 if (strcmp(function_table[i].name, tag) == 0) {
513 (*function_table[i].func)();
514 return;
515 }
516 }
517 ASSERT(0);
518}
519
520void runInAnotherProcess(const char *tag) {
521 pid_t pid = fork();
522 if (pid == 0) {
523 execlp(gExecutable, gExecutable, tag, NULL);
524 ASSERT(0);
525 } else {
526 int status;
527 ASSERT_EQ(pid, wait(&status));
528 ASSERT_EQ(0, status);
529 }
530}
531
532void testReconnect(int cameraId) {
533 INFO("%s", __func__);
534 sp<ICameraService> cs = getCameraService();
535 sp<MCameraClient> cc = new MCameraClient();
536 sp<ICamera> c = cs->connect(cc, cameraId);
537 ASSERT(c != 0);
538 // Reconnect to the same client -- ok.
539 ASSERT(c->connect(cc) == NO_ERROR);
540 // Reconnect to a different client (but the same pid) -- ok.
541 sp<MCameraClient> cc2 = new MCameraClient();
542 ASSERT(c->connect(cc2) == NO_ERROR);
543 c->disconnect();
544 cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
545}
546
547void testLockUnlock(int cameraId) {
548 sp<ICameraService> cs = getCameraService();
549 sp<MCameraClient> cc = new MCameraClient();
550 sp<ICamera> c = cs->connect(cc, cameraId);
551 ASSERT(c != 0);
552 // We can lock as many times as we want.
553 ASSERT(c->lock() == NO_ERROR);
554 ASSERT(c->lock() == NO_ERROR);
555 // Lock from a different process -- not ok.
556 putTempObject(c->asBinder());
557 runInAnotherProcess("testLockFailed");
558 // Unlock then lock from a different process -- ok.
559 ASSERT(c->unlock() == NO_ERROR);
560 runInAnotherProcess("testLockUnlockSuccess");
561 // Unlock then lock from a different process -- ok.
562 runInAnotherProcess("testLockSuccess");
563 clearTempObject();
564}
565
566void testReconnectFromAnotherProcess(int cameraId) {
567 INFO("%s", __func__);
568
569 sp<ICameraService> cs = getCameraService();
570 sp<MCameraClient> cc = new MCameraClient();
571 sp<ICamera> c = cs->connect(cc, cameraId);
572 ASSERT(c != 0);
573 // Reconnect from a different process -- not ok.
574 putTempObject(c->asBinder());
575 runInAnotherProcess("testReconnectFailed");
576 // Unlock then reconnect from a different process -- ok.
577 ASSERT(c->unlock() == NO_ERROR);
578 runInAnotherProcess("testReconnectSuccess");
579 clearTempObject();
580}
581
582// We need to flush the command buffer after the reference
583// to ICamera is gone. The sleep is for the server to run
584// the destructor for it.
585static void flushCommands() {
586 IPCThreadState::self()->flushCommands();
587 usleep(200000); // 200ms
588}
589
590// Run a test case
591#define RUN(class_name, cameraId) do { \
592 { \
593 INFO(#class_name); \
594 class_name instance; \
595 instance.init(cameraId); \
596 instance.run(); \
597 } \
598 flushCommands(); \
599} while(0)
600
601// Base test case after the the camera is connected.
602class AfterConnect {
603public:
604 void init(int cameraId) {
605 cs = getCameraService();
606 cc = new MCameraClient();
607 c = cs->connect(cc, cameraId);
608 ASSERT(c != 0);
609 }
610
611protected:
612 sp<ICameraService> cs;
613 sp<MCameraClient> cc;
614 sp<ICamera> c;
615
616 ~AfterConnect() {
617 c->disconnect();
618 c.clear();
619 cc.clear();
620 cs.clear();
621 }
622};
623
624class TestSetPreviewDisplay : public AfterConnect {
625public:
626 void run() {
627 sp<MSurface> surface = new MSurface();
628 ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
629 c->disconnect();
630 cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
631 }
632};
633
634class TestStartPreview : public AfterConnect {
635public:
636 void run() {
637 sp<MSurface> surface = new MSurface();
638 ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
639
640 ASSERT(c->startPreview() == NO_ERROR);
641 ASSERT(c->previewEnabled() == true);
642
643 surface->waitUntil(1, 10, 0); // needs 1 registerBuffers and 10 postBuffer
644 surface->clearStat();
645
646 sp<MSurface> another_surface = new MSurface();
647 c->setPreviewDisplay(another_surface); // just to make sure unregisterBuffers
648 // is called.
649 surface->waitUntil(0, 0, 1); // needs unregisterBuffers
650
651 cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
652 }
653};
654
655class TestStartPreviewWithoutDisplay : public AfterConnect {
656public:
657 void run() {
658 ASSERT(c->startPreview() == NO_ERROR);
659 ASSERT(c->previewEnabled() == true);
660 c->disconnect();
661 cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
662 }
663};
664
665// Base test case after the the camera is connected and the preview is started.
666class AfterStartPreview : public AfterConnect {
667public:
668 void init(int cameraId) {
669 AfterConnect::init(cameraId);
670 surface = new MSurface();
671 ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
672 ASSERT(c->startPreview() == NO_ERROR);
673 }
674
675protected:
676 sp<MSurface> surface;
677
678 ~AfterStartPreview() {
679 surface.clear();
680 }
681};
682
683class TestAutoFocus : public AfterStartPreview {
684public:
685 void run() {
686 cc->assertNotify(CAMERA_MSG_FOCUS, MCameraClient::EQ, 0);
687 c->autoFocus();
688 cc->waitNotify(CAMERA_MSG_FOCUS, MCameraClient::EQ, 1);
689 c->disconnect();
690 cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
691 }
692};
693
694class TestStopPreview : public AfterStartPreview {
695public:
696 void run() {
697 ASSERT(c->previewEnabled() == true);
698 c->stopPreview();
699 ASSERT(c->previewEnabled() == false);
700 c->disconnect();
701 cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
702 }
703};
704
705class TestTakePicture: public AfterStartPreview {
706public:
707 void run() {
708 ASSERT(c->takePicture() == NO_ERROR);
709 cc->waitNotify(CAMERA_MSG_SHUTTER, MCameraClient::EQ, 1);
710 cc->waitData(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, 1);
711 cc->waitData(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::EQ, 1);
712 c->stopPreview();
713 c->disconnect();
714 cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
715 }
716};
717
718class TestTakeMultiplePictures: public AfterStartPreview {
719public:
720 void run() {
721 for (int i = 0; i < 10; i++) {
722 cc->clearStat();
723 ASSERT(c->takePicture() == NO_ERROR);
724 cc->waitNotify(CAMERA_MSG_SHUTTER, MCameraClient::EQ, 1);
725 cc->waitData(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, 1);
726 cc->waitData(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::EQ, 1);
727 }
728 c->disconnect();
729 cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
730 }
731};
732
733class TestGetParameters: public AfterStartPreview {
734public:
735 void run() {
736 String8 param_str = c->getParameters();
737 INFO("%s", static_cast<const char*>(param_str));
738 }
739};
740
741static bool getNextSize(const char **ptrS, int *w, int *h) {
742 const char *s = *ptrS;
743
744 // skip over ','
745 if (*s == ',') s++;
746
747 // remember start position in p
748 const char *p = s;
749 while (*s != '\0' && *s != 'x') {
750 s++;
751 }
752 if (*s == '\0') return false;
753
754 // get the width
755 *w = atoi(p);
756
757 // skip over 'x'
758 ASSERT(*s == 'x');
759 p = s + 1;
760 while (*s != '\0' && *s != ',') {
761 s++;
762 }
763
764 // get the height
765 *h = atoi(p);
766 *ptrS = s;
767 return true;
768}
769
770class TestPictureSize : public AfterStartPreview {
771public:
772 void checkOnePicture(int w, int h) {
773 const float rate = 0.9; // byte per pixel limit
774 int pixels = w * h;
775
776 CameraParameters param(c->getParameters());
777 param.setPictureSize(w, h);
778 // disable thumbnail to get more accurate size.
779 param.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, 0);
780 param.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, 0);
781 c->setParameters(param.flatten());
782
783 cc->clearStat();
784 ASSERT(c->takePicture() == NO_ERROR);
785 cc->waitData(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, 1);
786 //cc->assertDataSize(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, pixels*3/2);
787 cc->waitData(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::EQ, 1);
788 cc->assertDataSize(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::LT,
789 int(pixels * rate));
790 cc->assertDataSize(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::GT, 0);
791 cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
792 }
793
794 void run() {
795 CameraParameters param(c->getParameters());
796 int w, h;
797 const char *s = param.get(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES);
798 while (getNextSize(&s, &w, &h)) {
Steve Blockb8a80522011-12-20 16:23:08 +0000799 ALOGD("checking picture size %dx%d", w, h);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700800 checkOnePicture(w, h);
801 }
802 }
803};
804
805class TestPreviewCallbackFlag : public AfterConnect {
806public:
807 void run() {
808 sp<MSurface> surface = new MSurface();
809 ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
810
811 // Try all flag combinations.
812 for (int v = 0; v < 8; v++) {
Steve Blockb8a80522011-12-20 16:23:08 +0000813 ALOGD("TestPreviewCallbackFlag: flag=%d", v);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700814 usleep(100000); // sleep a while to clear the in-flight callbacks.
815 cc->clearStat();
816 c->setPreviewCallbackFlag(v);
817 ASSERT(c->previewEnabled() == false);
818 ASSERT(c->startPreview() == NO_ERROR);
819 ASSERT(c->previewEnabled() == true);
820 sleep(2);
821 c->stopPreview();
Iliyan Malchev9e626522011-04-14 16:51:21 -0700822 if ((v & CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK) == 0) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700823 cc->assertData(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::EQ, 0);
824 } else {
Iliyan Malchev9e626522011-04-14 16:51:21 -0700825 if ((v & CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) == 0) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700826 cc->assertData(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::GE, 10);
827 } else {
828 cc->assertData(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::EQ, 1);
829 }
830 }
831 }
832 }
833};
834
835class TestRecording : public AfterConnect {
836public:
837 void run() {
838 ASSERT(c->recordingEnabled() == false);
839 sp<MSurface> surface = new MSurface();
840 ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
Iliyan Malchev9e626522011-04-14 16:51:21 -0700841 c->setPreviewCallbackFlag(CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700842 cc->setReleaser(c.get());
843 c->startRecording();
844 ASSERT(c->recordingEnabled() == true);
845 sleep(2);
846 c->stopRecording();
847 usleep(100000); // sleep a while to clear the in-flight callbacks.
848 cc->setReleaser(NULL);
849 cc->assertData(CAMERA_MSG_VIDEO_FRAME, MCameraClient::GE, 10);
850 }
851};
852
853class TestPreviewSize : public AfterStartPreview {
854public:
855 void checkOnePicture(int w, int h) {
856 int size = w*h*3/2; // should read from parameters
857
858 c->stopPreview();
859
860 CameraParameters param(c->getParameters());
861 param.setPreviewSize(w, h);
Iliyan Malchev9e626522011-04-14 16:51:21 -0700862 c->setPreviewCallbackFlag(CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700863 c->setParameters(param.flatten());
864
865 c->startPreview();
866
867 cc->clearStat();
868 cc->waitData(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::GE, 1);
869 cc->assertDataSize(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::EQ, size);
870 }
871
872 void run() {
873 CameraParameters param(c->getParameters());
874 int w, h;
875 const char *s = param.get(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES);
876 while (getNextSize(&s, &w, &h)) {
Steve Blockb8a80522011-12-20 16:23:08 +0000877 ALOGD("checking preview size %dx%d", w, h);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700878 checkOnePicture(w, h);
879 }
880 }
881};
882
883void runHolderService() {
884 defaultServiceManager()->addService(
885 String16("CameraServiceTest.Holder"), new HolderService());
886 ProcessState::self()->startThreadPool();
887}
888
889int main(int argc, char **argv)
890{
891 if (argc != 1) {
892 runFunction(argv[1]);
893 return 0;
894 }
895 INFO("CameraServiceTest start");
896 gExecutable = argv[0];
897 runHolderService();
898 int n = getNumberOfCameras();
899 INFO("%d Cameras available", n);
900
901 for (int id = 0; id < n; id++) {
902 INFO("Testing camera %d", id);
903 testConnect(id); flushCommands();
904 testAllowConnectOnceOnly(id); flushCommands();
905 testReconnect(id); flushCommands();
906 testLockUnlock(id); flushCommands();
907 testReconnectFromAnotherProcess(id); flushCommands();
908
909 RUN(TestSetPreviewDisplay, id);
910 RUN(TestStartPreview, id);
911 RUN(TestStartPreviewWithoutDisplay, id);
912 RUN(TestAutoFocus, id);
913 RUN(TestStopPreview, id);
914 RUN(TestTakePicture, id);
915 RUN(TestTakeMultiplePictures, id);
916 RUN(TestGetParameters, id);
917 RUN(TestPictureSize, id);
918 RUN(TestPreviewCallbackFlag, id);
919 RUN(TestRecording, id);
920 RUN(TestPreviewSize, id);
921 }
922
923 INFO("CameraServiceTest finished");
924}