Merge "MAP: Support MAP Client role on Bluedroid."
diff --git a/src/org/codeaurora/bluetooth/btcservice/BTCEventProvider.java b/src/org/codeaurora/bluetooth/btcservice/BTCEventProvider.java
index 3ec668c..0e317d3 100644
--- a/src/org/codeaurora/bluetooth/btcservice/BTCEventProvider.java
+++ b/src/org/codeaurora/bluetooth/btcservice/BTCEventProvider.java
@@ -53,8 +53,8 @@
 
 public class BTCEventProvider extends BroadcastReceiver {
     private static final String TAG = "BTCEventProvider";
-    private static final boolean D = /*Constants.DEBUG*/true;
-    private static final boolean V = true/*Constants.VERBOSE*/;
+    private static final boolean D = /*Constants.DEBUG*/false;
+    private static final boolean V = false/*Constants.VERBOSE*/;
     private int state;
     BTCService.BTCEvent event = BTCService.BTCEvent.BLUETOOTH_NONE;
 
@@ -72,7 +72,7 @@
                 if (service != null) {
                     event =  BTCService.BTCEvent.BLUETOOTH_ON;
                 } else {
-                    Log.e(TAG, "Could Not Start BTC Service ");
+                    if (D) Log.d(TAG, "Could Not Start BTC Service ");
                     return;
                 }
             } else if (BluetoothAdapter.STATE_OFF == state) {
@@ -125,10 +125,10 @@
             if (V) Log.v(TAG, "BluetoothA2dp.ACTION_PLAYING_STATE_CHANGED");
             state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, BluetoothAdapter.ERROR);
             if (BluetoothA2dp.STATE_PLAYING == state) {
-                if (V) Log.v(TAG, "A2DP. PLAYING_STATE_CHANGED: CONNECTED");
+                if (V) Log.v(TAG, "A2DP. PLAYING_STATE_CHANGED: PLAYING");
                 event =  BTCService.BTCEvent.BLUETOOTH_SINK_STREAM_STARTED;
             } else if (BluetoothA2dp.STATE_NOT_PLAYING == state) {
-                if (V) Log.v(TAG, "A2DP.PLAYING_STATE_CHANGED: DISCONNECTED");
+                if (V) Log.v(TAG, "A2DP.PLAYING_STATE_CHANGED: PLAYING_STOPPED");
                 event =  BTCService.BTCEvent.BLUETOOTH_SINK_STREAM_STOPPED;
             }
         } else if (action.equals(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED)) {
@@ -150,10 +150,10 @@
               if (V) Log.v(TAG, "Event:" + event.getValue() + "Written Succesfully");
            }
            else {
-              Log.e(TAG, "Error while sending Event:" + event.getValue());
+              if (D) Log.d(TAG, "Error while sending Event:" + event.getValue());
            }
            if (event ==  BTCService.BTCEvent.BLUETOOTH_OFF) {
-               Log.v(TAG, "Stop the BTC Service");
+               if (V) Log.v(TAG, "Stop the BTC Service");
                context.stopService(new Intent(context, BTCService.class));
            }
         }
diff --git a/src/org/codeaurora/bluetooth/btcservice/BTCService.java b/src/org/codeaurora/bluetooth/btcservice/BTCService.java
index c1a8c82..ff3c6df 100644
--- a/src/org/codeaurora/bluetooth/btcservice/BTCService.java
+++ b/src/org/codeaurora/bluetooth/btcservice/BTCService.java
@@ -79,6 +79,8 @@
     private static OutputStream mOutputStream = null;
     private static Thread mSocketAcceptThread;
     private static boolean mLocalConnectInitiated = false;
