FileDocCategorySizeDatePackage
HandleNativeHeap.javaAPI DocAndroid 1.5 API10254Wed May 06 22:41:08 BST 2009com.android.ddmlib

HandleNativeHeap

public final class HandleNativeHeap extends ChunkHandler
Handle thread status updates.

Fields Summary
public static final int
CHUNK_NHGT
public static final int
CHUNK_NHSG
public static final int
CHUNK_NHST
public static final int
CHUNK_NHEN
private static final HandleNativeHeap
mInst
Constructors Summary
private HandleNativeHeap()


      
    
Methods Summary
public voidclientDisconnected(Client client)
Client went away.

public voidclientReady(Client client)
Client is ready.

public voidhandleChunk(Client client, int type, java.nio.ByteBuffer data, boolean isReply, int msgId)
Chunk handler entry point.


        Log.d("ddm-nativeheap", "handling " + ChunkHandler.name(type));

        if (type == CHUNK_NHGT) {
            handleNHGT(client, data);
        } else if (type == CHUNK_NHST) {
            // start chunk before any NHSG chunk(s)
            client.getClientData().getNativeHeapData().clearHeapData();
        } else if (type == CHUNK_NHEN) {
            // end chunk after NHSG chunk(s)
            client.getClientData().getNativeHeapData().sealHeapData();
        } else if (type == CHUNK_NHSG) {
            handleNHSG(client, data);
        } else {
            handleUnknownChunk(client, type, data, isReply, msgId);
        }

        client.update(Client.CHANGE_NATIVE_HEAP_DATA);
    
private voidhandleNHGT(Client client, java.nio.ByteBuffer data)

        ClientData cd = client.getClientData();

        Log.d("ddm-nativeheap", "NHGT: " + data.limit() + " bytes");

        // TODO - process incoming data and save in "cd"
        byte[] copy = new byte[data.limit()];
        data.get(copy);

        // clear the previous run
        cd.clearNativeAllocationInfo();

        ByteBuffer buffer = ByteBuffer.wrap(copy);
        buffer.order(ByteOrder.LITTLE_ENDIAN);

//        read the header
//        typedef struct Header {
//            uint32_t mapSize;
//            uint32_t allocSize;
//            uint32_t allocInfoSize;
//            uint32_t totalMemory;
//              uint32_t backtraceSize;
//        };

        int mapSize = buffer.getInt();
        int allocSize = buffer.getInt();
        int allocInfoSize = buffer.getInt();
        int totalMemory = buffer.getInt();
        int backtraceSize = buffer.getInt();

        Log.d("ddms", "mapSize: " + mapSize);
        Log.d("ddms", "allocSize: " + allocSize);
        Log.d("ddms", "allocInfoSize: " + allocInfoSize);
        Log.d("ddms", "totalMemory: " + totalMemory);

        cd.setTotalNativeMemory(totalMemory);

        // this means that updates aren't turned on.
        if (allocInfoSize == 0)
          return;

        if (mapSize > 0) {
            byte[] maps = new byte[mapSize];
            buffer.get(maps, 0, mapSize);
            parseMaps(cd, maps);
        }

        int iterations = allocSize / allocInfoSize;

        for (int i = 0 ; i < iterations ; i++) {
            NativeAllocationInfo info = new NativeAllocationInfo(
                    buffer.getInt() /* size */,
                    buffer.getInt() /* allocations */);

            for (int j = 0 ; j < backtraceSize ; j++) {
                long addr = ((long)buffer.getInt()) & 0x00000000ffffffffL;

                info.addStackCallAddress(addr);;
            }

            cd.addNativeAllocation(info);
        }
    
private voidhandleNHSG(Client client, java.nio.ByteBuffer data)

        byte dataCopy[] = new byte[data.limit()];
        data.rewind();
        data.get(dataCopy);
        data = ByteBuffer.wrap(dataCopy);
        client.getClientData().getNativeHeapData().addHeapData(data);

        if (true) {
            return;
        }

        // WORK IN PROGRESS

//        Log.e("ddm-nativeheap", "NHSG: ----------------------------------");
//        Log.e("ddm-nativeheap", "NHSG: " + data.limit() + " bytes");

        byte[] copy = new byte[data.limit()];
        data.get(copy);

        ByteBuffer buffer = ByteBuffer.wrap(copy);
        buffer.order(ByteOrder.BIG_ENDIAN);

        int id = buffer.getInt();
        int unitsize = (int) buffer.get();
        long startAddress = (long) buffer.getInt() & 0x00000000ffffffffL;
        int offset = buffer.getInt();
        int allocationUnitCount = buffer.getInt();

