DdmHandleHello.java revision 406ec15647b7664cadadde41dbaaa10e298c582b
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. This is called during JNI_CreateJavaVM
101     * before frameworks native methods are registered, so be careful not
102     * to call any APIs that depend on frameworks native code.
103     */
104    private Chunk handleHELO(Chunk request) {
105        if (false)
106            return createFailChunk(123, "This is a test");
107
108        /*
109         * Process the request.
110         */
111        ByteBuffer in = wrapChunk(request);
112
113        int serverProtoVers = in.getInt();
114        if (false)
115            Log.v("ddm-hello", "Server version is " + serverProtoVers);
116
117        /*
118         * Create a response.
119         */
120        String vmName = System.getProperty("java.vm.name", "?");
121        String vmVersion = System.getProperty("java.vm.version", "?");
122        String vmIdent = vmName + " v" + vmVersion;
123
124        //String appName = android.app.ActivityThread.currentPackageName();
125        //if (appName == null)
126        //    appName = "unknown";
127        String appName = DdmHandleAppName.getAppName();
128
129        ByteBuffer out = ByteBuffer.allocate(20
130                            + vmIdent.length()*2 + appName.length()*2);
131        out.order(ChunkHandler.CHUNK_ORDER);
132        out.putInt(DdmServer.CLIENT_PROTOCOL_VERSION);
133        out.putInt(android.os.Process.myPid());
134        out.putInt(vmIdent.length());
135        out.putInt(appName.length());
136        putString(out, vmIdent);
137        putString(out, appName);
138        out.putInt(UserHandle.myUserId());
139
140        Chunk reply = new Chunk(CHUNK_HELO, out);
141
142        /*
143         * Take the opportunity to inform DDMS if we are waiting for a
144         * debugger to attach.
145         */
146        if (Debug.waitingForDebugger())
147            sendWAIT(0);
148
149        return reply;
150    }
151
152    /*
153     * Handle request for list of supported features.
154     */
155    private Chunk handleFEAT(Chunk request) {
156        // TODO: query the VM to ensure that support for these features
157        // is actually compiled in
158        final String[] vmFeatures = Debug.getVmFeatureList();
159
160        if (false)
161            Log.v("ddm-heap", "Got feature list request");
162
163        int size = 4 + 4 * (vmFeatures.length + FRAMEWORK_FEATURES.length);
164        for (int i = vmFeatures.length-1; i >= 0; i--)
165            size += vmFeatures[i].length() * 2;
166        for (int i = FRAMEWORK_FEATURES.length-1; i>= 0; i--)
167            size += FRAMEWORK_FEATURES[i].length() * 2;
168
169        ByteBuffer out = ByteBuffer.allocate(size);
170        out.order(ChunkHandler.CHUNK_ORDER);
171        out.putInt(vmFeatures.length + FRAMEWORK_FEATURES.length);
172        for (int i = vmFeatures.length-1; i >= 0; i--) {
173            out.putInt(vmFeatures[i].length());
174            putString(out, vmFeatures[i]);
175        }
176        for (int i = FRAMEWORK_FEATURES.length-1; i >= 0; i--) {
177            out.putInt(FRAMEWORK_FEATURES[i].length());
178            putString(out, FRAMEWORK_FEATURES[i]);
179        }
180
181        return new Chunk(CHUNK_FEAT, out);
182    }
183
184    /**
185     * Send up a WAIT chunk.  The only currently defined value for "reason"
186     * is zero, which means "waiting for a debugger".
187     */
188    public static void sendWAIT(int reason) {
189        byte[] data = new byte[] { (byte) reason };
190        Chunk waitChunk = new Chunk(CHUNK_WAIT, data, 0, 1);
191        DdmServer.sendChunk(waitChunk);
192    }
193}
194
195