1 /* 2 * Copyright (C) 2021 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.car.internal.util; 18 19 import android.os.SystemClock; 20 21 import com.android.internal.annotations.GuardedBy; 22 23 import java.io.FileDescriptor; 24 import java.io.PrintWriter; 25 import java.time.Instant; 26 import java.time.LocalDateTime; 27 import java.util.ArrayDeque; 28 import java.util.Deque; 29 import java.util.Iterator; 30 31 // Copied from frameworks/base 32 /** 33 * Utility for in memory logging 34 * 35 * @hide 36 */ 37 public final class LocalLog { 38 39 private final int mMaxLines; 40 41 private final Object mLock = new Object(); 42 43 @GuardedBy("mLock") 44 private final Deque<String> mLog; 45 46 /** 47 * {@code true} to use log timestamps expressed in local date/time, {@code false} to use log 48 * timestamped expressed with the elapsed realtime clock and UTC system clock. {@code false} is 49 * useful when logging behavior that modifies device time zone or system clock. 50 */ 51 private final boolean mUseLocalTimestamps; 52 53 /** Constructor with max lines limit */ LocalLog(int maxLines)54 public LocalLog(int maxLines) { 55 this(maxLines, true /* useLocalTimestamps */); 56 } 57 58 /** Constructor */ LocalLog(int maxLines, boolean useLocalTimestamps)59 public LocalLog(int maxLines, boolean useLocalTimestamps) { 60 mMaxLines = Math.max(0, maxLines); 61 mLog = new ArrayDeque<>(mMaxLines); 62 mUseLocalTimestamps = useLocalTimestamps; 63 } 64 65 /** Adds log */ log(String msg)66 public void log(String msg) { 67 if (mMaxLines <= 0) { 68 return; 69 } 70 final String logLine; 71 if (mUseLocalTimestamps) { 72 logLine = LocalDateTime.now() + " - " + msg; 73 } else { 74 logLine = SystemClock.elapsedRealtime() + " / " + Instant.now() + " - " + msg; 75 } 76 append(logLine); 77 } 78 79 /** Appends log and trims */ append(String logLine)80 private void append(String logLine) { 81 synchronized (mLock) { 82 while (mLog.size() >= mMaxLines) { 83 mLog.remove(); 84 } 85 mLog.add(logLine); 86 } 87 } 88 89 /** Dumps saved log */ dump(FileDescriptor fd, PrintWriter pw, String[] args)90 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 91 dump(pw); 92 } 93 94 /** Dumps saved log */ dump(PrintWriter pw)95 public void dump(PrintWriter pw) { 96 dump("", pw); 97 } 98 99 /** 100 * Dumps the content of local log to print writer with each log entry predeced with indent 101 * 102 * @param indent indent that precedes each log entry 103 * @param pw printer writer to write into 104 */ dump(String indent, PrintWriter pw)105 public void dump(String indent, PrintWriter pw) { 106 synchronized (mLock) { 107 Iterator<String> itr = mLog.iterator(); 108 while (itr.hasNext()) { 109 pw.printf("%s%s\n", indent, itr.next()); 110 } 111 } 112 } 113 114 /** Dumps saved log in reerse order */ reverseDump(FileDescriptor fd, PrintWriter pw, String[] args)115 public void reverseDump(FileDescriptor fd, PrintWriter pw, String[] args) { 116 reverseDump(pw); 117 } 118 119 /** Dumps saved log in reerse order */ reverseDump(PrintWriter pw)120 public void reverseDump(PrintWriter pw) { 121 synchronized (mLock) { 122 Iterator<String> itr = mLog.descendingIterator(); 123 while (itr.hasNext()) { 124 pw.println(itr.next()); 125 } 126 } 127 } 128 } 129