Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(281)

Side by Side Diff: base/test/android/java/src/org/chromium/base/MultiprocessTestClientLauncher.java

Issue 2781913002: Change ITestClient to be similar to IChildProcessService. (Closed)
Patch Set: Fix compile error sync Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 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.base; 5 package org.chromium.base;
6 6
7 import android.content.ComponentName; 7 import android.content.ComponentName;
8 import android.content.Context; 8 import android.content.Context;
9 import android.content.Intent; 9 import android.content.Intent;
10 import android.content.ServiceConnection; 10 import android.content.ServiceConnection;
11 import android.os.Bundle;
11 import android.os.IBinder; 12 import android.os.IBinder;
12 import android.os.ParcelFileDescriptor; 13 import android.os.ParcelFileDescriptor;
13 import android.os.RemoteException; 14 import android.os.RemoteException;
14 15
15 import org.chromium.base.annotations.CalledByNative; 16 import org.chromium.base.annotations.CalledByNative;
16 import org.chromium.base.annotations.JNINamespace; 17 import org.chromium.base.annotations.JNINamespace;
17 import org.chromium.base.process_launcher.FileDescriptorInfo; 18 import org.chromium.base.process_launcher.FileDescriptorInfo;
18 19
19 import java.io.IOException; 20 import java.io.IOException;
20 import java.util.ArrayList; 21 import java.util.ArrayList;
21 import java.util.LinkedList; 22 import java.util.LinkedList;
22 import java.util.List; 23 import java.util.List;
23 import java.util.Queue; 24 import java.util.Queue;
25 import java.util.concurrent.CountDownLatch;
24 26
25 import javax.annotation.concurrent.GuardedBy; 27 import javax.annotation.concurrent.GuardedBy;
26 28
27 /** 29 /**
28 * Helper class for launching test client processes for multiprocess unit tests. 30 * Helper class for launching test client processes for multiprocess unit tests.
29 */ 31 */
30 @JNINamespace("base::android") 32 @JNINamespace("base::android")
31 public final class MultiprocessTestClientLauncher { 33 public final class MultiprocessTestClientLauncher {
32 private static final String TAG = "cr_MProcTCLauncher"; 34 private static final String TAG = "cr_MProcTCLauncher";
33 35
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 if (connection.getPid() == pid) { 94 if (connection.getPid() == pid) {
93 return connection; 95 return connection;
94 } 96 }
95 } 97 }
96 } 98 }
97 return null; 99 return null;
98 } 100 }
99 } 101 }
100 102
101 private static class ClientServiceConnection implements ServiceConnection { 103 private static class ClientServiceConnection implements ServiceConnection {
102 private final String[] mCommandLine; 104 private final Bundle mSetupBundle;
103 private final FileDescriptorInfo[] mFilesToMap;
104 private final Object mConnectedLock = new Object(); 105 private final Object mConnectedLock = new Object();
106 private final CountDownLatch mPidReceived = new CountDownLatch(1);
105 private final int mSlot; 107 private final int mSlot;
106 private ITestClient mService = null; 108 private ITestClient mService = null;
107 @GuardedBy("mConnectedLock") 109 @GuardedBy("mConnectedLock")
108 private boolean mConnected; 110 private boolean mConnected;
109 private int mPid; 111 private int mPid;
112 private ITestController mTestController;
113 private final ITestCallback.Stub mCallback = new ITestCallback.Stub() {
114 public void childConnected(ITestController controller) {
115 mTestController = controller;
116 // This method can be called before onServiceConnected below has set the PID.
117 // Wait for mPid to be set before notifying.
118 try {
119 mPidReceived.await();
120 } catch (InterruptedException ie) {
121 Log.e(TAG, "Interrupted while waiting for connection PID.");
122 return;
123 }
124 // Now we are fully initialized, notify clients.
125 synchronized (mConnectedLock) {
126 mConnected = true;
127 mConnectedLock.notifyAll();
128 }
129 }
130 };
110 131
111 ClientServiceConnection(int slot, String[] commandLine, FileDescriptorIn fo[] filesToMap) { 132 ClientServiceConnection(int slot, String[] commandLine, FileDescriptorIn fo[] filesToMap) {
112 mSlot = slot; 133 mSlot = slot;
113 mCommandLine = commandLine; 134 mSetupBundle = new Bundle();
114 mFilesToMap = filesToMap; 135 mSetupBundle.putStringArray(ChildProcessConstants.EXTRA_COMMAND_LINE , commandLine);
136 mSetupBundle.putParcelableArray(ChildProcessConstants.EXTRA_FILES, f ilesToMap);
115 } 137 }
116 138
117 public void waitForConnection() { 139 public void waitForConnection() {
118 synchronized (mConnectedLock) { 140 synchronized (mConnectedLock) {
119 while (!mConnected) { 141 while (!mConnected) {
120 try { 142 try {
121 mConnectedLock.wait(); 143 mConnectedLock.wait();
122 } catch (InterruptedException ie) { 144 } catch (InterruptedException ie) {
123 Log.e(TAG, "Interrupted while waiting for connection."); 145 Log.e(TAG, "Interrupted while waiting for connection.");
124 } 146 }
125 } 147 }
126 } 148 }
127 } 149 }
128 150
129 @Override 151 @Override
130 public void onServiceConnected(ComponentName className, IBinder service) { 152 public void onServiceConnected(ComponentName className, IBinder service) {
131 try { 153 try {
132 mService = ITestClient.Stub.asInterface(service); 154 mService = ITestClient.Stub.asInterface(service);
133 mPid = mService.launch(mCommandLine, mFilesToMap); 155 if (!mService.bindToCaller()) {
134 synchronized (mConnectedLock) { 156 Log.e(TAG, "Failed to bind to child service");
135 mConnected = true; 157 return;
136 mConnectedLock.notifyAll();
137 } 158 }
159 mPid = mService.setupConnection(mSetupBundle, mCallback);
160 mPidReceived.countDown();
138 } catch (RemoteException e) { 161 } catch (RemoteException e) {
139 Log.e(TAG, "Connect failed"); 162 Log.e(TAG, "Connect failed");
140 } 163 }
141 } 164 }
142 165
143 @Override 166 @Override
144 public void onServiceDisconnected(ComponentName className) { 167 public void onServiceDisconnected(ComponentName className) {
145 if (mPid == 0) { 168 if (mPid == 0) {
146 Log.e(TAG, "Early ClientServiceConnection disconnection."); 169 Log.e(TAG, "Early ClientServiceConnection disconnection.");
147 return; 170 return;
148 } 171 }
149 sConnectionAllocator.freeConnection(this); 172 sConnectionAllocator.freeConnection(this);
150 } 173 }
151 174
152 public ITestClient getService() { 175 public ITestController getTestController() {
153 return mService; 176 return mTestController;
154 } 177 }
155 178
156 public String getServiceClassName() { 179 public String getServiceClassName() {
157 // In order to use different processes, we have to declare multiple services in the 180 // In order to use different processes, we have to declare multiple services in the
158 // AndroidManifest.xml file, each service associated with its own pr ocess. The various 181 // AndroidManifest.xml file, each service associated with its own pr ocess. The various
159 // services are functionnaly identical but need to each have their o wn class. 182 // services are functionnaly identical but need to each have their o wn class.
160 // We differentiate them by their class name having a trailing numbe r. 183 // We differentiate them by their class name having a trailing numbe r.
161 return MultiprocessTestClientService.class.getName() + mSlot; 184 return MultiprocessTestClientService.class.getName() + mSlot;
162 } 185 }
163 186
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
221 * @return the return code returned by the main method or whether it timed-o ut. 244 * @return the return code returned by the main method or whether it timed-o ut.
222 */ 245 */
223 @CalledByNative 246 @CalledByNative
224 private static MainReturnCodeResult waitForMainToReturn(int pid, int timeout Ms) { 247 private static MainReturnCodeResult waitForMainToReturn(int pid, int timeout Ms) {
225 ClientServiceConnection connection = sConnectionAllocator.getConnectionB yPid(pid); 248 ClientServiceConnection connection = sConnectionAllocator.getConnectionB yPid(pid);
226 if (connection == null) { 249 if (connection == null) {
227 Log.e(TAG, "waitForMainToReturn called on unknown connection for pid " + pid); 250 Log.e(TAG, "waitForMainToReturn called on unknown connection for pid " + pid);
228 return null; 251 return null;
229 } 252 }
230 try { 253 try {
231 return connection.getService().waitForMainToReturn(timeoutMs); 254 return connection.getTestController().waitForMainToReturn(timeoutMs) ;
232 } catch (RemoteException e) { 255 } catch (RemoteException e) {
233 Log.e(TAG, "Remote call to waitForMainToReturn failed."); 256 Log.e(TAG, "Remote call to waitForMainToReturn failed.");
234 return null; 257 return null;
235 } finally { 258 } finally {
236 freeConnection(connection); 259 freeConnection(connection);
237 } 260 }
238 } 261 }
239 262
240 @CalledByNative 263 @CalledByNative
241 private static boolean terminate(int pid, int exitCode, boolean wait) { 264 private static boolean terminate(int pid, int exitCode, boolean wait) {
242 ClientServiceConnection connection = sConnectionAllocator.getConnectionB yPid(pid); 265 ClientServiceConnection connection = sConnectionAllocator.getConnectionB yPid(pid);
243 if (connection == null) { 266 if (connection == null) {
244 Log.e(TAG, "terminate called on unknown connection for pid " + pid); 267 Log.e(TAG, "terminate called on unknown connection for pid " + pid);
245 return false; 268 return false;
246 } 269 }
247 try { 270 try {
248 if (wait) { 271 if (wait) {
249 connection.getService().forceStopSynchronous(exitCode); 272 connection.getTestController().forceStopSynchronous(exitCode);
250 } else { 273 } else {
251 connection.getService().forceStop(exitCode); 274 connection.getTestController().forceStop(exitCode);
252 } 275 }
253 } catch (RemoteException e) { 276 } catch (RemoteException e) {
254 // We expect this failure, since the forceStop's service implementat ion calls 277 // We expect this failure, since the forceStop's service implementat ion calls
255 // System.exit(). 278 // System.exit().
256 } finally { 279 } finally {
257 freeConnection(connection); 280 freeConnection(connection);
258 } 281 }
259 return true; 282 return true;
260 } 283 }
261 284
(...skipping 21 matching lines...) Expand all
283 ParcelFileDescriptor parcelableFd = null; 306 ParcelFileDescriptor parcelableFd = null;
284 try { 307 try {
285 parcelableFd = ParcelFileDescriptor.fromFd(fd); 308 parcelableFd = ParcelFileDescriptor.fromFd(fd);
286 } catch (IOException e) { 309 } catch (IOException e) {
287 Log.e(TAG, "Invalid FD provided for process connection, aborting con nection.", e); 310 Log.e(TAG, "Invalid FD provided for process connection, aborting con nection.", e);
288 return null; 311 return null;
289 } 312 }
290 return new FileDescriptorInfo(id, parcelableFd, 0 /* offset */, 0 /* siz e */); 313 return new FileDescriptorInfo(id, parcelableFd, 0 /* offset */, 0 /* siz e */);
291 } 314 }
292 } 315 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698