ProCameraTests.cpp revision 69e22433b9d7df77907579f67e47a159aa57f876
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_RGBA_8888 //TODO: YUY2 instead 45 46#if TEST_DEBUGGING 47#define dout std::cerr 48#else 49#define dout if (0) std::cerr 50#endif 51 52#define EXPECT_OK(x) EXPECT_EQ(OK, (x)) 53#define ASSERT_OK(x) ASSERT_EQ(OK, (x)) 54 55class ProCameraTest; 56 57enum LockEvent { 58 UNKNOWN, 59 ACQUIRED, 60 RELEASED, 61 STOLEN 62}; 63 64typedef Vector<LockEvent> EventList; 65 66class ProCameraTestThread : public Thread 67{ 68public: 69 ProCameraTestThread() { 70 } 71 72 virtual bool threadLoop() { 73 mProc = ProcessState::self(); 74 mProc->startThreadPool(); 75 76 IPCThreadState *ptr = IPCThreadState::self(); 77 78 ptr->joinThreadPool(); 79 80 return false; 81 } 82 83 sp<ProcessState> mProc; 84}; 85 86class ProCameraTestListener : public ProCameraListener { 87 88public: 89 status_t WaitForEvent() { 90 Mutex::Autolock cal(mConditionMutex); 91 92 { 93 Mutex::Autolock al(mListenerMutex); 94 95 if (mLockEventList.size() > 0) { 96 return OK; 97 } 98 } 99 100 return mListenerCondition.waitRelative(mConditionMutex, 101 TEST_LISTENER_TIMEOUT); 102 } 103 104 /* Read events into out. Existing queue is flushed */ 105 void ReadEvents(EventList& out) { 106 Mutex::Autolock al(mListenerMutex); 107 108 for (size_t i = 0; i < mLockEventList.size(); ++i) { 109 out.push(mLockEventList[i]); 110 } 111 112 mLockEventList.clear(); 113 } 114 115 /** 116 * Dequeue 1 event from the event queue. 117 * Returns UNKNOWN if queue is empty 118 */ 119 LockEvent ReadEvent() { 120 Mutex::Autolock al(mListenerMutex); 121 122 if (mLockEventList.size() == 0) { 123 return UNKNOWN; 124 } 125 126 LockEvent ev = mLockEventList[0]; 127 mLockEventList.removeAt(0); 128 129 return ev; 130 } 131 132private: 133 void QueueEvent(LockEvent ev) { 134 { 135 Mutex::Autolock al(mListenerMutex); 136 mLockEventList.push(ev); 137 } 138 139 140 mListenerCondition.broadcast(); 141 } 142 143protected: 144 145 ////////////////////////////////////////////////// 146 ///////// ProCameraListener ////////////////////// 147 ////////////////////////////////////////////////// 148 149 150 // Lock has been acquired. Write operations now available. 151 virtual void onLockAcquired() { 152 QueueEvent(ACQUIRED); 153 } 154 // Lock has been released with exclusiveUnlock 155 virtual void onLockReleased() { 156 QueueEvent(RELEASED); 157 } 158 159 // Lock has been stolen by another client. 160 virtual void onLockStolen() { 161 QueueEvent(STOLEN); 162 } 163 164 // Lock free. 165 virtual void onTriggerNotify(int32_t ext1, int32_t ext2, int32_t ext3) { 166 167 dout << "Trigger notify: " << ext1 << " " << ext2 168 << " " << ext3 << std::endl; 169 } 170 171 // TODO: remove 172 173 virtual void notify(int32_t , int32_t , int32_t ) {} 174 virtual void postData(int32_t , const sp<IMemory>& , 175 camera_frame_metadata_t *) {} 176 virtual void postDataTimestamp(nsecs_t , int32_t , const sp<IMemory>& ) {} 177 178 179 Vector<LockEvent> mLockEventList; 180 Mutex mListenerMutex; 181 Mutex mConditionMutex; 182 Condition mListenerCondition; 183}; 184 185class ProCameraTest : public ::testing::Test { 186 187public: 188 ProCameraTest() { 189 } 190 191 static void SetUpTestCase() { 192 // Binder Thread Pool Initialization 193 mTestThread = new ProCameraTestThread(); 194 mTestThread->run("ProCameraTestThread"); 195 } 196 197 virtual void SetUp() { 198 mCamera = ProCamera::connect(CAMERA_ID); 199 ASSERT_NE((void*)NULL, mCamera.get()); 200 201 mListener = new ProCameraTestListener(); 202 mCamera->setListener(mListener); 203 } 204 205 virtual void TearDown() { 206 ASSERT_NE((void*)NULL, mCamera.get()); 207 mCamera->disconnect(); 208 } 209 210protected: 211 sp<ProCamera> mCamera; 212 sp<ProCameraTestListener> mListener; 213 214 static sp<Thread> mTestThread; 215 216 int mDisplaySecs; 217 sp<SurfaceComposerClient> mComposerClient; 218 sp<SurfaceControl> mSurfaceControl; 219 220 int getSurfaceWidth() { 221 return 512; 222 } 223 int getSurfaceHeight() { 224 return 512; 225 } 226 227 void createOnScreenSurface(sp<Surface>& surface) { 228 mComposerClient = new SurfaceComposerClient; 229 ASSERT_EQ(NO_ERROR, mComposerClient->initCheck()); 230 231 mSurfaceControl = mComposerClient->createSurface( 232 String8("ProCameraTest StreamingImage Surface"), 233 getSurfaceWidth(), getSurfaceHeight(), 234 PIXEL_FORMAT_RGB_888, 0); 235 236 ASSERT_TRUE(mSurfaceControl != NULL); 237 ASSERT_TRUE(mSurfaceControl->isValid()); 238 239 SurfaceComposerClient::openGlobalTransaction(); 240 ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7FFFFFFF)); 241 ASSERT_EQ(NO_ERROR, mSurfaceControl->show()); 242 SurfaceComposerClient::closeGlobalTransaction(); 243 244 sp<ANativeWindow> window = mSurfaceControl->getSurface(); 245 surface = mSurfaceControl->getSurface(); 246 247 ASSERT_NE((void*)NULL, surface.get()); 248 } 249 250}; 251 252sp<Thread> ProCameraTest::mTestThread; 253 254// test around exclusiveTryLock (immediate locking) 255TEST_F(ProCameraTest, LockingImmediate) { 256 257 if (HasFatalFailure()) { 258 return; 259 } 260 261 EXPECT_FALSE(mCamera->hasExclusiveLock()); 262 EXPECT_EQ(OK, mCamera->exclusiveTryLock()); 263 // at this point we definitely have the lock 264 265 EXPECT_EQ(OK, mListener->WaitForEvent()); 266 EXPECT_EQ(ACQUIRED, mListener->ReadEvent()); 267 268 EXPECT_TRUE(mCamera->hasExclusiveLock()); 269 EXPECT_EQ(OK, mCamera->exclusiveUnlock()); 270 271 EXPECT_EQ(OK, mListener->WaitForEvent()); 272 EXPECT_EQ(RELEASED, mListener->ReadEvent()); 273 274 EXPECT_FALSE(mCamera->hasExclusiveLock()); 275} 276 277// test around exclusiveLock (locking at some future point in time) 278TEST_F(ProCameraTest, LockingAsynchronous) { 279 280 if (HasFatalFailure()) { 281 return; 282 } 283 284 // TODO: Add another procamera that has a lock here. 285 // then we can be test that the lock wont immediately be acquired 286 287 EXPECT_FALSE(mCamera->hasExclusiveLock()); 288 EXPECT_EQ(OK, mCamera->exclusiveLock()); 289 // at this point we may or may not have the lock 290 // we cant be sure until we get an ACQUIRED event 291 292 EXPECT_EQ(OK, mListener->WaitForEvent()); 293 EXPECT_EQ(ACQUIRED, mListener->ReadEvent()); 294 295 EXPECT_TRUE(mCamera->hasExclusiveLock()); 296 EXPECT_EQ(OK, mCamera->exclusiveUnlock()); 297 298 EXPECT_EQ(OK, mListener->WaitForEvent()); 299 EXPECT_EQ(RELEASED, mListener->ReadEvent()); 300 301 EXPECT_FALSE(mCamera->hasExclusiveLock()); 302} 303 304// Stream directly to the screen. 305TEST_F(ProCameraTest, StreamingImage) { 306 if (HasFatalFailure()) { 307 return; 308 } 309 char* displaySecsEnv = getenv("TEST_DISPLAY_SECS"); 310 if (displaySecsEnv != NULL) { 311 mDisplaySecs = atoi(displaySecsEnv); 312 if (mDisplaySecs < 0) { 313 mDisplaySecs = 0; 314 } 315 } else { 316 mDisplaySecs = 0; 317 } 318 319 sp<Surface> surface; 320 if (mDisplaySecs > 0) { 321 createOnScreenSurface(/*out*/surface); 322 } 323 int streamId = -1; 324 EXPECT_OK(mCamera->createStream(/*width*/640, /*height*/480, TEST_FORMAT, 325 surface, &streamId)); 326 EXPECT_NE(-1, streamId); 327 328 EXPECT_OK(mCamera->exclusiveTryLock()); 329 /* iterate in a loop submitting requests every frame. 330 * what kind of requests doesnt really matter, just whatever. 331 */ 332 333 // it would probably be better to use CameraMetadata from camera service. 334 camera_metadata_t *request = NULL; 335 EXPECT_OK(mCamera->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW, 336 /*out*/&request)); 337 EXPECT_NE((void*)NULL, request); 338 339 /* FIXME: dont need this later, at which point the above should become an 340 ASSERT_NE*/ 341 if(request == NULL) request = allocate_camera_metadata(10, 100); 342 343 // set the output streams to just this stream ID 344 345 // wow what a verbose API. 346 // i would give a loaf of bread for 347 // metadata->updateOrInsert(keys.request.output.streams, streamId); 348 camera_metadata_entry_t entry; 349 uint32_t tag = static_cast<uint32_t>(ANDROID_REQUEST_OUTPUT_STREAMS); 350 int find = find_camera_metadata_entry(request, tag, &entry); 351 if (find == -ENOENT) { 352 if (add_camera_metadata_entry(request, tag, &streamId, /*data_count*/1) 353 != OK) { 354 camera_metadata_t *tmp = allocate_camera_metadata(1000, 10000); 355 ASSERT_OK(append_camera_metadata(tmp, request)); 356 free_camera_metadata(request); 357 request = tmp; 358 359 ASSERT_OK(add_camera_metadata_entry(request, tag, &streamId, 360 /*data_count*/1)); 361 } 362 } else { 363 ASSERT_OK(update_camera_metadata_entry(request, entry.index, &streamId, 364 /*data_count*/1, &entry)); 365 } 366 367 EXPECT_OK(mCamera->submitRequest(request, /*streaming*/true)); 368 369 dout << "will sleep now for " << mDisplaySecs << std::endl; 370 sleep(mDisplaySecs); 371 372 free_camera_metadata(request); 373 EXPECT_OK(mCamera->cancelStream(streamId)); 374 EXPECT_OK(mCamera->exclusiveUnlock()); 375} 376 377} 378} 379} 380} 381 382