blob: f0a36e8ddcbf559951ee20ed63588843cf749c75 [file] [log] [blame]
Igor Murashkin634a5152013-02-20 17:15:11 -08001/*
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
Igor Murashkin53765732013-02-20 17:41:57 -080020#include <binder/IPCThreadState.h>
21#include <utils/Thread.h>
22
Igor Murashkin634a5152013-02-20 17:15:11 -080023#include "Camera.h"
24#include "ProCamera.h"
Igor Murashkin53765732013-02-20 17:41:57 -080025#include <utils/Vector.h>
26#include <utils/Mutex.h>
27#include <utils/Condition.h>
Igor Murashkin634a5152013-02-20 17:15:11 -080028
Igor Murashkin68506fd2013-02-20 17:57:31 -080029#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
Igor Murashkin634a5152013-02-20 17:15:11 -080035namespace android {
36namespace camera2 {
37namespace tests {
38namespace client {
39
40#define CAMERA_ID 0
41#define TEST_DEBUGGING 0
42
Igor Murashkin68506fd2013-02-20 17:57:31 -080043#define TEST_LISTENER_TIMEOUT 1000000000 // 1 second listener timeout
Igor Murashkin5835cc42013-02-20 19:29:53 -080044#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
Igor Murashkin53765732013-02-20 17:41:57 -080050
Igor Murashkin634a5152013-02-20 17:15:11 -080051#if TEST_DEBUGGING
52#define dout std::cerr
53#else
54#define dout if (0) std::cerr
55#endif
56
Igor Murashkin39f79f72013-01-30 10:14:24 -080057#define EXPECT_OK(x) EXPECT_EQ(OK, (x))
58#define ASSERT_OK(x) ASSERT_EQ(OK, (x))
59
60class ProCameraTest;
61
Igor Murashkin5835cc42013-02-20 19:29:53 -080062enum ProEvent {
Igor Murashkin53765732013-02-20 17:41:57 -080063 UNKNOWN,
64 ACQUIRED,
65 RELEASED,
Igor Murashkin5835cc42013-02-20 19:29:53 -080066 STOLEN,
67 BUFFER_RECEIVED,
Igor Murashkin53765732013-02-20 17:41:57 -080068};
69
Igor Murashkin5835cc42013-02-20 19:29:53 -080070typedef Vector<ProEvent> EventList;
Igor Murashkin53765732013-02-20 17:41:57 -080071
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
Igor Murashkin53765732013-02-20 17:41:57 -080084 ptr->joinThreadPool();
Igor Murashkin53765732013-02-20 17:41:57 -080085
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
Igor Murashkin5835cc42013-02-20 19:29:53 -0800101 if (mProEventList.size() > 0) {
Igor Murashkin53765732013-02-20 17:41:57 -0800102 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
Igor Murashkin5835cc42013-02-20 19:29:53 -0800114 for (size_t i = 0; i < mProEventList.size(); ++i) {
115 out.push(mProEventList[i]);
Igor Murashkin53765732013-02-20 17:41:57 -0800116 }
117
Igor Murashkin5835cc42013-02-20 19:29:53 -0800118 mProEventList.clear();
Igor Murashkin53765732013-02-20 17:41:57 -0800119 }
120
121 /**
122 * Dequeue 1 event from the event queue.
123 * Returns UNKNOWN if queue is empty
124 */
Igor Murashkin5835cc42013-02-20 19:29:53 -0800125 ProEvent ReadEvent() {
Igor Murashkin53765732013-02-20 17:41:57 -0800126 Mutex::Autolock al(mListenerMutex);
127
Igor Murashkin5835cc42013-02-20 19:29:53 -0800128 if (mProEventList.size() == 0) {
Igor Murashkin53765732013-02-20 17:41:57 -0800129 return UNKNOWN;
130 }
131
Igor Murashkin5835cc42013-02-20 19:29:53 -0800132 ProEvent ev = mProEventList[0];
133 mProEventList.removeAt(0);
Igor Murashkin53765732013-02-20 17:41:57 -0800134
135 return ev;
136 }
137
138private:
Igor Murashkin5835cc42013-02-20 19:29:53 -0800139 void QueueEvent(ProEvent ev) {
Igor Murashkin53765732013-02-20 17:41:57 -0800140 {
141 Mutex::Autolock al(mListenerMutex);
Igor Murashkin5835cc42013-02-20 19:29:53 -0800142 mProEventList.push(ev);
Igor Murashkin53765732013-02-20 17:41:57 -0800143 }
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
Igor Murashkin5835cc42013-02-20 19:29:53 -0800177 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
Igor Murashkin53765732013-02-20 17:41:57 -0800191 // 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
Igor Murashkin5835cc42013-02-20 19:29:53 -0800199 Vector<ProEvent> mProEventList;
Igor Murashkin53765732013-02-20 17:41:57 -0800200 Mutex mListenerMutex;
201 Mutex mConditionMutex;
202 Condition mListenerCondition;
203};
204
Igor Murashkin634a5152013-02-20 17:15:11 -0800205class ProCameraTest : public ::testing::Test {
206
Igor Murashkin53765732013-02-20 17:41:57 -0800207public:
208 ProCameraTest() {
209 }
210
Igor Murashkin39f79f72013-01-30 10:14:24 -0800211 static void SetUpTestCase() {
212 // Binder Thread Pool Initialization
Igor Murashkin53765732013-02-20 17:41:57 -0800213 mTestThread = new ProCameraTestThread();
214 mTestThread->run("ProCameraTestThread");
Igor Murashkin39f79f72013-01-30 10:14:24 -0800215 }
Igor Murashkin53765732013-02-20 17:41:57 -0800216
Igor Murashkin39f79f72013-01-30 10:14:24 -0800217 virtual void SetUp() {
Igor Murashkin634a5152013-02-20 17:15:11 -0800218 mCamera = ProCamera::connect(CAMERA_ID);
219 ASSERT_NE((void*)NULL, mCamera.get());
Igor Murashkin53765732013-02-20 17:41:57 -0800220
221 mListener = new ProCameraTestListener();
222 mCamera->setListener(mListener);
Igor Murashkin634a5152013-02-20 17:15:11 -0800223 }
224
225 virtual void TearDown() {
226 ASSERT_NE((void*)NULL, mCamera.get());
227 mCamera->disconnect();
228 }
229
230protected:
231 sp<ProCamera> mCamera;
Igor Murashkin53765732013-02-20 17:41:57 -0800232 sp<ProCameraTestListener> mListener;
233
Igor Murashkin39f79f72013-01-30 10:14:24 -0800234 static sp<Thread> mTestThread;
Igor Murashkin53765732013-02-20 17:41:57 -0800235
Igor Murashkin68506fd2013-02-20 17:57:31 -0800236 int mDisplaySecs;
237 sp<SurfaceComposerClient> mComposerClient;
238 sp<SurfaceControl> mSurfaceControl;
239
Igor Murashkin5835cc42013-02-20 19:29:53 -0800240 sp<SurfaceComposerClient> mDepthComposerClient;
241 sp<SurfaceControl> mDepthSurfaceControl;
242
Igor Murashkin68506fd2013-02-20 17:57:31 -0800243 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
Igor Murashkin5835cc42013-02-20 19:29:53 -0800259 mSurfaceControl->setPosition(640, 0);
260
Igor Murashkin68506fd2013-02-20 17:57:31 -0800261 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
Igor Murashkin5835cc42013-02-20 19:29:53 -0800275 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
Igor Murashkin634a5152013-02-20 17:15:11 -0800300};
301
Igor Murashkin39f79f72013-01-30 10:14:24 -0800302sp<Thread> ProCameraTest::mTestThread;
303
304// test around exclusiveTryLock (immediate locking)
Igor Murashkin53765732013-02-20 17:41:57 -0800305TEST_F(ProCameraTest, LockingImmediate) {
Igor Murashkin634a5152013-02-20 17:15:11 -0800306
307 if (HasFatalFailure()) {
308 return;
309 }
310
Igor Murashkin53765732013-02-20 17:41:57 -0800311 EXPECT_FALSE(mCamera->hasExclusiveLock());
312 EXPECT_EQ(OK, mCamera->exclusiveTryLock());
Igor Murashkin39f79f72013-01-30 10:14:24 -0800313 // 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
Igor Murashkin53765732013-02-20 17:41:57 -0800341
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());
Igor Murashkin634a5152013-02-20 17:15:11 -0800352}
353
Igor Murashkin68506fd2013-02-20 17:57:31 -0800354// 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
Igor Murashkin5835cc42013-02-20 19:29:53 -0800369 sp<Surface> depthSurface;
Igor Murashkin68506fd2013-02-20 17:57:31 -0800370 if (mDisplaySecs > 0) {
Igor Murashkin5835cc42013-02-20 19:29:53 -0800371 createDepthOnScreenSurface(/*out*/depthSurface);
Igor Murashkin68506fd2013-02-20 17:57:31 -0800372 }
Igor Murashkin5835cc42013-02-20 19:29:53 -0800373
374 int depthStreamId = -1;
375 EXPECT_OK(mCamera->createStream(/*width*/320, /*height*/240,
376 TEST_FORMAT_DEPTH, depthSurface, &depthStreamId));
377 EXPECT_NE(-1, depthStreamId);
Igor Murashkin68506fd2013-02-20 17:57:31 -0800378
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);
Igor Murashkin5835cc42013-02-20 19:29:53 -0800399 uint8_t allStreams[] = { depthStreamId };
400 size_t streamCount = sizeof(allStreams) / sizeof(allStreams[0]);
401
Igor Murashkin68506fd2013-02-20 17:57:31 -0800402 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) {
Igor Murashkin5835cc42013-02-20 19:29:53 -0800406 if (add_camera_metadata_entry(request, tag, &allStreams,
407 /*data_count*/streamCount) != OK) {
Igor Murashkin985fd302013-02-20 18:24:43 -0800408 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
Igor Murashkin5835cc42013-02-20 19:29:53 -0800413 ASSERT_OK(add_camera_metadata_entry(request, tag, &allStreams,
414 /*data_count*/streamCount));
Igor Murashkin985fd302013-02-20 18:24:43 -0800415 }
Igor Murashkin68506fd2013-02-20 17:57:31 -0800416 } else {
Igor Murashkin5835cc42013-02-20 19:29:53 -0800417 ASSERT_OK(update_camera_metadata_entry(request, entry.index,
418 &allStreams, /*data_count*/streamCount, &entry));
Igor Murashkin68506fd2013-02-20 17:57:31 -0800419 }
420
421 EXPECT_OK(mCamera->submitRequest(request, /*streaming*/true));
422
Igor Murashkin985fd302013-02-20 18:24:43 -0800423 dout << "will sleep now for " << mDisplaySecs << std::endl;
Igor Murashkin68506fd2013-02-20 17:57:31 -0800424 sleep(mDisplaySecs);
Igor Murashkin68506fd2013-02-20 17:57:31 -0800425
426 free_camera_metadata(request);
Igor Murashkin5835cc42013-02-20 19:29:53 -0800427
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));
Igor Murashkin68506fd2013-02-20 17:57:31 -0800493 EXPECT_OK(mCamera->exclusiveUnlock());
494}
495
Igor Murashkin634a5152013-02-20 17:15:11 -0800496}
497}
498}
499}
500