blob: af7b9e18dc4dffc3a12e25d3788f3ef338c57f5c [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
44 wp<NotificationListener> weakThis(this);
45 res = mOfflineSession->initialize(weakThis);
46 if (res != OK) {
47 ALOGE("%s: Camera %s: unable to initialize device: %s (%d)",
48 __FUNCTION__, mCameraIdStr.string(), strerror(-res), res);
49 return res;
50 }
51
Emilian Peevb2bc5a42019-11-20 16:02:14 -080052 return OK;
53}
54
Emilian Peevd99c8ae2019-11-26 13:19:13 -080055status_t CameraOfflineSessionClient::dump(int fd, const Vector<String16>& args) {
56 return BasicClient::dump(fd, args);
Emilian Peevb2bc5a42019-11-20 16:02:14 -080057}
58
Emilian Peevd99c8ae2019-11-26 13:19:13 -080059status_t CameraOfflineSessionClient::dumpClient(int fd, const Vector<String16>& /*args*/) {
60 String8 result;
61
62 result = " Offline session dump:\n";
63 write(fd, result.string(), result.size());
64
65 if (mOfflineSession.get() == nullptr) {
66 result = " *** Offline session is detached\n";
67 write(fd, result.string(), result.size());
68 return NO_ERROR;
69 }
70
71 auto res = mOfflineSession->dump(fd);
72 if (res != OK) {
73 result = String8::format(" Error dumping offline session: %s (%d)",
74 strerror(-res), res);
75 write(fd, result.string(), result.size());
76 }
77
Emilian Peevb2bc5a42019-11-20 16:02:14 -080078 return OK;
79}
80
81binder::Status CameraOfflineSessionClient::disconnect() {
Emilian Peevd99c8ae2019-11-26 13:19:13 -080082 Mutex::Autolock icl(mBinderSerializationLock);
83
Emilian Peevb2bc5a42019-11-20 16:02:14 -080084 binder::Status res = Status::ok();
85 if (mDisconnected) {
86 return res;
87 }
Emilian Peevd99c8ae2019-11-26 13:19:13 -080088 // Allow both client and the media server to disconnect at all times
89 int callingPid = CameraThreadState::getCallingPid();
90 if (callingPid != mClientPid &&
91 callingPid != mServicePid) {
92 return res;
93 }
94
Emilian Peevb2bc5a42019-11-20 16:02:14 -080095 mDisconnected = true;
96
97 sCameraService->removeByClient(this);
98 sCameraService->logDisconnectedOffline(mCameraIdStr, mClientPid, String8(mClientPackageName));
99
100 sp<IBinder> remote = getRemote();
101 if (remote != nullptr) {
102 remote->unlinkToDeath(sCameraService);
103 }
104
105 finishCameraOps();
106 ALOGI("%s: Disconnected client for offline camera %s for PID %d", __FUNCTION__,
107 mCameraIdStr.string(), mClientPid);
108
109 // client shouldn't be able to call into us anymore
110 mClientPid = 0;
111
Emilian Peevd99c8ae2019-11-26 13:19:13 -0800112 if (mOfflineSession.get() != nullptr) {
113 auto ret = mOfflineSession->disconnect();
114 if (ret != OK) {
115 ALOGE("%s: Failed disconnecting from offline session %s (%d)", __FUNCTION__,
116 strerror(-ret), ret);
117 }
118 mOfflineSession = nullptr;
119 }
120
Emilian Peev4697b642019-11-19 17:11:14 -0800121 for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
122 auto ret = mCompositeStreamMap.valueAt(i)->deleteInternalStreams();
123 if (ret != OK) {
124 ALOGE("%s: Failed removing composite stream %s (%d)", __FUNCTION__,
125 strerror(-ret), ret);
126 }
127 }
128 mCompositeStreamMap.clear();
129
Emilian Peevb2bc5a42019-11-20 16:02:14 -0800130 return res;
131}
132
133void CameraOfflineSessionClient::notifyError(int32_t errorCode,
134 const CaptureResultExtras& resultExtras) {
135 // Thread safe. Don't bother locking.
Emilian Peev4697b642019-11-19 17:11:14 -0800136 // Composites can have multiple internal streams. Error notifications coming from such internal
137 // streams may need to remain within camera service.
138 bool skipClientNotification = false;
139 for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
140 skipClientNotification |= mCompositeStreamMap.valueAt(i)->onError(errorCode, resultExtras);
141 }
142
Emilian Peevd99c8ae2019-11-26 13:19:13 -0800143 if ((mRemoteCallback.get() != nullptr) && (!skipClientNotification)) {
144 mRemoteCallback->onDeviceError(errorCode, resultExtras);
Emilian Peevb2bc5a42019-11-20 16:02:14 -0800145 }
146}
147
148status_t CameraOfflineSessionClient::startCameraOps() {
149 ATRACE_CALL();
150 {
151 ALOGV("%s: Start camera ops, package name = %s, client UID = %d",
152 __FUNCTION__, String8(mClientPackageName).string(), mClientUid);
153 }
154
155 if (mAppOpsManager != nullptr) {
156 // Notify app ops that the camera is not available
157 mOpsCallback = new OpsCallback(this);
158 int32_t res;
159 // TODO : possibly change this to OP_OFFLINE_CAMERA_SESSION
160 mAppOpsManager->startWatchingMode(AppOpsManager::OP_CAMERA,
161 mClientPackageName, mOpsCallback);
162 // TODO : possibly change this to OP_OFFLINE_CAMERA_SESSION
163 res = mAppOpsManager->startOpNoThrow(AppOpsManager::OP_CAMERA,
164 mClientUid, mClientPackageName, /*startIfModeDefault*/ false);
165
166 if (res == AppOpsManager::MODE_ERRORED) {
167 ALOGI("Offline Camera %s: Access for \"%s\" has been revoked",
168 mCameraIdStr.string(), String8(mClientPackageName).string());
169 return PERMISSION_DENIED;
170 }
171
172 if (res == AppOpsManager::MODE_IGNORED) {
173 ALOGI("Offline Camera %s: Access for \"%s\" has been restricted",
174 mCameraIdStr.string(), String8(mClientPackageName).string());
175 // Return the same error as for device policy manager rejection
176 return -EACCES;
177 }
178 }
179
180 mOpsActive = true;
181
182 // Transition device state to OPEN
183 sCameraService->mUidPolicy->registerMonitorUid(mClientUid);
184
185 return OK;
186}
187
188status_t CameraOfflineSessionClient::finishCameraOps() {
189 ATRACE_CALL();
190
191 // Check if startCameraOps succeeded, and if so, finish the camera op
192 if (mOpsActive) {
193 // Notify app ops that the camera is available again
194 if (mAppOpsManager != nullptr) {
195 // TODO : possibly change this to OP_OFFLINE_CAMERA_SESSION
196 mAppOpsManager->finishOp(AppOpsManager::OP_CAMERA, mClientUid,
197 mClientPackageName);
198 mOpsActive = false;
199 }
200 }
201 // Always stop watching, even if no camera op is active
202 if (mOpsCallback != nullptr && mAppOpsManager != nullptr) {
203 mAppOpsManager->stopWatchingMode(mOpsCallback);
204 }
205 mOpsCallback.clear();
206
207 sCameraService->mUidPolicy->unregisterMonitorUid(mClientUid);
208
209 return OK;
210}
211
Emilian Peev4697b642019-11-19 17:11:14 -0800212void CameraOfflineSessionClient::onResultAvailable(const CaptureResult& result) {
213 ATRACE_CALL();
214 ALOGV("%s", __FUNCTION__);
215
Emilian Peevd99c8ae2019-11-26 13:19:13 -0800216 if (mRemoteCallback.get() != NULL) {
217 mRemoteCallback->onResultReceived(result.mMetadata, result.mResultExtras,
Emilian Peev4697b642019-11-19 17:11:14 -0800218 result.mPhysicalMetadatas);
219 }
220
221 for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
222 mCompositeStreamMap.valueAt(i)->onResultAvailable(result);
223 }
224}
225
226void CameraOfflineSessionClient::notifyShutter(const CaptureResultExtras& resultExtras,
227 nsecs_t timestamp) {
Emilian Peevd99c8ae2019-11-26 13:19:13 -0800228
229 if (mRemoteCallback.get() != nullptr) {
230 mRemoteCallback->onCaptureStarted(resultExtras, timestamp);
Emilian Peev4697b642019-11-19 17:11:14 -0800231 }
232
233 for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
234 mCompositeStreamMap.valueAt(i)->onShutter(resultExtras, timestamp);
235 }
236}
237
Emilian Peevd99c8ae2019-11-26 13:19:13 -0800238void CameraOfflineSessionClient::notifyIdle() {
239 if (mRemoteCallback.get() != nullptr) {
240 mRemoteCallback->onDeviceIdle();
241 }
242}
243
244void CameraOfflineSessionClient::notifyAutoFocus(uint8_t newState, int triggerId) {
245 (void)newState;
246 (void)triggerId;
247
248 ALOGV("%s: Autofocus state now %d, last trigger %d",
249 __FUNCTION__, newState, triggerId);
250}
251
252void CameraOfflineSessionClient::notifyAutoExposure(uint8_t newState, int triggerId) {
253 (void)newState;
254 (void)triggerId;
255
256 ALOGV("%s: Autoexposure state now %d, last trigger %d",
257 __FUNCTION__, newState, triggerId);
258}
259
260void CameraOfflineSessionClient::notifyAutoWhitebalance(uint8_t newState, int triggerId) {
261 (void)newState;
262 (void)triggerId;
263
264 ALOGV("%s: Auto-whitebalance state now %d, last trigger %d", __FUNCTION__, newState,
265 triggerId);
266}
267
268void CameraOfflineSessionClient::notifyPrepared(int /*streamId*/) {
269 ALOGE("%s: Unexpected stream prepare notification in offline mode!", __FUNCTION__);
270 notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
271 CaptureResultExtras());
272}
273
274void CameraOfflineSessionClient::notifyRequestQueueEmpty() {
275 if (mRemoteCallback.get() != nullptr) {
276 mRemoteCallback->onRequestQueueEmpty();
277 }
278}
279
280void CameraOfflineSessionClient::notifyRepeatingRequestError(long /*lastFrameNumber*/) {
281 ALOGE("%s: Unexpected repeating request error in offline mode!", __FUNCTION__);
282 notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
283 CaptureResultExtras());
284}
285
Emilian Peevb2bc5a42019-11-20 16:02:14 -0800286// ----------------------------------------------------------------------------
287}; // namespace android