blob: 69f60ca22a7ce2313e88071ed967a9b7d4bb6436 [file] [log] [blame]
James Dong199d1c12011-03-17 11:48:13 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +080017#define LOG_TAG "CameraServiceTest"
18
19#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22#include <sys/types.h>
23#include <sys/wait.h>
24#include <unistd.h>
Mathias Agopian000479f2010-02-09 17:46:37 -080025#include <surfaceflinger/ISurface.h>
26#include <camera/Camera.h>
27#include <camera/CameraParameters.h>
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +080028#include <ui/GraphicBuffer.h>
Mathias Agopian000479f2010-02-09 17:46:37 -080029#include <camera/ICamera.h>
30#include <camera/ICameraClient.h>
31#include <camera/ICameraService.h>
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +080032#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"); \
Steve Block5baa3a62011-12-20 16:23:08 +000049 ALOGD(__VA_ARGS__); \
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +080050 } 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);
Chih-Chung Change25cc652010-05-06 16:36:58 +080056 abort();
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +080057}
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);
Chih-Chung Change25cc652010-05-06 16:36:58 +080064 abort();
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +080065}
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,
Chih-Chung Change25cc652010-05-06 16:36:58 +0800173 int32_t msgType, const sp<IMemory>& data);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800174
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);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800194 void assertTest(OP op, int v1, int v2);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800195
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
Chih-Chung Change25cc652010-05-06 16:36:58 +0800218void 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
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800225void MCameraClient::assertNotify(int32_t msgType, OP op, int count) {
226 Mutex::Autolock _l(mLock);
227 int v = mNotifyCount.valueFor(msgType);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800228 assertTest(op, v, count);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800229}
230
231void MCameraClient::assertData(int32_t msgType, OP op, int count) {
232 Mutex::Autolock _l(mLock);
233 int v = mDataCount.valueFor(msgType);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800234 assertTest(op, v, count);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800235}
236
237void MCameraClient::assertDataSize(int32_t msgType, OP op, int dataSize) {
238 Mutex::Autolock _l(mLock);
239 int v = mDataSize.valueFor(msgType);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800240 assertTest(op, v, dataSize);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800241}
242
243void MCameraClient::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) {
Nick Kralevich1e4dc542010-05-13 15:09:03 -0700244 INFO("%s", __func__);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800245 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) {
Nick Kralevich1e4dc542010-05-13 15:09:03 -0700256 INFO("%s", __func__);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800257 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
Chih-Chung Change25cc652010-05-06 16:36:58 +0800276void MCameraClient::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType,
277 const sp<IMemory>& data) {
278 dataCallback(msgType, data);
279}
280
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800281void 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();
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800313 virtual sp<GraphicBuffer> requestBuffer(int bufferIdx, int usage);
Mathias Agopian75181b42010-05-12 18:37:43 -0700314 virtual status_t setBufferCount(int bufferCount);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800315
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) {
Nick Kralevich1e4dc542010-05-13 15:09:03 -0700330 INFO("%s", __func__);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800331 Mutex::Autolock _l(mLock);
332 ++registerBuffersCount;
333 mCond.signal();
334 return NO_ERROR;
335}
336
337void MSurface::postBuffer(ssize_t offset) {
Nick Kralevich1e4dc542010-05-13 15:09:03 -0700338 // INFO("%s", __func__);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800339 Mutex::Autolock _l(mLock);
340 ++postBufferCount;
341 mCond.signal();
342}
343
344void MSurface::unregisterBuffers() {
Nick Kralevich1e4dc542010-05-13 15:09:03 -0700345 INFO("%s", __func__);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800346 Mutex::Autolock _l(mLock);
347 ++unregisterBuffersCount;
348 mCond.signal();
349}
350
351sp<GraphicBuffer> MSurface::requestBuffer(int bufferIdx, int usage) {
Nick Kralevich1e4dc542010-05-13 15:09:03 -0700352 INFO("%s", __func__);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800353 return NULL;
354}
355
Mathias Agopian75181b42010-05-12 18:37:43 -0700356status_t MSurface::setBufferCount(int bufferCount) {
Nick Kralevich942a2fb2010-05-14 10:29:13 -0700357 INFO("%s", __func__);
Mathias Agopian75181b42010-05-12 18:37:43 -0700358 return NULL;
359}
360
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800361void 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
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800381//
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) {
Nick Kralevich1e4dc542010-05-13 15:09:03 -0700395 INFO("%s", __func__);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800396 getHolder()->put(obj);
397}
398
399sp<IBinder> getTempObject() {
Nick Kralevich1e4dc542010-05-13 15:09:03 -0700400 INFO("%s", __func__);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800401 return getHolder()->get();
402}
403
404void clearTempObject() {
Nick Kralevich1e4dc542010-05-13 15:09:03 -0700405 INFO("%s", __func__);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800406 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
Chih-Chung Change25cc652010-05-06 16:36:58 +0800422int getNumberOfCameras() {
423 sp<ICameraService> cs = getCameraService();
424 return cs->getNumberOfCameras();
425}
426
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800427//
428// Various Connect Tests
429//
Chih-Chung Change25cc652010-05-06 16:36:58 +0800430void testConnect(int cameraId) {
Nick Kralevich1e4dc542010-05-13 15:09:03 -0700431 INFO("%s", __func__);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800432 sp<ICameraService> cs = getCameraService();
433 sp<MCameraClient> cc = new MCameraClient();
Chih-Chung Change25cc652010-05-06 16:36:58 +0800434 sp<ICamera> c = cs->connect(cc, cameraId);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800435 ASSERT(c != 0);
436 c->disconnect();
437}
438
Chih-Chung Change25cc652010-05-06 16:36:58 +0800439void testAllowConnectOnceOnly(int cameraId) {
Nick Kralevich1e4dc542010-05-13 15:09:03 -0700440 INFO("%s", __func__);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800441 sp<ICameraService> cs = getCameraService();
442 // Connect the first client.
443 sp<MCameraClient> cc = new MCameraClient();
Chih-Chung Change25cc652010-05-06 16:36:58 +0800444 sp<ICamera> c = cs->connect(cc, cameraId);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800445 ASSERT(c != 0);
446 // Same client -- ok.
Chih-Chung Change25cc652010-05-06 16:36:58 +0800447 ASSERT(cs->connect(cc, cameraId) != 0);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800448 // Different client -- not ok.
449 sp<MCameraClient> cc2 = new MCameraClient();
Chih-Chung Change25cc652010-05-06 16:36:58 +0800450 ASSERT(cs->connect(cc2, cameraId) == 0);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800451 c->disconnect();
452}
453
454void testReconnectFailed() {
Nick Kralevich1e4dc542010-05-13 15:09:03 -0700455 INFO("%s", __func__);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800456 sp<ICamera> c = interface_cast<ICamera>(getTempObject());
Chih-Chung Change25cc652010-05-06 16:36:58 +0800457 sp<MCameraClient> cc = new MCameraClient();
458 ASSERT(c->connect(cc) != NO_ERROR);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800459}
460
461void testReconnectSuccess() {
Nick Kralevich1e4dc542010-05-13 15:09:03 -0700462 INFO("%s", __func__);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800463 sp<ICamera> c = interface_cast<ICamera>(getTempObject());
464 sp<MCameraClient> cc = new MCameraClient();
465 ASSERT(c->connect(cc) == NO_ERROR);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800466 c->disconnect();
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800467}
468
469void testLockFailed() {
Nick Kralevich1e4dc542010-05-13 15:09:03 -0700470 INFO("%s", __func__);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800471 sp<ICamera> c = interface_cast<ICamera>(getTempObject());
472 ASSERT(c->lock() != NO_ERROR);
473}
474
475void testLockUnlockSuccess() {
Nick Kralevich1e4dc542010-05-13 15:09:03 -0700476 INFO("%s", __func__);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800477 sp<ICamera> c = interface_cast<ICamera>(getTempObject());
478 ASSERT(c->lock() == NO_ERROR);
479 ASSERT(c->unlock() == NO_ERROR);
480}
481
482void testLockSuccess() {
Nick Kralevich1e4dc542010-05-13 15:09:03 -0700483 INFO("%s", __func__);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800484 sp<ICamera> c = interface_cast<ICamera>(getTempObject());
485 ASSERT(c->lock() == NO_ERROR);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800486 c->disconnect();
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800487}
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
Chih-Chung Change25cc652010-05-06 16:36:58 +0800533void testReconnect(int cameraId) {
Nick Kralevich1e4dc542010-05-13 15:09:03 -0700534 INFO("%s", __func__);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800535 sp<ICameraService> cs = getCameraService();
536 sp<MCameraClient> cc = new MCameraClient();
Chih-Chung Change25cc652010-05-06 16:36:58 +0800537 sp<ICamera> c = cs->connect(cc, cameraId);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800538 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
Chih-Chung Change25cc652010-05-06 16:36:58 +0800548void testLockUnlock(int cameraId) {
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800549 sp<ICameraService> cs = getCameraService();
550 sp<MCameraClient> cc = new MCameraClient();
Chih-Chung Change25cc652010-05-06 16:36:58 +0800551 sp<ICamera> c = cs->connect(cc, cameraId);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800552 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");
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800564 clearTempObject();
565}
566
Chih-Chung Change25cc652010-05-06 16:36:58 +0800567void testReconnectFromAnotherProcess(int cameraId) {
Nick Kralevich1e4dc542010-05-13 15:09:03 -0700568 INFO("%s", __func__);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800569
570 sp<ICameraService> cs = getCameraService();
571 sp<MCameraClient> cc = new MCameraClient();
Chih-Chung Change25cc652010-05-06 16:36:58 +0800572 sp<ICamera> c = cs->connect(cc, cameraId);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800573 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");
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800580 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
Chih-Chung Change25cc652010-05-06 16:36:58 +0800592#define RUN(class_name, cameraId) do { \
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800593 { \
594 INFO(#class_name); \
595 class_name instance; \
Chih-Chung Change25cc652010-05-06 16:36:58 +0800596 instance.init(cameraId); \
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800597 instance.run(); \
598 } \
599 flushCommands(); \
600} while(0)
601
602// Base test case after the the camera is connected.
603class AfterConnect {
Chih-Chung Change25cc652010-05-06 16:36:58 +0800604public:
605 void init(int cameraId) {
606 cs = getCameraService();
607 cc = new MCameraClient();
608 c = cs->connect(cc, cameraId);
609 ASSERT(c != 0);
610 }
611
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800612protected:
613 sp<ICameraService> cs;
614 sp<MCameraClient> cc;
615 sp<ICamera> c;
616
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800617 ~AfterConnect() {
Chih-Chung Change25cc652010-05-06 16:36:58 +0800618 c->disconnect();
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800619 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
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800647 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
Chih-Chung Change25cc652010-05-06 16:36:58 +0800651
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800652 cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
653 }
654};
655
Chih-Chung Change25cc652010-05-06 16:36:58 +0800656class TestStartPreviewWithoutDisplay : public AfterConnect {
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800657public:
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 {
Chih-Chung Change25cc652010-05-06 16:36:58 +0800668public:
669 void init(int cameraId) {
670 AfterConnect::init(cameraId);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800671 surface = new MSurface();
672 ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
673 ASSERT(c->startPreview() == NO_ERROR);
674 }
675
Chih-Chung Change25cc652010-05-06 16:36:58 +0800676protected:
677 sp<MSurface> surface;
678
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800679 ~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();
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800714 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);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800728 }
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();
Nick Kralevich1e4dc542010-05-13 15:09:03 -0700738 INFO("%s", static_cast<const char*>(param_str));
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800739 }
740};
741
Chih-Chung Change25cc652010-05-06 16:36:58 +0800742static 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
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800771class TestPictureSize : public AfterStartPreview {
772public:
773 void checkOnePicture(int w, int h) {
Chih-Chung Change25cc652010-05-06 16:36:58 +0800774 const float rate = 0.9; // byte per pixel limit
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800775 int pixels = w * h;
776
777 CameraParameters param(c->getParameters());
778 param.setPictureSize(w, h);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800779 // 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);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800782 c->setParameters(param.flatten());
783
784 cc->clearStat();
785 ASSERT(c->takePicture() == NO_ERROR);
786 cc->waitData(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, 1);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800787 //cc->assertDataSize(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, pixels*3/2);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800788 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);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800793 }
794
795 void run() {
Chih-Chung Change25cc652010-05-06 16:36:58 +0800796 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)) {
Steve Block5baa3a62011-12-20 16:23:08 +0000800 ALOGD("checking picture size %dx%d", w, h);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800801 checkOnePicture(w, h);
802 }
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800803 }
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++) {
Steve Block5baa3a62011-12-20 16:23:08 +0000814 ALOGD("TestPreviewCallbackFlag: flag=%d", v);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800815 usleep(100000); // sleep a while to clear the in-flight callbacks.
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800816 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();
Iliyan Malchev9c7ac0d2011-04-14 16:51:21 -0700823 if ((v & CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK) == 0) {
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800824 cc->assertData(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::EQ, 0);
825 } else {
Iliyan Malchev9c7ac0d2011-04-14 16:51:21 -0700826 if ((v & CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) == 0) {
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800827 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);
Iliyan Malchev9c7ac0d2011-04-14 16:51:21 -0700842 c->setPreviewCallbackFlag(CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800843 cc->setReleaser(c.get());
844 c->startRecording();
845 ASSERT(c->recordingEnabled() == true);
846 sleep(2);
847 c->stopRecording();
Chih-Chung Change25cc652010-05-06 16:36:58 +0800848 usleep(100000); // sleep a while to clear the in-flight callbacks.
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800849 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);
Iliyan Malchev9c7ac0d2011-04-14 16:51:21 -0700863 c->setPreviewCallbackFlag(CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800864 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() {
Chih-Chung Change25cc652010-05-06 16:36:58 +0800874 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)) {
Steve Block5baa3a62011-12-20 16:23:08 +0000878 ALOGD("checking preview size %dx%d", w, h);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800879 checkOnePicture(w, h);
880 }
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800881 }
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();
Chih-Chung Change25cc652010-05-06 16:36:58 +0800899 int n = getNumberOfCameras();
900 INFO("%d Cameras available", n);
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800901
Chih-Chung Change25cc652010-05-06 16:36:58 +0800902 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();
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800909
Chih-Chung Change25cc652010-05-06 16:36:58 +0800910 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");
Chih-Chung Chang5b0fc3d2009-11-13 12:49:14 +0800925}