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