gt:       Message message = uiHandler.obtainMessage(1, signalingMessage);
context: /*
   * TeleStax, Open Source Cloud Communications
   * Copyright 2011-2015, Telestax Inc and individual contributors
   * by the @authors tag.
   *
   * This program is free software: you can redistribute it and/or modify
   * under the terms of the GNU Affero General Public License as
   * published by the Free Software Foundation; either version 3 of
   * the License, or (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU Affero General Public License for more details.
   *
   * You should have received a copy of the GNU Affero General Public License
   * along with this program.  If not, see <http://www.gnu.org/licenses/>
   *
   * For questions related to commercial use licensing, please contact sales@telestax.com.
   *
   */
  
  package org.restcomm.android.sdk.SignalingClient;
  
  import android.os.Handler;
  import android.os.Looper;
  import android.os.Message;
  
  import org.restcomm.android.sdk.RCClient;
  import org.restcomm.android.sdk.RCDeviceListener;
  import org.restcomm.android.sdk.SignalingClient.JainSipClient.JainSipCall;
  import org.restcomm.android.sdk.SignalingClient.JainSipClient.JainSipClient;
  import org.restcomm.android.sdk.util.RCLogger;
  
  import java.util.HashMap;
  
  /**
   * SignalingHandler takes care of all the messaging from UI thread -> JainSipClient and the opposite
   */
  class SignalingHandler extends Handler implements JainSipClient.JainSipClientListener, JainSipCall.JainSipCallListener {
     JainSipClient jainSipClient;
     Handler uiHandler;
     private static final String TAG = "SignalingHandler";
  
     public SignalingHandler(Looper looper, Handler uiHandler)
     {
        // instantiate parent Handler, and pass non UI looper remember by default associates this handler with the Looper for the current thread, hence signaling thread
        super(looper);
        this.uiHandler = uiHandler;
        jainSipClient = null;
     }
  
     @Override
     public void handleMessage(Message inputMessage)
     {
        // Gets the image task from the incoming Message object.
        SignalingMessage message = (SignalingMessage) inputMessage.obj;
  
        RCLogger.i(TAG, "handleMessage: type: " + message.type + ", jobId: " + message.jobId);
  
        // all requests apart from OPEN_REQUEST require an initialized jainSipClient
        if (message.type != SignalingMessage.MessageType.OPEN_REQUEST && jainSipClient == null) {
           // wrong usage of API
           throw new RuntimeException("JainSipClient has not been initialized");
        }
  
        if (message.type == SignalingMessage.MessageType.OPEN_REQUEST) {
           if (jainSipClient != null) {
              onClientOpenedReply(message.jobId, RCDeviceListener.RCConnectivityStatus.RCConnectivityStatusNone,
                    RCClient.ErrorCodes.ERROR_DEVICE_ALREADY_OPEN,
                    RCClient.errorText(RCClient.ErrorCodes.ERROR_DEVICE_ALREADY_OPEN));
              return;
           }
           jainSipClient = new JainSipClient(this);
           jainSipClient.open(message.jobId, message.androidContext, message.parameters, this);
        }
        else if (message.type == SignalingMessage.MessageType.CLOSE_REQUEST) {
           jainSipClient.close(message.jobId);
        }
        if (message.type == SignalingMessage.MessageType.RECONFIGURE_REQUEST) {
           jainSipClient.reconfigure(message.jobId, message.parameters, this);
        }
        else if (message.type == SignalingMessage.MessageType.CALL_REQUEST) {
           jainSipClient.call(message.jobId, message.parameters, this);
        }
        else if (message.type == SignalingMessage.MessageType.CALL_DISCONNECT_REQUEST) {
           jainSipClient.disconnect(message.jobId, message.reason, this);
        }
        else if (message.type == SignalingMessage.MessageType.CALL_ACCEPT_REQUEST) {
           jainSipClient.accept(message.jobId, message.parameters, this);
        }
        else if (message.type == SignalingMessage.MessageType.MESSAGE_REQUEST) {
           jainSipClient.sendMessage(message.jobId, message.parameters);
        }
        else if (message.type == SignalingMessage.MessageType.CALL_SEND_DIGITS_REQUEST) {
           jainSipClient.sendDigits(message.jobId, message.dtmfDigits);
        }
     }
  
     // -- JainSipClientListener events
     public void onClientOpenedReply(String jobId, RCDeviceListener.RCConnectivityStatus connectivityStatus, RCClient.ErrorCodes status, String text)
     {
        RCLogger.v(TAG, "onClientOpenedReply: jobId: " + jobId + ", connectivityStatus: " + connectivityStatus + ", status: " + status + ", text: " + text);
  
        SignalingMessage signalingMessage = new SignalingMessage(jobId, SignalingMessage.MessageType.OPEN_REPLY);
        signalingMessage.status = status;  //RCClient.ErrorCodes.SUCCESS;
        signalingMessage.text = text;  //"Success";
        signalingMessage.connectivityStatus = connectivityStatus;
        Message message = uiHandler.obtainMessage(1, signalingMessage);
        message.sendToTarget();
     }
  
     public void onClientErrorReply(String jobId, RCDeviceListener.RCConnectivityStatus connectivityStatus, RCClient.ErrorCodes status, String text)
     {
        RCLogger.v(TAG, "onClientErrorReply: jobId: " + jobId + ", connectivityStatus: " + connectivityStatus + ", status: " + status + ", text: " + text);
  
        SignalingMessage signalingMessage = new SignalingMessage(jobId, SignalingMessage.MessageType.ERROR_EVENT);
        signalingMessage.status = status;
        signalingMessage.text = text;
        signalingMessage.connectivityStatus = connectivityStatus;
        Message message = uiHandler.obtainMessage(1, signalingMessage);
        message.sendToTarget();
     }
  
     public void onClientClosedEvent(String jobId, RCClient.ErrorCodes status, String text)
     {
        RCLogger.v(TAG, "onClientClosedEvent: jobId: " + jobId + ", status: " + status + ", text: " + text);
  
        SignalingMessage signalingMessage = new SignalingMessage(jobId, SignalingMessage.MessageType.CLOSE_REPLY);
        signalingMessage.status = status;  //RCClient.ErrorCodes.SUCCESS;
        signalingMessage.text = text;  //"Success";
        Message message = uiHandler.obtainMessage(1, signalingMessage);
        message.sendToTarget();
  
        // remove reference so that it can be GC'd
        this.jainSipClient = null;
     }
  
     public void onClientReconfigureReply(String jobId, RCDeviceListener.RCConnectivityStatus connectivityStatus, RCClient.ErrorCodes status, String text)
     {
        RCLogger.v(TAG, "onClientReconfigureReply: jobId: " + jobId + ", connectivityStatus: " + connectivityStatus + ", status: " + status + ", text: " + text);
  
        SignalingMessage signalingMessage = new SignalingMessage(jobId, SignalingMessage.MessageType.RECONFIGURE_REPLY);
        signalingMessage.status = status;  //RCClient.ErrorCodes.SUCCESS;
        signalingMessage.text = text;  //"Success";
        signalingMessage.connectivityStatus = connectivityStatus;
        Message message = uiHandler.obtainMessage(1, signalingMessage);
        message.sendToTarget();
     }
  
     public void onClientConnectivityEvent(String jobId, RCDeviceListener.RCConnectivityStatus connectivityStatus)
     {
        RCLogger.v(TAG, "onClientConnectivityEvent: jobId: " + jobId + ", connectivityStatus: " + connectivityStatus);
  
        SignalingMessage signalingMessage = new SignalingMessage(jobId, SignalingMessage.MessageType.CONNECTIVITY_EVENT);
        signalingMessage.connectivityStatus = connectivityStatus;
        Message message = uiHandler.obtainMessage(1, signalingMessage);
        message.sendToTarget();
     }
  
     public void onClientMessageArrivedEvent(String jobId, String peer, String messageText)
     {
        RCLogger.v(TAG, "onClientMessageArrivedEvent: jobId: " + jobId + ", peer: " + peer + ", messageText: " + messageText);
  
        SignalingMessage signalingMessage = new SignalingMessage(jobId, SignalingMessage.MessageType.MESSAGE_INCOMING_EVENT);
        signalingMessage.messageText = messageText;
        signalingMessage.peer = peer;
        Message message = uiHandler.obtainMessage(1, signalingMessage);
        message.sendToTarget();
     }
  
     public void onClientMessageReply(String jobId, RCClient.ErrorCodes status, String text)
     {
        RCLogger.v(TAG, "onClientMessageReply: jobId: " + jobId + ", status: " + status + ", text: " + text);
        SignalingMessage signalingMessage = new SignalingMessage(jobId, SignalingMessage.MessageType.MESSAGE_REPLY);
        signalingMessage.status = status;
        signalingMessage.text = text;
        Message message = uiHandler.obtainMessage(1, signalingMessage);
        message.sendToTarget();
     }
  
     public void onClientRegisteringEvent(String jobId)
     {
        RCLogger.v(TAG, "onClientRegisteringEvent: jobId: " + jobId);
        SignalingMessage signalingMessage = new SignalingMessage(jobId, SignalingMessage.MessageType.REGISTERING_EVENT);
        Message message = uiHandler.obtainMessage(1, signalingMessage);
        message.sendToTarget();
     }
  
     // -- JainSipCallListener events
     public void onCallArrivedEvent(String jobId, String peer, String sdpOffer, HashMap<String, String> customHeaders)
     {
        RCLogger.v(TAG, "onCallArrivedEvent: jobId: " + jobId + ", peer: " + peer + ", sdpOffer: " + sdpOffer);
        SignalingMessage signalingMessage = new SignalingMessage(jobId, SignalingMessage.MessageType.CALL_INCOMING_EVENT);
        signalingMessage.sdp = sdpOffer;
        signalingMessage.customHeaders = customHeaders;
        signalingMessage.peer = peer;
        Message message = uiHandler.obtainMessage(1, signalingMessage);
        message.sendToTarget();
     }
  
     public void onCallOutgoingConnectedEvent(String jobId, String sdpAnswer, HashMap<String, String> customHeaders)
     {
        RCLogger.v(TAG, "onCallOutgoingConnectedEvent: jobId: " + jobId + ", sdpAnswer: " + sdpAnswer);
        SignalingMessage signalingMessage = new SignalingMessage(jobId, SignalingMessage.MessageType.CALL_OUTGOING_CONNECTED_EVENT);
        signalingMessage.sdp = sdpAnswer;
        signalingMessage.customHeaders = customHeaders;
        Message message = uiHandler.obtainMessage(1, signalingMessage);
        message.sendToTarget();
     }
  
     public void onCallIncomingConnectedEvent(String jobId)
     {
        RCLogger.v(TAG, "onCallIncomingConnectedEvent: jobId: " + jobId);
        SignalingMessage signalingMessage = new SignalingMessage(jobId, SignalingMessage.MessageType.CALL_INCOMING_CONNECTED_EVENT);
        Message message = uiHandler.obtainMessage(1, signalingMessage);
        message.sendToTarget();
     }
  
     public void onCallPeerDisconnectedEvent(String jobId)
     {
        RCLogger.v(TAG, "onCallPeerDisconnectedEvent: jobId: " + jobId);
        SignalingMessage signalingMessage = new SignalingMessage(jobId, SignalingMessage.MessageType.CALL_PEER_DISCONNECT_EVENT);
        Message message = uiHandler.obtainMessage(1, signalingMessage);
        message.sendToTarget();
     }
  
     public void onCallLocalDisconnectedEvent(String jobId)
     {
        RCLogger.v(TAG, "onCallLocalDisconnectedEvent: jobId: " + jobId);
        SignalingMessage signalingMessage = new SignalingMessage(jobId, SignalingMessage.MessageType.CALL_LOCAL_DISCONNECT_EVENT);
  