/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.nfc;

import android.content.Intent;
import android.content.pm.UserInfo;

import com.android.nfc.beam.BeamManager;
import com.android.nfc.beam.BeamSendService;
import com.android.nfc.beam.BeamTransferRecord;

import android.os.UserManager;
import com.android.nfc.sneptest.ExtDtaSnepServer;
import com.android.nfc.sneptest.DtaSnepClient;
import com.android.nfc.echoserver.EchoServer;
import com.android.nfc.handover.HandoverClient;
import com.android.nfc.handover.HandoverDataParser;
import com.android.nfc.handover.HandoverServer;
import com.android.nfc.ndefpush.NdefPushClient;
import com.android.nfc.ndefpush.NdefPushServer;
import com.android.nfc.snep.SnepClient;
import com.android.nfc.snep.SnepMessage;
import com.android.nfc.snep.SnepServer;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.nfc.BeamShareData;
import android.nfc.IAppCallback;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.os.UserHandle;
import android.util.Log;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.io.UnsupportedEncodingException;

/**
 * Interface to listen for P2P events.
 * All callbacks are made from the UI thread.
 */
interface P2pEventListener {
    /**
     * Indicates the user has expressed an intent to share
     * over NFC, but a remote device has not come into range
     * yet. Prompt the user to NFC tap.
     */
    public void onP2pNfcTapRequested();

    /**
     * Indicates the user has expressed an intent to share over
     * NFC, but the link hasn't come up yet and we no longer
     * want to wait for it
     */
    public void onP2pTimeoutWaitingForLink();

    /**
     * Indicates a P2P device is in range.
     * <p>onP2pInRange() and onP2pOutOfRange() will always be called
     * alternately.
     */
    public void onP2pInRange();

    /**
     * Called when a NDEF payload is prepared to send, and confirmation is
     * required. Call Callback.onP2pSendConfirmed() to make the confirmation.
     */
    public void onP2pSendConfirmationRequested();

    /**
     * Called to indicate a send was successful.
     */
    public void onP2pSendComplete();

    /**
     *
     * Called to indicate the link has broken while we were trying to send
     * a message. We'll start a debounce timer for the user to get the devices
     * back together. UI may show a hint to achieve that
     */
    public void onP2pSendDebounce();

    /**
     * Called to indicate a link has come back up after being temporarily
     * broken, and sending is resuming
     */
    public void onP2pResumeSend();

    /**
     * Called to indicate the remote device does not support connection handover
     */
    public void onP2pHandoverNotSupported();

    /**
     * Called to indicate the device is busy with another handover transfer
     */
    public void onP2pHandoverBusy();

    /**
     * Called to indicate a receive was successful.
     */
    public void onP2pReceiveComplete(boolean playSound);

    /**
     * Indicates the P2P device went out of range.
     */
    public void onP2pOutOfRange();

    /**
     * Indicates the P2P Beam UI is in idle mode.
     */
    public boolean isP2pIdle();

    public interface Callback {
        public void onP2pSendConfirmed();
        public void onP2pCanceled();
    }
}

/**
 * Manages sending and receiving NDEF message over LLCP link.
 * Does simple debouncing of the LLCP link - so that even if the link
 * drops and returns the user does not know.
 */
class P2pLinkManager implements Handler.Callback, P2pEventListener.Callback {
    static final String TAG = "NfcP2pLinkManager";
    static final boolean DBG = true;

    /** Include this constant as a meta-data entry in the manifest
     *  of an application to disable beaming the market/AAR link, like this:
     *  <pre>{@code
     *  <application ...>
     *      <meta-data android:name="android.nfc.disable_beam_default"
     *          android:value="true" />
     *  </application>
     *  }</pre>
     */
    static final String DISABLE_BEAM_DEFAULT = "android.nfc.disable_beam_default";

    /** Enables the LLCP EchoServer, which can be used to test the android
     * LLCP stack against nfcpy.
     */
    static final boolean ECHOSERVER_ENABLED = false;

    // TODO dynamically assign SAP values
    static final int NDEFPUSH_SAP = 0x10;
    static final int HANDOVER_SAP = 0x14;

    static final int LINK_SEND_PENDING_DEBOUNCE_MS = 3000;
    static final int LINK_SEND_CONFIRMED_DEBOUNCE_MS = 5000;
    static final int LINK_SEND_COMPLETE_DEBOUNCE_MS = 500;
    static final int LINK_SEND_CANCELED_DEBOUNCE_MS = 250;

    // The amount of time we wait for the link to come up
    // after a user has manually invoked Beam.
    static final int WAIT_FOR_LINK_TIMEOUT_MS = 10000;

    static final int MSG_DEBOUNCE_TIMEOUT = 1;
    static final int MSG_RECEIVE_COMPLETE = 2;
    static final int MSG_RECEIVE_HANDOVER = 3;
    static final int MSG_SEND_COMPLETE = 4;
    static final int MSG_START_ECHOSERVER = 5;
    static final int MSG_STOP_ECHOSERVER = 6;
    static final int MSG_HANDOVER_NOT_SUPPORTED = 7;
    static final int MSG_SHOW_CONFIRMATION_UI = 8;
    static final int MSG_WAIT_FOR_LINK_TIMEOUT = 9;
    static final int MSG_HANDOVER_BUSY = 10;

    // values for mLinkState
    static final int LINK_STATE_DOWN = 1;
    static final int LINK_STATE_UP = 2;
    static final int LINK_STATE_DEBOUNCE = 3;

