Home | History | Annotate | Download | only in LogWrapper
      1 /** Log wrapper for Android.
      2  * @{
      3  * @file
      4  *
      5  * Maps LOG_*() macros to __android_log_print() if LOG_ANDROID is defined.
      6  * Adds some extra info to log output like LOG_TAG, file name and line number.
      7  *
      8  * <!-- Copyright Giesecke & Devrient GmbH 2010 - 2011 -->
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  * 3. The name of the author may not be used to endorse or promote
     19  *    products derived from this software without specific prior
     20  *    written permission.
     21  *
     22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
     23  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     24  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
     26  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     28  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     30  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     31  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     33  */
     34 #ifndef TLCWRAPPERANDROIDLOG_H_
     35 #define TLCWRAPPERANDROIDLOG_H_
     36 
     37 #include <unistd.h>
     38 #include <stdio.h>
     39 #include <android/log.h>
     40 
     41 /** LOG_I(fmt, args...)
     42  * Informative logging, only shown in debug version
     43  */
     44 
     45 /** LOG_W(fmt, args...)
     46  * Warnings logging, only shown in debug version
     47  */
     48 
     49 /** LOG_E(fmt, args...)
     50  * Error logging, shown in debug and release version
     51  */
     52 
     53 /** LOG_V(fmt, args...)
     54  * Verbose logging, shown in debug version if the including file defines LOG_VERBOSE
     55  */
     56 
     57 /** LOG_I_BUF(szDescriptor, blob, sizeOfBlob)
     58  * Binary logging, line-wise output to LOG_I
     59  */
     60 
     61 #define EOL "\n"
     62 #define DUMMY_FUNCTION()    do{}while(0)
     63 
     64 #ifdef LOG_ANDROID
     65 // log to adb logcat
     66 #ifdef NDEBUG // no logging in debug version
     67     #define LOG_I(fmt, args...) DUMMY_FUNCTION()
     68     #define LOG_W(fmt, args...) DUMMY_FUNCTION()
     69 #else
     70     // add LINE
     71     #define LOG_I(fmt, args...) LOG_i(fmt";%d", ## args, __LINE__)
     72     #define LOG_W(fmt, args...) LOG_w(fmt";%d", ## args, __LINE__)
     73 #endif
     74     // LOG_E is always defined
     75     #define _LOG_E(fmt, args...) LOG_e(fmt, ## args)
     76 
     77     // actually mapping to log system, adding level and tag.
     78     #define LOG_i(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
     79     #define LOG_w(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
     80     #define LOG_e(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
     81 
     82 #else //!defined(LOG_ANDROID)
     83 // log to std.out using printf
     84 
     85     // #level / #LOG_TAG ( process_id): __VA_ARGS__
     86     // Example:
     87     // I/McDrvBasicTest_0_1( 4075): setUp
     88     #define _LOG_x(_x_,...) \
     89                 do \
     90                 { \
     91                     printf("%s/%s(%d): ",_x_,LOG_TAG,getpid()); \
     92                     printf(__VA_ARGS__); \
     93                     printf(EOL); \
     94                 } while(1!=1)
     95 
     96 
     97 #ifdef NDEBUG // no logging in debug version
     98     #define LOG_I(fmt, args...) DUMMY_FUNCTION()
     99     #define LOG_W(fmt, args...) DUMMY_FUNCTION()
    100 #else
    101     #define LOG_I(...)  _LOG_x("I",__VA_ARGS__)
    102     #define LOG_W(...)  _LOG_x("W",__VA_ARGS__)
    103 #endif
    104     #define _LOG_E(...)  _LOG_x("E",__VA_ARGS__)
    105 
    106 #endif //defined(LOG_ANDROID)
    107 
    108 #if defined(LOG_VERBOSE)
    109 #define LOG_V LOG_I
    110 #else
    111 #define LOG_V(...) DUMMY_FUNCTION()
    112 #endif
    113 
    114 /** LOG_E() needs to be more prominent:
    115  * Display "*********** ERROR ***********" before actual error message.
    116  */
    117 #define LOG_E(...) \
    118             do \
    119             { \
    120                 _LOG_E("  *****************************"); \
    121                 _LOG_E("  *** ERROR: "__VA_ARGS__); \
    122                 _LOG_E("  *** Detected in %s:%i/%s()", __FILE__, __LINE__, __FUNCTION__); \
    123                 _LOG_E("  *****************************"); \
    124             } while(1!=1)
    125 
    126 #define LOG_ERRNO(MESSAGE) \
    127     LOG_E("%s failed with \"%s\"(errno %i)", MESSAGE, strerror(errno), errno);
    128 
    129 #define LOG_I_BUF   LOG_I_Buf
    130 
    131 __attribute__ ((unused))
    132 static void LOG_I_Buf(
    133 	const char *  szDescriptor,
    134 	const void *  blob,
    135 	size_t        sizeOfBlob
    136 ) {
    137 
    138 	#define CPL         0x10  // chars per line
    139 	#define OVERHEAD    20
    140 
    141 	char buffer[CPL * 4 + OVERHEAD];
    142 
    143 	uint32_t index = 0;
    144 
    145 	uint32_t moreThanOneLine = (sizeOfBlob > CPL);
    146 	uint32_t blockLen = CPL;
    147 	uint32_t addr = 0;
    148 	uint32_t i = 0;
    149 
    150 	if (NULL != szDescriptor)
    151 	{
    152 		index += sprintf(&buffer[index], "%s", szDescriptor);
    153 	}
    154 
    155 	if (moreThanOneLine)
    156 	{
    157 		if (NULL == szDescriptor)
    158 		{
    159 			index += sprintf(&buffer[index], "memory dump");
    160 		}
    161 		index += sprintf(&buffer[index], " (0x%08x, %d bytes)", (uint32_t)blob,sizeOfBlob);
    162 		LOG_I("%s", buffer);
    163 		index = 0;
    164 	}
    165 	else if (NULL == szDescriptor)
    166 	{
    167 		index += sprintf(&buffer[index], "Data at 0x%08x: ", (uint32_t)blob);
    168 	}
    169 
    170 	if(sizeOfBlob == 0) {
    171 		LOG_I("%s", buffer);
    172 	}
    173 	else
    174 	{
    175 		while (sizeOfBlob > 0)
    176 		{
    177 			if (sizeOfBlob < blockLen)
    178 			{
    179 				blockLen = sizeOfBlob;
    180 			}
    181 
    182 			// address
    183 			if (moreThanOneLine)
    184 			{
    185 				index += sprintf(&buffer[index], "0x%08X | ",addr);
    186 				addr += CPL;
    187 			}
    188 			// bytes as hex
    189 			for (i=0; i<blockLen; ++i)
    190 			{
    191 				index += sprintf(&buffer[index], "%02x ", ((const char *)blob)[i] );
    192 			}
    193 			// spaces if necessary
    194 			if ((blockLen < CPL) && (moreThanOneLine))
    195 			{
    196 				// add spaces
    197 				for (i=0; i<(3*(CPL-blockLen)); ++i) {
    198 				index += sprintf(&buffer[index], " ");
    199 				}
    200 			}
    201 			// bytes as ASCII
    202 			index += sprintf(&buffer[index], "| ");
    203 			for (i=0; i<blockLen; ++i)
    204 			{
    205 				char c = ((const char *)blob)[i];
    206 				index += sprintf(&buffer[index], "%c",(c>32)?c:'.');
    207 			}
    208 
    209 			blob = &(((const char *)blob)[blockLen]);
    210 			sizeOfBlob -= blockLen;
    211 
    212 			// print line to logcat / stdout
    213 			LOG_I("%s", buffer);
    214 			index = 0;
    215 		}
    216 	}
    217 }
    218 
    219 #endif /** TLCWRAPPERANDROIDLOG_H_ */
    220 
    221 /** @} */
    222