19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.ddm;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.harmony.dalvik.ddmc.Chunk;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.harmony.dalvik.ddmc.ChunkHandler;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.apache.harmony.dalvik.ddmc.DdmServer;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Debug;
24d693dfa75b7a156898890014e7192a792314b757Siva Velusamyimport android.os.UserHandle;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.nio.ByteBuffer;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
297b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project * Handle "hello" messages and feature discovery.
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class DdmHandleHello extends ChunkHandler {
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int CHUNK_HELO = type("HELO");
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int CHUNK_WAIT = type("WAIT");
357b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project    public static final int CHUNK_FEAT = type("FEAT");
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static DdmHandleHello mInstance = new DdmHandleHello();
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* singleton, do not instantiate */
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private DdmHandleHello() {}
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Register for the messages we're interested in.
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void register() {
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        DdmServer.registerHandler(CHUNK_HELO, mInstance);
487b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project        DdmServer.registerHandler(CHUNK_FEAT, mInstance);
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called when the DDM server connects.  The handler is allowed to
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * send messages to the server.
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void connected() {
5643a17654cf4bfe7f1ec22bd8b7b32daccdf27c09Joe Onorato        if (false)
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.v("ddm-hello", "Connected!");
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
59e577232406649450a513140bf09cb3fc8c3fe046Andy McFadden        if (false) {
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /* test spontaneous transmission */
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            byte[] data = new byte[] { 0, 1, 2, 3, 4, -4, -3, -2, -1, 127 };
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Chunk testChunk =
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                new Chunk(ChunkHandler.type("TEST"), data, 1, data.length-2);
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            DdmServer.sendChunk(testChunk);
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Called when the DDM server disconnects.  Can be used to disable
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * periodic transmissions or clean up saved state.
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void disconnected() {
7343a17654cf4bfe7f1ec22bd8b7b32daccdf27c09Joe Onorato        if (false)
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.v("ddm-hello", "Disconnected!");
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
787b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project     * Handle a chunk of data.
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Chunk handleChunk(Chunk request) {
8143a17654cf4bfe7f1ec22bd8b7b32daccdf27c09Joe Onorato        if (false)
827b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project            Log.v("ddm-heap", "Handling " + name(request.type) + " chunk");
837b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project        int type = request.type;
847b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project
857b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project        if (type == CHUNK_HELO) {
867b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project            return handleHELO(request);
877b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project        } else if (type == CHUNK_FEAT) {
887b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project            return handleFEAT(request);
897b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project        } else {
907b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project            throw new RuntimeException("Unknown packet "
917b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project                + ChunkHandler.name(type));
927b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project        }
937b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project    }
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
957b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project    /*
967b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project     * Handle introductory packet.
977b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project     */
987b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project    private Chunk handleHELO(Chunk request) {
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (false)
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return createFailChunk(123, "This is a test");
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Process the request.
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ByteBuffer in = wrapChunk(request);
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int serverProtoVers = in.getInt();
10843a17654cf4bfe7f1ec22bd8b7b32daccdf27c09Joe Onorato        if (false)
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.v("ddm-hello", "Server version is " + serverProtoVers);
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Create a response.
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String vmName = System.getProperty("java.vm.name", "?");
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String vmVersion = System.getProperty("java.vm.version", "?");
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String vmIdent = vmName + " v" + vmVersion;
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //String appName = android.app.ActivityThread.currentPackageName();
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //if (appName == null)
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //    appName = "unknown";
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String appName = DdmHandleAppName.getAppName();
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
123d693dfa75b7a156898890014e7192a792314b757Siva Velusamy        ByteBuffer out = ByteBuffer.allocate(20
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            + vmIdent.length()*2 + appName.length()*2);
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        out.order(ChunkHandler.CHUNK_ORDER);
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        out.putInt(DdmServer.CLIENT_PROTOCOL_VERSION);
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        out.putInt(android.os.Process.myPid());
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        out.putInt(vmIdent.length());
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        out.putInt(appName.length());
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        putString(out, vmIdent);
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        putString(out, appName);
132d693dfa75b7a156898890014e7192a792314b757Siva Velusamy        out.putInt(UserHandle.myUserId());
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Chunk reply = new Chunk(CHUNK_HELO, out);
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Take the opportunity to inform DDMS if we are waiting for a
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * debugger to attach.
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (Debug.waitingForDebugger())
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sendWAIT(0);
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return reply;
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1467b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project    /*
1477b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project     * Handle request for list of supported features.
1487b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project     */
1497b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project    private Chunk handleFEAT(Chunk request) {
1507b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project        // TODO: query the VM to ensure that support for these features
1517b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project        // is actually compiled in
152e577232406649450a513140bf09cb3fc8c3fe046Andy McFadden        final String[] features = Debug.getVmFeatureList();
1537b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project
15443a17654cf4bfe7f1ec22bd8b7b32daccdf27c09Joe Onorato        if (false)
15598d493588f0ec55b8b6b3762189b2c02f17005c7Andy McFadden            Log.v("ddm-heap", "Got feature list request");
1567b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project
1577b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project        int size = 4 + 4 * features.length;
1587b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project        for (int i = features.length-1; i >= 0; i--)
1597b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project            size += features[i].length() * 2;
1607b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project
1617b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project        ByteBuffer out = ByteBuffer.allocate(size);
1627b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project        out.order(ChunkHandler.CHUNK_ORDER);
1637b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project        out.putInt(features.length);
1647b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project        for (int i = features.length-1; i >= 0; i--) {
1657b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project            out.putInt(features[i].length());
1667b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project            putString(out, features[i]);
1677b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project        }
1687b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project
1697b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project        return new Chunk(CHUNK_FEAT, out);
1707b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project    }
1717b0b1ed979aa665175bf3952c8902ce13c763ab8The Android Open Source Project
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Send up a WAIT chunk.  The only currently defined value for "reason"
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is zero, which means "waiting for a debugger".
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void sendWAIT(int reason) {
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        byte[] data = new byte[] { (byte) reason };
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Chunk waitChunk = new Chunk(CHUNK_WAIT, data, 0, 1);
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        DdmServer.sendChunk(waitChunk);
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
183