    // values for mSendState
    static final int SEND_STATE_NOTHING_TO_SEND = 1;
    static final int SEND_STATE_NEED_CONFIRMATION = 2;
    static final int SEND_STATE_PENDING = 3;
    static final int SEND_STATE_SENDING = 4;
    static final int SEND_STATE_COMPLETE = 5;
    static final int SEND_STATE_CANCELED = 6;

    // return values for doSnepProtocol
    static final int SNEP_SUCCESS = 0;
    static final int SNEP_FAILURE = 1;

    // return values for doHandover
    static final int HANDOVER_SUCCESS = 0;
    static final int HANDOVER_FAILURE = 1;
    static final int HANDOVER_UNSUPPORTED = 2;
    static final int HANDOVER_BUSY = 3;

    final NdefPushServer mNdefPushServer;
    final SnepServer mDefaultSnepServer;
    final HandoverServer mHandoverServer;
    final EchoServer mEchoServer;
    final Context mContext;
    final P2pEventListener mEventListener;
    final Handler mHandler;
    final HandoverDataParser mHandoverDataParser;
    final ForegroundUtils mForegroundUtils;

    final int mDefaultMiu;
    final int mDefaultRwSize;

    // Locked on NdefP2pManager.this
    PackageManager mPackageManager;
    int mLinkState;
    int mSendState;  // valid during LINK_STATE_UP or LINK_STATE_DEBOUNCE
    boolean mIsSendEnabled;
    boolean mIsReceiveEnabled;
    NdefMessage mMessageToSend;  // not valid in SEND_STATE_NOTHING_TO_SEND
    Uri[] mUrisToSend;  // not valid in SEND_STATE_NOTHING_TO_SEND
    UserHandle mUserHandle; // not valid in SEND_STATE_NOTHING_TO_SEND
    int mSendFlags; // not valid in SEND_STATE_NOTHING_TO_SEND
    IAppCallback mCallbackNdef;
    int mNdefCallbackUid;
    SendTask mSendTask;
    SharedPreferences mPrefs;
    SnepClient mSnepClient;
    HandoverClient mHandoverClient;
    NdefPushClient mNdefPushClient;
    ConnectTask mConnectTask;
    boolean mLlcpServicesConnected;
    long mLastLlcpActivationTime;
    byte mPeerLlcpVersion;
    // for DTA Mode
    private int mDtaMiu;
    private int mDtaRwSize;
    private int mServiceSap;
    private int mTestCaseID;
    private String mServiceName;
    private ExtDtaSnepServer mExtDtaSnepServer = null;
    private DtaSnepClient mDtaSnepClient = null;
    private boolean mClientEnabled = false;
    private boolean mServerEnabled = false;
    private boolean mExtDtaSnepServerRunning = false;
    private boolean mPutBeforeGet = false;

    public P2pLinkManager(Context context, HandoverDataParser handoverDataParser, int defaultMiu,
            int defaultRwSize) {
        mNdefPushServer = new NdefPushServer(NDEFPUSH_SAP, mNppCallback);
        mDefaultSnepServer = new SnepServer(mDefaultSnepCallback, defaultMiu, defaultRwSize);
        mHandoverServer = new HandoverServer(context, HANDOVER_SAP, handoverDataParser, mHandoverCallback);

        if (ECHOSERVER_ENABLED) {
            mEchoServer = new EchoServer();
        } else {
            mEchoServer = null;
        }
        mPackageManager = context.getPackageManager();
        mContext = context;
        mEventListener = new P2pEventManager(context, this);
        mHandler = new Handler(this);
        mLinkState = LINK_STATE_DOWN;
        mSendState = SEND_STATE_NOTHING_TO_SEND;
        mIsSendEnabled = false;
        mIsReceiveEnabled = false;
        mPrefs = context.getSharedPreferences(NfcService.PREF, Context.MODE_PRIVATE);
        mHandoverDataParser = handoverDataParser;
        mDefaultMiu = defaultMiu;
        mDefaultRwSize = defaultRwSize;
        mLlcpServicesConnected = false;
        mNdefCallbackUid = -1;
        mForegroundUtils = ForegroundUtils.getInstance();
     }

    /**
     * May be called from any thread.
     * Assumes that NFC is already on if any parameter is true.
     */
    public void enableDisable(boolean sendEnable, boolean receiveEnable) {
        synchronized (this) {
            if (!mIsReceiveEnabled && receiveEnable) {
                mDefaultSnepServer.start();
                mNdefPushServer.start();
                mHandoverServer.start();
                if (mEchoServer != null) {
                    mHandler.sendEmptyMessage(MSG_START_ECHOSERVER);
                }
            } else if (mIsReceiveEnabled && !receiveEnable) {
                if (DBG) Log.d(TAG, "enableDisable: llcp deactivate");
                onLlcpDeactivated ();
                mDefaultSnepServer.stop();
                mNdefPushServer.stop();
                mHandoverServer.stop();
                if (mEchoServer != null) {
                    mHandler.sendEmptyMessage(MSG_STOP_ECHOSERVER);
                }
                if (mExtDtaSnepServerRunning)
                    disableExtDtaSnepServer();
            }
            mIsSendEnabled = sendEnable;
            mIsReceiveEnabled = receiveEnable;
        }
    }

