Add marshallers for the new common clock methods.

Add marshallers and stub implementations for new methods in the common
clock interface to support new functionality being added in the
process of integrating the common time service more closely with the
Java level of Android.

Change-Id: Iac2d3fb405d1b64cea1d8e13f988160afb76a06d
diff --git a/include/common_time/ICommonClock.h b/include/common_time/ICommonClock.h
index 65f0c01..d7073f1 100644
--- a/include/common_time/ICommonClock.h
+++ b/include/common_time/ICommonClock.h
@@ -18,6 +18,7 @@
 #define ANDROID_ICOMMONCLOCK_H
 
 #include <stdint.h>
+#include <linux/socket.h>
 
 #include <binder/IInterface.h>
 #include <binder/IServiceManager.h>
@@ -28,8 +29,7 @@
   public:
     DECLARE_META_INTERFACE(CommonClockListener);
 
-    virtual void onClockSync(uint32_t timelineID) = 0;
-    virtual void onClockSyncLoss() = 0;
+    virtual void onTimelineChanged(uint64_t timelineID) = 0;
 };
 
 class BnCommonClockListener : public BnInterface<ICommonClockListener> {
@@ -46,30 +46,10 @@
     static const String16 kServiceName;
 
     // a reserved invalid timeline ID
-    static const uint32_t kInvalidTimelineID;
+    static const uint64_t kInvalidTimelineID;
 
-    virtual status_t isCommonTimeValid(bool* valid, uint32_t* timelineID) = 0;
-    virtual status_t commonTimeToLocalTime(int64_t commonTime,
-                                           int64_t* localTime) = 0;
-    virtual status_t localTimeToCommonTime(int64_t localTime,
-                                           int64_t* commonTime) = 0;
-    virtual status_t getCommonTime(int64_t* commonTime) = 0;
-    virtual status_t getCommonFreq(uint64_t* freq) = 0;
-    virtual status_t getLocalTime(int64_t* localTime) = 0;
-    virtual status_t getLocalFreq(uint64_t* freq) = 0;
-
-    virtual status_t registerListener(
-            const sp<ICommonClockListener>& listener) = 0;
-    virtual status_t unregisterListener(
-            const sp<ICommonClockListener>& listener) = 0;
-
-    // Simple helper to make it easier to connect to the CommonClock service.
-    static inline sp<ICommonClock> getInstance() {
-        sp<IBinder> binder = defaultServiceManager()->checkService(
-                ICommonClock::kServiceName);
-        sp<ICommonClock> clk = interface_cast<ICommonClock>(binder);
-        return clk;
-    }
+    // a reserved invalid error estimate
+    static const int32_t kErrorEstimateUnknown;
 
     enum State {
         // the device just came up and is trying to discover the master
@@ -89,6 +69,32 @@
         STATE_WAIT_FOR_ELECTION,
     };
 
+    virtual status_t isCommonTimeValid(bool* valid, uint32_t* timelineID) = 0;
+    virtual status_t commonTimeToLocalTime(int64_t commonTime,
+                                           int64_t* localTime) = 0;
+    virtual status_t localTimeToCommonTime(int64_t localTime,
+                                           int64_t* commonTime) = 0;
+    virtual status_t getCommonTime(int64_t* commonTime) = 0;
+    virtual status_t getCommonFreq(uint64_t* freq) = 0;
+    virtual status_t getLocalTime(int64_t* localTime) = 0;
+    virtual status_t getLocalFreq(uint64_t* freq) = 0;
+    virtual status_t getEstimatedError(int32_t* estimate) = 0;
+    virtual status_t getTimelineID(uint64_t* id) = 0;
+    virtual status_t getState(State* state) = 0;
+    virtual status_t getMasterAddr(struct sockaddr_storage* addr) = 0;
+
+    virtual status_t registerListener(
+            const sp<ICommonClockListener>& listener) = 0;
+    virtual status_t unregisterListener(
+            const sp<ICommonClockListener>& listener) = 0;
+
+    // Simple helper to make it easier to connect to the CommonClock service.
+    static inline sp<ICommonClock> getInstance() {
+        sp<IBinder> binder = defaultServiceManager()->checkService(
+                ICommonClock::kServiceName);
+        sp<ICommonClock> clk = interface_cast<ICommonClock>(binder);
+        return clk;
+    }
 };
 
 class BnCommonClock : public BnInterface<ICommonClock> {
diff --git a/libs/common_time/Android.mk b/libs/common_time/Android.mk
index 1d484c2..6aa3597 100644
--- a/libs/common_time/Android.mk
+++ b/libs/common_time/Android.mk
@@ -11,7 +11,8 @@
 LOCAL_MODULE_TAGS := optional
 LOCAL_SRC_FILES := cc_helper.cpp \
                    local_clock.cpp \
-                   ICommonClock.cpp
+                   ICommonClock.cpp \
+                   utils.cpp
 LOCAL_SHARED_LIBRARIES := libbinder \
                           libhardware \
                           libutils
diff --git a/libs/common_time/ICommonClock.cpp b/libs/common_time/ICommonClock.cpp
index c7f4847..28b43ac 100644
--- a/libs/common_time/ICommonClock.cpp
+++ b/libs/common_time/ICommonClock.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2012 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.
@@ -13,10 +13,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#include <linux/socket.h>
 
 #include <common_time/ICommonClock.h>
 #include <binder/Parcel.h>
 
+#include "utils.h"
+
 namespace android {
 
 /***** ICommonClock *****/
@@ -29,12 +32,17 @@
     GET_COMMON_FREQ,
     GET_LOCAL_TIME,
     GET_LOCAL_FREQ,
+    GET_ESTIMATED_ERROR,
+    GET_TIMELINE_ID,
+    GET_STATE,
+    GET_MASTER_ADDRESS,
     REGISTER_LISTENER,
     UNREGISTER_LISTENER,
 };
 
 const String16 ICommonClock::kServiceName("common_time.clock");
 const uint64_t ICommonClock::kInvalidTimelineID = 0;
+const int32_t ICommonClock::kErrorEstimateUnknown = 0x7FFFFFFF;
 
 class BpCommonClock : public BpInterface<ICommonClock>
 {
@@ -142,6 +150,57 @@
         return status;
     }
 
+    virtual status_t getEstimatedError(int32_t* estimate) {
+        Parcel data, reply;
+        data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor());
+        status_t status = remote()->transact(GET_ESTIMATED_ERROR, data, &reply);
+        if (status == OK) {
+            status = reply.readInt32();
+            if (status == OK) {
+                *estimate = reply.readInt32();
+            }
+        }
+        return status;
+    }
+
+    virtual status_t getTimelineID(uint64_t* id) {
+        Parcel data, reply;
+        data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor());
+        status_t status = remote()->transact(GET_TIMELINE_ID, data, &reply);
+        if (status == OK) {
+            status = reply.readInt32();
+            if (status == OK) {
+                *id = static_cast<uint64_t>(reply.readInt64());
+            }
+        }
+        return status;
+    }
+
+    virtual status_t getState(State* state) {
+        Parcel data, reply;
+        data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor());
+        status_t status = remote()->transact(GET_STATE, data, &reply);
+        if (status == OK) {
+            status = reply.readInt32();
+            if (status == OK) {
+                *state = static_cast<State>(reply.readInt32());
+            }
+        }
+        return status;
+    }
+
+    virtual status_t getMasterAddr(struct sockaddr_storage* addr) {
+        Parcel data, reply;
+        data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor());
+        status_t status = remote()->transact(GET_MASTER_ADDRESS, data, &reply);
+        if (status == OK) {
+            status = reply.readInt32();
+            if (status == OK)
+                deserializeSockaddr(&reply, addr);
+        }
+        return status;
+    }
+
     virtual status_t registerListener(
             const sp<ICommonClockListener>& listener) {
         Parcel data, reply;
@@ -260,6 +319,57 @@
             return OK;
         } break;
 
