diff --git a/.github/actions/on_host_tests/action.yaml b/.github/actions/on_host_tests/action.yaml index b4e7f74e91ab..a8c33f90a6ce 100644 --- a/.github/actions/on_host_tests/action.yaml +++ b/.github/actions/on_host_tests/action.yaml @@ -35,17 +35,17 @@ runs: env # Explicitly point to libraries in extracted dir. - LD_LIBRARY_PATH="${test_dir}/out/${{ matrix.platform }}_${{ matrix.config }}/starboard" - LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${test_dir}/out/${{ matrix.platform }}_${{ matrix.config }}" + LD_LIBRARY_PATH="${test_dir}/starboard" + LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${test_dir}" export LD_LIBRARY_PATH # Make results dir available to the archiving step below. results_dir="${GITHUB_WORKSPACE}/results" echo "results_dir=${results_dir}" >> $GITHUB_ENV + failed_suites="" cd ${test_dir} - for test_binary_path in $(ls -d out/**/*tests out/**/nplb); do - test_binary=$(basename "${test_binary_path}") + for test_binary in $(ls {*tests,nplb}); do echo "Running tests for suite: ${test_binary}" test_filter="*" @@ -57,9 +57,16 @@ runs: echo "Test filter evaluated to: ${test_filter}" xml_path="${results_dir}/${test_binary}_testoutput.xml" - /usr/bin/xvfb-run -a --server-args="${XVFB_SERVER_ARGS}" ./$test_binary_path --gtest_filter="${test_filter}" --gtest_output="xml:${xml_path}" + /usr/bin/xvfb-run -a --server-args="${XVFB_SERVER_ARGS}" "./${test_binary}" --gtest_filter="${test_filter}" --gtest_output="xml:${xml_path}" || { + # Set exit code on failure. + failed_suites="${failed_suites} ${test_binary}" + } done echo "Finished running all unit tests..." + if [ -n "${failed_suites}" ]; then + echo "Test suites failed:${failed_suites}" + exit 1 + fi - name: Archive Test Results if: success() || failure() uses: actions/upload-artifact@v4 diff --git a/.github/actions/process_test_results/action.yaml b/.github/actions/process_test_results/action.yaml index 89a2f13a5d42..bce228e5ad79 100644 --- a/.github/actions/process_test_results/action.yaml +++ b/.github/actions/process_test_results/action.yaml @@ -10,18 +10,23 @@ inputs: runs: using: "composite" steps: - - name: Download Artifacts + - name: Download Test Results uses: actions/download-artifact@v4 with: name: ${{ inputs.test_results_key }} path: results/ - - name: Publish Test Report + - name: Test Summary action continue-on-error: true - uses: mikepenz/action-junit-report@992d97d6eb2e5f3de985fbf9df6a04386874114d + uses: test-summary/action@31493c76ec9e7aa675f1585d3ed6f1da69269a86 with: - report_paths: results/*.xml - annotate_only: true + paths: "results/*.xml" + output: test-report-summary.md + show: "fail, skip" + + - name: Output test summary markdown to github + run: cat test-report-summary.md >> $GITHUB_STEP_SUMMARY + shell: bash - name: Get Datadog CLI id: download-dd-cli diff --git a/.github/actions/upload_test_artifacts/action.yaml b/.github/actions/upload_test_artifacts/action.yaml index 53402606ee34..017950dce2ff 100644 --- a/.github/actions/upload_test_artifacts/action.yaml +++ b/.github/actions/upload_test_artifacts/action.yaml @@ -31,13 +31,20 @@ runs: if: inputs.on_host == 'true' run: | set -x - cd src - tar cvf - out/${{ matrix.platform }}_${{ matrix.config }}/*tests out/${{ matrix.platform }}_${{ matrix.config }}/nplb out/${{ matrix.platform }}_${{ matrix.config }}/*.so out/${{ matrix.platform }}_${{ matrix.config }}/*.so.* out/${{ matrix.platform }}_${{ matrix.config }}/starboard/*.so.* out/${{ matrix.platform }}_${{ matrix.config }}/content/test | xz -T0 -1 -z - > test_artifacts.tar.xz + cd src/out/${{ matrix.platform }}_${{ matrix.config }} + test_deps_file="test.deps" + for test_binary in $(ls {nplb,*tests}); do + echo $test_binary + if [ -f "${test_binary}.runtime_deps" ]; then + cat "${test_binary}.runtime_deps" >> "${test_deps_file}" + fi + done + tar cvf - -T "${test_deps_file}" | xz -T0 -1 -z - > "${GITHUB_WORKSPACE}/test_artifacts.tar.xz" shell: bash - name: Upload On-Host Test Artifacts Archive if: inputs.on_host == 'true' uses: actions/upload-artifact@v4 with: name: ${{ inputs.test_artifacts_key }} - path: src/test_artifacts.tar.xz + path: test_artifacts.tar.xz retention-days: 3 diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 963d6e253402..bfd96b5d001c 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -133,7 +133,7 @@ jobs: matrix: platform: ${{ fromJson(needs.initialize.outputs.platforms) }} include: ${{ fromJson(needs.initialize.outputs.includes) }} - config: [devel, debug, qa, gold] + config: [devel, qa, gold] container: ${{ needs.docker-build-image.outputs.docker_tag }} env: TEST_ARTIFACTS_KEY: ${{ matrix.platform }}_${{ matrix.name }}_test_artifacts @@ -156,7 +156,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 # TODO(bug?): android debug builds are broken. - if: ${{ ! (startsWith(matrix.platform, 'android') && matrix.config == 'debug') }} + if: ${{ ! (contains(matrix.platform, 'android') && matrix.config == 'debug') }} with: path: src # Use fetch depth of 0 to get full history for a valid build id. @@ -164,7 +164,7 @@ jobs: - name: Build Cobalt uses: ./src/.github/actions/build # TODO(bug?): android debug builds are broken. - if: ${{ ! (startsWith(matrix.platform, 'android') && matrix.config == 'debug') }} + if: ${{ ! (contains(matrix.platform, 'android') && matrix.config == 'debug') }} with: targets: ${{ needs.initialize.outputs.targets }} - name: Upload Test Artifacts diff --git a/build/build_config.h b/build/build_config.h index 4d7d0d984343..0a6d93b878b5 100644 --- a/build/build_config.h +++ b/build/build_config.h @@ -284,7 +284,7 @@ #define BUILDFLAG_INTERNAL_MODULAR_BUILD() (0) #endif -#if defined(COBALT_IS_RELEASE_BUILD) +#if defined(ENABLE_BUILDFLAG_COBALT_IS_RELEASE_BUILD) #define BUILDFLAG_INTERNAL_COBALT_IS_RELEASE_BUILD() (1) #else #define BUILDFLAG_INTERNAL_COBALT_IS_RELEASE_BUILD() (0) diff --git a/cobalt/BUILD.gn b/cobalt/BUILD.gn index 646d29c54acc..0e8901255339 100644 --- a/cobalt/BUILD.gn +++ b/cobalt/BUILD.gn @@ -77,16 +77,18 @@ action("cobalt_build_info") { ] } -test("cobalt_unittests") { - testonly = true +if (is_android) { + test("cobalt_unittests") { + testonly = true - sources = [ "//cobalt/user_agent/user_agent_platform_info_test.cc" ] + sources = [ "//cobalt/user_agent/user_agent_platform_info_test.cc" ] - deps = [ - "//base/test:run_all_unittests", - "//cobalt/user_agent", - "//starboard:starboard_group", - "//testing/gmock", - "//testing/gtest", - ] + deps = [ + "//base/test:run_all_unittests", + "//cobalt/user_agent", + "//starboard:starboard_group", + "//testing/gmock", + "//testing/gtest", + ] + } } diff --git a/cobalt/android/BUILD.gn b/cobalt/android/BUILD.gn index 85e5e0d69d75..eb9b6249f6ae 100644 --- a/cobalt/android/BUILD.gn +++ b/cobalt/android/BUILD.gn @@ -32,13 +32,21 @@ jinja_template("cobalt_manifest") { variables = [ "manifest_package=dev.cobalt.coat" ] } +generate_jni("jni_headers") { + sources = [ "apk/app/src/main/java/dev/cobalt/coat/StarboardBridge.java" ] +} + # TODO(cobalt): Re-enable or remove disabled java files. android_library("cobalt_apk_java") { testonly = true resources_package = "dev.cobalt.coat" + annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ] + deps = [ ":cobalt_java_resources", + ":jni_headers", "//base:base_java", + "//base:jni_java", "//base:process_launcher_java", "//build/android:build_java", "//components/embedder_support/android:view_java", @@ -57,6 +65,7 @@ android_library("cobalt_apk_java") { "//ui/android:ui_no_recycler_view_java", "//url:gurl_java", ] + sources = [ "apk/app/src/app/java/dev/cobalt/app/CobaltApplication.java", "apk/app/src/app/java/dev/cobalt/app/MainActivity.java", @@ -202,7 +211,6 @@ content_shell_apk_tmpl("cobalt_apk") { ":cobalt_apk_java", ] shared_libraries = [ ":libcobalt_content_shell_content_view" ] - command_line_flags_file = "content-shell-command-line" include_size_info = is_official_build } diff --git a/cobalt/android/apk/app/src/main/java/dev/cobalt/coat/CobaltActivity.java b/cobalt/android/apk/app/src/main/java/dev/cobalt/coat/CobaltActivity.java index 84bae40f70b3..5b2b75e133b8 100644 --- a/cobalt/android/apk/app/src/main/java/dev/cobalt/coat/CobaltActivity.java +++ b/cobalt/android/apk/app/src/main/java/dev/cobalt/coat/CobaltActivity.java @@ -35,7 +35,6 @@ import android.widget.LinearLayout; import android.widget.Toast; import androidx.annotation.Nullable; -import dev.cobalt.app.CobaltApplication; import dev.cobalt.coat.javabridge.CobaltJavaScriptAndroidObject; import dev.cobalt.coat.javabridge.CobaltJavaScriptInterface; import dev.cobalt.coat.javabridge.H5vccPlatformService; @@ -102,13 +101,10 @@ public abstract class CobaltActivity extends Activity { protected void createContent(final Bundle savedInstanceState) { // Initializing the command line must occur before loading the library. if (!CommandLine.isInitialized()) { - ((CobaltApplication) getApplication()).initCommandLine(); + CommandLine.init(null); - // Note that appendSwitchesAndArguments excludes cobaltCommandLineParams[0] - // as the program name, and all other arguments SHOULD start with '--'. String[] cobaltCommandLineParams = new String[] { - "", // Disable first run experience. "--disable-fre", // Disable user prompts in the first run. @@ -476,6 +472,11 @@ protected void onStop() { getStarboardBridge().onActivityStop(this); super.onStop(); + WebContents webContents = getActiveWebContents(); + if (webContents != null) { + webContents.onHide(); + } + if (VideoSurfaceView.getCurrentSurface() != null) { forceCreateNewVideoSurfaceView = true; } diff --git a/cobalt/android/apk/app/src/main/java/dev/cobalt/coat/StarboardBridge.java b/cobalt/android/apk/app/src/main/java/dev/cobalt/coat/StarboardBridge.java index d94590f00523..1c2ab30c339d 100644 --- a/cobalt/android/apk/app/src/main/java/dev/cobalt/coat/StarboardBridge.java +++ b/cobalt/android/apk/app/src/main/java/dev/cobalt/coat/StarboardBridge.java @@ -26,11 +26,7 @@ import android.hardware.input.InputManager; import android.media.AudioDeviceInfo; import android.media.AudioManager; -import android.net.ConnectivityManager; -import android.net.Network; -import android.net.NetworkCapabilities; import android.os.Build; -import android.util.Pair; import android.util.Size; import android.util.SizeF; import android.view.Display; @@ -44,16 +40,16 @@ import dev.cobalt.util.Log; import dev.cobalt.util.UsedByNative; import java.lang.reflect.Method; -import java.net.InterfaceAddress; -import java.net.NetworkInterface; -import java.net.SocketException; import java.util.Calendar; -import java.util.Enumeration; import java.util.HashMap; import java.util.Locale; import java.util.TimeZone; +import org.chromium.base.annotations.CalledByNative; +import org.chromium.base.annotations.JNINamespace; +import org.chromium.base.annotations.NativeMethods; /** Implementation of the required JNI methods called by the Starboard C++ code. */ +@JNINamespace("starboard::android::shared") public class StarboardBridge { /** Interface to be implemented by the Android Application hosting the starboard app. */ @@ -144,7 +140,19 @@ public StarboardBridge( private native void closeNativeStarboard(long nativeApp); - private native long nativeCurrentMonotonicTime(); + @NativeMethods + interface Natives { + void onStop(); + + long currentMonotonicTime(); + + // TODO(cobalt, b/372559388): move below native methods to the Natives interface. + // boolean initJNI(); + + // long startNativeStarboard(); + + // void closeNativeStarboard(long nativeApp); + } protected void onActivityStart(Activity activity) { Log.e(TAG, "onActivityStart ran"); @@ -160,16 +168,14 @@ protected void onActivityStop(Activity activity) { activityHolder.set(null); } sysConfigChangeReceiver.setForeground(false); - afterStopped(); } - private native void nativeOnStop(); - protected void onActivityDestroy(Activity activity) { if (applicationStopped) { // We can't restart the starboard app, so kill the process for a clean start next time. Log.i(TAG, "Activity destroyed after shutdown; killing app."); closeNativeStarboard(nativeApp); + closeAllServices(); System.exit(0); } else { Log.i(TAG, "Activity destroyed without shutdown; app suspended in background."); @@ -186,8 +192,6 @@ protected void onServiceDestroy(Service service) { } } - @SuppressWarnings("unused") - @UsedByNative protected void beforeStartOrResume() { Log.i(TAG, "Prepare to resume"); // Bring our platform services to life before resuming so that they're ready to deal with @@ -201,8 +205,6 @@ protected void beforeStartOrResume() { advertisingId.refresh(); } - @SuppressWarnings("unused") - @UsedByNative protected void beforeSuspend() { try { Log.i(TAG, "Prepare to suspend"); @@ -219,14 +221,19 @@ protected void beforeSuspend() { } } - @SuppressWarnings("unused") - @UsedByNative - protected void afterStopped() { - applicationStopped = true; + private void closeAllServices() { ttsHelper.shutdown(); for (CobaltService service : cobaltServices.values()) { service.afterStopped(); } + } + + // Warning: "Stopped" refers to Starboard "Stopped" event, it's different from Android's "onStop". + @SuppressWarnings("unused") + @CalledByNative + protected void afterStopped() { + applicationStopped = true; + closeAllServices(); Activity activity = activityHolder.get(); if (activity != null) { // Wait until the activity is destroyed to exit. @@ -240,18 +247,20 @@ protected void afterStopped() { } @SuppressWarnings("unused") - @UsedByNative + @CalledByNative protected void applicationStarted() { applicationReady = true; } @SuppressWarnings("unused") - @UsedByNative + @CalledByNative protected void applicationStopping() { applicationReady = false; applicationStopped = true; } + // TODO: (cobalt b/372559388) remove or migrate JNI? + // Used in starboard/android/shared/system_request_conceal.cc @SuppressWarnings("unused") @UsedByNative public void requestSuspend() { @@ -272,6 +281,7 @@ public boolean onSearchRequested() { // private native boolean nativeOnSearchRequested(); + // TODO: (cobalt b/372559388) remove or migrate JNI? @SuppressWarnings("unused") @UsedByNative public Context getApplicationContext() { @@ -281,6 +291,8 @@ public Context getApplicationContext() { return appContext; } + // TODO: (cobalt b/372559388) remove or migrate JNI? + // Used in starboard/android/shared/system_platform_error.cc @SuppressWarnings("unused") @UsedByNative void raisePlatformError(@PlatformError.ErrorType int errorType, long data) { @@ -302,7 +314,7 @@ protected Holder getActivityHolder() { } @SuppressWarnings("unused") - @UsedByNative + @CalledByNative protected String[] getArgs() { if (args == null) { throw new IllegalArgumentException("args cannot be null"); @@ -312,7 +324,7 @@ protected String[] getArgs() { /** Returns the URL from the Intent that started the app. */ @SuppressWarnings("unused") - @UsedByNative + @CalledByNative protected String getStartDeepLink() { if (startDeepLink == null) { throw new IllegalArgumentException("startDeepLink cannot be null"); @@ -335,6 +347,8 @@ private void nativeHandleDeepLink(String url) { // TODO(b/374147993): Implement deep link } + // TODO: (cobalt b/372559388) remove or migrate JNI? + // Used in starboard/android/shared/file_internal.cc /** * Returns the absolute path to the directory where application specific files should be written. * May be overridden for use cases that need to segregate storage. @@ -345,6 +359,8 @@ protected String getFilesAbsolutePath() { return appContext.getFilesDir().getAbsolutePath(); } + // TODO: (cobalt b/372559388) remove or migrate JNI? + // Used in starboard/android/shared/file_internal.cc /** * Returns the absolute path to the application specific cache directory on the filesystem. May be * overridden for use cases that need to segregate storage. @@ -355,59 +371,8 @@ protected String getCacheAbsolutePath() { return appContext.getCacheDir().getAbsolutePath(); } - /** - * Returns non-loopback network interface address and its netmask, or null if none. - * - *

