DdmHandleHello.java revision 945bfb6068d4ac1414a37a3ebe4dc4d02383e38e
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;
24import android.os.UserHandle;
25
26import java.nio.ByteBuffer;
27
28/**
29 * Handle "hello" messages and feature discovery.
30 */
31public class DdmHandleHello extends ChunkHandler {
32
33    public static final int CHUNK_HELO = type("HELO");
34    public static final int CHUNK_WAIT = type("WAIT");
35    public static final int CHUNK_FEAT = type("FEAT");
36
37    private static DdmHandleHello mInstance = new DdmHandleHello();
38
39    private static final String[] FRAMEWORK_FEATURES = new String[] {
40        "opengl-tracing",
41        "view-hierarchy",
42    };
43
44    /* singleton, do not instantiate */
45    private DdmHandleHello() {}
46
47    /**
48     * Register for the messages we're interested in.
49     */
50    public static void register() {
51        DdmServer.registerHandler(CHUNK_HELO, mInstance);
52        DdmServer.registerHandler(CHUNK_FEAT, mInstance);
53    }
54
55    /**
56     * Called when the DDM server connects.  The handler is allowed to
57     * send messages to the server.
58     */
59    public void connected() {
60        if (false)
61            Log.v("ddm-hello", "Connected!");
62
63        if (false) {
64            /* test spontaneous transmission */
65            byte[] data = new byte[] { 0, 1, 2, 3, 4, -4, -3, -2, -1, 127 };
66            Chunk testChunk =
67                new Chunk(ChunkHandler.type("TEST"), data, 1, data.length-2);
68            DdmServer.sendChunk(testChunk);
69        }
70    }
71
72    /**
73     * Called when the DDM server disconnects.  Can be used to disable
74     * periodic transmissions or clean up saved state.
75     */
76    public void disconnected() {
77        if (false)
78            Log.v("ddm-hello", "Disconnected!");
79    }
80
81    /**
82     * Handle a chunk of data.
83     */
84    public Chunk handleChunk(Chunk request) {
85        if (false)
86            Log.v("ddm-heap", "Handling " + name(request.type) + " chunk");
87        int type = request.type;
88
89        if (type == CHUNK_HELO) {
90            return handleHELO(request);
91        } else if (type == CHUNK_FEAT) {
92            return handleFEAT(request);
93        } else {
94            throw new RuntimeException("Unknown packet "
95                + ChunkHandler.name(type));
96        }
97    }
98
99    /*
100     * Handle introductory packet.
101     */
102    private Chunk handleHELO(Chunk request) {
103        if (false)
104            return createFailChunk(123, "This is a test");
105
106        /*
107         * Process the request.
108         */
109        ByteBuffer in = wrapChunk(request);
110
111        int serverProtoVers = in.getInt();
112        if (false)
113            Log.v("ddm-hello", "Server version is " + serverProtoVers);
114
115        /*
116         * Create a response.
117         */
118        String vmName = System.getProperty("java.vm.name", "?");
119        String vmVersion = System.getProperty("java.vm.version", "?");
120        String vmIdent = vmName + " v" + vmVersion;
121
122        //String appName = android.app.ActivityThread.currentPackageName();
123        //if (appName == null)
124        //    appName = "unknown";
125        String appName = DdmHandleAppName.getAppName();
126
127        ByteBuffer out = ByteBuffer.allocate(20
128                            + vmIdent.length()*2 + appName.length()*2);
129        out.order(ChunkHandler.CHUNK_ORDER);
130        out.putInt(DdmServer.CLIENT_PROTOCOL_VERSION);
131        out.putInt(android.os.Process.myPid());
132        out.putInt(vmIdent.length());
133        out.putInt(appName.length());
134        putString(out, vmIdent);
135        putString(out, appName);
136        out.putInt(UserHandle.myUserId());
137
138        Chunk reply = new Chunk(CHUNK_HELO, out);
139
140        /*
141         * Take the opportunity to inform DDMS if we are waiting for a
142         * debugger to attach.
143         */
144        if (Debug.waitingForDebugger())
145            sendWAIT(0);
146
147        return reply;
148    }
149
150    /*
151     * Handle request for list of supported features.
152     */
153    private Chunk handleFEAT(Chunk request) {
154        // TODO: query the VM to ensure that support for these features
155        // is actually compiled in
156        final String[] vmFeatures = Debug.getVmFeatureList();
157
158        if (false)
159            Log.v("ddm-heap", "Got feature list request");
160
161        int size = 4 + 4 * (vmFeatures.length + FRAMEWORK_FEATURES.length);
162        for (int i = vmFeatures.length-1; i >= 0; i--)
163            size += vmFeatures[i].length() * 2;
164        for (int i = FRAMEWORK_FEATURES.length-1; i>= 0; i--)
165            size += FRAMEWORK_FEATURES[i].length() * 2;
166
167        ByteBuffer out = ByteBuffer.allocate(size);
168        out.order(ChunkHandler.CHUNK_ORDER);
169        out.putInt(vmFeatures.length + FRAMEWORK_FEATURES.length);
170        for (int i = vmFeatures.length-1; i >= 0; i--) {
171            out.putInt(vmFeatures[i].length());
172            putString(out, vmFeatures[i]);
173        }
174        for (int i = FRAMEWORK_FEATURES.length-1; i >= 0; i--) {
175            out.putInt(FRAMEWORK_FEATURES[i].length());
176            putString(out, FRAMEWORK_FEATURES[i]);
177        }
178
179        return new Chunk(CHUNK_FEAT, out);
180    }
181
182    /**
183     * Send up a WAIT chunk.  The only currently defined value for "reason"
184     * is zero, which means "waiting for a debugger".
185     */
186    public static void sendWAIT(int reason) {
187        byte[] data = new byte[] { (byte) reason };
188        Chunk waitChunk = new Chunk(CHUNK_WAIT, data, 0, 1);
189        DdmServer.sendChunk(waitChunk);
190    }
191}
192
193