blob: ea9098728d21c703ade916c06e4433d7524ba5e3 [file] [log] [blame]
Emilian Peevb2bc5a42019-11-20 16:02:14 -08001/*
Emilian Peevd99c8ae2019-11-26 13:19:13 -08002 * Copyright (C) 2019 The Android Open Source Project
Emilian Peevb2bc5a42019-11-20 16:02:14 -08003 *
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#define LOG_TAG "CameraOfflineClient"
18#define ATRACE_TAG ATRACE_TAG_CAMERA
19//#define LOG_NDEBUG 0
20
21#include "CameraOfflineSessionClient.h"
Emilian Peevd99c8ae2019-11-26 13:19:13 -080022#include "utils/CameraThreadState.h"
Emilian Peevb2bc5a42019-11-20 16:02:14 -080023#include <utils/Trace.h>
24
25namespace android {
26
27using binder::Status;
28
29status_t CameraOfflineSessionClient::initialize(sp<CameraProviderManager>, const String8&) {
Emilian Peevd99c8ae2019-11-26 13:19:13 -080030 ATRACE_CALL();
31
32 // Verify ops permissions
33 auto res = startCameraOps();
34 if (res != OK) {
35 return res;
36 }
37
38 if (mOfflineSession.get() == nullptr) {
39 ALOGE("%s: Camera %s: No valid offline session",
40 __FUNCTION__, mCameraIdStr.string());
41 return NO_INIT;
42 }
43
Emilian Peevfaa4bde2020-01-23 12:19:37 -080044 String8 threadName;
45 mFrameProcessor = new camera2::FrameProcessorBase(mOfflineSession);
46 threadName = String8::format("Offline-%s-FrameProc", mCameraIdStr.string());
Austin Borger7b129542022-06-09 13:23:06 -070047 res = mFrameProcessor->run(threadName.string());
48 if (res != OK) {
49 ALOGE("%s: Unable to start frame processor thread: %s (%d)",
50 __FUNCTION__, strerror(-res), res);
51 return res;
52 }
Emilian Peevfaa4bde2020-01-23 12:19:37 -080053
54 mFrameProcessor->registerListener(camera2::FrameProcessorBase::FRAME_PROCESSOR_LISTENER_MIN_ID,
55 camera2::FrameProcessorBase::FRAME_PROCESSOR_LISTENER_MAX_ID,
56 /*listener*/this,
57 /*sendPartials*/true);
58
Emilian Peevd99c8ae2019-11-26 13:19:13 -080059 wp<NotificationListener> weakThis(this);
60 res = mOfflineSession->initialize(weakThis);
61 if (res != OK) {
62 ALOGE("%s: Camera %s: unable to initialize device: %s (%d)",
63 __FUNCTION__, mCameraIdStr.string(), strerror(-res), res);
64 return res;
65 }
66
Emilian Peevc0fe54c2020-03-11 14:05:07 -070067 for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
68 mCompositeStreamMap.valueAt(i)->switchToOffline();
69 }
70
Emilian Peevb2bc5a42019-11-20 16:02:14 -080071 return OK;
72}
73
Ravneetaeb20dc2022-03-30 05:33:03 +000074status_t CameraOfflineSessionClient::setCameraServiceWatchdog(bool) {
75 return OK;
76}
77
Eino-Ville Talvalaf2e37092020-01-07 15:32:32 -080078status_t CameraOfflineSessionClient::setRotateAndCropOverride(uint8_t /*rotateAndCrop*/) {
79 // Since we're not submitting more capture requests, changes to rotateAndCrop override
80 // make no difference.
81 return OK;
82}
83
Bharatt Kukreja7146ced2022-10-25 15:45:29 +000084status_t CameraOfflineSessionClient::setAutoframingOverride(uint8_t) {
85 return OK;
86}
87
Eino-Ville Talvala305cec62020-11-12 14:18:17 -080088bool CameraOfflineSessionClient::supportsCameraMute() {
89 // Offline mode doesn't support muting
90 return false;
91}
92
93status_t CameraOfflineSessionClient::setCameraMute(bool) {
94 return INVALID_OPERATION;
95}
96
97
Emilian Peevd99c8ae2019-11-26 13:19:13 -080098status_t CameraOfflineSessionClient::dump(int fd, const Vector<String16>& args) {
99 return BasicClient::dump(fd, args);
Emilian Peevb2bc5a42019-11-20 16:02:14 -0800100}
101
Emilian Peevfaa4bde2020-01-23 12:19:37 -0800102status_t CameraOfflineSessionClient::dumpClient(int fd, const Vector<String16>& args) {
Emilian Peevd99c8ae2019-11-26 13:19:13 -0800103 String8 result;
104
105 result = " Offline session dump:\n";
106 write(fd, result.string(), result.size());
107
108 if (mOfflineSession.get() == nullptr) {
109 result = " *** Offline session is detached\n";
110 write(fd, result.string(), result.size());
111 return NO_ERROR;
112 }
113
Emilian Peevfaa4bde2020-01-23 12:19:37 -0800114 mFrameProcessor->dump(fd, args);
115
Emilian Peevd99c8ae2019-11-26 13:19:13 -0800116 auto res = mOfflineSession->dump(fd);
117 if (res != OK) {
118 result = String8::format(" Error dumping offline session: %s (%d)",
119 strerror(-res), res);
120 write(fd, result.string(), result.size());
121 }
122
Emilian Peevb2bc5a42019-11-20 16:02:14 -0800123 return OK;
124}
125
Avichal Rakesh7e53cad2021-10-05 13:46:30 -0700126status_t CameraOfflineSessionClient::startWatchingTags(const String8 &tags, int outFd) {
127 return BasicClient::startWatchingTags(tags, outFd);
128}
129
130status_t CameraOfflineSessionClient::stopWatchingTags(int outFd) {
131 return BasicClient::stopWatchingTags(outFd);
132}
133
134status_t CameraOfflineSessionClient::dumpWatchedEventsToVector(std::vector<std::string> &out) {
135 return BasicClient::dumpWatchedEventsToVector(out);
136}
137
Emilian Peevb2bc5a42019-11-20 16:02:14 -0800138binder::Status CameraOfflineSessionClient::disconnect() {
Emilian Peevd99c8ae2019-11-26 13:19:13 -0800139 Mutex::Autolock icl(mBinderSerializationLock);
140
Emilian Peevb2bc5a42019-11-20 16:02:14 -0800141 binder::Status res = Status::ok();
142 if (mDisconnected) {
143 return res;
144 }
Emilian Peevd99c8ae2019-11-26 13:19:13 -0800145 // Allow both client and the media server to disconnect at all times
146 int callingPid = CameraThreadState::getCallingPid();
147 if (callingPid != mClientPid &&
148 callingPid != mServicePid) {
149 return res;
150 }
151
Emilian Peevb2bc5a42019-11-20 16:02:14 -0800152 mDisconnected = true;
153
154 sCameraService->removeByClient(this);
155 sCameraService->logDisconnectedOffline(mCameraIdStr, mClientPid, String8(mClientPackageName));
156
157 sp<IBinder> remote = getRemote();
158 if (remote != nullptr) {
159 remote->unlinkToDeath(sCameraService);
160 }
161
Emilian Peevfaa4bde2020-01-23 12:19:37 -0800162 mFrameProcessor->removeListener(camera2::FrameProcessorBase::FRAME_PROCESSOR_LISTENER_MIN_ID,
163 camera2::FrameProcessorBase::FRAME_PROCESSOR_LISTENER_MAX_ID,
164 /*listener*/this);
165 mFrameProcessor->requestExit();
166 mFrameProcessor->join();
167
Emilian Peevb2bc5a42019-11-20 16:02:14 -0800168 finishCameraOps();
169 ALOGI("%s: Disconnected client for offline camera %s for PID %d", __FUNCTION__,
170 mCameraIdStr.string(), mClientPid);
171
172 // client shouldn't be able to call into us anymore
173 mClientPid = 0;
174
Emilian Peevd99c8ae2019-11-26 13:19:13 -0800175 if (mOfflineSession.get() != nullptr) {
176 auto ret = mOfflineSession->disconnect();
177 if (ret != OK) {
178 ALOGE("%s: Failed disconnecting from offline session %s (%d)", __FUNCTION__,
179 strerror(-ret), ret);
180 }
181 mOfflineSession = nullptr;
182 }
183
Emilian Peev4697b642019-11-19 17:11:14 -0800184 for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
185 auto ret = mCompositeStreamMap.valueAt(i)->deleteInternalStreams();
186 if (ret != OK) {
187 ALOGE("%s: Failed removing composite stream %s (%d)", __FUNCTION__,
188 strerror(-ret), ret);
189 }
190 }
191 mCompositeStreamMap.clear();
192
Emilian Peevb2bc5a42019-11-20 16:02:14 -0800193 return res;
194}
195
196void CameraOfflineSessionClient::notifyError(int32_t errorCode,
197 const CaptureResultExtras& resultExtras) {
198 // Thread safe. Don't bother locking.
Emilian Peev4697b642019-11-19 17:11:14 -0800199 // Composites can have multiple internal streams. Error notifications coming from such internal
200 // streams may need to remain within camera service.
201 bool skipClientNotification = false;
202 for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
203 skipClientNotification |= mCompositeStreamMap.valueAt(i)->onError(errorCode, resultExtras);
204 }
205
Emilian Peevd99c8ae2019-11-26 13:19:13 -0800206 if ((mRemoteCallback.get() != nullptr) && (!skipClientNotification)) {
207 mRemoteCallback->onDeviceError(errorCode, resultExtras);
Emilian Peevb2bc5a42019-11-20 16:02:14 -0800208 }
209}
210
211status_t CameraOfflineSessionClient::startCameraOps() {
212 ATRACE_CALL();
213 {
214 ALOGV("%s: Start camera ops, package name = %s, client UID = %d",
215 __FUNCTION__, String8(mClientPackageName).string(), mClientUid);
216 }
217
218 if (mAppOpsManager != nullptr) {
219 // Notify app ops that the camera is not available
220 mOpsCallback = new OpsCallback(this);
221 int32_t res;
222 // TODO : possibly change this to OP_OFFLINE_CAMERA_SESSION
223 mAppOpsManager->startWatchingMode(AppOpsManager::OP_CAMERA,
224 mClientPackageName, mOpsCallback);
225 // TODO : possibly change this to OP_OFFLINE_CAMERA_SESSION
226 res = mAppOpsManager->startOpNoThrow(AppOpsManager::OP_CAMERA,
227 mClientUid, mClientPackageName, /*startIfModeDefault*/ false);
228
229 if (res == AppOpsManager::MODE_ERRORED) {
230 ALOGI("Offline Camera %s: Access for \"%s\" has been revoked",
231 mCameraIdStr.string(), String8(mClientPackageName).string());
232 return PERMISSION_DENIED;
233 }
234
Shuzhen Wang2c656792020-04-13 17:36:49 -0700235 // If the calling Uid is trusted (a native service), the AppOpsManager could
236 // return MODE_IGNORED. Do not treat such case as error.
237 if (!mUidIsTrusted && res == AppOpsManager::MODE_IGNORED) {
Emilian Peevb2bc5a42019-11-20 16:02:14 -0800238 ALOGI("Offline Camera %s: Access for \"%s\" has been restricted",
239 mCameraIdStr.string(), String8(mClientPackageName).string());
240 // Return the same error as for device policy manager rejection
241 return -EACCES;
242 }
243 }
244
245 mOpsActive = true;
246
247 // Transition device state to OPEN
248 sCameraService->mUidPolicy->registerMonitorUid(mClientUid);
249
250 return OK;
251}
252
253status_t CameraOfflineSessionClient::finishCameraOps() {
254 ATRACE_CALL();
255
256 // Check if startCameraOps succeeded, and if so, finish the camera op
257 if (mOpsActive) {
258 // Notify app ops that the camera is available again
259 if (mAppOpsManager != nullptr) {
260 // TODO : possibly change this to OP_OFFLINE_CAMERA_SESSION
261 mAppOpsManager->finishOp(AppOpsManager::OP_CAMERA, mClientUid,
262 mClientPackageName);
263 mOpsActive = false;
264 }
265 }
266 // Always stop watching, even if no camera op is active
267 if (mOpsCallback != nullptr && mAppOpsManager != nullptr) {
268 mAppOpsManager->stopWatchingMode(mOpsCallback);
269 }
270 mOpsCallback.clear();
271
272 sCameraService->mUidPolicy->unregisterMonitorUid(mClientUid);
273
274 return OK;
275}
276
Emilian Peev4697b642019-11-19 17:11:14 -0800277void CameraOfflineSessionClient::onResultAvailable(const CaptureResult& result) {
278 ATRACE_CALL();
279 ALOGV("%s", __FUNCTION__);
280
Emilian Peevd99c8ae2019-11-26 13:19:13 -0800281 if (mRemoteCallback.get() != NULL) {
282 mRemoteCallback->onResultReceived(result.mMetadata, result.mResultExtras,
Emilian Peev4697b642019-11-19 17:11:14 -0800283 result.mPhysicalMetadatas);
284 }
285
286 for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
287 mCompositeStreamMap.valueAt(i)->onResultAvailable(result);
288 }
289}
290
291void CameraOfflineSessionClient::notifyShutter(const CaptureResultExtras& resultExtras,
292 nsecs_t timestamp) {
Emilian Peevd99c8ae2019-11-26 13:19:13 -0800293
294 if (mRemoteCallback.get() != nullptr) {
295 mRemoteCallback->onCaptureStarted(resultExtras, timestamp);
Emilian Peev4697b642019-11-19 17:11:14 -0800296 }
297
298 for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
299 mCompositeStreamMap.valueAt(i)->onShutter(resultExtras, timestamp);
300 }
301}
302
Austin Borger4a870a32022-02-25 01:48:41 +0000303status_t CameraOfflineSessionClient::notifyActive(float maxPreviewFps __unused) {
Eino-Ville Talvala178e8232021-04-16 18:41:39 -0700304 return startCameraStreamingOps();
305}
306
Shuzhen Wang316781a2020-08-18 18:11:01 -0700307void CameraOfflineSessionClient::notifyIdle(
308 int64_t /*requestCount*/, int64_t /*resultErrorCount*/, bool /*deviceError*/,
309 const std::vector<hardware::CameraStreamStats>& /*streamStats*/) {
Emilian Peevd99c8ae2019-11-26 13:19:13 -0800310 if (mRemoteCallback.get() != nullptr) {
311 mRemoteCallback->onDeviceIdle();
312 }
Eino-Ville Talvala178e8232021-04-16 18:41:39 -0700313 finishCameraStreamingOps();
Emilian Peevd99c8ae2019-11-26 13:19:13 -0800314}
315
316void CameraOfflineSessionClient::notifyAutoFocus(uint8_t newState, int triggerId) {
317 (void)newState;
318 (void)triggerId;
319
320 ALOGV("%s: Autofocus state now %d, last trigger %d",
321 __FUNCTION__, newState, triggerId);
322}
323
324void CameraOfflineSessionClient::notifyAutoExposure(uint8_t newState, int triggerId) {
325 (void)newState;
326 (void)triggerId;
327
328 ALOGV("%s: Autoexposure state now %d, last trigger %d",
329 __FUNCTION__, newState, triggerId);
330}
331
332void CameraOfflineSessionClient::notifyAutoWhitebalance(uint8_t newState, int triggerId) {
333 (void)newState;
334 (void)triggerId;
335
336 ALOGV("%s: Auto-whitebalance state now %d, last trigger %d", __FUNCTION__, newState,
337 triggerId);
338}
339
340void CameraOfflineSessionClient::notifyPrepared(int /*streamId*/) {
341 ALOGE("%s: Unexpected stream prepare notification in offline mode!", __FUNCTION__);
342 notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
343 CaptureResultExtras());
344}
345
346void CameraOfflineSessionClient::notifyRequestQueueEmpty() {
347 if (mRemoteCallback.get() != nullptr) {
348 mRemoteCallback->onRequestQueueEmpty();
349 }
350}
351
352void CameraOfflineSessionClient::notifyRepeatingRequestError(long /*lastFrameNumber*/) {
353 ALOGE("%s: Unexpected repeating request error in offline mode!", __FUNCTION__);
354 notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
355 CaptureResultExtras());
356}
357
Cliff Wud3a05312021-04-26 23:07:31 +0800358status_t CameraOfflineSessionClient::injectCamera(const String8& injectedCamId,
359 sp<CameraProviderManager> manager) {
360 ALOGV("%s: This client doesn't support the injection camera. injectedCamId: %s providerPtr: %p",
361 __FUNCTION__, injectedCamId.string(), manager.get());
362
363 return OK;
364}
365
366status_t CameraOfflineSessionClient::stopInjection() {
367 ALOGV("%s: This client doesn't support the injection camera.", __FUNCTION__);
368
369 return OK;
370}
371
Emilian Peevb2bc5a42019-11-20 16:02:14 -0800372// ----------------------------------------------------------------------------
373}; // namespace android