Bug 1533861 - Add a telemetry to detect disk type r=chutten,froydnj,bdekoz
authorSean Feng <sefeng@mozilla.com>
Wed, 08 May 2019 15:30:07 +0000
changeset 532052 035696395109f035a7c314c9f759843a364dc01f
parent 532051 1e371ad57bd0be4039954e30bc0832350e9f3656
child 532053 6f7374e16ef5826b723a558a2447dda0595dc57b
push id11265
push userffxbld-merge
push dateMon, 13 May 2019 10:53:39 +0000
treeherdermozilla-beta@77e0fe8dbdd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerschutten, froydnj, bdekoz
bugs1533861
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1533861 - Add a telemetry to detect disk type r=chutten,froydnj,bdekoz Differential Revision: https://phabricator.services.mozilla.com/D29383
toolkit/components/telemetry/app/TelemetryEnvironment.jsm
toolkit/components/telemetry/docs/data/environment.rst
toolkit/components/telemetry/tests/unit/test_TelemetryEnvironment.js
xpcom/base/nsSystemInfo.cpp
--- a/toolkit/components/telemetry/app/TelemetryEnvironment.jsm
+++ b/toolkit/components/telemetry/app/TelemetryEnvironment.jsm
@@ -1713,24 +1713,27 @@ EnvironmentCache.prototype = {
    * Get the HDD information.
    * @return Object containing the HDD data.
    */
   _getHDDData() {
     return {
       profile: { // hdd where the profile folder is located
         model: getSysinfoProperty("profileHDDModel", null),
         revision: getSysinfoProperty("profileHDDRevision", null),
+        type: getSysinfoProperty("profileHDDType", null),
       },
       binary:  { // hdd where the application binary is located
         model: getSysinfoProperty("binHDDModel", null),
         revision: getSysinfoProperty("binHDDRevision", null),
+        type: getSysinfoProperty("binHDDType", null),
       },
       system:  { // hdd where the system files are located
         model: getSysinfoProperty("winHDDModel", null),
         revision: getSysinfoProperty("winHDDRevision", null),
+        type: getSysinfoProperty("winHDDType", null),
       },
     };
   },
 
   /**
    * Get registered security product information.
    * @return Object containing the security product data
    */
--- a/toolkit/components/telemetry/docs/data/environment.rst
+++ b/toolkit/components/telemetry/docs/data/environment.rst
@@ -136,24 +136,27 @@ Structure:
             windowsUBR: <number>, // windows 10 only or null on failure
             installYear: <number>, // windows only or null on failure
             locale: <string>, // "en" or null on failure
         },
         hdd: {
           profile: { // hdd where the profile folder is located
               model: <string>, // windows only or null on failure
               revision: <string>, // windows only or null on failure
+              type: <string>, // "SSD" or "HDD" windows only or null on failure
           },
           binary:  { // hdd where the application binary is located
               model: <string>, // windows only or null on failure
               revision: <string>, // windows only or null on failure
+              type: <string>, // "SSD" or "HDD" windows only or null on failure
           },
           system:  { // hdd where the system files are located
               model: <string>, // windows only or null on failure
               revision: <string>, // windows only or null on failure
+              type: <string>, // "SSD" or "HDD" windows only or null on failure
           },
         },
         gfx: {
             D2DEnabled: <bool>, // null on failure
             DWriteEnabled: <bool>, // null on failure
             Headless: <bool>, // null on failure
             //DWriteVersion: <string>, // temporarily removed, pending bug 1154500
             adapters: [
--- a/toolkit/components/telemetry/tests/unit/test_TelemetryEnvironment.js
+++ b/toolkit/components/telemetry/tests/unit/test_TelemetryEnvironment.js
@@ -602,16 +602,17 @@ function checkSystemSection(data) {
   } else if (gIsAndroid) {
     Assert.ok(checkNullOrString(osData.kernelVersion));
   }
 
   let check = gIsWindows ? checkString : checkNullOrString;
   for (let disk of EXPECTED_HDD_FIELDS) {
     Assert.ok(check(data.system.hdd[disk].model));
     Assert.ok(check(data.system.hdd[disk].revision));
+    Assert.ok(check(data.system.hdd[disk].type));
   }
 
   let gfxData = data.system.gfx;
   Assert.ok("D2DEnabled" in gfxData);
   Assert.ok("DWriteEnabled" in gfxData);
   Assert.ok("Headless" in gfxData);
   // DWriteVersion is disabled due to main thread jank and will be enabled
   // again as part of bug 1154500.
--- a/xpcom/base/nsSystemInfo.cpp
+++ b/xpcom/base/nsSystemInfo.cpp
@@ -96,19 +96,20 @@ static void SimpleParseKeyValuePairs(
     }
   }
 }
 #endif
 
 #if defined(XP_WIN)
 namespace {
 nsresult GetHDDInfo(const char* aSpecialDirName, nsAutoCString& aModel,
-                    nsAutoCString& aRevision) {
+                    nsAutoCString& aRevision, nsAutoCString& aType) {
   aModel.Truncate();
   aRevision.Truncate();
+  aType.Truncate();
 
   nsCOMPtr<nsIFile> profDir;
   nsresult rv =
       NS_GetSpecialDirectory(aSpecialDirName, getter_AddRefs(profDir));
   NS_ENSURE_SUCCESS(rv, rv);
   nsAutoString profDirPath;
   rv = profDir->GetPath(profDirPath);
   NS_ENSURE_SUCCESS(rv, rv);
@@ -144,16 +145,46 @@ nsresult GetHDDInfo(const char* aSpecial
   PSTORAGE_DEVICE_DESCRIPTOR deviceOutput =
       (PSTORAGE_DEVICE_DESCRIPTOR)malloc(outputHeader.Size);
   if (!::DeviceIoControl(handle, IOCTL_STORAGE_QUERY_PROPERTY, &queryParameters,
                          sizeof(queryParameters), deviceOutput,
                          outputHeader.Size, &bytesRead, nullptr)) {
     free(deviceOutput);
     return NS_ERROR_FAILURE;
   }
+
+  queryParameters.PropertyId = StorageDeviceTrimProperty;
+  bytesRead = 0;
+  bool isSSD = false;
+  DEVICE_TRIM_DESCRIPTOR trimDescriptor = {sizeof(DEVICE_TRIM_DESCRIPTOR)};
+  if (::DeviceIoControl(handle, IOCTL_STORAGE_QUERY_PROPERTY, &queryParameters,
+                        sizeof(queryParameters), &trimDescriptor,
+                        sizeof(trimDescriptor), &bytesRead, nullptr)) {
+    if (trimDescriptor.TrimEnabled) {
+      isSSD = true;
+    }
+  }
+
+  if (isSSD) {
+    // Get Seek Penalty
+    queryParameters.PropertyId = StorageDeviceSeekPenaltyProperty;
+    bytesRead = 0;
+    DEVICE_SEEK_PENALTY_DESCRIPTOR seekPenaltyDescriptor = {
+      sizeof(DEVICE_SEEK_PENALTY_DESCRIPTOR)};
+    if (::DeviceIoControl(handle, IOCTL_STORAGE_QUERY_PROPERTY, &queryParameters,
+          sizeof(queryParameters), &seekPenaltyDescriptor,
+          sizeof(seekPenaltyDescriptor), &bytesRead, nullptr)) {
+      // It is possible that the disk has TrimEnabled, but also IncursSeekPenalty;
+      // In this case, this is an HDD
+      if (seekPenaltyDescriptor.IncursSeekPenalty) {
+        isSSD = false;
+      }
+    }
+  }
+
   // Some HDDs are including product ID info in the vendor field. Since PNP
   // IDs include vendor info and product ID concatenated together, we'll do
   // that here and interpret the result as a unique ID for the HDD model.
   if (deviceOutput->VendorIdOffset) {
     aModel =
         reinterpret_cast<char*>(deviceOutput) + deviceOutput->VendorIdOffset;
   }
   if (deviceOutput->ProductIdOffset) {
@@ -161,16 +192,21 @@ nsresult GetHDDInfo(const char* aSpecial
         reinterpret_cast<char*>(deviceOutput) + deviceOutput->ProductIdOffset;
   }
   aModel.CompressWhitespace();
   if (deviceOutput->ProductRevisionOffset) {
     aRevision = reinterpret_cast<char*>(deviceOutput) +
                 deviceOutput->ProductRevisionOffset;
     aRevision.CompressWhitespace();
   }
+  if (isSSD) {
+    aType = "SSD";
+  } else {
+    aType = "HDD";
+  }
   free(deviceOutput);
   return NS_OK;
 }
 
 nsresult GetInstallYear(uint32_t& aYear) {
   HKEY hKey;
   LONG status = RegOpenKeyExW(
       HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0,
@@ -777,30 +813,35 @@ nsresult nsSystemInfo::Init() {
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     rv = obsService->AddObserver(this, "profile-do-change", false);
     if (NS_FAILED(rv)) {
       return rv;
     }
   }
-  nsAutoCString hddModel, hddRevision;
-  if (NS_SUCCEEDED(GetHDDInfo(NS_GRE_DIR, hddModel, hddRevision))) {
+  nsAutoCString hddModel, hddRevision, hddType;
+  if (NS_SUCCEEDED(GetHDDInfo(NS_GRE_DIR, hddModel, hddRevision, hddType))) {
     rv = SetPropertyAsACString(NS_LITERAL_STRING("binHDDModel"), hddModel);
     NS_ENSURE_SUCCESS(rv, rv);
     rv =
         SetPropertyAsACString(NS_LITERAL_STRING("binHDDRevision"), hddRevision);
     NS_ENSURE_SUCCESS(rv, rv);
+    rv = SetPropertyAsACString(NS_LITERAL_STRING("binHDDType"), hddType);
+    NS_ENSURE_SUCCESS(rv, rv);
   }
-  if (NS_SUCCEEDED(GetHDDInfo(NS_WIN_WINDOWS_DIR, hddModel, hddRevision))) {
+  if (NS_SUCCEEDED(
+          GetHDDInfo(NS_WIN_WINDOWS_DIR, hddModel, hddRevision, hddType))) {
     rv = SetPropertyAsACString(NS_LITERAL_STRING("winHDDModel"), hddModel);
     NS_ENSURE_SUCCESS(rv, rv);
     rv =
         SetPropertyAsACString(NS_LITERAL_STRING("winHDDRevision"), hddRevision);
     NS_ENSURE_SUCCESS(rv, rv);
+    rv = SetPropertyAsACString(NS_LITERAL_STRING("winHDDType"), hddType);
+    NS_ENSURE_SUCCESS(rv, rv);
   }
 
   nsAutoString countryCode;
   if (NS_SUCCEEDED(GetCountryCode(countryCode))) {
     rv = SetPropertyAsAString(NS_LITERAL_STRING("countryCode"), countryCode);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
@@ -1057,24 +1098,29 @@ nsSystemInfo::Observe(nsISupports* aSubj
       return rv;
     }
     return GetProfileHDDInfo();
   }
   return NS_OK;
 }
 
 nsresult nsSystemInfo::GetProfileHDDInfo() {
-  nsAutoCString hddModel, hddRevision;
-  nsresult rv = GetHDDInfo(NS_APP_USER_PROFILE_50_DIR, hddModel, hddRevision);
+  nsAutoCString hddModel, hddRevision, hddType;
+  nsresult rv =
+      GetHDDInfo(NS_APP_USER_PROFILE_50_DIR, hddModel, hddRevision, hddType);
   if (NS_FAILED(rv)) {
     return rv;
   }
   rv = SetPropertyAsACString(NS_LITERAL_STRING("profileHDDModel"), hddModel);
   if (NS_FAILED(rv)) {
     return rv;
   }
   rv = SetPropertyAsACString(NS_LITERAL_STRING("profileHDDRevision"),
                              hddRevision);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  rv = SetPropertyAsACString(NS_LITERAL_STRING("profileHDDType"), hddType);
   return rv;
 }
 
 NS_IMPL_ISUPPORTS_INHERITED(nsSystemInfo, nsHashPropertyBag, nsIObserver)
 #endif  // defined(XP_WIN)