FileDocCategorySizeDatePackage
DdmHandleViewDebug.javaAPI DocAndroid 5.1 API15592Thu Mar 12 22:22:10 GMT 2015android.ddm

DdmHandleViewDebug

public class DdmHandleViewDebug extends org.apache.harmony.dalvik.ddmc.ChunkHandler
Handle various requests related to profiling / debugging of the view system. Support for these features are advertised via {@link DdmHandleHello}.

Fields Summary
public static final int
CHUNK_VUGL
Enable/Disable tracing of OpenGL calls.
private static final int
CHUNK_VULW
List {@link ViewRootImpl}'s of this process.
private static final int
CHUNK_VURT
Operation on view root, first parameter in packet should be one of VURT_* constants
private static final int
VURT_DUMP_HIERARCHY
Dump view hierarchy.
private static final int
VURT_CAPTURE_LAYERS
Capture View Layers.
private static final int
VURT_DUMP_THEME
Dump View Theme.
private static final int
CHUNK_VUOP
Generic View Operation, first parameter in the packet should be one of the VUOP_* constants below.
private static final int
VUOP_CAPTURE_VIEW
Capture View.
private static final int
VUOP_DUMP_DISPLAYLIST
Obtain the Display List corresponding to the view.
private static final int
VUOP_PROFILE_VIEW
Profile a view.
private static final int
VUOP_INVOKE_VIEW_METHOD
Invoke a method on the view.
private static final int
VUOP_SET_LAYOUT_PARAMETER
Set layout parameter.
private static final int
ERR_INVALID_OP
Error code indicating operation specified in chunk is invalid.
private static final int
ERR_INVALID_PARAM
Error code indicating that the parameters are invalid.
private static final int
ERR_EXCEPTION
Error code indicating an exception while performing operation.
private static final String
TAG
private static final DdmHandleViewDebug
sInstance
Constructors Summary
private DdmHandleViewDebug()
singleton, do not instantiate.


         
      
Methods Summary
private org.apache.harmony.dalvik.ddmc.ChunkcaptureLayers(android.view.View rootView)
Returns a buffer with region details & bitmap of every single view.

        ByteArrayOutputStream b = new ByteArrayOutputStream(1024);
        DataOutputStream dos = new DataOutputStream(b);
        try {
            ViewDebug.captureLayers(rootView, dos);
        } catch (IOException e) {
            return createFailChunk(1, "Unexpected error while obtaining view hierarchy: "
                    + e.getMessage());
        } finally {
            try {
                dos.close();
            } catch (IOException e) {
                // ignore
            }
        }

        byte[] data = b.toByteArray();
        return new Chunk(CHUNK_VURT, data, 0, data.length);
    
private org.apache.harmony.dalvik.ddmc.ChunkcaptureView(android.view.View rootView, android.view.View targetView)

        ByteArrayOutputStream b = new ByteArrayOutputStream(1024);
        try {
            ViewDebug.capture(rootView, b, targetView);
        } catch (IOException e) {
            return createFailChunk(1, "Unexpected error while capturing view: "
                    + e.getMessage());
        }

        byte[] data = b.toByteArray();
        return new Chunk(CHUNK_VUOP, data, 0, data.length);
    
public voidconnected()

    
public voiddisconnected()

    
private org.apache.harmony.dalvik.ddmc.ChunkdumpDisplayLists(android.view.View rootView, android.view.View targetView)
Returns the display lists corresponding to the provided view.

        rootView.post(new Runnable() {
            @Override
            public void run() {
                ViewDebug.outputDisplayList(rootView, targetView);
            }
        });
        return null;
    
private org.apache.harmony.dalvik.ddmc.ChunkdumpHierarchy(android.view.View rootView, java.nio.ByteBuffer in)
Returns the view hierarchy and/or view properties starting at the provided view. Based on the input options, the return data may include: - just the view hierarchy - view hierarchy & the properties for each of the views - just the view properties for a specific view. TODO: Currently this only returns views starting at the root, need to fix so that it can return properties of any view.

        boolean skipChildren = in.getInt() > 0;
        boolean includeProperties = in.getInt() > 0;

        ByteArrayOutputStream b = new ByteArrayOutputStream(1024);
        try {
            ViewDebug.dump(rootView, skipChildren, includeProperties, b);
        } catch (IOException e) {
            return createFailChunk(1, "Unexpected error while obtaining view hierarchy: "
                    + e.getMessage());
        }

        byte[] data = b.toByteArray();
        return new Chunk(CHUNK_VURT, data, 0, data.length);
    
