blob: 42d99e817ae410fafd64e21196b0ce7f744f265c [file] [log] [blame]
Austin Borger86a588e2022-05-23 12:41:58 -07001/*
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/hardware/BnCameraServiceListener.h>
18#include <android/hardware/BnCameraServiceProxy.h>
19#include <android/hardware/camera2/BnCameraDeviceCallbacks.h>
20#include <android/hardware/ICameraService.h>
21
22#include <private/android_filesystem_config.h>
23
24#include "../CameraService.h"
25#include "../utils/CameraServiceProxyWrapper.h"
26
27#include <gtest/gtest.h>
28
29#include <memory>
30#include <vector>
31
32using namespace android;
33using namespace android::hardware::camera;
34
35// Empty service listener.
36class TestCameraServiceListener : public hardware::BnCameraServiceListener {
37public:
38 virtual ~TestCameraServiceListener() {};
39
40 virtual binder::Status onStatusChanged(int32_t , const String16&) {
41 return binder::Status::ok();
42 };
43
44 virtual binder::Status onPhysicalCameraStatusChanged(int32_t /*status*/,
45 const String16& /*cameraId*/, const String16& /*physicalCameraId*/) {
46 // No op
47 return binder::Status::ok();
48 };
49
50 virtual binder::Status onTorchStatusChanged(int32_t /*status*/, const String16& /*cameraId*/) {
51 return binder::Status::ok();
52 };
53
54 virtual binder::Status onCameraAccessPrioritiesChanged() {
55 // No op
56 return binder::Status::ok();
57 }
58
59 virtual binder::Status onCameraOpened(const String16& /*cameraId*/,
60 const String16& /*clientPackageName*/) {
61 // No op
62 return binder::Status::ok();
63 }
64
65 virtual binder::Status onCameraClosed(const String16& /*cameraId*/) {
66 // No op
67 return binder::Status::ok();
68 }
69
70 virtual binder::Status onTorchStrengthLevelChanged(const String16& /*cameraId*/,
71 int32_t /*torchStrength*/) {
72 // No op
73 return binder::Status::ok();
74 }
75};
76
77// Empty device callback.
78class TestCameraDeviceCallbacks : public hardware::camera2::BnCameraDeviceCallbacks {
79public:
80 TestCameraDeviceCallbacks() {}
81
82 virtual ~TestCameraDeviceCallbacks() {}
83
84 virtual binder::Status onDeviceError(int /*errorCode*/,
85 const CaptureResultExtras& /*resultExtras*/) {
86 return binder::Status::ok();
87 }
88
89 virtual binder::Status onDeviceIdle() {
90 return binder::Status::ok();
91 }
92
93 virtual binder::Status onCaptureStarted(const CaptureResultExtras& /*resultExtras*/,
94 int64_t /*timestamp*/) {
95 return binder::Status::ok();
96 }
97
98 virtual binder::Status onResultReceived(const CameraMetadata& /*metadata*/,
99 const CaptureResultExtras& /*resultExtras*/,
100 const std::vector<PhysicalCaptureResultInfo>& /*physicalResultInfos*/) {
101 return binder::Status::ok();
102 }
103
104 virtual binder::Status onPrepared(int /*streamId*/) {
105 return binder::Status::ok();
106 }
107
108 virtual binder::Status onRepeatingRequestError(
109 int64_t /*lastFrameNumber*/, int32_t /*stoppedSequenceId*/) {
110 return binder::Status::ok();
111 }
112
113 virtual binder::Status onRequestQueueEmpty() {
114 return binder::Status::ok();
115 }
116};
117
118// Override isCameraDisabled from the CameraServiceProxy with a flag.
119class CameraServiceProxyOverride : public ::android::hardware::BnCameraServiceProxy {
120public:
121 CameraServiceProxyOverride() :
122 mCameraServiceProxy(CameraServiceProxyWrapper::getDefaultCameraServiceProxy()),
Greg Kaiserf18ea7c2022-06-06 09:39:00 -0700123 mCameraDisabled(false), mOverrideCameraDisabled(false)
Austin Borger86a588e2022-05-23 12:41:58 -0700124 { }
125
126 virtual binder::Status getRotateAndCropOverride(const String16& packageName, int lensFacing,
127 int userId, int *ret) override {
128 return mCameraServiceProxy->getRotateAndCropOverride(packageName, lensFacing,
129 userId, ret);
130 }
131
132 virtual binder::Status pingForUserUpdate() override {
133 return mCameraServiceProxy->pingForUserUpdate();
134 }
135
136 virtual binder::Status notifyCameraState(
137 const hardware::CameraSessionStats& cameraSessionStats) override {
138 return mCameraServiceProxy->notifyCameraState(cameraSessionStats);
139 }
140
Austin Borger9bfa0a72022-08-03 17:50:40 -0700141 virtual binder::Status isCameraDisabled(int userId, bool *ret) override {
Austin Borger86a588e2022-05-23 12:41:58 -0700142 if (mOverrideCameraDisabled) {
143 *ret = mCameraDisabled;
144 return binder::Status::ok();
145 }
Austin Borger9bfa0a72022-08-03 17:50:40 -0700146 return mCameraServiceProxy->isCameraDisabled(userId, ret);
Austin Borger86a588e2022-05-23 12:41:58 -0700147 }
148
149 void setCameraDisabled(bool cameraDisabled) {
150 mCameraDisabled = cameraDisabled;
151 }
152
153 void setOverrideCameraDisabled(bool overrideCameraDisabled) {
154 mOverrideCameraDisabled = overrideCameraDisabled;
155 }
156
157protected:
158 sp<hardware::ICameraServiceProxy> mCameraServiceProxy;
159 bool mCameraDisabled;
160 bool mOverrideCameraDisabled;
161};
162
163class AutoDisconnectDevice {
164public:
165 AutoDisconnectDevice(sp<hardware::camera2::ICameraDeviceUser> device) :
166 mDevice(device)
167 { }
168
169 ~AutoDisconnectDevice() {
Austin Borger9bfa0a72022-08-03 17:50:40 -0700170 if (mDevice != nullptr) {
Austin Borger86a588e2022-05-23 12:41:58 -0700171 mDevice->disconnect();
172 }
173 }
174
175private:
176 sp<hardware::camera2::ICameraDeviceUser> mDevice;
177};
178
179class CameraPermissionsTest : public ::testing::Test {
180protected:
181 static sp<CameraService> sCameraService;
182 static sp<CameraServiceProxyOverride> sCameraServiceProxy;
183 static std::shared_ptr<CameraServiceProxyWrapper> sCameraServiceProxyWrapper;
184 static uid_t sOldUid;
185
186 static void SetUpTestSuite() {
187 sOldUid = getuid();
188 setuid(AID_CAMERASERVER);
189 sCameraServiceProxy = new CameraServiceProxyOverride();
190 sCameraServiceProxyWrapper =
191 std::make_shared<CameraServiceProxyWrapper>(sCameraServiceProxy);
192 sCameraService = new CameraService(sCameraServiceProxyWrapper);
193 sCameraService->clearCachedVariables();
194 }
195
196 static void TearDownTestSuite() {
197 sCameraServiceProxyWrapper = nullptr;
198 sCameraServiceProxy = nullptr;
199 sCameraService = nullptr;
200 setuid(sOldUid);
201 }
202};
203
204sp<CameraService> CameraPermissionsTest::sCameraService = nullptr;
205sp<CameraServiceProxyOverride> CameraPermissionsTest::sCameraServiceProxy = nullptr;
206std::shared_ptr<CameraServiceProxyWrapper>
207CameraPermissionsTest::sCameraServiceProxyWrapper = nullptr;
208uid_t CameraPermissionsTest::sOldUid = 0;
209
210// Test that camera connections fail with ERROR_DISABLED when the camera is disabled via device
211// policy, and succeed when it isn't.
212TEST_F(CameraPermissionsTest, TestCameraDisabled) {
213 std::vector<hardware::CameraStatus> statuses;
214 sp<TestCameraServiceListener> serviceListener = new TestCameraServiceListener();
215 sCameraService->addListenerTest(serviceListener, &statuses);
216 sCameraServiceProxy->setOverrideCameraDisabled(true);
217
218 sCameraServiceProxy->setCameraDisabled(true);
219 for (auto s : statuses) {
220 sp<TestCameraDeviceCallbacks> callbacks = new TestCameraDeviceCallbacks();
221 sp<hardware::camera2::ICameraDeviceUser> device;
222 binder::Status status =
223 sCameraService->connectDevice(callbacks, String16(s.cameraId), String16(), {},
224 android::CameraService::USE_CALLING_UID, 0/*oomScoreDiff*/,
225 /*targetSdkVersion*/__ANDROID_API_FUTURE__, &device);
226 AutoDisconnectDevice autoDisconnect(device);
227 ASSERT_TRUE(!status.isOk()) << "connectDevice returned OK status";
228 ASSERT_EQ(status.serviceSpecificErrorCode(), hardware::ICameraService::ERROR_DISABLED)
229 << "connectDevice returned exception code " << status.exceptionCode();
230 }
231
232 sCameraServiceProxy->setCameraDisabled(false);
233 for (auto s : statuses) {
234 sp<TestCameraDeviceCallbacks> callbacks = new TestCameraDeviceCallbacks();
235 sp<hardware::camera2::ICameraDeviceUser> device;
236 binder::Status status =
237 sCameraService->connectDevice(callbacks, String16(s.cameraId), String16(), {},
238 android::CameraService::USE_CALLING_UID, 0/*oomScoreDiff*/,
239 /*targetSdkVersion*/__ANDROID_API_FUTURE__, &device);
240 AutoDisconnectDevice autoDisconnect(device);
241 ASSERT_TRUE(status.isOk());
242 }
243}
244
245// Test that consecutive camera connections succeed.
246TEST_F(CameraPermissionsTest, TestConsecutiveConnections) {
247 std::vector<hardware::CameraStatus> statuses;
248 sp<TestCameraServiceListener> serviceListener = new TestCameraServiceListener();
249 sCameraService->addListenerTest(serviceListener, &statuses);
250 sCameraServiceProxy->setOverrideCameraDisabled(false);
251
252 for (auto s : statuses) {
253 sp<TestCameraDeviceCallbacks> callbacks = new TestCameraDeviceCallbacks();
254 sp<hardware::camera2::ICameraDeviceUser> deviceA, deviceB;
255 binder::Status status =
256 sCameraService->connectDevice(callbacks, String16(s.cameraId), String16(), {},
257 android::CameraService::USE_CALLING_UID, 0/*oomScoreDiff*/,
258 /*targetSdkVersion*/__ANDROID_API_FUTURE__, &deviceA);
259 AutoDisconnectDevice autoDisconnectA(deviceA);
260 ASSERT_TRUE(status.isOk()) << "Exception code " << status.exceptionCode() <<
261 " service specific error code " << status.serviceSpecificErrorCode();
262 status =
263 sCameraService->connectDevice(callbacks, String16(s.cameraId), String16(), {},
264 android::CameraService::USE_CALLING_UID, 0/*oomScoreDiff*/,
265 /*targetSdkVersion*/__ANDROID_API_FUTURE__, &deviceB);
266 AutoDisconnectDevice autoDisconnectB(deviceB);
267 ASSERT_TRUE(status.isOk()) << "Exception code " << status.exceptionCode() <<
268 " service specific error code " << status.serviceSpecificErrorCode();
269 }
270}
271
272// Test that consecutive camera connections succeed even when a nonzero oomScoreOffset is provided
273// in the second call.
274TEST_F(CameraPermissionsTest, TestConflictingOomScoreOffset) {
275 std::vector<hardware::CameraStatus> statuses;
276 sp<TestCameraServiceListener> serviceListener = new TestCameraServiceListener();
277 sCameraService->addListenerTest(serviceListener, &statuses);
278 sCameraServiceProxy->setOverrideCameraDisabled(false);
279
280 for (auto s : statuses) {
281 sp<TestCameraDeviceCallbacks> callbacks = new TestCameraDeviceCallbacks();
282 sp<hardware::camera2::ICameraDeviceUser> deviceA, deviceB;
283 binder::Status status =
284 sCameraService->connectDevice(callbacks, String16(s.cameraId), String16(), {},
285 android::CameraService::USE_CALLING_UID, 0/*oomScoreDiff*/,
286 /*targetSdkVersion*/__ANDROID_API_FUTURE__, &deviceA);
287 AutoDisconnectDevice autoDisconnectA(deviceA);
288 ASSERT_TRUE(status.isOk()) << "Exception code " << status.exceptionCode() <<
289 " service specific error code " << status.serviceSpecificErrorCode();
290 status =
291 sCameraService->connectDevice(callbacks, String16(s.cameraId), String16(), {},
292 android::CameraService::USE_CALLING_UID, 1/*oomScoreDiff*/,
293 /*targetSdkVersion*/__ANDROID_API_FUTURE__, &deviceB);
294 AutoDisconnectDevice autoDisconnectB(deviceB);
295 ASSERT_TRUE(status.isOk()) << "Exception code " << status.exceptionCode() <<
296 " service specific error code " << status.serviceSpecificErrorCode();
297 }
298}