1 /* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 *     * Redistributions of source code must retain the above copyright
7 *       notice, this list of conditions and the following disclaimer.
8 *     * Redistributions in binary form must reproduce the above
9 *       copyright notice, this list of conditions and the following
10 *       disclaimer in the documentation and/or other materials provided
11 *       with the distribution.
12 *     * Neither the name of The Linux Foundation nor the names of its
13 *       contributors may be used to endorse or promote products derived
14 *       from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29 
30 #define LOG_TAG "QCameraPerf"
31 
32 // To remove
33 #include <cutils/properties.h>
34 #include <utils/Errors.h>
35 
36 // System dependencies
37 #include <stdlib.h>
38 #include <dlfcn.h>
39 #include <utils/Timers.h>
40 
41 #include <aidl/android/hardware/power/Boost.h>
42 #include <aidl/android/hardware/power/IPower.h>
43 #include <aidl/android/hardware/power/Mode.h>
44 #include <android/binder_manager.h>
45 #include <android-base/properties.h>
46 
47 // Camera dependencies
48 #include "QCameraPerf.h"
49 #include "QCameraTrace.h"
50 
51 extern "C" {
52 #include "mm_camera_dbg.h"
53 }
54 
55 namespace qcamera {
56 
57 using aidl::android::hardware::power::Boost;
58 using aidl::android::hardware::power::Mode;
59 
60 // Protect gPowerHal_1_2_ and gPowerHal_Aidl_
61 static android::sp<android::hardware::power::V1_2::IPower> gPowerHal_1_2_ = nullptr;
62 static std::shared_ptr<aidl::android::hardware::power::IPower> gPowerHal_Aidl_ = nullptr;
63 static std::mutex gPowerHalMutex;
64 static const std::string kInstance =
65     std::string() + aidl::android::hardware::power::IPower::descriptor + "/default";
66 
67 namespace {
68     constexpr int kDefaultBoostDurationMs = 1000;
69     constexpr int kDisableBoostDurationMs = -1;
70 }
71 
72 enum hal_version {
73     NONE,
74     HIDL_1_2,
75     AIDL,
76 };
77 
78 // Connnect PowerHAL
connectPowerHalLocked()79 static hal_version connectPowerHalLocked() {
80     static bool gPowerHalHidlExists = true;
81     static bool gPowerHalAidlExists = true;
82 
83     if (!gPowerHalHidlExists && !gPowerHalAidlExists) {
84         return NONE;
85     }
86 
87     if (gPowerHalHidlExists) {
88         if (!gPowerHal_1_2_) {
89             gPowerHal_1_2_ =
90                     android::hardware::power::V1_2::IPower::getService();
91         }
92         if (gPowerHal_1_2_) {
93             ALOGV("Successfully connected to Power Hal Hidl service.");
94             return HIDL_1_2;
95         } else {
96             gPowerHalHidlExists = false;
97         }
98     }
99 
100     if (gPowerHalAidlExists) {
101         if (!gPowerHal_Aidl_) {
102             ndk::SpAIBinder pwBinder = ndk::SpAIBinder(AServiceManager_getService(kInstance.c_str()));
103             gPowerHal_Aidl_ = aidl::android::hardware::power::IPower::fromBinder(pwBinder);
104         }
105         if (gPowerHal_Aidl_) {
106             ALOGV("Successfully connected to Power Hal Aidl service.");
107             return AIDL;
108         } else {
109             gPowerHalAidlExists = false;
110         }
111     }
112 
113     return NONE;
114 }
115 
116 typedef enum {
117     MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_0     = 0x40800000,
118     MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_1     = 0x40800010,
119     MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_2     = 0x40800020,
120     MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_3     = 0x40800030,
121     MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_0  = 0x40800100,
122     MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_1  = 0x40800110,
123     MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_2  = 0x40800120,
124     MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_3  = 0x40800130,
125 
126     MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_0     = 0x40804000,
127     MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_1     = 0x40804010,
128     MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_2     = 0x40804020,
129     MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_3     = 0x40804030,
130     MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_0  = 0x40804100,
131     MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_1  = 0x40804110,
132     MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_2  = 0x40804120,
133     MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_3  = 0x40804130,
134 
135     MPCTLV3_MIN_ONLINE_CPU_CLUSTER_BIG      = 0x41000000,
136     MPCTLV3_MIN_ONLINE_CPU_CLUSTER_LITTLE   = 0x41000100,
137     MPCTLV3_MAX_ONLINE_CPU_CLUSTER_BIG      = 0x41004000,
138     MPCTLV3_MAX_ONLINE_CPU_CLUSTER_LITTLE   = 0x41004100,
139 
140     MPCTLV3_ALL_CPUS_PWR_CLPS_DIS           = 0x40400000,
141     MPCTLV3_CPUBW_HWMON_MIN_FREQ            = 0x41800000,
142     MPCTLV3_CPUBW_HWMON_HYST_OPT            = 0x4180C000
143 } perf_lock_params;
144 
145 
146 static int32_t perfLockParamsOpenCamera[] = {
147     // Disable power collapse and set CPU cloks to turbo
148     MPCTLV3_ALL_CPUS_PWR_CLPS_DIS,          0x1,
149     MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_0,    0xFFF,
150     MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_0,    0xFFF,
151     MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF,
152     MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF
153 };
154 
155 static int32_t perfLockParamsCloseCamera[] = {
156     // Disable power collapse and set CPU cloks to turbo
157     MPCTLV3_ALL_CPUS_PWR_CLPS_DIS,          0x1,
158     MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_0,    0xFFF,
159     MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_0,    0xFFF,
160     MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF,
161     MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF
162 };
163 
164 static int32_t perfLockParamsStartPreview[] = {
165     // Disable power collapse and set CPU cloks to turbo
166     MPCTLV3_ALL_CPUS_PWR_CLPS_DIS,          0x1,
167     MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_0,    0xFFF,
168     MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_0,    0xFFF,
169     MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF,
170     MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF
171 };
172 
173 static int32_t perfLockParamsTakeSnapshot[] = {
174     // Disable power collapse and set CPU cloks to turbo
175     MPCTLV3_ALL_CPUS_PWR_CLPS_DIS,          0x1,
176     MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_0,    0xFFF,
177     MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_0,    0xFFF,
178     MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF,
179     MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF,
180     MPCTLV3_CPUBW_HWMON_HYST_OPT,           0x0,
181     MPCTLV3_CPUBW_HWMON_MIN_FREQ,           0x8C
182 };
183 
184 PerfLockInfo QCameraPerfLock::mPerfLockInfo[] = {
185     { //PERF_LOCK_OPEN_CAMERA
186       perfLockParamsOpenCamera,
187       sizeof(perfLockParamsOpenCamera)/sizeof(int32_t) },
188     { //PERF_LOCK_CLOSE_CAMERA
189       perfLockParamsCloseCamera,
190       sizeof(perfLockParamsCloseCamera)/sizeof(int32_t) },
191     { //PERF_LOCK_START_PREVIEW
192       perfLockParamsStartPreview,
193       sizeof(perfLockParamsStartPreview)/sizeof(int32_t) },
194     { //PERF_LOCK_TAKE_SNAPSHOT
195       perfLockParamsTakeSnapshot,
196       sizeof(perfLockParamsTakeSnapshot)/sizeof(int32_t) },
197     { //PERF_LOCK_POWERHINT_PREVIEW
198       NULL, 0},
199     { //PERF_LOCK_POWERHINT_ENCODE
200       NULL, 0}
201     };
202 
203 Mutex                QCameraPerfLockIntf::mMutex;
204 QCameraPerfLockIntf* QCameraPerfLockIntf::mInstance = NULL;
205 
206 
207 /*===========================================================================
208  * FUNCTION   : QCameraPerfLockMgr constructor
209  *
210  * DESCRIPTION: Initialize the perf locks
211  *
212  * PARAMETERS : None
213  *
214  * RETURN     : void
215  *
216  *==========================================================================*/
QCameraPerfLockMgr()217 QCameraPerfLockMgr::QCameraPerfLockMgr() :
218     mState(LOCK_MGR_STATE_UNINITIALIZED)
219 {
220     for (int i = 0; i < PERF_LOCK_COUNT; ++i) {
221         mPerfLock[i] = QCameraPerfLock::create((PerfLockEnum)i);
222 
223         if (mPerfLock[i] == NULL) {
224             mState = LOCK_MGR_STATE_ERROR;
225             LOGE("Could not allocate perf locks");
226 
227             // Set the remaining perf locks to NULL
228             for (int j = i+1; j < PERF_LOCK_COUNT; ++j) {
229                 mPerfLock[j] = NULL;
230             }
231             return;
232         }
233     }
234     mState = LOCK_MGR_STATE_READY;
235 }
236 
237 
238 /*===========================================================================
239  * FUNCTION   : QCameraPerfLockMgr destructor
240  *
241  * DESCRIPTION: class destructor
242  *
243  * PARAMETERS : None
244  *
245  * RETURN     : void
246  *
247  *==========================================================================*/
~QCameraPerfLockMgr()248 QCameraPerfLockMgr::~QCameraPerfLockMgr()
249 {
250     for (int i = 0; i < PERF_LOCK_COUNT; ++i) {
251         if (mPerfLock[i]) {
252             delete mPerfLock[i];
253         }
254     }
255 }
256 
257 
258 /*===========================================================================
259  * FUNCTION   : acquirePerfLock
260  *
261  * DESCRIPTION: Call acquirePerfLock function for the requested perf lock
262  *
263  * PARAMETERS :
264  * @perfLockType: Perf lock enum
265  * @timer:        Timer value in ms
266  *
267  * RETURN     : true  on success
268  *              false on failure
269  *==========================================================================*/
acquirePerfLock(PerfLockEnum perfLockType,uint32_t timer)270 bool QCameraPerfLockMgr::acquirePerfLock(
271         PerfLockEnum perfLockType,
272         uint32_t     timer)
273 {
274     bool ret = false;
275     if ((mState == LOCK_MGR_STATE_READY) &&
276         isValidPerfLockEnum(perfLockType)) {
277         ret = mPerfLock[perfLockType]->acquirePerfLock(true, timer);
278     }
279     return ret;
280 }
281 
282 
283 /*===========================================================================
284  * FUNCTION   : acquirePerfLockIfExpired
285  *
286  * DESCRIPTION: Call acquirePerfLock function for the requested perf lock
287  *
288  * PARAMETERS :
289  * @perfLockType: Type of perf lock
290  * @timer:        Timer value in ms
291  *
292  * RETURN     : true  on success
293  *              false on failure
294  *==========================================================================*/
acquirePerfLockIfExpired(PerfLockEnum perfLockType,uint32_t timer)295 bool QCameraPerfLockMgr::acquirePerfLockIfExpired(
296         PerfLockEnum perfLockType,
297         uint32_t     timer)
298 {
299     bool ret = false;
300     if ((mState == LOCK_MGR_STATE_READY) &&
301         isValidPerfLockEnum(perfLockType)) {
302         ret = mPerfLock[perfLockType]->acquirePerfLock(false, timer);
303     }
304     return ret;
305 
306 }
307 
308 
309 /*===========================================================================
310  * FUNCTION   : releasePerfLock
311  *
312  * DESCRIPTION: Call releasePerfLock function for the requested perf lock
313  *
314  * PARAMETERS :
315  * @perfLockType: Enum of perf lock
316  *
317  * RETURN     : true  on success
318  *              false on failure
319  *==========================================================================*/
releasePerfLock(PerfLockEnum perfLockType)320 bool QCameraPerfLockMgr::releasePerfLock(
321         PerfLockEnum perfLockType)
322 {
323     bool ret = false;
324     if ((mState == LOCK_MGR_STATE_READY) &&
325         isValidPerfLockEnum(perfLockType)) {
326         ret = mPerfLock[perfLockType]->releasePerfLock();
327     }
328     return ret;
329 }
330 
331 
332 /*===========================================================================
333  * FUNCTION   : powerHintInternal
334  *
335  * DESCRIPTION: Calls the appropriate perf lock's powerHintInternal function
336  *
337  * PARAMETERS :
338  * @perfLockType: Type of perf lock
339  * @hint        : Power hint
340  * @enable      : Enable power hint if set to 1. Disable if set to 0.
341  *
342  * RETURN     : void
343  *
344  *==========================================================================*/
powerHintInternal(PerfLockEnum perfLockType,PowerHint powerHint,int32_t time_out)345 void QCameraPerfLockMgr::powerHintInternal(
346         PerfLockEnum perfLockType,
347         PowerHint    powerHint,
348         int32_t      time_out)
349 {
350     if ((mState == LOCK_MGR_STATE_READY) &&
351         isValidPerfLockEnum(perfLockType)) {
352         mPerfLock[perfLockType]->powerHintInternal(powerHint, time_out);
353     }
354 }
355 
356 
357 /*===========================================================================
358  * FUNCTION   : create
359  *
360  * DESCRIPTION: This is a static method to create perf lock object. It calls
361  *              protected constructor of the class and only returns a valid object
362  *              if it can successfully initialize the perf lock.
363  *
364  * PARAMETERS : None
365  *
366  * RETURN     : QCameraPerfLock object pointer on success
367  *              NULL on failure
368  *
369  *==========================================================================*/
create(PerfLockEnum perfLockType)370 QCameraPerfLock* QCameraPerfLock::create(
371         PerfLockEnum perfLockType)
372 {
373     QCameraPerfLock *perfLock = NULL;
374 
375     if (perfLockType < PERF_LOCK_COUNT) {
376         QCameraPerfLockIntf *perfLockIntf = QCameraPerfLockIntf::createSingleton();
377         if (perfLockIntf) {
378             perfLock = new QCameraPerfLock(perfLockType, perfLockIntf);
379         }
380     }
381     return perfLock;
382 }
383 
384 
385 /*===========================================================================
386  * FUNCTION   : QCameraPerfLock constructor
387  *
388  * DESCRIPTION: Initialize member variables
389  *
390  * PARAMETERS : None
391  *
392  * RETURN     : void
393  *
394  *==========================================================================*/
QCameraPerfLock(PerfLockEnum perfLockType,QCameraPerfLockIntf * perfLockIntf)395 QCameraPerfLock::QCameraPerfLock(
396         PerfLockEnum         perfLockType,
397         QCameraPerfLockIntf *perfLockIntf) :
398         mHandle(0),
399         mRefCount(0),
400         mTimeOut(0),
401         mPerfLockType(perfLockType),
402         mPerfLockIntf(perfLockIntf)
403 {
404     mIsPerfdEnabled = android::base::GetBoolProperty("persist.camera.perfd.enable", false);
405 }
406 
407 
408 /*===========================================================================
409  * FUNCTION   : QCameraPerfLock destructor
410  *
411  * DESCRIPTION: class destructor
412  *
413  * PARAMETERS : None
414  *
415  * RETURN     : void
416  *
417  *==========================================================================*/
~QCameraPerfLock()418 QCameraPerfLock::~QCameraPerfLock()
419 {
420     if (mHandle > 0) {
421         (*mPerfLockIntf->perfLockRel())(mHandle);
422     }
423     QCameraPerfLockIntf::deleteInstance();
424 }
425 
426 
427 /*===========================================================================
428  * FUNCTION   : isTimedOut
429  *
430  * DESCRIPTION: Check if the perf lock is timed out
431  *
432  * PARAMETERS : None
433  *
434  * RETURN     : boolean indicating if the perf lock is timed out
435  *
436  *==========================================================================*/
isTimedOut()437 bool QCameraPerfLock::isTimedOut()
438 {
439     if (mTimeOut && (systemTime() > mTimeOut)) {
440         return true;
441     }
442     return false;
443 }
444 
445 
446 /*===========================================================================
447  * FUNCTION   : restartTimer
448  *
449  * DESCRIPTION: Restart the timer for the duration specified
450  *
451  * PARAMETERS :
452  *  @timer    : timer duration in milliseconds
453  *
454  * RETURN     : void
455  *
456  *==========================================================================*/
restartTimer(uint32_t timer)457 void inline QCameraPerfLock::restartTimer(
458         uint32_t timer)
459 {
460     if (timer > 0) {
461         mTimeOut = systemTime() + ms2ns(timer);
462     }
463 }
464 
465 
466 /*===========================================================================
467  * FUNCTION   : acquirePerfLock
468  *
469  * DESCRIPTION: Acquires the perf lock for the duration specified. Do not acquire
470  *              the perf lock is reacquire flag is set to false provided the perf
471  *              lock is already acquired.
472  *
473  * PARAMETERS :
474  * @forceReaquirePerfLock: Reacquire
475  * @timer     : Duration of the perf lock
476  *
477  * RETURN     : true  on success
478  *              false on failure
479  *
480  *==========================================================================*/
acquirePerfLock(bool forceReaquirePerfLock,uint32_t timer)481 bool QCameraPerfLock::acquirePerfLock(
482         bool     forceReaquirePerfLock,
483         uint32_t timer)
484 {
485     bool ret = true;
486     Mutex::Autolock lock(mMutex);
487 
488     switch (mPerfLockType) {
489         case PERF_LOCK_POWERHINT_PREVIEW:
490         case PERF_LOCK_POWERHINT_ENCODE:
491             powerHintInternal(PowerHint::CAMERA_STREAMING, true);
492             return true;
493         case PERF_LOCK_OPEN_CAMERA:
494         case PERF_LOCK_CLOSE_CAMERA:
495             powerHintInternal(PowerHint::CAMERA_LAUNCH, timer);
496             return true;
497         case PERF_LOCK_START_PREVIEW:
498             powerHintInternal(PowerHint::CAMERA_SHOT, timer);
499             return true;
500         case PERF_LOCK_TAKE_SNAPSHOT:
501             powerHintInternal(PowerHint::CAMERA_SHOT, timer);
502             return true;
503         default:
504             LOGE("Unknown powerhint %d",(int)mPerfLockType);
505             return false;
506     }
507 
508     if (!mIsPerfdEnabled) return ret;
509 
510     if (isTimedOut()) {
511         mHandle   = 0;
512         mRefCount = 0;
513     }
514 
515     if ((mRefCount == 0) || forceReaquirePerfLock) {
516         mHandle = (*mPerfLockIntf->perfLockAcq())(
517             mHandle, timer,
518             mPerfLockInfo[mPerfLockType].perfLockParams,
519             mPerfLockInfo[mPerfLockType].perfLockParamsCount);
520 
521         if (mHandle > 0) {
522             ++mRefCount;
523             restartTimer(timer);
524             LOGD("perfLockHandle %d, updated refCount: %d, perfLockType: %d",
525                 mHandle, mRefCount, mPerfLockType);
526         } else {
527             LOGE("Failed to acquire the perf lock");
528             ret = false;
529         }
530     } else {
531         LOGD("Perf lock already acquired, not re-aquiring");
532     }
533 
534     return ret;
535 }
536 
537 
538 /*===========================================================================
539  * FUNCTION   : releasePerfLock
540  *
541  * DESCRIPTION: Releases the perf lock
542  *
543  * PARAMETERS : None
544  *
545  * RETURN     : true  on success
546  *              false on failure
547  *
548  *==========================================================================*/
releasePerfLock()549 bool QCameraPerfLock::releasePerfLock()
550 {
551     bool ret = true;
552     Mutex::Autolock lock(mMutex);
553 
554     switch (mPerfLockType) {
555         case PERF_LOCK_POWERHINT_PREVIEW:
556         case PERF_LOCK_POWERHINT_ENCODE:
557             powerHintInternal(PowerHint::CAMERA_STREAMING, false);
558             return true;
559         case PERF_LOCK_OPEN_CAMERA:
560         case PERF_LOCK_CLOSE_CAMERA:
561             powerHintInternal(PowerHint::CAMERA_LAUNCH, false);
562             return true;
563         case PERF_LOCK_START_PREVIEW:
564             powerHintInternal(PowerHint::CAMERA_SHOT, false);
565             return true;
566         case PERF_LOCK_TAKE_SNAPSHOT:
567             powerHintInternal(PowerHint::CAMERA_SHOT, false);
568             return true;
569         default:
570             LOGE("Unknown powerhint %d",(int)mPerfLockType);
571             return false;
572     }
573 
574     if (!mIsPerfdEnabled) return ret;
575 
576     if (mHandle > 0) {
577         LOGD("perfLockHandle %d, refCount: %d, perfLockType: %d",
578                     mHandle, mRefCount, mPerfLockType);
579 
580         if (isTimedOut()) {
581             mHandle   = 0;
582             mRefCount = 0;
583         } else if (--mRefCount == 0) {
584             int32_t rc = (*mPerfLockIntf->perfLockRel())(mHandle);
585             mHandle = 0;
586             mTimeOut = 0;
587             if (rc < 0) {
588                 LOGE("Failed to release the perf lock");
589                 ret = false;
590             }
591         }
592     } else {
593         LOGW("Perf lock %d either not acquired or already released", mPerfLockType);
594     }
595 
596     return ret;
597 }
598 
599 
600 /*===========================================================================
601  * FUNCTION   : powerHintInternal
602  *
603  * DESCRIPTION: Sets the requested power hint and state to power HAL.
604  *
605  * PARAMETERS :
606  * @hint      : Power hint
607  * @enable    : Enable power hint if set to 1. Disable if set to 0.
608  *
609  * RETURN     : void
610  *
611  *==========================================================================*/
powerHintInternal(PowerHint powerHint,int32_t time_out)612 void QCameraPerfLock::powerHintInternal(
613         PowerHint    powerHint,
614         int32_t      time_out)
615 {
616 #ifdef HAS_MULTIMEDIA_HINTS
617     if (!mPerfLockIntf->powerHint(powerHint, time_out)) {
618         LOGE("Send powerhint to PowerHal failed");
619     }
620 #endif
621 }
622 
623 
624 
625 /*===========================================================================
626  * FUNCTION   : createSingleton
627  *
628  * DESCRIPTION: Open the perf lock library, query the function pointers and
629  *              create a singleton object upon success
630  *
631  * PARAMETERS : None
632  *
633  * RETURN     : QCameraPerfLockIntf object pointer on success
634  *              NULL on failure
635  *
636  *==========================================================================*/
createSingleton()637 QCameraPerfLockIntf* QCameraPerfLockIntf::createSingleton()
638 {
639     bool error = true;
640     Mutex::Autolock lock(mMutex);
641 
642     if (mInstance == NULL) {
643         // Open perflock library and query for the function pointers
644         uint32_t perfLockEnable = 0;
645         char value[PROPERTY_VALUE_MAX];
646 
647         property_get("persist.camera.perflock.enable", value, "1");
648         perfLockEnable = atoi(value);
649 
650         if (perfLockEnable) {
651             mInstance = new QCameraPerfLockIntf();
652             if (mInstance) {
653                 #ifdef HAS_MULTIMEDIA_HINTS
654                 std::lock_guard<std::mutex> lock(gPowerHalMutex);
655                 if (connectPowerHalLocked() == NONE) {
656                     ALOGE("Couldn't load PowerHAL module");
657                 } else {
658                     error = false;
659                 }
660                 #else
661                 {
662                     /* Retrieve the name of the vendor extension library */
663                     void *dlHandle = NULL;
664                     if ((property_get("ro.vendor.extension_library", value, NULL) > 0) &&
665                         (dlHandle = dlopen(value, RTLD_NOW | RTLD_LOCAL))) {
666 
667                         perfLockAcquire pLockAcq = (perfLockAcquire)dlsym(dlHandle, "perf_lock_acq");
668                         perfLockRelease pLockRel = (perfLockRelease)dlsym(dlHandle, "perf_lock_rel");
669 
670                         if (pLockAcq && pLockRel) {
671                             mInstance->mDlHandle    = dlHandle;
672                             mInstance->mPerfLockAcq = pLockAcq;
673                             mInstance->mPerfLockRel = pLockRel;
674                             error = false;
675                         } else {
676                             LOGE("Failed to link the symbols- perf_lock_acq, perf_lock_rel");
677                             bool IsPerfdEnabled = android::base::GetBoolProperty("persist.camera.perfd.enable", false);
678                             if (!IsPerfdEnabled) {
679                                 mInstance->mDlHandle    = nullptr;
680                                 mInstance->mPerfLockAcq = nullptr;
681                                 mInstance->mPerfLockRel = nullptr;
682                                 error = false;
683                             }
684                         }
685                     } else {
686                         LOGE("Unable to load lib: %s", value);
687                     }
688                 }
689                 #endif
690                 if (error && mInstance) {
691                     delete mInstance;
692                     mInstance = NULL;
693                 }
694             }
695         }
696     }
697 
698     if (mInstance) {
699         ++(mInstance->mRefCount);
700     }
701 
702     return mInstance;
703 }
704 
705 
706 /*===========================================================================
707  * FUNCTION   : deleteInstance
708  *
709  * DESCRIPTION: Delete the object if refCount is 0
710  *
711  * PARAMETERS : None
712  *
713  * RETURN     : void
714  *
715  *==========================================================================*/
deleteInstance()716 void QCameraPerfLockIntf::deleteInstance()
717 {
718     Mutex::Autolock lock(mMutex);
719 
720     if (mInstance && (--(mInstance->mRefCount) == 0)) {
721         delete mInstance;
722         mInstance = NULL;
723     }
724 }
725 
726 
727 /*===========================================================================
728  * FUNCTION   : QCameraPerfLockIntf destructor
729  *
730  * DESCRIPTION: class destructor
731  *
732  * PARAMETERS : None
733  *
734  * RETURN     : void
735  *
736  *==========================================================================*/
~QCameraPerfLockIntf()737 QCameraPerfLockIntf::~QCameraPerfLockIntf()
738 {
739     if (mDlHandle) {
740         dlclose(mDlHandle);
741     }
742 }
743 
powerHint(PowerHint hint,int32_t data)744 bool QCameraPerfLockIntf::powerHint(PowerHint hint, int32_t data) {
745     std::lock_guard<std::mutex> lock(gPowerHalMutex);
746     switch(connectPowerHalLocked()) {
747         case NONE:
748             return false;
749         case HIDL_1_2:
750             {
751               auto ret = gPowerHal_1_2_->powerHintAsync_1_2(hint, data);
752                 if (!ret.isOk()) {
753                     ALOGE("powerHint failed, error: %s",
754                           ret.description().c_str());
755                     gPowerHal_1_2_ = nullptr;
756                 }
757                 return ret.isOk();
758             }
759         case AIDL:
760             {
761                 bool ret = false;
762                 if (hint == PowerHint::CAMERA_LAUNCH) {
763                     int32_t durationMs = data ? kDefaultBoostDurationMs : kDisableBoostDurationMs;
764                     ret = gPowerHal_Aidl_->setBoost(Boost::CAMERA_LAUNCH, durationMs).isOk();
765                 } else if (hint == PowerHint::CAMERA_SHOT) {
766                     ret = gPowerHal_Aidl_->setBoost(Boost::CAMERA_SHOT, data).isOk();
767                 } else if (hint == PowerHint::CAMERA_STREAMING) {
768                     // Only CAMERA_STREAMING_MID is used
769                     ret = gPowerHal_Aidl_->setMode(Mode::CAMERA_STREAMING_MID, static_cast<bool>(data)).isOk();
770                 }
771                 if (!ret) {
772                     ALOGE("Failed to set power hint: %s.", toString(hint).c_str());
773                     gPowerHal_Aidl_ = nullptr;
774                 }
775                 return ret;
776             }
777         default:
778             ALOGE("Unknown HAL state");
779             return false;
780     }
781 }
782 
783 }; // namespace qcamera
784