xref: /aosp_15_r20/frameworks/base/libs/hwui/jni/GraphicsStatsService.cpp (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1*d57664e9SAndroid Build Coastguard Worker /*
2*d57664e9SAndroid Build Coastguard Worker  * Copyright (C) 2017 The Android Open Source Project
3*d57664e9SAndroid Build Coastguard Worker  *
4*d57664e9SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*d57664e9SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*d57664e9SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*d57664e9SAndroid Build Coastguard Worker  *
8*d57664e9SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*d57664e9SAndroid Build Coastguard Worker  *
10*d57664e9SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*d57664e9SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*d57664e9SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*d57664e9SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*d57664e9SAndroid Build Coastguard Worker  * limitations under the License.
15*d57664e9SAndroid Build Coastguard Worker  */
16*d57664e9SAndroid Build Coastguard Worker 
17*d57664e9SAndroid Build Coastguard Worker #include <JankTracker.h>
18*d57664e9SAndroid Build Coastguard Worker #include <log/log.h>
19*d57664e9SAndroid Build Coastguard Worker #include <nativehelper/ScopedPrimitiveArray.h>
20*d57664e9SAndroid Build Coastguard Worker #include <nativehelper/ScopedUtfChars.h>
21*d57664e9SAndroid Build Coastguard Worker #include <service/GraphicsStatsService.h>
22*d57664e9SAndroid Build Coastguard Worker #include <stats_event.h>
23*d57664e9SAndroid Build Coastguard Worker #include <stats_pull_atom_callback.h>
24*d57664e9SAndroid Build Coastguard Worker #include <statslog_hwui.h>
25*d57664e9SAndroid Build Coastguard Worker 
26*d57664e9SAndroid Build Coastguard Worker #include "GraphicsJNI.h"
27*d57664e9SAndroid Build Coastguard Worker #include "android/graphics/jni_runtime.h"
28*d57664e9SAndroid Build Coastguard Worker 
29*d57664e9SAndroid Build Coastguard Worker namespace android {
30*d57664e9SAndroid Build Coastguard Worker 
31*d57664e9SAndroid Build Coastguard Worker using namespace android::uirenderer;
32*d57664e9SAndroid Build Coastguard Worker 
getAshmemSize(JNIEnv *,jobject)33*d57664e9SAndroid Build Coastguard Worker static jint getAshmemSize(JNIEnv*, jobject) {
34*d57664e9SAndroid Build Coastguard Worker     return sizeof(ProfileData);
35*d57664e9SAndroid Build Coastguard Worker }
36*d57664e9SAndroid Build Coastguard Worker 
createDump(JNIEnv *,jobject,jint fd,jboolean isProto)37*d57664e9SAndroid Build Coastguard Worker static jlong createDump(JNIEnv*, jobject, jint fd, jboolean isProto) {
38*d57664e9SAndroid Build Coastguard Worker     GraphicsStatsService::Dump* dump =
39*d57664e9SAndroid Build Coastguard Worker             GraphicsStatsService::createDump(fd,
40*d57664e9SAndroid Build Coastguard Worker                                              isProto ? GraphicsStatsService::DumpType::Protobuf
41*d57664e9SAndroid Build Coastguard Worker                                                      : GraphicsStatsService::DumpType::Text);
42*d57664e9SAndroid Build Coastguard Worker     return reinterpret_cast<jlong>(dump);
43*d57664e9SAndroid Build Coastguard Worker }
44*d57664e9SAndroid Build Coastguard Worker 
addToDump(JNIEnv * env,jobject,jlong dumpPtr,jstring jpath,jint uid,jstring jpackage,jlong versionCode,jlong startTime,jlong endTime,jbyteArray jdata)45*d57664e9SAndroid Build Coastguard Worker static void addToDump(JNIEnv* env, jobject, jlong dumpPtr, jstring jpath, jint uid,
46*d57664e9SAndroid Build Coastguard Worker                       jstring jpackage, jlong versionCode, jlong startTime, jlong endTime,
47*d57664e9SAndroid Build Coastguard Worker                       jbyteArray jdata) {
48*d57664e9SAndroid Build Coastguard Worker     std::string path;
49*d57664e9SAndroid Build Coastguard Worker     const ProfileData* data = nullptr;
50*d57664e9SAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL_IF(jdata == nullptr && jpath == nullptr, "Path and data can't both be null");
51*d57664e9SAndroid Build Coastguard Worker     ScopedByteArrayRO buffer{env};
52*d57664e9SAndroid Build Coastguard Worker     if (jdata != nullptr) {
53*d57664e9SAndroid Build Coastguard Worker         buffer.reset(jdata);
54*d57664e9SAndroid Build Coastguard Worker         LOG_ALWAYS_FATAL_IF(buffer.size() != sizeof(ProfileData),
55*d57664e9SAndroid Build Coastguard Worker                             "Buffer size %zu doesn't match expected %zu!", buffer.size(),
56*d57664e9SAndroid Build Coastguard Worker                             sizeof(ProfileData));
57*d57664e9SAndroid Build Coastguard Worker         data = reinterpret_cast<const ProfileData*>(buffer.get());
58*d57664e9SAndroid Build Coastguard Worker     }
59*d57664e9SAndroid Build Coastguard Worker     if (jpath != nullptr) {
60*d57664e9SAndroid Build Coastguard Worker         ScopedUtfChars pathChars(env, jpath);
61*d57664e9SAndroid Build Coastguard Worker         LOG_ALWAYS_FATAL_IF(pathChars.size() <= 0 || !pathChars.c_str(),
62*d57664e9SAndroid Build Coastguard Worker                             "Failed to get path chars");
63*d57664e9SAndroid Build Coastguard Worker         path.assign(pathChars.c_str(), pathChars.size());
64*d57664e9SAndroid Build Coastguard Worker     }
65*d57664e9SAndroid Build Coastguard Worker     ScopedUtfChars packageChars(env, jpackage);
66*d57664e9SAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL_IF(packageChars.size() <= 0 || !packageChars.c_str(),
67*d57664e9SAndroid Build Coastguard Worker                         "Failed to get path chars");
68*d57664e9SAndroid Build Coastguard Worker     GraphicsStatsService::Dump* dump = reinterpret_cast<GraphicsStatsService::Dump*>(dumpPtr);
69*d57664e9SAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL_IF(!dump, "null passed for dump pointer");
70*d57664e9SAndroid Build Coastguard Worker 
71*d57664e9SAndroid Build Coastguard Worker     const std::string package(packageChars.c_str(), packageChars.size());
72*d57664e9SAndroid Build Coastguard Worker     GraphicsStatsService::addToDump(dump, path, static_cast<uid_t>(uid), package, versionCode,
73*d57664e9SAndroid Build Coastguard Worker                                     startTime, endTime, data);
74*d57664e9SAndroid Build Coastguard Worker }
75*d57664e9SAndroid Build Coastguard Worker 
addFileToDump(JNIEnv * env,jobject,jlong dumpPtr,jstring jpath)76*d57664e9SAndroid Build Coastguard Worker static void addFileToDump(JNIEnv* env, jobject, jlong dumpPtr, jstring jpath) {
77*d57664e9SAndroid Build Coastguard Worker     ScopedUtfChars pathChars(env, jpath);
78*d57664e9SAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL_IF(pathChars.size() <= 0 || !pathChars.c_str(), "Failed to get path chars");
79*d57664e9SAndroid Build Coastguard Worker     const std::string path(pathChars.c_str(), pathChars.size());
80*d57664e9SAndroid Build Coastguard Worker     GraphicsStatsService::Dump* dump = reinterpret_cast<GraphicsStatsService::Dump*>(dumpPtr);
81*d57664e9SAndroid Build Coastguard Worker     GraphicsStatsService::addToDump(dump, path);
82*d57664e9SAndroid Build Coastguard Worker }
83*d57664e9SAndroid Build Coastguard Worker 
finishDump(JNIEnv *,jobject,jlong dumpPtr)84*d57664e9SAndroid Build Coastguard Worker static void finishDump(JNIEnv*, jobject, jlong dumpPtr) {
85*d57664e9SAndroid Build Coastguard Worker     GraphicsStatsService::Dump* dump = reinterpret_cast<GraphicsStatsService::Dump*>(dumpPtr);
86*d57664e9SAndroid Build Coastguard Worker     GraphicsStatsService::finishDump(dump);
87*d57664e9SAndroid Build Coastguard Worker }
88*d57664e9SAndroid Build Coastguard Worker 
finishDumpInMemory(JNIEnv * env,jobject,jlong dumpPtr,jlong pulledData,jboolean lastFullDay)89*d57664e9SAndroid Build Coastguard Worker static void finishDumpInMemory(JNIEnv* env, jobject, jlong dumpPtr, jlong pulledData,
90*d57664e9SAndroid Build Coastguard Worker                                jboolean lastFullDay) {
91*d57664e9SAndroid Build Coastguard Worker     GraphicsStatsService::Dump* dump = reinterpret_cast<GraphicsStatsService::Dump*>(dumpPtr);
92*d57664e9SAndroid Build Coastguard Worker     AStatsEventList* data = reinterpret_cast<AStatsEventList*>(pulledData);
93*d57664e9SAndroid Build Coastguard Worker     GraphicsStatsService::finishDumpInMemory(dump, data, lastFullDay == JNI_TRUE);
94*d57664e9SAndroid Build Coastguard Worker }
95*d57664e9SAndroid Build Coastguard Worker 
saveBuffer(JNIEnv * env,jobject clazz,jstring jpath,jint uid,jstring jpackage,jlong versionCode,jlong startTime,jlong endTime,jbyteArray jdata)96*d57664e9SAndroid Build Coastguard Worker static void saveBuffer(JNIEnv* env, jobject clazz, jstring jpath, jint uid, jstring jpackage,
97*d57664e9SAndroid Build Coastguard Worker                        jlong versionCode, jlong startTime, jlong endTime, jbyteArray jdata) {
98*d57664e9SAndroid Build Coastguard Worker     ScopedByteArrayRO buffer(env, jdata);
99*d57664e9SAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL_IF(buffer.size() != sizeof(ProfileData),
100*d57664e9SAndroid Build Coastguard Worker                         "Buffer size %zu doesn't match expected %zu!", buffer.size(),
101*d57664e9SAndroid Build Coastguard Worker                         sizeof(ProfileData));
102*d57664e9SAndroid Build Coastguard Worker     ScopedUtfChars pathChars(env, jpath);
103*d57664e9SAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL_IF(pathChars.size() <= 0 || !pathChars.c_str(), "Failed to get path chars");
104*d57664e9SAndroid Build Coastguard Worker     ScopedUtfChars packageChars(env, jpackage);
105*d57664e9SAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL_IF(packageChars.size() <= 0 || !packageChars.c_str(),
106*d57664e9SAndroid Build Coastguard Worker                         "Failed to get path chars");
107*d57664e9SAndroid Build Coastguard Worker 
108*d57664e9SAndroid Build Coastguard Worker     const std::string path(pathChars.c_str(), pathChars.size());
109*d57664e9SAndroid Build Coastguard Worker     const std::string package(packageChars.c_str(), packageChars.size());
110*d57664e9SAndroid Build Coastguard Worker     const ProfileData* data = reinterpret_cast<const ProfileData*>(buffer.get());
111*d57664e9SAndroid Build Coastguard Worker     GraphicsStatsService::saveBuffer(path, static_cast<uid_t>(uid), package, versionCode, startTime,
112*d57664e9SAndroid Build Coastguard Worker                                      endTime, data);
113*d57664e9SAndroid Build Coastguard Worker }
114*d57664e9SAndroid Build Coastguard Worker 
115*d57664e9SAndroid Build Coastguard Worker static jobject gGraphicsStatsServiceObject = nullptr;
116*d57664e9SAndroid Build Coastguard Worker static jmethodID gGraphicsStatsService_pullGraphicsStatsMethodID;
117*d57664e9SAndroid Build Coastguard Worker 
getJNIEnv()118*d57664e9SAndroid Build Coastguard Worker static JNIEnv* getJNIEnv() {
119*d57664e9SAndroid Build Coastguard Worker     JavaVM* vm = GraphicsJNI::getJavaVM();
120*d57664e9SAndroid Build Coastguard Worker     JNIEnv* env = nullptr;
121*d57664e9SAndroid Build Coastguard Worker     if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
122*d57664e9SAndroid Build Coastguard Worker         if (vm->AttachCurrentThreadAsDaemon(&env, nullptr) != JNI_OK) {
123*d57664e9SAndroid Build Coastguard Worker             LOG_ALWAYS_FATAL("Failed to AttachCurrentThread!");
124*d57664e9SAndroid Build Coastguard Worker         }
125*d57664e9SAndroid Build Coastguard Worker     }
126*d57664e9SAndroid Build Coastguard Worker     return env;
127*d57664e9SAndroid Build Coastguard Worker }
128*d57664e9SAndroid Build Coastguard Worker 
129*d57664e9SAndroid Build Coastguard Worker // graphicsStatsPullCallback is invoked by statsd service to pull GRAPHICS_STATS atom.
graphicsStatsPullCallback(int32_t atom_tag,AStatsEventList * data,void * cookie)130*d57664e9SAndroid Build Coastguard Worker static AStatsManager_PullAtomCallbackReturn graphicsStatsPullCallback(int32_t atom_tag,
131*d57664e9SAndroid Build Coastguard Worker                                                                       AStatsEventList* data,
132*d57664e9SAndroid Build Coastguard Worker                                                                       void* cookie) {
133*d57664e9SAndroid Build Coastguard Worker     JNIEnv* env = getJNIEnv();
134*d57664e9SAndroid Build Coastguard Worker     if (!env) {
135*d57664e9SAndroid Build Coastguard Worker         return false;
136*d57664e9SAndroid Build Coastguard Worker     }
137*d57664e9SAndroid Build Coastguard Worker     if (gGraphicsStatsServiceObject == nullptr) {
138*d57664e9SAndroid Build Coastguard Worker         ALOGE("Failed to get graphicsstats service");
139*d57664e9SAndroid Build Coastguard Worker         return AStatsManager_PULL_SKIP;
140*d57664e9SAndroid Build Coastguard Worker     }
141*d57664e9SAndroid Build Coastguard Worker 
142*d57664e9SAndroid Build Coastguard Worker     for (bool lastFullDay : {true, false}) {
143*d57664e9SAndroid Build Coastguard Worker         env->CallVoidMethod(gGraphicsStatsServiceObject,
144*d57664e9SAndroid Build Coastguard Worker                             gGraphicsStatsService_pullGraphicsStatsMethodID,
145*d57664e9SAndroid Build Coastguard Worker                             (jboolean)(lastFullDay ? JNI_TRUE : JNI_FALSE),
146*d57664e9SAndroid Build Coastguard Worker                             reinterpret_cast<jlong>(data));
147*d57664e9SAndroid Build Coastguard Worker         if (env->ExceptionCheck()) {
148*d57664e9SAndroid Build Coastguard Worker             env->ExceptionDescribe();
149*d57664e9SAndroid Build Coastguard Worker             env->ExceptionClear();
150*d57664e9SAndroid Build Coastguard Worker             ALOGE("Failed to invoke graphicsstats service");
151*d57664e9SAndroid Build Coastguard Worker             return AStatsManager_PULL_SKIP;
152*d57664e9SAndroid Build Coastguard Worker         }
153*d57664e9SAndroid Build Coastguard Worker     }
154*d57664e9SAndroid Build Coastguard Worker     return AStatsManager_PULL_SUCCESS;
155*d57664e9SAndroid Build Coastguard Worker }
156*d57664e9SAndroid Build Coastguard Worker 
157*d57664e9SAndroid Build Coastguard Worker // Register a puller for GRAPHICS_STATS atom with the statsd service.
nativeInit(JNIEnv * env,jobject javaObject)158*d57664e9SAndroid Build Coastguard Worker static void nativeInit(JNIEnv* env, jobject javaObject) {
159*d57664e9SAndroid Build Coastguard Worker     gGraphicsStatsServiceObject = env->NewGlobalRef(javaObject);
160*d57664e9SAndroid Build Coastguard Worker     AStatsManager_PullAtomMetadata* metadata = AStatsManager_PullAtomMetadata_obtain();
161*d57664e9SAndroid Build Coastguard Worker     AStatsManager_PullAtomMetadata_setCoolDownMillis(metadata, 10);             // 10 milliseconds
162*d57664e9SAndroid Build Coastguard Worker     AStatsManager_PullAtomMetadata_setTimeoutMillis(metadata, 2 * MS_PER_SEC);  // 2 seconds
163*d57664e9SAndroid Build Coastguard Worker 
164*d57664e9SAndroid Build Coastguard Worker     AStatsManager_setPullAtomCallback(stats::GRAPHICS_STATS, metadata, &graphicsStatsPullCallback,
165*d57664e9SAndroid Build Coastguard Worker                                       nullptr);
166*d57664e9SAndroid Build Coastguard Worker 
167*d57664e9SAndroid Build Coastguard Worker     AStatsManager_PullAtomMetadata_release(metadata);
168*d57664e9SAndroid Build Coastguard Worker }
169*d57664e9SAndroid Build Coastguard Worker 
nativeDestructor(JNIEnv * env,jobject javaObject)170*d57664e9SAndroid Build Coastguard Worker static void nativeDestructor(JNIEnv* env, jobject javaObject) {
171*d57664e9SAndroid Build Coastguard Worker     AStatsManager_clearPullAtomCallback(stats::GRAPHICS_STATS);
172*d57664e9SAndroid Build Coastguard Worker     env->DeleteGlobalRef(gGraphicsStatsServiceObject);
173*d57664e9SAndroid Build Coastguard Worker     gGraphicsStatsServiceObject = nullptr;
174*d57664e9SAndroid Build Coastguard Worker }
175*d57664e9SAndroid Build Coastguard Worker 
176*d57664e9SAndroid Build Coastguard Worker } // namespace android
177*d57664e9SAndroid Build Coastguard Worker using namespace android;
178*d57664e9SAndroid Build Coastguard Worker 
179*d57664e9SAndroid Build Coastguard Worker static const JNINativeMethod sMethods[] = {
180*d57664e9SAndroid Build Coastguard Worker         {"nGetAshmemSize", "()I", (void*)getAshmemSize},
181*d57664e9SAndroid Build Coastguard Worker         {"nCreateDump", "(IZ)J", (void*)createDump},
182*d57664e9SAndroid Build Coastguard Worker         {"nAddToDump", "(JLjava/lang/String;ILjava/lang/String;JJJ[B)V", (void*)addToDump},
183*d57664e9SAndroid Build Coastguard Worker         {"nAddToDump", "(JLjava/lang/String;)V", (void*)addFileToDump},
184*d57664e9SAndroid Build Coastguard Worker         {"nFinishDump", "(J)V", (void*)finishDump},
185*d57664e9SAndroid Build Coastguard Worker         {"nFinishDumpInMemory", "(JJZ)V", (void*)finishDumpInMemory},
186*d57664e9SAndroid Build Coastguard Worker         {"nSaveBuffer", "(Ljava/lang/String;ILjava/lang/String;JJJ[B)V", (void*)saveBuffer},
187*d57664e9SAndroid Build Coastguard Worker         {"nativeInit", "()V", (void*)nativeInit},
188*d57664e9SAndroid Build Coastguard Worker         {"nativeDestructor", "()V", (void*)nativeDestructor}};
189*d57664e9SAndroid Build Coastguard Worker 
register_android_graphics_GraphicsStatsService(JNIEnv * env)190*d57664e9SAndroid Build Coastguard Worker int register_android_graphics_GraphicsStatsService(JNIEnv* env) {
191*d57664e9SAndroid Build Coastguard Worker     jclass graphicsStatsService_class =
192*d57664e9SAndroid Build Coastguard Worker             FindClassOrDie(env, "android/graphics/GraphicsStatsService");
193*d57664e9SAndroid Build Coastguard Worker     gGraphicsStatsService_pullGraphicsStatsMethodID =
194*d57664e9SAndroid Build Coastguard Worker             GetMethodIDOrDie(env, graphicsStatsService_class, "pullGraphicsStats", "(ZJ)V");
195*d57664e9SAndroid Build Coastguard Worker     return jniRegisterNativeMethods(env, "android/graphics/GraphicsStatsService", sMethods,
196*d57664e9SAndroid Build Coastguard Worker                                     NELEM(sMethods));
197*d57664e9SAndroid Build Coastguard Worker }
198