OLD | NEW |
---|---|
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.content.app; | 5 package org.chromium.content.app; |
6 | 6 |
7 import android.app.Service; | |
8 import android.content.Context; | 7 import android.content.Context; |
9 import android.content.Intent; | 8 import android.content.Intent; |
10 import android.graphics.SurfaceTexture; | 9 import android.graphics.SurfaceTexture; |
11 import android.os.Bundle; | 10 import android.os.Bundle; |
12 import android.os.IBinder; | 11 import android.os.IBinder; |
13 import android.os.Parcelable; | 12 import android.os.Parcelable; |
14 import android.os.Process; | 13 import android.os.Process; |
15 import android.os.RemoteException; | 14 import android.os.RemoteException; |
16 import android.view.Surface; | 15 import android.view.Surface; |
17 | 16 |
18 import org.chromium.base.BaseSwitches; | 17 import org.chromium.base.BaseSwitches; |
19 import org.chromium.base.CommandLine; | 18 import org.chromium.base.CommandLine; |
20 import org.chromium.base.ContextUtils; | 19 import org.chromium.base.ContextUtils; |
21 import org.chromium.base.Log; | 20 import org.chromium.base.Log; |
22 import org.chromium.base.annotations.CalledByNative; | 21 import org.chromium.base.annotations.CalledByNative; |
23 import org.chromium.base.annotations.JNINamespace; | 22 import org.chromium.base.annotations.JNINamespace; |
24 import org.chromium.base.annotations.SuppressFBWarnings; | 23 import org.chromium.base.annotations.SuppressFBWarnings; |
25 import org.chromium.base.library_loader.LibraryLoader; | 24 import org.chromium.base.library_loader.LibraryLoader; |
26 import org.chromium.base.library_loader.Linker; | 25 import org.chromium.base.library_loader.Linker; |
27 import org.chromium.base.library_loader.ProcessInitException; | 26 import org.chromium.base.library_loader.ProcessInitException; |
28 import org.chromium.content.browser.ChildProcessConstants; | 27 import org.chromium.content.browser.ChildProcessConstants; |
29 import org.chromium.content.browser.ChildProcessCreationParams; | 28 import org.chromium.content.browser.ChildProcessCreationParams; |
30 import org.chromium.content.browser.ChildProcessLauncher; | |
31 import org.chromium.content.browser.FileDescriptorInfo; | 29 import org.chromium.content.browser.FileDescriptorInfo; |
32 import org.chromium.content.common.ContentSwitches; | 30 import org.chromium.content.common.ContentSwitches; |
33 import org.chromium.content.common.IChildProcessCallback; | 31 import org.chromium.content.common.IChildProcessCallback; |
34 import org.chromium.content.common.IChildProcessService; | 32 import org.chromium.content.common.IChildProcessService; |
35 import org.chromium.content.common.SurfaceWrapper; | 33 import org.chromium.content.common.SurfaceWrapper; |
36 | 34 |
37 import java.util.concurrent.Semaphore; | 35 import java.util.concurrent.Semaphore; |
38 import java.util.concurrent.atomic.AtomicReference; | 36 import java.util.concurrent.atomic.AtomicReference; |
39 | 37 |
40 /** | 38 /** |
41 * This is the base class for child services; the [Non]SandboxedProcessService0, 1.. etc | 39 * This class provides all the implementations for {@link ChildProcessService} w hich owns an |
42 * subclasses provide the concrete service entry points, to enable the browser t o connect | 40 * object of {@link ChildProcessServiceImpl}. |
43 * to more than one distinct process (i.e. one process per service number, up to limit of N). | 41 * It makes possible that WebAPK's ChildProcessService owns a ChildProcessServic eImpl object |
44 * The embedding application must declare these service instances in the applica tion section | 42 * and uses the same functionalities to create renderer process for WebAPKs when "--enable-webapk" |
45 * of its AndroidManifest.xml, for example with N entries of the form:- | 43 * flag is turned on. |
46 * <service android:name="org.chromium.content.app.[Non]SandboxedProcessServ iceX" | |
47 * android:process=":[non]sandboxed_processX" /> | |
48 * for X in 0...N-1 (where N is {@link ChildProcessLauncher#MAX_REGISTERED_SERVI CES}) | |
49 */ | 44 */ |
50 @JNINamespace("content") | 45 @JNINamespace("content") |
51 @SuppressWarnings("SynchronizeOnNonFinalField") | 46 @SuppressWarnings("SynchronizeOnNonFinalField") |
52 public class ChildProcessService extends Service { | 47 public class ChildProcessServiceImpl { |
53 private static final String MAIN_THREAD_NAME = "ChildProcessMain"; | 48 private static final String MAIN_THREAD_NAME = "ChildProcessMain"; |
54 private static final String TAG = "ChildProcessService"; | 49 private static final String TAG = "ChildProcessService"; |
55 protected static final FileDescriptorInfo[] EMPTY_FILE_DESCRIPTOR_INFO = {}; | 50 protected static final FileDescriptorInfo[] EMPTY_FILE_DESCRIPTOR_INFO = {}; |
56 private IChildProcessCallback mCallback; | 51 private IChildProcessCallback mCallback; |
57 | 52 |
58 // This is the native "Main" thread for the renderer / utility process. | 53 // This is the native "Main" thread for the renderer / utility process. |
59 private Thread mMainThread; | 54 private Thread mMainThread; |
60 // Parameters received via IPC, only accessed while holding the mMainThread monitor. | 55 // Parameters received via IPC, only accessed while holding the mMainThread monitor. |
61 private String[] mCommandLineParams; | 56 private String[] mCommandLineParams; |
62 private int mCpuCount; | 57 private int mCpuCount; |
63 private long mCpuFeatures; | 58 private long mCpuFeatures; |
64 // File descriptors that should be registered natively. | 59 // File descriptors that should be registered natively. |
65 private FileDescriptorInfo[] mFdInfos; | 60 private FileDescriptorInfo[] mFdInfos; |
66 // Linker-specific parameters for this child process service. | 61 // Linker-specific parameters for this child process service. |
67 private ChromiumLinkerParams mLinkerParams; | 62 private ChromiumLinkerParams mLinkerParams; |
68 // Child library process type. | 63 // Child library process type. |
69 private int mLibraryProcessType; | 64 private int mLibraryProcessType; |
70 | 65 |
71 private static AtomicReference<Context> sContext = new AtomicReference<Conte xt>(null); | 66 private static AtomicReference<Context> sContext = new AtomicReference<Conte xt>(null); |
72 private boolean mLibraryInitialized = false; | 67 private boolean mLibraryInitialized = false; |
73 // Becomes true once the service is bound. Access must synchronize around mM ainThread. | 68 // Becomes true once the service is bound. Access must synchronize around mM ainThread. |
74 private boolean mIsBound = false; | 69 private boolean mIsBound = false; |
75 | 70 |
76 private final Semaphore mActivitySemaphore = new Semaphore(1); | 71 private final Semaphore mActivitySemaphore = new Semaphore(1); |
72 private final IChildProcessService.Stub mBinder; | |
73 private ClassLoader mClassLoader; | |
77 | 74 |
78 // Return a Linker instance. If testing, the Linker needs special setup. | 75 // Return a Linker instance. If testing, the Linker needs special setup. |
79 private Linker getLinker() { | 76 private Linker getLinker() { |
80 if (Linker.areTestsEnabled()) { | 77 if (Linker.areTestsEnabled()) { |
81 // For testing, set the Linker implementation and the test runner | 78 // For testing, set the Linker implementation and the test runner |
82 // class name to match those used by the parent. | 79 // class name to match those used by the parent. |
83 assert mLinkerParams != null; | 80 assert mLinkerParams != null; |
84 Linker.setupForTesting( | 81 Linker.setupForTesting( |
85 mLinkerParams.mLinkerImplementationForTesting, | 82 mLinkerParams.mLinkerImplementationForTesting, |
86 mLinkerParams.mTestRunnerClassNameForTesting); | 83 mLinkerParams.mTestRunnerClassNameForTesting); |
87 } | 84 } |
88 return Linker.getInstance(); | 85 return Linker.getInstance(); |
89 } | 86 } |
90 | 87 |
91 // Binder object used by clients for this service. | |
pkotwicz
2016/06/10 21:29:48
Why this change? I tried reverting this change and
Xi Han
2016/06/13 20:04:11
Good catch. I made this changes before introducing
| |
92 private final IChildProcessService.Stub mBinder = new IChildProcessService.S tub() { | |
93 // NOTE: Implement any IChildProcessService methods here. | |
94 @Override | |
95 public int setupConnection(Bundle args, IChildProcessCallback callback) { | |
96 mCallback = callback; | |
97 getServiceInfo(args); | |
98 return Process.myPid(); | |
99 } | |
100 | |
101 @Override | |
102 public void crashIntentionallyForTesting() { | |
103 Process.killProcess(Process.myPid()); | |
104 } | |
105 }; | |
106 | |
107 /* package */ static Context getContext() { | 88 /* package */ static Context getContext() { |
108 return sContext.get(); | 89 return sContext.get(); |
109 } | 90 } |
110 | 91 |
111 @Override | 92 public ChildProcessServiceImpl() { |
112 public void onCreate() { | 93 super(); |
94 mBinder = new IChildProcessService.Stub() { | |
95 // NOTE: Implement any IChildProcessService methods here. | |
96 @Override | |
97 public int setupConnection(Bundle args, IChildProcessCallback callba ck) { | |
98 mCallback = callback; | |
99 getServiceInfo(args); | |
100 return Process.myPid(); | |
101 } | |
102 | |
103 @Override | |
104 public void crashIntentionallyForTesting() { | |
105 Process.killProcess(Process.myPid()); | |
106 } | |
107 }; | |
108 } | |
109 | |
pkotwicz
2016/06/10 21:29:48
📚 Please document this method.
Xi Han
2016/06/13 20:04:11
Done.
| |
110 public void create(final Context context, final Context hostBrowserContext, | |
111 ClassLoader classLoader) { | |
112 //Debug.waitForDebugger(); | |
pkotwicz
2016/06/10 21:29:47
😁
Xi Han
2016/06/13 20:04:11
Missed this, removed.
| |
113 Log.i(TAG, "Creating new ChildProcessService pid=%d", Process.myPid()); | 113 Log.i(TAG, "Creating new ChildProcessService pid=%d", Process.myPid()); |
114 if (sContext.get() != null) { | 114 if (sContext.get() != null) { |
115 throw new RuntimeException("Illegal child process reuse."); | 115 throw new RuntimeException("Illegal child process reuse."); |
116 } | 116 } |
117 sContext.set(this); | 117 sContext.set(context); |
118 super.onCreate(); | |
119 | 118 |
120 ContextUtils.initApplicationContext(getApplicationContext()); | 119 ContextUtils.initApplicationContext(context); |
120 mClassLoader = classLoader; | |
pkotwicz
2016/06/10 21:29:48
Nit: initialize |mClassLoader| at the top of the m
Xi Han
2016/06/13 20:04:11
Done.
| |
121 final ChildProcessServiceImpl instance = this; | |
pkotwicz
2016/06/10 21:29:47
Remove line 121. You can use ChildProcessServiceIm
Xi Han
2016/06/13 20:04:11
Good to know, thanks!
| |
121 | 122 |
122 mMainThread = new Thread(new Runnable() { | 123 mMainThread = new Thread(new Runnable() { |
123 @Override | 124 @Override |
124 @SuppressFBWarnings("DM_EXIT") | 125 @SuppressFBWarnings("DM_EXIT") |
125 public void run() { | 126 public void run() { |
126 try { | 127 try { |
127 // CommandLine must be initialized before everything else. | 128 // CommandLine must be initialized before everything else. |
128 synchronized (mMainThread) { | 129 synchronized (mMainThread) { |
129 while (mCommandLineParams == null) { | 130 while (mCommandLineParams == null) { |
130 mMainThread.wait(); | 131 mMainThread.wait(); |
(...skipping 18 matching lines...) Expand all Loading... | |
149 } | 150 } |
150 } | 151 } |
151 boolean isLoaded = false; | 152 boolean isLoaded = false; |
152 if (CommandLine.getInstance().hasSwitch( | 153 if (CommandLine.getInstance().hasSwitch( |
153 BaseSwitches.RENDERER_WAIT_FOR_JAVA_DEBUGGER)) { | 154 BaseSwitches.RENDERER_WAIT_FOR_JAVA_DEBUGGER)) { |
154 android.os.Debug.waitForDebugger(); | 155 android.os.Debug.waitForDebugger(); |
155 } | 156 } |
156 | 157 |
157 boolean loadAtFixedAddressFailed = false; | 158 boolean loadAtFixedAddressFailed = false; |
158 try { | 159 try { |
159 LibraryLoader.get(mLibraryProcessType).loadNow(getApplic ationContext()); | 160 LibraryLoader.get(mLibraryProcessType).loadNow(hostBrows erContext); |
160 isLoaded = true; | 161 isLoaded = true; |
161 } catch (ProcessInitException e) { | 162 } catch (ProcessInitException e) { |
162 if (requestedSharedRelro) { | 163 if (requestedSharedRelro) { |
163 Log.w(TAG, "Failed to load native library with share d RELRO, " | 164 Log.w(TAG, "Failed to load native library with share d RELRO, " |
164 + "retrying without"); | 165 + "retrying without"); |
165 loadAtFixedAddressFailed = true; | 166 loadAtFixedAddressFailed = true; |
166 } else { | 167 } else { |
167 Log.e(TAG, "Failed to load native library", e); | 168 Log.e(TAG, "Failed to load native library", e); |
168 } | 169 } |
169 } | 170 } |
170 if (!isLoaded && requestedSharedRelro) { | 171 if (!isLoaded && requestedSharedRelro) { |
171 linker.disableSharedRelros(); | 172 linker.disableSharedRelros(); |
172 try { | 173 try { |
173 LibraryLoader.get(mLibraryProcessType).loadNow(getAp plicationContext()); | 174 LibraryLoader.get(mLibraryProcessType).loadNow(conte xt); |
174 isLoaded = true; | 175 isLoaded = true; |
175 } catch (ProcessInitException e) { | 176 } catch (ProcessInitException e) { |
176 Log.e(TAG, "Failed to load native library on retry", e); | 177 Log.e(TAG, "Failed to load native library on retry", e); |
177 } | 178 } |
178 } | 179 } |
179 if (!isLoaded) { | 180 if (!isLoaded) { |
180 System.exit(-1); | 181 System.exit(-1); |
181 } | 182 } |
182 LibraryLoader.get(mLibraryProcessType) | 183 LibraryLoader.get(mLibraryProcessType) |
183 .registerRendererProcessHistogram(requestedSharedRel ro, | 184 .registerRendererProcessHistogram(requestedSharedRel ro, |
184 loadAtFixedAddressFailed); | 185 loadAtFixedAddressFailed); |
185 LibraryLoader.get(mLibraryProcessType).initialize(); | 186 LibraryLoader.get(mLibraryProcessType).initialize(); |
186 synchronized (mMainThread) { | 187 synchronized (mMainThread) { |
187 mLibraryInitialized = true; | 188 mLibraryInitialized = true; |
188 mMainThread.notifyAll(); | 189 mMainThread.notifyAll(); |
189 while (mFdInfos == null) { | 190 while (mFdInfos == null) { |
190 mMainThread.wait(); | 191 mMainThread.wait(); |
191 } | 192 } |
192 } | 193 } |
193 for (FileDescriptorInfo fdInfo : mFdInfos) { | 194 for (FileDescriptorInfo fdInfo : mFdInfos) { |
194 nativeRegisterGlobalFileDescriptor( | 195 nativeRegisterGlobalFileDescriptor( |
195 fdInfo.mId, fdInfo.mFd.detachFd(), fdInfo.mOffse t, fdInfo.mSize); | 196 fdInfo.mId, fdInfo.mFd.detachFd(), fdInfo.mOffse t, fdInfo.mSize); |
196 } | 197 } |
197 nativeInitChildProcess(ChildProcessService.this, mCpuCount, mCpuFeatures); | 198 nativeInitChildProcessImpl(instance, mCpuCount, mCpuFeatures ); |
198 if (mActivitySemaphore.tryAcquire()) { | 199 if (mActivitySemaphore.tryAcquire()) { |
199 ContentMain.start(); | 200 ContentMain.start(); |
200 nativeExitChildProcess(); | 201 nativeExitChildProcess(); |
201 } | 202 } |
202 } catch (InterruptedException e) { | 203 } catch (InterruptedException e) { |
203 Log.w(TAG, "%s startup failed: %s", MAIN_THREAD_NAME, e); | 204 Log.w(TAG, "%s startup failed: %s", MAIN_THREAD_NAME, e); |
204 } catch (ProcessInitException e) { | 205 } catch (ProcessInitException e) { |
205 Log.w(TAG, "%s startup failed: %s", MAIN_THREAD_NAME, e); | 206 Log.w(TAG, "%s startup failed: %s", MAIN_THREAD_NAME, e); |
206 } | 207 } |
207 } | 208 } |
208 }, MAIN_THREAD_NAME); | 209 }, MAIN_THREAD_NAME); |
209 mMainThread.start(); | 210 mMainThread.start(); |
211 Log.d(TAG, "mMainThread is started: %s", mMainThread.getName()); | |
pkotwicz
2016/06/10 21:29:47
Log.i() to match the remainder of the file?
Xi Han
2016/06/13 20:04:11
Sorry, it was debugging log, removed.
| |
210 } | 212 } |
211 | 213 |
212 @Override | |
213 @SuppressFBWarnings("DM_EXIT") | 214 @SuppressFBWarnings("DM_EXIT") |
214 public void onDestroy() { | 215 public void destroy() { |
215 Log.i(TAG, "Destroying ChildProcessService pid=%d", Process.myPid()); | 216 Log.i(TAG, "Destroying ChildProcessService pid=%d", Process.myPid()); |
216 super.onDestroy(); | |
217 if (mActivitySemaphore.tryAcquire()) { | 217 if (mActivitySemaphore.tryAcquire()) { |
218 // TODO(crbug.com/457406): This is a bit hacky, but there is no know n better solution | 218 // TODO(crbug.com/457406): This is a bit hacky, but there is no know n better solution |
219 // as this service will get reused (at least if not sandboxed). | 219 // as this service will get reused (at least if not sandboxed). |
220 // In fact, we might really want to always exit() from onDestroy(), not just from | 220 // In fact, we might really want to always exit() from onDestroy(), not just from |
221 // the early return here. | 221 // the early return here. |
222 System.exit(0); | 222 System.exit(0); |
223 return; | 223 return; |
224 } | 224 } |
225 synchronized (mMainThread) { | 225 synchronized (mMainThread) { |
226 try { | 226 try { |
227 while (!mLibraryInitialized) { | 227 while (!mLibraryInitialized) { |
228 // Avoid a potential race in calling through to native code before the library | 228 // Avoid a potential race in calling through to native code before the library |
229 // has loaded. | 229 // has loaded. |
230 mMainThread.wait(); | 230 mMainThread.wait(); |
231 } | 231 } |
232 } catch (InterruptedException e) { | 232 } catch (InterruptedException e) { |
233 // Ignore | 233 // Ignore |
234 } | 234 } |
235 } | 235 } |
236 // Try to shutdown the MainThread gracefully, but it might not | 236 // Try to shutdown the MainThread gracefully, but it might not |
237 // have chance to exit normally. | 237 // have chance to exit normally. |
238 nativeShutdownMainThread(); | 238 nativeShutdownMainThread(); |
239 } | 239 } |
240 | 240 |
241 @Override | 241 public IBinder bind(Intent intent) { |
242 public IBinder onBind(Intent intent) { | |
243 // We call stopSelf() to request that this service be stopped as soon as the client | 242 // We call stopSelf() to request that this service be stopped as soon as the client |
244 // unbinds. Otherwise the system may keep it around and available for a reconnect. The | 243 // unbinds. Otherwise the system may keep it around and available for a reconnect. The |
245 // child processes do not currently support reconnect; they must be init ialized from | 244 // child processes do not currently support reconnect; they must be init ialized from |
246 // scratch every time. | 245 // scratch every time. |
pkotwicz
2016/06/10 21:29:47
Nit: Remove the comment w.r.t to stopSelf()
Xi Han
2016/06/13 20:04:11
Done.
| |
247 stopSelf(); | |
248 initializeParams(intent); | 246 initializeParams(intent); |
249 return mBinder; | 247 return mBinder; |
250 } | 248 } |
251 | 249 |
252 /** | 250 /** |
253 * Helper method to initialize the params from intent. | 251 * Helper method to initialize the params from intent. |
254 * @param intent Intent to launch the service. | 252 * @param intent Intent to launch the service. |
255 */ | 253 */ |
256 protected void initializeParams(Intent intent) { | 254 protected void initializeParams(Intent intent) { |
257 synchronized (mMainThread) { | 255 synchronized (mMainThread) { |
258 mCommandLineParams = | 256 mCommandLineParams = |
259 intent.getStringArrayExtra(ChildProcessConstants.EXTRA_COMMA ND_LINE); | 257 intent.getStringArrayExtra(ChildProcessConstants.EXTRA_COMMA ND_LINE); |
260 // mLinkerParams is never used if Linker.isUsed() returns false. | 258 // mLinkerParams is never used if Linker.isUsed() returns false. |
261 // See onCreate(). | 259 // See onCreate(). |
262 mLinkerParams = new ChromiumLinkerParams(intent); | 260 mLinkerParams = new ChromiumLinkerParams(intent); |
263 mLibraryProcessType = ChildProcessCreationParams.getLibraryProcessTy pe(intent); | 261 mLibraryProcessType = ChildProcessCreationParams.getLibraryProcessTy pe(intent); |
264 mIsBound = true; | 262 mIsBound = true; |
265 mMainThread.notifyAll(); | 263 mMainThread.notifyAll(); |
266 } | 264 } |
267 } | 265 } |
268 | 266 |
269 /** | 267 /** |
270 * Helper method to get the information about the service from a given bundl e. | 268 * Helper method to get the information about the service from a given bundl e. |
271 * @param bundle Bundle that contains the information to start the service. | 269 * @param bundle Bundle that contains the information to start the service. |
272 */ | 270 */ |
273 void getServiceInfo(Bundle bundle) { | 271 void getServiceInfo(Bundle bundle) { |
274 // Required to unparcel FileDescriptorInfo. | 272 // Required to unparcel FileDescriptorInfo. |
275 bundle.setClassLoader(getClassLoader()); | 273 bundle.setClassLoader(mClassLoader); |
276 synchronized (mMainThread) { | 274 synchronized (mMainThread) { |
277 // Allow the command line to be set via bind() intent or setupConnec tion, but | 275 // Allow the command line to be set via bind() intent or setupConnec tion, but |
278 // the FD can only be transferred here. | 276 // the FD can only be transferred here. |
279 if (mCommandLineParams == null) { | 277 if (mCommandLineParams == null) { |
280 mCommandLineParams = | 278 mCommandLineParams = |
281 bundle.getStringArray(ChildProcessConstants.EXTRA_COMMAN D_LINE); | 279 bundle.getStringArray(ChildProcessConstants.EXTRA_COMMAN D_LINE); |
282 } | 280 } |
283 // We must have received the command line by now | 281 // We must have received the command line by now |
284 assert mCommandLineParams != null; | 282 assert mCommandLineParams != null; |
285 mCpuCount = bundle.getInt(ChildProcessConstants.EXTRA_CPU_COUNT); | 283 mCpuCount = bundle.getInt(ChildProcessConstants.EXTRA_CPU_COUNT); |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
420 * This includes the IPC channel, the crash dump signals and resource relate d | 418 * This includes the IPC channel, the crash dump signals and resource relate d |
421 * files. | 419 * files. |
422 */ | 420 */ |
423 private static native void nativeRegisterGlobalFileDescriptor( | 421 private static native void nativeRegisterGlobalFileDescriptor( |
424 int id, int fd, long offset, long size); | 422 int id, int fd, long offset, long size); |
425 | 423 |
426 /** | 424 /** |
427 * The main entry point for a child process. This should be called from a ne w thread since | 425 * The main entry point for a child process. This should be called from a ne w thread since |
428 * it will not return until the child process exits. See child_process_servi ce.{h,cc} | 426 * it will not return until the child process exits. See child_process_servi ce.{h,cc} |
429 * | 427 * |
430 * @param service The current ChildProcessService object. | 428 * @param serviceImpl The current ChildProcessServiceImpl object. |
431 * renderer. | 429 * renderer. |
432 */ | 430 */ |
433 private static native void nativeInitChildProcess( | 431 private static native void nativeInitChildProcessImpl( |
434 ChildProcessService service, int cpuCount, long cpuFeatures); | 432 ChildProcessServiceImpl serviceImpl, int cpuCount, long cpuFeatures) ; |
435 | 433 |
436 /** | 434 /** |
437 * Force the child process to exit. | 435 * Force the child process to exit. |
438 */ | 436 */ |
439 private static native void nativeExitChildProcess(); | 437 private static native void nativeExitChildProcess(); |
440 | 438 |
441 private native void nativeShutdownMainThread(); | 439 private native void nativeShutdownMainThread(); |
442 } | 440 } |
OLD | NEW |