/*
 * 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 android.annotation.UnsupportedAppUsage;

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 */
        @UnsupportedAppUsage
        /*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) {}
        }
    }
}
