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