Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Final refactor of video_player_android before SurfaceProducer#setCallback. #6982

Merged
merged 8 commits into from
Jun 25, 2024

Conversation

matanlurey
Copy link
Contributor

@matanlurey matanlurey commented Jun 25, 2024

I'm working on re-landing #6456, this time without using the ActivityAware interface (see flutter/flutter#148417). As part of that work, I'll need to better control the ExoPlayer lifecycle and save/restore internal state.

Follows the patterns of some of the previous PRs, i.e.

The changes in this PR are mostly tests, it was extremely difficult to just add more tests to the already very leaky VideoPlayer abstraction which had lots of @VisibleForTesting methods and other "holes" to observe state. This PR removes all of that, and adds test coverage where it was missing.

Namely it:

  • Adds a new class, VideoAsset, that builds and configures the media that ExoPlayer uses.
  • Removes all "testing" state from VidePlayer, keeping it nearly immutable.
  • Added tests for most of the classes I've added since, which were mostly missing.

That being said, this is a large change. I'm happy to sit down with either of you and walk through it.


Opening as a draft for the moment, since there is a pubspec change needing I want to handle first.

@matanlurey matanlurey added the override: no versioning needed Override the check requiring version bumps for most changes label Jun 25, 2024
Copy link
Contributor

@camsim99 camsim99 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall! Left some questions and a nit.

abstract MediaSource.Factory getMediaSourceFactory(Context context);