A Java function to help implement Starboard's SbSocketGetLocalInterfaceAddress. - */ - @SuppressWarnings("unused") - @UsedByNative - Pair getLocalInterfaceAddressAndNetmask(boolean wantIPv6) { - try { - Enumeration it = NetworkInterface.getNetworkInterfaces(); - - while (it.hasMoreElements()) { - NetworkInterface ni = it.nextElement(); - if (ni.isLoopback()) { - continue; - } - if (!ni.isUp()) { - continue; - } - if (ni.isPointToPoint()) { - continue; - } - - for (InterfaceAddress ia : ni.getInterfaceAddresses()) { - byte[] address = ia.getAddress().getAddress(); - boolean isIPv6 = (address.length > 4); - if (isIPv6 == wantIPv6) { - // Convert the network prefix length to a network mask. - int prefix = ia.getNetworkPrefixLength(); - byte[] netmask = new byte[address.length]; - for (int i = 0; i < netmask.length; i++) { - if (prefix == 0) { - netmask[i] = 0; - } else if (prefix >= 8) { - netmask[i] = (byte) 0xFF; - prefix -= 8; - } else { - netmask[i] = (byte) (0xFF << (8 - prefix)); - prefix = 0; - } - } - return new Pair<>(address, netmask); - } - } - } - } catch (SocketException ex) { - // TODO should we have a logging story that strips logs for production? - Log.w(TAG, "sbSocketGetLocalInterfaceAddress exception", ex); - return null; - } - return null; - } - + // TODO: (cobalt b/372559388) remove or migrate JNI? + // Used in starboard/android/shared/speech_synthesis_speak.cc @SuppressWarnings("unused") @UsedByNative CobaltTextToSpeechHelper getTextToSpeechHelper() { @@ -417,6 +382,8 @@ CobaltTextToSpeechHelper getTextToSpeechHelper() { return ttsHelper; } + // TODO: (cobalt b/372559388) remove or migrate JNI? + // Used in starboard/android/shared/accessibility_get_caption_settings.cc /** * @return A new CaptionSettings object with the current system caption settings. */ @@ -428,6 +395,8 @@ CaptionSettings getCaptionSettings() { return new CaptionSettings(cm); } + // TODO: (cobalt b/372559388) remove or migrate JNI? + // Used in starboard/android/shared/system_get_locale_id.cc /** Java-layer implementation of SbSystemGetLocaleId. */ @SuppressWarnings("unused") @UsedByNative @@ -435,6 +404,8 @@ String systemGetLocaleId() { return Locale.getDefault().toLanguageTag(); } + // TODO: (cobalt b/372559388) remove or migrate JNI? + // Used in starboard/android/shared/time_zone_get_name.cc @SuppressWarnings("unused") @UsedByNative String getTimeZoneId() { @@ -447,18 +418,19 @@ String getTimeZoneId() { return timeZone.getID(); } + // TODO: (cobalt b/372559388) remove or migrate JNI? + // Used in starboard/android/shared/window_get_diagonal_size_in_inches.cc @SuppressWarnings("unused") @UsedByNative SizeF getDisplayDpi() { return DisplayUtil.getDisplayDpi(); } - @SuppressWarnings("unused") - @UsedByNative Size getDisplaySize() { return DisplayUtil.getSystemDisplaySize(); } + // TODO: (cobalt b/372559388) migrate JNI. @SuppressWarnings("unused") @UsedByNative public ResourceOverlay getResourceOverlay() { @@ -481,6 +453,8 @@ private static String getSystemProperty(String name) { } } + // TODO: (cobalt b/372559388) remove or migrate JNI? + // Used in starboard/android/shared/window_get_size.cc @SuppressWarnings("unused") @UsedByNative Size getDeviceResolution() { @@ -505,6 +479,8 @@ Size getDeviceResolution() { } } + // TODO: (cobalt b/372559388) remove or migrate JNI? + // Used in starboard/android/shared/system_network_is_disconnected.cc @SuppressWarnings("unused") @UsedByNative boolean isNetworkConnected() { @@ -514,6 +490,8 @@ boolean isNetworkConnected() { return networkStatus.isConnected(); } + // TODO: (cobalt b/372559388) remove or migrate JNI? + // Used in starboard/android/shared/microphone_impl.cc /** * Checks if there is no microphone connected to the system. * @@ -543,6 +521,8 @@ public boolean isMicrophoneDisconnected() { return true; } + // TODO: (cobalt b/372559388) remove or migrate JNI? + // Used in starboard/android/shared/microphone_impl.cc /** * Checks if the microphone is muted. * @@ -555,26 +535,8 @@ public boolean isMicrophoneMute() { return audioManager.isMicrophoneMute(); } - /** - * @return true if we have an active network connection and it's on an wireless network. - */ - @SuppressWarnings("unused") - @UsedByNative - boolean isCurrentNetworkWireless() { - ConnectivityManager connMgr = - (ConnectivityManager) appContext.getSystemService(Context.CONNECTIVITY_SERVICE); - Network activeNetwork = connMgr.getActiveNetwork(); - if (activeNetwork == null) { - return false; - } - NetworkCapabilities activeCapabilities = connMgr.getNetworkCapabilities(activeNetwork); - if (activeCapabilities == null) { - return false; - } - // Consider anything that's not definitely wired to be wireless. - return !activeCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET); - } - + // TODO: (cobalt b/372559388) remove or migrate JNI? + // Used in starboard/android/shared/accessibility_get_display_settings.cc /** * @return true if the user has enabled accessibility high contrast text in the operating system. */ @@ -593,6 +555,8 @@ boolean isAccessibilityHighContrastTextEnabled() { } } + // TODO: (cobalt b/372559388) remove or migrate JNI? + // Used in starboard/android/shared/android_media_session_client.cc @SuppressWarnings("unused") @UsedByNative void updateMediaSession( @@ -612,6 +576,8 @@ void updateMediaSession( // playbackState, actions, positionMs, speed, title, artist, album, artwork, duration); } + // TODO: (cobalt b/372559388) remove or migrate JNI? + // Used in starboard/android/shared/android_media_session_client.cc @SuppressWarnings("unused") @UsedByNative public void deactivateMediaSession() { @@ -620,6 +586,8 @@ public void deactivateMediaSession() { // cobaltMediaSession.deactivateMediaSession(); } + // TODO: (cobalt b/372559388) remove or migrate JNI? + // Used in starboard/android/shared/system_get_property.cc /** Returns string for kSbSystemPropertyUserAgentAuxField */ @SuppressWarnings("unused") @UsedByNative @@ -648,6 +616,8 @@ protected String getUserAgentAuxField() { return sb.toString(); } + // TODO: (cobalt b/372559388) remove or migrate JNI? + // Used in starboard/android/shared/system_get_property.cc /** Returns string for kSbSystemPropertyAdvertisingId */ @SuppressWarnings("unused") @UsedByNative @@ -655,6 +625,8 @@ protected String getAdvertisingId() { return this.advertisingId.getId(); } + // TODO: (cobalt b/372559388) remove or migrate JNI? + // Used in starboard/android/shared/system_get_property.cc /** Returns boolean for kSbSystemPropertyLimitAdTracking */ @SuppressWarnings("unused") @UsedByNative @@ -662,6 +634,8 @@ protected boolean getLimitAdTracking() { return this.advertisingId.isLimitAdTrackingEnabled(); } + // TODO: (cobalt b/372559388) remove or migrate JNI? + // Used in starboard/android/shared/audio_track_bridge.cc @SuppressWarnings("unused") @UsedByNative AudioOutputManager getAudioOutputManager() { @@ -682,6 +656,8 @@ AudioOutputManager getAudioOutputManager() { // audioPermissionRequester.onRequestPermissionsResult(requestCode, permissions, grantResults); // } + // TODO: (cobalt b/372559388) remove or migrate JNI? + // Used in starboard/android/shared/video_window.cc @SuppressWarnings("unused") @UsedByNative public void resetVideoSurface() { @@ -691,6 +667,8 @@ public void resetVideoSurface() { } } + // TODO: (cobalt b/372559388) remove or migrate JNI? + // Used in starboard/android/shared/player_set_bounds.cc @SuppressWarnings("unused") @UsedByNative public void setVideoSurfaceBounds(final int x, final int y, final int width, final int height) { @@ -700,9 +678,11 @@ public void setVideoSurfaceBounds(final int x, final int y, final int width, fin } } + // TODO: (cobalt b/372559388) remove or migrate JNI? + // Used in starboard/android/shared/media_capabilities_cache.cc /** Return supported hdr types. */ @SuppressWarnings("unused") - @UsedByNative + @CalledByNative public int[] getSupportedHdrTypes() { Display defaultDisplay = DisplayUtil.getDefaultDisplay(); if (defaultDisplay == null) { @@ -778,14 +758,15 @@ public byte[] sendToCobaltService(String serviceName, byte [] data) { return response.data; } + // TODO: (cobalt b/372559388) remove or migrate JNI? /** Returns the application start timestamp. */ @SuppressWarnings("unused") - @UsedByNative + @CalledByNative protected long getAppStartTimestamp() { Activity activity = activityHolder.get(); if (activity instanceof CobaltActivity) { long javaStartTimestamp = ((CobaltActivity) activity).getAppStartTimestamp(); - long cppTimestamp = nativeCurrentMonotonicTime(); + long cppTimestamp = StarboardBridgeJni.get().currentMonotonicTime(); long javaStopTimestamp = System.nanoTime(); return cppTimestamp - (javaStopTimestamp - javaStartTimestamp) / timeNanosecondsPerMicrosecond; @@ -793,6 +774,8 @@ protected long getAppStartTimestamp() { return 0; } + // TODO: (cobalt b/372559388) remove or migrate JNI? + // Used in starboard/android/shared/graphics.cc @SuppressWarnings("unused") @UsedByNative void reportFullyDrawn() { @@ -802,6 +785,8 @@ void reportFullyDrawn() { } } + // TODO: (cobalt b/372559388) remove or migrate JNI? + // Used in starboard/android/shared/crash_handler.cc @SuppressWarnings("unused") @UsedByNative public void setCrashContext(String key, String value) { @@ -821,19 +806,19 @@ public void registerCrashContextUpdateHandler(CrashContextUpdateHandler handler) } @SuppressWarnings("unused") - @UsedByNative + @CalledByNative protected boolean getIsAmatiDevice() { return this.isAmatiDevice; } @SuppressWarnings("unused") - @UsedByNative + @CalledByNative protected String getBuildFingerprint() { return Build.FINGERPRINT; } @SuppressWarnings("unused") - @UsedByNative + @CalledByNative protected long getPlayServicesVersion() { try { if (android.os.Build.VERSION.SDK_INT < 28) { diff --git a/cobalt/build/configs/BUILD.gn b/cobalt/build/configs/BUILD.gn index 81f47ec01aac..c731b81109d0 100644 --- a/cobalt/build/configs/BUILD.gn +++ b/cobalt/build/configs/BUILD.gn @@ -55,6 +55,6 @@ config("buildflag_defines") { defines += [ "ENABLE_BUILDFLAG_MODULAR_BUILD" ] } if (cobalt_is_release_build) { - defines += [ "COBALT_IS_RELEASE_BUILD" ] + defines += [ "ENABLE_BUILDFLAG_COBALT_IS_RELEASE_BUILD" ] } } diff --git a/cobalt/build/gn.py b/cobalt/build/gn.py index 998ee7d942af..8e34d4e2b7c7 100755 --- a/cobalt/build/gn.py +++ b/cobalt/build/gn.py @@ -56,7 +56,6 @@ def get_build_args(build_args_path): }, 'qa': { 'symbol_level': 1, - 'is_debug': 'false', 'is_official_build': 'true' }, 'gold': { diff --git a/cobalt/cobalt_content_browser_client.cc b/cobalt/cobalt_content_browser_client.cc index 11fbc9641bc7..8b612b359872 100644 --- a/cobalt/cobalt_content_browser_client.cc +++ b/cobalt/cobalt_content_browser_client.cc @@ -83,11 +83,11 @@ blink::UserAgentMetadata CobaltContentBrowserClient::GetUserAgentMetadata() { void CobaltContentBrowserClient::OverrideWebkitPrefs( content::WebContents* web_contents, blink::web_pref::WebPreferences* prefs) { -#if !defined(OFFICIAL_BUILD) +#if !defined(COBALT_IS_RELEASE_BUILD) // Allow creating a ws: connection on a https: page to allow current // testing set up. See b/377410179. prefs->allow_running_insecure_content = true; -#endif // !defined(OFFICIAL_BUILD) +#endif // !defined(COBALT_IS_RELEASE_BUILD) content::ShellContentBrowserClient::OverrideWebkitPrefs(web_contents, prefs); } diff --git a/cobalt/devinfra/kokoro/bin/cleanup.sh b/cobalt/devinfra/kokoro/bin/cleanup.sh index 725d0f29ef98..7df9b12f3c0a 100755 --- a/cobalt/devinfra/kokoro/bin/cleanup.sh +++ b/cobalt/devinfra/kokoro/bin/cleanup.sh @@ -1,12 +1,10 @@ set -x -REPO_ROOT="$(dirname "$0")/../../.." # After kokoro build finishes, changed files in c:/tmpfs get rsync'ed to a borg executor, # from where the artifacts and reports are processed. # Especially on Windows, the rsync can take long time, so we cleanup the cobalt workspace # after finishing each build. set +e -pushd $REPO_ROOT -time git clean -fdx -popd +git config --global --add safe.directory "${WORKSPACE_COBALT}" +time git -C "${WORKSPACE_COBALT}" clean -dfx exit 0 diff --git a/cobalt/devinfra/kokoro/bin/common.sh b/cobalt/devinfra/kokoro/bin/common.sh index aff77e3c3704..eed0bbd9f3f5 100755 --- a/cobalt/devinfra/kokoro/bin/common.sh +++ b/cobalt/devinfra/kokoro/bin/common.sh @@ -265,19 +265,9 @@ create_and_upload_nightly_archive () { fi local gcs_archive_path="gs://$(get_bucket_name)/${platform}${gcs_path_suffix}/$(date +%F)/${KOKORO_ROOT_BUILD_NUMBER}/" - # Creates nightly archive from package directory. - python3 "${WORKSPACE_COBALT}/tools/create_archive.py" \ - -s "${package_dir}" \ - -d "${local_archive_path}" \ - --intermediate - init_gcloud - # Uploads nightly archive. - "${GSUTIL}" cp "${local_archive_path}" "${gcs_archive_path}" - - # Uploads build_info.json. - "${GSUTIL}" cp "${build_info_path}" "${gcs_archive_path}" + "${GSUTIL}" cp -r "${package_dir}" "${gcs_archive_path}" } run_package_release_pipeline () { @@ -300,11 +290,7 @@ run_package_release_pipeline () { # Create release package. if [[ "${PLATFORM}" =~ "android" ]]; then - # Creates Android package directory. - python3 "${WORKSPACE_COBALT}/cobalt/devinfra/kokoro/build/android/simple_packager.py" \ - "${out_dir}" \ - "${package_dir}" \ - "${WORKSPACE_COBALT}" + cp "${out_dir}/apks/Cobalt.apk" "${package_dir}" elif [[ "${PLATFORM}" =~ "evergreen" ]]; then local bootloader_out_dir= if [ -n "${BOOTLOADER:-}" ]; then @@ -316,8 +302,7 @@ run_package_release_pipeline () { "${package_dir}" \ "${bootloader_out_dir:-}" else - # Sets package directory as out directory. - package_dir="${out_dir}" + cp "${out_dir}/cobalt" "${package_dir}" fi # Create and upload nightly archive. diff --git a/cobalt/devinfra/kokoro/bin/dind_build.sh b/cobalt/devinfra/kokoro/bin/dind_build.sh index cc41bed4a4d0..7d4e6dc9969a 100755 --- a/cobalt/devinfra/kokoro/bin/dind_build.sh +++ b/cobalt/devinfra/kokoro/bin/dind_build.sh @@ -8,13 +8,11 @@ # Kokoro Instance # └── Generic DinD Image # ├── dind_builder_runner.sh -# │ ├── configure_environment (common.sh) # │ ├── main_build_image_and_run.py # │ │ └── Specific Cobalt Image # │ │ └── dind_build.sh <= THIS SCRIPT # │ └── run_package_release_pipeline (common.sh) # └── dind_runner.sh -# ├── configure_environment (common.sh) # ├── main_pull_image_and_run.py # │ └── Specific Cobalt Image # │ └── dind_build.sh <= THIS SCRIPT @@ -42,10 +40,6 @@ fi # Load common routines (we only need run_gn and ninja_build). . $(dirname "$0")/common.sh -WORKSPACE_COBALT="${KOKORO_ARTIFACTS_DIR}/git/src" - -configure_environment - pipeline () { local out_dir="${WORKSPACE_COBALT}/out/${TARGET_PLATFORM}_${CONFIG}" local gclient_root="${KOKORO_ARTIFACTS_DIR}/chromium" diff --git a/cobalt/devinfra/kokoro/bin/dind_builder_runner.sh b/cobalt/devinfra/kokoro/bin/dind_builder_runner.sh index 302a395106d0..b9135d48b334 100755 --- a/cobalt/devinfra/kokoro/bin/dind_builder_runner.sh +++ b/cobalt/devinfra/kokoro/bin/dind_builder_runner.sh @@ -9,13 +9,11 @@ # Kokoro Instance # └── Generic DinD Image # ├── dind_builder_runner.sh <== THIS SCRIPT -# │ ├── configure_environment (common.sh) # │ ├── main_build_image_and_run.py # │ │ └── Specific Cobalt Image # │ │ └── dind_build.sh # │ └── run_package_release_pipeline (common.sh) # └── dind_runner.sh -# ├── configure_environment (common.sh) # ├── main_pull_image_and_run.py # │ └── Specific Cobalt Image # │ └── dind_build.sh @@ -27,15 +25,12 @@ set -ueEx # Using repository root as work directory. export WORKSPACE_COBALT="${KOKORO_ARTIFACTS_DIR}/git/src" -cd "${WORKSPACE_COBALT}" # Clean up workspace on exit or error. trap "bash ${WORKSPACE_COBALT}/cobalt/devinfra/kokoro/bin/cleanup.sh" EXIT INT TERM configure_dind_environment -configure_environment - set -x # The python script is responsible for running containerized Cobalt builds. python3 "${WORKSPACE_COBALT}/cobalt/devinfra/kokoro/bin/dind_py/main_build_image_and_run.py" diff --git a/cobalt/devinfra/kokoro/bin/dind_py/dind_common.py b/cobalt/devinfra/kokoro/bin/dind_py/dind_common.py index 94b4df0eafc2..d6bb8f367b37 100644 --- a/cobalt/devinfra/kokoro/bin/dind_py/dind_common.py +++ b/cobalt/devinfra/kokoro/bin/dind_py/dind_common.py @@ -31,10 +31,6 @@ # within the inner Docker container. _INTERNAL_KOKORO_BUILD_SCRIPT = 'cobalt/devinfra/kokoro/bin/dind_build.sh' -_WORKSPACE_COBALT_VAR = 'WORKSPACE_COBALT' - -_SERVICE_NOT_FOUND = 'SERVICE_NOT_FOUND' - _PLATFORM_TO_SERVICE_MAP = { 'android-x86': 'linux', 'android-arm': 'linux', @@ -70,7 +66,7 @@ def push_image(target_image): utils.exec_cmd(command) -def get_local_image_name(service, compose_file='docker-compose.yaml'): +def get_local_image_name(service, compose_file): """ Parses the docker-compose file to determine the image-name from the service-name. When the compose-file is used to build the image, it will get @@ -90,9 +86,7 @@ def tag_image(src_img, dest_img): utils.exec_cmd(tag_command) -def run_docker_build(platform, - target_image, - compose_file='docker-compose.yaml'): +def run_docker_build(platform, target_image, compose_file): """ Runs the docker build for the provided platform, and tags the newly built image with the registry/image/tag arguments. If the build fails, instead it diff --git a/cobalt/devinfra/kokoro/bin/dind_py/main_build_image_and_run.py b/cobalt/devinfra/kokoro/bin/dind_py/main_build_image_and_run.py index a3f3cd07be90..46fb9bccf981 100644 --- a/cobalt/devinfra/kokoro/bin/dind_py/main_build_image_and_run.py +++ b/cobalt/devinfra/kokoro/bin/dind_py/main_build_image_and_run.py @@ -24,13 +24,11 @@ Kokoro Instance └── Generic DinD Image ├── dind_builder_runner.sh - │ ├── configure_environment (common.sh) │ ├── main_build_image_and_run.py <= THIS SCRIPT │ │ └── Specific Cobalt Image │ │ └── dind_build.sh │ └── run_package_release_pipeline (common.sh) └── dind_runner.sh - ├── configure_environment (common.sh) ├── main_pull_image_and_run.py │ └── Specific Cobalt Image │ └── dind_build.sh @@ -95,7 +93,8 @@ def main(): utils.logging_info_spacer('Building Docker Image') build_start_time = time.time() try: - dind.run_docker_build(args.platform, target_image) + dind.run_docker_build(args.platform, target_image, + args.src_root + '/docker-compose.yaml') dind.tag_image(target_image, floating_image) dind.push_image(floating_image) docker_build_duration = time.time() - build_start_time diff --git a/cobalt/devinfra/kokoro/bin/dind_py/main_pull_image_and_run.py b/cobalt/devinfra/kokoro/bin/dind_py/main_pull_image_and_run.py index a7e14582f22c..852c11137c7b 100644 --- a/cobalt/devinfra/kokoro/bin/dind_py/main_pull_image_and_run.py +++ b/cobalt/devinfra/kokoro/bin/dind_py/main_pull_image_and_run.py @@ -21,13 +21,11 @@ Kokoro Instance └── Generic DinD Image ├── dind_builder_runner.sh - │ ├── configure_environment (common.sh) │ ├── main_build_image_and_run.py │ │ └── Specific Cobalt Image │ │ └── dind_build.sh │ └── run_package_release_pipeline (common.sh) └── dind_runner.sh - ├── configure_environment (common.sh) ├── main_pull_image_and_run.py <= THIS SCRIPT │ └── Specific Cobalt Image │ └── dind_build.sh diff --git a/cobalt/devinfra/kokoro/bin/dind_runner.sh b/cobalt/devinfra/kokoro/bin/dind_runner.sh index 157aa6141caa..ed0534e236e6 100755 --- a/cobalt/devinfra/kokoro/bin/dind_runner.sh +++ b/cobalt/devinfra/kokoro/bin/dind_runner.sh @@ -9,13 +9,11 @@ # Kokoro Instance # └── Generic DinD Image # ├── dind_builder_runner.sh -# │ ├── configure_environment (common.sh) # │ ├── main_build_image_and_run.py # │ │ └── Specific Cobalt Image # │ │ └── dind_build.sh # │ └── run_package_release_pipeline (common.sh) # └── dind_runner.sh <== THIS SCRIPT -# ├── configure_environment (common.sh) # ├── main_pull_image_and_run.py # │ └── Specific Cobalt Image # │ └── dind_build.sh @@ -27,15 +25,12 @@ set -ueEx # Using repository root as work directory. export WORKSPACE_COBALT="${KOKORO_ARTIFACTS_DIR}/git/src" -cd "${WORKSPACE_COBALT}" # Clean up workspace on exit or error. trap "bash ${WORKSPACE_COBALT}/cobalt/devinfra/kokoro/bin/cleanup.sh" EXIT INT TERM configure_dind_environment -configure_environment - set -x # The python script is responsible for running containerized Cobalt builds. python3 "${WORKSPACE_COBALT}/cobalt/devinfra/kokoro/bin/dind_py/main_pull_image_and_run.py" diff --git a/cobalt/devinfra/kokoro/docker-compose.yaml b/cobalt/devinfra/kokoro/docker-compose.yaml index 20800f61d970..756943ab3479 100644 --- a/cobalt/devinfra/kokoro/docker-compose.yaml +++ b/cobalt/devinfra/kokoro/docker-compose.yaml @@ -56,6 +56,7 @@ services: SCCACHE_GCS_OAUTH_URL: ${SCCACHE_GCS_OAUTH_URL} SCCACHE_GCS_RW_MODE: ${SCCACHE_GCS_RW_MODE} SCCACHE_IDLE_TIMEOUT: ${SCCACHE_IDLE_TIMEOUT} + WORKSPACE_COBALT: ${WORKSPACE_COBALT} # Kokoro Specific Variables to forward: KOKORO_ARTIFACTS_DIR: ${KOKORO_ARTIFACTS_DIR} KOKORO_BUILD_ARTIFACTS_SUBDIR: ${KOKORO_BUILD_ARTIFACTS_SUBDIR} diff --git a/cobalt/user_agent/BUILD.gn b/cobalt/user_agent/BUILD.gn index e019640ad639..21fa26c5ebc3 100644 --- a/cobalt/user_agent/BUILD.gn +++ b/cobalt/user_agent/BUILD.gn @@ -12,6 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. +if (is_android) { + import("//build/config/android/abi.gni") +} + static_library("user_agent") { sources = [ "user_agent_platform_info.cc", @@ -24,4 +28,11 @@ static_library("user_agent") { "//starboard/common", "//v8:v8_version", ] + + if (is_android) { + defines = [ + # Enable compile-time decisions based on the ABI + "ANDROID_ABI=$android_app_abi", + ] + } } diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 7824a83f0a7f..7e224c74a664 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn @@ -2321,6 +2321,13 @@ source_set("browser") { "worker_host/worker_script_loader_factory.h", ] + if (is_cobalt) { + sources += [ + "cobalt/crash_annotator/crash_annotator_impl.cc", + "cobalt/crash_annotator/crash_annotator_impl.h", + ] + } + if (use_starscan) { sources += [ "starscan_load_observer.cc", diff --git a/content/browser/browser_interface_binders.cc b/content/browser/browser_interface_binders.cc index 90bd74a313bf..78da69eda21c 100644 --- a/content/browser/browser_interface_binders.cc +++ b/content/browser/browser_interface_binders.cc @@ -174,6 +174,11 @@ #include "third_party/blink/public/public_buildflags.h" #include "url/origin.h" +#if BUILDFLAG(IS_COBALT) +#include "content/browser/cobalt/crash_annotator/crash_annotator_impl.h" +#include "third_party/blink/public/mojom/cobalt/crash_annotator/crash_annotator.mojom.h" +#endif + #if BUILDFLAG(IS_ANDROID) #include "content/browser/android/date_time_chooser_android.h" #include "content/browser/android/text_suggestion_host_android.h" @@ -841,6 +846,11 @@ void PopulateFrameBinders(RenderFrameHostImpl* host, mojo::BinderMap* map) { map->Add(base::BindRepeating( &RenderFrameHostImpl::GetSpeechSynthesis, base::Unretained(host))); +#if BUILDFLAG(IS_COBALT) + map->Add(base::BindRepeating( + &RenderFrameHostImpl::GetCrashAnnotator, base::Unretained(host))); +#endif + #if !BUILDFLAG(IS_ANDROID) map->Add(base::BindRepeating( &RenderFrameHostImpl::GetDeviceInfoService, base::Unretained(host))); diff --git a/content/browser/cobalt/crash_annotator/crash_annotator_impl.cc b/content/browser/cobalt/crash_annotator/crash_annotator_impl.cc new file mode 100644 index 000000000000..72bb36a25658 --- /dev/null +++ b/content/browser/cobalt/crash_annotator/crash_annotator_impl.cc @@ -0,0 +1,31 @@ +// 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 "content/browser/cobalt/crash_annotator/crash_annotator_impl.h" + +#include "base/functional/bind.h" +#include "base/functional/callback.h" + +namespace content { + +void CrashAnnotatorImpl::SetString(const std::string& key, + const std::string& value, + SetStringCallback callback) { + // TODO(cobalt, b/383301493): actually implement this. + LOG(INFO) << "CrashAnnotatorImpl::SetString key=" << key << " value=" + << value; + std::move(callback).Run(false); +} + +} // namespace content diff --git a/content/browser/cobalt/crash_annotator/crash_annotator_impl.h b/content/browser/cobalt/crash_annotator/crash_annotator_impl.h new file mode 100644 index 000000000000..2573de92f779 --- /dev/null +++ b/content/browser/cobalt/crash_annotator/crash_annotator_impl.h @@ -0,0 +1,47 @@ +// 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 CONTENT_BROWSER_CRASH_ANNOTATOR_IMPL_H_ +#define CONTENT_BROWSER_CRASH_ANNOTATOR_IMPL_H_ + +#include + +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/receiver.h" +#include "third_party/blink/public/mojom/cobalt/crash_annotator/crash_annotator.mojom.h" + +namespace content { + +// TODO(cobalt, b/383301493): consider another location for Cobalt's Mojo +// implementations, since they are not "core" services. mcasas@ suggested +// //components or //services as possible destinations. +class CrashAnnotatorImpl : public blink::mojom::CrashAnnotator { + public: + explicit CrashAnnotatorImpl( + mojo::PendingReceiver receiver) + : receiver_(this, std::move(receiver)) {} + CrashAnnotatorImpl(const CrashAnnotatorImpl&) = delete; + CrashAnnotatorImpl& operator=(const CrashAnnotatorImpl&) = delete; + + void SetString(const std::string& key, + const std::string& value, + SetStringCallback callback) override; + + private: + mojo::Receiver receiver_; +}; + +} // namespace content + +#endif // CONTENT_BROWSER_CRASH_ANNOTATOR_IMPL_H_ diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc index 3b35cc5d4492..be77a68af476 100644 --- a/content/browser/renderer_host/render_frame_host_impl.cc +++ b/content/browser/renderer_host/render_frame_host_impl.cc @@ -269,6 +269,10 @@ #include "url/origin.h" #include "url/url_constants.h" +#if BUILDFLAG(IS_COBALT) +#include "content/browser/cobalt/crash_annotator/crash_annotator_impl.h" +#endif + #if BUILDFLAG(IS_ANDROID) #include "content/browser/android/content_url_loader_factory.h" #include "content/browser/android/java_interfaces_impl.h" @@ -11593,6 +11597,13 @@ void RenderFrameHostImpl::GetFileSystemManager( storage_key(), std::move(receiver))); } +#if BUILDFLAG(IS_COBALT) +void RenderFrameHostImpl::GetCrashAnnotator( + mojo::PendingReceiver receiver) { + crash_annotator_ = std::make_unique(std::move(receiver)); +} +#endif + void RenderFrameHostImpl::GetGeolocationService( mojo::PendingReceiver receiver) { if (!geolocation_service_) { diff --git a/content/browser/renderer_host/render_frame_host_impl.h b/content/browser/renderer_host/render_frame_host_impl.h index 0c61e60b8a11..52c56fd94333 100644 --- a/content/browser/renderer_host/render_frame_host_impl.h +++ b/content/browser/renderer_host/render_frame_host_impl.h @@ -172,6 +172,11 @@ #include "ui/gfx/geometry/rect.h" #include "url/gurl.h" +#if BUILDFLAG(IS_COBALT) +#include "third_party/blink/public/mojom/cobalt/crash_annotator/crash_annotator.mojom-forward.h" +#include "third_party/blink/public/mojom/cobalt/crash_annotator/crash_annotator.mojom.h" +#endif + #if BUILDFLAG(IS_ANDROID) #include "base/containers/id_map.h" #include "services/device/public/mojom/nfc.mojom.h" @@ -249,6 +254,9 @@ class DocumentServiceBase; class AgentSchedulingGroupHost; class BrowsingContextState; class CodeCacheHostImpl; +#if BUILDFLAG(IS_COBALT) +class CrashAnnotatorImpl; +#endif class CrossOriginEmbedderPolicyReporter; class CrossOriginOpenerPolicyAccessReportManager; class FeatureObserver; @@ -1942,6 +1950,11 @@ class CONTENT_EXPORT RenderFrameHostImpl void GetFileSystemAccessManager( mojo::PendingReceiver receiver); +#if BUILDFLAG(IS_COBALT) + void GetCrashAnnotator( + mojo::PendingReceiver receiver); +#endif + #if !BUILDFLAG(IS_ANDROID) void GetHidService(mojo::PendingReceiver receiver); @@ -4492,6 +4505,10 @@ class CONTENT_EXPORT RenderFrameHostImpl // Tracks the document policy which has been set on this frame. std::unique_ptr document_policy_; +#if BUILDFLAG(IS_COBALT) + std::unique_ptr crash_annotator_; +#endif + #if BUILDFLAG(IS_ANDROID) // An InterfaceProvider for Java-implemented interfaces that are scoped to // this RenderFrameHost. This provides access to interfaces implemented in diff --git a/media/filters/chunk_demuxer.cc b/media/filters/chunk_demuxer.cc index 6b2410f99d9f..7778437a2ec5 100644 --- a/media/filters/chunk_demuxer.cc +++ b/media/filters/chunk_demuxer.cc @@ -172,6 +172,9 @@ void ChunkDemuxerStream::Seek(base::TimeDelta time) { DCHECK(state_ == UNINITIALIZED || state_ == RETURNING_ABORT_FOR_READS) << state_; +#if BUILDFLAG(USE_STARBOARD_MEDIA) + write_head_ = time; +#endif // BUILDFLAG(USE_STARBOARD_MEDIA) stream_->Seek(time); } @@ -217,6 +220,13 @@ bool ChunkDemuxerStream::EvictCodedFrames(base::TimeDelta media_time, return stream_->GarbageCollectIfNeeded(media_time, newDataSize); } +#if BUILDFLAG(USE_STARBOARD_MEDIA) +base::TimeDelta ChunkDemuxerStream::GetWriteHead() const { + base::AutoLock auto_lock(lock_); + return write_head_; +} +#endif // BUILDFLAG(USE_STARBOARD_MEDIA) + void ChunkDemuxerStream::OnMemoryPressure( base::TimeDelta media_time, base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level, @@ -490,6 +500,13 @@ void ChunkDemuxerStream::CompletePendingReadIfPossible_Locked() { // Other cases are kOk and just return the buffers. DCHECK(!buffers.empty()); requested_buffer_count_ = 0; +#if BUILDFLAG(USE_STARBOARD_MEDIA) + for (auto&& buffer : buffers) { + if (!buffer->end_of_stream()) { + write_head_ = std::max(write_head_, buffer->timestamp()); + } + } +#endif // BUILDFLAG(USE_STARBOARD_MEDIA) std::move(read_cb_).Run(kOk, std::move(buffers)); } @@ -1051,6 +1068,22 @@ bool ChunkDemuxer::EvictCodedFrames(const std::string& id, return itr->second->EvictCodedFrames(currentMediaTime, newDataSize); } +#if BUILDFLAG(USE_STARBOARD_MEDIA) +base::TimeDelta ChunkDemuxer::GetWriteHead(const std::string& id) const { + base::AutoLock auto_lock(lock_); + DCHECK(IsValidId_Locked(id)); + + auto iter = id_to_streams_map_.find(id); + if (iter == id_to_streams_map_.end() || iter->second.empty()) { + // Handled just in case. + NOTREACHED(); + return base::TimeDelta(); + } + + return iter->second[0]->GetWriteHead(); +} +#endif // BUILDFLAG(USE_STARBOARD_MEDIA) + bool ChunkDemuxer::AppendToParseBuffer(const std::string& id, const uint8_t* data, size_t length) { diff --git a/media/filters/chunk_demuxer.h b/media/filters/chunk_demuxer.h index 49b7199e0943..fb66b32bfcb0 100644 --- a/media/filters/chunk_demuxer.h +++ b/media/filters/chunk_demuxer.h @@ -83,6 +83,12 @@ class MEDIA_EXPORT ChunkDemuxerStream : public DemuxerStream { // https://w3c.github.io/media-source/#sourcebuffer-coded-frame-eviction bool EvictCodedFrames(base::TimeDelta media_time, size_t newDataSize); +#if BUILDFLAG(USE_STARBOARD_MEDIA) + // Returns the latest presentation timestamp of the buffers queued in the + // stream. + base::TimeDelta GetWriteHead() const; +#endif // BUILDFLAG(USE_STARBOARD_MEDIA) + void OnMemoryPressure( base::TimeDelta media_time, base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level, @@ -190,6 +196,7 @@ class MEDIA_EXPORT ChunkDemuxerStream : public DemuxerStream { #if BUILDFLAG(USE_STARBOARD_MEDIA) const std::string mime_type_; + base::TimeDelta write_head_ GUARDED_BY(lock_); #endif // BUILDFLAG(USE_STARBOARD_MEDIA) // Specifies the type of the stream. @@ -416,6 +423,12 @@ class MEDIA_EXPORT ChunkDemuxer : public Demuxer { base::TimeDelta currentMediaTime, size_t newDataSize); +#if BUILDFLAG(USE_STARBOARD_MEDIA) + // Returns the latest presentation timestamp of the buffers to be read + // from the DemuxerStream. + [[nodiscard]] base::TimeDelta GetWriteHead(const std::string& id) const; +#endif // BUILDFLAG(USE_STARBOARD_MEDIA) + void OnMemoryPressure( base::TimeDelta currentMediaTime, base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level, diff --git a/media/starboard/starboard_renderer.cc b/media/starboard/starboard_renderer.cc index 4ed2ed2426f9..9be127ea9fd9 100644 --- a/media/starboard/starboard_renderer.cc +++ b/media/starboard/starboard_renderer.cc @@ -592,9 +592,11 @@ void StarboardRenderer::OnDemuxerStreamRead( DCHECK(audio_read_in_progress_); audio_read_in_progress_ = false; for (const auto& buffer : buffers) { - last_audio_sample_interval_ = - buffer->timestamp() - timestamp_of_last_written_audio_; - timestamp_of_last_written_audio_ = buffer->timestamp(); + if (!buffer->end_of_stream()) { + last_audio_sample_interval_ = + buffer->timestamp() - timestamp_of_last_written_audio_; + timestamp_of_last_written_audio_ = buffer->timestamp(); + } } player_bridge_->WriteBuffers(DemuxerStream::AUDIO, buffers); } else { diff --git a/starboard/CHANGELOG.md b/starboard/CHANGELOG.md index 6df4a1fdb3b4..14a2ba33fe30 100644 --- a/starboard/CHANGELOG.md +++ b/starboard/CHANGELOG.md @@ -50,6 +50,13 @@ It was only used by win32 platforms ### Removed starboad/atomic.h support for C. The existing code was migrated to C11 atomics. +### Renamed `SbMediaIs*Supported()` functions +`SbMediaIsAudioSupported()`, `SbMediaIsSupported()`, and +`SbMediaIsVideoSupported()` were never part of the Starboard interface. +Their Sb prefixes were removed and renamed to `MediaIsAudioSupported()`, +`MediaIsSupported()`, and `MediaIsVideoSupported()`. They are also moved from +the global namespace into ::starboard::shared::starboard::media. + ## Version 16 A key update in Starboard version 16 is the adoption of POSIX APIs. For a full overview of Starboard POSIX migrations, please refer to diff --git a/starboard/android/arm/platform_configuration/configuration.gni b/starboard/android/arm/platform_configuration/configuration.gni index 77e2920e49a6..1cfa2ddb08c1 100644 --- a/starboard/android/arm/platform_configuration/configuration.gni +++ b/starboard/android/arm/platform_configuration/configuration.gni @@ -14,7 +14,6 @@ import("//starboard/android/shared/platform_configuration/configuration.gni") -android_abi = "armeabi-v7a" arm_float_abi = "softfp" sb_evergreen_compatible_package = true diff --git a/starboard/android/arm64/platform_configuration/configuration.gni b/starboard/android/arm64/platform_configuration/configuration.gni index 34daf92deb12..12583a39a513 100644 --- a/starboard/android/arm64/platform_configuration/configuration.gni +++ b/starboard/android/arm64/platform_configuration/configuration.gni @@ -14,6 +14,5 @@ import("//starboard/android/shared/platform_configuration/configuration.gni") -android_abi = "arm64-v8a" sabi_path = "//starboard/sabi/arm64/sabi-v$sb_api_version.json" sb_evergreen_compatible_package = true diff --git a/starboard/android/shared/BUILD.gn b/starboard/android/shared/BUILD.gn index eef374515f49..cf4b70c4dd9f 100644 --- a/starboard/android/shared/BUILD.gn +++ b/starboard/android/shared/BUILD.gn @@ -103,7 +103,6 @@ static_library("starboard_platform") { "//starboard/shared/starboard/command_line.cc", "//starboard/shared/starboard/command_line.h", "//starboard/shared/starboard/decode_target/decode_target_get_info.cc", - "//starboard/shared/starboard/decode_target/decode_target_internal.cc", "//starboard/shared/starboard/decode_target/decode_target_internal.h", "//starboard/shared/starboard/decode_target/decode_target_release.cc", "//starboard/shared/starboard/drm/drm_close_session.cc", @@ -265,6 +264,8 @@ static_library("starboard_platform") { #"speech_synthesis_internal.cc", #"speech_synthesis_is_supported.cc", #"speech_synthesis_speak.cc", + "starboard_bridge.cc", + "starboard_bridge.h", "system_get_extensions.cc", "system_get_locale_id.cc", "system_get_path.cc", @@ -316,12 +317,14 @@ static_library("starboard_platform") { public_deps = [ ":starboard_base_symbolize", ":starboard_jni_state", + "//cobalt/android:jni_headers", "//starboard/common", "//starboard/shared/starboard/media:media_util", "//starboard/shared/starboard/player/filter:filter_based_player_sources", ] deps = [ + "//base", "//third_party/libevent", "//third_party/opus", ] diff --git a/starboard/android/shared/android_main.cc b/starboard/android/shared/android_main.cc index 0ed8090673aa..1a42ab2c65e2 100644 --- a/starboard/android/shared/android_main.cc +++ b/starboard/android/shared/android_main.cc @@ -18,11 +18,11 @@ #include #include -// #include "game-activity/GameActivity.h" #include "starboard/android/shared/application_android.h" #include "starboard/android/shared/jni_env_ext.h" #include "starboard/android/shared/jni_utils.h" #include "starboard/android/shared/log_internal.h" +#include "starboard/android/shared/starboard_bridge.h" #include "starboard/common/file.h" #include "starboard/common/semaphore.h" #include "starboard/common/string.h" @@ -30,6 +30,7 @@ #include "starboard/event.h" #include "starboard/log.h" #include "starboard/shared/starboard/command_line.h" +#include "starboard/shared/starboard/log_mutex.h" #include "starboard/thread.h" #if SB_IS(EVERGREEN_COMPATIBLE) #include "starboard/crashpad_wrapper/wrapper.h" // nogncheck @@ -61,40 +62,14 @@ std::atomic_bool g_app_running{false}; std::vector GetArgs() { std::vector args; // Fake program name as args[0] - args.push_back(strdup("android_main")); + args.push_back("android_main"); - JniEnvExt* env = JniEnvExt::Get(); - - ScopedLocalJavaRef args_array( - env->CallStarboardObjectMethodOrAbort("getArgs", - "()[Ljava/lang/String;")); - jint argc = !args_array ? 0 : env->GetArrayLength(args_array.Get()); - - for (jint i = 0; i < argc; i++) { - ScopedLocalJavaRef element( - env->GetObjectArrayElementOrAbort(args_array.Get(), i)); - args.push_back(env->GetStringStandardUTFOrAbort(element.Get())); - } + JNIEnv* env = base::android::AttachCurrentThread(); + StarboardBridge::GetInstance()->AppendArgs(env, &args); return args; } -std::string GetStartDeepLink() { - JniEnvExt* env = JniEnvExt::Get(); - std::string start_url; - - ScopedLocalJavaRef j_url(env->CallStarboardObjectMethodOrAbort( - "getStartDeepLink", "()Ljava/lang/String;")); - if (j_url) { - auto j_url_str = j_url.Get(); - if (env->GetStringLength(j_url_str) != 0) { - start_url = env->GetStringStandardUTFOrAbort(j_url_str); - } - } - SB_LOG(INFO) << "GetStartDeepLink: " << start_url; - return start_url; -} - #if SB_IS(EVERGREEN_COMPATIBLE) bool CopyDirContents(const std::string& src_dir_path, const std::string& dst_dir_path) { @@ -252,9 +227,8 @@ void* ThreadEntryPoint(void* context) { // Inform StarboardBridge that the run loop has exited so it can cleanup and // kill the process. - JniEnvExt* env = JniEnvExt::Get(); - env->CallStarboardVoidMethodOrAbort("afterStopped", "()V"); - + JNIEnv* env = base::android::AttachCurrentThread(); + StarboardBridge::GetInstance()->AfterStopped(env); return NULL; } #endif // SB_IS(EVERGREEN_COMPATIBLE) @@ -292,10 +266,16 @@ void StarboardThreadLaunch() { } #endif // SB_IS(EVERGREEN_COMPATIBLE) +// TODO(cobalt, b/372559388): consolidate this function when fully deprecate +// JniEnvExt. extern "C" SB_EXPORT_PLATFORM void Java_dev_cobalt_coat_StarboardBridge_initJNI( JniEnvExt* env, jobject starboard_bridge) { JniEnvExt::Initialize(env, starboard_bridge); + + // Initialize the singleton instance of StarboardBridge + JNIEnv* jni_env = base::android::AttachCurrentThread(); + StarboardBridge::GetInstance()->Initialize(jni_env, starboard_bridge); } extern "C" SB_EXPORT_PLATFORM jlong @@ -303,6 +283,7 @@ Java_dev_cobalt_coat_StarboardBridge_startNativeStarboard(JniEnvExt* env) { #if SB_IS(EVERGREEN_COMPATIBLE) StarboardThreadLaunch(); #else + starboard::shared::starboard::GetLoggingMutex(); auto command_line = std::make_unique(GetArgs()); LogInit(*command_line); auto* nativeApp = new ApplicationAndroid(std::move(command_line)); @@ -372,8 +353,10 @@ extern "C" int SbRunStarboardMain(int argc, g_app_created_semaphore->Put(); // Enter the Starboard run loop until stopped. - int error_level = - app.Run(std::move(command_line), GetStartDeepLink().c_str()); + JNIEnv* env = base::android::AttachCurrentThread(); + std::string start_url = StarboardBridge::GetInstance()->GetStartDeepLink(env); + SB_LOG(INFO) << "GetStartDeepLink: " << start_url; + int error_level = app.Run(std::move(command_line), start_url.c_str()); // Mark the app not running before informing StarboardBridge that the app is // stopped so that we won't send any more AndroidCommands as a result of diff --git a/starboard/android/shared/application_android.cc b/starboard/android/shared/application_android.cc index 5d076a7f2688..1e29cb0a075d 100644 --- a/starboard/android/shared/application_android.cc +++ b/starboard/android/shared/application_android.cc @@ -24,6 +24,7 @@ #include #include +#include "base/android/jni_android.h" #include "starboard/extension/accessibility.h" #include "starboard/android/shared/file_internal.h" @@ -44,14 +45,6 @@ namespace starboard { namespace android { namespace shared { -namespace { -int64_t GetAppStartTimestamp() { - JniEnvExt* env = JniEnvExt::Get(); - jlong app_start_timestamp = - env->CallStarboardLongMethodOrAbort("getAppStartTimestamp", "()J"); - return app_start_timestamp; -} -} // namespace // TODO(cobalt, b/378708359): Remove this dummy init. void stubSbEventHandle(const SbEvent* event) { @@ -74,14 +67,18 @@ ApplicationAndroid::ApplicationAndroid( jobject local_ref = env->CallStarboardObjectMethodOrAbort( "getResourceOverlay", "()Ldev/cobalt/coat/ResourceOverlay;"); resource_overlay_ = env->ConvertLocalRefToGlobalRef(local_ref); - SbAudioSinkPrivate::Initialize(); - app_start_timestamp_ = GetAppStartTimestamp(); - env->CallStarboardVoidMethodOrAbort("applicationStarted", "()V"); + + ::starboard::shared::starboard::audio_sink::SbAudioSinkImpl::Initialize(); + + JNIEnv* jni_env = base::android::AttachCurrentThread(); + app_start_timestamp_ = starboard_bridge_->GetAppStartTimestamp(jni_env); + + starboard_bridge_->ApplicationStarted(jni_env); } ApplicationAndroid::~ApplicationAndroid() { - JniEnvExt* env = JniEnvExt::Get(); - env->CallStarboardVoidMethodOrAbort("applicationStopping", "()V"); + JNIEnv* env = base::android::AttachCurrentThread(); + starboard_bridge_->ApplicationStopping(env); // The application is exiting. // Release the global reference. @@ -94,12 +91,6 @@ ApplicationAndroid::~ApplicationAndroid() { JniEnvExt::OnThreadShutdown(); } -extern "C" SB_EXPORT_PLATFORM void -Java_dev_cobalt_coat_StarboardBridge_nativeOnStop(JniEnvExt* env) { - SbAudioSinkPrivate::TearDown(); - SbFileAndroidTeardown(); -} - extern "C" SB_EXPORT_PLATFORM jboolean Java_dev_cobalt_coat_StarboardBridge_nativeOnSearchRequested( JniEnvExt* env, @@ -108,14 +99,6 @@ Java_dev_cobalt_coat_StarboardBridge_nativeOnSearchRequested( return true; } -extern "C" SB_EXPORT_PLATFORM jlong -Java_dev_cobalt_coat_StarboardBridge_nativeCurrentMonotonicTime( - JNIEnv* env, - jobject jcaller, - jboolean online) { - return CurrentMonotonicTime(); -} - extern "C" SB_EXPORT_PLATFORM void Java_dev_cobalt_coat_CobaltSystemConfigChangeReceiver_nativeDateTimeConfigurationChanged( JNIEnv* env, diff --git a/starboard/android/shared/application_android.h b/starboard/android/shared/application_android.h index 16c2a577840a..abf11b6734f7 100644 --- a/starboard/android/shared/application_android.h +++ b/starboard/android/shared/application_android.h @@ -20,7 +20,7 @@ #include #include -#include "starboard/android/shared/jni_env_ext.h" +#include "starboard/android/shared/starboard_bridge.h" #include "starboard/common/log.h" #include "starboard/common/mutex.h" #include "starboard/shared/internal_only.h" @@ -66,6 +66,10 @@ class ApplicationAndroid void WakeSystemEventWait() override {} private: + // starboard_bridge_ is a global singleton, use a raw pointer to not interfere + // with it's lifecycle management. + const raw_ptr starboard_bridge_ = + StarboardBridge::GetInstance(); jobject resource_overlay_; Mutex overlay_mutex_; diff --git a/starboard/android/shared/audio_track_audio_sink_type.cc b/starboard/android/shared/audio_track_audio_sink_type.cc index 4af3a1751f18..cb7845c1fae4 100644 --- a/starboard/android/shared/audio_track_audio_sink_type.cc +++ b/starboard/android/shared/audio_track_audio_sink_type.cc @@ -561,20 +561,30 @@ int AudioTrackAudioSinkType::GetMinBufferSizeInFramesInternal( } // namespace android } // namespace starboard +namespace starboard { +namespace shared { +namespace starboard { +namespace audio_sink { + // static -void SbAudioSinkPrivate::PlatformInitialize() { +void SbAudioSinkImpl::PlatformInitialize() { SB_DCHECK(!audio_track_audio_sink_type_); audio_track_audio_sink_type_ = - new starboard::android::shared::AudioTrackAudioSinkType; + new ::starboard::android::shared::AudioTrackAudioSinkType; SetPrimaryType(audio_track_audio_sink_type_); EnableFallbackToStub(); audio_track_audio_sink_type_->TestMinRequiredFrames(); } // static -void SbAudioSinkPrivate::PlatformTearDown() { +void SbAudioSinkImpl::PlatformTearDown() { SB_DCHECK(audio_track_audio_sink_type_ == GetPrimaryType()); SetPrimaryType(NULL); delete audio_track_audio_sink_type_; audio_track_audio_sink_type_ = NULL; } + +} // namespace audio_sink +} // namespace starboard +} // namespace shared +} // namespace starboard diff --git a/starboard/android/shared/audio_track_audio_sink_type.h b/starboard/android/shared/audio_track_audio_sink_type.h index 9d59c8049e92..700f421094ed 100644 --- a/starboard/android/shared/audio_track_audio_sink_type.h +++ b/starboard/android/shared/audio_track_audio_sink_type.h @@ -100,7 +100,8 @@ class AudioTrackAudioSinkType : public SbAudioSinkPrivate::Type { bool has_remote_audio_output_ = false; }; -class AudioTrackAudioSink : public SbAudioSinkPrivate { +class AudioTrackAudioSink + : public ::starboard::shared::starboard::audio_sink::SbAudioSinkImpl { public: AudioTrackAudioSink( Type* type, diff --git a/starboard/android/shared/media_capabilities_cache.cc b/starboard/android/shared/media_capabilities_cache.cc index 10e2d1998d84..436eed009bba 100644 --- a/starboard/android/shared/media_capabilities_cache.cc +++ b/starboard/android/shared/media_capabilities_cache.cc @@ -18,6 +18,7 @@ #include "starboard/android/shared/jni_utils.h" #include "starboard/android/shared/media_common.h" +#include "starboard/android/shared/starboard_bridge.h" #include "starboard/common/log.h" #include "starboard/common/once.h" #include "starboard/shared/starboard/media/key_system_supportability_cache.h" @@ -188,9 +189,9 @@ bool GetIsCbcsSupported() { std::set GetSupportedHdrTypes() { std::set supported_transfer_ids; - JniEnvExt* env = JniEnvExt::Get(); - jintArray j_supported_hdr_types = static_cast( - env->CallStarboardObjectMethodOrAbort("getSupportedHdrTypes", "()[I")); + JNIEnv* env = base::android::AttachCurrentThread(); + base::android::ScopedJavaLocalRef j_supported_hdr_types = + StarboardBridge::GetInstance()->GetSupportedHdrTypes(env); if (!j_supported_hdr_types) { // Failed to get supported hdr types. @@ -198,8 +199,9 @@ std::set GetSupportedHdrTypes() { return std::set(); } - jsize length = env->GetArrayLength(j_supported_hdr_types); - jint* numbers = env->GetIntArrayElements(j_supported_hdr_types, 0); + jsize length = env->GetArrayLength(j_supported_hdr_types.obj()); + jint* numbers = + env->GetIntArrayElements(j_supported_hdr_types.obj(), nullptr); for (int i = 0; i < length; i++) { switch (numbers[i]) { case HDR_TYPE_DOLBY_VISION: @@ -214,7 +216,7 @@ std::set GetSupportedHdrTypes() { continue; } } - env->ReleaseIntArrayElements(j_supported_hdr_types, numbers, 0); + env->ReleaseIntArrayElements(j_supported_hdr_types.obj(), numbers, 0); return supported_transfer_ids; } diff --git a/starboard/android/shared/media_is_audio_supported.cc b/starboard/android/shared/media_is_audio_supported.cc index 023cbfc5f8fb..01f2e6638fca 100644 --- a/starboard/android/shared/media_is_audio_supported.cc +++ b/starboard/android/shared/media_is_audio_supported.cc @@ -22,13 +22,17 @@ #include "starboard/configuration_constants.h" #include "starboard/media.h" -using starboard::android::shared::MediaCapabilitiesCache; -using starboard::android::shared::SupportedAudioCodecToMimeType; -using starboard::shared::starboard::media::MimeType; +namespace starboard { +namespace shared { +namespace starboard { +namespace media { -bool SbMediaIsAudioSupported(SbMediaAudioCodec audio_codec, - const MimeType* mime_type, - int64_t bitrate) { +using ::starboard::android::shared::MediaCapabilitiesCache; +using ::starboard::android::shared::SupportedAudioCodecToMimeType; + +bool MediaIsAudioSupported(SbMediaAudioCodec audio_codec, + const MimeType* mime_type, + int64_t bitrate) { if (bitrate >= kSbMediaMaxAudioBitrateInBitsPerSecond) { return false; } @@ -80,3 +84,8 @@ bool SbMediaIsAudioSupported(SbMediaAudioCodec audio_codec, return MediaCapabilitiesCache::GetInstance()->IsPassthroughSupported( audio_codec); } + +} // namespace media +} // namespace starboard +} // namespace shared +} // namespace starboard diff --git a/starboard/android/shared/media_is_supported.cc b/starboard/android/shared/media_is_supported.cc index 04acefb035b1..f68de335d6e3 100644 --- a/starboard/android/shared/media_is_supported.cc +++ b/starboard/android/shared/media_is_supported.cc @@ -21,13 +21,17 @@ #include "starboard/media.h" #include "starboard/shared/starboard/media/mime_type.h" -bool SbMediaIsSupported(SbMediaVideoCodec video_codec, - SbMediaAudioCodec audio_codec, - const char* key_system) { - using starboard::android::shared::IsWidevineL1; - using starboard::android::shared::IsWidevineL3; - using starboard::android::shared::MediaCapabilitiesCache; - using starboard::shared::starboard::media::MimeType; +namespace starboard { +namespace shared { +namespace starboard { +namespace media { + +bool MediaIsSupported(SbMediaVideoCodec video_codec, + SbMediaAudioCodec audio_codec, + const char* key_system) { + using ::starboard::android::shared::IsWidevineL1; + using ::starboard::android::shared::IsWidevineL3; + using ::starboard::android::shared::MediaCapabilitiesCache; // It is possible that the |key_system| comes with extra attributes, like // `com.widevine.alpha; encryptionscheme="cenc"`. We prepend "key_system/" @@ -64,3 +68,8 @@ bool SbMediaIsSupported(SbMediaVideoCodec video_codec, return true; } + +} // namespace media +} // namespace starboard +} // namespace shared +} // namespace starboard diff --git a/starboard/android/shared/media_is_video_supported.cc b/starboard/android/shared/media_is_video_supported.cc index cee2457b3a66..4b33f7a40c5e 100644 --- a/starboard/android/shared/media_is_video_supported.cc +++ b/starboard/android/shared/media_is_video_supported.cc @@ -21,25 +21,28 @@ #include "starboard/media.h" #include "starboard/shared/starboard/media/media_util.h" -using starboard::android::shared::MaxMediaCodecOutputBuffersLookupTable; -using starboard::android::shared::MediaCapabilitiesCache; -using starboard::android::shared::SupportedVideoCodecToMimeType; -using starboard::shared::starboard::media::IsSDRVideo; -using starboard::shared::starboard::media::MimeType; - -bool SbMediaIsVideoSupported(SbMediaVideoCodec video_codec, - const MimeType* mime_type, - int profile, - int level, - int bit_depth, - SbMediaPrimaryId primary_id, - SbMediaTransferId transfer_id, - SbMediaMatrixId matrix_id, - int frame_width, - int frame_height, - int64_t bitrate, - int fps, - bool decode_to_texture_required) { +namespace starboard { +namespace shared { +namespace starboard { +namespace media { + +using ::starboard::android::shared::MaxMediaCodecOutputBuffersLookupTable; +using ::starboard::android::shared::MediaCapabilitiesCache; +using ::starboard::android::shared::SupportedVideoCodecToMimeType; + +bool MediaIsVideoSupported(SbMediaVideoCodec video_codec, + const MimeType* mime_type, + int profile, + int level, + int bit_depth, + SbMediaPrimaryId primary_id, + SbMediaTransferId transfer_id, + SbMediaMatrixId matrix_id, + int frame_width, + int frame_height, + int64_t bitrate, + int fps, + bool decode_to_texture_required) { const bool must_support_hdr = !IsSDRVideo(bit_depth, primary_id, transfer_id, matrix_id); if (must_support_hdr && @@ -115,3 +118,8 @@ bool SbMediaIsVideoSupported(SbMediaVideoCodec video_codec, mime, require_secure_playback, must_support_hdr, must_support_tunnel_mode, frame_width, frame_height, bitrate, fps); } + +} // namespace media +} // namespace starboard +} // namespace shared +} // namespace starboard diff --git a/starboard/android/shared/player_components_factory.h b/starboard/android/shared/player_components_factory.h index 469fd669746b..d17e7489a6e0 100644 --- a/starboard/android/shared/player_components_factory.h +++ b/starboard/android/shared/player_components_factory.h @@ -99,7 +99,8 @@ class AudioRendererSinkAndroid : public ::starboard::shared::starboard::player:: SbAudioSinkPrivate::ErrorFunc error_func, void* context) { auto type = static_cast( - SbAudioSinkPrivate::GetPreferredType()); + ::starboard::shared::starboard::audio_sink::SbAudioSinkImpl:: + GetPreferredType()); return type->Create( channels, sampling_frequency_hz, audio_sample_type, diff --git a/starboard/android/shared/starboard_bridge.cc b/starboard/android/shared/starboard_bridge.cc new file mode 100644 index 000000000000..b53eca201e40 --- /dev/null +++ b/starboard/android/shared/starboard_bridge.cc @@ -0,0 +1,99 @@ +// 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/android/shared/starboard_bridge.h" + +#include "starboard/android/shared/file_internal.h" +#include "starboard/common/time.h" +#include "starboard/media.h" +#include "starboard/shared/starboard/audio_sink/audio_sink_internal.h" + +// Must come after all headers that specialize FromJniType() / ToJniType(). +#include "base/android/jni_array.h" +#include "base/android/jni_string.h" +#include "cobalt/android/jni_headers/StarboardBridge_jni.h" + +namespace starboard { +namespace android { +namespace shared { + +extern "C" SB_EXPORT_PLATFORM void JNI_StarboardBridge_OnStop(JNIEnv* env) { + ::starboard::shared::starboard::audio_sink::SbAudioSinkImpl::TearDown(); + SbFileAndroidTeardown(); +} + +extern "C" SB_EXPORT_PLATFORM jlong +JNI_StarboardBridge_CurrentMonotonicTime(JNIEnv* env) { + return CurrentMonotonicTime(); +} + +// StarboardBridge::GetInstance() should not be inlined in the +// header. This makes sure that when source files from multiple targets include +// this header they don't end up with different copies of the inlined code +// creating multiple copies of the singleton. +// static +StarboardBridge* StarboardBridge::GetInstance() { + return base::Singleton::get(); +} + +void StarboardBridge::Initialize(JNIEnv* env, jobject obj) { + j_starboard_bridge_.Reset(env, obj); +} + +long StarboardBridge::GetAppStartTimestamp(JNIEnv* env) { + CHECK(env); + return Java_StarboardBridge_getAppStartTimestamp(env, j_starboard_bridge_); +} + +void StarboardBridge::ApplicationStarted(JNIEnv* env) { + CHECK(env); + Java_StarboardBridge_applicationStarted(env, j_starboard_bridge_); +} + +void StarboardBridge::ApplicationStopping(JNIEnv* env) { + CHECK(env); + Java_StarboardBridge_applicationStopping(env, j_starboard_bridge_); +} + +void StarboardBridge::AfterStopped(JNIEnv* env) { + CHECK(env); + Java_StarboardBridge_afterStopped(env, j_starboard_bridge_); +} + +void StarboardBridge::AppendArgs(JNIEnv* env, + std::vector* args_vector) { + CHECK(env); + base::android::ScopedJavaLocalRef args_java = + Java_StarboardBridge_getArgs(env, j_starboard_bridge_); + base::android::AppendJavaStringArrayToStringVector(env, args_java, + args_vector); +} + +std::string StarboardBridge::GetStartDeepLink(JNIEnv* env) { + CHECK(env); + base::android::ScopedJavaLocalRef start_deep_link_java = + Java_StarboardBridge_getStartDeepLink(env, j_starboard_bridge_); + std::string start_deep_link = + base::android::ConvertJavaStringToUTF8(env, start_deep_link_java); + return start_deep_link; +} + +base::android::ScopedJavaLocalRef +StarboardBridge::GetSupportedHdrTypes(JNIEnv* env) { + CHECK(env); + return Java_StarboardBridge_getSupportedHdrTypes(env, j_starboard_bridge_); +} +} // namespace shared +} // namespace android +} // namespace starboard diff --git a/starboard/android/shared/starboard_bridge.h b/starboard/android/shared/starboard_bridge.h new file mode 100644 index 000000000000..d834c3b20543 --- /dev/null +++ b/starboard/android/shared/starboard_bridge.h @@ -0,0 +1,70 @@ +// 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_STARBOARD_BRIDGE_H_ +#define STARBOARD_ANDROID_SHARED_STARBOARD_BRIDGE_H_ + +#include + +#include "base/android/jni_android.h" +#include "base/android/scoped_java_ref.h" +#include "base/memory/singleton.h" + +namespace starboard { +namespace android { +namespace shared { + +// This class serves as a bridge between the native code and Android +// StarboardBridge Java class. +class StarboardBridge { + public: + // Returns the singleton. + static StarboardBridge* GetInstance(); + + void Initialize(JNIEnv* env, jobject obj); + + long GetAppStartTimestamp(JNIEnv* env); + + void ApplicationStarted(JNIEnv* env); + + void ApplicationStopping(JNIEnv* env); + + void AfterStopped(JNIEnv* env); + + void AppendArgs(JNIEnv* env, std::vector* args_vector); + + std::string GetStartDeepLink(JNIEnv* env); + + base::android::ScopedJavaLocalRef GetSupportedHdrTypes( + JNIEnv* env); + + private: + StarboardBridge() = default; + ~StarboardBridge() = default; + + // Prevent copy construction and assignment + StarboardBridge(const StarboardBridge&) = delete; + StarboardBridge& operator=(const StarboardBridge&) = delete; + + friend struct base::DefaultSingletonTraits; + + // Java StarboardBridge instance. + base::android::ScopedJavaGlobalRef j_starboard_bridge_; +}; + +} // namespace shared +} // namespace android +} // namespace starboard + +#endif // STARBOARD_ANDROID_SHARED_STARBOARD_BRIDGE_H_ diff --git a/starboard/android/x86/platform_configuration/configuration.gni b/starboard/android/x86/platform_configuration/configuration.gni index 7b1100758777..3754e8c889b8 100644 --- a/starboard/android/x86/platform_configuration/configuration.gni +++ b/starboard/android/x86/platform_configuration/configuration.gni @@ -14,7 +14,6 @@ import("//starboard/android/shared/platform_configuration/configuration.gni") -android_abi = "x86" sabi_path = "//starboard/sabi/x86/sabi-v$sb_api_version.json" sb_enable_opus_sse = false diff --git a/starboard/linux/shared/audio_sink_type_dispatcher.cc b/starboard/linux/shared/audio_sink_type_dispatcher.cc index 2a0b5817f93a..4d956205125c 100644 --- a/starboard/linux/shared/audio_sink_type_dispatcher.cc +++ b/starboard/linux/shared/audio_sink_type_dispatcher.cc @@ -17,28 +17,38 @@ #include "starboard/shared/pulse/pulse_audio_sink_type.h" #include "starboard/shared/starboard/audio_sink/audio_sink_internal.h" +namespace starboard { +namespace shared { +namespace starboard { +namespace audio_sink { namespace { bool is_fallback_to_alsa = false; -} +} // namespace // static -void SbAudioSinkPrivate::PlatformInitialize() { - starboard::shared::pulse::PlatformInitialize(); +void SbAudioSinkImpl::PlatformInitialize() { + ::starboard::shared::pulse::PlatformInitialize(); if (GetPrimaryType()) { SB_LOG(INFO) << "Use PulseAudio"; } else { SB_LOG(INFO) << "Use ALSA"; - starboard::shared::alsa::PlatformInitialize(); + ::starboard::shared::alsa::PlatformInitialize(); is_fallback_to_alsa = true; } - SbAudioSinkPrivate::EnableFallbackToStub(); + ::starboard::shared::starboard::audio_sink::SbAudioSinkImpl:: + EnableFallbackToStub(); } // static -void SbAudioSinkPrivate::PlatformTearDown() { +void SbAudioSinkImpl::PlatformTearDown() { if (is_fallback_to_alsa) { - starboard::shared::alsa::PlatformTearDown(); + ::starboard::shared::alsa::PlatformTearDown(); } else { - starboard::shared::pulse::PlatformTearDown(); + ::starboard::shared::pulse::PlatformTearDown(); } } + +} // namespace audio_sink +} // namespace starboard +} // namespace shared +} // namespace starboard diff --git a/starboard/linux/shared/media_is_audio_supported.cc b/starboard/linux/shared/media_is_audio_supported.cc index ce2fbdff69a1..6b77bb0eeb3f 100644 --- a/starboard/linux/shared/media_is_audio_supported.cc +++ b/starboard/linux/shared/media_is_audio_supported.cc @@ -19,11 +19,14 @@ #include "starboard/configuration_constants.h" #include "starboard/media.h" -using ::starboard::shared::starboard::media::MimeType; - -bool SbMediaIsAudioSupported(SbMediaAudioCodec audio_codec, - const MimeType* mime_type, - int64_t bitrate) { +namespace starboard { +namespace shared { +namespace starboard { +namespace media { + +bool MediaIsAudioSupported(SbMediaAudioCodec audio_codec, + const MimeType* mime_type, + int64_t bitrate) { if (audio_codec == kSbMediaAudioCodecAac) { return bitrate <= kSbMediaMaxAudioBitrateInBitsPerSecond; } @@ -52,3 +55,8 @@ bool SbMediaIsAudioSupported(SbMediaAudioCodec audio_codec, return false; } + +} // namespace media +} // namespace starboard +} // namespace shared +} // namespace starboard diff --git a/starboard/linux/shared/media_is_video_supported.cc b/starboard/linux/shared/media_is_video_supported.cc index e932cb17f9b7..3fb39910b0de 100644 --- a/starboard/linux/shared/media_is_video_supported.cc +++ b/starboard/linux/shared/media_is_video_supported.cc @@ -22,23 +22,26 @@ #include "starboard/shared/libde265/de265_library_loader.h" #include "starboard/shared/starboard/media/media_util.h" +namespace starboard { +namespace shared { +namespace starboard { +namespace media { + using ::starboard::shared::de265::is_de265_supported; -using ::starboard::shared::starboard::media::IsSDRVideo; -using ::starboard::shared::starboard::media::MimeType; -bool SbMediaIsVideoSupported(SbMediaVideoCodec video_codec, - const MimeType* mime_type, - int profile, - int level, - int bit_depth, - SbMediaPrimaryId primary_id, - SbMediaTransferId transfer_id, - SbMediaMatrixId matrix_id, - int frame_width, - int frame_height, - int64_t bitrate, - int fps, - bool decode_to_texture_required) { +bool MediaIsVideoSupported(SbMediaVideoCodec video_codec, + const MimeType* mime_type, + int profile, + int level, + int bit_depth, + SbMediaPrimaryId primary_id, + SbMediaTransferId transfer_id, + SbMediaMatrixId matrix_id, + int frame_width, + int frame_height, + int64_t bitrate, + int fps, + bool decode_to_texture_required) { if (!IsSDRVideo(bit_depth, primary_id, transfer_id, matrix_id)) { if (bit_depth != 10 && bit_depth != 12) { return false; @@ -68,3 +71,8 @@ bool SbMediaIsVideoSupported(SbMediaVideoCodec video_codec, frame_width <= 1920 && frame_height <= 1080 && bitrate <= kSbMediaMaxVideoBitrateInBitsPerSecond && fps <= 60; } + +} // namespace media +} // namespace starboard +} // namespace shared +} // namespace starboard diff --git a/starboard/nplb/BUILD.gn b/starboard/nplb/BUILD.gn index a6c3b9e0a2ec..6910b4e02555 100644 --- a/starboard/nplb/BUILD.gn +++ b/starboard/nplb/BUILD.gn @@ -47,6 +47,8 @@ test("nplb") { "//starboard/nplb/sabi/struct_alignment_test.cc", "//starboard/shared/starboard/drm/drm_test_helpers.cc", "//starboard/shared/starboard/drm/drm_test_helpers.h", + "//starboard/testing/fake_graphics_context_provider.cc", + "//starboard/testing/fake_graphics_context_provider.h", "align_test.cc", "audio_sink_create_test.cc", "audio_sink_destroy_test.cc", @@ -219,8 +221,6 @@ test("nplb") { if (!is_android) { sources += [ - "//starboard/testing/fake_graphics_context_provider.cc", - "//starboard/testing/fake_graphics_context_provider.h", "maximum_player_configuration_explorer_test.cc", "media_set_audio_write_duration_test.cc", "multiple_player_test.cc", diff --git a/starboard/nplb/maximum_player_configuration_explorer.h b/starboard/nplb/maximum_player_configuration_explorer.h index 80ddf7b34bc2..bf74aea0309c 100644 --- a/starboard/nplb/maximum_player_configuration_explorer.h +++ b/starboard/nplb/maximum_player_configuration_explorer.h @@ -23,8 +23,7 @@ #include "starboard/nplb/player_test_util.h" #include "starboard/player.h" #include "starboard/shared/starboard/media/media_util.h" -// TODO(cobalt, b/377295011): remove the nogncheck annotation. -#include "starboard/testing/fake_graphics_context_provider.h" // nogncheck +#include "starboard/testing/fake_graphics_context_provider.h" namespace starboard { namespace nplb { diff --git a/starboard/nplb/player_test_util.cc b/starboard/nplb/player_test_util.cc index 01bfd49c6830..ec9bf4ac6016 100644 --- a/starboard/nplb/player_test_util.cc +++ b/starboard/nplb/player_test_util.cc @@ -24,8 +24,6 @@ #include "starboard/nplb/maximum_player_configuration_explorer.h" #include "starboard/nplb/player_creation_param_helpers.h" #include "starboard/shared/starboard/player/video_dmp_reader.h" -// TODO(cobalt, b/377295011): remove the nogncheck annotation. -#include "starboard/testing/fake_graphics_context_provider.h" // nogncheck #include "testing/gtest/include/gtest/gtest.h" namespace starboard { @@ -40,7 +38,6 @@ using std::placeholders::_1; using std::placeholders::_2; using std::placeholders::_3; using std::placeholders::_4; -using testing::FakeGraphicsContextProvider; const char* kAudioTestFiles[] = { "beneath_the_canopy_aac_stereo.dmp", diff --git a/starboard/raspi/shared/application_dispmanx.cc b/starboard/raspi/shared/application_dispmanx.cc index ef924b0e92b5..a5987c21664e 100644 --- a/starboard/raspi/shared/application_dispmanx.cc +++ b/starboard/raspi/shared/application_dispmanx.cc @@ -68,12 +68,12 @@ bool ApplicationDispmanx::DestroyWindow(SbWindow window) { } void ApplicationDispmanx::Initialize() { - SbAudioSinkPrivate::Initialize(); + ::starboard::shared::starboard::audio_sink::SbAudioSinkImpl::Initialize(); } void ApplicationDispmanx::Teardown() { ShutdownDispmanx(); - SbAudioSinkPrivate::TearDown(); + ::starboard::shared::starboard::audio_sink::SbAudioSinkImpl::TearDown(); } void ApplicationDispmanx ::OnSuspend() { diff --git a/starboard/raspi/shared/audio_sink_type_dispatcher.cc b/starboard/raspi/shared/audio_sink_type_dispatcher.cc index 97b918d0f794..70a8d746154f 100644 --- a/starboard/raspi/shared/audio_sink_type_dispatcher.cc +++ b/starboard/raspi/shared/audio_sink_type_dispatcher.cc @@ -15,13 +15,23 @@ #include "starboard/shared/alsa/alsa_audio_sink_type.h" #include "starboard/shared/starboard/audio_sink/audio_sink_internal.h" +namespace starboard { +namespace shared { +namespace starboard { +namespace audio_sink { + // static -void SbAudioSinkPrivate::PlatformInitialize() { - starboard::shared::alsa::PlatformInitialize(); +void SbAudioSinkImpl::PlatformInitialize() { + ::starboard::shared::alsa::PlatformInitialize(); SbAudioSinkPrivate::EnableFallbackToStub(); } // static -void SbAudioSinkPrivate::PlatformTearDown() { - starboard::shared::alsa::PlatformTearDown(); +void SbAudioSinkImpl::PlatformTearDown() { + ::starboard::shared::alsa::PlatformTearDown(); } + +} // namespace audio_sink +} // namespace starboard +} // namespace shared +} // namespace starboard diff --git a/starboard/raspi/shared/media_is_video_supported.cc b/starboard/raspi/shared/media_is_video_supported.cc index 16a7088ed5f3..5e5da15b6626 100644 --- a/starboard/raspi/shared/media_is_video_supported.cc +++ b/starboard/raspi/shared/media_is_video_supported.cc @@ -19,22 +19,24 @@ #include "starboard/media.h" #include "starboard/shared/starboard/media/media_util.h" -using ::starboard::shared::starboard::media::IsSDRVideo; -using ::starboard::shared::starboard::media::MimeType; +namespace starboard { +namespace shared { +namespace starboard { +namespace media { -bool SbMediaIsVideoSupported(SbMediaVideoCodec video_codec, - const MimeType* mime_type, - int profile, - int level, - int bit_depth, - SbMediaPrimaryId primary_id, - SbMediaTransferId transfer_id, - SbMediaMatrixId matrix_id, - int frame_width, - int frame_height, - int64_t bitrate, - int fps, - bool decode_to_texture_required) { +bool MediaIsVideoSupported(SbMediaVideoCodec video_codec, + const MimeType* mime_type, + int profile, + int level, + int bit_depth, + SbMediaPrimaryId primary_id, + SbMediaTransferId transfer_id, + SbMediaMatrixId matrix_id, + int frame_width, + int frame_height, + int64_t bitrate, + int fps, + bool decode_to_texture_required) { if (!IsSDRVideo(bit_depth, primary_id, transfer_id, matrix_id)) { return false; } @@ -46,3 +48,8 @@ bool SbMediaIsVideoSupported(SbMediaVideoCodec video_codec, frame_height <= 1080 && bitrate <= kSbMediaMaxVideoBitrateInBitsPerSecond && fps <= 30; } + +} // namespace media +} // namespace starboard +} // namespace shared +} // namespace starboard diff --git a/starboard/shared/alsa/alsa_audio_sink_type.cc b/starboard/shared/alsa/alsa_audio_sink_type.cc index 08bfd20bba30..8a683d943560 100644 --- a/starboard/shared/alsa/alsa_audio_sink_type.cc +++ b/starboard/shared/alsa/alsa_audio_sink_type.cc @@ -36,10 +36,11 @@ namespace shared { namespace alsa { namespace { -using starboard::ScopedLock; -using starboard::ScopedTryLock; -using starboard::shared::alsa::AlsaGetBufferedFrames; -using starboard::shared::alsa::AlsaWriteFrames; +using ::starboard::ScopedLock; +using ::starboard::ScopedTryLock; +using ::starboard::shared::alsa::AlsaGetBufferedFrames; +using ::starboard::shared::alsa::AlsaWriteFrames; +using ::starboard::shared::starboard::audio_sink::SbAudioSinkImpl; // The maximum number of frames that can be written to ALSA once. It must be a // power of 2. It is also used as the ALSA polling size. A small number will @@ -81,7 +82,7 @@ void* IncrementPointerByBytes(void* pointer, size_t offset) { // 2. It never stops the underlying ALSA audio sink once created. When its // source cannot provide enough data to continue playback, it simply writes // silence to ALSA. -class AlsaAudioSink : public SbAudioSinkPrivate { +class AlsaAudioSink : public SbAudioSinkImpl { public: AlsaAudioSink(Type* type, int channels, @@ -142,8 +143,8 @@ class AlsaAudioSink : public SbAudioSinkPrivate { SbMediaAudioSampleType sample_type_; pthread_t audio_out_thread_; - starboard::Mutex mutex_; - starboard::ConditionVariable creation_signal_; + ::starboard::Mutex mutex_; + ::starboard::ConditionVariable creation_signal_; int64_t time_to_wait_; @@ -215,7 +216,7 @@ AlsaAudioSink::~AlsaAudioSink() { // static void* AlsaAudioSink::ThreadEntryPoint(void* context) { pthread_setname_np(pthread_self(), "alsa_audio_out"); - starboard::shared::pthread::ThreadSetPriority(kSbThreadPriorityRealTime); + ::starboard::shared::pthread::ThreadSetPriority(kSbThreadPriorityRealTime); SB_DCHECK(context); AlsaAudioSink* sink = reinterpret_cast(context); sink->AudioThreadFunc(); @@ -228,7 +229,7 @@ void AlsaAudioSink::AudioThreadFunc() { sample_type_ == kSbMediaAudioSampleTypeFloat32 ? SND_PCM_FORMAT_FLOAT_LE : SND_PCM_FORMAT_S16; - playback_handle_ = starboard::shared::alsa::AlsaOpenPlaybackDevice( + playback_handle_ = ::starboard::shared::alsa::AlsaOpenPlaybackDevice( channels_, sampling_frequency_hz_, kFramesPerRequest, kALSABufferSizeInFrames, alsa_sample_type); { @@ -249,7 +250,7 @@ void AlsaAudioSink::AudioThreadFunc() { } } - starboard::shared::alsa::AlsaCloseDevice(playback_handle_); + ::starboard::shared::alsa::AlsaCloseDevice(playback_handle_); ScopedLock lock(mutex_); playback_handle_ = NULL; } @@ -450,25 +451,23 @@ SbAudioSink AlsaAudioSinkType::Create( return audio_sink; } -} // namespace - -namespace { AlsaAudioSinkType* alsa_audio_sink_type_; + } // namespace // static void PlatformInitialize() { SB_DCHECK(!alsa_audio_sink_type_); alsa_audio_sink_type_ = new AlsaAudioSinkType(); - SbAudioSinkPrivate::SetPrimaryType(alsa_audio_sink_type_); + SbAudioSinkImpl::SetPrimaryType(alsa_audio_sink_type_); } // static void PlatformTearDown() { SB_DCHECK(alsa_audio_sink_type_); - SB_DCHECK(alsa_audio_sink_type_ == SbAudioSinkPrivate::GetPrimaryType()); + SB_DCHECK(alsa_audio_sink_type_ == SbAudioSinkImpl::GetPrimaryType()); - SbAudioSinkPrivate::SetPrimaryType(NULL); + SbAudioSinkImpl::SetPrimaryType(NULL); delete alsa_audio_sink_type_; alsa_audio_sink_type_ = NULL; } diff --git a/starboard/shared/pulse/pulse_audio_sink_type.cc b/starboard/shared/pulse/pulse_audio_sink_type.cc index eb091fc508e3..ccbcc83b0765 100644 --- a/starboard/shared/pulse/pulse_audio_sink_type.cc +++ b/starboard/shared/pulse/pulse_audio_sink_type.cc @@ -53,6 +53,7 @@ namespace pulse { namespace { using starboard::media::GetBytesPerSample; +using ::starboard::shared::starboard::audio_sink::SbAudioSinkImpl; const int64_t kAudioIdleSleepIntervalUsec = 15'000; // 15ms const int64_t kAudioRunningSleepIntervalUsec = 5'000; // 5ms @@ -65,7 +66,7 @@ const size_t kPulseBufferSizeInFrames = 8192; class PulseAudioSinkType; -class PulseAudioSink : public SbAudioSinkPrivate { +class PulseAudioSink : public SbAudioSinkImpl { public: PulseAudioSink(PulseAudioSinkType* type, int channels, @@ -554,7 +555,7 @@ void PulseAudioSinkType::StateCallback(pa_context* context, void* userdata) { void* PulseAudioSinkType::ThreadEntryPoint(void* context) { pthread_setname_np(pthread_self(), "pulse_audio"); - shared::pthread::ThreadSetPriority(kSbThreadPriorityRealTime); + ::starboard::shared::pthread::ThreadSetPriority(kSbThreadPriorityRealTime); SB_DCHECK(context); PulseAudioSinkType* type = static_cast(context); @@ -602,16 +603,16 @@ void PlatformInitialize() { std::unique_ptr(new PulseAudioSinkType()); if (audio_sink_type->Initialize()) { pulse_audio_sink_type_ = audio_sink_type.release(); - SbAudioSinkPrivate::SetPrimaryType(pulse_audio_sink_type_); + SbAudioSinkImpl::SetPrimaryType(pulse_audio_sink_type_); } } // static void PlatformTearDown() { SB_DCHECK(pulse_audio_sink_type_); - SB_DCHECK(pulse_audio_sink_type_ == SbAudioSinkPrivate::GetPrimaryType()); + SB_DCHECK(pulse_audio_sink_type_ == SbAudioSinkImpl::GetPrimaryType()); - SbAudioSinkPrivate::SetPrimaryType(NULL); + SbAudioSinkImpl::SetPrimaryType(NULL); delete pulse_audio_sink_type_; pulse_audio_sink_type_ = NULL; pulse_unload_library(); diff --git a/starboard/shared/starboard/audio_sink/audio_sink_create.cc b/starboard/shared/starboard/audio_sink/audio_sink_create.cc index 7061745ff814..14867aa7e3e3 100644 --- a/starboard/shared/starboard/audio_sink/audio_sink_create.cc +++ b/starboard/shared/starboard/audio_sink/audio_sink_create.cc @@ -27,7 +27,7 @@ SbAudioSink SbAudioSinkCreate( SbAudioSinkUpdateSourceStatusFunc update_source_status_func, SbAudioSinkConsumeFramesFunc consume_frames_func, void* context) { - return SbAudioSinkPrivate::Create( + return ::starboard::shared::starboard::audio_sink::SbAudioSinkImpl::Create( channels, sampling_frequency_hz, audio_sample_type, audio_frame_storage_type, frame_buffers, frame_buffers_size_in_frames, update_source_status_func, consume_frames_func, NULL /*error_func*/, diff --git a/starboard/shared/starboard/audio_sink/audio_sink_destroy.cc b/starboard/shared/starboard/audio_sink/audio_sink_destroy.cc index 4dea688d9606..ac0b1abd978b 100644 --- a/starboard/shared/starboard/audio_sink/audio_sink_destroy.cc +++ b/starboard/shared/starboard/audio_sink/audio_sink_destroy.cc @@ -18,16 +18,18 @@ #include "starboard/shared/starboard/audio_sink/audio_sink_internal.h" void SbAudioSinkDestroy(SbAudioSink audio_sink) { + using ::starboard::shared::starboard::audio_sink::SbAudioSinkImpl; + if (audio_sink == kSbAudioSinkInvalid) { return; } - SbAudioSinkPrivate::Type* type = SbAudioSinkPrivate::GetPrimaryType(); + SbAudioSinkPrivate::Type* type = SbAudioSinkImpl::GetPrimaryType(); if (type && type->IsValid(audio_sink)) { type->Destroy(audio_sink); return; } - type = SbAudioSinkPrivate::GetFallbackType(); + type = SbAudioSinkImpl::GetFallbackType(); if (type && type->IsValid(audio_sink)) { type->Destroy(audio_sink); return; diff --git a/starboard/shared/starboard/audio_sink/audio_sink_internal.cc b/starboard/shared/starboard/audio_sink/audio_sink_internal.cc index 450c4186928a..5fb1ded88b85 100644 --- a/starboard/shared/starboard/audio_sink/audio_sink_internal.cc +++ b/starboard/shared/starboard/audio_sink/audio_sink_internal.cc @@ -21,6 +21,10 @@ #include "starboard/shared/starboard/audio_sink/stub_audio_sink_type.h" #include "starboard/shared/starboard/command_line.h" +namespace starboard { +namespace shared { +namespace starboard { +namespace audio_sink { namespace { using std::placeholders::_1; @@ -28,8 +32,8 @@ using std::placeholders::_2; using std::placeholders::_3; bool is_fallback_to_stub_enabled; -SbAudioSinkPrivate::Type* primary_audio_sink_type; -SbAudioSinkPrivate::Type* fallback_audio_sink_type; +SbAudioSinkImpl::Type* primary_audio_sink_type; +SbAudioSinkImpl::Type* fallback_audio_sink_type; // Command line switch that controls whether we default to the stub audio sink, // even when the primary audio sink may be available. @@ -45,36 +49,34 @@ void WrapConsumeFramesFunc(SbAudioSinkConsumeFramesFunc sb_consume_frames_func, } // namespace -using starboard::shared::starboard::audio_sink::StubAudioSinkType; - // static -void SbAudioSinkPrivate::Initialize() { +void SbAudioSinkImpl::Initialize() { fallback_audio_sink_type = new StubAudioSinkType; PlatformInitialize(); } // static -void SbAudioSinkPrivate::TearDown() { +void SbAudioSinkImpl::TearDown() { PlatformTearDown(); delete fallback_audio_sink_type; fallback_audio_sink_type = NULL; } // static -void SbAudioSinkPrivate::SetPrimaryType(Type* type) { +void SbAudioSinkImpl::SetPrimaryType(Type* type) { primary_audio_sink_type = type; } // static -SbAudioSinkPrivate::Type* SbAudioSinkPrivate::GetPrimaryType() { +SbAudioSinkImpl::Type* SbAudioSinkImpl::GetPrimaryType() { return primary_audio_sink_type; } // static -void SbAudioSinkPrivate::EnableFallbackToStub() { +void SbAudioSinkImpl::EnableFallbackToStub() { is_fallback_to_stub_enabled = true; } // static -SbAudioSinkPrivate::Type* SbAudioSinkPrivate::GetFallbackType() { +SbAudioSinkImpl::Type* SbAudioSinkImpl::GetFallbackType() { if (is_fallback_to_stub_enabled) { return fallback_audio_sink_type; } @@ -82,17 +84,16 @@ SbAudioSinkPrivate::Type* SbAudioSinkPrivate::GetFallbackType() { } // static -SbAudioSinkPrivate::Type* SbAudioSinkPrivate::GetPreferredType() { - SbAudioSinkPrivate::Type* audio_sink_type = NULL; - auto command_line = - starboard::shared::starboard::Application::Get()->GetCommandLine(); +SbAudioSinkImpl::Type* SbAudioSinkImpl::GetPreferredType() { + SbAudioSinkImpl::Type* audio_sink_type = NULL; + auto command_line = Application::Get()->GetCommandLine(); if (!command_line->HasSwitch(kUseStubAudioSink)) { - audio_sink_type = SbAudioSinkPrivate::GetPrimaryType(); + audio_sink_type = SbAudioSinkImpl::GetPrimaryType(); } if (!audio_sink_type) { SB_LOG(WARNING) << "Primary audio sink type not selected or missing, " "opting to use Fallback instead."; - audio_sink_type = SbAudioSinkPrivate::GetFallbackType(); + audio_sink_type = SbAudioSinkImpl::GetFallbackType(); } if (audio_sink_type == NULL) { SB_LOG(WARNING) << "Fallback audio sink type is not enabled."; @@ -100,7 +101,7 @@ SbAudioSinkPrivate::Type* SbAudioSinkPrivate::GetPreferredType() { return audio_sink_type; } -SbAudioSink SbAudioSinkPrivate::Create( +SbAudioSink SbAudioSinkImpl::Create( int channels, int sampling_frequency_hz, SbMediaAudioSampleType audio_sample_type, @@ -169,7 +170,7 @@ SbAudioSink SbAudioSinkPrivate::Create( } SB_LOG(WARNING) << "Try to create AudioSink using fallback type."; - if (auto fallback_type = SbAudioSinkPrivate::GetFallbackType()) { + if (auto fallback_type = SbAudioSinkImpl::GetFallbackType()) { auto audio_sink = fallback_type->Create( channels, sampling_frequency_hz, audio_sample_type, audio_frame_storage_type, frame_buffers, frame_buffers_size_in_frames, @@ -186,7 +187,7 @@ SbAudioSink SbAudioSinkPrivate::Create( } // static -SbAudioSink SbAudioSinkPrivate::Create( +SbAudioSink SbAudioSinkImpl::Create( int channels, int sampling_frequency_hz, SbMediaAudioSampleType audio_sample_type, @@ -201,8 +202,13 @@ SbAudioSink SbAudioSinkPrivate::Create( audio_frame_storage_type, frame_buffers, frame_buffers_size_in_frames, update_source_status_func, sb_consume_frames_func - ? std::bind(&::WrapConsumeFramesFunc, - sb_consume_frames_func, _1, _2, _3) + ? std::bind(&WrapConsumeFramesFunc, sb_consume_frames_func, + _1, _2, _3) : ConsumeFramesFunc(), error_func, context); } + +} // namespace audio_sink +} // namespace starboard +} // namespace shared +} // namespace starboard diff --git a/starboard/shared/starboard/audio_sink/audio_sink_internal.h b/starboard/shared/starboard/audio_sink/audio_sink_internal.h index fa0cc550d1f6..35c628c9f013 100644 --- a/starboard/shared/starboard/audio_sink/audio_sink_internal.h +++ b/starboard/shared/starboard/audio_sink/audio_sink_internal.h @@ -56,12 +56,19 @@ struct SbAudioSinkPrivate { }; virtual ~SbAudioSinkPrivate() {} - virtual void SetPlaybackRate(double playback_rate) = 0; + virtual void SetPlaybackRate(double playback_rate) = 0; virtual void SetVolume(double volume) = 0; - virtual bool IsType(Type* type) = 0; +}; + +namespace starboard { +namespace shared { +namespace starboard { +namespace audio_sink { +class SbAudioSinkImpl : public SbAudioSinkPrivate { + public: // The following two functions will be called during application startup and // termination. static void Initialize(); @@ -112,4 +119,9 @@ struct SbAudioSinkPrivate { static void PlatformTearDown(); }; +} // namespace audio_sink +} // namespace starboard +} // namespace shared +} // namespace starboard + #endif // STARBOARD_SHARED_STARBOARD_AUDIO_SINK_AUDIO_SINK_INTERNAL_H_ diff --git a/starboard/shared/starboard/audio_sink/audio_sink_is_valid.cc b/starboard/shared/starboard/audio_sink/audio_sink_is_valid.cc index 05b2ceab0529..7e608a460260 100644 --- a/starboard/shared/starboard/audio_sink/audio_sink_is_valid.cc +++ b/starboard/shared/starboard/audio_sink/audio_sink_is_valid.cc @@ -17,11 +17,13 @@ #include "starboard/shared/starboard/audio_sink/audio_sink_internal.h" bool SbAudioSinkIsValid(SbAudioSink audio_sink) { - SbAudioSinkPrivate::Type* type = SbAudioSinkPrivate::GetPrimaryType(); + using ::starboard::shared::starboard::audio_sink::SbAudioSinkImpl; + + SbAudioSinkPrivate::Type* type = SbAudioSinkImpl::GetPrimaryType(); if (type && type->IsValid(audio_sink)) { return true; } - type = SbAudioSinkPrivate::GetFallbackType(); + type = SbAudioSinkImpl::GetFallbackType(); if (type && type->IsValid(audio_sink)) { return true; } diff --git a/starboard/shared/starboard/decode_target/decode_target_internal.h b/starboard/shared/starboard/decode_target/decode_target_internal.h index f1db07cf338e..779ad897ddcb 100644 --- a/starboard/shared/starboard/decode_target/decode_target_internal.h +++ b/starboard/shared/starboard/decode_target/decode_target_internal.h @@ -20,7 +20,7 @@ #include "starboard/common/ref_counted.h" struct SbDecodeTargetPrivate : starboard::RefCounted { - SbDecodeTargetPrivate(); + SbDecodeTargetPrivate() = default; SbDecodeTargetPrivate(const SbDecodeTargetPrivate&) = delete; SbDecodeTargetPrivate& operator=(const SbDecodeTargetPrivate&) = delete; @@ -30,7 +30,7 @@ struct SbDecodeTargetPrivate : starboard::RefCounted { protected: friend class starboard::RefCounted; - virtual ~SbDecodeTargetPrivate(); + virtual ~SbDecodeTargetPrivate() = default; }; #endif // STARBOARD_SHARED_STARBOARD_DECODE_TARGET_DECODE_TARGET_INTERNAL_H_ diff --git a/starboard/shared/starboard/media/media_is_audio_supported_aac_and_opus.cc b/starboard/shared/starboard/media/media_is_audio_supported_aac_and_opus.cc index e4689ca5c69e..772a81acd382 100644 --- a/starboard/shared/starboard/media/media_is_audio_supported_aac_and_opus.cc +++ b/starboard/shared/starboard/media/media_is_audio_supported_aac_and_opus.cc @@ -18,11 +18,14 @@ #include "starboard/configuration_constants.h" #include "starboard/media.h" -using ::starboard::shared::starboard::media::MimeType; +namespace starboard { +namespace shared { +namespace starboard { +namespace media { -bool SbMediaIsAudioSupported(SbMediaAudioCodec audio_codec, - const MimeType* mime_type, - int64_t bitrate) { +bool MediaIsAudioSupported(SbMediaAudioCodec audio_codec, + const MimeType* mime_type, + int64_t bitrate) { if (audio_codec == kSbMediaAudioCodecAac) { return bitrate <= kSbMediaMaxAudioBitrateInBitsPerSecond; } @@ -33,3 +36,8 @@ bool SbMediaIsAudioSupported(SbMediaAudioCodec audio_codec, return false; } + +} // namespace media +} // namespace starboard +} // namespace shared +} // namespace starboard diff --git a/starboard/shared/starboard/media/media_is_audio_supported_aac_only.cc b/starboard/shared/starboard/media/media_is_audio_supported_aac_only.cc index 83dbd141b4e8..d6c10617d436 100644 --- a/starboard/shared/starboard/media/media_is_audio_supported_aac_only.cc +++ b/starboard/shared/starboard/media/media_is_audio_supported_aac_only.cc @@ -18,11 +18,19 @@ #include "starboard/configuration_constants.h" #include "starboard/media.h" -using ::starboard::shared::starboard::media::MimeType; +namespace starboard { +namespace shared { +namespace starboard { +namespace media { -bool SbMediaIsAudioSupported(SbMediaAudioCodec audio_codec, - const MimeType* mime_type, - int64_t bitrate) { +bool MediaIsAudioSupported(SbMediaAudioCodec audio_codec, + const MimeType* mime_type, + int64_t bitrate) { return audio_codec == kSbMediaAudioCodecAac && bitrate <= kSbMediaMaxAudioBitrateInBitsPerSecond; } + +} // namespace media +} // namespace starboard +} // namespace shared +} // namespace starboard diff --git a/starboard/shared/starboard/media/media_support_internal.h b/starboard/shared/starboard/media/media_support_internal.h index 31481482a8de..89d959302a17 100644 --- a/starboard/shared/starboard/media/media_support_internal.h +++ b/starboard/shared/starboard/media/media_support_internal.h @@ -20,9 +20,10 @@ #include "starboard/shared/internal_only.h" #include "starboard/shared/starboard/media/mime_type.h" -#ifdef __cplusplus -extern "C" { -#endif +namespace starboard { +namespace shared { +namespace starboard { +namespace media { // Indicates whether this platform supports decoding |video_codec| and // |audio_codec| along with decrypting using |key_system|. If |video_codec| is @@ -35,9 +36,9 @@ extern "C" { // |audio_codec|: The |SbMediaAudioCodec| being checked for platform // compatibility. // |key_system|: The key system being checked for platform compatibility. -SB_EXPORT bool SbMediaIsSupported(SbMediaVideoCodec video_codec, - SbMediaAudioCodec audio_codec, - const char* key_system); +SB_EXPORT bool MediaIsSupported(SbMediaVideoCodec video_codec, + SbMediaAudioCodec audio_codec, + const char* key_system); // Indicates whether a given combination of (|frame_width| x |frame_height|) // frames at |bitrate| and |fps| is supported on this platform with @@ -73,20 +74,19 @@ SB_EXPORT bool SbMediaIsSupported(SbMediaVideoCodec video_codec, // it indicates that the fps shouldn't be considered. // |decode_to_texture_required|: Whether or not the resulting video frames can // be decoded and used as textures by the GPU. -bool SbMediaIsVideoSupported( - SbMediaVideoCodec video_codec, - const starboard::shared::starboard::media::MimeType* mime_type, - int profile, - int level, - int bit_depth, - SbMediaPrimaryId primary_id, - SbMediaTransferId transfer_id, - SbMediaMatrixId matrix_id, - int frame_width, - int frame_height, - int64_t bitrate, - int fps, - bool decode_to_texture_required); +bool MediaIsVideoSupported(SbMediaVideoCodec video_codec, + const MimeType* mime_type, + int profile, + int level, + int bit_depth, + SbMediaPrimaryId primary_id, + SbMediaTransferId transfer_id, + SbMediaMatrixId matrix_id, + int frame_width, + int frame_height, + int64_t bitrate, + int fps, + bool decode_to_texture_required); // Indicates whether this platform supports |audio_codec| at |bitrate|. // If |audio_codec| is not supported under any condition, this function @@ -96,13 +96,13 @@ bool SbMediaIsVideoSupported( // |mime_type|: The parsed mime type passed to the corresponding interface. // Note that |mime_type| can be NULL. // |bitrate|: The media's bitrate. -bool SbMediaIsAudioSupported( - SbMediaAudioCodec audio_codec, - const starboard::shared::starboard::media::MimeType* mime_type, - int64_t bitrate); +bool MediaIsAudioSupported(SbMediaAudioCodec audio_codec, + const MimeType* mime_type, + int64_t bitrate); -#ifdef __cplusplus -} // extern "C" -#endif +} // namespace media +} // namespace starboard +} // namespace shared +} // namespace starboard #endif // STARBOARD_SHARED_STARBOARD_MEDIA_MEDIA_SUPPORT_INTERNAL_H_ diff --git a/starboard/shared/starboard/media/mime_util.cc b/starboard/shared/starboard/media/mime_util.cc index e0fc0280558d..a3c0b2ce4815 100644 --- a/starboard/shared/starboard/media/mime_util.cc +++ b/starboard/shared/starboard/media/mime_util.cc @@ -59,7 +59,7 @@ bool IsSupportedKeySystem(SbMediaAudioCodec codec, const char* key_system) { // |key_system|, so here it should always be non empty. SB_DCHECK(strlen(key_system) > 0); - return SbMediaIsSupported(kSbMediaVideoCodecNone, codec, key_system); + return MediaIsSupported(kSbMediaVideoCodecNone, codec, key_system); } bool IsSupportedKeySystem(SbMediaVideoCodec codec, const char* key_system) { @@ -68,7 +68,7 @@ bool IsSupportedKeySystem(SbMediaVideoCodec codec, const char* key_system) { // |key_system|, so here it should always be non empty. SB_DCHECK(strlen(key_system) > 0); - return SbMediaIsSupported(codec, kSbMediaAudioCodecNone, key_system); + return MediaIsSupported(codec, kSbMediaAudioCodecNone, key_system); } bool IsSupportedAudioCodec(const ParsedMimeInfo& mime_info) { @@ -123,8 +123,8 @@ bool IsSupportedAudioCodec(const ParsedMimeInfo& mime_info) { return false; } - return SbMediaIsAudioSupported(audio_info.codec, &mime_type, - audio_info.bitrate); + return MediaIsAudioSupported(audio_info.codec, &mime_type, + audio_info.bitrate); } bool IsSupportedVideoCodec(const ParsedMimeInfo& mime_info) { @@ -175,7 +175,7 @@ bool IsSupportedVideoCodec(const ParsedMimeInfo& mime_info) { } } - return SbMediaIsVideoSupported( + return MediaIsVideoSupported( video_info.codec, &mime_type, video_info.profile, video_info.level, video_info.bit_depth, video_info.primary_id, video_info.transfer_id, video_info.matrix_id, video_info.frame_width, video_info.frame_height, diff --git a/starboard/shared/starboard/media/mime_util_test.cc b/starboard/shared/starboard/media/mime_util_test.cc index 8cfcb6495b14..c21469cef20c 100644 --- a/starboard/shared/starboard/media/mime_util_test.cc +++ b/starboard/shared/starboard/media/mime_util_test.cc @@ -35,8 +35,7 @@ TEST(MimeUtilTest, ChecksSupportedMp3Containers) { const MimeType valid_mp3_mime_1(valid_mp3_mime_str_1); EXPECT_EQ( CanPlayMimeAndKeySystem(valid_mp3_mime_str_1.c_str(), kEmptyKeySystem), - SbMediaIsAudioSupported(kSbMediaAudioCodecMp3, &valid_mp3_mime_1, - kBitrate) + MediaIsAudioSupported(kSbMediaAudioCodecMp3, &valid_mp3_mime_1, kBitrate) ? kSbMediaSupportTypeProbably : kSbMediaSupportTypeNotSupported); @@ -45,8 +44,7 @@ TEST(MimeUtilTest, ChecksSupportedMp3Containers) { const MimeType valid_mp3_mime_2(valid_mp3_mime_str_2); EXPECT_EQ( CanPlayMimeAndKeySystem(valid_mp3_mime_str_2.c_str(), kEmptyKeySystem), - SbMediaIsAudioSupported(kSbMediaAudioCodecMp3, &valid_mp3_mime_2, - kBitrate) + MediaIsAudioSupported(kSbMediaAudioCodecMp3, &valid_mp3_mime_2, kBitrate) ? kSbMediaSupportTypeProbably : kSbMediaSupportTypeNotSupported); } @@ -67,8 +65,7 @@ TEST(MimeUtilTest, ChecksSupportedFlacContainers) { const MimeType valid_flac_mime_1(valid_flac_mime_str_1); EXPECT_EQ( CanPlayMimeAndKeySystem(valid_flac_mime_str_1.c_str(), kEmptyKeySystem), - SbMediaIsAudioSupported(kSbMediaAudioCodecMp3, &valid_flac_mime_1, - kBitrate) + MediaIsAudioSupported(kSbMediaAudioCodecMp3, &valid_flac_mime_1, kBitrate) ? kSbMediaSupportTypeProbably : kSbMediaSupportTypeNotSupported); @@ -77,8 +74,7 @@ TEST(MimeUtilTest, ChecksSupportedFlacContainers) { const MimeType valid_flac_mime_2(valid_flac_mime_str_2); EXPECT_EQ( CanPlayMimeAndKeySystem(valid_flac_mime_str_2.c_str(), kEmptyKeySystem), - SbMediaIsAudioSupported(kSbMediaAudioCodecMp3, &valid_flac_mime_2, - kBitrate) + MediaIsAudioSupported(kSbMediaAudioCodecMp3, &valid_flac_mime_2, kBitrate) ? kSbMediaSupportTypeProbably : kSbMediaSupportTypeNotSupported); } @@ -99,7 +95,7 @@ TEST(MimeUtilTest, ChecksSupportedPcmContainers) { const MimeType valid_pcm_mime(valid_pcm_mime_str); EXPECT_EQ( CanPlayMimeAndKeySystem(valid_pcm_mime_str.c_str(), kEmptyKeySystem), - SbMediaIsAudioSupported(kSbMediaAudioCodecPcm, &valid_pcm_mime, kBitrate) + MediaIsAudioSupported(kSbMediaAudioCodecPcm, &valid_pcm_mime, kBitrate) ? kSbMediaSupportTypeProbably : kSbMediaSupportTypeNotSupported); } diff --git a/starboard/shared/starboard/player/filter/audio_renderer_sink_impl.cc b/starboard/shared/starboard/player/filter/audio_renderer_sink_impl.cc index 1f7ad987833e..d0569f3c78d8 100644 --- a/starboard/shared/starboard/player/filter/audio_renderer_sink_impl.cc +++ b/starboard/shared/starboard/player/filter/audio_renderer_sink_impl.cc @@ -39,7 +39,7 @@ AudioRendererSinkImpl::AudioRendererSinkImpl() SbAudioSinkPrivate::ConsumeFramesFunc consume_frames_func, SbAudioSinkPrivate::ErrorFunc error_func, void* context) { - return SbAudioSinkPrivate::Create( + return audio_sink::SbAudioSinkImpl::Create( channels, sampling_frequency_hz, audio_sample_type, audio_frame_storage_type, frame_buffers, frame_buffers_size_in_frames, update_source_status_func, diff --git a/starboard/shared/starboard/player/filter/testing/test_util.cc b/starboard/shared/starboard/player/filter/testing/test_util.cc index fd99aee105d8..05585ac0614b 100644 --- a/starboard/shared/starboard/player/filter/testing/test_util.cc +++ b/starboard/shared/starboard/player/filter/testing/test_util.cc @@ -143,8 +143,8 @@ std::vector GetSupportedAudioTestFiles( const std::string audio_mime = GetContentTypeFromAudioCodec( audio_file_info.audio_codec, extra_mime_attributes); const MimeType audio_mime_type(audio_mime.c_str()); - if (!SbMediaIsAudioSupported(audio_file_info.audio_codec, &audio_mime_type, - audio_file_info.bitrate)) { + if (!MediaIsAudioSupported(audio_file_info.audio_codec, &audio_mime_type, + audio_file_info.bitrate)) { continue; } @@ -186,7 +186,7 @@ std::vector GetSupportedVideoTests() { const auto& video_stream_info = dmp_reader.video_stream_info(); const std::string video_mime = dmp_reader.video_mime_type(); const MimeType video_mime_type(video_mime.c_str()); - // SbMediaIsVideoSupported may return false for gpu based decoder that in + // MediaIsVideoSupported may return false for gpu based decoder that in // fact supports av1 or/and vp9 because the system can make async // initialization at startup. // To minimize probability of false negative we check result few times @@ -196,7 +196,7 @@ std::vector GetSupportedVideoTests() { bool need_to_check_with_wait = video_codec == kSbMediaVideoCodecAv1 || video_codec == kSbMediaVideoCodecVp9; do { - if (SbMediaIsVideoSupported( + if (MediaIsVideoSupported( video_codec, video_mime.size() > 0 ? &video_mime_type : nullptr, -1, -1, 8, kSbMediaPrimaryIdUnspecified, kSbMediaTransferIdUnspecified, kSbMediaMatrixIdUnspecified, diff --git a/starboard/shared/starboard/player/player_create.cc b/starboard/shared/starboard/player/player_create.cc index 5e86db11b056..427fa3ef0bc8 100644 --- a/starboard/shared/starboard/player/player_create.cc +++ b/starboard/shared/starboard/player/player_create.cc @@ -132,7 +132,7 @@ SbPlayer SbPlayerCreate(SbWindow window, const int64_t kDefaultBitRate = 0; if (audio_codec != kSbMediaAudioCodecNone) { const MimeType audio_mime_type(audio_mime); - if (!SbMediaIsAudioSupported( + if (!MediaIsAudioSupported( audio_codec, strlen(audio_mime) > 0 ? &audio_mime_type : nullptr, kDefaultBitRate)) { SB_LOG(ERROR) << "Unsupported audio codec " @@ -154,7 +154,7 @@ SbPlayer SbPlayerCreate(SbWindow window, const int kDefaultFrameRate = 0; if (video_codec != kSbMediaVideoCodecNone) { const MimeType video_mime_type(video_mime); - if (!SbMediaIsVideoSupported( + if (!MediaIsVideoSupported( video_codec, strlen(video_mime) > 0 ? &video_mime_type : nullptr, kDefaultProfile, kDefaultLevel, kDefaultColorDepth, kSbMediaPrimaryIdUnspecified, kSbMediaTransferIdUnspecified, diff --git a/starboard/shared/stub/media_is_audio_supported.cc b/starboard/shared/stub/media_is_audio_supported.cc index 853eca07306b..a8625a993aaf 100644 --- a/starboard/shared/stub/media_is_audio_supported.cc +++ b/starboard/shared/stub/media_is_audio_supported.cc @@ -16,10 +16,18 @@ #include "starboard/media.h" -using ::starboard::shared::starboard::media::MimeType; +namespace starboard { +namespace shared { +namespace starboard { +namespace media { -bool SbMediaIsAudioSupported(SbMediaAudioCodec audio_codec, - const MimeType* mime_type, - int64_t bitrate) { +bool MediaIsAudioSupported(SbMediaAudioCodec audio_codec, + const MimeType* mime_type, + int64_t bitrate) { return false; } + +} // namespace media +} // namespace starboard +} // namespace shared +} // namespace starboard diff --git a/starboard/shared/stub/media_is_supported.cc b/starboard/shared/stub/media_is_supported.cc index fd53e2e10cfa..6e07c4992dd0 100644 --- a/starboard/shared/stub/media_is_supported.cc +++ b/starboard/shared/stub/media_is_supported.cc @@ -16,8 +16,18 @@ #include "starboard/media.h" -bool SbMediaIsSupported(SbMediaVideoCodec video_codec, - SbMediaAudioCodec audio_codec, - const char* key_system) { +namespace starboard { +namespace shared { +namespace starboard { +namespace media { + +bool MediaIsSupported(SbMediaVideoCodec video_codec, + SbMediaAudioCodec audio_codec, + const char* key_system) { return false; } + +} // namespace media +} // namespace starboard +} // namespace shared +} // namespace starboard diff --git a/starboard/shared/stub/media_is_video_supported.cc b/starboard/shared/stub/media_is_video_supported.cc index 1049791d09ee..6b6d4fbdc648 100644 --- a/starboard/shared/stub/media_is_video_supported.cc +++ b/starboard/shared/stub/media_is_video_supported.cc @@ -16,20 +16,28 @@ #include "starboard/media.h" -using ::starboard::shared::starboard::media::MimeType; +namespace starboard { +namespace shared { +namespace starboard { +namespace media { -bool SbMediaIsVideoSupported(SbMediaVideoCodec video_codec, - const MimeType* mime_type, - int profile, - int level, - int bit_depth, - SbMediaPrimaryId primary_id, - SbMediaTransferId transfer_id, - SbMediaMatrixId matrix_id, - int frame_width, - int frame_height, - int64_t bitrate, - int fps, - bool decode_to_texture_required) { +bool MediaIsVideoSupported(SbMediaVideoCodec video_codec, + const MimeType* mime_type, + int profile, + int level, + int bit_depth, + SbMediaPrimaryId primary_id, + SbMediaTransferId transfer_id, + SbMediaMatrixId matrix_id, + int frame_width, + int frame_height, + int64_t bitrate, + int fps, + bool decode_to_texture_required) { return false; } + +} // namespace media +} // namespace starboard +} // namespace shared +} // namespace starboard diff --git a/starboard/shared/widevine/media_is_supported.cc b/starboard/shared/widevine/media_is_supported.cc index 413fd22367a1..fc0bcb6bd9be 100644 --- a/starboard/shared/widevine/media_is_supported.cc +++ b/starboard/shared/widevine/media_is_supported.cc @@ -17,10 +17,20 @@ #include "starboard/media.h" #include "starboard/shared/widevine/drm_system_widevine.h" -bool SbMediaIsSupported(SbMediaVideoCodec video_codec, - SbMediaAudioCodec audio_codec, - const char* key_system) { - using starboard::shared::widevine::DrmSystemWidevine; +namespace starboard { +namespace shared { +namespace starboard { +namespace media { + +bool MediaIsSupported(SbMediaVideoCodec video_codec, + SbMediaAudioCodec audio_codec, + const char* key_system) { + using ::starboard::shared::widevine::DrmSystemWidevine; return DrmSystemWidevine::IsKeySystemSupported(key_system); } + +} // namespace media +} // namespace starboard +} // namespace shared +} // namespace starboard diff --git a/starboard/shared/x11/application_x11.cc b/starboard/shared/x11/application_x11.cc index c6a838efa5d1..bac7cd074507 100644 --- a/starboard/shared/x11/application_x11.cc +++ b/starboard/shared/x11/application_x11.cc @@ -701,12 +701,12 @@ ApplicationX11::ApplicationX11(SbEventHandleCallback sb_event_handle_callback) composite_event_id_(kSbEventIdInvalid), display_(NULL), paste_buffer_key_release_pending_(false) { - SbAudioSinkPrivate::Initialize(); + ::starboard::shared::starboard::audio_sink::SbAudioSinkImpl::Initialize(); NetworkNotifier::GetOrCreateInstance(); } ApplicationX11::~ApplicationX11() { - SbAudioSinkPrivate::TearDown(); + ::starboard::shared::starboard::audio_sink::SbAudioSinkImpl::TearDown(); } SbWindow ApplicationX11::CreateWindow(const SbWindowOptions* options) { diff --git a/third_party/android_deps/.gitignore b/third_party/android_deps/.gitignore index 8066eb49d992..2c0c14b59480 100644 --- a/third_party/android_deps/.gitignore +++ b/third_party/android_deps/.gitignore @@ -6,6 +6,7 @@ buildSrc/.gradle/ buildSrc/build/ # JAR and AAR files will be fetched via CIPD. +cipd/ libs/*/*.jar libs/*/*.aar diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn index b1145a98a6d1..a4f61e8fca99 100644 --- a/third_party/blink/public/mojom/BUILD.gn +++ b/third_party/blink/public/mojom/BUILD.gn @@ -241,6 +241,10 @@ mojom("mojom_platform") { "worker/worker_options.mojom", ] + if (is_cobalt) { + sources += [ "cobalt/crash_annotator/crash_annotator.mojom" ] + } + if (is_android) { sources += [ "input/synchronous_compositor.mojom" ] } diff --git a/third_party/blink/public/mojom/cobalt/crash_annotator/crash_annotator.mojom b/third_party/blink/public/mojom/cobalt/crash_annotator/crash_annotator.mojom new file mode 100644 index 000000000000..84deafd8df26 --- /dev/null +++ b/third_party/blink/public/mojom/cobalt/crash_annotator/crash_annotator.mojom @@ -0,0 +1,22 @@ +// 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. + +module blink.mojom; + +// The browser process must provide an implementation of this interface so that +// the renderer process can implement the CrashAnnotator Blink API. +interface CrashAnnotator { + // Recieves an annotation to set and responds with the result. + SetString(string key, string value) => (bool result); +}; diff --git a/third_party/blink/public/platform/web_source_buffer.h b/third_party/blink/public/platform/web_source_buffer.h index 7ac41eedb64f..fc3defa085be 100644 --- a/third_party/blink/public/platform/web_source_buffer.h +++ b/third_party/blink/public/platform/web_source_buffer.h @@ -37,6 +37,10 @@ namespace blink { +#if BUILDFLAG(USE_STARBOARD_MEDIA) +class ExceptionState; +#endif // BUILDFLAG(USE_STARBOARD_MEDIA) + class WebSourceBufferClient; // Interface for actuating the media engine implementation of Media Source @@ -140,6 +144,11 @@ class WebSourceBuffer { // After this method is called, this WebSourceBuffer should never use the // client pointer passed to SetClient(). virtual void RemovedFromMediaSource() = 0; + +#if BUILDFLAG(USE_STARBOARD_MEDIA) + // Return the highest presentation timestamp written to the Renderer. + virtual double GetWriteHead(ExceptionState& exception_state) const = 0; +#endif // BUILDFLAG(USE_STARBOARD_MEDIA) }; } // namespace blink diff --git a/third_party/blink/renderer/bindings/generated_in_modules.gni b/third_party/blink/renderer/bindings/generated_in_modules.gni index 0b3ea3360c6c..118f11e214c6 100644 --- a/third_party/blink/renderer/bindings/generated_in_modules.gni +++ b/third_party/blink/renderer/bindings/generated_in_modules.gni @@ -2791,6 +2791,13 @@ generated_interface_sources_in_modules = [ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_xr_webgl_sub_image.h", ] +if (is_cobalt) { + generated_interface_sources_in_modules += [ + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_crash_annotator.cc", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_crash_annotator.h", + ] +} + generated_namespace_sources_in_modules = [ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_css.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_css.h", diff --git a/third_party/blink/renderer/bindings/idl_in_modules.gni b/third_party/blink/renderer/bindings/idl_in_modules.gni index 7f915ac9c55d..3445984b8088 100644 --- a/third_party/blink/renderer/bindings/idl_in_modules.gni +++ b/third_party/blink/renderer/bindings/idl_in_modules.gni @@ -4,6 +4,10 @@ import("//third_party/blink/renderer/config.gni") +if (is_cobalt) { + import("//starboard/build/buildflags.gni") +} + # Statically-defined (not build-time-generated) IDL files in 'modules' component # for production. static_idl_files_in_modules = get_path_info( @@ -1202,6 +1206,15 @@ static_idl_files_in_modules = get_path_info( ], "abspath") +if (is_cobalt) { + static_idl_files_in_modules += get_path_info( + [ + "//third_party/blink/renderer/modules/cobalt/crash_annotator/crash_annotator.idl", + "//third_party/blink/renderer/modules/cobalt/crash_annotator/navigator_crash_annotator.idl", + ], + "abspath") +} + # Direct Sockets # This uses target_os rather than current_os (which is what is_android is set # from) for the case of generating the v8 context snapshot for android. When @@ -1279,6 +1292,15 @@ if (target_os != "android") { "abspath") } +# SourceBufferWriteHead +# An extension to the SourceBuffer interface that allows web apps to check the +# highest presentation timestamp written to the Renderer. +if (is_cobalt && use_starboard_media) { + static_idl_files_in_modules += get_path_info( + [ "//third_party/blink/renderer/modules/mediasource/source_buffer_write_head.idl" ], + "abspath") +} + # Statically-defined (not runtime-generated) IDL files in 'modules' component. # These IDL definitions are used only for testing. static_idl_files_in_modules_for_testing = get_path_info( diff --git a/third_party/blink/renderer/core/html/media/html_media_element.cc b/third_party/blink/renderer/core/html/media/html_media_element.cc index 0ecba68e421f..e565c5c81d77 100644 --- a/third_party/blink/renderer/core/html/media/html_media_element.cc +++ b/third_party/blink/renderer/core/html/media/html_media_element.cc @@ -124,6 +124,7 @@ // For BUILDFLAG(USE_STARBOARD_MEDIA) #include "build/build_config.h" #if BUILDFLAG(USE_STARBOARD_MEDIA) +#include "base/strings/string_util.h" #include "starboard/media.h" #endif // BUILDFLAG(USE_STARBOARD_MEDIA) @@ -408,7 +409,8 @@ std::ostream& operator<<(std::ostream& stream, #if BUILDFLAG(USE_STARBOARD_MEDIA) // Checks for progressive formats served by the YouTube H5 player. // These formats have a mime type of "video/mp4", and lists both audio and -// video codecs under the "codecs" parameter. +// video codecs under the "codecs" parameter. This is not a comprehensive +// check and may not detect all progressive formats. bool IsProgressiveFormat(const ContentType& content_type) { const String type = content_type.GetType(); const String codecs = content_type.Parameter("codecs"); @@ -418,7 +420,7 @@ bool IsProgressiveFormat(const ContentType& content_type) { } Vector split_codecs; - const String separator(", "); + const String separator(","); codecs.Split(separator, split_codecs); return type.Utf8() == "video/mp4" && split_codecs.size() == 2; } diff --git a/third_party/blink/renderer/core/html/media/html_media_element_test.cc b/third_party/blink/renderer/core/html/media/html_media_element_test.cc index 81841cfae1d3..c3439a87a486 100644 --- a/third_party/blink/renderer/core/html/media/html_media_element_test.cc +++ b/third_party/blink/renderer/core/html/media/html_media_element_test.cc @@ -1578,6 +1578,8 @@ TEST_P(HTMLMediaElementTest, CanFreezeWithMediaPlayerAttached) { TEST(HTMLMediaElementTest, CanHandleCobaltProgressiveSupportQueries) { const ContentType progressive_type( "video/mp4; codecs=\"avc1.42001E, mp4a.40.2\""); + const ContentType progressive_type_missing_whitespace( + "video/mp4; codecs=\"avc1.42001E,mp4a.40.2\""); const ContentType adaptive_video_type( "video/mp4; codecs=\"avc1.4d4015\"; framerate=30"); const ContentType adaptive_audio_type( @@ -1590,6 +1592,11 @@ TEST(HTMLMediaElementTest, CanHandleCobaltProgressiveSupportQueries) { // disabled. EXPECT_EQ(HTMLMediaElement::GetSupportsType(progressive_type), MIMETypeRegistry::kNotSupported); + // Reject progressive content types when the "codecs" parameter lacks + // whitespace. + EXPECT_EQ( + HTMLMediaElement::GetSupportsType(progressive_type_missing_whitespace), + MIMETypeRegistry::kNotSupported); // Continue to support adaptive content types. EXPECT_NE(HTMLMediaElement::GetSupportsType(adaptive_video_type), MIMETypeRegistry::kNotSupported); @@ -1603,6 +1610,11 @@ TEST(HTMLMediaElementTest, CanHandleCobaltProgressiveSupportQueries) { // enabled. EXPECT_NE(HTMLMediaElement::GetSupportsType(progressive_type), MIMETypeRegistry::kNotSupported); + // Continue to accept progressive content types when the "codecs" parameter + // lacks whitespace. + EXPECT_NE( + HTMLMediaElement::GetSupportsType(progressive_type_missing_whitespace), + MIMETypeRegistry::kNotSupported); // Continue to support adaptive content types. EXPECT_NE(HTMLMediaElement::GetSupportsType(adaptive_video_type), MIMETypeRegistry::kNotSupported); diff --git a/third_party/blink/renderer/modules/BUILD.gn b/third_party/blink/renderer/modules/BUILD.gn index 855d33552a2d..19a3b5f5ab47 100644 --- a/third_party/blink/renderer/modules/BUILD.gn +++ b/third_party/blink/renderer/modules/BUILD.gn @@ -167,6 +167,10 @@ component("modules") { "//third_party/blink/renderer/modules/xr", ] + if (is_cobalt) { + sub_modules += [ "//third_party/blink/renderer/modules/cobalt/crash_annotator" ] + } + # This uses target_os rather than current_os (which is what is_android is set # from) for the case of generating the v8 context snapshot for android. When # generating the snapshot for android, blink is compiled with diff --git a/third_party/blink/renderer/modules/cobalt/crash_annotator/BUILD.gn b/third_party/blink/renderer/modules/cobalt/crash_annotator/BUILD.gn new file mode 100644 index 000000000000..cb5b0e61e73f --- /dev/null +++ b/third_party/blink/renderer/modules/cobalt/crash_annotator/BUILD.gn @@ -0,0 +1,22 @@ +# 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. + +import("//third_party/blink/renderer/modules/modules.gni") + +blink_modules_sources("crash_annotator") { + sources = [ + "crash_annotator.cc", + "crash_annotator.h", + ] +} diff --git a/third_party/blink/renderer/modules/cobalt/crash_annotator/crash_annotator.cc b/third_party/blink/renderer/modules/cobalt/crash_annotator/crash_annotator.cc new file mode 100644 index 000000000000..4485eadbe71a --- /dev/null +++ b/third_party/blink/renderer/modules/cobalt/crash_annotator/crash_annotator.cc @@ -0,0 +1,92 @@ +// 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 "third_party/blink/renderer/modules/cobalt/crash_annotator/crash_annotator.h" + +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/remote.h" +#include "third_party/blink/public/mojom/cobalt/crash_annotator/crash_annotator.mojom-blink.h" +#include "third_party/blink/renderer/bindings/core/v8/script_promise.h" +#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" +#include "third_party/blink/renderer/core/execution_context/execution_context.h" +#include "third_party/blink/renderer/core/execution_context/navigator_base.h" +#include "third_party/blink/renderer/platform/bindings/exception_state.h" +#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" + +namespace blink { + +// static +const char CrashAnnotator::kSupplementName[] = "CrashAnnotator"; + +// static +CrashAnnotator* CrashAnnotator::crashAnnotator(NavigatorBase& navigator) { + CrashAnnotator* crash_annotator = + Supplement::From(navigator); + if (!crash_annotator && navigator.GetExecutionContext()) { + crash_annotator = MakeGarbageCollected(navigator); + ProvideTo(navigator, crash_annotator); + } + return crash_annotator; +} + +CrashAnnotator::CrashAnnotator(NavigatorBase& navigator) + : Supplement(navigator), + ExecutionContextLifecycleObserver(navigator.GetExecutionContext()), + crash_annotator_(navigator.GetExecutionContext()) {} + +void CrashAnnotator::ContextDestroyed() {} + +ScriptPromise CrashAnnotator::setString(ScriptState* script_state, + const String& key, + const String& value, + ExceptionState& exception_state) { + auto* resolver = MakeGarbageCollected( + script_state, exception_state.GetContext()); + + EnsureReceiverIsBound(); + + crash_annotator_->SetString(key, + value, + WTF::BindOnce( + &CrashAnnotator::OnSetString, + WrapPersistent(this), WrapPersistent(resolver))); + + return resolver->Promise(); +} + +void CrashAnnotator::OnSetString(ScriptPromiseResolver* resolver, bool result) { + resolver->Resolve(result); +} + +void CrashAnnotator::EnsureReceiverIsBound() { + DCHECK(GetExecutionContext()); + + if (crash_annotator_.is_bound()) { + return; + } + + auto task_runner = + GetExecutionContext()->GetTaskRunner(TaskType::kMiscPlatformAPI); + GetExecutionContext()->GetBrowserInterfaceBroker().GetInterface( + crash_annotator_.BindNewPipeAndPassReceiver(task_runner)); +} + +void CrashAnnotator::Trace(Visitor* visitor) const { + visitor->Trace(crash_annotator_); + Supplement::Trace(visitor); + ExecutionContextLifecycleObserver::Trace(visitor); + ScriptWrappable::Trace(visitor); +} + +} // namespace blink diff --git a/third_party/blink/renderer/modules/cobalt/crash_annotator/crash_annotator.h b/third_party/blink/renderer/modules/cobalt/crash_annotator/crash_annotator.h new file mode 100644 index 000000000000..1ea37ac1e1a0 --- /dev/null +++ b/third_party/blink/renderer/modules/cobalt/crash_annotator/crash_annotator.h @@ -0,0 +1,66 @@ +// 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 THIRD_PARTY_BLINK_RENDERER_MODULES_COBALT_CRASH_ANNOTATOR_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_COBALT_CRASH_ANNOTATOR_H_ + +#include "third_party/blink/public/mojom/cobalt/crash_annotator/crash_annotator.mojom-blink.h" +#include "third_party/blink/renderer/bindings/core/v8/script_promise.h" +#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h" +#include "third_party/blink/renderer/modules/modules_export.h" +#include "third_party/blink/renderer/platform/bindings/script_wrappable.h" +#include "third_party/blink/renderer/platform/mojo/heap_mojo_receiver.h" +#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h" +#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h" + +namespace blink { + +class ExecutionContext; +class NavigatorBase; +class ScriptPromiseResolver; +class ScriptState; + +class MODULES_EXPORT CrashAnnotator final + : public ScriptWrappable, + public Supplement, + public ExecutionContextLifecycleObserver { + DEFINE_WRAPPERTYPEINFO(); + + public: + static const char kSupplementName[]; + + // For navigator.crashAnnotator + static CrashAnnotator* crashAnnotator(NavigatorBase&); + + explicit CrashAnnotator(NavigatorBase&); + + void ContextDestroyed() override; + + ScriptPromise setString(ScriptState*, + const String& key, + const String& value, + ExceptionState&); + + void Trace(Visitor*) const override; + + private: + void OnSetString(ScriptPromiseResolver*, bool); + void EnsureReceiverIsBound(); + + HeapMojoRemote crash_annotator_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_COBALT_CRASH_ANNOTATOR_H_ diff --git a/third_party/blink/renderer/modules/cobalt/crash_annotator/crash_annotator.idl b/third_party/blink/renderer/modules/cobalt/crash_annotator/crash_annotator.idl new file mode 100644 index 000000000000..9f8596e5456d --- /dev/null +++ b/third_party/blink/renderer/modules/cobalt/crash_annotator/crash_annotator.idl @@ -0,0 +1,24 @@ +// 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. + +// Allows (key, value) pairs to be added to uploaded crash reports as context. +[ + Exposed=Window, + SecureContext +] +interface CrashAnnotator { + // Returns a promise of true on success and false on failure. + [CallWith=ScriptState, RaisesException] + Promise setString(DOMString key, DOMString value); +}; diff --git a/starboard/shared/starboard/decode_target/decode_target_internal.cc b/third_party/blink/renderer/modules/cobalt/crash_annotator/navigator_crash_annotator.idl similarity index 76% rename from starboard/shared/starboard/decode_target/decode_target_internal.cc rename to third_party/blink/renderer/modules/cobalt/crash_annotator/navigator_crash_annotator.idl index 29c40807efed..737ff89f910a 100644 --- a/starboard/shared/starboard/decode_target/decode_target_internal.cc +++ b/third_party/blink/renderer/modules/cobalt/crash_annotator/navigator_crash_annotator.idl @@ -12,8 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "starboard/shared/starboard/decode_target/decode_target_internal.h" - -SbDecodeTargetPrivate::SbDecodeTargetPrivate() = default; - -SbDecodeTargetPrivate::~SbDecodeTargetPrivate() = default; +// Extends the navigator interface. +[ + ImplementedAs=CrashAnnotator, + SecureContext +] partial interface Navigator { + [SameObject] readonly attribute CrashAnnotator crashAnnotator; +}; diff --git a/third_party/blink/renderer/modules/mediasource/BUILD.gn b/third_party/blink/renderer/modules/mediasource/BUILD.gn index a14bb0a20c07..0d8b68a606f5 100644 --- a/third_party/blink/renderer/modules/mediasource/BUILD.gn +++ b/third_party/blink/renderer/modules/mediasource/BUILD.gn @@ -56,8 +56,10 @@ blink_modules_sources("mediasource") { "//third_party/blink/renderer/modules/webcodecs:webcodecs", ] if (is_cobalt && use_starboard_media) { - deps += [ - "//starboard($starboard_toolchain)", + sources += [ + "source_buffer_write_head.cc", + "source_buffer_write_head.h", ] + deps += [ "//starboard($starboard_toolchain)" ] } } diff --git a/third_party/blink/renderer/modules/mediasource/source_buffer.cc b/third_party/blink/renderer/modules/mediasource/source_buffer.cc index 42a23253da5b..5cdd7a0ac68c 100644 --- a/third_party/blink/renderer/modules/mediasource/source_buffer.cc +++ b/third_party/blink/renderer/modules/mediasource/source_buffer.cc @@ -475,6 +475,20 @@ VideoTrackList& SourceBuffer::videoTracks() { return *video_tracks_; } +#if BUILDFLAG(USE_STARBOARD_MEDIA) +double SourceBuffer::GetWriteHead(ExceptionState& exception_state) const { + if (source_ == NULL) { + MediaSource::LogAndThrowDOMException( + exception_state, DOMExceptionCode::kInvalidStateError, + "Cannot obtain SourceBuffer write head with an invalid MediaSource"); + return 0.0; + } + + DCHECK(web_source_buffer_); + return web_source_buffer_->GetWriteHead(exception_state); +} +#endif // BUILDFLAG(USE_STARBOARD_MEDIA) + double SourceBuffer::appendWindowStart() const { return append_window_start_; } diff --git a/third_party/blink/renderer/modules/mediasource/source_buffer.h b/third_party/blink/renderer/modules/mediasource/source_buffer.h index 0178bf1a8e66..0ac28dca70f0 100644 --- a/third_party/blink/renderer/modules/mediasource/source_buffer.h +++ b/third_party/blink/renderer/modules/mediasource/source_buffer.h @@ -113,6 +113,12 @@ class SourceBuffer final : public EventTargetWithInlineData, AudioTrackList& audioTracks(); VideoTrackList& videoTracks(); +#if BUILDFLAG(USE_STARBOARD_MEDIA) + // Cobalt-specific method that returns the highest presentation + // timestamp written to the Renderer. + double GetWriteHead(ExceptionState& exception_state) const; +#endif // BUILDFLAG(USE_STARBOARD_MEDIA) + // "_Locked" requires these be called while in the scope of callback of // |source_|'s attachment's RunExclusively(). Other methods without "_Locked" // may also require the same, since they can be called from within these diff --git a/third_party/blink/renderer/modules/mediasource/source_buffer_write_head.cc b/third_party/blink/renderer/modules/mediasource/source_buffer_write_head.cc new file mode 100644 index 000000000000..578ba3a42e0c --- /dev/null +++ b/third_party/blink/renderer/modules/mediasource/source_buffer_write_head.cc @@ -0,0 +1,31 @@ +// 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 "third_party/blink/renderer/modules/mediasource/source_buffer_write_head.h" + +#include "third_party/blink/renderer/modules/mediasource/source_buffer.h" +#include "third_party/blink/renderer/platform/bindings/exception_state.h" + +#if !BUILDFLAG(USE_STARBOARD_MEDIA) +#error "This file only works with Starboard media" +#endif // !BUILDFLAG(USE_STARBOARD_MEDIA) + +namespace blink { + +// static +double SourceBufferWriteHead::writeHead(SourceBuffer& source_buffer, + ExceptionState& exception_state) { + return source_buffer.GetWriteHead(exception_state); +} +} // namespace blink diff --git a/third_party/blink/renderer/modules/mediasource/source_buffer_write_head.h b/third_party/blink/renderer/modules/mediasource/source_buffer_write_head.h new file mode 100644 index 000000000000..e5a52110d793 --- /dev/null +++ b/third_party/blink/renderer/modules/mediasource/source_buffer_write_head.h @@ -0,0 +1,39 @@ +// 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 THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASOURCE_SOURCE_BUFFER_WRITE_HEAD_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASOURCE_SOURCE_BUFFER_WRITE_HEAD_H_ + +#include "build/build_config.h" +#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" + +#if !BUILDFLAG(USE_STARBOARD_MEDIA) +#error "This file only works with Starboard media" +#endif // !BUILDFLAG(USE_STARBOARD_MEDIA) + +namespace blink { + +class ExceptionState; +class SourceBuffer; + +class SourceBufferWriteHead { + STATIC_ONLY(SourceBufferWriteHead); + + public: + static double writeHead(SourceBuffer&, ExceptionState&); +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASOURCE_SOURCE_BUFFER_WRITE_HEAD_H_ diff --git a/third_party/blink/renderer/modules/mediasource/source_buffer_write_head.idl b/third_party/blink/renderer/modules/mediasource/source_buffer_write_head.idl new file mode 100644 index 000000000000..8ff5c972d000 --- /dev/null +++ b/third_party/blink/renderer/modules/mediasource/source_buffer_write_head.idl @@ -0,0 +1,24 @@ +// 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. + +// Non standard interface used for Cobalt only. +// Returns the highest presentation timestamp written to the Renderer; +// raises `InvalidStateError` if the SourceBuffer object has been removed +// from the MediaSource object. + +[ + ImplementedAs=SourceBufferWriteHead +] partial interface SourceBuffer { + [RaisesException] readonly attribute double writeHead; +}; \ No newline at end of file diff --git a/third_party/blink/renderer/platform/media/web_source_buffer_impl.cc b/third_party/blink/renderer/platform/media/web_source_buffer_impl.cc index a040298abd08..a3eb88f63b34 100644 --- a/third_party/blink/renderer/platform/media/web_source_buffer_impl.cc +++ b/third_party/blink/renderer/platform/media/web_source_buffer_impl.cc @@ -245,6 +245,14 @@ void WebSourceBufferImpl::RemovedFromMediaSource() { client_ = nullptr; } +#if BUILDFLAG(USE_STARBOARD_MEDIA) +double WebSourceBufferImpl::GetWriteHead( + ExceptionState& exception_state) const { + DCHECK(demuxer_); + return demuxer_->GetWriteHead(id_).InSecondsF(); +} +#endif // BUILDFLAG(USE_STARBOARD_MEDIA) + WebMediaPlayer::TrackType mediaTrackTypeToBlink(media::MediaTrack::Type type) { switch (type) { case media::MediaTrack::Audio: diff --git a/third_party/blink/renderer/platform/media/web_source_buffer_impl.h b/third_party/blink/renderer/platform/media/web_source_buffer_impl.h index 5ecfab637271..25c272f8d1f5 100644 --- a/third_party/blink/renderer/platform/media/web_source_buffer_impl.h +++ b/third_party/blink/renderer/platform/media/web_source_buffer_impl.h @@ -24,6 +24,10 @@ enum class SourceBufferParseWarning; namespace blink { +#if BUILDFLAG(USE_STARBOARD_MEDIA) +class ExceptionState; +#endif // BUILDFLAG(USE_STARBOARD_MEDIA) + class PLATFORM_EXPORT WebSourceBufferImpl : public WebSourceBuffer { public: WebSourceBufferImpl(const std::string& id, media::ChunkDemuxer* demuxer); @@ -57,6 +61,11 @@ class PLATFORM_EXPORT WebSourceBufferImpl : public WebSourceBuffer { void SetAppendWindowEnd(double end) override; void RemovedFromMediaSource() override; +#if BUILDFLAG(USE_STARBOARD_MEDIA) + // Return the highest presentation timestamp written to the Renderer. + double GetWriteHead(ExceptionState& exception_state) const override; +#endif // BUILDFLAG(USE_STARBOARD_MEDIA) + private: // Demuxer callback handler to process an initialization segment received // during an append() call. diff --git a/third_party/blink/renderer/platform/widget/compositing/layer_tree_settings.cc b/third_party/blink/renderer/platform/widget/compositing/layer_tree_settings.cc index 3ebaee0026af..0a0888ceb3de 100644 --- a/third_party/blink/renderer/platform/widget/compositing/layer_tree_settings.cc +++ b/third_party/blink/renderer/platform/widget/compositing/layer_tree_settings.cc @@ -105,71 +105,16 @@ cc::ManagedMemoryPolicy GetGpuMemoryPolicy( } #if BUILDFLAG(IS_ANDROID) - // We can't query available GPU memory from the system on Android. - // Physical memory is also mis-reported sometimes (eg. Nexus 10 reports - // 1262MB when it actually has 2GB, while Razr M has 1GB but only reports - // 128MB java heap size). First we estimate physical memory using both. - size_t dalvik_mb = base::SysInfo::DalvikHeapSizeMB(); - size_t physical_mb = base::SysInfo::AmountOfPhysicalMemoryMB(); - size_t physical_memory_mb = 0; - if (base::SysInfo::IsLowEndDevice()) { - // TODO(crbug.com/742534): The code below appears to no longer work. - // |dalvik_mb| no longer follows the expected heuristic pattern, causing us - // to over-estimate memory on low-end devices. This entire section probably - // needs to be re-written, but for now we can address the low-end Android - // issues by ignoring |dalvik_mb|. - physical_memory_mb = physical_mb; - } else if (dalvik_mb >= 256) { - physical_memory_mb = dalvik_mb * 4; + if (base::SysInfo::IsLowEndDevice() || + base::SysInfo::AmountOfPhysicalMemoryMB() < 2000) { + actual.bytes_limit_when_visible = 96 * 1024 * 1024; } else { - physical_memory_mb = std::max(dalvik_mb * 4, (physical_mb * 4) / 3); + actual.bytes_limit_when_visible = 256 * 1024 * 1024; } - - // Now we take a default of 1/8th of memory on high-memory devices, - // and gradually scale that back for low-memory devices (to be nicer - // to other apps so they don't get killed). Examples: - // Nexus 4/10(2GB) 256MB (normally 128MB) - // Droid Razr M(1GB) 114MB (normally 57MB) - // Galaxy Nexus(1GB) 100MB (normally 50MB) - // Xoom(1GB) 100MB (normally 50MB) - // Nexus S(low-end) 8MB (normally 8MB) - // Note that the compositor now uses only some of this memory for - // pre-painting and uses the rest only for 'emergencies'. - if (actual.bytes_limit_when_visible == 0) { - // NOTE: Non-low-end devices use only 50% of these limits, - // except during 'emergencies' where 100% can be used. - if (physical_memory_mb >= 1536) { - actual.bytes_limit_when_visible = physical_memory_mb / 8; // >192MB - } else if (physical_memory_mb >= 1152) { - actual.bytes_limit_when_visible = physical_memory_mb / 8; // >144MB - } else if (physical_memory_mb >= 768) { - actual.bytes_limit_when_visible = physical_memory_mb / 10; // >76MB - } else if (physical_memory_mb >= 513) { - actual.bytes_limit_when_visible = physical_memory_mb / 12; // <64MB - } else { - // Devices with this little RAM have very little headroom so we hardcode - // the limit rather than relying on the heuristics above. (They also use - // 4444 textures so we can use a lower limit.) - actual.bytes_limit_when_visible = 8; - } - - actual.bytes_limit_when_visible = - actual.bytes_limit_when_visible * 1024 * 1024; - // Clamp the observed value to a specific range on Android. - actual.bytes_limit_when_visible = std::max( - actual.bytes_limit_when_visible, static_cast(8 * 1024 * 1024)); - actual.bytes_limit_when_visible = - std::min(actual.bytes_limit_when_visible, - static_cast(256 * 1024 * 1024)); - } - actual.priority_cutoff_when_visible = - gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING; #else // Ignore what the system said and give all clients the same maximum // allocation on desktop platforms. actual.bytes_limit_when_visible = 512 * 1024 * 1024; - actual.priority_cutoff_when_visible = - gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE; // For large monitors (4k), double the tile memory to avoid frequent out of // memory problems. 4k could mean a screen width of anywhere from 3840 to 4096 @@ -181,6 +126,9 @@ cc::ManagedMemoryPolicy GetGpuMemoryPolicy( if (display_width >= kLargeDisplayThreshold) actual.bytes_limit_when_visible *= 2; #endif + actual.priority_cutoff_when_visible = + gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE; + return actual; } diff --git a/third_party/blink/web_tests/external/wpt/cobalt/crash-annotator/README.md b/third_party/blink/web_tests/external/wpt/cobalt/crash-annotator/README.md new file mode 100644 index 000000000000..cd1c51ca4972 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/cobalt/crash-annotator/README.md @@ -0,0 +1,6 @@ +# Web tests for CrashAnnotator + +These automated tests rely on a test-only interface that must be provided by the +browser under test. The pattern from the Serial API is followed: an +implementation of the CrashAnnotator Mojo interface is provided by +`../../resources/chromium/cobalt/fake-crash-annotator.js`. diff --git a/third_party/blink/web_tests/external/wpt/cobalt/crash-annotator/crash_annotator_setString.https.any.js b/third_party/blink/web_tests/external/wpt/cobalt/crash-annotator/crash_annotator_setString.https.any.js new file mode 100644 index 000000000000..21fba8cdd5ae --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/cobalt/crash-annotator/crash_annotator_setString.https.any.js @@ -0,0 +1,18 @@ +// META: global=window +// META: script=/resources/test-only-api.js +// META: script=resources/automation.js + +crash_annotator_test(async (t, fake) => { + let expectedSetStringResult = true; + fake.stubResult(expectedSetStringResult); + let setStringResult = + await navigator.crashAnnotator.setString("some key", "some val"); + assert_equals(setStringResult, expectedSetStringResult); +}, 'setString() returns value provided by browser endpoint'); + +crash_annotator_test(async (t, fake) => { + let key = "some key"; + let value = "some value"; + await navigator.crashAnnotator.setString(key, value); + assert_equals(fake.getAnnotation(key), value); +}, 'setString() sends expected key and value to browser endpoint'); diff --git a/third_party/blink/web_tests/external/wpt/cobalt/crash-annotator/resources/automation.js b/third_party/blink/web_tests/external/wpt/cobalt/crash-annotator/resources/automation.js new file mode 100644 index 000000000000..c630f663ca58 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/cobalt/crash-annotator/resources/automation.js @@ -0,0 +1,26 @@ +'use strict'; + +// These tests use a fake implementation of the CrashAnnotator Mojo interface. + +let fakeCrashAnnotator = undefined; + +function crash_annotator_test(func, name, properties) { + promise_test(async (test) => { + assert_implements(navigator.crashAnnotator, + 'missing navigator.crashAnnotator'); + if (fakeCrashAnnotator === undefined) { + const fakes = + await import('/resources/chromium/cobalt/fake-crash-annotator.js'); + fakeCrashAnnotator = fakes.fakeCrashAnnotator; + } + assert_implements(fakeCrashAnnotator, 'missing fakeCrashAnnotator'); + + fakeCrashAnnotator.start(); + try { + await func(test, fakeCrashAnnotator); + } finally { + fakeCrashAnnotator.stop(); + fakeCrashAnnotator.reset(); + } + }, name, properties); + } diff --git a/third_party/blink/web_tests/external/wpt/media-source/SourceBuffer-writeHead.html b/third_party/blink/web_tests/external/wpt/media-source/SourceBuffer-writeHead.html new file mode 100644 index 000000000000..56b93e84c945 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/media-source/SourceBuffer-writeHead.html @@ -0,0 +1,102 @@ + + + + + SourceBuffer.writeHead test cases + + + + + + +

+ + + + diff --git a/third_party/blink/web_tests/external/wpt/resources/chromium/cobalt/fake-crash-annotator.js b/third_party/blink/web_tests/external/wpt/resources/chromium/cobalt/fake-crash-annotator.js new file mode 100644 index 000000000000..484bcb57bf36 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resources/chromium/cobalt/fake-crash-annotator.js @@ -0,0 +1,50 @@ +import {CrashAnnotator, CrashAnnotatorReceiver} from '/gen/third_party/blink/public/mojom/cobalt/crash_annotator/crash_annotator.mojom.m.js'; + +// Implementation of blink.mojom.CrashAnnotator. +class FakeCrashAnnotator { + constructor() { + this.interceptor_ = + new MojoInterfaceInterceptor(CrashAnnotator.$interfaceName); + this.interceptor_.oninterfacerequest = e => this.bind(e.handle); + this.receiver_ = new CrashAnnotatorReceiver(this); + this.stub_result_ = null; + this.annotations_ = new Map(); + } + + start() { + this.interceptor_.start(); + } + + stop() { + this.interceptor_.stop(); + } + + reset() { + this.stub_result_ = null; + this.annotations_ = new Map(); + } + + async setString(key, value) { + this.annotations_.set(key, value); + return { + result: this.stub_result_ + }; + } + + // Added for stubbing setString() result in tests. + stubResult(stub_result) { + this.stub_result_ = stub_result; + } + + // Added for testing setString() interactions. + getAnnotation(key) { + return this.annotations_.get(key); + } + + bind(handle) { + this.receiver_.$.bindHandle(handle); + } + +} + +export const fakeCrashAnnotator = new FakeCrashAnnotator();