• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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