• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 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 android.util;
18 
19 import android.compat.annotation.UnsupportedAppUsage;
20 import android.os.Build;
21 import android.os.SystemClock;
22 
23 import java.io.FileDescriptor;
24 import java.io.PrintWriter;
25 import java.time.Duration;
26 import java.time.Instant;
27 import java.time.LocalDateTime;
28 import java.util.ArrayDeque;
29 import java.util.Deque;
30 import java.util.Iterator;
31 
32 /**
33  * @hide
34  */
35 // Exported to Mainline modules; cannot use annotations
36 // @android.ravenwood.annotation.RavenwoodKeepWholeClass
37 public final class LocalLog {
38 
39     private final Deque<String> mLog;
40     private final int mMaxLines;
41 
42     /**
43      * {@code true} to use log timestamps expressed in local date/time, {@code false} to use log
44      * timestamped expressed with the elapsed realtime clock and UTC system clock. {@code false} is
45      * useful when logging behavior that modifies device time zone or system clock.
46      */
47     private final boolean mUseLocalTimestamps;
48 
49     @UnsupportedAppUsage
LocalLog(int maxLines)50     public LocalLog(int maxLines) {
51         this(maxLines, true /* useLocalTimestamps */);
52     }
53 
LocalLog(int maxLines, boolean useLocalTimestamps)54     public LocalLog(int maxLines, boolean useLocalTimestamps) {
55         mMaxLines = Math.max(0, maxLines);
56         mLog = new ArrayDeque<>(mMaxLines);
57         mUseLocalTimestamps = useLocalTimestamps;
58     }
59 
60     @UnsupportedAppUsage
log(String msg)61     public void log(String msg) {
62         if (mMaxLines <= 0) {
63             return;
64         }
65         final String logLine;
66         if (mUseLocalTimestamps) {
67             logLine = LocalDateTime.now() + " - " + msg;
68         } else {
69             logLine = Duration.ofMillis(SystemClock.elapsedRealtime())
70                     + " / " + Instant.now() + " - " + msg;
71         }
72         append(logLine);
73     }
74 
append(String logLine)75     private synchronized void append(String logLine) {
76         while (mLog.size() >= mMaxLines) {
77             mLog.remove();
78         }
79         mLog.add(logLine);
80     }
81 
82     @UnsupportedAppUsage
dump(FileDescriptor fd, PrintWriter pw, String[] args)83     public synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
84         dump(pw);
85     }
86 
dump(PrintWriter pw)87     public synchronized void dump(PrintWriter pw) {
88         dump("", pw);
89     }
90 
91     /**
92      * Dumps the content of local log to print writer with each log entry predeced with indent
93      *
94      * @param indent indent that precedes each log entry
95      * @param pw printer writer to write into
96      */
dump(String indent, PrintWriter pw)97     public synchronized void dump(String indent, PrintWriter pw) {
98         Iterator<String> itr = mLog.iterator();
99         while (itr.hasNext()) {
100             pw.printf("%s%s\n", indent, itr.next());
101         }
102     }
103 
reverseDump(FileDescriptor fd, PrintWriter pw, String[] args)104     public synchronized void reverseDump(FileDescriptor fd, PrintWriter pw, String[] args) {
105         reverseDump(pw);
106     }
107 
reverseDump(PrintWriter pw)108     public synchronized void reverseDump(PrintWriter pw) {
109         Iterator<String> itr = mLog.descendingIterator();
110         while (itr.hasNext()) {
111             pw.println(itr.next());
112         }
113     }
114 
115     public static class ReadOnlyLocalLog {
116         private final LocalLog mLog;
ReadOnlyLocalLog(LocalLog log)117         ReadOnlyLocalLog(LocalLog log) {
118             mLog = log;
119         }
120         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
dump(FileDescriptor fd, PrintWriter pw, String[] args)121         public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
122             mLog.dump(pw);
123         }
dump(PrintWriter pw)124         public void dump(PrintWriter pw) {
125             mLog.dump(pw);
126         }
reverseDump(FileDescriptor fd, PrintWriter pw, String[] args)127         public void reverseDump(FileDescriptor fd, PrintWriter pw, String[] args) {
128             mLog.reverseDump(pw);
129         }
reverseDump(PrintWriter pw)130         public void reverseDump(PrintWriter pw) {
131             mLog.reverseDump(pw);
132         }
133     }
134 
135     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
readOnlyLocalLog()136     public ReadOnlyLocalLog readOnlyLocalLog() {
137         return new ReadOnlyLocalLog(this);
138     }
139 }
140