| /* |
| * 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 <sys/socket.h> |
| |
| #include <common_time/ICommonClock.h> |
| #include <binder/Parcel.h> |
| |
| #include "utils.h" |
| |
| namespace android { |
| |
| /***** ICommonClock *****/ |
| |
| enum { |
| IS_COMMON_TIME_VALID = IBinder::FIRST_CALL_TRANSACTION, |
| COMMON_TIME_TO_LOCAL_TIME, |
| LOCAL_TIME_TO_COMMON_TIME, |
| GET_COMMON_TIME, |
| 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> |
| { |
| public: |
| BpCommonClock(const sp<IBinder>& impl) |
| : BpInterface<ICommonClock>(impl) {} |
| |
| virtual status_t isCommonTimeValid(bool* valid, uint32_t* timelineID) { |
| Parcel data, reply; |
| data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor()); |
| status_t status = remote()->transact(IS_COMMON_TIME_VALID, |
| data, |
| &reply); |
| if (status == OK) { |
| status = reply.readInt32(); |
| if (status == OK) { |
| *valid = reply.readInt32(); |
| *timelineID = reply.readInt32(); |
| } |
| } |
| return status; |
| } |
| |
| virtual status_t commonTimeToLocalTime(int64_t commonTime, |
| int64_t* localTime) { |
| Parcel data, reply; |
| data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor()); |
| data.writeInt64(commonTime); |
| status_t status = remote()->transact(COMMON_TIME_TO_LOCAL_TIME, |
| data, &reply); |
| if (status == OK) { |
| status = reply.readInt32(); |
| if (status == OK) { |
| *localTime = reply.readInt64(); |
| } |
| } |
| return status; |
| } |
| |
| virtual status_t localTimeToCommonTime(int64_t localTime, |
| int64_t* commonTime) { |
| Parcel data, reply; |
| data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor()); |
| data.writeInt64(localTime); |
| status_t status = remote()->transact(LOCAL_TIME_TO_COMMON_TIME, |
| data, &reply); |
| if (status == OK) { |
| status = reply.readInt32(); |
| if (status == OK) { |
| *commonTime = reply.readInt64(); |
| } |
| } |
| return status; |
| } |
| |
| virtual status_t getCommonTime(int64_t* commonTime) { |
| Parcel data, reply; |
| data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor()); |
| status_t status = remote()->transact(GET_COMMON_TIME, data, &reply); |
| if (status == OK) { |
| status = reply.readInt32(); |
| if (status == OK) { |
| *commonTime = reply.readInt64(); |
| } |
| } |
| return status; |
| } |
| |
| virtual status_t getCommonFreq(uint64_t* freq) { |
| Parcel data, reply; |
| data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor()); |
| status_t status = remote()->transact(GET_COMMON_FREQ, data, &reply); |
| if (status == OK) { |
| status = reply.readInt32(); |
| if (status == OK) { |
| *freq = reply.readInt64(); |
| } |
| } |
| return status; |
| } |
| |
| virtual status_t getLocalTime(int64_t* localTime) { |
| Parcel data, reply; |
| data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor()); |
| status_t status = remote()->transact(GET_LOCAL_TIME, data, &reply); |
| if (status == OK) { |
| status = reply.readInt32(); |
| if (status == OK) { |
| *localTime = reply.readInt64(); |
| } |
| } |
| return status; |
| } |
| |
| virtual status_t getLocalFreq(uint64_t* freq) { |
| Parcel data, reply; |
| data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor()); |
| status_t status = remote()->transact(GET_LOCAL_FREQ, data, &reply); |
| if (status == OK) { |
| status = reply.readInt32(); |
| if (status == OK) { |
| *freq = reply.readInt64(); |
| } |
| } |
| 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; |
| data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor()); |
| data.writeStrongBinder(listener->asBinder()); |
| |
| status_t status = remote()->transact(REGISTER_LISTENER, data, &reply); |
| |
| if (status == OK) { |
| status = reply.readInt32(); |
| } |
| |
| return status; |
| } |
| |
| virtual status_t unregisterListener( |
| const sp<ICommonClockListener>& listener) { |
| Parcel data, reply; |
| data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor()); |
| data.writeStrongBinder(listener->asBinder()); |
| status_t status = remote()->transact(UNREGISTER_LISTENER, data, &reply); |
| |
| if (status == OK) { |
| status = reply.readInt32(); |
| } |
| |
| return status; |
| } |
| }; |
| |
| IMPLEMENT_META_INTERFACE(CommonClock, "android.os.ICommonClock"); |
| |
| status_t BnCommonClock::onTransact(uint32_t code, |
| const Parcel& data, |
| Parcel* reply, |
| uint32_t flags) { |
| switch(code) { |
| case IS_COMMON_TIME_VALID: { |
| CHECK_INTERFACE(ICommonClock, data, reply); |
| bool valid; |
| uint32_t timelineID; |
| status_t status = isCommonTimeValid(&valid, &timelineID); |
| reply->writeInt32(status); |
| if (status == OK) { |
| reply->writeInt32(valid); |
| reply->writeInt32(timelineID); |
| } |
| return OK; |
| } break; |
| |
| case COMMON_TIME_TO_LOCAL_TIME: { |
| CHECK_INTERFACE(ICommonClock, data, reply); |
| int64_t commonTime = data.readInt64(); |
| int64_t localTime; |
| status_t status = commonTimeToLocalTime(commonTime, &localTime); |
| reply->writeInt32(status); |
| if (status == OK) { |
| reply->writeInt64(localTime); |
| } |
| return OK; |
| } break; |
| |
| case LOCAL_TIME_TO_COMMON_TIME: { |
| CHECK_INTERFACE(ICommonClock, data, reply); |
| int64_t localTime = data.readInt64(); |
| int64_t commonTime; |
| status_t status = localTimeToCommonTime(localTime, &commonTime); |
| reply->writeInt32(status); |
| if (status == OK) { |
| reply->writeInt64(commonTime); |
| } |
| return OK; |
| } break; |
| |
| case GET_COMMON_TIME: { |
| CHECK_INTERFACE(ICommonClock, data, reply); |
| int64_t commonTime; |
| status_t status = getCommonTime(&commonTime); |
| reply->writeInt32(status); |
| if (status == OK) { |
| reply->writeInt64(commonTime); |
| } |
| return OK; |
| } break; |
| |
| case GET_COMMON_FREQ: { |
| CHECK_INTERFACE(ICommonClock, data, reply); |
| uint64_t freq; |
| status_t status = getCommonFreq(&freq); |
| reply->writeInt32(status); |
| if (status == OK) { |
| reply->writeInt64(freq); |
| } |
| return OK; |
| } break; |
| |
| case GET_LOCAL_TIME: { |
| CHECK_INTERFACE(ICommonClock, data, reply); |
| int64_t localTime; |
| status_t status = getLocalTime(&localTime); |
| reply->writeInt32(status); |
| if (status == OK) { |
| reply->writeInt64(localTime); |
| } |
| return OK; |
| } break; |
| |
| case GET_LOCAL_FREQ: { |
| CHECK_INTERFACE(ICommonClock, data, reply); |
| uint64_t freq; |
| status_t status = getLocalFreq(&freq); |
| reply->writeInt32(status); |
| if (status == OK) { |
| reply->writeInt64(freq); |
| } |
| 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 = |
| interface_cast<ICommonClockListener>(data.readStrongBinder()); |
| status_t status = registerListener(listener); |
| reply->writeInt32(status); |
| return OK; |
| } break; |
| |
| case UNREGISTER_LISTENER: { |
| CHECK_INTERFACE(ICommonClock, data, reply); |
| sp<ICommonClockListener> listener = |
| interface_cast<ICommonClockListener>(data.readStrongBinder()); |
| status_t status = unregisterListener(listener); |
| reply->writeInt32(status); |
| return OK; |
| } break; |
| } |
| return BBinder::onTransact(code, data, reply, flags); |
| } |
| |
| /***** ICommonClockListener *****/ |
| |
| enum { |
| ON_TIMELINE_CHANGED = IBinder::FIRST_CALL_TRANSACTION, |
| }; |
| |
| class BpCommonClockListener : public BpInterface<ICommonClockListener> |
| { |
| public: |
| BpCommonClockListener(const sp<IBinder>& impl) |
| : BpInterface<ICommonClockListener>(impl) {} |
| |
| virtual void onTimelineChanged(uint64_t timelineID) { |
| Parcel data, reply; |
| data.writeInterfaceToken( |
| ICommonClockListener::getInterfaceDescriptor()); |
| data.writeInt64(timelineID); |
| remote()->transact(ON_TIMELINE_CHANGED, data, &reply); |
| } |
| }; |
| |
| IMPLEMENT_META_INTERFACE(CommonClockListener, |
| "android.os.ICommonClockListener"); |
| |
| status_t BnCommonClockListener::onTransact( |
| uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { |
| switch(code) { |
| case ON_TIMELINE_CHANGED: { |
| CHECK_INTERFACE(ICommonClockListener, data, reply); |
| uint32_t timelineID = data.readInt64(); |
| onTimelineChanged(timelineID); |
| return NO_ERROR; |
| } break; |
| } |
| |
| return BBinder::onTransact(code, data, reply, flags); |
| } |
| |
| }; // namespace android |