• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  *==========================================================================*/
QCameraPerfLock()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  *==========================================================================*/
~QCameraPerfLock()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  *==========================================================================*/
lock_init()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  *==========================================================================*/
lock_deinit()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  *==========================================================================*/
isTimerReset()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  *==========================================================================*/
resetTimer()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  *==========================================================================*/
startTimer(uint32_t timer_val)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  *==========================================================================*/
lock_acq_timed(int32_t timer_val)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  *==========================================================================*/
lock_acq()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  *==========================================================================*/
lock_rel_timed()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  *==========================================================================*/
lock_rel()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  *==========================================================================*/
powerHintInternal(PowerHint hint,bool enable)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  *==========================================================================*/
powerHint(PowerHint hint,bool enable)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