blob: 731eebfcc8474087ad6b0534c8290c00eb1d4d21 [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
Bharatt Kukreja7146ced2022-10-25 15:45:29 +0000132 virtual binder::Status getAutoframingOverride(const String16& packageName, int *ret) override {
133 return mCameraServiceProxy->getAutoframingOverride(packageName, ret);
134 }
135
Austin Borger86a588e2022-05-23 12:41:58 -0700136 virtual binder::Status pingForUserUpdate() override {
137 return mCameraServiceProxy->pingForUserUpdate();
138 }
139
140 virtual binder::Status notifyCameraState(
141 const hardware::CameraSessionStats& cameraSessionStats) override {
142 return mCameraServiceProxy->notifyCameraState(cameraSessionStats);
143 }
144
Austin Borger9bfa0a72022-08-03 17:50:40 -0700145 virtual binder::Status isCameraDisabled(int userId, bool *ret) override {
Austin Borger86a588e2022-05-23 12:41:58 -0700146 if (mOverrideCameraDisabled) {
147 *ret = mCameraDisabled;
148 return binder::Status::ok();
149 }
Austin Borger9bfa0a72022-08-03 17:50:40 -0700150 return mCameraServiceProxy->isCameraDisabled(userId, ret);
Austin Borger86a588e2022-05-23 12:41:58 -0700151 }
152
153 void setCameraDisabled(bool cameraDisabled) {
154 mCameraDisabled = cameraDisabled;
155 }
156
157 void setOverrideCameraDisabled(bool overrideCameraDisabled) {
158 mOverrideCameraDisabled = overrideCameraDisabled;
159 }
160
161protected:
162 sp<hardware::ICameraServiceProxy> mCameraServiceProxy;
163 bool mCameraDisabled;
164 bool mOverrideCameraDisabled;
165};
166
167class AutoDisconnectDevice {
168public:
169 AutoDisconnectDevice(sp<hardware::camera2::ICameraDeviceUser> device) :
170 mDevice(device)
171 { }
172
173 ~AutoDisconnectDevice() {
Austin Borger9bfa0a72022-08-03 17:50:40 -0700174 if (mDevice != nullptr) {
Austin Borger86a588e2022-05-23 12:41:58 -0700175 mDevice->disconnect();
176 }
177 }
178
179private:
180 sp<hardware::camera2::ICameraDeviceUser> mDevice;
181};
182
183class CameraPermissionsTest : public ::testing::Test {
184protected:
185 static sp<CameraService> sCameraService;
186 static sp<CameraServiceProxyOverride> sCameraServiceProxy;
187 static std::shared_ptr<CameraServiceProxyWrapper> sCameraServiceProxyWrapper;
188 static uid_t sOldUid;
189
190 static void SetUpTestSuite() {
191 sOldUid = getuid();
192 setuid(AID_CAMERASERVER);
193 sCameraServiceProxy = new CameraServiceProxyOverride();
194 sCameraServiceProxyWrapper =
195 std::make_shared<CameraServiceProxyWrapper>(sCameraServiceProxy);
196 sCameraService = new CameraService(sCameraServiceProxyWrapper);
197 sCameraService->clearCachedVariables();
198 }
199
200 static void TearDownTestSuite() {
201 sCameraServiceProxyWrapper = nullptr;
202 sCameraServiceProxy = nullptr;
203 sCameraService = nullptr;
204 setuid(sOldUid);
205 }
206};
207
208sp<CameraService> CameraPermissionsTest::sCameraService = nullptr;
209sp<CameraServiceProxyOverride> CameraPermissionsTest::sCameraServiceProxy = nullptr;
210std::shared_ptr<CameraServiceProxyWrapper>
211CameraPermissionsTest::sCameraServiceProxyWrapper = nullptr;
212uid_t CameraPermissionsTest::sOldUid = 0;
213
214// Test that camera connections fail with ERROR_DISABLED when the camera is disabled via device
215// policy, and succeed when it isn't.
216TEST_F(CameraPermissionsTest, TestCameraDisabled) {
217 std::vector<hardware::CameraStatus> statuses;
218 sp<TestCameraServiceListener> serviceListener = new TestCameraServiceListener();
219 sCameraService->addListenerTest(serviceListener, &statuses);
220 sCameraServiceProxy->setOverrideCameraDisabled(true);
221
222 sCameraServiceProxy->setCameraDisabled(true);
223 for (auto s : statuses) {
224 sp<TestCameraDeviceCallbacks> callbacks = new TestCameraDeviceCallbacks();
225 sp<hardware::camera2::ICameraDeviceUser> device;
226 binder::Status status =
227 sCameraService->connectDevice(callbacks, String16(s.cameraId), String16(), {},
228 android::CameraService::USE_CALLING_UID, 0/*oomScoreDiff*/,
Austin Borger18b30a72022-10-27 12:20:29 -0700229 /*targetSdkVersion*/__ANDROID_API_FUTURE__, /*overrideToPortrait*/false, &device);
Austin Borger86a588e2022-05-23 12:41:58 -0700230 AutoDisconnectDevice autoDisconnect(device);
231 ASSERT_TRUE(!status.isOk()) << "connectDevice returned OK status";
232 ASSERT_EQ(status.serviceSpecificErrorCode(), hardware::ICameraService::ERROR_DISABLED)
233 << "connectDevice returned exception code " << status.exceptionCode();
234 }
235
236 sCameraServiceProxy->setCameraDisabled(false);
237 for (auto s : statuses) {
238 sp<TestCameraDeviceCallbacks> callbacks = new TestCameraDeviceCallbacks();
239 sp<hardware::camera2::ICameraDeviceUser> device;
240 binder::Status status =
241 sCameraService->connectDevice(callbacks, String16(s.cameraId), String16(), {},
242 android::CameraService::USE_CALLING_UID, 0/*oomScoreDiff*/,
Austin Borger18b30a72022-10-27 12:20:29 -0700243 /*targetSdkVersion*/__ANDROID_API_FUTURE__, /*overrideToPortrait*/false, &device);
Austin Borger86a588e2022-05-23 12:41:58 -0700244 AutoDisconnectDevice autoDisconnect(device);
245 ASSERT_TRUE(status.isOk());
246 }
247}
248
249// Test that consecutive camera connections succeed.
250TEST_F(CameraPermissionsTest, TestConsecutiveConnections) {
251 std::vector<hardware::CameraStatus> statuses;
252 sp<TestCameraServiceListener> serviceListener = new TestCameraServiceListener();
253 sCameraService->addListenerTest(serviceListener, &statuses);
254 sCameraServiceProxy->setOverrideCameraDisabled(false);
255
256 for (auto s : statuses) {
257 sp<TestCameraDeviceCallbacks> callbacks = new TestCameraDeviceCallbacks();
258 sp<hardware::camera2::ICameraDeviceUser> deviceA, deviceB;
259 binder::Status status =
260 sCameraService->connectDevice(callbacks, String16(s.cameraId), String16(), {},
261 android::CameraService::USE_CALLING_UID, 0/*oomScoreDiff*/,
Austin Borger18b30a72022-10-27 12:20:29 -0700262 /*targetSdkVersion*/__ANDROID_API_FUTURE__, /*overrideToPortrait*/false, &deviceA);
Austin Borger86a588e2022-05-23 12:41:58 -0700263 AutoDisconnectDevice autoDisconnectA(deviceA);
264 ASSERT_TRUE(status.isOk()) << "Exception code " << status.exceptionCode() <<
265 " service specific error code " << status.serviceSpecificErrorCode();
266 status =
267 sCameraService->connectDevice(callbacks, String16(s.cameraId), String16(), {},
268 android::CameraService::USE_CALLING_UID, 0/*oomScoreDiff*/,
Austin Borger18b30a72022-10-27 12:20:29 -0700269 /*targetSdkVersion*/__ANDROID_API_FUTURE__, /*overrideToPortrait*/false, &deviceB);
Austin Borger86a588e2022-05-23 12:41:58 -0700270 AutoDisconnectDevice autoDisconnectB(deviceB);
271 ASSERT_TRUE(status.isOk()) << "Exception code " << status.exceptionCode() <<
272 " service specific error code " << status.serviceSpecificErrorCode();
273 }
274}
275
276// Test that consecutive camera connections succeed even when a nonzero oomScoreOffset is provided
277// in the second call.
278TEST_F(CameraPermissionsTest, TestConflictingOomScoreOffset) {
279 std::vector<hardware::CameraStatus> statuses;
280 sp<TestCameraServiceListener> serviceListener = new TestCameraServiceListener();
281 sCameraService->addListenerTest(serviceListener, &statuses);
282 sCameraServiceProxy->setOverrideCameraDisabled(false);
283
284 for (auto s : statuses) {
285 sp<TestCameraDeviceCallbacks> callbacks = new TestCameraDeviceCallbacks();
286 sp<hardware::camera2::ICameraDeviceUser> deviceA, deviceB;
287 binder::Status status =
288 sCameraService->connectDevice(callbacks, String16(s.cameraId), String16(), {},
289 android::CameraService::USE_CALLING_UID, 0/*oomScoreDiff*/,
Austin Borger18b30a72022-10-27 12:20:29 -0700290 /*targetSdkVersion*/__ANDROID_API_FUTURE__, /*overrideToPortrait*/false, &deviceA);
Austin Borger86a588e2022-05-23 12:41:58 -0700291 AutoDisconnectDevice autoDisconnectA(deviceA);
292 ASSERT_TRUE(status.isOk()) << "Exception code " << status.exceptionCode() <<
293 " service specific error code " << status.serviceSpecificErrorCode();
294 status =
295 sCameraService->connectDevice(callbacks, String16(s.cameraId), String16(), {},
296 android::CameraService::USE_CALLING_UID, 1/*oomScoreDiff*/,
Austin Borger18b30a72022-10-27 12:20:29 -0700297 /*targetSdkVersion*/__ANDROID_API_FUTURE__, /*overrideToPortrait*/false, &deviceB);
Austin Borger86a588e2022-05-23 12:41:58 -0700298 AutoDisconnectDevice autoDisconnectB(deviceB);
299 ASSERT_TRUE(status.isOk()) << "Exception code " << status.exceptionCode() <<
300 " service specific error code " << status.serviceSpecificErrorCode();
301 }
302}