Home | History | Annotate | Download | only in util
      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 
     35 // System dependencies
     36 #include <stdlib.h>
     37 #include <dlfcn.h>
     38 
     39 // Camera dependencies
     40 #include "QCameraPerf.h"
     41 #include "QCameraTrace.h"
     42 
     43 extern "C" {
     44 #include "mm_camera_dbg.h"
     45 }
     46 
     47 namespace qcamera {
     48 
     49 /*===========================================================================
     50  * FUNCTION   : QCameraPerfLock constructor
     51  *
     52  * DESCRIPTION: initialize member variables
     53  *
     54  * PARAMETERS :
     55  *   None
     56  *
     57  * RETURN     : void
     58  *
     59  *==========================================================================*/
     60 QCameraPerfLock::QCameraPerfLock() :
     61         perf_lock_acq(NULL),
     62         perf_lock_rel(NULL),
     63         mDlHandle(NULL),
     64         mPerfLockEnable(0),
     65         mPerfLockHandle(-1),
     66         mPerfLockHandleTimed(-1),
     67         mTimerSet(0),
     68         mPerfLockTimeout(0),
     69         mStartTimeofLock(0)
     70 {
     71 }
     72 
     73 /*===========================================================================
     74  * FUNCTION   : QCameraPerfLock destructor
     75  *
     76  * DESCRIPTION: class desctructor
     77  *
     78  * PARAMETERS :
     79  *   None
     80  *
     81  * RETURN     : void
     82  *
     83  *==========================================================================*/
     84 QCameraPerfLock::~QCameraPerfLock()
     85 {
     86     lock_deinit();
     87 }
     88 
     89 
     90 /*===========================================================================
     91  * FUNCTION   : lock_init
     92  *
     93  * DESCRIPTION: opens the performance lib and initilizes the perf lock functions
     94  *
     95  * PARAMETERS :
     96  *   None
     97  *
     98  * RETURN     : void
     99  *
    100  *==========================================================================*/
    101 void QCameraPerfLock::lock_init()
    102 {
    103     const char *rc;
    104     char value[PROPERTY_VALUE_MAX];
    105 
    106     LOGD("E");
    107     Mutex::Autolock lock(mLock);
    108 
    109     // Clear the list of active power hints
    110     mActivePowerHints.clear();
    111     mCurrentPowerHint       = static_cast<PowerHint>(0);
    112     mCurrentPowerHintEnable = false;
    113 
    114     property_get("persist.camera.perflock.enable", value, "1");
    115     mPerfLockEnable = atoi(value);
    116 #ifdef HAS_MULTIMEDIA_HINTS
    117     mPowerHal = IPower::getService();
    118     if (mPowerHal == nullptr) {
    119         ALOGE("Couldn't load PowerHAL module");
    120     }
    121 #endif
    122 
    123     if (mPerfLockEnable) {
    124         perf_lock_acq = NULL;
    125         perf_lock_rel = NULL;
    126         mPerfLockHandle = -1;
    127         /* Retrieve name of vendor extension library */
    128         if (property_get("ro.vendor.extension_library", value, NULL) <= 0) {
    129             goto cleanup;
    130         }
    131 
    132         mDlHandle = dlopen(value, RTLD_NOW | RTLD_LOCAL);
    133         if (mDlHandle == NULL) {
    134             goto cleanup;
    135         }
    136 
    137         dlerror();
    138 
    139         perf_lock_acq = (int (*) (int, int, int[], int))dlsym(mDlHandle, "perf_lock_acq");
    140         if ((rc = dlerror()) != NULL) {
    141             LOGE("failed to perf_lock_acq function handle");
    142             goto cleanup;
    143         }
    144 
    145         perf_lock_rel = (int (*) (int))dlsym(mDlHandle, "perf_lock_rel");
    146         if ((rc = dlerror()) != NULL) {
    147             LOGE("failed to perf_lock_rel function handle");
    148             goto cleanup;
    149         }
    150         LOGD("X");
    151         return;
    152 
    153 cleanup:
    154         perf_lock_acq  = NULL;
    155         perf_lock_rel  = NULL;
    156         mPerfLockEnable = 0;
    157         if (mDlHandle) {
    158             dlclose(mDlHandle);
    159             mDlHandle = NULL;
    160         }
    161     }
    162     LOGD("X");
    163 }
    164 
    165 /*===========================================================================
    166  * FUNCTION   : lock_deinit
    167  *
    168  * DESCRIPTION: deinitialize the perf lock parameters
    169  *
    170  * PARAMETERS :
    171  *   None
    172  *
    173  * RETURN     : void
    174  *
    175  *==========================================================================*/
    176 void QCameraPerfLock::lock_deinit()
    177 {
    178     Mutex::Autolock lock(mLock);
    179     if (mPerfLockEnable) {
    180         LOGD("E");
    181 
    182         if (mActivePowerHints.empty() == false) {
    183             // Disable the active power hint
    184             mCurrentPowerHint = *mActivePowerHints.begin();
    185             powerHintInternal(mCurrentPowerHint, false);
    186             mActivePowerHints.clear();
    187         }
    188 
    189         if ((NULL != perf_lock_rel) && (mPerfLockHandleTimed >= 0)) {
    190             (*perf_lock_rel)(mPerfLockHandleTimed);
    191         }
    192 
    193         if ((NULL != perf_lock_rel) && (mPerfLockHandle >= 0)) {
    194             (*perf_lock_rel)(mPerfLockHandle);
    195         }
    196 
    197         if (mDlHandle) {
    198             perf_lock_acq  = NULL;
    199             perf_lock_rel  = NULL;
    200 
    201             dlclose(mDlHandle);
    202             mDlHandle       = NULL;
    203         }
    204         mPerfLockEnable = 0;
    205         LOGD("X");
    206     }
    207 }
    208 
    209 /*===========================================================================
    210  * FUNCTION   : isTimerReset
    211  *
    212  * DESCRIPTION: Check if timout duration is reached
    213  *
    214  * PARAMETERS : None
    215  *
    216  * RETURN     : true if timeout reached
    217  *              false if timeout not reached
    218  *
    219  *==========================================================================*/
    220 bool QCameraPerfLock::isTimerReset()
    221 {
    222     Mutex::Autolock lock(mLock);
    223     if (mPerfLockEnable && mTimerSet) {
    224         nsecs_t timeDiff = systemTime() - mStartTimeofLock;
    225         if (ns2ms(timeDiff) > (uint32_t)mPerfLockTimeout) {
    226             resetTimer();
    227             return true;
    228         }
    229     }
    230     return false;
    231 }
    232 
    233 /*===========================================================================
    234  * FUNCTION   : resetTimer
    235  *
    236  * DESCRIPTION: Reset the timer used in timed perf lock
    237  *
    238  * PARAMETERS : None
    239  *
    240  * RETURN     : void
    241  *
    242  *==========================================================================*/
    243 void QCameraPerfLock::resetTimer()
    244 {
    245     mPerfLockTimeout = 0;
    246     mTimerSet = 0;
    247 }
    248 
    249 /*===========================================================================
    250  * FUNCTION   : start_timer
    251  *
    252  * DESCRIPTION: get the start of the timer
    253  *
    254  * PARAMETERS :
    255  *  @timer_val: timer duration in milliseconds
    256  *
    257  * RETURN     : int32_t type of status
    258  *              NO_ERROR  -- success
    259  *              none-zero failure code
    260  *
    261  *==========================================================================*/
    262 void QCameraPerfLock::startTimer(uint32_t timer_val)
    263 {
    264     mStartTimeofLock = systemTime();
    265     mTimerSet = 1;
    266     mPerfLockTimeout = timer_val;
    267 }
    268 
    269 /*===========================================================================
    270  * FUNCTION   : lock_acq_timed
    271  *
    272  * DESCRIPTION: Acquire the performance lock for the specified duration.
    273  *              If an existing lock timeout has not elapsed, extend the
    274  *              lock further for the specified duration
    275  *
    276  * PARAMETERS :
    277  *  @timer_val: lock duration
    278  *
    279  * RETURN     : int32_t type of status
    280  *              NO_ERROR  -- success
    281  *              none-zero failure code
    282  *
    283  *==========================================================================*/
    284 int32_t QCameraPerfLock::lock_acq_timed(int32_t timer_val)
    285 {
    286     int32_t ret = -1;
    287 
    288     LOGD("E");
    289     Mutex::Autolock lock(mLock);
    290 
    291     if (mPerfLockEnable) {
    292         int32_t perf_lock_params[] = {
    293                 ALL_CPUS_PWR_CLPS_DIS,
    294                 CPU0_MIN_FREQ_TURBO_MAX,
    295                 CPU4_MIN_FREQ_TURBO_MAX
    296         };
    297         if (mTimerSet) {
    298             nsecs_t curElapsedTime = systemTime() - mStartTimeofLock;
    299             int32_t pendingTimeout = mPerfLockTimeout - ns2ms(curElapsedTime);
    300             timer_val += pendingTimeout;
    301         }
    302         startTimer(timer_val);
    303 
    304         // Disable power hint when acquiring the perf lock
    305         if (mCurrentPowerHintEnable) {
    306             LOGD("mCurrentPowerHintEnable %d" ,mCurrentPowerHintEnable);
    307             powerHintInternal(mCurrentPowerHint, false);
    308         }
    309 
    310         if ((NULL != perf_lock_acq) && (mPerfLockHandleTimed < 0)) {
    311             ret = (*perf_lock_acq)(mPerfLockHandleTimed, timer_val, perf_lock_params,
    312                     sizeof(perf_lock_params) / sizeof(int32_t));
    313             LOGD("ret %d", ret);
    314             if (ret < 0) {
    315                 LOGE("failed to acquire lock");
    316             } else {
    317                 mPerfLockHandleTimed = ret;
    318             }
    319         }
    320         LOGD("perf_handle_acq %d ", mPerfLockHandleTimed);
    321     }
    322 
    323     LOGD("X");
    324     return ret;
    325 }
    326 
    327 /*===========================================================================
    328  * FUNCTION   : lock_acq
    329  *
    330  * DESCRIPTION: acquire the performance lock
    331  *
    332  * PARAMETERS :
    333  *   None
    334  *
    335  * RETURN     : int32_t type of status
    336  *              NO_ERROR  -- success
    337  *              none-zero failure code
    338  *
    339  *==========================================================================*/
    340 int32_t QCameraPerfLock::lock_acq()
    341 {
    342     int32_t ret = -1;
    343 
    344     LOGD("E");
    345     Mutex::Autolock lock(mLock);
    346 
    347     if (mPerfLockEnable) {
    348         int32_t perf_lock_params[] = {
    349                 ALL_CPUS_PWR_CLPS_DIS,
    350                 CPU0_MIN_FREQ_TURBO_MAX,
    351                 CPU4_MIN_FREQ_TURBO_MAX
    352         };
    353 
    354         // Disable power hint when acquiring the perf lock
    355         if (mCurrentPowerHintEnable) {
    356             powerHintInternal(mCurrentPowerHint, false);
    357         }
    358 
    359         if ((NULL != perf_lock_acq) && (mPerfLockHandle < 0)) {
    360             ret = (*perf_lock_acq)(mPerfLockHandle, ONE_SEC, perf_lock_params,
    361                     sizeof(perf_lock_params) / sizeof(int32_t));
    362             LOGD("ret %d", ret);
    363             if (ret < 0) {
    364                 LOGE("failed to acquire lock");
    365             } else {
    366                 mPerfLockHandle = ret;
    367             }
    368         }
    369         LOGD("perf_handle_acq %d ", mPerfLockHandle);
    370     }
    371 
    372     LOGD("X");
    373     return ret;
    374 }
    375 
    376 /*===========================================================================
    377  * FUNCTION   : lock_rel_timed
    378  *
    379  * DESCRIPTION: release the performance lock
    380  *
    381  * PARAMETERS :
    382  *   None
    383  *
    384  * RETURN     : int32_t type of status
    385  *              NO_ERROR  -- success
    386  *              none-zero failure code
    387  *
    388  *==========================================================================*/
    389 int32_t QCameraPerfLock::lock_rel_timed()
    390 {
    391     int ret = -1;
    392     Mutex::Autolock lock(mLock);
    393     if (mPerfLockEnable) {
    394         LOGD("E");
    395         if (mPerfLockHandleTimed < 0) {
    396             LOGW("mPerfLockHandle < 0,check if lock is acquired");
    397             return ret;
    398         }
    399         LOGD("perf_handle_rel %d ", mPerfLockHandleTimed);
    400 
    401         if ((NULL != perf_lock_rel) && (0 <= mPerfLockHandleTimed)) {
    402             ret = (*perf_lock_rel)(mPerfLockHandleTimed);
    403             if (ret < 0) {
    404                 LOGE("failed to release lock");
    405             }
    406             mPerfLockHandleTimed = -1;
    407             resetTimer();
    408         }
    409 
    410         if ((mCurrentPowerHintEnable == 1) && (mTimerSet == 0)) {
    411             powerHintInternal(mCurrentPowerHint, mCurrentPowerHintEnable);
    412         }
    413         LOGD("X");
    414     }
    415     return ret;
    416 }
    417 
    418 /*===========================================================================
    419  * FUNCTION   : lock_rel
    420  *
    421  * DESCRIPTION: release the performance lock
    422  *
    423  * PARAMETERS :
    424  *   None
    425  *
    426  * RETURN     : int32_t type of status
    427  *              NO_ERROR  -- success
    428  *              none-zero failure code
    429  *
    430  *==========================================================================*/
    431 int32_t QCameraPerfLock::lock_rel()
    432 {
    433     int ret = -1;
    434     Mutex::Autolock lock(mLock);
    435     if (mPerfLockEnable) {
    436         LOGD("E");
    437         if (mPerfLockHandle < 0) {
    438             LOGW("mPerfLockHandle < 0,check if lock is acquired");
    439             return ret;
    440         }
    441         LOGD("perf_handle_rel %d ", mPerfLockHandle);
    442 
    443         if ((NULL != perf_lock_rel) && (0 <= mPerfLockHandle)) {
    444             ret = (*perf_lock_rel)(mPerfLockHandle);
    445             if (ret < 0) {
    446                 LOGE("failed to release lock");
    447             }
    448             mPerfLockHandle = -1;
    449         }
    450 
    451         if (mCurrentPowerHintEnable == 1) {
    452             powerHintInternal(mCurrentPowerHint, mCurrentPowerHintEnable);
    453         }
    454         LOGD("X");
    455     }
    456     return ret;
    457 }
    458 
    459 /*===========================================================================
    460  * FUNCTION   : powerHintInternal
    461  *
    462  * DESCRIPTION: Sets the requested power hint and state to power HAL.
    463  *
    464  * PARAMETERS :
    465  * hint       : Power hint
    466  * enable     : Enable power hint if set to 1. Disable if set to 0.
    467  * RETURN     : void
    468  *
    469  *==========================================================================*/
    470 void QCameraPerfLock::powerHintInternal(PowerHint hint, bool enable)
    471 {
    472 #ifdef HAS_MULTIMEDIA_HINTS
    473     if (mPowerHal != nullptr && !mPowerHal->powerHintAsync(hint, enable).isOk()) {
    474         LOGE("Send powerhint to PowerHal failed");
    475     }
    476 #endif
    477 }
    478 
    479 /*===========================================================================
    480  * FUNCTION   : powerHint
    481  *
    482  * DESCRIPTION: Updates the list containing active/enabled power hints.
    483  *              If needed, calls the internal powerHint function with
    484  *              requested power hint and state.
    485  * PARAMETERS :
    486  * hint       : Power hint
    487  * enable     : Enable power hint if set to 1. Disable if set to 0.
    488  * RETURN     : void
    489  *
    490  *==========================================================================*/
    491 void QCameraPerfLock::powerHint(PowerHint hint, bool enable)
    492 {
    493 #ifdef HAS_MULTIMEDIA_HINTS
    494     if (enable == true) {
    495         if ((hint != mCurrentPowerHint) || (enable != mCurrentPowerHintEnable)) {
    496             // Disable the current active power hint
    497             if (mCurrentPowerHintEnable == true) {
    498                 powerHintInternal(mCurrentPowerHint, false);
    499             }
    500             // Push the new power hint at the head of the active power hint list
    501             mActivePowerHints.push_front(hint);
    502 
    503             // Set the new power hint
    504             mCurrentPowerHint       = hint;
    505             mCurrentPowerHintEnable = enable;
    506             powerHintInternal(hint, enable);
    507         }
    508     } else {
    509         // Remove the power hint from the list
    510         for (List<PowerHint>::iterator it = mActivePowerHints.begin();
    511                 it != mActivePowerHints.end(); ++it) {
    512             if (*it == hint) {
    513                 if (it != mActivePowerHints.begin()) {
    514                     LOGW("Request to remove the previous power hint: %d instead of "
    515                             "currently active power hint: %d", static_cast<int>(hint),
    516                                                             static_cast<int>(mCurrentPowerHint));
    517                 }
    518                 mActivePowerHints.erase(it);
    519                 break;
    520             }
    521         }
    522 
    523         if (hint == mCurrentPowerHint) {
    524             // Disable the power hint
    525             powerHintInternal(hint, false);
    526 
    527             // If the active power hint list is not empty,
    528             // restore the previous power hint from the head of the list
    529             if (mActivePowerHints.empty() == false) {
    530                 mCurrentPowerHint       = *mActivePowerHints.begin();
    531                 mCurrentPowerHintEnable = true;
    532                 powerHintInternal(mCurrentPowerHint, true);
    533             } else {
    534                 mCurrentPowerHint       = static_cast<PowerHint>(0);
    535                 mCurrentPowerHintEnable = false;
    536             }
    537         }
    538     }
    539 #endif
    540 }
    541 
    542 }; // namespace qcamera
    543