• 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     private static final String[] FRAMEWORK_FEATURES = new String[] {
40         "opengl-tracing",
41         "view-hierarchy",
42     };
43 
44     /* singleton, do not instantiate */
DdmHandleHello()45     private DdmHandleHello() {}
46 
47     /**
48      * Register for the messages we're interested in.
49      */
register()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      */
connected()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      */
disconnected()76     public void disconnected() {
77         if (false)
78             Log.v("ddm-hello", "Disconnected!");
79     }
80 
81     /**
82      * Handle a chunk of data.
83      */
handleChunk(Chunk request)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      */
handleHELO(Chunk request)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      */
handleFEAT(Chunk request)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      */
sendWAIT(int reason)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