//        Log.e("ddm-nativeheap", "id: " + id);
//        Log.e("ddm-nativeheap", "unitsize: " + unitsize);
//        Log.e("ddm-nativeheap", "startAddress: 0x" + Long.toHexString(startAddress));
//        Log.e("ddm-nativeheap", "offset: " + offset);
//        Log.e("ddm-nativeheap", "allocationUnitCount: " + allocationUnitCount);
//        Log.e("ddm-nativeheap", "end: 0x" +
//                Long.toHexString(startAddress + unitsize * allocationUnitCount));

        // read the usage
        while (buffer.position() < buffer.limit()) {
            int eState = (int)buffer.get() & 0x000000ff;
            int eLen = ((int)buffer.get() & 0x000000ff) + 1;
            //Log.e("ddm-nativeheap", "solidity: " + (eState & 0x7) + " - kind: "
            //        + ((eState >> 3) & 0x7) + " - len: " + eLen);
        }


//        count += unitsize * allocationUnitCount;
//        Log.e("ddm-nativeheap", "count = " + count);

    
private voidparseMaps(ClientData cd, byte[] maps)

        InputStreamReader input = new InputStreamReader(new ByteArrayInputStream(maps));
        BufferedReader reader = new BufferedReader(input);

        String line;

        try {

            // most libraries are defined on several lines, so we need to make sure we parse
            // all the library lines and only add the library at the end
            long startAddr = 0;
            long endAddr = 0;
            String library = null;

            while ((line = reader.readLine()) != null) {
                Log.d("ddms", "line: " + line);
                if (line.length() < 16) {
                    continue;
                }

                try {
                    long tmpStart = Long.parseLong(line.substring(0, 8), 16);
                    long tmpEnd = Long.parseLong(line.substring(9, 17), 16);

                     /*
                      * only check for library addresses as defined in
                      * //device/config/prelink-linux-arm.map
                      */
                    if (tmpStart >= 0x0000000080000000L && tmpStart <= 0x00000000BFFFFFFFL) {

                        int index = line.indexOf('/");

                        if (index == -1)
                            continue;

                        String tmpLib = line.substring(index);

                        if (library == null ||
                                (library != null && tmpLib.equals(library) == false)) {

                            if (library != null) {
                                cd.addNativeLibraryMapInfo(startAddr, endAddr, library);
                                Log.d("ddms", library + "(" + Long.toHexString(startAddr) +
                                        " - " + Long.toHexString(endAddr) + ")");
                            }

                            // now init the new library
                            library = tmpLib;
                            startAddr = tmpStart;
                            endAddr = tmpEnd;
                        } else {
                            // add the new end
                            endAddr = tmpEnd;
                        }
                    }
                } catch (NumberFormatException e) {
                    e.printStackTrace();
                }
            }

            if (library != null) {
                cd.addNativeLibraryMapInfo(startAddr, endAddr, library);
                Log.d("ddms", library + "(" + Long.toHexString(startAddr) +
                        " - " + Long.toHexString(endAddr) + ")");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    
public static voidregister(MonitorThread mt)
Register for the packets we expect to get from the client.

        mt.registerChunkHandler(CHUNK_NHGT, mInst);
        mt.registerChunkHandler(CHUNK_NHSG, mInst);
        mt.registerChunkHandler(CHUNK_NHST, mInst);
        mt.registerChunkHandler(CHUNK_NHEN, mInst);
    
public static voidsendNHGT(Client client)
Send an NHGT (Native Thread GeT) request to the client.


        ByteBuffer rawBuf = allocBuffer(0);
        JdwpPacket packet = new JdwpPacket(rawBuf);
        ByteBuffer buf = getChunkDataBuf(rawBuf);

        // no data in request message

        finishChunkPacket(packet, CHUNK_NHGT, buf.position());
        Log.d("ddm-nativeheap", "Sending " + name(CHUNK_NHGT));
        client.sendAndConsume(packet, mInst);

        rawBuf = allocBuffer(2);
        packet = new JdwpPacket(rawBuf);
        buf = getChunkDataBuf(rawBuf);

        buf.put((byte)HandleHeap.WHEN_GC);
        buf.put((byte)HandleHeap.WHAT_OBJ);

        finishChunkPacket(packet, CHUNK_NHSG, buf.position());
        Log.d("ddm-nativeheap", "Sending " + name(CHUNK_NHSG));
        client.sendAndConsume(packet, mInst);