• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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/CameraThreadState.h"
23 #include <utils/Trace.h>
24 
25 namespace android {
26 
27 using binder::Status;
28 
initialize(sp<CameraProviderManager>,const String8 &)29 status_t CameraOfflineSessionClient::initialize(sp<CameraProviderManager>, const String8&) {
30     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     String8 threadName;
45     mFrameProcessor = new camera2::FrameProcessorBase(mOfflineSession);
46     threadName = String8::format("Offline-%s-FrameProc", mCameraIdStr.string());
47     mFrameProcessor->run(threadName.string());
48 
49     mFrameProcessor->registerListener(camera2::FrameProcessorBase::FRAME_PROCESSOR_LISTENER_MIN_ID,
50                                       camera2::FrameProcessorBase::FRAME_PROCESSOR_LISTENER_MAX_ID,
51                                       /*listener*/this,
52                                       /*sendPartials*/true);
53 
54     wp<NotificationListener> weakThis(this);
55     res = mOfflineSession->initialize(weakThis);
56     if (res != OK) {
57         ALOGE("%s: Camera %s: unable to initialize device: %s (%d)",
58                 __FUNCTION__, mCameraIdStr.string(), strerror(-res), res);
59         return res;
60     }
61 
62     for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
63         mCompositeStreamMap.valueAt(i)->switchToOffline();
64     }
65 
66     return OK;
67 }
68 
setRotateAndCropOverride(uint8_t)69 status_t CameraOfflineSessionClient::setRotateAndCropOverride(uint8_t /*rotateAndCrop*/) {
70     // Since we're not submitting more capture requests, changes to rotateAndCrop override
71     // make no difference.
72     return OK;
73 }
74 
supportsCameraMute()75 bool CameraOfflineSessionClient::supportsCameraMute() {
76     // Offline mode doesn't support muting
77     return false;
78 }
79 
setCameraMute(bool)80 status_t CameraOfflineSessionClient::setCameraMute(bool) {
81     return INVALID_OPERATION;
82 }
83 
84 
dump(int fd,const Vector<String16> & args)85 status_t CameraOfflineSessionClient::dump(int fd, const Vector<String16>& args) {
86     return BasicClient::dump(fd, args);
87 }
88 
dumpClient(int fd,const Vector<String16> & args)89 status_t CameraOfflineSessionClient::dumpClient(int fd, const Vector<String16>& args) {
90     String8 result;
91 
92     result = "  Offline session dump:\n";
93     write(fd, result.string(), result.size());
94 
95     if (mOfflineSession.get() == nullptr) {
96         result = "  *** Offline session is detached\n";
97         write(fd, result.string(), result.size());
98         return NO_ERROR;
99     }
100 
101     mFrameProcessor->dump(fd, args);
102 
103     auto res = mOfflineSession->dump(fd);
104     if (res != OK) {
105         result = String8::format("   Error dumping offline session: %s (%d)",
106                 strerror(-res), res);
107         write(fd, result.string(), result.size());
108     }
109 
110     return OK;
111 }
112 
disconnect()113 binder::Status CameraOfflineSessionClient::disconnect() {
114     Mutex::Autolock icl(mBinderSerializationLock);
115 
116     binder::Status res = Status::ok();
117     if (mDisconnected) {
118         return res;
119     }
120     // Allow both client and the media server to disconnect at all times
121     int callingPid = CameraThreadState::getCallingPid();
122     if (callingPid != mClientPid &&
123             callingPid != mServicePid) {
124         return res;
125     }
126 
127     mDisconnected = true;
128 
129     sCameraService->removeByClient(this);
130     sCameraService->logDisconnectedOffline(mCameraIdStr, mClientPid, String8(mClientPackageName));
131 
132     sp<IBinder> remote = getRemote();
133     if (remote != nullptr) {
134         remote->unlinkToDeath(sCameraService);
135     }
136 
137     mFrameProcessor->removeListener(camera2::FrameProcessorBase::FRAME_PROCESSOR_LISTENER_MIN_ID,
138                                     camera2::FrameProcessorBase::FRAME_PROCESSOR_LISTENER_MAX_ID,
139                                     /*listener*/this);
140     mFrameProcessor->requestExit();
141     mFrameProcessor->join();
142 
143     finishCameraOps();
144     ALOGI("%s: Disconnected client for offline camera %s for PID %d", __FUNCTION__,
145             mCameraIdStr.string(), mClientPid);
146 
147     // client shouldn't be able to call into us anymore
148     mClientPid = 0;
149 
150     if (mOfflineSession.get() != nullptr) {
151         auto ret = mOfflineSession->disconnect();
152         if (ret != OK) {
153             ALOGE("%s: Failed disconnecting from offline session %s (%d)", __FUNCTION__,
154                     strerror(-ret), ret);
155         }
156         mOfflineSession = nullptr;
157     }
158 
159     for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
160         auto ret = mCompositeStreamMap.valueAt(i)->deleteInternalStreams();
161         if (ret != OK) {
162             ALOGE("%s: Failed removing composite stream  %s (%d)", __FUNCTION__,
163                     strerror(-ret), ret);
164         }
165     }
166     mCompositeStreamMap.clear();
167 
168     return res;
169 }
170 
notifyError(int32_t errorCode,const CaptureResultExtras & resultExtras)171 void CameraOfflineSessionClient::notifyError(int32_t errorCode,
172         const CaptureResultExtras& resultExtras) {
173     // Thread safe. Don't bother locking.
174     // Composites can have multiple internal streams. Error notifications coming from such internal
175     // streams may need to remain within camera service.
176     bool skipClientNotification = false;
177     for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
178         skipClientNotification |= mCompositeStreamMap.valueAt(i)->onError(errorCode, resultExtras);
179     }
180 
181     if ((mRemoteCallback.get() != nullptr) && (!skipClientNotification)) {
182         mRemoteCallback->onDeviceError(errorCode, resultExtras);
183     }
184 }
185 
startCameraOps()186 status_t CameraOfflineSessionClient::startCameraOps() {
187     ATRACE_CALL();
188     {
189         ALOGV("%s: Start camera ops, package name = %s, client UID = %d",
190               __FUNCTION__, String8(mClientPackageName).string(), mClientUid);
191     }
192 
193     if (mAppOpsManager != nullptr) {
194         // Notify app ops that the camera is not available
195         mOpsCallback = new OpsCallback(this);
196         int32_t res;
197         // TODO : possibly change this to OP_OFFLINE_CAMERA_SESSION
198         mAppOpsManager->startWatchingMode(AppOpsManager::OP_CAMERA,
199                 mClientPackageName, mOpsCallback);
200         // TODO : possibly change this to OP_OFFLINE_CAMERA_SESSION
201         res = mAppOpsManager->startOpNoThrow(AppOpsManager::OP_CAMERA,
202                 mClientUid, mClientPackageName, /*startIfModeDefault*/ false);
203 
204         if (res == AppOpsManager::MODE_ERRORED) {
205             ALOGI("Offline Camera %s: Access for \"%s\" has been revoked",
206                     mCameraIdStr.string(), String8(mClientPackageName).string());
207             return PERMISSION_DENIED;
208         }
209 
210         // If the calling Uid is trusted (a native service), the AppOpsManager could
211         // return MODE_IGNORED. Do not treat such case as error.
212         if (!mUidIsTrusted && res == AppOpsManager::MODE_IGNORED) {
213             ALOGI("Offline Camera %s: Access for \"%s\" has been restricted",
214                     mCameraIdStr.string(), String8(mClientPackageName).string());
215             // Return the same error as for device policy manager rejection
216             return -EACCES;
217         }
218     }
219 
220     mOpsActive = true;
221 
222     // Transition device state to OPEN
223     sCameraService->mUidPolicy->registerMonitorUid(mClientUid);
224 
225     return OK;
226 }
227 
finishCameraOps()228 status_t CameraOfflineSessionClient::finishCameraOps() {
229     ATRACE_CALL();
230 
231     // Check if startCameraOps succeeded, and if so, finish the camera op
232     if (mOpsActive) {
233         // Notify app ops that the camera is available again
234         if (mAppOpsManager != nullptr) {
235         // TODO : possibly change this to OP_OFFLINE_CAMERA_SESSION
236             mAppOpsManager->finishOp(AppOpsManager::OP_CAMERA, mClientUid,
237                     mClientPackageName);
238             mOpsActive = false;
239         }
240     }
241     // Always stop watching, even if no camera op is active
242     if (mOpsCallback != nullptr && mAppOpsManager != nullptr) {
243         mAppOpsManager->stopWatchingMode(mOpsCallback);
244     }
245     mOpsCallback.clear();
246 
247     sCameraService->mUidPolicy->unregisterMonitorUid(mClientUid);
248 
249     return OK;
250 }
251 
onResultAvailable(const CaptureResult & result)252 void CameraOfflineSessionClient::onResultAvailable(const CaptureResult& result) {
253     ATRACE_CALL();
254     ALOGV("%s", __FUNCTION__);
255 
256     if (mRemoteCallback.get() != NULL) {
257         mRemoteCallback->onResultReceived(result.mMetadata, result.mResultExtras,
258                 result.mPhysicalMetadatas);
259     }
260 
261     for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
262         mCompositeStreamMap.valueAt(i)->onResultAvailable(result);
263     }
264 }
265 
notifyShutter(const CaptureResultExtras & resultExtras,nsecs_t timestamp)266 void CameraOfflineSessionClient::notifyShutter(const CaptureResultExtras& resultExtras,
267         nsecs_t timestamp) {
268 
269     if (mRemoteCallback.get() != nullptr) {
270         mRemoteCallback->onCaptureStarted(resultExtras, timestamp);
271     }
272 
273     for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
274         mCompositeStreamMap.valueAt(i)->onShutter(resultExtras, timestamp);
275     }
276 }
277 
notifyActive()278 status_t CameraOfflineSessionClient::notifyActive() {
279     return startCameraStreamingOps();
280 }
281 
notifyIdle(int64_t,int64_t,bool,const std::vector<hardware::CameraStreamStats> &)282 void CameraOfflineSessionClient::notifyIdle(
283         int64_t /*requestCount*/, int64_t /*resultErrorCount*/, bool /*deviceError*/,
284         const std::vector<hardware::CameraStreamStats>& /*streamStats*/) {
285     if (mRemoteCallback.get() != nullptr) {
286         mRemoteCallback->onDeviceIdle();
287     }
288     finishCameraStreamingOps();
289 }
290 
notifyAutoFocus(uint8_t newState,int triggerId)291 void CameraOfflineSessionClient::notifyAutoFocus(uint8_t newState, int triggerId) {
292     (void)newState;
293     (void)triggerId;
294 
295     ALOGV("%s: Autofocus state now %d, last trigger %d",
296           __FUNCTION__, newState, triggerId);
297 }
298 
notifyAutoExposure(uint8_t newState,int triggerId)299 void CameraOfflineSessionClient::notifyAutoExposure(uint8_t newState, int triggerId) {
300     (void)newState;
301     (void)triggerId;
302 
303     ALOGV("%s: Autoexposure state now %d, last trigger %d",
304             __FUNCTION__, newState, triggerId);
305 }
306 
notifyAutoWhitebalance(uint8_t newState,int triggerId)307 void CameraOfflineSessionClient::notifyAutoWhitebalance(uint8_t newState, int triggerId) {
308     (void)newState;
309     (void)triggerId;
310 
311     ALOGV("%s: Auto-whitebalance state now %d, last trigger %d", __FUNCTION__, newState,
312             triggerId);
313 }
314 
notifyPrepared(int)315 void CameraOfflineSessionClient::notifyPrepared(int /*streamId*/) {
316     ALOGE("%s: Unexpected stream prepare notification in offline mode!", __FUNCTION__);
317     notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
318                 CaptureResultExtras());
319 }
320 
notifyRequestQueueEmpty()321 void CameraOfflineSessionClient::notifyRequestQueueEmpty() {
322     if (mRemoteCallback.get() != nullptr) {
323         mRemoteCallback->onRequestQueueEmpty();
324     }
325 }
326 
notifyRepeatingRequestError(long)327 void CameraOfflineSessionClient::notifyRepeatingRequestError(long /*lastFrameNumber*/) {
328     ALOGE("%s: Unexpected repeating request error in offline mode!", __FUNCTION__);
329     notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
330                 CaptureResultExtras());
331 }
332 
333 // ----------------------------------------------------------------------------
334 }; // namespace android
335