1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

Stats: Unique Machine ID

This commit is contained in:
chroma 2022-08-31 15:16:20 +01:00
parent 4418376335
commit 6bd1582b47
9 changed files with 201 additions and 14 deletions

View file

@ -47,6 +47,22 @@ namespace AndroidStatsHelpers
javaString (name).get())));
}
static String getAndroidID()
{
auto* env = getEnv();
if (auto settings = (jclass) env->FindClass ("android/provider/Settings$Secure"))
{
if (auto fId = env->GetStaticFieldID (settings, "ANDROID_ID", "Ljava/lang/String;"))
{
auto androidID = (jstring) env->GetStaticObjectField (settings, fId);
return juceString (LocalRef<jstring> (androidID));
}
}
return "";
}
static String getLocaleValue (bool isRegion)
{
auto* env = getEnv();
@ -170,6 +186,15 @@ String SystemStats::getUserLanguage() { return AndroidStatsHelpers::getLocale
String SystemStats::getUserRegion() { return AndroidStatsHelpers::getLocaleValue (true); }
String SystemStats::getDisplayLanguage() { return getUserLanguage() + "-" + getUserRegion(); }
String SystemStats::getUniqueDeviceID()
{
auto id = String ((uint64_t) AndroidStatsHelpers::getAndroidID().hashCode64());
// Please tell someone at JUCE if this occurs
jassert (id.isNotEmpty());
return id;
}
//==============================================================================
void CPUInformation::initialise() noexcept
{

View file

@ -304,6 +304,64 @@ void CPUInformation::initialise() noexcept
#endif
}
String SystemStats::getUniqueDeviceID()
{
static const auto deviceId = []()
{
const auto call = [] (auto command) -> String
{
ChildProcess proc;
if (proc.start (command, ChildProcess::wantStdOut))
return proc.readAllProcessOutput();
return {};
};
auto data = call ("cat /sys/class/dmi/id/board_serial");
// 'board_serial' is enough on its own, fallback to bios stuff if we can't find it.
if (data.isEmpty())
{
data = call ("cat /sys/class/dmi/id/bios_date")
+ call ("cat /sys/class/dmi/id/bios_release")
+ call ("cat /sys/class/dmi/id/bios_vendor")
+ call ("cat /sys/class/dmi/id/bios_version");
}
auto cpuData = call ("lscpu");
if (cpuData.isNotEmpty())
{
auto getCpuInfo = [&cpuData] (auto key) -> String
{
auto index = cpuData.indexOf (key);
if (index >= 0)
{
auto start = cpuData.indexOf (index, ":");
auto end = cpuData.indexOf (start, "\n");
return cpuData.substring (start + 1, end).trim();
}
return {};
};
data += getCpuInfo ("CPU family:");
data += getCpuInfo ("Model:");
data += getCpuInfo ("Model name:");
data += getCpuInfo ("Vendor ID:");
}
return String ((uint64_t) data.hashCode64());
}();
// Please tell someone at JUCE if this occurs
jassert (deviceId.isNotEmpty());
return deviceId;
}
//==============================================================================
uint32 juce_millisecondsSinceStartup() noexcept
{

View file

@ -351,4 +351,34 @@ int SystemStats::getPageSize()
return (int) NSPageSize();
}
String SystemStats::getUniqueDeviceID()
{
static const auto deviceId = []
{
ChildProcess proc;
if (proc.start ("ioreg -rd1 -c IOPlatformExpertDevice", ChildProcess::wantStdOut))
{
constexpr const char key[] = "\"IOPlatformUUID\"";
constexpr const auto keyLen = (int) sizeof (key);
auto output = proc.readAllProcessOutput();
auto index = output.indexOf (key);
if (index >= 0)
{
auto start = output.indexOf (index + keyLen, "\"");
auto end = output.indexOf (start + 1, "\"");
return output.substring (start + 1, end).replace("-", "");
}
}
return String();
}();
// Please tell someone at JUCE if this occurs
jassert (deviceId.isNotEmpty());
return deviceId;
}
} // namespace juce

View file

@ -592,4 +592,33 @@ String SystemStats::getDisplayLanguage()
return languagesBuffer.data();
}
String SystemStats::getUniqueDeviceID()
{
#define PROVIDER(string) (DWORD) (string[0] << 24 | string[1] << 16 | string[2] << 8 | string[3])
auto bufLen = GetSystemFirmwareTable (PROVIDER ("RSMB"), PROVIDER ("RSDT"), nullptr, 0);
if (bufLen > 0)
{
HeapBlock<uint8_t> buffer { bufLen };
GetSystemFirmwareTable (PROVIDER ("RSMB"), PROVIDER ("RSDT"), (void*) buffer.getData(), bufLen);
return [&]
{
uint64_t hash = 0;
const auto start = buffer.getData();
const auto end = start + jmin (1024, (int) bufLen);
for (auto dataPtr = start; dataPtr != end; ++dataPtr)
hash = hash * (uint64_t) 101 + *dataPtr;
return String (hash);
}();
}
// Please tell someone at JUCE if this occurs
jassertfalse;
return {};
}
} // namespace juce

