1945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy/*
2945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy * Copyright (C) 2013 The Android Open Source Project
3945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy *
4945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy * Licensed under the Apache License, Version 2.0 (the "License");
5945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy * you may not use this file except in compliance with the License.
6945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy * You may obtain a copy of the License at
7945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy *
8945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy *      http://www.apache.org/licenses/LICENSE-2.0
9945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy *
10945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy * Unless required by applicable law or agreed to in writing, software
11945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy * distributed under the License is distributed on an "AS IS" BASIS,
12945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy * See the License for the specific language governing permissions and
14945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy * limitations under the License.
15945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy */
16945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
17945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamypackage android.ddm;
18945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
19945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamyimport android.util.Log;
20945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamyimport android.view.View;
21945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamyimport android.view.ViewDebug;
22945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamyimport android.view.ViewRootImpl;
23945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamyimport android.view.WindowManagerGlobal;
24945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
25945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamyimport org.apache.harmony.dalvik.ddmc.Chunk;
26945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamyimport org.apache.harmony.dalvik.ddmc.ChunkHandler;
27945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamyimport org.apache.harmony.dalvik.ddmc.DdmServer;
28945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
29945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamyimport java.io.BufferedWriter;
30945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamyimport java.io.ByteArrayOutputStream;
31945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamyimport java.io.DataOutputStream;
32945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamyimport java.io.IOException;
33945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamyimport java.io.OutputStreamWriter;
34f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamyimport java.lang.reflect.Method;
35945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamyimport java.nio.BufferUnderflowException;
36945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamyimport java.nio.ByteBuffer;
37945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
38945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy/**
39945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy * Handle various requests related to profiling / debugging of the view system.
40945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy * Support for these features are advertised via {@link DdmHandleHello}.
41945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy */
42945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamypublic class DdmHandleViewDebug extends ChunkHandler {
43945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    /** List {@link ViewRootImpl}'s of this process. */
44945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    private static final int CHUNK_VULW = type("VULW");
45945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
46945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    /** Operation on view root, first parameter in packet should be one of VURT_* constants */
47945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    private static final int CHUNK_VURT = type("VURT");
48945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
49945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    /** Dump view hierarchy. */
50945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    private static final int VURT_DUMP_HIERARCHY = 1;
51945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
52945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    /** Capture View Layers. */
53945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    private static final int VURT_CAPTURE_LAYERS = 2;
54945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
55e82a4eeb40090f15054e2c76c0cea84b198a2b61Jon Miranda    /** Dump View Theme. */
56e82a4eeb40090f15054e2c76c0cea84b198a2b61Jon Miranda    private static final int VURT_DUMP_THEME = 3;
57e82a4eeb40090f15054e2c76c0cea84b198a2b61Jon Miranda
58945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    /**
59945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy     * Generic View Operation, first parameter in the packet should be one of the
60945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy     * VUOP_* constants below.
61945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy     */
62945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    private static final int CHUNK_VUOP = type("VUOP");
63945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
64945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    /** Capture View. */
65945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    private static final int VUOP_CAPTURE_VIEW = 1;
66945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
67945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    /** Obtain the Display List corresponding to the view. */
68945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    private static final int VUOP_DUMP_DISPLAYLIST = 2;
69945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
70f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy    /** Profile a view. */
71f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy    private static final int VUOP_PROFILE_VIEW = 3;
72945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
73f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy    /** Invoke a method on the view. */
74f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy    private static final int VUOP_INVOKE_VIEW_METHOD = 4;
75945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
76f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy    /** Set layout parameter. */
77f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy    private static final int VUOP_SET_LAYOUT_PARAMETER = 5;
78945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
79945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    /** Error code indicating operation specified in chunk is invalid. */
80945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    private static final int ERR_INVALID_OP = -1;
81945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
82945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    /** Error code indicating that the parameters are invalid. */
83945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    private static final int ERR_INVALID_PARAM = -2;
84945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
85f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy    /** Error code indicating an exception while performing operation. */
86f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy    private static final int ERR_EXCEPTION = -3;
87f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy
88f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy    private static final String TAG = "DdmViewDebug";
89f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy
90945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    private static final DdmHandleViewDebug sInstance = new DdmHandleViewDebug();
91945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
92945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    /** singleton, do not instantiate. */
93945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    private DdmHandleViewDebug() {}
94945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
95945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    public static void register() {
96945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        DdmServer.registerHandler(CHUNK_VULW, sInstance);
97945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        DdmServer.registerHandler(CHUNK_VURT, sInstance);
98945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        DdmServer.registerHandler(CHUNK_VUOP, sInstance);
99945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    }
100945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
101945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    @Override
102945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    public void connected() {
103945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    }
104945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
105945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    @Override
106945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    public void disconnected() {
107945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    }
108945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
109945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    @Override
110945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    public Chunk handleChunk(Chunk request) {
111945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        int type = request.type;
112945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
113a4d4e82927ceadc23863e74b7e1160e4497504a7Pablo Ceballos        if (type == CHUNK_VULW) {
114945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy            return listWindows();
115945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        }
116945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
117945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        ByteBuffer in = wrapChunk(request);
118945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        int op = in.getInt();
119945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
120945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        View rootView = getRootView(in);
121945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        if (rootView == null) {
122945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy            return createFailChunk(ERR_INVALID_PARAM, "Invalid View Root");
123945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        }
124945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
125945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        if (type == CHUNK_VURT) {
126945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy            if (op == VURT_DUMP_HIERARCHY)
127945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy                return dumpHierarchy(rootView, in);
128945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy            else if (op == VURT_CAPTURE_LAYERS)
129945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy                return captureLayers(rootView);
130e82a4eeb40090f15054e2c76c0cea84b198a2b61Jon Miranda            else if (op == VURT_DUMP_THEME)
131e82a4eeb40090f15054e2c76c0cea84b198a2b61Jon Miranda                return dumpTheme(rootView);
132945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy            else
133945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy                return createFailChunk(ERR_INVALID_OP, "Unknown view root operation: " + op);
134945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        }
135945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
136945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        final View targetView = getTargetView(rootView, in);
137945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        if (targetView == null) {
138945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy            return createFailChunk(ERR_INVALID_PARAM, "Invalid target view");
139945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        }
140945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
141945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        if (type == CHUNK_VUOP) {
142945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy            switch (op) {
143945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy                case VUOP_CAPTURE_VIEW:
144945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy                    return captureView(rootView, targetView);
145945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy                case VUOP_DUMP_DISPLAYLIST:
146945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy                    return dumpDisplayLists(rootView, targetView);
147945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy                case VUOP_PROFILE_VIEW:
148945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy                    return profileView(rootView, targetView);
149f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                case VUOP_INVOKE_VIEW_METHOD:
150f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                    return invokeViewMethod(rootView, targetView, in);
151f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                case VUOP_SET_LAYOUT_PARAMETER:
152f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                    return setLayoutParameter(rootView, targetView, in);
153945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy                default:
154945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy                    return createFailChunk(ERR_INVALID_OP, "Unknown view operation: " + op);
155945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy            }
156945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        } else {
157945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy            throw new RuntimeException("Unknown packet " + ChunkHandler.name(type));
158945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        }
159945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    }
160945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
161945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    /** Returns the list of windows owned by this client. */
162945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    private Chunk listWindows() {
163945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        String[] windowNames = WindowManagerGlobal.getInstance().getViewRootNames();
164945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
165945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        int responseLength = 4;                     // # of windows
166945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        for (String name : windowNames) {
167945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy            responseLength += 4;                    // length of next window name
168945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy            responseLength += name.length() * 2;    // window name
169945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        }
170945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
171945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        ByteBuffer out = ByteBuffer.allocate(responseLength);
172945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        out.order(ChunkHandler.CHUNK_ORDER);
173945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
174945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        out.putInt(windowNames.length);
175945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        for (String name : windowNames) {
176945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy            out.putInt(name.length());
177945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy            putString(out, name);
178945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        }
179945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
180945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        return new Chunk(CHUNK_VULW, out);
181945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    }
182945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
183945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    private View getRootView(ByteBuffer in) {
184945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        try {
185945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy            int viewRootNameLength = in.getInt();
186945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy            String viewRootName = getString(in, viewRootNameLength);
187945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy            return WindowManagerGlobal.getInstance().getRootView(viewRootName);
188945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        } catch (BufferUnderflowException e) {
189945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy            return null;
190945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        }
191945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    }
192945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
193945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    private View getTargetView(View root, ByteBuffer in) {
194945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        int viewLength;
195945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        String viewName;
196945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
197945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        try {
198945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy            viewLength = in.getInt();
199945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy            viewName = getString(in, viewLength);
200945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        } catch (BufferUnderflowException e) {
201945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy            return null;
202945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        }
203945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
204945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        return ViewDebug.findView(root, viewName);
205945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    }
206945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
207945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    /**
208945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy     * Returns the view hierarchy and/or view properties starting at the provided view.
209945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy     * Based on the input options, the return data may include:
210945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy     *  - just the view hierarchy
211945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy     *  - view hierarchy & the properties for each of the views
212945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy     *  - just the view properties for a specific view.
213945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy     *  TODO: Currently this only returns views starting at the root, need to fix so that
214945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy     *  it can return properties of any view.
215945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy     */
216945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    private Chunk dumpHierarchy(View rootView, ByteBuffer in) {
217945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        boolean skipChildren = in.getInt() > 0;
218945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        boolean includeProperties = in.getInt() > 0;
2190d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy        boolean v2 = in.hasRemaining() && in.getInt() > 0;
220945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
2210d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy        long start = System.currentTimeMillis();
2220d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy
2230d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy        ByteArrayOutputStream b = new ByteArrayOutputStream(2*1024*1024);
224945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        try {
2250d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy            if (v2) {
2260d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy                ViewDebug.dumpv2(rootView, b);
2270d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy            } else {
2280d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy                ViewDebug.dump(rootView, skipChildren, includeProperties, b);
2290d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy            }
2300d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy        } catch (IOException | InterruptedException e) {
231945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy            return createFailChunk(1, "Unexpected error while obtaining view hierarchy: "
232945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy                    + e.getMessage());
233945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        }
234945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
2350d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy        long end = System.currentTimeMillis();
2360d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy        Log.d(TAG, "Time to obtain view hierarchy (ms): " + (end - start));
2370d857b9028f2702ce439e13feccde8182d40e1e5Siva Velusamy
238945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        byte[] data = b.toByteArray();
239945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        return new Chunk(CHUNK_VURT, data, 0, data.length);
240945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    }
241945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
242945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    /** Returns a buffer with region details & bitmap of every single view. */
243945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    private Chunk captureLayers(View rootView) {
244945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        ByteArrayOutputStream b = new ByteArrayOutputStream(1024);
245945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        DataOutputStream dos = new DataOutputStream(b);
246945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        try {
247945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy            ViewDebug.captureLayers(rootView, dos);
248945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        } catch (IOException e) {
249945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy            return createFailChunk(1, "Unexpected error while obtaining view hierarchy: "
250945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy                    + e.getMessage());
251945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        } finally {
252945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy            try {
253945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy                dos.close();
254945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy            } catch (IOException e) {
255945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy                // ignore
256945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy            }
257945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        }
258945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
259945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        byte[] data = b.toByteArray();
260945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        return new Chunk(CHUNK_VURT, data, 0, data.length);
261945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    }
262945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
263e82a4eeb40090f15054e2c76c0cea84b198a2b61Jon Miranda    /**
264e82a4eeb40090f15054e2c76c0cea84b198a2b61Jon Miranda     * Returns the Theme dump of the provided view.
265e82a4eeb40090f15054e2c76c0cea84b198a2b61Jon Miranda     */
266e82a4eeb40090f15054e2c76c0cea84b198a2b61Jon Miranda    private Chunk dumpTheme(View rootView) {
267e82a4eeb40090f15054e2c76c0cea84b198a2b61Jon Miranda        ByteArrayOutputStream b = new ByteArrayOutputStream(1024);
268e82a4eeb40090f15054e2c76c0cea84b198a2b61Jon Miranda        try {
269e82a4eeb40090f15054e2c76c0cea84b198a2b61Jon Miranda            ViewDebug.dumpTheme(rootView, b);
270e82a4eeb40090f15054e2c76c0cea84b198a2b61Jon Miranda        } catch (IOException e) {
271e82a4eeb40090f15054e2c76c0cea84b198a2b61Jon Miranda            return createFailChunk(1, "Unexpected error while dumping the theme: "
272e82a4eeb40090f15054e2c76c0cea84b198a2b61Jon Miranda                    + e.getMessage());
273e82a4eeb40090f15054e2c76c0cea84b198a2b61Jon Miranda        }
274e82a4eeb40090f15054e2c76c0cea84b198a2b61Jon Miranda
275e82a4eeb40090f15054e2c76c0cea84b198a2b61Jon Miranda        byte[] data = b.toByteArray();
276e82a4eeb40090f15054e2c76c0cea84b198a2b61Jon Miranda        return new Chunk(CHUNK_VURT, data, 0, data.length);
277e82a4eeb40090f15054e2c76c0cea84b198a2b61Jon Miranda    }
278e82a4eeb40090f15054e2c76c0cea84b198a2b61Jon Miranda
279945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    private Chunk captureView(View rootView, View targetView) {
280945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        ByteArrayOutputStream b = new ByteArrayOutputStream(1024);
281945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        try {
282945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy            ViewDebug.capture(rootView, b, targetView);
283945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        } catch (IOException e) {
284945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy            return createFailChunk(1, "Unexpected error while capturing view: "
285945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy                    + e.getMessage());
286945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        }
287945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
288945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        byte[] data = b.toByteArray();
289945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        return new Chunk(CHUNK_VUOP, data, 0, data.length);
290945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    }
291945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
292945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    /** Returns the display lists corresponding to the provided view. */
293945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    private Chunk dumpDisplayLists(final View rootView, final View targetView) {
294945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        rootView.post(new Runnable() {
295945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy            @Override
296945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy            public void run() {
297945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy                ViewDebug.outputDisplayList(rootView, targetView);
298945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy            }
299945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        });
300945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        return null;
301945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    }
302945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
303f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy    /**
304f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy     * Invokes provided method on the view.
305f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy     * The method name and its arguments are passed in as inputs via the byte buffer.
306f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy     * The buffer contains:<ol>
307f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy     *  <li> len(method name) </li>
308f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy     *  <li> method name </li>
309f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy     *  <li> # of args </li>
310f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy     *  <li> arguments: Each argument comprises of a type specifier followed by the actual argument.
311f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy     *          The type specifier is a single character as used in JNI:
312f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy     *          (Z - boolean, B - byte, C - char, S - short, I - int, J - long,
313f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy     *          F - float, D - double). <p>
314f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy     *          The type specifier is followed by the actual value of argument.
315f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy     *          Booleans are encoded via bytes with 0 indicating false.</li>
316f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy     * </ol>
317f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy     * Methods that take no arguments need only specify the method name.
318f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy     */
319f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy    private Chunk invokeViewMethod(final View rootView, final View targetView, ByteBuffer in) {
320f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy        int l = in.getInt();
321f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy        String methodName = getString(in, l);
322f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy
323f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy        Class<?>[] argTypes;
324f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy        Object[] args;
325f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy        if (!in.hasRemaining()) {
326f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy            argTypes = new Class<?>[0];
327f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy            args = new Object[0];
328f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy        } else {
329f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy            int nArgs = in.getInt();
330f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy
331f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy            argTypes = new Class<?>[nArgs];
332f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy            args = new Object[nArgs];
333f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy
334f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy            for (int i = 0; i < nArgs; i++) {
335f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                char c = in.getChar();
336f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                switch (c) {
337f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                    case 'Z':
338f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                        argTypes[i] = boolean.class;
339f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                        args[i] = in.get() == 0 ? false : true;
340f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                        break;
341f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                    case 'B':
342f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                        argTypes[i] = byte.class;
343f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                        args[i] = in.get();
344f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                        break;
345f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                    case 'C':
346f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                        argTypes[i] = char.class;
347f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                        args[i] = in.getChar();
348f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                        break;
349f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                    case 'S':
350f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                        argTypes[i] = short.class;
351f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                        args[i] = in.getShort();
352f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                        break;
353f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                    case 'I':
354f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                        argTypes[i] = int.class;
355f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                        args[i] = in.getInt();
356f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                        break;
357f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                    case 'J':
358f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                        argTypes[i] = long.class;
359f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                        args[i] = in.getLong();
360f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                        break;
361f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                    case 'F':
362f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                        argTypes[i] = float.class;
363f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                        args[i] = in.getFloat();
364f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                        break;
365f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                    case 'D':
366f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                        argTypes[i] = double.class;
367f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                        args[i] = in.getDouble();
368f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                        break;
369f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                    default:
370f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                        Log.e(TAG, "arg " + i + ", unrecognized type: " + c);
371f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                        return createFailChunk(ERR_INVALID_PARAM,
372f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                                "Unsupported parameter type (" + c + ") to invoke view method.");
373f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                }
374f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy            }
375f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy        }
376f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy
377f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy        Method method = null;
378f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy        try {
379f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy            method = targetView.getClass().getMethod(methodName, argTypes);
380f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy        } catch (NoSuchMethodException e) {
381f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy            Log.e(TAG, "No such method: " + e.getMessage());
382f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy            return createFailChunk(ERR_INVALID_PARAM,
383f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                    "No such method: " + e.getMessage());
384f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy        }
385f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy
386f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy        try {
387f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy            ViewDebug.invokeViewMethod(targetView, method, args);
388f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy        } catch (Exception e) {
389f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy            Log.e(TAG, "Exception while invoking method: " + e.getCause().getMessage());
390f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy            String msg = e.getCause().getMessage();
391f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy            if (msg == null) {
392f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                msg = e.getCause().toString();
393f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy            }
394f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy            return createFailChunk(ERR_EXCEPTION, msg);
395f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy        }
396f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy
397945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        return null;
398945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    }
399945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
400f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy    private Chunk setLayoutParameter(final View rootView, final View targetView, ByteBuffer in) {
401f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy        int l = in.getInt();
402f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy        String param = getString(in, l);
403f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy        int value = in.getInt();
404f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy        try {
405f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy            ViewDebug.setLayoutParameter(targetView, param, value);
406f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy        } catch (Exception e) {
407f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy            Log.e(TAG, "Exception setting layout parameter: " + e);
408f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy            return createFailChunk(ERR_EXCEPTION, "Error accessing field "
409f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy                        + param + ":" + e.getMessage());
410f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy        }
411f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy
412945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        return null;
413945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    }
414945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
415945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    /** Profiles provided view. */
416945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    private Chunk profileView(View rootView, final View targetView) {
417945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        ByteArrayOutputStream b = new ByteArrayOutputStream(32 * 1024);
418945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(b), 32 * 1024);
419945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        try {
420945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy            ViewDebug.profileViewAndChildren(targetView, bw);
421945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        } catch (IOException e) {
422945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy            return createFailChunk(1, "Unexpected error while profiling view: " + e.getMessage());
423945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        } finally {
424945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy            try {
425945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy                bw.close();
426945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy            } catch (IOException e) {
427945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy                // ignore
428945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy            }
429945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        }
430945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy
431945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        byte[] data = b.toByteArray();
432945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy        return new Chunk(CHUNK_VUOP, data, 0, data.length);
433945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy    }
434945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy}
435