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