+        case GET_ESTIMATED_ERROR: {
+            CHECK_INTERFACE(ICommonClock, data, reply);
+            int32_t error;
+            status_t status = getEstimatedError(&error);
+            reply->writeInt32(status);
+            if (status == OK) {
+                reply->writeInt32(error);
+            }
+            return OK;
+        } break;
+
+        case GET_TIMELINE_ID: {
+            CHECK_INTERFACE(ICommonClock, data, reply);
+            uint64_t id;
+            status_t status = getTimelineID(&id);
+            reply->writeInt32(status);
+            if (status == OK) {
+                reply->writeInt64(static_cast<int64_t>(id));
+            }
+            return OK;
+        } break;
+
+        case GET_STATE: {
+            CHECK_INTERFACE(ICommonClock, data, reply);
+            State state;
+            status_t status = getState(&state);
+            reply->writeInt32(status);
+            if (status == OK) {
+                reply->writeInt32(static_cast<int32_t>(state));
+            }
+            return OK;
+        } break;
+
+        case GET_MASTER_ADDRESS: {
+            CHECK_INTERFACE(ICommonClock, data, reply);
+            struct sockaddr_storage addr;
+            status_t status = getMasterAddr(&addr);
+
+            if ((status == OK) && !canSerializeSockaddr(&addr)) {
+                status = UNKNOWN_ERROR;
+            }
+
+            reply->writeInt32(status);
+
+            if (status == OK) {
+                serializeSockaddr(reply, &addr);
+            }
+
+            return OK;
+        } break;
+
         case REGISTER_LISTENER: {
             CHECK_INTERFACE(ICommonClock, data, reply);
             sp<ICommonClockListener> listener =
@@ -284,8 +394,7 @@
 /***** ICommonClockListener *****/
 
 enum {
-    ON_CLOCK_SYNC = IBinder::FIRST_CALL_TRANSACTION,
-    ON_CLOCK_SYNC_LOSS,
+    ON_TIMELINE_CHANGED = IBinder::FIRST_CALL_TRANSACTION,
 };
 
 class BpCommonClockListener : public BpInterface<ICommonClockListener>
@@ -294,19 +403,12 @@
     BpCommonClockListener(const sp<IBinder>& impl)
         : BpInterface<ICommonClockListener>(impl) {}
 
-    virtual void onClockSync(uint32_t timelineID) {
+    virtual void onTimelineChanged(uint64_t timelineID) {
         Parcel data, reply;
         data.writeInterfaceToken(
                 ICommonClockListener::getInterfaceDescriptor());
-        data.writeInt32(timelineID);
-        remote()->transact(ON_CLOCK_SYNC, data, &reply);
-    }
-
-    virtual void onClockSyncLoss() {
-        Parcel data, reply;
-        data.writeInterfaceToken(
-                ICommonClockListener::getInterfaceDescriptor());
-        remote()->transact(ON_CLOCK_SYNC_LOSS, data, &reply);
+        data.writeInt64(timelineID);
+        remote()->transact(ON_TIMELINE_CHANGED, data, &reply);
     }
 };
 
@@ -316,16 +418,10 @@
 status_t BnCommonClockListener::onTransact(
         uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
     switch(code) {
-        case ON_CLOCK_SYNC: {
+        case ON_TIMELINE_CHANGED: {
             CHECK_INTERFACE(ICommonClockListener, data, reply);
-            uint32_t timelineID = data.readInt32();
-            onClockSync(timelineID);
-            return NO_ERROR;
-        } break;
-
-        case ON_CLOCK_SYNC_LOSS: {
-            CHECK_INTERFACE(ICommonClockListener, data, reply);
-            onClockSyncLoss();
+            uint32_t timelineID = data.readInt64();
+            onTimelineChanged(timelineID);
             return NO_ERROR;
         } break;
     }
diff --git a/libs/common_time/utils.cpp b/libs/common_time/utils.cpp
new file mode 100644
index 0000000..6539171
--- /dev/null
+++ b/libs/common_time/utils.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#include <arpa/inet.h>
+#include <linux/socket.h>
+
+#include <binder/Parcel.h>
+
+namespace android {
+
+bool canSerializeSockaddr(const struct sockaddr_storage* addr) {
+    switch (addr->ss_family) {
+        case AF_INET:
+        case AF_INET6:
+            return true;
+        default:
+            return false;
+    }
+}
+
+void serializeSockaddr(Parcel* p, const struct sockaddr_storage* addr) {
+    switch (addr->ss_family) {
+        case AF_INET: {
+            const struct sockaddr_in* s =
+                reinterpret_cast<const struct sockaddr_in*>(addr);
+            p->writeInt32(AF_INET);
+            p->writeInt32(ntohl(s->sin_addr.s_addr));
+            p->writeInt32(static_cast<int32_t>(ntohs(s->sin_port)));
+        } break;
+
+        case AF_INET6: {
+            const struct sockaddr_in6* s =
+                reinterpret_cast<const struct sockaddr_in6*>(addr);
+            const int32_t* a =
+                reinterpret_cast<const int32_t*>(s->sin6_addr.s6_addr);
+            p->writeInt32(AF_INET6);
+            p->writeInt32(ntohl(a[0]));
+            p->writeInt32(ntohl(a[1]));
+            p->writeInt32(ntohl(a[2]));
+            p->writeInt32(ntohl(a[3]));
+            p->writeInt32(static_cast<int32_t>(ntohs(s->sin6_port)));
+            p->writeInt32(ntohl(s->sin6_flowinfo));
+            p->writeInt32(ntohl(s->sin6_scope_id));
+        } break;
+    }
+}
+
+void deserializeSockaddr(const Parcel* p, struct sockaddr_storage* addr) {
+    memset(addr, 0, sizeof(addr));
+
+    addr->ss_family = p->readInt32();
+    switch(addr->ss_family) {
+        case AF_INET: {
+            struct sockaddr_in* s =
+                reinterpret_cast<struct sockaddr_in*>(addr);
+            s->sin_addr.s_addr = htonl(p->readInt32());
+            s->sin_port = htons(static_cast<uint16_t>(p->readInt32()));
+        } break;
+
+        case AF_INET6: {
+            struct sockaddr_in6* s =
+                reinterpret_cast<struct sockaddr_in6*>(addr);
+            int32_t* a = reinterpret_cast<int32_t*>(s->sin6_addr.s6_addr);
+
+            a[0] = htonl(p->readInt32());
+            a[1] = htonl(p->readInt32());
+            a[2] = htonl(p->readInt32());
+            a[3] = htonl(p->readInt32());
+            s->sin6_port = htons(static_cast<uint16_t>(p->readInt32()));
+            s->sin6_flowinfo = htonl(p->readInt32());
+            s->sin6_scope_id = htonl(p->readInt32());
+        } break;
+    }
+}
+
+}  // namespace android
diff --git a/libs/common_time/utils.h b/libs/common_time/utils.h
new file mode 100644
index 0000000..ce79d0d
--- /dev/null
+++ b/libs/common_time/utils.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#ifndef ANDROID_LIBCOMMONCLOCK_UTILS_H
+#define ANDROID_LIBCOMMONCLOCK_UTILS_H
+
+#include <linux/socket.h>
+
+#include <binder/Parcel.h>
+#include <utils/Errors.h>
+
+namespace android {
+
+extern bool canSerializeSockaddr(const struct sockaddr_storage* addr);
+extern void serializeSockaddr(Parcel* p, const struct sockaddr_storage* addr);
+extern status_t deserializeSockaddr(const Parcel* p,
+                                    struct sockaddr_storage* addr);
+
+};  // namespace android
+
+#endif  // ANDROID_LIBCOMMONCLOCK_UTILS_H
diff --git a/services/common_time/common_clock_service.cpp b/services/common_time/common_clock_service.cpp
index bd399f3..5a66e16 100644
--- a/services/common_time/common_clock_service.cpp
+++ b/services/common_time/common_clock_service.cpp
@@ -112,6 +112,22 @@
     return OK;
 }
 
+status_t CommonClockService::getEstimatedError(int32_t* estimate) {
+    return UNKNOWN_ERROR;
+}
+
+status_t CommonClockService::getTimelineID(uint64_t* id) {
+    return UNKNOWN_ERROR;
+}
+
+status_t CommonClockService::getState(State* state) {
+    return UNKNOWN_ERROR;
+}
+
+status_t CommonClockService::getMasterAddr(struct sockaddr_storage* addr) {
+    return UNKNOWN_ERROR;
+}
+
 status_t CommonClockService::registerListener(
         const sp<ICommonClockListener>& listener) {
     Mutex::Autolock lock(mLock);
@@ -152,21 +168,12 @@
     }
 }
 
-void CommonClockService::notifyOnClockSync(uint32_t timelineID) {
+void CommonClockService::notifyOnTimelineChanged(uint64_t timelineID) {
     Mutex::Autolock lock(mLock);
 
     mTimelineID = timelineID;
     for (size_t i = 0; i < mListeners.size(); i++) {
-        mListeners[i]->onClockSync(mTimelineID);
-    }
-}
-
-void CommonClockService::notifyOnClockSyncLoss() {
-    Mutex::Autolock lock(mLock);
-
-    mTimelineID = kInvalidTimelineID;
-    for (size_t i = 0; i < mListeners.size(); i++) {
-        mListeners[i]->onClockSyncLoss();
+        mListeners[i]->onTimelineChanged(mTimelineID);
     }
 }
 
diff --git a/services/common_time/common_clock_service.h b/services/common_time/common_clock_service.h
index 9a4b521..f648427 100644
--- a/services/common_time/common_clock_service.h
+++ b/services/common_time/common_clock_service.h
@@ -41,14 +41,17 @@
     virtual status_t getCommonFreq(uint64_t* freq);
     virtual status_t getLocalTime(int64_t* local_time);
     virtual status_t getLocalFreq(uint64_t* freq);
+    virtual status_t getEstimatedError(int32_t* estimate);
+    virtual status_t getTimelineID(uint64_t* id);
+    virtual status_t getState(ICommonClock::State* state);
+    virtual status_t getMasterAddr(struct sockaddr_storage* addr);
 
     virtual status_t registerListener(
             const sp<ICommonClockListener>& listener);
     virtual status_t unregisterListener(
             const sp<ICommonClockListener>& listener);
 
-    void notifyOnClockSync(uint32_t timelineID);
-    void notifyOnClockSyncLoss();
+    void notifyOnTimelineChanged(uint64_t timelineID);
 
   private:
     CommonClockService() {}
diff --git a/services/common_time/common_time_server.cpp b/services/common_time/common_time_server.cpp
index bc59ca9..4a46c45 100644
--- a/services/common_time/common_time_server.cpp
+++ b/services/common_time/common_time_server.cpp
@@ -1114,15 +1114,16 @@
 
 void CommonTimeServer::notifyClockSync() {
     if (!mClockSynced) {
-        mICommonClock->notifyOnClockSync(mTimelineID);
         mClockSynced = true;
+        mICommonClock->notifyOnTimelineChanged(mTimelineID);
     }
 }
 
 void CommonTimeServer::notifyClockSyncLoss() {
     if (mClockSynced) {
-        mICommonClock->notifyOnClockSyncLoss();
         mClockSynced = false;
+        mICommonClock->notifyOnTimelineChanged(
+                ICommonClock::kInvalidTimelineID);
     }
 }