• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.android.launcher3.util.rule;
2 
3 import static androidx.test.InstrumentationRegistry.getInstrumentation;
4 
5 import android.os.FileUtils;
6 import android.os.ParcelFileDescriptor.AutoCloseInputStream;
7 import android.util.Log;
8 
9 import androidx.test.uiautomator.UiDevice;
10 
11 import com.android.launcher3.tapl.LauncherInstrumentation;
12 import com.android.launcher3.ui.AbstractLauncherUiTest;
13 
14 import org.junit.rules.TestWatcher;
15 import org.junit.runner.Description;
16 
17 import java.io.File;
18 import java.io.FileOutputStream;
19 import java.io.IOException;
20 import java.io.OutputStream;
21 import java.util.zip.ZipEntry;
22 import java.util.zip.ZipOutputStream;
23 
24 public class FailureWatcher extends TestWatcher {
25     private static final String TAG = "FailureWatcher";
26     final private UiDevice mDevice;
27     private final LauncherInstrumentation mLauncher;
28 
FailureWatcher(UiDevice device, LauncherInstrumentation launcher)29     public FailureWatcher(UiDevice device, LauncherInstrumentation launcher) {
30         mDevice = device;
31         mLauncher = launcher;
32     }
33 
34     @Override
succeeded(Description description)35     protected void succeeded(Description description) {
36         super.succeeded(description);
37         AbstractLauncherUiTest.checkDetectedLeaks(mLauncher);
38     }
39 
40     @Override
failed(Throwable e, Description description)41     protected void failed(Throwable e, Description description) {
42         onError(mDevice, description, e);
43     }
44 
onError(UiDevice device, Description description, Throwable e)45     public static void onError(UiDevice device, Description description, Throwable e) {
46         if (device == null) return;
47         final File parentFile = getInstrumentation().getTargetContext().getFilesDir();
48         final File sceenshot = new File(parentFile,
49                 "TestScreenshot-" + description.getMethodName() + ".png");
50         final File hierarchy = new File(parentFile,
51                 "Hierarchy-" + description.getMethodName() + ".zip");
52 
53         // Dump window hierarchy
54         try (ZipOutputStream out = new ZipOutputStream(new FileOutputStream(hierarchy))) {
55             out.putNextEntry(new ZipEntry("bugreport.txt"));
56             dumpStringCommand("dumpsys window windows", out);
57             dumpStringCommand("dumpsys package", out);
58             dumpStringCommand("dumpsys activity service TouchInteractionService", out);
59             out.closeEntry();
60 
61             out.putNextEntry(new ZipEntry("visible_windows.zip"));
62             dumpCommand("cmd window dump-visible-window-views", out);
63             out.closeEntry();
64         } catch (IOException ex) { }
65 
66         Log.e(TAG, "Failed test " + description.getMethodName()
67                 + ",\nscreenshot will be saved to " + sceenshot
68                 + ",\nUI dump at: " + hierarchy
69                 + " (use go/web-hv to open the dump file)", e);
70         device.takeScreenshot(sceenshot);
71     }
72 
dumpStringCommand(String cmd, OutputStream out)73     private static void dumpStringCommand(String cmd, OutputStream out) throws IOException {
74         out.write(("\n\n" + cmd + "\n").getBytes());
75         dumpCommand(cmd, out);
76     }
77 
dumpCommand(String cmd, OutputStream out)78     private static void dumpCommand(String cmd, OutputStream out) throws IOException {
79         try (AutoCloseInputStream in = new AutoCloseInputStream(getInstrumentation()
80                 .getUiAutomation().executeShellCommand(cmd))) {
81             FileUtils.copy(in, out);
82         }
83     }
84 }
85