From 9d70021561a2e736ef958cb3c9d855d4b2264550 Mon Sep 17 00:00:00 2001 From: Colin Liang Date: Fri, 12 Jan 2024 19:23:04 -0800 Subject: [PATCH] Revert "Revert "Disable MediaPlaybackService by default"" --- .../enable-background-playback-test.html | 16 ++++++ cobalt/media/BUILD.gn | 1 + cobalt/media/media_module.cc | 15 ++++++ cobalt/media/media_module_test.cc | 29 +++++++++++ .../java/dev/cobalt/coat/StarboardBridge.java | 30 +++++++++-- .../dev/cobalt/media/CobaltMediaSession.java | 9 +++- starboard/android/shared/BUILD.gn | 2 + starboard/android/shared/h5vcc_config.cc | 50 +++++++++++++++++++ starboard/android/shared/h5vcc_config.h | 28 +++++++++++ .../android/shared/system_get_extensions.cc | 5 ++ starboard/extension/extension_test.cc | 21 ++++++++ starboard/extension/h5vcc_config.h | 43 ++++++++++++++++ 12 files changed, 245 insertions(+), 4 deletions(-) create mode 100644 cobalt/demos/content/enable-background-playback/enable-background-playback-test.html create mode 100644 cobalt/media/media_module_test.cc create mode 100644 starboard/android/shared/h5vcc_config.cc create mode 100644 starboard/android/shared/h5vcc_config.h create mode 100644 starboard/extension/h5vcc_config.h diff --git a/cobalt/demos/content/enable-background-playback/enable-background-playback-test.html b/cobalt/demos/content/enable-background-playback/enable-background-playback-test.html new file mode 100644 index 000000000000..a00216bd1bd4 --- /dev/null +++ b/cobalt/demos/content/enable-background-playback/enable-background-playback-test.html @@ -0,0 +1,16 @@ + + + + Test Enable Background Playback + + + + + diff --git a/cobalt/media/BUILD.gn b/cobalt/media/BUILD.gn index 0b509f96e34a..7779989a1341 100644 --- a/cobalt/media/BUILD.gn +++ b/cobalt/media/BUILD.gn @@ -124,6 +124,7 @@ target(gtest_target_type, "media_test") { "base/decoder_buffer_cache_test.cc", "bidirectional_fit_reuse_allocator_test.cc", "file_data_source_test.cc", + "media_module_test.cc", "progressive/demuxer_extension_wrapper_test.cc", "progressive/mock_data_source_reader.h", "progressive/mp4_map_unittest.cc", diff --git a/cobalt/media/media_module.cc b/cobalt/media/media_module.cc index 06e7e260bd09..024c660203a0 100644 --- a/cobalt/media/media_module.cc +++ b/cobalt/media/media_module.cc @@ -26,6 +26,7 @@ #include "base/synchronization/waitable_event.h" #include "cobalt/media/base/format_support_query_metrics.h" #include "starboard/common/string.h" +#include "starboard/extension/h5vcc_config.h" #include "starboard/media.h" #include "starboard/window.h" #include "third_party/chromium/media/base/mime_util.h" @@ -198,6 +199,20 @@ bool MediaModule::SetConfiguration(const std::string& name, int32 value) { LOG(INFO) << (value ? "Enabling" : "Disabling") << " media metrics collection."; return true; + } else if (name == "BackgroundPlaybackEnabled") { + const StarboardExtensionH5vccConfigApi* h5vcc_config_api = + static_cast( + SbSystemGetExtension(kStarboardExtensionH5vccConfigName)); + if (h5vcc_config_api && + strcmp(h5vcc_config_api->name, kStarboardExtensionH5vccConfigName) == + 0 && + h5vcc_config_api->version >= 1) { + bool enable_background_playback = value; + LOG(INFO) << "Set BackgroundPlaybackEnabled to " + << (enable_background_playback ? "enabled" : "disabled"); + h5vcc_config_api->EnableBackgroundPlayback(enable_background_playback); + } + return true; #if SB_API_VERSION >= 15 } else if (name == "AudioWriteDurationLocal" && value > 0) { audio_write_duration_local_ = value; diff --git a/cobalt/media/media_module_test.cc b/cobalt/media/media_module_test.cc new file mode 100644 index 000000000000..af3c93fc67c9 --- /dev/null +++ b/cobalt/media/media_module_test.cc @@ -0,0 +1,29 @@ +// Copyright 2024 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "cobalt/media/media_module.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace cobalt { +namespace media { + +TEST(MediaModuleTest, SetConfiguration) { + MediaModule mediaModule(nullptr, nullptr); + + EXPECT_EQ(mediaModule.SetConfiguration("BackgroundPlaybackEnabled", 1), true); + EXPECT_EQ(mediaModule.SetConfiguration("BackgroundPlaybackEnabled", 0), true); +} +} // namespace media +} // namespace cobalt 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 36907c1778bc..ca59344a0809 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 @@ -118,6 +118,8 @@ public void run() { private static final TimeZone DEFAULT_TIME_ZONE = TimeZone.getTimeZone("America/Los_Angeles"); private final long timeNanosecondsPerMicrosecond = 1000; + public static boolean enableBackgroundPlayback = false; + public StarboardBridge( Context appContext, Holder activityHolder, @@ -189,6 +191,11 @@ protected void onServiceDestroy(Service service) { @SuppressWarnings("unused") @UsedByNative protected void startMediaPlaybackService() { + if (!enableBackgroundPlayback) { + Log.v(TAG, "Media Playback Service is disabled. Skip startMediaPlaybackService()."); + return; + } + if (cobaltMediaSession == null || !cobaltMediaSession.isActive()) { Log.w(TAG, "Do not start a MediaPlaybackService when the MediSsession is null or inactive."); return; @@ -208,13 +215,18 @@ protected void startMediaPlaybackService() { } else { appContext.startService(intent); } - } catch (SecurityException e) { + } catch (RuntimeException e) { Log.e(TAG, "Failed to start MediaPlaybackService with intent.", e); return; } } else { Log.i(TAG, "Warm start - Restarting the MediaPlaybackService."); - ((MediaPlaybackService) service).startService(); + try { + ((MediaPlaybackService) service).startService(); + } catch (RuntimeException e) { + Log.e(TAG, "Failed to restart MediaPlaybackService.", e); + return; + } } } @@ -224,7 +236,12 @@ protected void stopMediaPlaybackService() { Service service = serviceHolder.get(); if (service != null) { Log.i(TAG, "Stopping the MediaPlaybackService."); - ((MediaPlaybackService) service).stopService(); + try { + ((MediaPlaybackService) service).stopService(); + } catch (RuntimeException e) { + Log.e(TAG, "Failed to stop MediaPlaybackService.", e); + return; + } } } @@ -846,4 +863,11 @@ protected boolean getIsAmatiDevice() { protected String getBuildFingerprint() { return Build.FINGERPRINT; } + + @SuppressWarnings("unused") + @UsedByNative + protected void enableBackgroundPlayback(boolean value) { + enableBackgroundPlayback = value; + Log.v(TAG, "StarboardBridge set enableBackgroundPlayback: %b", value); + } } diff --git a/starboard/android/apk/app/src/main/java/dev/cobalt/media/CobaltMediaSession.java b/starboard/android/apk/app/src/main/java/dev/cobalt/media/CobaltMediaSession.java index 0b28e088079f..cd62cf009f57 100644 --- a/starboard/android/apk/app/src/main/java/dev/cobalt/media/CobaltMediaSession.java +++ b/starboard/android/apk/app/src/main/java/dev/cobalt/media/CobaltMediaSession.java @@ -31,6 +31,7 @@ import android.support.v4.media.session.PlaybackStateCompat; import android.view.WindowManager; import androidx.annotation.RequiresApi; +import dev.cobalt.coat.StarboardBridge; import dev.cobalt.util.Holder; import dev.cobalt.util.Log; @@ -129,6 +130,10 @@ public CobaltMediaSession( } public boolean isActive() { + if (!StarboardBridge.enableBackgroundPlayback) { + return false; + } + if (this.mediaSession == null) { return false; } else { @@ -254,7 +259,9 @@ private void configureMediaFocus(int playbackState, long positionMs, float speed Log.i(TAG, "MediaSession already released"); return; } - mediaSession.setActive(playbackState != PLAYBACK_STATE_NONE); + if (StarboardBridge.enableBackgroundPlayback) { + mediaSession.setActive(playbackState != PLAYBACK_STATE_NONE); + } if (lifecycleCallback != null) { lifecycleCallback.onMediaSessionLifecycle( this.mediaSession.isActive(), this.mediaSession.getSessionToken()); diff --git a/starboard/android/shared/BUILD.gn b/starboard/android/shared/BUILD.gn index 15c003b4dc6b..2faeef583228 100644 --- a/starboard/android/shared/BUILD.gn +++ b/starboard/android/shared/BUILD.gn @@ -319,6 +319,8 @@ static_library("starboard_platform") { "get_home_directory.cc", "graphics.cc", "graphics.h", + "h5vcc_config.cc", + "h5vcc_config.h", "input_events_generator.cc", "input_events_generator.h", "jni_env_ext.cc", diff --git a/starboard/android/shared/h5vcc_config.cc b/starboard/android/shared/h5vcc_config.cc new file mode 100644 index 000000000000..059b417309bc --- /dev/null +++ b/starboard/android/shared/h5vcc_config.cc @@ -0,0 +1,50 @@ +// Copyright 2024 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/extension/h5vcc_config.h" +#include "starboard/android/shared/h5vcc_config.h" +#include "starboard/android/shared/jni_env_ext.h" +#include "starboard/android/shared/jni_utils.h" +#include "starboard/common/log.h" + +namespace starboard { +namespace android { +namespace shared { + +namespace { + +// Definitions of any functions included as components in the extension +// are added here. + +void EnableBackgroundPlayback(bool value) { + JniEnvExt* env = JniEnvExt::Get(); + JniEnvExt::Get()->CallStarboardVoidMethodOrAbort("enableBackgroundPlayback", + "(Z)V", (jboolean)value); +} + +const StarboardExtensionH5vccConfigApi kH5vccConfigApi = { + kStarboardExtensionH5vccConfigName, + 1, // API version that's implemented. + &EnableBackgroundPlayback, +}; + +} // namespace + +const void* GetH5vccConfigApi() { + return &kH5vccConfigApi; +} + +} // namespace shared +} // namespace android +} // namespace starboard diff --git a/starboard/android/shared/h5vcc_config.h b/starboard/android/shared/h5vcc_config.h new file mode 100644 index 000000000000..f2a501c10b71 --- /dev/null +++ b/starboard/android/shared/h5vcc_config.h @@ -0,0 +1,28 @@ +// Copyright 2024 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef STARBOARD_ANDROID_SHARED_H5VCC_CONFIG_H_ +#define STARBOARD_ANDROID_SHARED_H5VCC_CONFIG_H_ + +namespace starboard { +namespace android { +namespace shared { + +const void* GetH5vccConfigApi(); + +} // namespace shared +} // namespace android +} // namespace starboard + +#endif // STARBOARD_ANDROID_SHARED_H5VCC_CONFIG_H_ diff --git a/starboard/android/shared/system_get_extensions.cc b/starboard/android/shared/system_get_extensions.cc index 0fcd77441fe6..e43388e72523 100644 --- a/starboard/android/shared/system_get_extensions.cc +++ b/starboard/android/shared/system_get_extensions.cc @@ -17,6 +17,7 @@ #include "starboard/android/shared/android_media_session_client.h" #include "starboard/android/shared/configuration.h" #include "starboard/android/shared/graphics.h" +#include "starboard/android/shared/h5vcc_config.h" #include "starboard/android/shared/platform_info.h" #include "starboard/android/shared/platform_service.h" #include "starboard/common/log.h" @@ -30,6 +31,7 @@ #include "starboard/extension/configuration.h" #include "starboard/extension/crash_handler.h" #include "starboard/extension/graphics.h" +#include "starboard/extension/h5vcc_config.h" #include "starboard/extension/media_session.h" #include "starboard/extension/platform_info.h" #include "starboard/extension/platform_service.h" @@ -68,5 +70,8 @@ const void* SbSystemGetExtension(const char* name) { if (strcmp(name, kCobaltExtensionPlatformInfoName) == 0) { return starboard::android::shared::GetPlatformInfoApi(); } + if (strcmp(name, kStarboardExtensionH5vccConfigName) == 0) { + return starboard::android::shared::GetH5vccConfigApi(); + } return NULL; } diff --git a/starboard/extension/extension_test.cc b/starboard/extension/extension_test.cc index 874cce11bbfd..d99b1997250b 100644 --- a/starboard/extension/extension_test.cc +++ b/starboard/extension/extension_test.cc @@ -21,6 +21,7 @@ #include "starboard/extension/font.h" #include "starboard/extension/free_space.h" #include "starboard/extension/graphics.h" +#include "starboard/extension/h5vcc_config.h" #include "starboard/extension/ifa.h" #include "starboard/extension/installation_manager.h" #include "starboard/extension/javascript_cache.h" @@ -481,5 +482,25 @@ TEST(ExtensionTest, Ifa) { << "Extension struct should be a singleton"; } +TEST(ExtensionTest, H5vccConfig) { + typedef StarboardExtensionH5vccConfigApi ExtensionApi; + const char* kExtensionName = kStarboardExtensionH5vccConfigName; + + const ExtensionApi* extension_api = + static_cast(SbSystemGetExtension(kExtensionName)); + if (!extension_api) { + return; + } + + EXPECT_STREQ(extension_api->name, kExtensionName); + EXPECT_EQ(extension_api->version, 1u); + EXPECT_NE(extension_api->EnableBackgroundPlayback, nullptr); + + const ExtensionApi* second_extension_api = + static_cast(SbSystemGetExtension(kExtensionName)); + EXPECT_EQ(second_extension_api, extension_api) + << "Extension struct should be a singleton"; +} + } // namespace extension } // namespace starboard diff --git a/starboard/extension/h5vcc_config.h b/starboard/extension/h5vcc_config.h new file mode 100644 index 000000000000..a88a2f33df86 --- /dev/null +++ b/starboard/extension/h5vcc_config.h @@ -0,0 +1,43 @@ +// Copyright 2024 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef STARBOARD_EXTENSION_H5VCC_CONFIG_H_ +#define STARBOARD_EXTENSION_H5VCC_CONFIG_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define kStarboardExtensionH5vccConfigName "dev.starboard.extension.H5vccConfig" + +typedef struct StarboardExtensionH5vccConfigApi { + // Name should be the string |kStarboardExtensionH5vccConfigName|. + // This helps to validate that the extension API is correct. + const char* name; + + // This specifies the version of the API that is implemented. + uint32_t version; + + // This API enable the Cobalt background playback mode. + void (*EnableBackgroundPlayback)(bool value); + +} StarboardExtensionH5vccConfigApi; + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // STARBOARD_EXTENSION_H5VCC_CONFIG_H_