1 /*
2  * Copyright (C) 2020 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 "CameraServiceProxyWrapper"
18 #define ATRACE_TAG ATRACE_TAG_CAMERA
19 //#define LOG_NDEBUG 0
20 
21 #include <inttypes.h>
22 #include <utils/Log.h>
23 #include <binder/IServiceManager.h>
24 
25 #include "CameraServiceProxyWrapper.h"
26 
27 namespace android {
28 
29 using hardware::CameraExtensionSessionStats;
30 using hardware::CameraSessionStats;
31 using hardware::ICameraServiceProxy;
32 
33 namespace {
34 // Sentinel value to be returned when extension session with a stale or invalid key is reported.
35 const String16 POISON_EXT_STATS_KEY("poisoned_stats");
36 } // anonymous namespace
37 
38 /**
39  * CameraSessionStatsWrapper functions
40  */
41 
updateProxyDeviceState(sp<hardware::ICameraServiceProxy> & proxyBinder)42 void CameraServiceProxyWrapper::CameraSessionStatsWrapper::updateProxyDeviceState(
43         sp<hardware::ICameraServiceProxy>& proxyBinder) {
44     if (proxyBinder == nullptr) return;
45     proxyBinder->notifyCameraState(mSessionStats);
46 }
47 
onOpen(sp<hardware::ICameraServiceProxy> & proxyBinder)48 void CameraServiceProxyWrapper::CameraSessionStatsWrapper::onOpen(
49         sp<hardware::ICameraServiceProxy>& proxyBinder) {
50     Mutex::Autolock l(mLock);
51     updateProxyDeviceState(proxyBinder);
52 }
53 
onClose(sp<hardware::ICameraServiceProxy> & proxyBinder,int32_t latencyMs,bool deviceError)54 void CameraServiceProxyWrapper::CameraSessionStatsWrapper::onClose(
55     sp<hardware::ICameraServiceProxy>& proxyBinder, int32_t latencyMs,
56     bool deviceError) {
57     Mutex::Autolock l(mLock);
58 
59     mSessionStats.mNewCameraState = CameraSessionStats::CAMERA_STATE_CLOSED;
60     mSessionStats.mLatencyMs = latencyMs;
61     mSessionStats.mDeviceError = deviceError;
62     mSessionStats.mSessionIndex = 0;
63     updateProxyDeviceState(proxyBinder);
64 }
65 
onStreamConfigured(int operatingMode,bool internalReconfig,int32_t latencyMs)66 void CameraServiceProxyWrapper::CameraSessionStatsWrapper::onStreamConfigured(
67         int operatingMode, bool internalReconfig, int32_t latencyMs) {
68     Mutex::Autolock l(mLock);
69 
70     if (internalReconfig) {
71         mSessionStats.mInternalReconfigure++;
72     } else {
73         mSessionStats.mLatencyMs = latencyMs;
74         mSessionStats.mSessionType = operatingMode;
75     }
76 }
77 
onActive(sp<hardware::ICameraServiceProxy> & proxyBinder,float maxPreviewFps)78 void CameraServiceProxyWrapper::CameraSessionStatsWrapper::onActive(
79     sp<hardware::ICameraServiceProxy>& proxyBinder, float maxPreviewFps) {
80     Mutex::Autolock l(mLock);
81 
82     mSessionStats.mNewCameraState = CameraSessionStats::CAMERA_STATE_ACTIVE;
83     mSessionStats.mMaxPreviewFps = maxPreviewFps;
84     mSessionStats.mSessionIndex++;
85     updateProxyDeviceState(proxyBinder);
86 
87     // Reset mCreationDuration to -1 to distinguish between 1st session
88     // after configuration, and all other sessions after configuration.
89     mSessionStats.mLatencyMs = -1;
90 }
91 
onIdle(sp<hardware::ICameraServiceProxy> & proxyBinder,int64_t requestCount,int64_t resultErrorCount,bool deviceError,const std::string & userTag,int32_t videoStabilizationMode,const std::vector<hardware::CameraStreamStats> & streamStats)92 void CameraServiceProxyWrapper::CameraSessionStatsWrapper::onIdle(
93         sp<hardware::ICameraServiceProxy>& proxyBinder,
94         int64_t requestCount, int64_t resultErrorCount, bool deviceError,
95         const std::string& userTag, int32_t videoStabilizationMode,
96         const std::vector<hardware::CameraStreamStats>& streamStats) {
97     Mutex::Autolock l(mLock);
98 
99     mSessionStats.mNewCameraState = CameraSessionStats::CAMERA_STATE_IDLE;
100     mSessionStats.mRequestCount = requestCount;
101     mSessionStats.mResultErrorCount = resultErrorCount;
102     mSessionStats.mDeviceError = deviceError;
103     mSessionStats.mUserTag = String16(userTag.c_str());
104     mSessionStats.mVideoStabilizationMode = videoStabilizationMode;
105     mSessionStats.mStreamStats = streamStats;
106 
107     updateProxyDeviceState(proxyBinder);
108 
109     mSessionStats.mInternalReconfigure = 0;
110     mSessionStats.mStreamStats.clear();
111     mSessionStats.mCameraExtensionSessionStats = {};
112 }
113 
getLogId()114 int64_t CameraServiceProxyWrapper::CameraSessionStatsWrapper::getLogId() {
115     Mutex::Autolock l(mLock);
116     return mSessionStats.mLogId;
117 }
118 
updateExtensionSessionStats(const hardware::CameraExtensionSessionStats & extStats)119 String16 CameraServiceProxyWrapper::CameraSessionStatsWrapper::updateExtensionSessionStats(
120         const hardware::CameraExtensionSessionStats& extStats) {
121     Mutex::Autolock l(mLock);
122     CameraExtensionSessionStats& currStats = mSessionStats.mCameraExtensionSessionStats;
123     if (currStats.key != extStats.key) {
124         // Mismatched keys. Extensions stats likely reported for a closed session
125         ALOGW("%s: mismatched extensions stats key: current='%s' reported='%s'. Dropping stats.",
126               __FUNCTION__, String8(currStats.key).c_str(), String8(extStats.key).c_str());
127         return POISON_EXT_STATS_KEY; // return poisoned key to so future calls are
128                                      // definitely dropped.
129     }
130 
131     // Matching keys...
132     if (currStats.key.size()) {
133         // non-empty matching keys. overwrite.
134         ALOGV("%s: Overwriting extension session stats: %s", __FUNCTION__,
135               extStats.toString().c_str());
136         currStats = extStats;
137         return currStats.key;
138     }
139 
140     // Matching empty keys...
141     if (mSessionStats.mClientName != extStats.clientName) {
142         ALOGW("%s: extension stats reported for unexpected package: current='%s' reported='%s'. "
143               "Dropping stats.", __FUNCTION__,
144               String8(mSessionStats.mClientName).c_str(),
145               String8(extStats.clientName).c_str());
146         return POISON_EXT_STATS_KEY;
147     }
148 
149     // Matching empty keys for the current client...
150     if (mSessionStats.mNewCameraState == CameraSessionStats::CAMERA_STATE_OPEN ||
151         mSessionStats.mNewCameraState == CameraSessionStats::CAMERA_STATE_IDLE) {
152         // Camera is open, but not active. It is possible that the active callback hasn't
153         // occurred yet. Keep the stats, but don't associate it with any session.
154         ALOGV("%s: extension stat reported for an open, but not active camera. "
155               "Saving stats, but not generating key.", __FUNCTION__);
156         currStats = extStats;
157         return {}; // Subsequent calls will handle setting the correct key.
158     }
159 
160     if (mSessionStats.mNewCameraState == CameraSessionStats::CAMERA_STATE_ACTIVE) {
161         // camera is active. First call for the session!
162         currStats = extStats;
163 
164         // Generate a new key from logId and sessionIndex.
165         std::ostringstream key;
166         key << mSessionStats.mSessionIndex << '/' << mSessionStats.mLogId;
167         currStats.key = String16(key.str().c_str());
168         ALOGV("%s: New extension session stats: %s", __FUNCTION__, currStats.toString().c_str());
169         return currStats.key;
170     }
171 
172     // Camera is closed. Probably a stale call.
173     ALOGW("%s: extension stats reported for closed camera id '%s'. Dropping stats.",
174           __FUNCTION__, String8(mSessionStats.mCameraId).c_str());
175     return {};
176 }
177 
178 /**
179  * CameraServiceProxyWrapper functions
180  */
181 
getCameraServiceProxy()182 sp<ICameraServiceProxy> CameraServiceProxyWrapper::getCameraServiceProxy() {
183 #ifndef __BRILLO__
184     Mutex::Autolock al(mProxyMutex);
185     if (mCameraServiceProxy == nullptr) {
186         mCameraServiceProxy = getDefaultCameraServiceProxy();
187     }
188 #endif
189     return mCameraServiceProxy;
190 }
191 
getDefaultCameraServiceProxy()192 sp<hardware::ICameraServiceProxy> CameraServiceProxyWrapper::getDefaultCameraServiceProxy() {
193 #ifndef __BRILLO__
194     sp<IServiceManager> sm = defaultServiceManager();
195     // Use checkService because cameraserver normally starts before the
196     // system server and the proxy service. So the long timeout that getService
197     // has before giving up is inappropriate.
198     sp<IBinder> binder = sm->checkService(String16("media.camera.proxy"));
199     if (binder != nullptr) {
200         return interface_cast<ICameraServiceProxy>(binder);
201     }
202 #endif
203     return nullptr;
204 }
205 
pingCameraServiceProxy()206 void CameraServiceProxyWrapper::pingCameraServiceProxy() {
207     sp<ICameraServiceProxy> proxyBinder = getCameraServiceProxy();
208     if (proxyBinder == nullptr) return;
209     proxyBinder->pingForUserUpdate();
210 }
211 
getRotateAndCropOverride(String16 packageName,int lensFacing,int userId)212 int CameraServiceProxyWrapper::getRotateAndCropOverride(String16 packageName, int lensFacing,
213         int userId) {
214     sp<ICameraServiceProxy> proxyBinder = getCameraServiceProxy();
215     if (proxyBinder == nullptr) return true;
216     int ret = 0;
217     auto status = proxyBinder->getRotateAndCropOverride(packageName, lensFacing, userId, &ret);
218     if (!status.isOk()) {
219         ALOGE("%s: Failed during top activity orientation query: %s", __FUNCTION__,
220                 status.exceptionMessage().c_str());
221     }
222 
223     return ret;
224 }
225 
getAutoframingOverride(const String16 & packageName)226 int CameraServiceProxyWrapper::getAutoframingOverride(const String16& packageName) {
227     sp<ICameraServiceProxy> proxyBinder = getCameraServiceProxy();
228     if (proxyBinder == nullptr) {
229         return ANDROID_CONTROL_AUTOFRAMING_OFF;
230     }
231     int ret = 0;
232     auto status = proxyBinder->getAutoframingOverride(packageName, &ret);
233     if (!status.isOk()) {
234         ALOGE("%s: Failed during autoframing override query: %s", __FUNCTION__,
235                 status.exceptionMessage().c_str());
236     }
237 
238     return ret;
239 }
240 
logStreamConfigured(const String8 & id,int operatingMode,bool internalConfig,int32_t latencyMs)241 void CameraServiceProxyWrapper::logStreamConfigured(const String8& id,
242         int operatingMode, bool internalConfig, int32_t latencyMs) {
243     std::shared_ptr<CameraSessionStatsWrapper> sessionStats;
244     {
245         Mutex::Autolock l(mLock);
246         if (mSessionStatsMap.count(id) == 0) {
247             ALOGE("%s: SessionStatsMap should contain camera %s",
248                     __FUNCTION__, id.c_str());
249             return;
250         }
251         sessionStats = mSessionStatsMap[id];
252     }
253 
254     ALOGV("%s: id %s, operatingMode %d, internalConfig %d, latencyMs %d",
255             __FUNCTION__, id.c_str(), operatingMode, internalConfig, latencyMs);
256     sessionStats->onStreamConfigured(operatingMode, internalConfig, latencyMs);
257 }
258 
logActive(const String8 & id,float maxPreviewFps)259 void CameraServiceProxyWrapper::logActive(const String8& id, float maxPreviewFps) {
260     std::shared_ptr<CameraSessionStatsWrapper> sessionStats;
261     {
262         Mutex::Autolock l(mLock);
263         if (mSessionStatsMap.count(id) == 0) {
264             ALOGE("%s: SessionStatsMap should contain camera %s when logActive is called",
265                     __FUNCTION__, id.c_str());
266             return;
267         }
268         sessionStats = mSessionStatsMap[id];
269     }
270 
271     ALOGV("%s: id %s", __FUNCTION__, id.c_str());
272     sp<hardware::ICameraServiceProxy> proxyBinder = getCameraServiceProxy();
273     sessionStats->onActive(proxyBinder, maxPreviewFps);
274 }
275 
logIdle(const String8 & id,int64_t requestCount,int64_t resultErrorCount,bool deviceError,const std::string & userTag,int32_t videoStabilizationMode,const std::vector<hardware::CameraStreamStats> & streamStats)276 void CameraServiceProxyWrapper::logIdle(const String8& id,
277         int64_t requestCount, int64_t resultErrorCount, bool deviceError,
278         const std::string& userTag, int32_t videoStabilizationMode,
279         const std::vector<hardware::CameraStreamStats>& streamStats) {
280     std::shared_ptr<CameraSessionStatsWrapper> sessionStats;
281     {
282         Mutex::Autolock l(mLock);
283         if (mSessionStatsMap.count(id) == 0) {
284             ALOGE("%s: SessionStatsMap should contain camera %s when logIdle is called",
285                 __FUNCTION__, id.c_str());
286             return;
287         }
288         sessionStats = mSessionStatsMap[id];
289     }
290 
291     ALOGV("%s: id %s, requestCount %" PRId64 ", resultErrorCount %" PRId64 ", deviceError %d"
292             ", userTag %s, videoStabilizationMode %d", __FUNCTION__, id.c_str(), requestCount,
293             resultErrorCount, deviceError, userTag.c_str(), videoStabilizationMode);
294     for (size_t i = 0; i < streamStats.size(); i++) {
295         ALOGV("%s: streamStats[%zu]: w %d h %d, requestedCount %" PRId64 ", dropCount %"
296                 PRId64 ", startTimeMs %d" ,
297                 __FUNCTION__, i, streamStats[i].mWidth, streamStats[i].mHeight,
298                 streamStats[i].mRequestCount, streamStats[i].mErrorCount,
299                 streamStats[i].mStartLatencyMs);
300     }
301 
302     sp<hardware::ICameraServiceProxy> proxyBinder = getCameraServiceProxy();
303     sessionStats->onIdle(proxyBinder, requestCount, resultErrorCount, deviceError, userTag,
304             videoStabilizationMode, streamStats);
305 }
306 
logOpen(const String8 & id,int facing,const String16 & clientPackageName,int effectiveApiLevel,bool isNdk,int32_t latencyMs)307 void CameraServiceProxyWrapper::logOpen(const String8& id, int facing,
308             const String16& clientPackageName, int effectiveApiLevel, bool isNdk,
309             int32_t latencyMs) {
310     std::shared_ptr<CameraSessionStatsWrapper> sessionStats;
311     {
312         Mutex::Autolock l(mLock);
313         if (mSessionStatsMap.count(id) > 0) {
314             ALOGE("%s: SessionStatsMap shouldn't contain camera %s",
315                     __FUNCTION__, id.c_str());
316             return;
317         }
318 
319         int apiLevel = CameraSessionStats::CAMERA_API_LEVEL_1;
320         if (effectiveApiLevel == 2) {
321             apiLevel = CameraSessionStats::CAMERA_API_LEVEL_2;
322         }
323 
324         // Generate a new log ID for open events
325         int64_t logId = generateLogId(mRandomDevice);
326 
327         sessionStats = std::make_shared<CameraSessionStatsWrapper>(
328                 String16(id), facing, CameraSessionStats::CAMERA_STATE_OPEN, clientPackageName,
329                 apiLevel, isNdk, latencyMs, logId);
330         mSessionStatsMap.emplace(id, sessionStats);
331         ALOGV("%s: Adding id %s", __FUNCTION__, id.c_str());
332     }
333 
334     ALOGV("%s: id %s, facing %d, effectiveApiLevel %d, isNdk %d, latencyMs %d",
335             __FUNCTION__, id.c_str(), facing, effectiveApiLevel, isNdk, latencyMs);
336     sp<hardware::ICameraServiceProxy> proxyBinder = getCameraServiceProxy();
337     sessionStats->onOpen(proxyBinder);
338 }
339 
logClose(const String8 & id,int32_t latencyMs,bool deviceError)340 void CameraServiceProxyWrapper::logClose(const String8& id, int32_t latencyMs, bool deviceError) {
341     std::shared_ptr<CameraSessionStatsWrapper> sessionStats;
342     {
343         Mutex::Autolock l(mLock);
344         if (mSessionStatsMap.count(id) == 0) {
345             ALOGE("%s: SessionStatsMap should contain camera %s before it's closed",
346                     __FUNCTION__, id.c_str());
347             return;
348         }
349 
350         sessionStats = mSessionStatsMap[id];
351         if (sessionStats == nullptr) {
352             ALOGE("%s: SessionStatsMap should contain camera %s",
353                     __FUNCTION__, id.c_str());
354             return;
355         }
356 
357         mSessionStatsMap.erase(id);
358         ALOGV("%s: Erasing id %s, deviceError %d", __FUNCTION__, id.c_str(), deviceError);
359     }
360 
361     ALOGV("%s: id %s, latencyMs %d, deviceError %d", __FUNCTION__,
362             id.c_str(), latencyMs, deviceError);
363     sp<hardware::ICameraServiceProxy> proxyBinder = getCameraServiceProxy();
364     sessionStats->onClose(proxyBinder, latencyMs, deviceError);
365 }
366 
isCameraDisabled(int userId)367 bool CameraServiceProxyWrapper::isCameraDisabled(int userId) {
368     sp<ICameraServiceProxy> proxyBinder = getCameraServiceProxy();
369     if (proxyBinder == nullptr) return true;
370     bool ret = false;
371     auto status = proxyBinder->isCameraDisabled(userId, &ret);
372     if (!status.isOk()) {
373         ALOGE("%s: Failed during camera disabled query: %s", __FUNCTION__,
374                 status.exceptionMessage().c_str());
375     }
376     return ret;
377 }
378 
getCurrentLogIdForCamera(const String8 & cameraId)379 int64_t CameraServiceProxyWrapper::getCurrentLogIdForCamera(const String8& cameraId) {
380     std::shared_ptr<CameraSessionStatsWrapper> stats;
381     {
382         Mutex::Autolock _l(mLock);
383         if (mSessionStatsMap.count(cameraId) == 0) {
384             ALOGE("%s: SessionStatsMap should contain camera %s before asking for its logging ID.",
385                   __FUNCTION__, cameraId.c_str());
386             return 0;
387         }
388 
389         stats = mSessionStatsMap[cameraId];
390     }
391     return stats->getLogId();
392 }
393 
generateLogId(std::random_device & randomDevice)394 int64_t CameraServiceProxyWrapper::generateLogId(std::random_device& randomDevice) {
395     int64_t ret = 0;
396     do {
397         // std::random_device generates 32 bits per call, so we call it twice
398         ret = randomDevice();
399         ret = ret << 32;
400         ret = ret | randomDevice();
401     } while (ret == 0); // 0 is not a valid identifier
402 
403     return ret;
404 }
405 
updateExtensionStats(const hardware::CameraExtensionSessionStats & extStats)406 String16 CameraServiceProxyWrapper::updateExtensionStats(
407         const hardware::CameraExtensionSessionStats& extStats) {
408     std::shared_ptr<CameraSessionStatsWrapper> stats;
409     String8 cameraId = String8(extStats.cameraId);
410     {
411         Mutex::Autolock _l(mLock);
412         if (mSessionStatsMap.count(cameraId) == 0) {
413             ALOGE("%s CameraExtensionSessionStats reported for camera id that isn't open: %s",
414                   __FUNCTION__, cameraId.c_str());
415             return {};
416         }
417 
418         stats = mSessionStatsMap[cameraId];
419         return stats->updateExtensionSessionStats(extStats);
420     }
421 }
422 
423 }  // namespace android
424