blob: f713419c4c2e25df397724c19e6671677a54e3b4 [file] [log] [blame]
Emilian Peevb2bc5a42019-11-20 16:02:14 -08001/*
2 * Copyright (C) 2009 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#define LOG_TAG "CameraOfflineClient"
18#define ATRACE_TAG ATRACE_TAG_CAMERA
19//#define LOG_NDEBUG 0
20
21#include "CameraOfflineSessionClient.h"
22#include <utils/Trace.h>
23
24namespace android {
25
26using binder::Status;
27
28status_t CameraOfflineSessionClient::initialize(sp<CameraProviderManager>, const String8&) {
29 return OK;
30}
31
32status_t CameraOfflineSessionClient::dump(int /*fd*/, const Vector<String16>& /*args*/) {
33 return OK;
34}
35
36status_t CameraOfflineSessionClient::dumpClient(int /*fd*/, const Vector<String16>& /*args*/) {
37 return OK;
38}
39
40binder::Status CameraOfflineSessionClient::disconnect() {
41 binder::Status res = Status::ok();
42 if (mDisconnected) {
43 return res;
44 }
45 mDisconnected = true;
46
47 sCameraService->removeByClient(this);
48 sCameraService->logDisconnectedOffline(mCameraIdStr, mClientPid, String8(mClientPackageName));
49
50 sp<IBinder> remote = getRemote();
51 if (remote != nullptr) {
52 remote->unlinkToDeath(sCameraService);
53 }
54
55 finishCameraOps();
56 ALOGI("%s: Disconnected client for offline camera %s for PID %d", __FUNCTION__,
57 mCameraIdStr.string(), mClientPid);
58
59 // client shouldn't be able to call into us anymore
60 mClientPid = 0;
61
Emilian Peev4697b642019-11-19 17:11:14 -080062 for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
63 auto ret = mCompositeStreamMap.valueAt(i)->deleteInternalStreams();
64 if (ret != OK) {
65 ALOGE("%s: Failed removing composite stream %s (%d)", __FUNCTION__,
66 strerror(-ret), ret);
67 }
68 }
69 mCompositeStreamMap.clear();
70
Emilian Peevb2bc5a42019-11-20 16:02:14 -080071 return res;
72}
73
74void CameraOfflineSessionClient::notifyError(int32_t errorCode,
75 const CaptureResultExtras& resultExtras) {
76 // Thread safe. Don't bother locking.
77 sp<hardware::camera2::ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
Emilian Peev4697b642019-11-19 17:11:14 -080078 //
79 // Composites can have multiple internal streams. Error notifications coming from such internal
80 // streams may need to remain within camera service.
81 bool skipClientNotification = false;
82 for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
83 skipClientNotification |= mCompositeStreamMap.valueAt(i)->onError(errorCode, resultExtras);
84 }
85
86 if ((remoteCb != 0) && (!skipClientNotification)) {
Emilian Peevb2bc5a42019-11-20 16:02:14 -080087 remoteCb->onDeviceError(errorCode, resultExtras);
88 }
89}
90
91status_t CameraOfflineSessionClient::startCameraOps() {
92 ATRACE_CALL();
93 {
94 ALOGV("%s: Start camera ops, package name = %s, client UID = %d",
95 __FUNCTION__, String8(mClientPackageName).string(), mClientUid);
96 }
97
98 if (mAppOpsManager != nullptr) {
99 // Notify app ops that the camera is not available
100 mOpsCallback = new OpsCallback(this);
101 int32_t res;
102 // TODO : possibly change this to OP_OFFLINE_CAMERA_SESSION
103 mAppOpsManager->startWatchingMode(AppOpsManager::OP_CAMERA,
104 mClientPackageName, mOpsCallback);
105 // TODO : possibly change this to OP_OFFLINE_CAMERA_SESSION
106 res = mAppOpsManager->startOpNoThrow(AppOpsManager::OP_CAMERA,
107 mClientUid, mClientPackageName, /*startIfModeDefault*/ false);
108
109 if (res == AppOpsManager::MODE_ERRORED) {
110 ALOGI("Offline Camera %s: Access for \"%s\" has been revoked",
111 mCameraIdStr.string(), String8(mClientPackageName).string());
112 return PERMISSION_DENIED;
113 }
114
115 if (res == AppOpsManager::MODE_IGNORED) {
116 ALOGI("Offline Camera %s: Access for \"%s\" has been restricted",
117 mCameraIdStr.string(), String8(mClientPackageName).string());
118 // Return the same error as for device policy manager rejection
119 return -EACCES;
120 }
121 }
122
123 mOpsActive = true;
124
125 // Transition device state to OPEN
126 sCameraService->mUidPolicy->registerMonitorUid(mClientUid);
127
128 return OK;
129}
130
131status_t CameraOfflineSessionClient::finishCameraOps() {
132 ATRACE_CALL();
133
134 // Check if startCameraOps succeeded, and if so, finish the camera op
135 if (mOpsActive) {
136 // Notify app ops that the camera is available again
137 if (mAppOpsManager != nullptr) {
138 // TODO : possibly change this to OP_OFFLINE_CAMERA_SESSION
139 mAppOpsManager->finishOp(AppOpsManager::OP_CAMERA, mClientUid,
140 mClientPackageName);
141 mOpsActive = false;
142 }
143 }
144 // Always stop watching, even if no camera op is active
145 if (mOpsCallback != nullptr && mAppOpsManager != nullptr) {
146 mAppOpsManager->stopWatchingMode(mOpsCallback);
147 }
148 mOpsCallback.clear();
149
150 sCameraService->mUidPolicy->unregisterMonitorUid(mClientUid);
151
152 return OK;
153}
154
Emilian Peev4697b642019-11-19 17:11:14 -0800155void CameraOfflineSessionClient::onResultAvailable(const CaptureResult& result) {
156 ATRACE_CALL();
157 ALOGV("%s", __FUNCTION__);
158
159 // Thread-safe. No lock necessary.
160 sp<hardware::camera2::ICameraDeviceCallbacks> remoteCb = mRemoteCallback;
161 if (remoteCb != NULL) {
162 remoteCb->onResultReceived(result.mMetadata, result.mResultExtras,
163 result.mPhysicalMetadatas);
164 }
165
166 for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
167 mCompositeStreamMap.valueAt(i)->onResultAvailable(result);
168 }
169}
170
171void CameraOfflineSessionClient::notifyShutter(const CaptureResultExtras& resultExtras,
172 nsecs_t timestamp) {
173 // Thread safe. Don't bother locking.
174 sp<hardware::camera2::ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
175 if (remoteCb != 0) {
176 remoteCb->onCaptureStarted(resultExtras, timestamp);
177 }
178
179 for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
180 mCompositeStreamMap.valueAt(i)->onShutter(resultExtras, timestamp);
181 }
182}
183
Emilian Peevb2bc5a42019-11-20 16:02:14 -0800184// ----------------------------------------------------------------------------
185}; // namespace android