    /**
     * To Enable DTA SNEP Server for NFC Forum testing
     */
    public void enableExtDtaSnepServer(String serviceName, int serviceSap, int miu, int rwSize,int testCaseId) {
        if (DBG) Log.d(TAG, "Enabling Extended DTA Server");
        mServiceName = serviceName;
        mServiceSap = serviceSap;
        mDtaMiu = miu;
        mDtaRwSize  = rwSize;
        mTestCaseID = testCaseId;
        synchronized (this) {
            if(mExtDtaSnepServer == null)
            mExtDtaSnepServer = new ExtDtaSnepServer(mServiceName, mServiceSap, mDtaMiu, mDtaRwSize,
                                                     mExtDtaSnepServerCallback,mContext, mTestCaseID);
            mExtDtaSnepServer.start();
            mExtDtaSnepServerRunning = true;
        }
        mServerEnabled = true;
    }

    /**
     * To Disable DTA SNEP Server for NFC Forum testing
     */
    public void disableExtDtaSnepServer() {
        if (DBG) Log.d(TAG, "Disabling Extended DTA Server");
        if (!mExtDtaSnepServerRunning)
            return;
        synchronized (this) {
            mExtDtaSnepServer.stop();
            mExtDtaSnepServer = null;
            mExtDtaSnepServerRunning = false;
        }
        mServerEnabled = false;
    }

    /**
     * To Enable DTA SNEP Client for NFC Forum testing
     */
    public void enableDtaSnepClient(String serviceName, int miu, int rwSize, int testCaseId) {
        if (DBG) Log.d(TAG, "enableDtaSnepClient");
        mClientEnabled = true;
        mServiceName = serviceName;
        mServiceSap = -1;
        mDtaMiu = miu;
        mDtaRwSize = rwSize;
        mTestCaseID = testCaseId;
    }

    /**
     * To Disable DTA SNEP Client for NFC Forum testing
     */
    public void disableDtaSnepClient() {
        if (DBG) Log.d(TAG, "disableDtaSnepClient");
        mDtaSnepClient = null;
        mClientEnabled = false;
    }


    /**
     * May be called from any thread.
     * @return whether the LLCP link is in an active or debounce state
     */
    public boolean isLlcpActive() {
        synchronized (this) {
            return mLinkState != LINK_STATE_DOWN;
        }
    }

    /**
     * Set NDEF callback for sending.
     * May be called from any thread.
     * NDEF callbacks may be set at any time (even if NFC is
     * currently off or P2P send is currently off). They will become
     * active as soon as P2P send is enabled.
     */
    public void setNdefCallback(IAppCallback callbackNdef, int callingUid) {
        synchronized (this) {
            mCallbackNdef = callbackNdef;
            mNdefCallbackUid = callingUid;
        }
    }


    public void onManualBeamInvoke(BeamShareData shareData) {
        synchronized (P2pLinkManager.this)    {
            if (mLinkState != LINK_STATE_DOWN) {
                return;
            }
            if (mForegroundUtils.getForegroundUids().contains(mNdefCallbackUid)) {
                // Try to get data from the registered NDEF callback
                prepareMessageToSend(false);
            } else {
                mMessageToSend = null;
                mUrisToSend = null;
            }
            if (mMessageToSend == null && mUrisToSend == null && shareData != null) {
                // No data from the NDEF callback, get data from ShareData
                if (shareData.uris != null) {
                    mUrisToSend = shareData.uris;
                } else if (shareData.ndefMessage != null) {
                    mMessageToSend = shareData.ndefMessage;
                }

                mUserHandle = shareData.userHandle;
            }
            if (mMessageToSend != null ||
                    (mUrisToSend != null && mHandoverDataParser.isHandoverSupported())) {
                mSendState = SEND_STATE_PENDING;
                mEventListener.onP2pNfcTapRequested();
                scheduleTimeoutLocked(MSG_WAIT_FOR_LINK_TIMEOUT, WAIT_FOR_LINK_TIMEOUT_MS);
            }
        }
    }

    /**
     * Must be called on UI Thread.
     */
    public void onLlcpActivated(byte peerLlcpVersion) {
        Log.i(TAG, "LLCP activated");
        synchronized (P2pLinkManager.this) {
            if (mEchoServer != null) {
                mEchoServer.onLlcpActivated();
            }
            mLastLlcpActivationTime = SystemClock.elapsedRealtime();
            mPeerLlcpVersion = peerLlcpVersion;
            switch (mLinkState) {
                case LINK_STATE_DOWN:
                    if (!mEventListener.isP2pIdle() && mSendState != SEND_STATE_PENDING) {
                        break;
                    }

                    if (DBG) Log.d(TAG, "onP2pInRange()");
                    // Start taking a screenshot
                    mEventListener.onP2pInRange();
                    mLinkState = LINK_STATE_UP;
                    // If we had a pending send (manual Beam invoke),
                    // mark it as sending
                    if (mSendState == SEND_STATE_PENDING) {
                        mSendState = SEND_STATE_SENDING;
                        mHandler.removeMessages(MSG_WAIT_FOR_LINK_TIMEOUT);
                        // Immediately try to connect LLCP services
                        connectLlcpServices();
                    } else {
                        mSendState = SEND_STATE_NOTHING_TO_SEND;
                        prepareMessageToSend(true);
                        if (mMessageToSend != null ||
                                (mUrisToSend != null && mHandoverDataParser.isHandoverSupported())) {
                            // We have data to send, connect LLCP services
                            connectLlcpServices();
                            if ((mSendFlags & NfcAdapter.FLAG_NDEF_PUSH_NO_CONFIRM) != 0) {
                                mSendState = SEND_STATE_SENDING;
                            } else {
                                mSendState = SEND_STATE_NEED_CONFIRMATION;
                            }
                        }
                    }
                    break;
                case LINK_STATE_UP:
                    if (DBG) Log.d(TAG, "Duplicate onLlcpActivated()");
                    return;
                case LINK_STATE_DEBOUNCE:
                    // Immediately connect and try to send again
                    mLinkState = LINK_STATE_UP;
                    if (mSendState == SEND_STATE_SENDING ||
                            mSendState == SEND_STATE_NEED_CONFIRMATION) {
                        // If we have something to send still, connect LLCP
                        connectLlcpServices();
                    }
                    mHandler.removeMessages(MSG_DEBOUNCE_TIMEOUT);
                    break;
            }
        }
    }