+    private static final boolean D = false/*Constants.DEBUG*/;
+    private static final boolean V = false/*Constants.VERBOSE*/;
     private static final Object mLock = new Object();
 
     public enum BTCEvent {
@@ -119,16 +121,16 @@
         if (mSocket != null) {
             mSocket.close();
             mSocket = null;
-            Log.v(LOGTAG, "Server Socket closed");
+            if (V) Log.v(LOGTAG, "Server Socket closed");
         }
         if (mRemoteSocket != null) {
             mRemoteSocket.close();
             mRemoteSocket = null;
-            Log.v(LOGTAG, "Client Socket closed");
+            if (V) Log.v(LOGTAG, "Client Socket closed");
         }
         if( mSocketAcceptThread != null ) {
             mSocketAcceptThread.interrupt();
-            Log.v(LOGTAG, "Acceptor thread stopped");
+            if (V) Log.v(LOGTAG, "Acceptor thread stopped");
         }
     }
     }
@@ -142,9 +144,9 @@
      *        -2 when there is issue while writing on client socket.
      */
     static public int sendEvent(BTCEvent event) {
-        Log.v(LOGTAG, "sendEvent: " + event.getValue());
+        if (V) Log.v(LOGTAG, "sendEvent: " + event.getValue());
         if (mRemoteSocket == null) {
-            Log.v(LOGTAG, "No Valid Connection" );
+            if(D) Log.d(LOGTAG, "No Valid Connection" );
             return -1;
         }
 
@@ -155,8 +157,8 @@
             mOutputStream.write(buffer.array());
         }
         catch (java.io.IOException e) {
-            Log.e(LOGTAG, "Error while posting the event: " + event + "Error:" + e);
-            Log.e(LOGTAG, "connectoin is closed for Unknown reason, restart the acceptor thread ");
+            if (D) Log.d(LOGTAG, "Error while posting the event: " + event + "Error:" + e);
+            if (D) Log.d(LOGTAG, "connectoin is closed for Unknown reason, restart the acceptor thread ");
             startListener();
             return -2;
         }
