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;