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/child_process_launcher_android.h"
7 #include "base/android/jni_android.h"
8 #include "base/android/jni_array.h"
9 #include "base/logging.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "content/browser/frame_host/render_frame_host_impl.h"
12 #include "content/browser/media/android/browser_media_player_manager.h"
13 #include "content/browser/media/media_web_contents_observer.h"
14 #include "content/browser/renderer_host/compositor_impl_android.h"
15 #include "content/browser/renderer_host/render_view_host_impl.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/render_process_host.h"
18 #include "content/public/common/content_switches.h"
19 #include "jni/ChildProcessLauncher_jni.h"
20 #include "media/base/android/media_player_android.h"
21 #include "ui/gl/android/scoped_java_surface.h"
23 using base::android::AttachCurrentThread
;
24 using base::android::ToJavaArrayOfStrings
;
25 using base::android::ScopedJavaGlobalRef
;
26 using base::android::ScopedJavaLocalRef
;
27 using content::StartChildProcessCallback
;
33 // Pass a java surface object to the MediaPlayerAndroid object
34 // identified by render process handle, render frame ID and player ID.
35 static void SetSurfacePeer(
36 const base::android::JavaRef
<jobject
>& surface
,
37 base::ProcessHandle render_process_handle
,
40 int render_process_id
= 0;
41 RenderProcessHost::iterator it
= RenderProcessHost::AllHostsIterator();
42 while (!it
.IsAtEnd()) {
43 if (it
.GetCurrentValue()->GetHandle() == render_process_handle
) {
44 render_process_id
= it
.GetCurrentValue()->GetID();
49 if (!render_process_id
) {
50 DVLOG(1) << "Cannot find render process for render_process_handle "
51 << render_process_handle
;
55 RenderFrameHostImpl
* frame
=
56 RenderFrameHostImpl::FromID(render_process_id
, render_frame_id
);
58 DVLOG(1) << "Cannot find frame for render_frame_id " << render_frame_id
;
62 RenderViewHostImpl
* view
=
63 static_cast<RenderViewHostImpl
*>(frame
->GetRenderViewHost());
64 BrowserMediaPlayerManager
* player_manager
=
65 view
->media_web_contents_observer()->GetMediaPlayerManager(frame
);
66 if (!player_manager
) {
67 DVLOG(1) << "Cannot find the media player manager for frame " << frame
;
71 media::MediaPlayerAndroid
* player
= player_manager
->GetPlayer(player_id
);
73 DVLOG(1) << "Cannot find media player for player_id " << player_id
;
77 if (player
!= player_manager
->GetFullscreenPlayer()) {
78 gfx::ScopedJavaSurface
scoped_surface(surface
);
79 player
->SetVideoSurface(scoped_surface
.Pass());
83 } // anonymous namespace
85 // Called from ChildProcessLauncher.java when the ChildProcess was
87 // |client_context| is the pointer to StartChildProcessCallback which was
88 // passed in from StartChildProcess.
89 // |handle| is the processID of the child process as originated in Java, 0 if
90 // the ChildProcess could not be created.
91 static void OnChildProcessStarted(JNIEnv
*,
95 StartChildProcessCallback
* callback
=
96 reinterpret_cast<StartChildProcessCallback
*>(client_context
);
98 callback
->Run(static_cast<base::ProcessHandle
>(handle
));
102 void StartChildProcess(
103 const base::CommandLine::StringVector
& argv
,
104 int child_process_id
,
105 const std::vector
<content::FileDescriptorInfo
>& files_to_register
,
106 const StartChildProcessCallback
& callback
) {
107 JNIEnv
* env
= AttachCurrentThread();
110 // Create the Command line String[]
111 ScopedJavaLocalRef
<jobjectArray
> j_argv
= ToJavaArrayOfStrings(env
, argv
);
113 size_t file_count
= files_to_register
.size();
114 DCHECK(file_count
> 0);
116 ScopedJavaLocalRef
<jintArray
> j_file_ids(env
, env
->NewIntArray(file_count
));
117 base::android::CheckException(env
);
118 jint
* file_ids
= env
->GetIntArrayElements(j_file_ids
.obj(), NULL
);
119 base::android::CheckException(env
);
120 ScopedJavaLocalRef
<jintArray
> j_file_fds(env
, env
->NewIntArray(file_count
));
121 base::android::CheckException(env
);
122 jint
* file_fds
= env
->GetIntArrayElements(j_file_fds
.obj(), NULL
);
123 base::android::CheckException(env
);
124 ScopedJavaLocalRef
<jbooleanArray
> j_file_auto_close(
125 env
, env
->NewBooleanArray(file_count
));
126 base::android::CheckException(env
);
127 jboolean
* file_auto_close
=
128 env
->GetBooleanArrayElements(j_file_auto_close
.obj(), NULL
);
129 base::android::CheckException(env
);
130 for (size_t i
= 0; i
< file_count
; ++i
) {
131 const content::FileDescriptorInfo
& fd_info
= files_to_register
[i
];
132 file_ids
[i
] = fd_info
.id
;
133 file_fds
[i
] = fd_info
.fd
.fd
;
134 file_auto_close
[i
] = fd_info
.fd
.auto_close
;
136 env
->ReleaseIntArrayElements(j_file_ids
.obj(), file_ids
, 0);
137 env
->ReleaseIntArrayElements(j_file_fds
.obj(), file_fds
, 0);
138 env
->ReleaseBooleanArrayElements(j_file_auto_close
.obj(), file_auto_close
, 0);
140 Java_ChildProcessLauncher_start(env
,
141 base::android::GetApplicationContext(),
146 j_file_auto_close
.obj(),
147 reinterpret_cast<intptr_t>(new StartChildProcessCallback(callback
)));
150 void StopChildProcess(base::ProcessHandle handle
) {
151 JNIEnv
* env
= AttachCurrentThread();
153 Java_ChildProcessLauncher_stop(env
, static_cast<jint
>(handle
));
156 bool IsChildProcessOomProtected(base::ProcessHandle handle
) {
157 JNIEnv
* env
= AttachCurrentThread();
159 return Java_ChildProcessLauncher_isOomProtected(env
,
160 static_cast<jint
>(handle
));
163 void SetChildProcessInForeground(base::ProcessHandle handle
,
164 bool in_foreground
) {
165 JNIEnv
* env
= AttachCurrentThread();
167 return Java_ChildProcessLauncher_setInForeground(env
,
168 static_cast<jint
>(handle
), static_cast<jboolean
>(in_foreground
));
171 void EstablishSurfacePeer(
172 JNIEnv
* env
, jclass clazz
,
173 jint pid
, jobject surface
, jint primary_id
, jint secondary_id
) {
174 ScopedJavaGlobalRef
<jobject
> jsurface
;
175 jsurface
.Reset(env
, surface
);
176 if (jsurface
.is_null())
179 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI
));
180 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
, base::Bind(
181 &SetSurfacePeer
, jsurface
, pid
, primary_id
, secondary_id
));
184 void RegisterViewSurface(int surface_id
, jobject j_surface
) {
185 JNIEnv
* env
= AttachCurrentThread();
187 Java_ChildProcessLauncher_registerViewSurface(env
, surface_id
, j_surface
);
190 void UnregisterViewSurface(int surface_id
) {
191 JNIEnv
* env
= AttachCurrentThread();
193 Java_ChildProcessLauncher_unregisterViewSurface(env
, surface_id
);
196 void RegisterChildProcessSurfaceTexture(int surface_texture_id
,
197 int child_process_id
,
198 jobject j_surface_texture
) {
199 JNIEnv
* env
= AttachCurrentThread();
201 Java_ChildProcessLauncher_registerSurfaceTexture(
202 env
, surface_texture_id
, child_process_id
, j_surface_texture
);
205 void UnregisterChildProcessSurfaceTexture(int surface_texture_id
,
206 int child_process_id
) {
207 JNIEnv
* env
= AttachCurrentThread();
209 Java_ChildProcessLauncher_unregisterSurfaceTexture(
210 env
, surface_texture_id
, child_process_id
);
213 jboolean
IsSingleProcess(JNIEnv
* env
, jclass clazz
) {
214 return base::CommandLine::ForCurrentProcess()->HasSwitch(
215 switches::kSingleProcess
);
218 bool RegisterChildProcessLauncher(JNIEnv
* env
) {
219 return RegisterNativesImpl(env
);
222 } // namespace content