ProCameraTests.cpp revision c0767f148e29ce821281b5965c0e25b4c143e76d
1/* 2 * Copyright (C) 2013 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#include <gtest/gtest.h> 18#include <iostream> 19 20#include <binder/IPCThreadState.h> 21#include <utils/Thread.h> 22 23#include "Camera.h" 24#include "ProCamera.h" 25#include <utils/Vector.h> 26#include <utils/Mutex.h> 27#include <utils/Condition.h> 28 29#include <gui/SurfaceComposerClient.h> 30#include <gui/Surface.h> 31 32#include <system/camera_metadata.h> 33#include <hardware/camera2.h> // for CAMERA2_TEMPLATE_PREVIEW only 34 35namespace android { 36namespace camera2 { 37namespace tests { 38namespace client { 39 40#define CAMERA_ID 0 41#define TEST_DEBUGGING 0 42 43#define TEST_LISTENER_TIMEOUT 1000000000 // 1 second listener timeout 44#define TEST_FORMAT HAL_PIXEL_FORMAT_Y16 //TODO: YUY2 instead 45 46#define TEST_FORMAT_DEPTH HAL_PIXEL_FORMAT_Y16 47 48#define TEST_CPU_FRAME_COUNT 2 49#define TEST_CPU_HEAP_COUNT 5 50 51#if TEST_DEBUGGING 52#define dout std::cerr 53#else 54#define dout if (0) std::cerr 55#endif 56 57#define EXPECT_OK(x) EXPECT_EQ(OK, (x)) 58#define ASSERT_OK(x) ASSERT_EQ(OK, (x)) 59 60class ProCameraTest; 61 62enum ProEvent { 63 UNKNOWN, 64 ACQUIRED, 65 RELEASED, 66 STOLEN, 67 BUFFER_RECEIVED, 68}; 69 70typedef Vector<ProEvent> EventList; 71 72class ProCameraTestThread : public Thread 73{ 74public: 75 ProCameraTestThread() { 76 } 77 78 virtual bool threadLoop() { 79 mProc = ProcessState::self(); 80 mProc->startThreadPool(); 81 82 IPCThreadState *ptr = IPCThreadState::self(); 83 84 ptr->joinThreadPool(); 85 86 return false; 87 } 88 89 sp<ProcessState> mProc; 90}; 91 92class ProCameraTestListener : public ProCameraListener { 93 94public: 95 status_t WaitForEvent() { 96 Mutex::Autolock cal(mConditionMutex); 97 98 { 99 Mutex::Autolock al(mListenerMutex); 100 101 if (mProEventList.size() > 0) { 102 return OK; 103 } 104 } 105 106 return mListenerCondition.waitRelative(mConditionMutex, 107 TEST_LISTENER_TIMEOUT); 108 } 109 110 /* Read events into out. Existing queue is flushed */ 111 void ReadEvents(EventList& out) { 112 Mutex::Autolock al(mListenerMutex); 113 114 for (size_t i = 0; i < mProEventList.size(); ++i) { 115 out.push(mProEventList[i]); 116 } 117 118 mProEventList.clear(); 119 } 120 121 /** 122 * Dequeue 1 event from the event queue. 123 * Returns UNKNOWN if queue is empty 124 */ 125 ProEvent ReadEvent() { 126 Mutex::Autolock al(mListenerMutex); 127 128 if (mProEventList.size() == 0) { 129 return UNKNOWN; 130 } 131 132 ProEvent ev = mProEventList[0]; 133 mProEventList.removeAt(0); 134 135 return ev; 136 } 137 138private: 139 void QueueEvent(ProEvent ev) { 140 { 141 Mutex::Autolock al(mListenerMutex); 142 mProEventList.push(ev); 143 } 144 145 146 mListenerCondition.broadcast(); 147 } 148 149protected: 150 151 ////////////////////////////////////////////////// 152 ///////// ProCameraListener ////////////////////// 153 ////////////////////////////////////////////////// 154 155 156 // Lock has been acquired. Write operations now available. 157 virtual void onLockAcquired() { 158 QueueEvent(ACQUIRED); 159 } 160 // Lock has been released with exclusiveUnlock 161 virtual void onLockReleased() { 162 QueueEvent(RELEASED); 163 } 164 165 // Lock has been stolen by another client. 166 virtual void onLockStolen() { 167 QueueEvent(STOLEN); 168 } 169 170 // Lock free. 171 virtual void onTriggerNotify(int32_t ext1, int32_t ext2, int32_t ext3) { 172 173 dout << "Trigger notify: " << ext1 << " " << ext2 174 << " " << ext3 << std::endl; 175 } 176 177 virtual void onBufferReceived(int streamId, 178 const CpuConsumer::LockedBuffer& buf) { 179 180 dout << "Buffer received on streamId = " << streamId << 181 ", dataPtr = " << (void*)buf.data << std::endl; 182 183 QueueEvent(BUFFER_RECEIVED); 184 185 } 186 virtual void onRequestReceived( 187 camera_metadata* request) { 188 free_camera_metadata(request); 189 } 190 191 // TODO: remove 192 193 virtual void notify(int32_t , int32_t , int32_t ) {} 194 virtual void postData(int32_t , const sp<IMemory>& , 195 camera_frame_metadata_t *) {} 196 virtual void postDataTimestamp(nsecs_t , int32_t , const sp<IMemory>& ) {} 197 198 199 Vector<ProEvent> mProEventList; 200 Mutex mListenerMutex; 201 Mutex mConditionMutex; 202 Condition mListenerCondition; 203}; 204 205class ProCameraTest : public ::testing::Test { 206 207public: 208 ProCameraTest() { 209 } 210 211 static void SetUpTestCase() { 212 // Binder Thread Pool Initialization 213 mTestThread = new ProCameraTestThread(); 214 mTestThread->run("ProCameraTestThread"); 215 } 216 217 virtual void SetUp() { 218 mCamera = ProCamera::connect(CAMERA_ID); 219 ASSERT_NE((void*)NULL, mCamera.get()); 220 221 mListener = new ProCameraTestListener(); 222 mCamera->setListener(mListener); 223 } 224 225 virtual void TearDown() { 226 ASSERT_NE((void*)NULL, mCamera.get()); 227 mCamera->disconnect(); 228 } 229 230protected: 231 sp<ProCamera> mCamera; 232 sp<ProCameraTestListener> mListener; 233 234 static sp<Thread> mTestThread; 235 236 int mDisplaySecs; 237 sp<SurfaceComposerClient> mComposerClient; 238 sp<SurfaceControl> mSurfaceControl; 239 240 sp<SurfaceComposerClient> mDepthComposerClient; 241 sp<SurfaceControl> mDepthSurfaceControl; 242 243 int getSurfaceWidth() { 244 return 512; 245 } 246 int getSurfaceHeight() { 247 return 512; 248 } 249 250 void createOnScreenSurface(sp<Surface>& surface) { 251 mComposerClient = new SurfaceComposerClient; 252 ASSERT_EQ(NO_ERROR, mComposerClient->initCheck()); 253 254 mSurfaceControl = mComposerClient->createSurface( 255 String8("ProCameraTest StreamingImage Surface"), 256 getSurfaceWidth(), getSurfaceHeight(), 257 PIXEL_FORMAT_RGB_888, 0); 258 259 mSurfaceControl->setPosition(640, 0); 260 261 ASSERT_TRUE(mSurfaceControl != NULL); 262 ASSERT_TRUE(mSurfaceControl->isValid()); 263 264 SurfaceComposerClient::openGlobalTransaction(); 265 ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7FFFFFFF)); 266 ASSERT_EQ(NO_ERROR, mSurfaceControl->show()); 267 SurfaceComposerClient::closeGlobalTransaction(); 268 269 sp<ANativeWindow> window = mSurfaceControl->getSurface(); 270 surface = mSurfaceControl->getSurface(); 271 272 ASSERT_NE((void*)NULL, surface.get()); 273 } 274 275 void createDepthOnScreenSurface(sp<Surface>& surface) { 276 mDepthComposerClient = new SurfaceComposerClient; 277 ASSERT_EQ(NO_ERROR, mDepthComposerClient->initCheck()); 278 279 mDepthSurfaceControl = mDepthComposerClient->createSurface( 280 String8("ProCameraTest StreamingImage Surface"), 281 getSurfaceWidth(), getSurfaceHeight(), 282 PIXEL_FORMAT_RGB_888, 0); 283 284 mDepthSurfaceControl->setPosition(640, 0); 285 286 ASSERT_TRUE(mDepthSurfaceControl != NULL); 287 ASSERT_TRUE(mDepthSurfaceControl->isValid()); 288 289 SurfaceComposerClient::openGlobalTransaction(); 290 ASSERT_EQ(NO_ERROR, mDepthSurfaceControl->setLayer(0x7FFFFFFF)); 291 ASSERT_EQ(NO_ERROR, mDepthSurfaceControl->show()); 292 SurfaceComposerClient::closeGlobalTransaction(); 293 294 sp<ANativeWindow> window = mDepthSurfaceControl->getSurface(); 295 surface = mDepthSurfaceControl->getSurface(); 296 297 ASSERT_NE((void*)NULL, surface.get()); 298 } 299 300}; 301 302sp<Thread> ProCameraTest::mTestThread; 303 304// test around exclusiveTryLock (immediate locking) 305TEST_F(ProCameraTest, LockingImmediate) { 306 307 if (HasFatalFailure()) { 308 return; 309 } 310 311 EXPECT_FALSE(mCamera->hasExclusiveLock()); 312 EXPECT_EQ(OK, mCamera->exclusiveTryLock()); 313 // at this point we definitely have the lock 314 315 EXPECT_EQ(OK, mListener->WaitForEvent()); 316 EXPECT_EQ(ACQUIRED, mListener->ReadEvent()); 317 318 EXPECT_TRUE(mCamera->hasExclusiveLock()); 319 EXPECT_EQ(OK, mCamera->exclusiveUnlock()); 320 321 EXPECT_EQ(OK, mListener->WaitForEvent()); 322 EXPECT_EQ(RELEASED, mListener->ReadEvent()); 323 324 EXPECT_FALSE(mCamera->hasExclusiveLock()); 325} 326 327// test around exclusiveLock (locking at some future point in time) 328TEST_F(ProCameraTest, LockingAsynchronous) { 329 330 if (HasFatalFailure()) { 331 return; 332 } 333 334 // TODO: Add another procamera that has a lock here. 335 // then we can be test that the lock wont immediately be acquired 336 337 EXPECT_FALSE(mCamera->hasExclusiveLock()); 338 EXPECT_EQ(OK, mCamera->exclusiveLock()); 339 // at this point we may or may not have the lock 340 // we cant be sure until we get an ACQUIRED event 341 342 EXPECT_EQ(OK, mListener->WaitForEvent()); 343 EXPECT_EQ(ACQUIRED, mListener->ReadEvent()); 344 345 EXPECT_TRUE(mCamera->hasExclusiveLock()); 346 EXPECT_EQ(OK, mCamera->exclusiveUnlock()); 347 348 EXPECT_EQ(OK, mListener->WaitForEvent()); 349 EXPECT_EQ(RELEASED, mListener->ReadEvent()); 350 351 EXPECT_FALSE(mCamera->hasExclusiveLock()); 352} 353 354// Stream directly to the screen. 355TEST_F(ProCameraTest, StreamingImage) { 356 if (HasFatalFailure()) { 357 return; 358 } 359 char* displaySecsEnv = getenv("TEST_DISPLAY_SECS"); 360 if (displaySecsEnv != NULL) { 361 mDisplaySecs = atoi(displaySecsEnv); 362 if (mDisplaySecs < 0) { 363 mDisplaySecs = 0; 364 } 365 } else { 366 mDisplaySecs = 0; 367 } 368 369 sp<Surface> depthSurface; 370 if (mDisplaySecs > 0) { 371 createDepthOnScreenSurface(/*out*/depthSurface); 372 } 373 374 int depthStreamId = -1; 375 EXPECT_OK(mCamera->createStream(/*width*/320, /*height*/240, 376 TEST_FORMAT_DEPTH, depthSurface, &depthStreamId)); 377 EXPECT_NE(-1, depthStreamId); 378 379 EXPECT_OK(mCamera->exclusiveTryLock()); 380 /* iterate in a loop submitting requests every frame. 381 * what kind of requests doesnt really matter, just whatever. 382 */ 383 384 // it would probably be better to use CameraMetadata from camera service. 385 camera_metadata_t *request = NULL; 386 EXPECT_OK(mCamera->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW, 387 /*out*/&request)); 388 EXPECT_NE((void*)NULL, request); 389 390 /* FIXME: dont need this later, at which point the above should become an 391 ASSERT_NE*/ 392 if(request == NULL) request = allocate_camera_metadata(10, 100); 393 394 // set the output streams to just this stream ID 395 396 // wow what a verbose API. 397 // i would give a loaf of bread for 398 // metadata->updateOrInsert(keys.request.output.streams, streamId); 399 uint8_t allStreams[] = { depthStreamId }; 400 size_t streamCount = sizeof(allStreams) / sizeof(allStreams[0]); 401 402 camera_metadata_entry_t entry; 403 uint32_t tag = static_cast<uint32_t>(ANDROID_REQUEST_OUTPUT_STREAMS); 404 int find = find_camera_metadata_entry(request, tag, &entry); 405 if (find == -ENOENT) { 406 if (add_camera_metadata_entry(request, tag, &allStreams, 407 /*data_count*/streamCount) != OK) { 408 camera_metadata_t *tmp = allocate_camera_metadata(1000, 10000); 409 ASSERT_OK(append_camera_metadata(tmp, request)); 410 free_camera_metadata(request); 411 request = tmp; 412 413 ASSERT_OK(add_camera_metadata_entry(request, tag, &allStreams, 414 /*data_count*/streamCount)); 415 } 416 } else { 417 ASSERT_OK(update_camera_metadata_entry(request, entry.index, 418 &allStreams, /*data_count*/streamCount, &entry)); 419 } 420 421 EXPECT_OK(mCamera->submitRequest(request, /*streaming*/true)); 422 423 dout << "will sleep now for " << mDisplaySecs << std::endl; 424 sleep(mDisplaySecs); 425 426 free_camera_metadata(request); 427 428 for (int i = 0; i < streamCount; ++i) { 429 EXPECT_OK(mCamera->deleteStream(allStreams[i])); 430 } 431 EXPECT_OK(mCamera->exclusiveUnlock()); 432} 433 434TEST_F(ProCameraTest, CpuConsumer) { 435 if (HasFatalFailure()) { 436 return; 437 } 438 int streamId = -1; 439 EXPECT_OK(mCamera->createStreamCpu(/*width*/320, /*height*/240, 440 TEST_FORMAT_DEPTH, TEST_CPU_HEAP_COUNT, &streamId)); 441 EXPECT_NE(-1, streamId); 442 443 EXPECT_OK(mCamera->exclusiveTryLock()); 444 EXPECT_EQ(OK, mListener->WaitForEvent()); 445 EXPECT_EQ(ACQUIRED, mListener->ReadEvent()); 446 /* iterate in a loop submitting requests every frame. 447 * what kind of requests doesnt really matter, just whatever. 448 */ 449 450 // it would probably be better to use CameraMetadata from camera service. 451 camera_metadata_t *request = NULL; 452 EXPECT_OK(mCamera->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW, 453 /*out*/&request)); 454 EXPECT_NE((void*)NULL, request); 455 456 /*FIXME: dont need this later, at which point the above should become an 457 ASSERT_NE*/ 458 if(request == NULL) request = allocate_camera_metadata(10, 100); 459 460 // set the output streams to just this stream ID 461 462 uint8_t allStreams[] = { streamId }; 463 camera_metadata_entry_t entry; 464 uint32_t tag = static_cast<uint32_t>(ANDROID_REQUEST_OUTPUT_STREAMS); 465 int find = find_camera_metadata_entry(request, tag, &entry); 466 if (find == -ENOENT) { 467 if (add_camera_metadata_entry(request, tag, &allStreams, 468 /*data_count*/1) != OK) { 469 camera_metadata_t *tmp = allocate_camera_metadata(1000, 10000); 470 ASSERT_OK(append_camera_metadata(tmp, request)); 471 free_camera_metadata(request); 472 request = tmp; 473 474 ASSERT_OK(add_camera_metadata_entry(request, tag, &allStreams, 475 /*data_count*/1)); 476 } 477 } else { 478 ASSERT_OK(update_camera_metadata_entry(request, entry.index, 479 &allStreams, /*data_count*/1, &entry)); 480 } 481 482 EXPECT_OK(mCamera->submitRequest(request, /*streaming*/true)); 483 484 // Consume a couple of frames 485 for (int i = 0; i < TEST_CPU_FRAME_COUNT; ++i) { 486 EXPECT_EQ(OK, mListener->WaitForEvent()); 487 EXPECT_EQ(BUFFER_RECEIVED, mListener->ReadEvent()); 488 } 489 490 // Done: clean up 491 free_camera_metadata(request); 492 EXPECT_OK(mCamera->deleteStream(streamId)); 493 EXPECT_OK(mCamera->exclusiveUnlock()); 494} 495 496} 497} 498} 499} 500 501