/*
 * Copyright 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.media;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.os.Bundle;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Objects;

/**
 * MediaMetrics is the Java interface to the MediaMetrics service.
 *
 * This is used to collect media statistics by the framework.
 * It is not intended for direct application use.
 *
 * @hide
 */
public class MediaMetrics {
    public static final String TAG = "MediaMetrics";

    public static final String SEPARATOR = ".";

    /**
     * A list of established MediaMetrics names that can be used for Items.
     */
    public static class Name {
        public static final String AUDIO = "audio";
        public static final String AUDIO_BLUETOOTH = AUDIO + SEPARATOR + "bluetooth";
        public static final String AUDIO_DEVICE = AUDIO + SEPARATOR + "device";
        public static final String AUDIO_FOCUS = AUDIO + SEPARATOR + "focus";
        public static final String AUDIO_FORCE_USE = AUDIO + SEPARATOR + "forceUse";
        public static final String AUDIO_MIC = AUDIO + SEPARATOR + "mic";
        public static final String AUDIO_SERVICE = AUDIO + SEPARATOR + "service";
        public static final String AUDIO_VOLUME = AUDIO + SEPARATOR + "volume";
        public static final String AUDIO_VOLUME_EVENT = AUDIO_VOLUME + SEPARATOR + "event";
    }

    /**
     * A list of established string values.
     */
    public static class Value {
        public static final String CONNECT = "connect";
        public static final String CONNECTED = "connected";
        public static final String DISCONNECT = "disconnect";
        public static final String DISCONNECTED = "disconnected";
        public static final String DOWN = "down";
        public static final String MUTE = "mute";
        public static final String NO = "no";
        public static final String OFF = "off";
        public static final String ON = "on";
        public static final String UNMUTE = "unmute";
        public static final String UP = "up";
        public static final String YES = "yes";
    }

    /**
     * A list of standard property keys for consistent use and type.
     */
    public static class Property {
        // A use for Bluetooth or USB device addresses
        public static final Key<String> ADDRESS = createKey("address", String.class);
        // A string representing the Audio Attributes
        public static final Key<String> ATTRIBUTES = createKey("attributes", String.class);

        // The calling package responsible for the state change
        public static final Key<String> CALLING_PACKAGE =
                createKey("callingPackage", String.class);

        // The client name
        public static final Key<String> CLIENT_NAME = createKey("clientName", String.class);

        // The device type
        public static final Key<Integer> DELAY_MS = createKey("delayMs", Integer.class);

        // The device type
        public static final Key<String> DEVICE = createKey("device", String.class);

        // For volume changes, up or down
        public static final Key<String> DIRECTION = createKey("direction", String.class);

        // A reason for early return or error
        public static final Key<String> EARLY_RETURN =
                createKey("earlyReturn", String.class);
        // ENCODING_ ... string to match AudioFormat encoding
        public static final Key<String> ENCODING = createKey("encoding", String.class);

        public static final Key<String> EVENT = createKey("event#", String.class);

        // event generated is external (yes, no)
        public static final Key<String> EXTERNAL = createKey("external", String.class);

        public static final Key<Integer> FLAGS = createKey("flags", Integer.class);
        public static final Key<String> FOCUS_CHANGE_HINT =
                createKey("focusChangeHint", String.class);
        public static final Key<String> FORCE_USE_DUE_TO =
                createKey("forceUseDueTo", String.class);
        public static final Key<String> FORCE_USE_MODE =
                createKey("forceUseMode", String.class);
        public static final Key<Double> GAIN_DB =
                createKey("gainDb", Double.class);
        public static final Key<String> GROUP =
                createKey("group", String.class);
        // For volume
        public static final Key<Integer> INDEX = createKey("index", Integer.class);
        public static final Key<Integer> MAX_INDEX = createKey("maxIndex", Integer.class);
        public static final Key<Integer> MIN_INDEX = createKey("minIndex", Integer.class);
        public static final Key<String> MODE =
                createKey("mode", String.class); // audio_mode
        public static final Key<String> MUTE =
                createKey("mute", String.class); // microphone, on or off.