@@ -176,7 +178,7 @@
         public void run() {
         do {
            try {
-               Log.v(LOGTAG, "Waiting for connection...");
+               if (V) Log.v(LOGTAG, "Waiting for connection...");
                try {
                    mRemoteSocket = mSocket.accept();
                } catch (java.io.IOException e) {
@@ -187,7 +189,7 @@
                if (mLocalConnectInitiated) {
                    //This is just a local connection
                    //to unblock the accept
-                   Log.e(LOGTAG, "Terminator in action: ");
+                   if (D) Log.d(LOGTAG, "Terminator in action: ");
                    cleanupService();
                    mLocalConnectInitiated = false;
                    return;
diff --git a/src/org/codeaurora/bluetooth/ftp/BluetoothFtpObexServer.java b/src/org/codeaurora/bluetooth/ftp/BluetoothFtpObexServer.java
index f4e561b..b8f273c 100644
--- a/src/org/codeaurora/bluetooth/ftp/BluetoothFtpObexServer.java
+++ b/src/org/codeaurora/bluetooth/ftp/BluetoothFtpObexServer.java
@@ -441,12 +441,7 @@
                 Log.e(TAG, "onPut File receive"+ e1.toString());
                 if (D) Log.d(TAG, "Error when receiving file");
                 ((ServerOperation)op).isAborted = true;
-                /* If the transfer completed due to a
-                 * abort from Ftp client, clean up the
-                 * file in the Server
-                 */
-                fileinfo.delete();
-                return ResponseCodes.OBEX_HTTP_BAD_REQUEST;
+                sIsAborted = true;
             }
 
             long finishtimestamp = System.currentTimeMillis();
@@ -462,6 +457,16 @@
                 }
             }
             if(D) Log.d(TAG,"close Stream >");
+            if(sIsAborted == true){
+                sIsAborted = false;
+                /* If the transfer completed due to a
+                 * abort from Ftp client, clean up the
+                 * file in the Server
+                 */
+                fileinfo.delete();
+                Log.e(TAG, " SET isAborted on excepton");
+                return ResponseCodes.OBEX_HTTP_BAD_REQUEST;
+            }
             if (!closeStream(in_stream, op)) {
                 if (D) Log.d(TAG,"Failed to close Input stream");
                 return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
diff --git a/src/org/codeaurora/bluetooth/ftp/BluetoothFtpService.java b/src/org/codeaurora/bluetooth/ftp/BluetoothFtpService.java
index 2f9c2c9..ceec144 100644
--- a/src/org/codeaurora/bluetooth/ftp/BluetoothFtpService.java
+++ b/src/org/codeaurora/bluetooth/ftp/BluetoothFtpService.java
@@ -299,12 +299,10 @@
                 if (mSessionStatusHandler.hasMessages(MSG_INTERNAL_USER_TIMEOUT)) {
                     Intent i = new Intent(USER_CONFIRM_TIMEOUT_ACTION);
                     sendBroadcast(i);
-                    removeFtpNotification(NOTIFICATION_ID_AUTH);
+                    removeFtpNotification(NOTIFICATION_ID_ACCESS);
                 }
                 // Release all resources
                 closeService();
-            } else {
-                removeTimeoutMsg = false;
             }
         } else if (action.equals(ACCESS_ALLOWED_ACTION)) {
             if (!isWaitingAuthorization) {
diff --git a/src/org/codeaurora/bluetooth/map/BluetoothMasAppSmsMms.java b/src/org/codeaurora/bluetooth/map/BluetoothMasAppSmsMms.java
index 55e967b..68fa1e6 100644
--- a/src/org/codeaurora/bluetooth/map/BluetoothMasAppSmsMms.java
+++ b/src/org/codeaurora/bluetooth/map/BluetoothMasAppSmsMms.java
@@ -39,6 +39,7 @@
 import android.telephony.SmsManager;
 import android.telephony.SmsMessage;
 import android.telephony.TelephonyManager;
+import android.provider.Telephony.Threads;
 import android.text.format.Time;
 import android.util.Log;
 import android.util.TimeFormatException;
@@ -1256,6 +1257,63 @@
         }
         return folderName;
     }
+    /**
+     * Get SMS RecipientAddresses for DRAFT folder based on threadId
+     *
+    */
+    private String getMessageSmsRecipientAddress(int threadId){
+       String [] RECIPIENT_ID_PROJECTION = { "recipient_ids" };
+        /*
+         1. Get Recipient Ids from Threads.CONTENT_URI
+         2. Get Recipient Address for corresponding Id from canonical-addresses table.
+        */
+
+        Uri sAllCanonical = Uri.parse("content://mms-sms/canonical-addresses");
+        Uri sAllThreadsUri =  Threads.CONTENT_URI.buildUpon().appendQueryParameter("simple", "true").build();
+        Cursor cr = null;
+        String recipientAddress= "";
+        String recipientIds = null;
+        String whereClause = "_id="+threadId;
+        cr = mContext.getContentResolver().query(sAllThreadsUri, RECIPIENT_ID_PROJECTION, whereClause, null,
+                null);
+        if (cr != null && cr.moveToFirst()) {
+            recipientIds = cr.getString(0);
+            if (V) Log.v(TAG, "cursor.getCount(): " + cr.getCount() + "recipientIds: "+ recipientIds +"whrClus: "+ whereClause );
+        }
+        if(cr != null){
+            cr.close();
+            cr = null;
+        }
+
+        if (V) Log.v(TAG, "recipientIds with spaces: "+ recipientIds +"\n");
+
+        if(recipientIds != null) {
+           String recipients[] = null;
+           whereClause = "";
+           recipients = recipientIds.split(" ");
+           for (String id: recipients) {
+                if(whereClause.length() != 0)
+                   whereClause +=" OR ";
+                whereClause +="_id="+id;
+           }
+           cr = mContext.getContentResolver().query(sAllCanonical , null, whereClause, null, null);
+           if (cr != null && cr.moveToFirst()) {
+              do {
+                //TODO: Multiple Recipeints are appended with ";" for now.
+                if(recipientAddress.length() != 0 )
+                   recipientAddress+=";";
+                recipientAddress+=cr.getString(cr.getColumnIndex("address"));
+              } while(cr.moveToNext());
+           }
+           if(cr != null)
+              cr.close();
+
+        }
+
+        if(V) Log.v(TAG,"Final recipientAddress : "+ recipientAddress);
+        return recipientAddress;
+
+     }
 
     /**
      * Build an MMS bMessage when given a message handle
@@ -2047,6 +2105,7 @@
             int subjectInd = cursor.getColumnIndex("subject");
             int typeInd = cursor.getColumnIndex("type");
             int bodyInd = cursor.getColumnIndex("body");
+            int threadIdInd = cursor.getColumnIndex("thread_id");
 
             do {
                 /*
@@ -2147,6 +2206,11 @@
                 String timestampSms = cursor.getString(dateInd);
                 String addressSms = cursor.getString(addressInd);
                 String readStatusSms = cursor.getString(readInd);
+                String threadIdStr = cursor.getString(threadIdInd);
+                if(addressSms == null &&( DRAFT.equalsIgnoreCase(folder) || DRAFTS.equalsIgnoreCase(folder))) {
+                      addressSms = getMessageSmsRecipientAddress(Integer.valueOf(threadIdStr));
+                      if(V)  Log.v(TAG, "threadId = " + threadIdStr + " adressSms:" + addressSms +"\n");
+                }
 
                 MsgListingConsts ml = bldSmsMsgLstItem(appParams, subjectSms,
                                 timestampSms, addressSms, msgIdSms,
diff --git a/src/org/codeaurora/bluetooth/map/BluetoothMasService.java b/src/org/codeaurora/bluetooth/map/BluetoothMasService.java
index 08e518d..cbdbdba 100755
--- a/src/org/codeaurora/bluetooth/map/BluetoothMasService.java
+++ b/src/org/codeaurora/bluetooth/map/BluetoothMasService.java
@@ -801,9 +801,10 @@
         }
 
       private final void closeRfcommSocket(boolean server, boolean accept) throws IOException {
+          if (VERBOSE) Log.v(TAG, "closeRfcommSocket server: "+server + "  conn: " +accept);
           if (server == true) {
             // Stop the possible trying to init serverSocket
-            mInterrupted = false;
+            mInterrupted = true;
 
              if (mServerSocket != null) {
                  mServerSocket.close();
@@ -821,6 +822,11 @@
 
         public void closeConnection() {
             if (VERBOSE) Log.v(TAG, "Mas connection closing");
+            try {
+                closeRfcommSocket(true, true);
+            } catch (IOException ex) {
+                Log.e(TAG, "CloseSocket error: " + ex);
+            }
 
             if (mAcceptThread != null) {
                 try {
@@ -837,11 +843,6 @@
                 mServerSession.close();
                 mServerSession = null;
             }
-            try {
-                closeRfcommSocket(true, true);
-            } catch (IOException ex) {
-                Log.e(TAG, "CloseSocket error: " + ex);
-            }
 
             if (VERBOSE) Log.v(TAG, "Mas connection closed");
         }
diff --git a/src/org/codeaurora/bluetooth/map/MapUtils/EmailUtils.java b/src/org/codeaurora/bluetooth/map/MapUtils/EmailUtils.java
index ce4aecf..dde8b25 100755
--- a/src/org/codeaurora/bluetooth/map/MapUtils/EmailUtils.java
+++ b/src/org/codeaurora/bluetooth/map/MapUtils/EmailUtils.java
@@ -611,6 +611,16 @@
                         bmsg.setRecipientVcard_email(multiRecepients.trim());
                     }
                 }
+                else if(recipientName.contains(",")){
+                    multiRecepients = recipientName.replace(',', ';');
+                    if(multiRecepients != null){
+                        if (V){
+                            Log.v(TAG, " ::Recepient name :: " + multiRecepients);
+                        }
+                        bmsg.setRecipientVcard_name(multiRecepients.trim());
+                        bmsg.setRecipientVcard_email(multiRecepients.trim());
+                    }
+                }
                 else{
                     bmsg.setRecipientVcard_name(recipientName.trim());
                     bmsg.setRecipientVcard_email(recipientName.trim());
diff --git a/src/org/codeaurora/bluetooth/map/MapUtils/MapUtils.java b/src/org/codeaurora/bluetooth/map/MapUtils/MapUtils.java
index 7bceff7..45656a9 100755
--- a/src/org/codeaurora/bluetooth/map/MapUtils/MapUtils.java
+++ b/src/org/codeaurora/bluetooth/map/MapUtils/MapUtils.java
@@ -835,36 +835,73 @@
             // End Originator
 
             sb.append("BEGIN:BENV").append("\r\n");
+            if ((bmsg.recipient_vcard_email != null) &&
+                            (bmsg.recipient_vcard_email.contains(";"))) {
+                if (V) Log.v (TAG, "recipient_vcard_name:" + bmsg.recipient_vcard_name);
+                if (V) Log.v (TAG, "recipient_vcard_phone_number:" + bmsg.recipient_vcard_email);
+                String emailTokens[] = bmsg.recipient_vcard_email.split(";");
+                String nameTokens[] = bmsg.recipient_vcard_name.split(";");
+                if (V) Log.v (TAG, "Length:name:" + nameTokens.length + "number:" + emailTokens.length);
+                for (int i=0; i < emailTokens.length; i++) {
+                    // Recipient
+                    sb.append("BEGIN:VCARD").append("\r\n");
 
-            // Recipient
-            sb.append("BEGIN:VCARD").append("\r\n");
+                    if (bmsg.vcard_version != null) {
+                        sb.append("VERSION:").append(bmsg.vcard_version).append("\r\n");
+                    } else {
 
-            if (bmsg.vcard_version != null) {
-                sb.append("VERSION:").append(bmsg.vcard_version).append("\r\n");
+                    }
+
+                    if (nameTokens[i] != null) {
+                        sb.append("N:").append(nameTokens[i])
+                            .append("\r\n");
+                        sb.append("FN:").append(nameTokens[i])
+                           .append("\r\n");
+                    } else {
+
+                    }
+                    sb.append("TEL:").append("\r\n");
+
+                    if (emailTokens[i] != null) {
+                        sb.append("EMAIL:").append(emailTokens[i])
+                            .append("\r\n");
+                    } else {
+
+                    }
+
+                    sb.append("END:VCARD").append("\r\n");
+                    // End Recipient
+                }
             } else {
+                // Recipient
+                sb.append("BEGIN:VCARD").append("\r\n");
+                if (bmsg.vcard_version != null) {
+                   sb.append("VERSION:").append(bmsg.vcard_version).append("\r\n");
+                } else {
 
-            }
-            if (bmsg.recipient_vcard_name != null) {
-                sb.append("N:").append(bmsg.recipient_vcard_name)
+                }
+                if (bmsg.recipient_vcard_name != null) {
+                   sb.append("N:").append(bmsg.recipient_vcard_name)
                         .append("\r\n");
-            } else {
+                } else {
 
-            }
-            if (bmsg.recipient_vcard_name != null) {
-                sb.append("FN:").append(bmsg.recipient_vcard_name)
+                }
+                if (bmsg.recipient_vcard_name != null) {
+                   sb.append("FN:").append(bmsg.recipient_vcard_name)
                         .append("\r\n");
-            } else {
+                } else {
 
-            }
-            sb.append("TEL:").append("\r\n");
-            if (bmsg.recipient_vcard_email != null) {
-                sb.append("EMAIL:").append(bmsg.recipient_vcard_email)
+                }
+                sb.append("TEL:").append("\r\n");
+                if (bmsg.recipient_vcard_email != null) {
+                   sb.append("EMAIL:").append(bmsg.recipient_vcard_email)
                         .append("\r\n");
-            } else {
+                } else {
 
+                }
+                sb.append("END:VCARD").append("\r\n");
+                // End Recipient
             }
-            sb.append("END:VCARD").append("\r\n");
-            // End Recipient
 
             sb.append("BEGIN:BBODY").append("\r\n");