• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 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 #define LOG_TAG "PerfHint-jni"
18 
19 #include "jni.h"
20 
21 #include <dlfcn.h>
22 #include <nativehelper/JNIHelp.h>
23 #include <nativehelper/ScopedPrimitiveArray.h>
24 #include <utils/Log.h>
25 #include <vector>
26 
27 #include "core_jni_helpers.h"
28 
29 namespace android {
30 
31 namespace {
32 
33 struct APerformanceHintManager;
34 struct APerformanceHintSession;
35 
36 typedef APerformanceHintManager* (*APH_getManager)();
37 typedef APerformanceHintSession* (*APH_createSession)(APerformanceHintManager*, const int32_t*,
38                                                       size_t, int64_t);
39 typedef int64_t (*APH_getPreferredUpdateRateNanos)(APerformanceHintManager* manager);
40 typedef void (*APH_updateTargetWorkDuration)(APerformanceHintSession*, int64_t);
41 typedef void (*APH_reportActualWorkDuration)(APerformanceHintSession*, int64_t);
42 typedef void (*APH_closeSession)(APerformanceHintSession* session);
43 
44 bool gAPerformanceHintBindingInitialized = false;
45 APH_getManager gAPH_getManagerFn = nullptr;
46 APH_createSession gAPH_createSessionFn = nullptr;
47 APH_getPreferredUpdateRateNanos gAPH_getPreferredUpdateRateNanosFn = nullptr;
48 APH_updateTargetWorkDuration gAPH_updateTargetWorkDurationFn = nullptr;
49 APH_reportActualWorkDuration gAPH_reportActualWorkDurationFn = nullptr;
50 APH_closeSession gAPH_closeSessionFn = nullptr;
51 
ensureAPerformanceHintBindingInitialized()52 void ensureAPerformanceHintBindingInitialized() {
53     if (gAPerformanceHintBindingInitialized) return;
54 
55     void* handle_ = dlopen("libandroid.so", RTLD_NOW | RTLD_NODELETE);
56     LOG_ALWAYS_FATAL_IF(handle_ == nullptr, "Failed to dlopen libandroid.so!");
57 
58     gAPH_getManagerFn = (APH_getManager)dlsym(handle_, "APerformanceHint_getManager");
59     LOG_ALWAYS_FATAL_IF(gAPH_getManagerFn == nullptr,
60                         "Failed to find required symbol APerformanceHint_getManager!");
61 
62     gAPH_createSessionFn = (APH_createSession)dlsym(handle_, "APerformanceHint_createSession");
63     LOG_ALWAYS_FATAL_IF(gAPH_createSessionFn == nullptr,
64                         "Failed to find required symbol APerformanceHint_createSession!");
65 
66     gAPH_getPreferredUpdateRateNanosFn =
67             (APH_getPreferredUpdateRateNanos)dlsym(handle_,
68                                                    "APerformanceHint_getPreferredUpdateRateNanos");
69     LOG_ALWAYS_FATAL_IF(gAPH_getPreferredUpdateRateNanosFn == nullptr,
70                         "Failed to find required symbol "
71                         "APerformanceHint_getPreferredUpdateRateNanos!");
72 
73     gAPH_updateTargetWorkDurationFn =
74             (APH_updateTargetWorkDuration)dlsym(handle_,
75                                                 "APerformanceHint_updateTargetWorkDuration");
76     LOG_ALWAYS_FATAL_IF(gAPH_updateTargetWorkDurationFn == nullptr,
77                         "Failed to find required symbol "
78                         "APerformanceHint_updateTargetWorkDuration!");
79 
80     gAPH_reportActualWorkDurationFn =
81             (APH_reportActualWorkDuration)dlsym(handle_,
82                                                 "APerformanceHint_reportActualWorkDuration");
83     LOG_ALWAYS_FATAL_IF(gAPH_reportActualWorkDurationFn == nullptr,
84                         "Failed to find required symbol "
85                         "APerformanceHint_reportActualWorkDuration!");
86 
87     gAPH_closeSessionFn = (APH_closeSession)dlsym(handle_, "APerformanceHint_closeSession");
88     LOG_ALWAYS_FATAL_IF(gAPH_closeSessionFn == nullptr,
89                         "Failed to find required symbol APerformanceHint_closeSession!");
90 
91     gAPerformanceHintBindingInitialized = true;
92 }
93 
94 } // namespace
95 
nativeAcquireManager(JNIEnv * env,jclass clazz)96 static jlong nativeAcquireManager(JNIEnv* env, jclass clazz) {
97     ensureAPerformanceHintBindingInitialized();
98     return reinterpret_cast<jlong>(gAPH_getManagerFn());
99 }
100 
nativeGetPreferredUpdateRateNanos(JNIEnv * env,jclass clazz,jlong nativeManagerPtr)101 static jlong nativeGetPreferredUpdateRateNanos(JNIEnv* env, jclass clazz, jlong nativeManagerPtr) {
102     ensureAPerformanceHintBindingInitialized();
103     return gAPH_getPreferredUpdateRateNanosFn(
104             reinterpret_cast<APerformanceHintManager*>(nativeManagerPtr));
105 }
106 
nativeCreateSession(JNIEnv * env,jclass clazz,jlong nativeManagerPtr,jintArray tids,jlong initialTargetWorkDurationNanos)107 static jlong nativeCreateSession(JNIEnv* env, jclass clazz, jlong nativeManagerPtr, jintArray tids,
108                                  jlong initialTargetWorkDurationNanos) {
109     ensureAPerformanceHintBindingInitialized();
110     if (tids == nullptr) return 0;
111     std::vector<int32_t> tidsVector;
112     ScopedIntArrayRO tidsArray(env, tids);
113     for (size_t i = 0; i < tidsArray.size(); ++i) {
114         tidsVector.push_back(static_cast<int32_t>(tidsArray[i]));
115     }
116     return reinterpret_cast<jlong>(
117             gAPH_createSessionFn(reinterpret_cast<APerformanceHintManager*>(nativeManagerPtr),
118                                  tidsVector.data(), tidsVector.size(),
119                                  initialTargetWorkDurationNanos));
120 }
121 
nativeUpdateTargetWorkDuration(JNIEnv * env,jclass clazz,jlong nativeSessionPtr,jlong targetDurationNanos)122 static void nativeUpdateTargetWorkDuration(JNIEnv* env, jclass clazz, jlong nativeSessionPtr,
123                                            jlong targetDurationNanos) {
124     ensureAPerformanceHintBindingInitialized();
125     gAPH_updateTargetWorkDurationFn(reinterpret_cast<APerformanceHintSession*>(nativeSessionPtr),
126                                     targetDurationNanos);
127 }
128 
nativeReportActualWorkDuration(JNIEnv * env,jclass clazz,jlong nativeSessionPtr,jlong actualDurationNanos)129 static void nativeReportActualWorkDuration(JNIEnv* env, jclass clazz, jlong nativeSessionPtr,
130                                            jlong actualDurationNanos) {
131     ensureAPerformanceHintBindingInitialized();
132     gAPH_reportActualWorkDurationFn(reinterpret_cast<APerformanceHintSession*>(nativeSessionPtr),
133                                     actualDurationNanos);
134 }
135 
nativeCloseSession(JNIEnv * env,jclass clazz,jlong nativeSessionPtr)136 static void nativeCloseSession(JNIEnv* env, jclass clazz, jlong nativeSessionPtr) {
137     ensureAPerformanceHintBindingInitialized();
138     gAPH_closeSessionFn(reinterpret_cast<APerformanceHintSession*>(nativeSessionPtr));
139 }
140 
141 static const JNINativeMethod gPerformanceHintMethods[] = {
142         {"nativeAcquireManager", "()J", (void*)nativeAcquireManager},
143         {"nativeGetPreferredUpdateRateNanos", "(J)J", (void*)nativeGetPreferredUpdateRateNanos},
144         {"nativeCreateSession", "(J[IJ)J", (void*)nativeCreateSession},
145         {"nativeUpdateTargetWorkDuration", "(JJ)V", (void*)nativeUpdateTargetWorkDuration},
146         {"nativeReportActualWorkDuration", "(JJ)V", (void*)nativeReportActualWorkDuration},
147         {"nativeCloseSession", "(J)V", (void*)nativeCloseSession},
148 };
149 
register_android_os_PerformanceHintManager(JNIEnv * env)150 int register_android_os_PerformanceHintManager(JNIEnv* env) {
151     return RegisterMethodsOrDie(env, "android/os/PerformanceHintManager", gPerformanceHintMethods,
152                                 NELEM(gPerformanceHintMethods));
153 }
154 
155 } // namespace android
156