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