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.opengl.GLUtils; 20945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamyimport android.util.Log; 21945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamyimport android.view.View; 22945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamyimport android.view.ViewDebug; 23945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamyimport android.view.ViewRootImpl; 24945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamyimport android.view.WindowManagerGlobal; 25945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 26945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamyimport org.apache.harmony.dalvik.ddmc.Chunk; 27945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamyimport org.apache.harmony.dalvik.ddmc.ChunkHandler; 28945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamyimport org.apache.harmony.dalvik.ddmc.DdmServer; 29945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 30945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamyimport java.io.BufferedWriter; 31945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamyimport java.io.ByteArrayOutputStream; 32945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamyimport java.io.DataOutputStream; 33945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamyimport java.io.IOException; 34945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamyimport java.io.OutputStreamWriter; 35f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamyimport java.lang.reflect.Method; 36945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamyimport java.nio.BufferUnderflowException; 37945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamyimport java.nio.ByteBuffer; 38945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 39945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy/** 40945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy * Handle various requests related to profiling / debugging of the view system. 41945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy * Support for these features are advertised via {@link DdmHandleHello}. 42945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy */ 43945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamypublic class DdmHandleViewDebug extends ChunkHandler { 44945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy /** Enable/Disable tracing of OpenGL calls. */ 45945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy public static final int CHUNK_VUGL = type("VUGL"); 46945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 47945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy /** List {@link ViewRootImpl}'s of this process. */ 48945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy private static final int CHUNK_VULW = type("VULW"); 49945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 50945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy /** Operation on view root, first parameter in packet should be one of VURT_* constants */ 51945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy private static final int CHUNK_VURT = type("VURT"); 52945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 53945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy /** Dump view hierarchy. */ 54945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy private static final int VURT_DUMP_HIERARCHY = 1; 55945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 56945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy /** Capture View Layers. */ 57945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy private static final int VURT_CAPTURE_LAYERS = 2; 58945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 59945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy /** 60945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy * Generic View Operation, first parameter in the packet should be one of the 61945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy * VUOP_* constants below. 62945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy */ 63945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy private static final int CHUNK_VUOP = type("VUOP"); 64945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 65945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy /** Capture View. */ 66945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy private static final int VUOP_CAPTURE_VIEW = 1; 67945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 68945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy /** Obtain the Display List corresponding to the view. */ 69945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy private static final int VUOP_DUMP_DISPLAYLIST = 2; 70945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 71f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy /** Profile a view. */ 72f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy private static final int VUOP_PROFILE_VIEW = 3; 73945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 74f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy /** Invoke a method on the view. */ 75f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy private static final int VUOP_INVOKE_VIEW_METHOD = 4; 76945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 77f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy /** Set layout parameter. */ 78f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy private static final int VUOP_SET_LAYOUT_PARAMETER = 5; 79945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 80945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy /** Error code indicating operation specified in chunk is invalid. */ 81945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy private static final int ERR_INVALID_OP = -1; 82945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 83945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy /** Error code indicating that the parameters are invalid. */ 84945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy private static final int ERR_INVALID_PARAM = -2; 85945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 86f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy /** Error code indicating an exception while performing operation. */ 87f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy private static final int ERR_EXCEPTION = -3; 88f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy 89f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy private static final String TAG = "DdmViewDebug"; 90f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy 91945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy private static final DdmHandleViewDebug sInstance = new DdmHandleViewDebug(); 92945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 93945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy /** singleton, do not instantiate. */ 94945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy private DdmHandleViewDebug() {} 95945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 96945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy public static void register() { 97945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy DdmServer.registerHandler(CHUNK_VUGL, sInstance); 98945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy DdmServer.registerHandler(CHUNK_VULW, sInstance); 99945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy DdmServer.registerHandler(CHUNK_VURT, sInstance); 100945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy DdmServer.registerHandler(CHUNK_VUOP, sInstance); 101945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } 102945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 103945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy @Override 104945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy public void connected() { 105945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } 106945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 107945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy @Override 108945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy public void disconnected() { 109945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } 110945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 111945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy @Override 112945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy public Chunk handleChunk(Chunk request) { 113945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy int type = request.type; 114945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 115945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy if (type == CHUNK_VUGL) { 116945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy return handleOpenGlTrace(request); 117945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } else if (type == CHUNK_VULW) { 118945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy return listWindows(); 119945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } 120945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 121945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy ByteBuffer in = wrapChunk(request); 122945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy int op = in.getInt(); 123945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 124945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy View rootView = getRootView(in); 125945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy if (rootView == null) { 126945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy return createFailChunk(ERR_INVALID_PARAM, "Invalid View Root"); 127945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } 128945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 129945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy if (type == CHUNK_VURT) { 130945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy if (op == VURT_DUMP_HIERARCHY) 131945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy return dumpHierarchy(rootView, in); 132945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy else if (op == VURT_CAPTURE_LAYERS) 133945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy return captureLayers(rootView); 134945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy else 135945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy return createFailChunk(ERR_INVALID_OP, "Unknown view root operation: " + op); 136945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } 137945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 138945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy final View targetView = getTargetView(rootView, in); 139945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy if (targetView == null) { 140945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy return createFailChunk(ERR_INVALID_PARAM, "Invalid target view"); 141945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } 142945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 143945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy if (type == CHUNK_VUOP) { 144945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy switch (op) { 145945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy case VUOP_CAPTURE_VIEW: 146945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy return captureView(rootView, targetView); 147945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy case VUOP_DUMP_DISPLAYLIST: 148945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy return dumpDisplayLists(rootView, targetView); 149945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy case VUOP_PROFILE_VIEW: 150945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy return profileView(rootView, targetView); 151f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy case VUOP_INVOKE_VIEW_METHOD: 152f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy return invokeViewMethod(rootView, targetView, in); 153f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy case VUOP_SET_LAYOUT_PARAMETER: 154f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy return setLayoutParameter(rootView, targetView, in); 155945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy default: 156945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy return createFailChunk(ERR_INVALID_OP, "Unknown view operation: " + op); 157945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } 158945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } else { 159945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy throw new RuntimeException("Unknown packet " + ChunkHandler.name(type)); 160945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } 161945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } 162945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 163945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy private Chunk handleOpenGlTrace(Chunk request) { 164945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy ByteBuffer in = wrapChunk(request); 165945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy GLUtils.setTracingLevel(in.getInt()); 166945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy return null; // empty response 167945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } 168945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 169945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy /** Returns the list of windows owned by this client. */ 170945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy private Chunk listWindows() { 171945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy String[] windowNames = WindowManagerGlobal.getInstance().getViewRootNames(); 172945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 173945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy int responseLength = 4; // # of windows 174945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy for (String name : windowNames) { 175945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy responseLength += 4; // length of next window name 176945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy responseLength += name.length() * 2; // window name 177945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } 178945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 179945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy ByteBuffer out = ByteBuffer.allocate(responseLength); 180945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy out.order(ChunkHandler.CHUNK_ORDER); 181945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 182945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy out.putInt(windowNames.length); 183945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy for (String name : windowNames) { 184945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy out.putInt(name.length()); 185945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy putString(out, name); 186945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } 187945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 188945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy return new Chunk(CHUNK_VULW, out); 189945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } 190945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 191945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy private View getRootView(ByteBuffer in) { 192945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy try { 193945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy int viewRootNameLength = in.getInt(); 194945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy String viewRootName = getString(in, viewRootNameLength); 195945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy return WindowManagerGlobal.getInstance().getRootView(viewRootName); 196945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } catch (BufferUnderflowException e) { 197945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy return null; 198945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } 199945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } 200945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 201945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy private View getTargetView(View root, ByteBuffer in) { 202945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy int viewLength; 203945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy String viewName; 204945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 205945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy try { 206945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy viewLength = in.getInt(); 207945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy viewName = getString(in, viewLength); 208945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } catch (BufferUnderflowException e) { 209945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy return null; 210945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } 211945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 212945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy return ViewDebug.findView(root, viewName); 213945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } 214945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 215945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy /** 216945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy * Returns the view hierarchy and/or view properties starting at the provided view. 217945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy * Based on the input options, the return data may include: 218945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy * - just the view hierarchy 219945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy * - view hierarchy & the properties for each of the views 220945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy * - just the view properties for a specific view. 221945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy * TODO: Currently this only returns views starting at the root, need to fix so that 222945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy * it can return properties of any view. 223945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy */ 224945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy private Chunk dumpHierarchy(View rootView, ByteBuffer in) { 225945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy boolean skipChildren = in.getInt() > 0; 226945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy boolean includeProperties = in.getInt() > 0; 227945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 228945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy ByteArrayOutputStream b = new ByteArrayOutputStream(1024); 229945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy try { 230945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy ViewDebug.dump(rootView, skipChildren, includeProperties, b); 231945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } catch (IOException e) { 232945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy return createFailChunk(1, "Unexpected error while obtaining view hierarchy: " 233945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy + e.getMessage()); 234945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } 235945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 236945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy byte[] data = b.toByteArray(); 237945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy return new Chunk(CHUNK_VURT, data, 0, data.length); 238945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } 239945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 240945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy /** Returns a buffer with region details & bitmap of every single view. */ 241945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy private Chunk captureLayers(View rootView) { 242945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy ByteArrayOutputStream b = new ByteArrayOutputStream(1024); 243945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy DataOutputStream dos = new DataOutputStream(b); 244945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy try { 245945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy ViewDebug.captureLayers(rootView, dos); 246945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } catch (IOException e) { 247945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy return createFailChunk(1, "Unexpected error while obtaining view hierarchy: " 248945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy + e.getMessage()); 249945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } finally { 250945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy try { 251945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy dos.close(); 252945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } catch (IOException e) { 253945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy // ignore 254945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } 255945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } 256945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 257945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy byte[] data = b.toByteArray(); 258945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy return new Chunk(CHUNK_VURT, data, 0, data.length); 259945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } 260945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 261945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy private Chunk captureView(View rootView, View targetView) { 262945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy ByteArrayOutputStream b = new ByteArrayOutputStream(1024); 263945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy try { 264945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy ViewDebug.capture(rootView, b, targetView); 265945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } catch (IOException e) { 266945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy return createFailChunk(1, "Unexpected error while capturing view: " 267945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy + e.getMessage()); 268945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } 269945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 270945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy byte[] data = b.toByteArray(); 271945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy return new Chunk(CHUNK_VUOP, data, 0, data.length); 272945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } 273945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 274945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy /** Returns the display lists corresponding to the provided view. */ 275945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy private Chunk dumpDisplayLists(final View rootView, final View targetView) { 276945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy rootView.post(new Runnable() { 277945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy @Override 278945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy public void run() { 279945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy ViewDebug.outputDisplayList(rootView, targetView); 280945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } 281945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy }); 282945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy return null; 283945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } 284945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 285f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy /** 286f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy * Invokes provided method on the view. 287f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy * The method name and its arguments are passed in as inputs via the byte buffer. 288f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy * The buffer contains:<ol> 289f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy * <li> len(method name) </li> 290f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy * <li> method name </li> 291f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy * <li> # of args </li> 292f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy * <li> arguments: Each argument comprises of a type specifier followed by the actual argument. 293f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy * The type specifier is a single character as used in JNI: 294f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy * (Z - boolean, B - byte, C - char, S - short, I - int, J - long, 295f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy * F - float, D - double). <p> 296f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy * The type specifier is followed by the actual value of argument. 297f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy * Booleans are encoded via bytes with 0 indicating false.</li> 298f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy * </ol> 299f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy * Methods that take no arguments need only specify the method name. 300f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy */ 301f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy private Chunk invokeViewMethod(final View rootView, final View targetView, ByteBuffer in) { 302f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy int l = in.getInt(); 303f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy String methodName = getString(in, l); 304f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy 305f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy Class<?>[] argTypes; 306f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy Object[] args; 307f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy if (!in.hasRemaining()) { 308f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy argTypes = new Class<?>[0]; 309f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy args = new Object[0]; 310f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy } else { 311f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy int nArgs = in.getInt(); 312f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy 313f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy argTypes = new Class<?>[nArgs]; 314f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy args = new Object[nArgs]; 315f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy 316f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy for (int i = 0; i < nArgs; i++) { 317f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy char c = in.getChar(); 318f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy switch (c) { 319f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy case 'Z': 320f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy argTypes[i] = boolean.class; 321f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy args[i] = in.get() == 0 ? false : true; 322f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy break; 323f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy case 'B': 324f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy argTypes[i] = byte.class; 325f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy args[i] = in.get(); 326f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy break; 327f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy case 'C': 328f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy argTypes[i] = char.class; 329f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy args[i] = in.getChar(); 330f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy break; 331f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy case 'S': 332f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy argTypes[i] = short.class; 333f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy args[i] = in.getShort(); 334f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy break; 335f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy case 'I': 336f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy argTypes[i] = int.class; 337f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy args[i] = in.getInt(); 338f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy break; 339f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy case 'J': 340f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy argTypes[i] = long.class; 341f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy args[i] = in.getLong(); 342f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy break; 343f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy case 'F': 344f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy argTypes[i] = float.class; 345f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy args[i] = in.getFloat(); 346f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy break; 347f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy case 'D': 348f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy argTypes[i] = double.class; 349f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy args[i] = in.getDouble(); 350f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy break; 351f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy default: 352f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy Log.e(TAG, "arg " + i + ", unrecognized type: " + c); 353f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy return createFailChunk(ERR_INVALID_PARAM, 354f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy "Unsupported parameter type (" + c + ") to invoke view method."); 355f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy } 356f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy } 357f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy } 358f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy 359f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy Method method = null; 360f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy try { 361f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy method = targetView.getClass().getMethod(methodName, argTypes); 362f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy } catch (NoSuchMethodException e) { 363f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy Log.e(TAG, "No such method: " + e.getMessage()); 364f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy return createFailChunk(ERR_INVALID_PARAM, 365f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy "No such method: " + e.getMessage()); 366f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy } 367f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy 368f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy try { 369f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy ViewDebug.invokeViewMethod(targetView, method, args); 370f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy } catch (Exception e) { 371f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy Log.e(TAG, "Exception while invoking method: " + e.getCause().getMessage()); 372f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy String msg = e.getCause().getMessage(); 373f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy if (msg == null) { 374f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy msg = e.getCause().toString(); 375f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy } 376f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy return createFailChunk(ERR_EXCEPTION, msg); 377f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy } 378f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy 379945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy return null; 380945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } 381945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 382f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy private Chunk setLayoutParameter(final View rootView, final View targetView, ByteBuffer in) { 383f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy int l = in.getInt(); 384f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy String param = getString(in, l); 385f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy int value = in.getInt(); 386f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy try { 387f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy ViewDebug.setLayoutParameter(targetView, param, value); 388f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy } catch (Exception e) { 389f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy Log.e(TAG, "Exception setting layout parameter: " + e); 390f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy return createFailChunk(ERR_EXCEPTION, "Error accessing field " 391f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy + param + ":" + e.getMessage()); 392f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy } 393f9455fafb690f23cee9cc9a59bfb68f31e695990Siva Velusamy 394945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy return null; 395945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } 396945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 397945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy /** Profiles provided view. */ 398945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy private Chunk profileView(View rootView, final View targetView) { 399945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy ByteArrayOutputStream b = new ByteArrayOutputStream(32 * 1024); 400945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(b), 32 * 1024); 401945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy try { 402945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy ViewDebug.profileViewAndChildren(targetView, bw); 403945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } catch (IOException e) { 404945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy return createFailChunk(1, "Unexpected error while profiling view: " + e.getMessage()); 405945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } finally { 406945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy try { 407945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy bw.close(); 408945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } catch (IOException e) { 409945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy // ignore 410945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } 411945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } 412945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy 413945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy byte[] data = b.toByteArray(); 414945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy return new Chunk(CHUNK_VUOP, data, 0, data.length); 415945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy } 416945bfb6068d4ac1414a37a3ebe4dc4d02383e38eSiva Velusamy} 417