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. 4 5 #include "content/browser/android/child_process_launcher_android.h" 6 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/media/android/browser_media_player_manager.h" 12 #include "content/browser/renderer_host/compositor_impl_android.h" 13 #include "content/browser/renderer_host/render_view_host_impl.h" 14 #include "content/public/browser/browser_thread.h" 15 #include "content/public/browser/render_process_host.h" 16 #include "content/public/common/content_switches.h" 17 #include "jni/ChildProcessLauncher_jni.h" 18 #include "media/base/android/media_player_android.h" 19 #include "ui/gl/android/scoped_java_surface.h" 20 21 using base::android::AttachCurrentThread; 22 using base::android::ToJavaArrayOfStrings; 23 using base::android::ScopedJavaGlobalRef; 24 using base::android::ScopedJavaLocalRef; 25 using content::StartChildProcessCallback; 26 27 namespace content { 28 29 namespace { 30 31 // Pass a java surface object to the MediaPlayerAndroid object 32 // identified by render process handle, render view ID and player ID. 33 static void SetSurfacePeer( 34 const base::android::JavaRef<jobject>& surface, 35 base::ProcessHandle render_process_handle, 36 int render_view_id, 37 int player_id) { 38 int renderer_id = 0; 39 RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator(); 40 while (!it.IsAtEnd()) { 41 if (it.GetCurrentValue()->GetHandle() == render_process_handle) { 42 renderer_id = it.GetCurrentValue()->GetID(); 43 break; 44 } 45 it.Advance(); 46 } 47 48 if (renderer_id) { 49 RenderViewHostImpl* host = RenderViewHostImpl::FromID( 50 renderer_id, render_view_id); 51 if (host) { 52 media::MediaPlayerAndroid* player = 53 host->media_player_manager()->GetPlayer(player_id); 54 if (player && 55 player != host->media_player_manager()->GetFullscreenPlayer()) { 56 gfx::ScopedJavaSurface scoped_surface(surface); 57 player->SetVideoSurface(scoped_surface.Pass()); 58 } 59 } 60 } 61 } 62 63 } // anonymous namespace 64 65 // Called from ChildProcessLauncher.java when the ChildProcess was 66 // started. 67 // |client_context| is the pointer to StartChildProcessCallback which was 68 // passed in from StartChildProcess. 69 // |handle| is the processID of the child process as originated in Java, 0 if 70 // the ChildProcess could not be created. 71 static void OnChildProcessStarted(JNIEnv*, 72 jclass, 73 jlong client_context, 74 jint handle) { 75 StartChildProcessCallback* callback = 76 reinterpret_cast<StartChildProcessCallback*>(client_context); 77 if (handle) 78 callback->Run(static_cast<base::ProcessHandle>(handle)); 79 delete callback; 80 } 81 82 void StartChildProcess( 83 const CommandLine::StringVector& argv, 84 const std::vector<content::FileDescriptorInfo>& files_to_register, 85 const StartChildProcessCallback& callback) { 86 JNIEnv* env = AttachCurrentThread(); 87 DCHECK(env); 88 89 // Create the Command line String[] 90 ScopedJavaLocalRef<jobjectArray> j_argv = ToJavaArrayOfStrings(env, argv); 91 92 size_t file_count = files_to_register.size(); 93 DCHECK(file_count > 0); 94 95 ScopedJavaLocalRef<jintArray> j_file_ids(env, env->NewIntArray(file_count)); 96 base::android::CheckException(env); 97 jint* file_ids = env->GetIntArrayElements(j_file_ids.obj(), NULL); 98 base::android::CheckException(env); 99 ScopedJavaLocalRef<jintArray> j_file_fds(env, env->NewIntArray(file_count)); 100 base::android::CheckException(env); 101 jint* file_fds = env->GetIntArrayElements(j_file_fds.obj(), NULL); 102 base::android::CheckException(env); 103 ScopedJavaLocalRef<jbooleanArray> j_file_auto_close( 104 env, env->NewBooleanArray(file_count)); 105 base::android::CheckException(env); 106 jboolean* file_auto_close = 107 env->GetBooleanArrayElements(j_file_auto_close.obj(), NULL); 108 base::android::CheckException(env); 109 for (size_t i = 0; i < file_count; ++i) { 110 const content::FileDescriptorInfo& fd_info = files_to_register[i]; 111 file_ids[i] = fd_info.id; 112 file_fds[i] = fd_info.fd.fd; 113 file_auto_close[i] = fd_info.fd.auto_close; 114 } 115 env->ReleaseIntArrayElements(j_file_ids.obj(), file_ids, 0); 116 env->ReleaseIntArrayElements(j_file_fds.obj(), file_fds, 0); 117 env->ReleaseBooleanArrayElements(j_file_auto_close.obj(), file_auto_close, 0); 118 119 Java_ChildProcessLauncher_start(env, 120 base::android::GetApplicationContext(), 121 j_argv.obj(), 122 j_file_ids.obj(), 123 j_file_fds.obj(), 124 j_file_auto_close.obj(), 125 reinterpret_cast<intptr_t>(new StartChildProcessCallback(callback))); 126 } 127 128 void StopChildProcess(base::ProcessHandle handle) { 129 JNIEnv* env = AttachCurrentThread(); 130 DCHECK(env); 131 Java_ChildProcessLauncher_stop(env, static_cast<jint>(handle)); 132 } 133 134 bool IsChildProcessOomProtected(base::ProcessHandle handle) { 135 JNIEnv* env = AttachCurrentThread(); 136 DCHECK(env); 137 return Java_ChildProcessLauncher_isOomProtected(env, 138 static_cast<jint>(handle)); 139 } 140 141 void EstablishSurfacePeer( 142 JNIEnv* env, jclass clazz, 143 jint pid, jobject surface, jint primary_id, jint secondary_id) { 144 ScopedJavaGlobalRef<jobject> jsurface; 145 jsurface.Reset(env, surface); 146 if (jsurface.is_null()) 147 return; 148 149 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI)); 150 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( 151 &SetSurfacePeer, jsurface, pid, primary_id, secondary_id)); 152 } 153 154 jobject GetViewSurface(JNIEnv* env, jclass clazz, jint surface_id) { 155 // This is a synchronous call from the GPU process and is expected to be 156 // handled on a binder thread. Handling this on the UI thread will lead 157 // to deadlocks. 158 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI)); 159 return CompositorImpl::GetSurface(surface_id); 160 } 161 162 jboolean IsSingleProcess(JNIEnv* env, jclass clazz) { 163 return CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess); 164 } 165 166 bool RegisterChildProcessLauncher(JNIEnv* env) { 167 return RegisterNativesImpl(env); 168 } 169 170 } // namespace content 171