1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/*
2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * you may not use this file except in compliance with the License.
6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * You may obtain a copy of the License at
7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and
14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License.
15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage org.apache.harmony.dalvik.ddmc;
18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
19fa5b565a3f6c6d7cbd6106ee8d360304c3a939a3Igor Murashkinimport dalvik.annotation.optimization.FastNative;
20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Collection;
21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.HashMap;
22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Iterator;
23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This represents our connection to the DDM Server.
27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class DdmServer {
29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final int CLIENT_PROTOCOL_VERSION = 1;
31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static HashMap<Integer,ChunkHandler> mHandlerMap =
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        new HashMap<Integer,ChunkHandler>();
34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int CONNECTED = 1;
36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int DISCONNECTED = 2;
37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static volatile boolean mRegistrationComplete = false;
39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static boolean mRegistrationTimedOut = false;
40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Don't instantiate; all members and methods are static.
44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private DdmServer() {}
46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Register an instance of the ChunkHandler class to handle a specific
49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * chunk type.
50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Throws an exception if the type already has a handler registered.
52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static void registerHandler(int type, ChunkHandler handler) {
54c2d0a1f1bd2c6414c29dd44fe240dcf1f45e59b9Elliott Hughes        if (handler == null) {
55c2d0a1f1bd2c6414c29dd44fe240dcf1f45e59b9Elliott Hughes            throw new NullPointerException("handler == null");
56c2d0a1f1bd2c6414c29dd44fe240dcf1f45e59b9Elliott Hughes        }
57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (mHandlerMap) {
58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (mHandlerMap.get(type) != null)
59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new RuntimeException("type " + Integer.toHexString(type)
60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    + " already registered");
61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            mHandlerMap.put(type, handler);
63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Unregister the existing handler for the specified type.
68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the old handler.
70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static ChunkHandler unregisterHandler(int type) {
72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (mHandlerMap) {
73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return mHandlerMap.remove(type);
74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The application must call here after it finishes registering
79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * handlers.
80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static void registrationComplete() {
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // sync on mHandlerMap because it's convenient and makes a kind of
83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // sense
84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (mHandlerMap) {
85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            mRegistrationComplete = true;
86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            mHandlerMap.notifyAll();
87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Send a chunk of data to the DDM server.  This takes the form of a
92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * JDWP "event", which does not elicit a response from the server.
93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Use this for "unsolicited" chunks.
95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static void sendChunk(Chunk chunk) {
97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nativeSendChunk(chunk.type, chunk.data, chunk.offset, chunk.length);
98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /* send a chunk to the DDM server */
101fa5b565a3f6c6d7cbd6106ee8d360304c3a939a3Igor Murashkin    @FastNative
102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    native private static void nativeSendChunk(int type, byte[] data,
103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int offset, int length);
104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /*
106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Called by the VM when the DDM server connects or disconnects.
107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static void broadcast(int event)
109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    {
110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (mHandlerMap) {
111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            Collection values = mHandlerMap.values();
112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            Iterator iter = values.iterator();
113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            while (iter.hasNext()) {
115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                ChunkHandler handler = (ChunkHandler) iter.next();
116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                switch (event) {
117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    case CONNECTED:
118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        handler.connected();
119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        break;
120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    case DISCONNECTED:
121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        handler.disconnected();
122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        break;
123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    default:
124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        throw new UnsupportedOperationException();
125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /*
131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This is called by the VM when a chunk arrives.
132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * For a DDM-aware application, we want to wait until the app has had
134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * a chance to register all of its chunk handlers.  Otherwise, we'll
135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * end up dropping early-arriving packets on the floor.
136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * For a non-DDM-aware application, we'll end up waiting here forever
138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * if DDMS happens to connect.  It's hard to know for sure that
139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * registration isn't going to happen, so we settle for a timeout.
140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static Chunk dispatch(int type, byte[] data, int offset, int length)
142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    {
143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        ChunkHandler handler;
144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (mHandlerMap) {
146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            /*
147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             * If registration hasn't completed, and we haven't timed out
148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             * waiting for it, wait a bit.
149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             */
150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            while (!mRegistrationComplete && !mRegistrationTimedOut) {
151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                //System.out.println("dispatch() waiting for reg");
152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                try {
153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    mHandlerMap.wait(1000);     // 1.0 sec
154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } catch (InterruptedException ie) {
155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    continue;
156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (!mRegistrationComplete) {
159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    /* timed out, don't wait again */
160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    mRegistrationTimedOut = true;
161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            handler = mHandlerMap.get(type);
165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //System.out.println(" dispatch cont");
167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (handler == null) {
169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return null;
170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        Chunk chunk = new Chunk(type, data, offset, length);
173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return handler.handleChunk(chunk);
174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
176