/** Streaming formats that can be provided to the video player as a hint. */
enum StreamingFormat {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I think the enum values generally are all caps in Java

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! Done.

@@ -97,6 +97,7 @@ public void onError(@NonNull String code, @Nullable String message, @Nullable Ob
@Override
public void onIsPlayingStateUpdate(boolean isPlaying) {
Map<String, Object> event = new HashMap<>();
event.put("event", "isPlayingStateUpdate");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this event on top of isPlaying?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was actually a regression in a previous refactor, we just haven't made another release since they have been internal refactors only. In other words, all events contain an event key-value pair and I made a mistake!


@Test
public void remoteVideoByDefaultSetsUserAgentAndCrossProtocolRedirects() {
RemoteVideoAsset asset =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the tests constructing RemoteVideoAssets be using VideoAsset.fromRemoteUrl?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question. It's intentionally using this constructor so that we have access to the @VisibleForTesting method, but I think it could be made as or more clear by casting. Let me make that change and add a comment.

(Great suggestion btw, consistency is king)


assert mediaItem.localConfiguration != null;
assertEquals(mediaItem.localConfiguration.uri, Uri.parse("asset:///asset-key"));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think it's helpful to test that the type of asset. getMediaSourceFactory is what we expect?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because of the wrapping, I don't think it is possible.

"https://flutter.dev/video.mp4", VideoAsset.StreamingFormat.Unknown, headers);

DefaultHttpDataSource.Factory mockFactory = mockHttpFactory();
asset.getMediaSourceFactory(ApplicationProvider.getApplicationContext(), mockFactory);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think it'd be helpful to test the overridden behavior of getMediaSourceFactory for RemoteVideoAssets?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So in production, there is a single method, getMediaSourceFactory(Context), which always uses a new DefaultHttpDataSource.Factory (the same behavior before this patch).

For testing, we added a way to not call new DefaultHttpDataSource.Factory, as we'd otherwise we'd not be able to assert that the HTTP factory is configured as expected.

I suspect I could assert that the factory makes a real HTTP connection by default? I will leave a comment for the next person, and otherwise at least assert the returned object is real.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I see makes sense!

*
* <p>It's hypothetically possible to write better tests using {@link
* androidx.media3.test.utils.FakeMediaSource}, but you really need a PhD in the Android media APIs
* in order to figure out how to set everything up so the player "works".
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your disclaimers are the best lol!

Copy link
Contributor Author

@matanlurey matanlurey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the thoughtful review!

abstract MediaSource.Factory getMediaSourceFactory(Context context);

/** Streaming formats that can be provided to the video player as a hint. */
enum StreamingFormat {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! Done.


assert mediaItem.localConfiguration != null;
assertEquals(mediaItem.localConfiguration.uri, Uri.parse("asset:///asset-key"));
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because of the wrapping, I don't think it is possible.


@Test
public void remoteVideoByDefaultSetsUserAgentAndCrossProtocolRedirects() {
RemoteVideoAsset asset =
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question. It's intentionally using this constructor so that we have access to the @VisibleForTesting method, but I think it could be made as or more clear by casting. Let me make that change and add a comment.

(Great suggestion btw, consistency is king)

"https://flutter.dev/video.mp4", VideoAsset.StreamingFormat.Unknown, headers);

DefaultHttpDataSource.Factory mockFactory = mockHttpFactory();
asset.getMediaSourceFactory(ApplicationProvider.getApplicationContext(), mockFactory);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So in production, there is a single method, getMediaSourceFactory(Context), which always uses a new DefaultHttpDataSource.Factory (the same behavior before this patch).

For testing, we added a way to not call new DefaultHttpDataSource.Factory, as we'd otherwise we'd not be able to assert that the HTTP factory is configured as expected.

I suspect I could assert that the factory makes a real HTTP connection by default? I will leave a comment for the next person, and otherwise at least assert the returned object is real.

@matanlurey matanlurey added override: no changelog needed Override the check requiring CHANGELOG updates for most changes autosubmit Merge PR when tree becomes green via auto submit App and removed autosubmit Merge PR when tree becomes green via auto submit App labels Jun 25, 2024
Copy link
Member

@gmackall gmackall left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM


unstableUpdateDataSourceFactory(
httpDataSourceFactory, httpHeaders, userAgent, httpHeadersNotEmpty);
setUpVideoPlayer(exoPlayer);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not worth blocking anything but if you agree and want to change:

Seems a bit odd to me to do half the setup of exoPlayer out of setUpVideoPlayer and half of it in.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. This will change (for the better) in the next PR.

@matanlurey matanlurey added the autosubmit Merge PR when tree becomes green via auto submit App label Jun 25, 2024
@matanlurey matanlurey merged commit 1612774 into main Jun 25, 2024
74 checks passed
@matanlurey matanlurey deleted the video-player-android-further-refactor branch June 25, 2024 21:59
gabbopalma pushed a commit to gabbopalma/packages that referenced this pull request Jun 26, 2024
…allback`. (flutter#6982)

I'm working on re-landing flutter#6456,
this time without using the `ActivityAware` interface (see
flutter/flutter#148417). As part of that work,
I'll need to better control the `ExoPlayer` lifecycle and save/restore
internal state.

Follows the patterns of some of the previous PRs, i.e.

- flutter#6922
- flutter#6908

The changes in this PR are _mostly_ tests, it was extremely difficult to
just add more tests to the already very leaky `VideoPlayer` abstraction
which had lots of `@VisibleForTesting` methods and other "holes" to
observe state. This PR removes all of that, and adds test coverage where
it was missing.

Namely it:

- Adds a new class, `VideoAsset`, that builds and configures the media
that `ExoPlayer` uses.
- Removes all "testing" state from `VidePlayer`, keeping it nearly
immutable.
- Added tests for most of the classes I've added since, which were
mostly missing.

That being said, this is a large change. I'm happy to sit down with
either of you and walk through it.

---

Opening as a draft for the moment, since there is a pubspec change
needing I want to handle first.
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 26, 2024
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 26, 2024
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 27, 2024
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 27, 2024
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 27, 2024
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 28, 2024
auto-submit bot pushed a commit to flutter/flutter that referenced this pull request Jun 28, 2024
flutter/packages@03f5f6d...412ec46

2024-06-28 49699333+dependabot[bot]@users.noreply.github.com Bump github/codeql-action from 3.25.6 to 3.25.10 (flutter/packages#6924)
2024-06-27 ditman@gmail.com [video_player] Exposes VideoPlayerWebOptions. (flutter/packages#6990)
2024-06-27 ditman@gmail.com [ci] Add Wasm compilation to all_packages web app. (flutter/packages#6981)
2024-06-27 10687576+bparrishMines@users.noreply.github.com [interactive_media_ads] Updates `README` with a usage section and fix some interface docs (flutter/packages#6988)
2024-06-27 stuartmorgan@google.com [tools] Fix vm test requirement (flutter/packages#6995)
2024-06-27 jacksongardner@google.com Update `web_benchmarks` package to properly support wasm. (flutter/packages#6970)
2024-06-27 stuartmorgan@google.com [pigeon] Implement equals for Java data classes (flutter/packages#6992)
2024-06-25 matanlurey@users.noreply.github.com Final refactor of `video_player_android` before `SurfaceProducer#setCallback`. (flutter/packages#6982)
2024-06-25 stuartmorgan@google.com [pigeon] Update testing and docs (flutter/packages#6984)
2024-06-25 parlough@gmail.com [various] Update flutter.dev links to more reliable destinations (flutter/packages#6963)
2024-06-25 10687576+bparrishMines@users.noreply.github.com [interactive_media_ads] Adds initial Android implementation (flutter/packages#6733)
2024-06-25 engine-flutter-autoroll@skia.org Roll Flutter from 6c06abb to e726eb4 (51 revisions) (flutter/packages#6987)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages-flutter-autoroll
Please CC flutter-ecosystem@google.com,rmistry@google.com on the revert to ensure that a human
is aware of the problem.

To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
victorsanni pushed a commit to victorsanni/flutter that referenced this pull request Jul 8, 2024
flutter/packages@03f5f6d...412ec46

2024-06-28 49699333+dependabot[bot]@users.noreply.github.com Bump github/codeql-action from 3.25.6 to 3.25.10 (flutter/packages#6924)
2024-06-27 ditman@gmail.com [video_player] Exposes VideoPlayerWebOptions. (flutter/packages#6990)
2024-06-27 ditman@gmail.com [ci] Add Wasm compilation to all_packages web app. (flutter/packages#6981)
2024-06-27 10687576+bparrishMines@users.noreply.github.com [interactive_media_ads] Updates `README` with a usage section and fix some interface docs (flutter/packages#6988)
2024-06-27 stuartmorgan@google.com [tools] Fix vm test requirement (flutter/packages#6995)
2024-06-27 jacksongardner@google.com Update `web_benchmarks` package to properly support wasm. (flutter/packages#6970)
2024-06-27 stuartmorgan@google.com [pigeon] Implement equals for Java data classes (flutter/packages#6992)
2024-06-25 matanlurey@users.noreply.github.com Final refactor of `video_player_android` before `SurfaceProducer#setCallback`. (flutter/packages#6982)
2024-06-25 stuartmorgan@google.com [pigeon] Update testing and docs (flutter/packages#6984)
2024-06-25 parlough@gmail.com [various] Update flutter.dev links to more reliable destinations (flutter/packages#6963)
2024-06-25 10687576+bparrishMines@users.noreply.github.com [interactive_media_ads] Adds initial Android implementation (flutter/packages#6733)
2024-06-25 engine-flutter-autoroll@skia.org Roll Flutter from 6c06abb to e726eb4 (51 revisions) (flutter/packages#6987)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages-flutter-autoroll
Please CC flutter-ecosystem@google.com,rmistry@google.com on the revert to ensure that a human
is aware of the problem.

To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
autosubmit Merge PR when tree becomes green via auto submit App override: no changelog needed Override the check requiring CHANGELOG updates for most changes override: no versioning needed Override the check requiring version bumps for most changes p: video_player platform-android
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants