diff options
-rw-r--r-- | core/java/com/android/internal/os/DmabufInfoReader.java | 51 | ||||
-rw-r--r-- | core/jni/Android.bp | 1 | ||||
-rw-r--r-- | core/jni/AndroidRuntime.cpp | 2 | ||||
-rw-r--r-- | core/jni/com_android_internal_os_DmabufInfoReader.cpp | 60 | ||||
-rw-r--r-- | services/core/java/com/android/server/stats/pull/StatsPullAtomService.java | 43 |
5 files changed, 157 insertions, 0 deletions
diff --git a/core/java/com/android/internal/os/DmabufInfoReader.java b/core/java/com/android/internal/os/DmabufInfoReader.java new file mode 100644 index 000000000000..786a6eedf343 --- /dev/null +++ b/core/java/com/android/internal/os/DmabufInfoReader.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2021 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. + */ + +package com.android.internal.os; + +import android.annotation.Nullable; + +/** Wrapper around libdmabufinfo. */ +public final class DmabufInfoReader { + private DmabufInfoReader() {} + + /** Process dma-buf stats. */ + public static final class ProcessDmabuf { + /** Size of buffers retained by the process. */ + public final int retainedSizeKb; + /** Number of buffers retained by the process. */ + public final int retainedBuffersCount; + /** Size of buffers mapped to the address space. */ + public final int mappedSizeKb; + /** Count of buffers mapped to the address space. */ + public final int mappedBuffersCount; + + ProcessDmabuf(int retainedSizeKb, int retainedBuffersCount, + int mappedSizeKb, int mappedBuffersCount) { + this.retainedSizeKb = retainedSizeKb; + this.retainedBuffersCount = retainedBuffersCount; + this.mappedSizeKb = mappedSizeKb; + this.mappedBuffersCount = mappedBuffersCount; + } + } + + /** + * Return stats for DMA-BUFs retained by process pid or null if the DMA-BUF + * stats could not be read. + */ + @Nullable + public static native ProcessDmabuf getProcessStats(int pid); +} diff --git a/core/jni/Android.bp b/core/jni/Android.bp index 20d257e98278..de85ff93ccb2 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -202,6 +202,7 @@ cc_library_shared { "com_android_internal_content_om_OverlayConfig.cpp", "com_android_internal_net_NetworkUtilsInternal.cpp", "com_android_internal_os_ClassLoaderFactory.cpp", + "com_android_internal_os_DmabufInfoReader.cpp", "com_android_internal_os_FuseAppLoop.cpp", "com_android_internal_os_KernelCpuBpfTracking.cpp", "com_android_internal_os_KernelCpuTotalBpfMapReader.cpp", diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 0c3f265b84cc..6636b1f6327b 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -191,6 +191,7 @@ extern int register_com_android_internal_content_NativeLibraryHelper(JNIEnv *env extern int register_com_android_internal_content_om_OverlayConfig(JNIEnv *env); extern int register_com_android_internal_net_NetworkUtilsInternal(JNIEnv* env); extern int register_com_android_internal_os_ClassLoaderFactory(JNIEnv* env); +extern int register_com_android_internal_os_DmabufInfoReader(JNIEnv* env); extern int register_com_android_internal_os_FuseAppLoop(JNIEnv* env); extern int register_com_android_internal_os_KernelCpuBpfTracking(JNIEnv* env); extern int register_com_android_internal_os_KernelCpuTotalBpfMapReader(JNIEnv* env); @@ -1616,6 +1617,7 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_animation_PropertyValuesHolder), REG_JNI(register_android_security_Scrypt), REG_JNI(register_com_android_internal_content_NativeLibraryHelper), + REG_JNI(register_com_android_internal_os_DmabufInfoReader), REG_JNI(register_com_android_internal_os_FuseAppLoop), REG_JNI(register_com_android_internal_os_KernelCpuBpfTracking), REG_JNI(register_com_android_internal_os_KernelCpuTotalBpfMapReader), diff --git a/core/jni/com_android_internal_os_DmabufInfoReader.cpp b/core/jni/com_android_internal_os_DmabufInfoReader.cpp new file mode 100644 index 000000000000..4b0a6ac5b6c4 --- /dev/null +++ b/core/jni/com_android_internal_os_DmabufInfoReader.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2021 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. + */ + +#include <dmabufinfo/dmabufinfo.h> +#include "core_jni_helpers.h" + +namespace android { + +static jobject DmabufInfoReader_getProcessStats(JNIEnv *env, jobject, jint pid) { + std::vector<dmabufinfo::DmaBuffer> buffers; + if (!dmabufinfo::ReadDmaBufMapRefs(pid, &buffers)) { + return nullptr; + } + jint mappedSize = 0; + jint mappedCount = buffers.size(); + for (const auto &buffer : buffers) { + mappedSize += buffer.size(); + } + mappedSize /= 1024; + + jint retainedSize = -1; + jint retainedCount = -1; + if (dmabufinfo::ReadDmaBufFdRefs(pid, &buffers)) { + retainedCount = buffers.size(); + retainedSize = 0; + for (const auto &buffer : buffers) { + retainedSize += buffer.size(); + } + retainedSize /= 1024; + } + + jclass clazz = FindClassOrDie(env, "com/android/internal/os/DmabufInfoReader$ProcessDmabuf"); + jmethodID constructID = GetMethodIDOrDie(env, clazz, "<init>", "(IIII)V"); + return env->NewObject(clazz, constructID, retainedSize, retainedCount, mappedSize, mappedCount); +} + +static const JNINativeMethod methods[] = { + {"getProcessStats", "(I)Lcom/android/internal/os/DmabufInfoReader$ProcessDmabuf;", + (void *)DmabufInfoReader_getProcessStats}, +}; + +int register_com_android_internal_os_DmabufInfoReader(JNIEnv *env) { + return RegisterMethodsOrDie(env, "com/android/internal/os/DmabufInfoReader", methods, + NELEM(methods)); +} + +} // namespace android diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java index a7b9e95d44d1..91231c3032b4 100644 --- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java +++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java @@ -111,6 +111,7 @@ import android.os.IThermalService; import android.os.OutcomeReceiver; import android.os.ParcelFileDescriptor; import android.os.Parcelable; +import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.os.StatFs; @@ -148,6 +149,7 @@ import com.android.internal.os.BackgroundThread; import com.android.internal.os.BatterySipper; import com.android.internal.os.BatteryStatsHelper; import com.android.internal.os.BinderCallsStats.ExportedCallStat; +import com.android.internal.os.DmabufInfoReader; import com.android.internal.os.KernelCpuBpfTracking; import com.android.internal.os.KernelCpuThreadReader; import com.android.internal.os.KernelCpuThreadReaderDiff; @@ -198,6 +200,7 @@ import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.Arrays; +import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -528,6 +531,8 @@ public class StatsPullAtomService extends SystemService { synchronized (mProcessSystemIonHeapSizeLock) { return pullProcessSystemIonHeapSizeLocked(atomTag, data); } + case FrameworkStatsLog.PROCESS_DMABUF_MEMORY: + return pullProcessDmabufMemory(atomTag, data); case FrameworkStatsLog.SYSTEM_MEMORY: return pullSystemMemory(atomTag, data); case FrameworkStatsLog.TEMPERATURE: @@ -818,6 +823,7 @@ public class StatsPullAtomService extends SystemService { registerIonHeapSize(); registerProcessSystemIonHeapSize(); registerSystemMemory(); + registerProcessDmabufMemory(); registerTemperature(); registerCoolingDevice(); registerBinderCallsStats(); @@ -2183,6 +2189,43 @@ public class StatsPullAtomService extends SystemService { return StatsManager.PULL_SUCCESS; } + private void registerProcessDmabufMemory() { + int tagId = FrameworkStatsLog.PROCESS_DMABUF_MEMORY; + mStatsManager.setPullAtomCallback( + tagId, + null, // use default PullAtomMetadata values + DIRECT_EXECUTOR, + mStatsCallbackImpl + ); + } + + int pullProcessDmabufMemory(int atomTag, List<StatsEvent> pulledData) { + List<ProcessMemoryState> managedProcessList = + LocalServices.getService(ActivityManagerInternal.class) + .getMemoryStateForProcesses(); + managedProcessList.sort(Comparator.comparingInt(x -> x.oomScore)); + for (ProcessMemoryState process : managedProcessList) { + if (process.uid == Process.SYSTEM_UID) { + continue; + } + DmabufInfoReader.ProcessDmabuf proc = DmabufInfoReader.getProcessStats(process.pid); + if (proc == null || (proc.retainedBuffersCount <= 0 && proc.mappedBuffersCount <= 0)) { + continue; + } + pulledData.add( + FrameworkStatsLog.buildStatsEvent( + atomTag, + process.uid, + process.processName, + process.oomScore, + proc.retainedSizeKb, + proc.retainedBuffersCount, + proc.mappedSizeKb, + proc.mappedBuffersCount)); + } + return StatsManager.PULL_SUCCESS; + } + private void registerSystemMemory() { int tagId = FrameworkStatsLog.SYSTEM_MEMORY; mStatsManager.setPullAtomCallback( |