Implement sendMessageStatus callback in EAS

* Change API for callback to include message subject (when msg is isn't valid)
* Update users of callback to add the new argument
* Use API in EasOutboxService to send status messages back to the UI

Still TODO:  Add relevant error codes for sending problems that are not related
to connection or login issues
diff --git a/src/com/android/exchange/EasOutboxService.java b/src/com/android/exchange/EasOutboxService.java
index 75eff09..ddbadf6 100644
--- a/src/com/android/exchange/EasOutboxService.java
+++ b/src/com/android/exchange/EasOutboxService.java
@@ -32,6 +32,7 @@
 import android.content.ContentValues;
 import android.content.Context;
 import android.database.Cursor;
+import android.os.RemoteException;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -49,6 +50,14 @@
         mContext = _context;
     }
 
+    private void sendCallback(long msgId, String subject, int status) {
+        try {
+            SyncManager.callback().sendMessageStatus(msgId, subject, status, 0);
+        } catch (RemoteException e) {
+            // It's all good
+        }
+    }
+
     /**
      * Send a single message via EAS
      * Note that we mark messages SEND_FAILED when there is a permanent failure, rather than an
@@ -59,6 +68,7 @@
      * @throws IOException
      */
     void sendMessage(File cacheDir, long msgId) throws IOException, MessagingException {
+        sendCallback(msgId, null, EmailServiceStatus.IN_PROGRESS);
         File tmpFile = File.createTempFile("eas_", "tmp", cacheDir);
         // Write the output to a temporary file
         try {
@@ -76,18 +86,29 @@
             int code = resp.getStatusLine().getStatusCode();
             if (code == HttpStatus.SC_OK) {
                 userLog("Deleting message...");
+                // Yes it would be marginally faster to get only the subject, but it would also
+                // be more code; note, we need the subject for the callback below, since the
+                // message gets deleted just below.  This allows the UI to present the subject
+                // of the message in a Toast or other notification
+                Message msg = Message.restoreMessageWithId(mContext, msgId);
                 mContext.getContentResolver().delete(ContentUris.withAppendedId(
                         Message.CONTENT_URI, msgId), null, null);
+                sendCallback(-1, msg.mSubject, EmailServiceStatus.SUCCESS);
             } else {
-                // This case handles post-connection failures (i.e. errors coming back from the
-                // server)
-                // TODO Handle login failures?
                 ContentValues cv = new ContentValues();
                 cv.put(SyncColumns.SERVER_ID, SEND_FAILED);
                 Message.update(mContext, Message.CONTENT_URI, msgId, cv);
+                // TODO REMOTE_EXCEPTION is temporary; add better error codes
+                int result = EmailServiceStatus.REMOTE_EXCEPTION;
+                if (isAuthError(code)) {
+                    result = EmailServiceStatus.LOGIN_FAILED;
+                }
+                sendCallback(msgId, null, result);
             }
-            // TODO Implement the upcoming EmailServiceCallback for messageSent
-            // sendMessageResult(messageId, result);
+        } catch (IOException e) {
+            // We catch this just to send the callback
+            sendCallback(msgId, null, EmailServiceStatus.CONNECTION_ERROR);
+            throw e;
         } finally {
             // Clean up the temporary file
             if (tmpFile.exists()) {
diff --git a/src/com/android/exchange/EasSyncService.java b/src/com/android/exchange/EasSyncService.java
index 98ddce2..9d0e21b 100644
--- a/src/com/android/exchange/EasSyncService.java
+++ b/src/com/android/exchange/EasSyncService.java
@@ -185,7 +185,7 @@
      * @param code the HTTP code returned by the server
      * @return whether or not the code represents an authentication error
      */
-    private boolean isAuthError(int code) {
+    protected boolean isAuthError(int code) {
         return ((code == HttpStatus.SC_UNAUTHORIZED) || (code == HttpStatus.SC_FORBIDDEN));
     }
 
diff --git a/src/com/android/exchange/IEmailServiceCallback.aidl b/src/com/android/exchange/IEmailServiceCallback.aidl
index 9d3bd55..a789c4a 100644
--- a/src/com/android/exchange/IEmailServiceCallback.aidl
+++ b/src/com/android/exchange/IEmailServiceCallback.aidl
@@ -64,5 +64,5 @@
      * statusCode = 0 for OK, 1 for progress, other codes for error
      * progress = 0 for "start", 1..100 for optional progress reports
      */
-    void sendMessageStatus(long messageId, int statusCode, int progress);
+    void sendMessageStatus(long messageId, String subject, int statusCode, int progress);
 }
diff --git a/src/com/android/exchange/SyncManager.java b/src/com/android/exchange/SyncManager.java
index 87d0fbb..dcd6d20 100644
--- a/src/com/android/exchange/SyncManager.java
+++ b/src/com/android/exchange/SyncManager.java
@@ -203,11 +203,11 @@
             }
         }
 
-        public void sendMessageStatus(long messageId, int statusCode, int progress)
+        public void sendMessageStatus(long messageId, String subject, int statusCode, int progress)
                 throws RemoteException {
             IEmailServiceCallback cb = INSTANCE == null ? null: INSTANCE.mCallback;
             if (cb != null) {
-                cb.sendMessageStatus(messageId, statusCode, progress);
+                cb.sendMessageStatus(messageId, subject, statusCode, progress);
             }
         }