summaryrefslogtreecommitdiff
path: root/libs/hwui/jni/GraphicsStatsService.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/hwui/jni/GraphicsStatsService.cpp')
-rw-r--r--libs/hwui/jni/GraphicsStatsService.cpp195
1 files changed, 195 insertions, 0 deletions
diff --git a/libs/hwui/jni/GraphicsStatsService.cpp b/libs/hwui/jni/GraphicsStatsService.cpp
new file mode 100644
index 000000000000..ef0aacc4d9ec
--- /dev/null
+++ b/libs/hwui/jni/GraphicsStatsService.cpp
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GraphicsStatsService"
+
+#include <JankTracker.h>
+#include <jni.h>
+#include <log/log.h>
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedPrimitiveArray.h>
+#include <nativehelper/ScopedUtfChars.h>
+#include <service/GraphicsStatsService.h>
+#include <stats_event.h>
+#include <stats_pull_atom_callback.h>
+#include <statslog.h>
+#include "core_jni_helpers.h"
+
+namespace android {
+
+using namespace android::uirenderer;
+
+static jint getAshmemSize(JNIEnv*, jobject) {
+ return sizeof(ProfileData);
+}
+
+static jlong createDump(JNIEnv*, jobject, jint fd, jboolean isProto) {
+ GraphicsStatsService::Dump* dump =
+ GraphicsStatsService::createDump(fd,
+ isProto ? GraphicsStatsService::DumpType::Protobuf
+ : GraphicsStatsService::DumpType::Text);
+ return reinterpret_cast<jlong>(dump);
+}
+
+static void addToDump(JNIEnv* env, jobject, jlong dumpPtr, jstring jpath, jstring jpackage,
+ jlong versionCode, jlong startTime, jlong endTime, jbyteArray jdata) {
+ std::string path;
+ const ProfileData* data = nullptr;
+ LOG_ALWAYS_FATAL_IF(jdata == nullptr && jpath == nullptr, "Path and data can't both be null");
+ ScopedByteArrayRO buffer{env};
+ if (jdata != nullptr) {
+ buffer.reset(jdata);
+ LOG_ALWAYS_FATAL_IF(buffer.size() != sizeof(ProfileData),
+ "Buffer size %zu doesn't match expected %zu!", buffer.size(),
+ sizeof(ProfileData));
+ data = reinterpret_cast<const ProfileData*>(buffer.get());
+ }
+ if (jpath != nullptr) {
+ ScopedUtfChars pathChars(env, jpath);
+ LOG_ALWAYS_FATAL_IF(pathChars.size() <= 0 || !pathChars.c_str(),
+ "Failed to get path chars");
+ path.assign(pathChars.c_str(), pathChars.size());
+ }
+ ScopedUtfChars packageChars(env, jpackage);
+ LOG_ALWAYS_FATAL_IF(packageChars.size() <= 0 || !packageChars.c_str(),
+ "Failed to get path chars");
+ GraphicsStatsService::Dump* dump = reinterpret_cast<GraphicsStatsService::Dump*>(dumpPtr);
+ LOG_ALWAYS_FATAL_IF(!dump, "null passed for dump pointer");
+
+ const std::string package(packageChars.c_str(), packageChars.size());
+ GraphicsStatsService::addToDump(dump, path, package, versionCode, startTime, endTime, data);
+}
+
+static void addFileToDump(JNIEnv* env, jobject, jlong dumpPtr, jstring jpath) {
+ ScopedUtfChars pathChars(env, jpath);
+ LOG_ALWAYS_FATAL_IF(pathChars.size() <= 0 || !pathChars.c_str(), "Failed to get path chars");
+ const std::string path(pathChars.c_str(), pathChars.size());
+ GraphicsStatsService::Dump* dump = reinterpret_cast<GraphicsStatsService::Dump*>(dumpPtr);
+ GraphicsStatsService::addToDump(dump, path);
+}
+
+static void finishDump(JNIEnv*, jobject, jlong dumpPtr) {
+ GraphicsStatsService::Dump* dump = reinterpret_cast<GraphicsStatsService::Dump*>(dumpPtr);
+ GraphicsStatsService::finishDump(dump);
+}
+
+static void finishDumpInMemory(JNIEnv* env, jobject, jlong dumpPtr, jlong pulledData,
+ jboolean lastFullDay) {
+ GraphicsStatsService::Dump* dump = reinterpret_cast<GraphicsStatsService::Dump*>(dumpPtr);
+ AStatsEventList* data = reinterpret_cast<AStatsEventList*>(pulledData);
+ GraphicsStatsService::finishDumpInMemory(dump, data, lastFullDay == JNI_TRUE);
+}
+
+static void saveBuffer(JNIEnv* env, jobject clazz, jstring jpath, jstring jpackage,
+ jlong versionCode, jlong startTime, jlong endTime, jbyteArray jdata) {
+ ScopedByteArrayRO buffer(env, jdata);
+ LOG_ALWAYS_FATAL_IF(buffer.size() != sizeof(ProfileData),
+ "Buffer size %zu doesn't match expected %zu!", buffer.size(),
+ sizeof(ProfileData));
+ ScopedUtfChars pathChars(env, jpath);
+ LOG_ALWAYS_FATAL_IF(pathChars.size() <= 0 || !pathChars.c_str(), "Failed to get path chars");
+ ScopedUtfChars packageChars(env, jpackage);
+ LOG_ALWAYS_FATAL_IF(packageChars.size() <= 0 || !packageChars.c_str(),
+ "Failed to get path chars");
+
+ const std::string path(pathChars.c_str(), pathChars.size());
+ const std::string package(packageChars.c_str(), packageChars.size());
+ const ProfileData* data = reinterpret_cast<const ProfileData*>(buffer.get());
+ GraphicsStatsService::saveBuffer(path, package, versionCode, startTime, endTime, data);
+}
+
+static jobject gGraphicsStatsServiceObject = nullptr;
+static jmethodID gGraphicsStatsService_pullGraphicsStatsMethodID;
+
+static JNIEnv* getJNIEnv() {
+ JavaVM* vm = AndroidRuntime::getJavaVM();
+ JNIEnv* env = nullptr;
+ if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+ if (vm->AttachCurrentThreadAsDaemon(&env, nullptr) != JNI_OK) {
+ LOG_ALWAYS_FATAL("Failed to AttachCurrentThread!");
+ }
+ }
+ return env;
+}
+
+// graphicsStatsPullCallback is invoked by statsd service to pull GRAPHICS_STATS atom.
+static AStatsManager_PullAtomCallbackReturn graphicsStatsPullCallback(int32_t atom_tag,
+ AStatsEventList* data,
+ void* cookie) {
+ JNIEnv* env = getJNIEnv();
+ if (!env) {
+ return false;
+ }
+ if (gGraphicsStatsServiceObject == nullptr) {
+ ALOGE("Failed to get graphicsstats service");
+ return AStatsManager_PULL_SKIP;
+ }
+
+ for (bool lastFullDay : {true, false}) {
+ env->CallVoidMethod(gGraphicsStatsServiceObject,
+ gGraphicsStatsService_pullGraphicsStatsMethodID,
+ (jboolean)(lastFullDay ? JNI_TRUE : JNI_FALSE),
+ reinterpret_cast<jlong>(data));
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ ALOGE("Failed to invoke graphicsstats service");
+ return AStatsManager_PULL_SKIP;
+ }
+ }
+ return AStatsManager_PULL_SUCCESS;
+}
+
+// Register a puller for GRAPHICS_STATS atom with the statsd service.
+static void nativeInit(JNIEnv* env, jobject javaObject) {
+ gGraphicsStatsServiceObject = env->NewGlobalRef(javaObject);
+ AStatsManager_PullAtomMetadata* metadata = AStatsManager_PullAtomMetadata_obtain();
+ AStatsManager_PullAtomMetadata_setCoolDownNs(metadata, 10 * 1000000); // 10 milliseconds
+ AStatsManager_PullAtomMetadata_setTimeoutNs(metadata, 2 * NS_PER_SEC); // 2 seconds
+
+ AStatsManager_registerPullAtomCallback(android::util::GRAPHICS_STATS,
+ &graphicsStatsPullCallback, metadata, nullptr);
+
+ AStatsManager_PullAtomMetadata_release(metadata);
+}
+
+static void nativeDestructor(JNIEnv* env, jobject javaObject) {
+ AStatsManager_unregisterPullAtomCallback(android::util::GRAPHICS_STATS);
+ env->DeleteGlobalRef(gGraphicsStatsServiceObject);
+ gGraphicsStatsServiceObject = nullptr;
+}
+
+static const JNINativeMethod sMethods[] =
+ {{"nGetAshmemSize", "()I", (void*)getAshmemSize},
+ {"nCreateDump", "(IZ)J", (void*)createDump},
+ {"nAddToDump", "(JLjava/lang/String;Ljava/lang/String;JJJ[B)V", (void*)addToDump},
+ {"nAddToDump", "(JLjava/lang/String;)V", (void*)addFileToDump},
+ {"nFinishDump", "(J)V", (void*)finishDump},
+ {"nFinishDumpInMemory", "(JJZ)V", (void*)finishDumpInMemory},
+ {"nSaveBuffer", "(Ljava/lang/String;Ljava/lang/String;JJJ[B)V", (void*)saveBuffer},
+ {"nativeInit", "()V", (void*)nativeInit},
+ {"nativeDestructor", "()V", (void*)nativeDestructor}};
+
+int register_android_graphics_GraphicsStatsService(JNIEnv* env) {
+ jclass graphicsStatsService_class =
+ FindClassOrDie(env, "android/graphics/GraphicsStatsService");
+ gGraphicsStatsService_pullGraphicsStatsMethodID =
+ GetMethodIDOrDie(env, graphicsStatsService_class, "pullGraphicsStats", "(ZJ)V");
+ return jniRegisterNativeMethods(env, "android/graphics/GraphicsStatsService", sMethods,
+ NELEM(sMethods));
+}
+
+} // namespace android