package org.societies.comm.android.ipc; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import android.os.Handler; import android.os.Message; import android.os.Messenger; import android.util.Log; class Client { private Messenger outMessenger, inMessenger; private String id; private Map<String, Object> callbacks = new HashMap<String, Object>(); private Object mutex = new Object(); private Object methodReturn; private boolean hasThrowable = false; private Throwable throwable; private static final String LOG_TAG = Client.class.getName(); private class IncomingHandler extends Handler { @Override public void handleMessage(Message msg) { MessageMethodResult result; switch (msg.what) { case MessageMethodInvocation.WHAT: MessageMethodInvocation msgMethod = new MessageMethodInvocation(msg); Object callback = callbacks.get(msgMethod.callerId()); try { Method method = msgMethod.getMethod(callback.getClass()); Object rv = method.invoke(callback, msgMethod.params()); result = new MessageMethodResult(msgMethod, rv); } catch(Exception e) { result = new MessageMethodResult(msgMethod, e); } try { msg.replyTo.send(result.message()); } catch (Exception e) { Log.e(LOG_TAG, e.getMessage(), e); } break; case MessageMethodResult.WHAT: result = new MessageMethodResult(msg); synchronized(mutex) { if(result.hasThrowable()) { hasThrowable = true; throwable = result.throwable(); } else { hasThrowable = false; methodReturn = result.returnValue(); } mutex.notify(); } break; default: super.handleMessage(msg); } } } public Client(String id, Messenger messenger) { outMessenger = messenger; inMessenger = new MessengerThreadFactory() { @Override protected Handler createHandler() { return new IncomingHandler(); } }.createMessengerThread(); this.id = id; } public Object invoke(String name, Object[] params) throws Throwable{ Message msg = (new MessageMethodInvocation(id, name, params, inMessenger)).message(); waitMethodReturn(msg); return methodReturn; } public Object invoke(String name, Object[] params, Object callback) throws Throwable{ MessageMethodInvocation msg = new MessageMethodInvocation(id, name, params, callback.getClass(), inMessenger); callbacks.put(msg.id(), callback); waitMethodReturn(msg.message()); return methodReturn; } private void waitMethodReturn(Message msg) throws Throwable { synchronized(mutex){ outMessenger.send(msg); mutex.wait(); } if(hasThrowable) throw throwable; } }