summaryrefslogtreecommitdiff
path: root/Runtime/Utilities/ReportHardware.cpp
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2019-08-14 22:50:43 +0800
committerchai <chaifix@163.com>2019-08-14 22:50:43 +0800
commit15740faf9fe9fe4be08965098bbf2947e096aeeb (patch)
treea730ec236656cc8cab5b13f088adfaed6bb218fb /Runtime/Utilities/ReportHardware.cpp
+Unity Runtime codeHEADmaster
Diffstat (limited to 'Runtime/Utilities/ReportHardware.cpp')
-rw-r--r--Runtime/Utilities/ReportHardware.cpp391
1 files changed, 391 insertions, 0 deletions
diff --git a/Runtime/Utilities/ReportHardware.cpp b/Runtime/Utilities/ReportHardware.cpp
new file mode 100644
index 0000000..868287f
--- /dev/null
+++ b/Runtime/Utilities/ReportHardware.cpp
@@ -0,0 +1,391 @@
+#include "UnityPrefix.h"
+#include "ReportHardware.h"
+#include "Runtime/Misc/SystemInfo.h"
+#include "Runtime/Shaders/GraphicsCaps.h"
+#include "HashFunctions.h"
+#include "Configuration/UnityConfigureVersion.h"
+#include "Configuration/UnityConfigureOther.h"
+#include "Configuration/UnityConfigure.h"
+#include "Runtime/Graphics/ScreenManager.h"
+#include "Runtime/Export/WWW.h"
+#include "Runtime/Misc/BuildSettings.h"
+#include "Runtime/Misc/CPUInfo.h"
+#include "Runtime/Misc/PlayerSettings.h"
+#include "Runtime/Utilities/GlobalPreferences.h"
+#include "Runtime/Utilities/Argv.h"
+#include "Runtime/Utilities/Word.h"
+
+#if UNITY_LINUX
+#include "PlatformDependent/Linux/X11Quarantine.h"
+#endif
+
+#if SUPPORT_REPRODUCE_LOG
+#include "Runtime/Misc/ReproductionLog.h"
+#endif
+
+#if UNITY_ANDROID
+#include "PlatformDependent/AndroidPlayer/AndroidSystemInfo.h"
+#include "PlatformDependent/AndroidPlayer/EntryPoint.h"
+#endif
+
+#if UNITY_IPHONE
+ extern "C" const char* UnityAdvertisingIdentifier();
+ extern "C" bool UnityAdvertisingTrackingEnabled();
+#endif
+
+#if UNITY_METRO
+#include "PlatformDependent/MetroPlayer/AppCallbacks.h"
+#include "PlatformDependent/MetroPlayer/MetroCapabilities.h"
+#endif
+
+#if UNITY_OSX
+static int numberForKey( CFDictionaryRef desc, CFStringRef key )
+{
+ CFNumberRef value;
+ int num = 0;
+ if ( (value = (CFNumberRef)CFDictionaryGetValue(desc, key)) == NULL )
+ return 0;
+ CFNumberGetValue(value, kCFNumberIntType, &num);
+ return num;
+}
+#endif
+
+#if UNITY_EDITOR
+const char* kHardwareReportDoneKey = "Editor StatsDone";
+#elif UNITY_STANDALONE
+const char* kHardwareReportDoneKey = "StandaloneStatsDone";
+#else
+const char* kHardwareReportDoneKey = "StatsDone";
+#endif
+
+// URL to report hardware info to
+const char* kHardwareReportURL = "http://stats.unity3d.com/HWStats.cgi";
+
+
+static bool CheckHardwareReportNeeded()
+{
+ #if !UNITY_ENABLE_HWSTATS_REPORT
+ return false;
+ #endif
+
+ #if SUPPORT_REPRODUCE_LOG
+ if (RunningReproduction())
+ return false;
+ #endif
+
+ #if !WEBPLUG
+ if (!IsHumanControllingUs())
+ return false;
+ #endif
+
+ #if UNITY_ANDROID
+ // development player == no stats
+ if (UNITY_DEVELOPER_BUILD)
+ return false;
+
+ if (!GetPlayerSettings().GetEnableHWStatistics())
+ return false;
+
+ // Only report once per OS version
+ std::string osName = systeminfo::GetOperatingSystem();
+ UInt8 md5Value[16];
+ ComputeMD5Hash( reinterpret_cast<const UInt8*>( osName.c_str() ), osName.size(), md5Value );
+ std::string md5String = BytesToHexString( md5Value, 16 );
+
+ if (GetGlobalPreference(UNITY_VERSION_DIGITS) == md5String)
+ return false;
+
+ SetGlobalPreference(UNITY_VERSION_DIGITS, md5String);
+
+ return true;
+ #endif // #if UNITY_ANDROID
+
+
+ #if UNITY_METRO
+ if (metro::Capabilities::IsSupported(metro::Capabilities::kInternetClient, "", false) == false &&
+ metro::Capabilities::IsSupported(metro::Capabilities::kInternetClientServer, "", false) == false)
+ return false;
+ #endif // #if UNITY_METRO
+
+ #if UNITY_IPHONE || UNITY_BB10 || UNITY_TIZEN
+ if (!GetPlayerSettings().GetEnableHWStatistics())
+ return false;
+ #endif
+
+ if ( GetGlobalBoolPreference (kHardwareReportDoneKey, false) )
+ return false;
+ SetGlobalBoolPreference (kHardwareReportDoneKey, true);
+
+ return true;
+}
+
+
+static std::string EscapeFieldString( const std::string& s )
+{
+ const char* kHexToLiteral = "0123456789abcdef";
+ const char *kForbidden = "@&;:<>=?\"'/\\!#%+";
+
+ std::string result;
+ result.reserve( s.size() );
+ for( size_t i = 0; i < s.size(); ++i ) {
+ unsigned char c = s[i];
+ if( c == 32 )
+ result += '+';
+ else if( c < 32 || c > 126 || strchr(kForbidden, c) != NULL )
+ {
+ result += '%';
+ result += kHexToLiteral[c >> 4];
+ result += kHexToLiteral[c & 0xF];
+ }
+ else
+ result += c;
+ }
+ return result;
+}
+
+
+void HardwareInfoReporter::Shutdown()
+{
+ #if ENABLE_WWW
+ if( m_InfoPost != NULL )
+ {
+ m_InfoPost->Release();
+ m_InfoPost = NULL;
+ }
+ #endif
+}
+
+static void StripGfxDriverVersion(std::string& fullName, const std::string& version)
+{
+ size_t pos = fullName.find(version);
+
+ if (pos != std::string::npos && pos > 1)
+ fullName.erase(pos-1, version.size()+1);
+}
+
+void HardwareInfoReporter::ReportHardwareInfo()
+{
+#if ENABLE_WWW
+ AssertIf( m_InfoPost != NULL );
+
+ // If hardware info already reported, do nothing
+ if( !CheckHardwareReportNeeded() )
+ return;
+
+
+ // Get all the information to post
+ std::string infoUUID; // Used to be sent by 2.0.2, not anymore with 2.1. Keeping to match the hash value. Now used by Android and iPhone only.
+ std::string deviceModel; // Used by Android and iPhone only
+ // Report runtime version used
+ std::string infoOS = systeminfo::GetOperatingSystem();
+ std::string infoCPU = systeminfo::GetProcessorType();
+ std::string infoGfxName = gGraphicsCaps.rendererString;
+ std::string infoGfxVendor = gGraphicsCaps.vendorString;
+ std::string infoGfxVersion = gGraphicsCaps.fixedVersionString;
+ std::string infoGfxDriver = gGraphicsCaps.driverLibraryString;
+#if UNITY_ANDROID || UNITY_IPHONE || UNITY_BB10 || UNITY_TIZEN
+ std::string appId = GetPlayerSettings().GetiPhoneBundleIdentifier();
+#else
+ std::string appId = Format("%s.%s",GetPlayerSettings().GetCompanyName().c_str(), GetPlayerSettings().GetProductName().c_str());
+#endif
+ int infoCpuCount = systeminfo::GetProcessorCount();
+ int infoRAM = systeminfo::GetPhysicalMemoryMB();
+ int infoVRAM = gGraphicsCaps.videoMemoryMB;
+
+ std::string unityVersion = UNITY_VERSION; // Report runtime version used
+ std::string buildVersion = "0.0.0"; // Unknown build version used
+
+ // Get desktop display mode dimensions. Do this directly because
+ // we initiate the report before screen manager is even set up
+ // (so that in case something horrible happens while initializing
+ // the game, we'd still get a chance to get the report).
+ #if UNITY_WIN && !UNITY_WINRT
+ DEVMODE displayMode;
+ memset( &displayMode, 0, sizeof(displayMode) );
+ displayMode.dmSize = sizeof(DEVMODE);
+ EnumDisplaySettings( NULL, ENUM_CURRENT_SETTINGS, &displayMode );
+ std::string infoScreenRes = Format("%i x %i", displayMode.dmPelsWidth, displayMode.dmPelsHeight);
+
+ #elif UNITY_OSX
+ CFDictionaryRef currentMode = CGDisplayCurrentMode(kCGDirectMainDisplay);
+ int desktopWidth = numberForKey(currentMode, kCGDisplayWidth);
+ int desktopHeight = numberForKey(currentMode, kCGDisplayHeight);
+ std::string infoScreenRes = Format("%i x %i", desktopWidth, desktopHeight);
+
+ #elif UNITY_LINUX
+ unsigned width = 0;
+ unsigned height = 0;
+ #if SUPPORT_X11
+ NativeDisplayPtr display = OpenDisplay(NULL);
+ NativeWindow rootWindow = GetRootWindow(display);
+ GetWindowSize(display, rootWindow, &width, &height);
+ CloseDisplay(display);
+ #endif
+ std::string infoScreenRes = Format("%u x %u", width, height);
+ #elif UNITY_ANDROID
+ // Create a less obscure OS string
+ infoOS = Format ("%s API-%i", systeminfo::GetDeviceSystemName(), android::systeminfo::ApiLevel());
+ // Strip 'driverLibraryString' from 'fixedVersionString', if duplicated
+ StripGfxDriverVersion(infoGfxVersion, infoGfxDriver);
+ // Get the raw display size (physical size of the display)
+ int width, height;
+ android::systeminfo::DisplaySize(&width, &height);
+ std::string infoScreenRes = Format("%u x %u", width, height);
+ // Use ANDROID ID/IMEI/WiFi MAC as UUID
+ infoUUID = android::systeminfo::UniqueIdentifier();
+ // This matches the first part of ro.build.fingerprint
+ deviceModel = Format ("%s/%s/%s", android::systeminfo::Manufacturer(), android::systeminfo::Model(), android::systeminfo::Device());
+ #elif UNITY_IPHONE
+ std::string infoScreenRes = Format("%u x %u", GetScreenManager().GetWidth(), GetScreenManager().GetHeight());
+ infoUUID = systeminfo::GetDeviceUniqueIdentifier(); // it is hash of WiFi MAC address
+ deviceModel = systeminfo::GetDeviceModel();
+ StripGfxDriverVersion(infoGfxVersion, infoGfxDriver);
+ #elif UNITY_BLACKBERRY
+ std::string infoScreenRes = Format("%u x %u", GetScreenManager().GetWidth(), GetScreenManager().GetHeight());
+ // This will be EMPTY for Blackberry if permission is set false
+ infoUUID = systeminfo::GetDeviceUniqueIdentifier(); // Unique ID from OS / it is hash of WiFi MAC address
+ deviceModel = Format("%s/%s", "BlackBerry", systeminfo::GetDeviceModel());
+ StripGfxDriverVersion(infoGfxVersion, infoGfxDriver);
+ #elif UNITY_METRO
+ std::string infoScreenRes = Format("%u x %u", GetScreenManager().GetWidth(), GetScreenManager().GetHeight());
+ // It seems if we call GetDeviceUniqueIdentifier, this somehow distrubts the data flow, and server doesn't accept it
+ infoUUID = systeminfo::GetDeviceUniqueIdentifier(); // it is hash of WiFi MAC address
+ {
+ // Make infoUUID different one from the Editor and encode it again
+ infoUUID+="Metro";
+ UInt8 md5Value[16];
+ ComputeMD5Hash( reinterpret_cast<const UInt8*>(infoUUID.c_str() ), infoUUID.size(), md5Value);
+ infoUUID = BytesToHexString(md5Value, 16);
+ }
+ deviceModel = "n/a";
+ #elif UNITY_WP8
+ auto& screenManager = GetScreenManager ();
+ std::string infoScreenRes;
+ if (screenManager.GetScreenOrientation () == ScreenOrientation::kLandscapeLeft || screenManager.GetScreenOrientation () == ScreenOrientation::kLandscapeRight)
+ {
+ infoScreenRes = Format ("%u x %u", screenManager.GetHeight (), screenManager.GetWidth ());
+ }
+ else
+ {
+ infoScreenRes = Format ("%u x %u", screenManager.GetWidth (), screenManager.GetHeight ());
+ }
+ infoUUID = systeminfo::GetDeviceUniqueIdentifier ();
+ deviceModel = systeminfo::GetDeviceName ();
+ #elif UNITY_TIZEN
+ std::string infoScreenRes = Format("%u x %u", GetScreenManager().GetWidth(), GetScreenManager().GetHeight());
+ infoUUID = systeminfo::GetDeviceUniqueIdentifier();
+ deviceModel = Format("%s/%s", "Tizen", systeminfo::GetDeviceModel());
+ StripGfxDriverVersion(infoGfxVersion, infoGfxDriver);
+ #else
+ #error "Unsupported platform"
+ #endif
+
+ // Various flags, bits:
+ // 0..3: license type
+ // 4..5: metro presentation types
+ // 6..17: CPU capabilities, reserved up to 23
+ // 24..25: GPU capabilities
+ int flags = 0;
+ BuildSettings* buildSettings = &GetBuildSettings();
+ if (buildSettings)
+ {
+ // bits 0..2: 1=Indie, 2=Pro
+ flags |= buildSettings->hasPROVersion ? 2 : 1;
+ // bit 3: 0=Licensed, 1=Trial
+ if (!buildSettings->hasPublishingRights)
+ flags |= 8;
+
+ // Report build version used
+ buildVersion = buildSettings->GetVersion();
+ }
+
+#if UNITY_METRO
+ // bits 4..5: 1=XAML app, 2=D3D app
+ flags |= UnityPlayer::AppCallbacks::Instance->GetAppType() == UnityPlayer::AppCallbacks::kAppTypeD3DXAML ? (1 << 4) : (1 << 5);
+#endif
+
+ // CPU capabilities flags, bits 6..17
+ flags |= (1<<6); // CPU caps bits are present (to determine between earlier versions that did not send these flags at all)
+ if (CPUInfo::HasSSE2Support())
+ flags |= (1<<7);
+ if (CPUInfo::HasSSE41Support())
+ flags |= (1<<8);
+ if (CPUInfo::HasSSE42Support())
+ flags |= (1<<9);
+ if (CPUInfo::HasAVXSupport())
+ flags |= (1<<10);
+ if (CPUInfo::HasNEONSupport())
+ flags |= (1<<11);
+ if (CPUInfo::HasSSE3Support())
+ flags |= (1<<12);
+ if (CPUInfo::HasSupplementalSSE3Support())
+ flags |= (1<<13);
+ if (CPUInfo::HasAVX2Support())
+ flags |= (1<<14);
+ if (CPUInfo::HasAVX512Support())
+ flags |= (1<<15);
+ if (CPUInfo::HasFP16CSupport())
+ flags |= (1<<16);
+ if (CPUInfo::HasFMASupport())
+ flags |= (1<<17);
+
+ // GPU capabilities flags, bits 24..25
+ if (gGraphicsCaps.hasNativeDepthTexture)
+ flags |= (1<<24);
+ if (gGraphicsCaps.hasNativeShadowMap)
+ flags |= (1<<25);
+
+
+ // Send a hash some fields plus a salt as a cheap way to prevent "spam" on hardware
+ // report script.
+ std::string stringToHash;
+ stringToHash = std::string("KonfiguracijosReportoDruska-") + infoUUID + infoOS + infoCPU + infoGfxName + infoGfxVendor + infoGfxVersion;
+
+ UInt8 md5Value[16];
+ ComputeMD5Hash( reinterpret_cast<const UInt8*>( stringToHash.c_str() ), stringToHash.size(), md5Value );
+ std::string md5String = BytesToHexString( md5Value, 16 );
+
+ // Construct POST request data
+ std::string postData;
+ postData += "os=" + EscapeFieldString(infoOS);
+ postData += "&cpu=" + EscapeFieldString(infoCPU);
+ postData += "&gfxname=" + EscapeFieldString(infoGfxName);
+ postData += "&gfxvendor=" + EscapeFieldString(infoGfxVendor);
+ postData += "&gfxversion=" + EscapeFieldString(infoGfxVersion);
+ postData += "&gfxdriver=" + EscapeFieldString(infoGfxDriver);
+ postData += "&cpucount=" + IntToString(infoCpuCount);
+ postData += "&ram=" + IntToString(infoRAM);
+ postData += "&vram=" + IntToString(infoVRAM);
+ postData += "&screen=" + EscapeFieldString(infoScreenRes);
+ postData += "&platform=" + IntToString(systeminfo::GetRuntimePlatform());
+ postData += "&flags=" + IntToString(flags);
+ postData += "&hash=" + md5String;
+ postData += "&appId=" + EscapeFieldString(appId);
+#if UNITY_ANDROID || UNITY_IPHONE || UNITY_BB10 || UNITY_WINRT || UNITY_TIZEN
+ postData += "&uuid=" + infoUUID;
+ postData += "&model=" + deviceModel;
+#endif
+#if UNITY_IPHONE
+ if (const char *iOSAdvertisingIdentifier = UnityAdvertisingIdentifier())
+ postData += "&adid=" + std::string(iOSAdvertisingIdentifier);
+ postData += "&adtrack=" + std::string(UnityAdvertisingTrackingEnabled()?"1":"0");
+#endif
+ postData += "&unity=" + unityVersion;
+ postData += "&build=" + buildVersion;
+
+ // Initiate POST request
+ std::map<std::string,std::string> headers;
+ headers.insert( std::make_pair("Content-Type", "application/x-www-form-urlencoded") );
+
+ m_InfoPost = WWW::Create( kHardwareReportURL, postData.c_str(), postData.size(), headers, false );
+
+ /*
+ // Server accepts only 5% percent of data, so if you want to debug, use the loop below, to ensure that data reaches server
+ for (int i = 0; i < 100; i++)
+ {
+ m_InfoPost = WWW::Create( kHardwareReportURL, postData.c_str(), postData.size(), headers, false );
+ Thread::Sleep(0.1f);
+ }
+ */
+#endif // ENABLE_WWW
+}