aboutsummaryrefslogtreecommitdiffstats
path: root/apps/SdkController/SdkControllerApp/src/com/android/tools/sdkcontroller/handlers/BaseHandler.java
diff options
context:
space:
mode:
Diffstat (limited to 'apps/SdkController/SdkControllerApp/src/com/android/tools/sdkcontroller/handlers/BaseHandler.java')
-rwxr-xr-xapps/SdkController/SdkControllerApp/src/com/android/tools/sdkcontroller/handlers/BaseHandler.java187
1 files changed, 155 insertions, 32 deletions
diff --git a/apps/SdkController/SdkControllerApp/src/com/android/tools/sdkcontroller/handlers/BaseHandler.java b/apps/SdkController/SdkControllerApp/src/com/android/tools/sdkcontroller/handlers/BaseHandler.java
index a89eefd..0e30c4d 100755
--- a/apps/SdkController/SdkControllerApp/src/com/android/tools/sdkcontroller/handlers/BaseHandler.java
+++ b/apps/SdkController/SdkControllerApp/src/com/android/tools/sdkcontroller/handlers/BaseHandler.java
@@ -18,8 +18,13 @@ package com.android.tools.sdkcontroller.handlers;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.atomic.AtomicInteger;
import android.content.Context;
+import android.os.Message;
+import android.util.Log;
import com.android.tools.sdkcontroller.lib.EmulatorConnection;
import com.android.tools.sdkcontroller.lib.EmulatorListener;
@@ -31,9 +36,35 @@ import com.android.tools.sdkcontroller.service.ControllerService;
* <p/>
* The {@link ControllerService} can deal with several handlers, each have a specific
* purpose as described by {@link HandlerType}.
+ * <p/>
+ * The {@link BaseHandler} class adds support for activities to connect by providing
+ * an {@link android.os.Handler} (which we'll call a "UI Handler" to differentiate it
+ * from our "Service Handler"). The service handler will provide events via this
+ * UI handler directly on the activity's UI thread.
+ * <p/>
+ * The {@link BaseHandler} keeps track of the current {@link EmulatorConnection} given
+ * via {@link #onStart(EmulatorConnection, Context)}.
+ * <p/>
+ * The {@link BaseHandler} provides a simple way for activities to send event messages
+ * back to the emulator by using {@link #sendEventToEmulator(String)}. This method
+ * is safe to call from any thread, even the UI thread.
*/
public abstract class BaseHandler {
+ protected static final boolean DEBUG = false;
+ protected static final String TAG = null;
+
+ private EmulatorConnection mConnection;
+
+ private final AtomicInteger mEventCount = new AtomicInteger(0);
+ private volatile boolean mRunEventQueue = true;
+ private final BlockingQueue<String> mEventQueue = new LinkedBlockingQueue<String>();
+ private static String EVENT_QUEUE_END = "@end@";
+ private final List<android.os.Handler> mUiHandlers = new ArrayList<android.os.Handler>();
+ private final HandlerType mHandlerType;
+ private final Thread mEventThread;
+ private int mPort;
+
/**
* The type of action that this handler manages.
*/
@@ -46,13 +77,48 @@ public abstract class BaseHandler {
}
/**
- * Returns the type of this handler.
+ * Initializes a new base handler.
+ *
+ * @param type A non-null {@link HandlerType} value.
+ * @param port A non-null communication port number.
+ */
+ protected BaseHandler(HandlerType type, int port) {
+ mHandlerType = type;
+ mPort = port;
+
+ final String name = type.toString();
+ mEventThread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ if (DEBUG) Log.d(TAG, "EventThread.started-" + name);
+ while(mRunEventQueue) {
+ try {
+ String msg = mEventQueue.take();
+ if (msg != null && mConnection != null && !msg.equals(EVENT_QUEUE_END)) {
+ mConnection.sendNotification(msg);
+ mEventCount.incrementAndGet();
+ }
+ } catch (InterruptedException e) {
+ Log.e(TAG, "EventThread-" + name, e);
+ }
+ }
+ if (DEBUG) Log.d(TAG, "EventThread.terminate-" + name);
+ }
+ }, "EventThread-" + name);
+ }
+
+ /**
+ * Returns the type of this handler, as given to the constructor.
+ *
* @return One of the {@link HandlerType} values.
*/
- public abstract HandlerType getType();
+ public HandlerType getType() {
+ return mHandlerType;
+ }
/**
- * The communication port used by this handler to communicate with the emulator.
+ * Returns he communication port used by this handler to communicate with the emulator,
+ * as given to the constructor.
* <p/>
* Note that right now we have 2 handlers that each use their own port. The goal is
* to move to a single-connection mechanism where all the handlers' data will be
@@ -60,13 +126,28 @@ public abstract class BaseHandler {
*
* @return A non-null port value.
*/
- public abstract int getPort();
+ public int getPort() {
+ return mPort;
+ }
+
+ /**
+ * Returns the last {@link EmulatorConnection} passed to
+ * {@link #onStart(EmulatorConnection, Context)}.
+ * It becomes null when {@link #onStop()} is called.
+ *
+ * @return The current {@link EmulatorConnection}.
+ */
+ public EmulatorConnection getConnection() {
+ return mConnection;
+ }
/**
* Called once the {@link EmulatorConnection} has been successfully initialized.
* <p/>
* Note that this will <em>not</em> be called if the {@link EmulatorConnection}
* fails to bind to the underlying socket.
+ * <p/>
+ * This base implementation keeps tracks of the connection.
*
* @param connection The connection that has just been created.
* A handler might want to use this to send data to the emulator via
@@ -74,13 +155,45 @@ public abstract class BaseHandler {
* need to be particularly careful in <em>not</em> sending network data
* from the main UI thread.
* @param context The controller service' context.
+ * @see #getConnection()
*/
- public abstract void onStart(EmulatorConnection connection, Context context);
+ public void onStart(EmulatorConnection connection, Context context) {
+ assert connection != null;
+ mConnection = connection;
+ mRunEventQueue = true;
+ mEventThread.start();
+ }
/**
* Called once the {@link EmulatorConnection} is being disconnected.
+ * This nullifies the connection returned by {@link #getConnection()}.
*/
- public abstract void onStop();
+ public void onStop() {
+ // Stop the message queue
+ mConnection = null;
+ if (mRunEventQueue) {
+ mRunEventQueue = false;
+ mEventQueue.offer(EVENT_QUEUE_END);
+ }
+ }
+
+ public int getEventSentCount() {
+ return mEventCount.get();
+ }
+
+ /**
+ * Utility for handlers or activities to sends a string event to the emulator.
+ * This method is safe for the activity to call from any thread, including the UI thread.
+ *
+ * @param msg Event message. Must not be null.
+ */
+ public void sendEventToEmulator(String msg) {
+ try {
+ mEventQueue.put(msg);
+ } catch (InterruptedException e) {
+ Log.e(TAG, "EventQueue.put", e);
+ }
+ }
// ------------
// Interaction from the emulator connection towards the handler
@@ -103,51 +216,61 @@ public abstract class BaseHandler {
// Interaction from handler towards listening UI
/**
- * Interface to be implemented by activities that use this handler.
- * This is used by the handler to send event data to any UI.
+ * Indicates whether the given UI handler is already registered with the handler.
+ *
+ * @param uiHandler The UI handler.
+ * @return True if the UI handler is not null and already registered.
*/
- public interface UiListener {
- public void onHandlerEvent(int event, Object...params);
+ public boolean hasUiHandler(android.os.Handler uiHandler) {
+ return uiHandler != null && mUiHandlers.contains(uiHandler);
}
- private final List<UiListener> mUiListeners = new ArrayList<UiListener>();
-
/**
- * Registers a new UI listener.
+ * Registers a new UI handler.
*
- * @param listener A non-null UI listener to register.
- * Ignored if the listener is null or already registered.
+ * @param uiHandler A non-null UI handler to register.
+ * Ignored if the UI handler is null or already registered.
*/
- public void addUiListener(UiListener listener) {
- assert listener != null;
- if (listener != null) {
- if (!mUiListeners.contains(listener)) {
- mUiListeners.add(listener);
+ public void addUiHandler(android.os.Handler uiHandler) {
+ assert uiHandler != null;
+ if (uiHandler != null) {
+ if (!mUiHandlers.contains(uiHandler)) {
+ mUiHandlers.add(uiHandler);
}
}
}
-
/**
- * Unregisters an UI listener.
+ * Unregisters an UI handler.
*
- * @param listener A non-null UI listener to unregister.
+ * @param uiHandler A non-null UI listener to unregister.
* Ignored if the listener is null or already registered.
*/
- public void removeUiListener(UiListener listener) {
- assert listener != null;
- mUiListeners.remove(listener);
+ public void removeUiHandler(android.os.Handler uiHandler) {
+ assert uiHandler != null;
+ mUiHandlers.remove(uiHandler);
+ }
+
+ /**
+ * Protected method to be used by handlers to send an event to all UI handlers.
+ *
+ * @param event An integer event code with no specific parameters.
+ * To be defined by the handler itself.
+ */
+ protected void notifyUiHandlers(int event) {
+ for (android.os.Handler uiHandler : mUiHandlers) {
+ uiHandler.sendEmptyMessage(event);
+ }
}
/**
- * Protected method to be used by handlers to send an event to any listening UI.
+ * Protected method to be used by handlers to send an event to all UI handlers.
*
- * @param event The event code. To be defined by the handler itself.
- * @param params Any parameters that the handler defines for this event.
+ * @param msg An event with parameters. To be defined by the handler itself.
*/
- protected void notifyUi(int event, Object...params) {
- for (UiListener listener : mUiListeners) {
- listener.onHandlerEvent(event, params);
+ protected void notifyUiHandlers(Message msg) {
+ for (android.os.Handler uiHandler : mUiHandlers) {
+ uiHandler.sendMessage(msg);
}
}