Set selfAttendeeStatus and busyStatus properly on downsync/upsync

* Set selfAttendeeStatus on download from busy status
* Set busyStatus on upload from selfAttendeeStatus

Bug: 2587076

Change-Id: I34eaa0d3861bcec0cbfd51761b31965e44f5162b
diff --git a/src/com/android/exchange/adapter/CalendarSyncAdapter.java b/src/com/android/exchange/adapter/CalendarSyncAdapter.java
index 3eab4fb..30549da 100644
--- a/src/com/android/exchange/adapter/CalendarSyncAdapter.java
+++ b/src/com/android/exchange/adapter/CalendarSyncAdapter.java
@@ -97,8 +97,6 @@
     private static final String CATEGORY_TOKENIZER_DELIMITER = "\\";
     private static final String ATTENDEE_TOKENIZER_DELIMITER = CATEGORY_TOKENIZER_DELIMITER;
 
-    private static final String FREE_BUSY_BUSY = "2";
-
     private static final ContentProviderOperation PLACEHOLDER_OPERATION =
         ContentProviderOperation.newInsert(Uri.EMPTY).build();
 
@@ -411,7 +409,9 @@
                         ops.newExtendedProperty("meeting_status", getValue());
                         break;
                     case Tags.CALENDAR_BUSY_STATUS:
-                        ops.newExtendedProperty("busy_status", getValue());
+                        int busyStatus = getValueInt();
+                        cv.put(Events.SELF_ATTENDEE_STATUS,
+                                CalendarUtilities.selfAttendeeStatusFromBusyStatus(busyStatus));
                         break;
                     case Tags.CALENDAR_CATEGORIES:
                         String categories = categoriesParser(ops);
@@ -618,21 +618,19 @@
                     case Tags.CALENDAR_SENSITIVITY:
                         cv.put(Events.VISIBILITY, encodeVisibility(getValueInt()));
                         break;
+                    case Tags.CALENDAR_BUSY_STATUS:
+                        int busyStatus = getValueInt();
+                        cv.put(Events.SELF_ATTENDEE_STATUS,
+                                CalendarUtilities.selfAttendeeStatusFromBusyStatus(busyStatus));
+                        break;
 
                         // TODO How to handle these items that are linked to event id!
-
 //                    case Tags.CALENDAR_DTSTAMP:
 //                        ops.newExtendedProperty("dtstamp", getValue());
 //                        break;
-//                    case Tags.CALENDAR_BUSY_STATUS:
-//                        // TODO Try to fit this into Calendar scheme
-//                        ops.newExtendedProperty("busy_status", getValue());
-//                        break;
 //                    case Tags.CALENDAR_REMINDER_MINS_BEFORE:
 //                        ops.newReminder(getValueInt());
 //                        break;
-
-                        // Not yet handled
                     default:
                         skipTag();
                 }
@@ -1173,7 +1171,10 @@
 
         // Busy status is only required for 2.5, but we need to send it with later
         // versions as well, because if we don't, the server will clear it.
-        s.data(Tags.CALENDAR_BUSY_STATUS, FREE_BUSY_BUSY);
+        int selfAttendeeStatus = entityValues.getAsInteger(Events.SELF_ATTENDEE_STATUS);
+        s.data(Tags.CALENDAR_BUSY_STATUS,
+                Integer.toString(CalendarUtilities
+                        .busyStatusFromSelfAttendeeStatus(selfAttendeeStatus)));
 
         boolean allDay = false;
         if (entityValues.containsKey(Events.ALL_DAY)) {
diff --git a/src/com/android/exchange/utility/CalendarUtilities.java b/src/com/android/exchange/utility/CalendarUtilities.java
index 35e42e1..263b136 100644
--- a/src/com/android/exchange/utility/CalendarUtilities.java
+++ b/src/com/android/exchange/utility/CalendarUtilities.java
@@ -137,6 +137,11 @@
     static final String ICALENDAR_ATTENDEE_TENTATIVE =
         ICALENDAR_ATTENDEE + ";PARTSTAT=TENTATIVE";
 
+    public static final int BUSY_STATUS_BUSY = 0;
+    public static final int BUSY_STATUS_FREE = 1;
+    public static final int BUSY_STATUS_TENTATIVE = 2;
+    public static final int BUSY_STATUS_OOF = 3;
+
     // Return a 4-byte long from a byte array (little endian)
     static int getLong(byte[] bytes, int offset) {
         return (bytes[offset++] & 0xFF) | ((bytes[offset++] & 0xFF) << 8) |
@@ -1210,6 +1215,55 @@
         }
     }
 
