Add Google Tensor SoC detection. (#382)

Identify Google Tensor SoCs (Tensor, GS201) in ro.soc.model Android system property.
Updated src/arm/api.h and src/arm/linux/chipset.c to match internal Google CL 604382821.

GitOrigin-RevId: ea6b9f1bb6e1001d8b21574d5bc78ddef62e499d
Change-Id: Ib3f9a46ad1b2960f33baeffb7af8eb23d12202af
diff --git a/src/arm/api.h b/src/arm/api.h
index cfb99ff..d7c74c8 100644
--- a/src/arm/api.h
+++ b/src/arm/api.h
@@ -36,6 +36,7 @@
 	cpuinfo_arm_chipset_vendor_texas_instruments,
 	cpuinfo_arm_chipset_vendor_unisoc,
 	cpuinfo_arm_chipset_vendor_wondermedia,
+	cpuinfo_arm_chipset_vendor_google,
 	cpuinfo_arm_chipset_vendor_max,
 };
 
@@ -73,6 +74,7 @@
 	cpuinfo_arm_chipset_series_unisoc_t,
 	cpuinfo_arm_chipset_series_unisoc_ums,
 	cpuinfo_arm_chipset_series_wondermedia_wm,
+	cpuinfo_arm_chipset_series_google_tensor,
 	cpuinfo_arm_chipset_series_max,
 };
 
diff --git a/src/arm/linux/api.h b/src/arm/linux/api.h
index 453b1e9..43bbbc3 100644
--- a/src/arm/linux/api.h
+++ b/src/arm/linux/api.h
@@ -366,7 +366,7 @@
 CPUINFO_INTERNAL struct cpuinfo_arm_chipset cpuinfo_arm_android_decode_chipset_from_ro_hardware_chipname(
 	const char ro_hardware_chipname[restrict static CPUINFO_BUILD_PROP_VALUE_MAX]);
 CPUINFO_INTERNAL struct cpuinfo_arm_chipset cpuinfo_arm_android_decode_chipset_from_ro_soc_model(
-	const char ro_soc_model[restrict static CPUINFO_BUILD_PROP_VALUE_MAX]);
+	const char soc_model[restrict static CPUINFO_BUILD_PROP_VALUE_MAX]);
 #else
 CPUINFO_INTERNAL struct cpuinfo_arm_chipset cpuinfo_arm_linux_decode_chipset_from_proc_cpuinfo_revision(
 	const char proc_cpuinfo_revision[restrict static CPUINFO_REVISION_VALUE_MAX]);
diff --git a/src/arm/linux/chipset.c b/src/arm/linux/chipset.c
index 0a03642..1dfe788 100644
--- a/src/arm/linux/chipset.c
+++ b/src/arm/linux/chipset.c
@@ -3492,9 +3492,20 @@
 	};
 }
 
+/*
+ * Decodes chipset name from ro.soc.model Android system property.
+ *
+ * @param[in] soc_model - ro.soc.model value.
+ *
+ * @returns Decoded chipset name. If chipset could not be decoded, the resulting
+ * structure would use `unknown` vendor and series identifiers.
+ */
 struct cpuinfo_arm_chipset cpuinfo_arm_android_decode_chipset_from_ro_soc_model(
 	const char soc_model[restrict static CPUINFO_BUILD_PROP_VALUE_MAX]) {
-	struct cpuinfo_arm_chipset chipset;
+	struct cpuinfo_arm_chipset chipset = {
+		.vendor = cpuinfo_arm_chipset_vendor_unknown,
+		.series = cpuinfo_arm_chipset_series_unknown,
+	};
 	const size_t soc_model_length = strnlen(soc_model, CPUINFO_BUILD_PROP_VALUE_MAX);
 	const char* soc_model_end = soc_model + soc_model_length;
 
@@ -3516,10 +3527,28 @@
 		return chipset;
 	}
 
