xref: /aosp_15_r20/external/oboe/src/common/AdpfWrapper.cpp (revision 05767d913155b055644481607e6fa1e35e2fe72c)
1*05767d91SRobert Wu /*
2*05767d91SRobert Wu  * Copyright 2021 The Android Open Source Project
3*05767d91SRobert Wu  *
4*05767d91SRobert Wu  * Licensed under the Apache License, Version 2.0 (the "License");
5*05767d91SRobert Wu  * you may not use this file except in compliance with the License.
6*05767d91SRobert Wu  * You may obtain a copy of the License at
7*05767d91SRobert Wu  *
8*05767d91SRobert Wu  *      http://www.apache.org/licenses/LICENSE-2.0
9*05767d91SRobert Wu  *
10*05767d91SRobert Wu  * Unless required by applicable law or agreed to in writing, software
11*05767d91SRobert Wu  * distributed under the License is distributed on an "AS IS" BASIS,
12*05767d91SRobert Wu  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*05767d91SRobert Wu  * See the License for the specific language governing permissions and
14*05767d91SRobert Wu  * limitations under the License.
15*05767d91SRobert Wu  */
16*05767d91SRobert Wu 
17*05767d91SRobert Wu #include <dlfcn.h>
18*05767d91SRobert Wu #include <stdint.h>
19*05767d91SRobert Wu #include <sys/types.h>
20*05767d91SRobert Wu 
21*05767d91SRobert Wu #include "AdpfWrapper.h"
22*05767d91SRobert Wu #include "AudioClock.h"
23*05767d91SRobert Wu #include "OboeDebug.h"
24*05767d91SRobert Wu 
25*05767d91SRobert Wu typedef APerformanceHintManager* (*APH_getManager)();
26*05767d91SRobert Wu typedef APerformanceHintSession* (*APH_createSession)(APerformanceHintManager*, const int32_t*,
27*05767d91SRobert Wu                                                       size_t, int64_t);
28*05767d91SRobert Wu typedef void (*APH_reportActualWorkDuration)(APerformanceHintSession*, int64_t);
29*05767d91SRobert Wu typedef void (*APH_closeSession)(APerformanceHintSession* session);
30*05767d91SRobert Wu 
31*05767d91SRobert Wu static bool gAPerformanceHintBindingInitialized = false;
32*05767d91SRobert Wu static APH_getManager gAPH_getManagerFn = nullptr;
33*05767d91SRobert Wu static APH_createSession gAPH_createSessionFn = nullptr;
34*05767d91SRobert Wu static APH_reportActualWorkDuration gAPH_reportActualWorkDurationFn = nullptr;
35*05767d91SRobert Wu static APH_closeSession gAPH_closeSessionFn = nullptr;
36*05767d91SRobert Wu 
loadAphFunctions()37*05767d91SRobert Wu static int loadAphFunctions() {
38*05767d91SRobert Wu     if (gAPerformanceHintBindingInitialized) return true;
39*05767d91SRobert Wu 
40*05767d91SRobert Wu     void* handle_ = dlopen("libandroid.so", RTLD_NOW | RTLD_NODELETE);
41*05767d91SRobert Wu     if (handle_ == nullptr) {
42*05767d91SRobert Wu         return -1000;
43*05767d91SRobert Wu     }
44*05767d91SRobert Wu 
45*05767d91SRobert Wu     gAPH_getManagerFn = (APH_getManager)dlsym(handle_, "APerformanceHint_getManager");
46*05767d91SRobert Wu     if (gAPH_getManagerFn == nullptr) {
47*05767d91SRobert Wu         return -1001;
48*05767d91SRobert Wu     }
49*05767d91SRobert Wu 
50*05767d91SRobert Wu     gAPH_createSessionFn = (APH_createSession)dlsym(handle_, "APerformanceHint_createSession");
51*05767d91SRobert Wu     if (gAPH_getManagerFn == nullptr) {
52*05767d91SRobert Wu         return -1002;
53*05767d91SRobert Wu     }
54*05767d91SRobert Wu 
55*05767d91SRobert Wu     gAPH_reportActualWorkDurationFn = (APH_reportActualWorkDuration)dlsym(
56*05767d91SRobert Wu             handle_, "APerformanceHint_reportActualWorkDuration");
57*05767d91SRobert Wu     if (gAPH_getManagerFn == nullptr) {
58*05767d91SRobert Wu         return -1003;
59*05767d91SRobert Wu     }
60*05767d91SRobert Wu 
61*05767d91SRobert Wu     gAPH_closeSessionFn = (APH_closeSession)dlsym(handle_, "APerformanceHint_closeSession");
62*05767d91SRobert Wu     if (gAPH_getManagerFn == nullptr) {
63*05767d91SRobert Wu         return -1004;
64*05767d91SRobert Wu     }
65*05767d91SRobert Wu 
66*05767d91SRobert Wu     gAPerformanceHintBindingInitialized = true;
67*05767d91SRobert Wu     return 0;
68*05767d91SRobert Wu }
69*05767d91SRobert Wu 
70*05767d91SRobert Wu bool AdpfWrapper::sUseAlternativeHack = false; // TODO remove hack
71*05767d91SRobert Wu 
open(pid_t threadId,int64_t targetDurationNanos)72*05767d91SRobert Wu int AdpfWrapper::open(pid_t threadId,
73*05767d91SRobert Wu                       int64_t targetDurationNanos) {
74*05767d91SRobert Wu     std::lock_guard<std::mutex> lock(mLock);
75*05767d91SRobert Wu     int result = loadAphFunctions();
76*05767d91SRobert Wu     if (result < 0) return result;
77*05767d91SRobert Wu 
78*05767d91SRobert Wu     // This is a singleton.
79*05767d91SRobert Wu     APerformanceHintManager* manager = gAPH_getManagerFn();
80*05767d91SRobert Wu 
81*05767d91SRobert Wu     int32_t thread32 = threadId;
82*05767d91SRobert Wu     if (sUseAlternativeHack) {
83*05767d91SRobert Wu         // TODO Remove this hack when we finish experimenting with alternative algorithms.
84*05767d91SRobert Wu         // The A5 is an arbitrary signal to a hacked version of ADPF to try an alternative
85*05767d91SRobert Wu         // algorithm that is not based on PID.
86*05767d91SRobert Wu         targetDurationNanos = (targetDurationNanos & ~0xFF) | 0xA5;
87*05767d91SRobert Wu     }
88*05767d91SRobert Wu     mHintSession = gAPH_createSessionFn(manager, &thread32, 1 /* size */, targetDurationNanos);
89*05767d91SRobert Wu     if (mHintSession == nullptr) {
90*05767d91SRobert Wu         return -1;
91*05767d91SRobert Wu     }
92*05767d91SRobert Wu     return 0;
93*05767d91SRobert Wu }
94*05767d91SRobert Wu 
reportActualDuration(int64_t actualDurationNanos)95*05767d91SRobert Wu void AdpfWrapper::reportActualDuration(int64_t actualDurationNanos) {
96*05767d91SRobert Wu     //LOGD("ADPF Oboe %s(dur=%lld)", __func__, (long long)actualDurationNanos);
97*05767d91SRobert Wu     std::lock_guard<std::mutex> lock(mLock);
98*05767d91SRobert Wu     if (mHintSession != nullptr) {
99*05767d91SRobert Wu         gAPH_reportActualWorkDurationFn(mHintSession, actualDurationNanos);
100*05767d91SRobert Wu     }
101*05767d91SRobert Wu }
102*05767d91SRobert Wu 
close()103*05767d91SRobert Wu void AdpfWrapper::close() {
104*05767d91SRobert Wu     std::lock_guard<std::mutex> lock(mLock);
105*05767d91SRobert Wu     if (mHintSession != nullptr) {
106*05767d91SRobert Wu         gAPH_closeSessionFn(mHintSession);
107*05767d91SRobert Wu         mHintSession = nullptr;
108*05767d91SRobert Wu     }
109*05767d91SRobert Wu }
110*05767d91SRobert Wu 
onBeginCallback()111*05767d91SRobert Wu void AdpfWrapper::onBeginCallback() {
112*05767d91SRobert Wu     if (isOpen()) {
113*05767d91SRobert Wu         mBeginCallbackNanos = oboe::AudioClock::getNanoseconds(CLOCK_REALTIME);
114*05767d91SRobert Wu     }
115*05767d91SRobert Wu }
116*05767d91SRobert Wu 
onEndCallback(double durationScaler)117*05767d91SRobert Wu void AdpfWrapper::onEndCallback(double durationScaler) {
118*05767d91SRobert Wu     if (isOpen()) {
119*05767d91SRobert Wu         int64_t endCallbackNanos = oboe::AudioClock::getNanoseconds(CLOCK_REALTIME);
120*05767d91SRobert Wu         int64_t actualDurationNanos = endCallbackNanos - mBeginCallbackNanos;
121*05767d91SRobert Wu         int64_t scaledDurationNanos = static_cast<int64_t>(actualDurationNanos * durationScaler);
122*05767d91SRobert Wu         reportActualDuration(scaledDurationNanos);
123*05767d91SRobert Wu     }
124*05767d91SRobert Wu }
125