blob: 30bd2b6197cc2faff55e3a4af7acbb9e009ac379 [file] [log] [blame]
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +01001/*
2 * Copyright (C) 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 <cstdint>
18#include <memory>
19
Jan Sebechlebsky3b478c42023-11-23 13:15:56 +010020#include "VirtualCameraDevice.h"
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +010021#include "VirtualCameraSession.h"
22#include "aidl/android/companion/virtualcamera/BnVirtualCameraCallback.h"
Jan Sebechlebsky3b478c42023-11-23 13:15:56 +010023#include "aidl/android/companion/virtualcamera/SupportedStreamConfiguration.h"
Jan Sebechlebsky0bb5e092023-12-08 16:17:54 +010024#include "aidl/android/hardware/camera/common/Status.h"
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +010025#include "aidl/android/hardware/camera/device/BnCameraDeviceCallback.h"
26#include "aidl/android/hardware/camera/device/StreamConfiguration.h"
27#include "aidl/android/hardware/graphics/common/PixelFormat.h"
28#include "android/binder_auto_utils.h"
29#include "android/binder_interface_utils.h"
30#include "gmock/gmock.h"
31#include "gtest/gtest.h"
32#include "util/MetadataBuilder.h"
33
34namespace android {
35namespace companion {
36namespace virtualcamera {
37namespace {
38
39constexpr int kWidth = 640;
40constexpr int kHeight = 480;
41constexpr int kStreamId = 0;
Jan Sebechlebsky3b478c42023-11-23 13:15:56 +010042constexpr int kCameraId = 42;
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +010043
44using ::aidl::android::companion::virtualcamera::BnVirtualCameraCallback;
45using ::aidl::android::companion::virtualcamera::Format;
Jan Sebechlebsky3b478c42023-11-23 13:15:56 +010046using ::aidl::android::companion::virtualcamera::SupportedStreamConfiguration;
Jan Sebechlebsky0bb5e092023-12-08 16:17:54 +010047using ::aidl::android::hardware::camera::common::Status;
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +010048using ::aidl::android::hardware::camera::device::BnCameraDeviceCallback;
49using ::aidl::android::hardware::camera::device::BufferRequest;
50using ::aidl::android::hardware::camera::device::BufferRequestStatus;
51using ::aidl::android::hardware::camera::device::CaptureRequest;
52using ::aidl::android::hardware::camera::device::CaptureResult;
53using ::aidl::android::hardware::camera::device::HalStream;
54using ::aidl::android::hardware::camera::device::NotifyMsg;
55using ::aidl::android::hardware::camera::device::Stream;
56using ::aidl::android::hardware::camera::device::StreamBuffer;
57using ::aidl::android::hardware::camera::device::StreamBufferRet;
58using ::aidl::android::hardware::camera::device::StreamConfiguration;
59using ::aidl::android::hardware::graphics::common::PixelFormat;
60using ::aidl::android::view::Surface;
61using ::testing::_;
62using ::testing::ElementsAre;
63using ::testing::Eq;
64using ::testing::Return;
65using ::testing::SizeIs;
66
67Stream createStream(int streamId, int width, int height, PixelFormat format) {
68 Stream s;
69 s.id = streamId;
70 s.width = width;
71 s.height = height;
72 s.format = format;
73 return s;
74}
75
76class MockCameraDeviceCallback : public BnCameraDeviceCallback {
77 public:
78 MOCK_METHOD(ndk::ScopedAStatus, notify, (const std::vector<NotifyMsg>&),
79 (override));
80 MOCK_METHOD(ndk::ScopedAStatus, processCaptureResult,
81 (const std::vector<CaptureResult>&), (override));
82 MOCK_METHOD(ndk::ScopedAStatus, requestStreamBuffers,
83 (const std::vector<BufferRequest>&, std::vector<StreamBufferRet>*,
84 BufferRequestStatus*),
85 (override));
86 MOCK_METHOD(ndk::ScopedAStatus, returnStreamBuffers,
87 (const std::vector<StreamBuffer>&), (override));
88};
89
90class MockVirtualCameraCallback : public BnVirtualCameraCallback {
91 public:
92 MOCK_METHOD(ndk::ScopedAStatus, onStreamConfigured,
93 (int, const Surface&, int32_t, int32_t, Format), (override));
94 MOCK_METHOD(ndk::ScopedAStatus, onProcessCaptureRequest, (int, int),
95 (override));
96 MOCK_METHOD(ndk::ScopedAStatus, onStreamClosed, (int), (override));
97};
98
99class VirtualCameraSessionTest : public ::testing::Test {
100 public:
101 void SetUp() override {
102 mMockCameraDeviceCallback =
103 ndk::SharedRefBase::make<MockCameraDeviceCallback>();
104 mMockVirtualCameraClientCallback =
105 ndk::SharedRefBase::make<MockVirtualCameraCallback>();
Jan Sebechlebsky3b478c42023-11-23 13:15:56 +0100106 mVirtualCameraDevice = ndk::SharedRefBase::make<VirtualCameraDevice>(
107 kCameraId,
108 std::vector<SupportedStreamConfiguration>{
109 SupportedStreamConfiguration{.width = kWidth,
110 .height = kHeight,
111 .pixelFormat = Format::YUV_420_888}},
112 mMockVirtualCameraClientCallback);
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +0100113 mVirtualCameraSession = ndk::SharedRefBase::make<VirtualCameraSession>(
Jan Sebechlebsky0bb5e092023-12-08 16:17:54 +0100114 mVirtualCameraDevice, mMockCameraDeviceCallback,
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +0100115 mMockVirtualCameraClientCallback);
116
Jan Sebechlebsky85a2aef2023-11-29 10:35:55 +0100117 // Explicitly defining default actions below to prevent gmock from
118 // default-constructing ndk::ScopedAStatus, because default-constructed
119 // status wraps nullptr AStatus and causes crash when attempting to print
120 // it in gtest report.
121 ON_CALL(*mMockCameraDeviceCallback, notify)
122 .WillByDefault(ndk::ScopedAStatus::ok);
123 ON_CALL(*mMockCameraDeviceCallback, processCaptureResult)
124 .WillByDefault(ndk::ScopedAStatus::ok);
125 ON_CALL(*mMockCameraDeviceCallback, requestStreamBuffers)
126 .WillByDefault(ndk::ScopedAStatus::ok);
127 ON_CALL(*mMockCameraDeviceCallback, returnStreamBuffers)
128 .WillByDefault(ndk::ScopedAStatus::ok);
129
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +0100130 ON_CALL(*mMockVirtualCameraClientCallback, onStreamConfigured)
131 .WillByDefault(ndk::ScopedAStatus::ok);
132 ON_CALL(*mMockVirtualCameraClientCallback, onProcessCaptureRequest)
133 .WillByDefault(ndk::ScopedAStatus::ok);
Jan Sebechlebsky85a2aef2023-11-29 10:35:55 +0100134 ON_CALL(*mMockVirtualCameraClientCallback, onStreamClosed)
135 .WillByDefault(ndk::ScopedAStatus::ok);
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +0100136 }
137
138 protected:
139 std::shared_ptr<MockCameraDeviceCallback> mMockCameraDeviceCallback;
140 std::shared_ptr<MockVirtualCameraCallback> mMockVirtualCameraClientCallback;
Jan Sebechlebsky3b478c42023-11-23 13:15:56 +0100141 std::shared_ptr<VirtualCameraDevice> mVirtualCameraDevice;
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +0100142 std::shared_ptr<VirtualCameraSession> mVirtualCameraSession;
143};
144
145TEST_F(VirtualCameraSessionTest, ConfigureTriggersClientConfigureCallback) {
146 PixelFormat format = PixelFormat::YCBCR_420_888;
147 StreamConfiguration streamConfiguration;
148 streamConfiguration.streams = {
149 createStream(kStreamId, kWidth, kHeight, format)};
150 std::vector<HalStream> halStreams;
151 EXPECT_CALL(
152 *mMockVirtualCameraClientCallback,
153 onStreamConfigured(kStreamId, _, kWidth, kHeight, Format::YUV_420_888));
154
155 ASSERT_TRUE(
156 mVirtualCameraSession->configureStreams(streamConfiguration, &halStreams)
157 .isOk());
158
159 EXPECT_THAT(halStreams, SizeIs(streamConfiguration.streams.size()));
160 EXPECT_THAT(mVirtualCameraSession->getStreamIds(), ElementsAre(0));
161}
162
163TEST_F(VirtualCameraSessionTest, SecondConfigureDropsUnreferencedStreams) {
164 PixelFormat format = PixelFormat::YCBCR_420_888;
165 StreamConfiguration streamConfiguration;
166 std::vector<HalStream> halStreams;
167
168 streamConfiguration.streams = {createStream(0, kWidth, kHeight, format),
169 createStream(1, kWidth, kHeight, format),
170 createStream(2, kWidth, kHeight, format)};
171 ASSERT_TRUE(
172 mVirtualCameraSession->configureStreams(streamConfiguration, &halStreams)
173 .isOk());
174
175 EXPECT_THAT(mVirtualCameraSession->getStreamIds(), ElementsAre(0, 1, 2));
176
177 streamConfiguration.streams = {createStream(0, kWidth, kHeight, format),
178 createStream(2, kWidth, kHeight, format),
179 createStream(3, kWidth, kHeight, format)};
180 ASSERT_TRUE(
181 mVirtualCameraSession->configureStreams(streamConfiguration, &halStreams)
182 .isOk());
183
184 EXPECT_THAT(mVirtualCameraSession->getStreamIds(), ElementsAre(0, 2, 3));
185}
186
187TEST_F(VirtualCameraSessionTest, CloseTriggersClientTerminateCallback) {
188 EXPECT_CALL(*mMockVirtualCameraClientCallback, onStreamClosed(kStreamId))
189 .WillOnce(Return(ndk::ScopedAStatus::ok()));
190
191 ASSERT_TRUE(mVirtualCameraSession->close().isOk());
192}
193
Jan Sebechlebskyb0d8cab2023-11-28 10:55:04 +0100194TEST_F(VirtualCameraSessionTest, FlushBeforeConfigure) {
195 // Flush request coming before the configure request finished
196 // (so potentially the thread is not yet running) should be
197 // gracefully handled.
198
199 EXPECT_TRUE(mVirtualCameraSession->flush().isOk());
200}
201
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +0100202TEST_F(VirtualCameraSessionTest, onProcessCaptureRequestTriggersClientCallback) {
203 StreamConfiguration streamConfiguration;
204 streamConfiguration.streams = {
205 createStream(kStreamId, kWidth, kHeight, PixelFormat::YCBCR_420_888)};
206 std::vector<CaptureRequest> requests(1);
207 requests[0].frameNumber = 42;
208 requests[0].settings = *(
209 MetadataBuilder().setControlAfMode(ANDROID_CONTROL_AF_MODE_AUTO).build());
210
211 std::vector<HalStream> halStreams;
212 ASSERT_TRUE(
213 mVirtualCameraSession->configureStreams(streamConfiguration, &halStreams)
214 .isOk());
215
216 EXPECT_CALL(*mMockVirtualCameraClientCallback,
217 onProcessCaptureRequest(kStreamId, requests[0].frameNumber))
218 .WillOnce(Return(ndk::ScopedAStatus::ok()));
219 int32_t aidlReturn = 0;
220 ASSERT_TRUE(mVirtualCameraSession
221 ->processCaptureRequest(requests, /*in_cachesToRemove=*/{},
222 &aidlReturn)
223 .isOk());
224 EXPECT_THAT(aidlReturn, Eq(requests.size()));
225}
226
Jan Sebechlebsky0bb5e092023-12-08 16:17:54 +0100227TEST_F(VirtualCameraSessionTest, configureAfterCameraRelease) {
228 StreamConfiguration streamConfiguration;
229 streamConfiguration.streams = {
230 createStream(kStreamId, kWidth, kHeight, PixelFormat::YCBCR_420_888)};
231 std::vector<HalStream> halStreams;
232
233 // Release virtual camera.
234 mVirtualCameraDevice.reset();
235
236 // Expect configuration attempt returns CAMERA_DISCONNECTED service specific code.
237 EXPECT_THAT(
238 mVirtualCameraSession->configureStreams(streamConfiguration, &halStreams)
239 .getServiceSpecificError(),
240 Eq(static_cast<int32_t>(Status::CAMERA_DISCONNECTED)));
241}
242
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +0100243} // namespace
244} // namespace virtualcamera
245} // namespace companion
246} // namespace android