    /**
     * Must be called on UI Thread.
     */
    public void onLlcpFirstPacketReceived() {
        synchronized (P2pLinkManager.this) {
            long totalTime = SystemClock.elapsedRealtime() - mLastLlcpActivationTime;
            if (DBG) Log.d(TAG, "Took " + Long.toString(totalTime) + " to get first LLCP PDU");
        }
    }

    public void onUserSwitched(int userId) {
        // Update the cached package manager in case of user switch
        synchronized (P2pLinkManager.this) {
            try {
                mPackageManager  = mContext.createPackageContextAsUser("android", 0,
                        new UserHandle(userId)).getPackageManager();
            } catch (NameNotFoundException e) {
                Log.e(TAG, "Failed to retrieve PackageManager for user");
            }
        }
    }

    void prepareMessageToSend(boolean generatePlayLink) {
        synchronized (P2pLinkManager.this) {
            mMessageToSend = null;
            mUrisToSend = null;
            if (!mIsSendEnabled) {
                return;
            }

            List<Integer> foregroundUids = mForegroundUtils.getForegroundUids();
            if (foregroundUids.isEmpty()) {
                Log.e(TAG, "Could not determine foreground UID.");
                return;
            }

            if (isBeamDisabled(foregroundUids.get(0))) {
                if (DBG) Log.d(TAG, "Beam is disabled by policy.");
                return;
            }

            if (mCallbackNdef != null) {
                if (foregroundUids.contains(mNdefCallbackUid)) {
                    try {
                        BeamShareData shareData = mCallbackNdef.createBeamShareData(mPeerLlcpVersion);
                        mMessageToSend = shareData.ndefMessage;
                        mUrisToSend = shareData.uris;
                        mUserHandle = shareData.userHandle;
                        mSendFlags = shareData.flags;
                        return;
                    } catch (Exception e) {
                        Log.e(TAG, "Failed NDEF callback: ", e);
                    }
                } else {
                    // This is not necessarily an error - we no longer unset callbacks from
                    // the app process itself (to prevent IPC calls on every pause).
                    // Hence it may simply be a stale callback.
                    if (DBG) Log.d(TAG, "Last registered callback is not running in the foreground.");
                }
            }

            // fall back to default NDEF for the foreground activity, unless the
            // application disabled this explicitly in their manifest.
            String[] pkgs = mPackageManager.getPackagesForUid(foregroundUids.get(0));
            if (pkgs != null && pkgs.length >= 1) {
                if (!generatePlayLink || beamDefaultDisabled(pkgs[0])) {
                    if (DBG) Log.d(TAG, "Disabling default Beam behavior");
                    mMessageToSend = null;
                    mUrisToSend = null;
                } else {
                    mMessageToSend = createDefaultNdef(pkgs[0]);
                    mUrisToSend = null;
                    mSendFlags = 0;
                }
            }

            if (DBG) Log.d(TAG, "mMessageToSend = " + mMessageToSend);
            if (DBG) Log.d(TAG, "mUrisToSend = " + mUrisToSend);
        }
    }

    private boolean isBeamDisabled(int uid) {
        UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
        UserInfo userInfo = userManager.getUserInfo(UserHandle.getUserId(uid));
        return userManager.hasUserRestriction(
                        UserManager.DISALLOW_OUTGOING_BEAM, userInfo.getUserHandle());

    }

    boolean beamDefaultDisabled(String pkgName) {
        try {
            ApplicationInfo ai = mPackageManager.getApplicationInfo(pkgName,
                    PackageManager.GET_META_DATA);
            if (ai == null || ai.metaData == null) {
                return false;
            }
            return ai.metaData.getBoolean(DISABLE_BEAM_DEFAULT);
        } catch (NameNotFoundException e) {
            return false;
        }
    }

    NdefMessage createDefaultNdef(String pkgName) {
        NdefRecord appUri = NdefRecord.createUri(Uri.parse(
                "http://play.google.com/store/apps/details?id=" + pkgName + "&feature=beam"));
        NdefRecord appRecord = NdefRecord.createApplicationRecord(pkgName);
        return new NdefMessage(new NdefRecord[] { appUri, appRecord });
    }

    void disconnectLlcpServices() {
        synchronized (this) {
            if (mConnectTask != null) {
                mConnectTask.cancel(true);
                mConnectTask = null;
            }
            // Close any already connected LLCP clients
            if (mNdefPushClient != null) {
                mNdefPushClient.close();
                mNdefPushClient = null;
            }
            if (mSnepClient != null) {
                mSnepClient.close();
                mSnepClient = null;
            }
            if (mHandoverClient != null) {
                mHandoverClient.close();
                mHandoverClient = null;
            }
            mLlcpServicesConnected = false;
        }
    }