        // Bluetooth or Usb device name
        public static final Key<String> NAME =
                createKey("name", String.class);

        // Number of observers
        public static final Key<Integer> OBSERVERS =
                createKey("observers", Integer.class);

        public static final Key<String> REQUEST =
                createKey("request", String.class);

        // For Bluetooth
        public static final Key<String> SCO_AUDIO_MODE =
                createKey("scoAudioMode", String.class);
        public static final Key<Integer> SDK = createKey("sdk", Integer.class);
        public static final Key<String> STATE = createKey("state", String.class);
        public static final Key<Integer> STATUS = createKey("status", Integer.class);
        public static final Key<String> STREAM_TYPE = createKey("streamType", String.class);
    }

    /**
     * The TYPE constants below should match those in native MediaMetricsItem.h
     */
    private static final int TYPE_NONE = 0;
    private static final int TYPE_INT32 = 1;     // Java integer
    private static final int TYPE_INT64 = 2;     // Java long
    private static final int TYPE_DOUBLE = 3;    // Java double
    private static final int TYPE_CSTRING = 4;   // Java string
    private static final int TYPE_RATE = 5;      // Two longs, ignored in Java

    // The charset used for encoding Strings to bytes.
    private static final Charset MEDIAMETRICS_CHARSET = StandardCharsets.UTF_8;

    /**
     * Key interface.
     *
     * The presence of this {@code Key} interface on an object allows
     * it to be used to set metrics.
     *
     * @param <T> type of value associated with {@code Key}.
     */
    public interface Key<T> {
        /**
         * Returns the internal name of the key.
         */
        @NonNull
        String getName();

        /**
         * Returns the class type of the associated value.
         */
        @NonNull
        Class<T> getValueClass();
    }

    /**
     * Returns a Key object with the correct interface for MediaMetrics.
     *
     * @param name The name of the key.
     * @param type The class type of the value represented by the key.
     * @param <T> The type of value.
     * @return a new key interface.
     */
    @NonNull
    public static <T> Key<T> createKey(@NonNull String name, @NonNull Class<T> type) {
        // Implementation specific.
        return new Key<T>() {
            private final String mName = name;
            private final Class<T> mType = type;

            @Override
            @NonNull
            public String getName() {
                return mName;
            }

            @Override
            @NonNull
            public Class<T> getValueClass() {
                return mType;
            }

            /**
             * Return true if the name and the type of two objects are the same.
             */
            @Override
            public boolean equals(Object obj) {
                if (obj == this) {
                    return true;
                }
                if (!(obj instanceof Key)) {
                    return false;
                }
                Key<?> other = (Key<?>) obj;
                return mName.equals(other.getName()) && mType.equals(other.getValueClass());
            }

            @Override
            public int hashCode() {
                return Objects.hash(mName, mType);
            }
        };
    }

    /**
     * Item records properties and delivers to the MediaMetrics service
     *
     */
    public static class Item {

