From c90438175fcd83c8890c426c28a3ded006faee35 Mon Sep 17 00:00:00 2001 From: Stan Iliev Date: Mon, 3 Feb 2020 16:57:09 -0500 Subject: [PATCH] Refactor GraphicsStatsService for updateability Move GraphicsStatsService to android.graphics package. Move GraphicsStatsService JNI from libservices.core to libandroid_runtime. Declare GraphicsStatsService ctor as the only @SystemApi. Remove MemoryFile usage from GraphicsStatsService, but use SharedMemory and other SDK APIs instead. This is done to avoid using unstable API MemoryFile.getFileDescriptor. Propose new SharedMemory.getFdDup API for next release, which is hidden for now. Refactor statsd puller to avoid proto serialization by moving data directly into AStatsEventList. "libprotoutil" is added as a static dependancy to libhwui, which should be fine because its implementation does not link anything. Bug: 146353313 Test: Ran "adb shell cmd stats pull-source 10068" Test: Passed unit tests and GraphicsStatsValidationTest CTS Change-Id: If16c5addbd519cba33e03bd84ac312595032e0e1 --- Android.bp | 7 - core/java/android/os/SharedMemory.java | 15 + core/jni/Android.bp | 2 + .../android/graphics/GraphicsStatsService.cpp | 195 ++++++++++++ .../graphics}/GraphicsStatsService.java | 118 ++++--- libs/hwui/Android.bp | 3 + libs/hwui/service/GraphicsStatsService.cpp | 147 ++++----- libs/hwui/service/GraphicsStatsService.h | 8 +- services/core/jni/Android.bp | 4 - ...om_android_server_GraphicsStatsService.cpp | 292 ------------------ services/core/jni/onload.cpp | 4 +- .../java/com/android/server/SystemServer.java | 1 + 12 files changed, 367 insertions(+), 429 deletions(-) create mode 100644 core/jni/android/graphics/GraphicsStatsService.cpp rename {services/core/java/com/android/server => graphics/java/android/graphics}/GraphicsStatsService.java (85%) delete mode 100644 services/core/jni/com_android_server_GraphicsStatsService.cpp diff --git a/Android.bp b/Android.bp index 69d654fbddbcd..f63e78bedd43f 100644 --- a/Android.bp +++ b/Android.bp @@ -444,13 +444,6 @@ filegroup { path: "core/java", } -filegroup { - name: "graphicsstats_proto", - srcs: [ - "libs/hwui/protos/graphicsstats.proto", - ], -} - filegroup { name: "libvibrator_aidl", srcs: [ diff --git a/core/java/android/os/SharedMemory.java b/core/java/android/os/SharedMemory.java index 26d9c7d687eb6..75123528a6b8d 100644 --- a/core/java/android/os/SharedMemory.java +++ b/core/java/android/os/SharedMemory.java @@ -27,6 +27,7 @@ import dalvik.system.VMRuntime; import java.io.Closeable; import java.io.FileDescriptor; +import java.io.IOException; import java.nio.ByteBuffer; import java.nio.DirectByteBuffer; import java.nio.NioUtils; @@ -272,6 +273,20 @@ public final class SharedMemory implements Parcelable, Closeable { dest.writeFileDescriptor(mFileDescriptor); } + /** + * Returns a dup'd ParcelFileDescriptor from the SharedMemory FileDescriptor. + * This obeys standard POSIX semantics, where the + * new file descriptor shared state such as file position with the + * original file descriptor. + * TODO: propose this method as a public or system API for next release to achieve parity with + * NDK ASharedMemory_dupFromJava. + * + * @hide + */ + public ParcelFileDescriptor getFdDup() throws IOException { + return ParcelFileDescriptor.dup(mFileDescriptor); + } + public static final @android.annotation.NonNull Parcelable.Creator CREATOR = new Parcelable.Creator() { @Override diff --git a/core/jni/Android.bp b/core/jni/Android.bp index 35eb0fc986d7c..04c1c58cdb4c3 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -182,6 +182,7 @@ cc_library_shared { "android_hardware_UsbRequest.cpp", "android_hardware_location_ActivityRecognitionHardware.cpp", "android_util_FileObserver.cpp", + "android/graphics/GraphicsStatsService.cpp", "android/graphics/SurfaceTexture.cpp", "android/opengl/poly_clip.cpp", // TODO: .arm "android/opengl/util.cpp", @@ -273,6 +274,7 @@ cc_library_shared { "libstats_jni", "libstatslog", "server_configurable_flags", + "libstatspull", ], export_shared_lib_headers: [ // AndroidRuntime.h depends on nativehelper/jni.h diff --git a/core/jni/android/graphics/GraphicsStatsService.cpp b/core/jni/android/graphics/GraphicsStatsService.cpp new file mode 100644 index 0000000000000..ef0aacc4d9eca --- /dev/null +++ b/core/jni/android/graphics/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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(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(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(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(dumpPtr); + GraphicsStatsService::addToDump(dump, path); +} + +static void finishDump(JNIEnv*, jobject, jlong dumpPtr) { + GraphicsStatsService::Dump* dump = reinterpret_cast(dumpPtr); + GraphicsStatsService::finishDump(dump); +} + +static void finishDumpInMemory(JNIEnv* env, jobject, jlong dumpPtr, jlong pulledData, + jboolean lastFullDay) { + GraphicsStatsService::Dump* dump = reinterpret_cast(dumpPtr); + AStatsEventList* data = reinterpret_cast(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(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(&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(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 diff --git a/services/core/java/com/android/server/GraphicsStatsService.java b/graphics/java/android/graphics/GraphicsStatsService.java similarity index 85% rename from services/core/java/com/android/server/GraphicsStatsService.java rename to graphics/java/android/graphics/GraphicsStatsService.java index 5179fa7a6eb55..8dfd6ee92a9a9 100644 --- a/services/core/java/com/android/server/GraphicsStatsService.java +++ b/graphics/java/android/graphics/GraphicsStatsService.java @@ -14,8 +14,9 @@ * limitations under the License. */ -package com.android.server; +package android.graphics; +import android.annotation.SystemApi; import android.app.AlarmManager; import android.app.AppOpsManager; import android.content.Context; @@ -26,13 +27,14 @@ import android.os.Environment; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; -import android.os.MemoryFile; import android.os.Message; import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.RemoteException; +import android.os.SharedMemory; import android.os.Trace; import android.os.UserHandle; +import android.system.ErrnoException; import android.util.Log; import android.view.IGraphicsStats; import android.view.IGraphicsStatsCallback; @@ -45,6 +47,7 @@ import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; +import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; @@ -84,8 +87,8 @@ public class GraphicsStatsService extends IGraphicsStats.Stub { // This isn't static because we need this to happen after registerNativeMethods, however // the class is loaded (and thus static ctor happens) before that occurs. - private final int ASHMEM_SIZE = nGetAshmemSize(); - private final byte[] ZERO_DATA = new byte[ASHMEM_SIZE]; + private final int mAshmemSize = nGetAshmemSize(); + private final byte[] mZeroData = new byte[mAshmemSize]; private final Context mContext; private final AppOpsManager mAppOps; @@ -97,6 +100,7 @@ public class GraphicsStatsService extends IGraphicsStats.Stub { private Handler mWriteOutHandler; private boolean mRotateIsScheduled = false; + @SystemApi public GraphicsStatsService(Context context) { mContext = context; mAppOps = context.getSystemService(AppOpsManager.class); @@ -108,7 +112,8 @@ public class GraphicsStatsService extends IGraphicsStats.Stub { throw new IllegalStateException("Graphics stats directory does not exist: " + mGraphicsStatsDir.getAbsolutePath()); } - HandlerThread bgthread = new HandlerThread("GraphicsStats-disk", Process.THREAD_PRIORITY_BACKGROUND); + HandlerThread bgthread = new HandlerThread("GraphicsStats-disk", + Process.THREAD_PRIORITY_BACKGROUND); bgthread.start(); mWriteOutHandler = new Handler(bgthread.getLooper(), new Handler.Callback() { @@ -159,7 +164,7 @@ public class GraphicsStatsService extends IGraphicsStats.Stub { active.mCallback.onRotateGraphicsStatsBuffer(); } catch (RemoteException e) { Log.w(TAG, String.format("Failed to notify '%s' (pid=%d) to rotate buffers", - active.mInfo.packageName, active.mPid), e); + active.mInfo.mPackageName, active.mPid), e); } } // Give a few seconds for everyone to rotate before doing the cleanup @@ -167,8 +172,8 @@ public class GraphicsStatsService extends IGraphicsStats.Stub { } @Override - public ParcelFileDescriptor requestBufferForProcess(String packageName, IGraphicsStatsCallback token) - throws RemoteException { + public ParcelFileDescriptor requestBufferForProcess(String packageName, + IGraphicsStatsCallback token) throws RemoteException { int uid = Binder.getCallingUid(); int pid = Binder.getCallingPid(); ParcelFileDescriptor pfd = null; @@ -196,7 +201,7 @@ public class GraphicsStatsService extends IGraphicsStats.Stub { // current day. // This method is invoked from native code only. @SuppressWarnings({"UnusedDeclaration"}) - private long pullGraphicsStats(boolean lastFullDay) throws RemoteException { + private void pullGraphicsStats(boolean lastFullDay, long pulledData) throws RemoteException { int uid = Binder.getCallingUid(); // DUMP and PACKAGE_USAGE_STATS permissions are required to invoke this method. @@ -213,13 +218,13 @@ public class GraphicsStatsService extends IGraphicsStats.Stub { long callingIdentity = Binder.clearCallingIdentity(); try { - return pullGraphicsStatsImpl(lastFullDay); + pullGraphicsStatsImpl(lastFullDay, pulledData); } finally { Binder.restoreCallingIdentity(callingIdentity); } } - private long pullGraphicsStatsImpl(boolean lastFullDay) { + private void pullGraphicsStatsImpl(boolean lastFullDay, long pulledData) { long targetDay; if (lastFullDay) { // Get stats from yesterday. Stats stay constant, because the day is over. @@ -235,7 +240,7 @@ public class GraphicsStatsService extends IGraphicsStats.Stub { buffers = new ArrayList<>(mActive.size()); for (int i = 0; i < mActive.size(); i++) { ActiveBuffer buffer = mActive.get(i); - if (buffer.mInfo.startTime == targetDay) { + if (buffer.mInfo.mStartTime == targetDay) { try { buffers.add(new HistoricalBuffer(buffer)); } catch (IOException ex) { @@ -267,18 +272,7 @@ public class GraphicsStatsService extends IGraphicsStats.Stub { } } } finally { - return nFinishDumpInMemory(dump); - } - } - - private ParcelFileDescriptor getPfd(MemoryFile file) { - try { - if (!file.getFileDescriptor().valid()) { - throw new IllegalStateException("Invalid file descriptor"); - } - return ParcelFileDescriptor.dup(file.getFileDescriptor()); - } catch (IOException ex) { - throw new IllegalStateException("Failed to get PFD from memory file", ex); + nFinishDumpInMemory(dump, pulledData, lastFullDay); } } @@ -286,7 +280,7 @@ public class GraphicsStatsService extends IGraphicsStats.Stub { int uid, int pid, String packageName, long versionCode) throws RemoteException { ActiveBuffer buffer = fetchActiveBuffersLocked(token, uid, pid, packageName, versionCode); scheduleRotateLocked(); - return getPfd(buffer.mProcessBuffer); + return buffer.getPfd(); } private Calendar normalizeDate(long timestamp) { @@ -301,13 +295,15 @@ public class GraphicsStatsService extends IGraphicsStats.Stub { private File pathForApp(BufferInfo info) { String subPath = String.format("%d/%s/%d/total", - normalizeDate(info.startTime).getTimeInMillis(), info.packageName, info.versionCode); + normalizeDate(info.mStartTime).getTimeInMillis(), info.mPackageName, + info.mVersionCode); return new File(mGraphicsStatsDir, subPath); } private void saveBuffer(HistoricalBuffer buffer) { if (Trace.isTagEnabled(Trace.TRACE_TAG_SYSTEM_SERVER)) { - Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "saving graphicsstats for " + buffer.mInfo.packageName); + Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, + "saving graphicsstats for " + buffer.mInfo.mPackageName); } synchronized (mFileAccessLock) { File path = pathForApp(buffer.mInfo); @@ -317,8 +313,9 @@ public class GraphicsStatsService extends IGraphicsStats.Stub { Log.w(TAG, "Unable to create path: '" + parent.getAbsolutePath() + "'"); return; } - nSaveBuffer(path.getAbsolutePath(), buffer.mInfo.packageName, buffer.mInfo.versionCode, - buffer.mInfo.startTime, buffer.mInfo.endTime, buffer.mData); + nSaveBuffer(path.getAbsolutePath(), buffer.mInfo.mPackageName, + buffer.mInfo.mVersionCode, buffer.mInfo.mStartTime, buffer.mInfo.mEndTime, + buffer.mData); } Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); } @@ -365,7 +362,7 @@ public class GraphicsStatsService extends IGraphicsStats.Stub { HistoricalBuffer data = new HistoricalBuffer(buffer); Message.obtain(mWriteOutHandler, SAVE_BUFFER, data).sendToTarget(); } catch (IOException e) { - Log.w(TAG, "Failed to copy graphicsstats from " + buffer.mInfo.packageName, e); + Log.w(TAG, "Failed to copy graphicsstats from " + buffer.mInfo.mPackageName, e); } buffer.closeAllBuffers(); } @@ -386,7 +383,7 @@ public class GraphicsStatsService extends IGraphicsStats.Stub { if (buffer.mPid == pid && buffer.mUid == uid) { // If the buffer is too old we remove it and return a new one - if (buffer.mInfo.startTime < today) { + if (buffer.mInfo.mStartTime < today) { buffer.binderDied(); break; } else { @@ -410,8 +407,8 @@ public class GraphicsStatsService extends IGraphicsStats.Stub { HistoricalBuffer buffer = buffers.get(i); File path = pathForApp(buffer.mInfo); skipFiles.add(path); - nAddToDump(dump, path.getAbsolutePath(), buffer.mInfo.packageName, - buffer.mInfo.versionCode, buffer.mInfo.startTime, buffer.mInfo.endTime, + nAddToDump(dump, path.getAbsolutePath(), buffer.mInfo.mPackageName, + buffer.mInfo.mVersionCode, buffer.mInfo.mStartTime, buffer.mInfo.mEndTime, buffer.mData); } return skipFiles; @@ -478,20 +475,20 @@ public class GraphicsStatsService extends IGraphicsStats.Stub { long versionCode, long startTime, long endTime, byte[] data); private static native void nAddToDump(long dump, String path); private static native void nFinishDump(long dump); - private static native long nFinishDumpInMemory(long dump); + private static native void nFinishDumpInMemory(long dump, long pulledData, boolean lastFullDay); private static native void nSaveBuffer(String path, String packageName, long versionCode, long startTime, long endTime, byte[] data); private final class BufferInfo { - final String packageName; - final long versionCode; - long startTime; - long endTime; + final String mPackageName; + final long mVersionCode; + long mStartTime; + long mEndTime; BufferInfo(String packageName, long versionCode, long startTime) { - this.packageName = packageName; - this.versionCode = versionCode; - this.startTime = startTime; + this.mPackageName = packageName; + this.mVersionCode = versionCode; + this.mStartTime = startTime; } } @@ -501,7 +498,8 @@ public class GraphicsStatsService extends IGraphicsStats.Stub { final int mPid; final IGraphicsStatsCallback mCallback; final IBinder mToken; - MemoryFile mProcessBuffer; + SharedMemory mProcessBuffer; + ByteBuffer mMapping; ActiveBuffer(IGraphicsStatsCallback token, int uid, int pid, String packageName, long versionCode) @@ -512,8 +510,14 @@ public class GraphicsStatsService extends IGraphicsStats.Stub { mCallback = token; mToken = mCallback.asBinder(); mToken.linkToDeath(this, 0); - mProcessBuffer = new MemoryFile("GFXStats-" + pid, ASHMEM_SIZE); - mProcessBuffer.writeBytes(ZERO_DATA, 0, 0, ASHMEM_SIZE); + try { + mProcessBuffer = SharedMemory.create("GFXStats-" + pid, mAshmemSize); + mMapping = mProcessBuffer.mapReadWrite(); + } catch (ErrnoException ex) { + ex.rethrowAsIOException(); + } + mMapping.position(0); + mMapping.put(mZeroData, 0, mAshmemSize); } @Override @@ -523,20 +527,40 @@ public class GraphicsStatsService extends IGraphicsStats.Stub { } void closeAllBuffers() { + if (mMapping != null) { + SharedMemory.unmap(mMapping); + mMapping = null; + } if (mProcessBuffer != null) { mProcessBuffer.close(); mProcessBuffer = null; } } + + ParcelFileDescriptor getPfd() { + try { + return mProcessBuffer.getFdDup(); + } catch (IOException ex) { + throw new IllegalStateException("Failed to get PFD from memory file", ex); + } + } + + void readBytes(byte[] buffer, int count) throws IOException { + if (mMapping == null) { + throw new IOException("SharedMemory has been deactivated"); + } + mMapping.position(0); + mMapping.get(buffer, 0, count); + } } private final class HistoricalBuffer { final BufferInfo mInfo; - final byte[] mData = new byte[ASHMEM_SIZE]; + final byte[] mData = new byte[mAshmemSize]; HistoricalBuffer(ActiveBuffer active) throws IOException { mInfo = active.mInfo; - mInfo.endTime = System.currentTimeMillis(); - active.mProcessBuffer.readBytes(mData, 0, 0, ASHMEM_SIZE); + mInfo.mEndTime = System.currentTimeMillis(); + active.readBytes(mData, mAshmemSize); } } } diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index 51270f5bcebdd..301d1afc6c13c 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -92,9 +92,12 @@ cc_defaults { "libandroidfw", "libcrypto", "libsync", + "libstatspull", + "libstatssocket", ], static_libs: [ "libEGL_blobCache", + "libprotoutil", ], }, host: { diff --git a/libs/hwui/service/GraphicsStatsService.cpp b/libs/hwui/service/GraphicsStatsService.cpp index c4186174b637b..644d5fbd5bf9e 100644 --- a/libs/hwui/service/GraphicsStatsService.cpp +++ b/libs/hwui/service/GraphicsStatsService.cpp @@ -26,9 +26,9 @@ #include #include -#include -#include -#include +#include +#include +#include #include "JankTracker.h" #include "protos/graphicsstats.pb.h" @@ -61,7 +61,7 @@ public: } } bool valid() { return mFd != -1; } - operator int() { return mFd; } // NOLINT(google-explicit-constructor) + operator int() { return mFd; } // NOLINT(google-explicit-constructor) private: int mFd; @@ -485,79 +485,82 @@ void GraphicsStatsService::finishDump(Dump* dump) { delete dump; } -class MemOutputStreamLite : public io::ZeroCopyOutputStream { -public: - explicit MemOutputStreamLite() : mCopyAdapter(), mImpl(&mCopyAdapter) {} - virtual ~MemOutputStreamLite() {} +using namespace google::protobuf; - virtual bool Next(void** data, int* size) override { return mImpl.Next(data, size); } +// Field ids taken from FrameTimingHistogram message in atoms.proto +#define TIME_MILLIS_BUCKETS_FIELD_NUMBER 1 +#define FRAME_COUNTS_FIELD_NUMBER 2 - virtual void BackUp(int count) override { mImpl.BackUp(count); } - - virtual int64 ByteCount() const override { return mImpl.ByteCount(); } - - bool Flush() { return mImpl.Flush(); } - - void copyData(const DumpMemoryFn& reader, void* param1, void* param2) { - int bufferOffset = 0; - int totalSize = mCopyAdapter.mBuffersSize - mCopyAdapter.mCurrentBufferUnusedSize; - int totalDataLeft = totalSize; - for (auto& it : mCopyAdapter.mBuffers) { - int bufferSize = std::min(totalDataLeft, (int)it.size()); // last buffer is not full - reader(it.data(), bufferOffset, bufferSize, totalSize, param1, param2); - bufferOffset += bufferSize; - totalDataLeft -= bufferSize; - } +static void writeCpuHistogram(AStatsEvent* event, + const uirenderer::protos::GraphicsStatsProto& stat) { + util::ProtoOutputStream proto; + for (int bucketIndex = 0; bucketIndex < stat.histogram_size(); bucketIndex++) { + auto& bucket = stat.histogram(bucketIndex); + proto.write(android::util::FIELD_TYPE_INT32 | android::util::FIELD_COUNT_REPEATED | + TIME_MILLIS_BUCKETS_FIELD_NUMBER /* field id */, + (int)bucket.render_millis()); } - -private: - struct MemAdapter : public io::CopyingOutputStream { - // Data is stored in an array of buffers. - // JNI SetByteArrayRegion assembles data in one continuous Java byte[] buffer. - std::vector> mBuffers; - int mBuffersSize = 0; // total bytes allocated in mBuffers - int mCurrentBufferUnusedSize = 0; // unused bytes in the last buffer mBuffers.back() - unsigned char* mCurrentBuffer = nullptr; // pointer to next free byte in mBuffers.back() - - explicit MemAdapter() {} - virtual ~MemAdapter() {} - - virtual bool Write(const void* buffer, int size) override { - while (size > 0) { - if (0 == mCurrentBufferUnusedSize) { - mCurrentBufferUnusedSize = - std::max(size, mBuffersSize ? 2 * mBuffersSize : 10000); - mBuffers.emplace_back(); - mBuffers.back().resize(mCurrentBufferUnusedSize); - mCurrentBuffer = mBuffers.back().data(); - mBuffersSize += mCurrentBufferUnusedSize; - } - int dataMoved = std::min(mCurrentBufferUnusedSize, size); - memcpy(mCurrentBuffer, buffer, dataMoved); - mCurrentBufferUnusedSize -= dataMoved; - mCurrentBuffer += dataMoved; - buffer = reinterpret_cast(buffer) + dataMoved; - size -= dataMoved; - } - return true; - } - }; - - MemOutputStreamLite::MemAdapter mCopyAdapter; - io::CopyingOutputStreamAdaptor mImpl; -}; - -void GraphicsStatsService::finishDumpInMemory(Dump* dump, const DumpMemoryFn& reader, void* param1, - void* param2) { - MemOutputStreamLite stream; - dump->updateProto(); - bool success = dump->proto().SerializeToZeroCopyStream(&stream) && stream.Flush(); - delete dump; - if (!success) { - return; + for (int bucketIndex = 0; bucketIndex < stat.histogram_size(); bucketIndex++) { + auto& bucket = stat.histogram(bucketIndex); + proto.write(android::util::FIELD_TYPE_INT64 | android::util::FIELD_COUNT_REPEATED | + FRAME_COUNTS_FIELD_NUMBER /* field id */, + (long long)bucket.frame_count()); } - stream.copyData(reader, param1, param2); + std::vector outVector; + proto.serializeToVector(&outVector); + AStatsEvent_writeByteArray(event, outVector.data(), outVector.size()); } +static void writeGpuHistogram(AStatsEvent* event, + const uirenderer::protos::GraphicsStatsProto& stat) { + util::ProtoOutputStream proto; + for (int bucketIndex = 0; bucketIndex < stat.gpu_histogram_size(); bucketIndex++) { + auto& bucket = stat.gpu_histogram(bucketIndex); + proto.write(android::util::FIELD_TYPE_INT32 | android::util::FIELD_COUNT_REPEATED | + TIME_MILLIS_BUCKETS_FIELD_NUMBER /* field id */, + (int)bucket.render_millis()); + } + for (int bucketIndex = 0; bucketIndex < stat.gpu_histogram_size(); bucketIndex++) { + auto& bucket = stat.gpu_histogram(bucketIndex); + proto.write(android::util::FIELD_TYPE_INT64 | android::util::FIELD_COUNT_REPEATED | + FRAME_COUNTS_FIELD_NUMBER /* field id */, + (long long)bucket.frame_count()); + } + std::vector outVector; + proto.serializeToVector(&outVector); + AStatsEvent_writeByteArray(event, outVector.data(), outVector.size()); +} + + +void GraphicsStatsService::finishDumpInMemory(Dump* dump, AStatsEventList* data, + bool lastFullDay) { + dump->updateProto(); + auto& serviceDump = dump->proto(); + for (int stat_index = 0; stat_index < serviceDump.stats_size(); stat_index++) { + auto& stat = serviceDump.stats(stat_index); + AStatsEvent* event = AStatsEventList_addStatsEvent(data); + AStatsEvent_setAtomId(event, android::util::GRAPHICS_STATS); + AStatsEvent_writeString(event, stat.package_name().c_str()); + AStatsEvent_writeInt64(event, (int64_t)stat.version_code()); + AStatsEvent_writeInt64(event, (int64_t)stat.stats_start()); + AStatsEvent_writeInt64(event, (int64_t)stat.stats_end()); + AStatsEvent_writeInt32(event, (int32_t)stat.pipeline()); + AStatsEvent_writeInt32(event, (int32_t)stat.summary().total_frames()); + AStatsEvent_writeInt32(event, (int32_t)stat.summary().missed_vsync_count()); + AStatsEvent_writeInt32(event, (int32_t)stat.summary().high_input_latency_count()); + AStatsEvent_writeInt32(event, (int32_t)stat.summary().slow_ui_thread_count()); + AStatsEvent_writeInt32(event, (int32_t)stat.summary().slow_bitmap_upload_count()); + AStatsEvent_writeInt32(event, (int32_t)stat.summary().slow_draw_count()); + AStatsEvent_writeInt32(event, (int32_t)stat.summary().missed_deadline_count()); + writeCpuHistogram(event, stat); + writeGpuHistogram(event, stat); + // TODO: fill in UI mainline module version, when the feature is available. + AStatsEvent_writeInt64(event, (int64_t)0); + AStatsEvent_writeBool(event, !lastFullDay); + AStatsEvent_build(event); + } +} + + } /* namespace uirenderer */ } /* namespace android */ diff --git a/libs/hwui/service/GraphicsStatsService.h b/libs/hwui/service/GraphicsStatsService.h index 4bed96330a52e..59e21d039c9dd 100644 --- a/libs/hwui/service/GraphicsStatsService.h +++ b/libs/hwui/service/GraphicsStatsService.h @@ -20,6 +20,7 @@ #include "JankTracker.h" #include "utils/Macros.h" +#include namespace android { namespace uirenderer { @@ -27,9 +28,6 @@ namespace protos { class GraphicsStatsProto; } -typedef void (*DumpMemoryFn)(void* buffer, int bufferOffset, int bufferSize, int totalSize, - void* param1, void* param2); - /* * The exported entry points used by GraphicsStatsService.java in f/b/services/core * @@ -56,8 +54,8 @@ public: int64_t startTime, int64_t endTime, const ProfileData* data); ANDROID_API static void addToDump(Dump* dump, const std::string& path); ANDROID_API static void finishDump(Dump* dump); - ANDROID_API static void finishDumpInMemory(Dump* dump, const DumpMemoryFn& reader, void* param1, - void* param2); + ANDROID_API static void finishDumpInMemory(Dump* dump, AStatsEventList* data, + bool lastFullDay); // Visible for testing static bool parseFromFile(const std::string& path, protos::GraphicsStatsProto* output); diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp index 812bc438246f0..49c7e0a3b2424 100644 --- a/services/core/jni/Android.bp +++ b/services/core/jni/Android.bp @@ -13,7 +13,6 @@ cc_library_static { ], srcs: [ - ":graphicsstats_proto", ":lib_alarmManagerService_native", "BroadcastRadio/JavaRef.cpp", "BroadcastRadio/NativeCallbackThread.cpp", @@ -53,7 +52,6 @@ cc_library_static { "com_android_server_UsbHostManager.cpp", "com_android_server_VibratorService.cpp", "com_android_server_PersistentDataBlockService.cpp", - "com_android_server_GraphicsStatsService.cpp", "com_android_server_am_CachedAppOptimizer.cpp", "com_android_server_am_LowMemDetector.cpp", "com_android_server_incremental_IncrementalManagerService.cpp", @@ -107,8 +105,6 @@ cc_defaults { "libinputflinger", "libinputflinger_base", "libinputservice", - "libprotobuf-cpp-lite", - "libprotoutil", "libstatshidl", "libstatspull", "libstatssocket", diff --git a/services/core/jni/com_android_server_GraphicsStatsService.cpp b/services/core/jni/com_android_server_GraphicsStatsService.cpp deleted file mode 100644 index aa7067ee7509e..0000000000000 --- a/services/core/jni/com_android_server_GraphicsStatsService.cpp +++ /dev/null @@ -1,292 +0,0 @@ -/* - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "android/graphics/Utils.h" -#include "core_jni_helpers.h" -#include "protos/graphicsstats.pb.h" -#include -#include - -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(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(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(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(dumpPtr); - GraphicsStatsService::addToDump(dump, path); -} - -static void finishDump(JNIEnv*, jobject, jlong dumpPtr) { - GraphicsStatsService::Dump* dump = reinterpret_cast(dumpPtr); - GraphicsStatsService::finishDump(dump); -} - -static jlong finishDumpInMemory(JNIEnv* env, jobject, jlong dumpPtr) { - GraphicsStatsService::Dump* dump = reinterpret_cast(dumpPtr); - std::vector* result = new std::vector(); - GraphicsStatsService::finishDumpInMemory(dump, - [](void* buffer, int bufferOffset, int bufferSize, int totalSize, void* param1, void* param2) { - std::vector* outBuffer = reinterpret_cast*>(param2); - if (outBuffer->size() < totalSize) { - outBuffer->resize(totalSize); - } - std::memcpy(outBuffer->data() + bufferOffset, buffer, bufferSize); - }, env, result); - return reinterpret_cast(result); -} - -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(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(&env), JNI_VERSION_1_6) != JNI_OK) { - if (vm->AttachCurrentThreadAsDaemon(&env, nullptr) != JNI_OK) { - LOG_ALWAYS_FATAL("Failed to AttachCurrentThread!"); - } - } - return env; -} - -using namespace google::protobuf; - -// Field ids taken from FrameTimingHistogram message in atoms.proto -#define TIME_MILLIS_BUCKETS_FIELD_NUMBER 1 -#define FRAME_COUNTS_FIELD_NUMBER 2 - -static void writeCpuHistogram(AStatsEvent* event, - const uirenderer::protos::GraphicsStatsProto& stat) { - util::ProtoOutputStream proto; - for (int bucketIndex = 0; bucketIndex < stat.histogram_size(); bucketIndex++) { - auto& bucket = stat.histogram(bucketIndex); - proto.write(android::util::FIELD_TYPE_INT32 | android::util::FIELD_COUNT_REPEATED | - TIME_MILLIS_BUCKETS_FIELD_NUMBER /* field id */, - (int)bucket.render_millis()); - } - for (int bucketIndex = 0; bucketIndex < stat.histogram_size(); bucketIndex++) { - auto& bucket = stat.histogram(bucketIndex); - proto.write(android::util::FIELD_TYPE_INT64 | android::util::FIELD_COUNT_REPEATED | - FRAME_COUNTS_FIELD_NUMBER /* field id */, - (long long)bucket.frame_count()); - } - std::vector outVector; - proto.serializeToVector(&outVector); - AStatsEvent_writeByteArray(event, outVector.data(), outVector.size()); -} - -static void writeGpuHistogram(AStatsEvent* event, - const uirenderer::protos::GraphicsStatsProto& stat) { - util::ProtoOutputStream proto; - for (int bucketIndex = 0; bucketIndex < stat.gpu_histogram_size(); bucketIndex++) { - auto& bucket = stat.gpu_histogram(bucketIndex); - proto.write(android::util::FIELD_TYPE_INT32 | android::util::FIELD_COUNT_REPEATED | - TIME_MILLIS_BUCKETS_FIELD_NUMBER /* field id */, - (int)bucket.render_millis()); - } - for (int bucketIndex = 0; bucketIndex < stat.gpu_histogram_size(); bucketIndex++) { - auto& bucket = stat.gpu_histogram(bucketIndex); - proto.write(android::util::FIELD_TYPE_INT64 | android::util::FIELD_COUNT_REPEATED | - FRAME_COUNTS_FIELD_NUMBER /* field id */, - (long long)bucket.frame_count()); - } - std::vector outVector; - proto.serializeToVector(&outVector); - AStatsEvent_writeByteArray(event, outVector.data(), outVector.size()); -} - -// 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}) { - jlong jdata = (jlong) env->CallLongMethod( - gGraphicsStatsServiceObject, - gGraphicsStatsService_pullGraphicsStatsMethodID, - (jboolean)(lastFullDay ? JNI_TRUE : JNI_FALSE)); - if (env->ExceptionCheck()) { - env->ExceptionDescribe(); - env->ExceptionClear(); - ALOGE("Failed to invoke graphicsstats service"); - return AStatsManager_PULL_SKIP; - } - if (!jdata) { - // null means data is not available for that day. - continue; - } - android::uirenderer::protos::GraphicsStatsServiceDumpProto serviceDump; - std::vector* buffer = reinterpret_cast*>(jdata); - std::unique_ptr> bufferRelease(buffer); - int dataSize = buffer->size(); - if (!dataSize) { - // Data is not available for that day. - continue; - } - io::ArrayInputStream input{buffer->data(), dataSize}; - bool success = serviceDump.ParseFromZeroCopyStream(&input); - if (!success) { - ALOGW("Parse failed on GraphicsStatsPuller error='%s' dataSize='%d'", - serviceDump.InitializationErrorString().c_str(), dataSize); - return AStatsManager_PULL_SKIP; - } - - for (int stat_index = 0; stat_index < serviceDump.stats_size(); stat_index++) { - auto& stat = serviceDump.stats(stat_index); - AStatsEvent* event = AStatsEventList_addStatsEvent(data); - AStatsEvent_setAtomId(event, android::util::GRAPHICS_STATS); - AStatsEvent_writeString(event, stat.package_name().c_str()); - AStatsEvent_writeInt64(event, (int64_t)stat.version_code()); - AStatsEvent_writeInt64(event, (int64_t)stat.stats_start()); - AStatsEvent_writeInt64(event, (int64_t)stat.stats_end()); - AStatsEvent_writeInt32(event, (int32_t)stat.pipeline()); - AStatsEvent_writeInt32(event, (int32_t)stat.summary().total_frames()); - AStatsEvent_writeInt32(event, (int32_t)stat.summary().missed_vsync_count()); - AStatsEvent_writeInt32(event, (int32_t)stat.summary().high_input_latency_count()); - AStatsEvent_writeInt32(event, (int32_t)stat.summary().slow_ui_thread_count()); - AStatsEvent_writeInt32(event, (int32_t)stat.summary().slow_bitmap_upload_count()); - AStatsEvent_writeInt32(event, (int32_t)stat.summary().slow_draw_count()); - AStatsEvent_writeInt32(event, (int32_t)stat.summary().missed_deadline_count()); - writeCpuHistogram(event, stat); - writeGpuHistogram(event, stat); - // TODO: fill in UI mainline module version, when the feature is available. - AStatsEvent_writeInt64(event, (int64_t)0); - AStatsEvent_writeBool(event, !lastFullDay); - AStatsEvent_build(event); - } - } - 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", "(J)J", (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_server_GraphicsStatsService(JNIEnv* env) -{ - jclass graphicsStatsService_class = FindClassOrDie(env, - "com/android/server/GraphicsStatsService"); - gGraphicsStatsService_pullGraphicsStatsMethodID = GetMethodIDOrDie(env, - graphicsStatsService_class, "pullGraphicsStats", "(Z)J"); - return jniRegisterNativeMethods(env, "com/android/server/GraphicsStatsService", - sMethods, NELEM(sMethods)); -} - -} // namespace android diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp index 1202ad33996de..c1864945f9212 100644 --- a/services/core/jni/onload.cpp +++ b/services/core/jni/onload.cpp @@ -49,7 +49,7 @@ int register_android_server_PersistentDataBlockService(JNIEnv* env); int register_android_server_Watchdog(JNIEnv* env); int register_android_server_HardwarePropertiesManagerService(JNIEnv* env); int register_android_server_SyntheticPasswordManager(JNIEnv* env); -int register_android_server_GraphicsStatsService(JNIEnv* env); +int register_android_graphics_GraphicsStatsService(JNIEnv* env); int register_android_hardware_display_DisplayViewport(JNIEnv* env); int register_android_server_net_NetworkStatsFactory(JNIEnv* env); int register_android_server_net_NetworkStatsService(JNIEnv* env); @@ -102,7 +102,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) register_android_server_HardwarePropertiesManagerService(env); register_android_server_storage_AppFuse(env); register_android_server_SyntheticPasswordManager(env); - register_android_server_GraphicsStatsService(env); + register_android_graphics_GraphicsStatsService(env); register_android_hardware_display_DisplayViewport(env); register_android_server_net_NetworkStatsFactory(env); register_android_server_net_NetworkStatsService(env); diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 036335ca90113..eef6c63d29c99 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -41,6 +41,7 @@ import android.content.res.Configuration; import android.content.res.Resources.Theme; import android.database.sqlite.SQLiteCompatibilityWalFlags; import android.database.sqlite.SQLiteGlobal; +import android.graphics.GraphicsStatsService; import android.hardware.display.DisplayManagerInternal; import android.net.ConnectivityModuleConnector; import android.net.ITetheringConnector;