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