        /*
         * MediaMetrics Item
         *
         * Creates a Byte String and sends to the MediaMetrics service.
         * The Byte String serves as a compact form for logging data
         * with low overhead for storage.
         *
         * The Byte String format is as follows:
         *
         * For Java
         *  int64 corresponds to long
         *  int32, uint32 corresponds to int
         *  uint16 corresponds to char
         *  uint8, int8 corresponds to byte
         *
         * For items transmitted from Java, uint8 and uint32 values are limited
         * to INT8_MAX and INT32_MAX.  This constrains the size of large items
         * to 2GB, which is consistent with ByteBuffer max size. A native item
         * can conceivably have size of 4GB.
         *
         * Physical layout of integers and doubles within the MediaMetrics byte string
         * is in Native / host order, which is usually little endian.
         *
         * Note that primitive data (ints, doubles) within a Byte String has
         * no extra padding or alignment requirements, like ByteBuffer.
         *
         * -- begin of item
         * -- begin of header
         * (uint32) item size: including the item size field
         * (uint32) header size, including the item size and header size fields.
         * (uint16) version: exactly 0
         * (uint16) key size, that is key strlen + 1 for zero termination.
         * (int8)+ key, a string which is 0 terminated (UTF-8).
         * (int32) pid
         * (int32) uid
         * (int64) timestamp
         * -- end of header
         * -- begin body
         * (uint32) number of properties
         * -- repeat for number of properties
         *     (uint16) property size, including property size field itself
         *     (uint8) type of property
         *     (int8)+ key string, including 0 termination
         *      based on type of property (given above), one of:
         *       (int32)
         *       (int64)
         *       (double)
         *       (int8)+ for TYPE_CSTRING, including 0 termination
         *       (int64, int64) for rate
         * -- end body
         * -- end of item
         *
         * To record a MediaMetrics event, one creates a new item with an id,
         * then use a series of puts to add properties
         * and then a record() to send to the MediaMetrics service.
         *
         * The properties may not be unique, and putting a later property with
         * the same name as an earlier property will overwrite the value and type
         * of the prior property.
         *
         * The timestamp can only be recorded by a system service (and is ignored otherwise;
         * the MediaMetrics service will fill in the timestamp as needed).
         *
         * The units of time are in SystemClock.elapsedRealtimeNanos().
         *
         * A clear() may be called to reset the properties to empty, the time to 0, but keep
         * the other entries the same. This may be called after record().
         * Additional properties may be added after calling record().  Changing the same property
         * repeatedly is discouraged as - for this particular implementation - extra data
         * is stored per change.
         *
         * new MediaMetrics.Item(mSomeId)
         *     .putString("event", "javaCreate")
         *     .putInt("value", intValue)
         *     .record();
         */

        /**
         * Creates an Item with server added uid, time.
         *
         * This is the typical way to record a MediaMetrics item.
         *
         * @param key the Metrics ID associated with the item.
         */
        public Item(String key) {
            this(key, -1 /* pid */, -1 /* uid */, 0 /* SystemClock.elapsedRealtimeNanos() */,
                    2048 /* capacity */);
        }

        /**
         * Creates an Item specifying pid, uid, time, and initial Item capacity.
         *
         * This might be used by a service to specify a different PID or UID for a client.
         *
         * @param key the Metrics ID associated with the item.
         *        An app may only set properties on an item which has already been
         *        logged previously by a service.
         * @param pid the process ID corresponding to the item.
         *        A value of -1 (or a record() from an app instead of a service) causes
         *        the MediaMetrics service to fill this in.
         * @param uid the user ID corresponding to the item.
         *        A value of -1 (or a record() from an app instead of a service) causes
         *        the MediaMetrics service to fill this in.
         * @param timeNs the time when the item occurred (may be in the past).
         *        A value of 0 (or a record() from an app instead of a service) causes
         *        the MediaMetrics service to fill it in.
         *        Should be obtained from SystemClock.elapsedRealtimeNanos().
         * @param capacity the anticipated size to use for the buffer.
         *        If the capacity is too small, the buffer will be resized to accommodate.
         *        This is amortized to copy data no more than twice.
         */
        public Item(String key, int pid, int uid, long timeNs, int capacity) {
            final byte[] keyBytes = key.getBytes(MEDIAMETRICS_CHARSET);
            final int keyLength = keyBytes.length;
            if (keyLength > Character.MAX_VALUE - 1) {
                throw new IllegalArgumentException("Key length too large");
            }

            // Version 0 - compute the header offsets here.
            mHeaderSize = 4 + 4 + 2 + 2 + keyLength + 1 + 4 + 4 + 8; // see format above.
            mPidOffset = mHeaderSize - 16;
            mUidOffset = mHeaderSize - 12;
            mTimeNsOffset = mHeaderSize - 8;
            mPropertyCountOffset = mHeaderSize;
            mPropertyStartOffset = mHeaderSize + 4;

            mKey = key;
            mBuffer = ByteBuffer.allocateDirect(
                    Math.max(capacity, mHeaderSize + MINIMUM_PAYLOAD_SIZE));

            // Version 0 - fill the ByteBuffer with the header (some details updated later).
            mBuffer.order(ByteOrder.nativeOrder())
                .putInt((int) 0)                      // total size in bytes (filled in later)
                .putInt((int) mHeaderSize)            // size of header
                .putChar((char) FORMAT_VERSION)       // version
                .putChar((char) (keyLength + 1))      // length, with zero termination
                .put(keyBytes).put((byte) 0)
                .putInt(pid)
                .putInt(uid)
                .putLong(timeNs);
            if (mHeaderSize != mBuffer.position()) {
                throw new IllegalStateException("Mismatched sizing");
            }
            mBuffer.putInt(0);     // number of properties (to be later filled in by record()).
        }

