• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.audio;
18 
19 import android.annotation.IntDef;
20 import android.util.Log;
21 
22 import java.io.PrintWriter;
23 import java.lang.annotation.Retention;
24 import java.lang.annotation.RetentionPolicy;
25 import java.text.SimpleDateFormat;
26 import java.util.Date;
27 import java.util.LinkedList;
28 
29 public class AudioEventLogger {
30 
31     // ring buffer of events to log.
32     private final LinkedList<Event> mEvents;
33 
34     private final String mTitle;
35 
36     // the maximum number of events to keep in log
37     private final int mMemSize;
38 
39     public static abstract class Event {
40         // formatter for timestamps
41         private final static SimpleDateFormat sFormat = new SimpleDateFormat("MM-dd HH:mm:ss:SSS");
42 
43         private final long mTimestamp;
44 
Event()45         Event() {
46             mTimestamp = System.currentTimeMillis();
47         }
48 
toString()49         public String toString() {
50             return (new StringBuilder(sFormat.format(new Date(mTimestamp))))
51                     .append(" ").append(eventToString()).toString();
52         }
53 
54         /**
55          * Causes the string message for the event to appear in the logcat.
56          * Here is an example of how to create a new event (a StringEvent), adding it to the logger
57          * (an instance of AudioEventLogger) while also making it show in the logcat:
58          * <pre>
59          *     myLogger.log(
60          *         (new StringEvent("something for logcat and logger")).printLog(MyClass.TAG) );
61          * </pre>
62          * @param tag the tag for the android.util.Log.v
63          * @return the same instance of the event
64          */
printLog(String tag)65         public Event printLog(String tag) {
66             return printLog(ALOGI, tag);
67         }
68 
69         /** @hide */
70         @IntDef(flag = false, value = {
71                 ALOGI,
72                 ALOGE,
73                 ALOGW,
74                 ALOGV }
75         )
76         @Retention(RetentionPolicy.SOURCE)
77         public @interface LogType {}
78 
79         public static final int ALOGI = 0;
80         public static final int ALOGE = 1;
81         public static final int ALOGW = 2;
82         public static final int ALOGV = 3;
83 
84         /**
85          * Same as {@link #printLog(String)} with a log type
86          * @param type one of {@link #ALOGI}, {@link #ALOGE}, {@link #ALOGV}
87          * @param tag
88          * @return
89          */
printLog(@ogType int type, String tag)90         public Event printLog(@LogType int type, String tag) {
91             switch (type) {
92                 case ALOGI:
93                     Log.i(tag, eventToString());
94                     break;
95                 case ALOGE:
96                     Log.e(tag, eventToString());
97                     break;
98                 case ALOGW:
99                     Log.w(tag, eventToString());
100                     break;
101                 case ALOGV:
102                 default:
103                     Log.v(tag, eventToString());
104                     break;
105             }
106             return this;
107         }
108 
109         /**
110          * Convert event to String.
111          * This method is only called when the logger history is about to the dumped,
112          * so this method is where expensive String conversions should be made, not when the Event
113          * subclass is created.
114          * Timestamp information will be automatically added, do not include it.
115          * @return a string representation of the event that occurred.
116          */
eventToString()117         abstract public String eventToString();
118     }
119 
120     public static class StringEvent extends Event {
121         private final String mMsg;
122 
StringEvent(String msg)123         public StringEvent(String msg) {
124             mMsg = msg;
125         }
126 
127         @Override
eventToString()128         public String eventToString() {
129             return mMsg;
130         }
131     }
132 
133     /**
134      * Constructor for logger.
135      * @param size the maximum number of events to keep in log
136      * @param title the string displayed before the recorded log
137      */
AudioEventLogger(int size, String title)138     public AudioEventLogger(int size, String title) {
139         mEvents = new LinkedList<Event>();
140         mMemSize = size;
141         mTitle = title;
142     }
143 
log(Event evt)144     public synchronized void log(Event evt) {
145         if (mEvents.size() >= mMemSize) {
146             mEvents.removeFirst();
147         }
148         mEvents.add(evt);
149     }
150 
151     /**
152      * Add a string-based event to the log, and print it to logcat as info.
153      * @param msg the message for the logs
154      * @param tag the logcat tag to use
155      */
loglogi(String msg, String tag)156     public synchronized void loglogi(String msg, String tag) {
157         final Event event = new StringEvent(msg);
158         log(event.printLog(tag));
159     }
160 
161     /**
162      * Same as {@link #loglogi(String, String)} but specifying the logcat type
163      * @param msg the message for the logs
164      * @param logType the type of logcat entry
165      * @param tag the logcat tag to use
166      */
loglog(String msg, @Event.LogType int logType, String tag)167     public synchronized void loglog(String msg, @Event.LogType int logType, String tag) {
168         final Event event = new StringEvent(msg);
169         log(event.printLog(logType, tag));
170     }
171 
dump(PrintWriter pw)172     public synchronized void dump(PrintWriter pw) {
173         pw.println("Audio event log: " + mTitle);
174         for (Event evt : mEvents) {
175             pw.println(evt.toString());
176         }
177     }
178 }
179