1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <sys/socket.h>
18
19#include <common_time/ICommonClock.h>
20#include <binder/Parcel.h>
21
22#include "utils.h"
23
24namespace android {
25
26/***** ICommonClock *****/
27
28enum {
29    IS_COMMON_TIME_VALID = IBinder::FIRST_CALL_TRANSACTION,
30    COMMON_TIME_TO_LOCAL_TIME,
31    LOCAL_TIME_TO_COMMON_TIME,
32    GET_COMMON_TIME,
33    GET_COMMON_FREQ,
34    GET_LOCAL_TIME,
35    GET_LOCAL_FREQ,
36    GET_ESTIMATED_ERROR,
37    GET_TIMELINE_ID,
38    GET_STATE,
39    GET_MASTER_ADDRESS,
40    REGISTER_LISTENER,
41    UNREGISTER_LISTENER,
42};
43
44const String16 ICommonClock::kServiceName("common_time.clock");
45const uint64_t ICommonClock::kInvalidTimelineID = 0;
46const int32_t ICommonClock::kErrorEstimateUnknown = 0x7FFFFFFF;
47
48class BpCommonClock : public BpInterface<ICommonClock>
49{
50  public:
51    explicit BpCommonClock(const sp<IBinder>& impl)
52        : BpInterface<ICommonClock>(impl) {}
53
54    virtual status_t isCommonTimeValid(bool* valid, uint32_t* timelineID) {
55        Parcel data, reply;
56        data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor());
57        status_t status = remote()->transact(IS_COMMON_TIME_VALID,
58                                             data,
59                                             &reply);
60        if (status == OK) {
61            status = reply.readInt32();
62            if (status == OK) {
63                *valid = reply.readInt32();
64                *timelineID = reply.readInt32();
65            }
66        }
67        return status;
68    }
69
70    virtual status_t commonTimeToLocalTime(int64_t commonTime,
71            int64_t* localTime) {
72        Parcel data, reply;
73        data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor());
74        data.writeInt64(commonTime);
75        status_t status = remote()->transact(COMMON_TIME_TO_LOCAL_TIME,
76                data, &reply);
77        if (status == OK) {
78            status = reply.readInt32();
79            if (status == OK) {
80                *localTime = reply.readInt64();
81            }
82        }
83        return status;
84    }
85
86    virtual status_t localTimeToCommonTime(int64_t localTime,
87            int64_t* commonTime) {
88        Parcel data, reply;
89        data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor());
90        data.writeInt64(localTime);
91        status_t status = remote()->transact(LOCAL_TIME_TO_COMMON_TIME,
92                data, &reply);
93        if (status == OK) {
94            status = reply.readInt32();
95            if (status == OK) {
96                *commonTime = reply.readInt64();
97            }
98        }
99        return status;
100    }
101
102    virtual status_t getCommonTime(int64_t* commonTime) {
103        Parcel data, reply;
104        data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor());
105        status_t status = remote()->transact(GET_COMMON_TIME, data, &reply);
106        if (status == OK) {
107            status = reply.readInt32();
108            if (status == OK) {
109                *commonTime = reply.readInt64();
110            }
111        }
112        return status;
113    }
114
115    virtual status_t getCommonFreq(uint64_t* freq) {
116        Parcel data, reply;
117        data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor());
118        status_t status = remote()->transact(GET_COMMON_FREQ, data, &reply);
119        if (status == OK) {
120            status = reply.readInt32();
121            if (status == OK) {
122                *freq = reply.readInt64();
123            }
124        }
125        return status;
126    }
127
128    virtual status_t getLocalTime(int64_t* localTime) {
129        Parcel data, reply;
130        data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor());
131        status_t status = remote()->transact(GET_LOCAL_TIME, data, &reply);
132        if (status == OK) {
133            status = reply.readInt32();
134            if (status == OK) {
135                *localTime = reply.readInt64();
136            }
137        }
138        return status;
139    }
140
141    virtual status_t getLocalFreq(uint64_t* freq) {
142        Parcel data, reply;
143        data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor());
144        status_t status = remote()->transact(GET_LOCAL_FREQ, data, &reply);
145        if (status == OK) {
146            status = reply.readInt32();
147            if (status == OK) {
148                *freq = reply.readInt64();
149            }
150        }
151        return status;
152    }
153
154    virtual status_t getEstimatedError(int32_t* estimate) {
155        Parcel data, reply;
156        data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor());
157        status_t status = remote()->transact(GET_ESTIMATED_ERROR, data, &reply);
158        if (status == OK) {
159            status = reply.readInt32();
160            if (status == OK) {
161                *estimate = reply.readInt32();
162            }
163        }
164        return status;
165    }
166
167    virtual status_t getTimelineID(uint64_t* id) {
168        Parcel data, reply;
169        data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor());
170        status_t status = remote()->transact(GET_TIMELINE_ID, data, &reply);
171        if (status == OK) {
172            status = reply.readInt32();
173            if (status == OK) {
174                *id = static_cast<uint64_t>(reply.readInt64());
175            }
176        }
177        return status;
178    }
179
180    virtual status_t getState(State* state) {
181        Parcel data, reply;
182        data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor());
183        status_t status = remote()->transact(GET_STATE, data, &reply);
184        if (status == OK) {
185            status = reply.readInt32();
186            if (status == OK) {
187                *state = static_cast<State>(reply.readInt32());
188            }
189        }
190        return status;
191    }
192
193    virtual status_t getMasterAddr(struct sockaddr_storage* addr) {
194        Parcel data, reply;
195        data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor());
196        status_t status = remote()->transact(GET_MASTER_ADDRESS, data, &reply);
197        if (status == OK) {
198            status = reply.readInt32();
199            if (status == OK)
200                deserializeSockaddr(&reply, addr);
201        }
202        return status;
203    }
204
205    virtual status_t registerListener(
206            const sp<ICommonClockListener>& listener) {
207        Parcel data, reply;
208        data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor());
209        data.writeStrongBinder(IInterface::asBinder(listener));
210
211        status_t status = remote()->transact(REGISTER_LISTENER, data, &reply);
212
213        if (status == OK) {
214            status = reply.readInt32();
215        }
216
217        return status;
218    }
219
220    virtual status_t unregisterListener(
221            const sp<ICommonClockListener>& listener) {
222        Parcel data, reply;
223        data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor());
224        data.writeStrongBinder(IInterface::asBinder(listener));
225        status_t status = remote()->transact(UNREGISTER_LISTENER, data, &reply);
226
227        if (status == OK) {
228            status = reply.readInt32();
229        }
230
231        return status;
232    }
233};
234
235IMPLEMENT_META_INTERFACE(CommonClock, "android.os.ICommonClock");
236
237status_t BnCommonClock::onTransact(uint32_t code,
238                                   const Parcel& data,
239                                   Parcel* reply,
240                                   uint32_t flags) {
241    switch(code) {
242        case IS_COMMON_TIME_VALID: {
243            CHECK_INTERFACE(ICommonClock, data, reply);
244            bool valid;
245            uint32_t timelineID;
246            status_t status = isCommonTimeValid(&valid, &timelineID);
247            reply->writeInt32(status);
248            if (status == OK) {
249                reply->writeInt32(valid);
250                reply->writeInt32(timelineID);
251            }
252            return OK;
253        } break;
254
255        case COMMON_TIME_TO_LOCAL_TIME: {
256            CHECK_INTERFACE(ICommonClock, data, reply);
257            int64_t commonTime = data.readInt64();
258            int64_t localTime;
259            status_t status = commonTimeToLocalTime(commonTime, &localTime);
260            reply->writeInt32(status);
261            if (status == OK) {
262                reply->writeInt64(localTime);
263            }
264            return OK;
265        } break;
266
267        case LOCAL_TIME_TO_COMMON_TIME: {
268            CHECK_INTERFACE(ICommonClock, data, reply);
269            int64_t localTime = data.readInt64();
270            int64_t commonTime;
271            status_t status = localTimeToCommonTime(localTime, &commonTime);
272            reply->writeInt32(status);
273            if (status == OK) {
274                reply->writeInt64(commonTime);
275            }
276            return OK;
277        } break;
278
279        case GET_COMMON_TIME: {
280            CHECK_INTERFACE(ICommonClock, data, reply);
281            int64_t commonTime;
282            status_t status = getCommonTime(&commonTime);
283            reply->writeInt32(status);
284            if (status == OK) {
285                reply->writeInt64(commonTime);
286            }
287            return OK;
288        } break;
289
290        case GET_COMMON_FREQ: {
291            CHECK_INTERFACE(ICommonClock, data, reply);
292            uint64_t freq;
293            status_t status = getCommonFreq(&freq);
294            reply->writeInt32(status);
295            if (status == OK) {
296                reply->writeInt64(freq);
297            }
298            return OK;
299        } break;
300
301        case GET_LOCAL_TIME: {
302            CHECK_INTERFACE(ICommonClock, data, reply);
303            int64_t localTime;
304            status_t status = getLocalTime(&localTime);
305            reply->writeInt32(status);
306            if (status == OK) {
307                reply->writeInt64(localTime);
308            }
309            return OK;
310        } break;
311
312        case GET_LOCAL_FREQ: {
313            CHECK_INTERFACE(ICommonClock, data, reply);
314            uint64_t freq;
315            status_t status = getLocalFreq(&freq);
316            reply->writeInt32(status);
317            if (status == OK) {
318                reply->writeInt64(freq);
319            }
320            return OK;
321        } break;
322
323        case GET_ESTIMATED_ERROR: {
324            CHECK_INTERFACE(ICommonClock, data, reply);
325            int32_t error;
326            status_t status = getEstimatedError(&error);
327            reply->writeInt32(status);
328            if (status == OK) {
329                reply->writeInt32(error);
330            }
331            return OK;
332        } break;
333
334        case GET_TIMELINE_ID: {
335            CHECK_INTERFACE(ICommonClock, data, reply);
336            uint64_t id;
337            status_t status = getTimelineID(&id);
338            reply->writeInt32(status);
339            if (status == OK) {
340                reply->writeInt64(static_cast<int64_t>(id));
341            }
342            return OK;
343        } break;
344
345        case GET_STATE: {
346            CHECK_INTERFACE(ICommonClock, data, reply);
347            State state;
348            status_t status = getState(&state);
349            reply->writeInt32(status);
350            if (status == OK) {
351                reply->writeInt32(static_cast<int32_t>(state));
352            }
353            return OK;
354        } break;
355
356        case GET_MASTER_ADDRESS: {
357            CHECK_INTERFACE(ICommonClock, data, reply);
358            struct sockaddr_storage addr;
359            status_t status = getMasterAddr(&addr);
360
361            if ((status == OK) && !canSerializeSockaddr(&addr)) {
362                status = UNKNOWN_ERROR;
363            }
364
365            reply->writeInt32(status);
366
367            if (status == OK) {
368                serializeSockaddr(reply, &addr);
369            }
370
371            return OK;
372        } break;
373
374        case REGISTER_LISTENER: {
375            CHECK_INTERFACE(ICommonClock, data, reply);
376            sp<ICommonClockListener> listener =
377                interface_cast<ICommonClockListener>(data.readStrongBinder());
378            status_t status = registerListener(listener);
379            reply->writeInt32(status);
380            return OK;
381        } break;
382
383        case UNREGISTER_LISTENER: {
384            CHECK_INTERFACE(ICommonClock, data, reply);
385            sp<ICommonClockListener> listener =
386                interface_cast<ICommonClockListener>(data.readStrongBinder());
387            status_t status = unregisterListener(listener);
388            reply->writeInt32(status);
389            return OK;
390        } break;
391    }
392    return BBinder::onTransact(code, data, reply, flags);
393}
394
395/***** ICommonClockListener *****/
396
397enum {
398    ON_TIMELINE_CHANGED = IBinder::FIRST_CALL_TRANSACTION,
399};
400
401class BpCommonClockListener : public BpInterface<ICommonClockListener>
402{
403  public:
404    explicit BpCommonClockListener(const sp<IBinder>& impl)
405        : BpInterface<ICommonClockListener>(impl) {}
406
407    virtual void onTimelineChanged(uint64_t timelineID) {
408        Parcel data, reply;
409        data.writeInterfaceToken(
410                ICommonClockListener::getInterfaceDescriptor());
411        data.writeInt64(timelineID);
412        remote()->transact(ON_TIMELINE_CHANGED, data, &reply);
413    }
414};
415
416IMPLEMENT_META_INTERFACE(CommonClockListener,
417                         "android.os.ICommonClockListener");
418
419status_t BnCommonClockListener::onTransact(
420        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
421    switch(code) {
422        case ON_TIMELINE_CHANGED: {
423            CHECK_INTERFACE(ICommonClockListener, data, reply);
424            uint32_t timelineID = data.readInt64();
425            onTimelineChanged(timelineID);
426            return NO_ERROR;
427        } break;
428    }
429
430    return BBinder::onTransact(code, data, reply, flags);
431}
432
433}; // namespace android
434