        /**
         * Sets a metrics typed key
         * @param key
         * @param value
         * @param <T>
         * @return
         */
        @NonNull
        public <T> Item set(@NonNull Key<T> key, @Nullable T value) {
            if (value instanceof Integer) {
                putInt(key.getName(), (int) value);
            } else if (value instanceof Long) {
                putLong(key.getName(), (long) value);
            } else if (value instanceof Double) {
                putDouble(key.getName(), (double) value);
            } else if (value instanceof String) {
                putString(key.getName(), (String) value);
            }
            // if value is null, etc. no error is raised.
            return this;
        }

        /**
         * Sets the property with key to an integer (32 bit) value.
         *
         * @param key
         * @param value
         * @return itself
         */
        public Item putInt(String key, int value) {
            final byte[] keyBytes = key.getBytes(MEDIAMETRICS_CHARSET);
            final char propSize = (char) reserveProperty(keyBytes, 4 /* payloadSize */);
            final int estimatedFinalPosition = mBuffer.position() + propSize;
            mBuffer.putChar(propSize)
                .put((byte) TYPE_INT32)
                .put(keyBytes).put((byte) 0) // key, zero terminated
                .putInt(value);
            ++mPropertyCount;
            if (mBuffer.position() != estimatedFinalPosition) {
                throw new IllegalStateException("Final position " + mBuffer.position()
                        + " != estimatedFinalPosition " + estimatedFinalPosition);
            }
            return this;
        }

        /**
         * Sets the property with key to a long (64 bit) value.
         *
         * @param key
         * @param value
         * @return itself
         */
        public Item putLong(String key, long value) {
            final byte[] keyBytes = key.getBytes(MEDIAMETRICS_CHARSET);
            final char propSize = (char) reserveProperty(keyBytes, 8 /* payloadSize */);
            final int estimatedFinalPosition = mBuffer.position() + propSize;
            mBuffer.putChar(propSize)
                .put((byte) TYPE_INT64)
                .put(keyBytes).put((byte) 0) // key, zero terminated
                .putLong(value);
            ++mPropertyCount;
            if (mBuffer.position() != estimatedFinalPosition) {
                throw new IllegalStateException("Final position " + mBuffer.position()
                    + " != estimatedFinalPosition " + estimatedFinalPosition);
            }
            return this;
        }

        /**
         * Sets the property with key to a double value.
         *
         * @param key
         * @param value
         * @return itself
         */
        public Item putDouble(String key, double value) {
            final byte[] keyBytes = key.getBytes(MEDIAMETRICS_CHARSET);
            final char propSize = (char) reserveProperty(keyBytes, 8 /* payloadSize */);
            final int estimatedFinalPosition = mBuffer.position() + propSize;
            mBuffer.putChar(propSize)
                .put((byte) TYPE_DOUBLE)
                .put(keyBytes).put((byte) 0) // key, zero terminated
                .putDouble(value);
            ++mPropertyCount;
            if (mBuffer.position() != estimatedFinalPosition) {
                throw new IllegalStateException("Final position " + mBuffer.position()
                    + " != estimatedFinalPosition " + estimatedFinalPosition);
            }
            return this;
        }

        /**
         * Sets the property with key to a String value.
         *
         * @param key
         * @param value
         * @return itself
         */
        public Item putString(String key, String value) {
            final byte[] keyBytes = key.getBytes(MEDIAMETRICS_CHARSET);
            final byte[] valueBytes = value.getBytes(MEDIAMETRICS_CHARSET);
            final char propSize = (char) reserveProperty(keyBytes, valueBytes.length + 1);
            final int estimatedFinalPosition = mBuffer.position() + propSize;
            mBuffer.putChar(propSize)
                .put((byte) TYPE_CSTRING)
                .put(keyBytes).put((byte) 0) // key, zero terminated
                .put(valueBytes).put((byte) 0); // value, zero term.
            ++mPropertyCount;
            if (mBuffer.position() != estimatedFinalPosition) {
                throw new IllegalStateException("Final position " + mBuffer.position()
                    + " != estimatedFinalPosition " + estimatedFinalPosition);
            }
            return this;
        }

        /**
         * Sets the pid to the provided value.
         *
         * @param pid which can be -1 if the service is to fill it in from the calling info.
         * @return itself
         */
        public Item setPid(int pid) {
            mBuffer.putInt(mPidOffset, pid); // pid location in byte string.
            return this;
        }

        /**
         * Sets the uid to the provided value.
         *
         * The UID represents the client associated with the property. This must be the UID
         * of the application if it comes from the application client.
         *
         * Trusted services are allowed to set the uid for a client-related item.
         *
         * @param uid which can be -1 if the service is to fill it in from calling info.
         * @return itself
         */
        public Item setUid(int uid) {
            mBuffer.putInt(mUidOffset, uid); // uid location in byte string.
            return this;
        }

        /**
         * Sets the timestamp to the provided value.
         *
         * The time is referenced by the Boottime obtained by SystemClock.elapsedRealtimeNanos().
         * This should be associated with the occurrence of the event.  It is recommended that
         * the event be registered immediately when it occurs, and no later than 500ms
         * (and certainly not in the future).
         *
         * @param timeNs which can be 0 if the service is to fill it in at the time of call.
         * @return itself
         */
        public Item setTimestamp(long timeNs) {
            mBuffer.putLong(mTimeNsOffset, timeNs); // time location in byte string.
            return this;
        }

        /**
         * Clears the properties and resets the time to 0.
         *
         * No other values are changed.
         *
         * @return itself
         */
        public Item clear() {
            mBuffer.position(mPropertyStartOffset);
            mBuffer.limit(mBuffer.capacity());
            mBuffer.putLong(mTimeNsOffset, 0); // reset time.
            mPropertyCount = 0;
            return this;
        }

        /**
         * Sends the item to the MediaMetrics service.
         *
         * The item properties are unchanged, hence record() may be called more than once
         * to send the same item twice. Also, record() may be called without any properties.
         *
         * @return true if successful.
         */
        public boolean record() {
            updateHeader();
            return native_submit_bytebuffer(mBuffer, mBuffer.limit()) >= 0;
        }

        /**
         * Converts the Item to a Bundle.
         *
         * This is primarily used as a test API for CTS.
         *
         * @return a Bundle with the keys set according to data in the Item's buffer.
         */
        @TestApi
        public Bundle toBundle() {
            updateHeader();

            final ByteBuffer buffer = mBuffer.duplicate();
            buffer.order(ByteOrder.nativeOrder()) // restore order property
                .flip();                          // convert from write buffer to read buffer

            return toBundle(buffer);
        }

        // The following constants are used for tests to extract
        // the content of the Bundle for CTS testing.
        @TestApi
        public static final String BUNDLE_TOTAL_SIZE = "_totalSize";
        @TestApi
        public static final String BUNDLE_HEADER_SIZE = "_headerSize";
        @TestApi
        public static final String BUNDLE_VERSION = "_version";
        @TestApi
        public static final String BUNDLE_KEY_SIZE = "_keySize";
        @TestApi
        public static final String BUNDLE_KEY = "_key";
        @TestApi
        public static final String BUNDLE_PID = "_pid";
        @TestApi
        public static final String BUNDLE_UID = "_uid";
        @TestApi
        public static final String BUNDLE_TIMESTAMP = "_timestamp";
        @TestApi
        public static final String BUNDLE_PROPERTY_COUNT = "_propertyCount";

