OLD | NEW |
---|---|
(Empty) | |
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 package org.chromium.content.app; | |
6 | |
7 import android.app.Service; | |
8 import android.content.Context; | |
9 import android.content.Intent; | |
10 import android.graphics.SurfaceTexture; | |
11 import android.os.Bundle; | |
12 import android.os.IBinder; | |
13 import android.os.ParcelFileDescriptor; | |
14 import android.os.Process; | |
15 import android.os.RemoteException; | |
16 import android.util.Log; | |
17 import android.view.Surface; | |
18 | |
19 import org.chromium.base.CalledByNative; | |
20 import org.chromium.content.app.ContentMain; | |
21 import org.chromium.content.browser.SandboxedProcessConnection; | |
22 import org.chromium.content.common.ISandboxedProcessCallback; | |
23 import org.chromium.content.common.ISandboxedProcessService; | |
24 import org.chromium.content.common.SurfaceCallback; | |
25 | |
26 /** | |
27 * This is the base class for sandboxed services; the SandboxedProcessService0, 1.. etc | |
28 * subclasses provide the concrete service entry points, to enable the browser t o connect | |
29 * to more than one distinct process (i.e. one process per service number, up to limit of N). | |
30 * The embedding application must declare these service instances in the applica tion section | |
31 * of its AndroidManifest.xml, for example with N entries of the form:- | |
32 * <service android:name="org.chromium.content.browser.SandboxedProcessServi ceX" | |
33 * android:process=":sandboxed_processX" /> | |
34 * for X in 0...N-1 (where N is {@link SandboxedProcessLauncher#MAX_REGISTERED_S ERVICES}) | |
35 */ | |
36 public class SandboxedProcessService extends Service { | |
37 private static final String MAIN_THREAD_NAME = "SandboxedProcessMain"; | |
38 private static final String TAG = "SandboxedProcessService"; | |
39 private ISandboxedProcessCallback mCallback; | |
40 | |
41 // This is the native "Main" thread for the renderer / utility process. | |
42 private Thread mSandboxMainThread; | |
43 // Parameters received via IPC, only accessed while holding the mSandboxMain Thread monitor. | |
44 private String[] mCommandLineParams; | |
45 private ParcelFileDescriptor mIPCFd; | |
46 private ParcelFileDescriptor mCrashFd; | |
47 private ParcelFileDescriptor mChromePakFd; | |
48 private ParcelFileDescriptor mLocalePakFd; | |
49 | |
50 private static Context sContext = null; | |
51 private boolean mLibraryInitialized = false; | |
52 | |
53 // Binder object used by clients for this service. | |
54 private final ISandboxedProcessService.Stub mBinder = new ISandboxedProcessS ervice.Stub() { | |
55 // NOTE: Implement any ISandboxedProcessService methods here. | |
56 @Override | |
57 public int setupConnection(Bundle args, ISandboxedProcessCallback callba ck) { | |
58 mCallback = callback; | |
59 synchronized (mSandboxMainThread) { | |
60 // Allow the command line to be set via bind() intent or setupCo nnection, but | |
61 // the FD can only be transferred here. | |
62 if (mCommandLineParams == null) { | |
63 mCommandLineParams = args.getStringArray( | |
64 SandboxedProcessConnection.EXTRA_COMMAND_LINE); | |
65 } | |
66 // We must have received the command line by now | |
67 assert mCommandLineParams != null; | |
68 mIPCFd = args.getParcelable(SandboxedProcessConnection.EXTRA_IPC _FD); | |
69 mChromePakFd = args.getParcelable(SandboxedProcessConnection.EXT RA_CHROME_PAK_FD); | |
Yaron
2012/06/11 19:46:22
Hmm. Not entirely sure how to fix this right now a
michaelbai
2012/06/11 20:30:16
Done.
Yaron
2012/06/11 20:45:51
So mLocalePakFd is part of the same problem. Pleas
| |
70 mLocalePakFd = args.getParcelable(SandboxedProcessConnection.EXT RA_LOCALE_PAK_FD); | |
71 // mCrashFd may be null if native crash reporting is disabled. | |
72 if (args.containsKey(SandboxedProcessConnection.EXTRA_CRASH_FD)) { | |
73 mCrashFd = args.getParcelable(SandboxedProcessConnection.EXT RA_CRASH_FD); | |
74 } | |
75 mSandboxMainThread.notifyAll(); | |
76 } | |
77 return Process.myPid(); | |
78 } | |
79 | |
80 @Override | |
81 public void setSurface(int type, Surface surface, int primaryID, int sec ondaryID) { | |
82 // This gives up ownership of the Surface. | |
83 SurfaceCallback.setSurface(type, surface, primaryID, secondaryID); | |
84 } | |
85 }; | |
86 | |
87 /* package */ static Context getContext() { | |
88 return sContext; | |
89 } | |
90 | |
91 @Override | |
92 public void onCreate() { | |
93 sContext = this; | |
94 super.onCreate(); | |
95 | |
96 mSandboxMainThread = new Thread(new Runnable() { | |
97 @Override | |
98 public void run() { | |
99 try { | |
100 // TODO(michaelbai): Upstream LibraryLoader.java | |
101 // if (!LibraryLoader.loadNow()) return; | |
102 synchronized (mSandboxMainThread) { | |
103 while (mCommandLineParams == null) { | |
104 mSandboxMainThread.wait(); | |
105 } | |
106 } | |
107 // LibraryLoader.initializeOnMainThread(mCommandLineParams); | |
108 synchronized (mSandboxMainThread) { | |
109 mLibraryInitialized = true; | |
110 mSandboxMainThread.notifyAll(); | |
111 while (mIPCFd == null) { | |
112 mSandboxMainThread.wait(); | |
113 } | |
114 } | |
115 int crashFd = (mCrashFd == null) ? -1 : mCrashFd.detachFd(); | |
116 ContentMain.initApplicationContext(sContext.getApplicationCo ntext()); | |
117 nativeInitSandboxedProcess(sContext.getApplicationContext(), | |
118 SandboxedProcessService.this, mIPCFd.detachFd(), cra shFd, | |
119 mChromePakFd.detachFd(), mLocalePakFd.detachFd()); | |
120 ContentMain.start(); | |
121 nativeExitSandboxedProcess(); | |
122 } catch (InterruptedException e) { | |
123 Log.w(TAG, MAIN_THREAD_NAME + " startup failed: " + e); | |
124 } | |
125 } | |
126 }, MAIN_THREAD_NAME); | |
127 mSandboxMainThread.start(); | |
128 } | |
129 | |
130 @Override | |
131 public void onDestroy() { | |
132 super.onDestroy(); | |
133 if (mCommandLineParams == null) { | |
134 // This process was destroyed before it even started. Nothing more t o do. | |
135 return; | |
136 } | |
137 synchronized (mSandboxMainThread) { | |
138 try { | |
139 while (!mLibraryInitialized) { | |
140 // Avoid a potential race in calling through to native code before the library | |
141 // has loaded. | |
142 mSandboxMainThread.wait(); | |
143 } | |
144 } catch (InterruptedException e) { | |
145 } | |
146 } | |
147 | |
148 // This is not synchronized with the main thread in any way, but this is analogous | |
149 // to how desktop chrome terminates processes using SIGTERM. The mSandbo xMainThread | |
150 // may run briefly before this is executed, but will eventually get a ch annel error | |
151 // and similarly commit suicide via SuicideOnChannelErrorFilter(). | |
152 // TODO(tedbo): Why doesn't the activity manager SIGTERM/SIGKILL this se rvice process? | |
153 nativeExitSandboxedProcess(); | |
154 } | |
155 | |
156 @Override | |
157 public IBinder onBind(Intent intent) { | |
158 // We call stopSelf() to request that this service be stopped as soon as the client | |
159 // unbinds. Otherwise the system may keep it around and available for a reconnect. The | |
160 // sandboxed processes do not currently support reconnect; they must be initialized from | |
161 // scratch every time. | |
162 stopSelf(); | |
163 | |
164 synchronized (mSandboxMainThread) { | |
165 mCommandLineParams = intent.getStringArrayExtra( | |
166 SandboxedProcessConnection.EXTRA_COMMAND_LINE); | |
167 mSandboxMainThread.notifyAll(); | |
168 } | |
169 | |
170 return mBinder; | |
171 } | |
172 | |
173 /** | |
174 * Called from native code to share a surface texture with another child pro cess. | |
175 * Through using the callback object the browser is used as a proxy to route the | |
176 * call to the correct process. | |
177 * | |
178 * @param pid Process handle of the sandboxed process to share the SurfaceTe xture with. | |
179 * @param type The type of process that the SurfaceTexture is for. | |
180 * @param surfaceObject The Surface or SurfaceTexture to share with the othe r sandboxed process. | |
181 * @param primaryID Used to route the call to the correct client instance. | |
182 * @param secondaryID Used to route the call to the correct client instance. | |
183 */ | |
184 @SuppressWarnings("unused") | |
185 @CalledByNative | |
186 private void establishSurfaceTexturePeer(int pid, int type, Object surfaceOb ject, int primaryID, | |
187 int secondaryID) { | |
188 if (mCallback == null) { | |
189 Log.e(TAG, "No callback interface has been provided."); | |
190 return; | |
191 } | |
192 | |
193 Surface surface = null; | |
194 boolean needRelease = false; | |
195 if (surfaceObject instanceof Surface) { | |
196 surface = (Surface)surfaceObject; | |
197 } else if (surfaceObject instanceof SurfaceTexture) { | |
198 surface = new Surface((SurfaceTexture)surfaceObject); | |
199 needRelease = true; | |
200 } else { | |
201 Log.e(TAG, "Not a valid surfaceObject: " + surfaceObject); | |
202 return; | |
203 } | |
204 try { | |
205 mCallback.establishSurfacePeer(pid, type, surface, primaryID, second aryID); | |
206 } catch (RemoteException e) { | |
207 Log.e(TAG, "Unable to call establishSurfaceTexturePeer: " + e); | |
208 return; | |
209 } finally { | |
210 if (needRelease) { | |
211 surface.release(); | |
212 } | |
213 } | |
214 } | |
215 | |
216 /** | |
217 * The main entry point for a sandboxed process. This should be called from a new thread since | |
218 * it will not return until the sandboxed process exits. See sandboxed_proce ss_service.{h,cc} | |
219 * | |
220 * @param applicationContext The Application Context of the current process. | |
221 * @param service The current SandboxedProcessService object. | |
222 * @param ipcFd File descriptor to use for ipc. | |
223 * @param crashFd File descriptor for signaling crashes. | |
224 */ | |
225 private static native void nativeInitSandboxedProcess(Context applicationCon text, | |
226 SandboxedProcessService service, int ipcFd, int crashFd, int chromeP akFd, | |
227 int localePakFd); | |
228 | |
229 /** | |
230 * Force the sandboxed process to exit. | |
231 */ | |
232 private static native void nativeExitSandboxedProcess(); | |
233 } | |
OLD | NEW |