1 /*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <android/content/AttributionSourceState.h>
18 #include <android/hardware/BnCameraServiceListener.h>
19 #include <android/hardware/BnCameraServiceProxy.h>
20 #include <android/hardware/camera2/BnCameraDeviceCallbacks.h>
21 #include <android/hardware/ICameraService.h>
22
23 #include <private/android_filesystem_config.h>
24
25 #include <camera/CameraUtils.h>
26
27 #include "../CameraService.h"
28 #include "../utils/CameraServiceProxyWrapper.h"
29
30 #include <gtest/gtest.h>
31
32 #include <memory>
33 #include <vector>
34
35 using namespace android;
36 using namespace android::hardware::camera;
37 using android::hardware::camera2::CameraMetadataInfo;
38
39 // Empty service listener.
40 class TestCameraServiceListener : public hardware::BnCameraServiceListener {
41 public:
~TestCameraServiceListener()42 virtual ~TestCameraServiceListener() {}
43
onStatusChanged(int32_t,const std::string &,int32_t)44 virtual binder::Status onStatusChanged(int32_t , const std::string&, int32_t) {
45 return binder::Status::ok();
46 }
47
onPhysicalCameraStatusChanged(int32_t,const std::string &,const std::string &,int32_t)48 virtual binder::Status onPhysicalCameraStatusChanged(int32_t /*status*/,
49 const std::string& /*cameraId*/, const std::string& /*physicalCameraId*/,
50 int32_t /*deviceId*/) {
51 // No op
52 return binder::Status::ok();
53 }
54
onTorchStatusChanged(int32_t,const std::string &,int32_t)55 virtual binder::Status onTorchStatusChanged(int32_t /*status*/,
56 const std::string& /*cameraId*/, int32_t /*deviceId*/) {
57 return binder::Status::ok();
58 }
59
onCameraAccessPrioritiesChanged()60 virtual binder::Status onCameraAccessPrioritiesChanged() {
61 // No op
62 return binder::Status::ok();
63 }
64
onCameraOpened(const std::string &,const std::string &,int32_t)65 virtual binder::Status onCameraOpened(const std::string& /*cameraId*/,
66 const std::string& /*clientPackageName*/, int32_t /*deviceId*/) {
67 // No op
68 return binder::Status::ok();
69 }
70
onCameraClosed(const std::string &,int32_t)71 virtual binder::Status onCameraClosed(const std::string& /*cameraId*/, int32_t /*deviceId*/) {
72 // No op
73 return binder::Status::ok();
74 }
75
onTorchStrengthLevelChanged(const std::string &,int32_t,int32_t)76 virtual binder::Status onTorchStrengthLevelChanged(const std::string& /*cameraId*/,
77 int32_t /*torchStrength*/, int32_t /*deviceId*/) {
78 // No op
79 return binder::Status::ok();
80 }
81
onCameraOpenedInSharedMode(const std::string &,const std::string &,int32_t,bool)82 virtual binder::Status onCameraOpenedInSharedMode(const std::string& /*cameraId*/,
83 const std::string& /*clientPackageName*/, int32_t /*deviceId*/,
84 bool /*isPrimaryClient*/) {
85 // No op
86 return binder::Status::ok();
87 }
88 };
89
90 // Empty device callback.
91 class TestCameraDeviceCallbacks : public hardware::camera2::BnCameraDeviceCallbacks {
92 public:
TestCameraDeviceCallbacks()93 TestCameraDeviceCallbacks() {}
94
~TestCameraDeviceCallbacks()95 virtual ~TestCameraDeviceCallbacks() {}
96
onDeviceError(int,const CaptureResultExtras &)97 virtual binder::Status onDeviceError(int /*errorCode*/,
98 const CaptureResultExtras& /*resultExtras*/) {
99 return binder::Status::ok();
100 }
101
onDeviceIdle()102 virtual binder::Status onDeviceIdle() {
103 return binder::Status::ok();
104 }
105
onCaptureStarted(const CaptureResultExtras &,int64_t)106 virtual binder::Status onCaptureStarted(const CaptureResultExtras& /*resultExtras*/,
107 int64_t /*timestamp*/) {
108 return binder::Status::ok();
109 }
110
onResultReceived(const CameraMetadataInfo &,const CaptureResultExtras &,const std::vector<PhysicalCaptureResultInfo> &)111 virtual binder::Status onResultReceived(const CameraMetadataInfo& /*metadata*/,
112 const CaptureResultExtras& /*resultExtras*/,
113 const std::vector<PhysicalCaptureResultInfo>& /*physicalResultInfos*/) {
114 return binder::Status::ok();
115 }
116
onPrepared(int)117 virtual binder::Status onPrepared(int /*streamId*/) {
118 return binder::Status::ok();
119 }
120
onRepeatingRequestError(int64_t,int32_t)121 virtual binder::Status onRepeatingRequestError(
122 int64_t /*lastFrameNumber*/, int32_t /*stoppedSequenceId*/) {
123 return binder::Status::ok();
124 }
125
onRequestQueueEmpty()126 virtual binder::Status onRequestQueueEmpty() {
127 return binder::Status::ok();
128 }
129
onClientSharedAccessPriorityChanged(bool)130 virtual binder::Status onClientSharedAccessPriorityChanged(bool /*isPrimaryClient*/) {
131 return binder::Status::ok();
132 }
133 };
134
135 // Override isCameraDisabled from the CameraServiceProxy with a flag.
136 class CameraServiceProxyOverride : public ::android::hardware::BnCameraServiceProxy {
137 public:
CameraServiceProxyOverride()138 CameraServiceProxyOverride() :
139 mCameraServiceProxy(CameraServiceProxyWrapper::getDefaultCameraServiceProxy()),
140 mCameraDisabled(false), mOverrideCameraDisabled(false)
141 { }
142
getRotateAndCropOverride(const std::string & packageName,int lensFacing,int userId,int * ret)143 virtual binder::Status getRotateAndCropOverride(const std::string& packageName, int lensFacing,
144 int userId, int *ret) override {
145 return mCameraServiceProxy->getRotateAndCropOverride(packageName, lensFacing,
146 userId, ret);
147 }
148
getAutoframingOverride(const std::string & packageName,int * ret)149 virtual binder::Status getAutoframingOverride(const std::string& packageName, int *ret) override {
150 return mCameraServiceProxy->getAutoframingOverride(packageName, ret);
151 }
152
pingForUserUpdate()153 virtual binder::Status pingForUserUpdate() override {
154 return mCameraServiceProxy->pingForUserUpdate();
155 }
156
notifyCameraState(const hardware::CameraSessionStats & cameraSessionStats)157 virtual binder::Status notifyCameraState(
158 const hardware::CameraSessionStats& cameraSessionStats) override {
159 return mCameraServiceProxy->notifyCameraState(cameraSessionStats);
160 }
161
notifyFeatureCombinationStats(const hardware::CameraFeatureCombinationStats & featureCombStats)162 virtual binder::Status notifyFeatureCombinationStats(
163 const hardware::CameraFeatureCombinationStats& featureCombStats) override {
164 return mCameraServiceProxy->notifyFeatureCombinationStats(featureCombStats);
165 }
166
isCameraDisabled(int userId,bool * ret)167 virtual binder::Status isCameraDisabled(int userId, bool *ret) override {
168 if (mOverrideCameraDisabled) {
169 *ret = mCameraDisabled;
170 return binder::Status::ok();
171 }
172 return mCameraServiceProxy->isCameraDisabled(userId, ret);
173 }
174
setCameraDisabled(bool cameraDisabled)175 void setCameraDisabled(bool cameraDisabled) {
176 mCameraDisabled = cameraDisabled;
177 }
178
setOverrideCameraDisabled(bool overrideCameraDisabled)179 void setOverrideCameraDisabled(bool overrideCameraDisabled) {
180 mOverrideCameraDisabled = overrideCameraDisabled;
181 }
182
183 protected:
184 sp<hardware::ICameraServiceProxy> mCameraServiceProxy;
185 bool mCameraDisabled;
186 bool mOverrideCameraDisabled;
187 };
188
189 class AutoDisconnectDevice {
190 public:
AutoDisconnectDevice(sp<hardware::camera2::ICameraDeviceUser> device)191 AutoDisconnectDevice(sp<hardware::camera2::ICameraDeviceUser> device) :
192 mDevice(device)
193 { }
194
~AutoDisconnectDevice()195 ~AutoDisconnectDevice() {
196 if (mDevice != nullptr) {
197 mDevice->disconnect();
198 }
199 }
200
201 private:
202 sp<hardware::camera2::ICameraDeviceUser> mDevice;
203 };
204
205 class CameraPermissionsTest : public ::testing::Test {
206 protected:
207 static sp<CameraService> sCameraService;
208 static sp<CameraServiceProxyOverride> sCameraServiceProxy;
209 static std::shared_ptr<CameraServiceProxyWrapper> sCameraServiceProxyWrapper;
210 static uid_t sOldUid;
211
SetUpTestSuite()212 static void SetUpTestSuite() {
213 sOldUid = getuid();
214 setuid(AID_CAMERASERVER);
215 sCameraServiceProxy = new CameraServiceProxyOverride();
216 sCameraServiceProxyWrapper =
217 std::make_shared<CameraServiceProxyWrapper>(sCameraServiceProxy);
218 sCameraService = new CameraService(sCameraServiceProxyWrapper);
219 sCameraService->clearCachedVariables();
220 }
221
TearDownTestSuite()222 static void TearDownTestSuite() {
223 sCameraServiceProxyWrapper = nullptr;
224 sCameraServiceProxy = nullptr;
225 sCameraService = nullptr;
226 setuid(sOldUid);
227 }
228 };
229
230 sp<CameraService> CameraPermissionsTest::sCameraService = nullptr;
231 sp<CameraServiceProxyOverride> CameraPermissionsTest::sCameraServiceProxy = nullptr;
232 std::shared_ptr<CameraServiceProxyWrapper>
233 CameraPermissionsTest::sCameraServiceProxyWrapper = nullptr;
234 uid_t CameraPermissionsTest::sOldUid = 0;
235
236 // Test that camera connections fail with ERROR_DISABLED when the camera is disabled via device
237 // policy, and succeed when it isn't.
TEST_F(CameraPermissionsTest,TestCameraDisabled)238 TEST_F(CameraPermissionsTest, TestCameraDisabled) {
239 AttributionSourceState clientAttribution;
240 clientAttribution.deviceId = kDefaultDeviceId;
241 clientAttribution.uid = android::CameraService::USE_CALLING_UID;
242 clientAttribution.pid = android::CameraService::USE_CALLING_PID;
243
244 std::vector<hardware::CameraStatus> statuses;
245 sp<TestCameraServiceListener> serviceListener = new TestCameraServiceListener();
246 sCameraService->addListenerTest(serviceListener, &statuses);
247 sCameraServiceProxy->setOverrideCameraDisabled(true);
248
249 sCameraServiceProxy->setCameraDisabled(true);
250 for (auto s : statuses) {
251 sp<TestCameraDeviceCallbacks> callbacks = new TestCameraDeviceCallbacks();
252 sp<hardware::camera2::ICameraDeviceUser> device;
253 binder::Status status =
254 sCameraService->connectDevice(callbacks, s.cameraId,
255 0/*oomScoreDiff*/, /*targetSdkVersion*/__ANDROID_API_FUTURE__,
256 hardware::ICameraService::ROTATION_OVERRIDE_NONE,
257 clientAttribution, /*devicePolicy*/0, /*sharedMode*/false, &device);
258 AutoDisconnectDevice autoDisconnect(device);
259 ASSERT_TRUE(!status.isOk()) << "connectDevice returned OK status";
260 ASSERT_EQ(status.serviceSpecificErrorCode(), hardware::ICameraService::ERROR_DISABLED)
261 << "connectDevice returned exception code " << status.exceptionCode();
262 }
263
264 sCameraServiceProxy->setCameraDisabled(false);
265 for (auto s : statuses) {
266 sp<TestCameraDeviceCallbacks> callbacks = new TestCameraDeviceCallbacks();
267 sp<hardware::camera2::ICameraDeviceUser> device;
268 binder::Status status =
269 sCameraService->connectDevice(callbacks, s.cameraId,
270 0/*oomScoreDiff*/, /*targetSdkVersion*/__ANDROID_API_FUTURE__,
271 hardware::ICameraService::ROTATION_OVERRIDE_NONE,
272 clientAttribution, /*devicePolicy*/0, /*sharedMode*/false, &device);
273 AutoDisconnectDevice autoDisconnect(device);
274 ASSERT_TRUE(status.isOk());
275 }
276 }
277
278 // Test that consecutive camera connections succeed.
TEST_F(CameraPermissionsTest,TestConsecutiveConnections)279 TEST_F(CameraPermissionsTest, TestConsecutiveConnections) {
280 AttributionSourceState clientAttribution;
281 clientAttribution.deviceId = kDefaultDeviceId;
282 clientAttribution.uid = android::CameraService::USE_CALLING_UID;
283
284 std::vector<hardware::CameraStatus> statuses;
285 sp<TestCameraServiceListener> serviceListener = new TestCameraServiceListener();
286 sCameraService->addListenerTest(serviceListener, &statuses);
287 sCameraServiceProxy->setOverrideCameraDisabled(false);
288
289 for (auto s : statuses) {
290 sp<TestCameraDeviceCallbacks> callbacks = new TestCameraDeviceCallbacks();
291 sp<hardware::camera2::ICameraDeviceUser> deviceA, deviceB;
292 binder::Status status =
293 sCameraService->connectDevice(callbacks, s.cameraId,
294 0/*oomScoreDiff*/, /*targetSdkVersion*/__ANDROID_API_FUTURE__,
295 hardware::ICameraService::ROTATION_OVERRIDE_NONE,
296 clientAttribution, /*devicePolicy*/0, /*sharedMode*/false, &deviceA);
297 AutoDisconnectDevice autoDisconnectA(deviceA);
298 ASSERT_TRUE(status.isOk()) << "Exception code " << status.exceptionCode() <<
299 " service specific error code " << status.serviceSpecificErrorCode();
300 status =
301 sCameraService->connectDevice(callbacks, s.cameraId,
302 0/*oomScoreDiff*/, /*targetSdkVersion*/__ANDROID_API_FUTURE__,
303 hardware::ICameraService::ROTATION_OVERRIDE_NONE,
304 clientAttribution, /*devicePolicy*/0, /*sharedMode*/false, &deviceB);
305 AutoDisconnectDevice autoDisconnectB(deviceB);
306 ASSERT_TRUE(status.isOk()) << "Exception code " << status.exceptionCode() <<
307 " service specific error code " << status.serviceSpecificErrorCode();
308 }
309 }
310
311 // Test that consecutive camera connections succeed even when a nonzero oomScoreOffset is provided
312 // in the second call.
TEST_F(CameraPermissionsTest,TestConflictingOomScoreOffset)313 TEST_F(CameraPermissionsTest, TestConflictingOomScoreOffset) {
314 AttributionSourceState clientAttribution;
315 clientAttribution.deviceId = kDefaultDeviceId;
316 clientAttribution.uid = android::CameraService::USE_CALLING_UID;
317
318 std::vector<hardware::CameraStatus> statuses;
319 sp<TestCameraServiceListener> serviceListener = new TestCameraServiceListener();
320 sCameraService->addListenerTest(serviceListener, &statuses);
321 sCameraServiceProxy->setOverrideCameraDisabled(false);
322
323 for (auto s : statuses) {
324 sp<TestCameraDeviceCallbacks> callbacks = new TestCameraDeviceCallbacks();
325 sp<hardware::camera2::ICameraDeviceUser> deviceA, deviceB;
326 binder::Status status =
327 sCameraService->connectDevice(callbacks, s.cameraId,
328 0/*oomScoreDiff*/, /*targetSdkVersion*/__ANDROID_API_FUTURE__,
329 hardware::ICameraService::ROTATION_OVERRIDE_NONE,
330 clientAttribution, /*devicePolicy*/0, /*sharedMode*/false, &deviceA);
331 AutoDisconnectDevice autoDisconnectA(deviceA);
332 ASSERT_TRUE(status.isOk()) << "Exception code " << status.exceptionCode() <<
333 " service specific error code " << status.serviceSpecificErrorCode();
334 status =
335 sCameraService->connectDevice(callbacks, s.cameraId,
336 1/*oomScoreDiff*/, /*targetSdkVersion*/__ANDROID_API_FUTURE__,
337 hardware::ICameraService::ROTATION_OVERRIDE_NONE,
338 clientAttribution, /*devicePolicy*/0, /*sharedMode*/false, &deviceB);
339 AutoDisconnectDevice autoDisconnectB(deviceB);
340 ASSERT_TRUE(status.isOk()) << "Exception code " << status.exceptionCode() <<
341 " service specific error code " << status.serviceSpecificErrorCode();
342 }
343 }
344