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