-	return (struct cpuinfo_arm_chipset){
-		.vendor = cpuinfo_arm_chipset_vendor_unknown,
-		.series = cpuinfo_arm_chipset_series_unknown,
-	};
+	if (soc_model[0] != '\0') {
+		if (strncmp(soc_model, "Tensor", 6) == 0) {
+			chipset.vendor = cpuinfo_arm_chipset_vendor_google;
+			chipset.series = cpuinfo_arm_chipset_series_google_tensor;
+			const char* suffix_start = soc_model + 6;
+			while (*suffix_start == ' ') {
+				suffix_start++;
+			}
+			const size_t suffix_length = strnlen(suffix_start, CPUINFO_ARM_CHIPSET_SUFFIX_MAX);
+			if (suffix_length > 0) {
+				strncpy(chipset.suffix, suffix_start, suffix_length);
+			}
+			return chipset;
+		} else if (strncmp(soc_model, "GS201", 5) == 0) {
+			chipset.vendor = cpuinfo_arm_chipset_vendor_google;
+			chipset.series = cpuinfo_arm_chipset_series_google_tensor;
+			strncpy(chipset.suffix, "G2", 2);
+			return chipset;
+		}
+	}
+
+	return chipset;
 }
 #endif /* __ANDROID__ */
 
@@ -3858,6 +3887,7 @@
 	[cpuinfo_arm_chipset_vendor_texas_instruments] = "Texas Instruments",
 	[cpuinfo_arm_chipset_vendor_unisoc] = "Unisoc",
 	[cpuinfo_arm_chipset_vendor_wondermedia] = "WonderMedia",
+	[cpuinfo_arm_chipset_vendor_google] = "Google",
 };
 
 /* Map from ARM chipset series ID to its string representation */
@@ -3895,6 +3925,7 @@
 	[cpuinfo_arm_chipset_series_unisoc_t] = "T",
 	[cpuinfo_arm_chipset_series_unisoc_ums] = "UMS",
 	[cpuinfo_arm_chipset_series_wondermedia_wm] = "WM",
+	[cpuinfo_arm_chipset_series_google_tensor] = "Tensor",
 };
 
 /* Convert chipset name represented by cpuinfo_arm_chipset structure to a string
@@ -3913,14 +3944,35 @@
 	const char* vendor_string = chipset_vendor_string[vendor];
 	const char* series_string = chipset_series_string[series];
 	const uint32_t model = chipset->model;
+	const size_t suffix_length = strnlen(chipset->suffix, CPUINFO_ARM_CHIPSET_SUFFIX_MAX);
 	if (model == 0) {
-		if (series == cpuinfo_arm_chipset_series_unknown) {
-			strncpy(name, vendor_string, CPUINFO_ARM_CHIPSET_NAME_MAX);
+		if (suffix_length > 0) {
+			if (series == cpuinfo_arm_chipset_series_unknown) {
+				snprintf(
+					name,
+					CPUINFO_ARM_CHIPSET_NAME_MAX,
+					"%s %.*s",
+					vendor_string,
+					(int)suffix_length,
+					chipset->suffix);
+			} else {
+				snprintf(
+					name,
+					CPUINFO_ARM_CHIPSET_NAME_MAX,
+					"%s %s %.*s",
+					vendor_string,
+					series_string,
+					(int)suffix_length,
+					chipset->suffix);
+			}
 		} else {
-			snprintf(name, CPUINFO_ARM_CHIPSET_NAME_MAX, "%s %s", vendor_string, series_string);
+			if (series == cpuinfo_arm_chipset_series_unknown) {
+				strncpy(name, vendor_string, CPUINFO_ARM_CHIPSET_NAME_MAX);
+			} else {
+				snprintf(name, CPUINFO_ARM_CHIPSET_NAME_MAX, "%s %s", vendor_string, series_string);
+			}
 		}
 	} else {
-		const size_t suffix_length = strnlen(chipset->suffix, CPUINFO_ARM_CHIPSET_SUFFIX_MAX);
 		snprintf(
 			name,
 			CPUINFO_ARM_CHIPSET_NAME_MAX,
@@ -4051,7 +4103,6 @@
 	    (vendor_a == cpuinfo_arm_chipset_vendor_spreadtrum && vendor_b == cpuinfo_arm_chipset_vendor_unisoc)) {
 		return cpuinfo_arm_chipset_vendor_unisoc;
 	}
-
 	return cpuinfo_arm_chipset_vendor_unknown;
 }