Index: webrtc/base/systeminfo.cc |
diff --git a/webrtc/base/systeminfo.cc b/webrtc/base/systeminfo.cc |
index 6d8d5ba7514d0107c4911a1cdb3143274038f05f..1dc6a682e90e7ab88a092cb665924424d421c543 100644 |
--- a/webrtc/base/systeminfo.cc |
+++ b/webrtc/base/systeminfo.cc |
@@ -12,6 +12,7 @@ |
#if defined(WEBRTC_WIN) |
#include <winsock2.h> |
+#include <windows.h> |
#ifndef EXCLUDE_D3D9 |
#include <d3d9.h> |
#endif |
@@ -26,14 +27,6 @@ |
#include <sys/sysctl.h> |
#endif |
-#if defined(WEBRTC_WIN) |
-#include "webrtc/base/scoped_ptr.h" |
-#include "webrtc/base/win32.h" |
-#elif defined(WEBRTC_MAC) && !defined(WEBRTC_IOS) |
-#include "webrtc/base/macconversion.h" |
-#elif defined(WEBRTC_LINUX) |
-#include "webrtc/base/linux.h" |
-#endif |
#include "webrtc/base/common.h" |
#include "webrtc/base/logging.h" |
#include "webrtc/base/stringutils.h" |
@@ -41,47 +34,7 @@ |
namespace rtc { |
// See Also: http://msdn.microsoft.com/en-us/library/ms683194(v=vs.85).aspx |
-#if defined(WEBRTC_WIN) |
-typedef BOOL (WINAPI *LPFN_GLPI)( |
- PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, |
- PDWORD); |
- |
-static void GetProcessorInformation(int* physical_cpus, int* cache_size) { |
- // GetLogicalProcessorInformation() is available on Windows XP SP3 and beyond. |
- LPFN_GLPI glpi = reinterpret_cast<LPFN_GLPI>(GetProcAddress( |
- GetModuleHandle(L"kernel32"), |
- "GetLogicalProcessorInformation")); |
- if (NULL == glpi) { |
- return; |
- } |
- // Determine buffer size, allocate and get processor information. |
- // Size can change between calls (unlikely), so a loop is done. |
- DWORD return_length = 0; |
- scoped_ptr<SYSTEM_LOGICAL_PROCESSOR_INFORMATION[]> infos; |
- while (!glpi(infos.get(), &return_length)) { |
- if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { |
- infos.reset(new SYSTEM_LOGICAL_PROCESSOR_INFORMATION[ |
- return_length / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION)]); |
- } else { |
- return; |
- } |
- } |
- *physical_cpus = 0; |
- *cache_size = 0; |
- for (size_t i = 0; |
- i < return_length / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); ++i) { |
- if (infos[i].Relationship == RelationProcessorCore) { |
- ++*physical_cpus; |
- } else if (infos[i].Relationship == RelationCache) { |
- int next_cache_size = static_cast<int>(infos[i].Cache.Size); |
- if (next_cache_size >= *cache_size) { |
- *cache_size = next_cache_size; |
- } |
- } |
- } |
- return; |
-} |
-#else |
+#if !defined(WEBRTC_WIN) |
// TODO(fbarchard): Use gcc 4.4 provided cpuid intrinsic |
// 32 bit fpic requires ebx be preserved |
#if (defined(__pic__) || defined(__APPLE__)) && defined(__i386__) |
@@ -103,134 +56,64 @@ static inline void __cpuid(int cpu_info[4], int info_type) { |
); // NOLINT |
} |
#endif |
-#endif // WEBRTC_WIN |
+#endif // WEBRTC_WIN |
-// Note(fbarchard): |
-// Family and model are extended family and extended model. 8 bits each. |
-SystemInfo::SystemInfo() |
- : physical_cpus_(1), logical_cpus_(1), cache_size_(0), |
- cpu_family_(0), cpu_model_(0), cpu_stepping_(0), |
- cpu_speed_(0), memory_(0) { |
- // Initialize the basic information. |
-#if defined(__arm__) || defined(_M_ARM) |
- cpu_arch_ = SI_ARCH_ARM; |
-#elif defined(__x86_64__) || defined(_M_X64) |
- cpu_arch_ = SI_ARCH_X64; |
-#elif defined(__i386__) || defined(_M_IX86) |
- cpu_arch_ = SI_ARCH_X86; |
-#else |
- cpu_arch_ = SI_ARCH_UNKNOWN; |
-#endif |
+static int DetectNumberOfCores() { |
+ // We fall back on assuming a single core in case of errors. |
+ int number_of_cores = 1; |
#if defined(WEBRTC_WIN) |
SYSTEM_INFO si; |
GetSystemInfo(&si); |
- logical_cpus_ = si.dwNumberOfProcessors; |
- GetProcessorInformation(&physical_cpus_, &cache_size_); |
- if (physical_cpus_ <= 0) { |
- physical_cpus_ = logical_cpus_; |
- } |
- cpu_family_ = si.wProcessorLevel; |
- cpu_model_ = si.wProcessorRevision >> 8; |
- cpu_stepping_ = si.wProcessorRevision & 0xFF; |
+ number_of_cores = static_cast<int>(si.dwNumberOfProcessors); |
+#elif defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID) |
+ number_of_cores = static_cast<int>(sysconf(_SC_NPROCESSORS_ONLN)); |
#elif defined(WEBRTC_MAC) |
- uint32_t sysctl_value; |
- size_t length = sizeof(sysctl_value); |
- if (!sysctlbyname("hw.physicalcpu_max", &sysctl_value, &length, NULL, 0)) { |
- physical_cpus_ = static_cast<int>(sysctl_value); |
- } |
- length = sizeof(sysctl_value); |
- if (!sysctlbyname("hw.logicalcpu_max", &sysctl_value, &length, NULL, 0)) { |
- logical_cpus_ = static_cast<int>(sysctl_value); |
- } |
- uint64_t sysctl_value64; |
- length = sizeof(sysctl_value64); |
- if (!sysctlbyname("hw.l3cachesize", &sysctl_value64, &length, NULL, 0)) { |
- cache_size_ = static_cast<int>(sysctl_value64); |
- } |
- if (!cache_size_) { |
- length = sizeof(sysctl_value64); |
- if (!sysctlbyname("hw.l2cachesize", &sysctl_value64, &length, NULL, 0)) { |
- cache_size_ = static_cast<int>(sysctl_value64); |
- } |
- } |
- length = sizeof(sysctl_value); |
- if (!sysctlbyname("machdep.cpu.family", &sysctl_value, &length, NULL, 0)) { |
- cpu_family_ = static_cast<int>(sysctl_value); |
- } |
- length = sizeof(sysctl_value); |
- if (!sysctlbyname("machdep.cpu.model", &sysctl_value, &length, NULL, 0)) { |
- cpu_model_ = static_cast<int>(sysctl_value); |
- } |
- length = sizeof(sysctl_value); |
- if (!sysctlbyname("machdep.cpu.stepping", &sysctl_value, &length, NULL, 0)) { |
- cpu_stepping_ = static_cast<int>(sysctl_value); |
- } |
-#elif defined(__native_client__) |
- // TODO(ryanpetrie): Implement this via PPAPI when it's available. |
-#else // WEBRTC_LINUX |
- ProcCpuInfo proc_info; |
- if (proc_info.LoadFromSystem()) { |
- proc_info.GetNumCpus(&logical_cpus_); |
- proc_info.GetNumPhysicalCpus(&physical_cpus_); |
- proc_info.GetCpuFamily(&cpu_family_); |
-#if defined(CPU_X86) |
- // These values only apply to x86 systems. |
- proc_info.GetSectionIntValue(0, "model", &cpu_model_); |
- proc_info.GetSectionIntValue(0, "stepping", &cpu_stepping_); |
- proc_info.GetSectionIntValue(0, "cpu MHz", &cpu_speed_); |
- proc_info.GetSectionIntValue(0, "cache size", &cache_size_); |
- cache_size_ *= 1024; |
-#endif |
- } |
- // ProcCpuInfo reads cpu speed from "cpu MHz" under /proc/cpuinfo. |
- // But that number is a moving target which can change on-the-fly according to |
- // many factors including system workload. |
- // See /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors. |
- // The one in /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq is more |
- // accurate. We use it as our cpu speed when it is available. |
- // cpuinfo_max_freq is measured in KHz and requires conversion to MHz. |
- int max_freq = rtc::ReadCpuMaxFreq(); |
- if (max_freq > 0) { |
- cpu_speed_ = max_freq / 1000; |
- } |
-#endif |
-// For L2 CacheSize see also |
-// http://www.flounder.com/cpuid_explorer2.htm#CPUID(0x800000006) |
-#ifdef CPU_X86 |
- if (cache_size_ == 0) { |
- int cpu_info[4]; |
- __cpuid(cpu_info, 0x80000000); // query maximum extended cpuid function. |
- if (static_cast<uint32>(cpu_info[0]) >= 0x80000006) { |
- __cpuid(cpu_info, 0x80000006); |
- cache_size_ = (cpu_info[2] >> 16) * 1024; |
- } |
+ int name[] = {CTL_HW, HW_AVAILCPU}; |
+ size_t size = sizeof(number_of_cores); |
+ if (0 != sysctl(name, 2, &number_of_cores, &size, NULL, 0)) { |
+ LOG(LS_ERROR) << "Failed to get number of cores"; |
+ number_of_cores = 1; |
} |
+#else |
+ LOG(LS_ERROR) << "No function to get number of cores"; |
#endif |
+ |
+ LOG(LS_INFO) << "Available number of cores: " << number_of_cores; |
+ |
+ return number_of_cores; |
+} |
+ |
+// Statically cache the number of system cores available since if the process |
+// is running in a sandbox, we may only be able to read the value once (before |
+// the sandbox is initialized) and not thereafter. |
+// For more information see crbug.com/176522. |
+int SystemInfo::logical_cpus_ = 0; |
+ |
+SystemInfo::SystemInfo() { |
} |
// Return the number of cpu threads available to the system. |
+// static |
int SystemInfo::GetMaxCpus() { |
+ if (!logical_cpus_) |
+ logical_cpus_ = DetectNumberOfCores(); |
return logical_cpus_; |
} |
-// Return the number of cpu cores available to the system. |
-int SystemInfo::GetMaxPhysicalCpus() { |
- return physical_cpus_; |
-} |
- |
// Return the number of cpus available to the process. Since affinity can be |
// changed on the fly, do not cache this value. |
// Can be affected by heat. |
int SystemInfo::GetCurCpus() { |
- int cur_cpus; |
+ int cur_cpus = 0; |
#if defined(WEBRTC_WIN) |
- DWORD_PTR process_mask, system_mask; |
+ DWORD_PTR process_mask = 0; |
+ DWORD_PTR system_mask = 0; |
::GetProcessAffinityMask(::GetCurrentProcess(), &process_mask, &system_mask); |
- for (cur_cpus = 0; process_mask; ++cur_cpus) { |
- // Sparse-ones algorithm. There are slightly faster methods out there but |
- // they are unintuitive and won't make a difference on a single dword. |
- process_mask &= (process_mask - 1); |
+ for (int i = 0; i < sizeof(DWORD_PTR) * 8; ++i) { |
+ if (process_mask & 1) |
+ ++cur_cpus; |
+ process_mask >>= 1; |
} |
#elif defined(WEBRTC_MAC) |
uint32_t sysctl_value; |
@@ -239,285 +122,92 @@ int SystemInfo::GetCurCpus() { |
cur_cpus = !error ? static_cast<int>(sysctl_value) : 1; |
#else |
// Linux, Solaris, WEBRTC_ANDROID |
- cur_cpus = static_cast<int>(sysconf(_SC_NPROCESSORS_ONLN)); |
+ cur_cpus = GetMaxCpus(); |
#endif |
return cur_cpus; |
} |
// Return the type of this CPU. |
SystemInfo::Architecture SystemInfo::GetCpuArchitecture() { |
- return cpu_arch_; |
+#if defined(__arm__) || defined(_M_ARM) |
+ return SI_ARCH_ARM; |
+#elif defined(__x86_64__) || defined(_M_X64) |
+ return SI_ARCH_X64; |
+#elif defined(__i386__) || defined(_M_IX86) |
+ return SI_ARCH_X86; |
+#else |
+ return SI_ARCH_UNKNOWN; |
+#endif |
} |
// Returns the vendor string from the cpu, e.g. "GenuineIntel", "AuthenticAMD". |
// See "Intel Processor Identification and the CPUID Instruction" |
// (Intel document number: 241618) |
std::string SystemInfo::GetCpuVendor() { |
- if (cpu_vendor_.empty()) { |
#if defined(CPU_X86) |
- int cpu_info[4]; |
- __cpuid(cpu_info, 0); |
- cpu_info[0] = cpu_info[1]; // Reorder output |
- cpu_info[1] = cpu_info[3]; |
- // cpu_info[2] = cpu_info[2]; // Avoid -Werror=self-assign |
- cpu_info[3] = 0; |
- cpu_vendor_ = std::string(reinterpret_cast<char*>(&cpu_info[0])); |
+ int cpu_info[4]; |
+ __cpuid(cpu_info, 0); |
+ cpu_info[0] = cpu_info[1]; // Reorder output |
+ cpu_info[1] = cpu_info[3]; |
+ // cpu_info[2] = cpu_info[2]; // Avoid -Werror=self-assign |
+ cpu_info[3] = 0; |
+ return std::string(reinterpret_cast<char*>(&cpu_info[0])); |
#elif defined(CPU_ARM) |
- cpu_vendor_ = std::string("ARM"); |
+ return "ARM"; |
#else |
- cpu_vendor_ = std::string("Undefined"); |
-#endif |
- } |
- return cpu_vendor_; |
-} |
- |
-int SystemInfo::GetCpuCacheSize() { |
- return cache_size_; |
-} |
- |
-// Return the "family" of this CPU. |
-int SystemInfo::GetCpuFamily() { |
- return cpu_family_; |
-} |
- |
-// Return the "model" of this CPU. |
-int SystemInfo::GetCpuModel() { |
- return cpu_model_; |
-} |
- |
-// Return the "stepping" of this CPU. |
-int SystemInfo::GetCpuStepping() { |
- return cpu_stepping_; |
-} |
- |
-// Return the clockrate of the primary processor in Mhz. This value can be |
-// cached. Returns -1 on error. |
-int SystemInfo::GetMaxCpuSpeed() { |
- if (cpu_speed_) { |
- return cpu_speed_; |
- } |
-#if defined(WEBRTC_WIN) |
- HKEY key; |
- static const WCHAR keyName[] = |
- L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"; |
- |
- if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyName , 0, KEY_QUERY_VALUE, &key) |
- == ERROR_SUCCESS) { |
- DWORD data, len; |
- len = sizeof(data); |
- |
- if (RegQueryValueEx(key, L"~Mhz", 0, 0, reinterpret_cast<LPBYTE>(&data), |
- &len) == ERROR_SUCCESS) { |
- cpu_speed_ = data; |
- } else { |
- LOG(LS_WARNING) << "Failed to query registry value HKLM\\" << keyName |
- << "\\~Mhz"; |
- cpu_speed_ = -1; |
- } |
- |
- RegCloseKey(key); |
- } else { |
- LOG(LS_WARNING) << "Failed to open registry key HKLM\\" << keyName; |
- cpu_speed_ = -1; |
- } |
-#elif defined(WEBRTC_MAC) |
- uint64_t sysctl_value; |
- size_t length = sizeof(sysctl_value); |
- int error = sysctlbyname("hw.cpufrequency_max", &sysctl_value, &length, |
- NULL, 0); |
- cpu_speed_ = !error ? static_cast<int>(sysctl_value/1000000) : -1; |
-#else |
- // TODO(fbarchard): Implement using proc/cpuinfo |
- cpu_speed_ = 0; |
-#endif |
- return cpu_speed_; |
-} |
- |
-// Dynamically check the current clockrate, which could be reduced because of |
-// powersaving profiles. Eventually for windows we want to query WMI for |
-// root\WMI::ProcessorPerformance.InstanceName="Processor_Number_0".frequency |
-int SystemInfo::GetCurCpuSpeed() { |
-#if defined(WEBRTC_WIN) |
- // TODO(fbarchard): Add WMI check, requires COM initialization |
- // NOTE(fbarchard): Testable on Sandy Bridge. |
- return GetMaxCpuSpeed(); |
-#elif defined(WEBRTC_MAC) |
- uint64_t sysctl_value; |
- size_t length = sizeof(sysctl_value); |
- int error = sysctlbyname("hw.cpufrequency", &sysctl_value, &length, NULL, 0); |
- return !error ? static_cast<int>(sysctl_value/1000000) : GetMaxCpuSpeed(); |
-#else // WEBRTC_LINUX |
- // TODO(fbarchard): Use proc/cpuinfo for Cur speed on Linux. |
- return GetMaxCpuSpeed(); |
+ return "Undefined"; |
#endif |
} |
// Returns the amount of installed physical memory in Bytes. Cacheable. |
// Returns -1 on error. |
int64 SystemInfo::GetMemorySize() { |
- if (memory_) { |
- return memory_; |
- } |
+ int64 memory = -1; |
#if defined(WEBRTC_WIN) |
MEMORYSTATUSEX status = {0}; |
status.dwLength = sizeof(status); |
if (GlobalMemoryStatusEx(&status)) { |
- memory_ = status.ullTotalPhys; |
+ memory = status.ullTotalPhys; |
} else { |
LOG_GLE(LS_WARNING) << "GlobalMemoryStatusEx failed."; |
- memory_ = -1; |
} |
#elif defined(WEBRTC_MAC) |
- size_t len = sizeof(memory_); |
- int error = sysctlbyname("hw.memsize", &memory_, &len, NULL, 0); |
- if (error || memory_ == 0) { |
- memory_ = -1; |
- } |
+ size_t len = sizeof(memory); |
+ int error = sysctlbyname("hw.memsize", &memory, &len, NULL, 0); |
+ if (error || memory == 0) |
+ memory = -1; |
#else // WEBRTC_LINUX |
- memory_ = static_cast<int64>(sysconf(_SC_PHYS_PAGES)) * |
+ memory = static_cast<int64>(sysconf(_SC_PHYS_PAGES)) * |
static_cast<int64>(sysconf(_SC_PAGESIZE)); |
- if (memory_ < 0) { |
+ if (memory < 0) { |
LOG(LS_WARNING) << "sysconf(_SC_PHYS_PAGES) failed." |
<< "sysconf(_SC_PHYS_PAGES) " << sysconf(_SC_PHYS_PAGES) |
<< "sysconf(_SC_PAGESIZE) " << sysconf(_SC_PAGESIZE); |
- memory_ = -1; |
+ memory = -1; |
} |
#endif |
- return memory_; |
+ return memory; |
} |
- |
// Return the name of the machine model we are currently running on. |
// This is a human readable string that consists of the name and version |
// number of the hardware, i.e 'MacBookAir1,1'. Returns an empty string if |
-// model can not be determined. The string is cached for subsequent calls. |
+// model can not be determined. |
std::string SystemInfo::GetMachineModel() { |
- if (!machine_model_.empty()) { |
- return machine_model_; |
- } |
- |
#if defined(WEBRTC_MAC) |
char buffer[128]; |
size_t length = sizeof(buffer); |
int error = sysctlbyname("hw.model", buffer, &length, NULL, 0); |
- if (!error) { |
- machine_model_.assign(buffer, length - 1); |
- } else { |
- machine_model_.clear(); |
- } |
+ if (!error) |
+ return std::string(buffer, length - 1); |
+ return std::string(); |
#else |
- machine_model_ = "Not available"; |
+ return "Not available"; |
#endif |
- |
- return machine_model_; |
} |
-#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS) |
-// Helper functions to query IOKit for video hardware properties. |
-static CFTypeRef SearchForProperty(io_service_t port, CFStringRef name) { |
- return IORegistryEntrySearchCFProperty(port, kIOServicePlane, |
- name, kCFAllocatorDefault, |
- kIORegistryIterateRecursively | kIORegistryIterateParents); |
-} |
- |
-static void GetProperty(io_service_t port, CFStringRef name, int* value) { |
- if (!value) return; |
- CFTypeRef ref = SearchForProperty(port, name); |
- if (ref) { |
- CFTypeID refType = CFGetTypeID(ref); |
- if (CFNumberGetTypeID() == refType) { |
- CFNumberRef number = reinterpret_cast<CFNumberRef>(ref); |
- p_convertCFNumberToInt(number, value); |
- } else if (CFDataGetTypeID() == refType) { |
- CFDataRef data = reinterpret_cast<CFDataRef>(ref); |
- if (CFDataGetLength(data) == sizeof(UInt32)) { |
- *value = *reinterpret_cast<const UInt32*>(CFDataGetBytePtr(data)); |
- } |
- } |
- CFRelease(ref); |
- } |
-} |
- |
-static void GetProperty(io_service_t port, CFStringRef name, |
- std::string* value) { |
- if (!value) return; |
- CFTypeRef ref = SearchForProperty(port, name); |
- if (ref) { |
- CFTypeID refType = CFGetTypeID(ref); |
- if (CFStringGetTypeID() == refType) { |
- CFStringRef stringRef = reinterpret_cast<CFStringRef>(ref); |
- p_convertHostCFStringRefToCPPString(stringRef, *value); |
- } else if (CFDataGetTypeID() == refType) { |
- CFDataRef dataRef = reinterpret_cast<CFDataRef>(ref); |
- *value = std::string(reinterpret_cast<const char*>( |
- CFDataGetBytePtr(dataRef)), CFDataGetLength(dataRef)); |
- } |
- CFRelease(ref); |
- } |
-} |
-#endif |
- |
-SystemInfo::GpuInfo::GpuInfo() : vendor_id(0), device_id(0) { |
-} |
- |
-SystemInfo::GpuInfo::~GpuInfo() = default; |
- |
-// Fills a struct with information on the graphics adapater and returns true |
-// iff successful. |
-bool SystemInfo::GetGpuInfo(GpuInfo *info) { |
- if (!info) return false; |
-#if defined(WEBRTC_WIN) && !defined(EXCLUDE_D3D9) |
- D3DADAPTER_IDENTIFIER9 identifier; |
- HRESULT hr = E_FAIL; |
- HINSTANCE d3d_lib = LoadLibrary(L"d3d9.dll"); |
- |
- if (d3d_lib) { |
- typedef IDirect3D9* (WINAPI *D3DCreate9Proc)(UINT); |
- D3DCreate9Proc d3d_create_proc = reinterpret_cast<D3DCreate9Proc>( |
- GetProcAddress(d3d_lib, "Direct3DCreate9")); |
- if (d3d_create_proc) { |
- IDirect3D9* d3d = d3d_create_proc(D3D_SDK_VERSION); |
- if (d3d) { |
- hr = d3d->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &identifier); |
- d3d->Release(); |
- } |
- } |
- FreeLibrary(d3d_lib); |
- } |
- |
- if (hr != D3D_OK) { |
- LOG(LS_ERROR) << "Failed to access Direct3D9 information."; |
- return false; |
- } |
- |
- info->device_name = identifier.DeviceName; |
- info->description = identifier.Description; |
- info->vendor_id = identifier.VendorId; |
- info->device_id = identifier.DeviceId; |
- info->driver = identifier.Driver; |
- // driver_version format: product.version.subversion.build |
- std::stringstream ss; |
- ss << HIWORD(identifier.DriverVersion.HighPart) << "." |
- << LOWORD(identifier.DriverVersion.HighPart) << "." |
- << HIWORD(identifier.DriverVersion.LowPart) << "." |
- << LOWORD(identifier.DriverVersion.LowPart); |
- info->driver_version = ss.str(); |
- return true; |
-#elif defined(WEBRTC_MAC) && !defined(WEBRTC_IOS) |
- // We'll query the IOKit for the gpu of the main display. |
- io_service_t display_service_port = CGDisplayIOServicePort( |
- kCGDirectMainDisplay); |
- GetProperty(display_service_port, CFSTR("vendor-id"), &info->vendor_id); |
- GetProperty(display_service_port, CFSTR("device-id"), &info->device_id); |
- GetProperty(display_service_port, CFSTR("model"), &info->description); |
- return true; |
-#else // WEBRTC_LINUX |
- // TODO(fbarchard): Implement this on Linux |
- return false; |
-#endif |
-} |
} // namespace rtc |