blob: c260cfed75e0cda39db8498abe8a49d697847508 [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
Shuzhen Wang16610a62022-12-15 22:38:07 -080097void CameraOfflineSessionClient::setStreamUseCaseOverrides(
98 const std::vector<int64_t>& /*useCaseOverrides*/) {
99}
100
101void CameraOfflineSessionClient::clearStreamUseCaseOverrides() {
102}
103
Eino-Ville Talvala305cec62020-11-12 14:18:17 -0800104
Emilian Peevd99c8ae2019-11-26 13:19:13 -0800105status_t CameraOfflineSessionClient::dump(int fd, const Vector<String16>& args) {
106 return BasicClient::dump(fd, args);
Emilian Peevb2bc5a42019-11-20 16:02:14 -0800107}
108
Emilian Peevfaa4bde2020-01-23 12:19:37 -0800109status_t CameraOfflineSessionClient::dumpClient(int fd, const Vector<String16>& args) {
Emilian Peevd99c8ae2019-11-26 13:19:13 -0800110 String8 result;
111
112 result = " Offline session dump:\n";
113 write(fd, result.string(), result.size());
114
115 if (mOfflineSession.get() == nullptr) {
116 result = " *** Offline session is detached\n";
117 write(fd, result.string(), result.size());
118 return NO_ERROR;
119 }
120
Emilian Peevfaa4bde2020-01-23 12:19:37 -0800121 mFrameProcessor->dump(fd, args);
122
Emilian Peevd99c8ae2019-11-26 13:19:13 -0800123 auto res = mOfflineSession->dump(fd);
124 if (res != OK) {
125 result = String8::format(" Error dumping offline session: %s (%d)",
126 strerror(-res), res);
127 write(fd, result.string(), result.size());
128 }
129
Emilian Peevb2bc5a42019-11-20 16:02:14 -0800130 return OK;
131}
132
Avichal Rakesh7e53cad2021-10-05 13:46:30 -0700133status_t CameraOfflineSessionClient::startWatchingTags(const String8 &tags, int outFd) {
134 return BasicClient::startWatchingTags(tags, outFd);
135}
136
137status_t CameraOfflineSessionClient::stopWatchingTags(int outFd) {
138 return BasicClient::stopWatchingTags(outFd);
139}
140
141status_t CameraOfflineSessionClient::dumpWatchedEventsToVector(std::vector<std::string> &out) {
142 return BasicClient::dumpWatchedEventsToVector(out);
143}
144
Emilian Peevb2bc5a42019-11-20 16:02:14 -0800145binder::Status CameraOfflineSessionClient::disconnect() {
Emilian Peevd99c8ae2019-11-26 13:19:13 -0800146 Mutex::Autolock icl(mBinderSerializationLock);
147
Emilian Peevb2bc5a42019-11-20 16:02:14 -0800148 binder::Status res = Status::ok();
149 if (mDisconnected) {
150 return res;
151 }
Emilian Peevd99c8ae2019-11-26 13:19:13 -0800152 // Allow both client and the media server to disconnect at all times
153 int callingPid = CameraThreadState::getCallingPid();
154 if (callingPid != mClientPid &&
155 callingPid != mServicePid) {
156 return res;
157 }
158
Emilian Peevb2bc5a42019-11-20 16:02:14 -0800159 mDisconnected = true;
160
161 sCameraService->removeByClient(this);
162 sCameraService->logDisconnectedOffline(mCameraIdStr, mClientPid, String8(mClientPackageName));
163
164 sp<IBinder> remote = getRemote();
165 if (remote != nullptr) {
166 remote->unlinkToDeath(sCameraService);
167 }
168
Emilian Peevfaa4bde2020-01-23 12:19:37 -0800169 mFrameProcessor->removeListener(camera2::FrameProcessorBase::FRAME_PROCESSOR_LISTENER_MIN_ID,
170 camera2::FrameProcessorBase::FRAME_PROCESSOR_LISTENER_MAX_ID,
171 /*listener*/this);
172 mFrameProcessor->requestExit();
173 mFrameProcessor->join();
174
Emilian Peevb2bc5a42019-11-20 16:02:14 -0800175 finishCameraOps();
176 ALOGI("%s: Disconnected client for offline camera %s for PID %d", __FUNCTION__,
177 mCameraIdStr.string(), mClientPid);
178
179 // client shouldn't be able to call into us anymore
180 mClientPid = 0;
181
Emilian Peevd99c8ae2019-11-26 13:19:13 -0800182 if (mOfflineSession.get() != nullptr) {
183 auto ret = mOfflineSession->disconnect();
184 if (ret != OK) {
185 ALOGE("%s: Failed disconnecting from offline session %s (%d)", __FUNCTION__,
186 strerror(-ret), ret);
187 }
188 mOfflineSession = nullptr;
189 }
190
Emilian Peev4697b642019-11-19 17:11:14 -0800191 for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
192 auto ret = mCompositeStreamMap.valueAt(i)->deleteInternalStreams();
193 if (ret != OK) {
194 ALOGE("%s: Failed removing composite stream %s (%d)", __FUNCTION__,
195 strerror(-ret), ret);
196 }
197 }
198 mCompositeStreamMap.clear();
199
Emilian Peevb2bc5a42019-11-20 16:02:14 -0800200 return res;
201}
202
203void CameraOfflineSessionClient::notifyError(int32_t errorCode,
204 const CaptureResultExtras& resultExtras) {
205 // Thread safe. Don't bother locking.
Emilian Peev4697b642019-11-19 17:11:14 -0800206 // Composites can have multiple internal streams. Error notifications coming from such internal
207 // streams may need to remain within camera service.
208 bool skipClientNotification = false;
209 for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
210 skipClientNotification |= mCompositeStreamMap.valueAt(i)->onError(errorCode, resultExtras);
211 }
212
Emilian Peevd99c8ae2019-11-26 13:19:13 -0800213 if ((mRemoteCallback.get() != nullptr) && (!skipClientNotification)) {
214 mRemoteCallback->onDeviceError(errorCode, resultExtras);
Emilian Peevb2bc5a42019-11-20 16:02:14 -0800215 }
216}
217
218status_t CameraOfflineSessionClient::startCameraOps() {
219 ATRACE_CALL();
220 {
221 ALOGV("%s: Start camera ops, package name = %s, client UID = %d",
222 __FUNCTION__, String8(mClientPackageName).string(), mClientUid);
223 }
224
225 if (mAppOpsManager != nullptr) {
226 // Notify app ops that the camera is not available
227 mOpsCallback = new OpsCallback(this);
228 int32_t res;
229 // TODO : possibly change this to OP_OFFLINE_CAMERA_SESSION
230 mAppOpsManager->startWatchingMode(AppOpsManager::OP_CAMERA,
231 mClientPackageName, mOpsCallback);
232 // TODO : possibly change this to OP_OFFLINE_CAMERA_SESSION
233 res = mAppOpsManager->startOpNoThrow(AppOpsManager::OP_CAMERA,
234 mClientUid, mClientPackageName, /*startIfModeDefault*/ false);
235
236 if (res == AppOpsManager::MODE_ERRORED) {
237 ALOGI("Offline Camera %s: Access for \"%s\" has been revoked",
238 mCameraIdStr.string(), String8(mClientPackageName).string());
239 return PERMISSION_DENIED;
240 }
241
Shuzhen Wang2c656792020-04-13 17:36:49 -0700242 // If the calling Uid is trusted (a native service), the AppOpsManager could
243 // return MODE_IGNORED. Do not treat such case as error.
244 if (!mUidIsTrusted && res == AppOpsManager::MODE_IGNORED) {
Emilian Peevb2bc5a42019-11-20 16:02:14 -0800245 ALOGI("Offline Camera %s: Access for \"%s\" has been restricted",
246 mCameraIdStr.string(), String8(mClientPackageName).string());
247 // Return the same error as for device policy manager rejection
248 return -EACCES;
249 }
250 }
251
252 mOpsActive = true;
253
254 // Transition device state to OPEN
255 sCameraService->mUidPolicy->registerMonitorUid(mClientUid);
256
257 return OK;
258}
259
260status_t CameraOfflineSessionClient::finishCameraOps() {
261 ATRACE_CALL();
262
263 // Check if startCameraOps succeeded, and if so, finish the camera op
264 if (mOpsActive) {
265 // Notify app ops that the camera is available again
266 if (mAppOpsManager != nullptr) {
267 // TODO : possibly change this to OP_OFFLINE_CAMERA_SESSION
268 mAppOpsManager->finishOp(AppOpsManager::OP_CAMERA, mClientUid,
269 mClientPackageName);
270 mOpsActive = false;
271 }
272 }
273 // Always stop watching, even if no camera op is active
274 if (mOpsCallback != nullptr && mAppOpsManager != nullptr) {
275 mAppOpsManager->stopWatchingMode(mOpsCallback);
276 }
277 mOpsCallback.clear();
278
279 sCameraService->mUidPolicy->unregisterMonitorUid(mClientUid);
280
281 return OK;
282}
283
Emilian Peev4697b642019-11-19 17:11:14 -0800284void CameraOfflineSessionClient::onResultAvailable(const CaptureResult& result) {
285 ATRACE_CALL();
286 ALOGV("%s", __FUNCTION__);
287
Emilian Peevd99c8ae2019-11-26 13:19:13 -0800288 if (mRemoteCallback.get() != NULL) {
289 mRemoteCallback->onResultReceived(result.mMetadata, result.mResultExtras,
Emilian Peev4697b642019-11-19 17:11:14 -0800290 result.mPhysicalMetadatas);
291 }
292
293 for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
294 mCompositeStreamMap.valueAt(i)->onResultAvailable(result);
295 }
296}
297
298void CameraOfflineSessionClient::notifyShutter(const CaptureResultExtras& resultExtras,
299 nsecs_t timestamp) {
Emilian Peevd99c8ae2019-11-26 13:19:13 -0800300
301 if (mRemoteCallback.get() != nullptr) {
302 mRemoteCallback->onCaptureStarted(resultExtras, timestamp);
Emilian Peev4697b642019-11-19 17:11:14 -0800303 }
304
305 for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
306 mCompositeStreamMap.valueAt(i)->onShutter(resultExtras, timestamp);
307 }
308}
309
Austin Borger4a870a32022-02-25 01:48:41 +0000310status_t CameraOfflineSessionClient::notifyActive(float maxPreviewFps __unused) {
Eino-Ville Talvala178e8232021-04-16 18:41:39 -0700311 return startCameraStreamingOps();
312}
313
Shuzhen Wang316781a2020-08-18 18:11:01 -0700314void CameraOfflineSessionClient::notifyIdle(
315 int64_t /*requestCount*/, int64_t /*resultErrorCount*/, bool /*deviceError*/,
316 const std::vector<hardware::CameraStreamStats>& /*streamStats*/) {
Emilian Peevd99c8ae2019-11-26 13:19:13 -0800317 if (mRemoteCallback.get() != nullptr) {
318 mRemoteCallback->onDeviceIdle();
319 }
Eino-Ville Talvala178e8232021-04-16 18:41:39 -0700320 finishCameraStreamingOps();
Emilian Peevd99c8ae2019-11-26 13:19:13 -0800321}
322
323void CameraOfflineSessionClient::notifyAutoFocus(uint8_t newState, int triggerId) {
324 (void)newState;
325 (void)triggerId;
326
327 ALOGV("%s: Autofocus state now %d, last trigger %d",
328 __FUNCTION__, newState, triggerId);
329}
330
331void CameraOfflineSessionClient::notifyAutoExposure(uint8_t newState, int triggerId) {
332 (void)newState;
333 (void)triggerId;
334
335 ALOGV("%s: Autoexposure state now %d, last trigger %d",
336 __FUNCTION__, newState, triggerId);
337}
338
339void CameraOfflineSessionClient::notifyAutoWhitebalance(uint8_t newState, int triggerId) {
340 (void)newState;
341 (void)triggerId;
342
343 ALOGV("%s: Auto-whitebalance state now %d, last trigger %d", __FUNCTION__, newState,
344 triggerId);
345}
346
347void CameraOfflineSessionClient::notifyPrepared(int /*streamId*/) {
348 ALOGE("%s: Unexpected stream prepare notification in offline mode!", __FUNCTION__);
349 notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
350 CaptureResultExtras());
351}
352
353void CameraOfflineSessionClient::notifyRequestQueueEmpty() {
354 if (mRemoteCallback.get() != nullptr) {
355 mRemoteCallback->onRequestQueueEmpty();
356 }
357}
358
359void CameraOfflineSessionClient::notifyRepeatingRequestError(long /*lastFrameNumber*/) {
360 ALOGE("%s: Unexpected repeating request error in offline mode!", __FUNCTION__);
361 notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
362 CaptureResultExtras());
363}
364
Cliff Wud3a05312021-04-26 23:07:31 +0800365status_t CameraOfflineSessionClient::injectCamera(const String8& injectedCamId,
366 sp<CameraProviderManager> manager) {
367 ALOGV("%s: This client doesn't support the injection camera. injectedCamId: %s providerPtr: %p",
368 __FUNCTION__, injectedCamId.string(), manager.get());
369
370 return OK;
371}
372
373status_t CameraOfflineSessionClient::stopInjection() {
374 ALOGV("%s: This client doesn't support the injection camera.", __FUNCTION__);
375
376 return OK;
377}
378
Emilian Peevb2bc5a42019-11-20 16:02:14 -0800379// ----------------------------------------------------------------------------
380}; // namespace android