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

Commit ac5cbb5e authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add LongArrayMultiStateCounter.combineValues"

parents 31d82cf3 bb76e0fe
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]");
    }
}