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 <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>
31#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"); \
48        ALOGD(__VA_ARGS__); \
49    } 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)) {
219        ALOGE("assertTest failed: op=%d, v1=%d, v2=%d", op, v1, v2);
220        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();
312    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
380//
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)) {
799            ALOGD("checking picture size %dx%d", w, h);
800            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++) {
813            ALOGD("TestPreviewCallbackFlag: flag=%d", v);
814            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();
822            if ((v & CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK) == 0) {
823                cc->assertData(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::EQ, 0);
824            } else {
825                if ((v & CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) == 0) {
826                    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);
841        c->setPreviewCallbackFlag(CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK);
842        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);
862        c->setPreviewCallbackFlag(CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK);
863        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)) {
877            ALOGD("checking preview size %dx%d", w, h);
878            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}
925