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/web_contents/web_contents_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/surface_texture.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 WebContentsImpl
* web_contents
=
63 static_cast<WebContentsImpl
*>(WebContents::FromRenderFrameHost(frame
));
64 BrowserMediaPlayerManager
* player_manager
=
65 web_contents
->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
*,
92 const JavaParamRef
<jclass
>&,
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 scoped_ptr
<content::FileDescriptorInfo
> files_to_register
,
106 const std::map
<int, base::MemoryMappedFile::Region
>& regions
,
107 const StartChildProcessCallback
& callback
) {
108 JNIEnv
* env
= AttachCurrentThread();
111 // Create the Command line String[]
112 ScopedJavaLocalRef
<jobjectArray
> j_argv
= ToJavaArrayOfStrings(env
, argv
);
114 size_t file_count
= files_to_register
->GetMappingSize();
115 DCHECK(file_count
> 0);
117 ScopedJavaLocalRef
<jclass
> j_file_info_class
= base::android::GetClass(
118 env
, "org/chromium/content/browser/FileDescriptorInfo");
119 ScopedJavaLocalRef
<jobjectArray
> j_file_infos(
120 env
, env
->NewObjectArray(file_count
, j_file_info_class
.obj(), NULL
));
121 base::android::CheckException(env
);
123 for (size_t i
= 0; i
< file_count
; ++i
) {
124 int fd
= files_to_register
->GetFDAt(i
);
126 int id
= files_to_register
->GetIDAt(i
);
127 bool auto_close
= files_to_register
->OwnsFD(fd
);
130 auto found_region_iter
= regions
.find(id
);
131 if (found_region_iter
!= regions
.end()) {
132 offset
= found_region_iter
->second
.offset
;
133 size
= found_region_iter
->second
.size
;
135 ScopedJavaLocalRef
<jobject
> j_file_info
=
136 Java_ChildProcessLauncher_makeFdInfo(env
, id
, fd
, auto_close
, offset
,
138 PCHECK(j_file_info
.obj());
139 env
->SetObjectArrayElement(j_file_infos
.obj(), i
, j_file_info
.obj());
141 ignore_result(files_to_register
->ReleaseFD(fd
).release());
145 Java_ChildProcessLauncher_start(
146 env
, base::android::GetApplicationContext(), j_argv
.obj(),
147 child_process_id
, j_file_infos
.obj(),
148 reinterpret_cast<intptr_t>(new StartChildProcessCallback(callback
)));
151 void StopChildProcess(base::ProcessHandle handle
) {
152 JNIEnv
* env
= AttachCurrentThread();
154 Java_ChildProcessLauncher_stop(env
, static_cast<jint
>(handle
));
157 bool IsChildProcessOomProtected(base::ProcessHandle handle
) {
158 JNIEnv
* env
= AttachCurrentThread();
160 return Java_ChildProcessLauncher_isOomProtected(env
,
161 static_cast<jint
>(handle
));
164 void SetChildProcessInForeground(base::ProcessHandle handle
,
165 bool in_foreground
) {
166 JNIEnv
* env
= AttachCurrentThread();
168 return Java_ChildProcessLauncher_setInForeground(env
,
169 static_cast<jint
>(handle
), static_cast<jboolean
>(in_foreground
));
172 void EstablishSurfacePeer(JNIEnv
* env
,
173 const JavaParamRef
<jclass
>& clazz
,
175 const JavaParamRef
<jobject
>& surface
,
178 ScopedJavaGlobalRef
<jobject
> jsurface
;
179 jsurface
.Reset(env
, surface
);
180 if (jsurface
.is_null())
183 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI
));
184 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
, base::Bind(
185 &SetSurfacePeer
, jsurface
, pid
, primary_id
, secondary_id
));
188 void RegisterViewSurface(int surface_id
, jobject j_surface
) {
189 JNIEnv
* env
= AttachCurrentThread();
191 Java_ChildProcessLauncher_registerViewSurface(env
, surface_id
, j_surface
);
194 void UnregisterViewSurface(int surface_id
) {
195 JNIEnv
* env
= AttachCurrentThread();
197 Java_ChildProcessLauncher_unregisterViewSurface(env
, surface_id
);
200 void CreateSurfaceTextureSurface(int surface_texture_id
,
202 gfx::SurfaceTexture
* surface_texture
) {
203 JNIEnv
* env
= AttachCurrentThread();
205 Java_ChildProcessLauncher_createSurfaceTextureSurface(
209 surface_texture
->j_surface_texture().obj());
212 void DestroySurfaceTextureSurface(int surface_texture_id
, int client_id
) {
213 JNIEnv
* env
= AttachCurrentThread();
215 Java_ChildProcessLauncher_destroySurfaceTextureSurface(
216 env
, surface_texture_id
, client_id
);
219 gfx::ScopedJavaSurface
GetSurfaceTextureSurface(int surface_texture_id
,
221 JNIEnv
* env
= AttachCurrentThread();
223 return gfx::ScopedJavaSurface::AcquireExternalSurface(
224 Java_ChildProcessLauncher_getSurfaceTextureSurface(
225 env
, surface_texture_id
, client_id
).obj());
228 jboolean
IsSingleProcess(JNIEnv
* env
, const JavaParamRef
<jclass
>& clazz
) {
229 return base::CommandLine::ForCurrentProcess()->HasSwitch(
230 switches::kSingleProcess
);
233 bool RegisterChildProcessLauncher(JNIEnv
* env
) {
234 return RegisterNativesImpl(env
);
237 } // namespace content