#ifndef __APPINSIGHT_H__ #define __APPINSIGHT_H__ #include #include #include #include #include #include #include #include #ifndef LOG_TAG #define LOG_TAG "AppInsight" #endif #define APPINSIGHT_LOGD(B, ...) if(B) __android_log_print(ANDROID_LOG_INFO,LOG_TAG, __VA_ARGS__) #define INFO_DUMP_GET_SYSTEM_PROP(TYPE, VAR, KEY, DEFAULT) \ {\ char value[PROPERTY_VALUE_MAX]; \ property_get(KEY, value, DEFAULT); \ VAR = (TYPE) atoi(value); \ } #define KEYLIST \ keyType(SCENARIO), \ keyType(APPNAME), \ keyType(CODECTYPE), \ keyType(WIDTH), \ keyType(HEIGHT), \ keyType(PIXEL_FORMAT), \ keyType(BITRATE), \ keyType(PROFILE), \ keyType(LEVEL), \ keyType(FRAMERATE), \ keyType(GRID_WIDTH), \ keyType(GRID_HEIGHT), \ keyType(TILE_WIDTH), \ keyType(TILE_HEIGHT), \ keyType(PROGRESSIVE), \ keyType(ICC_PROFILE), \ keyType(COLOR_TYPE), \ keyType(COLOR_SPACE), \ keyType(SAMPLE_SIZE), \ keyType(REGION_DECODE), \ keyType(INFODUMPMAX) #define TYPENONE(x) x #define TYPESTR(x) #x namespace AppInsight { #define OUTPATH "/sdcard/appinsight" #ifdef keyType #undef keyType #endif #define keyType TYPENONE enum InfoDumpKey {KEYLIST}; class InfoDump { public: InfoDump(bool vendor=true) :modified(false),enabled(false),isVendor(vendor) { if(isVendor) { INFO_DUMP_GET_SYSTEM_PROP(bool, enabled, "vendor.mtk.appinsight.videoimage.enabled", "0"); } else { INFO_DUMP_GET_SYSTEM_PROP(bool, enabled, "mtk.appinsight.videoimage.enabled", "0"); } info.fill(NULL); infoType.fill(UNINIT); if(!enabled) return; char temp[512]; if(isVendor) property_get("vendor.mtk.appinsight.videoimage.scenario", temp, ""); else property_get("mtk.appinsight.videoimage.scenario", temp, ""); if(temp[0]==0) { enabled = false; return; } else add(SCENARIO, temp); if(isVendor) property_get("vendor.mtk.appinsight.videoimage.appname", temp, ""); else property_get("mtk.appinsight.videoimage.appname", temp, ""); if(temp[0]==0) { enabled = false; return; } else add(APPNAME, temp); } ~InfoDump() { if(!enabled) return; for (int i=0;i=INFODUMPMAX) return false; int len = strlen(v) + 1; switch(infoType[k]) { case STRING: { int orilen = *((int*)info[k]); if(orilen < len) { free(info[k]); info[k] = (char*)malloc(sizeof(int) + len); *((int*)info[k]) = len; } break; } case NUMBER: case UNINIT: default: if(info[k]) free(info[k]); info[k] = (char*)malloc(sizeof(int) + len + 1); *((int*)info[k]) = len + 1; } memcpy(info[k]+4, v, len); infoType[k] = STRING; modified = true; return true; } bool add(InfoDumpKey k, int v) { if(!enabled) return false; if(k>=INFODUMPMAX) return false; switch(infoType[k]) { case NUMBER: if(info[k] == NULL) info[k] = (char*)malloc(sizeof(int)); if(*((int*)info[k]) == v) return false; break; case STRING: case UNINIT: default: if(info[k]) free(info[k]); info[k] = (char*)malloc(sizeof(int)); } *((int*)info[k]) = v; infoType[k] = NUMBER; modified = true; return true; } bool add(InfoDumpKey k, std::string v) { if(!enabled) return false; return add(k, v.c_str()); } void commit() { if(!enabled) return; if(!modified) return; time_t rawtime; struct tm * timeinfo; time(&rawtime); timeinfo = localtime(&rawtime); if(timeinfo == nullptr) return; int loglen = 2048; int offset = 0; // auto delete sp auto logbuffer_sp = std::shared_ptr((char*)malloc(loglen), [](char* ptr) {if(ptr) free(ptr);}); if(logbuffer_sp == nullptr) return; char* logbuffer = logbuffer_sp.get(); offset += snprintf(logbuffer, loglen-offset, "%s appinsight:", asctime(timeinfo)); for ( int i=0; i info; std::array infoType; /* * memlayout: * UNINIT: NULL * NUMBER: char[4] <--(value int) * STRING: char[4+LEN] <--(LEN int + value str) */ bool modified; bool enabled; bool isVendor; }; }; #endif