1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/android/content_video_view.h"
7 #include "base/command_line.h"
8 #include "base/logging.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/metrics/histogram.h"
11 #include "content/browser/android/content_view_core_impl.h"
12 #include "content/browser/media/android/browser_media_player_manager.h"
13 #include "content/browser/power_save_blocker_impl.h"
14 #include "content/common/android/surface_texture_peer.h"
15 #include "content/public/browser/user_metrics.h"
16 #include "content/public/common/content_switches.h"
17 #include "jni/ContentVideoView_jni.h"
19 using base::android::AttachCurrentThread
;
20 using base::android::CheckException
;
21 using base::android::ScopedJavaGlobalRef
;
22 using base::UserMetricsAction
;
23 using content::RecordAction
;
28 // There can only be one content video view at a time, this holds onto that
29 // singleton instance.
30 ContentVideoView
* g_content_video_view
= NULL
;
34 static jobject
GetSingletonJavaContentVideoView(JNIEnv
*env
, jclass
) {
35 if (g_content_video_view
)
36 return g_content_video_view
->GetJavaObject(env
).Release();
41 bool ContentVideoView::RegisterContentVideoView(JNIEnv
* env
) {
42 return RegisterNativesImpl(env
);
45 ContentVideoView
* ContentVideoView::GetInstance() {
46 return g_content_video_view
;
49 ContentVideoView::ContentVideoView(
50 BrowserMediaPlayerManager
* manager
)
53 DCHECK(!g_content_video_view
);
54 j_content_video_view_
= CreateJavaObject();
55 g_content_video_view
= this;
58 ContentVideoView::~ContentVideoView() {
59 DCHECK(g_content_video_view
);
60 JNIEnv
* env
= AttachCurrentThread();
61 ScopedJavaLocalRef
<jobject
> content_video_view
= GetJavaObject(env
);
62 if (!content_video_view
.is_null()) {
63 Java_ContentVideoView_destroyContentVideoView(env
,
64 content_video_view
.obj(), true);
65 j_content_video_view_
.reset();
67 g_content_video_view
= NULL
;
70 void ContentVideoView::OpenVideo() {
71 JNIEnv
* env
= AttachCurrentThread();
72 ScopedJavaLocalRef
<jobject
> content_video_view
= GetJavaObject(env
);
73 if (!content_video_view
.is_null()) {
74 Java_ContentVideoView_openVideo(env
, content_video_view
.obj());
78 void ContentVideoView::OnMediaPlayerError(int error_type
) {
79 JNIEnv
* env
= AttachCurrentThread();
80 ScopedJavaLocalRef
<jobject
> content_video_view
= GetJavaObject(env
);
81 if (!content_video_view
.is_null()) {
82 Java_ContentVideoView_onMediaPlayerError(env
, content_video_view
.obj(),
87 void ContentVideoView::OnVideoSizeChanged(int width
, int height
) {
88 JNIEnv
* env
= AttachCurrentThread();
89 ScopedJavaLocalRef
<jobject
> content_video_view
= GetJavaObject(env
);
90 if (!content_video_view
.is_null()) {
91 Java_ContentVideoView_onVideoSizeChanged(env
, content_video_view
.obj(),
96 void ContentVideoView::OnBufferingUpdate(int percent
) {
97 JNIEnv
* env
= AttachCurrentThread();
98 ScopedJavaLocalRef
<jobject
> content_video_view
= GetJavaObject(env
);
99 if (!content_video_view
.is_null()) {
100 Java_ContentVideoView_onBufferingUpdate(env
, content_video_view
.obj(),
105 void ContentVideoView::OnPlaybackComplete() {
106 JNIEnv
* env
= AttachCurrentThread();
107 ScopedJavaLocalRef
<jobject
> content_video_view
= GetJavaObject(env
);
108 if (!content_video_view
.is_null()) {
109 Java_ContentVideoView_onPlaybackComplete(env
, content_video_view
.obj());
113 void ContentVideoView::OnExitFullscreen() {
114 JNIEnv
* env
= AttachCurrentThread();
115 ScopedJavaLocalRef
<jobject
> content_video_view
= GetJavaObject(env
);
116 if (!content_video_view
.is_null())
117 Java_ContentVideoView_onExitFullscreen(env
, content_video_view
.obj());
120 void ContentVideoView::RecordFullscreenPlayback(
121 JNIEnv
*, jobject
, bool is_portrait_video
, bool is_orientation_portrait
) {
122 UMA_HISTOGRAM_BOOLEAN("MobileFullscreenVideo.OrientationPortrait",
123 is_orientation_portrait
);
124 UMA_HISTOGRAM_BOOLEAN("MobileFullscreenVideo.VideoPortrait",
128 void ContentVideoView::RecordExitFullscreenPlayback(
129 JNIEnv
*, jobject
, bool is_portrait_video
,
130 long playback_duration_in_milliseconds_before_orientation_change
,
131 long playback_duration_in_milliseconds_after_orientation_change
) {
132 bool orientation_changed
= (
133 playback_duration_in_milliseconds_after_orientation_change
!= 0);
134 if (is_portrait_video
) {
135 UMA_HISTOGRAM_COUNTS(
136 "MobileFullscreenVideo.PortraitDuration",
137 playback_duration_in_milliseconds_before_orientation_change
);
138 UMA_HISTOGRAM_COUNTS(
139 "MobileFullscreenVideo.PortraitRotation", orientation_changed
);
140 if (orientation_changed
) {
141 UMA_HISTOGRAM_COUNTS(
142 "MobileFullscreenVideo.DurationAfterPotraitRotation",
143 playback_duration_in_milliseconds_after_orientation_change
);
146 UMA_HISTOGRAM_COUNTS(
147 "MobileFullscreenVideo.LandscapeDuration",
148 playback_duration_in_milliseconds_before_orientation_change
);
149 UMA_HISTOGRAM_COUNTS(
150 "MobileFullscreenVideo.LandscapeRotation", orientation_changed
);
154 void ContentVideoView::UpdateMediaMetadata() {
155 JNIEnv
* env
= AttachCurrentThread();
156 ScopedJavaLocalRef
<jobject
> content_video_view
= GetJavaObject(env
);
157 if (content_video_view
.is_null())
160 media::MediaPlayerAndroid
* player
= manager_
->GetFullscreenPlayer();
161 if (player
&& player
->IsPlayerReady()) {
162 Java_ContentVideoView_onUpdateMediaMetadata(
163 env
, content_video_view
.obj(), player
->GetVideoWidth(),
164 player
->GetVideoHeight(),
165 static_cast<int>(player
->GetDuration().InMilliseconds()),
166 player
->CanPause(),player
->CanSeekForward(), player
->CanSeekBackward());
170 bool ContentVideoView::IsPlaying(JNIEnv
*, jobject obj
) {
171 media::MediaPlayerAndroid
* player
= manager_
->GetFullscreenPlayer();
172 return player
? player
->IsPlaying() : false;
175 void ContentVideoView::ExitFullscreen(
176 JNIEnv
*, jobject
, jboolean release_media_player
) {
177 j_content_video_view_
.reset();
178 manager_
->ExitFullscreen(release_media_player
);
181 void ContentVideoView::SetSurface(JNIEnv
* env
, jobject obj
,
183 manager_
->SetVideoSurface(
184 gfx::ScopedJavaSurface::AcquireExternalSurface(surface
));
187 void ContentVideoView::RequestMediaMetadata(JNIEnv
* env
, jobject obj
) {
188 base::MessageLoop::current()->PostTask(
190 base::Bind(&ContentVideoView::UpdateMediaMetadata
,
191 weak_factory_
.GetWeakPtr()));
194 ScopedJavaLocalRef
<jobject
> ContentVideoView::GetJavaObject(JNIEnv
* env
) {
195 return j_content_video_view_
.get(env
);
198 JavaObjectWeakGlobalRef
ContentVideoView::CreateJavaObject() {
199 ContentViewCore
* content_view_core
= manager_
->GetContentViewCore();
200 JNIEnv
* env
= AttachCurrentThread();
201 return JavaObjectWeakGlobalRef(
203 Java_ContentVideoView_createContentVideoView(
205 content_view_core
->GetJavaObject().obj(),
206 reinterpret_cast<intptr_t>(this)).obj());
208 } // namespace content