        /**
         * Converts a buffer contents to a bundle
         *
         * This is primarily used as a test API for CTS.
         *
         * @param buffer contains the byte data serialized according to the byte string version.
         * @return a Bundle with the keys set according to data in the buffer.
         */
        @TestApi
        public static Bundle toBundle(ByteBuffer buffer) {
            final Bundle bundle = new Bundle();

            final int totalSize = buffer.getInt();
            final int headerSize = buffer.getInt();
            final char version = buffer.getChar();
            final char keySize = buffer.getChar(); // includes zero termination, i.e. keyLength + 1

            if (totalSize < 0 || headerSize < 0) {
                throw new IllegalArgumentException("Item size cannot be > " + Integer.MAX_VALUE);
            }
            final String key;
            if (keySize > 0) {
                key = getStringFromBuffer(buffer, keySize);
            } else {
                throw new IllegalArgumentException("Illegal null key");
            }

            final int pid = buffer.getInt();
            final int uid = buffer.getInt();
            final long timestamp = buffer.getLong();

            // Verify header size (depending on version).
            final int headerRead = buffer.position();
            if (version == 0) {
                if (headerRead != headerSize) {
                    throw new IllegalArgumentException(
                            "Item key:" + key
                            + " headerRead:" + headerRead + " != headerSize:" + headerSize);
                }
            } else {
                // future versions should only increase header size
                // by adding to the end.
                if (headerRead > headerSize) {
                    throw new IllegalArgumentException(
                            "Item key:" + key
                            + " headerRead:" + headerRead + " > headerSize:" + headerSize);
                } else if (headerRead < headerSize) {
                    buffer.position(headerSize);
                }
            }

            // Body always starts with properties.
            final int propertyCount = buffer.getInt();
            if (propertyCount < 0) {
                throw new IllegalArgumentException(
                        "Cannot have more than " + Integer.MAX_VALUE + " properties");
            }
            bundle.putInt(BUNDLE_TOTAL_SIZE, totalSize);
            bundle.putInt(BUNDLE_HEADER_SIZE, headerSize);
            bundle.putChar(BUNDLE_VERSION, version);
            bundle.putChar(BUNDLE_KEY_SIZE, keySize);
            bundle.putString(BUNDLE_KEY, key);
            bundle.putInt(BUNDLE_PID, pid);
            bundle.putInt(BUNDLE_UID, uid);
            bundle.putLong(BUNDLE_TIMESTAMP, timestamp);
            bundle.putInt(BUNDLE_PROPERTY_COUNT, propertyCount);

            for (int i = 0; i < propertyCount; ++i) {
                final int initialBufferPosition = buffer.position();
                final char propSize = buffer.getChar();
                final byte type = buffer.get();

                // Log.d(TAG, "(" + i + ") propSize:" + ((int)propSize) + " type:" + type);
                final String propKey = getStringFromBuffer(buffer);
                switch (type) {
                    case TYPE_INT32:
                        bundle.putInt(propKey, buffer.getInt());
                        break;
                    case TYPE_INT64:
                        bundle.putLong(propKey, buffer.getLong());
                        break;
                    case TYPE_DOUBLE:
                        bundle.putDouble(propKey, buffer.getDouble());
                        break;
                    case TYPE_CSTRING:
                        bundle.putString(propKey, getStringFromBuffer(buffer));
                        break;
                    case TYPE_NONE:
                        break; // ignore on Java side
                    case TYPE_RATE:
                        buffer.getLong();  // consume the first int64_t of rate
                        buffer.getLong();  // consume the second int64_t of rate
                        break; // ignore on Java side
                    default:
                        // These are unsupported types for version 0
                        // We ignore them if the version is greater than 0.
                        if (version == 0) {
                            throw new IllegalArgumentException(
                                    "Property " + propKey + " has unsupported type " + type);
                        }
                        buffer.position(initialBufferPosition + propSize); // advance and skip
                        break;
                }
                final int deltaPosition = buffer.position() - initialBufferPosition;
                if (deltaPosition != propSize) {
                    throw new IllegalArgumentException("propSize:" + propSize
                        + " != deltaPosition:" + deltaPosition);
                }
            }

            final int finalPosition = buffer.position();
            if (finalPosition != totalSize) {
                throw new IllegalArgumentException("totalSize:" + totalSize
                    + " != finalPosition:" + finalPosition);
            }
            return bundle;
        }

