blob: d632b7ec351625eba203633fef4c17c5603d2209 [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
44#define TEST_FORMAT HAL_PIXEL_FORMAT_RGBA_8888 //TODO: YUY2 instead
Igor Murashkin53765732013-02-20 17:41:57 -080045
Igor Murashkin634a5152013-02-20 17:15:11 -080046#if TEST_DEBUGGING
47#define dout std::cerr
48#else
49#define dout if (0) std::cerr
50#endif
51
Igor Murashkin39f79f72013-01-30 10:14:24 -080052#define EXPECT_OK(x) EXPECT_EQ(OK, (x))
53#define ASSERT_OK(x) ASSERT_EQ(OK, (x))
54
55class ProCameraTest;
56
Igor Murashkin53765732013-02-20 17:41:57 -080057enum 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
Igor Murashkin53765732013-02-20 17:41:57 -080078 ptr->joinThreadPool();
Igor Murashkin53765732013-02-20 17:41:57 -080079
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
Igor Murashkin634a5152013-02-20 17:15:11 -0800185class ProCameraTest : public ::testing::Test {
186
Igor Murashkin53765732013-02-20 17:41:57 -0800187public:
188 ProCameraTest() {
189 }
190
Igor Murashkin39f79f72013-01-30 10:14:24 -0800191 static void SetUpTestCase() {
192 // Binder Thread Pool Initialization
Igor Murashkin53765732013-02-20 17:41:57 -0800193 mTestThread = new ProCameraTestThread();
194 mTestThread->run("ProCameraTestThread");
Igor Murashkin39f79f72013-01-30 10:14:24 -0800195 }
Igor Murashkin53765732013-02-20 17:41:57 -0800196
Igor Murashkin39f79f72013-01-30 10:14:24 -0800197 virtual void SetUp() {
Igor Murashkin634a5152013-02-20 17:15:11 -0800198 mCamera = ProCamera::connect(CAMERA_ID);
199 ASSERT_NE((void*)NULL, mCamera.get());
Igor Murashkin53765732013-02-20 17:41:57 -0800200
201 mListener = new ProCameraTestListener();
202 mCamera->setListener(mListener);
Igor Murashkin634a5152013-02-20 17:15:11 -0800203 }
204
205 virtual void TearDown() {
206 ASSERT_NE((void*)NULL, mCamera.get());
207 mCamera->disconnect();
208 }
209
210protected:
211 sp<ProCamera> mCamera;
Igor Murashkin53765732013-02-20 17:41:57 -0800212 sp<ProCameraTestListener> mListener;
213
Igor Murashkin39f79f72013-01-30 10:14:24 -0800214 static sp<Thread> mTestThread;
Igor Murashkin53765732013-02-20 17:41:57 -0800215
Igor Murashkin68506fd2013-02-20 17:57:31 -0800216 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
Igor Murashkin634a5152013-02-20 17:15:11 -0800250};
251
Igor Murashkin39f79f72013-01-30 10:14:24 -0800252sp<Thread> ProCameraTest::mTestThread;
253
254// test around exclusiveTryLock (immediate locking)
Igor Murashkin53765732013-02-20 17:41:57 -0800255TEST_F(ProCameraTest, LockingImmediate) {
Igor Murashkin634a5152013-02-20 17:15:11 -0800256
257 if (HasFatalFailure()) {
258 return;
259 }
260
Igor Murashkin53765732013-02-20 17:41:57 -0800261 EXPECT_FALSE(mCamera->hasExclusiveLock());
262 EXPECT_EQ(OK, mCamera->exclusiveTryLock());
Igor Murashkin39f79f72013-01-30 10:14:24 -0800263 // 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
Igor Murashkin53765732013-02-20 17:41:57 -0800291
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());
Igor Murashkin634a5152013-02-20 17:15:11 -0800302}
303
Igor Murashkin68506fd2013-02-20 17:57:31 -0800304// 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 sp<ANativeWindow> window;
321 if (mDisplaySecs > 0) {
322 createOnScreenSurface(/*out*/surface);
323 window = surface;
324 }
325 int streamId = -1;
326 EXPECT_OK(mCamera->createStream(/*width*/640, /*height*/480, TEST_FORMAT,
327 window, &streamId));
328 EXPECT_NE(-1, streamId);
329
330 EXPECT_OK(mCamera->exclusiveTryLock());
331 /* iterate in a loop submitting requests every frame.
332 * what kind of requests doesnt really matter, just whatever.
333 */
334
335 // it would probably be better to use CameraMetadata from camera service.
336 camera_metadata_t *request = NULL;
337 EXPECT_OK(mCamera->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
338 /*out*/&request));
339 EXPECT_NE((void*)NULL, request);
340
341 /* FIXME: dont need this later, at which point the above should become an
342 ASSERT_NE*/
343 if(request == NULL) request = allocate_camera_metadata(10, 100);
344
345 // set the output streams to just this stream ID
346
347 // wow what a verbose API.
348 // i would give a loaf of bread for
349 // metadata->updateOrInsert(keys.request.output.streams, streamId);
350 camera_metadata_entry_t entry;
351 uint32_t tag = static_cast<uint32_t>(ANDROID_REQUEST_OUTPUT_STREAMS);
352 int find = find_camera_metadata_entry(request, tag, &entry);
353 if (find == -ENOENT) {
354 ASSERT_OK(add_camera_metadata_entry(request, tag, &streamId,
355 /*data_count*/1));
356 } else {
357 ASSERT_OK(update_camera_metadata_entry(request, entry.index, &streamId,
358 /*data_count*/1, &entry));
359 }
360
361 EXPECT_OK(mCamera->submitRequest(request, /*streaming*/true));
362
363 sleep(mDisplaySecs);
364 //should the window be empty until the buffer is flipped?
365 // that would certainly make sense
366
367
368 free_camera_metadata(request);
369 EXPECT_OK(mCamera->cancelStream(streamId));
370 EXPECT_OK(mCamera->exclusiveUnlock());
371}
372
Igor Murashkin634a5152013-02-20 17:15:11 -0800373}
374}
375}
376}
377