diff --git a/cobalt/browser/client_hint_headers.cc b/cobalt/browser/client_hint_headers.cc index 99794d5d7050..b9acc0ac8cd8 100644 --- a/cobalt/browser/client_hint_headers.cc +++ b/cobalt/browser/client_hint_headers.cc @@ -49,6 +49,9 @@ std::vector GetClientHintHeaders( AddHeader(headers, "Android-OS-Experience", platform_info.android_os_experience()); + AddHeader(headers, "Android-Play-Services-Version", + platform_info.android_play_services_version()); + return headers; } diff --git a/cobalt/browser/client_hint_headers_test.cc b/cobalt/browser/client_hint_headers_test.cc index 7cb26e9a8e41..3706e1afe1b7 100644 --- a/cobalt/browser/client_hint_headers_test.cc +++ b/cobalt/browser/client_hint_headers_test.cc @@ -29,12 +29,14 @@ TEST(ClientHintHeadersTest, GetClientHintHeaders) { UserAgentPlatformInfo platform_info; platform_info.set_android_build_fingerprint("abc/def:123.456/xy-z"); platform_info.set_android_os_experience("Amati"); + platform_info.set_android_play_services_version("123"); std::vector headers = GetClientHintHeaders(platform_info); EXPECT_THAT(headers, UnorderedElementsAre( "Sec-CH-UA-Co-Android-Build-Fingerprint:abc/def:123.456/xy-z", - "Sec-CH-UA-Co-Android-OS-Experience:Amati")); + "Sec-CH-UA-Co-Android-OS-Experience:Amati", + "Sec-CH-UA-Co-Android-Play-Services-Version:123")); } } // namespace diff --git a/cobalt/browser/user_agent_platform_info.cc b/cobalt/browser/user_agent_platform_info.cc index 21e07747449a..5c0d65895531 100644 --- a/cobalt/browser/user_agent_platform_info.cc +++ b/cobalt/browser/user_agent_platform_info.cc @@ -280,16 +280,23 @@ void InitializeUserAgentPlatformInfoFields(UserAgentPlatformInfo& info) { auto platform_info_extension = static_cast( SbSystemGetExtension(kCobaltExtensionPlatformInfoName)); - if (platform_info_extension && - strcmp(platform_info_extension->name, kCobaltExtensionPlatformInfoName) == - 0 && - platform_info_extension->version >= 1) { - result = platform_info_extension->GetFirmwareVersionDetails( - value, kSystemPropertyMaxLength); - if (result) { - info.set_android_build_fingerprint(value); + if (platform_info_extension) { + if (platform_info_extension->version >= 1) { + result = platform_info_extension->GetFirmwareVersionDetails( + value, kSystemPropertyMaxLength); + if (result) { + info.set_android_build_fingerprint(value); + } + info.set_android_os_experience( + platform_info_extension->GetOsExperience()); + } + if (platform_info_extension->version >= 2) { + int64_t ver = platform_info_extension->GetCoreServicesVersion(); + if (ver != 0) { + std::string sver = std::to_string(ver); + info.set_android_play_services_version(sver); + } } - info.set_android_os_experience(platform_info_extension->GetOsExperience()); } info.set_cobalt_version(COBALT_VERSION); @@ -433,6 +440,9 @@ void InitializeUserAgentPlatformInfoFields(UserAgentPlatformInfo& info) { } else if (!input.first.compare("android_os_experience")) { info.set_android_os_experience(input.second); LOG(INFO) << "Set android os experience to " << input.second; + } else if (!input.first.compare("android_play_services_version")) { + info.set_android_play_services_version(input.second); + LOG(INFO) << "Set android play services version to " << input.second; } else if (!input.first.compare("cobalt_version")) { info.set_cobalt_version(input.second); LOG(INFO) << "Set cobalt type to " << input.second; @@ -559,6 +569,12 @@ void UserAgentPlatformInfo::set_android_os_experience( android_os_experience_ = Sanitize(android_os_experience, isTCHAR); } +void UserAgentPlatformInfo::set_android_play_services_version( + const std::string& android_play_services_version) { + android_play_services_version_ = + Sanitize(android_play_services_version, base::IsAsciiDigit); +} + void UserAgentPlatformInfo::set_cobalt_version( const std::string& cobalt_version) { cobalt_version_ = Sanitize(cobalt_version, isTCHAR); diff --git a/cobalt/browser/user_agent_platform_info.h b/cobalt/browser/user_agent_platform_info.h index 658e0cba0215..f9267345dff2 100644 --- a/cobalt/browser/user_agent_platform_info.h +++ b/cobalt/browser/user_agent_platform_info.h @@ -82,6 +82,9 @@ class UserAgentPlatformInfo : public web::UserAgentPlatformInfo { const std::string& android_os_experience() const override { return android_os_experience_; } + const std::string& android_play_services_version() const override { + return android_play_services_version_; + } const std::string& cobalt_version() const override { return cobalt_version_; } const std::string& cobalt_build_version_number() const override { return cobalt_build_version_number_; @@ -118,6 +121,8 @@ class UserAgentPlatformInfo : public web::UserAgentPlatformInfo { void set_android_build_fingerprint( const std::string& android_build_fingerprint); void set_android_os_experience(const std::string& android_os_experience); + void set_android_play_services_version( + const std::string& android_play_services_version); void set_cobalt_version(const std::string& cobalt_version); void set_cobalt_build_version_number( const std::string& cobalt_build_version_number); @@ -142,8 +147,9 @@ class UserAgentPlatformInfo : public web::UserAgentPlatformInfo { std::string evergreen_type_; std::string evergreen_file_type_; std::string evergreen_version_; - std::string android_build_fingerprint_; // Only via Client Hints - std::string android_os_experience_; // Only via Client Hints + std::string android_build_fingerprint_; // Only via Client Hints + std::string android_os_experience_; // Only via Client Hints + std::string android_play_services_version_; // Only via Client Hints std::string cobalt_version_; std::string cobalt_build_version_number_; diff --git a/cobalt/web/cobalt_ua_data_values.idl b/cobalt/web/cobalt_ua_data_values.idl index eef1fa00f3b1..8e33fbd97647 100644 --- a/cobalt/web/cobalt_ua_data_values.idl +++ b/cobalt/web/cobalt_ua_data_values.idl @@ -24,6 +24,7 @@ dictionary CobaltUADataValues : UADataValues { DOMString evergreenVersion; DOMString androidBuildFingerprint; DOMString androidOsExperience; + DOMString androidPlayServicesVersion; DOMString starboardVersion; DOMString originalDesignManufacturer; DOMString deviceType; diff --git a/cobalt/web/cobalt_ua_data_values_interface.cc b/cobalt/web/cobalt_ua_data_values_interface.cc index ac4a9c0d71f4..11f4c848ced8 100644 --- a/cobalt/web/cobalt_ua_data_values_interface.cc +++ b/cobalt/web/cobalt_ua_data_values_interface.cc @@ -73,6 +73,9 @@ CobaltUADataValuesInterface::CobaltUADataValuesInterface( if (init_dict.has_android_os_experience()) { android_os_experience_ = init_dict.android_os_experience(); } + if (init_dict.has_android_play_services_version()) { + android_play_services_version_ = init_dict.android_play_services_version(); + } if (init_dict.has_starboard_version()) { starboard_version_ = init_dict.starboard_version(); } diff --git a/cobalt/web/cobalt_ua_data_values_interface.h b/cobalt/web/cobalt_ua_data_values_interface.h index 22599ff77eb2..9f5b94135aed 100644 --- a/cobalt/web/cobalt_ua_data_values_interface.h +++ b/cobalt/web/cobalt_ua_data_values_interface.h @@ -54,6 +54,9 @@ class CobaltUADataValuesInterface : public script::Wrappable { const std::string& android_os_experience() const { return android_os_experience_; } + const std::string& android_play_services_version() const { + return android_play_services_version_; + } const std::string& starboard_version() const { return starboard_version_; } const std::string& original_design_manufacturer() const { return original_design_manufacturer_; @@ -87,6 +90,7 @@ class CobaltUADataValuesInterface : public script::Wrappable { std::string evergreen_version_; std::string android_build_fingerprint_; std::string android_os_experience_; + std::string android_play_services_version_; std::string starboard_version_; std::string original_design_manufacturer_; std::string device_type_; diff --git a/cobalt/web/cobalt_ua_data_values_interface.idl b/cobalt/web/cobalt_ua_data_values_interface.idl index b7ce6341ccd2..d3fbbacfb3a9 100644 --- a/cobalt/web/cobalt_ua_data_values_interface.idl +++ b/cobalt/web/cobalt_ua_data_values_interface.idl @@ -34,6 +34,7 @@ interface CobaltUADataValuesInterface { readonly attribute DOMString evergreenVersion; readonly attribute DOMString androidBuildFingerprint; readonly attribute DOMString androidOsExperience; + readonly attribute DOMString androidPlayServicesVersion; readonly attribute DOMString starboardVersion; readonly attribute DOMString originalDesignManufacturer; readonly attribute DOMString deviceType; diff --git a/cobalt/web/navigator_ua_data.cc b/cobalt/web/navigator_ua_data.cc index 25db46917b65..bbe0344ab226 100644 --- a/cobalt/web/navigator_ua_data.cc +++ b/cobalt/web/navigator_ua_data.cc @@ -65,6 +65,8 @@ NavigatorUAData::NavigatorUAData( platform_info->android_build_fingerprint()); all_high_entropy_values_.set_android_os_experience( platform_info->android_os_experience()); + all_high_entropy_values_.set_android_play_services_version( + platform_info->android_play_services_version()); all_high_entropy_values_.set_starboard_version( platform_info->starboard_version()); all_high_entropy_values_.set_original_design_manufacturer( diff --git a/cobalt/web/testing/mock_user_agent_platform_info.h b/cobalt/web/testing/mock_user_agent_platform_info.h index fca692f375b0..c8eeb2295448 100644 --- a/cobalt/web/testing/mock_user_agent_platform_info.h +++ b/cobalt/web/testing/mock_user_agent_platform_info.h @@ -27,7 +27,7 @@ namespace testing { class MockUserAgentPlatformInfo : public web::UserAgentPlatformInfo { public: MockUserAgentPlatformInfo() {} - ~MockUserAgentPlatformInfo() override{}; + ~MockUserAgentPlatformInfo() override {}; // From: dom:UserAgentPlatformInfo // @@ -81,6 +81,9 @@ class MockUserAgentPlatformInfo : public web::UserAgentPlatformInfo { const std::string& android_os_experience() const override { return empty_string_; } + const std::string& android_play_services_version() const override { + return empty_string_; + } const std::string& cobalt_version() const override { return empty_string_; } const std::string& cobalt_build_version_number() const override { return empty_string_; diff --git a/cobalt/web/user_agent_platform_info.h b/cobalt/web/user_agent_platform_info.h index d7b4ad141e31..f523addd888d 100644 --- a/cobalt/web/user_agent_platform_info.h +++ b/cobalt/web/user_agent_platform_info.h @@ -49,6 +49,7 @@ class UserAgentPlatformInfo { virtual const std::string& evergreen_version() const = 0; virtual const std::string& android_build_fingerprint() const = 0; virtual const std::string& android_os_experience() const = 0; + virtual const std::string& android_play_services_version() const = 0; virtual const std::string& cobalt_version() const = 0; virtual const std::string& cobalt_build_version_number() const = 0; diff --git a/starboard/android/apk/app/build.gradle b/starboard/android/apk/app/build.gradle index 55f291a34f13..55ba2b964ea1 100644 --- a/starboard/android/apk/app/build.gradle +++ b/starboard/android/apk/app/build.gradle @@ -16,6 +16,8 @@ apply plugin: 'com.android.application' final DEFAULT_COBALT_TARGET = 'cobalt' final String[] SUPPORTED_ABIS = [ 'x86', 'armeabi-v7a', 'arm64-v8a' ] +final MIN_SUPPORTED_SDK_VERSION = 24 +final LATEST_SUPPORTED_SDK_VERSION = 34 // Parse the NDK_VERSION and CMAKE_VERSION defined in sdk_utils.py final SDK_UTILS = project.rootProject.file('../shared/sdk_utils.py') @@ -45,8 +47,8 @@ println "TARGET: ${cobaltTarget}" android { namespace "dev.cobalt.coat" - compileSdkVersion 'android-31' - buildToolsVersion '31.0.0' + compileSdkVersion "android-${LATEST_SUPPORTED_SDK_VERSION}" + buildToolsVersion "${LATEST_SUPPORTED_SDK_VERSION}.0.0" ndkVersion NDK_VERSION compileOptions { @@ -75,8 +77,9 @@ android { } defaultConfig { applicationId "dev.cobalt.coat" - minSdkVersion 24 - targetSdkVersion 34 + minSdkVersion MIN_SUPPORTED_SDK_VERSION + targetSdkVersion LATEST_SUPPORTED_SDK_VERSION + compileSdkVersion LATEST_SUPPORTED_SDK_VERSION versionCode 1 versionName "${buildId}" manifestPlaceholders = [ diff --git a/starboard/android/apk/app/src/main/java/dev/cobalt/coat/StarboardBridge.java b/starboard/android/apk/app/src/main/java/dev/cobalt/coat/StarboardBridge.java index 4c0f61cd37d6..381b18862d12 100644 --- a/starboard/android/apk/app/src/main/java/dev/cobalt/coat/StarboardBridge.java +++ b/starboard/android/apk/app/src/main/java/dev/cobalt/coat/StarboardBridge.java @@ -111,6 +111,7 @@ public void run() { private final HashMap cobaltServices = new HashMap<>(); private final HashMap crashContext = new HashMap<>(); + private static final String GOOGLE_PLAY_SERVICES_PACKAGE = "com.google.android.gms"; private static final String AMATI_EXPERIENCE_FEATURE = "com.google.android.feature.AMATI_EXPERIENCE"; private final boolean isAmatiDevice; @@ -620,7 +621,15 @@ protected String getUserAgentAuxField() { sb.append('/'); try { - sb.append(appContext.getPackageManager().getPackageInfo(packageName, 0).versionName); + if (android.os.Build.VERSION.SDK_INT < 33) { + sb.append(appContext.getPackageManager().getPackageInfo(packageName, 0).versionName); + } else { + sb.append( + appContext + .getPackageManager() + .getPackageInfo(packageName, PackageManager.PackageInfoFlags.of(0)) + .versionName); + } } catch (PackageManager.NameNotFoundException ex) { // Should never happen Log.e(TAG, "Can't find our own package", ex); @@ -799,4 +808,30 @@ protected boolean getIsAmatiDevice() { protected String getBuildFingerprint() { return Build.FINGERPRINT; } + + @SuppressWarnings("unused") + @UsedByNative + protected long getPlayServicesVersion() { + try { + if (android.os.Build.VERSION.SDK_INT < 28) { + return appContext + .getPackageManager() + .getPackageInfo(GOOGLE_PLAY_SERVICES_PACKAGE, 0) + .versionCode; + } else if (android.os.Build.VERSION.SDK_INT < 33) { + return appContext + .getPackageManager() + .getPackageInfo(GOOGLE_PLAY_SERVICES_PACKAGE, 0) + .getLongVersionCode(); + } else { + return appContext + .getPackageManager() + .getPackageInfo(GOOGLE_PLAY_SERVICES_PACKAGE, PackageManager.PackageInfoFlags.of(0)) + .getLongVersionCode(); + } + } catch (Exception e) { + Log.w(TAG, "Unable to query Google Play Services package version", e); + return 0; + } + } } diff --git a/starboard/android/shared/platform_info.cc b/starboard/android/shared/platform_info.cc index 39d036bf63b6..967fe146aba0 100644 --- a/starboard/android/shared/platform_info.cc +++ b/starboard/android/shared/platform_info.cc @@ -50,12 +50,20 @@ const char* GetOsExperience() { return "Watson"; } +int64_t GetCoreServicesVersion() { + return JniEnvExt::Get()->CallStarboardLongMethodOrAbort( + "getPlayServicesVersion", "()J"); +} + +// clang-format off const CobaltExtensionPlatformInfoApi kPlatformInfoApi = { kCobaltExtensionPlatformInfoName, - 1, + 2, &GetFirmwareVersionDetails, &GetOsExperience, + &GetCoreServicesVersion, }; +// clang-format on } // namespace diff --git a/starboard/extension/extension_test.cc b/starboard/extension/extension_test.cc index 539c38919414..16c7c97baadc 100644 --- a/starboard/extension/extension_test.cc +++ b/starboard/extension/extension_test.cc @@ -435,9 +435,10 @@ TEST(ExtensionTest, PlatformInfo) { } EXPECT_STREQ(extension_api->name, kExtensionName); - EXPECT_EQ(extension_api->version, 1u); + EXPECT_EQ(extension_api->version, 2u); EXPECT_NE(extension_api->GetFirmwareVersionDetails, nullptr); EXPECT_NE(extension_api->GetOsExperience, nullptr); + EXPECT_NE(extension_api->GetCoreServicesVersion, nullptr); const ExtensionApi* second_extension_api = static_cast(SbSystemGetExtension(kExtensionName)); diff --git a/starboard/extension/platform_info.h b/starboard/extension/platform_info.h index e670044f7bbb..2cda3f7483f4 100644 --- a/starboard/extension/platform_info.h +++ b/starboard/extension/platform_info.h @@ -41,6 +41,10 @@ typedef struct CobaltExtensionPlatformInfoApi { // Returns the OS experience. (e.g. Amati or Watson on an Android device). const char* (*GetOsExperience)(); + + // Returns the Core Services version (e.g. the Google Play Services package + // version on an Android device). + int64_t (*GetCoreServicesVersion)(); } CobaltExtensionPlatformInfoApi; #ifdef __cplusplus