8
8
import java .io .InputStream ;
9
9
import java .nio .charset .StandardCharsets ;
10
10
import java .util .ArrayList ;
11
+ import java .util .Arrays ;
11
12
import java .util .List ;
12
13
import java .util .concurrent .atomic .AtomicReference ;
13
14
import java .util .function .UnaryOperator ;
15
+ import org .apache .commons .io .IOUtils ;
14
16
15
17
import com .android .build .gradle .internal .tasks .DeviceProviderInstrumentTestTask ;
16
18
import org .gradle .api .Action ;
17
19
import org .gradle .api .Plugin ;
18
20
import org .gradle .api .Project ;
21
+ import org .gradle .api .logging .Logger ;
19
22
import org .gradle .api .Task ;
20
23
import org .gradle .api .tasks .AbstractExecTask ;
21
24
import org .gradle .api .tasks .Exec ;
@@ -137,6 +140,8 @@ private static void createCreateEmulatorTask(final Project project, final Emulat
137
140
}
138
141
139
142
private static void createStartStopEmulatorTasks (final Project project , final EmulatorConfiguration emulatorConfiguration ) {
143
+ final boolean logEmulatorOutput = emulatorConfiguration .getLogEmulatorOutput ();
144
+
140
145
final List <String > command = new ArrayList <>();
141
146
command .add (emulatorConfiguration .getEmulator ().getAbsolutePath ());
142
147
command .add ("@" + emulatorConfiguration .getEmulatorName ());
@@ -148,15 +153,21 @@ private static void createStartStopEmulatorTasks(final Project project, final Em
148
153
}
149
154
final ProcessBuilder pb = new ProcessBuilder (command .toArray (new String [0 ]));
150
155
pb .environment ().putAll (emulatorConfiguration .getEnvironmentVariableMap ());
151
- pb .inheritIO ();
156
+ if (!logEmulatorOutput ) {
157
+ pb .inheritIO ();
158
+ }
152
159
153
160
final AtomicReference <Process > process = new AtomicReference <>();
154
161
155
162
project .getTasks ().create (START_ANDROID_EMULATOR_TASK_NAME , task -> {
156
163
task .doFirst (t -> {
157
164
project .getLogger ().debug ("Starting emulator with command {} {}" , pb .environment (), pb .command ());
158
165
try {
159
- process .set (pb .start ());
166
+ final Process directProcess = pb .start ();
167
+ process .set (directProcess );
168
+ if (logEmulatorOutput ) {
169
+ logOutput (directProcess , project .getLogger ());
170
+ }
160
171
Runtime .getRuntime ().addShutdownHook (new Thread (() -> process .getAndUpdate (DESTROY_AND_REPLACE_WITH_NULL )));
161
172
} catch (final IOException e ) {
162
173
throw new RuntimeException ("Emulator failed to start successfully" , e );
@@ -175,11 +186,34 @@ private static void createStartStopEmulatorTasks(final Project project, final Em
175
186
});
176
187
}
177
188
189
+ /**
190
+ * Logs emulator output via new threads.
191
+ * @param process The process to log the output of
192
+ * @param logger The logger to report output with
193
+ */
194
+ private static void logOutput (final Process process , final Logger logger ) {
195
+ final InputStream stdout = process .getInputStream ();
196
+ final InputStream stderr = process .getErrorStream ();
197
+ new Thread (() -> {
198
+ try {
199
+ IOUtils .lineIterator (stdout , StandardCharsets .UTF_8 ).forEachRemaining (s -> logger .info ("[Android Emulator - STDOUT] " + s ));
200
+ } catch (IOException e ) {
201
+ logger .error ("Error reading Android emulator stdout" , e );
202
+ }
203
+ }).start ();
204
+ new Thread (() -> {
205
+ try {
206
+ IOUtils .lineIterator (stderr , StandardCharsets .UTF_8 ).forEachRemaining (s -> logger .info ("[Android Emulator - STDERR] " + s ));
207
+ } catch (IOException e ) {
208
+ logger .error ("Error reading Android emulator stderr" , e );
209
+ }
210
+ }).start ();
211
+ }
212
+
178
213
private static void createWaitForEmulatorTask (final Project project , final EmulatorConfiguration emulatorConfiguration ) {
179
214
createExecTask (project , emulatorConfiguration , WAIT_FOR_ANDROID_EMULATOR_TASK_NAME , exec -> {
180
215
exec .setExecutable (emulatorConfiguration .getAdb ());
181
216
exec .setArgs (l ("wait-for-device" , "shell" , "while $(exit $(getprop sys.boot_completed)) ; do sleep 1; done;" ));
182
- // exec.setArgs(l("wait-for-device", "shell", "sleep 1000000; while [ -z $(getprop sys.boot_completed) ]; do sleep 1; done;"));
183
217
184
218
exec .dependsOn (ENSURE_ANDROID_EMULATOR_PERMISSIONS_TASK_NAME , START_ANDROID_EMULATOR_TASK_NAME );
185
219
});
@@ -209,12 +243,9 @@ private static Task createExecTask(final Project project,
209
243
}
210
244
211
245
@ SafeVarargs
246
+ @ SuppressWarnings ("varargs" )
212
247
private static <T > List <T > l (T ... arr ) {
213
- final List <T > ret = new ArrayList <>();
214
- for (final T v : arr ) {
215
- ret .add (v );
216
- }
217
- return ret ;
248
+ return Arrays .asList (arr );
218
249
}
219
250
220
251
private static InputStream buildStandardInLines (String ... lines ) {
0 commit comments