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

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

Merge "Fix StatsEvent memory usage for pulled events"

parents 88704f0b 9e829804
Loading
Loading
Loading
Loading
+58 −8
Original line number Diff line number Diff line
@@ -31,14 +31,23 @@ import com.android.internal.annotations.VisibleForTesting;
 *
 * <p>Usage:</p>
 * <pre>
 *      // Pushed event
 *      StatsEvent statsEvent = StatsEvent.newBuilder()
 *          .setAtomId(atomId)
 *          .writeBoolean(false)
 *          .writeString("annotated String field")
 *          .addBooleanAnnotation(annotationId, true)
 *          .usePooledBuffer()
 *          .build();
 *
 *      StatsLog.write(statsEvent);
 *
 *      // Pulled event
 *      StatsEvent statsEvent = StatsEvent.newBuilder()
 *          .setAtomId(atomId)
 *          .writeBoolean(false)
 *          .writeString("annotated String field")
 *          .addBooleanAnnotation(annotationId, true)
 *          .build();
 * </pre>
 * @hide
 **/
@@ -210,12 +219,15 @@ public final class StatsEvent {
    private static final int MAX_PAYLOAD_SIZE = LOGGER_ENTRY_MAX_PAYLOAD - 4;

    private final int mAtomId;
    private final Buffer mBuffer;
    private final byte[] mPayload;
    private Buffer mBuffer;
    private final int mNumBytes;

    private StatsEvent(final int atomId, @NonNull final Buffer buffer, final int numBytes) {
    private StatsEvent(final int atomId, @Nullable final Buffer buffer,
            @NonNull final byte[] payload, final int numBytes) {
        mAtomId = atomId;
        mBuffer = buffer;
        mPayload = payload;
        mNumBytes = numBytes;
    }

@@ -243,7 +255,7 @@ public final class StatsEvent {
     **/
    @NonNull
    public byte[] getBytes() {
        return mBuffer.getBytes();
        return mPayload;
    }

    /**
@@ -256,10 +268,14 @@ public final class StatsEvent {
    }

    /**
     * Recycle this StatsEvent object.
     * Recycle resources used by this StatsEvent object.
     * No actions should be taken on this StatsEvent after release() is called.
     **/
    public void release() {
        if (mBuffer != null) {
            mBuffer.release();
            mBuffer = null;
        }
    }

    /**
@@ -280,7 +296,18 @@ public final class StatsEvent {
     *         optional string field3 = 3 [(annotation1) = true];
     *     }
     *
     *     // StatsEvent construction.
     *     // StatsEvent construction for pushed event.
     *     StatsEvent.newBuilder()
     *     StatsEvent statsEvent = StatsEvent.newBuilder()
     *         .setAtomId(atomId)
     *         .writeInt(3) // field1
     *         .writeLong(8L) // field2
     *         .writeString("foo") // field 3
     *         .addBooleanAnnotation(annotation1Id, true)
     *         .usePooledBuffer()
     *         .build();
     *
     *     // StatsEvent construction for pulled event.
     *     StatsEvent.newBuilder()
     *     StatsEvent statsEvent = StatsEvent.newBuilder()
     *         .setAtomId(atomId)
@@ -306,6 +333,7 @@ public final class StatsEvent {
        private byte mLastType;
        private int mNumElements;
        private int mErrorMask;
        private boolean mUsePooledBuffer = false;

        private Builder(final Buffer buffer) {
            mBuffer = buffer;
@@ -568,6 +596,17 @@ public final class StatsEvent {
            return this;
        }

        /**
         * Indicates to reuse Buffer's byte array as the underlying payload in StatsEvent.
         * This should be called for pushed events to reduce memory allocations and garbage
         * collections.
         **/
        @NonNull
        public Builder usePooledBuffer() {
            mUsePooledBuffer = true;
            return this;
        }

        /**
         * Builds a StatsEvent object with values entered in this Builder.
         **/
@@ -599,7 +638,18 @@ public final class StatsEvent {
                size = mPos;
            }

            return new StatsEvent(mAtomId, mBuffer, size);
            if (mUsePooledBuffer) {
                return new StatsEvent(mAtomId, mBuffer, mBuffer.getBytes(), size);
            } else {
                // Create a copy of the buffer with the required number of bytes.
                final byte[] payload = new byte[size];
                System.arraycopy(mBuffer.getBytes(), 0, payload, 0, size);

                // Return Buffer instance to the pool.
                mBuffer.release();

                return new StatsEvent(mAtomId, null, payload, size);
            }
        }

        private void writeTypeId(final byte typeId) {
+3 −0
Original line number Diff line number Diff line
@@ -248,12 +248,15 @@ public final class StatsLog extends StatsLogInternal {

    /**
     * Write an event to stats log using the raw format encapsulated in StatsEvent.
     * After writing to stats log, release() is called on the StatsEvent object.
     * No further action should be taken on the StatsEvent object following this call.
     *
     * @param statsEvent    The StatsEvent object containing the encoded buffer of data to write.
     * @hide
     */
    public static void write(@NonNull final StatsEvent statsEvent) {
        writeImpl(statsEvent.getBytes(), statsEvent.getNumBytes(), statsEvent.getAtomId());
        statsEvent.release();
    }

    private static void enforceDumpCallingPermission(Context context) {
+6 −1
Original line number Diff line number Diff line
@@ -44,7 +44,7 @@ public class StatsEventTest {
    @Test
    public void testNoFields() {
        final long minTimestamp = SystemClock.elapsedRealtimeNanos();
        final StatsEvent statsEvent = StatsEvent.newBuilder().build();
        final StatsEvent statsEvent = StatsEvent.newBuilder().usePooledBuffer().build();
        final long maxTimestamp = SystemClock.elapsedRealtimeNanos();

        final int expectedAtomId = 0;
@@ -99,6 +99,7 @@ public class StatsEventTest {
                .writeBoolean(field2)
                .writeInt(field3)
                .writeInt(field4)
                .usePooledBuffer()
                .build();
        final long maxTimestamp = SystemClock.elapsedRealtimeNanos();

@@ -167,6 +168,7 @@ public class StatsEventTest {
                .writeString(field1)
                .writeFloat(field2)
                .writeByteArray(field3)
                .usePooledBuffer()
                .build();
        final long maxTimestamp = SystemClock.elapsedRealtimeNanos();

@@ -230,6 +232,7 @@ public class StatsEventTest {
                .setAtomId(expectedAtomId)
                .writeAttributionChain(uids, tags)
                .writeLong(field2)
                .usePooledBuffer()
                .build();
        final long maxTimestamp = SystemClock.elapsedRealtimeNanos();

@@ -299,6 +302,7 @@ public class StatsEventTest {
        final StatsEvent statsEvent = StatsEvent.newBuilder()
                .setAtomId(expectedAtomId)
                .writeKeyValuePairs(intMap, longMap, stringMap, floatMap)
                .usePooledBuffer()
                .build();
        final long maxTimestamp = SystemClock.elapsedRealtimeNanos();

@@ -392,6 +396,7 @@ public class StatsEventTest {
                .addBooleanAnnotation(field1AnnotationId, field1AnnotationValue)
                .writeBoolean(field2)
                .addIntAnnotation(field2AnnotationId, field2AnnotationValue)
                .usePooledBuffer()
                .build();
        final long maxTimestamp = SystemClock.elapsedRealtimeNanos();

+1 −0
Original line number Diff line number Diff line
@@ -189,6 +189,7 @@ static int write_java_methods(
        }

        fprintf(out, "\n");
        fprintf(out, "%s        builder.usePooledBuffer();\n", indent.c_str());
        fprintf(out, "%s        StatsLog.write(builder.build());\n", indent.c_str());

        // Add support for writing using Q schema if this is not the default module.