diff options
author | 2024-10-22 14:51:17 -0700 | |
---|---|---|
committer | 2024-10-22 15:29:39 -0700 | |
commit | b4f5f9e8ed86db9c775ce29fe216d9dc4cfdbb97 (patch) | |
tree | 08e38b51de7971996c78115fae84d5312b0848f9 /ravenwood/runtime-helper-src | |
parent | 0eb0be0ff5abdb611b6b2caddcc59d11e866516c (diff) |
Support StatsD Java API on Ravenwood (f/b)
For now, no actual logging happens. We just make the Java APIs
available.
Flag: EXEMPT host test change only
Bug: 375042206
Test: $ANDROID_BUILD_TOP/frameworks/base/ravenwood/scripts/run-ravenwood-tests.sh
Change-Id: Id60fe9009852e01a7a40d99a2cd205cec868ae90
Diffstat (limited to 'ravenwood/runtime-helper-src')
-rw-r--r-- | ravenwood/runtime-helper-src/framework/android/util/StatsEvent.java | 1035 | ||||
-rw-r--r-- | ravenwood/runtime-helper-src/framework/android/util/StatsLog.java | 478 |
2 files changed, 0 insertions, 1513 deletions
diff --git a/ravenwood/runtime-helper-src/framework/android/util/StatsEvent.java b/ravenwood/runtime-helper-src/framework/android/util/StatsEvent.java deleted file mode 100644 index 1e3b3fcd733f..000000000000 --- a/ravenwood/runtime-helper-src/framework/android/util/StatsEvent.java +++ /dev/null @@ -1,1035 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.util; - -// [ravenwood] This is an exact copy from StatsD, until we make StatsD available on Ravenwood. - -import static java.nio.charset.StandardCharsets.UTF_8; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.SystemApi; -import android.os.Build; -import android.os.SystemClock; - -import androidx.annotation.RequiresApi; - -import com.android.internal.annotations.GuardedBy; -import com.android.internal.annotations.VisibleForTesting; - -import java.nio.ByteBuffer; -import java.util.Arrays; - -/** - * StatsEvent builds and stores the buffer sent over the statsd socket. - * This class defines and encapsulates the socket protocol. - * - * <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 - **/ -@SystemApi -public final class StatsEvent { - // Type Ids. - /** - * @hide - **/ - @VisibleForTesting - public static final byte TYPE_INT = 0x00; - - /** - * @hide - **/ - @VisibleForTesting - public static final byte TYPE_LONG = 0x01; - - /** - * @hide - **/ - @VisibleForTesting - public static final byte TYPE_STRING = 0x02; - - /** - * @hide - **/ - @VisibleForTesting - public static final byte TYPE_LIST = 0x03; - - /** - * @hide - **/ - @VisibleForTesting - public static final byte TYPE_FLOAT = 0x04; - - /** - * @hide - **/ - @VisibleForTesting - public static final byte TYPE_BOOLEAN = 0x05; - - /** - * @hide - **/ - @VisibleForTesting - public static final byte TYPE_BYTE_ARRAY = 0x06; - - /** - * @hide - **/ - @VisibleForTesting - public static final byte TYPE_OBJECT = 0x07; - - /** - * @hide - **/ - @VisibleForTesting - public static final byte TYPE_KEY_VALUE_PAIRS = 0x08; - - /** - * @hide - **/ - @VisibleForTesting - public static final byte TYPE_ATTRIBUTION_CHAIN = 0x09; - - /** - * @hide - **/ - @VisibleForTesting - public static final byte TYPE_ERRORS = 0x0F; - - // Error flags. - /** - * @hide - **/ - @VisibleForTesting - public static final int ERROR_NO_TIMESTAMP = 0x1; - - /** - * @hide - **/ - @VisibleForTesting - public static final int ERROR_NO_ATOM_ID = 0x2; - - /** - * @hide - **/ - @VisibleForTesting - public static final int ERROR_OVERFLOW = 0x4; - - /** - * @hide - **/ - @VisibleForTesting - public static final int ERROR_ATTRIBUTION_CHAIN_TOO_LONG = 0x8; - - /** - * @hide - **/ - @VisibleForTesting - public static final int ERROR_TOO_MANY_KEY_VALUE_PAIRS = 0x10; - - /** - * @hide - **/ - @VisibleForTesting - public static final int ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD = 0x20; - - /** - * @hide - **/ - @VisibleForTesting - public static final int ERROR_INVALID_ANNOTATION_ID = 0x40; - - /** - * @hide - **/ - @VisibleForTesting - public static final int ERROR_ANNOTATION_ID_TOO_LARGE = 0x80; - - /** - * @hide - **/ - @VisibleForTesting - public static final int ERROR_TOO_MANY_ANNOTATIONS = 0x100; - - /** - * @hide - **/ - @VisibleForTesting - public static final int ERROR_TOO_MANY_FIELDS = 0x200; - - /** - * @hide - **/ - @VisibleForTesting - public static final int ERROR_ATTRIBUTION_UIDS_TAGS_SIZES_NOT_EQUAL = 0x1000; - - /** - * @hide - **/ - @VisibleForTesting - public static final int ERROR_ATOM_ID_INVALID_POSITION = 0x2000; - - /** - * @hide - **/ - @VisibleForTesting public static final int ERROR_LIST_TOO_LONG = 0x4000; - - // Size limits. - - /** - * @hide - **/ - @VisibleForTesting - public static final int MAX_ANNOTATION_COUNT = 15; - - /** - * @hide - **/ - @VisibleForTesting - public static final int MAX_ATTRIBUTION_NODES = 127; - - /** - * @hide - **/ - @VisibleForTesting - public static final int MAX_NUM_ELEMENTS = 127; - - /** - * @hide - **/ - @VisibleForTesting - public static final int MAX_KEY_VALUE_PAIRS = 127; - - private static final int LOGGER_ENTRY_MAX_PAYLOAD = 4068; - - // Max payload size is 4 bytes less as 4 bytes are reserved for statsEventTag. - // See android_util_StatsLog.cpp. - private static final int MAX_PUSH_PAYLOAD_SIZE = LOGGER_ENTRY_MAX_PAYLOAD - 4; - - private static final int MAX_PULL_PAYLOAD_SIZE = 50 * 1024; // 50 KB - - private final int mAtomId; - private final byte[] mPayload; - private Buffer mBuffer; - private final int mNumBytes; - - private StatsEvent(final int atomId, @Nullable final Buffer buffer, - @NonNull final byte[] payload, final int numBytes) { - mAtomId = atomId; - mBuffer = buffer; - mPayload = payload; - mNumBytes = numBytes; - } - - /** - * Returns a new StatsEvent.Builder for building StatsEvent object. - **/ - @NonNull - public static Builder newBuilder() { - return new Builder(Buffer.obtain()); - } - - /** - * Get the atom Id of the atom encoded in this StatsEvent object. - * - * @hide - **/ - public int getAtomId() { - return mAtomId; - } - - /** - * Get the byte array that contains the encoded payload that can be sent to statsd. - * - * @hide - **/ - @NonNull - public byte[] getBytes() { - return mPayload; - } - - /** - * Get the number of bytes used to encode the StatsEvent payload. - * - * @hide - **/ - public int getNumBytes() { - return mNumBytes; - } - - /** - * Recycle resources used by this StatsEvent object. - * No actions should be taken on this StatsEvent after release() is called. - * - * @hide - **/ - public void release() { - if (mBuffer != null) { - mBuffer.release(); - mBuffer = null; - } - } - - /** - * Builder for constructing a StatsEvent object. - * - * <p>This class defines and encapsulates the socket encoding for the - *buffer. The write methods must be called in the same order as the order of - *fields in the atom definition.</p> - * - * <p>setAtomId() must be called immediately after - *StatsEvent.newBuilder().</p> - * - * <p>Example:</p> - * <pre> - * // Atom definition. - * message MyAtom { - * optional int32 field1 = 1; - * optional int64 field2 = 2; - * optional string field3 = 3 [(annotation1) = true]; - * optional repeated int32 field4 = 4; - * } - * - * // 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) - * .writeIntArray({ 1, 2, 3 }); - * .usePooledBuffer() - * .build(); - * - * // StatsEvent construction for pulled event. - * StatsEvent.newBuilder() - * StatsEvent statsEvent = StatsEvent.newBuilder() - * .setAtomId(atomId) - * .writeInt(3) // field1 - * .writeLong(8L) // field2 - * .writeString("foo") // field 3 - * .addBooleanAnnotation(annotation1Id, true) - * .writeIntArray({ 1, 2, 3 }); - * .build(); - * </pre> - **/ - public static final class Builder { - // Fixed positions. - private static final int POS_NUM_ELEMENTS = 1; - private static final int POS_TIMESTAMP_NS = POS_NUM_ELEMENTS + Byte.BYTES; - private static final int POS_ATOM_ID = POS_TIMESTAMP_NS + Byte.BYTES + Long.BYTES; - - private final Buffer mBuffer; - private long mTimestampNs; - private int mAtomId; - private byte mCurrentAnnotationCount; - private int mPos; - private int mPosLastField; - private byte mLastType; - private int mNumElements; - private int mErrorMask; - private boolean mUsePooledBuffer = false; - - private Builder(final Buffer buffer) { - mBuffer = buffer; - mCurrentAnnotationCount = 0; - mAtomId = 0; - mTimestampNs = SystemClock.elapsedRealtimeNanos(); - mNumElements = 0; - - // Set mPos to 0 for writing TYPE_OBJECT at 0th position. - mPos = 0; - writeTypeId(TYPE_OBJECT); - - // Write timestamp. - mPos = POS_TIMESTAMP_NS; - writeLong(mTimestampNs); - } - - /** - * Sets the atom id for this StatsEvent. - * - * This should be called immediately after StatsEvent.newBuilder() - * and should only be called once. - * Not calling setAtomId will result in ERROR_NO_ATOM_ID. - * Calling setAtomId out of order will result in ERROR_ATOM_ID_INVALID_POSITION. - **/ - @NonNull - public Builder setAtomId(final int atomId) { - if (0 == mAtomId) { - mAtomId = atomId; - - if (1 == mNumElements) { // Only timestamp is written so far. - writeInt(atomId); - } else { - // setAtomId called out of order. - mErrorMask |= ERROR_ATOM_ID_INVALID_POSITION; - } - } - - return this; - } - - /** - * Write a boolean field to this StatsEvent. - **/ - @NonNull - public Builder writeBoolean(final boolean value) { - // Write boolean typeId byte followed by boolean byte representation. - writeTypeId(TYPE_BOOLEAN); - mPos += mBuffer.putBoolean(mPos, value); - mNumElements++; - return this; - } - - /** - * Write an integer field to this StatsEvent. - **/ - @NonNull - public Builder writeInt(final int value) { - // Write integer typeId byte followed by 4-byte representation of value. - writeTypeId(TYPE_INT); - mPos += mBuffer.putInt(mPos, value); - mNumElements++; - return this; - } - - /** - * Write a long field to this StatsEvent. - **/ - @NonNull - public Builder writeLong(final long value) { - // Write long typeId byte followed by 8-byte representation of value. - writeTypeId(TYPE_LONG); - mPos += mBuffer.putLong(mPos, value); - mNumElements++; - return this; - } - - /** - * Write a float field to this StatsEvent. - **/ - @NonNull - public Builder writeFloat(final float value) { - // Write float typeId byte followed by 4-byte representation of value. - writeTypeId(TYPE_FLOAT); - mPos += mBuffer.putFloat(mPos, value); - mNumElements++; - return this; - } - - /** - * Write a String field to this StatsEvent. - **/ - @NonNull - public Builder writeString(@NonNull final String value) { - // Write String typeId byte, followed by 4-byte representation of number of bytes - // in the UTF-8 encoding, followed by the actual UTF-8 byte encoding of value. - final byte[] valueBytes = stringToBytes(value); - writeByteArray(valueBytes, TYPE_STRING); - return this; - } - - /** - * Write a byte array field to this StatsEvent. - **/ - @NonNull - public Builder writeByteArray(@NonNull final byte[] value) { - // Write byte array typeId byte, followed by 4-byte representation of number of bytes - // in value, followed by the actual byte array. - writeByteArray(value, TYPE_BYTE_ARRAY); - return this; - } - - private void writeByteArray(@NonNull final byte[] value, final byte typeId) { - writeTypeId(typeId); - final int numBytes = value.length; - mPos += mBuffer.putInt(mPos, numBytes); - mPos += mBuffer.putByteArray(mPos, value); - mNumElements++; - } - - /** - * Write an attribution chain field to this StatsEvent. - * - * The sizes of uids and tags must be equal. The AttributionNode at position i is - * made up of uids[i] and tags[i]. - * - * @param uids array of uids in the attribution nodes. - * @param tags array of tags in the attribution nodes. - **/ - @NonNull - public Builder writeAttributionChain( - @NonNull final int[] uids, @NonNull final String[] tags) { - final byte numUids = (byte) uids.length; - final byte numTags = (byte) tags.length; - - if (numUids != numTags) { - mErrorMask |= ERROR_ATTRIBUTION_UIDS_TAGS_SIZES_NOT_EQUAL; - } else if (numUids > MAX_ATTRIBUTION_NODES) { - mErrorMask |= ERROR_ATTRIBUTION_CHAIN_TOO_LONG; - } else { - // Write attribution chain typeId byte, followed by 1-byte representation of - // number of attribution nodes, followed by encoding of each attribution node. - writeTypeId(TYPE_ATTRIBUTION_CHAIN); - mPos += mBuffer.putByte(mPos, numUids); - for (int i = 0; i < numUids; i++) { - // Each uid is encoded as 4-byte representation of its int value. - mPos += mBuffer.putInt(mPos, uids[i]); - - // Each tag is encoded as 4-byte representation of number of bytes in its - // UTF-8 encoding, followed by the actual UTF-8 bytes. - final byte[] tagBytes = stringToBytes(tags[i]); - mPos += mBuffer.putInt(mPos, tagBytes.length); - mPos += mBuffer.putByteArray(mPos, tagBytes); - } - mNumElements++; - } - return this; - } - - /** - * Write KeyValuePairsAtom entries to this StatsEvent. - * - * @param intMap Integer key-value pairs. - * @param longMap Long key-value pairs. - * @param stringMap String key-value pairs. - * @param floatMap Float key-value pairs. - **/ - @NonNull - public Builder writeKeyValuePairs( - @Nullable final SparseIntArray intMap, - @Nullable final SparseLongArray longMap, - @Nullable final SparseArray<String> stringMap, - @Nullable final SparseArray<Float> floatMap) { - final int intMapSize = null == intMap ? 0 : intMap.size(); - final int longMapSize = null == longMap ? 0 : longMap.size(); - final int stringMapSize = null == stringMap ? 0 : stringMap.size(); - final int floatMapSize = null == floatMap ? 0 : floatMap.size(); - final int totalCount = intMapSize + longMapSize + stringMapSize + floatMapSize; - - if (totalCount > MAX_KEY_VALUE_PAIRS) { - mErrorMask |= ERROR_TOO_MANY_KEY_VALUE_PAIRS; - } else { - writeTypeId(TYPE_KEY_VALUE_PAIRS); - mPos += mBuffer.putByte(mPos, (byte) totalCount); - - for (int i = 0; i < intMapSize; i++) { - final int key = intMap.keyAt(i); - final int value = intMap.valueAt(i); - mPos += mBuffer.putInt(mPos, key); - writeTypeId(TYPE_INT); - mPos += mBuffer.putInt(mPos, value); - } - - for (int i = 0; i < longMapSize; i++) { - final int key = longMap.keyAt(i); - final long value = longMap.valueAt(i); - mPos += mBuffer.putInt(mPos, key); - writeTypeId(TYPE_LONG); - mPos += mBuffer.putLong(mPos, value); - } - - for (int i = 0; i < stringMapSize; i++) { - final int key = stringMap.keyAt(i); - final String value = stringMap.valueAt(i); - mPos += mBuffer.putInt(mPos, key); - writeTypeId(TYPE_STRING); - final byte[] valueBytes = stringToBytes(value); - mPos += mBuffer.putInt(mPos, valueBytes.length); - mPos += mBuffer.putByteArray(mPos, valueBytes); - } - - for (int i = 0; i < floatMapSize; i++) { - final int key = floatMap.keyAt(i); - final float value = floatMap.valueAt(i); - mPos += mBuffer.putInt(mPos, key); - writeTypeId(TYPE_FLOAT); - mPos += mBuffer.putFloat(mPos, value); - } - - mNumElements++; - } - - return this; - } - - /** - * Write a repeated boolean field to this StatsEvent. - * - * The list size must not exceed 127. Otherwise, the array isn't written - * to the StatsEvent and ERROR_LIST_TOO_LONG is appended to the - * StatsEvent errors field. - * - * @param elements array of booleans. - **/ - @RequiresApi(Build.VERSION_CODES.TIRAMISU) - @NonNull - public Builder writeBooleanArray(@NonNull final boolean[] elements) { - final byte numElements = (byte)elements.length; - - if (writeArrayInfo(numElements, TYPE_BOOLEAN)) { - // Write encoding of each element. - for (int i = 0; i < numElements; i++) { - mPos += mBuffer.putBoolean(mPos, elements[i]); - } - mNumElements++; - } - return this; - } - - /** - * Write a repeated int field to this StatsEvent. - * - * The list size must not exceed 127. Otherwise, the array isn't written - * to the StatsEvent and ERROR_LIST_TOO_LONG is appended to the - * StatsEvent errors field. - * - * @param elements array of ints. - **/ - @RequiresApi(Build.VERSION_CODES.TIRAMISU) - @NonNull - public Builder writeIntArray(@NonNull final int[] elements) { - final byte numElements = (byte)elements.length; - - if (writeArrayInfo(numElements, TYPE_INT)) { - // Write encoding of each element. - for (int i = 0; i < numElements; i++) { - mPos += mBuffer.putInt(mPos, elements[i]); - } - mNumElements++; - } - return this; - } - - /** - * Write a repeated long field to this StatsEvent. - * - * The list size must not exceed 127. Otherwise, the array isn't written - * to the StatsEvent and ERROR_LIST_TOO_LONG is appended to the - * StatsEvent errors field. - * - * @param elements array of longs. - **/ - @RequiresApi(Build.VERSION_CODES.TIRAMISU) - @NonNull - public Builder writeLongArray(@NonNull final long[] elements) { - final byte numElements = (byte)elements.length; - - if (writeArrayInfo(numElements, TYPE_LONG)) { - // Write encoding of each element. - for (int i = 0; i < numElements; i++) { - mPos += mBuffer.putLong(mPos, elements[i]); - } - mNumElements++; - } - return this; - } - - /** - * Write a repeated float field to this StatsEvent. - * - * The list size must not exceed 127. Otherwise, the array isn't written - * to the StatsEvent and ERROR_LIST_TOO_LONG is appended to the - * StatsEvent errors field. - * - * @param elements array of floats. - **/ - @RequiresApi(Build.VERSION_CODES.TIRAMISU) - @NonNull - public Builder writeFloatArray(@NonNull final float[] elements) { - final byte numElements = (byte)elements.length; - - if (writeArrayInfo(numElements, TYPE_FLOAT)) { - // Write encoding of each element. - for (int i = 0; i < numElements; i++) { - mPos += mBuffer.putFloat(mPos, elements[i]); - } - mNumElements++; - } - return this; - } - - /** - * Write a repeated string field to this StatsEvent. - * - * The list size must not exceed 127. Otherwise, the array isn't written - * to the StatsEvent and ERROR_LIST_TOO_LONG is appended to the - * StatsEvent errors field. - * - * @param elements array of strings. - **/ - @RequiresApi(Build.VERSION_CODES.TIRAMISU) - @NonNull - public Builder writeStringArray(@NonNull final String[] elements) { - final byte numElements = (byte)elements.length; - - if (writeArrayInfo(numElements, TYPE_STRING)) { - // Write encoding of each element. - for (int i = 0; i < numElements; i++) { - final byte[] elementBytes = stringToBytes(elements[i]); - mPos += mBuffer.putInt(mPos, elementBytes.length); - mPos += mBuffer.putByteArray(mPos, elementBytes); - } - mNumElements++; - } - return this; - } - - /** - * Write a boolean annotation for the last field written. - **/ - @NonNull - public Builder addBooleanAnnotation( - final byte annotationId, final boolean value) { - // Ensure there's a field written to annotate. - if (mNumElements < 2) { - mErrorMask |= ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD; - } else if (mCurrentAnnotationCount >= MAX_ANNOTATION_COUNT) { - mErrorMask |= ERROR_TOO_MANY_ANNOTATIONS; - } else { - mPos += mBuffer.putByte(mPos, annotationId); - mPos += mBuffer.putByte(mPos, TYPE_BOOLEAN); - mPos += mBuffer.putBoolean(mPos, value); - mCurrentAnnotationCount++; - writeAnnotationCount(); - } - - return this; - } - - /** - * Write an integer annotation for the last field written. - **/ - @NonNull - public Builder addIntAnnotation(final byte annotationId, final int value) { - if (mNumElements < 2) { - mErrorMask |= ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD; - } else if (mCurrentAnnotationCount >= MAX_ANNOTATION_COUNT) { - mErrorMask |= ERROR_TOO_MANY_ANNOTATIONS; - } else { - mPos += mBuffer.putByte(mPos, annotationId); - mPos += mBuffer.putByte(mPos, TYPE_INT); - mPos += mBuffer.putInt(mPos, value); - mCurrentAnnotationCount++; - writeAnnotationCount(); - } - - 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; - mBuffer.setMaxSize(MAX_PUSH_PAYLOAD_SIZE, mPos); - return this; - } - - /** - * Builds a StatsEvent object with values entered in this Builder. - **/ - @NonNull - public StatsEvent build() { - if (0L == mTimestampNs) { - mErrorMask |= ERROR_NO_TIMESTAMP; - } - if (0 == mAtomId) { - mErrorMask |= ERROR_NO_ATOM_ID; - } - if (mBuffer.hasOverflowed()) { - mErrorMask |= ERROR_OVERFLOW; - } - if (mNumElements > MAX_NUM_ELEMENTS) { - mErrorMask |= ERROR_TOO_MANY_FIELDS; - } - - if (0 == mErrorMask) { - mBuffer.putByte(POS_NUM_ELEMENTS, (byte) mNumElements); - } else { - // Write atom id and error mask. Overwrite any annotations for atom Id. - mPos = POS_ATOM_ID; - mPos += mBuffer.putByte(mPos, TYPE_INT); - mPos += mBuffer.putInt(mPos, mAtomId); - mPos += mBuffer.putByte(mPos, TYPE_ERRORS); - mPos += mBuffer.putInt(mPos, mErrorMask); - mBuffer.putByte(POS_NUM_ELEMENTS, (byte) 3); - } - - final int size = mPos; - - 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) { - mPosLastField = mPos; - mLastType = typeId; - mCurrentAnnotationCount = 0; - final byte encodedId = (byte) (typeId & 0x0F); - mPos += mBuffer.putByte(mPos, encodedId); - } - - private void writeAnnotationCount() { - // Use first 4 bits for annotation count and last 4 bits for typeId. - final byte encodedId = (byte) ((mCurrentAnnotationCount << 4) | (mLastType & 0x0F)); - mBuffer.putByte(mPosLastField, encodedId); - } - - @NonNull - private static byte[] stringToBytes(@Nullable final String value) { - return (null == value ? "" : value).getBytes(UTF_8); - } - - private boolean writeArrayInfo(final byte numElements, - final byte elementTypeId) { - if (numElements > MAX_NUM_ELEMENTS) { - mErrorMask |= ERROR_LIST_TOO_LONG; - return false; - } - // Write list typeId byte, 1-byte representation of number of - // elements, and element typeId byte. - writeTypeId(TYPE_LIST); - mPos += mBuffer.putByte(mPos, numElements); - // Write element typeId byte without setting mPosLastField and mLastType (i.e. don't use - // #writeTypeId) - final byte encodedId = (byte) (elementTypeId & 0x0F); - mPos += mBuffer.putByte(mPos, encodedId); - return true; - } - } - - private static final class Buffer { - private static Object sLock = new Object(); - - @GuardedBy("sLock") - private static Buffer sPool; - - private byte[] mBytes; - private boolean mOverflow = false; - private int mMaxSize = MAX_PULL_PAYLOAD_SIZE; - - @NonNull - private static Buffer obtain() { - final Buffer buffer; - synchronized (sLock) { - buffer = null == sPool ? new Buffer() : sPool; - sPool = null; - } - buffer.reset(); - return buffer; - } - - private Buffer() { - final ByteBuffer tempBuffer = ByteBuffer.allocateDirect(MAX_PUSH_PAYLOAD_SIZE); - mBytes = tempBuffer.hasArray() ? tempBuffer.array() : new byte [MAX_PUSH_PAYLOAD_SIZE]; - } - - @NonNull - private byte[] getBytes() { - return mBytes; - } - - private void release() { - // Recycle this Buffer if its size is MAX_PUSH_PAYLOAD_SIZE or under. - if (mMaxSize <= MAX_PUSH_PAYLOAD_SIZE) { - synchronized (sLock) { - if (null == sPool) { - sPool = this; - } - } - } - } - - private void reset() { - mOverflow = false; - mMaxSize = MAX_PULL_PAYLOAD_SIZE; - } - - private void setMaxSize(final int maxSize, final int numBytesWritten) { - mMaxSize = maxSize; - if (numBytesWritten > maxSize) { - mOverflow = true; - } - } - - private boolean hasOverflowed() { - return mOverflow; - } - - /** - * Checks for available space in the byte array. - * - * @param index starting position in the buffer to start the check. - * @param numBytes number of bytes to check from index. - * @return true if space is available, false otherwise. - **/ - private boolean hasEnoughSpace(final int index, final int numBytes) { - final int totalBytesNeeded = index + numBytes; - - if (totalBytesNeeded > mMaxSize) { - mOverflow = true; - return false; - } - - // Expand buffer if needed. - if (mBytes.length < mMaxSize && totalBytesNeeded > mBytes.length) { - int newSize = mBytes.length; - do { - newSize *= 2; - } while (newSize <= totalBytesNeeded); - - if (newSize > mMaxSize) { - newSize = mMaxSize; - } - - mBytes = Arrays.copyOf(mBytes, newSize); - } - - return true; - } - - /** - * Writes a byte into the buffer. - * - * @param index position in the buffer where the byte is written. - * @param value the byte to write. - * @return number of bytes written to buffer from this write operation. - **/ - private int putByte(final int index, final byte value) { - if (hasEnoughSpace(index, Byte.BYTES)) { - mBytes[index] = (byte) (value); - return Byte.BYTES; - } - return 0; - } - - /** - * Writes a boolean into the buffer. - * - * @param index position in the buffer where the boolean is written. - * @param value the boolean to write. - * @return number of bytes written to buffer from this write operation. - **/ - private int putBoolean(final int index, final boolean value) { - return putByte(index, (byte) (value ? 1 : 0)); - } - - /** - * Writes an integer into the buffer. - * - * @param index position in the buffer where the integer is written. - * @param value the integer to write. - * @return number of bytes written to buffer from this write operation. - **/ - private int putInt(final int index, final int value) { - if (hasEnoughSpace(index, Integer.BYTES)) { - // Use little endian byte order. - mBytes[index] = (byte) (value); - mBytes[index + 1] = (byte) (value >> 8); - mBytes[index + 2] = (byte) (value >> 16); - mBytes[index + 3] = (byte) (value >> 24); - return Integer.BYTES; - } - return 0; - } - - /** - * Writes a long into the buffer. - * - * @param index position in the buffer where the long is written. - * @param value the long to write. - * @return number of bytes written to buffer from this write operation. - **/ - private int putLong(final int index, final long value) { - if (hasEnoughSpace(index, Long.BYTES)) { - // Use little endian byte order. - mBytes[index] = (byte) (value); - mBytes[index + 1] = (byte) (value >> 8); - mBytes[index + 2] = (byte) (value >> 16); - mBytes[index + 3] = (byte) (value >> 24); - mBytes[index + 4] = (byte) (value >> 32); - mBytes[index + 5] = (byte) (value >> 40); - mBytes[index + 6] = (byte) (value >> 48); - mBytes[index + 7] = (byte) (value >> 56); - return Long.BYTES; - } - return 0; - } - - /** - * Writes a float into the buffer. - * - * @param index position in the buffer where the float is written. - * @param value the float to write. - * @return number of bytes written to buffer from this write operation. - **/ - private int putFloat(final int index, final float value) { - return putInt(index, Float.floatToIntBits(value)); - } - - /** - * Copies a byte array into the buffer. - * - * @param index position in the buffer where the byte array is copied. - * @param value the byte array to copy. - * @return number of bytes written to buffer from this write operation. - **/ - private int putByteArray(final int index, @NonNull final byte[] value) { - final int numBytes = value.length; - if (hasEnoughSpace(index, numBytes)) { - System.arraycopy(value, 0, mBytes, index, numBytes); - return numBytes; - } - return 0; - } - } -} diff --git a/ravenwood/runtime-helper-src/framework/android/util/StatsLog.java b/ravenwood/runtime-helper-src/framework/android/util/StatsLog.java deleted file mode 100644 index c1c20cfac9dd..000000000000 --- a/ravenwood/runtime-helper-src/framework/android/util/StatsLog.java +++ /dev/null @@ -1,478 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.util; - -/* - * [Ravenwood] This is copied from StatsD, with the following changes: - * - The static {} is commented out. - * - All references to IStatsD and StatsdStatsLog are commented out. - * - The native method is no-oped. - */ - -import static android.Manifest.permission.DUMP; -import static android.Manifest.permission.PACKAGE_USAGE_STATS; - -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.annotation.RequiresPermission; -import android.annotation.SuppressLint; -import android.annotation.SystemApi; -import android.os.Build; -//import android.os.IStatsd; -import android.os.Process; -import android.util.proto.ProtoOutputStream; - -import androidx.annotation.RequiresApi; - -//import com.android.internal.statsd.StatsdStatsLog; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * StatsLog provides an API for developers to send events to statsd. The events can be used to - * define custom metrics in side statsd. - */ -public final class StatsLog { - -// // Load JNI library -// static { -// System.loadLibrary("stats_jni"); -// } - private static final String TAG = "StatsLog"; - private static final boolean DEBUG = false; - private static final int EXPERIMENT_IDS_FIELD_ID = 1; - - /** - * Annotation ID constant for logging UID field. - * - * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation() - * accept byte as the type for annotation ids to save space. - * - * @hide - */ - @SuppressLint("NoByteOrShort") - @SystemApi - public static final byte ANNOTATION_ID_IS_UID = 1; - - /** - * Annotation ID constant to indicate logged atom event's timestamp should be truncated. - * - * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation() - * accept byte as the type for annotation ids to save space. - * - * @hide - */ - @SuppressLint("NoByteOrShort") - @SystemApi - public static final byte ANNOTATION_ID_TRUNCATE_TIMESTAMP = 2; - - /** - * Annotation ID constant for a state atom's primary field. - * - * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation() - * accept byte as the type for annotation ids to save space. - * - * @hide - */ - @SuppressLint("NoByteOrShort") - @SystemApi - public static final byte ANNOTATION_ID_PRIMARY_FIELD = 3; - - /** - * Annotation ID constant for state atom's state field. - * - * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation() - * accept byte as the type for annotation ids to save space. - * - * @hide - */ - @SuppressLint("NoByteOrShort") - @SystemApi - public static final byte ANNOTATION_ID_EXCLUSIVE_STATE = 4; - - /** - * Annotation ID constant to indicate the first UID in the attribution chain - * is a primary field. - * Should only be used for attribution chain fields. - * - * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation() - * accept byte as the type for annotation ids to save space. - * - * @hide - */ - @SuppressLint("NoByteOrShort") - @SystemApi - public static final byte ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID = 5; - - /** - * Annotation ID constant to indicate which state is default for the state atom. - * - * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation() - * accept byte as the type for annotation ids to save space. - * - * @hide - */ - @SuppressLint("NoByteOrShort") - @SystemApi - public static final byte ANNOTATION_ID_DEFAULT_STATE = 6; - - /** - * Annotation ID constant to signal all states should be reset to the default state. - * - * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation() - * accept byte as the type for annotation ids to save space. - * - * @hide - */ - @SuppressLint("NoByteOrShort") - @SystemApi - public static final byte ANNOTATION_ID_TRIGGER_STATE_RESET = 7; - - /** - * Annotation ID constant to indicate state changes need to account for nesting. - * This should only be used with binary state atoms. - * - * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation() - * accept byte as the type for annotation ids to save space. - * - * @hide - */ - @SuppressLint("NoByteOrShort") - @SystemApi - public static final byte ANNOTATION_ID_STATE_NESTED = 8; - - /** - * Annotation ID constant to indicate the restriction category of an atom. - * This annotation must only be attached to the atom id. This is an int annotation. - * - * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation() - * accept byte as the type for annotation ids to save space. - * - * @hide - */ - @SuppressLint("NoByteOrShort") - @SystemApi - @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) - public static final byte ANNOTATION_ID_RESTRICTION_CATEGORY = 9; - - /** - * Annotation ID to indicate that a field of an atom contains peripheral device info. - * This is a bool annotation. - * - * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation() - * accept byte as the type for annotation ids to save space. - * - * @hide - */ - @SuppressLint("NoByteOrShort") - @SystemApi - @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) - public static final byte ANNOTATION_ID_FIELD_RESTRICTION_PERIPHERAL_DEVICE_INFO = 10; - - /** - * Annotation ID to indicate that a field of an atom contains app usage information. - * This is a bool annotation. - * - * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation() - * accept byte as the type for annotation ids to save space. - * - * @hide - */ - @SuppressLint("NoByteOrShort") - @SystemApi - @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) - public static final byte ANNOTATION_ID_FIELD_RESTRICTION_APP_USAGE = 11; - - /** - * Annotation ID to indicate that a field of an atom contains app activity information. - * This is a bool annotation. - * - * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation() - * accept byte as the type for annotation ids to save space. - * - * @hide - */ - @SuppressLint("NoByteOrShort") - @SystemApi - @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) - public static final byte ANNOTATION_ID_FIELD_RESTRICTION_APP_ACTIVITY = 12; - - /** - * Annotation ID to indicate that a field of an atom contains health connect information. - * This is a bool annotation. - * - * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation() - * accept byte as the type for annotation ids to save space. - * - * @hide - */ - @SuppressLint("NoByteOrShort") - @SystemApi - @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) - public static final byte ANNOTATION_ID_FIELD_RESTRICTION_HEALTH_CONNECT = 13; - - /** - * Annotation ID to indicate that a field of an atom contains accessibility information. - * This is a bool annotation. - * - * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation() - * accept byte as the type for annotation ids to save space. - * - * @hide - */ - @SuppressLint("NoByteOrShort") - @SystemApi - @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) - public static final byte ANNOTATION_ID_FIELD_RESTRICTION_ACCESSIBILITY = 14; - - /** - * Annotation ID to indicate that a field of an atom contains system search information. - * This is a bool annotation. - * - * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation() - * accept byte as the type for annotation ids to save space. - * - * @hide - */ - @SuppressLint("NoByteOrShort") - @SystemApi - @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) - public static final byte ANNOTATION_ID_FIELD_RESTRICTION_SYSTEM_SEARCH = 15; - - /** - * Annotation ID to indicate that a field of an atom contains user engagement information. - * This is a bool annotation. - * - * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation() - * accept byte as the type for annotation ids to save space. - * - * @hide - */ - @SuppressLint("NoByteOrShort") - @SystemApi - @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) - public static final byte ANNOTATION_ID_FIELD_RESTRICTION_USER_ENGAGEMENT = 16; - - /** - * Annotation ID to indicate that a field of an atom contains ambient sensing information. - * This is a bool annotation. - * - * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation() - * accept byte as the type for annotation ids to save space. - * - * @hide - */ - @SuppressLint("NoByteOrShort") - @SystemApi - @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) - public static final byte ANNOTATION_ID_FIELD_RESTRICTION_AMBIENT_SENSING = 17; - - /** - * Annotation ID to indicate that a field of an atom contains demographic classification - * information. This is a bool annotation. - * - * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation() - * accept byte as the type for annotation ids to save space. - * - * @hide - */ - @SuppressLint("NoByteOrShort") - @SystemApi - @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) - public static final byte ANNOTATION_ID_FIELD_RESTRICTION_DEMOGRAPHIC_CLASSIFICATION = 18; - - - /** @hide */ - @IntDef(prefix = { "RESTRICTION_CATEGORY_" }, value = { - RESTRICTION_CATEGORY_DIAGNOSTIC, - RESTRICTION_CATEGORY_SYSTEM_INTELLIGENCE, - RESTRICTION_CATEGORY_AUTHENTICATION, - RESTRICTION_CATEGORY_FRAUD_AND_ABUSE}) - @Retention(RetentionPolicy.SOURCE) - public @interface RestrictionCategory {} - - /** - * Restriction category for atoms about diagnostics. - * - * @hide - */ - @SystemApi - @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) - public static final int RESTRICTION_CATEGORY_DIAGNOSTIC = 1; - - /** - * Restriction category for atoms about system intelligence. - * - * @hide - */ - @SystemApi - @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) - public static final int RESTRICTION_CATEGORY_SYSTEM_INTELLIGENCE = 2; - - /** - * Restriction category for atoms about authentication. - * - * @hide - */ - @SystemApi - @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) - public static final int RESTRICTION_CATEGORY_AUTHENTICATION = 3; - - /** - * Restriction category for atoms about fraud and abuse. - * - * @hide - */ - @SystemApi - @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) - public static final int RESTRICTION_CATEGORY_FRAUD_AND_ABUSE = 4; - - private StatsLog() { - } - - /** - * Logs a start event. - * - * @param label developer-chosen label. - * @return True if the log request was sent to statsd. - */ - public static boolean logStart(int label) { - int callingUid = Process.myUid(); -// StatsdStatsLog.write( -// StatsdStatsLog.APP_BREADCRUMB_REPORTED, -// callingUid, -// label, -// StatsdStatsLog.APP_BREADCRUMB_REPORTED__STATE__START); - return true; - } - - /** - * Logs a stop event. - * - * @param label developer-chosen label. - * @return True if the log request was sent to statsd. - */ - public static boolean logStop(int label) { - int callingUid = Process.myUid(); -// StatsdStatsLog.write( -// StatsdStatsLog.APP_BREADCRUMB_REPORTED, -// callingUid, -// label, -// StatsdStatsLog.APP_BREADCRUMB_REPORTED__STATE__STOP); - return true; - } - - /** - * Logs an event that does not represent a start or stop boundary. - * - * @param label developer-chosen label. - * @return True if the log request was sent to statsd. - */ - public static boolean logEvent(int label) { - int callingUid = Process.myUid(); -// StatsdStatsLog.write( -// StatsdStatsLog.APP_BREADCRUMB_REPORTED, -// callingUid, -// label, -// StatsdStatsLog.APP_BREADCRUMB_REPORTED__STATE__UNSPECIFIED); - return true; - } - - /** - * Logs an event for binary push for module updates. - * - * @param trainName name of install train. - * @param trainVersionCode version code of the train. - * @param options optional flags about this install. - * The last 3 bits indicate options: - * 0x01: FLAG_REQUIRE_STAGING - * 0x02: FLAG_ROLLBACK_ENABLED - * 0x04: FLAG_REQUIRE_LOW_LATENCY_MONITOR - * @param state current install state. Defined as State enums in - * BinaryPushStateChanged atom in - * frameworks/proto_logging/stats/atoms.proto - * @param experimentIds experiment ids. - * @return True if the log request was sent to statsd. - */ - @RequiresPermission(allOf = {DUMP, PACKAGE_USAGE_STATS}) - public static boolean logBinaryPushStateChanged(@NonNull String trainName, - long trainVersionCode, int options, int state, - @NonNull long[] experimentIds) { - ProtoOutputStream proto = new ProtoOutputStream(); - for (long id : experimentIds) { - proto.write( - ProtoOutputStream.FIELD_TYPE_INT64 - | ProtoOutputStream.FIELD_COUNT_REPEATED - | EXPERIMENT_IDS_FIELD_ID, - id); - } -// StatsdStatsLog.write(StatsdStatsLog.BINARY_PUSH_STATE_CHANGED, -// trainName, -// trainVersionCode, -// (options & IStatsd.FLAG_REQUIRE_STAGING) > 0, -// (options & IStatsd.FLAG_ROLLBACK_ENABLED) > 0, -// (options & IStatsd.FLAG_REQUIRE_LOW_LATENCY_MONITOR) > 0, -// state, -// proto.getBytes(), -// 0, -// 0, -// false); - return true; - } - - /** - * Write an event to stats log using the raw format. - * - * @param buffer The encoded buffer of data to write. - * @param size The number of bytes from the buffer to write. - * @hide - * @deprecated Use {@link write(final StatsEvent statsEvent)} instead. - * - */ - @Deprecated - @SystemApi - public static void writeRaw(@NonNull byte[] buffer, int size) { - writeImpl(buffer, size, 0); - } - - /** - * Write an event to stats log using the raw format. - * - * @param buffer The encoded buffer of data to write. - * @param size The number of bytes from the buffer to write. - * @param atomId The id of the atom to which the event belongs. - */ -// private static native void writeImpl(@NonNull byte[] buffer, int size, int atomId); - private static void writeImpl(@NonNull byte[] buffer, int size, int atomId) { - // no-op for now - } - - /** - * 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 - */ - @SystemApi - public static void write(@NonNull final StatsEvent statsEvent) { - writeImpl(statsEvent.getBytes(), statsEvent.getNumBytes(), statsEvent.getAtomId()); - statsEvent.release(); - } -} |