FileDocCategorySizeDatePackage
SmsDataChannel.javaAPI DocAndroid 1.5 API10567Wed May 06 22:42:46 BST 2009com.android.im.imps

SmsDataChannel

public class SmsDataChannel extends DataChannel implements com.android.im.engine.SmsService.SmsListener, HeartbeatService.Callback

Fields Summary
private com.android.im.engine.SmsService
mSmsService
private String
mSmsAddr
private short
mSmsPort
private long
mLastActive
private SmsSplitter
mSplitter
private SmsAssembler
mAssembler
private LinkedBlockingQueue
mReceiveQueue
private ImpsTransactionManager
mTxManager
private boolean
mConnected
private long
mKeepAliveMillis
private Primitive
mKeepAlivePrimitive
private long
mReplyTimeout
private LinkedList
mPendingTransactions
private Timer
mTimer
Constructors Summary
protected SmsDataChannel(ImpsConnection connection)

        super(connection);

        mTxManager = connection.getTransactionManager();

        ImpsConnectionConfig config = connection.getConfig();
        mReplyTimeout = config.getReplyTimeout();
        mSmsAddr = config.getSmsAddr();
        mSmsPort = (short) config.getSmsPort();
        mSmsService = SystemService.getDefault().getSmsService();

        mParser = new PtsPrimitiveParser();
        try {
            mSerializer = new PtsPrimitiveSerializer(config.getImpsVersion());
        } catch (SerializerException e) {
            throw new ImException(e);
        }
        mSplitter = new SmsSplitter(mSmsService.getMaxSmsLength());
        mAssembler = new SmsAssembler();
        mAssembler.setSmsListener(this);
    
Methods Summary
private voidaddPendingTransaction(java.lang.String transId)

        synchronized (mPendingTransactions) {
            mPendingTransactions.add(new PendingTransaction(transId));
        }
    
voidcheckTimeout()

        synchronized (mPendingTransactions) {
            Iterator<PendingTransaction> iter = mPendingTransactions.iterator();
            while (iter.hasNext()) {
                PendingTransaction tx = iter.next();
                if (tx.isExpired(mReplyTimeout)) {
                    notifyTimeout(tx);
                } else {
                    break;
                }
            }
        }
    
public voidconnect()

        mSmsService.addSmsListener(mSmsAddr, mSmsPort, mAssembler);
        mReceiveQueue = new LinkedBlockingQueue<Primitive>();
        mPendingTransactions = new LinkedList<PendingTransaction>();
        mTimer = new Timer(mReplyTimeout);
        new Thread(mTimer, "SmsDataChannel timer").start();
        mConnected = true;
    
private java.lang.StringextractTrId(byte[] data)

        int transIdStart = 4;
        int index = transIdStart;
        while(Character.isDigit(data[index])) {
            index++;
        }
        int transIdLen = index - transIdStart;
        try {
            return new String(data, transIdStart, transIdLen, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            return null;
        }
    
public longgetLastActiveTime()

        return mLastActive;
    
private voidhandleError(byte[] data, int errCode, java.lang.String info)

        String trId = extractTrId(data);
        if (trId != null) {
            mTxManager.notifyErrorResponse(trId, errCode, info);
            removePendingTransaction(trId);
        }
    
public booleanisSendingQueueEmpty()

        // Always true since we don't have a sending queue.
        return true;
    
private booleanneedSendKeepAlive(long inactiveTime)

        return mKeepAliveMillis - inactiveTime <= 500;
    
private voidnotifyTimeout(com.android.im.imps.SmsDataChannel$PendingTransaction tx)

        String transId = tx.mTransId;
        mTxManager.notifyErrorResponse(transId, ImpsErrorInfo.TIMEOUT,
                "Timeout");
        removePendingTransaction(transId);
    
public voidonIncomingSms(byte[] data)

        try {
            Primitive p = mParser.parse(new ByteArrayInputStream(data));
            mReceiveQueue.put(p);
            removePendingTransaction(p.getTransactionID());
        } catch (ParserException e) {
            handleError(data, ImpsErrorInfo.PARSER_ERROR, e.getLocalizedMessage());
        } catch (IOException e) {
            handleError(data, ImpsErrorInfo.PARSER_ERROR, e.getLocalizedMessage());
        } catch (InterruptedException e) {
            handleError(data, ImpsErrorInfo.UNKNOWN_ERROR, e.getLocalizedMessage());
        }
    
public PrimitivereceivePrimitive()

        return mReceiveQueue.take();
    
private voidremovePendingTransaction(java.lang.String transId)

        synchronized (mPendingTransactions) {
            Iterator<PendingTransaction> iter = mPendingTransactions.iterator();
            while (iter.hasNext()) {
                PendingTransaction tx = iter.next();
                if (tx.mTransId.equals(transId)) {
                    iter.remove();
                    break;
                }
            }
        }
    
public booleanresume()

        return true;
    
public longsendHeartbeat()

        if (!mConnected) {
            return 0;
        }

        long inactiveTime = SystemClock.elapsedRealtime() - mLastActive;
        if (needSendKeepAlive(inactiveTime)) {
            sendKeepAlive();
            return mKeepAliveMillis;
        } else {
            return mKeepAliveMillis - inactiveTime;
        }
    
private voidsendKeepAlive()

        ImpsTransactionManager tm = mConnection.getTransactionManager();
        AsyncTransaction tx = new AsyncTransaction(tm) {
            @Override
            public void onResponseError(ImpsErrorInfo error) {
            }

            @Override
            public void onResponseOk(Primitive response) {
                // Since we never request a new timeout value, the response
                // can be ignored
            }
        };
        tx.sendRequest(mKeepAlivePrimitive);
    
public voidsendPrimitive(Primitive p)

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
            mSerializer.serialize(p, out);
            mSplitter.split(out.toByteArray());
            SmsService smsService =  SystemService.getDefault().getSmsService();
            SendFailureCallback sendFailureCallback
                    = new SendFailureCallback(p.getTransactionID());
            while (mSplitter.hasNext()) {
                smsService.sendSms(mSmsAddr, mSmsPort, mSplitter.getNext(),
                        sendFailureCallback);
            }
            mLastActive = SystemClock.elapsedRealtime();
            addPendingTransaction(p.getTransactionID());
        } catch (IOException e) {
            mTxManager.notifyErrorResponse(p.getTransactionID(),
                    ImpsErrorInfo.SERIALIZER_ERROR, e.getLocalizedMessage());
        } catch (SerializerException e) {
            mTxManager.notifyErrorResponse(p.getTransactionID(),
                    ImpsErrorInfo.SERIALIZER_ERROR, e.getLocalizedMessage());
        }
    
public voidshutdown()

        mSmsService.removeSmsListener(this);
        mTimer.stop();
        mConnected = false;
    
public voidstartKeepAlive(long interval)

        if (!mConnected) {
            throw new IllegalStateException();
        }

        if (interval <= 0) {
            interval = mConnection.getConfig().getDefaultKeepAliveInterval();
        }

        mKeepAliveMillis = interval * 1000;
        if (mKeepAliveMillis < 0) {
            ImpsLog.log("Negative keep alive time. Won't send keep-alive");
        }
        mKeepAlivePrimitive = new Primitive(ImpsTags.KeepAlive_Request);

        HeartbeatService heartbeatService
            = SystemService.getDefault().getHeartbeatService();
        if (heartbeatService != null) {
            heartbeatService.startHeartbeat(this, mKeepAliveMillis);
        }
    
public voidsuspend()

        // do nothing.