    /**
     * Must be called on UI Thread.
     */
    public void onLlcpDeactivated() {
        Log.i(TAG, "LLCP deactivated.");
        synchronized (this) {
            if (mEchoServer != null) {
                mEchoServer.onLlcpDeactivated();
            }

            switch (mLinkState) {
                case LINK_STATE_DOWN:
                case LINK_STATE_DEBOUNCE:
                    Log.i(TAG, "Duplicate onLlcpDectivated()");
                    break;
                case LINK_STATE_UP:
                    // Debounce
                    mLinkState = LINK_STATE_DEBOUNCE;
                    int debounceTimeout = 0;
                    switch (mSendState) {
                        case SEND_STATE_NOTHING_TO_SEND:
                            debounceTimeout = 0;
                            break;
                        case SEND_STATE_NEED_CONFIRMATION:
                            debounceTimeout = LINK_SEND_PENDING_DEBOUNCE_MS;
                            break;
                        case SEND_STATE_SENDING:
                            debounceTimeout = LINK_SEND_CONFIRMED_DEBOUNCE_MS;
                            break;
                        case SEND_STATE_COMPLETE:
                            debounceTimeout = LINK_SEND_COMPLETE_DEBOUNCE_MS;
                            break;
                        case SEND_STATE_CANCELED:
                            debounceTimeout = LINK_SEND_CANCELED_DEBOUNCE_MS;
                    }
                    scheduleTimeoutLocked(MSG_DEBOUNCE_TIMEOUT, debounceTimeout);
                    if (mSendState == SEND_STATE_SENDING) {
                        Log.e(TAG, "onP2pSendDebounce()");
                        mEventListener.onP2pSendDebounce();
                    }
                    cancelSendNdefMessage();
                    disconnectLlcpServices();
                    break;
            }
         }
     }

    void onHandoverUnsupported() {
        mHandler.sendEmptyMessage(MSG_HANDOVER_NOT_SUPPORTED);
    }

    void onHandoverBusy() {
        mHandler.sendEmptyMessage(MSG_HANDOVER_BUSY);
    }

    void onSendComplete(NdefMessage msg, long elapsedRealtime) {
        // Make callbacks on UI thread
        mHandler.sendEmptyMessage(MSG_SEND_COMPLETE);
    }

    void sendNdefMessage() {
        synchronized (this) {
            cancelSendNdefMessage();
            mSendTask = new SendTask();
            mSendTask.execute();
        }
    }

    void cancelSendNdefMessage() {
        synchronized (P2pLinkManager.this) {
            if (mSendTask != null) {
                mSendTask.cancel(true);
            }
        }
    }

    void connectLlcpServices() {
        synchronized (P2pLinkManager.this) {
            if (mConnectTask != null) {
                Log.e(TAG, "Still had a reference to mConnectTask!");
            }
            mConnectTask = new ConnectTask();
            mConnectTask.execute();
        }
    }

    // Must be called on UI-thread
    void onLlcpServicesConnected() {
        if (DBG) Log.d(TAG, "onLlcpServicesConnected");
        synchronized (P2pLinkManager.this) {
            if (mLinkState != LINK_STATE_UP) {
                return;
            }
            mLlcpServicesConnected = true;
            if (mSendState == SEND_STATE_NEED_CONFIRMATION) {
                if (DBG) Log.d(TAG, "onP2pSendConfirmationRequested()");
                mEventListener.onP2pSendConfirmationRequested();
            } else if (mSendState == SEND_STATE_SENDING) {
                mEventListener.onP2pResumeSend();
                sendNdefMessage();
            } else {
                // Either nothing to send or canceled/complete, ignore
            }
        }
    }

    final class ConnectTask extends AsyncTask<Void, Void, Boolean> {
        @Override
        protected void onPostExecute(Boolean result)  {
            if (isCancelled()) {
                if (DBG) Log.d(TAG, "ConnectTask was cancelled");
                return;
            }
            if (result) {
                onLlcpServicesConnected();
            } else {
                Log.e(TAG, "Could not connect required NFC transports");
            }
        }

