1 /*
2  * Copyright (C) 2015 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 package com.android.voicemail.impl;
17 
18 import com.android.dialer.common.LogUtil;
19 import com.android.dialer.persistentlog.PersistentLogger;
20 import com.android.voicemail.impl.utils.IndentingPrintWriter;
21 import java.io.FileDescriptor;
22 import java.io.PrintWriter;
23 import java.util.ArrayDeque;
24 import java.util.Calendar;
25 import java.util.Deque;
26 import java.util.Iterator;
27 
28 /** Helper methods for adding to OMTP visual voicemail local logs. */
29 public class VvmLog {
30 
31   private static final int MAX_OMTP_VVM_LOGS = 100;
32 
33   private static final LocalLog localLog = new LocalLog(MAX_OMTP_VVM_LOGS);
34 
log(String tag, String log)35   public static void log(String tag, String log) {
36     PersistentLogger.logText(tag, log);
37   }
38 
dump(FileDescriptor fd, PrintWriter printwriter, String[] args)39   public static void dump(FileDescriptor fd, PrintWriter printwriter, String[] args) {
40     IndentingPrintWriter indentingPrintWriter = new IndentingPrintWriter(printwriter, "  ");
41     indentingPrintWriter.increaseIndent();
42     localLog.dump(fd, indentingPrintWriter, args);
43     indentingPrintWriter.decreaseIndent();
44   }
45 
e(String tag, String log)46   public static void e(String tag, String log) {
47     log(tag, log);
48     LogUtil.e(tag, log);
49   }
50 
e(String tag, String log, Throwable e)51   public static void e(String tag, String log, Throwable e) {
52     log(tag, log + " " + e);
53     LogUtil.e(tag, log, e);
54   }
55 
w(String tag, String log)56   public static void w(String tag, String log) {
57     log(tag, log);
58     LogUtil.w(tag, log);
59   }
60 
w(String tag, String log, Throwable e)61   public static void w(String tag, String log, Throwable e) {
62     log(tag, log + " " + e);
63     LogUtil.w(tag, log, e);
64   }
65 
i(String tag, String log)66   public static void i(String tag, String log) {
67     log(tag, log);
68     LogUtil.i(tag, log);
69   }
70 
i(String tag, String log, Throwable e)71   public static void i(String tag, String log, Throwable e) {
72     log(tag, log + " " + e);
73     LogUtil.i(tag, log, e);
74   }
75 
d(String tag, String log)76   public static void d(String tag, String log) {
77     log(tag, log);
78     LogUtil.d(tag, log);
79   }
80 
d(String tag, String log, Throwable e)81   public static void d(String tag, String log, Throwable e) {
82     log(tag, log + " " + e);
83     LogUtil.d(tag, log, e);
84   }
85 
v(String tag, String log)86   public static void v(String tag, String log) {
87     log(tag, log);
88     LogUtil.v(tag, log);
89   }
90 
v(String tag, String log, Throwable e)91   public static void v(String tag, String log, Throwable e) {
92     log(tag, log + " " + e);
93     LogUtil.v(tag, log, e);
94   }
95 
wtf(String tag, String log)96   public static void wtf(String tag, String log) {
97     log(tag, log);
98     LogUtil.e(tag, log);
99   }
100 
wtf(String tag, String log, Throwable e)101   public static void wtf(String tag, String log, Throwable e) {
102     log(tag, log + " " + e);
103     LogUtil.e(tag, log, e);
104   }
105 
106   /**
107    * Redact personally identifiable information for production users. If we are running in verbose
108    * mode, return the original string, otherwise return a SHA-1 hash of the input string.
109    */
pii(Object pii)110   public static String pii(Object pii) {
111     if (pii == null) {
112       return String.valueOf(pii);
113     }
114     return "[PII]";
115   }
116 
117   public static class LocalLog {
118 
119     private final Deque<String> log;
120     private final int maxLines;
121 
LocalLog(int maxLines)122     public LocalLog(int maxLines) {
123       this.maxLines = Math.max(0, maxLines);
124       log = new ArrayDeque<>(this.maxLines);
125     }
126 
log(String msg)127     public void log(String msg) {
128       if (maxLines <= 0) {
129         return;
130       }
131       Calendar c = Calendar.getInstance();
132       c.setTimeInMillis(System.currentTimeMillis());
133       append(String.format("%tm-%td %tH:%tM:%tS.%tL - %s", c, c, c, c, c, c, msg));
134     }
135 
append(String logLine)136     private synchronized void append(String logLine) {
137       while (log.size() >= maxLines) {
138         log.remove();
139       }
140       log.add(logLine);
141     }
142 
dump(FileDescriptor fd, PrintWriter pw, String[] args)143     public synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
144       Iterator<String> itr = log.iterator();
145       while (itr.hasNext()) {
146         pw.println(itr.next());
147       }
148     }
149 
reverseDump(FileDescriptor fd, PrintWriter pw, String[] args)150     public synchronized void reverseDump(FileDescriptor fd, PrintWriter pw, String[] args) {
151       Iterator<String> itr = log.descendingIterator();
152       while (itr.hasNext()) {
153         pw.println(itr.next());
154       }
155     }
156 
157     public static class ReadOnlyLocalLog {
158 
159       private final LocalLog log;
160 
ReadOnlyLocalLog(LocalLog log)161       ReadOnlyLocalLog(LocalLog log) {
162         this.log = log;
163       }
164 
dump(FileDescriptor fd, PrintWriter pw, String[] args)165       public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
166         log.dump(fd, pw, args);
167       }
168 
reverseDump(FileDescriptor fd, PrintWriter pw, String[] args)169       public void reverseDump(FileDescriptor fd, PrintWriter pw, String[] args) {
170         log.reverseDump(fd, pw, args);
171       }
172     }
173 
readOnlyLocalLog()174     public ReadOnlyLocalLog readOnlyLocalLog() {
175       return new ReadOnlyLocalLog(this);
176     }
177   }
178 }
179