CameraBinderTests.cpp revision d56db1d2bee182d1851097a9c712712fc094d117
1/* 2 * Copyright (C) 2015 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#define LOG_NDEBUG 0 18#define LOG_TAG "CameraBinderTests" 19 20#include <binder/IInterface.h> 21#include <binder/IServiceManager.h> 22#include <binder/Parcel.h> 23#include <binder/ProcessState.h> 24#include <utils/Errors.h> 25#include <utils/Log.h> 26#include <utils/List.h> 27#include <utils/String8.h> 28#include <utils/String16.h> 29#include <utils/Condition.h> 30#include <utils/Mutex.h> 31#include <system/graphics.h> 32#include <hardware/gralloc.h> 33 34#include <camera/CameraMetadata.h> 35#include <android/hardware/ICameraService.h> 36#include <android/hardware/ICameraServiceListener.h> 37#include <android/hardware/BnCameraServiceListener.h> 38#include <android/hardware/camera2/ICameraDeviceUser.h> 39#include <android/hardware/camera2/ICameraDeviceCallbacks.h> 40#include <android/hardware/camera2/BnCameraDeviceCallbacks.h> 41#include <camera/camera2/CaptureRequest.h> 42#include <camera/camera2/OutputConfiguration.h> 43#include <camera/camera2/SubmitInfo.h> 44 45#include <gui/BufferItemConsumer.h> 46#include <gui/IGraphicBufferProducer.h> 47#include <gui/Surface.h> 48 49#include <gtest/gtest.h> 50#include <unistd.h> 51#include <stdint.h> 52#include <utility> 53#include <vector> 54#include <map> 55#include <algorithm> 56 57using namespace android; 58 59#define ASSERT_NOT_NULL(x) \ 60 ASSERT_TRUE((x) != nullptr) 61 62#define SETUP_TIMEOUT 2000000000 // ns 63#define IDLE_TIMEOUT 2000000000 // ns 64 65// Stub listener implementation 66class TestCameraServiceListener : public hardware::BnCameraServiceListener { 67 std::map<String16, int32_t> mCameraTorchStatuses; 68 std::map<int32_t, int32_t> mCameraStatuses; 69 mutable Mutex mLock; 70 mutable Condition mCondition; 71 mutable Condition mTorchCondition; 72public: 73 virtual ~TestCameraServiceListener() {}; 74 75 virtual binder::Status onStatusChanged(int32_t status, int32_t cameraId) { 76 Mutex::Autolock l(mLock); 77 mCameraStatuses[cameraId] = status; 78 mCondition.broadcast(); 79 return binder::Status::ok(); 80 }; 81 82 virtual binder::Status onTorchStatusChanged(int32_t status, const String16& cameraId) { 83 Mutex::Autolock l(mLock); 84 mCameraTorchStatuses[cameraId] = status; 85 mTorchCondition.broadcast(); 86 return binder::Status::ok(); 87 }; 88 89 bool waitForNumCameras(size_t num) const { 90 Mutex::Autolock l(mLock); 91 92 if (mCameraStatuses.size() == num) { 93 return true; 94 } 95 96 while (mCameraStatuses.size() < num) { 97 if (mCondition.waitRelative(mLock, SETUP_TIMEOUT) != OK) { 98 return false; 99 } 100 } 101 return true; 102 }; 103 104 bool waitForTorchState(int32_t status, int32_t cameraId) const { 105 Mutex::Autolock l(mLock); 106 107 const auto& iter = mCameraTorchStatuses.find(String16(String8::format("%d", cameraId))); 108 if (iter != mCameraTorchStatuses.end() && iter->second == status) { 109 return true; 110 } 111 112 bool foundStatus = false; 113 while (!foundStatus) { 114 if (mTorchCondition.waitRelative(mLock, SETUP_TIMEOUT) != OK) { 115 return false; 116 } 117 const auto& iter = 118 mCameraTorchStatuses.find(String16(String8::format("%d", cameraId))); 119 foundStatus = (iter != mCameraTorchStatuses.end() && iter->second == status); 120 } 121 return true; 122 }; 123 124 int32_t getTorchStatus(int32_t cameraId) const { 125 Mutex::Autolock l(mLock); 126 const auto& iter = mCameraTorchStatuses.find(String16(String8::format("%d", cameraId))); 127 if (iter == mCameraTorchStatuses.end()) { 128 return hardware::ICameraServiceListener::TORCH_STATUS_UNKNOWN; 129 } 130 return iter->second; 131 }; 132 133 int32_t getStatus(int32_t cameraId) const { 134 Mutex::Autolock l(mLock); 135 const auto& iter = mCameraStatuses.find(cameraId); 136 if (iter == mCameraStatuses.end()) { 137 return hardware::ICameraServiceListener::STATUS_UNKNOWN; 138 } 139 return iter->second; 140 }; 141}; 142 143// Callback implementation 144class TestCameraDeviceCallbacks : public hardware::camera2::BnCameraDeviceCallbacks { 145public: 146 enum Status { 147 IDLE, 148 ERROR, 149 PREPARED, 150 RUNNING, 151 SENT_RESULT, 152 UNINITIALIZED 153 }; 154 155protected: 156 bool mError; 157 int32_t mLastStatus; 158 mutable std::vector<int32_t> mStatusesHit; 159 mutable Mutex mLock; 160 mutable Condition mStatusCondition; 161public: 162 TestCameraDeviceCallbacks() : mError(false), mLastStatus(UNINITIALIZED) {} 163 164 virtual ~TestCameraDeviceCallbacks() {} 165 166 virtual binder::Status onDeviceError(int errorCode, 167 const CaptureResultExtras& resultExtras) { 168 (void) resultExtras; 169 ALOGE("%s: onDeviceError occurred with: %d", __FUNCTION__, static_cast<int>(errorCode)); 170 Mutex::Autolock l(mLock); 171 mError = true; 172 mLastStatus = ERROR; 173 mStatusesHit.push_back(mLastStatus); 174 mStatusCondition.broadcast(); 175 return binder::Status::ok(); 176 } 177 178 virtual binder::Status onDeviceIdle() { 179 Mutex::Autolock l(mLock); 180 mLastStatus = IDLE; 181 mStatusesHit.push_back(mLastStatus); 182 mStatusCondition.broadcast(); 183 return binder::Status::ok(); 184 } 185 186 virtual binder::Status onCaptureStarted(const CaptureResultExtras& resultExtras, 187 int64_t timestamp) { 188 (void) resultExtras; 189 (void) timestamp; 190 Mutex::Autolock l(mLock); 191 mLastStatus = RUNNING; 192 mStatusesHit.push_back(mLastStatus); 193 mStatusCondition.broadcast(); 194 return binder::Status::ok(); 195 } 196 197 198 virtual binder::Status onResultReceived(const CameraMetadata& metadata, 199 const CaptureResultExtras& resultExtras) { 200 (void) metadata; 201 (void) resultExtras; 202 Mutex::Autolock l(mLock); 203 mLastStatus = SENT_RESULT; 204 mStatusesHit.push_back(mLastStatus); 205 mStatusCondition.broadcast(); 206 return binder::Status::ok(); 207 } 208 209 virtual binder::Status onPrepared(int streamId) { 210 (void) streamId; 211 Mutex::Autolock l(mLock); 212 mLastStatus = PREPARED; 213 mStatusesHit.push_back(mLastStatus); 214 mStatusCondition.broadcast(); 215 return binder::Status::ok(); 216 } 217 218 // Test helper functions: 219 220 bool hadError() const { 221 Mutex::Autolock l(mLock); 222 return mError; 223 } 224 225 bool waitForStatus(Status status) const { 226 Mutex::Autolock l(mLock); 227 if (mLastStatus == status) { 228 return true; 229 } 230 231 while (std::find(mStatusesHit.begin(), mStatusesHit.end(), status) 232 == mStatusesHit.end()) { 233 234 if (mStatusCondition.waitRelative(mLock, IDLE_TIMEOUT) != OK) { 235 mStatusesHit.clear(); 236 return false; 237 } 238 } 239 mStatusesHit.clear(); 240 241 return true; 242 243 } 244 245 void clearStatus() const { 246 Mutex::Autolock l(mLock); 247 mStatusesHit.clear(); 248 } 249 250 bool waitForIdle() const { 251 return waitForStatus(IDLE); 252 } 253 254}; 255 256namespace { 257 Mutex gLock; 258 class DeathNotifier : public IBinder::DeathRecipient 259 { 260 public: 261 DeathNotifier() {} 262 263 virtual void binderDied(const wp<IBinder>& /*who*/) { 264 ALOGV("binderDied"); 265 Mutex::Autolock _l(gLock); 266 ALOGW("Camera service died!"); 267 } 268 }; 269 sp<DeathNotifier> gDeathNotifier; 270}; // anonymous namespace 271 272// Exercise basic binder calls for the camera service 273TEST(CameraServiceBinderTest, CheckBinderCameraService) { 274 ProcessState::self()->startThreadPool(); 275 sp<IServiceManager> sm = defaultServiceManager(); 276 sp<IBinder> binder = sm->getService(String16("media.camera")); 277 ASSERT_NOT_NULL(binder); 278 if (gDeathNotifier == NULL) { 279 gDeathNotifier = new DeathNotifier(); 280 } 281 binder->linkToDeath(gDeathNotifier); 282 sp<hardware::ICameraService> service = 283 interface_cast<hardware::ICameraService>(binder); 284 285 binder::Status res; 286 287 int32_t numCameras = 0; 288 res = service->getNumberOfCameras(hardware::ICameraService::CAMERA_TYPE_ALL, &numCameras); 289 EXPECT_TRUE(res.isOk()) << res; 290 EXPECT_LE(0, numCameras); 291 292 // Check listener binder calls 293 sp<TestCameraServiceListener> listener(new TestCameraServiceListener()); 294 res = service->addListener(listener); 295 EXPECT_TRUE(res.isOk()) << res; 296 297 EXPECT_TRUE(listener->waitForNumCameras(numCameras)); 298 299 for (int32_t i = 0; i < numCameras; i++) { 300 bool isSupported = false; 301 res = service->supportsCameraApi(i, 302 hardware::ICameraService::API_VERSION_2, &isSupported); 303 EXPECT_TRUE(res.isOk()) << res; 304 305 // We only care about binder calls for the Camera2 API. Camera1 is deprecated. 306 if (!isSupported) { 307 continue; 308 } 309 310 // Check metadata binder call 311 CameraMetadata metadata; 312 res = service->getCameraCharacteristics(i, &metadata); 313 EXPECT_TRUE(res.isOk()) << res; 314 EXPECT_FALSE(metadata.isEmpty()); 315 316 // Make sure we're available, or skip device tests otherwise 317 int32_t s = listener->getStatus(i); 318 EXPECT_EQ(::android::hardware::ICameraServiceListener::STATUS_PRESENT, s); 319 if (s != ::android::hardware::ICameraServiceListener::STATUS_PRESENT) { 320 continue; 321 } 322 323 // Check connect binder calls 324 sp<TestCameraDeviceCallbacks> callbacks(new TestCameraDeviceCallbacks()); 325 sp<hardware::camera2::ICameraDeviceUser> device; 326 res = service->connectDevice(callbacks, i, String16("meeeeeeeee!"), 327 hardware::ICameraService::USE_CALLING_UID, /*out*/&device); 328 EXPECT_TRUE(res.isOk()) << res; 329 ASSERT_NE(nullptr, device.get()); 330 device->disconnect(); 331 EXPECT_FALSE(callbacks->hadError()); 332 333 int32_t torchStatus = listener->getTorchStatus(i); 334 if (torchStatus == hardware::ICameraServiceListener::TORCH_STATUS_AVAILABLE_OFF) { 335 // Check torch calls 336 res = service->setTorchMode(String16(String8::format("%d", i)), 337 /*enabled*/true, callbacks); 338 EXPECT_TRUE(res.isOk()) << res; 339 EXPECT_TRUE(listener->waitForTorchState( 340 hardware::ICameraServiceListener::TORCH_STATUS_AVAILABLE_ON, i)); 341 res = service->setTorchMode(String16(String8::format("%d", i)), 342 /*enabled*/false, callbacks); 343 EXPECT_TRUE(res.isOk()) << res; 344 EXPECT_TRUE(listener->waitForTorchState( 345 hardware::ICameraServiceListener::TORCH_STATUS_AVAILABLE_OFF, i)); 346 } 347 } 348 349 res = service->removeListener(listener); 350 EXPECT_TRUE(res.isOk()) << res; 351} 352 353// Test fixture for client focused binder tests 354class CameraClientBinderTest : public testing::Test { 355protected: 356 sp<hardware::ICameraService> service; 357 int32_t numCameras; 358 std::vector<std::pair<sp<TestCameraDeviceCallbacks>, sp<hardware::camera2::ICameraDeviceUser>>> 359 openDeviceList; 360 sp<TestCameraServiceListener> serviceListener; 361 362 std::pair<sp<TestCameraDeviceCallbacks>, sp<hardware::camera2::ICameraDeviceUser>> 363 openNewDevice(int deviceId) { 364 sp<TestCameraDeviceCallbacks> callbacks(new TestCameraDeviceCallbacks()); 365 sp<hardware::camera2::ICameraDeviceUser> device; 366 { 367 SCOPED_TRACE("openNewDevice"); 368 binder::Status res = service->connectDevice(callbacks, deviceId, String16("meeeeeeeee!"), 369 hardware::ICameraService::USE_CALLING_UID, /*out*/&device); 370 EXPECT_TRUE(res.isOk()) << res; 371 } 372 auto p = std::make_pair(callbacks, device); 373 openDeviceList.push_back(p); 374 return p; 375 } 376 377 void closeDevice(std::pair<sp<TestCameraDeviceCallbacks>, 378 sp<hardware::camera2::ICameraDeviceUser>>& p) { 379 if (p.second.get() != nullptr) { 380 binder::Status res = p.second->disconnect(); 381 EXPECT_TRUE(res.isOk()) << res; 382 { 383 SCOPED_TRACE("closeDevice"); 384 EXPECT_FALSE(p.first->hadError()); 385 } 386 } 387 auto iter = std::find(openDeviceList.begin(), openDeviceList.end(), p); 388 if (iter != openDeviceList.end()) { 389 openDeviceList.erase(iter); 390 } 391 } 392 393 virtual void SetUp() { 394 ProcessState::self()->startThreadPool(); 395 sp<IServiceManager> sm = defaultServiceManager(); 396 sp<IBinder> binder = sm->getService(String16("media.camera")); 397 service = interface_cast<hardware::ICameraService>(binder); 398 serviceListener = new TestCameraServiceListener(); 399 service->addListener(serviceListener); 400 service->getNumberOfCameras(hardware::ICameraService::CAMERA_TYPE_BACKWARD_COMPATIBLE, 401 &numCameras); 402 } 403 404 virtual void TearDown() { 405 service = nullptr; 406 numCameras = 0; 407 for (auto& p : openDeviceList) { 408 closeDevice(p); 409 } 410 } 411 412}; 413 414TEST_F(CameraClientBinderTest, CheckBinderCameraDeviceUser) { 415 ASSERT_NOT_NULL(service); 416 EXPECT_TRUE(serviceListener->waitForNumCameras(numCameras)); 417 for (int32_t i = 0; i < numCameras; i++) { 418 // Make sure we're available, or skip device tests otherwise 419 int32_t s = serviceListener->getStatus(i); 420 EXPECT_EQ(hardware::ICameraServiceListener::STATUS_PRESENT, s); 421 if (s != hardware::ICameraServiceListener::STATUS_PRESENT) { 422 continue; 423 } 424 binder::Status res; 425 426 auto p = openNewDevice(i); 427 sp<TestCameraDeviceCallbacks> callbacks = p.first; 428 sp<hardware::camera2::ICameraDeviceUser> device = p.second; 429 430 // Setup a buffer queue; I'm just using the vendor opaque format here as that is 431 // guaranteed to be present 432 sp<IGraphicBufferProducer> gbProducer; 433 sp<IGraphicBufferConsumer> gbConsumer; 434 BufferQueue::createBufferQueue(&gbProducer, &gbConsumer); 435 sp<BufferItemConsumer> opaqueConsumer = new BufferItemConsumer(gbConsumer, 436 GRALLOC_USAGE_SW_READ_NEVER, /*maxImages*/2, /*controlledByApp*/true); 437 EXPECT_TRUE(opaqueConsumer.get() != nullptr); 438 opaqueConsumer->setName(String8("nom nom nom")); 439 440 // Set to VGA dimens for default, as that is guaranteed to be present 441 EXPECT_EQ(OK, gbConsumer->setDefaultBufferSize(640, 480)); 442 EXPECT_EQ(OK, gbConsumer->setDefaultBufferFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED)); 443 444 sp<Surface> surface(new Surface(gbProducer, /*controlledByApp*/false)); 445 446 OutputConfiguration output(gbProducer, /*rotation*/0); 447 448 // Can we configure? 449 res = device->beginConfigure(); 450 EXPECT_TRUE(res.isOk()) << res; 451 status_t streamId; 452 res = device->createStream(output, &streamId); 453 EXPECT_TRUE(res.isOk()) << res; 454 EXPECT_LE(0, streamId); 455 res = device->endConfigure(/*isConstrainedHighSpeed*/ false); 456 EXPECT_TRUE(res.isOk()) << res; 457 EXPECT_FALSE(callbacks->hadError()); 458 459 // Can we make requests? 460 CameraMetadata requestTemplate; 461 res = device->createDefaultRequest(/*preview template*/1, 462 /*out*/&requestTemplate); 463 EXPECT_TRUE(res.isOk()) << res; 464 465 hardware::camera2::CaptureRequest request; 466 request.mMetadata = requestTemplate; 467 request.mSurfaceList.add(surface); 468 request.mIsReprocess = false; 469 int64_t lastFrameNumber = 0; 470 int64_t lastFrameNumberPrev = 0; 471 callbacks->clearStatus(); 472 473 hardware::camera2::utils::SubmitInfo info; 474 res = device->submitRequest(request, /*streaming*/true, /*out*/&info); 475 EXPECT_TRUE(res.isOk()) << res; 476 EXPECT_TRUE(callbacks->waitForStatus(TestCameraDeviceCallbacks::SENT_RESULT)); 477 EXPECT_LE(0, info.mRequestId); 478 479 // Can we stop requests? 480 res = device->cancelRequest(info.mRequestId, /*out*/&lastFrameNumber); 481 EXPECT_TRUE(res.isOk()) << res; 482 EXPECT_TRUE(callbacks->waitForIdle()); 483 EXPECT_FALSE(callbacks->hadError()); 484 485 // Can we do it again? 486 lastFrameNumberPrev = info.mLastFrameNumber; 487 lastFrameNumber = 0; 488 requestTemplate.clear(); 489 res = device->createDefaultRequest(hardware::camera2::ICameraDeviceUser::TEMPLATE_PREVIEW, 490 /*out*/&requestTemplate); 491 EXPECT_TRUE(res.isOk()) << res; 492 hardware::camera2::CaptureRequest request2; 493 request2.mMetadata = requestTemplate; 494 request2.mSurfaceList.add(surface); 495 request2.mIsReprocess = false; 496 callbacks->clearStatus(); 497 hardware::camera2::utils::SubmitInfo info2; 498 res = device->submitRequest(request2, /*streaming*/true, 499 /*out*/&info2); 500 EXPECT_TRUE(res.isOk()) << res; 501 EXPECT_EQ(hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES, 502 info2.mLastFrameNumber); 503 lastFrameNumber = 0; 504 EXPECT_TRUE(callbacks->waitForStatus(TestCameraDeviceCallbacks::SENT_RESULT)); 505 EXPECT_LE(0, info2.mRequestId); 506 res = device->cancelRequest(info2.mRequestId, /*out*/&lastFrameNumber); 507 EXPECT_TRUE(res.isOk()) << res; 508 EXPECT_TRUE(callbacks->waitForIdle()); 509 EXPECT_LE(lastFrameNumberPrev, lastFrameNumber); 510 sleep(/*second*/1); // allow some time for errors to show up, if any 511 EXPECT_FALSE(callbacks->hadError()); 512 513 // Can we do it with a request list? 514 lastFrameNumberPrev = lastFrameNumber; 515 lastFrameNumber = 0; 516 requestTemplate.clear(); 517 CameraMetadata requestTemplate2; 518 res = device->createDefaultRequest(hardware::camera2::ICameraDeviceUser::TEMPLATE_PREVIEW, 519 /*out*/&requestTemplate); 520 EXPECT_TRUE(res.isOk()) << res; 521 res = device->createDefaultRequest(hardware::camera2::ICameraDeviceUser::TEMPLATE_PREVIEW, 522 /*out*/&requestTemplate2); 523 EXPECT_TRUE(res.isOk()) << res; 524 android::hardware::camera2::CaptureRequest request3; 525 android::hardware::camera2::CaptureRequest request4; 526 request3.mMetadata = requestTemplate; 527 request3.mSurfaceList.add(surface); 528 request3.mIsReprocess = false; 529 request4.mMetadata = requestTemplate2; 530 request4.mSurfaceList.add(surface); 531 request4.mIsReprocess = false; 532 std::vector<hardware::camera2::CaptureRequest> requestList; 533 requestList.push_back(request3); 534 requestList.push_back(request4); 535 536 callbacks->clearStatus(); 537 hardware::camera2::utils::SubmitInfo info3; 538 res = device->submitRequestList(requestList, /*streaming*/false, 539 /*out*/&info3); 540 EXPECT_TRUE(res.isOk()) << res; 541 EXPECT_LE(0, info3.mRequestId); 542 EXPECT_TRUE(callbacks->waitForStatus(TestCameraDeviceCallbacks::SENT_RESULT)); 543 EXPECT_TRUE(callbacks->waitForIdle()); 544 EXPECT_LE(lastFrameNumberPrev, info3.mLastFrameNumber); 545 sleep(/*second*/1); // allow some time for errors to show up, if any 546 EXPECT_FALSE(callbacks->hadError()); 547 548 // Can we unconfigure? 549 res = device->beginConfigure(); 550 EXPECT_TRUE(res.isOk()) << res; 551 res = device->deleteStream(streamId); 552 EXPECT_TRUE(res.isOk()) << res; 553 res = device->endConfigure(/*isConstrainedHighSpeed*/ false); 554 EXPECT_TRUE(res.isOk()) << res; 555 556 sleep(/*second*/1); // allow some time for errors to show up, if any 557 EXPECT_FALSE(callbacks->hadError()); 558 559 closeDevice(p); 560 } 561 562}; 563