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