        // Version 0 byte offsets for the header.
        private static final int FORMAT_VERSION = 0;
        private static final int TOTAL_SIZE_OFFSET = 0;
        private static final int HEADER_SIZE_OFFSET = 4;
        private static final int MINIMUM_PAYLOAD_SIZE = 4;
        private final int mPidOffset;            // computed in constructor
        private final int mUidOffset;            // computed in constructor
        private final int mTimeNsOffset;         // computed in constructor
        private final int mPropertyCountOffset;  // computed in constructor
        private final int mPropertyStartOffset;  // computed in constructor
        private final int mHeaderSize;           // computed in constructor

        private final String mKey;

        private ByteBuffer mBuffer;     // may be reallocated if capacity is insufficient.
        private int mPropertyCount = 0; // overflow not checked (mBuffer would overflow first).

        private int reserveProperty(byte[] keyBytes, int payloadSize) {
            final int keyLength = keyBytes.length;
            if (keyLength > Character.MAX_VALUE) {
                throw new IllegalStateException("property key too long "
                        + new String(keyBytes, MEDIAMETRICS_CHARSET));
            }
            if (payloadSize > Character.MAX_VALUE) {
                throw new IllegalStateException("payload too large " + payloadSize);
            }

            // See the byte string property format above.
            final int size = 2      /* length */
                    + 1             /* type */
                    + keyLength + 1 /* key length with zero termination */
                    + payloadSize;  /* payload size */

            if (size > Character.MAX_VALUE) {
                throw new IllegalStateException("Item property "
                        + new String(keyBytes, MEDIAMETRICS_CHARSET) + " is too large to send");
            }

            if (mBuffer.remaining() < size) {
                int newCapacity = mBuffer.position() + size;
                if (newCapacity > Integer.MAX_VALUE >> 1) {
                    throw new IllegalStateException(
                        "Item memory requirements too large: " + newCapacity);
                }
                newCapacity <<= 1;
                ByteBuffer buffer = ByteBuffer.allocateDirect(newCapacity);
                buffer.order(ByteOrder.nativeOrder());

                // Copy data from old buffer to new buffer.
                mBuffer.flip();
                buffer.put(mBuffer);

                // set buffer to new buffer
                mBuffer = buffer;
            }
            return size;
        }

        // Used for test
        private static String getStringFromBuffer(ByteBuffer buffer) {
            return getStringFromBuffer(buffer, Integer.MAX_VALUE);
        }

        // Used for test
        private static String getStringFromBuffer(ByteBuffer buffer, int size) {
            int i = buffer.position();
            int limit = buffer.limit();
            if (size < Integer.MAX_VALUE - i && i + size < limit) {
                limit = i + size;
            }
            for (; i < limit; ++i) {
                if (buffer.get(i) == 0) {
                    final int newPosition = i + 1;
                    if (size != Integer.MAX_VALUE && newPosition - buffer.position() != size) {
                        throw new IllegalArgumentException("chars consumed at " + i + ": "
                            + (newPosition - buffer.position()) + " != size: " + size);
                    }
                    final String found;
                    if (buffer.hasArray()) {
                        found = new String(
                            buffer.array(), buffer.position() + buffer.arrayOffset(),
                            i - buffer.position(), MEDIAMETRICS_CHARSET);
                        buffer.position(newPosition);
                    } else {
                        final byte[] array = new byte[i - buffer.position()];
                        buffer.get(array);
                        found = new String(array, MEDIAMETRICS_CHARSET);
                        buffer.get(); // remove 0.
                    }
                    return found;
                }
            }
            throw new IllegalArgumentException(
                    "No zero termination found in string position: "
                    + buffer.position() + " end: " + i);
        }

        /**
         * May be called multiple times - just makes the header consistent with the current
         * properties written.
         */
        private void updateHeader() {
            // Buffer sized properly in constructor.
            mBuffer.putInt(TOTAL_SIZE_OFFSET, mBuffer.position())      // set total length
                .putInt(mPropertyCountOffset, (char) mPropertyCount); // set number of properties
        }
    }

    private static native int native_submit_bytebuffer(@NonNull ByteBuffer buffer, int length);
}
