DdmHandleHello.java revision 43a17654cf4bfe7f1ec22bd8b7b32daccdf27c09
1/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.ddm;
18
19import org.apache.harmony.dalvik.ddmc.Chunk;
20import org.apache.harmony.dalvik.ddmc.ChunkHandler;
21import org.apache.harmony.dalvik.ddmc.DdmServer;
22import android.util.Log;
23import android.os.Debug;
24
25import java.nio.ByteBuffer;
26
27/**
28 * Handle "hello" messages and feature discovery.
29 */
30public class DdmHandleHello extends ChunkHandler {
31
32    public static final int CHUNK_HELO = type("HELO");
33    public static final int CHUNK_WAIT = type("WAIT");
34    public static final int CHUNK_FEAT = type("FEAT");
35
36    private static DdmHandleHello mInstance = new DdmHandleHello();
37
38
39    /* singleton, do not instantiate */
40    private DdmHandleHello() {}
41
42    /**
43     * Register for the messages we're interested in.
44     */
45    public static void register() {
46        DdmServer.registerHandler(CHUNK_HELO, mInstance);
47        DdmServer.registerHandler(CHUNK_FEAT, mInstance);
48    }
49
50    /**
51     * Called when the DDM server connects.  The handler is allowed to
52     * send messages to the server.
53     */
54    public void connected() {
55        if (false)
56            Log.v("ddm-hello", "Connected!");
57
58        if (false) {
59            /* test spontaneous transmission */
60            byte[] data = new byte[] { 0, 1, 2, 3, 4, -4, -3, -2, -1, 127 };
61            Chunk testChunk =
62                new Chunk(ChunkHandler.type("TEST"), data, 1, data.length-2);
63            DdmServer.sendChunk(testChunk);
64        }
65    }
66
67    /**
68     * Called when the DDM server disconnects.  Can be used to disable
69     * periodic transmissions or clean up saved state.
70     */
71    public void disconnected() {
72        if (false)
73            Log.v("ddm-hello", "Disconnected!");
74    }
75
76    /**
77     * Handle a chunk of data.
78     */
79    public Chunk handleChunk(Chunk request) {
80        if (false)
81            Log.v("ddm-heap", "Handling " + name(request.type) + " chunk");
82        int type = request.type;
83
84        if (type == CHUNK_HELO) {
85            return handleHELO(request);
86        } else if (type == CHUNK_FEAT) {
87            return handleFEAT(request);
88        } else {
89            throw new RuntimeException("Unknown packet "
90                + ChunkHandler.name(type));
91        }
92    }
93
94    /*
95     * Handle introductory packet.
96     */
97    private Chunk handleHELO(Chunk request) {
98        if (false)
99            return createFailChunk(123, "This is a test");
100
101        /*
102         * Process the request.
103         */
104        ByteBuffer in = wrapChunk(request);
105
106        int serverProtoVers = in.getInt();
107        if (false)
108            Log.v("ddm-hello", "Server version is " + serverProtoVers);
109
110        /*
111         * Create a response.
112         */
113        String vmName = System.getProperty("java.vm.name", "?");
114        String vmVersion = System.getProperty("java.vm.version", "?");
115        String vmIdent = vmName + " v" + vmVersion;
116
117        //String appName = android.app.ActivityThread.currentPackageName();
118        //if (appName == null)
119        //    appName = "unknown";
120        String appName = DdmHandleAppName.getAppName();
121
122        ByteBuffer out = ByteBuffer.allocate(16
123                            + vmIdent.length()*2 + appName.length()*2);
124        out.order(ChunkHandler.CHUNK_ORDER);
125        out.putInt(DdmServer.CLIENT_PROTOCOL_VERSION);
126        out.putInt(android.os.Process.myPid());
127        out.putInt(vmIdent.length());
128        out.putInt(appName.length());
129        putString(out, vmIdent);
130        putString(out, appName);
131
132        Chunk reply = new Chunk(CHUNK_HELO, out);
133
134        /*
135         * Take the opportunity to inform DDMS if we are waiting for a
136         * debugger to attach.
137         */
138        if (Debug.waitingForDebugger())
139            sendWAIT(0);
140
141        return reply;
142    }
143
144    /*
145     * Handle request for list of supported features.
146     */
147    private Chunk handleFEAT(Chunk request) {
148        // TODO: query the VM to ensure that support for these features
149        // is actually compiled in
150        final String[] features = Debug.getVmFeatureList();
151
152        if (false)
153            Log.v("ddm-heap", "Got feature list request");
154
155        int size = 4 + 4 * features.length;
156        for (int i = features.length-1; i >= 0; i--)
157            size += features[i].length() * 2;
158
159        ByteBuffer out = ByteBuffer.allocate(size);
160        out.order(ChunkHandler.CHUNK_ORDER);
161        out.putInt(features.length);
162        for (int i = features.length-1; i >= 0; i--) {
163            out.putInt(features[i].length());
164            putString(out, features[i]);
165        }
166
167        return new Chunk(CHUNK_FEAT, out);
168    }
169
170    /**
171     * Send up a WAIT chunk.  The only currently defined value for "reason"
172     * is zero, which means "waiting for a debugger".
173     */
174    public static void sendWAIT(int reason) {
175        byte[] data = new byte[] { (byte) reason };
176        Chunk waitChunk = new Chunk(CHUNK_WAIT, data, 0, 1);
177        DdmServer.sendChunk(waitChunk);
178    }
179}
180
181