private org.apache.harmony.dalvik.ddmc.ChunkdumpTheme(android.view.View rootView)
Returns the Theme dump of the provided view.

        ByteArrayOutputStream b = new ByteArrayOutputStream(1024);
        try {
            ViewDebug.dumpTheme(rootView, b);
        } catch (IOException e) {
            return createFailChunk(1, "Unexpected error while dumping the theme: "
                    + e.getMessage());
        }

        byte[] data = b.toByteArray();
        return new Chunk(CHUNK_VURT, data, 0, data.length);
    
private android.view.ViewgetRootView(java.nio.ByteBuffer in)

        try {
            int viewRootNameLength = in.getInt();
            String viewRootName = getString(in, viewRootNameLength);
            return WindowManagerGlobal.getInstance().getRootView(viewRootName);
        } catch (BufferUnderflowException e) {
            return null;
        }
    
private android.view.ViewgetTargetView(android.view.View root, java.nio.ByteBuffer in)

        int viewLength;
        String viewName;

        try {
            viewLength = in.getInt();
            viewName = getString(in, viewLength);
        } catch (BufferUnderflowException e) {
            return null;
        }

        return ViewDebug.findView(root, viewName);
    
public org.apache.harmony.dalvik.ddmc.ChunkhandleChunk(org.apache.harmony.dalvik.ddmc.Chunk request)

        int type = request.type;

        if (type == CHUNK_VUGL) {
            return handleOpenGlTrace(request);
        } else if (type == CHUNK_VULW) {
            return listWindows();
        }

        ByteBuffer in = wrapChunk(request);
        int op = in.getInt();

        View rootView = getRootView(in);
        if (rootView == null) {
            return createFailChunk(ERR_INVALID_PARAM, "Invalid View Root");
        }

        if (type == CHUNK_VURT) {
            if (op == VURT_DUMP_HIERARCHY)
                return dumpHierarchy(rootView, in);
            else if (op == VURT_CAPTURE_LAYERS)
                return captureLayers(rootView);
            else if (op == VURT_DUMP_THEME)
                return dumpTheme(rootView);
            else
                return createFailChunk(ERR_INVALID_OP, "Unknown view root operation: " + op);
        }

        final View targetView = getTargetView(rootView, in);
        if (targetView == null) {
            return createFailChunk(ERR_INVALID_PARAM, "Invalid target view");
        }

        if (type == CHUNK_VUOP) {
            switch (op) {
                case VUOP_CAPTURE_VIEW:
                    return captureView(rootView, targetView);
                case VUOP_DUMP_DISPLAYLIST:
                    return dumpDisplayLists(rootView, targetView);
                case VUOP_PROFILE_VIEW:
                    return profileView(rootView, targetView);
                case VUOP_INVOKE_VIEW_METHOD:
                    return invokeViewMethod(rootView, targetView, in);
                case VUOP_SET_LAYOUT_PARAMETER:
                    return setLayoutParameter(rootView, targetView, in);
                default:
                    return createFailChunk(ERR_INVALID_OP, "Unknown view operation: " + op);
            }
        } else {
            throw new RuntimeException("Unknown packet " + ChunkHandler.name(type));
        }
    
private org.apache.harmony.dalvik.ddmc.ChunkhandleOpenGlTrace(org.apache.harmony.dalvik.ddmc.Chunk request)

        ByteBuffer in = wrapChunk(request);
        GLUtils.setTracingLevel(in.getInt());
        return null;    // empty response
    
private org.apache.harmony.dalvik.ddmc.ChunkinvokeViewMethod(android.view.View rootView, android.view.View targetView, java.nio.ByteBuffer in)
Invokes provided method on the view. The method name and its arguments are passed in as inputs via the byte buffer. The buffer contains:
  1. len(method name)
  2. method name
  3. # of args
  4. arguments: Each argument comprises of a type specifier followed by the actual argument. The type specifier is a single character as used in JNI: (Z - boolean, B - byte, C - char, S - short, I - int, J - long, F - float, D - double).

    The type specifier is followed by the actual value of argument. Booleans are encoded via bytes with 0 indicating false.

