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 // Camera dependencies
41 #include "QCameraPerf.h"
42 #include "QCameraTrace.h"
43 
44 #include <android-base/properties.h>
45 
46 extern "C" {
47 #include "mm_camera_dbg.h"
48 }
49 
50 namespace qcamera {
51 
52 using android::hidl::base::V1_0::IBase;
53 using android::hardware::hidl_death_recipient;
54 
55 static std::mutex gPowerHalMutex;
56 static sp<IPower> gPowerHal = nullptr;
57 static void getPowerHalLocked();
58 
59 // struct PowerHalDeathRecipient;
60 struct PowerHalDeathRecipient : virtual public hidl_death_recipient {
61     // hidl_death_recipient interface
serviceDiedqcamera::PowerHalDeathRecipient62     virtual void serviceDied(uint64_t, const wp<IBase>&) override {
63         std::lock_guard<std::mutex> lock(gPowerHalMutex);
64         ALOGE("PowerHAL just died");
65         gPowerHal = nullptr;
66         getPowerHalLocked();
67     }
68 };
69 
70 sp<PowerHalDeathRecipient> gPowerHalDeathRecipient = nullptr;
71 
72 // The caller must be holding gPowerHalMutex.
getPowerHalLocked()73 static void getPowerHalLocked() {
74     if (gPowerHal != nullptr) {
75         return;
76     }
77 
78     gPowerHal = IPower::getService();
79 
80     if (gPowerHal == nullptr) {
81         ALOGE("Unable to get Power service.");
82     } else {
83         if (gPowerHalDeathRecipient == nullptr) {
84             gPowerHalDeathRecipient = new PowerHalDeathRecipient();
85         }
86         hardware::Return<bool> linked = gPowerHal->linkToDeath(
87             gPowerHalDeathRecipient, 0x451F /* cookie */);
88         if (!linked.isOk()) {
89             ALOGE("Transaction error in linking to PowerHAL death: %s",
90                   linked.description().c_str());
91             gPowerHal = nullptr;
92         } else if (!linked) {
93             ALOGW("Unable to link to PowerHal death notifications");
94             gPowerHal = nullptr;
95         } else {
96             ALOGD("Link to death notification successful");
97         }
98     }
99 }
100 
101 typedef enum {
102     MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_0     = 0x40800000,
103     MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_1     = 0x40800010,
104     MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_2     = 0x40800020,
105     MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_3     = 0x40800030,
106     MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_0  = 0x40800100,
107     MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_1  = 0x40800110,
108     MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_2  = 0x40800120,
109     MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_3  = 0x40800130,
110 
111     MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_0     = 0x40804000,
112     MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_1     = 0x40804010,
113     MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_2     = 0x40804020,
114     MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_3     = 0x40804030,
115     MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_0  = 0x40804100,
116     MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_1  = 0x40804110,
117     MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_2  = 0x40804120,
118     MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_3  = 0x40804130,
119 
120     MPCTLV3_MIN_ONLINE_CPU_CLUSTER_BIG      = 0x41000000,
121     MPCTLV3_MIN_ONLINE_CPU_CLUSTER_LITTLE   = 0x41000100,
122     MPCTLV3_MAX_ONLINE_CPU_CLUSTER_BIG      = 0x41004000,
123     MPCTLV3_MAX_ONLINE_CPU_CLUSTER_LITTLE   = 0x41004100,
124 
125     MPCTLV3_ALL_CPUS_PWR_CLPS_DIS           = 0x40400000,
126     MPCTLV3_CPUBW_HWMON_MIN_FREQ            = 0x41800000,
127     MPCTLV3_CPUBW_HWMON_HYST_OPT            = 0x4180C000
128 } perf_lock_params;
129 
130 
131 static int32_t perfLockParamsOpenCamera[] = {
132     // Disable power collapse and set CPU cloks to turbo
133     MPCTLV3_ALL_CPUS_PWR_CLPS_DIS,          0x1,
134     MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_0,    0xFFF,
135     MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_0,    0xFFF,
136     MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF,
137     MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF
138 };
139 
140 static int32_t perfLockParamsCloseCamera[] = {
141     // Disable power collapse and set CPU cloks to turbo
142     MPCTLV3_ALL_CPUS_PWR_CLPS_DIS,          0x1,
143     MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_0,    0xFFF,
144     MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_0,    0xFFF,
145     MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF,
146     MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF
147 };
148 
149 static int32_t perfLockParamsStartPreview[] = {
150     // Disable power collapse and set CPU cloks to turbo
151     MPCTLV3_ALL_CPUS_PWR_CLPS_DIS,          0x1,
152     MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_0,    0xFFF,
153     MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_0,    0xFFF,
154     MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF,
155     MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF
156 };
157 
158 static int32_t perfLockParamsTakeSnapshot[] = {
159     // Disable power collapse and set CPU cloks to turbo
160     MPCTLV3_ALL_CPUS_PWR_CLPS_DIS,          0x1,
161     MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_0,    0xFFF,
162     MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_0,    0xFFF,
163     MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF,
164     MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF,
165     MPCTLV3_CPUBW_HWMON_HYST_OPT,           0x0,
166     MPCTLV3_CPUBW_HWMON_MIN_FREQ,           0x8C
167 };
168 
169 PerfLockInfo QCameraPerfLock::mPerfLockInfo[] = {
170     { //PERF_LOCK_OPEN_CAMERA
171       perfLockParamsOpenCamera,
172       sizeof(perfLockParamsOpenCamera)/sizeof(int32_t) },
173     { //PERF_LOCK_CLOSE_CAMERA
174       perfLockParamsCloseCamera,
175       sizeof(perfLockParamsCloseCamera)/sizeof(int32_t) },
176     { //PERF_LOCK_START_PREVIEW
177       perfLockParamsStartPreview,
178       sizeof(perfLockParamsStartPreview)/sizeof(int32_t) },
179     { //PERF_LOCK_TAKE_SNAPSHOT
180       perfLockParamsTakeSnapshot,
181       sizeof(perfLockParamsTakeSnapshot)/sizeof(int32_t) },
182     { //PERF_LOCK_POWERHINT_PREVIEW
183       NULL, 0},
184     { //PERF_LOCK_POWERHINT_ENCODE
185       NULL, 0}
186     };
187 
188 Mutex                QCameraPerfLockIntf::mMutex;
189 QCameraPerfLockIntf* QCameraPerfLockIntf::mInstance = NULL;
190 
191 
192 /*===========================================================================
193  * FUNCTION   : QCameraPerfLockMgr constructor
194  *
195  * DESCRIPTION: Initialize the perf locks
196  *
197  * PARAMETERS : None
198  *
199  * RETURN     : void
200  *
201  *==========================================================================*/
QCameraPerfLockMgr()202 QCameraPerfLockMgr::QCameraPerfLockMgr() :
203     mState(LOCK_MGR_STATE_UNINITIALIZED)
204 {
205     for (int i = 0; i < PERF_LOCK_COUNT; ++i) {
206         mPerfLock[i] = QCameraPerfLock::create((PerfLockEnum)i);
207 
208         if (mPerfLock[i] == NULL) {
209             mState = LOCK_MGR_STATE_ERROR;
210             LOGE("Could not allocate perf locks");
211 
212             // Set the remaining perf locks to NULL
213             for (int j = i+1; j < PERF_LOCK_COUNT; ++j) {
214                 mPerfLock[j] = NULL;
215             }
216             return;
217         }
218     }
219     mState = LOCK_MGR_STATE_READY;
220 }
221 
222 
223 /*===========================================================================
224  * FUNCTION   : QCameraPerfLockMgr destructor
225  *
226  * DESCRIPTION: class destructor
227  *
228  * PARAMETERS : None
229  *
230  * RETURN     : void
231  *
232  *==========================================================================*/
~QCameraPerfLockMgr()233 QCameraPerfLockMgr::~QCameraPerfLockMgr()
234 {
235     for (int i = 0; i < PERF_LOCK_COUNT; ++i) {
236         if (mPerfLock[i]) {
237             delete mPerfLock[i];
238         }
239     }
240 }
241 
242 
243 /*===========================================================================
244  * FUNCTION   : acquirePerfLock
245  *
246  * DESCRIPTION: Call acquirePerfLock function for the requested perf lock
247  *
248  * PARAMETERS :
249  * @perfLockType: Perf lock enum
250  * @timer:        Timer value in ms
251  *
252  * RETURN     : true  on success
253  *              false on failure
254  *==========================================================================*/
acquirePerfLock(PerfLockEnum perfLockType,uint32_t timer)255 bool QCameraPerfLockMgr::acquirePerfLock(
256         PerfLockEnum perfLockType,
257         uint32_t     timer)
258 {
259     bool ret = false;
260     if ((mState == LOCK_MGR_STATE_READY) &&
261         isValidPerfLockEnum(perfLockType)) {
262         ret = mPerfLock[perfLockType]->acquirePerfLock(true, timer);
263     }
264     return ret;
265 }
266 
267 
268 /*===========================================================================
269  * FUNCTION   : acquirePerfLockIfExpired
270  *
271  * DESCRIPTION: Call acquirePerfLock function for the requested perf lock
272  *
273  * PARAMETERS :
274  * @perfLockType: Type of perf lock
275  * @timer:        Timer value in ms
276  *
277  * RETURN     : true  on success
278  *              false on failure
279  *==========================================================================*/
acquirePerfLockIfExpired(PerfLockEnum perfLockType,uint32_t timer)280 bool QCameraPerfLockMgr::acquirePerfLockIfExpired(
281         PerfLockEnum perfLockType,
282         uint32_t     timer)
283 {
284     bool ret = false;
285     if ((mState == LOCK_MGR_STATE_READY) &&
286         isValidPerfLockEnum(perfLockType)) {
287         ret = mPerfLock[perfLockType]->acquirePerfLock(false, timer);
288     }
289     return ret;
290 
291 }
292 
293 
294 /*===========================================================================
295  * FUNCTION   : releasePerfLock
296  *
297  * DESCRIPTION: Call releasePerfLock function for the requested perf lock
298  *
299  * PARAMETERS :
300  * @perfLockType: Enum of perf lock
301  *
302  * RETURN     : true  on success
303  *              false on failure
304  *==========================================================================*/
releasePerfLock(PerfLockEnum perfLockType)305 bool QCameraPerfLockMgr::releasePerfLock(
306         PerfLockEnum perfLockType)
307 {
308     bool ret = false;
309     if ((mState == LOCK_MGR_STATE_READY) &&
310         isValidPerfLockEnum(perfLockType)) {
311         ret = mPerfLock[perfLockType]->releasePerfLock();
312     }
313     return ret;
314 }
315 
316 
317 /*===========================================================================
318  * FUNCTION   : powerHintInternal
319  *
320  * DESCRIPTION: Calls the appropriate perf lock's powerHintInternal function
321  *
322  * PARAMETERS :
323  * @perfLockType: Type of perf lock
324  * @hint        : Power hint
325  * @enable      : Enable power hint if set to 1. Disable if set to 0.
326  *
327  * RETURN     : void
328  *
329  *==========================================================================*/
powerHintInternal(PerfLockEnum perfLockType,PowerHint powerHint,int32_t time_out)330 void QCameraPerfLockMgr::powerHintInternal(
331         PerfLockEnum perfLockType,
332         PowerHint    powerHint,
333         int32_t      time_out)
334 {
335     if ((mState == LOCK_MGR_STATE_READY) &&
336         isValidPerfLockEnum(perfLockType)) {
337         mPerfLock[perfLockType]->powerHintInternal(powerHint, time_out);
338     }
339 }
340 
341 
342 /*===========================================================================
343  * FUNCTION   : create
344  *
345  * DESCRIPTION: This is a static method to create perf lock object. It calls
346  *              protected constructor of the class and only returns a valid object
347  *              if it can successfully initialize the perf lock.
348  *
349  * PARAMETERS : None
350  *
351  * RETURN     : QCameraPerfLock object pointer on success
352  *              NULL on failure
353  *
354  *==========================================================================*/
create(PerfLockEnum perfLockType)355 QCameraPerfLock* QCameraPerfLock::create(
356         PerfLockEnum perfLockType)
357 {
358     QCameraPerfLock *perfLock = NULL;
359 
360     if (perfLockType < PERF_LOCK_COUNT) {
361         QCameraPerfLockIntf *perfLockIntf = QCameraPerfLockIntf::createSingleton();
362         if (perfLockIntf) {
363             perfLock = new QCameraPerfLock(perfLockType, perfLockIntf);
364         }
365     }
366     return perfLock;
367 }
368 
369 
370 /*===========================================================================
371  * FUNCTION   : QCameraPerfLock constructor
372  *
373  * DESCRIPTION: Initialize member variables
374  *
375  * PARAMETERS : None
376  *
377  * RETURN     : void
378  *
379  *==========================================================================*/
QCameraPerfLock(PerfLockEnum perfLockType,QCameraPerfLockIntf * perfLockIntf)380 QCameraPerfLock::QCameraPerfLock(
381         PerfLockEnum         perfLockType,
382         QCameraPerfLockIntf *perfLockIntf) :
383         mHandle(0),
384         mRefCount(0),
385         mTimeOut(0),
386         mPerfLockType(perfLockType),
387         mPerfLockIntf(perfLockIntf)
388 {
389     mIsPerfdEnabled = android::base::GetBoolProperty("persist.camera.perfd.enable", false);
390 }
391 
392 
393 /*===========================================================================
394  * FUNCTION   : QCameraPerfLock destructor
395  *
396  * DESCRIPTION: class destructor
397  *
398  * PARAMETERS : None
399  *
400  * RETURN     : void
401  *
402  *==========================================================================*/
~QCameraPerfLock()403 QCameraPerfLock::~QCameraPerfLock()
404 {
405     if (mHandle > 0) {
406         (*mPerfLockIntf->perfLockRel())(mHandle);
407     }
408     QCameraPerfLockIntf::deleteInstance();
409 }
410 
411 
412 /*===========================================================================
413  * FUNCTION   : isTimedOut
414  *
415  * DESCRIPTION: Check if the perf lock is timed out
416  *
417  * PARAMETERS : None
418  *
419  * RETURN     : boolean indicating if the perf lock is timed out
420  *
421  *==========================================================================*/
isTimedOut()422 bool QCameraPerfLock::isTimedOut()
423 {
424     if (mTimeOut && (systemTime() > mTimeOut)) {
425         return true;
426     }
427     return false;
428 }
429 
430 
431 /*===========================================================================
432  * FUNCTION   : restartTimer
433  *
434  * DESCRIPTION: Restart the timer for the duration specified
435  *
436  * PARAMETERS :
437  *  @timer    : timer duration in milliseconds
438  *
439  * RETURN     : void
440  *
441  *==========================================================================*/
restartTimer(uint32_t timer)442 void inline QCameraPerfLock::restartTimer(
443         uint32_t timer)
444 {
445     if (timer > 0) {
446         mTimeOut = systemTime() + ms2ns(timer);
447     }
448 }
449 
450 
451 /*===========================================================================
452  * FUNCTION   : acquirePerfLock
453  *
454  * DESCRIPTION: Acquires the perf lock for the duration specified. Do not acquire
455  *              the perf lock is reacquire flag is set to false provided the perf
456  *              lock is already acquired.
457  *
458  * PARAMETERS :
459  * @forceReaquirePerfLock: Reacquire
460  * @timer     : Duration of the perf lock
461  *
462  * RETURN     : true  on success
463  *              false on failure
464  *
465  *==========================================================================*/
acquirePerfLock(bool forceReaquirePerfLock,uint32_t timer)466 bool QCameraPerfLock::acquirePerfLock(
467         bool     forceReaquirePerfLock,
468         uint32_t timer)
469 {
470     bool ret = true;
471     Mutex::Autolock lock(mMutex);
472 
473     switch (mPerfLockType) {
474         case PERF_LOCK_POWERHINT_PREVIEW:
475         case PERF_LOCK_POWERHINT_ENCODE:
476             powerHintInternal(PowerHint::CAMERA_STREAMING, true);
477             return true;
478         case PERF_LOCK_OPEN_CAMERA:
479         case PERF_LOCK_CLOSE_CAMERA:
480             powerHintInternal(PowerHint::CAMERA_LAUNCH, timer);
481             return true;
482         case PERF_LOCK_START_PREVIEW:
483             powerHintInternal(PowerHint::CAMERA_SHOT, timer);
484             return true;
485         case PERF_LOCK_TAKE_SNAPSHOT:
486             powerHintInternal(PowerHint::CAMERA_SHOT, timer);
487             return true;
488         default:
489             LOGE("Unknown powerhint %d",(int)mPerfLockType);
490             return false;
491     }
492 
493     if (!mIsPerfdEnabled) return ret;
494 
495     if (isTimedOut()) {
496         mHandle   = 0;
497         mRefCount = 0;
498     }
499 
500     if ((mRefCount == 0) || forceReaquirePerfLock) {
501         mHandle = (*mPerfLockIntf->perfLockAcq())(
502             mHandle, timer,
503             mPerfLockInfo[mPerfLockType].perfLockParams,
504             mPerfLockInfo[mPerfLockType].perfLockParamsCount);
505 
506         if (mHandle > 0) {
507             ++mRefCount;
508             restartTimer(timer);
509             LOGD("perfLockHandle %d, updated refCount: %d, perfLockType: %d",
510                 mHandle, mRefCount, mPerfLockType);
511         } else {
512             LOGE("Failed to acquire the perf lock");
513             ret = false;
514         }
515     } else {
516         LOGD("Perf lock already acquired, not re-aquiring");
517     }
518 
519     return ret;
520 }
521 
522 
523 /*===========================================================================
524  * FUNCTION   : releasePerfLock
525  *
526  * DESCRIPTION: Releases the perf lock
527  *
528  * PARAMETERS : None
529  *
530  * RETURN     : true  on success
531  *              false on failure
532  *
533  *==========================================================================*/
releasePerfLock()534 bool QCameraPerfLock::releasePerfLock()
535 {
536     bool ret = true;
537     Mutex::Autolock lock(mMutex);
538 
539     switch (mPerfLockType) {
540         case PERF_LOCK_POWERHINT_PREVIEW:
541         case PERF_LOCK_POWERHINT_ENCODE:
542             powerHintInternal(PowerHint::CAMERA_STREAMING, false);
543             return true;
544         case PERF_LOCK_OPEN_CAMERA:
545         case PERF_LOCK_CLOSE_CAMERA:
546             powerHintInternal(PowerHint::CAMERA_LAUNCH, false);
547             return true;
548         case PERF_LOCK_START_PREVIEW:
549             powerHintInternal(PowerHint::CAMERA_SHOT, false);
550             return true;
551         case PERF_LOCK_TAKE_SNAPSHOT:
552             powerHintInternal(PowerHint::CAMERA_SHOT, false);
553             return true;
554         default:
555             LOGE("Unknown powerhint %d",(int)mPerfLockType);
556             return false;
557     }
558 
559     if (!mIsPerfdEnabled) return ret;
560 
561     if (mHandle > 0) {
562         LOGD("perfLockHandle %d, refCount: %d, perfLockType: %d",
563                     mHandle, mRefCount, mPerfLockType);
564 
565         if (isTimedOut()) {
566             mHandle   = 0;
567             mRefCount = 0;
568         } else if (--mRefCount == 0) {
569             int32_t rc = (*mPerfLockIntf->perfLockRel())(mHandle);
570             mHandle = 0;
571             mTimeOut = 0;
572             if (rc < 0) {
573                 LOGE("Failed to release the perf lock");
574                 ret = false;
575             }
576         }
577     } else {
578         LOGW("Perf lock %d either not acquired or already released", mPerfLockType);
579     }
580 
581     return ret;
582 }
583 
584 
585 /*===========================================================================
586  * FUNCTION   : powerHintInternal
587  *
588  * DESCRIPTION: Sets the requested power hint and state to power HAL.
589  *
590  * PARAMETERS :
591  * @hint      : Power hint
592  * @enable    : Enable power hint if set to 1. Disable if set to 0.
593  *
594  * RETURN     : void
595  *
596  *==========================================================================*/
powerHintInternal(PowerHint powerHint,int32_t time_out)597 void QCameraPerfLock::powerHintInternal(
598         PowerHint    powerHint,
599         int32_t      time_out)
600 {
601 #ifdef HAS_MULTIMEDIA_HINTS
602     if (!mPerfLockIntf->powerHint(powerHint, time_out)) {
603         LOGE("Send powerhint to PowerHal failed");
604     }
605 #endif
606 }
607 
608 
609 
610 /*===========================================================================
611  * FUNCTION   : createSingleton
612  *
613  * DESCRIPTION: Open the perf lock library, query the function pointers and
614  *              create a singleton object upon success
615  *
616  * PARAMETERS : None
617  *
618  * RETURN     : QCameraPerfLockIntf object pointer on success
619  *              NULL on failure
620  *
621  *==========================================================================*/
createSingleton()622 QCameraPerfLockIntf* QCameraPerfLockIntf::createSingleton()
623 {
624     bool error = true;
625     Mutex::Autolock lock(mMutex);
626 
627     if (mInstance == NULL) {
628         // Open perflock library and query for the function pointers
629         uint32_t perfLockEnable = 0;
630         char value[PROPERTY_VALUE_MAX];
631 
632         property_get("persist.camera.perflock.enable", value, "1");
633         perfLockEnable = atoi(value);
634 
635         if (perfLockEnable) {
636             mInstance = new QCameraPerfLockIntf();
637             if (mInstance) {
638                 #ifdef HAS_MULTIMEDIA_HINTS
639                 std::lock_guard<std::mutex> lock(gPowerHalMutex);
640                 getPowerHalLocked();
641                 if (gPowerHal == nullptr) {
642                     ALOGE("Couldn't load PowerHAL module");
643                 }
644                 else
645                 #endif
646                 {
647                     /* Retrieve the name of the vendor extension library */
648                     void *dlHandle = NULL;
649                     if ((property_get("ro.vendor.extension_library", value, NULL) > 0) &&
650                         (dlHandle = dlopen(value, RTLD_NOW | RTLD_LOCAL))) {
651 
652                         perfLockAcquire pLockAcq = (perfLockAcquire)dlsym(dlHandle, "perf_lock_acq");
653                         perfLockRelease pLockRel = (perfLockRelease)dlsym(dlHandle, "perf_lock_rel");
654 
655                         if (pLockAcq && pLockRel) {
656                             mInstance->mDlHandle    = dlHandle;
657                             mInstance->mPerfLockAcq = pLockAcq;
658                             mInstance->mPerfLockRel = pLockRel;
659                             error = false;
660                         } else {
661                             LOGE("Failed to link the symbols- perf_lock_acq, perf_lock_rel");
662                             bool IsPerfdEnabled = android::base::GetBoolProperty("persist.camera.perfd.enable", false);
663                             if (!IsPerfdEnabled) {
664                                 mInstance->mDlHandle    = nullptr;
665                                 mInstance->mPerfLockAcq = nullptr;
666                                 mInstance->mPerfLockRel = nullptr;
667                                 error = false;
668                             }
669                         }
670                     } else {
671                         LOGE("Unable to load lib: %s", value);
672                     }
673                 }
674                 if (error && mInstance) {
675                     delete mInstance;
676                     mInstance = NULL;
677                 }
678             }
679         }
680     }
681 
682     if (mInstance) {
683         ++(mInstance->mRefCount);
684     }
685 
686     return mInstance;
687 }
688 
689 
690 /*===========================================================================
691  * FUNCTION   : deleteInstance
692  *
693  * DESCRIPTION: Delete the object if refCount is 0
694  *
695  * PARAMETERS : None
696  *
697  * RETURN     : void
698  *
699  *==========================================================================*/
deleteInstance()700 void QCameraPerfLockIntf::deleteInstance()
701 {
702     Mutex::Autolock lock(mMutex);
703 
704     if (mInstance && (--(mInstance->mRefCount) == 0)) {
705         delete mInstance;
706         mInstance = NULL;
707     }
708 }
709 
710 
711 /*===========================================================================
712  * FUNCTION   : QCameraPerfLockIntf destructor
713  *
714  * DESCRIPTION: class destructor
715  *
716  * PARAMETERS : None
717  *
718  * RETURN     : void
719  *
720  *==========================================================================*/
~QCameraPerfLockIntf()721 QCameraPerfLockIntf::~QCameraPerfLockIntf()
722 {
723     if (mDlHandle) {
724         dlclose(mDlHandle);
725     }
726 }
727 
powerHint(PowerHint hint,int32_t data)728 bool QCameraPerfLockIntf::powerHint(PowerHint hint, int32_t data) {
729     std::lock_guard<std::mutex> lock(gPowerHalMutex);
730     getPowerHalLocked();
731     if (gPowerHal == nullptr) {
732         ALOGE("Couldn't do powerHint because of HAL error.");
733         return false;
734     }
735     auto ret = gPowerHal->powerHintAsync_1_2(hint, data);
736     if (!ret.isOk()) {
737         ALOGE("powerHint failed error: %s", ret.description().c_str());
738     }
739     return ret.isOk();
740 }
741 
742 }; // namespace qcamera
743