11 #include <CoreFoundation/CoreFoundation.h>
12 #include <dispatch/dispatch.h>
15 #include "flutter/fml/build_config.h"
16 #include "flutter/fml/file.h"
17 #include "flutter/fml/logging.h"
18 #include "flutter/fml/mapping.h"
19 #include "flutter/fml/platform/darwin/cf_utils.h"
46 #define CF_PROPERTY_LIST_IMMUTABLE 0
54 std::string plist_path =
"/System/Library/CoreServices/SystemVersion.plist";
55 #if FML_OS_IOS_SIMULATOR
56 char* plist_path_prefix = getenv(
"IPHONE_SIMULATOR_ROOT");
57 if (!plist_path_prefix) {
58 FML_DLOG(ERROR) <<
"Failed to getenv IPHONE_SIMULATOR_ROOT";
61 plist_path = std::string(plist_path_prefix) + plist_path;
62 #endif // FML_OS_IOS_SIMULATOR
64 auto plist_mapping = fml::FileMapping::CreateReadOnly(plist_path);
68 auto file_contents = fml::CFRef<CFDataRef>(CFDataCreateWithBytesNoCopy(
69 nullptr, plist_mapping->GetMapping(),
70 static_cast<CFIndex
>(plist_mapping->GetSize()), kCFAllocatorNull));
72 FML_DLOG(ERROR) <<
"Failed to CFDataCreateWithBytesNoCopyFunc";
76 auto plist = fml::CFRef<CFDictionaryRef>(
77 reinterpret_cast<CFDictionaryRef
>(CFPropertyListCreateWithData(
81 FML_DLOG(ERROR) <<
"Failed to CFPropertyListCreateWithDataFunc or "
82 "CFPropertyListCreateFromXMLDataFunc";
86 auto product_version =
87 fml::CFRef<CFStringRef>(CFStringCreateWithCStringNoCopy(
88 nullptr,
"ProductVersion", kCFStringEncodingASCII, kCFAllocatorNull));
89 if (!product_version) {
90 FML_DLOG(ERROR) <<
"Failed to CFStringCreateWithCStringNoCopyFunc";
93 CFTypeRef opaque_value = CFDictionaryGetValue(plist, product_version);
94 if (!opaque_value || CFGetTypeID(opaque_value) != CFStringGetTypeID()) {
95 FML_DLOG(ERROR) <<
"Failed to CFDictionaryGetValueFunc";
100 if (!CFStringGetCString(
reinterpret_cast<CFStringRef
>(opaque_value),
101 version_str,
sizeof(version_str),
102 kCFStringEncodingUTF8)) {
103 FML_DLOG(ERROR) <<
"Failed to CFStringGetCStringFunc";
109 int32_t subminor = 0;
110 int matches = sscanf(version_str,
"%d.%d.%d", &major, &minor, &subminor);
114 FML_DLOG(ERROR) <<
"Failed to match product version string: "
124 const int32_t major = (encoded_lhs >> 16) & 0xffff;
125 const int32_t minor = (encoded_lhs >> 8) & 0xff;
126 const int32_t subminor = encoded_lhs & 0xff;
140 typedef uint32_t dyld_platform_t;
143 dyld_platform_t platform;
145 } dyld_build_version_t;
147 typedef bool (*AvailabilityVersionCheckFn)(uint32_t count,
148 dyld_build_version_t versions[]);
150 AvailabilityVersionCheckFn AvailabilityVersionCheck;
152 dispatch_once_t DispatchOnceCounter;
154 void InitializeAvailabilityCheck(
void* unused) {
155 if (AvailabilityVersionCheck) {
158 AvailabilityVersionCheck =
reinterpret_cast<AvailabilityVersionCheckFn
>(
159 dlsym(RTLD_DEFAULT,
"_availability_version_check"));
160 if (AvailabilityVersionCheck) {
167 if (product_version.has_value()) {
168 g_version = product_version.value();
172 #if FML_OS_IOS || FML_OS_IOS_SIMULATOR
173 g_version = std::make_tuple(11, 0, 0);
175 g_version = std::make_tuple(10, 14, 0);
176 #endif // FML_OS_MACOSX
180 extern "C" bool _availability_version_check(uint32_t count,
181 dyld_build_version_t versions[]) {
182 dispatch_once_f(&DispatchOnceCounter, NULL, InitializeAvailabilityCheck);
183 if (AvailabilityVersionCheck) {
184 return AvailabilityVersionCheck(count, versions);