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