        @Override
        protected Boolean doInBackground(Void... params) {
            boolean needsHandover = false;
            boolean needsNdef = false;
            boolean success = false;
            HandoverClient handoverClient = null;
            SnepClient snepClient = null;
            NdefPushClient nppClient = null;

            synchronized(P2pLinkManager.this) {
                if (mUrisToSend != null) {
                    needsHandover = true;
                }

                if (mMessageToSend != null) {
                    needsNdef = true;
                }
            }
            // We know either is requested - otherwise this task
            // wouldn't have been started.
            if (needsHandover) {
                handoverClient = new HandoverClient();
                try {
                    handoverClient.connect();
                    success = true; // Regardless of NDEF result
                } catch (IOException e) {
                    handoverClient = null;
                }
            }
            if (needsNdef || (needsHandover && handoverClient == null)) {
                if (NfcService.sIsDtaMode) {
                    if (mClientEnabled) {
                        if (mDtaSnepClient == null) {
                            if (DBG) Log.d(TAG, "Creating DTA Snep Client");
                            mDtaSnepClient = new DtaSnepClient(mServiceName, mDtaMiu, mDtaRwSize, mTestCaseID);
                        }
                    }
                } else
                    snepClient = new SnepClient();
                try {
                    if (NfcService.sIsDtaMode) {
                        if (mDtaSnepClient != null)
                            mDtaSnepClient.DtaClientOperations(mContext);
                    }
                    else
                        snepClient.connect();
                    success = true;
                    mDtaSnepClient = null;
                } catch (IOException e) {
                    snepClient = null;
                }

                if (!success) {
                    nppClient = new NdefPushClient();
                    try {
                        nppClient.connect();
                        success = true;
                    } catch (IOException e) {
                        nppClient = null;
                    }
                }
            }

            synchronized (P2pLinkManager.this) {
                if (isCancelled()) {
                    // Cancelled by onLlcpDeactivated on UI thread
                    if (handoverClient != null) {
                        handoverClient.close();
                    }
                    if (snepClient != null) {
                        snepClient.close();
                    }
                    if (nppClient != null) {
                        nppClient.close();
                    }
                    if (mDtaSnepClient != null) {
                        mDtaSnepClient.close();
                    }
                    return false;
                } else {
                    // Once assigned, these are the responsibility of
                    // the code on the UI thread to release - typically
                    // through onLlcpDeactivated().
                    mHandoverClient = handoverClient;
                    mSnepClient = snepClient;
                    mNdefPushClient = nppClient;
                    return success;
                }
            }
        }
    };

    final class SendTask extends AsyncTask<Void, Void, Void> {
        NdefPushClient nppClient;
        SnepClient snepClient;
        HandoverClient handoverClient;

        int doHandover(Uri[] uris, UserHandle userHandle) throws IOException {
            NdefMessage response = null;
            BeamManager beamManager = BeamManager.getInstance();

            if (beamManager.isBeamInProgress()) {
                return HANDOVER_BUSY;
            }

            NdefMessage request = mHandoverDataParser.createHandoverRequestMessage();
            if (request != null) {
                if (handoverClient != null) {
                    response = handoverClient.sendHandoverRequest(request);
                }
                if (response == null && snepClient != null) {
                    // Remote device may not support handover service,
                    // try the (deprecated) SNEP GET implementation
                    // for devices running Android 4.1
                    SnepMessage snepResponse = snepClient.get(request);
                    response = snepResponse.getNdefMessage();
                }
                if (response == null) {
                    if (snepClient != null)
                        return HANDOVER_UNSUPPORTED;
                    else
                        return HANDOVER_FAILURE;
                }
            } else {
                return HANDOVER_UNSUPPORTED;
            }

            if (!beamManager.startBeamSend(mContext,
                    mHandoverDataParser.getOutgoingHandoverData(response), uris, userHandle)) {
                return HANDOVER_BUSY;
            }

            return HANDOVER_SUCCESS;
        }

        int doSnepProtocol(NdefMessage msg) throws IOException {
            if (msg != null) {
                snepClient.put(msg);
                return SNEP_SUCCESS;
            } else {
                return SNEP_FAILURE;
            }
        }

        @Override
        public Void doInBackground(Void... args) {
            NdefMessage m;
            Uri[] uris;
            UserHandle userHandle;
            boolean result = false;

            synchronized (P2pLinkManager.this) {
                if (mLinkState != LINK_STATE_UP || mSendState != SEND_STATE_SENDING) {
                    return null;
                }
                m = mMessageToSend;
                uris = mUrisToSend;
                userHandle = mUserHandle;
                snepClient = mSnepClient;
                handoverClient = mHandoverClient;
                nppClient = mNdefPushClient;
            }

            long time = SystemClock.elapsedRealtime();

            if (uris != null) {
                if (DBG) Log.d(TAG, "Trying handover request");
                try {
                    int handoverResult = doHandover(uris, userHandle);
                    switch (handoverResult) {
                        case HANDOVER_SUCCESS:
                            result = true;
                            break;
                        case HANDOVER_FAILURE:
                            result = false;
                            break;
                        case HANDOVER_UNSUPPORTED:
                            result = false;
                            onHandoverUnsupported();
                            break;
                        case HANDOVER_BUSY:
                            result = false;
                            onHandoverBusy();
                            break;
                    }
                } catch (IOException e) {
                    result = false;
                }
            }

            if (!result && m != null && snepClient != null) {
                if (DBG) Log.d(TAG, "Sending ndef via SNEP");
                try {
                    int snepResult = doSnepProtocol(m);
                    switch (snepResult) {
                        case SNEP_SUCCESS:
                            result = true;
                            break;
                        case SNEP_FAILURE:
                            result = false;
                            break;
                        default:
                            result = false;
                    }
                } catch (IOException e) {
                    result = false;
                }
            }

            if (!result && m != null && nppClient != null) {
                result = nppClient.push(m);
            }

            time = SystemClock.elapsedRealtime() - time;
            if (DBG) Log.d(TAG, "SendTask result=" + result + ", time ms=" + time);
            if (result) {
                onSendComplete(m, time);
            }

            return null;
        }
    };


    final HandoverServer.Callback mHandoverCallback = new HandoverServer.Callback() {
        @Override
        public void onHandoverRequestReceived() {
            onReceiveHandover();
        }

        @Override
        public void onHandoverBusy() {
            P2pLinkManager.this.onHandoverBusy();
        }
    };

