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