12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/app/android/child_process_service.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <android/native_window_jni.h>
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <cpu-features.h>
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/android/jni_array.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/android/library_loader/library_loader_hooks.h"
12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/android/memory_pressure_listener_android.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/posix/global_descriptors.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/child/child_thread.h"
164ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch#include "content/common/android/surface_texture_lookup.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/common/android/surface_texture_peer.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/common/gpu/gpu_surface_lookup.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/app/android_library_loader_hooks.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/content_descriptors.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ipc/ipc_descriptors.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "jni/ChildProcessService_jni.h"
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/gl/android/scoped_java_surface.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using base::android::AttachCurrentThread;
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using base::android::CheckException;
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using base::android::JavaIntArrayToIntVector;
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace content {
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
334ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdochclass SurfaceTexturePeerChildImpl : public SurfaceTexturePeer,
344ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch                                    public GpuSurfaceLookup,
354ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch                                    public SurfaceTextureLookup {
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // |service| is the instance of
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // org.chromium.content.app.ChildProcessService.
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit SurfaceTexturePeerChildImpl(
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const base::android::ScopedJavaLocalRef<jobject>& service)
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : service_(service) {
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GpuSurfaceLookup::InitInstance(this);
434ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    SurfaceTextureLookup::InitInstance(this);
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~SurfaceTexturePeerChildImpl() {
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GpuSurfaceLookup::InitInstance(NULL);
484ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    SurfaceTextureLookup::InitInstance(NULL);
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
514ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  // Overridden from SurfaceTexturePeer:
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void EstablishSurfaceTexturePeer(
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::ProcessHandle pid,
54424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      scoped_refptr<gfx::SurfaceTexture> surface_texture,
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int primary_id,
56a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      int secondary_id) OVERRIDE {
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    JNIEnv* env = base::android::AttachCurrentThread();
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    content::Java_ChildProcessService_establishSurfaceTexturePeer(
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        env, service_.obj(), pid,
60424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        surface_texture->j_surface_texture().obj(), primary_id,
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        secondary_id);
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CheckException(env);
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
654ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  // Overridden from GpuSurfaceLookup:
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual gfx::AcceleratedWidget AcquireNativeWidget(int surface_id) OVERRIDE {
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    JNIEnv* env = base::android::AttachCurrentThread();
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    gfx::ScopedJavaSurface surface(
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        content::Java_ChildProcessService_getViewSurface(
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        env, service_.obj(), surface_id));
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (surface.j_surface().is_null())
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return NULL;
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
75c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // Note: This ensures that any local references used by
76c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // ANativeWindow_fromSurface are released immediately. This is needed as a
77c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // workaround for https://code.google.com/p/android/issues/detail?id=68174
78c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    base::android::ScopedJavaLocalFrame scoped_local_reference_frame(env);
79c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ANativeWindow* native_window =
80c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        ANativeWindow_fromSurface(env, surface.j_surface().obj());
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return native_window;
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
854ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  // Overridden from SurfaceTextureLookup:
864ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  virtual gfx::AcceleratedWidget AcquireNativeWidget(int primary_id,
874ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch                                                     int secondary_id)
884ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      OVERRIDE {
894ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    JNIEnv* env = base::android::AttachCurrentThread();
904ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    gfx::ScopedJavaSurface surface(
914ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch        content::Java_ChildProcessService_getSurfaceTextureSurface(
924ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch            env, service_.obj(), primary_id, secondary_id));
934ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch
944ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    if (surface.j_surface().is_null())
954ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      return NULL;
964ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch
97c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // Note: This ensures that any local references used by
98c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // ANativeWindow_fromSurface are released immediately. This is needed as a
99c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // workaround for https://code.google.com/p/android/issues/detail?id=68174
100c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    base::android::ScopedJavaLocalFrame scoped_local_reference_frame(env);
1014ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    ANativeWindow* native_window =
1024ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch        ANativeWindow_fromSurface(env, surface.j_surface().obj());
1034ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch
1044ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    return native_window;
1054ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  }
1064ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The instance of org.chromium.content.app.ChildProcessService.
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::android::ScopedJavaGlobalRef<jobject> service_;
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SurfaceTexturePeerChildImpl);
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Chrome actually uses the renderer code path for all of its child
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// processes such as renderers, plugins, etc.
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void InternalInitChildProcess(const std::vector<int>& file_ids,
117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              const std::vector<int>& file_fds,
118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              JNIEnv* env,
119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              jclass clazz,
120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              jobject context,
121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              jobject service_in,
122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              jint cpu_count,
123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              jlong cpu_features) {
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::android::ScopedJavaLocalRef<jobject> service(env, service_in);
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Set the CPU properties.
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  android_setCpu(cpu_count, cpu_features);
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Register the file descriptors.
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This includes the IPC channel, the crash dump signals and resource related
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // files.
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(file_fds.size() == file_ids.size());
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < file_ids.size(); ++i)
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::GlobalDescriptors::GetInstance()->Set(file_ids[i], file_fds[i]);
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1354ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  // SurfaceTexturePeerChildImpl implements the SurfaceTextureLookup interface,
1364ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  // which need to be set before we create a compositor thread that could be
1374ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  // using it to initialize resources.
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::SurfaceTexturePeer::InitInstance(
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new SurfaceTexturePeerChildImpl(service));
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::android::MemoryPressureListenerAndroid::RegisterSystemCallback(env);
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace <anonymous>
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void InitChildProcess(JNIEnv* env,
147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                      jclass clazz,
148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                      jobject context,
149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                      jobject service,
150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                      jintArray j_file_ids,
151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                      jintArray j_file_fds,
152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                      jint cpu_count,
153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                      jlong cpu_features) {
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<int> file_ids;
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<int> file_fds;
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  JavaIntArrayToIntVector(env, j_file_ids, &file_ids);
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  JavaIntArrayToIntVector(env, j_file_fds, &file_fds);
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InternalInitChildProcess(
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      file_ids, file_fds, env, clazz, context, service,
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      cpu_count, cpu_features);
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExitChildProcess(JNIEnv* env, jclass clazz) {
165f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  VLOG(0) << "ChildProcessService: Exiting child process.";
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::android::LibraryLoaderExitHook();
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  _exit(0);
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool RegisterChildProcessService(JNIEnv* env) {
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return RegisterNativesImpl(env);
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ShutdownMainThread(JNIEnv* env, jobject obj) {
175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ChildThread::ShutdownThread();
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace content
179