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