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

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

Add LongArrayMultiStateCounter.combineValues

This method combines values into a smaller array
by using an index map.

Bug: 244623253
Test: atest com.android.internal.os.LongArrayMultiStateCounterTest
Change-Id: Ic35d30cc1f8765cd4e21366943da8291355a0047
parent 955425bd
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -98,6 +98,18 @@ public final class LongArrayMultiStateCounter implements Parcelable {
            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];
@@ -116,6 +128,10 @@ public final class LongArrayMultiStateCounter implements Parcelable {

        @FastNative
        private native void native_getValues(long nativeObject, long[] array);

        @FastNative
        private native boolean native_combineValues(long nativeObject, long[] array,
                int[] indexMap);
    }

    private static final NativeAllocationRegistry sRegistry =
+34 −0
Original line number Diff line number Diff line
@@ -244,6 +244,38 @@ static void native_getValues_LongArrayContainer(JNIEnv *env, jobject self, jlong
    std::copy(vector->data(), vector->data() + vector->size(), scopedArray.get());
}

static jboolean native_combineValues_LongArrayContainer(JNIEnv *env, jobject self, jlong nativePtr,
                                                        jlongArray jarray, jintArray jindexMap) {
    std::vector<uint64_t> *vector = reinterpret_cast<std::vector<uint64_t> *>(nativePtr);
    ScopedLongArrayRW scopedArray(env, jarray);
    ScopedIntArrayRO scopedIndexMap(env, jindexMap);

    const uint64_t *data = vector->data();
    uint64_t *array = reinterpret_cast<uint64_t *>(scopedArray.get());
    const uint8_t size = scopedArray.size();

    for (int i = 0; i < size; i++) {
        array[i] = 0;
    }

    bool nonZero = false;
    for (int i = 0; i < vector->size(); i++) {
        jint index = scopedIndexMap[i];
        if (index < 0 || index >= size) {
            jniThrowExceptionFmt(env, "java/lang/IndexOutOfBoundsException",
                                 "Index %d is out of bounds: [0, %d]", index, size - 1);
            return false;
        }

        if (data[i] != 0L) {
            array[index] += data[i];
            nonZero = true;
        }
    }

    return nonZero;
}

static const JNINativeMethod g_LongArrayContainer_methods[] = {
        // @CriticalNative
        {"native_init", "(I)J", (void *)native_init_LongArrayContainer},
@@ -253,6 +285,8 @@ static const JNINativeMethod g_LongArrayContainer_methods[] = {
        {"native_setValues", "(J[J)V", (void *)native_setValues_LongArrayContainer},
        // @FastNative
        {"native_getValues", "(J[J)V", (void *)native_getValues_LongArrayContainer},
        // @FastNative
        {"native_combineValues", "(J[J[I)Z", (void *)native_combineValues_LongArrayContainer},
};

int register_com_android_internal_os_LongArrayMultiStateCounter(JNIEnv *env) {
+29 −0
Original line number Diff line number Diff line
@@ -161,4 +161,33 @@ public class LongArrayMultiStateCounterTest {
        assertThrows(RuntimeException.class,
                () -> LongArrayMultiStateCounter.CREATOR.createFromParcel(parcel));
    }

    @Test
    public void combineValues() {
        long[] values = new long[] {0, 1, 2, 3, 42};
        LongArrayMultiStateCounter.LongArrayContainer container =
                new LongArrayMultiStateCounter.LongArrayContainer(values.length);
        container.setValues(values);

        long[] out = new long[3];
        int[] indexes = {2, 1, 1, 0, 0};
        boolean nonZero = container.combineValues(out, indexes);
        assertThat(nonZero).isTrue();
        assertThat(out).isEqualTo(new long[]{45, 3, 0});

        // All zeros
        container.setValues(new long[]{0, 0, 0, 0, 0});
        nonZero = container.combineValues(out, indexes);
        assertThat(nonZero).isFalse();
        assertThat(out).isEqualTo(new long[]{0, 0, 0});

        // Index out of range
        IndexOutOfBoundsException e1 = assertThrows(
                IndexOutOfBoundsException.class,
                () -> container.combineValues(out, new int[]{0, 1, -1, 0, 0}));
        assertThat(e1.getMessage()).isEqualTo("Index -1 is out of bounds: [0, 2]");
        IndexOutOfBoundsException e2 = assertThrows(IndexOutOfBoundsException.class,
                () -> container.combineValues(out, new int[]{0, 1, 4, 0, 0}));
        assertThat(e2.getMessage()).isEqualTo("Index 4 is out of bounds: [0, 2]");
    }
}