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
notifyWatchdog(int pid,bool isNative)175 virtual binder::Status notifyWatchdog(int pid, bool isNative) override {
176 return mCameraServiceProxy->notifyWatchdog(pid, isNative);
177 }
178
setCameraDisabled(bool cameraDisabled)179 void setCameraDisabled(bool cameraDisabled) {
180 mCameraDisabled = cameraDisabled;
181 }
182
setOverrideCameraDisabled(bool overrideCameraDisabled)183 void setOverrideCameraDisabled(bool overrideCameraDisabled) {
184 mOverrideCameraDisabled = overrideCameraDisabled;
185 }
186
187 protected:
188 sp<hardware::ICameraServiceProxy> mCameraServiceProxy;
189 bool mCameraDisabled;
190 bool mOverrideCameraDisabled;
191 };
192
193 class AutoDisconnectDevice {
194 public:
AutoDisconnectDevice(sp<hardware::camera2::ICameraDeviceUser> device)195 AutoDisconnectDevice(sp<hardware::camera2::ICameraDeviceUser> device) :
196 mDevice(device)
197 { }
198
~AutoDisconnectDevice()199 ~AutoDisconnectDevice() {
200 if (mDevice != nullptr) {
201 mDevice->disconnect();
202 }
203 }
204
205 private:
206 sp<hardware::camera2::ICameraDeviceUser> mDevice;
207 };
208
209 class CameraPermissionsTest : public ::testing::Test {
210 protected:
211 static sp<CameraService> sCameraService;
212 static sp<CameraServiceProxyOverride> sCameraServiceProxy;
213 static std::shared_ptr<CameraServiceProxyWrapper> sCameraServiceProxyWrapper;
214 static uid_t sOldUid;
215
SetUpTestSuite()216 static void SetUpTestSuite() {
217 sOldUid = getuid();
218 setuid(AID_CAMERASERVER);
219 sCameraServiceProxy = new CameraServiceProxyOverride();
220 sCameraServiceProxyWrapper =
221 std::make_shared<CameraServiceProxyWrapper>(sCameraServiceProxy);
222 sCameraService = new CameraService(sCameraServiceProxyWrapper);
223 sCameraService->clearCachedVariables();
224 }
225
TearDownTestSuite()226 static void TearDownTestSuite() {
227 sCameraServiceProxyWrapper = nullptr;
228 sCameraServiceProxy = nullptr;
229 sCameraService = nullptr;
230 setuid(sOldUid);
231 }
232 };
233
234 sp<CameraService> CameraPermissionsTest::sCameraService = nullptr;
235 sp<CameraServiceProxyOverride> CameraPermissionsTest::sCameraServiceProxy = nullptr;
236 std::shared_ptr<CameraServiceProxyWrapper>
237 CameraPermissionsTest::sCameraServiceProxyWrapper = nullptr;
238 uid_t CameraPermissionsTest::sOldUid = 0;
239
240 // Test that camera connections fail with ERROR_DISABLED when the camera is disabled via device
241 // policy, and succeed when it isn't.
TEST_F(CameraPermissionsTest,TestCameraDisabled)242 TEST_F(CameraPermissionsTest, TestCameraDisabled) {
243 AttributionSourceState clientAttribution;
244 clientAttribution.deviceId = kDefaultDeviceId;
245 clientAttribution.uid = android::CameraService::USE_CALLING_UID;
246 clientAttribution.pid = android::CameraService::USE_CALLING_PID;
247
248 std::vector<hardware::CameraStatus> statuses;
249 sp<TestCameraServiceListener> serviceListener = new TestCameraServiceListener();
250 sCameraService->addListenerTest(serviceListener, &statuses);
251 sCameraServiceProxy->setOverrideCameraDisabled(true);
252
253 sCameraServiceProxy->setCameraDisabled(true);
254 for (auto s : statuses) {
255 sp<TestCameraDeviceCallbacks> callbacks = new TestCameraDeviceCallbacks();
256 sp<hardware::camera2::ICameraDeviceUser> device;
257 binder::Status status =
258 sCameraService->connectDevice(callbacks, s.cameraId,
259 0/*oomScoreDiff*/, /*targetSdkVersion*/__ANDROID_API_FUTURE__,
260 hardware::ICameraService::ROTATION_OVERRIDE_NONE,
261 clientAttribution, /*devicePolicy*/0, /*sharedMode*/false, &device);
262 AutoDisconnectDevice autoDisconnect(device);
263 ASSERT_TRUE(!status.isOk()) << "connectDevice returned OK status";
264 ASSERT_EQ(status.serviceSpecificErrorCode(), hardware::ICameraService::ERROR_DISABLED)
265 << "connectDevice returned exception code " << status.exceptionCode();
266 }
267
268 sCameraServiceProxy->setCameraDisabled(false);
269 for (auto s : statuses) {
270 sp<TestCameraDeviceCallbacks> callbacks = new TestCameraDeviceCallbacks();
271 sp<hardware::camera2::ICameraDeviceUser> device;
272 binder::Status status =
273 sCameraService->connectDevice(callbacks, s.cameraId,
274 0/*oomScoreDiff*/, /*targetSdkVersion*/__ANDROID_API_FUTURE__,
275 hardware::ICameraService::ROTATION_OVERRIDE_NONE,
276 clientAttribution, /*devicePolicy*/0, /*sharedMode*/false, &device);
277 AutoDisconnectDevice autoDisconnect(device);
278 ASSERT_TRUE(status.isOk());
279 }
280 }
281
282 // Test that consecutive camera connections succeed.
TEST_F(CameraPermissionsTest,TestConsecutiveConnections)283 TEST_F(CameraPermissionsTest, TestConsecutiveConnections) {
284 AttributionSourceState clientAttribution;
285 clientAttribution.deviceId = kDefaultDeviceId;
286 clientAttribution.uid = android::CameraService::USE_CALLING_UID;
287
288 std::vector<hardware::CameraStatus> statuses;
289 sp<TestCameraServiceListener> serviceListener = new TestCameraServiceListener();
290 sCameraService->addListenerTest(serviceListener, &statuses);
291 sCameraServiceProxy->setOverrideCameraDisabled(false);
292
293 for (auto s : statuses) {
294 sp<TestCameraDeviceCallbacks> callbacks = new TestCameraDeviceCallbacks();
295 sp<hardware::camera2::ICameraDeviceUser> deviceA, deviceB;
296 binder::Status status =
297 sCameraService->connectDevice(callbacks, s.cameraId,
298 0/*oomScoreDiff*/, /*targetSdkVersion*/__ANDROID_API_FUTURE__,
299 hardware::ICameraService::ROTATION_OVERRIDE_NONE,
300 clientAttribution, /*devicePolicy*/0, /*sharedMode*/false, &deviceA);
301 AutoDisconnectDevice autoDisconnectA(deviceA);
302 ASSERT_TRUE(status.isOk()) << "Exception code " << status.exceptionCode() <<
303 " service specific error code " << status.serviceSpecificErrorCode();
304 status =
305 sCameraService->connectDevice(callbacks, s.cameraId,
306 0/*oomScoreDiff*/, /*targetSdkVersion*/__ANDROID_API_FUTURE__,
307 hardware::ICameraService::ROTATION_OVERRIDE_NONE,
308 clientAttribution, /*devicePolicy*/0, /*sharedMode*/false, &deviceB);
309 AutoDisconnectDevice autoDisconnectB(deviceB);
310 ASSERT_TRUE(status.isOk()) << "Exception code " << status.exceptionCode() <<
311 " service specific error code " << status.serviceSpecificErrorCode();
312 }
313 }
314
315 // Test that consecutive camera connections succeed even when a nonzero oomScoreOffset is provided
316 // in the second call.
TEST_F(CameraPermissionsTest,TestConflictingOomScoreOffset)317 TEST_F(CameraPermissionsTest, TestConflictingOomScoreOffset) {
318 AttributionSourceState clientAttribution;
319 clientAttribution.deviceId = kDefaultDeviceId;
320 clientAttribution.uid = android::CameraService::USE_CALLING_UID;
321
322 std::vector<hardware::CameraStatus> statuses;
323 sp<TestCameraServiceListener> serviceListener = new TestCameraServiceListener();
324 sCameraService->addListenerTest(serviceListener, &statuses);
325 sCameraServiceProxy->setOverrideCameraDisabled(false);
326
327 for (auto s : statuses) {
328 sp<TestCameraDeviceCallbacks> callbacks = new TestCameraDeviceCallbacks();
329 sp<hardware::camera2::ICameraDeviceUser> deviceA, deviceB;
330 binder::Status status =
331 sCameraService->connectDevice(callbacks, s.cameraId,
332 0/*oomScoreDiff*/, /*targetSdkVersion*/__ANDROID_API_FUTURE__,
333 hardware::ICameraService::ROTATION_OVERRIDE_NONE,
334 clientAttribution, /*devicePolicy*/0, /*sharedMode*/false, &deviceA);
335 AutoDisconnectDevice autoDisconnectA(deviceA);
336 ASSERT_TRUE(status.isOk()) << "Exception code " << status.exceptionCode() <<
337 " service specific error code " << status.serviceSpecificErrorCode();
338 status =
339 sCameraService->connectDevice(callbacks, s.cameraId,
340 1/*oomScoreDiff*/, /*targetSdkVersion*/__ANDROID_API_FUTURE__,
341 hardware::ICameraService::ROTATION_OVERRIDE_NONE,
342 clientAttribution, /*devicePolicy*/0, /*sharedMode*/false, &deviceB);
343 AutoDisconnectDevice autoDisconnectB(deviceB);
344 ASSERT_TRUE(status.isOk()) << "Exception code " << status.exceptionCode() <<
345 " service specific error code " << status.serviceSpecificErrorCode();
346 }
347 }
348