com.android.ddmlib.HandleViewDebug Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ddmlib Show documentation
Show all versions of ddmlib Show documentation
Library providing APIs to talk to Android devices
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.ddmlib;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public final class HandleViewDebug extends ChunkHandler {
/** Enable/Disable tracing of OpenGL calls. */
public static final int CHUNK_VUGL = type("VUGL");
/** List {@link ViewRootImpl}'s of this process. */
public static final int CHUNK_VULW = type("VULW");
/** Operation on view root, first parameter in packet should be one of VURT_* constants */
public static final int CHUNK_VURT = type("VURT");
/** Dump view hierarchy. */
private static final int VURT_DUMP_HIERARCHY = 1;
/** Capture View Layers. */
private static final int VURT_CAPTURE_LAYERS = 2;
/** Dump View Theme. */
private static final int VURT_DUMP_THEME = 3;
/**
* Generic View Operation, first parameter in the packet should be one of the
* VUOP_* constants below.
*/
public static final int CHUNK_VUOP = type("VUOP");
/** Capture View. */
private static final int VUOP_CAPTURE_VIEW = 1;
/** Obtain the Display List corresponding to the view. */
private static final int VUOP_DUMP_DISPLAYLIST = 2;
/** Profile a view. */
private static final int VUOP_PROFILE_VIEW = 3;
/** Invoke a method on the view. */
private static final int VUOP_INVOKE_VIEW_METHOD = 4;
/** Set layout parameter. */
private static final int VUOP_SET_LAYOUT_PARAMETER = 5;
private static final String TAG = "ddmlib"; //$NON-NLS-1$
private static final HandleViewDebug sInstance = new HandleViewDebug();
private static final ViewDumpHandler sViewOpNullChunkHandler =
new NullChunkHandler(CHUNK_VUOP);
private HandleViewDebug() {}
public static void register(MonitorThread mt) {
// TODO: add chunk type for auto window updates
// and register here
mt.registerChunkHandler(CHUNK_VUGL, sInstance);
mt.registerChunkHandler(CHUNK_VULW, sInstance);
mt.registerChunkHandler(CHUNK_VUOP, sInstance);
mt.registerChunkHandler(CHUNK_VURT, sInstance);
}
@Override
public void clientReady(Client client) throws IOException {}
@Override
public void clientDisconnected(Client client) {}
public abstract static class ViewDumpHandler extends ChunkHandler {
private final CountDownLatch mLatch = new CountDownLatch(1);
private final int mChunkType;
public ViewDumpHandler(int chunkType) {
mChunkType = chunkType;
}
@Override
void clientReady(Client client) throws IOException {
}
@Override
void clientDisconnected(Client client) {
}
@Override
void handleChunk(Client client, int type, ByteBuffer data,
boolean isReply, int msgId) {
if (type != mChunkType) {
handleUnknownChunk(client, type, data, isReply, msgId);
return;
}
handleViewDebugResult(data);
mLatch.countDown();
}
protected abstract void handleViewDebugResult(ByteBuffer data);
protected void waitForResult(long timeout, TimeUnit unit) {
try {
mLatch.await(timeout, unit);
} catch (InterruptedException e) {
// pass
}
}
}
public static void listViewRoots(Client client, ViewDumpHandler replyHandler)
throws IOException {
ByteBuffer buf = allocBuffer(8);
JdwpPacket packet = new JdwpPacket(buf);
ByteBuffer chunkBuf = getChunkDataBuf(buf);
chunkBuf.putInt(1);
finishChunkPacket(packet, CHUNK_VULW, chunkBuf.position());
client.sendAndConsume(packet, replyHandler);
}
public static void dumpViewHierarchy(@NonNull Client client, @NonNull String viewRoot,
boolean skipChildren, boolean includeProperties, @NonNull ViewDumpHandler handler)
throws IOException {
ByteBuffer buf = allocBuffer(4 // opcode
+ 4 // view root length
+ viewRoot.length() * 2 // view root
+ 4 // skip children
+ 4); // include view properties
JdwpPacket packet = new JdwpPacket(buf);
ByteBuffer chunkBuf = getChunkDataBuf(buf);
chunkBuf.putInt(VURT_DUMP_HIERARCHY);
chunkBuf.putInt(viewRoot.length());
ByteBufferUtil.putString(chunkBuf, viewRoot);
chunkBuf.putInt(skipChildren ? 1 : 0);
chunkBuf.putInt(includeProperties ? 1 : 0);
finishChunkPacket(packet, CHUNK_VURT, chunkBuf.position());
client.sendAndConsume(packet, handler);
}
public static void captureLayers(@NonNull Client client, @NonNull String viewRoot,
@NonNull ViewDumpHandler handler) throws IOException {
int bufLen = 8 + viewRoot.length() * 2;
ByteBuffer buf = allocBuffer(bufLen);
JdwpPacket packet = new JdwpPacket(buf);
ByteBuffer chunkBuf = getChunkDataBuf(buf);
chunkBuf.putInt(VURT_CAPTURE_LAYERS);
chunkBuf.putInt(viewRoot.length());
ByteBufferUtil.putString(chunkBuf, viewRoot);
finishChunkPacket(packet, CHUNK_VURT, chunkBuf.position());
client.sendAndConsume(packet, handler);
}
private static void sendViewOpPacket(@NonNull Client client, int op, @NonNull String viewRoot,
@NonNull String view, @Nullable byte[] extra, @Nullable ViewDumpHandler handler)
throws IOException {
int bufLen = 4 + // opcode
4 + viewRoot.length() * 2 + // view root strlen + view root
4 + view.length() * 2; // view strlen + view
if (extra != null) {
bufLen += extra.length;
}
ByteBuffer buf = allocBuffer(bufLen);
JdwpPacket packet = new JdwpPacket(buf);
ByteBuffer chunkBuf = getChunkDataBuf(buf);
chunkBuf.putInt(op);
chunkBuf.putInt(viewRoot.length());
ByteBufferUtil.putString(chunkBuf, viewRoot);
chunkBuf.putInt(view.length());
ByteBufferUtil.putString(chunkBuf, view);
if (extra != null) {
chunkBuf.put(extra);
}
finishChunkPacket(packet, CHUNK_VUOP, chunkBuf.position());
if (handler != null) {
client.sendAndConsume(packet, handler);
} else {
client.sendAndConsume(packet);
}
}
public static void profileView(@NonNull Client client, @NonNull String viewRoot,
@NonNull String view, @NonNull ViewDumpHandler handler) throws IOException {
sendViewOpPacket(client, VUOP_PROFILE_VIEW, viewRoot, view, null, handler);
}
public static void captureView(@NonNull Client client, @NonNull String viewRoot,
@NonNull String view, @NonNull ViewDumpHandler handler) throws IOException {
sendViewOpPacket(client, VUOP_CAPTURE_VIEW, viewRoot, view, null, handler);
}
public static void invalidateView(@NonNull Client client, @NonNull String viewRoot,
@NonNull String view) throws IOException {
invokeMethod(client, viewRoot, view, "invalidate");
}
public static void requestLayout(@NonNull Client client, @NonNull String viewRoot,
@NonNull String view) throws IOException {
invokeMethod(client, viewRoot, view, "requestLayout");
}
public static void dumpDisplayList(@NonNull Client client, @NonNull String viewRoot,
@NonNull String view) throws IOException {
sendViewOpPacket(client, VUOP_DUMP_DISPLAYLIST, viewRoot, view, null,
sViewOpNullChunkHandler);
}
public static void dumpTheme(@NonNull Client client, @NonNull String viewRoot,
@NonNull ViewDumpHandler handler)
throws IOException {
ByteBuffer buf = allocBuffer(4 // opcode
+ 4 // view root length
+ viewRoot.length() * 2); // view root
JdwpPacket packet = new JdwpPacket(buf);
ByteBuffer chunkBuf = getChunkDataBuf(buf);
chunkBuf.putInt(VURT_DUMP_THEME);
chunkBuf.putInt(viewRoot.length());
ByteBufferUtil.putString(chunkBuf, viewRoot);
finishChunkPacket(packet, CHUNK_VURT, chunkBuf.position());
client.sendAndConsume(packet, handler);
}
/** A {@link ViewDumpHandler} to use when no response is expected. */
private static class NullChunkHandler extends ViewDumpHandler {
public NullChunkHandler(int chunkType) {
super(chunkType);
}
@Override
protected void handleViewDebugResult(ByteBuffer data) {
}
}
public static void invokeMethod(@NonNull Client client, @NonNull String viewRoot,
@NonNull String view, @NonNull String method, Object... args) throws IOException {
int len = 4 + method.length() * 2;
if (args != null) {
// # of args
len += 4;
// for each argument, we send a char type specifier (2 bytes) and
// the arg value (max primitive size = sizeof(double) = 8
len += 10 * args.length;
}
byte[] extra = new byte[len];
ByteBuffer b = ByteBuffer.wrap(extra);
b.putInt(method.length());
ByteBufferUtil.putString(b, method);
if (args != null) {
b.putInt(args.length);
for (int i = 0; i < args.length; i++) {
Object arg = args[i];
if (arg instanceof Boolean) {
b.putChar('Z');
b.put((byte) ((Boolean) arg ? 1 : 0));
} else if (arg instanceof Byte) {
b.putChar('B');
b.put((Byte) arg);
} else if (arg instanceof Character) {
b.putChar('C');
b.putChar((Character) arg);
} else if (arg instanceof Short) {
b.putChar('S');
b.putShort((Short) arg);
} else if (arg instanceof Integer) {
b.putChar('I');
b.putInt((Integer) arg);
} else if (arg instanceof Long) {
b.putChar('J');
b.putLong((Long) arg);
} else if (arg instanceof Float) {
b.putChar('F');
b.putFloat((Float) arg);
} else if (arg instanceof Double) {
b.putChar('D');
b.putDouble((Double) arg);
} else {
Log.e(TAG, "View method invocation only supports primitive arguments, supplied: " + arg);
return;
}
}
}
sendViewOpPacket(client, VUOP_INVOKE_VIEW_METHOD, viewRoot, view, extra,
sViewOpNullChunkHandler );
}
public static void setLayoutParameter(@NonNull Client client, @NonNull String viewRoot,
@NonNull String view, @NonNull String parameter, int value) throws IOException {
int len = 4 + parameter.length() * 2 + 4;
byte[] extra = new byte[len];
ByteBuffer b = ByteBuffer.wrap(extra);
b.putInt(parameter.length());
ByteBufferUtil.putString(b, parameter);
b.putInt(value);
sendViewOpPacket(client, VUOP_SET_LAYOUT_PARAMETER, viewRoot, view, extra,
sViewOpNullChunkHandler);
}
@Override
public void handleChunk(Client client, int type, ByteBuffer data,
boolean isReply, int msgId) {
}
public static void sendStartGlTracing(Client client) throws IOException {
ByteBuffer buf = allocBuffer(4);
JdwpPacket packet = new JdwpPacket(buf);
ByteBuffer chunkBuf = getChunkDataBuf(buf);
chunkBuf.putInt(1);
finishChunkPacket(packet, CHUNK_VUGL, chunkBuf.position());
client.sendAndConsume(packet);
}
public static void sendStopGlTracing(Client client) throws IOException {
ByteBuffer buf = allocBuffer(4);
JdwpPacket packet = new JdwpPacket(buf);
ByteBuffer chunkBuf = getChunkDataBuf(buf);
chunkBuf.putInt(0);
finishChunkPacket(packet, CHUNK_VUGL, chunkBuf.position());
client.sendAndConsume(packet);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy