1011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi/*
2011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi * Copyright (C) 2017 The Android Open Source Project
3011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi *
4011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License");
5011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi * you may not use this file except in compliance with the License.
6011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi * You may obtain a copy of the License at
7011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi *
8011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi *      http://www.apache.org/licenses/LICENSE-2.0
9011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi *
10011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi * Unless required by applicable law or agreed to in writing, software
11011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS,
12011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi * See the License for the specific language governing permissions and
14011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi * limitations under the License.
15011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi */
16011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi
17011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivipackage com.android.server.audio;
18011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi
1974a5596a8aeb4c112a6c024e9613d58ba662a5b5Jean-Michel Triviimport android.util.Log;
2074a5596a8aeb4c112a6c024e9613d58ba662a5b5Jean-Michel Trivi
21011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Triviimport java.io.PrintWriter;
22011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Triviimport java.text.SimpleDateFormat;
23011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Triviimport java.util.Date;
24011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Triviimport java.util.LinkedList;
25011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi
26011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivipublic class AudioEventLogger {
27011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi
28011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi    // ring buffer of events to log.
29011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi    private final LinkedList<Event> mEvents;
30011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi
31011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi    private final String mTitle;
32011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi
33011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi    // the maximum number of events to keep in log
34011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi    private final int mMemSize;
35011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi
36011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi    public static abstract class Event {
37011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi        // formatter for timestamps
38011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi        private final static SimpleDateFormat sFormat = new SimpleDateFormat("MM-dd HH:mm:ss:SSS");
39011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi
40011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi        private final long mTimestamp;
41011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi
42011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi        Event() {
43011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi            mTimestamp = System.currentTimeMillis();
44011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi        }
45011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi
46011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi        public String toString() {
47011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi            return (new StringBuilder(sFormat.format(new Date(mTimestamp))))
48011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi                    .append(" ").append(eventToString()).toString();
49011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi        }
50011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi
51011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi        /**
520b67b9fad6733492ffab238a5ba12b98a696ef0cJean-Michel Trivi         * Causes the string message for the event to appear in the logcat.
5374a5596a8aeb4c112a6c024e9613d58ba662a5b5Jean-Michel Trivi         * Here is an example of how to create a new event (a StringEvent), adding it to the logger
540b67b9fad6733492ffab238a5ba12b98a696ef0cJean-Michel Trivi         * (an instance of AudioEventLogger) while also making it show in the logcat:
5574a5596a8aeb4c112a6c024e9613d58ba662a5b5Jean-Michel Trivi         * <pre>
5674a5596a8aeb4c112a6c024e9613d58ba662a5b5Jean-Michel Trivi         *     myLogger.log(
5774a5596a8aeb4c112a6c024e9613d58ba662a5b5Jean-Michel Trivi         *         (new StringEvent("something for logcat and logger")).printLog(MyClass.TAG) );
5874a5596a8aeb4c112a6c024e9613d58ba662a5b5Jean-Michel Trivi         * </pre>
5974a5596a8aeb4c112a6c024e9613d58ba662a5b5Jean-Michel Trivi         * @param tag the tag for the android.util.Log.v
6074a5596a8aeb4c112a6c024e9613d58ba662a5b5Jean-Michel Trivi         * @return the same instance of the event
6174a5596a8aeb4c112a6c024e9613d58ba662a5b5Jean-Michel Trivi         */
6274a5596a8aeb4c112a6c024e9613d58ba662a5b5Jean-Michel Trivi        public Event printLog(String tag) {
630b67b9fad6733492ffab238a5ba12b98a696ef0cJean-Michel Trivi            Log.i(tag, eventToString());
6474a5596a8aeb4c112a6c024e9613d58ba662a5b5Jean-Michel Trivi            return this;
6574a5596a8aeb4c112a6c024e9613d58ba662a5b5Jean-Michel Trivi        }
6674a5596a8aeb4c112a6c024e9613d58ba662a5b5Jean-Michel Trivi
6774a5596a8aeb4c112a6c024e9613d58ba662a5b5Jean-Michel Trivi        /**
68011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi         * Convert event to String.
69011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi         * This method is only called when the logger history is about to the dumped,
70011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi         * so this method is where expensive String conversions should be made, not when the Event
71011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi         * subclass is created.
72011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi         * Timestamp information will be automatically added, do not include it.
73011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi         * @return a string representation of the event that occurred.
74011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi         */
75011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi        abstract public String eventToString();
76011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi    }
77011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi
78011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi    public static class StringEvent extends Event {
79011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi        private final String mMsg;
80011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi
81011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi        public StringEvent(String msg) {
82011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi            mMsg = msg;
83011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi        }
84011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi
85011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi        @Override
86011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi        public String eventToString() {
87011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi            return mMsg;
88011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi        }
89011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi    }
90011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi
91011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi    /**
92011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi     * Constructor for logger.
93011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi     * @param size the maximum number of events to keep in log
94011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi     * @param title the string displayed before the recorded log
95011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi     */
96011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi    public AudioEventLogger(int size, String title) {
97011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi        mEvents = new LinkedList<Event>();
98011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi        mMemSize = size;
99011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi        mTitle = title;
100011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi    }
101011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi
102011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi    public synchronized void log(Event evt) {
103011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi        if (mEvents.size() >= mMemSize) {
104011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi            mEvents.removeFirst();
105011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi        }
106011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi        mEvents.add(evt);
107011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi    }
108011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi
109011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi    public synchronized void dump(PrintWriter pw) {
110011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi        pw.println("Audio event log: " + mTitle);
111011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi        for (Event evt : mEvents) {
112011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi            pw.println(evt.toString());
113011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi        }
114011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi    }
115011f39e7c7a16424260310fb9f580c727b72e8d8Jean-Michel Trivi}
116