View file

@ -253,4 +253,25 @@ bool SystemStats::isRunningInAppExtensionSandbox() noexcept
#endif
}
#if JUCE_UNIT_TESTS
class UniqueHardwareIDTest : public UnitTest
{
public:
//==============================================================================
UniqueHardwareIDTest() : UnitTest ("UniqueHardwareID", UnitTestCategories::analytics) {}
void runTest() override
{
beginTest ("getUniqueDeviceID returns usable data.");
{
expect (SystemStats::getUniqueDeviceID().isNotEmpty());
}
}
};
static UniqueHardwareIDTest uniqueHardwareIDTest;
#endif
} // namespace juce

View file

@ -145,8 +145,17 @@ public:
The first choice for an ID is a filesystem ID for the user's home folder or
windows directory. If that fails then this function returns the MAC addresses.
*/
[[deprecated ("The identifiers produced by this function are not reliable. Use getUniqueDeviceID() instead.")]]
static StringArray getDeviceIdentifiers();
/** This method returns a machine unique ID unaffected by storage or peripheral
changes.
This ID will be invalidated by changes to the motherboard and CPU on non-mobile
platforms, or resetting an Android device.
*/
static String getUniqueDeviceID();
//==============================================================================
// CPU and memory information..

View file

@ -35,7 +35,6 @@ namespace UnitTestCategories
static const String cryptography { "Cryptography" };
static const String dsp { "DSP" };
static const String files { "Files" };
static const String function { "Function" };
static const String graphics { "Graphics" };
static const String gui { "GUI" };
static const String json { "JSON" };

View file

@ -314,6 +314,14 @@ void OnlineUnlockStatus::MachineIDUtilities::addMACAddressesToList (StringArray&
ids.add (getEncodedIDString (address.toString()));
}
String OnlineUnlockStatus::MachineIDUtilities::getUniqueMachineID()
{
return getEncodedIDString (SystemStats::getUniqueDeviceID());
}
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wdeprecated-declarations")
JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4996)
StringArray OnlineUnlockStatus::MachineIDUtilities::getLocalMachineIDs()
{
auto identifiers = SystemStats::getDeviceIdentifiers();
@ -329,6 +337,9 @@ StringArray OnlineUnlockStatus::getLocalMachineIDs()
return MachineIDUtilities::getLocalMachineIDs();
}
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
JUCE_END_IGNORE_WARNINGS_MSVC
void OnlineUnlockStatus::userCancelled()
{
}
@ -378,22 +389,19 @@ bool OnlineUnlockStatus::applyKeyFile (String keyFileContent)
return false;
}
static bool canConnectToWebsite (const URL& url)
{
return url.createInputStream (URL::InputStreamOptions (URL::ParameterHandling::inAddress)
.withConnectionTimeoutMs (2000)) != nullptr;
}
static bool areMajorWebsitesAvailable()
{
const char* urlsToTry[] = { "http://google.com", "http://bing.com", "http://amazon.com",
"https://google.com", "https://bing.com", "https://amazon.com", nullptr};
static constexpr const char* const urlsToTry[] = { "http://google.com", "http://bing.com", "http://amazon.com",
"https://google.com", "https://bing.com", "https://amazon.com" };
const auto canConnectToWebsite = [] (auto url)
{
return URL (url).createInputStream (URL::InputStreamOptions (URL::ParameterHandling::inAddress)
.withConnectionTimeoutMs (2000)) != nullptr;
};
for (const char** url = urlsToTry; *url != nullptr; ++url)
if (canConnectToWebsite (URL (*url)))
return true;
return false;
return std::any_of (std::begin (urlsToTry),
std::end (urlsToTry),
canConnectToWebsite);
}
OnlineUnlockStatus::UnlockResult OnlineUnlockStatus::handleXmlReply (XmlElement xml)

View file

@ -242,6 +242,7 @@ public:
/** Utility function that you may want to use in your machine-ID generation code.
This adds some ID strings to the given array which represent each MAC address of the machine.
*/
[[deprecated ("MAC addresses are no longer reliable methods of ID generation. You should use getUniqueMachineID() instead, You can still get a list of this device's MAC addresses with MACAddress::findAllAddresses().")]]
static void addMACAddressesToList (StringArray& result);
/** This method calculates some machine IDs based on things like network
@ -259,7 +260,14 @@ public:
registration on machines which have had hardware added/removed
since the product was first registered.
*/
[[deprecated ("The identifiers generated by this function are no longer reliable. Use getUniqueMachineID() instead.")]]
static StringArray getLocalMachineIDs();
/** Returns an encoded unique machine ID.
@see SystemStats::getUniqueDeviceID
*/
static String getUniqueMachineID();
};
private: