1 /*
2 * Copyright 2023 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 <memory>
18
19 #include "VirtualCameraProvider.h"
20 #include "aidl/android/hardware/camera/common/CameraDeviceStatus.h"
21 #include "aidl/android/hardware/camera/common/Status.h"
22 #include "aidl/android/hardware/camera/common/TorchModeStatus.h"
23 #include "aidl/android/hardware/camera/provider/BnCameraProviderCallback.h"
24 #include "android/binder_auto_utils.h"
25 #include "android/binder_interface_utils.h"
26 #include "gmock/gmock.h"
27 #include "gtest/gtest.h"
28 #include "util/Util.h"
29
30 namespace android {
31 namespace companion {
32 namespace virtualcamera {
33 namespace {
34
35 using ::aidl::android::companion::virtualcamera::Format;
36 using ::aidl::android::companion::virtualcamera::LensFacing;
37 using ::aidl::android::companion::virtualcamera::SensorOrientation;
38 using ::aidl::android::companion::virtualcamera::SupportedStreamConfiguration;
39 using ::aidl::android::companion::virtualcamera::VirtualCameraConfiguration;
40 using ::aidl::android::hardware::camera::common::CameraDeviceStatus;
41 using ::aidl::android::hardware::camera::common::Status;
42 using ::aidl::android::hardware::camera::common::TorchModeStatus;
43 using ::aidl::android::hardware::camera::provider::BnCameraProviderCallback;
44 using ::testing::_;
45 using ::testing::ElementsAre;
46 using ::testing::Eq;
47 using ::testing::IsEmpty;
48 using ::testing::IsNull;
49 using ::testing::MatchesRegex;
50 using ::testing::Not;
51 using ::testing::Return;
52
53 constexpr char kCameraId[] = "42";
54 constexpr int kVgaWidth = 640;
55 constexpr int kVgaHeight = 480;
56 constexpr int kMaxFps = 30;
57 constexpr int kDefaultDeviceId = 0;
58 constexpr char kVirtualCameraNameRegex[] = "device@[0-9]+\\.[0-9]+/virtual/.+";
59
60 class MockCameraProviderCallback : public BnCameraProviderCallback {
61 public:
62 MOCK_METHOD(ndk::ScopedAStatus, cameraDeviceStatusChange,
63 (const std::string&, CameraDeviceStatus), (override));
64 MOCK_METHOD(ndk::ScopedAStatus, torchModeStatusChange,
65 (const std::string&, TorchModeStatus), (override));
66 MOCK_METHOD(ndk::ScopedAStatus, physicalCameraDeviceStatusChange,
67 (const std::string&, const std::string&, CameraDeviceStatus),
68 (override));
69 };
70
71 class VirtualCameraProviderTest : public ::testing::Test {
72 public:
SetUp()73 void SetUp() override {
74 mCameraProvider = ndk::SharedRefBase::make<VirtualCameraProvider>();
75 mMockCameraProviderCallback =
76 ndk::SharedRefBase::make<MockCameraProviderCallback>();
77 ON_CALL(*mMockCameraProviderCallback, cameraDeviceStatusChange)
78 .WillByDefault([](const std::string&, CameraDeviceStatus) {
79 return ndk::ScopedAStatus::ok();
80 });
81 }
82
83 protected:
84 std::shared_ptr<VirtualCameraProvider> mCameraProvider;
85 std::shared_ptr<MockCameraProviderCallback> mMockCameraProviderCallback =
86 ndk::SharedRefBase::make<MockCameraProviderCallback>();
87 VirtualCameraConfiguration mInputConfig = VirtualCameraConfiguration{
88 .supportedStreamConfigs = {SupportedStreamConfiguration{
89 .width = kVgaWidth,
90 .height = kVgaHeight,
91 .pixelFormat = Format::YUV_420_888,
92 .maxFps = kMaxFps}},
93 .virtualCameraCallback = nullptr,
94 .sensorOrientation = SensorOrientation::ORIENTATION_0,
95 .lensFacing = LensFacing::FRONT};
96 };
97
TEST_F(VirtualCameraProviderTest,SetNullCameraCallbackFails)98 TEST_F(VirtualCameraProviderTest, SetNullCameraCallbackFails) {
99 // Attempting to set callback to nullptr should fail.
100 EXPECT_FALSE(mCameraProvider->setCallback(nullptr).isOk());
101 }
102
TEST_F(VirtualCameraProviderTest,NoCamerasInitially)103 TEST_F(VirtualCameraProviderTest, NoCamerasInitially) {
104 std::vector<std::string> cameras;
105
106 // Initially, the camera provider should return empty list
107 // of cameras.
108 ASSERT_TRUE(mCameraProvider->getCameraIdList(&cameras).isOk());
109 EXPECT_THAT(cameras, IsEmpty());
110 }
111
TEST_F(VirtualCameraProviderTest,CreateCamera)112 TEST_F(VirtualCameraProviderTest, CreateCamera) {
113 // When new camera is created, we expect
114 // cameraDeviceStatusChange to be called exactly once with
115 // PRESENT status.
116 EXPECT_CALL(*mMockCameraProviderCallback,
117 cameraDeviceStatusChange(_, CameraDeviceStatus::PRESENT))
118 .WillOnce(Return(ndk::ScopedAStatus::ok()));
119
120 ASSERT_TRUE(mCameraProvider->setCallback(mMockCameraProviderCallback).isOk());
121 std::shared_ptr<VirtualCameraDevice> camera =
122 mCameraProvider->createCamera(mInputConfig, kCameraId, kDefaultDeviceId);
123 EXPECT_THAT(camera, Not(IsNull()));
124 EXPECT_THAT(camera->getCameraName(), MatchesRegex(kVirtualCameraNameRegex));
125
126 // Created camera should be in the list of cameras.
127 std::vector<std::string> cameraIds;
128 ASSERT_TRUE(mCameraProvider->getCameraIdList(&cameraIds).isOk());
129 EXPECT_THAT(cameraIds, ElementsAre(camera->getCameraName()));
130 }
131
TEST_F(VirtualCameraProviderTest,CreateCameraBeforeCallbackIsSet)132 TEST_F(VirtualCameraProviderTest, CreateCameraBeforeCallbackIsSet) {
133 // We expect cameraDeviceStatusChange to be invoked even when the
134 // setCallback configures the callback after camera is already created.
135 EXPECT_CALL(*mMockCameraProviderCallback,
136 cameraDeviceStatusChange(_, CameraDeviceStatus::PRESENT))
137 .WillOnce(Return(ndk::ScopedAStatus::ok()));
138
139 std::shared_ptr<VirtualCameraDevice> camera =
140 mCameraProvider->createCamera(mInputConfig, kCameraId, kDefaultDeviceId);
141 ASSERT_TRUE(mCameraProvider->setCallback(mMockCameraProviderCallback).isOk());
142
143 // Created camera should be in the list of cameras.
144 std::vector<std::string> cameraIds;
145 EXPECT_TRUE(mCameraProvider->getCameraIdList(&cameraIds).isOk());
146 EXPECT_THAT(cameraIds, ElementsAre(camera->getCameraName()));
147 }
148
TEST_F(VirtualCameraProviderTest,RemoveCamera)149 TEST_F(VirtualCameraProviderTest, RemoveCamera) {
150 ASSERT_TRUE(mCameraProvider->setCallback(mMockCameraProviderCallback).isOk());
151 std::shared_ptr<VirtualCameraDevice> camera =
152 mCameraProvider->createCamera(mInputConfig, kCameraId, kDefaultDeviceId);
153
154 EXPECT_CALL(*mMockCameraProviderCallback,
155 cameraDeviceStatusChange(Eq(camera->getCameraName()),
156 CameraDeviceStatus::NOT_PRESENT))
157 .WillOnce(Return(ndk::ScopedAStatus::ok()));
158 EXPECT_TRUE(mCameraProvider->removeCamera(camera->getCameraName()));
159
160 // There are no cameras present after only camera is removed.
161 std::vector<std::string> cameraIds;
162 ASSERT_TRUE(mCameraProvider->getCameraIdList(&cameraIds).isOk());
163 EXPECT_THAT(cameraIds, IsEmpty());
164 }
165
TEST_F(VirtualCameraProviderTest,RemoveNonExistingCamera)166 TEST_F(VirtualCameraProviderTest, RemoveNonExistingCamera) {
167 ASSERT_TRUE(mCameraProvider->setCallback(mMockCameraProviderCallback).isOk());
168 std::shared_ptr<VirtualCameraDevice> camera =
169 mCameraProvider->createCamera(mInputConfig, kCameraId, kDefaultDeviceId);
170
171 // Removing non-existing camera should fail.
172 const std::string cameraName = "DefinitelyNoTCamera";
173 EXPECT_FALSE(mCameraProvider->removeCamera(cameraName));
174
175 // Camera should be still present in the camera list.
176 std::vector<std::string> cameraIds;
177 ASSERT_TRUE(mCameraProvider->getCameraIdList(&cameraIds).isOk());
178 EXPECT_THAT(cameraIds, ElementsAre(camera->getCameraName()));
179 }
180
181 } // namespace
182 } // namespace virtualcamera
183 } // namespace companion
184 } // namespace android
185