    final NdefPushServer.Callback mNppCallback = new NdefPushServer.Callback() {
        @Override
        public void onMessageReceived(NdefMessage msg) {
            onReceiveComplete(msg);
        }
    };

    final SnepServer.Callback mDefaultSnepCallback = new SnepServer.Callback() {
        @Override
        public SnepMessage doPut(NdefMessage msg) {
            if(NfcService.sIsDtaMode)
            Log.d(TAG, "DTA mode enabled, dont dispatch the tag");
            else
            onReceiveComplete(msg);
            return SnepMessage.getMessage(SnepMessage.RESPONSE_SUCCESS);
        }

        @Override
        public SnepMessage doGet(int acceptableLength, NdefMessage msg) {
            // The NFC Forum Default SNEP server is not allowed to respond to
            // SNEP GET requests - see SNEP 1.0 TS section 6.1. However,
            // since Android 4.1 used the NFC Forum default server to
            // implement connection handover, we will support this
            // until we can deprecate it.
            NdefMessage response = null;
            if (NfcService.sIsDtaMode){
               if(msg != null && mHandoverDataParser.getIncomingHandoverData(msg) !=  null) {
                   response = mHandoverDataParser.getIncomingHandoverData(msg).handoverSelect;
               }
            } else {
                response = mHandoverDataParser.getIncomingHandoverData(msg).handoverSelect;
            }
            if (response != null) {
                onReceiveHandover();
                return SnepMessage.getSuccessResponse(response);
            } else {
                return SnepMessage.getMessage(SnepMessage.RESPONSE_NOT_IMPLEMENTED);
            }
        }
    };
    final ExtDtaSnepServer.Callback mExtDtaSnepServerCallback = new ExtDtaSnepServer.Callback() {
        @Override
        public SnepMessage doPut(NdefMessage msg) {
            mPutBeforeGet = true;
            return SnepMessage.getMessage(SnepMessage.RESPONSE_SUCCESS);
        }

        @Override
        public SnepMessage doGet(int acceptableLength, NdefMessage msg) {
            if ((!mPutBeforeGet)) {
                return SnepMessage.getMessage(SnepMessage.RESPONSE_NOT_FOUND);
            } else if (acceptableLength == 501) {
                mPutBeforeGet = false;
                return SnepMessage.getMessage(SnepMessage.RESPONSE_EXCESS_DATA);
            } else if (mPutBeforeGet&&(acceptableLength == 1024)) {
                try {
                    mPutBeforeGet = false;
                    return SnepMessage.getSuccessResponse(SnepMessage.getLargeNdef());
                } catch (UnsupportedEncodingException e) {
                    mPutBeforeGet = false;
                    return null;
                }
            } else {
                mPutBeforeGet = false;
                return SnepMessage.getMessage(SnepMessage.RESPONSE_NOT_IMPLEMENTED);
            }
        }
    };

    void onReceiveHandover() {
        mHandler.obtainMessage(MSG_RECEIVE_HANDOVER).sendToTarget();
    }

    void onReceiveComplete(NdefMessage msg) {
        // Make callbacks on UI thread
        mHandler.obtainMessage(MSG_RECEIVE_COMPLETE, msg).sendToTarget();
    }

    @Override
    public boolean handleMessage(Message msg) {
        switch (msg.what) {
            case MSG_START_ECHOSERVER:
                synchronized (this) {
                    mEchoServer.start();
                    break;
                }
            case MSG_STOP_ECHOSERVER:
                synchronized (this) {
                    mEchoServer.stop();
                    break;
                }
            case MSG_WAIT_FOR_LINK_TIMEOUT:
                synchronized (this) {
                    // User wanted to send something but no link
                    // came up. Just cancel the send
                    mSendState = SEND_STATE_NOTHING_TO_SEND;
                    mEventListener.onP2pTimeoutWaitingForLink();
                }
                break;
            case MSG_DEBOUNCE_TIMEOUT:
                synchronized (this) {
                    if (mLinkState != LINK_STATE_DEBOUNCE) {
                        break;
                    }
                    if (DBG) Log.d(TAG, "Debounce timeout");
                    mLinkState = LINK_STATE_DOWN;
                    mSendState = SEND_STATE_NOTHING_TO_SEND;
                    mMessageToSend = null;
                    mUrisToSend = null;
                    if (DBG) Log.d(TAG, "onP2pOutOfRange()");
                    mEventListener.onP2pOutOfRange();
                }
                break;
            case MSG_RECEIVE_HANDOVER:
                // We're going to do a handover request
                synchronized (this) {
                    if (mLinkState == LINK_STATE_DOWN) {
                        break;
                    }
                    if (mSendState == SEND_STATE_SENDING) {
                        cancelSendNdefMessage();
                    }
                    mSendState = SEND_STATE_NOTHING_TO_SEND;
                    if (DBG) Log.d(TAG, "onP2pReceiveComplete()");
                    mEventListener.onP2pReceiveComplete(false);
                }
                break;
            case MSG_RECEIVE_COMPLETE:
                NdefMessage m = (NdefMessage) msg.obj;
                synchronized (this) {
                    if (mLinkState == LINK_STATE_DOWN) {
                        break;
                    }
                    if (mSendState == SEND_STATE_SENDING) {
                        cancelSendNdefMessage();
                    }
                    mSendState = SEND_STATE_NOTHING_TO_SEND;
                    if (DBG) Log.d(TAG, "onP2pReceiveComplete()");
                    mEventListener.onP2pReceiveComplete(true);
                    NfcService.getInstance().sendMockNdefTag(m);
                }
                break;
            case MSG_HANDOVER_NOT_SUPPORTED:
                synchronized (P2pLinkManager.this) {
                    mSendTask = null;

                    if (mLinkState == LINK_STATE_DOWN || mSendState != SEND_STATE_SENDING) {
                        break;
                    }
                    mSendState = SEND_STATE_NOTHING_TO_SEND;
                    if (DBG) Log.d(TAG, "onP2pHandoverNotSupported()");
                    mEventListener.onP2pHandoverNotSupported();
                }
                break;
            case MSG_SEND_COMPLETE:
                synchronized (P2pLinkManager.this) {
                    mSendTask = null;

                    if (mLinkState == LINK_STATE_DOWN || mSendState != SEND_STATE_SENDING) {
                        break;
                    }
                    mSendState = SEND_STATE_COMPLETE;
                    mHandler.removeMessages(MSG_DEBOUNCE_TIMEOUT);
                    if (DBG) Log.d(TAG, "onP2pSendComplete()");
                    mEventListener.onP2pSendComplete();
                    if (mCallbackNdef != null) {
                        try {
                            mCallbackNdef.onNdefPushComplete(mPeerLlcpVersion);
                        } catch (Exception e) {
                            Log.e(TAG, "Failed NDEF completed callback: " + e.getMessage());
                        }
                    }
                }
                break;
            case MSG_HANDOVER_BUSY:
                synchronized (P2pLinkManager.this) {
                    mSendTask = null;

                    if (mLinkState == LINK_STATE_DOWN || mSendState != SEND_STATE_SENDING) {
                        break;
                    }
                    mSendState = SEND_STATE_NOTHING_TO_SEND;
                    if (DBG) Log.d(TAG, "onP2pHandoverBusy()");
                    mEventListener.onP2pHandoverBusy();
                }
        }
        return true;
    }


