/* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef A_DEBUG_H_ #define A_DEBUG_H_ #include #include #include #include inline static const char *asString(android::status_t i, const char *def = "??") { using namespace android; switch (i) { case NO_ERROR: return "NO_ERROR"; case UNKNOWN_ERROR: return "UNKNOWN_ERROR"; case NO_MEMORY: return "NO_MEMORY"; case INVALID_OPERATION: return "INVALID_OPERATION"; case BAD_VALUE: return "BAD_VALUE"; case BAD_TYPE: return "BAD_TYPE"; case NAME_NOT_FOUND: return "NAME_NOT_FOUND"; case PERMISSION_DENIED: return "PERMISSION_DENIED"; case NO_INIT: return "NO_INIT"; case ALREADY_EXISTS: return "ALREADY_EXISTS"; case DEAD_OBJECT: return "DEAD_OBJECT"; case FAILED_TRANSACTION: return "FAILED_TRANSACTION"; case BAD_INDEX: return "BAD_INDEX"; case NOT_ENOUGH_DATA: return "NOT_ENOUGH_DATA"; case WOULD_BLOCK: return "WOULD_BLOCK"; case TIMED_OUT: return "TIMED_OUT"; case UNKNOWN_TRANSACTION: return "UNKNOWN_TRANSACTION"; case FDS_NOT_ALLOWED: return "FDS_NOT_ALLOWED"; default: return def; } } namespace android { #define LITERAL_TO_STRING_INTERNAL(x) #x #define LITERAL_TO_STRING(x) LITERAL_TO_STRING_INTERNAL(x) #define CHECK(condition) \ LOG_ALWAYS_FATAL_IF( \ !(condition), \ "%s", \ __FILE__ ":" LITERAL_TO_STRING(__LINE__) \ " CHECK(" #condition ") failed.") #define MAKE_COMPARATOR(suffix,op) \ template \ AString Compare_##suffix(const A &a, const B &b) { \ AString res; \ if (!(a op b)) { \ res.append(a); \ res.append(" vs. "); \ res.append(b); \ } \ return res; \ } MAKE_COMPARATOR(EQ,==) MAKE_COMPARATOR(NE,!=) MAKE_COMPARATOR(LE,<=) MAKE_COMPARATOR(GE,>=) MAKE_COMPARATOR(LT,<) MAKE_COMPARATOR(GT,>) #define CHECK_OP(x,y,suffix,op) \ do { \ AString ___res = Compare_##suffix(x, y); \ if (!___res.empty()) { \ AString ___full = \ __FILE__ ":" LITERAL_TO_STRING(__LINE__) \ " CHECK_" #suffix "( " #x "," #y ") failed: "; \ ___full.append(___res); \ \ LOG_ALWAYS_FATAL("%s", ___full.c_str()); \ } \ } while (false) #define CHECK_EQ(x,y) CHECK_OP(x,y,EQ,==) #define CHECK_NE(x,y) CHECK_OP(x,y,NE,!=) #define CHECK_LE(x,y) CHECK_OP(x,y,LE,<=) #define CHECK_LT(x,y) CHECK_OP(x,y,LT,<) #define CHECK_GE(x,y) CHECK_OP(x,y,GE,>=) #define CHECK_GT(x,y) CHECK_OP(x,y,GT,>) #define TRESPASS() \ LOG_ALWAYS_FATAL( \ __FILE__ ":" LITERAL_TO_STRING(__LINE__) \ " Should not be here."); struct ADebug { enum Level { kDebugNone, // no debug kDebugLifeCycle, // lifecycle events: creation/deletion kDebugState, // commands and events kDebugConfig, // configuration kDebugInternalState, // internal state changes kDebugAll, // all kDebugMax = kDebugAll, }; // parse the property or string to get a long-type level for a component name // string format is: // [:][,[:]...] // - is 0-5 corresponding to ADebug::Level // - is used to match component name case insensitively, if omitted, it // matches all components // - string is read left-to-right, and the last matching level is returned, or // the def if no terms matched static long GetLevelFromSettingsString( const char *name, const char *value, long def); static long GetLevelFromProperty( const char *name, const char *value, long def); // same for ADebug::Level - performs clamping to valid debug ranges static Level GetDebugLevelFromProperty( const char *name, const char *propertyName, Level def = kDebugNone); // remove redundant segments of a codec name, and return a newly allocated // string suitable for debugging static char *GetDebugName(const char *name); inline static bool isExperimentEnabled( const char *name __unused /* nonnull */, bool allow __unused = true) { #ifdef ENABLE_STAGEFRIGHT_EXPERIMENTS if (!strcmp(name, "legacy-adaptive")) { return getExperimentFlag(allow, name, 2, 1); // every other day } else if (!strcmp(name, "legacy-setsurface")) { return getExperimentFlag(allow, name, 3, 1); // every third day } else { ALOGE("unknown experiment '%s' (disabled)", name); } #endif return false; } private: // pass in allow, so we can print in the log if the experiment is disabled static bool getExperimentFlag( bool allow, const char *name, uint64_t modulo, uint64_t limit, uint64_t plus = 0, uint64_t timeDivisor = 24 * 60 * 60 /* 1 day */); }; } // namespace android #endif // A_DEBUG_H_