• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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