1 /* 2 * Copyright (C) 2010 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 #ifndef A_DEBUG_H_ 18 19 #define A_DEBUG_H_ 20 21 #include <string.h> 22 23 #include <media/stagefright/foundation/ABase.h> 24 #include <media/stagefright/foundation/AString.h> 25 #include <utils/Log.h> 26 27 namespace android { 28 29 inline static const char *asString(status_t i, const char *def = "??") { 30 switch (i) { 31 case NO_ERROR: return "NO_ERROR"; 32 case UNKNOWN_ERROR: return "UNKNOWN_ERROR"; 33 case NO_MEMORY: return "NO_MEMORY"; 34 case INVALID_OPERATION: return "INVALID_OPERATION"; 35 case BAD_VALUE: return "BAD_VALUE"; 36 case BAD_TYPE: return "BAD_TYPE"; 37 case NAME_NOT_FOUND: return "NAME_NOT_FOUND"; 38 case PERMISSION_DENIED: return "PERMISSION_DENIED"; 39 case NO_INIT: return "NO_INIT"; 40 case ALREADY_EXISTS: return "ALREADY_EXISTS"; 41 case DEAD_OBJECT: return "DEAD_OBJECT"; 42 case FAILED_TRANSACTION: return "FAILED_TRANSACTION"; 43 case BAD_INDEX: return "BAD_INDEX"; 44 case NOT_ENOUGH_DATA: return "NOT_ENOUGH_DATA"; 45 case WOULD_BLOCK: return "WOULD_BLOCK"; 46 case TIMED_OUT: return "TIMED_OUT"; 47 case UNKNOWN_TRANSACTION: return "UNKNOWN_TRANSACTION"; 48 case FDS_NOT_ALLOWED: return "FDS_NOT_ALLOWED"; 49 default: return def; 50 } 51 } 52 53 #define LITERAL_TO_STRING_INTERNAL(x) #x 54 #define LITERAL_TO_STRING(x) LITERAL_TO_STRING_INTERNAL(x) 55 56 // allow to use CHECK_OP from android-base/logging.h 57 // TODO: longterm replace this with android-base/logging.h, but there are some nuances, e.g. 58 // android-base CHECK_OP requires a copy constructor, whereas we don't. 59 #ifndef CHECK_OP 60 61 #define CHECK(condition) \ 62 LOG_ALWAYS_FATAL_IF( \ 63 !(condition), \ 64 "%s", \ 65 __FILE__ ":" LITERAL_TO_STRING(__LINE__) \ 66 " CHECK(" #condition ") failed.") 67 68 #define CHECK_OP(x,y,suffix,op) \ 69 do { \ 70 const auto &a = x; \ 71 const auto &b = y; \ 72 if (!(a op b)) { \ 73 AString ___full = \ 74 __FILE__ ":" LITERAL_TO_STRING(__LINE__) \ 75 " CHECK_" #suffix "( " #x "," #y ") failed: "; \ 76 ___full.append(a); \ 77 ___full.append(" vs. "); \ 78 ___full.append(b); \ 79 LOG_ALWAYS_FATAL("%s", ___full.c_str()); \ 80 } \ 81 } while (false) 82 83 #define CHECK_EQ(x,y) CHECK_OP(x,y,EQ,==) 84 #define CHECK_NE(x,y) CHECK_OP(x,y,NE,!=) 85 #define CHECK_LE(x,y) CHECK_OP(x,y,LE,<=) 86 #define CHECK_LT(x,y) CHECK_OP(x,y,LT,<) 87 #define CHECK_GE(x,y) CHECK_OP(x,y,GE,>=) 88 #define CHECK_GT(x,y) CHECK_OP(x,y,GT,>) 89 90 #endif 91 92 #define TRESPASS(...) \ 93 LOG_ALWAYS_FATAL( \ 94 __FILE__ ":" LITERAL_TO_STRING(__LINE__) \ 95 " Should not be here. " __VA_ARGS__); 96 97 #ifdef NDEBUG 98 #define CHECK_DBG CHECK 99 #define CHECK_EQ_DBG CHECK_EQ 100 #define CHECK_NE_DBG CHECK_NE 101 #define CHECK_LE_DBG CHECK_LE 102 #define CHECK_LT_DBG CHECK_LT 103 #define CHECK_GE_DBG CHECK_GE 104 #define CHECK_GT_DBG CHECK_GT 105 #define TRESPASS_DBG TRESPASS 106 #else 107 #define CHECK_DBG(condition) 108 #define CHECK_EQ_DBG(x,y) 109 #define CHECK_NE_DBG(x,y) 110 #define CHECK_LE_DBG(x,y) 111 #define CHECK_LT_DBG(x,y) 112 #define CHECK_GE_DBG(x,y) 113 #define CHECK_GT_DBG(x,y) 114 #define TRESPASS_DBG(...) 115 #endif 116 117 struct ADebug { 118 enum Level { 119 kDebugNone, // no debug 120 kDebugLifeCycle, // lifecycle events: creation/deletion 121 kDebugState, // commands and events 122 kDebugConfig, // configuration 123 kDebugInternalState, // internal state changes 124 kDebugAll, // all 125 kDebugMax = kDebugAll, 126 127 }; 128 129 // parse the property or string to get a long-type level for a component name 130 // string format is: 131 // <level>[:<glob>][,<level>[:<glob>]...] 132 // - <level> is 0-5 corresponding to ADebug::Level 133 // - <glob> is used to match component name case insensitively, if omitted, it 134 // matches all components 135 // - string is read left-to-right, and the last matching level is returned, or 136 // the def if no terms matched 137 static long GetLevelFromSettingsString( 138 const char *name, const char *value, long def); 139 static long GetLevelFromProperty( 140 const char *name, const char *value, long def); 141 142 // same for ADebug::Level - performs clamping to valid debug ranges 143 static Level GetDebugLevelFromProperty( 144 const char *name, const char *propertyName, Level def = kDebugNone); 145 146 // remove redundant segments of a codec name, and return a newly allocated 147 // string suitable for debugging 148 static char *GetDebugName(const char *name); 149 150 inline static bool isExperimentEnabled( 151 const char *name __attribute__((unused)) /* nonnull */, 152 bool allow __attribute__((unused)) = true) { 153 #ifdef ENABLE_STAGEFRIGHT_EXPERIMENTS 154 if (!strcmp(name, "legacy-adaptive")) { 155 return getExperimentFlag(allow, name, 2, 1); // every other day 156 } else if (!strcmp(name, "legacy-setsurface")) { 157 return getExperimentFlag(allow, name, 3, 1); // every third day 158 } else { 159 ALOGE("unknown experiment '%s' (disabled)", name); 160 } 161 #endif 162 return false; 163 } 164 165 private: 166 // pass in allow, so we can print in the log if the experiment is disabled 167 static bool getExperimentFlag( 168 bool allow, const char *name, uint64_t modulo, uint64_t limit, 169 uint64_t plus = 0, uint64_t timeDivisor = 24 * 60 * 60 /* 1 day */); 170 }; 171 172 } // namespace android 173 174 #endif // A_DEBUG_H_ 175 176