1401caaedd871894620accc1d14592c08095b5523Adrian Roos/* 2401caaedd871894620accc1d14592c08095b5523Adrian Roos * Copyright (C) 2016 The Android Open Source Project 3401caaedd871894620accc1d14592c08095b5523Adrian Roos * 4401caaedd871894620accc1d14592c08095b5523Adrian Roos * Licensed under the Apache License, Version 2.0 (the "License"); 5401caaedd871894620accc1d14592c08095b5523Adrian Roos * you may not use this file except in compliance with the License. 6401caaedd871894620accc1d14592c08095b5523Adrian Roos * You may obtain a copy of the License at 7401caaedd871894620accc1d14592c08095b5523Adrian Roos * 8401caaedd871894620accc1d14592c08095b5523Adrian Roos * http://www.apache.org/licenses/LICENSE-2.0 9401caaedd871894620accc1d14592c08095b5523Adrian Roos * 10401caaedd871894620accc1d14592c08095b5523Adrian Roos * Unless required by applicable law or agreed to in writing, software 11401caaedd871894620accc1d14592c08095b5523Adrian Roos * distributed under the License is distributed on an "AS IS" BASIS, 12401caaedd871894620accc1d14592c08095b5523Adrian Roos * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13401caaedd871894620accc1d14592c08095b5523Adrian Roos * See the License for the specific language governing permissions and 14401caaedd871894620accc1d14592c08095b5523Adrian Roos * limitations under the License 15401caaedd871894620accc1d14592c08095b5523Adrian Roos */ 16401caaedd871894620accc1d14592c08095b5523Adrian Roos 17401caaedd871894620accc1d14592c08095b5523Adrian Roospackage com.android.systemui.classifier; 18401caaedd871894620accc1d14592c08095b5523Adrian Roos 19401caaedd871894620accc1d14592c08095b5523Adrian Roosimport android.app.ActivityThread; 20401caaedd871894620accc1d14592c08095b5523Adrian Roosimport android.app.Application; 21401caaedd871894620accc1d14592c08095b5523Adrian Roosimport android.os.Build; 22401caaedd871894620accc1d14592c08095b5523Adrian Roosimport android.os.SystemProperties; 23401caaedd871894620accc1d14592c08095b5523Adrian Roosimport android.util.Log; 24401caaedd871894620accc1d14592c08095b5523Adrian Roos 25401caaedd871894620accc1d14592c08095b5523Adrian Roosimport java.io.File; 26401caaedd871894620accc1d14592c08095b5523Adrian Roosimport java.io.FileNotFoundException; 27401caaedd871894620accc1d14592c08095b5523Adrian Roosimport java.io.FileOutputStream; 28401caaedd871894620accc1d14592c08095b5523Adrian Roosimport java.io.IOException; 29401caaedd871894620accc1d14592c08095b5523Adrian Roosimport java.io.PrintWriter; 30401caaedd871894620accc1d14592c08095b5523Adrian Roosimport java.text.SimpleDateFormat; 31401caaedd871894620accc1d14592c08095b5523Adrian Roosimport java.util.ArrayDeque; 32401caaedd871894620accc1d14592c08095b5523Adrian Roosimport java.util.Date; 33401caaedd871894620accc1d14592c08095b5523Adrian Roosimport java.util.Locale; 34401caaedd871894620accc1d14592c08095b5523Adrian Roos 35401caaedd871894620accc1d14592c08095b5523Adrian Roos/** 36401caaedd871894620accc1d14592c08095b5523Adrian Roos * Keeps track of interesting falsing data. 37401caaedd871894620accc1d14592c08095b5523Adrian Roos * 38401caaedd871894620accc1d14592c08095b5523Adrian Roos * By default the log only gets collected on userdebug builds. To turn it on on user: 39401caaedd871894620accc1d14592c08095b5523Adrian Roos * adb shell setprop debug.falsing_log true 40401caaedd871894620accc1d14592c08095b5523Adrian Roos * 41401caaedd871894620accc1d14592c08095b5523Adrian Roos * The log gets dumped as part of the SystemUI services. To dump on demand: 42401caaedd871894620accc1d14592c08095b5523Adrian Roos * adb shell dumpsys activity service com.android.systemui SystemBars | grep -A 999 FALSING | less 43401caaedd871894620accc1d14592c08095b5523Adrian Roos * 44401caaedd871894620accc1d14592c08095b5523Adrian Roos * To dump into logcat: 45401caaedd871894620accc1d14592c08095b5523Adrian Roos * adb shell setprop debug.falsing_logcat true 46401caaedd871894620accc1d14592c08095b5523Adrian Roos * 47401caaedd871894620accc1d14592c08095b5523Adrian Roos * To adjust the log buffer size: 48401caaedd871894620accc1d14592c08095b5523Adrian Roos * adb shell setprop debug.falsing_log_size 200 49401caaedd871894620accc1d14592c08095b5523Adrian Roos */ 50401caaedd871894620accc1d14592c08095b5523Adrian Roospublic class FalsingLog { 51401caaedd871894620accc1d14592c08095b5523Adrian Roos public static final boolean ENABLED = SystemProperties.getBoolean("debug.falsing_log", 52401caaedd871894620accc1d14592c08095b5523Adrian Roos Build.IS_DEBUGGABLE); 53401caaedd871894620accc1d14592c08095b5523Adrian Roos private static final boolean LOGCAT = SystemProperties.getBoolean("debug.falsing_logcat", 54401caaedd871894620accc1d14592c08095b5523Adrian Roos false); 55401caaedd871894620accc1d14592c08095b5523Adrian Roos 56401caaedd871894620accc1d14592c08095b5523Adrian Roos public static final boolean VERBOSE = false; 57401caaedd871894620accc1d14592c08095b5523Adrian Roos 58401caaedd871894620accc1d14592c08095b5523Adrian Roos private static final int MAX_SIZE = SystemProperties.getInt("debug.falsing_log_size", 100); 59401caaedd871894620accc1d14592c08095b5523Adrian Roos 60401caaedd871894620accc1d14592c08095b5523Adrian Roos private static final String TAG = "FalsingLog"; 61401caaedd871894620accc1d14592c08095b5523Adrian Roos 62401caaedd871894620accc1d14592c08095b5523Adrian Roos private final ArrayDeque<String> mLog = new ArrayDeque<>(MAX_SIZE); 63401caaedd871894620accc1d14592c08095b5523Adrian Roos private final SimpleDateFormat mFormat = new SimpleDateFormat("MM-dd HH:mm:ss", Locale.US); 64401caaedd871894620accc1d14592c08095b5523Adrian Roos 65401caaedd871894620accc1d14592c08095b5523Adrian Roos private static FalsingLog sInstance; 66401caaedd871894620accc1d14592c08095b5523Adrian Roos 67401caaedd871894620accc1d14592c08095b5523Adrian Roos private FalsingLog() { 68401caaedd871894620accc1d14592c08095b5523Adrian Roos } 69401caaedd871894620accc1d14592c08095b5523Adrian Roos 70401caaedd871894620accc1d14592c08095b5523Adrian Roos public static void v(String tag, String s) { 71401caaedd871894620accc1d14592c08095b5523Adrian Roos if (!VERBOSE) { 72401caaedd871894620accc1d14592c08095b5523Adrian Roos return; 73401caaedd871894620accc1d14592c08095b5523Adrian Roos } 74401caaedd871894620accc1d14592c08095b5523Adrian Roos if (LOGCAT) { 75401caaedd871894620accc1d14592c08095b5523Adrian Roos Log.v(TAG, tag + "\t" + s); 76401caaedd871894620accc1d14592c08095b5523Adrian Roos } 77401caaedd871894620accc1d14592c08095b5523Adrian Roos log("V", tag, s); 78401caaedd871894620accc1d14592c08095b5523Adrian Roos } 79401caaedd871894620accc1d14592c08095b5523Adrian Roos 80401caaedd871894620accc1d14592c08095b5523Adrian Roos public static void i(String tag, String s) { 81401caaedd871894620accc1d14592c08095b5523Adrian Roos if (LOGCAT) { 82401caaedd871894620accc1d14592c08095b5523Adrian Roos Log.i(TAG, tag + "\t" + s); 83401caaedd871894620accc1d14592c08095b5523Adrian Roos } 84401caaedd871894620accc1d14592c08095b5523Adrian Roos log("I", tag, s); 85401caaedd871894620accc1d14592c08095b5523Adrian Roos } 86401caaedd871894620accc1d14592c08095b5523Adrian Roos 878e291a5d3f6f90072ed91887359567d5640f6170Adrian Roos public static void wLogcat(String tag, String s) { 888e291a5d3f6f90072ed91887359567d5640f6170Adrian Roos Log.w(TAG, tag + "\t" + s); 898e291a5d3f6f90072ed91887359567d5640f6170Adrian Roos log("W", tag, s); 908e291a5d3f6f90072ed91887359567d5640f6170Adrian Roos } 918e291a5d3f6f90072ed91887359567d5640f6170Adrian Roos 92401caaedd871894620accc1d14592c08095b5523Adrian Roos public static void w(String tag, String s) { 93401caaedd871894620accc1d14592c08095b5523Adrian Roos if (LOGCAT) { 94401caaedd871894620accc1d14592c08095b5523Adrian Roos Log.w(TAG, tag + "\t" + s); 95401caaedd871894620accc1d14592c08095b5523Adrian Roos } 96401caaedd871894620accc1d14592c08095b5523Adrian Roos log("W", tag, s); 97401caaedd871894620accc1d14592c08095b5523Adrian Roos } 98401caaedd871894620accc1d14592c08095b5523Adrian Roos 99401caaedd871894620accc1d14592c08095b5523Adrian Roos public static void e(String tag, String s) { 100401caaedd871894620accc1d14592c08095b5523Adrian Roos if (LOGCAT) { 101401caaedd871894620accc1d14592c08095b5523Adrian Roos Log.e(TAG, tag + "\t" + s); 102401caaedd871894620accc1d14592c08095b5523Adrian Roos } 103401caaedd871894620accc1d14592c08095b5523Adrian Roos log("E", tag, s); 104401caaedd871894620accc1d14592c08095b5523Adrian Roos } 105401caaedd871894620accc1d14592c08095b5523Adrian Roos 106401caaedd871894620accc1d14592c08095b5523Adrian Roos public static synchronized void log(String level, String tag, String s) { 107401caaedd871894620accc1d14592c08095b5523Adrian Roos if (!ENABLED) { 108401caaedd871894620accc1d14592c08095b5523Adrian Roos return; 109401caaedd871894620accc1d14592c08095b5523Adrian Roos } 110401caaedd871894620accc1d14592c08095b5523Adrian Roos if (sInstance == null) { 111401caaedd871894620accc1d14592c08095b5523Adrian Roos sInstance = new FalsingLog(); 112401caaedd871894620accc1d14592c08095b5523Adrian Roos } 113401caaedd871894620accc1d14592c08095b5523Adrian Roos 114401caaedd871894620accc1d14592c08095b5523Adrian Roos if (sInstance.mLog.size() >= MAX_SIZE) { 115401caaedd871894620accc1d14592c08095b5523Adrian Roos sInstance.mLog.removeFirst(); 116401caaedd871894620accc1d14592c08095b5523Adrian Roos } 117401caaedd871894620accc1d14592c08095b5523Adrian Roos String entry = new StringBuilder().append(sInstance.mFormat.format(new Date())) 118401caaedd871894620accc1d14592c08095b5523Adrian Roos .append(" ").append(level).append(" ") 119401caaedd871894620accc1d14592c08095b5523Adrian Roos .append(tag).append(" ").append(s).toString(); 120401caaedd871894620accc1d14592c08095b5523Adrian Roos sInstance.mLog.add(entry); 121401caaedd871894620accc1d14592c08095b5523Adrian Roos } 122401caaedd871894620accc1d14592c08095b5523Adrian Roos 123401caaedd871894620accc1d14592c08095b5523Adrian Roos public static synchronized void dump(PrintWriter pw) { 124401caaedd871894620accc1d14592c08095b5523Adrian Roos pw.println("FALSING LOG:"); 125401caaedd871894620accc1d14592c08095b5523Adrian Roos if (!ENABLED) { 126401caaedd871894620accc1d14592c08095b5523Adrian Roos pw.println("Disabled, to enable: setprop debug.falsing_log 1"); 127401caaedd871894620accc1d14592c08095b5523Adrian Roos pw.println(); 128401caaedd871894620accc1d14592c08095b5523Adrian Roos return; 129401caaedd871894620accc1d14592c08095b5523Adrian Roos } 130401caaedd871894620accc1d14592c08095b5523Adrian Roos if (sInstance == null || sInstance.mLog.isEmpty()) { 131401caaedd871894620accc1d14592c08095b5523Adrian Roos pw.println("<empty>"); 132401caaedd871894620accc1d14592c08095b5523Adrian Roos pw.println(); 133401caaedd871894620accc1d14592c08095b5523Adrian Roos return; 134401caaedd871894620accc1d14592c08095b5523Adrian Roos } 135401caaedd871894620accc1d14592c08095b5523Adrian Roos for (String s : sInstance.mLog) { 136401caaedd871894620accc1d14592c08095b5523Adrian Roos pw.println(s); 137401caaedd871894620accc1d14592c08095b5523Adrian Roos } 138401caaedd871894620accc1d14592c08095b5523Adrian Roos pw.println(); 139401caaedd871894620accc1d14592c08095b5523Adrian Roos } 140401caaedd871894620accc1d14592c08095b5523Adrian Roos 1418e291a5d3f6f90072ed91887359567d5640f6170Adrian Roos public static synchronized void wtf(String tag, String s, Throwable here) { 142401caaedd871894620accc1d14592c08095b5523Adrian Roos if (!ENABLED) { 143401caaedd871894620accc1d14592c08095b5523Adrian Roos return; 144401caaedd871894620accc1d14592c08095b5523Adrian Roos } 145401caaedd871894620accc1d14592c08095b5523Adrian Roos e(tag, s); 146401caaedd871894620accc1d14592c08095b5523Adrian Roos 147401caaedd871894620accc1d14592c08095b5523Adrian Roos Application application = ActivityThread.currentApplication(); 148401caaedd871894620accc1d14592c08095b5523Adrian Roos String fileMessage = ""; 149401caaedd871894620accc1d14592c08095b5523Adrian Roos if (Build.IS_DEBUGGABLE && application != null) { 150401caaedd871894620accc1d14592c08095b5523Adrian Roos File f = new File(application.getDataDir(), "falsing-" 151401caaedd871894620accc1d14592c08095b5523Adrian Roos + new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()) + ".txt"); 152401caaedd871894620accc1d14592c08095b5523Adrian Roos PrintWriter pw = null; 153401caaedd871894620accc1d14592c08095b5523Adrian Roos try { 154401caaedd871894620accc1d14592c08095b5523Adrian Roos pw = new PrintWriter(f); 155401caaedd871894620accc1d14592c08095b5523Adrian Roos dump(pw); 156401caaedd871894620accc1d14592c08095b5523Adrian Roos pw.close(); 157401caaedd871894620accc1d14592c08095b5523Adrian Roos fileMessage = "Log written to " + f.getAbsolutePath(); 158401caaedd871894620accc1d14592c08095b5523Adrian Roos } catch (IOException e) { 159401caaedd871894620accc1d14592c08095b5523Adrian Roos Log.e(TAG, "Unable to write falsing log", e); 160401caaedd871894620accc1d14592c08095b5523Adrian Roos } finally { 161401caaedd871894620accc1d14592c08095b5523Adrian Roos if (pw != null) { 162401caaedd871894620accc1d14592c08095b5523Adrian Roos pw.close(); 163401caaedd871894620accc1d14592c08095b5523Adrian Roos } 164401caaedd871894620accc1d14592c08095b5523Adrian Roos } 165401caaedd871894620accc1d14592c08095b5523Adrian Roos } else { 166401caaedd871894620accc1d14592c08095b5523Adrian Roos Log.e(TAG, "Unable to write log, build must be debuggable."); 167401caaedd871894620accc1d14592c08095b5523Adrian Roos } 168401caaedd871894620accc1d14592c08095b5523Adrian Roos 1698e291a5d3f6f90072ed91887359567d5640f6170Adrian Roos Log.wtf(TAG, tag + " " + s + "; " + fileMessage, here); 170401caaedd871894620accc1d14592c08095b5523Adrian Roos } 171401caaedd871894620accc1d14592c08095b5523Adrian Roos} 172