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