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 /*
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
30 #include <inttypes.h>
31
32 namespace android {
33
34 //
35 // Clock API
36 //
getTimelineID()37 uint64_t CommonTimeServer::getTimelineID() {
38 AutoMutex _lock(&mLock);
39 return mTimelineID;
40 }
41
getState()42 ICommonClock::State CommonTimeServer::getState() {
43 AutoMutex _lock(&mLock);
44 return mState;
45 }
46
getMasterAddr(struct sockaddr_storage * addr)47 status_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
getEstimatedError()57 int32_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
isCommonTimeValid(bool * valid,uint32_t * timelineID)69 status_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 //
getMasterElectionPriority(uint8_t * priority)80 status_t CommonTimeServer::getMasterElectionPriority(uint8_t *priority) {
81 AutoMutex _lock(&mLock);
82 *priority = mMasterPriority;
83 return OK;
84 }
85
setMasterElectionPriority(uint8_t priority)86 status_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
getMasterElectionEndpoint(struct sockaddr_storage * addr)96 status_t CommonTimeServer::getMasterElectionEndpoint(
97 struct sockaddr_storage *addr) {
98 AutoMutex _lock(&mLock);
99 memcpy(addr, &mMasterElectionEP, sizeof(*addr));
100 return OK;
101 }
102
setMasterElectionEndpoint(const struct sockaddr_storage * addr)103 status_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
getMasterElectionGroupId(uint64_t * id)133 status_t CommonTimeServer::getMasterElectionGroupId(uint64_t *id) {
134 AutoMutex _lock(&mLock);
135 *id = mSyncGroupID;
136 return OK;
137 }
138
setMasterElectionGroupId(uint64_t id)139 status_t CommonTimeServer::setMasterElectionGroupId(uint64_t id) {
140 AutoMutex _lock(&mLock);
141 mSyncGroupID = id;
142 return OK;
143 }
144
getInterfaceBinding(String8 & ifaceName)145 status_t CommonTimeServer::getInterfaceBinding(String8& ifaceName) {
146 AutoMutex _lock(&mLock);
147 if (!mBindIfaceValid)
148 return INVALID_OPERATION;
149 ifaceName = mBindIface;
150 return OK;
151 }
152
setInterfaceBinding(const String8 & ifaceName)153 status_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
getMasterAnnounceInterval(int * interval)169 status_t CommonTimeServer::getMasterAnnounceInterval(int *interval) {
170 AutoMutex _lock(&mLock);
171 *interval = mMasterAnnounceIntervalMs;
172 return OK;
173 }
174
setMasterAnnounceInterval(int interval)175 status_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
getClientSyncInterval(int * interval)197 status_t CommonTimeServer::getClientSyncInterval(int *interval) {
198 AutoMutex _lock(&mLock);
199 *interval = mSyncRequestIntervalMs;
200 return OK;
201 }
202
setClientSyncInterval(int interval)203 status_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
getPanicThreshold(int * threshold)225 status_t CommonTimeServer::getPanicThreshold(int *threshold) {
226 AutoMutex _lock(&mLock);
227 *threshold = mPanicThresholdUsec;
228 return OK;
229 }
230
setPanicThreshold(int threshold)231 status_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
getAutoDisable(bool * autoDisable)241 status_t CommonTimeServer::getAutoDisable(bool *autoDisable) {
242 AutoMutex _lock(&mLock);
243 *autoDisable = mAutoDisable;
244 return OK;
245 }
246
setAutoDisable(bool autoDisable)247 status_t CommonTimeServer::setAutoDisable(bool autoDisable) {
248 AutoMutex _lock(&mLock);
249 mAutoDisable = autoDisable;
250 wakeupThread_l();
251 return OK;
252 }
253
forceNetworklessMasterMode()254 status_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
reevaluateAutoDisableState(bool commonClockHasClients)267 void 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)
288 #define checked_percentage(a, b) ((0 == b) ? 0.0f : ((100.0f * a) / b))
289
dumpClockInterface(int fd,const Vector<String16> &,size_t activeClients)290 status_t CommonTimeServer::dumpClockInterface(int fd,
291 const Vector<String16>& /* args */,
292 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
313 dump_printf("Common Clock Service Status\nLocal time : %" PRId64 "\n",
314 localTime);
315
316 if (synced)
317 dump_printf("Common time : %" PRId64 "\n", commonTime);
318 else
319 dump_printf("Common time : %s\n", "not synced");
320
321 dump_printf("Timeline ID : %016" PRIu64 "\n", mTimelineID);
322 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);
354 dump_printf("Last Good RX : %" PRId64 " uSec ago\n", usecDelta);
355 }
356
357 dump_printf("Active Clients : %zu\n", activeClients);
358 mClient_PacketRTTLog.dumpLog(fd, mCommonClock);
359 mStateChangeLog.dumpLog(fd);
360 mElectionLog.dumpLog(fd);
361 mBadPktLog.dumpLog(fd);
362 }
363
364 return NO_ERROR;
365 }
366
dumpConfigInterface(int fd,const Vector<String16> &)367 status_t CommonTimeServer::dumpConfigInterface(int fd,
368 const Vector<String16>& /* args */) {
369 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);
388 dump_printf("Master Election Group ID : %016" PRIu64 "\n", mSyncGroupID);
389 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
dumpLog(int fd,const CommonClock & cclk)408 void 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);
424 dump_printf("pkt[%2d] : localTX %12" PRId64 " localRX %12" PRId64 " "
425 "(%.3f msec RTT)\n",
426 ndx, txTimes[i], rxTimes[i],
427 static_cast<float>(deltaUsec) / 1000.0);
428 } else {
429 dump_printf("pkt[%2d] : localTX %12" PRId64 " localRX never\n",
430 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
441