Methods that take no arguments need only specify the method name.

        int l = in.getInt();
        String methodName = getString(in, l);

        Class<?>[] argTypes;
        Object[] args;
        if (!in.hasRemaining()) {
            argTypes = new Class<?>[0];
            args = new Object[0];
        } else {
            int nArgs = in.getInt();

            argTypes = new Class<?>[nArgs];
            args = new Object[nArgs];

            for (int i = 0; i < nArgs; i++) {
                char c = in.getChar();
                switch (c) {
                    case 'Z":
                        argTypes[i] = boolean.class;
                        args[i] = in.get() == 0 ? false : true;
                        break;
                    case 'B":
                        argTypes[i] = byte.class;
                        args[i] = in.get();
                        break;
                    case 'C":
                        argTypes[i] = char.class;
                        args[i] = in.getChar();
                        break;
                    case 'S":
                        argTypes[i] = short.class;
                        args[i] = in.getShort();
                        break;
                    case 'I":
                        argTypes[i] = int.class;
                        args[i] = in.getInt();
                        break;
                    case 'J":
                        argTypes[i] = long.class;
                        args[i] = in.getLong();
                        break;
                    case 'F":
                        argTypes[i] = float.class;
                        args[i] = in.getFloat();
                        break;
                    case 'D":
                        argTypes[i] = double.class;
                        args[i] = in.getDouble();
                        break;
                    default:
                        Log.e(TAG, "arg " + i + ", unrecognized type: " + c);
                        return createFailChunk(ERR_INVALID_PARAM,
                                "Unsupported parameter type (" + c + ") to invoke view method.");
                }
            }
        }

        Method method = null;
        try {
            method = targetView.getClass().getMethod(methodName, argTypes);
        } catch (NoSuchMethodException e) {
            Log.e(TAG, "No such method: " + e.getMessage());
            return createFailChunk(ERR_INVALID_PARAM,
                    "No such method: " + e.getMessage());
        }

        try {
            ViewDebug.invokeViewMethod(targetView, method, args);
        } catch (Exception e) {
            Log.e(TAG, "Exception while invoking method: " + e.getCause().getMessage());
            String msg = e.getCause().getMessage();
            if (msg == null) {
                msg = e.getCause().toString();
            }
            return createFailChunk(ERR_EXCEPTION, msg);
        }

        return null;
    
private org.apache.harmony.dalvik.ddmc.ChunklistWindows()
Returns the list of windows owned by this client.

        String[] windowNames = WindowManagerGlobal.getInstance().getViewRootNames();

        int responseLength = 4;                     // # of windows
        for (String name : windowNames) {
            responseLength += 4;                    // length of next window name
            responseLength += name.length() * 2;    // window name
        }

        ByteBuffer out = ByteBuffer.allocate(responseLength);
        out.order(ChunkHandler.CHUNK_ORDER);

        out.putInt(windowNames.length);
        for (String name : windowNames) {
            out.putInt(name.length());
            putString(out, name);
        }

        return new Chunk(CHUNK_VULW, out);
    
private org.apache.harmony.dalvik.ddmc.ChunkprofileView(android.view.View rootView, android.view.View targetView)
Profiles provided view.

        ByteArrayOutputStream b = new ByteArrayOutputStream(32 * 1024);
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(b), 32 * 1024);
        try {
            ViewDebug.profileViewAndChildren(targetView, bw);
        } catch (IOException e) {
            return createFailChunk(1, "Unexpected error while profiling view: " + e.getMessage());
        } finally {
            try {
                bw.close();
            } catch (IOException e) {
                // ignore
            }
        }

        byte[] data = b.toByteArray();
        return new Chunk(CHUNK_VUOP, data, 0, data.length);
    
public static voidregister()

        DdmServer.registerHandler(CHUNK_VUGL, sInstance);
        DdmServer.registerHandler(CHUNK_VULW, sInstance);
        DdmServer.registerHandler(CHUNK_VURT, sInstance);
        DdmServer.registerHandler(CHUNK_VUOP, sInstance);
    
private org.apache.harmony.dalvik.ddmc.ChunksetLayoutParameter(android.view.View rootView, android.view.View targetView, java.nio.ByteBuffer in)

        int l = in.getInt();
        String param = getString(in, l);
        int value = in.getInt();
        try {
            ViewDebug.setLayoutParameter(targetView, param, value);
        } catch (Exception e) {
            Log.e(TAG, "Exception setting layout parameter: " + e);
            return createFailChunk(ERR_EXCEPTION, "Error accessing field "
                        + param + ":" + e.getMessage());
        }

        return null;