+    /**
+     * Get a selfAttendeeStatus from a busy status
+     * The default here is NONE (i.e. we don't know the status)
+     * Note that a busy status of FREE must mean NONE as well, since it can't mean declined
+     * (there would be no event)
+     * @param busyStatus the busy status, from EAS
+     * @return the corresponding value for selfAttendeeStatus
+     */
+    static public int selfAttendeeStatusFromBusyStatus(int busyStatus) {
+        int selfAttendeeStatus;
+        switch (busyStatus) {
+            case BUSY_STATUS_BUSY:
+                selfAttendeeStatus = Attendees.ATTENDEE_STATUS_ACCEPTED;
+                break;
+            case BUSY_STATUS_TENTATIVE:
+                selfAttendeeStatus = Attendees.ATTENDEE_STATUS_TENTATIVE;
+                break;
+            case BUSY_STATUS_FREE:
+            case BUSY_STATUS_OOF:
+            default:
+                selfAttendeeStatus = Attendees.ATTENDEE_STATUS_NONE;
+        }
+        return selfAttendeeStatus;
+    }
+
+    /** Get a busy status from a selfAttendeeStatus
+     * The default here is BUSY
+     * @param selfAttendeeStatus from CalendarProvider2
+     * @return the corresponding value of busy status
+     */
+    static public int busyStatusFromSelfAttendeeStatus(int selfAttendeeStatus) {
+        int busyStatus;
+        switch (selfAttendeeStatus) {
+            case Attendees.ATTENDEE_STATUS_DECLINED:
+            case Attendees.ATTENDEE_STATUS_NONE:
+            case Attendees.ATTENDEE_STATUS_INVITED:
+                busyStatus = BUSY_STATUS_FREE;
+                break;
+            case Attendees.ATTENDEE_STATUS_TENTATIVE:
+                busyStatus = BUSY_STATUS_TENTATIVE;
+                break;
+            case Attendees.ATTENDEE_STATUS_ACCEPTED:
+            default:
+                busyStatus = BUSY_STATUS_BUSY;
+                break;
+        }
+        return busyStatus;
+    }
+
     static public String buildMessageTextFromEntityValues(Context context,
             ContentValues entityValues, StringBuilder sb) {
         if (sb == null) {
diff --git a/tests/src/com/android/exchange/utility/CalendarUtilitiesTests.java b/tests/src/com/android/exchange/utility/CalendarUtilitiesTests.java
index 20916e7..c99fa4b 100644
--- a/tests/src/com/android/exchange/utility/CalendarUtilitiesTests.java
+++ b/tests/src/com/android/exchange/utility/CalendarUtilitiesTests.java
@@ -714,6 +714,39 @@
         assertEquals(uid, "040000008200E00074C5B7101A82E00800000000C0093BBB29B3CA" +
                 "01000000000000000010000000E6E0B06E8756DD459B2FBB1A52DB1A16");
     }
+
+    public void testSelfAttendeeStatusFromBusyStatus() {
+        assertEquals(Attendees.ATTENDEE_STATUS_ACCEPTED,
+                CalendarUtilities.selfAttendeeStatusFromBusyStatus(
+                        CalendarUtilities.BUSY_STATUS_BUSY));
+        assertEquals(Attendees.ATTENDEE_STATUS_TENTATIVE,
+                CalendarUtilities.selfAttendeeStatusFromBusyStatus(
+                        CalendarUtilities.BUSY_STATUS_TENTATIVE));
+        assertEquals(Attendees.ATTENDEE_STATUS_NONE,
+                CalendarUtilities.selfAttendeeStatusFromBusyStatus(
+                        CalendarUtilities.BUSY_STATUS_FREE));
+        assertEquals(Attendees.ATTENDEE_STATUS_NONE,
+                CalendarUtilities.selfAttendeeStatusFromBusyStatus(
+                        CalendarUtilities.BUSY_STATUS_OOF));
+    }
+
+    public void testBusyStatusFromSelfStatus() {
+        assertEquals(CalendarUtilities.BUSY_STATUS_FREE,
+                CalendarUtilities.busyStatusFromSelfAttendeeStatus(
+                        Attendees.ATTENDEE_STATUS_DECLINED));
+        assertEquals(CalendarUtilities.BUSY_STATUS_BUSY,
+                CalendarUtilities.busyStatusFromSelfAttendeeStatus(
+                        Attendees.ATTENDEE_STATUS_NONE));
+        assertEquals(CalendarUtilities.BUSY_STATUS_BUSY,
+                CalendarUtilities.busyStatusFromSelfAttendeeStatus(
+                        Attendees.ATTENDEE_STATUS_INVITED));
+        assertEquals(CalendarUtilities.BUSY_STATUS_TENTATIVE,
+                CalendarUtilities.busyStatusFromSelfAttendeeStatus(
+                        Attendees.ATTENDEE_STATUS_TENTATIVE));
+        assertEquals(CalendarUtilities.BUSY_STATUS_BUSY,
+                CalendarUtilities.busyStatusFromSelfAttendeeStatus(
+                        Attendees.ATTENDEE_STATUS_ACCEPTED));
+    }
 }
 
     // TODO Planned unit tests