1*4d7e907cSAndroid Build Coastguard Worker /*
2*4d7e907cSAndroid Build Coastguard Worker * Copyright (C) 2022 The Android Open Source Project
3*4d7e907cSAndroid Build Coastguard Worker *
4*4d7e907cSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*4d7e907cSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*4d7e907cSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*4d7e907cSAndroid Build Coastguard Worker *
8*4d7e907cSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*4d7e907cSAndroid Build Coastguard Worker *
10*4d7e907cSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*4d7e907cSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*4d7e907cSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*4d7e907cSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*4d7e907cSAndroid Build Coastguard Worker * limitations under the License.
15*4d7e907cSAndroid Build Coastguard Worker */
16*4d7e907cSAndroid Build Coastguard Worker
17*4d7e907cSAndroid Build Coastguard Worker #include "FrameHandler.h"
18*4d7e907cSAndroid Build Coastguard Worker #include "FrameHandlerUltrasonics.h"
19*4d7e907cSAndroid Build Coastguard Worker
20*4d7e907cSAndroid Build Coastguard Worker #include <aidl/Gtest.h>
21*4d7e907cSAndroid Build Coastguard Worker #include <aidl/Vintf.h>
22*4d7e907cSAndroid Build Coastguard Worker #include <aidl/android/hardware/automotive/evs/BnEvsEnumeratorStatusCallback.h>
23*4d7e907cSAndroid Build Coastguard Worker #include <aidl/android/hardware/automotive/evs/BufferDesc.h>
24*4d7e907cSAndroid Build Coastguard Worker #include <aidl/android/hardware/automotive/evs/CameraDesc.h>
25*4d7e907cSAndroid Build Coastguard Worker #include <aidl/android/hardware/automotive/evs/CameraParam.h>
26*4d7e907cSAndroid Build Coastguard Worker #include <aidl/android/hardware/automotive/evs/DeviceStatus.h>
27*4d7e907cSAndroid Build Coastguard Worker #include <aidl/android/hardware/automotive/evs/DisplayDesc.h>
28*4d7e907cSAndroid Build Coastguard Worker #include <aidl/android/hardware/automotive/evs/DisplayState.h>
29*4d7e907cSAndroid Build Coastguard Worker #include <aidl/android/hardware/automotive/evs/EvsEventDesc.h>
30*4d7e907cSAndroid Build Coastguard Worker #include <aidl/android/hardware/automotive/evs/EvsEventType.h>
31*4d7e907cSAndroid Build Coastguard Worker #include <aidl/android/hardware/automotive/evs/EvsResult.h>
32*4d7e907cSAndroid Build Coastguard Worker #include <aidl/android/hardware/automotive/evs/IEvsCamera.h>
33*4d7e907cSAndroid Build Coastguard Worker #include <aidl/android/hardware/automotive/evs/IEvsDisplay.h>
34*4d7e907cSAndroid Build Coastguard Worker #include <aidl/android/hardware/automotive/evs/IEvsEnumerator.h>
35*4d7e907cSAndroid Build Coastguard Worker #include <aidl/android/hardware/automotive/evs/IEvsEnumeratorStatusCallback.h>
36*4d7e907cSAndroid Build Coastguard Worker #include <aidl/android/hardware/automotive/evs/IEvsUltrasonicsArray.h>
37*4d7e907cSAndroid Build Coastguard Worker #include <aidl/android/hardware/automotive/evs/ParameterRange.h>
38*4d7e907cSAndroid Build Coastguard Worker #include <aidl/android/hardware/automotive/evs/Stream.h>
39*4d7e907cSAndroid Build Coastguard Worker #include <aidl/android/hardware/automotive/evs/UltrasonicsArrayDesc.h>
40*4d7e907cSAndroid Build Coastguard Worker #include <aidl/android/hardware/common/NativeHandle.h>
41*4d7e907cSAndroid Build Coastguard Worker #include <aidl/android/hardware/graphics/common/HardwareBufferDescription.h>
42*4d7e907cSAndroid Build Coastguard Worker #include <aidl/android/hardware/graphics/common/PixelFormat.h>
43*4d7e907cSAndroid Build Coastguard Worker #include <aidlcommonsupport/NativeHandle.h>
44*4d7e907cSAndroid Build Coastguard Worker #include <android-base/logging.h>
45*4d7e907cSAndroid Build Coastguard Worker #include <android/binder_ibinder.h>
46*4d7e907cSAndroid Build Coastguard Worker #include <android/binder_manager.h>
47*4d7e907cSAndroid Build Coastguard Worker #include <android/binder_process.h>
48*4d7e907cSAndroid Build Coastguard Worker #include <android/binder_status.h>
49*4d7e907cSAndroid Build Coastguard Worker #include <system/camera_metadata.h>
50*4d7e907cSAndroid Build Coastguard Worker #include <ui/GraphicBuffer.h>
51*4d7e907cSAndroid Build Coastguard Worker #include <ui/GraphicBufferAllocator.h>
52*4d7e907cSAndroid Build Coastguard Worker #include <utils/Timers.h>
53*4d7e907cSAndroid Build Coastguard Worker
54*4d7e907cSAndroid Build Coastguard Worker #include <chrono>
55*4d7e907cSAndroid Build Coastguard Worker #include <deque>
56*4d7e907cSAndroid Build Coastguard Worker #include <thread>
57*4d7e907cSAndroid Build Coastguard Worker #include <unordered_set>
58*4d7e907cSAndroid Build Coastguard Worker
59*4d7e907cSAndroid Build Coastguard Worker namespace {
60*4d7e907cSAndroid Build Coastguard Worker
61*4d7e907cSAndroid Build Coastguard Worker // These values are called out in the EVS design doc (as of Mar 8, 2017)
62*4d7e907cSAndroid Build Coastguard Worker constexpr int kMaxStreamStartMilliseconds = 500;
63*4d7e907cSAndroid Build Coastguard Worker constexpr int kMinimumFramesPerSecond = 10;
64*4d7e907cSAndroid Build Coastguard Worker constexpr int kSecondsToMilliseconds = 1000;
65*4d7e907cSAndroid Build Coastguard Worker constexpr int kMillisecondsToMicroseconds = 1000;
66*4d7e907cSAndroid Build Coastguard Worker constexpr float kNanoToMilliseconds = 0.000001f;
67*4d7e907cSAndroid Build Coastguard Worker constexpr float kNanoToSeconds = 0.000000001f;
68*4d7e907cSAndroid Build Coastguard Worker
69*4d7e907cSAndroid Build Coastguard Worker /*
70*4d7e907cSAndroid Build Coastguard Worker * Please note that this is different from what is defined in
71*4d7e907cSAndroid Build Coastguard Worker * libhardware/modules/camera/3_4/metadata/types.h; this has one additional
72*4d7e907cSAndroid Build Coastguard Worker * field to store a framerate.
73*4d7e907cSAndroid Build Coastguard Worker */
74*4d7e907cSAndroid Build Coastguard Worker typedef struct {
75*4d7e907cSAndroid Build Coastguard Worker int32_t id;
76*4d7e907cSAndroid Build Coastguard Worker int32_t width;
77*4d7e907cSAndroid Build Coastguard Worker int32_t height;
78*4d7e907cSAndroid Build Coastguard Worker int32_t format;
79*4d7e907cSAndroid Build Coastguard Worker int32_t direction;
80*4d7e907cSAndroid Build Coastguard Worker int32_t framerate;
81*4d7e907cSAndroid Build Coastguard Worker } RawStreamConfig;
82*4d7e907cSAndroid Build Coastguard Worker constexpr size_t kStreamCfgSz = sizeof(RawStreamConfig) / sizeof(int32_t);
83*4d7e907cSAndroid Build Coastguard Worker
84*4d7e907cSAndroid Build Coastguard Worker using ::aidl::android::hardware::automotive::evs::BnEvsEnumeratorStatusCallback;
85*4d7e907cSAndroid Build Coastguard Worker using ::aidl::android::hardware::automotive::evs::BufferDesc;
86*4d7e907cSAndroid Build Coastguard Worker using ::aidl::android::hardware::automotive::evs::CameraDesc;
87*4d7e907cSAndroid Build Coastguard Worker using ::aidl::android::hardware::automotive::evs::CameraParam;
88*4d7e907cSAndroid Build Coastguard Worker using ::aidl::android::hardware::automotive::evs::DeviceStatus;
89*4d7e907cSAndroid Build Coastguard Worker using ::aidl::android::hardware::automotive::evs::DisplayDesc;
90*4d7e907cSAndroid Build Coastguard Worker using ::aidl::android::hardware::automotive::evs::DisplayState;
91*4d7e907cSAndroid Build Coastguard Worker using ::aidl::android::hardware::automotive::evs::EvsEventDesc;
92*4d7e907cSAndroid Build Coastguard Worker using ::aidl::android::hardware::automotive::evs::EvsEventType;
93*4d7e907cSAndroid Build Coastguard Worker using ::aidl::android::hardware::automotive::evs::EvsResult;
94*4d7e907cSAndroid Build Coastguard Worker using ::aidl::android::hardware::automotive::evs::IEvsCamera;
95*4d7e907cSAndroid Build Coastguard Worker using ::aidl::android::hardware::automotive::evs::IEvsDisplay;
96*4d7e907cSAndroid Build Coastguard Worker using ::aidl::android::hardware::automotive::evs::IEvsEnumerator;
97*4d7e907cSAndroid Build Coastguard Worker using ::aidl::android::hardware::automotive::evs::IEvsEnumeratorStatusCallback;
98*4d7e907cSAndroid Build Coastguard Worker using ::aidl::android::hardware::automotive::evs::IEvsUltrasonicsArray;
99*4d7e907cSAndroid Build Coastguard Worker using ::aidl::android::hardware::automotive::evs::ParameterRange;
100*4d7e907cSAndroid Build Coastguard Worker using ::aidl::android::hardware::automotive::evs::Stream;
101*4d7e907cSAndroid Build Coastguard Worker using ::aidl::android::hardware::automotive::evs::UltrasonicsArrayDesc;
102*4d7e907cSAndroid Build Coastguard Worker using ::aidl::android::hardware::graphics::common::BufferUsage;
103*4d7e907cSAndroid Build Coastguard Worker using ::aidl::android::hardware::graphics::common::HardwareBufferDescription;
104*4d7e907cSAndroid Build Coastguard Worker using ::aidl::android::hardware::graphics::common::PixelFormat;
105*4d7e907cSAndroid Build Coastguard Worker using std::chrono_literals::operator""s;
106*4d7e907cSAndroid Build Coastguard Worker
107*4d7e907cSAndroid Build Coastguard Worker } // namespace
108*4d7e907cSAndroid Build Coastguard Worker
109*4d7e907cSAndroid Build Coastguard Worker // The main test class for EVS
110*4d7e907cSAndroid Build Coastguard Worker class EvsAidlTest : public ::testing::TestWithParam<std::string> {
111*4d7e907cSAndroid Build Coastguard Worker public:
SetUp()112*4d7e907cSAndroid Build Coastguard Worker virtual void SetUp() override {
113*4d7e907cSAndroid Build Coastguard Worker // Make sure we can connect to the enumerator
114*4d7e907cSAndroid Build Coastguard Worker std::string service_name = GetParam();
115*4d7e907cSAndroid Build Coastguard Worker AIBinder* binder = AServiceManager_waitForService(service_name.data());
116*4d7e907cSAndroid Build Coastguard Worker ASSERT_NE(binder, nullptr);
117*4d7e907cSAndroid Build Coastguard Worker mEnumerator = IEvsEnumerator::fromBinder(::ndk::SpAIBinder(binder));
118*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Test target service: " << service_name;
119*4d7e907cSAndroid Build Coastguard Worker
120*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->isHardware(&mIsHwModule).isOk());
121*4d7e907cSAndroid Build Coastguard Worker }
122*4d7e907cSAndroid Build Coastguard Worker
TearDown()123*4d7e907cSAndroid Build Coastguard Worker virtual void TearDown() override {
124*4d7e907cSAndroid Build Coastguard Worker // Attempt to close any active camera
125*4d7e907cSAndroid Build Coastguard Worker for (auto&& cam : mActiveCameras) {
126*4d7e907cSAndroid Build Coastguard Worker if (cam != nullptr) {
127*4d7e907cSAndroid Build Coastguard Worker mEnumerator->closeCamera(cam);
128*4d7e907cSAndroid Build Coastguard Worker }
129*4d7e907cSAndroid Build Coastguard Worker }
130*4d7e907cSAndroid Build Coastguard Worker mActiveCameras.clear();
131*4d7e907cSAndroid Build Coastguard Worker }
132*4d7e907cSAndroid Build Coastguard Worker
133*4d7e907cSAndroid Build Coastguard Worker protected:
loadCameraList()134*4d7e907cSAndroid Build Coastguard Worker void loadCameraList() {
135*4d7e907cSAndroid Build Coastguard Worker // SetUp() must run first!
136*4d7e907cSAndroid Build Coastguard Worker ASSERT_NE(mEnumerator, nullptr);
137*4d7e907cSAndroid Build Coastguard Worker
138*4d7e907cSAndroid Build Coastguard Worker // Get the camera list
139*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->getCameraList(&mCameraInfo).isOk())
140*4d7e907cSAndroid Build Coastguard Worker << "Failed to get a list of available cameras";
141*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "We have " << mCameraInfo.size() << " cameras.";
142*4d7e907cSAndroid Build Coastguard Worker }
143*4d7e907cSAndroid Build Coastguard Worker
loadUltrasonicsArrayList()144*4d7e907cSAndroid Build Coastguard Worker void loadUltrasonicsArrayList() {
145*4d7e907cSAndroid Build Coastguard Worker // SetUp() must run first!
146*4d7e907cSAndroid Build Coastguard Worker ASSERT_NE(mEnumerator, nullptr);
147*4d7e907cSAndroid Build Coastguard Worker
148*4d7e907cSAndroid Build Coastguard Worker // Get the ultrasonics array list
149*4d7e907cSAndroid Build Coastguard Worker auto result = mEnumerator->getUltrasonicsArrayList(&mUltrasonicsArraysInfo);
150*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(result.isOk() ||
151*4d7e907cSAndroid Build Coastguard Worker // TODO(b/149874793): Remove below conditions when
152*4d7e907cSAndroid Build Coastguard Worker // getUltrasonicsArrayList() is implemented.
153*4d7e907cSAndroid Build Coastguard Worker (!result.isOk() && result.getServiceSpecificError() ==
154*4d7e907cSAndroid Build Coastguard Worker static_cast<int32_t>(EvsResult::NOT_IMPLEMENTED)))
155*4d7e907cSAndroid Build Coastguard Worker << "Failed to get a list of available ultrasonics arrays";
156*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "We have " << mCameraInfo.size() << " ultrasonics arrays.";
157*4d7e907cSAndroid Build Coastguard Worker }
158*4d7e907cSAndroid Build Coastguard Worker
isLogicalCamera(const camera_metadata_t * metadata)159*4d7e907cSAndroid Build Coastguard Worker bool isLogicalCamera(const camera_metadata_t* metadata) {
160*4d7e907cSAndroid Build Coastguard Worker if (metadata == nullptr) {
161*4d7e907cSAndroid Build Coastguard Worker // A logical camera device must have a valid camera metadata.
162*4d7e907cSAndroid Build Coastguard Worker return false;
163*4d7e907cSAndroid Build Coastguard Worker }
164*4d7e907cSAndroid Build Coastguard Worker
165*4d7e907cSAndroid Build Coastguard Worker // Looking for LOGICAL_MULTI_CAMERA capability from metadata.
166*4d7e907cSAndroid Build Coastguard Worker camera_metadata_ro_entry_t entry;
167*4d7e907cSAndroid Build Coastguard Worker int rc = find_camera_metadata_ro_entry(metadata, ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
168*4d7e907cSAndroid Build Coastguard Worker &entry);
169*4d7e907cSAndroid Build Coastguard Worker if (rc != 0) {
170*4d7e907cSAndroid Build Coastguard Worker // No capabilities are found.
171*4d7e907cSAndroid Build Coastguard Worker return false;
172*4d7e907cSAndroid Build Coastguard Worker }
173*4d7e907cSAndroid Build Coastguard Worker
174*4d7e907cSAndroid Build Coastguard Worker for (size_t i = 0; i < entry.count; ++i) {
175*4d7e907cSAndroid Build Coastguard Worker uint8_t cap = entry.data.u8[i];
176*4d7e907cSAndroid Build Coastguard Worker if (cap == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA) {
177*4d7e907cSAndroid Build Coastguard Worker return true;
178*4d7e907cSAndroid Build Coastguard Worker }
179*4d7e907cSAndroid Build Coastguard Worker }
180*4d7e907cSAndroid Build Coastguard Worker
181*4d7e907cSAndroid Build Coastguard Worker return false;
182*4d7e907cSAndroid Build Coastguard Worker }
183*4d7e907cSAndroid Build Coastguard Worker
getPhysicalCameraIds(const std::string & id,bool & flag)184*4d7e907cSAndroid Build Coastguard Worker std::unordered_set<std::string> getPhysicalCameraIds(const std::string& id, bool& flag) {
185*4d7e907cSAndroid Build Coastguard Worker std::unordered_set<std::string> physicalCameras;
186*4d7e907cSAndroid Build Coastguard Worker const auto it = std::find_if(mCameraInfo.begin(), mCameraInfo.end(),
187*4d7e907cSAndroid Build Coastguard Worker [&id](const CameraDesc& desc) { return id == desc.id; });
188*4d7e907cSAndroid Build Coastguard Worker if (it == mCameraInfo.end()) {
189*4d7e907cSAndroid Build Coastguard Worker // Unknown camera is requested. Return an empty list.
190*4d7e907cSAndroid Build Coastguard Worker return physicalCameras;
191*4d7e907cSAndroid Build Coastguard Worker }
192*4d7e907cSAndroid Build Coastguard Worker
193*4d7e907cSAndroid Build Coastguard Worker const camera_metadata_t* metadata = reinterpret_cast<camera_metadata_t*>(&it->metadata[0]);
194*4d7e907cSAndroid Build Coastguard Worker flag = isLogicalCamera(metadata);
195*4d7e907cSAndroid Build Coastguard Worker if (!flag) {
196*4d7e907cSAndroid Build Coastguard Worker // EVS assumes that the device w/o a valid metadata is a physical
197*4d7e907cSAndroid Build Coastguard Worker // device.
198*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << id << " is not a logical camera device.";
199*4d7e907cSAndroid Build Coastguard Worker physicalCameras.insert(id);
200*4d7e907cSAndroid Build Coastguard Worker return physicalCameras;
201*4d7e907cSAndroid Build Coastguard Worker }
202*4d7e907cSAndroid Build Coastguard Worker
203*4d7e907cSAndroid Build Coastguard Worker // Look for physical camera identifiers
204*4d7e907cSAndroid Build Coastguard Worker camera_metadata_ro_entry entry;
205*4d7e907cSAndroid Build Coastguard Worker int rc = find_camera_metadata_ro_entry(metadata, ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS,
206*4d7e907cSAndroid Build Coastguard Worker &entry);
207*4d7e907cSAndroid Build Coastguard Worker if (rc != 0) {
208*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << "No physical camera ID is found for a logical camera device";
209*4d7e907cSAndroid Build Coastguard Worker }
210*4d7e907cSAndroid Build Coastguard Worker
211*4d7e907cSAndroid Build Coastguard Worker const uint8_t* ids = entry.data.u8;
212*4d7e907cSAndroid Build Coastguard Worker size_t start = 0;
213*4d7e907cSAndroid Build Coastguard Worker for (size_t i = 0; i < entry.count; ++i) {
214*4d7e907cSAndroid Build Coastguard Worker if (ids[i] == '\0') {
215*4d7e907cSAndroid Build Coastguard Worker if (start != i) {
216*4d7e907cSAndroid Build Coastguard Worker std::string id(reinterpret_cast<const char*>(ids + start));
217*4d7e907cSAndroid Build Coastguard Worker physicalCameras.insert(id);
218*4d7e907cSAndroid Build Coastguard Worker }
219*4d7e907cSAndroid Build Coastguard Worker start = i + 1;
220*4d7e907cSAndroid Build Coastguard Worker }
221*4d7e907cSAndroid Build Coastguard Worker }
222*4d7e907cSAndroid Build Coastguard Worker
223*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << id << " consists of " << physicalCameras.size() << " physical camera devices";
224*4d7e907cSAndroid Build Coastguard Worker return physicalCameras;
225*4d7e907cSAndroid Build Coastguard Worker }
226*4d7e907cSAndroid Build Coastguard Worker
getFirstStreamConfiguration(camera_metadata_t * metadata)227*4d7e907cSAndroid Build Coastguard Worker Stream getFirstStreamConfiguration(camera_metadata_t* metadata) {
228*4d7e907cSAndroid Build Coastguard Worker Stream targetCfg = {};
229*4d7e907cSAndroid Build Coastguard Worker camera_metadata_entry_t streamCfgs;
230*4d7e907cSAndroid Build Coastguard Worker if (!find_camera_metadata_entry(metadata, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
231*4d7e907cSAndroid Build Coastguard Worker &streamCfgs)) {
232*4d7e907cSAndroid Build Coastguard Worker // Stream configurations are found in metadata
233*4d7e907cSAndroid Build Coastguard Worker RawStreamConfig* ptr = reinterpret_cast<RawStreamConfig*>(streamCfgs.data.i32);
234*4d7e907cSAndroid Build Coastguard Worker for (unsigned offset = 0; offset < streamCfgs.count; offset += kStreamCfgSz) {
235*4d7e907cSAndroid Build Coastguard Worker if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT) {
236*4d7e907cSAndroid Build Coastguard Worker targetCfg.width = ptr->width;
237*4d7e907cSAndroid Build Coastguard Worker targetCfg.height = ptr->height;
238*4d7e907cSAndroid Build Coastguard Worker targetCfg.format = static_cast<PixelFormat>(ptr->format);
239*4d7e907cSAndroid Build Coastguard Worker break;
240*4d7e907cSAndroid Build Coastguard Worker }
241*4d7e907cSAndroid Build Coastguard Worker ++ptr;
242*4d7e907cSAndroid Build Coastguard Worker }
243*4d7e907cSAndroid Build Coastguard Worker }
244*4d7e907cSAndroid Build Coastguard Worker
245*4d7e907cSAndroid Build Coastguard Worker return targetCfg;
246*4d7e907cSAndroid Build Coastguard Worker }
247*4d7e907cSAndroid Build Coastguard Worker
248*4d7e907cSAndroid Build Coastguard Worker class DeviceStatusCallback : public BnEvsEnumeratorStatusCallback {
deviceStatusChanged(const std::vector<DeviceStatus> &)249*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus deviceStatusChanged(const std::vector<DeviceStatus>&) override {
250*4d7e907cSAndroid Build Coastguard Worker // This empty implementation returns always ok().
251*4d7e907cSAndroid Build Coastguard Worker return ndk::ScopedAStatus::ok();
252*4d7e907cSAndroid Build Coastguard Worker }
253*4d7e907cSAndroid Build Coastguard Worker };
254*4d7e907cSAndroid Build Coastguard Worker
255*4d7e907cSAndroid Build Coastguard Worker // Every test needs access to the service
256*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<IEvsEnumerator> mEnumerator;
257*4d7e907cSAndroid Build Coastguard Worker // Empty unless/util loadCameraList() is called
258*4d7e907cSAndroid Build Coastguard Worker std::vector<CameraDesc> mCameraInfo;
259*4d7e907cSAndroid Build Coastguard Worker // boolean to tell current module under testing is HW module implementation
260*4d7e907cSAndroid Build Coastguard Worker // or not
261*4d7e907cSAndroid Build Coastguard Worker bool mIsHwModule;
262*4d7e907cSAndroid Build Coastguard Worker // A list of active camera handles that are need to be cleaned up
263*4d7e907cSAndroid Build Coastguard Worker std::deque<std::shared_ptr<IEvsCamera>> mActiveCameras;
264*4d7e907cSAndroid Build Coastguard Worker // Empty unless/util loadUltrasonicsArrayList() is called
265*4d7e907cSAndroid Build Coastguard Worker std::vector<UltrasonicsArrayDesc> mUltrasonicsArraysInfo;
266*4d7e907cSAndroid Build Coastguard Worker // A list of active ultrasonics array handles that are to be cleaned up
267*4d7e907cSAndroid Build Coastguard Worker std::deque<std::weak_ptr<IEvsUltrasonicsArray>> mActiveUltrasonicsArrays;
268*4d7e907cSAndroid Build Coastguard Worker };
269*4d7e907cSAndroid Build Coastguard Worker
270*4d7e907cSAndroid Build Coastguard Worker // Test cases, their implementations, and corresponding requirements are
271*4d7e907cSAndroid Build Coastguard Worker // documented at go/aae-evs-public-api-test.
272*4d7e907cSAndroid Build Coastguard Worker
273*4d7e907cSAndroid Build Coastguard Worker /*
274*4d7e907cSAndroid Build Coastguard Worker * CameraOpenClean:
275*4d7e907cSAndroid Build Coastguard Worker * Opens each camera reported by the enumerator and then explicitly closes it via a
276*4d7e907cSAndroid Build Coastguard Worker * call to closeCamera. Then repeats the test to ensure all cameras can be reopened.
277*4d7e907cSAndroid Build Coastguard Worker */
TEST_P(EvsAidlTest,CameraOpenClean)278*4d7e907cSAndroid Build Coastguard Worker TEST_P(EvsAidlTest, CameraOpenClean) {
279*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Starting CameraOpenClean test";
280*4d7e907cSAndroid Build Coastguard Worker
281*4d7e907cSAndroid Build Coastguard Worker // Get the camera list
282*4d7e907cSAndroid Build Coastguard Worker loadCameraList();
283*4d7e907cSAndroid Build Coastguard Worker
284*4d7e907cSAndroid Build Coastguard Worker // Open and close each camera twice
285*4d7e907cSAndroid Build Coastguard Worker for (auto&& cam : mCameraInfo) {
286*4d7e907cSAndroid Build Coastguard Worker bool isLogicalCam = false;
287*4d7e907cSAndroid Build Coastguard Worker auto devices = getPhysicalCameraIds(cam.id, isLogicalCam);
288*4d7e907cSAndroid Build Coastguard Worker if (mIsHwModule && isLogicalCam) {
289*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Skip a logical device, " << cam.id << " for HW target.";
290*4d7e907cSAndroid Build Coastguard Worker continue;
291*4d7e907cSAndroid Build Coastguard Worker }
292*4d7e907cSAndroid Build Coastguard Worker
293*4d7e907cSAndroid Build Coastguard Worker // Read a target resolution from the metadata
294*4d7e907cSAndroid Build Coastguard Worker Stream targetCfg = getFirstStreamConfiguration(
295*4d7e907cSAndroid Build Coastguard Worker reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
296*4d7e907cSAndroid Build Coastguard Worker ASSERT_GT(targetCfg.width, 0);
297*4d7e907cSAndroid Build Coastguard Worker ASSERT_GT(targetCfg.height, 0);
298*4d7e907cSAndroid Build Coastguard Worker
299*4d7e907cSAndroid Build Coastguard Worker for (int pass = 0; pass < 2; pass++) {
300*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<IEvsCamera> pCam;
301*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam).isOk());
302*4d7e907cSAndroid Build Coastguard Worker ASSERT_NE(pCam, nullptr);
303*4d7e907cSAndroid Build Coastguard Worker
304*4d7e907cSAndroid Build Coastguard Worker CameraDesc cameraInfo;
305*4d7e907cSAndroid Build Coastguard Worker for (auto&& devName : devices) {
306*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pCam->getPhysicalCameraInfo(devName, &cameraInfo).isOk());
307*4d7e907cSAndroid Build Coastguard Worker EXPECT_EQ(devName, cameraInfo.id);
308*4d7e907cSAndroid Build Coastguard Worker }
309*4d7e907cSAndroid Build Coastguard Worker
310*4d7e907cSAndroid Build Coastguard Worker // Store a camera handle for a clean-up
311*4d7e907cSAndroid Build Coastguard Worker mActiveCameras.push_back(pCam);
312*4d7e907cSAndroid Build Coastguard Worker
313*4d7e907cSAndroid Build Coastguard Worker // Verify that this camera self-identifies correctly
314*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pCam->getCameraInfo(&cameraInfo).isOk());
315*4d7e907cSAndroid Build Coastguard Worker EXPECT_EQ(cam.id, cameraInfo.id);
316*4d7e907cSAndroid Build Coastguard Worker
317*4d7e907cSAndroid Build Coastguard Worker // Verify methods for extended info
318*4d7e907cSAndroid Build Coastguard Worker const auto id = 0xFFFFFFFF; // meaningless id
319*4d7e907cSAndroid Build Coastguard Worker std::vector<uint8_t> values;
320*4d7e907cSAndroid Build Coastguard Worker bool isSupported = false;
321*4d7e907cSAndroid Build Coastguard Worker auto status = pCam->setExtendedInfo(id, values);
322*4d7e907cSAndroid Build Coastguard Worker if (isLogicalCam) {
323*4d7e907cSAndroid Build Coastguard Worker EXPECT_TRUE(!status.isOk() && status.getServiceSpecificError() ==
324*4d7e907cSAndroid Build Coastguard Worker static_cast<int>(EvsResult::NOT_SUPPORTED));
325*4d7e907cSAndroid Build Coastguard Worker } else {
326*4d7e907cSAndroid Build Coastguard Worker if (status.isOk()) {
327*4d7e907cSAndroid Build Coastguard Worker // 0xFFFFFFFF is valid for EVS HAL implementation under
328*4d7e907cSAndroid Build Coastguard Worker // test.
329*4d7e907cSAndroid Build Coastguard Worker isSupported = true;
330*4d7e907cSAndroid Build Coastguard Worker } else {
331*4d7e907cSAndroid Build Coastguard Worker EXPECT_TRUE(status.getServiceSpecificError() ==
332*4d7e907cSAndroid Build Coastguard Worker static_cast<int>(EvsResult::INVALID_ARG));
333*4d7e907cSAndroid Build Coastguard Worker }
334*4d7e907cSAndroid Build Coastguard Worker }
335*4d7e907cSAndroid Build Coastguard Worker
336*4d7e907cSAndroid Build Coastguard Worker status = pCam->getExtendedInfo(id, &values);
337*4d7e907cSAndroid Build Coastguard Worker if (isLogicalCam) {
338*4d7e907cSAndroid Build Coastguard Worker EXPECT_TRUE(!status.isOk() && status.getServiceSpecificError() ==
339*4d7e907cSAndroid Build Coastguard Worker static_cast<int>(EvsResult::NOT_SUPPORTED));
340*4d7e907cSAndroid Build Coastguard Worker } else {
341*4d7e907cSAndroid Build Coastguard Worker if (isSupported) {
342*4d7e907cSAndroid Build Coastguard Worker EXPECT_TRUE(status.isOk());
343*4d7e907cSAndroid Build Coastguard Worker } else {
344*4d7e907cSAndroid Build Coastguard Worker EXPECT_TRUE(!status.isOk() && status.getServiceSpecificError() ==
345*4d7e907cSAndroid Build Coastguard Worker static_cast<int>(EvsResult::INVALID_ARG));
346*4d7e907cSAndroid Build Coastguard Worker }
347*4d7e907cSAndroid Build Coastguard Worker }
348*4d7e907cSAndroid Build Coastguard Worker
349*4d7e907cSAndroid Build Coastguard Worker // Explicitly close the camera so resources are released right away
350*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->closeCamera(pCam).isOk());
351*4d7e907cSAndroid Build Coastguard Worker mActiveCameras.clear();
352*4d7e907cSAndroid Build Coastguard Worker }
353*4d7e907cSAndroid Build Coastguard Worker }
354*4d7e907cSAndroid Build Coastguard Worker }
355*4d7e907cSAndroid Build Coastguard Worker
356*4d7e907cSAndroid Build Coastguard Worker /*
357*4d7e907cSAndroid Build Coastguard Worker * CameraOpenAggressive:
358*4d7e907cSAndroid Build Coastguard Worker * Opens each camera reported by the enumerator twice in a row without an intervening closeCamera
359*4d7e907cSAndroid Build Coastguard Worker * call. This ensures that the intended "aggressive open" behavior works. This is necessary for
360*4d7e907cSAndroid Build Coastguard Worker * the system to be tolerant of shutdown/restart race conditions.
361*4d7e907cSAndroid Build Coastguard Worker */
TEST_P(EvsAidlTest,CameraOpenAggressive)362*4d7e907cSAndroid Build Coastguard Worker TEST_P(EvsAidlTest, CameraOpenAggressive) {
363*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Starting CameraOpenAggressive test";
364*4d7e907cSAndroid Build Coastguard Worker
365*4d7e907cSAndroid Build Coastguard Worker // Get the camera list
366*4d7e907cSAndroid Build Coastguard Worker loadCameraList();
367*4d7e907cSAndroid Build Coastguard Worker
368*4d7e907cSAndroid Build Coastguard Worker // Open and close each camera twice
369*4d7e907cSAndroid Build Coastguard Worker for (auto&& cam : mCameraInfo) {
370*4d7e907cSAndroid Build Coastguard Worker bool isLogicalCam = false;
371*4d7e907cSAndroid Build Coastguard Worker getPhysicalCameraIds(cam.id, isLogicalCam);
372*4d7e907cSAndroid Build Coastguard Worker if (mIsHwModule && isLogicalCam) {
373*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Skip a logical device, " << cam.id << " for HW target.";
374*4d7e907cSAndroid Build Coastguard Worker continue;
375*4d7e907cSAndroid Build Coastguard Worker }
376*4d7e907cSAndroid Build Coastguard Worker
377*4d7e907cSAndroid Build Coastguard Worker // Read a target resolution from the metadata
378*4d7e907cSAndroid Build Coastguard Worker Stream targetCfg = getFirstStreamConfiguration(
379*4d7e907cSAndroid Build Coastguard Worker reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
380*4d7e907cSAndroid Build Coastguard Worker ASSERT_GT(targetCfg.width, 0);
381*4d7e907cSAndroid Build Coastguard Worker ASSERT_GT(targetCfg.height, 0);
382*4d7e907cSAndroid Build Coastguard Worker
383*4d7e907cSAndroid Build Coastguard Worker mActiveCameras.clear();
384*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<IEvsCamera> pCam;
385*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam).isOk());
386*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(pCam, nullptr);
387*4d7e907cSAndroid Build Coastguard Worker
388*4d7e907cSAndroid Build Coastguard Worker // Store a camera handle for a clean-up
389*4d7e907cSAndroid Build Coastguard Worker mActiveCameras.push_back(pCam);
390*4d7e907cSAndroid Build Coastguard Worker
391*4d7e907cSAndroid Build Coastguard Worker // Verify that this camera self-identifies correctly
392*4d7e907cSAndroid Build Coastguard Worker CameraDesc cameraInfo;
393*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pCam->getCameraInfo(&cameraInfo).isOk());
394*4d7e907cSAndroid Build Coastguard Worker EXPECT_EQ(cam.id, cameraInfo.id);
395*4d7e907cSAndroid Build Coastguard Worker
396*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<IEvsCamera> pCam2;
397*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam2).isOk());
398*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(pCam2, nullptr);
399*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(pCam, pCam2);
400*4d7e907cSAndroid Build Coastguard Worker
401*4d7e907cSAndroid Build Coastguard Worker // Store a camera handle for a clean-up
402*4d7e907cSAndroid Build Coastguard Worker mActiveCameras.push_back(pCam2);
403*4d7e907cSAndroid Build Coastguard Worker
404*4d7e907cSAndroid Build Coastguard Worker auto status = pCam->setMaxFramesInFlight(2);
405*4d7e907cSAndroid Build Coastguard Worker if (mIsHwModule) {
406*4d7e907cSAndroid Build Coastguard Worker // Verify that the old camera rejects calls via HW module.
407*4d7e907cSAndroid Build Coastguard Worker EXPECT_TRUE(!status.isOk() && status.getServiceSpecificError() ==
408*4d7e907cSAndroid Build Coastguard Worker static_cast<int>(EvsResult::OWNERSHIP_LOST));
409*4d7e907cSAndroid Build Coastguard Worker } else {
410*4d7e907cSAndroid Build Coastguard Worker // default implementation supports multiple clients.
411*4d7e907cSAndroid Build Coastguard Worker EXPECT_TRUE(status.isOk());
412*4d7e907cSAndroid Build Coastguard Worker }
413*4d7e907cSAndroid Build Coastguard Worker
414*4d7e907cSAndroid Build Coastguard Worker // Close the superseded camera
415*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->closeCamera(pCam).isOk());
416*4d7e907cSAndroid Build Coastguard Worker mActiveCameras.pop_front();
417*4d7e907cSAndroid Build Coastguard Worker
418*4d7e907cSAndroid Build Coastguard Worker // Verify that the second camera instance self-identifies correctly
419*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pCam2->getCameraInfo(&cameraInfo).isOk());
420*4d7e907cSAndroid Build Coastguard Worker EXPECT_EQ(cam.id, cameraInfo.id);
421*4d7e907cSAndroid Build Coastguard Worker
422*4d7e907cSAndroid Build Coastguard Worker // Close the second camera instance
423*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->closeCamera(pCam2).isOk());
424*4d7e907cSAndroid Build Coastguard Worker mActiveCameras.pop_front();
425*4d7e907cSAndroid Build Coastguard Worker }
426*4d7e907cSAndroid Build Coastguard Worker
427*4d7e907cSAndroid Build Coastguard Worker // Sleep here to ensure the destructor cleanup has time to run so we don't break follow on tests
428*4d7e907cSAndroid Build Coastguard Worker sleep(1); // I hate that this is an arbitrary time to wait. :( b/36122635
429*4d7e907cSAndroid Build Coastguard Worker }
430*4d7e907cSAndroid Build Coastguard Worker
431*4d7e907cSAndroid Build Coastguard Worker /*
432*4d7e907cSAndroid Build Coastguard Worker * CameraStreamPerformance:
433*4d7e907cSAndroid Build Coastguard Worker * Measure and qualify the stream start up time and streaming frame rate of each reported camera
434*4d7e907cSAndroid Build Coastguard Worker */
TEST_P(EvsAidlTest,CameraStreamPerformance)435*4d7e907cSAndroid Build Coastguard Worker TEST_P(EvsAidlTest, CameraStreamPerformance) {
436*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Starting CameraStreamPerformance test";
437*4d7e907cSAndroid Build Coastguard Worker
438*4d7e907cSAndroid Build Coastguard Worker // Get the camera list
439*4d7e907cSAndroid Build Coastguard Worker loadCameraList();
440*4d7e907cSAndroid Build Coastguard Worker
441*4d7e907cSAndroid Build Coastguard Worker // Test each reported camera
442*4d7e907cSAndroid Build Coastguard Worker for (auto&& cam : mCameraInfo) {
443*4d7e907cSAndroid Build Coastguard Worker bool isLogicalCam = false;
444*4d7e907cSAndroid Build Coastguard Worker auto devices = getPhysicalCameraIds(cam.id, isLogicalCam);
445*4d7e907cSAndroid Build Coastguard Worker if (mIsHwModule && isLogicalCam) {
446*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Skip a logical device " << cam.id;
447*4d7e907cSAndroid Build Coastguard Worker continue;
448*4d7e907cSAndroid Build Coastguard Worker }
449*4d7e907cSAndroid Build Coastguard Worker
450*4d7e907cSAndroid Build Coastguard Worker // Read a target resolution from the metadata
451*4d7e907cSAndroid Build Coastguard Worker Stream targetCfg = getFirstStreamConfiguration(
452*4d7e907cSAndroid Build Coastguard Worker reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
453*4d7e907cSAndroid Build Coastguard Worker ASSERT_GT(targetCfg.width, 0);
454*4d7e907cSAndroid Build Coastguard Worker ASSERT_GT(targetCfg.height, 0);
455*4d7e907cSAndroid Build Coastguard Worker
456*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<IEvsCamera> pCam;
457*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam).isOk());
458*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(pCam, nullptr);
459*4d7e907cSAndroid Build Coastguard Worker
460*4d7e907cSAndroid Build Coastguard Worker // Store a camera handle for a clean-up
461*4d7e907cSAndroid Build Coastguard Worker mActiveCameras.push_back(pCam);
462*4d7e907cSAndroid Build Coastguard Worker
463*4d7e907cSAndroid Build Coastguard Worker // Set up a frame receiver object which will fire up its own thread
464*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<FrameHandler> frameHandler = ndk::SharedRefBase::make<FrameHandler>(
465*4d7e907cSAndroid Build Coastguard Worker pCam, cam, nullptr, FrameHandler::eAutoReturn);
466*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(frameHandler, nullptr);
467*4d7e907cSAndroid Build Coastguard Worker
468*4d7e907cSAndroid Build Coastguard Worker // Start the camera's video stream
469*4d7e907cSAndroid Build Coastguard Worker nsecs_t start = systemTime(SYSTEM_TIME_MONOTONIC);
470*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(frameHandler->startStream());
471*4d7e907cSAndroid Build Coastguard Worker
472*4d7e907cSAndroid Build Coastguard Worker // Ensure the first frame arrived within the expected time
473*4d7e907cSAndroid Build Coastguard Worker frameHandler->waitForFrameCount(1);
474*4d7e907cSAndroid Build Coastguard Worker nsecs_t firstFrame = systemTime(SYSTEM_TIME_MONOTONIC);
475*4d7e907cSAndroid Build Coastguard Worker nsecs_t timeToFirstFrame = systemTime(SYSTEM_TIME_MONOTONIC) - start;
476*4d7e907cSAndroid Build Coastguard Worker
477*4d7e907cSAndroid Build Coastguard Worker // Extra delays are expected when we attempt to start a video stream on
478*4d7e907cSAndroid Build Coastguard Worker // the logical camera device. The amount of delay is expected the
479*4d7e907cSAndroid Build Coastguard Worker // number of physical camera devices multiplied by
480*4d7e907cSAndroid Build Coastguard Worker // kMaxStreamStartMilliseconds at most.
481*4d7e907cSAndroid Build Coastguard Worker EXPECT_LE(nanoseconds_to_milliseconds(timeToFirstFrame),
482*4d7e907cSAndroid Build Coastguard Worker kMaxStreamStartMilliseconds * devices.size());
483*4d7e907cSAndroid Build Coastguard Worker printf("%s: Measured time to first frame %0.2f ms\n", cam.id.data(),
484*4d7e907cSAndroid Build Coastguard Worker timeToFirstFrame * kNanoToMilliseconds);
485*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << cam.id << ": Measured time to first frame " << std::scientific
486*4d7e907cSAndroid Build Coastguard Worker << timeToFirstFrame * kNanoToMilliseconds << " ms.";
487*4d7e907cSAndroid Build Coastguard Worker
488*4d7e907cSAndroid Build Coastguard Worker // Check aspect ratio
489*4d7e907cSAndroid Build Coastguard Worker unsigned width = 0, height = 0;
490*4d7e907cSAndroid Build Coastguard Worker frameHandler->getFrameDimension(&width, &height);
491*4d7e907cSAndroid Build Coastguard Worker EXPECT_GE(width, height);
492*4d7e907cSAndroid Build Coastguard Worker
493*4d7e907cSAndroid Build Coastguard Worker // Wait a bit, then ensure we get at least the required minimum number of frames
494*4d7e907cSAndroid Build Coastguard Worker sleep(5);
495*4d7e907cSAndroid Build Coastguard Worker nsecs_t end = systemTime(SYSTEM_TIME_MONOTONIC);
496*4d7e907cSAndroid Build Coastguard Worker
497*4d7e907cSAndroid Build Coastguard Worker // Even when the camera pointer goes out of scope, the FrameHandler object will
498*4d7e907cSAndroid Build Coastguard Worker // keep the stream alive unless we tell it to shutdown.
499*4d7e907cSAndroid Build Coastguard Worker // Also note that the FrameHandle and the Camera have a mutual circular reference, so
500*4d7e907cSAndroid Build Coastguard Worker // we have to break that cycle in order for either of them to get cleaned up.
501*4d7e907cSAndroid Build Coastguard Worker frameHandler->shutdown();
502*4d7e907cSAndroid Build Coastguard Worker
503*4d7e907cSAndroid Build Coastguard Worker unsigned framesReceived = 0;
504*4d7e907cSAndroid Build Coastguard Worker frameHandler->getFramesCounters(&framesReceived, nullptr);
505*4d7e907cSAndroid Build Coastguard Worker framesReceived = framesReceived - 1; // Back out the first frame we already waited for
506*4d7e907cSAndroid Build Coastguard Worker nsecs_t runTime = end - firstFrame;
507*4d7e907cSAndroid Build Coastguard Worker float framesPerSecond = framesReceived / (runTime * kNanoToSeconds);
508*4d7e907cSAndroid Build Coastguard Worker printf("Measured camera rate %3.2f fps\n", framesPerSecond);
509*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Measured camera rate " << std::scientific << framesPerSecond << " fps.";
510*4d7e907cSAndroid Build Coastguard Worker EXPECT_GE(framesPerSecond, kMinimumFramesPerSecond);
511*4d7e907cSAndroid Build Coastguard Worker
512*4d7e907cSAndroid Build Coastguard Worker // Explicitly release the camera
513*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->closeCamera(pCam).isOk());
514*4d7e907cSAndroid Build Coastguard Worker mActiveCameras.clear();
515*4d7e907cSAndroid Build Coastguard Worker }
516*4d7e907cSAndroid Build Coastguard Worker }
517*4d7e907cSAndroid Build Coastguard Worker
518*4d7e907cSAndroid Build Coastguard Worker /*
519*4d7e907cSAndroid Build Coastguard Worker * CameraStreamBuffering:
520*4d7e907cSAndroid Build Coastguard Worker * Ensure the camera implementation behaves properly when the client holds onto buffers for more
521*4d7e907cSAndroid Build Coastguard Worker * than one frame time. The camera must cleanly skip frames until the client is ready again.
522*4d7e907cSAndroid Build Coastguard Worker */
TEST_P(EvsAidlTest,CameraStreamBuffering)523*4d7e907cSAndroid Build Coastguard Worker TEST_P(EvsAidlTest, CameraStreamBuffering) {
524*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Starting CameraStreamBuffering test";
525*4d7e907cSAndroid Build Coastguard Worker
526*4d7e907cSAndroid Build Coastguard Worker // Arbitrary constant (should be > 1 and not too big)
527*4d7e907cSAndroid Build Coastguard Worker static const unsigned int kBuffersToHold = 6;
528*4d7e907cSAndroid Build Coastguard Worker
529*4d7e907cSAndroid Build Coastguard Worker // Get the camera list
530*4d7e907cSAndroid Build Coastguard Worker loadCameraList();
531*4d7e907cSAndroid Build Coastguard Worker
532*4d7e907cSAndroid Build Coastguard Worker // Test each reported camera
533*4d7e907cSAndroid Build Coastguard Worker for (auto&& cam : mCameraInfo) {
534*4d7e907cSAndroid Build Coastguard Worker bool isLogicalCam = false;
535*4d7e907cSAndroid Build Coastguard Worker getPhysicalCameraIds(cam.id, isLogicalCam);
536*4d7e907cSAndroid Build Coastguard Worker if (mIsHwModule && isLogicalCam) {
537*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Skip a logical device " << cam.id << " for HW target.";
538*4d7e907cSAndroid Build Coastguard Worker continue;
539*4d7e907cSAndroid Build Coastguard Worker }
540*4d7e907cSAndroid Build Coastguard Worker
541*4d7e907cSAndroid Build Coastguard Worker // Read a target resolution from the metadata
542*4d7e907cSAndroid Build Coastguard Worker Stream targetCfg = getFirstStreamConfiguration(
543*4d7e907cSAndroid Build Coastguard Worker reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
544*4d7e907cSAndroid Build Coastguard Worker ASSERT_GT(targetCfg.width, 0);
545*4d7e907cSAndroid Build Coastguard Worker ASSERT_GT(targetCfg.height, 0);
546*4d7e907cSAndroid Build Coastguard Worker
547*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<IEvsCamera> pCam;
548*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam).isOk());
549*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(pCam, nullptr);
550*4d7e907cSAndroid Build Coastguard Worker
551*4d7e907cSAndroid Build Coastguard Worker // Store a camera handle for a clean-up
552*4d7e907cSAndroid Build Coastguard Worker mActiveCameras.push_back(pCam);
553*4d7e907cSAndroid Build Coastguard Worker
554*4d7e907cSAndroid Build Coastguard Worker // Ask for a very large number of buffers in flight to ensure it errors correctly
555*4d7e907cSAndroid Build Coastguard Worker auto badResult = pCam->setMaxFramesInFlight(std::numeric_limits<int32_t>::max());
556*4d7e907cSAndroid Build Coastguard Worker EXPECT_TRUE(!badResult.isOk() && badResult.getServiceSpecificError() ==
557*4d7e907cSAndroid Build Coastguard Worker static_cast<int>(EvsResult::BUFFER_NOT_AVAILABLE));
558*4d7e907cSAndroid Build Coastguard Worker
559*4d7e907cSAndroid Build Coastguard Worker // Now ask for exactly two buffers in flight as we'll test behavior in that case
560*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pCam->setMaxFramesInFlight(kBuffersToHold).isOk());
561*4d7e907cSAndroid Build Coastguard Worker
562*4d7e907cSAndroid Build Coastguard Worker // Set up a frame receiver object which will fire up its own thread.
563*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<FrameHandler> frameHandler = ndk::SharedRefBase::make<FrameHandler>(
564*4d7e907cSAndroid Build Coastguard Worker pCam, cam, nullptr, FrameHandler::eNoAutoReturn);
565*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(frameHandler, nullptr);
566*4d7e907cSAndroid Build Coastguard Worker
567*4d7e907cSAndroid Build Coastguard Worker // Start the camera's video stream
568*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(frameHandler->startStream());
569*4d7e907cSAndroid Build Coastguard Worker
570*4d7e907cSAndroid Build Coastguard Worker // Check that the video stream stalls once we've gotten exactly the number of buffers
571*4d7e907cSAndroid Build Coastguard Worker // we requested since we told the frameHandler not to return them.
572*4d7e907cSAndroid Build Coastguard Worker sleep(1); // 1 second should be enough for at least 5 frames to be delivered worst case
573*4d7e907cSAndroid Build Coastguard Worker unsigned framesReceived = 0;
574*4d7e907cSAndroid Build Coastguard Worker frameHandler->getFramesCounters(&framesReceived, nullptr);
575*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(kBuffersToHold, framesReceived) << "Stream didn't stall at expected buffer limit";
576*4d7e907cSAndroid Build Coastguard Worker
577*4d7e907cSAndroid Build Coastguard Worker // Give back one buffer
578*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(frameHandler->returnHeldBuffer());
579*4d7e907cSAndroid Build Coastguard Worker
580*4d7e907cSAndroid Build Coastguard Worker // Once we return a buffer, it shouldn't take more than 1/10 second to get a new one
581*4d7e907cSAndroid Build Coastguard Worker // filled since we require 10fps minimum -- but give a 10% allowance just in case.
582*4d7e907cSAndroid Build Coastguard Worker usleep(110 * kMillisecondsToMicroseconds);
583*4d7e907cSAndroid Build Coastguard Worker frameHandler->getFramesCounters(&framesReceived, nullptr);
584*4d7e907cSAndroid Build Coastguard Worker EXPECT_EQ(kBuffersToHold + 1, framesReceived) << "Stream should've resumed";
585*4d7e907cSAndroid Build Coastguard Worker
586*4d7e907cSAndroid Build Coastguard Worker // Even when the camera pointer goes out of scope, the FrameHandler object will
587*4d7e907cSAndroid Build Coastguard Worker // keep the stream alive unless we tell it to shutdown.
588*4d7e907cSAndroid Build Coastguard Worker // Also note that the FrameHandle and the Camera have a mutual circular reference, so
589*4d7e907cSAndroid Build Coastguard Worker // we have to break that cycle in order for either of them to get cleaned up.
590*4d7e907cSAndroid Build Coastguard Worker frameHandler->shutdown();
591*4d7e907cSAndroid Build Coastguard Worker
592*4d7e907cSAndroid Build Coastguard Worker // Explicitly release the camera
593*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->closeCamera(pCam).isOk());
594*4d7e907cSAndroid Build Coastguard Worker mActiveCameras.clear();
595*4d7e907cSAndroid Build Coastguard Worker }
596*4d7e907cSAndroid Build Coastguard Worker }
597*4d7e907cSAndroid Build Coastguard Worker
598*4d7e907cSAndroid Build Coastguard Worker /*
599*4d7e907cSAndroid Build Coastguard Worker * CameraToDisplayRoundTrip:
600*4d7e907cSAndroid Build Coastguard Worker * End to end test of data flowing from the camera to the display. Each delivered frame of camera
601*4d7e907cSAndroid Build Coastguard Worker * imagery is simply copied to the display buffer and presented on screen. This is the one test
602*4d7e907cSAndroid Build Coastguard Worker * which a human could observe to see the operation of the system on the physical display.
603*4d7e907cSAndroid Build Coastguard Worker */
TEST_P(EvsAidlTest,CameraToDisplayRoundTrip)604*4d7e907cSAndroid Build Coastguard Worker TEST_P(EvsAidlTest, CameraToDisplayRoundTrip) {
605*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Starting CameraToDisplayRoundTrip test";
606*4d7e907cSAndroid Build Coastguard Worker
607*4d7e907cSAndroid Build Coastguard Worker // Get the camera list
608*4d7e907cSAndroid Build Coastguard Worker loadCameraList();
609*4d7e907cSAndroid Build Coastguard Worker
610*4d7e907cSAndroid Build Coastguard Worker // Request available display IDs
611*4d7e907cSAndroid Build Coastguard Worker uint8_t targetDisplayId = 0;
612*4d7e907cSAndroid Build Coastguard Worker std::vector<uint8_t> displayIds;
613*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->getDisplayIdList(&displayIds).isOk());
614*4d7e907cSAndroid Build Coastguard Worker EXPECT_GT(displayIds.size(), 0);
615*4d7e907cSAndroid Build Coastguard Worker targetDisplayId = displayIds[0];
616*4d7e907cSAndroid Build Coastguard Worker
617*4d7e907cSAndroid Build Coastguard Worker // Test each reported camera
618*4d7e907cSAndroid Build Coastguard Worker for (auto&& cam : mCameraInfo) {
619*4d7e907cSAndroid Build Coastguard Worker // Request exclusive access to the first EVS display
620*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<IEvsDisplay> pDisplay;
621*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->openDisplay(targetDisplayId, &pDisplay).isOk());
622*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(pDisplay, nullptr);
623*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Display " << static_cast<int>(targetDisplayId) << " is in use.";
624*4d7e907cSAndroid Build Coastguard Worker
625*4d7e907cSAndroid Build Coastguard Worker // Get the display descriptor
626*4d7e907cSAndroid Build Coastguard Worker DisplayDesc displayDesc;
627*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pDisplay->getDisplayInfo(&displayDesc).isOk());
628*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << " Resolution: " << displayDesc.width << "x" << displayDesc.height;
629*4d7e907cSAndroid Build Coastguard Worker ASSERT_GT(displayDesc.width, 0);
630*4d7e907cSAndroid Build Coastguard Worker ASSERT_GT(displayDesc.height, 0);
631*4d7e907cSAndroid Build Coastguard Worker
632*4d7e907cSAndroid Build Coastguard Worker bool isLogicalCam = false;
633*4d7e907cSAndroid Build Coastguard Worker getPhysicalCameraIds(cam.id, isLogicalCam);
634*4d7e907cSAndroid Build Coastguard Worker if (mIsHwModule && isLogicalCam) {
635*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Skip a logical device " << cam.id << " for HW target.";
636*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->closeDisplay(pDisplay).isOk());
637*4d7e907cSAndroid Build Coastguard Worker continue;
638*4d7e907cSAndroid Build Coastguard Worker }
639*4d7e907cSAndroid Build Coastguard Worker
640*4d7e907cSAndroid Build Coastguard Worker // Read a target resolution from the metadata
641*4d7e907cSAndroid Build Coastguard Worker Stream targetCfg = getFirstStreamConfiguration(
642*4d7e907cSAndroid Build Coastguard Worker reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
643*4d7e907cSAndroid Build Coastguard Worker ASSERT_GT(targetCfg.width, 0);
644*4d7e907cSAndroid Build Coastguard Worker ASSERT_GT(targetCfg.height, 0);
645*4d7e907cSAndroid Build Coastguard Worker
646*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<IEvsCamera> pCam;
647*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam).isOk());
648*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(pCam, nullptr);
649*4d7e907cSAndroid Build Coastguard Worker
650*4d7e907cSAndroid Build Coastguard Worker // Store a camera handle for a clean-up
651*4d7e907cSAndroid Build Coastguard Worker mActiveCameras.push_back(pCam);
652*4d7e907cSAndroid Build Coastguard Worker
653*4d7e907cSAndroid Build Coastguard Worker // Set up a frame receiver object which will fire up its own thread.
654*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<FrameHandler> frameHandler = ndk::SharedRefBase::make<FrameHandler>(
655*4d7e907cSAndroid Build Coastguard Worker pCam, cam, pDisplay, FrameHandler::eAutoReturn);
656*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(frameHandler, nullptr);
657*4d7e907cSAndroid Build Coastguard Worker
658*4d7e907cSAndroid Build Coastguard Worker // Activate the display
659*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pDisplay->setDisplayState(DisplayState::VISIBLE_ON_NEXT_FRAME).isOk());
660*4d7e907cSAndroid Build Coastguard Worker
661*4d7e907cSAndroid Build Coastguard Worker // Start the camera's video stream
662*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(frameHandler->startStream());
663*4d7e907cSAndroid Build Coastguard Worker
664*4d7e907cSAndroid Build Coastguard Worker // Wait a while to let the data flow
665*4d7e907cSAndroid Build Coastguard Worker static const int kSecondsToWait = 5;
666*4d7e907cSAndroid Build Coastguard Worker const int streamTimeMs =
667*4d7e907cSAndroid Build Coastguard Worker kSecondsToWait * kSecondsToMilliseconds - kMaxStreamStartMilliseconds;
668*4d7e907cSAndroid Build Coastguard Worker const unsigned minimumFramesExpected =
669*4d7e907cSAndroid Build Coastguard Worker streamTimeMs * kMinimumFramesPerSecond / kSecondsToMilliseconds;
670*4d7e907cSAndroid Build Coastguard Worker sleep(kSecondsToWait);
671*4d7e907cSAndroid Build Coastguard Worker unsigned framesReceived = 0;
672*4d7e907cSAndroid Build Coastguard Worker unsigned framesDisplayed = 0;
673*4d7e907cSAndroid Build Coastguard Worker frameHandler->getFramesCounters(&framesReceived, &framesDisplayed);
674*4d7e907cSAndroid Build Coastguard Worker EXPECT_EQ(framesReceived, framesDisplayed);
675*4d7e907cSAndroid Build Coastguard Worker EXPECT_GE(framesDisplayed, minimumFramesExpected);
676*4d7e907cSAndroid Build Coastguard Worker
677*4d7e907cSAndroid Build Coastguard Worker // Turn off the display (yes, before the stream stops -- it should be handled)
678*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pDisplay->setDisplayState(DisplayState::NOT_VISIBLE).isOk());
679*4d7e907cSAndroid Build Coastguard Worker
680*4d7e907cSAndroid Build Coastguard Worker // Shut down the streamer
681*4d7e907cSAndroid Build Coastguard Worker frameHandler->shutdown();
682*4d7e907cSAndroid Build Coastguard Worker
683*4d7e907cSAndroid Build Coastguard Worker // Explicitly release the camera
684*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->closeCamera(pCam).isOk());
685*4d7e907cSAndroid Build Coastguard Worker mActiveCameras.clear();
686*4d7e907cSAndroid Build Coastguard Worker
687*4d7e907cSAndroid Build Coastguard Worker // Explicitly release the display
688*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->closeDisplay(pDisplay).isOk());
689*4d7e907cSAndroid Build Coastguard Worker }
690*4d7e907cSAndroid Build Coastguard Worker }
691*4d7e907cSAndroid Build Coastguard Worker
692*4d7e907cSAndroid Build Coastguard Worker /*
693*4d7e907cSAndroid Build Coastguard Worker * MultiCameraStream:
694*4d7e907cSAndroid Build Coastguard Worker * Verify that each client can start and stop video streams on the same
695*4d7e907cSAndroid Build Coastguard Worker * underlying camera.
696*4d7e907cSAndroid Build Coastguard Worker */
TEST_P(EvsAidlTest,MultiCameraStream)697*4d7e907cSAndroid Build Coastguard Worker TEST_P(EvsAidlTest, MultiCameraStream) {
698*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Starting MultiCameraStream test";
699*4d7e907cSAndroid Build Coastguard Worker
700*4d7e907cSAndroid Build Coastguard Worker if (mIsHwModule) {
701*4d7e907cSAndroid Build Coastguard Worker // This test is not for HW module implementation.
702*4d7e907cSAndroid Build Coastguard Worker return;
703*4d7e907cSAndroid Build Coastguard Worker }
704*4d7e907cSAndroid Build Coastguard Worker
705*4d7e907cSAndroid Build Coastguard Worker // Get the camera list
706*4d7e907cSAndroid Build Coastguard Worker loadCameraList();
707*4d7e907cSAndroid Build Coastguard Worker
708*4d7e907cSAndroid Build Coastguard Worker // Test each reported camera
709*4d7e907cSAndroid Build Coastguard Worker for (auto&& cam : mCameraInfo) {
710*4d7e907cSAndroid Build Coastguard Worker // Read a target resolution from the metadata
711*4d7e907cSAndroid Build Coastguard Worker Stream targetCfg = getFirstStreamConfiguration(
712*4d7e907cSAndroid Build Coastguard Worker reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
713*4d7e907cSAndroid Build Coastguard Worker ASSERT_GT(targetCfg.width, 0);
714*4d7e907cSAndroid Build Coastguard Worker ASSERT_GT(targetCfg.height, 0);
715*4d7e907cSAndroid Build Coastguard Worker
716*4d7e907cSAndroid Build Coastguard Worker // Create two camera clients.
717*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<IEvsCamera> pCam0;
718*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam0).isOk());
719*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(pCam0, nullptr);
720*4d7e907cSAndroid Build Coastguard Worker
721*4d7e907cSAndroid Build Coastguard Worker // Store a camera handle for a clean-up
722*4d7e907cSAndroid Build Coastguard Worker mActiveCameras.push_back(pCam0);
723*4d7e907cSAndroid Build Coastguard Worker
724*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<IEvsCamera> pCam1;
725*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam1).isOk());
726*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(pCam1, nullptr);
727*4d7e907cSAndroid Build Coastguard Worker
728*4d7e907cSAndroid Build Coastguard Worker // Store a camera handle for a clean-up
729*4d7e907cSAndroid Build Coastguard Worker mActiveCameras.push_back(pCam1);
730*4d7e907cSAndroid Build Coastguard Worker
731*4d7e907cSAndroid Build Coastguard Worker // Set up per-client frame receiver objects which will fire up its own thread
732*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<FrameHandler> frameHandler0 = ndk::SharedRefBase::make<FrameHandler>(
733*4d7e907cSAndroid Build Coastguard Worker pCam0, cam, nullptr, FrameHandler::eAutoReturn);
734*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<FrameHandler> frameHandler1 = ndk::SharedRefBase::make<FrameHandler>(
735*4d7e907cSAndroid Build Coastguard Worker pCam1, cam, nullptr, FrameHandler::eAutoReturn);
736*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(frameHandler0, nullptr);
737*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(frameHandler1, nullptr);
738*4d7e907cSAndroid Build Coastguard Worker
739*4d7e907cSAndroid Build Coastguard Worker // Start the camera's video stream via client 0
740*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(frameHandler0->startStream());
741*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(frameHandler1->startStream());
742*4d7e907cSAndroid Build Coastguard Worker
743*4d7e907cSAndroid Build Coastguard Worker // Ensure the stream starts
744*4d7e907cSAndroid Build Coastguard Worker frameHandler0->waitForFrameCount(1);
745*4d7e907cSAndroid Build Coastguard Worker frameHandler1->waitForFrameCount(1);
746*4d7e907cSAndroid Build Coastguard Worker
747*4d7e907cSAndroid Build Coastguard Worker nsecs_t firstFrame = systemTime(SYSTEM_TIME_MONOTONIC);
748*4d7e907cSAndroid Build Coastguard Worker
749*4d7e907cSAndroid Build Coastguard Worker // Wait a bit, then ensure both clients get at least the required minimum number of frames
750*4d7e907cSAndroid Build Coastguard Worker sleep(5);
751*4d7e907cSAndroid Build Coastguard Worker nsecs_t end = systemTime(SYSTEM_TIME_MONOTONIC);
752*4d7e907cSAndroid Build Coastguard Worker unsigned framesReceived0 = 0, framesReceived1 = 0;
753*4d7e907cSAndroid Build Coastguard Worker frameHandler0->getFramesCounters(&framesReceived0, nullptr);
754*4d7e907cSAndroid Build Coastguard Worker frameHandler1->getFramesCounters(&framesReceived1, nullptr);
755*4d7e907cSAndroid Build Coastguard Worker framesReceived0 = framesReceived0 - 1; // Back out the first frame we already waited for
756*4d7e907cSAndroid Build Coastguard Worker framesReceived1 = framesReceived1 - 1; // Back out the first frame we already waited for
757*4d7e907cSAndroid Build Coastguard Worker nsecs_t runTime = end - firstFrame;
758*4d7e907cSAndroid Build Coastguard Worker float framesPerSecond0 = framesReceived0 / (runTime * kNanoToSeconds);
759*4d7e907cSAndroid Build Coastguard Worker float framesPerSecond1 = framesReceived1 / (runTime * kNanoToSeconds);
760*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Measured camera rate " << std::scientific << framesPerSecond0 << " fps and "
761*4d7e907cSAndroid Build Coastguard Worker << framesPerSecond1 << " fps";
762*4d7e907cSAndroid Build Coastguard Worker EXPECT_GE(framesPerSecond0, kMinimumFramesPerSecond);
763*4d7e907cSAndroid Build Coastguard Worker EXPECT_GE(framesPerSecond1, kMinimumFramesPerSecond);
764*4d7e907cSAndroid Build Coastguard Worker
765*4d7e907cSAndroid Build Coastguard Worker // Shutdown one client
766*4d7e907cSAndroid Build Coastguard Worker frameHandler0->shutdown();
767*4d7e907cSAndroid Build Coastguard Worker
768*4d7e907cSAndroid Build Coastguard Worker // Read frame counters again
769*4d7e907cSAndroid Build Coastguard Worker frameHandler0->getFramesCounters(&framesReceived0, nullptr);
770*4d7e907cSAndroid Build Coastguard Worker frameHandler1->getFramesCounters(&framesReceived1, nullptr);
771*4d7e907cSAndroid Build Coastguard Worker
772*4d7e907cSAndroid Build Coastguard Worker // Wait a bit again
773*4d7e907cSAndroid Build Coastguard Worker sleep(5);
774*4d7e907cSAndroid Build Coastguard Worker unsigned framesReceivedAfterStop0 = 0, framesReceivedAfterStop1 = 0;
775*4d7e907cSAndroid Build Coastguard Worker frameHandler0->getFramesCounters(&framesReceivedAfterStop0, nullptr);
776*4d7e907cSAndroid Build Coastguard Worker frameHandler1->getFramesCounters(&framesReceivedAfterStop1, nullptr);
777*4d7e907cSAndroid Build Coastguard Worker EXPECT_EQ(framesReceived0, framesReceivedAfterStop0);
778*4d7e907cSAndroid Build Coastguard Worker EXPECT_LT(framesReceived1, framesReceivedAfterStop1);
779*4d7e907cSAndroid Build Coastguard Worker
780*4d7e907cSAndroid Build Coastguard Worker // Shutdown another
781*4d7e907cSAndroid Build Coastguard Worker frameHandler1->shutdown();
782*4d7e907cSAndroid Build Coastguard Worker
783*4d7e907cSAndroid Build Coastguard Worker // Explicitly release the camera
784*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->closeCamera(pCam0).isOk());
785*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->closeCamera(pCam1).isOk());
786*4d7e907cSAndroid Build Coastguard Worker mActiveCameras.clear();
787*4d7e907cSAndroid Build Coastguard Worker
788*4d7e907cSAndroid Build Coastguard Worker // TODO(b/145459970, b/145457727): below sleep() is added to ensure the
789*4d7e907cSAndroid Build Coastguard Worker // destruction of active camera objects; this may be related with two
790*4d7e907cSAndroid Build Coastguard Worker // issues.
791*4d7e907cSAndroid Build Coastguard Worker sleep(1);
792*4d7e907cSAndroid Build Coastguard Worker }
793*4d7e907cSAndroid Build Coastguard Worker }
794*4d7e907cSAndroid Build Coastguard Worker
795*4d7e907cSAndroid Build Coastguard Worker /*
796*4d7e907cSAndroid Build Coastguard Worker * CameraParameter:
797*4d7e907cSAndroid Build Coastguard Worker * Verify that a client can adjust a camera parameter.
798*4d7e907cSAndroid Build Coastguard Worker */
TEST_P(EvsAidlTest,CameraParameter)799*4d7e907cSAndroid Build Coastguard Worker TEST_P(EvsAidlTest, CameraParameter) {
800*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Starting CameraParameter test";
801*4d7e907cSAndroid Build Coastguard Worker
802*4d7e907cSAndroid Build Coastguard Worker // Get the camera list
803*4d7e907cSAndroid Build Coastguard Worker loadCameraList();
804*4d7e907cSAndroid Build Coastguard Worker
805*4d7e907cSAndroid Build Coastguard Worker // Test each reported camera
806*4d7e907cSAndroid Build Coastguard Worker for (auto&& cam : mCameraInfo) {
807*4d7e907cSAndroid Build Coastguard Worker bool isLogicalCam = false;
808*4d7e907cSAndroid Build Coastguard Worker getPhysicalCameraIds(cam.id, isLogicalCam);
809*4d7e907cSAndroid Build Coastguard Worker if (isLogicalCam) {
810*4d7e907cSAndroid Build Coastguard Worker // TODO(b/145465724): Support camera parameter programming on
811*4d7e907cSAndroid Build Coastguard Worker // logical devices.
812*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Skip a logical device " << cam.id;
813*4d7e907cSAndroid Build Coastguard Worker continue;
814*4d7e907cSAndroid Build Coastguard Worker }
815*4d7e907cSAndroid Build Coastguard Worker
816*4d7e907cSAndroid Build Coastguard Worker // Read a target resolution from the metadata
817*4d7e907cSAndroid Build Coastguard Worker Stream targetCfg = getFirstStreamConfiguration(
818*4d7e907cSAndroid Build Coastguard Worker reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
819*4d7e907cSAndroid Build Coastguard Worker ASSERT_GT(targetCfg.width, 0);
820*4d7e907cSAndroid Build Coastguard Worker ASSERT_GT(targetCfg.height, 0);
821*4d7e907cSAndroid Build Coastguard Worker
822*4d7e907cSAndroid Build Coastguard Worker // Create a camera client
823*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<IEvsCamera> pCam;
824*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam).isOk());
825*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(pCam, nullptr);
826*4d7e907cSAndroid Build Coastguard Worker
827*4d7e907cSAndroid Build Coastguard Worker // Store a camera
828*4d7e907cSAndroid Build Coastguard Worker mActiveCameras.push_back(pCam);
829*4d7e907cSAndroid Build Coastguard Worker
830*4d7e907cSAndroid Build Coastguard Worker // Get the parameter list
831*4d7e907cSAndroid Build Coastguard Worker std::vector<CameraParam> cmds;
832*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pCam->getParameterList(&cmds).isOk());
833*4d7e907cSAndroid Build Coastguard Worker if (cmds.size() < 1) {
834*4d7e907cSAndroid Build Coastguard Worker continue;
835*4d7e907cSAndroid Build Coastguard Worker }
836*4d7e907cSAndroid Build Coastguard Worker
837*4d7e907cSAndroid Build Coastguard Worker // Set up per-client frame receiver objects which will fire up its own thread
838*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<FrameHandler> frameHandler = ndk::SharedRefBase::make<FrameHandler>(
839*4d7e907cSAndroid Build Coastguard Worker pCam, cam, nullptr, FrameHandler::eAutoReturn);
840*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(frameHandler, nullptr);
841*4d7e907cSAndroid Build Coastguard Worker
842*4d7e907cSAndroid Build Coastguard Worker // Start the camera's video stream
843*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(frameHandler->startStream());
844*4d7e907cSAndroid Build Coastguard Worker
845*4d7e907cSAndroid Build Coastguard Worker // Ensure the stream starts
846*4d7e907cSAndroid Build Coastguard Worker frameHandler->waitForFrameCount(1);
847*4d7e907cSAndroid Build Coastguard Worker
848*4d7e907cSAndroid Build Coastguard Worker // Set current client is the primary client
849*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pCam->setPrimaryClient().isOk());
850*4d7e907cSAndroid Build Coastguard Worker for (auto& cmd : cmds) {
851*4d7e907cSAndroid Build Coastguard Worker // Get a valid parameter value range
852*4d7e907cSAndroid Build Coastguard Worker ParameterRange range;
853*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pCam->getIntParameterRange(cmd, &range).isOk());
854*4d7e907cSAndroid Build Coastguard Worker
855*4d7e907cSAndroid Build Coastguard Worker std::vector<int32_t> values;
856*4d7e907cSAndroid Build Coastguard Worker if (cmd == CameraParam::ABSOLUTE_FOCUS) {
857*4d7e907cSAndroid Build Coastguard Worker // Try to turn off auto-focus
858*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pCam->setIntParameter(CameraParam::AUTO_FOCUS, 0, &values).isOk());
859*4d7e907cSAndroid Build Coastguard Worker for (auto&& v : values) {
860*4d7e907cSAndroid Build Coastguard Worker EXPECT_EQ(v, 0);
861*4d7e907cSAndroid Build Coastguard Worker }
862*4d7e907cSAndroid Build Coastguard Worker }
863*4d7e907cSAndroid Build Coastguard Worker
864*4d7e907cSAndroid Build Coastguard Worker // Try to program a parameter with a random value [minVal, maxVal]
865*4d7e907cSAndroid Build Coastguard Worker int32_t val0 = range.min + (std::rand() % (range.max - range.min));
866*4d7e907cSAndroid Build Coastguard Worker
867*4d7e907cSAndroid Build Coastguard Worker // Rounding down
868*4d7e907cSAndroid Build Coastguard Worker val0 = val0 - (val0 % range.step);
869*4d7e907cSAndroid Build Coastguard Worker values.clear();
870*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pCam->setIntParameter(cmd, val0, &values).isOk());
871*4d7e907cSAndroid Build Coastguard Worker
872*4d7e907cSAndroid Build Coastguard Worker values.clear();
873*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pCam->getIntParameter(cmd, &values).isOk());
874*4d7e907cSAndroid Build Coastguard Worker for (auto&& v : values) {
875*4d7e907cSAndroid Build Coastguard Worker EXPECT_EQ(val0, v) << "Values are not matched.";
876*4d7e907cSAndroid Build Coastguard Worker }
877*4d7e907cSAndroid Build Coastguard Worker }
878*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pCam->unsetPrimaryClient().isOk());
879*4d7e907cSAndroid Build Coastguard Worker
880*4d7e907cSAndroid Build Coastguard Worker // Shutdown
881*4d7e907cSAndroid Build Coastguard Worker frameHandler->shutdown();
882*4d7e907cSAndroid Build Coastguard Worker
883*4d7e907cSAndroid Build Coastguard Worker // Explicitly release the camera
884*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->closeCamera(pCam).isOk());
885*4d7e907cSAndroid Build Coastguard Worker mActiveCameras.clear();
886*4d7e907cSAndroid Build Coastguard Worker }
887*4d7e907cSAndroid Build Coastguard Worker }
888*4d7e907cSAndroid Build Coastguard Worker
889*4d7e907cSAndroid Build Coastguard Worker /*
890*4d7e907cSAndroid Build Coastguard Worker * CameraPrimaryClientRelease
891*4d7e907cSAndroid Build Coastguard Worker * Verify that non-primary client gets notified when the primary client either
892*4d7e907cSAndroid Build Coastguard Worker * terminates or releases a role.
893*4d7e907cSAndroid Build Coastguard Worker */
TEST_P(EvsAidlTest,CameraPrimaryClientRelease)894*4d7e907cSAndroid Build Coastguard Worker TEST_P(EvsAidlTest, CameraPrimaryClientRelease) {
895*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Starting CameraPrimaryClientRelease test";
896*4d7e907cSAndroid Build Coastguard Worker
897*4d7e907cSAndroid Build Coastguard Worker if (mIsHwModule) {
898*4d7e907cSAndroid Build Coastguard Worker // This test is not for HW module implementation.
899*4d7e907cSAndroid Build Coastguard Worker return;
900*4d7e907cSAndroid Build Coastguard Worker }
901*4d7e907cSAndroid Build Coastguard Worker
902*4d7e907cSAndroid Build Coastguard Worker // Get the camera list
903*4d7e907cSAndroid Build Coastguard Worker loadCameraList();
904*4d7e907cSAndroid Build Coastguard Worker
905*4d7e907cSAndroid Build Coastguard Worker // Test each reported camera
906*4d7e907cSAndroid Build Coastguard Worker for (auto&& cam : mCameraInfo) {
907*4d7e907cSAndroid Build Coastguard Worker bool isLogicalCam = false;
908*4d7e907cSAndroid Build Coastguard Worker getPhysicalCameraIds(cam.id, isLogicalCam);
909*4d7e907cSAndroid Build Coastguard Worker if (isLogicalCam) {
910*4d7e907cSAndroid Build Coastguard Worker // TODO(b/145465724): Support camera parameter programming on
911*4d7e907cSAndroid Build Coastguard Worker // logical devices.
912*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Skip a logical device " << cam.id;
913*4d7e907cSAndroid Build Coastguard Worker continue;
914*4d7e907cSAndroid Build Coastguard Worker }
915*4d7e907cSAndroid Build Coastguard Worker
916*4d7e907cSAndroid Build Coastguard Worker // Read a target resolution from the metadata
917*4d7e907cSAndroid Build Coastguard Worker Stream targetCfg = getFirstStreamConfiguration(
918*4d7e907cSAndroid Build Coastguard Worker reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
919*4d7e907cSAndroid Build Coastguard Worker ASSERT_GT(targetCfg.width, 0);
920*4d7e907cSAndroid Build Coastguard Worker ASSERT_GT(targetCfg.height, 0);
921*4d7e907cSAndroid Build Coastguard Worker
922*4d7e907cSAndroid Build Coastguard Worker // Create two camera clients.
923*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<IEvsCamera> pPrimaryCam;
924*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pPrimaryCam).isOk());
925*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(pPrimaryCam, nullptr);
926*4d7e907cSAndroid Build Coastguard Worker
927*4d7e907cSAndroid Build Coastguard Worker // Store a camera handle for a clean-up
928*4d7e907cSAndroid Build Coastguard Worker mActiveCameras.push_back(pPrimaryCam);
929*4d7e907cSAndroid Build Coastguard Worker
930*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<IEvsCamera> pSecondaryCam;
931*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pSecondaryCam).isOk());
932*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(pSecondaryCam, nullptr);
933*4d7e907cSAndroid Build Coastguard Worker
934*4d7e907cSAndroid Build Coastguard Worker // Store a camera handle for a clean-up
935*4d7e907cSAndroid Build Coastguard Worker mActiveCameras.push_back(pSecondaryCam);
936*4d7e907cSAndroid Build Coastguard Worker
937*4d7e907cSAndroid Build Coastguard Worker // Set up per-client frame receiver objects which will fire up its own thread
938*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<FrameHandler> frameHandlerPrimary = ndk::SharedRefBase::make<FrameHandler>(
939*4d7e907cSAndroid Build Coastguard Worker pPrimaryCam, cam, nullptr, FrameHandler::eAutoReturn);
940*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<FrameHandler> frameHandlerSecondary =
941*4d7e907cSAndroid Build Coastguard Worker ndk::SharedRefBase::make<FrameHandler>(pSecondaryCam, cam, nullptr,
942*4d7e907cSAndroid Build Coastguard Worker FrameHandler::eAutoReturn);
943*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(frameHandlerPrimary, nullptr);
944*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(frameHandlerSecondary, nullptr);
945*4d7e907cSAndroid Build Coastguard Worker
946*4d7e907cSAndroid Build Coastguard Worker // Set one client as the primary client
947*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pPrimaryCam->setPrimaryClient().isOk());
948*4d7e907cSAndroid Build Coastguard Worker
949*4d7e907cSAndroid Build Coastguard Worker // Try to set another client as the primary client.
950*4d7e907cSAndroid Build Coastguard Worker ASSERT_FALSE(pSecondaryCam->setPrimaryClient().isOk());
951*4d7e907cSAndroid Build Coastguard Worker
952*4d7e907cSAndroid Build Coastguard Worker // Start the camera's video stream via a primary client client.
953*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(frameHandlerPrimary->startStream());
954*4d7e907cSAndroid Build Coastguard Worker
955*4d7e907cSAndroid Build Coastguard Worker // Ensure the stream starts
956*4d7e907cSAndroid Build Coastguard Worker frameHandlerPrimary->waitForFrameCount(1);
957*4d7e907cSAndroid Build Coastguard Worker
958*4d7e907cSAndroid Build Coastguard Worker // Start the camera's video stream via another client
959*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(frameHandlerSecondary->startStream());
960*4d7e907cSAndroid Build Coastguard Worker
961*4d7e907cSAndroid Build Coastguard Worker // Ensure the stream starts
962*4d7e907cSAndroid Build Coastguard Worker frameHandlerSecondary->waitForFrameCount(1);
963*4d7e907cSAndroid Build Coastguard Worker
964*4d7e907cSAndroid Build Coastguard Worker // Non-primary client expects to receive a primary client role relesed
965*4d7e907cSAndroid Build Coastguard Worker // notification.
966*4d7e907cSAndroid Build Coastguard Worker EvsEventDesc aTargetEvent = {};
967*4d7e907cSAndroid Build Coastguard Worker EvsEventDesc aNotification = {};
968*4d7e907cSAndroid Build Coastguard Worker
969*4d7e907cSAndroid Build Coastguard Worker bool listening = false;
970*4d7e907cSAndroid Build Coastguard Worker std::mutex eventLock;
971*4d7e907cSAndroid Build Coastguard Worker std::condition_variable eventCond;
972*4d7e907cSAndroid Build Coastguard Worker std::thread listener =
973*4d7e907cSAndroid Build Coastguard Worker std::thread([&aNotification, &frameHandlerSecondary, &listening, &eventCond]() {
974*4d7e907cSAndroid Build Coastguard Worker // Notify that a listening thread is running.
975*4d7e907cSAndroid Build Coastguard Worker listening = true;
976*4d7e907cSAndroid Build Coastguard Worker eventCond.notify_all();
977*4d7e907cSAndroid Build Coastguard Worker
978*4d7e907cSAndroid Build Coastguard Worker EvsEventDesc aTargetEvent;
979*4d7e907cSAndroid Build Coastguard Worker aTargetEvent.aType = EvsEventType::MASTER_RELEASED;
980*4d7e907cSAndroid Build Coastguard Worker if (!frameHandlerSecondary->waitForEvent(aTargetEvent, aNotification, true)) {
981*4d7e907cSAndroid Build Coastguard Worker LOG(WARNING) << "A timer is expired before a target event is fired.";
982*4d7e907cSAndroid Build Coastguard Worker }
983*4d7e907cSAndroid Build Coastguard Worker });
984*4d7e907cSAndroid Build Coastguard Worker
985*4d7e907cSAndroid Build Coastguard Worker // Wait until a listening thread starts.
986*4d7e907cSAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(eventLock);
987*4d7e907cSAndroid Build Coastguard Worker auto timer = std::chrono::system_clock::now();
988*4d7e907cSAndroid Build Coastguard Worker while (!listening) {
989*4d7e907cSAndroid Build Coastguard Worker timer += 1s;
990*4d7e907cSAndroid Build Coastguard Worker eventCond.wait_until(lock, timer);
991*4d7e907cSAndroid Build Coastguard Worker }
992*4d7e907cSAndroid Build Coastguard Worker lock.unlock();
993*4d7e907cSAndroid Build Coastguard Worker
994*4d7e907cSAndroid Build Coastguard Worker // Release a primary client role.
995*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pPrimaryCam->unsetPrimaryClient().isOk());
996*4d7e907cSAndroid Build Coastguard Worker
997*4d7e907cSAndroid Build Coastguard Worker // Join a listening thread.
998*4d7e907cSAndroid Build Coastguard Worker if (listener.joinable()) {
999*4d7e907cSAndroid Build Coastguard Worker listener.join();
1000*4d7e907cSAndroid Build Coastguard Worker }
1001*4d7e907cSAndroid Build Coastguard Worker
1002*4d7e907cSAndroid Build Coastguard Worker // Verify change notifications.
1003*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(EvsEventType::MASTER_RELEASED, static_cast<EvsEventType>(aNotification.aType));
1004*4d7e907cSAndroid Build Coastguard Worker
1005*4d7e907cSAndroid Build Coastguard Worker // Non-primary becomes a primary client.
1006*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pSecondaryCam->setPrimaryClient().isOk());
1007*4d7e907cSAndroid Build Coastguard Worker
1008*4d7e907cSAndroid Build Coastguard Worker // Previous primary client fails to become a primary client.
1009*4d7e907cSAndroid Build Coastguard Worker ASSERT_FALSE(pPrimaryCam->setPrimaryClient().isOk());
1010*4d7e907cSAndroid Build Coastguard Worker
1011*4d7e907cSAndroid Build Coastguard Worker listening = false;
1012*4d7e907cSAndroid Build Coastguard Worker listener = std::thread([&aNotification, &frameHandlerPrimary, &listening, &eventCond]() {
1013*4d7e907cSAndroid Build Coastguard Worker // Notify that a listening thread is running.
1014*4d7e907cSAndroid Build Coastguard Worker listening = true;
1015*4d7e907cSAndroid Build Coastguard Worker eventCond.notify_all();
1016*4d7e907cSAndroid Build Coastguard Worker
1017*4d7e907cSAndroid Build Coastguard Worker EvsEventDesc aTargetEvent;
1018*4d7e907cSAndroid Build Coastguard Worker aTargetEvent.aType = EvsEventType::MASTER_RELEASED;
1019*4d7e907cSAndroid Build Coastguard Worker if (!frameHandlerPrimary->waitForEvent(aTargetEvent, aNotification, true)) {
1020*4d7e907cSAndroid Build Coastguard Worker LOG(WARNING) << "A timer is expired before a target event is fired.";
1021*4d7e907cSAndroid Build Coastguard Worker }
1022*4d7e907cSAndroid Build Coastguard Worker });
1023*4d7e907cSAndroid Build Coastguard Worker
1024*4d7e907cSAndroid Build Coastguard Worker // Wait until a listening thread starts.
1025*4d7e907cSAndroid Build Coastguard Worker timer = std::chrono::system_clock::now();
1026*4d7e907cSAndroid Build Coastguard Worker lock.lock();
1027*4d7e907cSAndroid Build Coastguard Worker while (!listening) {
1028*4d7e907cSAndroid Build Coastguard Worker eventCond.wait_until(lock, timer + 1s);
1029*4d7e907cSAndroid Build Coastguard Worker }
1030*4d7e907cSAndroid Build Coastguard Worker lock.unlock();
1031*4d7e907cSAndroid Build Coastguard Worker
1032*4d7e907cSAndroid Build Coastguard Worker // Closing current primary client.
1033*4d7e907cSAndroid Build Coastguard Worker frameHandlerSecondary->shutdown();
1034*4d7e907cSAndroid Build Coastguard Worker
1035*4d7e907cSAndroid Build Coastguard Worker // Join a listening thread.
1036*4d7e907cSAndroid Build Coastguard Worker if (listener.joinable()) {
1037*4d7e907cSAndroid Build Coastguard Worker listener.join();
1038*4d7e907cSAndroid Build Coastguard Worker }
1039*4d7e907cSAndroid Build Coastguard Worker
1040*4d7e907cSAndroid Build Coastguard Worker // Verify change notifications.
1041*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(EvsEventType::MASTER_RELEASED, static_cast<EvsEventType>(aNotification.aType));
1042*4d7e907cSAndroid Build Coastguard Worker
1043*4d7e907cSAndroid Build Coastguard Worker // Closing streams.
1044*4d7e907cSAndroid Build Coastguard Worker frameHandlerPrimary->shutdown();
1045*4d7e907cSAndroid Build Coastguard Worker
1046*4d7e907cSAndroid Build Coastguard Worker // Explicitly release the camera
1047*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->closeCamera(pPrimaryCam).isOk());
1048*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->closeCamera(pSecondaryCam).isOk());
1049*4d7e907cSAndroid Build Coastguard Worker mActiveCameras.clear();
1050*4d7e907cSAndroid Build Coastguard Worker }
1051*4d7e907cSAndroid Build Coastguard Worker }
1052*4d7e907cSAndroid Build Coastguard Worker
1053*4d7e907cSAndroid Build Coastguard Worker /*
1054*4d7e907cSAndroid Build Coastguard Worker * MultiCameraParameter:
1055*4d7e907cSAndroid Build Coastguard Worker * Verify that primary and non-primary clients behave as expected when they try to adjust
1056*4d7e907cSAndroid Build Coastguard Worker * camera parameters.
1057*4d7e907cSAndroid Build Coastguard Worker */
TEST_P(EvsAidlTest,MultiCameraParameter)1058*4d7e907cSAndroid Build Coastguard Worker TEST_P(EvsAidlTest, MultiCameraParameter) {
1059*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Starting MultiCameraParameter test";
1060*4d7e907cSAndroid Build Coastguard Worker
1061*4d7e907cSAndroid Build Coastguard Worker if (mIsHwModule) {
1062*4d7e907cSAndroid Build Coastguard Worker // This test is not for HW module implementation.
1063*4d7e907cSAndroid Build Coastguard Worker return;
1064*4d7e907cSAndroid Build Coastguard Worker }
1065*4d7e907cSAndroid Build Coastguard Worker
1066*4d7e907cSAndroid Build Coastguard Worker // Get the camera list
1067*4d7e907cSAndroid Build Coastguard Worker loadCameraList();
1068*4d7e907cSAndroid Build Coastguard Worker
1069*4d7e907cSAndroid Build Coastguard Worker // Test each reported camera
1070*4d7e907cSAndroid Build Coastguard Worker for (auto&& cam : mCameraInfo) {
1071*4d7e907cSAndroid Build Coastguard Worker bool isLogicalCam = false;
1072*4d7e907cSAndroid Build Coastguard Worker getPhysicalCameraIds(cam.id, isLogicalCam);
1073*4d7e907cSAndroid Build Coastguard Worker if (isLogicalCam) {
1074*4d7e907cSAndroid Build Coastguard Worker // TODO(b/145465724): Support camera parameter programming on
1075*4d7e907cSAndroid Build Coastguard Worker // logical devices.
1076*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Skip a logical device " << cam.id;
1077*4d7e907cSAndroid Build Coastguard Worker continue;
1078*4d7e907cSAndroid Build Coastguard Worker }
1079*4d7e907cSAndroid Build Coastguard Worker
1080*4d7e907cSAndroid Build Coastguard Worker // Read a target resolution from the metadata
1081*4d7e907cSAndroid Build Coastguard Worker Stream targetCfg = getFirstStreamConfiguration(
1082*4d7e907cSAndroid Build Coastguard Worker reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
1083*4d7e907cSAndroid Build Coastguard Worker ASSERT_GT(targetCfg.width, 0);
1084*4d7e907cSAndroid Build Coastguard Worker ASSERT_GT(targetCfg.height, 0);
1085*4d7e907cSAndroid Build Coastguard Worker
1086*4d7e907cSAndroid Build Coastguard Worker // Create two camera clients.
1087*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<IEvsCamera> pPrimaryCam;
1088*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pPrimaryCam).isOk());
1089*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(pPrimaryCam, nullptr);
1090*4d7e907cSAndroid Build Coastguard Worker
1091*4d7e907cSAndroid Build Coastguard Worker // Store a camera handle for a clean-up
1092*4d7e907cSAndroid Build Coastguard Worker mActiveCameras.push_back(pPrimaryCam);
1093*4d7e907cSAndroid Build Coastguard Worker
1094*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<IEvsCamera> pSecondaryCam;
1095*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pSecondaryCam).isOk());
1096*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(pSecondaryCam, nullptr);
1097*4d7e907cSAndroid Build Coastguard Worker
1098*4d7e907cSAndroid Build Coastguard Worker // Store a camera handle for a clean-up
1099*4d7e907cSAndroid Build Coastguard Worker mActiveCameras.push_back(pSecondaryCam);
1100*4d7e907cSAndroid Build Coastguard Worker
1101*4d7e907cSAndroid Build Coastguard Worker // Get the parameter list
1102*4d7e907cSAndroid Build Coastguard Worker std::vector<CameraParam> camPrimaryCmds, camSecondaryCmds;
1103*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pPrimaryCam->getParameterList(&camPrimaryCmds).isOk());
1104*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pSecondaryCam->getParameterList(&camSecondaryCmds).isOk());
1105*4d7e907cSAndroid Build Coastguard Worker if (camPrimaryCmds.size() < 1 || camSecondaryCmds.size() < 1) {
1106*4d7e907cSAndroid Build Coastguard Worker // Skip a camera device if it does not support any parameter.
1107*4d7e907cSAndroid Build Coastguard Worker continue;
1108*4d7e907cSAndroid Build Coastguard Worker }
1109*4d7e907cSAndroid Build Coastguard Worker
1110*4d7e907cSAndroid Build Coastguard Worker // Set up per-client frame receiver objects which will fire up its own thread
1111*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<FrameHandler> frameHandlerPrimary = ndk::SharedRefBase::make<FrameHandler>(
1112*4d7e907cSAndroid Build Coastguard Worker pPrimaryCam, cam, nullptr, FrameHandler::eAutoReturn);
1113*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<FrameHandler> frameHandlerSecondary =
1114*4d7e907cSAndroid Build Coastguard Worker ndk::SharedRefBase::make<FrameHandler>(pSecondaryCam, cam, nullptr,
1115*4d7e907cSAndroid Build Coastguard Worker FrameHandler::eAutoReturn);
1116*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(frameHandlerPrimary, nullptr);
1117*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(frameHandlerSecondary, nullptr);
1118*4d7e907cSAndroid Build Coastguard Worker
1119*4d7e907cSAndroid Build Coastguard Worker // Set one client as the primary client.
1120*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pPrimaryCam->setPrimaryClient().isOk());
1121*4d7e907cSAndroid Build Coastguard Worker
1122*4d7e907cSAndroid Build Coastguard Worker // Try to set another client as the primary client.
1123*4d7e907cSAndroid Build Coastguard Worker ASSERT_FALSE(pSecondaryCam->setPrimaryClient().isOk());
1124*4d7e907cSAndroid Build Coastguard Worker
1125*4d7e907cSAndroid Build Coastguard Worker // Start the camera's video stream via a primary client client.
1126*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(frameHandlerPrimary->startStream());
1127*4d7e907cSAndroid Build Coastguard Worker
1128*4d7e907cSAndroid Build Coastguard Worker // Ensure the stream starts
1129*4d7e907cSAndroid Build Coastguard Worker frameHandlerPrimary->waitForFrameCount(1);
1130*4d7e907cSAndroid Build Coastguard Worker
1131*4d7e907cSAndroid Build Coastguard Worker // Start the camera's video stream via another client
1132*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(frameHandlerSecondary->startStream());
1133*4d7e907cSAndroid Build Coastguard Worker
1134*4d7e907cSAndroid Build Coastguard Worker // Ensure the stream starts
1135*4d7e907cSAndroid Build Coastguard Worker frameHandlerSecondary->waitForFrameCount(1);
1136*4d7e907cSAndroid Build Coastguard Worker
1137*4d7e907cSAndroid Build Coastguard Worker int32_t val0 = 0;
1138*4d7e907cSAndroid Build Coastguard Worker std::vector<int32_t> values;
1139*4d7e907cSAndroid Build Coastguard Worker EvsEventDesc aNotification0 = {};
1140*4d7e907cSAndroid Build Coastguard Worker EvsEventDesc aNotification1 = {};
1141*4d7e907cSAndroid Build Coastguard Worker for (auto& cmd : camPrimaryCmds) {
1142*4d7e907cSAndroid Build Coastguard Worker // Get a valid parameter value range
1143*4d7e907cSAndroid Build Coastguard Worker ParameterRange range;
1144*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pPrimaryCam->getIntParameterRange(cmd, &range).isOk());
1145*4d7e907cSAndroid Build Coastguard Worker if (cmd == CameraParam::ABSOLUTE_FOCUS) {
1146*4d7e907cSAndroid Build Coastguard Worker // Try to turn off auto-focus
1147*4d7e907cSAndroid Build Coastguard Worker values.clear();
1148*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(
1149*4d7e907cSAndroid Build Coastguard Worker pPrimaryCam->setIntParameter(CameraParam::AUTO_FOCUS, 0, &values).isOk());
1150*4d7e907cSAndroid Build Coastguard Worker for (auto&& v : values) {
1151*4d7e907cSAndroid Build Coastguard Worker EXPECT_EQ(v, 0);
1152*4d7e907cSAndroid Build Coastguard Worker }
1153*4d7e907cSAndroid Build Coastguard Worker }
1154*4d7e907cSAndroid Build Coastguard Worker
1155*4d7e907cSAndroid Build Coastguard Worker // Calculate a parameter value to program.
1156*4d7e907cSAndroid Build Coastguard Worker val0 = range.min + (std::rand() % (range.max - range.min));
1157*4d7e907cSAndroid Build Coastguard Worker val0 = val0 - (val0 % range.step);
1158*4d7e907cSAndroid Build Coastguard Worker
1159*4d7e907cSAndroid Build Coastguard Worker // Prepare and start event listeners.
1160*4d7e907cSAndroid Build Coastguard Worker bool listening0 = false;
1161*4d7e907cSAndroid Build Coastguard Worker bool listening1 = false;
1162*4d7e907cSAndroid Build Coastguard Worker std::condition_variable eventCond;
1163*4d7e907cSAndroid Build Coastguard Worker std::thread listener0 = std::thread([cmd, val0, &aNotification0, &frameHandlerPrimary,
1164*4d7e907cSAndroid Build Coastguard Worker &listening0, &listening1, &eventCond]() {
1165*4d7e907cSAndroid Build Coastguard Worker listening0 = true;
1166*4d7e907cSAndroid Build Coastguard Worker if (listening1) {
1167*4d7e907cSAndroid Build Coastguard Worker eventCond.notify_all();
1168*4d7e907cSAndroid Build Coastguard Worker }
1169*4d7e907cSAndroid Build Coastguard Worker
1170*4d7e907cSAndroid Build Coastguard Worker EvsEventDesc aTargetEvent;
1171*4d7e907cSAndroid Build Coastguard Worker aTargetEvent.aType = EvsEventType::PARAMETER_CHANGED;
1172*4d7e907cSAndroid Build Coastguard Worker aTargetEvent.payload.push_back(static_cast<int32_t>(cmd));
1173*4d7e907cSAndroid Build Coastguard Worker aTargetEvent.payload.push_back(val0);
1174*4d7e907cSAndroid Build Coastguard Worker if (!frameHandlerPrimary->waitForEvent(aTargetEvent, aNotification0)) {
1175*4d7e907cSAndroid Build Coastguard Worker LOG(WARNING) << "A timer is expired before a target event is fired.";
1176*4d7e907cSAndroid Build Coastguard Worker }
1177*4d7e907cSAndroid Build Coastguard Worker });
1178*4d7e907cSAndroid Build Coastguard Worker std::thread listener1 = std::thread([cmd, val0, &aNotification1, &frameHandlerSecondary,
1179*4d7e907cSAndroid Build Coastguard Worker &listening0, &listening1, &eventCond]() {
1180*4d7e907cSAndroid Build Coastguard Worker listening1 = true;
1181*4d7e907cSAndroid Build Coastguard Worker if (listening0) {
1182*4d7e907cSAndroid Build Coastguard Worker eventCond.notify_all();
1183*4d7e907cSAndroid Build Coastguard Worker }
1184*4d7e907cSAndroid Build Coastguard Worker
1185*4d7e907cSAndroid Build Coastguard Worker EvsEventDesc aTargetEvent;
1186*4d7e907cSAndroid Build Coastguard Worker aTargetEvent.aType = EvsEventType::PARAMETER_CHANGED;
1187*4d7e907cSAndroid Build Coastguard Worker aTargetEvent.payload.push_back(static_cast<int32_t>(cmd));
1188*4d7e907cSAndroid Build Coastguard Worker aTargetEvent.payload.push_back(val0);
1189*4d7e907cSAndroid Build Coastguard Worker if (!frameHandlerSecondary->waitForEvent(aTargetEvent, aNotification1)) {
1190*4d7e907cSAndroid Build Coastguard Worker LOG(WARNING) << "A timer is expired before a target event is fired.";
1191*4d7e907cSAndroid Build Coastguard Worker }
1192*4d7e907cSAndroid Build Coastguard Worker });
1193*4d7e907cSAndroid Build Coastguard Worker
1194*4d7e907cSAndroid Build Coastguard Worker // Wait until a listening thread starts.
1195*4d7e907cSAndroid Build Coastguard Worker std::mutex eventLock;
1196*4d7e907cSAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(eventLock);
1197*4d7e907cSAndroid Build Coastguard Worker auto timer = std::chrono::system_clock::now();
1198*4d7e907cSAndroid Build Coastguard Worker while (!listening0 || !listening1) {
1199*4d7e907cSAndroid Build Coastguard Worker eventCond.wait_until(lock, timer + 1s);
1200*4d7e907cSAndroid Build Coastguard Worker }
1201*4d7e907cSAndroid Build Coastguard Worker lock.unlock();
1202*4d7e907cSAndroid Build Coastguard Worker
1203*4d7e907cSAndroid Build Coastguard Worker // Try to program a parameter
1204*4d7e907cSAndroid Build Coastguard Worker values.clear();
1205*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pPrimaryCam->setIntParameter(cmd, val0, &values).isOk());
1206*4d7e907cSAndroid Build Coastguard Worker for (auto&& v : values) {
1207*4d7e907cSAndroid Build Coastguard Worker EXPECT_EQ(val0, v) << "Values are not matched.";
1208*4d7e907cSAndroid Build Coastguard Worker }
1209*4d7e907cSAndroid Build Coastguard Worker
1210*4d7e907cSAndroid Build Coastguard Worker // Join a listening thread.
1211*4d7e907cSAndroid Build Coastguard Worker if (listener0.joinable()) {
1212*4d7e907cSAndroid Build Coastguard Worker listener0.join();
1213*4d7e907cSAndroid Build Coastguard Worker }
1214*4d7e907cSAndroid Build Coastguard Worker if (listener1.joinable()) {
1215*4d7e907cSAndroid Build Coastguard Worker listener1.join();
1216*4d7e907cSAndroid Build Coastguard Worker }
1217*4d7e907cSAndroid Build Coastguard Worker
1218*4d7e907cSAndroid Build Coastguard Worker // Verify a change notification
1219*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(EvsEventType::PARAMETER_CHANGED,
1220*4d7e907cSAndroid Build Coastguard Worker static_cast<EvsEventType>(aNotification0.aType));
1221*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(EvsEventType::PARAMETER_CHANGED,
1222*4d7e907cSAndroid Build Coastguard Worker static_cast<EvsEventType>(aNotification1.aType));
1223*4d7e907cSAndroid Build Coastguard Worker ASSERT_GE(aNotification0.payload.size(), 2);
1224*4d7e907cSAndroid Build Coastguard Worker ASSERT_GE(aNotification1.payload.size(), 2);
1225*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(cmd, static_cast<CameraParam>(aNotification0.payload[0]));
1226*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(cmd, static_cast<CameraParam>(aNotification1.payload[0]));
1227*4d7e907cSAndroid Build Coastguard Worker for (auto&& v : values) {
1228*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(v, aNotification0.payload[1]);
1229*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(v, aNotification1.payload[1]);
1230*4d7e907cSAndroid Build Coastguard Worker }
1231*4d7e907cSAndroid Build Coastguard Worker
1232*4d7e907cSAndroid Build Coastguard Worker // Clients expects to receive a parameter change notification
1233*4d7e907cSAndroid Build Coastguard Worker // whenever a primary client client adjusts it.
1234*4d7e907cSAndroid Build Coastguard Worker values.clear();
1235*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pPrimaryCam->getIntParameter(cmd, &values).isOk());
1236*4d7e907cSAndroid Build Coastguard Worker for (auto&& v : values) {
1237*4d7e907cSAndroid Build Coastguard Worker EXPECT_EQ(val0, v) << "Values are not matched.";
1238*4d7e907cSAndroid Build Coastguard Worker }
1239*4d7e907cSAndroid Build Coastguard Worker }
1240*4d7e907cSAndroid Build Coastguard Worker
1241*4d7e907cSAndroid Build Coastguard Worker // Try to adjust a parameter via non-primary client
1242*4d7e907cSAndroid Build Coastguard Worker values.clear();
1243*4d7e907cSAndroid Build Coastguard Worker ASSERT_FALSE(pSecondaryCam->setIntParameter(camSecondaryCmds[0], val0, &values).isOk());
1244*4d7e907cSAndroid Build Coastguard Worker
1245*4d7e907cSAndroid Build Coastguard Worker // Non-primary client attempts to be a primary client
1246*4d7e907cSAndroid Build Coastguard Worker ASSERT_FALSE(pSecondaryCam->setPrimaryClient().isOk());
1247*4d7e907cSAndroid Build Coastguard Worker
1248*4d7e907cSAndroid Build Coastguard Worker // Primary client retires from a primary client role
1249*4d7e907cSAndroid Build Coastguard Worker bool listening = false;
1250*4d7e907cSAndroid Build Coastguard Worker std::condition_variable eventCond;
1251*4d7e907cSAndroid Build Coastguard Worker std::thread listener =
1252*4d7e907cSAndroid Build Coastguard Worker std::thread([&aNotification0, &frameHandlerSecondary, &listening, &eventCond]() {
1253*4d7e907cSAndroid Build Coastguard Worker listening = true;
1254*4d7e907cSAndroid Build Coastguard Worker eventCond.notify_all();
1255*4d7e907cSAndroid Build Coastguard Worker
1256*4d7e907cSAndroid Build Coastguard Worker EvsEventDesc aTargetEvent;
1257*4d7e907cSAndroid Build Coastguard Worker aTargetEvent.aType = EvsEventType::MASTER_RELEASED;
1258*4d7e907cSAndroid Build Coastguard Worker if (!frameHandlerSecondary->waitForEvent(aTargetEvent, aNotification0, true)) {
1259*4d7e907cSAndroid Build Coastguard Worker LOG(WARNING) << "A timer is expired before a target event is fired.";
1260*4d7e907cSAndroid Build Coastguard Worker }
1261*4d7e907cSAndroid Build Coastguard Worker });
1262*4d7e907cSAndroid Build Coastguard Worker
1263*4d7e907cSAndroid Build Coastguard Worker std::mutex eventLock;
1264*4d7e907cSAndroid Build Coastguard Worker auto timer = std::chrono::system_clock::now();
1265*4d7e907cSAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(eventLock);
1266*4d7e907cSAndroid Build Coastguard Worker while (!listening) {
1267*4d7e907cSAndroid Build Coastguard Worker eventCond.wait_until(lock, timer + 1s);
1268*4d7e907cSAndroid Build Coastguard Worker }
1269*4d7e907cSAndroid Build Coastguard Worker lock.unlock();
1270*4d7e907cSAndroid Build Coastguard Worker
1271*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pPrimaryCam->unsetPrimaryClient().isOk());
1272*4d7e907cSAndroid Build Coastguard Worker
1273*4d7e907cSAndroid Build Coastguard Worker if (listener.joinable()) {
1274*4d7e907cSAndroid Build Coastguard Worker listener.join();
1275*4d7e907cSAndroid Build Coastguard Worker }
1276*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(EvsEventType::MASTER_RELEASED, static_cast<EvsEventType>(aNotification0.aType));
1277*4d7e907cSAndroid Build Coastguard Worker
1278*4d7e907cSAndroid Build Coastguard Worker // Try to adjust a parameter after being retired
1279*4d7e907cSAndroid Build Coastguard Worker values.clear();
1280*4d7e907cSAndroid Build Coastguard Worker ASSERT_FALSE(pPrimaryCam->setIntParameter(camPrimaryCmds[0], val0, &values).isOk());
1281*4d7e907cSAndroid Build Coastguard Worker
1282*4d7e907cSAndroid Build Coastguard Worker // Non-primary client becomes a primary client
1283*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pSecondaryCam->setPrimaryClient().isOk());
1284*4d7e907cSAndroid Build Coastguard Worker
1285*4d7e907cSAndroid Build Coastguard Worker // Try to adjust a parameter via new primary client
1286*4d7e907cSAndroid Build Coastguard Worker for (auto& cmd : camSecondaryCmds) {
1287*4d7e907cSAndroid Build Coastguard Worker // Get a valid parameter value range
1288*4d7e907cSAndroid Build Coastguard Worker ParameterRange range;
1289*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pSecondaryCam->getIntParameterRange(cmd, &range).isOk());
1290*4d7e907cSAndroid Build Coastguard Worker
1291*4d7e907cSAndroid Build Coastguard Worker values.clear();
1292*4d7e907cSAndroid Build Coastguard Worker if (cmd == CameraParam::ABSOLUTE_FOCUS) {
1293*4d7e907cSAndroid Build Coastguard Worker // Try to turn off auto-focus
1294*4d7e907cSAndroid Build Coastguard Worker values.clear();
1295*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(
1296*4d7e907cSAndroid Build Coastguard Worker pSecondaryCam->setIntParameter(CameraParam::AUTO_FOCUS, 0, &values).isOk());
1297*4d7e907cSAndroid Build Coastguard Worker for (auto&& v : values) {
1298*4d7e907cSAndroid Build Coastguard Worker EXPECT_EQ(v, 0);
1299*4d7e907cSAndroid Build Coastguard Worker }
1300*4d7e907cSAndroid Build Coastguard Worker }
1301*4d7e907cSAndroid Build Coastguard Worker
1302*4d7e907cSAndroid Build Coastguard Worker // Calculate a parameter value to program. This is being rounding down.
1303*4d7e907cSAndroid Build Coastguard Worker val0 = range.min + (std::rand() % (range.max - range.min));
1304*4d7e907cSAndroid Build Coastguard Worker val0 = val0 - (val0 % range.step);
1305*4d7e907cSAndroid Build Coastguard Worker
1306*4d7e907cSAndroid Build Coastguard Worker // Prepare and start event listeners.
1307*4d7e907cSAndroid Build Coastguard Worker bool listening0 = false;
1308*4d7e907cSAndroid Build Coastguard Worker bool listening1 = false;
1309*4d7e907cSAndroid Build Coastguard Worker std::condition_variable eventCond;
1310*4d7e907cSAndroid Build Coastguard Worker std::thread listener0 = std::thread([&]() {
1311*4d7e907cSAndroid Build Coastguard Worker listening0 = true;
1312*4d7e907cSAndroid Build Coastguard Worker if (listening1) {
1313*4d7e907cSAndroid Build Coastguard Worker eventCond.notify_all();
1314*4d7e907cSAndroid Build Coastguard Worker }
1315*4d7e907cSAndroid Build Coastguard Worker
1316*4d7e907cSAndroid Build Coastguard Worker EvsEventDesc aTargetEvent;
1317*4d7e907cSAndroid Build Coastguard Worker aTargetEvent.aType = EvsEventType::PARAMETER_CHANGED;
1318*4d7e907cSAndroid Build Coastguard Worker aTargetEvent.payload.push_back(static_cast<int32_t>(cmd));
1319*4d7e907cSAndroid Build Coastguard Worker aTargetEvent.payload.push_back(val0);
1320*4d7e907cSAndroid Build Coastguard Worker if (!frameHandlerPrimary->waitForEvent(aTargetEvent, aNotification0)) {
1321*4d7e907cSAndroid Build Coastguard Worker LOG(WARNING) << "A timer is expired before a target event is fired.";
1322*4d7e907cSAndroid Build Coastguard Worker }
1323*4d7e907cSAndroid Build Coastguard Worker });
1324*4d7e907cSAndroid Build Coastguard Worker std::thread listener1 = std::thread([&]() {
1325*4d7e907cSAndroid Build Coastguard Worker listening1 = true;
1326*4d7e907cSAndroid Build Coastguard Worker if (listening0) {
1327*4d7e907cSAndroid Build Coastguard Worker eventCond.notify_all();
1328*4d7e907cSAndroid Build Coastguard Worker }
1329*4d7e907cSAndroid Build Coastguard Worker
1330*4d7e907cSAndroid Build Coastguard Worker EvsEventDesc aTargetEvent;
1331*4d7e907cSAndroid Build Coastguard Worker aTargetEvent.aType = EvsEventType::PARAMETER_CHANGED;
1332*4d7e907cSAndroid Build Coastguard Worker aTargetEvent.payload.push_back(static_cast<int32_t>(cmd));
1333*4d7e907cSAndroid Build Coastguard Worker aTargetEvent.payload.push_back(val0);
1334*4d7e907cSAndroid Build Coastguard Worker if (!frameHandlerSecondary->waitForEvent(aTargetEvent, aNotification1)) {
1335*4d7e907cSAndroid Build Coastguard Worker LOG(WARNING) << "A timer is expired before a target event is fired.";
1336*4d7e907cSAndroid Build Coastguard Worker }
1337*4d7e907cSAndroid Build Coastguard Worker });
1338*4d7e907cSAndroid Build Coastguard Worker
1339*4d7e907cSAndroid Build Coastguard Worker // Wait until a listening thread starts.
1340*4d7e907cSAndroid Build Coastguard Worker std::mutex eventLock;
1341*4d7e907cSAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(eventLock);
1342*4d7e907cSAndroid Build Coastguard Worker auto timer = std::chrono::system_clock::now();
1343*4d7e907cSAndroid Build Coastguard Worker while (!listening0 || !listening1) {
1344*4d7e907cSAndroid Build Coastguard Worker eventCond.wait_until(lock, timer + 1s);
1345*4d7e907cSAndroid Build Coastguard Worker }
1346*4d7e907cSAndroid Build Coastguard Worker lock.unlock();
1347*4d7e907cSAndroid Build Coastguard Worker
1348*4d7e907cSAndroid Build Coastguard Worker // Try to program a parameter
1349*4d7e907cSAndroid Build Coastguard Worker values.clear();
1350*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pSecondaryCam->setIntParameter(cmd, val0, &values).isOk());
1351*4d7e907cSAndroid Build Coastguard Worker
1352*4d7e907cSAndroid Build Coastguard Worker // Clients expects to receive a parameter change notification
1353*4d7e907cSAndroid Build Coastguard Worker // whenever a primary client client adjusts it.
1354*4d7e907cSAndroid Build Coastguard Worker values.clear();
1355*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pSecondaryCam->getIntParameter(cmd, &values).isOk());
1356*4d7e907cSAndroid Build Coastguard Worker for (auto&& v : values) {
1357*4d7e907cSAndroid Build Coastguard Worker EXPECT_EQ(val0, v) << "Values are not matched.";
1358*4d7e907cSAndroid Build Coastguard Worker }
1359*4d7e907cSAndroid Build Coastguard Worker
1360*4d7e907cSAndroid Build Coastguard Worker // Join a listening thread.
1361*4d7e907cSAndroid Build Coastguard Worker if (listener0.joinable()) {
1362*4d7e907cSAndroid Build Coastguard Worker listener0.join();
1363*4d7e907cSAndroid Build Coastguard Worker }
1364*4d7e907cSAndroid Build Coastguard Worker if (listener1.joinable()) {
1365*4d7e907cSAndroid Build Coastguard Worker listener1.join();
1366*4d7e907cSAndroid Build Coastguard Worker }
1367*4d7e907cSAndroid Build Coastguard Worker
1368*4d7e907cSAndroid Build Coastguard Worker // Verify a change notification
1369*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(EvsEventType::PARAMETER_CHANGED,
1370*4d7e907cSAndroid Build Coastguard Worker static_cast<EvsEventType>(aNotification0.aType));
1371*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(EvsEventType::PARAMETER_CHANGED,
1372*4d7e907cSAndroid Build Coastguard Worker static_cast<EvsEventType>(aNotification1.aType));
1373*4d7e907cSAndroid Build Coastguard Worker ASSERT_GE(aNotification0.payload.size(), 2);
1374*4d7e907cSAndroid Build Coastguard Worker ASSERT_GE(aNotification1.payload.size(), 2);
1375*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(cmd, static_cast<CameraParam>(aNotification0.payload[0]));
1376*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(cmd, static_cast<CameraParam>(aNotification1.payload[0]));
1377*4d7e907cSAndroid Build Coastguard Worker for (auto&& v : values) {
1378*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(v, aNotification0.payload[1]);
1379*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(v, aNotification1.payload[1]);
1380*4d7e907cSAndroid Build Coastguard Worker }
1381*4d7e907cSAndroid Build Coastguard Worker }
1382*4d7e907cSAndroid Build Coastguard Worker
1383*4d7e907cSAndroid Build Coastguard Worker // New primary client retires from the role
1384*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pSecondaryCam->unsetPrimaryClient().isOk());
1385*4d7e907cSAndroid Build Coastguard Worker
1386*4d7e907cSAndroid Build Coastguard Worker // Shutdown
1387*4d7e907cSAndroid Build Coastguard Worker frameHandlerPrimary->shutdown();
1388*4d7e907cSAndroid Build Coastguard Worker frameHandlerSecondary->shutdown();
1389*4d7e907cSAndroid Build Coastguard Worker
1390*4d7e907cSAndroid Build Coastguard Worker // Explicitly release the camera
1391*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->closeCamera(pPrimaryCam).isOk());
1392*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->closeCamera(pSecondaryCam).isOk());
1393*4d7e907cSAndroid Build Coastguard Worker mActiveCameras.clear();
1394*4d7e907cSAndroid Build Coastguard Worker }
1395*4d7e907cSAndroid Build Coastguard Worker }
1396*4d7e907cSAndroid Build Coastguard Worker
1397*4d7e907cSAndroid Build Coastguard Worker /*
1398*4d7e907cSAndroid Build Coastguard Worker * HighPriorityCameraClient:
1399*4d7e907cSAndroid Build Coastguard Worker * EVS client, which owns the display, is priortized and therefore can take over
1400*4d7e907cSAndroid Build Coastguard Worker * a primary client role from other EVS clients without the display.
1401*4d7e907cSAndroid Build Coastguard Worker */
TEST_P(EvsAidlTest,HighPriorityCameraClient)1402*4d7e907cSAndroid Build Coastguard Worker TEST_P(EvsAidlTest, HighPriorityCameraClient) {
1403*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Starting HighPriorityCameraClient test";
1404*4d7e907cSAndroid Build Coastguard Worker
1405*4d7e907cSAndroid Build Coastguard Worker if (mIsHwModule) {
1406*4d7e907cSAndroid Build Coastguard Worker // This test is not for HW module implementation.
1407*4d7e907cSAndroid Build Coastguard Worker return;
1408*4d7e907cSAndroid Build Coastguard Worker }
1409*4d7e907cSAndroid Build Coastguard Worker
1410*4d7e907cSAndroid Build Coastguard Worker // Get the camera list
1411*4d7e907cSAndroid Build Coastguard Worker loadCameraList();
1412*4d7e907cSAndroid Build Coastguard Worker
1413*4d7e907cSAndroid Build Coastguard Worker // Test each reported camera
1414*4d7e907cSAndroid Build Coastguard Worker for (auto&& cam : mCameraInfo) {
1415*4d7e907cSAndroid Build Coastguard Worker bool isLogicalCam = false;
1416*4d7e907cSAndroid Build Coastguard Worker if (getPhysicalCameraIds(cam.id, isLogicalCam); isLogicalCam) {
1417*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Skip a logical device, " << cam.id;
1418*4d7e907cSAndroid Build Coastguard Worker continue;
1419*4d7e907cSAndroid Build Coastguard Worker }
1420*4d7e907cSAndroid Build Coastguard Worker
1421*4d7e907cSAndroid Build Coastguard Worker // Request available display IDs
1422*4d7e907cSAndroid Build Coastguard Worker uint8_t targetDisplayId = 0;
1423*4d7e907cSAndroid Build Coastguard Worker std::vector<uint8_t> displayIds;
1424*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->getDisplayIdList(&displayIds).isOk());
1425*4d7e907cSAndroid Build Coastguard Worker EXPECT_GT(displayIds.size(), 0);
1426*4d7e907cSAndroid Build Coastguard Worker targetDisplayId = displayIds[0];
1427*4d7e907cSAndroid Build Coastguard Worker
1428*4d7e907cSAndroid Build Coastguard Worker // Request exclusive access to the EVS display
1429*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<IEvsDisplay> pDisplay;
1430*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->openDisplay(targetDisplayId, &pDisplay).isOk());
1431*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(pDisplay, nullptr);
1432*4d7e907cSAndroid Build Coastguard Worker
1433*4d7e907cSAndroid Build Coastguard Worker // Read a target resolution from the metadata
1434*4d7e907cSAndroid Build Coastguard Worker Stream targetCfg = getFirstStreamConfiguration(
1435*4d7e907cSAndroid Build Coastguard Worker reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
1436*4d7e907cSAndroid Build Coastguard Worker ASSERT_GT(targetCfg.width, 0);
1437*4d7e907cSAndroid Build Coastguard Worker ASSERT_GT(targetCfg.height, 0);
1438*4d7e907cSAndroid Build Coastguard Worker
1439*4d7e907cSAndroid Build Coastguard Worker // Create two clients
1440*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<IEvsCamera> pCam0;
1441*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam0).isOk());
1442*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(pCam0, nullptr);
1443*4d7e907cSAndroid Build Coastguard Worker
1444*4d7e907cSAndroid Build Coastguard Worker // Store a camera handle for a clean-up
1445*4d7e907cSAndroid Build Coastguard Worker mActiveCameras.push_back(pCam0);
1446*4d7e907cSAndroid Build Coastguard Worker
1447*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<IEvsCamera> pCam1;
1448*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam1).isOk());
1449*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(pCam1, nullptr);
1450*4d7e907cSAndroid Build Coastguard Worker
1451*4d7e907cSAndroid Build Coastguard Worker // Store a camera handle for a clean-up
1452*4d7e907cSAndroid Build Coastguard Worker mActiveCameras.push_back(pCam1);
1453*4d7e907cSAndroid Build Coastguard Worker
1454*4d7e907cSAndroid Build Coastguard Worker // Get the parameter list; this test will use the first command in both
1455*4d7e907cSAndroid Build Coastguard Worker // lists.
1456*4d7e907cSAndroid Build Coastguard Worker std::vector<CameraParam> cam0Cmds, cam1Cmds;
1457*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pCam0->getParameterList(&cam0Cmds).isOk());
1458*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pCam1->getParameterList(&cam1Cmds).isOk());
1459*4d7e907cSAndroid Build Coastguard Worker if (cam0Cmds.size() < 1 || cam1Cmds.size() < 1) {
1460*4d7e907cSAndroid Build Coastguard Worker // Cannot execute this test.
1461*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->closeDisplay(pDisplay).isOk());
1462*4d7e907cSAndroid Build Coastguard Worker continue;
1463*4d7e907cSAndroid Build Coastguard Worker }
1464*4d7e907cSAndroid Build Coastguard Worker
1465*4d7e907cSAndroid Build Coastguard Worker // Set up a frame receiver object which will fire up its own thread.
1466*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<FrameHandler> frameHandler0 = ndk::SharedRefBase::make<FrameHandler>(
1467*4d7e907cSAndroid Build Coastguard Worker pCam0, cam, nullptr, FrameHandler::eAutoReturn);
1468*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<FrameHandler> frameHandler1 = ndk::SharedRefBase::make<FrameHandler>(
1469*4d7e907cSAndroid Build Coastguard Worker pCam1, cam, nullptr, FrameHandler::eAutoReturn);
1470*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(frameHandler0, nullptr);
1471*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(frameHandler1, nullptr);
1472*4d7e907cSAndroid Build Coastguard Worker
1473*4d7e907cSAndroid Build Coastguard Worker // Activate the display
1474*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pDisplay->setDisplayState(DisplayState::VISIBLE_ON_NEXT_FRAME).isOk());
1475*4d7e907cSAndroid Build Coastguard Worker
1476*4d7e907cSAndroid Build Coastguard Worker // Start the camera's video stream
1477*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(frameHandler0->startStream());
1478*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(frameHandler1->startStream());
1479*4d7e907cSAndroid Build Coastguard Worker
1480*4d7e907cSAndroid Build Coastguard Worker // Ensure the stream starts
1481*4d7e907cSAndroid Build Coastguard Worker frameHandler0->waitForFrameCount(1);
1482*4d7e907cSAndroid Build Coastguard Worker frameHandler1->waitForFrameCount(1);
1483*4d7e907cSAndroid Build Coastguard Worker
1484*4d7e907cSAndroid Build Coastguard Worker // Client 1 becomes a primary client and programs a parameter.
1485*4d7e907cSAndroid Build Coastguard Worker
1486*4d7e907cSAndroid Build Coastguard Worker // Get a valid parameter value range
1487*4d7e907cSAndroid Build Coastguard Worker ParameterRange range;
1488*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pCam1->getIntParameterRange(cam1Cmds[0], &range).isOk());
1489*4d7e907cSAndroid Build Coastguard Worker
1490*4d7e907cSAndroid Build Coastguard Worker // Client1 becomes a primary client
1491*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pCam1->setPrimaryClient().isOk());
1492*4d7e907cSAndroid Build Coastguard Worker
1493*4d7e907cSAndroid Build Coastguard Worker std::vector<int32_t> values;
1494*4d7e907cSAndroid Build Coastguard Worker EvsEventDesc aTargetEvent = {};
1495*4d7e907cSAndroid Build Coastguard Worker EvsEventDesc aNotification = {};
1496*4d7e907cSAndroid Build Coastguard Worker bool listening = false;
1497*4d7e907cSAndroid Build Coastguard Worker std::mutex eventLock;
1498*4d7e907cSAndroid Build Coastguard Worker std::condition_variable eventCond;
1499*4d7e907cSAndroid Build Coastguard Worker if (cam1Cmds[0] == CameraParam::ABSOLUTE_FOCUS) {
1500*4d7e907cSAndroid Build Coastguard Worker std::thread listener =
1501*4d7e907cSAndroid Build Coastguard Worker std::thread([&frameHandler0, &aNotification, &listening, &eventCond] {
1502*4d7e907cSAndroid Build Coastguard Worker listening = true;
1503*4d7e907cSAndroid Build Coastguard Worker eventCond.notify_all();
1504*4d7e907cSAndroid Build Coastguard Worker
1505*4d7e907cSAndroid Build Coastguard Worker EvsEventDesc aTargetEvent;
1506*4d7e907cSAndroid Build Coastguard Worker aTargetEvent.aType = EvsEventType::PARAMETER_CHANGED;
1507*4d7e907cSAndroid Build Coastguard Worker aTargetEvent.payload.push_back(
1508*4d7e907cSAndroid Build Coastguard Worker static_cast<int32_t>(CameraParam::AUTO_FOCUS));
1509*4d7e907cSAndroid Build Coastguard Worker aTargetEvent.payload.push_back(0);
1510*4d7e907cSAndroid Build Coastguard Worker if (!frameHandler0->waitForEvent(aTargetEvent, aNotification)) {
1511*4d7e907cSAndroid Build Coastguard Worker LOG(WARNING) << "A timer is expired before a target event is fired.";
1512*4d7e907cSAndroid Build Coastguard Worker }
1513*4d7e907cSAndroid Build Coastguard Worker });
1514*4d7e907cSAndroid Build Coastguard Worker
1515*4d7e907cSAndroid Build Coastguard Worker // Wait until a lister starts.
1516*4d7e907cSAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(eventLock);
1517*4d7e907cSAndroid Build Coastguard Worker auto timer = std::chrono::system_clock::now();
1518*4d7e907cSAndroid Build Coastguard Worker while (!listening) {
1519*4d7e907cSAndroid Build Coastguard Worker eventCond.wait_until(lock, timer + 1s);
1520*4d7e907cSAndroid Build Coastguard Worker }
1521*4d7e907cSAndroid Build Coastguard Worker lock.unlock();
1522*4d7e907cSAndroid Build Coastguard Worker
1523*4d7e907cSAndroid Build Coastguard Worker // Try to turn off auto-focus
1524*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pCam1->setIntParameter(CameraParam::AUTO_FOCUS, 0, &values).isOk());
1525*4d7e907cSAndroid Build Coastguard Worker for (auto&& v : values) {
1526*4d7e907cSAndroid Build Coastguard Worker EXPECT_EQ(v, 0);
1527*4d7e907cSAndroid Build Coastguard Worker }
1528*4d7e907cSAndroid Build Coastguard Worker
1529*4d7e907cSAndroid Build Coastguard Worker // Join a listener
1530*4d7e907cSAndroid Build Coastguard Worker if (listener.joinable()) {
1531*4d7e907cSAndroid Build Coastguard Worker listener.join();
1532*4d7e907cSAndroid Build Coastguard Worker }
1533*4d7e907cSAndroid Build Coastguard Worker
1534*4d7e907cSAndroid Build Coastguard Worker // Make sure AUTO_FOCUS is off.
1535*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(static_cast<EvsEventType>(aNotification.aType),
1536*4d7e907cSAndroid Build Coastguard Worker EvsEventType::PARAMETER_CHANGED);
1537*4d7e907cSAndroid Build Coastguard Worker }
1538*4d7e907cSAndroid Build Coastguard Worker
1539*4d7e907cSAndroid Build Coastguard Worker // Try to program a parameter with a random value [minVal, maxVal] after
1540*4d7e907cSAndroid Build Coastguard Worker // rounding it down.
1541*4d7e907cSAndroid Build Coastguard Worker int32_t val0 = range.min + (std::rand() % (range.max - range.min));
1542*4d7e907cSAndroid Build Coastguard Worker val0 = val0 - (val0 % range.step);
1543*4d7e907cSAndroid Build Coastguard Worker
1544*4d7e907cSAndroid Build Coastguard Worker std::thread listener = std::thread(
1545*4d7e907cSAndroid Build Coastguard Worker [&frameHandler1, &aNotification, &listening, &eventCond, &cam1Cmds, val0] {
1546*4d7e907cSAndroid Build Coastguard Worker listening = true;
1547*4d7e907cSAndroid Build Coastguard Worker eventCond.notify_all();
1548*4d7e907cSAndroid Build Coastguard Worker
1549*4d7e907cSAndroid Build Coastguard Worker EvsEventDesc aTargetEvent;
1550*4d7e907cSAndroid Build Coastguard Worker aTargetEvent.aType = EvsEventType::PARAMETER_CHANGED;
1551*4d7e907cSAndroid Build Coastguard Worker aTargetEvent.payload.push_back(static_cast<int32_t>(cam1Cmds[0]));
1552*4d7e907cSAndroid Build Coastguard Worker aTargetEvent.payload.push_back(val0);
1553*4d7e907cSAndroid Build Coastguard Worker if (!frameHandler1->waitForEvent(aTargetEvent, aNotification)) {
1554*4d7e907cSAndroid Build Coastguard Worker LOG(WARNING) << "A timer is expired before a target event is fired.";
1555*4d7e907cSAndroid Build Coastguard Worker }
1556*4d7e907cSAndroid Build Coastguard Worker });
1557*4d7e907cSAndroid Build Coastguard Worker
1558*4d7e907cSAndroid Build Coastguard Worker // Wait until a lister starts.
1559*4d7e907cSAndroid Build Coastguard Worker listening = false;
1560*4d7e907cSAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(eventLock);
1561*4d7e907cSAndroid Build Coastguard Worker auto timer = std::chrono::system_clock::now();
1562*4d7e907cSAndroid Build Coastguard Worker while (!listening) {
1563*4d7e907cSAndroid Build Coastguard Worker eventCond.wait_until(lock, timer + 1s);
1564*4d7e907cSAndroid Build Coastguard Worker }
1565*4d7e907cSAndroid Build Coastguard Worker lock.unlock();
1566*4d7e907cSAndroid Build Coastguard Worker
1567*4d7e907cSAndroid Build Coastguard Worker values.clear();
1568*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pCam1->setIntParameter(cam1Cmds[0], val0, &values).isOk());
1569*4d7e907cSAndroid Build Coastguard Worker for (auto&& v : values) {
1570*4d7e907cSAndroid Build Coastguard Worker EXPECT_EQ(val0, v);
1571*4d7e907cSAndroid Build Coastguard Worker }
1572*4d7e907cSAndroid Build Coastguard Worker
1573*4d7e907cSAndroid Build Coastguard Worker // Join a listener
1574*4d7e907cSAndroid Build Coastguard Worker if (listener.joinable()) {
1575*4d7e907cSAndroid Build Coastguard Worker listener.join();
1576*4d7e907cSAndroid Build Coastguard Worker }
1577*4d7e907cSAndroid Build Coastguard Worker
1578*4d7e907cSAndroid Build Coastguard Worker // Verify a change notification
1579*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(static_cast<EvsEventType>(aNotification.aType), EvsEventType::PARAMETER_CHANGED);
1580*4d7e907cSAndroid Build Coastguard Worker ASSERT_GE(aNotification.payload.size(), 2);
1581*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(static_cast<CameraParam>(aNotification.payload[0]), cam1Cmds[0]);
1582*4d7e907cSAndroid Build Coastguard Worker for (auto&& v : values) {
1583*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(v, aNotification.payload[1]);
1584*4d7e907cSAndroid Build Coastguard Worker }
1585*4d7e907cSAndroid Build Coastguard Worker
1586*4d7e907cSAndroid Build Coastguard Worker listener = std::thread([&frameHandler1, &aNotification, &listening, &eventCond] {
1587*4d7e907cSAndroid Build Coastguard Worker listening = true;
1588*4d7e907cSAndroid Build Coastguard Worker eventCond.notify_all();
1589*4d7e907cSAndroid Build Coastguard Worker
1590*4d7e907cSAndroid Build Coastguard Worker EvsEventDesc aTargetEvent;
1591*4d7e907cSAndroid Build Coastguard Worker aTargetEvent.aType = EvsEventType::MASTER_RELEASED;
1592*4d7e907cSAndroid Build Coastguard Worker if (!frameHandler1->waitForEvent(aTargetEvent, aNotification, true)) {
1593*4d7e907cSAndroid Build Coastguard Worker LOG(WARNING) << "A timer is expired before a target event is fired.";
1594*4d7e907cSAndroid Build Coastguard Worker }
1595*4d7e907cSAndroid Build Coastguard Worker });
1596*4d7e907cSAndroid Build Coastguard Worker
1597*4d7e907cSAndroid Build Coastguard Worker // Wait until a lister starts.
1598*4d7e907cSAndroid Build Coastguard Worker listening = false;
1599*4d7e907cSAndroid Build Coastguard Worker lock.lock();
1600*4d7e907cSAndroid Build Coastguard Worker timer = std::chrono::system_clock::now();
1601*4d7e907cSAndroid Build Coastguard Worker while (!listening) {
1602*4d7e907cSAndroid Build Coastguard Worker eventCond.wait_until(lock, timer + 1s);
1603*4d7e907cSAndroid Build Coastguard Worker }
1604*4d7e907cSAndroid Build Coastguard Worker lock.unlock();
1605*4d7e907cSAndroid Build Coastguard Worker
1606*4d7e907cSAndroid Build Coastguard Worker // Client 0 steals a primary client role
1607*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pCam0->forcePrimaryClient(pDisplay).isOk());
1608*4d7e907cSAndroid Build Coastguard Worker
1609*4d7e907cSAndroid Build Coastguard Worker // Join a listener
1610*4d7e907cSAndroid Build Coastguard Worker if (listener.joinable()) {
1611*4d7e907cSAndroid Build Coastguard Worker listener.join();
1612*4d7e907cSAndroid Build Coastguard Worker }
1613*4d7e907cSAndroid Build Coastguard Worker
1614*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(static_cast<EvsEventType>(aNotification.aType), EvsEventType::MASTER_RELEASED);
1615*4d7e907cSAndroid Build Coastguard Worker
1616*4d7e907cSAndroid Build Coastguard Worker // Client 0 programs a parameter
1617*4d7e907cSAndroid Build Coastguard Worker val0 = range.min + (std::rand() % (range.max - range.min));
1618*4d7e907cSAndroid Build Coastguard Worker
1619*4d7e907cSAndroid Build Coastguard Worker // Rounding down
1620*4d7e907cSAndroid Build Coastguard Worker val0 = val0 - (val0 % range.step);
1621*4d7e907cSAndroid Build Coastguard Worker
1622*4d7e907cSAndroid Build Coastguard Worker if (cam0Cmds[0] == CameraParam::ABSOLUTE_FOCUS) {
1623*4d7e907cSAndroid Build Coastguard Worker std::thread listener =
1624*4d7e907cSAndroid Build Coastguard Worker std::thread([&frameHandler1, &aNotification, &listening, &eventCond] {
1625*4d7e907cSAndroid Build Coastguard Worker listening = true;
1626*4d7e907cSAndroid Build Coastguard Worker eventCond.notify_all();
1627*4d7e907cSAndroid Build Coastguard Worker
1628*4d7e907cSAndroid Build Coastguard Worker EvsEventDesc aTargetEvent;
1629*4d7e907cSAndroid Build Coastguard Worker aTargetEvent.aType = EvsEventType::PARAMETER_CHANGED;
1630*4d7e907cSAndroid Build Coastguard Worker aTargetEvent.payload.push_back(
1631*4d7e907cSAndroid Build Coastguard Worker static_cast<int32_t>(CameraParam::AUTO_FOCUS));
1632*4d7e907cSAndroid Build Coastguard Worker aTargetEvent.payload.push_back(0);
1633*4d7e907cSAndroid Build Coastguard Worker if (!frameHandler1->waitForEvent(aTargetEvent, aNotification)) {
1634*4d7e907cSAndroid Build Coastguard Worker LOG(WARNING) << "A timer is expired before a target event is fired.";
1635*4d7e907cSAndroid Build Coastguard Worker }
1636*4d7e907cSAndroid Build Coastguard Worker });
1637*4d7e907cSAndroid Build Coastguard Worker
1638*4d7e907cSAndroid Build Coastguard Worker // Wait until a lister starts.
1639*4d7e907cSAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(eventLock);
1640*4d7e907cSAndroid Build Coastguard Worker auto timer = std::chrono::system_clock::now();
1641*4d7e907cSAndroid Build Coastguard Worker while (!listening) {
1642*4d7e907cSAndroid Build Coastguard Worker eventCond.wait_until(lock, timer + 1s);
1643*4d7e907cSAndroid Build Coastguard Worker }
1644*4d7e907cSAndroid Build Coastguard Worker lock.unlock();
1645*4d7e907cSAndroid Build Coastguard Worker
1646*4d7e907cSAndroid Build Coastguard Worker // Try to turn off auto-focus
1647*4d7e907cSAndroid Build Coastguard Worker values.clear();
1648*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pCam0->setIntParameter(CameraParam::AUTO_FOCUS, 0, &values).isOk());
1649*4d7e907cSAndroid Build Coastguard Worker for (auto&& v : values) {
1650*4d7e907cSAndroid Build Coastguard Worker EXPECT_EQ(v, 0);
1651*4d7e907cSAndroid Build Coastguard Worker }
1652*4d7e907cSAndroid Build Coastguard Worker
1653*4d7e907cSAndroid Build Coastguard Worker // Join a listener
1654*4d7e907cSAndroid Build Coastguard Worker if (listener.joinable()) {
1655*4d7e907cSAndroid Build Coastguard Worker listener.join();
1656*4d7e907cSAndroid Build Coastguard Worker }
1657*4d7e907cSAndroid Build Coastguard Worker
1658*4d7e907cSAndroid Build Coastguard Worker // Make sure AUTO_FOCUS is off.
1659*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(static_cast<EvsEventType>(aNotification.aType),
1660*4d7e907cSAndroid Build Coastguard Worker EvsEventType::PARAMETER_CHANGED);
1661*4d7e907cSAndroid Build Coastguard Worker }
1662*4d7e907cSAndroid Build Coastguard Worker
1663*4d7e907cSAndroid Build Coastguard Worker listener = std::thread(
1664*4d7e907cSAndroid Build Coastguard Worker [&frameHandler0, &aNotification, &listening, &eventCond, &cam0Cmds, val0] {
1665*4d7e907cSAndroid Build Coastguard Worker listening = true;
1666*4d7e907cSAndroid Build Coastguard Worker eventCond.notify_all();
1667*4d7e907cSAndroid Build Coastguard Worker
1668*4d7e907cSAndroid Build Coastguard Worker EvsEventDesc aTargetEvent;
1669*4d7e907cSAndroid Build Coastguard Worker aTargetEvent.aType = EvsEventType::PARAMETER_CHANGED;
1670*4d7e907cSAndroid Build Coastguard Worker aTargetEvent.payload.push_back(static_cast<int32_t>(cam0Cmds[0]));
1671*4d7e907cSAndroid Build Coastguard Worker aTargetEvent.payload.push_back(val0);
1672*4d7e907cSAndroid Build Coastguard Worker if (!frameHandler0->waitForEvent(aTargetEvent, aNotification)) {
1673*4d7e907cSAndroid Build Coastguard Worker LOG(WARNING) << "A timer is expired before a target event is fired.";
1674*4d7e907cSAndroid Build Coastguard Worker }
1675*4d7e907cSAndroid Build Coastguard Worker });
1676*4d7e907cSAndroid Build Coastguard Worker
1677*4d7e907cSAndroid Build Coastguard Worker // Wait until a lister starts.
1678*4d7e907cSAndroid Build Coastguard Worker listening = false;
1679*4d7e907cSAndroid Build Coastguard Worker timer = std::chrono::system_clock::now();
1680*4d7e907cSAndroid Build Coastguard Worker lock.lock();
1681*4d7e907cSAndroid Build Coastguard Worker while (!listening) {
1682*4d7e907cSAndroid Build Coastguard Worker eventCond.wait_until(lock, timer + 1s);
1683*4d7e907cSAndroid Build Coastguard Worker }
1684*4d7e907cSAndroid Build Coastguard Worker lock.unlock();
1685*4d7e907cSAndroid Build Coastguard Worker
1686*4d7e907cSAndroid Build Coastguard Worker values.clear();
1687*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pCam0->setIntParameter(cam0Cmds[0], val0, &values).isOk());
1688*4d7e907cSAndroid Build Coastguard Worker
1689*4d7e907cSAndroid Build Coastguard Worker // Join a listener
1690*4d7e907cSAndroid Build Coastguard Worker if (listener.joinable()) {
1691*4d7e907cSAndroid Build Coastguard Worker listener.join();
1692*4d7e907cSAndroid Build Coastguard Worker }
1693*4d7e907cSAndroid Build Coastguard Worker // Verify a change notification
1694*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(static_cast<EvsEventType>(aNotification.aType), EvsEventType::PARAMETER_CHANGED);
1695*4d7e907cSAndroid Build Coastguard Worker ASSERT_GE(aNotification.payload.size(), 2);
1696*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(static_cast<CameraParam>(aNotification.payload[0]), cam0Cmds[0]);
1697*4d7e907cSAndroid Build Coastguard Worker for (auto&& v : values) {
1698*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(v, aNotification.payload[1]);
1699*4d7e907cSAndroid Build Coastguard Worker }
1700*4d7e907cSAndroid Build Coastguard Worker
1701*4d7e907cSAndroid Build Coastguard Worker // Turn off the display (yes, before the stream stops -- it should be handled)
1702*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pDisplay->setDisplayState(DisplayState::NOT_VISIBLE).isOk());
1703*4d7e907cSAndroid Build Coastguard Worker
1704*4d7e907cSAndroid Build Coastguard Worker // Shut down the streamer
1705*4d7e907cSAndroid Build Coastguard Worker frameHandler0->shutdown();
1706*4d7e907cSAndroid Build Coastguard Worker frameHandler1->shutdown();
1707*4d7e907cSAndroid Build Coastguard Worker
1708*4d7e907cSAndroid Build Coastguard Worker // Explicitly release the camera
1709*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->closeCamera(pCam0).isOk());
1710*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->closeCamera(pCam1).isOk());
1711*4d7e907cSAndroid Build Coastguard Worker mActiveCameras.clear();
1712*4d7e907cSAndroid Build Coastguard Worker
1713*4d7e907cSAndroid Build Coastguard Worker // Explicitly release the display
1714*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->closeDisplay(pDisplay).isOk());
1715*4d7e907cSAndroid Build Coastguard Worker }
1716*4d7e907cSAndroid Build Coastguard Worker }
1717*4d7e907cSAndroid Build Coastguard Worker
1718*4d7e907cSAndroid Build Coastguard Worker /*
1719*4d7e907cSAndroid Build Coastguard Worker * CameraUseStreamConfigToDisplay:
1720*4d7e907cSAndroid Build Coastguard Worker * End to end test of data flowing from the camera to the display. Similar to
1721*4d7e907cSAndroid Build Coastguard Worker * CameraToDisplayRoundTrip test case but this case retrieves available stream
1722*4d7e907cSAndroid Build Coastguard Worker * configurations from EVS and uses one of them to start a video stream.
1723*4d7e907cSAndroid Build Coastguard Worker */
TEST_P(EvsAidlTest,CameraUseStreamConfigToDisplay)1724*4d7e907cSAndroid Build Coastguard Worker TEST_P(EvsAidlTest, CameraUseStreamConfigToDisplay) {
1725*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Starting CameraUseStreamConfigToDisplay test";
1726*4d7e907cSAndroid Build Coastguard Worker
1727*4d7e907cSAndroid Build Coastguard Worker // Get the camera list
1728*4d7e907cSAndroid Build Coastguard Worker loadCameraList();
1729*4d7e907cSAndroid Build Coastguard Worker
1730*4d7e907cSAndroid Build Coastguard Worker // Request available display IDs
1731*4d7e907cSAndroid Build Coastguard Worker uint8_t targetDisplayId = 0;
1732*4d7e907cSAndroid Build Coastguard Worker std::vector<uint8_t> displayIds;
1733*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->getDisplayIdList(&displayIds).isOk());
1734*4d7e907cSAndroid Build Coastguard Worker EXPECT_GT(displayIds.size(), 0);
1735*4d7e907cSAndroid Build Coastguard Worker targetDisplayId = displayIds[0];
1736*4d7e907cSAndroid Build Coastguard Worker
1737*4d7e907cSAndroid Build Coastguard Worker // Test each reported camera
1738*4d7e907cSAndroid Build Coastguard Worker for (auto&& cam : mCameraInfo) {
1739*4d7e907cSAndroid Build Coastguard Worker // Request exclusive access to the EVS display
1740*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<IEvsDisplay> pDisplay;
1741*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->openDisplay(targetDisplayId, &pDisplay).isOk());
1742*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(pDisplay, nullptr);
1743*4d7e907cSAndroid Build Coastguard Worker
1744*4d7e907cSAndroid Build Coastguard Worker // choose a configuration that has a frame rate faster than minReqFps.
1745*4d7e907cSAndroid Build Coastguard Worker Stream targetCfg = {};
1746*4d7e907cSAndroid Build Coastguard Worker const int32_t minReqFps = 15;
1747*4d7e907cSAndroid Build Coastguard Worker int32_t maxArea = 0;
1748*4d7e907cSAndroid Build Coastguard Worker camera_metadata_entry_t streamCfgs;
1749*4d7e907cSAndroid Build Coastguard Worker bool foundCfg = false;
1750*4d7e907cSAndroid Build Coastguard Worker if (!find_camera_metadata_entry(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()),
1751*4d7e907cSAndroid Build Coastguard Worker ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
1752*4d7e907cSAndroid Build Coastguard Worker &streamCfgs)) {
1753*4d7e907cSAndroid Build Coastguard Worker // Stream configurations are found in metadata
1754*4d7e907cSAndroid Build Coastguard Worker RawStreamConfig* ptr = reinterpret_cast<RawStreamConfig*>(streamCfgs.data.i32);
1755*4d7e907cSAndroid Build Coastguard Worker for (unsigned offset = 0; offset < streamCfgs.count; offset += kStreamCfgSz) {
1756*4d7e907cSAndroid Build Coastguard Worker if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT) {
1757*4d7e907cSAndroid Build Coastguard Worker if (ptr->width * ptr->height > maxArea && ptr->framerate >= minReqFps) {
1758*4d7e907cSAndroid Build Coastguard Worker targetCfg.width = ptr->width;
1759*4d7e907cSAndroid Build Coastguard Worker targetCfg.height = ptr->height;
1760*4d7e907cSAndroid Build Coastguard Worker targetCfg.format = static_cast<PixelFormat>(ptr->format);
1761*4d7e907cSAndroid Build Coastguard Worker
1762*4d7e907cSAndroid Build Coastguard Worker maxArea = ptr->width * ptr->height;
1763*4d7e907cSAndroid Build Coastguard Worker foundCfg = true;
1764*4d7e907cSAndroid Build Coastguard Worker }
1765*4d7e907cSAndroid Build Coastguard Worker }
1766*4d7e907cSAndroid Build Coastguard Worker ++ptr;
1767*4d7e907cSAndroid Build Coastguard Worker }
1768*4d7e907cSAndroid Build Coastguard Worker }
1769*4d7e907cSAndroid Build Coastguard Worker
1770*4d7e907cSAndroid Build Coastguard Worker if (!foundCfg) {
1771*4d7e907cSAndroid Build Coastguard Worker // Current EVS camera does not provide stream configurations in the
1772*4d7e907cSAndroid Build Coastguard Worker // metadata.
1773*4d7e907cSAndroid Build Coastguard Worker continue;
1774*4d7e907cSAndroid Build Coastguard Worker }
1775*4d7e907cSAndroid Build Coastguard Worker
1776*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<IEvsCamera> pCam;
1777*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam).isOk());
1778*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(pCam, nullptr);
1779*4d7e907cSAndroid Build Coastguard Worker
1780*4d7e907cSAndroid Build Coastguard Worker // Store a camera handle for a clean-up
1781*4d7e907cSAndroid Build Coastguard Worker mActiveCameras.push_back(pCam);
1782*4d7e907cSAndroid Build Coastguard Worker
1783*4d7e907cSAndroid Build Coastguard Worker // Set up a frame receiver object which will fire up its own thread.
1784*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<FrameHandler> frameHandler = ndk::SharedRefBase::make<FrameHandler>(
1785*4d7e907cSAndroid Build Coastguard Worker pCam, cam, pDisplay, FrameHandler::eAutoReturn);
1786*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(frameHandler, nullptr);
1787*4d7e907cSAndroid Build Coastguard Worker
1788*4d7e907cSAndroid Build Coastguard Worker // Activate the display
1789*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pDisplay->setDisplayState(DisplayState::VISIBLE_ON_NEXT_FRAME).isOk());
1790*4d7e907cSAndroid Build Coastguard Worker
1791*4d7e907cSAndroid Build Coastguard Worker // Start the camera's video stream
1792*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(frameHandler->startStream());
1793*4d7e907cSAndroid Build Coastguard Worker
1794*4d7e907cSAndroid Build Coastguard Worker // Wait a while to let the data flow
1795*4d7e907cSAndroid Build Coastguard Worker static const int kSecondsToWait = 5;
1796*4d7e907cSAndroid Build Coastguard Worker const int streamTimeMs =
1797*4d7e907cSAndroid Build Coastguard Worker kSecondsToWait * kSecondsToMilliseconds - kMaxStreamStartMilliseconds;
1798*4d7e907cSAndroid Build Coastguard Worker const unsigned minimumFramesExpected =
1799*4d7e907cSAndroid Build Coastguard Worker streamTimeMs * kMinimumFramesPerSecond / kSecondsToMilliseconds;
1800*4d7e907cSAndroid Build Coastguard Worker sleep(kSecondsToWait);
1801*4d7e907cSAndroid Build Coastguard Worker unsigned framesReceived = 0;
1802*4d7e907cSAndroid Build Coastguard Worker unsigned framesDisplayed = 0;
1803*4d7e907cSAndroid Build Coastguard Worker frameHandler->getFramesCounters(&framesReceived, &framesDisplayed);
1804*4d7e907cSAndroid Build Coastguard Worker EXPECT_EQ(framesReceived, framesDisplayed);
1805*4d7e907cSAndroid Build Coastguard Worker EXPECT_GE(framesDisplayed, minimumFramesExpected);
1806*4d7e907cSAndroid Build Coastguard Worker
1807*4d7e907cSAndroid Build Coastguard Worker // Turn off the display (yes, before the stream stops -- it should be handled)
1808*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pDisplay->setDisplayState(DisplayState::NOT_VISIBLE).isOk());
1809*4d7e907cSAndroid Build Coastguard Worker
1810*4d7e907cSAndroid Build Coastguard Worker // Shut down the streamer
1811*4d7e907cSAndroid Build Coastguard Worker frameHandler->shutdown();
1812*4d7e907cSAndroid Build Coastguard Worker
1813*4d7e907cSAndroid Build Coastguard Worker // Explicitly release the camera
1814*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->closeCamera(pCam).isOk());
1815*4d7e907cSAndroid Build Coastguard Worker mActiveCameras.clear();
1816*4d7e907cSAndroid Build Coastguard Worker
1817*4d7e907cSAndroid Build Coastguard Worker // Explicitly release the display
1818*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->closeDisplay(pDisplay).isOk());
1819*4d7e907cSAndroid Build Coastguard Worker }
1820*4d7e907cSAndroid Build Coastguard Worker }
1821*4d7e907cSAndroid Build Coastguard Worker
1822*4d7e907cSAndroid Build Coastguard Worker /*
1823*4d7e907cSAndroid Build Coastguard Worker * MultiCameraStreamUseConfig:
1824*4d7e907cSAndroid Build Coastguard Worker * Verify that each client can start and stop video streams on the same
1825*4d7e907cSAndroid Build Coastguard Worker * underlying camera with same configuration.
1826*4d7e907cSAndroid Build Coastguard Worker */
TEST_P(EvsAidlTest,MultiCameraStreamUseConfig)1827*4d7e907cSAndroid Build Coastguard Worker TEST_P(EvsAidlTest, MultiCameraStreamUseConfig) {
1828*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Starting MultiCameraStream test";
1829*4d7e907cSAndroid Build Coastguard Worker
1830*4d7e907cSAndroid Build Coastguard Worker if (mIsHwModule) {
1831*4d7e907cSAndroid Build Coastguard Worker // This test is not for HW module implementation.
1832*4d7e907cSAndroid Build Coastguard Worker return;
1833*4d7e907cSAndroid Build Coastguard Worker }
1834*4d7e907cSAndroid Build Coastguard Worker
1835*4d7e907cSAndroid Build Coastguard Worker // Get the camera list
1836*4d7e907cSAndroid Build Coastguard Worker loadCameraList();
1837*4d7e907cSAndroid Build Coastguard Worker
1838*4d7e907cSAndroid Build Coastguard Worker // Test each reported camera
1839*4d7e907cSAndroid Build Coastguard Worker for (auto&& cam : mCameraInfo) {
1840*4d7e907cSAndroid Build Coastguard Worker // choose a configuration that has a frame rate faster than minReqFps.
1841*4d7e907cSAndroid Build Coastguard Worker Stream targetCfg = {};
1842*4d7e907cSAndroid Build Coastguard Worker const int32_t minReqFps = 15;
1843*4d7e907cSAndroid Build Coastguard Worker int32_t maxArea = 0;
1844*4d7e907cSAndroid Build Coastguard Worker camera_metadata_entry_t streamCfgs;
1845*4d7e907cSAndroid Build Coastguard Worker bool foundCfg = false;
1846*4d7e907cSAndroid Build Coastguard Worker if (!find_camera_metadata_entry(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()),
1847*4d7e907cSAndroid Build Coastguard Worker ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
1848*4d7e907cSAndroid Build Coastguard Worker &streamCfgs)) {
1849*4d7e907cSAndroid Build Coastguard Worker // Stream configurations are found in metadata
1850*4d7e907cSAndroid Build Coastguard Worker RawStreamConfig* ptr = reinterpret_cast<RawStreamConfig*>(streamCfgs.data.i32);
1851*4d7e907cSAndroid Build Coastguard Worker for (unsigned offset = 0; offset < streamCfgs.count; offset += kStreamCfgSz) {
1852*4d7e907cSAndroid Build Coastguard Worker if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT) {
1853*4d7e907cSAndroid Build Coastguard Worker if (ptr->width * ptr->height > maxArea && ptr->framerate >= minReqFps) {
1854*4d7e907cSAndroid Build Coastguard Worker targetCfg.width = ptr->width;
1855*4d7e907cSAndroid Build Coastguard Worker targetCfg.height = ptr->height;
1856*4d7e907cSAndroid Build Coastguard Worker targetCfg.format = static_cast<PixelFormat>(ptr->format);
1857*4d7e907cSAndroid Build Coastguard Worker
1858*4d7e907cSAndroid Build Coastguard Worker maxArea = ptr->width * ptr->height;
1859*4d7e907cSAndroid Build Coastguard Worker foundCfg = true;
1860*4d7e907cSAndroid Build Coastguard Worker }
1861*4d7e907cSAndroid Build Coastguard Worker }
1862*4d7e907cSAndroid Build Coastguard Worker ++ptr;
1863*4d7e907cSAndroid Build Coastguard Worker }
1864*4d7e907cSAndroid Build Coastguard Worker }
1865*4d7e907cSAndroid Build Coastguard Worker
1866*4d7e907cSAndroid Build Coastguard Worker if (!foundCfg) {
1867*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Device " << cam.id
1868*4d7e907cSAndroid Build Coastguard Worker << " does not provide a list of supported stream configurations, skipped";
1869*4d7e907cSAndroid Build Coastguard Worker continue;
1870*4d7e907cSAndroid Build Coastguard Worker }
1871*4d7e907cSAndroid Build Coastguard Worker
1872*4d7e907cSAndroid Build Coastguard Worker // Create the first camera client with a selected stream configuration.
1873*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<IEvsCamera> pCam0;
1874*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam0).isOk());
1875*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(pCam0, nullptr);
1876*4d7e907cSAndroid Build Coastguard Worker
1877*4d7e907cSAndroid Build Coastguard Worker // Store a camera handle for a clean-up
1878*4d7e907cSAndroid Build Coastguard Worker mActiveCameras.push_back(pCam0);
1879*4d7e907cSAndroid Build Coastguard Worker
1880*4d7e907cSAndroid Build Coastguard Worker // Try to create the second camera client with different stream
1881*4d7e907cSAndroid Build Coastguard Worker // configuration.
1882*4d7e907cSAndroid Build Coastguard Worker int32_t id = targetCfg.id;
1883*4d7e907cSAndroid Build Coastguard Worker targetCfg.id += 1; // EVS manager sees only the stream id.
1884*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<IEvsCamera> pCam1;
1885*4d7e907cSAndroid Build Coastguard Worker ASSERT_FALSE(mEnumerator->openCamera(cam.id, targetCfg, &pCam1).isOk());
1886*4d7e907cSAndroid Build Coastguard Worker
1887*4d7e907cSAndroid Build Coastguard Worker // Try again with same stream configuration.
1888*4d7e907cSAndroid Build Coastguard Worker targetCfg.id = id;
1889*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam1).isOk());
1890*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(pCam1, nullptr);
1891*4d7e907cSAndroid Build Coastguard Worker
1892*4d7e907cSAndroid Build Coastguard Worker // Set up per-client frame receiver objects which will fire up its own thread
1893*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<FrameHandler> frameHandler0 = ndk::SharedRefBase::make<FrameHandler>(
1894*4d7e907cSAndroid Build Coastguard Worker pCam0, cam, nullptr, FrameHandler::eAutoReturn);
1895*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<FrameHandler> frameHandler1 = ndk::SharedRefBase::make<FrameHandler>(
1896*4d7e907cSAndroid Build Coastguard Worker pCam1, cam, nullptr, FrameHandler::eAutoReturn);
1897*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(frameHandler0, nullptr);
1898*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(frameHandler1, nullptr);
1899*4d7e907cSAndroid Build Coastguard Worker
1900*4d7e907cSAndroid Build Coastguard Worker // Start the camera's video stream via client 0
1901*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(frameHandler0->startStream());
1902*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(frameHandler1->startStream());
1903*4d7e907cSAndroid Build Coastguard Worker
1904*4d7e907cSAndroid Build Coastguard Worker // Ensure the stream starts
1905*4d7e907cSAndroid Build Coastguard Worker frameHandler0->waitForFrameCount(1);
1906*4d7e907cSAndroid Build Coastguard Worker frameHandler1->waitForFrameCount(1);
1907*4d7e907cSAndroid Build Coastguard Worker
1908*4d7e907cSAndroid Build Coastguard Worker nsecs_t firstFrame = systemTime(SYSTEM_TIME_MONOTONIC);
1909*4d7e907cSAndroid Build Coastguard Worker
1910*4d7e907cSAndroid Build Coastguard Worker // Wait a bit, then ensure both clients get at least the required minimum number of frames
1911*4d7e907cSAndroid Build Coastguard Worker sleep(5);
1912*4d7e907cSAndroid Build Coastguard Worker nsecs_t end = systemTime(SYSTEM_TIME_MONOTONIC);
1913*4d7e907cSAndroid Build Coastguard Worker unsigned framesReceived0 = 0, framesReceived1 = 0;
1914*4d7e907cSAndroid Build Coastguard Worker frameHandler0->getFramesCounters(&framesReceived0, nullptr);
1915*4d7e907cSAndroid Build Coastguard Worker frameHandler1->getFramesCounters(&framesReceived1, nullptr);
1916*4d7e907cSAndroid Build Coastguard Worker framesReceived0 = framesReceived0 - 1; // Back out the first frame we already waited for
1917*4d7e907cSAndroid Build Coastguard Worker framesReceived1 = framesReceived1 - 1; // Back out the first frame we already waited for
1918*4d7e907cSAndroid Build Coastguard Worker nsecs_t runTime = end - firstFrame;
1919*4d7e907cSAndroid Build Coastguard Worker float framesPerSecond0 = framesReceived0 / (runTime * kNanoToSeconds);
1920*4d7e907cSAndroid Build Coastguard Worker float framesPerSecond1 = framesReceived1 / (runTime * kNanoToSeconds);
1921*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Measured camera rate " << std::scientific << framesPerSecond0 << " fps and "
1922*4d7e907cSAndroid Build Coastguard Worker << framesPerSecond1 << " fps";
1923*4d7e907cSAndroid Build Coastguard Worker EXPECT_GE(framesPerSecond0, kMinimumFramesPerSecond);
1924*4d7e907cSAndroid Build Coastguard Worker EXPECT_GE(framesPerSecond1, kMinimumFramesPerSecond);
1925*4d7e907cSAndroid Build Coastguard Worker
1926*4d7e907cSAndroid Build Coastguard Worker // Shutdown one client
1927*4d7e907cSAndroid Build Coastguard Worker frameHandler0->shutdown();
1928*4d7e907cSAndroid Build Coastguard Worker
1929*4d7e907cSAndroid Build Coastguard Worker // Read frame counters again
1930*4d7e907cSAndroid Build Coastguard Worker frameHandler0->getFramesCounters(&framesReceived0, nullptr);
1931*4d7e907cSAndroid Build Coastguard Worker frameHandler1->getFramesCounters(&framesReceived1, nullptr);
1932*4d7e907cSAndroid Build Coastguard Worker
1933*4d7e907cSAndroid Build Coastguard Worker // Wait a bit again
1934*4d7e907cSAndroid Build Coastguard Worker sleep(5);
1935*4d7e907cSAndroid Build Coastguard Worker unsigned framesReceivedAfterStop0 = 0, framesReceivedAfterStop1 = 0;
1936*4d7e907cSAndroid Build Coastguard Worker frameHandler0->getFramesCounters(&framesReceivedAfterStop0, nullptr);
1937*4d7e907cSAndroid Build Coastguard Worker frameHandler1->getFramesCounters(&framesReceivedAfterStop1, nullptr);
1938*4d7e907cSAndroid Build Coastguard Worker EXPECT_EQ(framesReceived0, framesReceivedAfterStop0);
1939*4d7e907cSAndroid Build Coastguard Worker EXPECT_LT(framesReceived1, framesReceivedAfterStop1);
1940*4d7e907cSAndroid Build Coastguard Worker
1941*4d7e907cSAndroid Build Coastguard Worker // Shutdown another
1942*4d7e907cSAndroid Build Coastguard Worker frameHandler1->shutdown();
1943*4d7e907cSAndroid Build Coastguard Worker
1944*4d7e907cSAndroid Build Coastguard Worker // Explicitly release the camera
1945*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->closeCamera(pCam0).isOk());
1946*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->closeCamera(pCam1).isOk());
1947*4d7e907cSAndroid Build Coastguard Worker mActiveCameras.clear();
1948*4d7e907cSAndroid Build Coastguard Worker }
1949*4d7e907cSAndroid Build Coastguard Worker }
1950*4d7e907cSAndroid Build Coastguard Worker
1951*4d7e907cSAndroid Build Coastguard Worker /*
1952*4d7e907cSAndroid Build Coastguard Worker * LogicalCameraMetadata:
1953*4d7e907cSAndroid Build Coastguard Worker * Opens logical camera reported by the enumerator and validate its metadata by
1954*4d7e907cSAndroid Build Coastguard Worker * checking its capability and locating supporting physical camera device
1955*4d7e907cSAndroid Build Coastguard Worker * identifiers.
1956*4d7e907cSAndroid Build Coastguard Worker */
TEST_P(EvsAidlTest,LogicalCameraMetadata)1957*4d7e907cSAndroid Build Coastguard Worker TEST_P(EvsAidlTest, LogicalCameraMetadata) {
1958*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Starting LogicalCameraMetadata test";
1959*4d7e907cSAndroid Build Coastguard Worker
1960*4d7e907cSAndroid Build Coastguard Worker // Get the camera list
1961*4d7e907cSAndroid Build Coastguard Worker loadCameraList();
1962*4d7e907cSAndroid Build Coastguard Worker
1963*4d7e907cSAndroid Build Coastguard Worker // Open and close each camera twice
1964*4d7e907cSAndroid Build Coastguard Worker for (auto&& cam : mCameraInfo) {
1965*4d7e907cSAndroid Build Coastguard Worker bool isLogicalCam = false;
1966*4d7e907cSAndroid Build Coastguard Worker auto devices = getPhysicalCameraIds(cam.id, isLogicalCam);
1967*4d7e907cSAndroid Build Coastguard Worker if (isLogicalCam) {
1968*4d7e907cSAndroid Build Coastguard Worker ASSERT_GE(devices.size(), 1) << "Logical camera device must have at least one physical "
1969*4d7e907cSAndroid Build Coastguard Worker "camera device ID in its metadata.";
1970*4d7e907cSAndroid Build Coastguard Worker }
1971*4d7e907cSAndroid Build Coastguard Worker }
1972*4d7e907cSAndroid Build Coastguard Worker }
1973*4d7e907cSAndroid Build Coastguard Worker
1974*4d7e907cSAndroid Build Coastguard Worker /*
1975*4d7e907cSAndroid Build Coastguard Worker * CameraStreamExternalBuffering:
1976*4d7e907cSAndroid Build Coastguard Worker * This is same with CameraStreamBuffering except frame buffers are allocated by
1977*4d7e907cSAndroid Build Coastguard Worker * the test client and then imported by EVS framework.
1978*4d7e907cSAndroid Build Coastguard Worker */
TEST_P(EvsAidlTest,CameraStreamExternalBuffering)1979*4d7e907cSAndroid Build Coastguard Worker TEST_P(EvsAidlTest, CameraStreamExternalBuffering) {
1980*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Starting CameraStreamExternalBuffering test";
1981*4d7e907cSAndroid Build Coastguard Worker
1982*4d7e907cSAndroid Build Coastguard Worker // Arbitrary constant (should be > 1 and not too big)
1983*4d7e907cSAndroid Build Coastguard Worker static const unsigned int kBuffersToHold = 3;
1984*4d7e907cSAndroid Build Coastguard Worker
1985*4d7e907cSAndroid Build Coastguard Worker // Get the camera list
1986*4d7e907cSAndroid Build Coastguard Worker loadCameraList();
1987*4d7e907cSAndroid Build Coastguard Worker
1988*4d7e907cSAndroid Build Coastguard Worker // Acquire the graphics buffer allocator
1989*4d7e907cSAndroid Build Coastguard Worker android::GraphicBufferAllocator& alloc(android::GraphicBufferAllocator::get());
1990*4d7e907cSAndroid Build Coastguard Worker const auto usage =
1991*4d7e907cSAndroid Build Coastguard Worker GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_OFTEN;
1992*4d7e907cSAndroid Build Coastguard Worker
1993*4d7e907cSAndroid Build Coastguard Worker // Test each reported camera
1994*4d7e907cSAndroid Build Coastguard Worker for (auto&& cam : mCameraInfo) {
1995*4d7e907cSAndroid Build Coastguard Worker bool isLogicalCam = false;
1996*4d7e907cSAndroid Build Coastguard Worker getPhysicalCameraIds(cam.id, isLogicalCam);
1997*4d7e907cSAndroid Build Coastguard Worker if (isLogicalCam) {
1998*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Skip a logical device, " << cam.id;
1999*4d7e907cSAndroid Build Coastguard Worker continue;
2000*4d7e907cSAndroid Build Coastguard Worker }
2001*4d7e907cSAndroid Build Coastguard Worker
2002*4d7e907cSAndroid Build Coastguard Worker // Read a target resolution from the metadata
2003*4d7e907cSAndroid Build Coastguard Worker Stream targetCfg = getFirstStreamConfiguration(
2004*4d7e907cSAndroid Build Coastguard Worker reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
2005*4d7e907cSAndroid Build Coastguard Worker ASSERT_GT(targetCfg.width, 0);
2006*4d7e907cSAndroid Build Coastguard Worker ASSERT_GT(targetCfg.height, 0);
2007*4d7e907cSAndroid Build Coastguard Worker
2008*4d7e907cSAndroid Build Coastguard Worker // Allocate buffers to use
2009*4d7e907cSAndroid Build Coastguard Worker std::vector<BufferDesc> buffers;
2010*4d7e907cSAndroid Build Coastguard Worker buffers.resize(kBuffersToHold);
2011*4d7e907cSAndroid Build Coastguard Worker for (auto i = 0; i < kBuffersToHold; ++i) {
2012*4d7e907cSAndroid Build Coastguard Worker unsigned pixelsPerLine;
2013*4d7e907cSAndroid Build Coastguard Worker buffer_handle_t memHandle = nullptr;
2014*4d7e907cSAndroid Build Coastguard Worker android::status_t result =
2015*4d7e907cSAndroid Build Coastguard Worker alloc.allocate(targetCfg.width, targetCfg.height,
2016*4d7e907cSAndroid Build Coastguard Worker static_cast<android::PixelFormat>(targetCfg.format),
2017*4d7e907cSAndroid Build Coastguard Worker /* layerCount = */ 1, usage, &memHandle, &pixelsPerLine,
2018*4d7e907cSAndroid Build Coastguard Worker /* graphicBufferId = */ 0,
2019*4d7e907cSAndroid Build Coastguard Worker /* requestorName = */ "CameraStreamExternalBufferingTest");
2020*4d7e907cSAndroid Build Coastguard Worker if (result != android::NO_ERROR) {
2021*4d7e907cSAndroid Build Coastguard Worker LOG(ERROR) << __FUNCTION__ << " failed to allocate memory.";
2022*4d7e907cSAndroid Build Coastguard Worker // Release previous allocated buffers
2023*4d7e907cSAndroid Build Coastguard Worker for (auto j = 0; j < i; j++) {
2024*4d7e907cSAndroid Build Coastguard Worker alloc.free(::android::dupFromAidl(buffers[i].buffer.handle));
2025*4d7e907cSAndroid Build Coastguard Worker }
2026*4d7e907cSAndroid Build Coastguard Worker return;
2027*4d7e907cSAndroid Build Coastguard Worker } else {
2028*4d7e907cSAndroid Build Coastguard Worker BufferDesc buf;
2029*4d7e907cSAndroid Build Coastguard Worker HardwareBufferDescription* pDesc =
2030*4d7e907cSAndroid Build Coastguard Worker reinterpret_cast<HardwareBufferDescription*>(&buf.buffer.description);
2031*4d7e907cSAndroid Build Coastguard Worker pDesc->width = targetCfg.width;
2032*4d7e907cSAndroid Build Coastguard Worker pDesc->height = targetCfg.height;
2033*4d7e907cSAndroid Build Coastguard Worker pDesc->layers = 1;
2034*4d7e907cSAndroid Build Coastguard Worker pDesc->format = targetCfg.format;
2035*4d7e907cSAndroid Build Coastguard Worker pDesc->usage = static_cast<BufferUsage>(usage);
2036*4d7e907cSAndroid Build Coastguard Worker pDesc->stride = pixelsPerLine;
2037*4d7e907cSAndroid Build Coastguard Worker buf.buffer.handle = ::android::dupToAidl(memHandle);
2038*4d7e907cSAndroid Build Coastguard Worker buf.bufferId = i; // Unique number to identify this buffer
2039*4d7e907cSAndroid Build Coastguard Worker buffers[i] = std::move(buf);
2040*4d7e907cSAndroid Build Coastguard Worker }
2041*4d7e907cSAndroid Build Coastguard Worker }
2042*4d7e907cSAndroid Build Coastguard Worker
2043*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<IEvsCamera> pCam;
2044*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->openCamera(cam.id, targetCfg, &pCam).isOk());
2045*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(pCam, nullptr);
2046*4d7e907cSAndroid Build Coastguard Worker
2047*4d7e907cSAndroid Build Coastguard Worker // Store a camera handle for a clean-up
2048*4d7e907cSAndroid Build Coastguard Worker mActiveCameras.push_back(pCam);
2049*4d7e907cSAndroid Build Coastguard Worker
2050*4d7e907cSAndroid Build Coastguard Worker // Request to import buffers
2051*4d7e907cSAndroid Build Coastguard Worker int delta = 0;
2052*4d7e907cSAndroid Build Coastguard Worker auto status = pCam->importExternalBuffers(buffers, &delta);
2053*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(status.isOk());
2054*4d7e907cSAndroid Build Coastguard Worker EXPECT_GE(delta, kBuffersToHold);
2055*4d7e907cSAndroid Build Coastguard Worker
2056*4d7e907cSAndroid Build Coastguard Worker // Set up a frame receiver object which will fire up its own thread.
2057*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<FrameHandler> frameHandler = ndk::SharedRefBase::make<FrameHandler>(
2058*4d7e907cSAndroid Build Coastguard Worker pCam, cam, nullptr, FrameHandler::eNoAutoReturn);
2059*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(frameHandler, nullptr);
2060*4d7e907cSAndroid Build Coastguard Worker
2061*4d7e907cSAndroid Build Coastguard Worker // Start the camera's video stream
2062*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(frameHandler->startStream());
2063*4d7e907cSAndroid Build Coastguard Worker
2064*4d7e907cSAndroid Build Coastguard Worker // Check that the video stream stalls once we've gotten exactly the number of buffers
2065*4d7e907cSAndroid Build Coastguard Worker // we requested since we told the frameHandler not to return them.
2066*4d7e907cSAndroid Build Coastguard Worker sleep(1); // 1 second should be enough for at least 5 frames to be delivered worst case
2067*4d7e907cSAndroid Build Coastguard Worker unsigned framesReceived = 0;
2068*4d7e907cSAndroid Build Coastguard Worker frameHandler->getFramesCounters(&framesReceived, nullptr);
2069*4d7e907cSAndroid Build Coastguard Worker ASSERT_LE(kBuffersToHold, framesReceived) << "Stream didn't stall at expected buffer limit";
2070*4d7e907cSAndroid Build Coastguard Worker
2071*4d7e907cSAndroid Build Coastguard Worker // Give back one buffer
2072*4d7e907cSAndroid Build Coastguard Worker EXPECT_TRUE(frameHandler->returnHeldBuffer());
2073*4d7e907cSAndroid Build Coastguard Worker
2074*4d7e907cSAndroid Build Coastguard Worker // Once we return a buffer, it shouldn't take more than 1/10 second to get a new one
2075*4d7e907cSAndroid Build Coastguard Worker // filled since we require 10fps minimum -- but give a 10% allowance just in case.
2076*4d7e907cSAndroid Build Coastguard Worker unsigned framesReceivedAfter = 0;
2077*4d7e907cSAndroid Build Coastguard Worker usleep(110 * kMillisecondsToMicroseconds);
2078*4d7e907cSAndroid Build Coastguard Worker frameHandler->getFramesCounters(&framesReceivedAfter, nullptr);
2079*4d7e907cSAndroid Build Coastguard Worker EXPECT_EQ(framesReceived + 1, framesReceivedAfter) << "Stream should've resumed";
2080*4d7e907cSAndroid Build Coastguard Worker
2081*4d7e907cSAndroid Build Coastguard Worker // Even when the camera pointer goes out of scope, the FrameHandler object will
2082*4d7e907cSAndroid Build Coastguard Worker // keep the stream alive unless we tell it to shutdown.
2083*4d7e907cSAndroid Build Coastguard Worker // Also note that the FrameHandle and the Camera have a mutual circular reference, so
2084*4d7e907cSAndroid Build Coastguard Worker // we have to break that cycle in order for either of them to get cleaned up.
2085*4d7e907cSAndroid Build Coastguard Worker frameHandler->shutdown();
2086*4d7e907cSAndroid Build Coastguard Worker
2087*4d7e907cSAndroid Build Coastguard Worker // Explicitly release the camera
2088*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->closeCamera(pCam).isOk());
2089*4d7e907cSAndroid Build Coastguard Worker mActiveCameras.clear();
2090*4d7e907cSAndroid Build Coastguard Worker // Release buffers
2091*4d7e907cSAndroid Build Coastguard Worker for (auto& b : buffers) {
2092*4d7e907cSAndroid Build Coastguard Worker alloc.free(::android::dupFromAidl(b.buffer.handle));
2093*4d7e907cSAndroid Build Coastguard Worker }
2094*4d7e907cSAndroid Build Coastguard Worker buffers.resize(0);
2095*4d7e907cSAndroid Build Coastguard Worker }
2096*4d7e907cSAndroid Build Coastguard Worker }
2097*4d7e907cSAndroid Build Coastguard Worker
TEST_P(EvsAidlTest,DeviceStatusCallbackRegistration)2098*4d7e907cSAndroid Build Coastguard Worker TEST_P(EvsAidlTest, DeviceStatusCallbackRegistration) {
2099*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<IEvsEnumeratorStatusCallback> cb =
2100*4d7e907cSAndroid Build Coastguard Worker ndk::SharedRefBase::make<DeviceStatusCallback>();
2101*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus status = mEnumerator->registerStatusCallback(cb);
2102*4d7e907cSAndroid Build Coastguard Worker if (mIsHwModule) {
2103*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(status.isOk());
2104*4d7e907cSAndroid Build Coastguard Worker } else {
2105*4d7e907cSAndroid Build Coastguard Worker // A callback registration may fail if a HIDL EVS HAL implementation is
2106*4d7e907cSAndroid Build Coastguard Worker // running.
2107*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(status.isOk() ||
2108*4d7e907cSAndroid Build Coastguard Worker status.getServiceSpecificError() == static_cast<int>(EvsResult::NOT_SUPPORTED));
2109*4d7e907cSAndroid Build Coastguard Worker }
2110*4d7e907cSAndroid Build Coastguard Worker }
2111*4d7e907cSAndroid Build Coastguard Worker
2112*4d7e907cSAndroid Build Coastguard Worker /*
2113*4d7e907cSAndroid Build Coastguard Worker * UltrasonicsArrayOpenClean:
2114*4d7e907cSAndroid Build Coastguard Worker * Opens each ultrasonics arrays reported by the enumerator and then explicitly closes it via a
2115*4d7e907cSAndroid Build Coastguard Worker * call to closeUltrasonicsArray. Then repeats the test to ensure all ultrasonics arrays
2116*4d7e907cSAndroid Build Coastguard Worker * can be reopened.
2117*4d7e907cSAndroid Build Coastguard Worker */
TEST_P(EvsAidlTest,UltrasonicsArrayOpenClean)2118*4d7e907cSAndroid Build Coastguard Worker TEST_P(EvsAidlTest, UltrasonicsArrayOpenClean) {
2119*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Starting UltrasonicsArrayOpenClean test";
2120*4d7e907cSAndroid Build Coastguard Worker
2121*4d7e907cSAndroid Build Coastguard Worker // Get the ultrasonics array list
2122*4d7e907cSAndroid Build Coastguard Worker loadUltrasonicsArrayList();
2123*4d7e907cSAndroid Build Coastguard Worker
2124*4d7e907cSAndroid Build Coastguard Worker // Open and close each ultrasonics array twice
2125*4d7e907cSAndroid Build Coastguard Worker for (auto&& ultraInfo : mUltrasonicsArraysInfo) {
2126*4d7e907cSAndroid Build Coastguard Worker for (int pass = 0; pass < 2; pass++) {
2127*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<IEvsUltrasonicsArray> pUltrasonicsArray;
2128*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(
2129*4d7e907cSAndroid Build Coastguard Worker mEnumerator
2130*4d7e907cSAndroid Build Coastguard Worker ->openUltrasonicsArray(ultraInfo.ultrasonicsArrayId, &pUltrasonicsArray)
2131*4d7e907cSAndroid Build Coastguard Worker .isOk());
2132*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(pUltrasonicsArray, nullptr);
2133*4d7e907cSAndroid Build Coastguard Worker
2134*4d7e907cSAndroid Build Coastguard Worker // Verify that this ultrasonics array self-identifies correctly
2135*4d7e907cSAndroid Build Coastguard Worker UltrasonicsArrayDesc desc;
2136*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pUltrasonicsArray->getUltrasonicArrayInfo(&desc).isOk());
2137*4d7e907cSAndroid Build Coastguard Worker EXPECT_EQ(ultraInfo.ultrasonicsArrayId, desc.ultrasonicsArrayId);
2138*4d7e907cSAndroid Build Coastguard Worker LOG(DEBUG) << "Found ultrasonics array " << ultraInfo.ultrasonicsArrayId;
2139*4d7e907cSAndroid Build Coastguard Worker
2140*4d7e907cSAndroid Build Coastguard Worker // Explicitly close the ultrasonics array so resources are released right away
2141*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->closeUltrasonicsArray(pUltrasonicsArray).isOk());
2142*4d7e907cSAndroid Build Coastguard Worker }
2143*4d7e907cSAndroid Build Coastguard Worker }
2144*4d7e907cSAndroid Build Coastguard Worker }
2145*4d7e907cSAndroid Build Coastguard Worker
2146*4d7e907cSAndroid Build Coastguard Worker // Starts a stream and verifies all data received is valid.
TEST_P(EvsAidlTest,UltrasonicsVerifyStreamData)2147*4d7e907cSAndroid Build Coastguard Worker TEST_P(EvsAidlTest, UltrasonicsVerifyStreamData) {
2148*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Starting UltrasonicsVerifyStreamData";
2149*4d7e907cSAndroid Build Coastguard Worker
2150*4d7e907cSAndroid Build Coastguard Worker // Get the ultrasonics array list
2151*4d7e907cSAndroid Build Coastguard Worker loadUltrasonicsArrayList();
2152*4d7e907cSAndroid Build Coastguard Worker
2153*4d7e907cSAndroid Build Coastguard Worker // For each ultrasonics array.
2154*4d7e907cSAndroid Build Coastguard Worker for (auto&& ultraInfo : mUltrasonicsArraysInfo) {
2155*4d7e907cSAndroid Build Coastguard Worker LOG(DEBUG) << "Testing ultrasonics array: " << ultraInfo.ultrasonicsArrayId;
2156*4d7e907cSAndroid Build Coastguard Worker
2157*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<IEvsUltrasonicsArray> pUltrasonicsArray;
2158*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(
2159*4d7e907cSAndroid Build Coastguard Worker mEnumerator->openUltrasonicsArray(ultraInfo.ultrasonicsArrayId, &pUltrasonicsArray)
2160*4d7e907cSAndroid Build Coastguard Worker .isOk());
2161*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(pUltrasonicsArray, nullptr);
2162*4d7e907cSAndroid Build Coastguard Worker
2163*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<FrameHandlerUltrasonics> frameHandler =
2164*4d7e907cSAndroid Build Coastguard Worker ndk::SharedRefBase::make<FrameHandlerUltrasonics>(pUltrasonicsArray);
2165*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(frameHandler, nullptr);
2166*4d7e907cSAndroid Build Coastguard Worker
2167*4d7e907cSAndroid Build Coastguard Worker // Start stream.
2168*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pUltrasonicsArray->startStream(frameHandler).isOk());
2169*4d7e907cSAndroid Build Coastguard Worker
2170*4d7e907cSAndroid Build Coastguard Worker // Wait 5 seconds to receive frames.
2171*4d7e907cSAndroid Build Coastguard Worker sleep(5);
2172*4d7e907cSAndroid Build Coastguard Worker
2173*4d7e907cSAndroid Build Coastguard Worker // Stop stream.
2174*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pUltrasonicsArray->stopStream().isOk());
2175*4d7e907cSAndroid Build Coastguard Worker
2176*4d7e907cSAndroid Build Coastguard Worker EXPECT_GT(frameHandler->getReceiveFramesCount(), 0);
2177*4d7e907cSAndroid Build Coastguard Worker EXPECT_TRUE(frameHandler->areAllFramesValid());
2178*4d7e907cSAndroid Build Coastguard Worker
2179*4d7e907cSAndroid Build Coastguard Worker // Explicitly close the ultrasonics array so resources are released right away
2180*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->closeUltrasonicsArray(pUltrasonicsArray).isOk());
2181*4d7e907cSAndroid Build Coastguard Worker }
2182*4d7e907cSAndroid Build Coastguard Worker }
2183*4d7e907cSAndroid Build Coastguard Worker
2184*4d7e907cSAndroid Build Coastguard Worker // Sets frames in flight before and after start of stream and verfies success.
TEST_P(EvsAidlTest,UltrasonicsSetFramesInFlight)2185*4d7e907cSAndroid Build Coastguard Worker TEST_P(EvsAidlTest, UltrasonicsSetFramesInFlight) {
2186*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Starting UltrasonicsSetFramesInFlight";
2187*4d7e907cSAndroid Build Coastguard Worker
2188*4d7e907cSAndroid Build Coastguard Worker // Get the ultrasonics array list
2189*4d7e907cSAndroid Build Coastguard Worker loadUltrasonicsArrayList();
2190*4d7e907cSAndroid Build Coastguard Worker
2191*4d7e907cSAndroid Build Coastguard Worker // For each ultrasonics array.
2192*4d7e907cSAndroid Build Coastguard Worker for (auto&& ultraInfo : mUltrasonicsArraysInfo) {
2193*4d7e907cSAndroid Build Coastguard Worker LOG(DEBUG) << "Testing ultrasonics array: " << ultraInfo.ultrasonicsArrayId;
2194*4d7e907cSAndroid Build Coastguard Worker
2195*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<IEvsUltrasonicsArray> pUltrasonicsArray;
2196*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(
2197*4d7e907cSAndroid Build Coastguard Worker mEnumerator->openUltrasonicsArray(ultraInfo.ultrasonicsArrayId, &pUltrasonicsArray)
2198*4d7e907cSAndroid Build Coastguard Worker .isOk());
2199*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(pUltrasonicsArray, nullptr);
2200*4d7e907cSAndroid Build Coastguard Worker
2201*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pUltrasonicsArray->setMaxFramesInFlight(10).isOk());
2202*4d7e907cSAndroid Build Coastguard Worker
2203*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<FrameHandlerUltrasonics> frameHandler =
2204*4d7e907cSAndroid Build Coastguard Worker ndk::SharedRefBase::make<FrameHandlerUltrasonics>(pUltrasonicsArray);
2205*4d7e907cSAndroid Build Coastguard Worker EXPECT_NE(frameHandler, nullptr);
2206*4d7e907cSAndroid Build Coastguard Worker
2207*4d7e907cSAndroid Build Coastguard Worker // Start stream.
2208*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pUltrasonicsArray->startStream(frameHandler).isOk());
2209*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pUltrasonicsArray->setMaxFramesInFlight(5).isOk());
2210*4d7e907cSAndroid Build Coastguard Worker
2211*4d7e907cSAndroid Build Coastguard Worker // Stop stream.
2212*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pUltrasonicsArray->stopStream().isOk());
2213*4d7e907cSAndroid Build Coastguard Worker
2214*4d7e907cSAndroid Build Coastguard Worker // Explicitly close the ultrasonics array so resources are released right away
2215*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->closeUltrasonicsArray(pUltrasonicsArray).isOk());
2216*4d7e907cSAndroid Build Coastguard Worker }
2217*4d7e907cSAndroid Build Coastguard Worker }
2218*4d7e907cSAndroid Build Coastguard Worker
2219*4d7e907cSAndroid Build Coastguard Worker /*
2220*4d7e907cSAndroid Build Coastguard Worker * DisplayOpen:
2221*4d7e907cSAndroid Build Coastguard Worker * Test both clean shut down and "aggressive open" device stealing behavior.
2222*4d7e907cSAndroid Build Coastguard Worker */
TEST_P(EvsAidlTest,DisplayOpen)2223*4d7e907cSAndroid Build Coastguard Worker TEST_P(EvsAidlTest, DisplayOpen) {
2224*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Starting DisplayOpen test";
2225*4d7e907cSAndroid Build Coastguard Worker
2226*4d7e907cSAndroid Build Coastguard Worker // Request available display IDs.
2227*4d7e907cSAndroid Build Coastguard Worker std::vector<uint8_t> displayIds;
2228*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->getDisplayIdList(&displayIds).isOk());
2229*4d7e907cSAndroid Build Coastguard Worker EXPECT_GT(displayIds.size(), 0);
2230*4d7e907cSAndroid Build Coastguard Worker
2231*4d7e907cSAndroid Build Coastguard Worker for (const auto displayId : displayIds) {
2232*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<IEvsDisplay> pDisplay;
2233*4d7e907cSAndroid Build Coastguard Worker
2234*4d7e907cSAndroid Build Coastguard Worker // Request exclusive access to each EVS display, then let it go.
2235*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->openDisplay(displayId, &pDisplay).isOk());
2236*4d7e907cSAndroid Build Coastguard Worker ASSERT_NE(pDisplay, nullptr);
2237*4d7e907cSAndroid Build Coastguard Worker
2238*4d7e907cSAndroid Build Coastguard Worker {
2239*4d7e907cSAndroid Build Coastguard Worker // Ask the display what its name is.
2240*4d7e907cSAndroid Build Coastguard Worker DisplayDesc desc;
2241*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pDisplay->getDisplayInfo(&desc).isOk());
2242*4d7e907cSAndroid Build Coastguard Worker LOG(DEBUG) << "Found display " << desc.id;
2243*4d7e907cSAndroid Build Coastguard Worker }
2244*4d7e907cSAndroid Build Coastguard Worker
2245*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->closeDisplay(pDisplay).isOk());
2246*4d7e907cSAndroid Build Coastguard Worker
2247*4d7e907cSAndroid Build Coastguard Worker // Ensure we can reopen the display after it has been closed.
2248*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->openDisplay(displayId, &pDisplay).isOk());
2249*4d7e907cSAndroid Build Coastguard Worker ASSERT_NE(pDisplay, nullptr);
2250*4d7e907cSAndroid Build Coastguard Worker
2251*4d7e907cSAndroid Build Coastguard Worker // Open the display while its already open -- ownership should be transferred.
2252*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<IEvsDisplay> pDisplay2;
2253*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->openDisplay(displayId, &pDisplay2).isOk());
2254*4d7e907cSAndroid Build Coastguard Worker ASSERT_NE(pDisplay2, nullptr);
2255*4d7e907cSAndroid Build Coastguard Worker
2256*4d7e907cSAndroid Build Coastguard Worker {
2257*4d7e907cSAndroid Build Coastguard Worker // Ensure the old display properly reports its assassination.
2258*4d7e907cSAndroid Build Coastguard Worker DisplayState badState;
2259*4d7e907cSAndroid Build Coastguard Worker EXPECT_TRUE(pDisplay->getDisplayState(&badState).isOk());
2260*4d7e907cSAndroid Build Coastguard Worker EXPECT_EQ(badState, DisplayState::DEAD);
2261*4d7e907cSAndroid Build Coastguard Worker }
2262*4d7e907cSAndroid Build Coastguard Worker
2263*4d7e907cSAndroid Build Coastguard Worker // Close only the newest display instance -- the other should already be a zombie.
2264*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->closeDisplay(pDisplay2).isOk());
2265*4d7e907cSAndroid Build Coastguard Worker
2266*4d7e907cSAndroid Build Coastguard Worker // Finally, validate that we can open the display after the provoked failure above.
2267*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->openDisplay(displayId, &pDisplay).isOk());
2268*4d7e907cSAndroid Build Coastguard Worker ASSERT_NE(pDisplay, nullptr);
2269*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->closeDisplay(pDisplay).isOk());
2270*4d7e907cSAndroid Build Coastguard Worker }
2271*4d7e907cSAndroid Build Coastguard Worker }
2272*4d7e907cSAndroid Build Coastguard Worker
2273*4d7e907cSAndroid Build Coastguard Worker /*
2274*4d7e907cSAndroid Build Coastguard Worker * DisplayStates:
2275*4d7e907cSAndroid Build Coastguard Worker * Validate that display states transition as expected and can be queried from either the display
2276*4d7e907cSAndroid Build Coastguard Worker * object itself or the owning enumerator.
2277*4d7e907cSAndroid Build Coastguard Worker */
TEST_P(EvsAidlTest,DisplayStates)2278*4d7e907cSAndroid Build Coastguard Worker TEST_P(EvsAidlTest, DisplayStates) {
2279*4d7e907cSAndroid Build Coastguard Worker using std::literals::chrono_literals::operator""ms;
2280*4d7e907cSAndroid Build Coastguard Worker
2281*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << "Starting DisplayStates test";
2282*4d7e907cSAndroid Build Coastguard Worker
2283*4d7e907cSAndroid Build Coastguard Worker // Request available display IDs.
2284*4d7e907cSAndroid Build Coastguard Worker std::vector<uint8_t> displayIds;
2285*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->getDisplayIdList(&displayIds).isOk());
2286*4d7e907cSAndroid Build Coastguard Worker EXPECT_GT(displayIds.size(), 0);
2287*4d7e907cSAndroid Build Coastguard Worker
2288*4d7e907cSAndroid Build Coastguard Worker for (const auto displayId : displayIds) {
2289*4d7e907cSAndroid Build Coastguard Worker // Ensure the display starts in the expected state.
2290*4d7e907cSAndroid Build Coastguard Worker {
2291*4d7e907cSAndroid Build Coastguard Worker DisplayState state;
2292*4d7e907cSAndroid Build Coastguard Worker EXPECT_FALSE(mEnumerator->getDisplayState(&state).isOk());
2293*4d7e907cSAndroid Build Coastguard Worker }
2294*4d7e907cSAndroid Build Coastguard Worker for (const auto displayIdToQuery : displayIds) {
2295*4d7e907cSAndroid Build Coastguard Worker DisplayState state;
2296*4d7e907cSAndroid Build Coastguard Worker EXPECT_FALSE(mEnumerator->getDisplayStateById(displayIdToQuery, &state).isOk());
2297*4d7e907cSAndroid Build Coastguard Worker }
2298*4d7e907cSAndroid Build Coastguard Worker
2299*4d7e907cSAndroid Build Coastguard Worker // Scope to limit the lifetime of the pDisplay pointer, and thus the IEvsDisplay object.
2300*4d7e907cSAndroid Build Coastguard Worker {
2301*4d7e907cSAndroid Build Coastguard Worker // Request exclusive access to the EVS display.
2302*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<IEvsDisplay> pDisplay;
2303*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(mEnumerator->openDisplay(displayId, &pDisplay).isOk());
2304*4d7e907cSAndroid Build Coastguard Worker ASSERT_NE(pDisplay, nullptr);
2305*4d7e907cSAndroid Build Coastguard Worker {
2306*4d7e907cSAndroid Build Coastguard Worker DisplayState state;
2307*4d7e907cSAndroid Build Coastguard Worker EXPECT_TRUE(mEnumerator->getDisplayState(&state).isOk());
2308*4d7e907cSAndroid Build Coastguard Worker EXPECT_EQ(state, DisplayState::NOT_VISIBLE);
2309*4d7e907cSAndroid Build Coastguard Worker }
2310*4d7e907cSAndroid Build Coastguard Worker for (const auto displayIdToQuery : displayIds) {
2311*4d7e907cSAndroid Build Coastguard Worker DisplayState state;
2312*4d7e907cSAndroid Build Coastguard Worker bool get_state_ok =
2313*4d7e907cSAndroid Build Coastguard Worker mEnumerator->getDisplayStateById(displayIdToQuery, &state).isOk();
2314*4d7e907cSAndroid Build Coastguard Worker if (displayIdToQuery != displayId) {
2315*4d7e907cSAndroid Build Coastguard Worker EXPECT_FALSE(get_state_ok);
2316*4d7e907cSAndroid Build Coastguard Worker } else if (get_state_ok) {
2317*4d7e907cSAndroid Build Coastguard Worker EXPECT_EQ(state, DisplayState::NOT_VISIBLE);
2318*4d7e907cSAndroid Build Coastguard Worker }
2319*4d7e907cSAndroid Build Coastguard Worker }
2320*4d7e907cSAndroid Build Coastguard Worker
2321*4d7e907cSAndroid Build Coastguard Worker // Activate the display.
2322*4d7e907cSAndroid Build Coastguard Worker EXPECT_TRUE(pDisplay->setDisplayState(DisplayState::VISIBLE_ON_NEXT_FRAME).isOk());
2323*4d7e907cSAndroid Build Coastguard Worker {
2324*4d7e907cSAndroid Build Coastguard Worker DisplayState state;
2325*4d7e907cSAndroid Build Coastguard Worker EXPECT_TRUE(mEnumerator->getDisplayState(&state).isOk());
2326*4d7e907cSAndroid Build Coastguard Worker EXPECT_EQ(state, DisplayState::VISIBLE_ON_NEXT_FRAME);
2327*4d7e907cSAndroid Build Coastguard Worker }
2328*4d7e907cSAndroid Build Coastguard Worker {
2329*4d7e907cSAndroid Build Coastguard Worker DisplayState state;
2330*4d7e907cSAndroid Build Coastguard Worker EXPECT_TRUE(pDisplay->getDisplayState(&state).isOk());
2331*4d7e907cSAndroid Build Coastguard Worker EXPECT_EQ(state, DisplayState::VISIBLE_ON_NEXT_FRAME);
2332*4d7e907cSAndroid Build Coastguard Worker }
2333*4d7e907cSAndroid Build Coastguard Worker for (const auto displayIdToQuery : displayIds) {
2334*4d7e907cSAndroid Build Coastguard Worker DisplayState state;
2335*4d7e907cSAndroid Build Coastguard Worker bool get_state_ok =
2336*4d7e907cSAndroid Build Coastguard Worker mEnumerator->getDisplayStateById(displayIdToQuery, &state).isOk();
2337*4d7e907cSAndroid Build Coastguard Worker if (displayIdToQuery != displayId) {
2338*4d7e907cSAndroid Build Coastguard Worker EXPECT_FALSE(get_state_ok);
2339*4d7e907cSAndroid Build Coastguard Worker } else if (get_state_ok) {
2340*4d7e907cSAndroid Build Coastguard Worker EXPECT_EQ(state, DisplayState::VISIBLE_ON_NEXT_FRAME);
2341*4d7e907cSAndroid Build Coastguard Worker }
2342*4d7e907cSAndroid Build Coastguard Worker }
2343*4d7e907cSAndroid Build Coastguard Worker
2344*4d7e907cSAndroid Build Coastguard Worker // Get the output buffer we'd use to display the imagery.
2345*4d7e907cSAndroid Build Coastguard Worker BufferDesc tgtBuffer;
2346*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(pDisplay->getTargetBuffer(&tgtBuffer).isOk());
2347*4d7e907cSAndroid Build Coastguard Worker
2348*4d7e907cSAndroid Build Coastguard Worker // Send the target buffer back for display (we didn't actually fill anything).
2349*4d7e907cSAndroid Build Coastguard Worker EXPECT_TRUE(pDisplay->returnTargetBufferForDisplay(tgtBuffer).isOk());
2350*4d7e907cSAndroid Build Coastguard Worker
2351*4d7e907cSAndroid Build Coastguard Worker // Sleep for a tenth of a second to ensure the driver has time to get the image
2352*4d7e907cSAndroid Build Coastguard Worker // displayed.
2353*4d7e907cSAndroid Build Coastguard Worker std::this_thread::sleep_for(100ms);
2354*4d7e907cSAndroid Build Coastguard Worker {
2355*4d7e907cSAndroid Build Coastguard Worker DisplayState state;
2356*4d7e907cSAndroid Build Coastguard Worker EXPECT_TRUE(mEnumerator->getDisplayState(&state).isOk());
2357*4d7e907cSAndroid Build Coastguard Worker EXPECT_EQ(state, DisplayState::VISIBLE);
2358*4d7e907cSAndroid Build Coastguard Worker }
2359*4d7e907cSAndroid Build Coastguard Worker {
2360*4d7e907cSAndroid Build Coastguard Worker DisplayState state;
2361*4d7e907cSAndroid Build Coastguard Worker EXPECT_TRUE(pDisplay->getDisplayState(&state).isOk());
2362*4d7e907cSAndroid Build Coastguard Worker EXPECT_EQ(state, DisplayState::VISIBLE);
2363*4d7e907cSAndroid Build Coastguard Worker }
2364*4d7e907cSAndroid Build Coastguard Worker for (const auto displayIdToQuery : displayIds) {
2365*4d7e907cSAndroid Build Coastguard Worker DisplayState state;
2366*4d7e907cSAndroid Build Coastguard Worker bool get_state_ok =
2367*4d7e907cSAndroid Build Coastguard Worker mEnumerator->getDisplayStateById(displayIdToQuery, &state).isOk();
2368*4d7e907cSAndroid Build Coastguard Worker if (displayIdToQuery != displayId) {
2369*4d7e907cSAndroid Build Coastguard Worker EXPECT_FALSE(get_state_ok);
2370*4d7e907cSAndroid Build Coastguard Worker } else if (get_state_ok) {
2371*4d7e907cSAndroid Build Coastguard Worker EXPECT_EQ(state, DisplayState::VISIBLE);
2372*4d7e907cSAndroid Build Coastguard Worker }
2373*4d7e907cSAndroid Build Coastguard Worker }
2374*4d7e907cSAndroid Build Coastguard Worker
2375*4d7e907cSAndroid Build Coastguard Worker // Turn off the display.
2376*4d7e907cSAndroid Build Coastguard Worker EXPECT_TRUE(pDisplay->setDisplayState(DisplayState::NOT_VISIBLE).isOk());
2377*4d7e907cSAndroid Build Coastguard Worker std::this_thread::sleep_for(100ms);
2378*4d7e907cSAndroid Build Coastguard Worker {
2379*4d7e907cSAndroid Build Coastguard Worker DisplayState state;
2380*4d7e907cSAndroid Build Coastguard Worker EXPECT_TRUE(mEnumerator->getDisplayState(&state).isOk());
2381*4d7e907cSAndroid Build Coastguard Worker EXPECT_EQ(state, DisplayState::NOT_VISIBLE);
2382*4d7e907cSAndroid Build Coastguard Worker }
2383*4d7e907cSAndroid Build Coastguard Worker {
2384*4d7e907cSAndroid Build Coastguard Worker DisplayState state;
2385*4d7e907cSAndroid Build Coastguard Worker EXPECT_TRUE(pDisplay->getDisplayState(&state).isOk());
2386*4d7e907cSAndroid Build Coastguard Worker EXPECT_EQ(state, DisplayState::NOT_VISIBLE);
2387*4d7e907cSAndroid Build Coastguard Worker }
2388*4d7e907cSAndroid Build Coastguard Worker for (const auto displayIdToQuery : displayIds) {
2389*4d7e907cSAndroid Build Coastguard Worker DisplayState state;
2390*4d7e907cSAndroid Build Coastguard Worker bool get_state_ok =
2391*4d7e907cSAndroid Build Coastguard Worker mEnumerator->getDisplayStateById(displayIdToQuery, &state).isOk();
2392*4d7e907cSAndroid Build Coastguard Worker if (displayIdToQuery != displayId) {
2393*4d7e907cSAndroid Build Coastguard Worker EXPECT_FALSE(get_state_ok);
2394*4d7e907cSAndroid Build Coastguard Worker } else if (get_state_ok) {
2395*4d7e907cSAndroid Build Coastguard Worker EXPECT_EQ(state, DisplayState::NOT_VISIBLE);
2396*4d7e907cSAndroid Build Coastguard Worker }
2397*4d7e907cSAndroid Build Coastguard Worker }
2398*4d7e907cSAndroid Build Coastguard Worker
2399*4d7e907cSAndroid Build Coastguard Worker // Close the display.
2400*4d7e907cSAndroid Build Coastguard Worker mEnumerator->closeDisplay(pDisplay);
2401*4d7e907cSAndroid Build Coastguard Worker }
2402*4d7e907cSAndroid Build Coastguard Worker
2403*4d7e907cSAndroid Build Coastguard Worker // Now that the display pointer has gone out of scope, causing the IEvsDisplay interface
2404*4d7e907cSAndroid Build Coastguard Worker // object to be destroyed, we should be back to the "not open" state.
2405*4d7e907cSAndroid Build Coastguard Worker // NOTE: If we want this to pass without the sleep above, we'd have to add the
2406*4d7e907cSAndroid Build Coastguard Worker // (now recommended) closeDisplay() call instead of relying on the smarter pointer
2407*4d7e907cSAndroid Build Coastguard Worker // going out of scope. I've not done that because I want to verify that the deletion
2408*4d7e907cSAndroid Build Coastguard Worker // of the object does actually clean up (eventually).
2409*4d7e907cSAndroid Build Coastguard Worker {
2410*4d7e907cSAndroid Build Coastguard Worker DisplayState state;
2411*4d7e907cSAndroid Build Coastguard Worker EXPECT_FALSE(mEnumerator->getDisplayState(&state).isOk());
2412*4d7e907cSAndroid Build Coastguard Worker }
2413*4d7e907cSAndroid Build Coastguard Worker for (const auto displayIdToQuery : displayIds) {
2414*4d7e907cSAndroid Build Coastguard Worker DisplayState state;
2415*4d7e907cSAndroid Build Coastguard Worker EXPECT_FALSE(mEnumerator->getDisplayStateById(displayIdToQuery, &state).isOk());
2416*4d7e907cSAndroid Build Coastguard Worker }
2417*4d7e907cSAndroid Build Coastguard Worker }
2418*4d7e907cSAndroid Build Coastguard Worker }
2419*4d7e907cSAndroid Build Coastguard Worker
2420*4d7e907cSAndroid Build Coastguard Worker GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EvsAidlTest);
2421*4d7e907cSAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(
2422*4d7e907cSAndroid Build Coastguard Worker PerInstance, EvsAidlTest,
2423*4d7e907cSAndroid Build Coastguard Worker testing::ValuesIn(android::getAidlHalInstanceNames(IEvsEnumerator::descriptor)),
2424*4d7e907cSAndroid Build Coastguard Worker android::PrintInstanceNameToString);
2425*4d7e907cSAndroid Build Coastguard Worker
main(int argc,char ** argv)2426*4d7e907cSAndroid Build Coastguard Worker int main(int argc, char** argv) {
2427*4d7e907cSAndroid Build Coastguard Worker ::testing::InitGoogleTest(&argc, argv);
2428*4d7e907cSAndroid Build Coastguard Worker ABinderProcess_setThreadPoolMaxThreadCount(1);
2429*4d7e907cSAndroid Build Coastguard Worker ABinderProcess_startThreadPool();
2430*4d7e907cSAndroid Build Coastguard Worker return RUN_ALL_TESTS();
2431*4d7e907cSAndroid Build Coastguard Worker }
2432