/*
 * Copyright (C) 2007 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;

import android.annotation.SystemApi;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Access to the system diagnostic event record.  System diagnostic events are
 * used to record certain system-level events (such as garbage collection,
 * activity manager state, system watchdogs, and other low level activity),
 * which may be automatically collected and analyzed during system development.
 *
 * <p>This is <b>not</b> the main "logcat" debugging log ({@link android.util.Log})!
 * These diagnostic events are for system integrators, not application authors.
 *
 * <p>Events use integer tag codes corresponding to /system/etc/event-log-tags.
 * They carry a payload of one or more int, long, or String values.  The
 * event-log-tags file defines the payload contents for each type code.
 */
public class EventLog {
    /** @hide */ public EventLog() {}

    private static final String TAG = "EventLog";

    private static final String TAGS_FILE = "/system/etc/event-log-tags";
    private static final String COMMENT_PATTERN = "^\\s*(#.*)?$";
    private static final String TAG_PATTERN = "^\\s*(\\d+)\\s+(\\w+)\\s*(\\(.*\\))?\\s*$";
    private static HashMap<String, Integer> sTagCodes = null;
    private static HashMap<Integer, String> sTagNames = null;

    /** A previously logged event read from the logs. Instances are thread safe. */
    public static final class Event {
        private final ByteBuffer mBuffer;
        private Exception mLastWtf;

        // Layout of event log entry received from Android logger.
        //  see system/core/include/log/log.h
        private static final int LENGTH_OFFSET = 0;
        private static final int HEADER_SIZE_OFFSET = 2;
        private static final int PROCESS_OFFSET = 4;
        private static final int THREAD_OFFSET = 8;
        private static final int SECONDS_OFFSET = 12;
        private static final int NANOSECONDS_OFFSET = 16;
        private static final int UID_OFFSET = 24;

        // Layout for event log v1 format, v2 and v3 use HEADER_SIZE_OFFSET
        private static final int V1_PAYLOAD_START = 20;
        private static final int DATA_OFFSET = 4;

        // Value types
        private static final byte INT_TYPE    = 0;
        private static final byte LONG_TYPE   = 1;
        private static final byte STRING_TYPE = 2;
        private static final byte LIST_TYPE   = 3;
        private static final byte FLOAT_TYPE = 4;

        /** @param data containing event, read from the system */
        /*package*/ Event(byte[] data) {
            mBuffer = ByteBuffer.wrap(data);
            mBuffer.order(ByteOrder.nativeOrder());
        }

        /** @return the process ID which wrote the log entry */
        public int getProcessId() {
            return mBuffer.getInt(PROCESS_OFFSET);
        }

        /**
         * @return the UID which wrote the log entry
         * @hide
         */
        @SystemApi
        public int getUid() {
            try {
                return mBuffer.getInt(UID_OFFSET);
            } catch (IndexOutOfBoundsException e) {
                // buffer won't contain the UID if the caller doesn't have permission.
                return -1;
            }
        }

        /** @return the thread ID which wrote the log entry */
        public int getThreadId() {
            return mBuffer.getInt(THREAD_OFFSET);
        }

        /** @return the wall clock time when the entry was written */
        public long getTimeNanos() {
            return mBuffer.getInt(SECONDS_OFFSET) * 1000000000l
                    + mBuffer.getInt(NANOSECONDS_OFFSET);
        }

        /** @return the type tag code of the entry */
        public int getTag() {
            int offset = mBuffer.getShort(HEADER_SIZE_OFFSET);
            if (offset == 0) {
                offset = V1_PAYLOAD_START;
            }
            return mBuffer.getInt(offset);
        }

        /** @return one of Integer, Long, Float, String, null, or Object[] of same. */
        public synchronized Object getData() {
            try {
                int offset = mBuffer.getShort(HEADER_SIZE_OFFSET);
                if (offset == 0) {
                    offset = V1_PAYLOAD_START;
                }
                mBuffer.limit(offset + mBuffer.getShort(LENGTH_OFFSET));
                if ((offset + DATA_OFFSET) >= mBuffer.limit()) {
                    // no payload
                    return null;
                }
                mBuffer.position(offset + DATA_OFFSET); // Just after the tag.
                return decodeObject();
            } catch (IllegalArgumentException e) {
                Log.wtf(TAG, "Illegal entry payload: tag=" + getTag(), e);
                mLastWtf = e;
                return null;
            } catch (BufferUnderflowException e) {
                Log.wtf(TAG, "Truncated entry payload: tag=" + getTag(), e);
                mLastWtf = e;
                return null;
            }
        }

        /** @return the loggable item at the current position in mBuffer. */
        private Object decodeObject() {
            byte type = mBuffer.get();
            switch (type) {
            case INT_TYPE:
                return mBuffer.getInt();

            case LONG_TYPE:
                return mBuffer.getLong();

            case FLOAT_TYPE:
                return mBuffer.getFloat();

            case STRING_TYPE:
                try {
                    int length = mBuffer.getInt();
                    int start = mBuffer.position();
                    mBuffer.position(start + length);
                    return new String(mBuffer.array(), start, length, "UTF-8");
                } catch (UnsupportedEncodingException e) {
                    Log.wtf(TAG, "UTF-8 is not supported", e);
                    mLastWtf = e;
                    return null;
                }

            case LIST_TYPE:
                int length = mBuffer.get();
                if (length < 0) length += 256;  // treat as signed byte
                Object[] array = new Object[length];
                for (int i = 0; i < length; ++i) array[i] = decodeObject();
                return array;

            default:
                throw new IllegalArgumentException("Unknown entry type: " + type);
            }
        }

