1 /* 2 * Copyright 2020 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 androidx.camera.camera2.pipe.core 18 19 import android.util.Log 20 21 /** 22 * This object provides a set of common log functions that are optimized for CameraPipe with options 23 * to control which log levels are available to log at compile time via const val's. 24 * 25 * Log functions have been designed so that printing variables and doing string concatenation will 26 * not occur if the log level is disabled, which leads to slightly unusual syntax: 27 * 28 * Log.debug { "This is a log message with a $value" } 29 */ 30 public object Log { 31 public const val TAG: String = "CXCP" 32 33 private const val LOG_LEVEL_DEBUG = 1 34 private const val LOG_LEVEL_INFO = 2 35 private const val LOG_LEVEL_WARN = 3 36 private const val LOG_LEVEL_ERROR = 4 37 38 // This indicates the lowest log level that will always log. 39 private const val LOG_LEVEL = LOG_LEVEL_DEBUG 40 41 public val DEBUG_LOGGABLE: Boolean = 42 LOG_LEVEL <= LOG_LEVEL_DEBUG || Log.isLoggable(TAG, Log.DEBUG) 43 public val INFO_LOGGABLE: Boolean = LOG_LEVEL <= LOG_LEVEL_INFO || Log.isLoggable(TAG, Log.INFO) 44 public val WARN_LOGGABLE: Boolean = LOG_LEVEL <= LOG_LEVEL_WARN || Log.isLoggable(TAG, Log.WARN) 45 public val ERROR_LOGGABLE: Boolean = 46 LOG_LEVEL <= LOG_LEVEL_ERROR || Log.isLoggable(TAG, Log.ERROR) 47 48 /** Debug functions log noisy information related to the internals of the system. */ debugnull49 public inline fun debug(crossinline msg: () -> String) { 50 if (Debug.ENABLE_LOGGING && DEBUG_LOGGABLE) Log.d(TAG, msg()) 51 } 52 debugnull53 public inline fun debug(throwable: Throwable, crossinline msg: () -> String) { 54 if (Debug.ENABLE_LOGGING && DEBUG_LOGGABLE) Log.d(TAG, msg(), throwable) 55 } 56 57 /** Info functions log standard, useful information about the state of the system. */ infonull58 public inline fun info(crossinline msg: () -> String) { 59 if (Debug.ENABLE_LOGGING && INFO_LOGGABLE) Log.i(TAG, msg()) 60 } 61 infonull62 public inline fun info(throwable: Throwable, crossinline msg: () -> String) { 63 if (Debug.ENABLE_LOGGING && INFO_LOGGABLE) Log.i(TAG, msg(), throwable) 64 } 65 66 /** 67 * Warning functions are used when something unexpected may lead to a crash or fatal exception 68 * later on as a result if the unusual circumstances 69 */ warnnull70 public inline fun warn(crossinline msg: () -> String) { 71 if (Debug.ENABLE_LOGGING && WARN_LOGGABLE) Log.w(TAG, msg()) 72 } 73 warnnull74 public inline fun warn(throwable: Throwable, crossinline msg: () -> String) { 75 if (Debug.ENABLE_LOGGING && WARN_LOGGABLE) Log.w(TAG, msg(), throwable) 76 } 77 78 /** 79 * Error functions are reserved for something unexpected that will lead to a crash or data loss. 80 */ errornull81 public inline fun error(crossinline msg: () -> String) { 82 if (Debug.ENABLE_LOGGING && ERROR_LOGGABLE) Log.e(TAG, msg()) 83 } 84 errornull85 public inline fun error(throwable: Throwable, crossinline msg: () -> String) { 86 if (Debug.ENABLE_LOGGING && ERROR_LOGGABLE) Log.e(TAG, msg(), throwable) 87 } 88 89 /** 90 * Try-catch [block] and rethrow caught exception after logging with [msg]. 91 * 92 * @param msg The message to log with the exception. 93 * @param block Function to be wrapped in try-catch. 94 * @return Original returned value of `block` in case of no exception. 95 * @throws Exception that is caught while executing `block`. 96 */ rethrowExceptionAfterLoggingnull97 public inline fun <T> rethrowExceptionAfterLogging(msg: String, crossinline block: () -> T): T = 98 try { 99 block() 100 } catch (e: Exception) { <lambda>null101 error(e) { msg } 102 throw e 103 } 104 105 /** Read the stack trace of a calling method and join it to a formatted string. */ readStackTracenull106 public fun readStackTrace(limit: Int = 4): String { 107 val elements = Thread.currentThread().stackTrace 108 // Ignore the first 3 elements, which ignores: 109 // VMStack.getThreadStackTrace 110 // Thread.currentThread().getStackTrace() 111 // dumpStackTrace() 112 return elements 113 .drop(3) 114 .joinToString( 115 prefix = "\n\t", 116 separator = "\t", 117 limit = limit, 118 ) 119 } 120 121 /** 122 * Note that the message constants here may be used to parse test data, so these constant values 123 * should be changed with caution. See b/356108571 for details. 124 */ 125 public object MonitoredLogMessages { 126 public const val REPEATING_REQUEST_STARTED_TIMEOUT: String = 127 "awaitStarted on last repeating request timed out" 128 } 129 } 130