Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e036a133 authored by Dmitri Plotnikov's avatar Dmitri Plotnikov
Browse files

Reduce array locking in LongArrayMultiStateCounter

Do this by checking if the data is all-zeros and returning
false in that case, without locking the java long array in JNI

Bug: 395954049
Test: atest PowerStatsTests; atest PowerStatsTests:BatteryUsageStatsProviderPerfTest#getBatteryUsageStats_accumulated
Flag: EXEMPT bugfix

Change-Id: I81639d9d571afcbb61ea047d8b2ab5e1b2bcf6f0
parent 241cfec9
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.internal.os;

import android.annotation.CheckResult;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
@@ -196,7 +197,8 @@ public final class LongArrayMultiStateCounter implements Parcelable {
    /**
     * Populates the array with the accumulated counts for the specified state.
     */
    public void getCounts(long[] counts, int state) {
    @CheckResult
    public boolean getCounts(long[] counts, int state) {
        if (state < 0 || state >= mStateCount) {
            throw new IllegalArgumentException(
                    "State: " + state + ", outside the range: [0-" + mStateCount + "]");
@@ -205,7 +207,7 @@ public final class LongArrayMultiStateCounter implements Parcelable {
            throw new IllegalArgumentException(
                    "Invalid array length: " + counts.length + ", expected: " + mLength);
        }
        native_getCounts(mNativeObject, counts, state);
        return native_getCounts(mNativeObject, counts, state);
    }

    @Override
@@ -282,7 +284,8 @@ public final class LongArrayMultiStateCounter implements Parcelable {

    @FastNative
    @RavenwoodRedirect
    private static native void native_getCounts(long nativeObject, long[] counts, int state);
    @CheckResult
    private static native boolean native_getCounts(long nativeObject, long[] counts, int state);

    @FastNative
    @RavenwoodRedirect
+16 −4
Original line number Diff line number Diff line
@@ -168,8 +168,20 @@ class LongArrayMultiStateCounter_ravenwood {
            }
        }

        public void getValues(long[] values, int state) {
            System.arraycopy(mStates[state].mCounter, 0, values, 0, mArrayLength);
        public boolean getValues(long[] values, int state) {
            long[] counts = mStates[state].mCounter;
            boolean allZeros = true;
            for (int i = 0; i < counts.length; i++) {
                if (counts[i] != 0) {
                    allZeros = false;
                    break;
                }
            }
            if (allZeros) {
                return false;
            }
            System.arraycopy(counts, 0, values, 0, mArrayLength);
            return true;
        }

        public void reset() {
@@ -316,8 +328,8 @@ class LongArrayMultiStateCounter_ravenwood {
        getInstance(instanceId).addCounts(counts);
    }

    public static void native_getCounts(long instanceId, long[] counts, int state) {
        getInstance(instanceId).getValues(counts, state);
    public static boolean native_getCounts(long instanceId, long[] counts, int state) {
        return getInstance(instanceId).getValues(counts, state);
    }

    public static void native_reset(long instanceId) {
+17 −8
Original line number Diff line number Diff line
@@ -116,17 +116,26 @@ static void native_reset(jlong nativePtr) {
    counter->reset();
}

static void native_getCounts(JNIEnv *env, jclass, jlong nativePtr, jlongArray values, jint state) {
static bool native_getCounts(JNIEnv *env, jclass, jlong nativePtr, jlongArray values, jint state) {
    auto *counter = reinterpret_cast<LongArrayMultiStateCounter *>(nativePtr);
    ScopedLongArrayRW scopedArray(env, values);
    auto *data = counter->getCount(state).data();
    auto size = env->GetArrayLength(values);
    auto *outData = scopedArray.get();
    if (data == nullptr) {
        memset(outData, 0, size * sizeof(uint64_t));
    } else {
        memcpy(outData, data, size * sizeof(uint64_t));
        return false;
    }
    auto size = env->GetArrayLength(values);
    bool allZeros = true;
    for (int i = 0; i < size; i++) {
        if (data[i]) {
            allZeros = false;
            break;
        }
    }
    if (allZeros) {
        return false;
    }
    ScopedLongArrayRW scopedArray(env, values);
    memcpy(scopedArray.get(), data, size * sizeof(uint64_t));
    return true;
}

static jobject native_toString(JNIEnv *env, jclass, jlong nativePtr) {
@@ -255,7 +264,7 @@ static const JNINativeMethod g_LongArrayMultiStateCounter_methods[] = {
        // @CriticalNative
        {"native_reset", "(J)V", (void *)native_reset},
        // @FastNative
        {"native_getCounts", "(J[JI)V", (void *)native_getCounts},
        {"native_getCounts", "(J[JI)Z", (void *)native_getCounts},
        // @FastNative
        {"native_toString", "(J)Ljava/lang/String;", (void *)native_toString},
        // @FastNative
+2 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import android.annotation.SuppressLint;
import android.platform.test.annotations.IgnoreUnderRavenwood;
import android.platform.test.ravenwood.RavenwoodRule;
import android.util.SparseArray;
@@ -287,6 +288,7 @@ public class KernelSingleUidTimeReaderTest {
                0, lastUidCpuTimes.size());
    }

    @SuppressLint("CheckResult")
    @Test
    public void testAddDeltaFromBpf() {
        LongArrayMultiStateCounter counter = new LongArrayMultiStateCounter(2, 5);
+2 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat;

import static org.junit.Assert.assertThrows;

import android.annotation.SuppressLint;
import android.os.BadParcelableException;
import android.os.Parcel;
import android.platform.test.ravenwood.RavenwoodRule;
@@ -176,6 +177,7 @@ public class LongArrayMultiStateCounterTest {
        assertCounts(newCounter, 0, new long[]{116, 232, 364, 528});
    }

    @SuppressLint("CheckResult")
    private void assertCounts(LongArrayMultiStateCounter counter, int state, long[] expected) {
        long[] counts = new long[expected.length];
        counter.getCounts(counts, state);
Loading