        /** @hide */
        public static Event fromBytes(byte[] data) {
            return new Event(data);
        }

        /** @hide */
        public byte[] getBytes() {
            byte[] bytes = mBuffer.array();
            return Arrays.copyOf(bytes, bytes.length);
        }

        /**
         * Retreive the last WTF error generated by this object.
         * @hide
         */
        //VisibleForTesting
        public Exception getLastError() {
            return mLastWtf;
        }

        /**
         * Clear the error state for this object.
         * @hide
         */
        //VisibleForTesting
        public void clearError() {
            mLastWtf = null;
        }

        /**
         * @hide
         */
        @Override
        public boolean equals(Object o) {
            // Not using ByteBuffer.equals since it takes buffer position into account and we
            // always use absolute positions here.
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Event other = (Event) o;
            return Arrays.equals(mBuffer.array(), other.mBuffer.array());
        }

        /**
         * @hide
         */
        @Override
        public int hashCode() {
            // Not using ByteBuffer.hashCode since it takes buffer position into account and we
            // always use absolute positions here.
            return Arrays.hashCode(mBuffer.array());
        }
    }

    // We assume that the native methods deal with any concurrency issues.

    /**
     * Record an event log message.
     * @param tag The event type tag code
     * @param value A value to log
     * @return The number of bytes written
     */
    public static native int writeEvent(int tag, int value);

    /**
     * Record an event log message.
     * @param tag The event type tag code
     * @param value A value to log
     * @return The number of bytes written
     */
    public static native int writeEvent(int tag, long value);

    /**
     * Record an event log message.
     * @param tag The event type tag code
     * @param value A value to log
     * @return The number of bytes written
     */
    public static native int writeEvent(int tag, float value);

    /**
     * Record an event log message.
     * @param tag The event type tag code
     * @param str A value to log
     * @return The number of bytes written
     */
    public static native int writeEvent(int tag, String str);

    /**
     * Record an event log message.
     * @param tag The event type tag code
     * @param list A list of values to log
     * @return The number of bytes written
     */
    public static native int writeEvent(int tag, Object... list);

    /**
     * Read events from the log, filtered by type.
     * @param tags to search for
     * @param output container to add events into
     * @throws IOException if something goes wrong reading events
     */
    public static native void readEvents(int[] tags, Collection<Event> output)
            throws IOException;

    /**
     * Read events from the log, filtered by type, blocking until logs are about to be overwritten.
     * @param tags to search for
     * @param timestamp timestamp allow logs before this time to be overwritten.
     * @param output container to add events into
     * @throws IOException if something goes wrong reading events
     * @hide
     */
    @SystemApi
    public static native void readEventsOnWrapping(int[] tags, long timestamp,
            Collection<Event> output)
            throws IOException;

    /**
     * Get the name associated with an event type tag code.
     * @param tag code to look up
     * @return the name of the tag, or null if no tag has that number
     */
    public static String getTagName(int tag) {
        readTagsFile();
        return sTagNames.get(tag);
    }

    /**
     * Get the event type tag code associated with an event name.
     * @param name of event to look up
     * @return the tag code, or -1 if no tag has that name
     */
    public static int getTagCode(String name) {
        readTagsFile();
        Integer code = sTagCodes.get(name);
        return code != null ? code : -1;
    }

    /**
     * Read TAGS_FILE, populating sTagCodes and sTagNames, if not already done.
     */
    private static synchronized void readTagsFile() {
        if (sTagCodes != null && sTagNames != null) return;

        sTagCodes = new HashMap<String, Integer>();
        sTagNames = new HashMap<Integer, String>();

        Pattern comment = Pattern.compile(COMMENT_PATTERN);
        Pattern tag = Pattern.compile(TAG_PATTERN);
        BufferedReader reader = null;
        String line;

        try {
            reader = new BufferedReader(new FileReader(TAGS_FILE), 256);
            while ((line = reader.readLine()) != null) {
                if (comment.matcher(line).matches()) continue;

                Matcher m = tag.matcher(line);
                if (!m.matches()) {
                    Log.wtf(TAG, "Bad entry in " + TAGS_FILE + ": " + line);
                    continue;
                }

                try {
                    int num = Integer.parseInt(m.group(1));
                    String name = m.group(2);
                    sTagCodes.put(name, num);
                    sTagNames.put(num, name);
                } catch (NumberFormatException e) {
                    Log.wtf(TAG, "Error in " + TAGS_FILE + ": " + line, e);
                }
            }
        } catch (IOException e) {
            Log.wtf(TAG, "Error reading " + TAGS_FILE, e);
            // Leave the maps existing but unpopulated
        } finally {
            try { if (reader != null) reader.close(); } catch (IOException e) {}
        }
    }
}
