FileDocCategorySizeDatePackage
DumpCommand.javaAPI DocAndroid 5.1 API3943Thu Mar 12 22:22:08 GMT 2015com.android.commands.uiautomator

DumpCommand.java

/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.commands.uiautomator;

import android.app.UiAutomation;
import android.graphics.Point;
import android.hardware.display.DisplayManagerGlobal;
import android.os.Environment;
import android.view.Display;
import android.view.accessibility.AccessibilityNodeInfo;

import com.android.commands.uiautomator.Launcher.Command;
import com.android.uiautomator.core.AccessibilityNodeInfoDumper;
import com.android.uiautomator.core.UiAutomationShellWrapper;

import java.io.File;
import java.util.concurrent.TimeoutException;

/**
 * Implementation of the dump subcommand
 *
 * This creates an XML dump of current UI hierarchy
 */
public class DumpCommand extends Command {

    private static final File DEFAULT_DUMP_FILE = new File(
            Environment.getLegacyExternalStorageDirectory(), "window_dump.xml");

    public DumpCommand() {
        super("dump");
    }

    @Override
    public String shortHelp() {
        return "creates an XML dump of current UI hierarchy";
    }

    @Override
    public String detailedOptions() {
        return "    dump [--verbose][file]\n"
            + "      [--compressed]: dumps compressed layout information.\n"
            + "      [file]: the location where the dumped XML should be stored, default is\n      "
            + DEFAULT_DUMP_FILE.getAbsolutePath() + "\n";
    }

    @Override
    public void run(String[] args) {
        File dumpFile = DEFAULT_DUMP_FILE;
        boolean verboseMode = true;

        for (String arg : args) {
            if (arg.equals("--compressed"))
                verboseMode = false;
            else if (!arg.startsWith("-")) {
                dumpFile = new File(arg);
            }
        }

        UiAutomationShellWrapper automationWrapper = new UiAutomationShellWrapper();
        automationWrapper.connect();
        if (verboseMode) {
            // default
            automationWrapper.setCompressedLayoutHierarchy(false);
        } else {
            automationWrapper.setCompressedLayoutHierarchy(true);
        }

        // It appears that the bridge needs time to be ready. Making calls to the
        // bridge immediately after connecting seems to cause exceptions. So let's also
        // do a wait for idle in case the app is busy.
        try {
            UiAutomation uiAutomation = automationWrapper.getUiAutomation();
            uiAutomation.waitForIdle(1000, 1000 * 10);
            AccessibilityNodeInfo info = uiAutomation.getRootInActiveWindow();
            if (info == null) {
                System.err.println("ERROR: null root node returned by UiTestAutomationBridge.");
                return;
            }

            Display display =
                    DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
            int rotation = display.getRotation();
            Point size = new Point();
            display.getSize(size);
            AccessibilityNodeInfoDumper.dumpWindowToFile(info, dumpFile, rotation, size.x, size.y);
        } catch (TimeoutException re) {
            System.err.println("ERROR: could not get idle state.");
            return;
        } finally {
            automationWrapper.disconnect();
        }
        System.out.println(
                String.format("UI hierchary dumped to: %s", dumpFile.getAbsolutePath()));
    }
}