blob: 60e65677b2f9a1c55cd26ed2cf21e4c5bcf17108 [file] [log] [blame]
Mike J. Chen6c929512011-08-15 11:59:47 -07001/*
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/*
18 * A service that exchanges time synchronization information between
19 * a master that defines a timeline and clients that follow the timeline.
20 */
21
22#define LOG_TAG "common_time"
23#include <utils/Log.h>
24
25#include <binder/IServiceManager.h>
26#include <binder/IPCThreadState.h>
27
28#include "common_time_server.h"
29
Andreas Gampe4c57eda2014-11-10 11:51:01 -080030#include <inttypes.h>
31
Mike J. Chen6c929512011-08-15 11:59:47 -070032namespace android {
33
34//
35// Clock API
36//
37uint64_t CommonTimeServer::getTimelineID() {
38 AutoMutex _lock(&mLock);
39 return mTimelineID;
40}
41
42ICommonClock::State CommonTimeServer::getState() {
43 AutoMutex _lock(&mLock);
44 return mState;
45}
46
47status_t CommonTimeServer::getMasterAddr(struct sockaddr_storage* addr) {
48 AutoMutex _lock(&mLock);
49 if (mMasterEPValid) {
50 memcpy(addr, &mMasterEP, sizeof(*addr));
51 return OK;
52 }
53
54 return UNKNOWN_ERROR;
55}
56
57int32_t CommonTimeServer::getEstimatedError() {
58 AutoMutex _lock(&mLock);
59
60 if (ICommonClock::STATE_MASTER == mState)
61 return 0;
62
63 if (!mClockSynced)
64 return ICommonClock::kErrorEstimateUnknown;
65
66 return mClockRecovery.getLastErrorEstimate();
67}
68
69status_t CommonTimeServer::isCommonTimeValid(bool* valid,
70 uint32_t* timelineID) {
71 AutoMutex _lock(&mLock);
72 *valid = mCommonClock.isValid();
73 *timelineID = mTimelineID;
74 return OK;
75}
76
77//
78// Config API
79//
80status_t CommonTimeServer::getMasterElectionPriority(uint8_t *priority) {
81 AutoMutex _lock(&mLock);
82 *priority = mMasterPriority;
83 return OK;
84}
85
86status_t CommonTimeServer::setMasterElectionPriority(uint8_t priority) {
87 AutoMutex _lock(&mLock);
88
89 if (priority > 0x7F)
90 return BAD_VALUE;
91
92 mMasterPriority = priority;
93 return OK;
94}
95
96status_t CommonTimeServer::getMasterElectionEndpoint(
97 struct sockaddr_storage *addr) {
98 AutoMutex _lock(&mLock);
99 memcpy(addr, &mMasterElectionEP, sizeof(*addr));
100 return OK;
101}
102
103status_t CommonTimeServer::setMasterElectionEndpoint(
104 const struct sockaddr_storage *addr) {
105 AutoMutex _lock(&mLock);
106
107 if (!addr)
108 return BAD_VALUE;
109
110 // TODO: add proper support for IPv6
111 if (addr->ss_family != AF_INET)
112 return BAD_VALUE;
113
114 // Only multicast and broadcast endpoints with explicit ports are allowed.
115 uint16_t ipv4Port = ntohs(
116 reinterpret_cast<const struct sockaddr_in*>(addr)->sin_port);
117 if (!ipv4Port)
118 return BAD_VALUE;
119
120 uint32_t ipv4Addr = ntohl(
121 reinterpret_cast<const struct sockaddr_in*>(addr)->sin_addr.s_addr);
122 if ((ipv4Addr != 0xFFFFFFFF) && (0xE0000000 != (ipv4Addr & 0xF0000000)))
123 return BAD_VALUE;
124
125 memcpy(&mMasterElectionEP, addr, sizeof(mMasterElectionEP));
126
127 // Force a rebind in order to change election enpoints.
128 mBindIfaceDirty = true;
129 wakeupThread_l();
130 return OK;
131}
132
133status_t CommonTimeServer::getMasterElectionGroupId(uint64_t *id) {
134 AutoMutex _lock(&mLock);
135 *id = mSyncGroupID;
136 return OK;
137}
138
139status_t CommonTimeServer::setMasterElectionGroupId(uint64_t id) {
140 AutoMutex _lock(&mLock);
141 mSyncGroupID = id;
142 return OK;
143}
144
145status_t CommonTimeServer::getInterfaceBinding(String8& ifaceName) {
146 AutoMutex _lock(&mLock);
147 if (!mBindIfaceValid)
148 return INVALID_OPERATION;
149 ifaceName = mBindIface;
150 return OK;
151}
152
153status_t CommonTimeServer::setInterfaceBinding(const String8& ifaceName) {
154 AutoMutex _lock(&mLock);
155
156 mBindIfaceDirty = true;
157 if (ifaceName.size()) {
158 mBindIfaceValid = true;
159 mBindIface = ifaceName;
160 } else {
161 mBindIfaceValid = false;
162 mBindIface.clear();
163 }
164
165 wakeupThread_l();
166 return OK;
167}
168
169status_t CommonTimeServer::getMasterAnnounceInterval(int *interval) {
170 AutoMutex _lock(&mLock);
171 *interval = mMasterAnnounceIntervalMs;
172 return OK;
173}
174
175status_t CommonTimeServer::setMasterAnnounceInterval(int interval) {
176 AutoMutex _lock(&mLock);
177
178 if (interval > (6 *3600000)) // Max interval is once every 6 hrs
179 return BAD_VALUE;
180
181 if (interval < 500) // Min interval is once per 0.5 seconds
182 return BAD_VALUE;
183
184 mMasterAnnounceIntervalMs = interval;
185 if (ICommonClock::STATE_MASTER == mState) {
186 int pendingTimeout = mCurTimeout.msecTillTimeout();
187 if ((kInfiniteTimeout == pendingTimeout) ||
188 (pendingTimeout > interval)) {
189 mCurTimeout.setTimeout(mMasterAnnounceIntervalMs);
190 wakeupThread_l();
191 }
192 }
193
194 return OK;
195}
196
197status_t CommonTimeServer::getClientSyncInterval(int *interval) {
198 AutoMutex _lock(&mLock);
199 *interval = mSyncRequestIntervalMs;
200 return OK;
201}
202
203status_t CommonTimeServer::setClientSyncInterval(int interval) {
204 AutoMutex _lock(&mLock);
205
206 if (interval > (3600000)) // Max interval is once every 60 min
207 return BAD_VALUE;
208
209 if (interval < 250) // Min interval is once per 0.25 seconds
210 return BAD_VALUE;
211
212 mSyncRequestIntervalMs = interval;
213 if (ICommonClock::STATE_CLIENT == mState) {
214 int pendingTimeout = mCurTimeout.msecTillTimeout();
215 if ((kInfiniteTimeout == pendingTimeout) ||
216 (pendingTimeout > interval)) {
217 mCurTimeout.setTimeout(mSyncRequestIntervalMs);
218 wakeupThread_l();
219 }
220 }
221
222 return OK;
223}
224
225status_t CommonTimeServer::getPanicThreshold(int *threshold) {
226 AutoMutex _lock(&mLock);
227 *threshold = mPanicThresholdUsec;
228 return OK;
229}
230
231status_t CommonTimeServer::setPanicThreshold(int threshold) {
232 AutoMutex _lock(&mLock);
233
234 if (threshold < 1000) // Min threshold is 1mSec
235 return BAD_VALUE;
236
237 mPanicThresholdUsec = threshold;
238 return OK;
239}
240
241status_t CommonTimeServer::getAutoDisable(bool *autoDisable) {
242 AutoMutex _lock(&mLock);
243 *autoDisable = mAutoDisable;
244 return OK;
245}
246
247status_t CommonTimeServer::setAutoDisable(bool autoDisable) {
248 AutoMutex _lock(&mLock);
249 mAutoDisable = autoDisable;
250 wakeupThread_l();
251 return OK;
252}
253
254status_t CommonTimeServer::forceNetworklessMasterMode() {
255 AutoMutex _lock(&mLock);
256
257 // Can't force networkless master mode if we are currently bound to a
258 // network.
259 if (mSocket >= 0)
260 return INVALID_OPERATION;
261
262 becomeMaster("force networkless");
263
264 return OK;
265}
266
267void CommonTimeServer::reevaluateAutoDisableState(bool commonClockHasClients) {
268 AutoMutex _lock(&mLock);
269 bool needWakeup = (mAutoDisable && mMasterEPValid &&
270 (commonClockHasClients != mCommonClockHasClients));
271
272 mCommonClockHasClients = commonClockHasClients;
273
274 if (needWakeup) {
275 ALOGI("Waking up service, auto-disable is engaged and service now has%s"
276 " clients", mCommonClockHasClients ? "" : " no");
277 wakeupThread_l();
278 }
279}
280
281#define dump_printf(a, b...) do { \
282 int res; \
283 res = snprintf(buffer, sizeof(buffer), a, b); \
284 buffer[sizeof(buffer) - 1] = 0; \
285 if (res > 0) \
286 write(fd, buffer, res); \
287} while (0)
Chih-Hung Hsieh2bd7a3e2016-05-19 15:21:42 -0700288#define checked_percentage(a, b) ((0 == (b)) ? 0.0f : ((100.0f * (a)) / (b)))
Mike J. Chen6c929512011-08-15 11:59:47 -0700289
290status_t CommonTimeServer::dumpClockInterface(int fd,
Andreas Gampe4c57eda2014-11-10 11:51:01 -0800291 const Vector<String16>& /* args */,
Mike J. Chen6c929512011-08-15 11:59:47 -0700292 size_t activeClients) {
293 AutoMutex _lock(&mLock);
294 const size_t SIZE = 256;
295 char buffer[SIZE];
296
297 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
298 snprintf(buffer, SIZE, "Permission Denial: "
299 "can't dump CommonClockService from pid=%d, uid=%d\n",
300 IPCThreadState::self()->getCallingPid(),
301 IPCThreadState::self()->getCallingUid());
302 write(fd, buffer, strlen(buffer));
303 } else {
304 int64_t commonTime;
305 int64_t localTime;
306 bool synced;
307 char maStr[64];
308
309 localTime = mLocalClock.getLocalTime();
310 synced = (OK == mCommonClock.localToCommon(localTime, &commonTime));
311 sockaddrToString(mMasterEP, mMasterEPValid, maStr, sizeof(maStr));
312
Andreas Gampe4c57eda2014-11-10 11:51:01 -0800313 dump_printf("Common Clock Service Status\nLocal time : %" PRId64 "\n",
Mike J. Chen6c929512011-08-15 11:59:47 -0700314 localTime);
315
316 if (synced)
Andreas Gampe4c57eda2014-11-10 11:51:01 -0800317 dump_printf("Common time : %" PRId64 "\n", commonTime);
Mike J. Chen6c929512011-08-15 11:59:47 -0700318 else
319 dump_printf("Common time : %s\n", "not synced");
320
Andreas Gampe4c57eda2014-11-10 11:51:01 -0800321 dump_printf("Timeline ID : %016" PRIu64 "\n", mTimelineID);
Mike J. Chen6c929512011-08-15 11:59:47 -0700322 dump_printf("State : %s\n", stateToString(mState));
323 dump_printf("Master Addr : %s\n", maStr);
324
325
326 if (synced) {
327 int32_t est = (ICommonClock::STATE_MASTER != mState)
328 ? mClockRecovery.getLastErrorEstimate()
329 : 0;
330 dump_printf("Error Est. : %.3f msec\n",
331 static_cast<float>(est) / 1000.0);
332 } else {
333 dump_printf("Error Est. : %s\n", "unknown");
334 }
335
336 dump_printf("Syncs TXes : %u\n", mClient_SyncsSentToCurMaster);
337 dump_printf("Syncs RXes : %u (%.2f%%)\n",
338 mClient_SyncRespsRXedFromCurMaster,
339 checked_percentage(
340 mClient_SyncRespsRXedFromCurMaster,
341 mClient_SyncsSentToCurMaster));
342 dump_printf("RXs Expired : %u (%.2f%%)\n",
343 mClient_ExpiredSyncRespsRXedFromCurMaster,
344 checked_percentage(
345 mClient_ExpiredSyncRespsRXedFromCurMaster,
346 mClient_SyncsSentToCurMaster));
347
348 if (!mClient_LastGoodSyncRX) {
349 dump_printf("Last Good RX : %s\n", "unknown");
350 } else {
351 int64_t localDelta, usecDelta;
352 localDelta = localTime - mClient_LastGoodSyncRX;
353 usecDelta = mCommonClock.localDurationToCommonDuration(localDelta);
Andreas Gampe4c57eda2014-11-10 11:51:01 -0800354 dump_printf("Last Good RX : %" PRId64 " uSec ago\n", usecDelta);
Mike J. Chen6c929512011-08-15 11:59:47 -0700355 }
356
Andreas Gampe4c57eda2014-11-10 11:51:01 -0800357 dump_printf("Active Clients : %zu\n", activeClients);
Mike J. Chen6c929512011-08-15 11:59:47 -0700358 mClient_PacketRTTLog.dumpLog(fd, mCommonClock);
John Grossman79489c42012-07-20 10:17:26 -0700359 mStateChangeLog.dumpLog(fd);
360 mElectionLog.dumpLog(fd);
361 mBadPktLog.dumpLog(fd);
Mike J. Chen6c929512011-08-15 11:59:47 -0700362 }
363
364 return NO_ERROR;
365}
366
367status_t CommonTimeServer::dumpConfigInterface(int fd,
Andreas Gampe4c57eda2014-11-10 11:51:01 -0800368 const Vector<String16>& /* args */) {
Mike J. Chen6c929512011-08-15 11:59:47 -0700369 AutoMutex _lock(&mLock);
370 const size_t SIZE = 256;
371 char buffer[SIZE];
372
373 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
374 snprintf(buffer, SIZE, "Permission Denial: "
375 "can't dump CommonTimeConfigService from pid=%d, uid=%d\n",
376 IPCThreadState::self()->getCallingPid(),
377 IPCThreadState::self()->getCallingUid());
378 write(fd, buffer, strlen(buffer));
379 } else {
380 char meStr[64];
381
382 sockaddrToString(mMasterElectionEP, true, meStr, sizeof(meStr));
383
384 dump_printf("Common Time Config Service Status\n"
385 "Bound Interface : %s\n",
386 mBindIfaceValid ? mBindIface.string() : "<unbound>");
387 dump_printf("Master Election Endpoint : %s\n", meStr);
Andreas Gampe4c57eda2014-11-10 11:51:01 -0800388 dump_printf("Master Election Group ID : %016" PRIu64 "\n", mSyncGroupID);
Mike J. Chen6c929512011-08-15 11:59:47 -0700389 dump_printf("Master Announce Interval : %d mSec\n",
390 mMasterAnnounceIntervalMs);
391 dump_printf("Client Sync Interval : %d mSec\n",
392 mSyncRequestIntervalMs);
393 dump_printf("Panic Threshold : %d uSec\n",
394 mPanicThresholdUsec);
395 dump_printf("Base ME Prio : 0x%02x\n",
396 static_cast<uint32_t>(mMasterPriority));
397 dump_printf("Effective ME Prio : 0x%02x\n",
398 static_cast<uint32_t>(effectivePriority()));
399 dump_printf("Auto Disable Allowed : %s\n",
400 mAutoDisable ? "yes" : "no");
401 dump_printf("Auto Disable Engaged : %s\n",
402 shouldAutoDisable() ? "yes" : "no");
403 }
404
405 return NO_ERROR;
406}
407
408void CommonTimeServer::PacketRTTLog::dumpLog(int fd, const CommonClock& cclk) {
409 const size_t SIZE = 256;
410 char buffer[SIZE];
411 uint32_t avail = !logFull ? wrPtr : RTT_LOG_SIZE;
412
413 if (!avail)
414 return;
415
416 dump_printf("\nPacket Log (%d entries)\n", avail);
417
418 uint32_t ndx = 0;
419 uint32_t i = logFull ? wrPtr : 0;
420 do {
421 if (rxTimes[i]) {
422 int64_t delta = rxTimes[i] - txTimes[i];
423 int64_t deltaUsec = cclk.localDurationToCommonDuration(delta);
Andreas Gampe4c57eda2014-11-10 11:51:01 -0800424 dump_printf("pkt[%2d] : localTX %12" PRId64 " localRX %12" PRId64 " "
Mike J. Chen6c929512011-08-15 11:59:47 -0700425 "(%.3f msec RTT)\n",
426 ndx, txTimes[i], rxTimes[i],
427 static_cast<float>(deltaUsec) / 1000.0);
428 } else {
Andreas Gampe4c57eda2014-11-10 11:51:01 -0800429 dump_printf("pkt[%2d] : localTX %12" PRId64 " localRX never\n",
Mike J. Chen6c929512011-08-15 11:59:47 -0700430 ndx, txTimes[i]);
431 }
432 i = (i + 1) % RTT_LOG_SIZE;
433 ndx++;
434 } while (i != wrPtr);
435}
436
437#undef dump_printf
438#undef checked_percentage
439
440} // namespace android