1 /*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "ACameraManagerTest"
18 //#define LOG_NDEBUG 0
19
20 #include <gtest/gtest.h>
21
22 #include <mutex>
23 #include <set>
24 #include <string>
25
26 #include <utils/Log.h>
27 #include <camera/NdkCameraError.h>
28 #include <camera/NdkCameraManager.h>
29
30 namespace {
31
32 class CameraServiceListener {
33 public:
34 typedef std::set<std::pair<std::string, std::string>> StringPairSet;
35
onAvailable(void * obj,const char * cameraId)36 static void onAvailable(void* obj, const char* cameraId) {
37 ALOGV("Camera %s onAvailable", cameraId);
38 if (obj == nullptr) {
39 return;
40 }
41 CameraServiceListener* thiz = reinterpret_cast<CameraServiceListener*>(obj);
42 std::lock_guard<std::mutex> lock(thiz->mMutex);
43 thiz->mOnAvailableCount++;
44 thiz->mAvailableMap[cameraId] = true;
45 return;
46 }
47
onUnavailable(void * obj,const char * cameraId)48 static void onUnavailable(void* obj, const char* cameraId) {
49 ALOGV("Camera %s onUnavailable", cameraId);
50 if (obj == nullptr) {
51 return;
52 }
53 CameraServiceListener* thiz = reinterpret_cast<CameraServiceListener*>(obj);
54 std::lock_guard<std::mutex> lock(thiz->mMutex);
55 thiz->mOnUnavailableCount++;
56 thiz->mAvailableMap[cameraId] = false;
57 return;
58 }
59
onCameraAccessPrioritiesChanged(void *)60 static void onCameraAccessPrioritiesChanged(void* /*obj*/) {
61 return;
62 }
63
onPhysicalCameraAvailable(void * obj,const char * cameraId,const char * physicalCameraId)64 static void onPhysicalCameraAvailable(void* obj, const char* cameraId,
65 const char* physicalCameraId) {
66 ALOGV("Camera %s : %s onAvailable", cameraId, physicalCameraId);
67 if (obj == nullptr) {
68 return;
69 }
70 CameraServiceListener* thiz = reinterpret_cast<CameraServiceListener*>(obj);
71 std::lock_guard<std::mutex> lock(thiz->mMutex);
72 thiz->mOnPhysicalCameraAvailableCount++;
73 return;
74 }
75
onPhysicalCameraUnavailable(void * obj,const char * cameraId,const char * physicalCameraId)76 static void onPhysicalCameraUnavailable(void* obj, const char* cameraId,
77 const char* physicalCameraId) {
78 ALOGV("Camera %s : %s onUnavailable", cameraId, physicalCameraId);
79 if (obj == nullptr) {
80 return;
81 }
82 CameraServiceListener* thiz = reinterpret_cast<CameraServiceListener*>(obj);
83 std::lock_guard<std::mutex> lock(thiz->mMutex);
84 thiz->mUnavailablePhysicalCameras.emplace(cameraId, physicalCameraId);
85 return;
86 }
87
resetCount()88 void resetCount() {
89 std::lock_guard<std::mutex> lock(mMutex);
90 mOnAvailableCount = 0;
91 mOnUnavailableCount = 0;
92 mOnPhysicalCameraAvailableCount = 0;
93 mUnavailablePhysicalCameras.clear();
94 return;
95 }
96
getAvailableCount()97 int getAvailableCount() {
98 std::lock_guard<std::mutex> lock(mMutex);
99 return mOnAvailableCount;
100 }
101
getUnavailableCount()102 int getUnavailableCount() {
103 std::lock_guard<std::mutex> lock(mMutex);
104 return mOnUnavailableCount;
105 }
106
getPhysicalCameraAvailableCount()107 int getPhysicalCameraAvailableCount() {
108 std::lock_guard<std::mutex> lock(mMutex);
109 return mOnPhysicalCameraAvailableCount;
110 }
111
getUnavailablePhysicalCameras()112 StringPairSet getUnavailablePhysicalCameras() {
113 std::lock_guard<std::mutex> lock(mMutex);
114 return mUnavailablePhysicalCameras;
115 }
116
isAvailable(const char * cameraId)117 bool isAvailable(const char* cameraId) {
118 std::lock_guard<std::mutex> lock(mMutex);
119 if (mAvailableMap.count(cameraId) == 0) {
120 return false;
121 }
122 return mAvailableMap[cameraId];
123 }
124
125 private:
126 std::mutex mMutex;
127 int mOnAvailableCount = 0;
128 int mOnUnavailableCount = 0;
129 int mOnPhysicalCameraAvailableCount = 0;
130 std::map<std::string, bool> mAvailableMap;
131 StringPairSet mUnavailablePhysicalCameras;
132 };
133
134 class ACameraManagerTest : public ::testing::Test {
135 public:
SetUp()136 void SetUp() override {
137 mCameraManager = ACameraManager_create();
138 if (mCameraManager == nullptr) {
139 ALOGE("Failed to create ACameraManager.");
140 return;
141 }
142
143 camera_status_t ret = ACameraManager_getCameraIdList(mCameraManager, &mCameraIdList);
144 if (ret != ACAMERA_OK) {
145 ALOGE("Failed to get cameraIdList: ret=%d", ret);
146 return;
147 }
148 if (mCameraIdList->numCameras < 1) {
149 ALOGW("Device has no camera on board.");
150 return;
151 }
152 }
TearDown()153 void TearDown() override {
154 // Destroy camera manager
155 if (mCameraIdList) {
156 ACameraManager_deleteCameraIdList(mCameraIdList);
157 mCameraIdList = nullptr;
158 }
159 if (mCameraManager) {
160 ACameraManager_delete(mCameraManager);
161 mCameraManager = nullptr;
162 }
163 }
164
165 // Camera manager
166 ACameraManager* mCameraManager = nullptr;
167 ACameraIdList* mCameraIdList = nullptr;
168 CameraServiceListener mAvailabilityListener;
169 ACameraManager_ExtendedAvailabilityCallbacks mCbs = {
170 {
171 &mAvailabilityListener,
172 CameraServiceListener::onAvailable,
173 CameraServiceListener::onUnavailable
174 },
175 CameraServiceListener::onCameraAccessPrioritiesChanged,
176 CameraServiceListener::onPhysicalCameraAvailable,
177 CameraServiceListener::onPhysicalCameraUnavailable,
178 {}
179 };
180 };
181
TEST_F(ACameraManagerTest,testCameraManagerExtendedAvailabilityCallbacks)182 TEST_F(ACameraManagerTest, testCameraManagerExtendedAvailabilityCallbacks) {
183 camera_status_t ret = ACameraManager_registerExtendedAvailabilityCallback(mCameraManager,
184 &mCbs);
185 ASSERT_EQ(ret, ACAMERA_OK);
186
187 sleep(1);
188
189 // Should at least get onAvailable for each camera once
190 ASSERT_EQ(mAvailabilityListener.getAvailableCount(), mCameraIdList->numCameras);
191
192 // Expect no available callbacks for physical cameras
193 int availablePhysicalCamera = mAvailabilityListener.getPhysicalCameraAvailableCount();
194 ASSERT_EQ(availablePhysicalCamera, 0);
195
196 CameraServiceListener::StringPairSet unavailablePhysicalCameras;
197 CameraServiceListener::StringPairSet physicalCameraIdPairs;
198
199 unavailablePhysicalCameras = mAvailabilityListener.getUnavailablePhysicalCameras();
200 for (int i = 0; i < mCameraIdList->numCameras; i++) {
201 const char* cameraId = mCameraIdList->cameraIds[i];
202 ASSERT_NE(cameraId, nullptr);
203 ASSERT_TRUE(mAvailabilityListener.isAvailable(cameraId));
204
205 ACameraMetadata* chars = nullptr;
206 ret = ACameraManager_getCameraCharacteristics(mCameraManager, cameraId, &chars);
207 ASSERT_EQ(ret, ACAMERA_OK);
208 ASSERT_NE(chars, nullptr);
209
210 size_t physicalCameraCnt = 0;
211 const char *const* physicalCameraIds = nullptr;
212 if (!ACameraMetadata_isLogicalMultiCamera(
213 chars, &physicalCameraCnt, &physicalCameraIds)) {
214 ACameraMetadata_free(chars);
215 continue;
216 }
217 for (size_t j = 0; j < physicalCameraCnt; j++) {
218 physicalCameraIdPairs.emplace(cameraId, physicalCameraIds[j]);
219 }
220 ACameraMetadata_free(chars);
221 }
222 for (const auto& unavailIdPair : unavailablePhysicalCameras) {
223 bool validPair = false;
224 for (const auto& idPair : physicalCameraIdPairs) {
225 if (idPair.first == unavailIdPair.first && idPair.second == unavailIdPair.second) {
226 validPair = true;
227 break;
228 }
229 }
230 // Expect valid unavailable physical cameras
231 ASSERT_TRUE(validPair);
232 }
233
234 ret = ACameraManager_unregisterExtendedAvailabilityCallback(mCameraManager, &mCbs);
235 ASSERT_EQ(ret, ACAMERA_OK);
236 }
237
238 } // namespace
239