155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project/*
255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project *
455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project * you may not use this file except in compliance with the License.
655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project * You may obtain a copy of the License at
755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project *
855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project *
1055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
1155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
1255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project * See the License for the specific language governing permissions and
1455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project * limitations under the License.
1555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project */
1655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
1755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Projectpackage com.android.hierarchyviewer;
1855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
19f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guyimport com.android.ddmlib.IDevice;
20f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guyimport com.android.hierarchyviewer.device.Window;
21f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guyimport com.android.hierarchyviewer.scene.CaptureLoader;
2255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Projectimport com.android.hierarchyviewer.ui.Workspace;
2355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Projectimport com.android.hierarchyviewer.device.DeviceBridge;
2455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
2555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Projectimport javax.swing.SwingUtilities;
2655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Projectimport javax.swing.UIManager;
2755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Projectimport javax.swing.UnsupportedLookAndFeelException;
28f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guyimport java.io.File;
2955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
3055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Projectpublic class HierarchyViewer {
3155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    private static final CharSequence OS_WINDOWS = "Windows";
3255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    private static final CharSequence OS_MACOSX = "Mac OS X";
3355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
34cfa3a826f5924552889c750e6abb28d73b6d0597Romain Guy    private static boolean sProfilingEnabled = true;
35cfa3a826f5924552889c750e6abb28d73b6d0597Romain Guy
36cfa3a826f5924552889c750e6abb28d73b6d0597Romain Guy    public static boolean isProfilingEnabled() {
37cfa3a826f5924552889c750e6abb28d73b6d0597Romain Guy        return sProfilingEnabled;
38cfa3a826f5924552889c750e6abb28d73b6d0597Romain Guy    }
39cfa3a826f5924552889c750e6abb28d73b6d0597Romain Guy
4055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    private static void initUserInterface() {
4155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project        System.setProperty("apple.laf.useScreenMenuBar", "true");
4255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project        System.setProperty("apple.awt.brushMetalLook", "true");
4355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project        System.setProperty("com.apple.mrj.application.apple.menu.about.name", "HierarchyViewer");
4455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
4555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project        final String os = System.getProperty("os.name");
4655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
4755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project        try {
4855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project            if (os.contains(OS_WINDOWS) || os.contains(OS_MACOSX)) {
4955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
5055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project            } else {
51f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy                UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
5255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project            }
5355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project        } catch (ClassNotFoundException e) {
5455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project            e.printStackTrace();
5555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project        } catch (InstantiationException e) {
5655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project            e.printStackTrace();
5755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project        } catch (IllegalAccessException e) {
5855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project            e.printStackTrace();
5955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project        } catch (UnsupportedLookAndFeelException e) {
6055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project            e.printStackTrace();
6155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project        }
6255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    }
6355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
64f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy    private static void listDevices() {
65f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy        System.out.println("List of devices attached");
66f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy        try {
67f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy            Thread.sleep(500);
68f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy        } catch (InterruptedException e) {
69f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy            e.printStackTrace();
70f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy        }
71f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy        for (IDevice device : DeviceBridge.getDevices()) {
72f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy            printDevice(device);
73f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy        }
74f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy        DeviceBridge.terminate();
75f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy    }
76f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy
77f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy    private static void printDevice(IDevice device) {
78f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy        System.out.println(device.toString() + "\t\t" +
79f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy                (device.isEmulator() ? "emulator" : "device"));
80f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy    }
81f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy
82f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy    private static void outputPsd(String deviceName, String file) {
83f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy        IDevice device = selectDevice(deviceName);
84f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy        if (device != null) {
85f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy            if (DeviceBridge.isViewServerRunning(device)) {
86f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy                DeviceBridge.stopViewServer(device);
87f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy            }
88f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy            DeviceBridge.startViewServer(device);
89f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy            DeviceBridge.setupDeviceForward(device);
90f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy            System.out.println("Capturing layers to " + file);
91f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy            CaptureLoader.saveLayers(device, Window.FOCUSED_WINDOW, new File(file));
92f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy        } else {
93f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy            System.out.println("The selected device does not exist");
94f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy        }
95f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy        DeviceBridge.terminate();
96f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy    }
97f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy
98f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy    private static IDevice selectDevice(String deviceName) {
99f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy        try {
100f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy            Thread.sleep(500);
101f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy        } catch (InterruptedException e) {
102f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy            e.printStackTrace();
103f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy        }
104f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy        if (DeviceBridge.getDevices() == null) return null;
105f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy        if (deviceName == null) return DeviceBridge.getDevices()[0];
106f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy        for (IDevice device : DeviceBridge.getDevices()) {
107f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy            if (device.getSerialNumber().equalsIgnoreCase(deviceName)) {
108f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy                return device;
109f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy            }
110f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy        }
111f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy        return null;
112f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy    }
113f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy
11455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    public static void main(String[] args) {
115f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy        DeviceBridge.initDebugBridge();
116f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy
117cfa3a826f5924552889c750e6abb28d73b6d0597Romain Guy        if (args.length > 0) {
118f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy            for (int i = 0; i < args.length; i++) {
119f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy                String arg = args[i];
120f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy                if ("--help".equalsIgnoreCase(arg)) {
121f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy                    System.out.println("Usage: hierarchyviewer1 [options]\n");
122f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy                    System.out.println("Options:");
123f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy                    System.out.println("  --help\t\t\t Show this help message and exit");
124f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy                    System.out.println("  --no-profiling\t Disable views profiling");
125f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy                    System.out.println("  --devices\t\t\t Show the list of available devices");
126f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy                    System.out.println("  --psd [device] <file>\t Export psd and exit");
127f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy                    System.exit(0);
128f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy                } else if ("--no-profiling".equalsIgnoreCase(arg)) {
129f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy                    sProfilingEnabled = false;
130f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy                } else if ("--devices".equalsIgnoreCase(arg)) {
131f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy                    listDevices();
132f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy                    System.exit(0);
133f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy                } else if ("--psd".equalsIgnoreCase(arg)) {
134f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy                    if (i == args.length - 1) {
135f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy                        System.out.println("You must specify at least an output file with --psd");
136f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy                        System.exit(1);
137f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy                    }
138f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy                    String device = null;
139f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy                    String file = null;
140f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy                    if (i < args.length - 2) {
141f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy                        device = args[++i];
142f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy                    }
143f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy                    if (i < args.length - 1) {
144f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy                        file = args[++i];
145f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy                    }
146f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy                    outputPsd(device, file);
147f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy                    System.exit(0);
148f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy                }
149f50f3488336e613b8ffe1b7dd6a0c204e7350280Romain Guy            }
150cfa3a826f5924552889c750e6abb28d73b6d0597Romain Guy        }
151cfa3a826f5924552889c750e6abb28d73b6d0597Romain Guy
15255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project        initUserInterface();
15355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project        SwingUtilities.invokeLater(new Runnable() {
15455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project            public void run() {
15555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project                Workspace workspace = new Workspace();
15655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project                workspace.setDefaultCloseOperation(Workspace.EXIT_ON_CLOSE);
15755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project                workspace.setLocationRelativeTo(null);
15855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project                workspace.setVisible(true);
15955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project            }
16055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project        });
16155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    }
16255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project}
163