    @Override
    public void onP2pSendConfirmed() {
        onP2pSendConfirmed(true);
    }

    private void onP2pSendConfirmed(boolean requireConfirmation) {
        if (DBG) Log.d(TAG, "onP2pSendConfirmed()");
        synchronized (this) {
            if (mLinkState == LINK_STATE_DOWN || (requireConfirmation
                    && mSendState != SEND_STATE_NEED_CONFIRMATION)) {
                return;
            }
            mSendState = SEND_STATE_SENDING;
            if (mLinkState == LINK_STATE_UP) {
                if (mLlcpServicesConnected) {
                    sendNdefMessage();
                } // else, will send messages when link comes up
            } else if (mLinkState == LINK_STATE_DEBOUNCE) {
                // Restart debounce timeout and tell user to tap again
                scheduleTimeoutLocked(MSG_DEBOUNCE_TIMEOUT, LINK_SEND_CONFIRMED_DEBOUNCE_MS);
                mEventListener.onP2pSendDebounce();
            }
        }
    }


    @Override
    public void onP2pCanceled() {
        synchronized (this) {
            mSendState = SEND_STATE_CANCELED;
            if (mLinkState == LINK_STATE_DOWN) {
                // If we were waiting for the link to come up, stop doing so
                mHandler.removeMessages(MSG_WAIT_FOR_LINK_TIMEOUT);
            } else if (mLinkState == LINK_STATE_DEBOUNCE) {
                // We're in debounce state so link is down. Reschedule debounce
                // timeout to occur sooner, we don't want to wait any longer.
                scheduleTimeoutLocked(MSG_DEBOUNCE_TIMEOUT, LINK_SEND_CANCELED_DEBOUNCE_MS);
            } else {
                // Link is up, nothing else to do but wait for link to go down
            }
        }
    }

    void scheduleTimeoutLocked(int what, int timeout) {
        // Cancel any outstanding debounce timeouts.
        mHandler.removeMessages(what);
        mHandler.sendEmptyMessageDelayed(what, timeout);
    }

    static String sendStateToString(int state) {
        switch (state) {
            case SEND_STATE_NOTHING_TO_SEND:
                return "SEND_STATE_NOTHING_TO_SEND";
            case SEND_STATE_NEED_CONFIRMATION:
                return "SEND_STATE_NEED_CONFIRMATION";
            case SEND_STATE_SENDING:
                return "SEND_STATE_SENDING";
            case SEND_STATE_COMPLETE:
                return "SEND_STATE_COMPLETE";
            case SEND_STATE_CANCELED:
                return "SEND_STATE_CANCELED";
            default:
                return "<error>";
        }
    }

    static String linkStateToString(int state) {
        switch (state) {
            case LINK_STATE_DOWN:
                return "LINK_STATE_DOWN";
            case LINK_STATE_DEBOUNCE:
                return "LINK_STATE_DEBOUNCE";
            case LINK_STATE_UP:
                return "LINK_STATE_UP";
            default:
                return "<error>";
        }
    }

    void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        synchronized (this) {
            pw.println("mIsSendEnabled=" + mIsSendEnabled);
            pw.println("mIsReceiveEnabled=" + mIsReceiveEnabled);
            pw.println("mLinkState=" + linkStateToString(mLinkState));
            pw.println("mSendState=" + sendStateToString(mSendState));

            pw.println("mCallbackNdef=" + mCallbackNdef);
            pw.println("mMessageToSend=" + mMessageToSend);
            pw.println("mUrisToSend=" + mUrisToSend);
        }
    }
}
