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

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

Make LongArrayMultiStateCounter parcelable

Bug: 197162116
Test: atest FrameworksCoreTests:LongArrayMultiStateCounterTest
      atest CorePerfTests:LongArrayMultiStateCounterPerfTest

Change-Id: Ibc94620f2f106695fa7f17fc0737496f0e32ba48
parent 37b480c7
Loading
Loading
Loading
Loading
+27 −27
Original line number Diff line number Diff line
@@ -37,15 +37,15 @@ public class LongArrayMultiStateCounterPerfTest {

    /**
     * A complete line-for-line reimplementation of
     * {@link }com.android.internal.os.CpuTimeInFreqMultiStateCounter}, only in Java instead of
     * {@link com.android.internal.os.LongArrayMultiStateCounter}, only in Java instead of
     * native.
     */
    private static class TestLongArrayMultiStateCounter {
        private final int mStateCount;
        private final int mArrayLength;
        private int mCurrentState;
        private long mLastStateChangeTimestampMs;
        private long mLastUpdateTimestampMs;
        private long mLastStateChangeTimestampMs = -1;
        private long mLastUpdateTimestampMs = -1;

        private static class State {
            private long mTimeInStateSinceUpdate;
@@ -56,13 +56,9 @@ public class LongArrayMultiStateCounterPerfTest {
        private final long[] mLastTimeInFreq;
        private final long[] mDelta;

        TestLongArrayMultiStateCounter(int stateCount, int arrayLength, int initialState,
                long timestampMs) {
        TestLongArrayMultiStateCounter(int stateCount, int arrayLength) {
            mStateCount = stateCount;
            mArrayLength = arrayLength;
            mCurrentState = initialState;
            mLastStateChangeTimestampMs = timestampMs;
            mLastUpdateTimestampMs = timestampMs;
            mStates = new State[stateCount];
            for (int i = 0; i < mStateCount; i++) {
                mStates[i] = new State();
@@ -73,6 +69,7 @@ public class LongArrayMultiStateCounterPerfTest {
        }

        public void setState(int state, long timestampMs) {
            if (mLastStateChangeTimestampMs > 0) {
                if (timestampMs >= mLastStateChangeTimestampMs) {
                    mStates[mCurrentState].mTimeInStateSinceUpdate +=
                            timestampMs - mLastStateChangeTimestampMs;
@@ -81,6 +78,7 @@ public class LongArrayMultiStateCounterPerfTest {
                        mStates[i].mTimeInStateSinceUpdate = 0;
                    }
                }
            }
            mCurrentState = state;
            mLastStateChangeTimestampMs = timestampMs;
        }
@@ -88,6 +86,7 @@ public class LongArrayMultiStateCounterPerfTest {
        public void updateValue(long[] timeInFreq, long timestampMs) {
            setState(mCurrentState, timestampMs);

            if (mLastUpdateTimestampMs >= 0) {
                if (timestampMs > mLastUpdateTimestampMs) {
                    if (delta(mLastTimeInFreq, timeInFreq, mDelta)) {
                        long timeSinceUpdate = timestampMs - mLastUpdateTimestampMs;
@@ -104,6 +103,7 @@ public class LongArrayMultiStateCounterPerfTest {
                } else if (timestampMs < mLastUpdateTimestampMs) {
                    throw new RuntimeException();
                }
            }
            System.arraycopy(timeInFreq, 0, mLastTimeInFreq, 0, mArrayLength);
            mLastUpdateTimestampMs = timestampMs;
        }
@@ -142,7 +142,7 @@ public class LongArrayMultiStateCounterPerfTest {
    @Test
    public void javaImplementation() {
        TestLongArrayMultiStateCounter counter =
                new TestLongArrayMultiStateCounter(2, 4, 0, 1000);
                new TestLongArrayMultiStateCounter(2, 4);
        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
        long time = 1000;
        long[] timeInFreq = {100, 200, 300, 400};
@@ -156,7 +156,7 @@ public class LongArrayMultiStateCounterPerfTest {

    @Test
    public void nativeImplementation() {
        LongArrayMultiStateCounter counter = new LongArrayMultiStateCounter(2, 4, 0, 1000);
        LongArrayMultiStateCounter counter = new LongArrayMultiStateCounter(2, 4);
        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
        long time = 1000;
        LongArrayMultiStateCounter.LongArrayContainer timeInFreq =
+54 −6
Original line number Diff line number Diff line
@@ -16,6 +16,11 @@

package com.android.internal.os;

import android.os.Parcel;
import android.os.Parcelable;

import com.android.internal.util.Preconditions;

import dalvik.annotation.optimization.CriticalNative;
import dalvik.annotation.optimization.FastNative;

@@ -47,7 +52,7 @@ import libcore.util.NativeAllocationRegistry;
 *
 * @hide
 */
public class LongArrayMultiStateCounter {
public final class LongArrayMultiStateCounter implements Parcelable {

    /**
     * Container for a native equivalent of a long[].
@@ -112,14 +117,22 @@ public class LongArrayMultiStateCounter {
    // methods.
    final long mNativeObject;

    public LongArrayMultiStateCounter(int stateCount, int arrayLength, int initialState,
            long timestampMs) {
    public LongArrayMultiStateCounter(int stateCount, int arrayLength) {
        Preconditions.checkArgumentPositive(stateCount, "stateCount must be greater than 0");
        mStateCount = stateCount;
        mLength = arrayLength;
        mNativeObject = native_init(stateCount, arrayLength, initialState, timestampMs);
        mNativeObject = native_init(stateCount, arrayLength);
        sRegistry.registerNativeAllocation(this, mNativeObject);
    }

    private LongArrayMultiStateCounter(Parcel in) {
        mNativeObject = native_initFromParcel(in);
        sRegistry.registerNativeAllocation(this, mNativeObject);

        mStateCount = native_getStateCount(mNativeObject);
        mLength = native_getArrayLength(mNativeObject);
    }

    /**
     * Sets the current state to the supplied value.
     */
@@ -161,9 +174,32 @@ public class LongArrayMultiStateCounter {
        return native_toString(mNativeObject);
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        native_writeToParcel(mNativeObject, dest, flags);
    }

    @Override
    public int describeContents() {
        return 0;
    }

    public static final Creator<LongArrayMultiStateCounter> CREATOR =
            new Creator<LongArrayMultiStateCounter>() {
                @Override
                public LongArrayMultiStateCounter createFromParcel(Parcel in) {
                    return new LongArrayMultiStateCounter(in);
                }

                @Override
                public LongArrayMultiStateCounter[] newArray(int size) {
                    return new LongArrayMultiStateCounter[size];
                }
            };


    @CriticalNative
    private static native long native_init(int stateCount, int arrayLength, int initialState,
            long timestampMs);
    private static native long native_init(int stateCount, int arrayLength);

    @CriticalNative
    private static native long native_getReleaseFunc();
@@ -181,4 +217,16 @@ public class LongArrayMultiStateCounter {

    @FastNative
    private native String native_toString(long nativeObject);

    @FastNative
    private native void native_writeToParcel(long nativeObject, Parcel dest, int flags);

    @FastNative
    private static native long native_initFromParcel(Parcel parcel);

    @CriticalNative
    private static native int native_getStateCount(long nativeObject);

    @CriticalNative
    private static native int native_getArrayLength(long nativeObject);
}
+1 −0
Original line number Diff line number Diff line
@@ -263,6 +263,7 @@ cc_library_shared {
                "libdebuggerd_client",
                "libutils",
                "libbinder",
                "libbinder_ndk",
                "libui",
                "libgraphicsenv",
                "libgui",
+99 −4
Original line number Diff line number Diff line
@@ -14,17 +14,22 @@
 * limitations under the License.
 */

#include <android/binder_parcel.h>
#include <android/binder_parcel_jni.h>
#include <android/binder_parcel_utils.h>
#include <android_runtime/Log.h>
#include <nativehelper/ScopedPrimitiveArray.h>

#include <cstring>

#include "LongArrayMultiStateCounter.h"
#include "core_jni_helpers.h"

namespace android {

static jlong native_init(jint stateCount, jint arrayLength, jint initialState, jlong timestamp) {
static jlong native_init(jint stateCount, jint arrayLength) {
    battery::LongArrayMultiStateCounter *counter =
            new battery::LongArrayMultiStateCounter(stateCount, initialState,
                                                    std::vector<uint64_t>(arrayLength), timestamp);
            new battery::LongArrayMultiStateCounter(stateCount, std::vector<uint64_t>(arrayLength));
    return reinterpret_cast<jlong>(counter);
}

@@ -69,13 +74,95 @@ static jobject native_toString(JNIEnv *env, jobject self, jlong nativePtr) {
    return env->NewStringUTF(counter->toString().c_str());
}

static void throwWriteRE(JNIEnv *env, binder_status_t status) {
    ALOGE("Could not write LongArrayMultiStateCounter to Parcel, status = %d", status);
    jniThrowRuntimeException(env, "Could not write LongArrayMultiStateCounter to Parcel");
}

#define THROW_ON_WRITE_ERROR(expr)     \
    {                                  \
        binder_status_t status = expr; \
        if (status != STATUS_OK) {     \
            throwWriteRE(env, status); \
        }                              \
    }

static void native_writeToParcel(JNIEnv *env, jobject self, jlong nativePtr, jobject jParcel,
                                 jint flags) {
    battery::LongArrayMultiStateCounter *counter =
            reinterpret_cast<battery::LongArrayMultiStateCounter *>(nativePtr);
    AParcel *parcel = AParcel_fromJavaParcel(env, jParcel);

    uint16_t stateCount = counter->getStateCount();
    THROW_ON_WRITE_ERROR(AParcel_writeInt32(parcel, stateCount));

    // LongArrayMultiStateCounter has at least state 0
    const std::vector<uint64_t> &anyState = counter->getCount(0);
    THROW_ON_WRITE_ERROR(AParcel_writeInt32(parcel, anyState.size()));

    for (battery::state_t state = 0; state < stateCount; state++) {
        THROW_ON_WRITE_ERROR(ndk::AParcel_writeVector(parcel, counter->getCount(state)));
    }
}

static void throwReadRE(JNIEnv *env, binder_status_t status) {
    ALOGE("Could not read LongArrayMultiStateCounter from Parcel, status = %d", status);
    jniThrowRuntimeException(env, "Could not read LongArrayMultiStateCounter from Parcel");
}

#define THROW_ON_READ_ERROR(expr)      \
    {                                  \
        binder_status_t status = expr; \
        if (status != STATUS_OK) {     \
            throwReadRE(env, status);  \
        }                              \
    }

static jlong native_initFromParcel(JNIEnv *env, jclass theClass, jobject jParcel) {
    AParcel *parcel = AParcel_fromJavaParcel(env, jParcel);

    int32_t stateCount;
    THROW_ON_READ_ERROR(AParcel_readInt32(parcel, &stateCount));

    int32_t arrayLength;
    THROW_ON_READ_ERROR(AParcel_readInt32(parcel, &arrayLength));

    battery::LongArrayMultiStateCounter *counter =
            new battery::LongArrayMultiStateCounter(stateCount, std::vector<uint64_t>(arrayLength));

    std::vector<uint64_t> value;
    value.reserve(arrayLength);

    for (battery::state_t state = 0; state < stateCount; state++) {
        THROW_ON_READ_ERROR(ndk::AParcel_readVector(parcel, &value));
        counter->setValue(state, value);
    }

    return reinterpret_cast<jlong>(counter);
}

static jint native_getStateCount(jlong nativePtr) {
    battery::LongArrayMultiStateCounter *counter =
            reinterpret_cast<battery::LongArrayMultiStateCounter *>(nativePtr);
    return counter->getStateCount();
}

static jint native_getArrayLength(jlong nativePtr) {
    battery::LongArrayMultiStateCounter *counter =
            reinterpret_cast<battery::LongArrayMultiStateCounter *>(nativePtr);

    // LongArrayMultiStateCounter has at least state 0
    const std::vector<uint64_t> &anyState = counter->getCount(0);
    return anyState.size();
}

static jlong native_init_LongArrayContainer(jint length) {
    return reinterpret_cast<jlong>(new std::vector<uint64_t>(length));
}

static const JNINativeMethod g_LongArrayMultiStateCounter_methods[] = {
        // @CriticalNative
        {"native_init", "(IIIJ)J", (void *)native_init},
        {"native_init", "(II)J", (void *)native_init},
        // @CriticalNative
        {"native_getReleaseFunc", "()J", (void *)native_getReleaseFunc},
        // @CriticalNative
@@ -86,6 +173,14 @@ static const JNINativeMethod g_LongArrayMultiStateCounter_methods[] = {
        {"native_getCounts", "(JJI)V", (void *)native_getCounts},
        // @FastNative
        {"native_toString", "(J)Ljava/lang/String;", (void *)native_toString},
        // @FastNative
        {"native_writeToParcel", "(JLandroid/os/Parcel;I)V", (void *)native_writeToParcel},
        // @FastNative
        {"native_initFromParcel", "(Landroid/os/Parcel;)J", (void *)native_initFromParcel},
        // @CriticalNative
        {"native_getStateCount", "(J)I", (void *)native_getStateCount},
        // @CriticalNative
        {"native_getArrayLength", "(J)I", (void *)native_getArrayLength},
};

/////////////////////// LongArrayMultiStateCounter.LongArrayContainer ////////////////////////
+6 −2
Original line number Diff line number Diff line
@@ -282,7 +282,11 @@ public class KernelSingleUidTimeReaderTest {

    @Test
    public void testAddDeltaFromBpf() {
        LongArrayMultiStateCounter counter = new LongArrayMultiStateCounter(2, 5, 0, 0);
        LongArrayMultiStateCounter counter = new LongArrayMultiStateCounter(2, 5);
        counter.setState(0, 0);
        mInjector.setCpuTimeInStatePerClusterNs(new long[][]{{0, 0, 0}, {0, 0}});
        boolean success = mInjector.addDelta(TEST_UID, counter, 0);
        assertThat(success).isTrue();

        // Nanoseconds
        mInjector.setCpuTimeInStatePerClusterNs(
@@ -290,7 +294,7 @@ public class KernelSingleUidTimeReaderTest {
                        {1_000_000, 2_000_000, 3_000_000},
                        {4_000_000, 5_000_000}});

        boolean success = mInjector.addDelta(TEST_UID, counter, 2000);
        success = mInjector.addDelta(TEST_UID, counter, 2000);
        assertThat(success).isTrue();

        LongArrayMultiStateCounter.LongArrayContainer array =
Loading