1 /**
2  * Copyright (C) 2022 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 #include <ImsMediaCamera.h>
18 #include <ImsMediaTrace.h>
19 #include <ImsMediaVideoUtil.h>
20 #include <unistd.h>
21 #include <cinttypes>
22 #include <thread>
23 #include <camera/NdkCaptureRequest.h>
24 #include <media/NdkImage.h>
25 
26 #define UNKNOWN_TAG    "UNKNOWN_TAG"
27 #define MAKE_PAIR(val) std::make_pair(val, #val)
28 template <typename T>
GetPairStr(T key,std::vector<std::pair<T,const char * >> & store)29 const char* GetPairStr(T key, std::vector<std::pair<T, const char*>>& store)
30 {
31     typedef typename std::vector<std::pair<T, const char*>>::iterator iterator;
32     for (iterator it = store.begin(); it != store.end(); ++it)
33     {
34         if (it->first == key)
35         {
36             return it->second;
37         }
38     }
39     IMLOGW1("[GetPairStr] %#08x : UNKNOWN_TAG", key);
40     return UNKNOWN_TAG;
41 }
42 
43 /*
44  * camera_status_t error translation
45  */
46 using ERROR_PAIR = std::pair<camera_status_t, const char*>;
47 static std::vector<ERROR_PAIR> errorInfo{
48         MAKE_PAIR(ACAMERA_OK),
49         MAKE_PAIR(ACAMERA_ERROR_UNKNOWN),
50         MAKE_PAIR(ACAMERA_ERROR_INVALID_PARAMETER),
51         MAKE_PAIR(ACAMERA_ERROR_CAMERA_DISCONNECTED),
52         MAKE_PAIR(ACAMERA_ERROR_NOT_ENOUGH_MEMORY),
53         MAKE_PAIR(ACAMERA_ERROR_METADATA_NOT_FOUND),
54         MAKE_PAIR(ACAMERA_ERROR_CAMERA_DEVICE),
55         MAKE_PAIR(ACAMERA_ERROR_CAMERA_SERVICE),
56         MAKE_PAIR(ACAMERA_ERROR_SESSION_CLOSED),
57         MAKE_PAIR(ACAMERA_ERROR_INVALID_OPERATION),
58         MAKE_PAIR(ACAMERA_ERROR_STREAM_CONFIGURE_FAIL),
59         MAKE_PAIR(ACAMERA_ERROR_CAMERA_IN_USE),
60         MAKE_PAIR(ACAMERA_ERROR_MAX_CAMERA_IN_USE),
61         MAKE_PAIR(ACAMERA_ERROR_CAMERA_DISABLED),
62         MAKE_PAIR(ACAMERA_ERROR_PERMISSION_DENIED),
63 };
GetErrorStr(camera_status_t err)64 const char* GetErrorStr(camera_status_t err)
65 {
66     return GetPairStr<camera_status_t>(err, errorInfo);
67 }
68 
69 /**
70  * Range of Camera Exposure Time:
71  *     Camera's capability range have a very long range which may be disturbing
72  *     on camera. For this sample purpose, clamp to a range showing visible
73  *     video on preview: 100000ns ~ 250000000ns
74  */
75 static const uint64_t kMinExposureTime = static_cast<uint64_t>(1000000);
76 static const uint64_t kMaxExposureTime = static_cast<uint64_t>(250000000);
77 
78 std::map<std::string, CameraId> ImsMediaCamera::gCameraIds;
79 ImsMediaCondition ImsMediaCamera::gCondition;
80 ImsMediaCamera ImsMediaCamera::gCamera;
81 
getInstance()82 ImsMediaCamera* ImsMediaCamera::getInstance()
83 {
84     return &gCamera;
85 }
86 
ImsMediaCamera()87 ImsMediaCamera::ImsMediaCamera() :
88         mManager(nullptr),
89         mSessionOutputContainer(nullptr),
90         mCaptureSession(nullptr),
91         mCaptureSessionState(CaptureSessionState::kStateMax),
92         mExposureTime(0),
93         mSensitivity(0),
94         mCameraMode(kCameraModePreview),
95         mCameraFacing(ACAMERA_LENS_FACING_FRONT),
96         mCameraOrientation(0),
97         mActiveCameraId(""),
98         mCameraZoom(0),
99         mFramerate(-1)
100 {
101     IMLOGD0("[ImsMediaCamera]");
102 }
103 
~ImsMediaCamera()104 ImsMediaCamera::~ImsMediaCamera()
105 {
106     IMLOGD0("[~ImsMediaCamera]");
107 }
108 
Initialize()109 void ImsMediaCamera::Initialize()
110 {
111     IMLOGD0("[Initialize]");
112     gCameraIds.clear();
113     mManager = ACameraManager_create();
114 
115     if (mManager == nullptr)
116     {
117         IMLOGD0("[Initialize] manager is not created");
118         return;
119     }
120 
121     EnumerateCamera();
122     mCaptureRequest.outputNativeWindows.resize(0);
123     mCaptureRequest.sessionOutputs.resize(0);
124     mCaptureRequest.targets.resize(0);
125 }
126 
DeInitialize()127 void ImsMediaCamera::DeInitialize()
128 {
129     IMLOGD0("[DeInitialize]");
130 
131     for (auto& cam : gCameraIds)
132     {
133         if (cam.second.mDevice)
134         {
135             ACameraDevice_close(cam.second.mDevice);
136         }
137     }
138 
139     if (mManager)
140     {
141         camera_status_t status =
142                 ACameraManager_unregisterAvailabilityCallback(mManager, GetManagerListener());
143 
144         if (status != ACAMERA_OK)
145         {
146             IMLOGE0("[DeInitialize] error[%s], GetErrorStr(status)");
147         }
148 
149         ACameraManager_delete(mManager);
150         mManager = nullptr;
151     }
152 
153     gCameraIds.clear();
154     for (auto& cam : gCameraIds)
155     {
156         if (cam.second.mDevice)
157         {
158             ACameraDevice_close(cam.second.mDevice);
159         }
160     }
161 
162     if (mManager)
163     {
164         camera_status_t status =
165                 ACameraManager_unregisterAvailabilityCallback(mManager, GetManagerListener());
166 
167         if (status != ACAMERA_OK)
168         {
169             IMLOGE0("[~ImsMediaCamera] error[%s], GetErrorStr(status)");
170         }
171 
172         ACameraManager_delete(mManager);
173         mManager = nullptr;
174     }
175 
176     gCameraIds.clear();
177 }
178 
OpenCamera()179 bool ImsMediaCamera::OpenCamera()
180 {
181     IMLOGD1("[OpenCamera] active camera[%s]", mActiveCameraId.c_str());
182 
183     if (mManager == nullptr)
184     {
185         return false;
186     }
187 
188     if (mActiveCameraId.compare(std::string("")) == 0)
189     {
190         IMLOGE0("[OpenCamera] no active camera");
191         return false;
192     }
193 
194     camera_status_t status = ACameraManager_openCamera(mManager, mActiveCameraId.c_str(),
195             GetDeviceListener(), &gCameraIds[mActiveCameraId].mDevice);
196 
197     if (status != ACAMERA_OK)
198     {
199         IMLOGE1("[OpenCamera] cannot open camera, error[%s]", GetErrorStr(status));
200         return false;
201     }
202 
203     status = ACameraManager_registerAvailabilityCallback(mManager, GetManagerListener());
204 
205     if (status != ACAMERA_OK)
206     {
207         IMLOGE1("[OpenCamera] fail to register manager callback, error[%s]", GetErrorStr(status));
208         return false;
209     }
210 
211     // Initialize camera controls(exposure time and sensitivity), pick
212     // up value of 2% * range + min as starting value (just a number, no magic)
213     ACameraMetadata* metadataObj;
214     ACameraManager_getCameraCharacteristics(mManager, mActiveCameraId.c_str(), &metadataObj);
215     ACameraMetadata_const_entry val;
216     status = ACameraMetadata_getConstEntry(
217             metadataObj, ACAMERA_SENSOR_INFO_EXPOSURE_TIME_RANGE, &val);
218 
219     if (status == ACAMERA_OK)
220     {
221         mExposureRange.min = val.data.i64[0];
222 
223         if (mExposureRange.min < kMinExposureTime)
224         {
225             mExposureRange.min = kMinExposureTime;
226         }
227 
228         mExposureRange.max = val.data.i64[1];
229 
230         if (mExposureRange.max > kMaxExposureTime)
231         {
232             mExposureRange.max = kMaxExposureTime;
233         }
234 
235         mExposureTime = mExposureRange.value(2);
236     }
237     else
238     {
239         IMLOGW0("[OpenCamera] Unsupported ACAMERA_SENSOR_INFO_EXPOSURE_TIME_RANGE");
240         mExposureRange.min = mExposureRange.max = 0L;
241         mExposureTime = 0L;
242     }
243     status =
244             ACameraMetadata_getConstEntry(metadataObj, ACAMERA_SENSOR_INFO_SENSITIVITY_RANGE, &val);
245 
246     if (status == ACAMERA_OK)
247     {
248         mSensitivityRange.min = val.data.i32[0];
249         mSensitivityRange.max = val.data.i32[1];
250         mSensitivity = mSensitivityRange.value(2);
251     }
252     else
253     {
254         IMLOGW0("[OpenCamera] failed for ACAMERA_SENSOR_INFO_SENSITIVITY_RANGE");
255         mSensitivityRange.min = mSensitivityRange.max = 0;
256         mSensitivity = 0;
257     }
258 
259     return true;
260 }
261 
SetCameraConfig(int32_t cameraId,int32_t cameraZoom,int32_t framerate)262 void ImsMediaCamera::SetCameraConfig(int32_t cameraId, int32_t cameraZoom, int32_t framerate)
263 {
264     IMLOGD3("[SetCameraConfig] id[%d], zoom[%d], FPS[%d]", cameraId, cameraZoom, framerate);
265     uint32_t idx = 0;
266     for (std::map<std::string, CameraId>::iterator it = gCameraIds.begin(); it != gCameraIds.end();
267             ++it)
268     {
269         if (idx == cameraId)
270         {
271             mActiveCameraId = (it->second).mId;
272             break;
273         }
274         ++idx;
275     }
276 
277     mCameraZoom = cameraZoom;
278     mFramerate = framerate;
279 }
280 
CreateSession(ANativeWindow * preview,ANativeWindow * recording)281 bool ImsMediaCamera::CreateSession(ANativeWindow* preview, ANativeWindow* recording)
282 {
283     if (preview == nullptr)
284     {
285         return false;
286     }
287 
288     if (!MatchCaptureSizeRequest(preview))
289     {
290         IMLOGE0("[CreateSession] resolution is not matched");
291         return false;
292     }
293 
294     mCaptureRequest.outputNativeWindows.push_back(preview);
295 
296     if (recording != nullptr)
297     {
298         mCaptureRequest.outputNativeWindows.push_back(recording);
299     }
300 
301     mCaptureRequest.sessionOutputs.resize(mCaptureRequest.outputNativeWindows.size());
302     mCaptureRequest.targets.resize(mCaptureRequest.outputNativeWindows.size());
303 
304     // Create output from this app's ANativeWindow, and add into output container
305     recording == nullptr ? mCaptureRequest.requestTemplate = TEMPLATE_PREVIEW
306                          : mCaptureRequest.requestTemplate = TEMPLATE_RECORD;
307 
308     camera_status_t status = ACaptureSessionOutputContainer_create(&mSessionOutputContainer);
309 
310     if (status != ACAMERA_OK)
311     {
312         IMLOGE1("[CreateSession] create output container, error[%s]", GetErrorStr(status));
313         return false;
314     }
315 
316     for (int idxTarget = 0; idxTarget < mCaptureRequest.outputNativeWindows.size(); idxTarget++)
317     {
318         if (mCaptureRequest.outputNativeWindows[idxTarget] == nullptr)
319             continue;
320 
321         IMLOGD0("[CreateSession] acquire window");
322         ANativeWindow_acquire(mCaptureRequest.outputNativeWindows[idxTarget]);
323         status = ACaptureSessionOutput_create(mCaptureRequest.outputNativeWindows[idxTarget],
324                 &mCaptureRequest.sessionOutputs[idxTarget]);
325         if (status != ACAMERA_OK)
326         {
327             IMLOGE1("[CreateSession] create capture output, error[%s]", GetErrorStr(status));
328             continue;
329         }
330 
331         ACaptureSessionOutputContainer_add(
332                 mSessionOutputContainer, mCaptureRequest.sessionOutputs[idxTarget]);
333         status = ACameraOutputTarget_create(mCaptureRequest.outputNativeWindows[idxTarget],
334                 &mCaptureRequest.targets[idxTarget]);
335         if (status != ACAMERA_OK)
336         {
337             IMLOGE1("[CreateSession] create output target, error[%s]", GetErrorStr(status));
338             continue;
339         }
340     }
341 
342     if (!gCameraIds[mActiveCameraId].mAvailable)
343     {
344         gCondition.wait_timeout(MAX_WAIT_CAMERA);
345     }
346 
347     status = ACameraDevice_createCaptureRequest(gCameraIds[mActiveCameraId].mDevice,
348             mCaptureRequest.requestTemplate, &mCaptureRequest.request);
349     if (status != ACAMERA_OK)
350     {
351         IMLOGE1("[CreateSession] create capture request, error[%s]", GetErrorStr(status));
352         return false;
353     }
354 
355     for (int idxTarget = 0; idxTarget < mCaptureRequest.outputNativeWindows.size(); idxTarget++)
356     {
357         IMLOGD0("[CreateSession] add target");
358         ACaptureRequest_addTarget(mCaptureRequest.request, mCaptureRequest.targets[idxTarget]);
359     }
360 
361     // Create a capture session for the given preview request
362     mCaptureSessionState = CaptureSessionState::kStateReady;
363     status = ACameraDevice_createCaptureSession(gCameraIds[mActiveCameraId].mDevice,
364             mSessionOutputContainer, GetSessionListener(), &mCaptureSession);
365 
366     if (status != ACAMERA_OK)
367     {
368         IMLOGE1("[CreateSession] create capture session, error[%s]", GetErrorStr(status));
369         mCaptureSession = nullptr;
370         return false;
371     }
372 
373     IMLOGD1("[CreateSession] create capture session[%p]", mCaptureSession);
374 
375     uint8_t afModeAuto = ACAMERA_CONTROL_AF_MODE_AUTO;
376     ACaptureRequest_setEntry_u8(mCaptureRequest.request, ACAMERA_CONTROL_AF_MODE, 1, &afModeAuto);
377     const int32_t targetFps[2] = {mFramerate, mFramerate};
378     ACaptureRequest_setEntry_i32(
379             mCaptureRequest.request, ACAMERA_CONTROL_AE_TARGET_FPS_RANGE, 2, targetFps);
380 
381     return true;
382 }
383 
DeleteSession()384 bool ImsMediaCamera::DeleteSession()
385 {
386     IMLOGD0("[DeleteSession]");
387     camera_status_t status;
388 
389     if (mCaptureSession != nullptr)
390     {
391         IMLOGD0("[DeleteSession] session close");
392         gCondition.reset();
393         ACameraCaptureSession_close(mCaptureSession);
394         gCondition.wait_timeout(MAX_WAIT_CAMERA);
395         mCaptureSession = nullptr;
396     }
397 
398     if (mCaptureRequest.request != nullptr)
399     {
400         for (int idxTarget = 0; idxTarget < mCaptureRequest.outputNativeWindows.size(); idxTarget++)
401         {
402             if (mCaptureRequest.outputNativeWindows[idxTarget] == nullptr)
403             {
404                 continue;
405             }
406 
407             status = ACaptureRequest_removeTarget(
408                     mCaptureRequest.request, mCaptureRequest.targets[idxTarget]);
409 
410             if (status != ACAMERA_OK)
411             {
412                 IMLOGE1("[DeleteSession] error ACaptureRequest_removeTarget[%s]",
413                         GetErrorStr(status));
414             }
415 
416             ACameraOutputTarget_free(mCaptureRequest.targets[idxTarget]);
417             status = ACaptureSessionOutputContainer_remove(
418                     mSessionOutputContainer, mCaptureRequest.sessionOutputs[idxTarget]);
419 
420             if (status != ACAMERA_OK)
421             {
422                 IMLOGE1("[DeleteSession] error ACaptureSessionOutputContainer_remove[%s]",
423                         GetErrorStr(status));
424             }
425 
426             ACaptureSessionOutput_free(mCaptureRequest.sessionOutputs[idxTarget]);
427             ANativeWindow_release(mCaptureRequest.outputNativeWindows[idxTarget]);
428         }
429 
430         IMLOGD0("[DeleteSession] free request");
431         ACaptureRequest_free(mCaptureRequest.request);
432         mCaptureRequest.request = nullptr;
433     }
434 
435     mCaptureRequest.outputNativeWindows.resize(0);
436     mCaptureRequest.sessionOutputs.resize(0);
437     mCaptureRequest.targets.resize(0);
438 
439     if (mSessionOutputContainer != nullptr)
440     {
441         IMLOGD0("[DeleteSession] free container");
442         ACaptureSessionOutputContainer_free(mSessionOutputContainer);
443         mSessionOutputContainer = nullptr;
444     }
445 
446     return true;
447 }
448 
StartSession(bool bRecording)449 bool ImsMediaCamera::StartSession(bool bRecording)
450 {
451     IMLOGD1("[StartSession] recording[%d]", bRecording);
452 
453     camera_status_t status;
454     bRecording ? mCameraMode = kCameraModeRecord : kCameraModePreview;
455 
456     gCondition.reset();
457     status = ACameraCaptureSession_setRepeatingRequest(
458             mCaptureSession, nullptr, 1, &mCaptureRequest.request, nullptr);
459 
460     if (status != ACAMERA_OK)
461     {
462         IMLOGE1("[StartSession] error[%s]", GetErrorStr(status));
463         return false;
464     }
465 
466     gCondition.wait_timeout(MAX_WAIT_CAMERA);
467     return true;
468 }
469 
StopSession()470 bool ImsMediaCamera::StopSession()
471 {
472     IMLOGD1("[StopSession] state[%d]", mCaptureSessionState);
473 
474     if (mCaptureSessionState == CaptureSessionState::kStateActive)
475     {
476         gCondition.reset();
477         camera_status_t status = ACameraCaptureSession_stopRepeating(mCaptureSession);
478 
479         if (status != ACAMERA_OK)
480         {
481             IMLOGE1("[StopSession] stopRepeating error[%s]", GetErrorStr(status));
482             return false;
483         }
484     }
485 
486     gCondition.wait_timeout(MAX_WAIT_CAMERA);
487     return true;
488 }
489 
490 /*
491  * Camera Manager Listener object
492  */
OnCameraAvailable(void * context,const char * id)493 void OnCameraAvailable(void* context, const char* id)
494 {
495     IMLOGD1("[OnCameraAvailable] id[%s]", id == nullptr ? "nullptr" : id);
496 
497     if (context != nullptr)
498     {
499         reinterpret_cast<ImsMediaCamera*>(context)->OnCameraStatusChanged(id, true);
500     }
501 }
502 
OnCameraUnavailable(void * context,const char * id)503 void OnCameraUnavailable(void* context, const char* id)
504 {
505     IMLOGD1("[OnCameraUnavailable] id[%s]", id == nullptr ? "nullptr" : id);
506 
507     if (context != nullptr)
508     {
509         reinterpret_cast<ImsMediaCamera*>(context)->OnCameraStatusChanged(id, false);
510     }
511 }
512 
OnCameraStatusChanged(const char * id,bool available)513 void ImsMediaCamera::OnCameraStatusChanged(const char* id, bool available)
514 {
515     IMLOGD2("[OnCameraStatusChanged] id[%s], available[%d]", id == nullptr ? "nullptr" : id,
516             available);
517 
518     if (id != nullptr && mManager != nullptr && !gCameraIds.empty())
519     {
520         if (gCameraIds.find(std::string(id)) != gCameraIds.end())
521         {
522             gCameraIds[std::string(id)].mAvailable = available;
523 
524             if (available)
525             {
526                 gCondition.signal();
527             }
528         }
529     }
530 }
531 
GetManagerListener()532 ACameraManager_AvailabilityCallbacks* ImsMediaCamera::GetManagerListener()
533 {
534     static ACameraManager_AvailabilityCallbacks cameraMgrListener = {
535             .context = this,
536             .onCameraAvailable = ::OnCameraAvailable,
537             .onCameraUnavailable = ::OnCameraUnavailable,
538     };
539     return &cameraMgrListener;
540 }
541 
542 /*
543  * CameraDevice callbacks
544  */
OnDeviceStateChanges(void * context,ACameraDevice * dev)545 void OnDeviceStateChanges(void* context, ACameraDevice* dev)
546 {
547     IMLOGW0("[OnDeviceStateChanges]");
548 
549     if (context != nullptr)
550     {
551         reinterpret_cast<ImsMediaCamera*>(context)->OnDeviceState(dev);
552     }
553 }
554 
OnDeviceErrorChanges(void * context,ACameraDevice * dev,int err)555 void OnDeviceErrorChanges(void* context, ACameraDevice* dev, int err)
556 {
557     IMLOGW0("[OnDeviceErrorChanges]");
558 
559     if (context != nullptr)
560     {
561         reinterpret_cast<ImsMediaCamera*>(context)->OnDeviceError(dev, err);
562     }
563 }
564 
GetDeviceListener()565 ACameraDevice_stateCallbacks* ImsMediaCamera::GetDeviceListener()
566 {
567     static ACameraDevice_stateCallbacks cameraDeviceListener = {
568             .context = this,
569             .onDisconnected = ::OnDeviceStateChanges,
570             .onError = ::OnDeviceErrorChanges,
571     };
572     return &cameraDeviceListener;
573 }
574 
OnDeviceState(ACameraDevice * dev)575 void ImsMediaCamera::OnDeviceState(ACameraDevice* dev)
576 {
577     std::string id(ACameraDevice_getId(dev));
578     IMLOGW1("[OnDeviceState] device %s is disconnected", id.c_str());
579     gCameraIds[id].mAvailable = false;
580     ACameraDevice_close(gCameraIds[id].mDevice);
581 }
582 
583 /*
584  * CameraDevice error state translation, used in
585  *     ACameraDevice_ErrorStateCallback
586  */
587 using DEV_ERROR_PAIR = std::pair<int, const char*>;
588 static std::vector<DEV_ERROR_PAIR> devErrors{
589         MAKE_PAIR(ERROR_CAMERA_IN_USE),
590         MAKE_PAIR(ERROR_MAX_CAMERAS_IN_USE),
591         MAKE_PAIR(ERROR_CAMERA_DISABLED),
592         MAKE_PAIR(ERROR_CAMERA_DEVICE),
593         MAKE_PAIR(ERROR_CAMERA_SERVICE),
594 };
595 
GetCameraDeviceErrorStr(int err)596 const char* GetCameraDeviceErrorStr(int err)
597 {
598     return GetPairStr<int>(err, devErrors);
599 }
600 
PrintCameraDeviceError(int err)601 void PrintCameraDeviceError(int err)
602 {
603     IMLOGD2("[PrintCameraDeviceError] CameraDeviceError(%#x): %s", err,
604             GetCameraDeviceErrorStr(err));
605 }
606 
OnDeviceError(ACameraDevice * dev,int err)607 void ImsMediaCamera::OnDeviceError(ACameraDevice* dev, int err)
608 {
609     std::string id(ACameraDevice_getId(dev));
610     IMLOGE2("[OnDeviceError] CameraDevice %s is in error %#x", id.c_str(), err);
611     PrintCameraDeviceError(err);
612     gCameraIds[id].mAvailable = false;
613     gCameraIds[id].mOwner = false;
614 }
615 
616 // CaptureSession state callbacks
OnSessionClosed(void * context,ACameraCaptureSession * session)617 void OnSessionClosed(void* context, ACameraCaptureSession* session)
618 {
619     IMLOGW1("[OnSessionClosed] session[%p] closed", session);
620     reinterpret_cast<ImsMediaCamera*>(context)->OnSessionState(
621             session, CaptureSessionState::kStateClosed);
622 }
623 
OnSessionReady(void * context,ACameraCaptureSession * session)624 void OnSessionReady(void* context, ACameraCaptureSession* session)
625 {
626     IMLOGW1("[OnSessionReady] session[%p] ready", session);
627     reinterpret_cast<ImsMediaCamera*>(context)->OnSessionState(
628             session, CaptureSessionState::kStateReady);
629 }
630 
OnSessionActive(void * context,ACameraCaptureSession * session)631 void OnSessionActive(void* context, ACameraCaptureSession* session)
632 {
633     IMLOGW1("[OnSessionActive] session[%p] active", session);
634     reinterpret_cast<ImsMediaCamera*>(context)->OnSessionState(
635             session, CaptureSessionState::kStateActive);
636 }
637 
GetSessionListener()638 ACameraCaptureSession_stateCallbacks* ImsMediaCamera::GetSessionListener()
639 {
640     static ACameraCaptureSession_stateCallbacks sessionListener = {
641             .context = this,
642             .onClosed = ::OnSessionClosed,
643             .onReady = ::OnSessionReady,
644             .onActive = ::OnSessionActive,
645     };
646     return &sessionListener;
647 }
648 
OnSessionState(ACameraCaptureSession * session,CaptureSessionState state)649 void ImsMediaCamera::OnSessionState(ACameraCaptureSession* session, CaptureSessionState state)
650 {
651     IMLOGD0("[OnSessionState]");
652 
653     if (mCaptureSession == nullptr)
654     {
655         IMLOGW0("[OnSessionState] CaptureSession closed");
656         return;
657     }
658 
659     if (!session || session != mCaptureSession)
660     {
661         IMLOGW1("[OnSessionState] CaptureSession is %s", (session ? "NOT our session" : "nullptr"));
662         return;
663     }
664 
665     if (state >= CaptureSessionState::kStateMax)
666     {
667         IMLOGE1("[OnSessionState] Wrong state[%d]", state);
668     }
669     else
670     {
671         mCaptureSessionState = state;
672         gCondition.signal();
673         IMLOGD1("[OnSessionState] state[%d]", state);
674     }
675 }
676 
EnumerateCamera()677 void ImsMediaCamera::EnumerateCamera()
678 {
679     if (mManager == nullptr)
680     {
681         return;
682     }
683 
684     ACameraIdList* cameraIds = nullptr;
685     auto ret = ACameraManager_getCameraIdList(mManager, &cameraIds);
686 
687     if (ret != ACAMERA_OK)
688     {
689         return;
690     }
691 
692     for (int i = 0; i < cameraIds->numCameras; ++i)
693     {
694         const char* id = cameraIds->cameraIds[i];
695         ACameraMetadata* metadataObj;
696         ACameraManager_getCameraCharacteristics(mManager, id, &metadataObj);
697 
698         int32_t count = 0;
699         const uint32_t* tags = nullptr;
700         ACameraMetadata_getAllTags(metadataObj, &count, &tags);
701 
702         for (int tagIdx = 0; tagIdx < count; ++tagIdx)
703         {
704             if (ACAMERA_LENS_FACING == tags[tagIdx])
705             {
706                 ACameraMetadata_const_entry lensInfo;
707                 ACameraMetadata_getConstEntry(metadataObj, tags[tagIdx], &lensInfo);
708                 CameraId cam(id);
709                 cam.mFacing = static_cast<acamera_metadata_enum_android_lens_facing_t>(
710                         lensInfo.data.u8[0]);
711                 cam.mOwner = false;
712                 cam.mDevice = nullptr;
713                 gCameraIds[cam.mId] = cam;
714                 IMLOGD2("[EnumerateCamera] cameraId[%s], facing[%d]", cam.mId.c_str(), cam.mFacing);
715             }
716         }
717         ACameraMetadata_free(metadataObj);
718     }
719 
720     if (gCameraIds.size() == 0)
721     {
722         IMLOGD0("[EnumerateCamera] No Camera Available on the device");
723     }
724 
725     ACameraManager_deleteCameraIdList(cameraIds);
726 }
727 
GetSensorOrientation(const int cameraId,int32_t * facing,int32_t * angle)728 bool ImsMediaCamera::GetSensorOrientation(const int cameraId, int32_t* facing, int32_t* angle)
729 {
730     if (!mManager || facing == nullptr || angle == nullptr)
731     {
732         return false;
733     }
734 
735     ACameraMetadata* metadataObj;
736     uint32_t idx = 0;
737 
738     for (std::map<std::string, CameraId>::iterator it = gCameraIds.begin(); it != gCameraIds.end();
739             ++it)
740     {
741         if (idx == cameraId)
742         {
743             camera_status_t status = ACameraManager_getCameraCharacteristics(
744                     mManager, (it->second).mId.c_str(), &metadataObj);
745             if (status == ACAMERA_OK)
746             {
747                 ACameraMetadata_const_entry face, orientation;
748                 ACameraMetadata_getConstEntry(metadataObj, ACAMERA_LENS_FACING, &face);
749                 mCameraFacing = static_cast<int32_t>(face.data.u8[0]);
750                 ACameraMetadata_getConstEntry(
751                         metadataObj, ACAMERA_SENSOR_ORIENTATION, &orientation);
752                 mCameraOrientation = orientation.data.i32[0];
753                 mCameraFacing == 0 ? * facing = kCameraFacingFront : * facing = kCameraFacingRear;
754                 *angle = mCameraOrientation;
755                 ACameraMetadata_free(metadataObj);
756                 return true;
757             }
758         }
759         ++idx;
760     }
761 
762     return false;
763 }
764 
GetExposureRange(int64_t * min,int64_t * max,int64_t * curVal)765 bool ImsMediaCamera::GetExposureRange(int64_t* min, int64_t* max, int64_t* curVal)
766 {
767     if (!mExposureRange.Supported() || !mExposureTime || !min || !max || !curVal)
768     {
769         return false;
770     }
771     *min = mExposureRange.min;
772     *max = mExposureRange.max;
773     *curVal = mExposureTime;
774 
775     return true;
776 }
777 
GetSensitivityRange(int64_t * min,int64_t * max,int64_t * curVal)778 bool ImsMediaCamera::GetSensitivityRange(int64_t* min, int64_t* max, int64_t* curVal)
779 {
780     if (!mSensitivityRange.Supported() || !mSensitivity || !min || !max || !curVal)
781     {
782         return false;
783     }
784     *min = static_cast<int64_t>(mSensitivityRange.min);
785     *max = static_cast<int64_t>(mSensitivityRange.max);
786     *curVal = mSensitivity;
787     return true;
788 }
789 
790 /**
791  * A helper class to assist image size comparison, by comparing the absolute
792  * size
793  * regardless of the portrait or landscape mode.
794  */
795 class DisplayDimension
796 {
797 public:
DisplayDimension(int32_t w,int32_t h)798     DisplayDimension(int32_t w, int32_t h) :
799             w_(w),
800             h_(h),
801             portrait_(false)
802     {
803         if (h > w)
804         {
805             // make it landscape
806             w_ = h;
807             h_ = w;
808             portrait_ = true;
809         }
810     }
DisplayDimension(const DisplayDimension & other)811     DisplayDimension(const DisplayDimension& other)
812     {
813         w_ = other.w_;
814         h_ = other.h_;
815         portrait_ = other.portrait_;
816     }
817 
DisplayDimension(void)818     DisplayDimension(void)
819     {
820         w_ = 0;
821         h_ = 0;
822         portrait_ = false;
823     }
operator =(const DisplayDimension & other)824     DisplayDimension& operator=(const DisplayDimension& other)
825     {
826         if (this != &other)
827         {
828             w_ = other.w_;
829             h_ = other.h_;
830             portrait_ = other.portrait_;
831         }
832 
833         return (*this);
834     }
835 
IsSameRatio(const DisplayDimension & other) const836     bool IsSameRatio(const DisplayDimension& other) const
837     {
838         return (w_ * other.h_ == h_ * other.w_);
839     }
operator >(const DisplayDimension & other) const840     bool operator>(const DisplayDimension& other) const
841     {
842         return (w_ >= other.w_ && h_ >= other.h_);
843     }
operator ==(const DisplayDimension & other) const844     bool operator==(const DisplayDimension& other) const
845     {
846         return (w_ == other.w_ && h_ == other.h_ && portrait_ == other.portrait_);
847     }
operator -(const DisplayDimension & other)848     DisplayDimension operator-(const DisplayDimension& other)
849     {
850         DisplayDimension delta(w_ - other.w_, h_ - other.h_);
851         return delta;
852     }
Flip(void)853     void Flip(void) { portrait_ = !portrait_; }
width(void) const854     int32_t width(void) const { return w_; }
height(void) const855     int32_t height(void) const { return h_; }
856 
857 private:
858     int32_t w_, h_;
859     bool portrait_;
860 };
861 
MatchCaptureSizeRequest(ANativeWindow * window)862 bool ImsMediaCamera::MatchCaptureSizeRequest(ANativeWindow* window)
863 {
864     DisplayDimension disp(ANativeWindow_getWidth(window), ANativeWindow_getHeight(window));
865     IMLOGD3("[MatchCaptureSizeRequest] request width[%d], height[%d], camOrientation[%d]",
866             disp.width(), disp.height(), mCameraOrientation);
867 
868     if (mCameraOrientation == 90 || mCameraOrientation == 270)
869     {
870         disp.Flip();
871     }
872 
873     ACameraMetadata* metadata;
874     ACameraManager_getCameraCharacteristics(mManager, mActiveCameraId.c_str(), &metadata);
875     ACameraMetadata_const_entry entry;
876     ACameraMetadata_getConstEntry(metadata, ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, &entry);
877 
878     for (int32_t i = 0; i < entry.count; i += 4)
879     {
880         int32_t input = entry.data.i32[i + 3];
881         int32_t format = entry.data.i32[i + 0];
882         if (input)
883             continue;
884 
885         if (format == AIMAGE_FORMAT_YUV_420_888 || format == AIMAGE_FORMAT_JPEG)
886         {
887             DisplayDimension dimension(entry.data.i32[i + 1], entry.data.i32[i + 2]);
888             if (!disp.IsSameRatio(dimension))
889                 continue;
890 
891             // here only width and height should be compared and not portrait flag.
892             if (disp.width() == dimension.width() && disp.height() == dimension.height())
893             {
894                 return true;
895             }
896         }
897     }
898 
899     return false;
900 }
901