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