@Override protected void setUp() throws Exception { super.setUp(); // Get the device, this gives a handle to run commands and install APKs. mDevice = getDevice(); // Remove any previously installed versions of this APK. mDevice.uninstallPackage(PACKAGE); // Get the APK from the build. File app = mBuild.getTestApp(APK); // Get the ABI flag. String[] options = {AbiUtils.createAbiFlag(mAbi.getName())}; // Install the APK on the device. mDevice.installPackage(app, false, options); final String densityProp; if (mDevice.getSerialNumber().startsWith("emulator-")) { densityProp = DENSITY_PROP_EMULATOR; } else { densityProp = DENSITY_PROP_DEVICE; } final String zip = String.format( "/%s.zip", getDensityBucket(Integer.parseInt(mDevice.getProperty(densityProp)))); Log.logAndDisplay(LogLevel.INFO, TAG, "Loading resources from " + zip); final InputStream zipStream = this.getClass().getResourceAsStream(zip); if (zipStream != null) { final ZipInputStream in = new ZipInputStream(zipStream); try { ZipEntry ze; final byte[] buffer = new byte[1024]; while ((ze = in.getNextEntry()) != null) { final String name = ze.getName(); final File tmp = File.createTempFile("ref_" + name, ".png"); final FileOutputStream out = new FileOutputStream(tmp); int count; while ((count = in.read(buffer)) != -1) { out.write(buffer, 0, count); } out.flush(); out.close(); mReferences.put(name, tmp); } } finally { in.close(); } } mExecutionService = Executors.newFixedThreadPool(2); // 2 worker threads mCompletionService = new ExecutorCompletionService<Boolean>(mExecutionService); }
/** Tests that atrace captures app launch, including app level tracing */ public void testTracingContent() throws Exception { String atraceOutput = null; try { // cleanup test apps that might be installed from previous partial test run getDevice().uninstallPackage(TEST_PKG); // install the test app File testAppFile = mCtsBuild.getTestApp(TEST_APK); String installResult = getDevice().installPackage(testAppFile, false); assertNull( String.format("failed to install atrace test app. Reason: %s", installResult), installResult); // capture a launch of the app with async tracing // content traced by 'view' tag tested below, 'sched' used to ensure tgid printed String atraceArgs = "-a " + TEST_PKG + " -c -b 16000 view"; // TODO: zipping getDevice().executeShellCommand("atrace --async_stop " + atraceArgs); getDevice().executeShellCommand("atrace --async_start " + atraceArgs); getDevice().executeShellCommand("am start " + TEST_PKG); getDevice().executeShellCommand("sleep 1"); atraceOutput = getDevice().executeShellCommand("atrace --async_stop " + atraceArgs); } finally { assertNotNull("unable to capture atrace output", atraceOutput); getDevice().uninstallPackage(TEST_PKG); } // now parse the trace data (see external/chromium-trace/systrace.py) final String MARKER = "TRACE:"; int dataStart = atraceOutput.indexOf(MARKER); assertTrue(dataStart >= 0); String traceData = atraceOutput.substring(dataStart + MARKER.length()); FtraceEntryCallback callback = new FtraceEntryCallback() { private int userSpaceMatches = 0; private int beginMatches = 0; private int nextSectionIndex = -1; private int appTid = -1; private final String initialSection = "traceable-app-test-section"; // list of tags expected to be seen on app launch, in order, after the initial. private final String[] requiredSectionList = { "inflate", "Choreographer#doFrame", "traversal", "measure", "layout", "draw", "Record View#draw()" }; @Override public void onTraceEntry( String truncatedThreadName, int pid, int tid, String eventName, String details) { if (!"tracing_mark_write".equals(eventName)) { // not userspace trace, ignore return; } assertNotNull(truncatedThreadName); assertTrue(tid > 0); userSpaceMatches++; if (details == null || !details.startsWith("B|")) { // not a begin event return; } beginMatches++; if (details.endsWith("|" + initialSection)) { // initial section observed, start looking for others in order assertEquals(nextSectionIndex, -1); nextSectionIndex = 0; appTid = tid; return; } if (nextSectionIndex >= 0 && tid == appTid && nextSectionIndex < requiredSectionList.length && details.endsWith("|" + requiredSectionList[nextSectionIndex])) { // found next required section in sequence nextSectionIndex++; } } @Override public void onFinished() { assertTrue( "Unable to parse any userspace sections from atrace output", userSpaceMatches != 0); assertTrue( "Unable to parse any section begin events from atrace output", beginMatches != 0); assertTrue( "Unable to parse initial userspace sections from test app", nextSectionIndex >= 0); assertEquals( "Didn't see required list of traced sections, in order", requiredSectionList.length, nextSectionIndex); } }; FtraceParser.parse(new StringReader(traceData), callback); }