Loading apct-tests/perftests/core/src/android/os/LongArrayMultiStateCounterPerfTest.java +1 −3 Original line number Diff line number Diff line Loading @@ -159,9 +159,7 @@ public class LongArrayMultiStateCounterPerfTest { LongArrayMultiStateCounter counter = new LongArrayMultiStateCounter(2, 4); final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); long time = 1000; LongArrayMultiStateCounter.LongArrayContainer timeInFreq = new LongArrayMultiStateCounter.LongArrayContainer(4); timeInFreq.setValues(new long[]{100, 200, 300, 400}); long[] timeInFreq = {100, 200, 300, 400}; while (state.keepRunning()) { counter.setState(1, time); counter.setState(0, time + 1000); Loading core/java/android/os/BatteryUsageStats.java +1 −1 Original line number Diff line number Diff line Loading @@ -1315,7 +1315,7 @@ public final class BatteryUsageStats implements Parcelable, Closeable { } synchronized (BatteryUsageStats.class) { if (!sInstances.isEmpty()) { if (sInstances != null && !sInstances.isEmpty()) { Exception callSite = sInstances.entrySet().iterator().next().getValue(); int count = sInstances.size(); sInstances.clear(); Loading core/java/com/android/internal/os/KernelSingleUidTimeReader.java +9 −12 Original line number Diff line number Diff line Loading @@ -18,14 +18,13 @@ package com.android.internal.os; import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE; import android.annotation.NonNull; import android.annotation.Nullable; import android.util.Slog; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import dalvik.annotation.optimization.CriticalNative; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; Loading Loading @@ -255,8 +254,8 @@ public class KernelSingleUidTimeReader { * the delta in the supplied array container. */ public void addDelta(int uid, LongArrayMultiStateCounter counter, long timestampMs, LongArrayMultiStateCounter.LongArrayContainer deltaContainer) { mInjector.addDelta(uid, counter, timestampMs, deltaContainer); long[] delta) { mInjector.addDelta(uid, counter, timestampMs, delta); } @VisibleForTesting Loading @@ -274,15 +273,13 @@ public class KernelSingleUidTimeReader { * The delta is also returned via the optional deltaOut parameter. */ public boolean addDelta(int uid, LongArrayMultiStateCounter counter, long timestampMs, LongArrayMultiStateCounter.LongArrayContainer deltaOut) { return addDeltaFromBpf(uid, counter.mNativeObject, timestampMs, deltaOut != null ? deltaOut.mNativeObject : 0); long[] deltaOut) { return addDeltaFromBpf(uid, counter.mNativeObject, timestampMs, deltaOut); } @CriticalNative private static native boolean addDeltaFromBpf(int uid, long longArrayMultiStateCounterNativePointer, long timestampMs, long longArrayContainerNativePointer); @Nullable long[] deltaOut); /** * Used for testing. Loading @@ -291,14 +288,14 @@ public class KernelSingleUidTimeReader { */ public boolean addDeltaForTest(int uid, LongArrayMultiStateCounter counter, long timestampMs, long[][] timeInFreqDataNanos, LongArrayMultiStateCounter.LongArrayContainer deltaOut) { long[] deltaOut) { return addDeltaForTest(uid, counter.mNativeObject, timestampMs, timeInFreqDataNanos, deltaOut != null ? deltaOut.mNativeObject : 0); deltaOut); } private static native boolean addDeltaForTest(int uid, long longArrayMultiStateCounterNativePointer, long timestampMs, long[][] timeInFreqDataNanos, long longArrayContainerNativePointer); long[][] timeInFreqDataNanos, long[] deltaOut); } @VisibleForTesting Loading core/java/com/android/internal/os/LongArrayMultiStateCounter.java +40 −193 Original line number Diff line number Diff line Loading @@ -30,9 +30,6 @@ import dalvik.annotation.optimization.FastNative; import libcore.util.NativeAllocationRegistry; import java.util.Arrays; import java.util.concurrent.atomic.AtomicReference; /** * Performs per-state counting of multi-element values over time. The class' behavior is illustrated * by this example: Loading @@ -44,15 +41,14 @@ import java.util.concurrent.atomic.AtomicReference; * counter.setState(1, 1000); * * // At 3000 ms, the tracked values are updated to {30, 300} * arrayContainer.setValues(new long[]{{30, 300}}; * counter.updateValues(arrayContainer, 3000); * counter.updateValues(arrayContainer, new long[]{{30, 300}, 3000); * * // The values are distributed between states 0 and 1 according to the time * // spent in those respective states. In this specific case, 1000 and 2000 ms. * counter.getValues(arrayContainer, 0); * // arrayContainer now has values {10, 100} * counter.getValues(arrayContainer, 1); * // arrayContainer now has values {20, 200} * counter.getCounts(array, 0); * // array now has values {10, 100} * counter.getCounts(array, 1); * // array now has values {20, 200} * </pre> * * The tracked values are expected to increase monotonically. Loading @@ -62,110 +58,7 @@ import java.util.concurrent.atomic.AtomicReference; @RavenwoodKeepWholeClass @RavenwoodRedirectionClass("LongArrayMultiStateCounter_host") public final class LongArrayMultiStateCounter implements Parcelable { /** * Container for a native equivalent of a long[]. */ @RavenwoodKeepWholeClass @RavenwoodRedirectionClass("LongArrayContainer_host") public static class LongArrayContainer { private static NativeAllocationRegistry sRegistry; // Visible to other objects in this package so that it can be passed to @CriticalNative // methods. final long mNativeObject; private final int mLength; public LongArrayContainer(int length) { mLength = length; mNativeObject = native_init(length); registerNativeAllocation(); } @RavenwoodReplace private void registerNativeAllocation() { if (sRegistry == null) { synchronized (LongArrayMultiStateCounter.class) { if (sRegistry == null) { sRegistry = NativeAllocationRegistry.createMalloced( LongArrayContainer.class.getClassLoader(), native_getReleaseFunc()); } } } sRegistry.registerNativeAllocation(this, mNativeObject); } private void registerNativeAllocation$ravenwood() { // No-op under ravenwood } /** * Copies the supplied values into the underlying native array. */ public void setValues(long[] array) { if (array.length != mLength) { throw new IllegalArgumentException( "Invalid array length: " + array.length + ", expected: " + mLength); } native_setValues(mNativeObject, array); } /** * Copies the underlying native array values to the supplied array. */ public void getValues(long[] array) { if (array.length != mLength) { throw new IllegalArgumentException( "Invalid array length: " + array.length + ", expected: " + mLength); } native_getValues(mNativeObject, array); } /** * Combines contained values into a smaller array by aggregating them * according to an index map. */ public boolean combineValues(long[] array, int[] indexMap) { if (indexMap.length != mLength) { throw new IllegalArgumentException( "Wrong index map size " + indexMap.length + ", expected " + mLength); } return native_combineValues(mNativeObject, array, indexMap); } @Override public String toString() { final long[] array = new long[mLength]; getValues(array); return Arrays.toString(array); } @CriticalNative @RavenwoodRedirect private static native long native_init(int length); @CriticalNative @RavenwoodRedirect private static native long native_getReleaseFunc(); @FastNative @RavenwoodRedirect private static native void native_setValues(long nativeObject, long[] array); @FastNative @RavenwoodRedirect private static native void native_getValues(long nativeObject, long[] array); @FastNative @RavenwoodRedirect private static native boolean native_combineValues(long nativeObject, long[] array, int[] indexMap); } private static volatile NativeAllocationRegistry sRegistry; private static final AtomicReference<LongArrayContainer> sTmpArrayContainer = new AtomicReference<>(); private final int mStateCount; private final int mLength; Loading Loading @@ -257,41 +150,14 @@ public final class LongArrayMultiStateCounter implements Parcelable { throw new IllegalArgumentException( "Invalid array length: " + values.length + ", expected: " + mLength); } LongArrayContainer container = sTmpArrayContainer.getAndSet(null); if (container == null || container.mLength != values.length) { container = new LongArrayContainer(values.length); } container.setValues(values); native_setValues(mNativeObject, state, container.mNativeObject); sTmpArrayContainer.set(container); } /** * Sets the new values. The delta between the previously set values and these values * is distributed among the state according to the time the object spent in those states * since the previous call to updateValues. */ public void updateValues(long[] values, long timestampMs) { LongArrayContainer container = sTmpArrayContainer.getAndSet(null); if (container == null || container.mLength != values.length) { container = new LongArrayContainer(values.length); } container.setValues(values); updateValues(container, timestampMs); sTmpArrayContainer.set(container); native_setValues(mNativeObject, state, values); } /** * Adds the supplied values to the current accumulated values in the counter. */ public void incrementValues(long[] values, long timestampMs) { LongArrayContainer container = sTmpArrayContainer.getAndSet(null); if (container == null || container.mLength != values.length) { container = new LongArrayContainer(values.length); } container.setValues(values); native_incrementValues(mNativeObject, container.mNativeObject, timestampMs); sTmpArrayContainer.set(container); native_incrementValues(mNativeObject, values, timestampMs); } /** Loading @@ -299,24 +165,23 @@ public final class LongArrayMultiStateCounter implements Parcelable { * is distributed among the state according to the time the object spent in those states * since the previous call to updateValues. */ public void updateValues(LongArrayContainer longArrayContainer, long timestampMs) { if (longArrayContainer.mLength != mLength) { public void updateValues(long[] values, long timestampMs) { if (values.length != mLength) { throw new IllegalArgumentException( "Invalid array length: " + longArrayContainer.mLength + ", expected: " + mLength); "Invalid array length: " + values.length + ", expected: " + mLength); } native_updateValues(mNativeObject, longArrayContainer.mNativeObject, timestampMs); native_updateValues(mNativeObject, values, timestampMs); } /** * Adds the supplied values to the current accumulated values in the counter. */ public void addCounts(LongArrayContainer counts) { if (counts.mLength != mLength) { public void addCounts(long[] counts) { if (counts.length != mLength) { throw new IllegalArgumentException( "Invalid array length: " + counts.mLength + ", expected: " + mLength); "Invalid array length: " + counts.length + ", expected: " + mLength); } native_addCounts(mNativeObject, counts.mNativeObject); native_addCounts(mNativeObject, counts); } /** Loading @@ -330,29 +195,15 @@ public final class LongArrayMultiStateCounter implements Parcelable { * Populates the array with the accumulated counts for the specified state. */ public void getCounts(long[] counts, int state) { LongArrayContainer container = sTmpArrayContainer.getAndSet(null); if (container == null || container.mLength != counts.length) { container = new LongArrayContainer(counts.length); } getCounts(container, state); container.getValues(counts); sTmpArrayContainer.set(container); } /** * Populates longArrayContainer with the accumulated counts for the specified state. */ public void getCounts(LongArrayContainer longArrayContainer, int state) { if (state < 0 || state >= mStateCount) { throw new IllegalArgumentException( "State: " + state + ", outside the range: [0-" + mStateCount + "]"); } if (longArrayContainer.mLength != mLength) { if (counts.length != mLength) { throw new IllegalArgumentException( "Invalid array length: " + longArrayContainer.mLength + ", expected: " + mLength); "Invalid array length: " + counts.length + ", expected: " + mLength); } native_getCounts(mNativeObject, longArrayContainer.mNativeObject, state); native_getCounts(mNativeObject, counts, state); } @Override Loading @@ -370,8 +221,7 @@ public final class LongArrayMultiStateCounter implements Parcelable { return 0; } public static final Creator<LongArrayMultiStateCounter> CREATOR = new Creator<LongArrayMultiStateCounter>() { public static final Creator<LongArrayMultiStateCounter> CREATOR = new Creator<>() { @Override public LongArrayMultiStateCounter createFromParcel(Parcel in) { return new LongArrayMultiStateCounter(in); Loading Loading @@ -406,34 +256,31 @@ public final class LongArrayMultiStateCounter implements Parcelable { private static native void native_copyStatesFrom(long nativeObjectTarget, long nativeObjectSource); @CriticalNative @FastNative @RavenwoodRedirect private static native void native_setValues(long nativeObject, int state, long longArrayContainerNativeObject); private static native void native_setValues(long nativeObject, int state, long[] values); @CriticalNative @FastNative @RavenwoodRedirect private static native void native_updateValues(long nativeObject, long longArrayContainerNativeObject, long timestampMs); private static native void native_updateValues(long nativeObject, long[] values, long timestampMs); @CriticalNative @FastNative @RavenwoodRedirect private static native void native_incrementValues(long nativeObject, long longArrayContainerNativeObject, long timestampMs); private static native void native_incrementValues(long nativeObject, long[] values, long timestampMs); @CriticalNative @FastNative @RavenwoodRedirect private static native void native_addCounts(long nativeObject, long longArrayContainerNativeObject); private static native void native_addCounts(long nativeObject, long[] counts); @CriticalNative @RavenwoodRedirect private static native void native_reset(long nativeObject); @CriticalNative @FastNative @RavenwoodRedirect private static native void native_getCounts(long nativeObject, long longArrayContainerNativeObject, int state); private static native void native_getCounts(long nativeObject, long[] counts, int state); @FastNative @RavenwoodRedirect Loading core/jni/com_android_internal_os_KernelSingleUidTimeReader.cpp +28 −28 Original line number Diff line number Diff line Loading @@ -49,27 +49,26 @@ static jlongArray getUidCpuFreqTimeMs(JNIEnv *env, jclass, jint uid) { * to the supplied multi-state counter in accordance with the counter's state. */ static jboolean addCpuTimeInFreqDelta( jint uid, jlong counterNativePtr, jlong timestampMs, JNIEnv *env, jint uid, jlong counterNativePtr, jlong timestampMs, std::optional<std::vector<std::vector<uint64_t>>> timeInFreqDataNanos, jlong deltaOutContainerNativePtr) { jlongArray deltaOut) { if (!timeInFreqDataNanos) { return false; } battery::LongArrayMultiStateCounter *counter = reinterpret_cast<battery::LongArrayMultiStateCounter *>(counterNativePtr); auto counter = reinterpret_cast<battery::LongArrayMultiStateCounter *>(counterNativePtr); size_t s = 0; for (const auto &cluster : *timeInFreqDataNanos) s += cluster.size(); std::vector<uint64_t> flattened; flattened.reserve(s); auto offset = flattened.begin(); battery::Uint64ArrayRW flattened(s); uint64_t *out = flattened.dataRW(); auto offset = out; for (const auto &cluster : *timeInFreqDataNanos) { flattened.insert(offset, cluster.begin(), cluster.end()); memcpy(offset, cluster.data(), cluster.size() * sizeof(uint64_t)); offset += cluster.size(); } for (size_t i = 0; i < s; ++i) { flattened[i] /= NSEC_PER_MSEC; out[i] /= NSEC_PER_MSEC; } if (s != counter->getCount(0).size()) { // Counter has at least one state ALOGE("Mismatch between eBPF data size (%d) and the counter size (%d)", (int)s, Loading @@ -77,29 +76,32 @@ static jboolean addCpuTimeInFreqDelta( return false; } const std::vector<uint64_t> &delta = counter->updateValue(flattened, timestampMs); if (deltaOutContainerNativePtr) { std::vector<uint64_t> *vector = reinterpret_cast<std::vector<uint64_t> *>(deltaOutContainerNativePtr); *vector = delta; const battery::Uint64Array &delta = counter->updateValue(flattened, timestampMs); if (deltaOut) { ScopedLongArrayRW scopedArray(env, deltaOut); uint64_t *array = reinterpret_cast<uint64_t *>(scopedArray.get()); if (delta.data() != nullptr) { memcpy(array, delta.data(), s * sizeof(uint64_t)); } else { memset(array, 0, s * sizeof(uint64_t)); } } return true; } static jboolean addDeltaFromBpf(jint uid, jlong counterNativePtr, jlong timestampMs, jlong deltaOutContainerNativePtr) { return addCpuTimeInFreqDelta(uid, counterNativePtr, timestampMs, android::bpf::getUidCpuFreqTimes(uid), deltaOutContainerNativePtr); static jboolean addDeltaFromBpf(JNIEnv *env, jlong self, jint uid, jlong counterNativePtr, jlong timestampMs, jlongArray deltaOut) { return addCpuTimeInFreqDelta(env, uid, counterNativePtr, timestampMs, android::bpf::getUidCpuFreqTimes(uid), deltaOut); } static jboolean addDeltaForTest(JNIEnv *env, jclass, jint uid, jlong counterNativePtr, jlong timestampMs, jobjectArray timeInFreqDataNanos, jlong deltaOutContainerNativePtr) { jlongArray deltaOut) { if (!timeInFreqDataNanos) { return addCpuTimeInFreqDelta(uid, counterNativePtr, timestampMs, std::optional<std::vector<std::vector<uint64_t>>>(), deltaOutContainerNativePtr); return addCpuTimeInFreqDelta(env, uid, counterNativePtr, timestampMs, std::optional<std::vector<std::vector<uint64_t>>>(), deltaOut); } std::vector<std::vector<uint64_t>> timeInFreqData; Loading @@ -113,18 +115,16 @@ static jboolean addDeltaForTest(JNIEnv *env, jclass, jint uid, jlong counterNati } timeInFreqData.push_back(cluster); } return addCpuTimeInFreqDelta(uid, counterNativePtr, timestampMs, std::optional(timeInFreqData), deltaOutContainerNativePtr); return addCpuTimeInFreqDelta(env, uid, counterNativePtr, timestampMs, std::optional(timeInFreqData), deltaOut); } static const JNINativeMethod g_single_methods[] = { {"readBpfData", "(I)[J", (void *)getUidCpuFreqTimeMs}, // @CriticalNative {"addDeltaFromBpf", "(IJJJ)Z", (void *)addDeltaFromBpf}, {"addDeltaFromBpf", "(IJJ[J)Z", (void *)addDeltaFromBpf}, // Used for testing {"addDeltaForTest", "(IJJ[[JJ)Z", (void *)addDeltaForTest}, {"addDeltaForTest", "(IJJ[[J[J)Z", (void *)addDeltaForTest}, }; int register_com_android_internal_os_KernelSingleUidTimeReader(JNIEnv *env) { Loading Loading
apct-tests/perftests/core/src/android/os/LongArrayMultiStateCounterPerfTest.java +1 −3 Original line number Diff line number Diff line Loading @@ -159,9 +159,7 @@ public class LongArrayMultiStateCounterPerfTest { LongArrayMultiStateCounter counter = new LongArrayMultiStateCounter(2, 4); final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); long time = 1000; LongArrayMultiStateCounter.LongArrayContainer timeInFreq = new LongArrayMultiStateCounter.LongArrayContainer(4); timeInFreq.setValues(new long[]{100, 200, 300, 400}); long[] timeInFreq = {100, 200, 300, 400}; while (state.keepRunning()) { counter.setState(1, time); counter.setState(0, time + 1000); Loading
core/java/android/os/BatteryUsageStats.java +1 −1 Original line number Diff line number Diff line Loading @@ -1315,7 +1315,7 @@ public final class BatteryUsageStats implements Parcelable, Closeable { } synchronized (BatteryUsageStats.class) { if (!sInstances.isEmpty()) { if (sInstances != null && !sInstances.isEmpty()) { Exception callSite = sInstances.entrySet().iterator().next().getValue(); int count = sInstances.size(); sInstances.clear(); Loading
core/java/com/android/internal/os/KernelSingleUidTimeReader.java +9 −12 Original line number Diff line number Diff line Loading @@ -18,14 +18,13 @@ package com.android.internal.os; import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE; import android.annotation.NonNull; import android.annotation.Nullable; import android.util.Slog; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import dalvik.annotation.optimization.CriticalNative; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; Loading Loading @@ -255,8 +254,8 @@ public class KernelSingleUidTimeReader { * the delta in the supplied array container. */ public void addDelta(int uid, LongArrayMultiStateCounter counter, long timestampMs, LongArrayMultiStateCounter.LongArrayContainer deltaContainer) { mInjector.addDelta(uid, counter, timestampMs, deltaContainer); long[] delta) { mInjector.addDelta(uid, counter, timestampMs, delta); } @VisibleForTesting Loading @@ -274,15 +273,13 @@ public class KernelSingleUidTimeReader { * The delta is also returned via the optional deltaOut parameter. */ public boolean addDelta(int uid, LongArrayMultiStateCounter counter, long timestampMs, LongArrayMultiStateCounter.LongArrayContainer deltaOut) { return addDeltaFromBpf(uid, counter.mNativeObject, timestampMs, deltaOut != null ? deltaOut.mNativeObject : 0); long[] deltaOut) { return addDeltaFromBpf(uid, counter.mNativeObject, timestampMs, deltaOut); } @CriticalNative private static native boolean addDeltaFromBpf(int uid, long longArrayMultiStateCounterNativePointer, long timestampMs, long longArrayContainerNativePointer); @Nullable long[] deltaOut); /** * Used for testing. Loading @@ -291,14 +288,14 @@ public class KernelSingleUidTimeReader { */ public boolean addDeltaForTest(int uid, LongArrayMultiStateCounter counter, long timestampMs, long[][] timeInFreqDataNanos, LongArrayMultiStateCounter.LongArrayContainer deltaOut) { long[] deltaOut) { return addDeltaForTest(uid, counter.mNativeObject, timestampMs, timeInFreqDataNanos, deltaOut != null ? deltaOut.mNativeObject : 0); deltaOut); } private static native boolean addDeltaForTest(int uid, long longArrayMultiStateCounterNativePointer, long timestampMs, long[][] timeInFreqDataNanos, long longArrayContainerNativePointer); long[][] timeInFreqDataNanos, long[] deltaOut); } @VisibleForTesting Loading
core/java/com/android/internal/os/LongArrayMultiStateCounter.java +40 −193 Original line number Diff line number Diff line Loading @@ -30,9 +30,6 @@ import dalvik.annotation.optimization.FastNative; import libcore.util.NativeAllocationRegistry; import java.util.Arrays; import java.util.concurrent.atomic.AtomicReference; /** * Performs per-state counting of multi-element values over time. The class' behavior is illustrated * by this example: Loading @@ -44,15 +41,14 @@ import java.util.concurrent.atomic.AtomicReference; * counter.setState(1, 1000); * * // At 3000 ms, the tracked values are updated to {30, 300} * arrayContainer.setValues(new long[]{{30, 300}}; * counter.updateValues(arrayContainer, 3000); * counter.updateValues(arrayContainer, new long[]{{30, 300}, 3000); * * // The values are distributed between states 0 and 1 according to the time * // spent in those respective states. In this specific case, 1000 and 2000 ms. * counter.getValues(arrayContainer, 0); * // arrayContainer now has values {10, 100} * counter.getValues(arrayContainer, 1); * // arrayContainer now has values {20, 200} * counter.getCounts(array, 0); * // array now has values {10, 100} * counter.getCounts(array, 1); * // array now has values {20, 200} * </pre> * * The tracked values are expected to increase monotonically. Loading @@ -62,110 +58,7 @@ import java.util.concurrent.atomic.AtomicReference; @RavenwoodKeepWholeClass @RavenwoodRedirectionClass("LongArrayMultiStateCounter_host") public final class LongArrayMultiStateCounter implements Parcelable { /** * Container for a native equivalent of a long[]. */ @RavenwoodKeepWholeClass @RavenwoodRedirectionClass("LongArrayContainer_host") public static class LongArrayContainer { private static NativeAllocationRegistry sRegistry; // Visible to other objects in this package so that it can be passed to @CriticalNative // methods. final long mNativeObject; private final int mLength; public LongArrayContainer(int length) { mLength = length; mNativeObject = native_init(length); registerNativeAllocation(); } @RavenwoodReplace private void registerNativeAllocation() { if (sRegistry == null) { synchronized (LongArrayMultiStateCounter.class) { if (sRegistry == null) { sRegistry = NativeAllocationRegistry.createMalloced( LongArrayContainer.class.getClassLoader(), native_getReleaseFunc()); } } } sRegistry.registerNativeAllocation(this, mNativeObject); } private void registerNativeAllocation$ravenwood() { // No-op under ravenwood } /** * Copies the supplied values into the underlying native array. */ public void setValues(long[] array) { if (array.length != mLength) { throw new IllegalArgumentException( "Invalid array length: " + array.length + ", expected: " + mLength); } native_setValues(mNativeObject, array); } /** * Copies the underlying native array values to the supplied array. */ public void getValues(long[] array) { if (array.length != mLength) { throw new IllegalArgumentException( "Invalid array length: " + array.length + ", expected: " + mLength); } native_getValues(mNativeObject, array); } /** * Combines contained values into a smaller array by aggregating them * according to an index map. */ public boolean combineValues(long[] array, int[] indexMap) { if (indexMap.length != mLength) { throw new IllegalArgumentException( "Wrong index map size " + indexMap.length + ", expected " + mLength); } return native_combineValues(mNativeObject, array, indexMap); } @Override public String toString() { final long[] array = new long[mLength]; getValues(array); return Arrays.toString(array); } @CriticalNative @RavenwoodRedirect private static native long native_init(int length); @CriticalNative @RavenwoodRedirect private static native long native_getReleaseFunc(); @FastNative @RavenwoodRedirect private static native void native_setValues(long nativeObject, long[] array); @FastNative @RavenwoodRedirect private static native void native_getValues(long nativeObject, long[] array); @FastNative @RavenwoodRedirect private static native boolean native_combineValues(long nativeObject, long[] array, int[] indexMap); } private static volatile NativeAllocationRegistry sRegistry; private static final AtomicReference<LongArrayContainer> sTmpArrayContainer = new AtomicReference<>(); private final int mStateCount; private final int mLength; Loading Loading @@ -257,41 +150,14 @@ public final class LongArrayMultiStateCounter implements Parcelable { throw new IllegalArgumentException( "Invalid array length: " + values.length + ", expected: " + mLength); } LongArrayContainer container = sTmpArrayContainer.getAndSet(null); if (container == null || container.mLength != values.length) { container = new LongArrayContainer(values.length); } container.setValues(values); native_setValues(mNativeObject, state, container.mNativeObject); sTmpArrayContainer.set(container); } /** * Sets the new values. The delta between the previously set values and these values * is distributed among the state according to the time the object spent in those states * since the previous call to updateValues. */ public void updateValues(long[] values, long timestampMs) { LongArrayContainer container = sTmpArrayContainer.getAndSet(null); if (container == null || container.mLength != values.length) { container = new LongArrayContainer(values.length); } container.setValues(values); updateValues(container, timestampMs); sTmpArrayContainer.set(container); native_setValues(mNativeObject, state, values); } /** * Adds the supplied values to the current accumulated values in the counter. */ public void incrementValues(long[] values, long timestampMs) { LongArrayContainer container = sTmpArrayContainer.getAndSet(null); if (container == null || container.mLength != values.length) { container = new LongArrayContainer(values.length); } container.setValues(values); native_incrementValues(mNativeObject, container.mNativeObject, timestampMs); sTmpArrayContainer.set(container); native_incrementValues(mNativeObject, values, timestampMs); } /** Loading @@ -299,24 +165,23 @@ public final class LongArrayMultiStateCounter implements Parcelable { * is distributed among the state according to the time the object spent in those states * since the previous call to updateValues. */ public void updateValues(LongArrayContainer longArrayContainer, long timestampMs) { if (longArrayContainer.mLength != mLength) { public void updateValues(long[] values, long timestampMs) { if (values.length != mLength) { throw new IllegalArgumentException( "Invalid array length: " + longArrayContainer.mLength + ", expected: " + mLength); "Invalid array length: " + values.length + ", expected: " + mLength); } native_updateValues(mNativeObject, longArrayContainer.mNativeObject, timestampMs); native_updateValues(mNativeObject, values, timestampMs); } /** * Adds the supplied values to the current accumulated values in the counter. */ public void addCounts(LongArrayContainer counts) { if (counts.mLength != mLength) { public void addCounts(long[] counts) { if (counts.length != mLength) { throw new IllegalArgumentException( "Invalid array length: " + counts.mLength + ", expected: " + mLength); "Invalid array length: " + counts.length + ", expected: " + mLength); } native_addCounts(mNativeObject, counts.mNativeObject); native_addCounts(mNativeObject, counts); } /** Loading @@ -330,29 +195,15 @@ public final class LongArrayMultiStateCounter implements Parcelable { * Populates the array with the accumulated counts for the specified state. */ public void getCounts(long[] counts, int state) { LongArrayContainer container = sTmpArrayContainer.getAndSet(null); if (container == null || container.mLength != counts.length) { container = new LongArrayContainer(counts.length); } getCounts(container, state); container.getValues(counts); sTmpArrayContainer.set(container); } /** * Populates longArrayContainer with the accumulated counts for the specified state. */ public void getCounts(LongArrayContainer longArrayContainer, int state) { if (state < 0 || state >= mStateCount) { throw new IllegalArgumentException( "State: " + state + ", outside the range: [0-" + mStateCount + "]"); } if (longArrayContainer.mLength != mLength) { if (counts.length != mLength) { throw new IllegalArgumentException( "Invalid array length: " + longArrayContainer.mLength + ", expected: " + mLength); "Invalid array length: " + counts.length + ", expected: " + mLength); } native_getCounts(mNativeObject, longArrayContainer.mNativeObject, state); native_getCounts(mNativeObject, counts, state); } @Override Loading @@ -370,8 +221,7 @@ public final class LongArrayMultiStateCounter implements Parcelable { return 0; } public static final Creator<LongArrayMultiStateCounter> CREATOR = new Creator<LongArrayMultiStateCounter>() { public static final Creator<LongArrayMultiStateCounter> CREATOR = new Creator<>() { @Override public LongArrayMultiStateCounter createFromParcel(Parcel in) { return new LongArrayMultiStateCounter(in); Loading Loading @@ -406,34 +256,31 @@ public final class LongArrayMultiStateCounter implements Parcelable { private static native void native_copyStatesFrom(long nativeObjectTarget, long nativeObjectSource); @CriticalNative @FastNative @RavenwoodRedirect private static native void native_setValues(long nativeObject, int state, long longArrayContainerNativeObject); private static native void native_setValues(long nativeObject, int state, long[] values); @CriticalNative @FastNative @RavenwoodRedirect private static native void native_updateValues(long nativeObject, long longArrayContainerNativeObject, long timestampMs); private static native void native_updateValues(long nativeObject, long[] values, long timestampMs); @CriticalNative @FastNative @RavenwoodRedirect private static native void native_incrementValues(long nativeObject, long longArrayContainerNativeObject, long timestampMs); private static native void native_incrementValues(long nativeObject, long[] values, long timestampMs); @CriticalNative @FastNative @RavenwoodRedirect private static native void native_addCounts(long nativeObject, long longArrayContainerNativeObject); private static native void native_addCounts(long nativeObject, long[] counts); @CriticalNative @RavenwoodRedirect private static native void native_reset(long nativeObject); @CriticalNative @FastNative @RavenwoodRedirect private static native void native_getCounts(long nativeObject, long longArrayContainerNativeObject, int state); private static native void native_getCounts(long nativeObject, long[] counts, int state); @FastNative @RavenwoodRedirect Loading
core/jni/com_android_internal_os_KernelSingleUidTimeReader.cpp +28 −28 Original line number Diff line number Diff line Loading @@ -49,27 +49,26 @@ static jlongArray getUidCpuFreqTimeMs(JNIEnv *env, jclass, jint uid) { * to the supplied multi-state counter in accordance with the counter's state. */ static jboolean addCpuTimeInFreqDelta( jint uid, jlong counterNativePtr, jlong timestampMs, JNIEnv *env, jint uid, jlong counterNativePtr, jlong timestampMs, std::optional<std::vector<std::vector<uint64_t>>> timeInFreqDataNanos, jlong deltaOutContainerNativePtr) { jlongArray deltaOut) { if (!timeInFreqDataNanos) { return false; } battery::LongArrayMultiStateCounter *counter = reinterpret_cast<battery::LongArrayMultiStateCounter *>(counterNativePtr); auto counter = reinterpret_cast<battery::LongArrayMultiStateCounter *>(counterNativePtr); size_t s = 0; for (const auto &cluster : *timeInFreqDataNanos) s += cluster.size(); std::vector<uint64_t> flattened; flattened.reserve(s); auto offset = flattened.begin(); battery::Uint64ArrayRW flattened(s); uint64_t *out = flattened.dataRW(); auto offset = out; for (const auto &cluster : *timeInFreqDataNanos) { flattened.insert(offset, cluster.begin(), cluster.end()); memcpy(offset, cluster.data(), cluster.size() * sizeof(uint64_t)); offset += cluster.size(); } for (size_t i = 0; i < s; ++i) { flattened[i] /= NSEC_PER_MSEC; out[i] /= NSEC_PER_MSEC; } if (s != counter->getCount(0).size()) { // Counter has at least one state ALOGE("Mismatch between eBPF data size (%d) and the counter size (%d)", (int)s, Loading @@ -77,29 +76,32 @@ static jboolean addCpuTimeInFreqDelta( return false; } const std::vector<uint64_t> &delta = counter->updateValue(flattened, timestampMs); if (deltaOutContainerNativePtr) { std::vector<uint64_t> *vector = reinterpret_cast<std::vector<uint64_t> *>(deltaOutContainerNativePtr); *vector = delta; const battery::Uint64Array &delta = counter->updateValue(flattened, timestampMs); if (deltaOut) { ScopedLongArrayRW scopedArray(env, deltaOut); uint64_t *array = reinterpret_cast<uint64_t *>(scopedArray.get()); if (delta.data() != nullptr) { memcpy(array, delta.data(), s * sizeof(uint64_t)); } else { memset(array, 0, s * sizeof(uint64_t)); } } return true; } static jboolean addDeltaFromBpf(jint uid, jlong counterNativePtr, jlong timestampMs, jlong deltaOutContainerNativePtr) { return addCpuTimeInFreqDelta(uid, counterNativePtr, timestampMs, android::bpf::getUidCpuFreqTimes(uid), deltaOutContainerNativePtr); static jboolean addDeltaFromBpf(JNIEnv *env, jlong self, jint uid, jlong counterNativePtr, jlong timestampMs, jlongArray deltaOut) { return addCpuTimeInFreqDelta(env, uid, counterNativePtr, timestampMs, android::bpf::getUidCpuFreqTimes(uid), deltaOut); } static jboolean addDeltaForTest(JNIEnv *env, jclass, jint uid, jlong counterNativePtr, jlong timestampMs, jobjectArray timeInFreqDataNanos, jlong deltaOutContainerNativePtr) { jlongArray deltaOut) { if (!timeInFreqDataNanos) { return addCpuTimeInFreqDelta(uid, counterNativePtr, timestampMs, std::optional<std::vector<std::vector<uint64_t>>>(), deltaOutContainerNativePtr); return addCpuTimeInFreqDelta(env, uid, counterNativePtr, timestampMs, std::optional<std::vector<std::vector<uint64_t>>>(), deltaOut); } std::vector<std::vector<uint64_t>> timeInFreqData; Loading @@ -113,18 +115,16 @@ static jboolean addDeltaForTest(JNIEnv *env, jclass, jint uid, jlong counterNati } timeInFreqData.push_back(cluster); } return addCpuTimeInFreqDelta(uid, counterNativePtr, timestampMs, std::optional(timeInFreqData), deltaOutContainerNativePtr); return addCpuTimeInFreqDelta(env, uid, counterNativePtr, timestampMs, std::optional(timeInFreqData), deltaOut); } static const JNINativeMethod g_single_methods[] = { {"readBpfData", "(I)[J", (void *)getUidCpuFreqTimeMs}, // @CriticalNative {"addDeltaFromBpf", "(IJJJ)Z", (void *)addDeltaFromBpf}, {"addDeltaFromBpf", "(IJJ[J)Z", (void *)addDeltaFromBpf}, // Used for testing {"addDeltaForTest", "(IJJ[[JJ)Z", (void *)addDeltaForTest}, {"addDeltaForTest", "(IJJ[[J[J)Z", (void *)addDeltaForTest}, }; int register_com_android_internal_os_KernelSingleUidTimeReader(JNIEnv *env) { Loading