summaryrefslogtreecommitdiffstats
path: root/services/common_time
diff options
context:
space:
mode:
Diffstat (limited to 'services/common_time')
-rw-r--r--services/common_time/Android.mk36
-rw-r--r--services/common_time/clock_recovery.cpp423
-rw-r--r--services/common_time/clock_recovery.h159
-rw-r--r--services/common_time/common_clock.cpp150
-rw-r--r--services/common_time/common_clock.h57
-rw-r--r--services/common_time/common_clock_service.cpp157
-rw-r--r--services/common_time/common_clock_service.h91
-rw-r--r--services/common_time/common_time_config_service.cpp112
-rw-r--r--services/common_time/common_time_config_service.h60
-rw-r--r--services/common_time/common_time_server.cpp1506
-rw-r--r--services/common_time/common_time_server.h324
-rw-r--r--services/common_time/common_time_server_api.cpp438
-rw-r--r--services/common_time/common_time_server_packets.cpp293
-rw-r--r--services/common_time/common_time_server_packets.h189
-rw-r--r--services/common_time/diag_thread.cpp323
-rw-r--r--services/common_time/diag_thread.h76
-rw-r--r--services/common_time/main.cpp43
-rw-r--r--services/common_time/utils.cpp164
-rw-r--r--services/common_time/utils.h83
19 files changed, 0 insertions, 4684 deletions
diff --git a/services/common_time/Android.mk b/services/common_time/Android.mk
deleted file mode 100644
index 75eb528..0000000
--- a/services/common_time/Android.mk
+++ /dev/null
@@ -1,36 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-#
-# common_time_service
-#
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
- common_clock_service.cpp \
- common_time_config_service.cpp \
- common_time_server.cpp \
- common_time_server_api.cpp \
- common_time_server_packets.cpp \
- clock_recovery.cpp \
- common_clock.cpp \
- main.cpp \
- utils.cpp
-
-# Uncomment to enable vesbose logging and debug service.
-#TIME_SERVICE_DEBUG=true
-ifeq ($(TIME_SERVICE_DEBUG), true)
-LOCAL_SRC_FILES += diag_thread.cpp
-LOCAL_CFLAGS += -DTIME_SERVICE_DEBUG
-endif
-
-LOCAL_SHARED_LIBRARIES := \
- libbinder \
- libcommon_time_client \
- libutils \
- liblog
-
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE := common_time
-
-include $(BUILD_EXECUTABLE)
diff --git a/services/common_time/clock_recovery.cpp b/services/common_time/clock_recovery.cpp
deleted file mode 100644
index 3a7c70c..0000000
--- a/services/common_time/clock_recovery.cpp
+++ /dev/null
@@ -1,423 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * A service that exchanges time synchronization information between
- * a master that defines a timeline and clients that follow the timeline.
- */
-
-#define __STDC_LIMIT_MACROS
-#define LOG_TAG "common_time"
-#include <utils/Log.h>
-#include <stdint.h>
-
-#include <common_time/local_clock.h>
-#include <assert.h>
-
-#include "clock_recovery.h"
-#include "common_clock.h"
-#ifdef TIME_SERVICE_DEBUG
-#include "diag_thread.h"
-#endif
-
-// Define log macro so we can make LOGV into LOGE when we are exclusively
-// debugging this code.
-#ifdef TIME_SERVICE_DEBUG
-#define LOG_TS ALOGE
-#else
-#define LOG_TS ALOGV
-#endif
-
-namespace android {
-
-ClockRecoveryLoop::ClockRecoveryLoop(LocalClock* local_clock,
- CommonClock* common_clock) {
- assert(NULL != local_clock);
- assert(NULL != common_clock);
-
- local_clock_ = local_clock;
- common_clock_ = common_clock;
-
- local_clock_can_slew_ = local_clock_->initCheck() &&
- (local_clock_->setLocalSlew(0) == OK);
- tgt_correction_ = 0;
- cur_correction_ = 0;
-
- // Precompute the max rate at which we are allowed to change the VCXO
- // control.
- uint64_t N = 0x10000ull * 1000ull;
- uint64_t D = local_clock_->getLocalFreq() * kMinFullRangeSlewChange_mSec;
- LinearTransform::reduce(&N, &D);
- while ((N > INT32_MAX) || (D > UINT32_MAX)) {
- N >>= 1;
- D >>= 1;
- LinearTransform::reduce(&N, &D);
- }
- time_to_cur_slew_.a_to_b_numer = static_cast<int32_t>(N);
- time_to_cur_slew_.a_to_b_denom = static_cast<uint32_t>(D);
-
- reset(true, true);
-
-#ifdef TIME_SERVICE_DEBUG
- diag_thread_ = new DiagThread(common_clock_, local_clock_);
- if (diag_thread_ != NULL) {
- status_t res = diag_thread_->startWorkThread();
- if (res != OK)
- ALOGW("Failed to start A@H clock recovery diagnostic thread.");
- } else
- ALOGW("Failed to allocate diagnostic thread.");
-#endif
-}
-
-ClockRecoveryLoop::~ClockRecoveryLoop() {
-#ifdef TIME_SERVICE_DEBUG
- diag_thread_->stopWorkThread();
-#endif
-}
-
-// Constants.
-const float ClockRecoveryLoop::dT = 1.0;
-const float ClockRecoveryLoop::Kc = 1.0f;
-const float ClockRecoveryLoop::Ti = 15.0f;
-const float ClockRecoveryLoop::Tf = 0.05;
-const float ClockRecoveryLoop::bias_Fc = 0.01;
-const float ClockRecoveryLoop::bias_RC = (dT / (2 * 3.14159f * bias_Fc));
-const float ClockRecoveryLoop::bias_Alpha = (dT / (bias_RC + dT));
-const int64_t ClockRecoveryLoop::panic_thresh_ = 50000;
-const int64_t ClockRecoveryLoop::control_thresh_ = 10000;
-const float ClockRecoveryLoop::COmin = -100.0f;
-const float ClockRecoveryLoop::COmax = 100.0f;
-const uint32_t ClockRecoveryLoop::kMinFullRangeSlewChange_mSec = 300;
-const int ClockRecoveryLoop::kSlewChangeStepPeriod_mSec = 10;
-
-
-void ClockRecoveryLoop::reset(bool position, bool frequency) {
- Mutex::Autolock lock(&lock_);
- reset_l(position, frequency);
-}
-
-uint32_t ClockRecoveryLoop::findMinRTTNdx(DisciplineDataPoint* data,
- uint32_t count) {
- uint32_t min_rtt = 0;
- for (uint32_t i = 1; i < count; ++i)
- if (data[min_rtt].rtt > data[i].rtt)
- min_rtt = i;
-
- return min_rtt;
-}
-
-bool ClockRecoveryLoop::pushDisciplineEvent(int64_t local_time,
- int64_t nominal_common_time,
- int64_t rtt) {
- Mutex::Autolock lock(&lock_);
-
- int64_t local_common_time = 0;
- common_clock_->localToCommon(local_time, &local_common_time);
- int64_t raw_delta = nominal_common_time - local_common_time;
-
-#ifdef TIME_SERVICE_DEBUG
- ALOGE("local=%lld, common=%lld, delta=%lld, rtt=%lld\n",
- local_common_time, nominal_common_time,
- raw_delta, rtt);
-#endif
-
- // If we have not defined a basis for common time, then we need to use these
- // initial points to do so. In order to avoid significant initial error
- // from a particularly bad startup data point, we collect the first N data
- // points and choose the best of them before moving on.
- if (!common_clock_->isValid()) {
- if (startup_filter_wr_ < kStartupFilterSize) {
- DisciplineDataPoint& d = startup_filter_data_[startup_filter_wr_];
- d.local_time = local_time;
- d.nominal_common_time = nominal_common_time;
- d.rtt = rtt;
- startup_filter_wr_++;
- }
-
- if (startup_filter_wr_ == kStartupFilterSize) {
- uint32_t min_rtt = findMinRTTNdx(startup_filter_data_,
- kStartupFilterSize);
-
- common_clock_->setBasis(
- startup_filter_data_[min_rtt].local_time,
- startup_filter_data_[min_rtt].nominal_common_time);
- }
-
- return true;
- }
-
- int64_t observed_common;
- int64_t delta;
- float delta_f, dCO;
- int32_t tgt_correction;
-
- if (OK != common_clock_->localToCommon(local_time, &observed_common)) {
- // Since we just checked to make certain that this conversion was valid,
- // and no one else in the system should be messing with it, if this
- // conversion is suddenly invalid, it is a good reason to panic.
- ALOGE("Failed to convert local time to common time in %s:%d",
- __PRETTY_FUNCTION__, __LINE__);
- return false;
- }
-
- // Implement a filter which should match NTP filtering behavior when a
- // client is associated with only one peer of lower stratum. Basically,
- // always use the best of the N last data points, where best is defined as
- // lowest round trip time. NTP uses an N of 8; we use a value of 6.
- //
- // TODO(johngro) : experiment with other filter strategies. The goal here
- // is to mitigate the effects of high RTT data points which typically have
- // large asymmetries in the TX/RX legs. Downside of the existing NTP
- // approach (particularly because of the PID controller we are using to
- // produce the control signal from the filtered data) are that the rate at
- // which discipline events are actually acted upon becomes irregular and can
- // become drawn out (the time between actionable event can go way up). If
- // the system receives a strong high quality data point, the proportional
- // component of the controller can produce a strong correction which is left
- // in place for too long causing overshoot. In addition, the integral
- // component of the system currently is an approximation based on the
- // assumption of a more or less homogeneous sampling of the error. Its
- // unclear what the effect of undermining this assumption would be right
- // now.
-
- // Two ideas which come to mind immediately would be to...
- // 1) Keep a history of more data points (32 or so) and ignore data points
- // whose RTT is more than a certain number of standard deviations outside
- // of the norm.
- // 2) Eliminate the PID controller portion of this system entirely.
- // Instead, move to a system which uses a very wide filter (128 data
- // points or more) with a sum-of-least-squares line fitting approach to
- // tracking the long term drift. This would take the place of the I
- // component in the current PID controller. Also use a much more narrow
- // outlier-rejector filter (as described in #1) to drive a short term
- // correction factor similar to the P component of the PID controller.
- assert(filter_wr_ < kFilterSize);
- filter_data_[filter_wr_].local_time = local_time;
- filter_data_[filter_wr_].observed_common_time = observed_common;
- filter_data_[filter_wr_].nominal_common_time = nominal_common_time;
- filter_data_[filter_wr_].rtt = rtt;
- filter_data_[filter_wr_].point_used = false;
- uint32_t current_point = filter_wr_;
- filter_wr_ = (filter_wr_ + 1) % kFilterSize;
- if (!filter_wr_)
- filter_full_ = true;
-
- uint32_t scan_end = filter_full_ ? kFilterSize : filter_wr_;
- uint32_t min_rtt = findMinRTTNdx(filter_data_, scan_end);
- // We only use packets with low RTTs for control. If the packet RTT
- // is less than the panic threshold, we can probably eat the jitter with the
- // control loop. Otherwise, take the packet only if it better than all
- // of the packets we have in the history. That way we try to track
- // something, even if it is noisy.
- if (current_point == min_rtt || rtt < control_thresh_) {
- delta_f = delta = nominal_common_time - observed_common;
-
- last_error_est_valid_ = true;
- last_error_est_usec_ = delta;
-
- // Compute the error then clamp to the panic threshold. If we ever
- // exceed this amt of error, its time to panic and reset the system.
- // Given that the error in the measurement of the error could be as
- // high as the RTT of the data point, we don't actually panic until
- // the implied error (delta) is greater than the absolute panic
- // threashold plus the RTT. IOW - we don't panic until we are
- // absoluely sure that our best case sync is worse than the absolute
- // panic threshold.
- int64_t effective_panic_thresh = panic_thresh_ + rtt;
- if ((delta > effective_panic_thresh) ||
- (delta < -effective_panic_thresh)) {
- // PANIC!!!
- reset_l(false, true);
- return false;
- }
-
- } else {
- // We do not have a good packet to look at, but we also do not want to
- // free-run the clock at some crazy slew rate. So we guess the
- // trajectory of the clock based on the last controller output and the
- // estimated bias of our clock against the master.
- // The net effect of this is that CO == CObias after some extended
- // period of no feedback.
- delta_f = last_delta_f_ - dT*(CO - CObias);
- delta = delta_f;
- }
-
- // Velocity form PI control equation.
- dCO = Kc * (1.0f + dT/Ti) * delta_f - Kc * last_delta_f_;
- CO += dCO * Tf; // Filter CO by applying gain <1 here.
-
- // Save error terms for later.
- last_delta_f_ = delta_f;
-
- // Clamp CO to +/- 100ppm.
- if (CO < COmin)
- CO = COmin;
- else if (CO > COmax)
- CO = COmax;
-
- // Update the controller bias.
- CObias = bias_Alpha * CO + (1.0f - bias_Alpha) * lastCObias;
- lastCObias = CObias;
-
- // Convert PPM to 16-bit int range. Add some guard band (-0.01) so we
- // don't get fp weirdness.
- tgt_correction = CO * 327.66;
-
- // If there was a change in the amt of correction to use, update the
- // system.
- setTargetCorrection_l(tgt_correction);
-
- LOG_TS("clock_loop %lld %f %f %f %d\n", raw_delta, delta_f, CO, CObias, tgt_correction);
-
-#ifdef TIME_SERVICE_DEBUG
- diag_thread_->pushDisciplineEvent(
- local_time,
- observed_common,
- nominal_common_time,
- tgt_correction,
- rtt);
-#endif
-
- return true;
-}
-
-int32_t ClockRecoveryLoop::getLastErrorEstimate() {
- Mutex::Autolock lock(&lock_);
-
- if (last_error_est_valid_)
- return last_error_est_usec_;
- else
- return ICommonClock::kErrorEstimateUnknown;
-}
-
-void ClockRecoveryLoop::reset_l(bool position, bool frequency) {
- assert(NULL != common_clock_);
-
- if (position) {
- common_clock_->resetBasis();
- startup_filter_wr_ = 0;
- }
-
- if (frequency) {
- last_error_est_valid_ = false;
- last_error_est_usec_ = 0;
- last_delta_f_ = 0.0;
- CO = 0.0f;
- lastCObias = CObias = 0.0f;
- setTargetCorrection_l(0);
- applySlew_l();
- }
-
- filter_wr_ = 0;
- filter_full_ = false;
-}
-
-void ClockRecoveryLoop::setTargetCorrection_l(int32_t tgt) {
- // When we make a change to the slew rate, we need to be careful to not
- // change it too quickly as it can anger some HDMI sinks out there, notably
- // some Sony panels from the 2010-2011 timeframe. From experimenting with
- // some of these sinks, it seems like swinging from one end of the range to
- // another in less that 190mSec or so can start to cause trouble. Adding in
- // a hefty margin, we limit the system to a full range sweep in no less than
- // 300mSec.
- if (tgt_correction_ != tgt) {
- int64_t now = local_clock_->getLocalTime();
- status_t res;
-
- tgt_correction_ = tgt;
-
- // Set up the transformation to figure out what the slew should be at
- // any given point in time in the future.
- time_to_cur_slew_.a_zero = now;
- time_to_cur_slew_.b_zero = cur_correction_;
-
- // Make sure the sign of the slope is headed in the proper direction.
- bool needs_increase = (cur_correction_ < tgt_correction_);
- bool is_increasing = (time_to_cur_slew_.a_to_b_numer > 0);
- if (( needs_increase && !is_increasing) ||
- (!needs_increase && is_increasing)) {
- time_to_cur_slew_.a_to_b_numer = -time_to_cur_slew_.a_to_b_numer;
- }
-
- // Finally, figure out when the change will be finished and start the
- // slew operation.
- time_to_cur_slew_.doReverseTransform(tgt_correction_,
- &slew_change_end_time_);
-
- applySlew_l();
- }
-}
-
-bool ClockRecoveryLoop::applySlew_l() {
- bool ret = true;
-
- // If cur == tgt, there is no ongoing sleq rate change and we are already
- // finished.
- if (cur_correction_ == tgt_correction_)
- goto bailout;
-
- if (local_clock_can_slew_) {
- int64_t now = local_clock_->getLocalTime();
- int64_t tmp;
-
- if (now >= slew_change_end_time_) {
- cur_correction_ = tgt_correction_;
- next_slew_change_timeout_.setTimeout(-1);
- } else {
- time_to_cur_slew_.doForwardTransform(now, &tmp);
-
- if (tmp > INT16_MAX)
- cur_correction_ = INT16_MAX;
- else if (tmp < INT16_MIN)
- cur_correction_ = INT16_MIN;
- else
- cur_correction_ = static_cast<int16_t>(tmp);
-
- next_slew_change_timeout_.setTimeout(kSlewChangeStepPeriod_mSec);
- ret = false;
- }
-
- local_clock_->setLocalSlew(cur_correction_);
- } else {
- // Since we are not actually changing the rate of a HW clock, we don't
- // need to worry to much about changing the slew rate so fast that we
- // anger any downstream HDMI devices.
- cur_correction_ = tgt_correction_;
- next_slew_change_timeout_.setTimeout(-1);
-
- // The SW clock recovery implemented by the common clock class expects
- // values expressed in PPM. CO is in ppm.
- common_clock_->setSlew(local_clock_->getLocalTime(), CO);
- }
-
-bailout:
- return ret;
-}
-
-int ClockRecoveryLoop::applyRateLimitedSlew() {
- Mutex::Autolock lock(&lock_);
-
- int ret = next_slew_change_timeout_.msecTillTimeout();
- if (!ret) {
- if (applySlew_l())
- next_slew_change_timeout_.setTimeout(-1);
- ret = next_slew_change_timeout_.msecTillTimeout();
- }
-
- return ret;
-}
-
-} // namespace android
diff --git a/services/common_time/clock_recovery.h b/services/common_time/clock_recovery.h
deleted file mode 100644
index b6c87ff..0000000
--- a/services/common_time/clock_recovery.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __CLOCK_RECOVERY_H__
-#define __CLOCK_RECOVERY_H__
-
-#include <stdint.h>
-#include <common_time/ICommonClock.h>
-#include <utils/LinearTransform.h>
-#include <utils/threads.h>
-
-#ifdef TIME_SERVICE_DEBUG
-#include "diag_thread.h"
-#endif
-
-#include "utils.h"
-
-namespace android {
-
-class CommonClock;
-class LocalClock;
-
-class ClockRecoveryLoop {
- public:
- ClockRecoveryLoop(LocalClock* local_clock, CommonClock* common_clock);
- ~ClockRecoveryLoop();
-
- void reset(bool position, bool frequency);
- bool pushDisciplineEvent(int64_t local_time,
- int64_t nominal_common_time,
- int64_t data_point_rtt);
- int32_t getLastErrorEstimate();
-
- // Applies the next step in any ongoing slew change operation. Returns a
- // timeout suitable for use with poll/select indicating the number of mSec
- // until the next change should be applied.
- int applyRateLimitedSlew();
-
- private:
-
- // Tuned using the "Good Gain" method.
- // See:
- // http://techteach.no/publications/books/dynamics_and_control/tuning_pid_controller.pdf
-
- // Controller period (1Hz for now).
- static const float dT;
-
- // Controller gain, positive and unitless. Larger values converge faster,
- // but can cause instability.
- static const float Kc;
-
- // Integral reset time. Smaller values cause loop to track faster, but can
- // also cause instability.
- static const float Ti;
-
- // Controller output filter time constant. Range (0-1). Smaller values make
- // output smoother, but slow convergence.
- static const float Tf;
-
- // Low-pass filter for bias tracker.
- static const float bias_Fc; // HZ
- static const float bias_RC; // Computed in constructor.
- static const float bias_Alpha; // Computed inconstructor.
-
- // The maximum allowed error (as indicated by a pushDisciplineEvent) before
- // we panic.
- static const int64_t panic_thresh_;
-
- // The maximum allowed error rtt time for packets to be used for control
- // feedback, unless the packet is the best in recent memory.
- static const int64_t control_thresh_;
-
- typedef struct {
- int64_t local_time;
- int64_t observed_common_time;
- int64_t nominal_common_time;
- int64_t rtt;
- bool point_used;
- } DisciplineDataPoint;
-
- static uint32_t findMinRTTNdx(DisciplineDataPoint* data, uint32_t count);
-
- void reset_l(bool position, bool frequency);
- void setTargetCorrection_l(int32_t tgt);
- bool applySlew_l();
-
- // The local clock HW abstraction we use as the basis for common time.
- LocalClock* local_clock_;
- bool local_clock_can_slew_;
-
- // The common clock we end up controlling along with the lock used to
- // serialize operations.
- CommonClock* common_clock_;
- Mutex lock_;
-
- // parameters maintained while running and reset during a reset
- // of the frequency correction.
- bool last_error_est_valid_;
- int32_t last_error_est_usec_;
- float last_delta_f_;
- int32_t integrated_error_;
- int32_t tgt_correction_;
- int32_t cur_correction_;
- LinearTransform time_to_cur_slew_;
- int64_t slew_change_end_time_;
- Timeout next_slew_change_timeout_;
-
- // Contoller Output.
- float CO;
-
- // Bias tracking for trajectory estimation.
- float CObias;
- float lastCObias;
-
- // Controller output bounds. The controller will not try to
- // slew faster that +/-100ppm offset from center per interation.
- static const float COmin;
- static const float COmax;
-
- // State kept for filtering the discipline data.
- static const uint32_t kFilterSize = 16;
- DisciplineDataPoint filter_data_[kFilterSize];
- uint32_t filter_wr_;
- bool filter_full_;
-
- static const uint32_t kStartupFilterSize = 4;
- DisciplineDataPoint startup_filter_data_[kStartupFilterSize];
- uint32_t startup_filter_wr_;
-
- // Minimum number of milliseconds over which we allow a full range change
- // (from rail to rail) of the VCXO control signal. This is the rate
- // limiting factor which keeps us from changing the clock rate so fast that
- // we get in trouble with certain HDMI sinks.
- static const uint32_t kMinFullRangeSlewChange_mSec;
-
- // How much time (in msec) to wait
- static const int kSlewChangeStepPeriod_mSec;
-
-#ifdef TIME_SERVICE_DEBUG
- sp<DiagThread> diag_thread_;
-#endif
-};
-
-} // namespace android
-
-#endif // __CLOCK_RECOVERY_H__
diff --git a/services/common_time/common_clock.cpp b/services/common_time/common_clock.cpp
deleted file mode 100644
index c9eb388..0000000
--- a/services/common_time/common_clock.cpp
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define __STDC_LIMIT_MACROS
-
-#define LOG_TAG "common_time"
-#include <utils/Log.h>
-
-#include <stdint.h>
-
-#include <utils/Errors.h>
-#include <utils/LinearTransform.h>
-
-#include "common_clock.h"
-
-namespace android {
-
-CommonClock::CommonClock() {
- cur_slew_ = 0;
- cur_trans_valid_ = false;
-
- cur_trans_.a_zero = 0;
- cur_trans_.b_zero = 0;
- cur_trans_.a_to_b_numer = local_to_common_freq_numer_ = 1;
- cur_trans_.a_to_b_denom = local_to_common_freq_denom_ = 1;
- duration_trans_ = cur_trans_;
-}
-
-bool CommonClock::init(uint64_t local_freq) {
- Mutex::Autolock lock(&lock_);
-
- if (!local_freq)
- return false;
-
- uint64_t numer = kCommonFreq;
- uint64_t denom = local_freq;
-
- LinearTransform::reduce(&numer, &denom);
- if ((numer > UINT32_MAX) || (denom > UINT32_MAX)) {
- ALOGE("Overflow in CommonClock::init while trying to reduce %lld/%lld",
- kCommonFreq, local_freq);
- return false;
- }
-
- cur_trans_.a_to_b_numer = local_to_common_freq_numer_ =
- static_cast<uint32_t>(numer);
- cur_trans_.a_to_b_denom = local_to_common_freq_denom_ =
- static_cast<uint32_t>(denom);
- duration_trans_ = cur_trans_;
-
- return true;
-}
-
-status_t CommonClock::localToCommon(int64_t local, int64_t *common_out) const {
- Mutex::Autolock lock(&lock_);
-
- if (!cur_trans_valid_)
- return INVALID_OPERATION;
-
- if (!cur_trans_.doForwardTransform(local, common_out))
- return INVALID_OPERATION;
-
- return OK;
-}
-
-status_t CommonClock::commonToLocal(int64_t common, int64_t *local_out) const {
- Mutex::Autolock lock(&lock_);
-
- if (!cur_trans_valid_)
- return INVALID_OPERATION;
-
- if (!cur_trans_.doReverseTransform(common, local_out))
- return INVALID_OPERATION;
-
- return OK;
-}
-
-int64_t CommonClock::localDurationToCommonDuration(int64_t localDur) const {
- int64_t ret;
- duration_trans_.doForwardTransform(localDur, &ret);
- return ret;
-}
-
-void CommonClock::setBasis(int64_t local, int64_t common) {
- Mutex::Autolock lock(&lock_);
-
- cur_trans_.a_zero = local;
- cur_trans_.b_zero = common;
- cur_trans_valid_ = true;
-}
-
-void CommonClock::resetBasis() {
- Mutex::Autolock lock(&lock_);
-
- cur_trans_.a_zero = 0;
- cur_trans_.b_zero = 0;
- cur_trans_valid_ = false;
-}
-
-status_t CommonClock::setSlew(int64_t change_time, int32_t ppm) {
- Mutex::Autolock lock(&lock_);
-
- int64_t new_local_basis;
- int64_t new_common_basis;
-
- if (cur_trans_valid_) {
- new_local_basis = change_time;
- if (!cur_trans_.doForwardTransform(change_time, &new_common_basis)) {
- ALOGE("Overflow when attempting to set slew rate to %d", ppm);
- return INVALID_OPERATION;
- }
- } else {
- new_local_basis = 0;
- new_common_basis = 0;
- }
-
- cur_slew_ = ppm;
- uint32_t n1 = local_to_common_freq_numer_;
- uint32_t n2 = 1000000 + cur_slew_;
-
- uint32_t d1 = local_to_common_freq_denom_;
- uint32_t d2 = 1000000;
-
- // n1/d1 has already been reduced, no need to do so here.
- LinearTransform::reduce(&n1, &d2);
- LinearTransform::reduce(&n2, &d1);
- LinearTransform::reduce(&n2, &d2);
-
- cur_trans_.a_zero = new_local_basis;
- cur_trans_.b_zero = new_common_basis;
- cur_trans_.a_to_b_numer = n1 * n2;
- cur_trans_.a_to_b_denom = d1 * d2;
-
- return OK;
-}
-
-} // namespace android
diff --git a/services/common_time/common_clock.h b/services/common_time/common_clock.h
deleted file mode 100644
index b786fdc..0000000
--- a/services/common_time/common_clock.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __COMMON_CLOCK_H__
-#define __COMMON_CLOCK_H__
-
-#include <stdint.h>
-
-#include <utils/Errors.h>
-#include <utils/LinearTransform.h>
-#include <utils/threads.h>
-
-namespace android {
-
-class CommonClock {
- public:
- CommonClock();
-
- bool init(uint64_t local_freq);
-
- status_t localToCommon(int64_t local, int64_t *common_out) const;
- status_t commonToLocal(int64_t common, int64_t *local_out) const;
- int64_t localDurationToCommonDuration(int64_t localDur) const;
- uint64_t getCommonFreq() const { return kCommonFreq; }
- bool isValid() const { return cur_trans_valid_; }
- status_t setSlew(int64_t change_time, int32_t ppm);
- void setBasis(int64_t local, int64_t common);
- void resetBasis();
- private:
- mutable Mutex lock_;
-
- int32_t cur_slew_;
- uint32_t local_to_common_freq_numer_;
- uint32_t local_to_common_freq_denom_;
-
- LinearTransform duration_trans_;
- LinearTransform cur_trans_;
- bool cur_trans_valid_;
-
- static const uint64_t kCommonFreq = 1000000ull;
-};
-
-} // namespace android
-#endif // __COMMON_CLOCK_H__
diff --git a/services/common_time/common_clock_service.cpp b/services/common_time/common_clock_service.cpp
deleted file mode 100644
index 9ca6f35..0000000
--- a/services/common_time/common_clock_service.cpp
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <common_time/local_clock.h>
-#include <utils/String8.h>
-
-#include "common_clock_service.h"
-#include "common_clock.h"
-#include "common_time_server.h"
-
-namespace android {
-
-sp<CommonClockService> CommonClockService::instantiate(
- CommonTimeServer& timeServer) {
- sp<CommonClockService> tcc = new CommonClockService(timeServer);
- if (tcc == NULL)
- return NULL;
-
- defaultServiceManager()->addService(ICommonClock::kServiceName, tcc);
- return tcc;
-}
-
-status_t CommonClockService::dump(int fd, const Vector<String16>& args) {
- Mutex::Autolock lock(mRegistrationLock);
- return mTimeServer.dumpClockInterface(fd, args, mListeners.size());
-}
-
-status_t CommonClockService::isCommonTimeValid(bool* valid,
- uint32_t* timelineID) {
- return mTimeServer.isCommonTimeValid(valid, timelineID);
-}
-
-status_t CommonClockService::commonTimeToLocalTime(int64_t commonTime,
- int64_t* localTime) {
- return mTimeServer.getCommonClock().commonToLocal(commonTime, localTime);
-}
-
-status_t CommonClockService::localTimeToCommonTime(int64_t localTime,
- int64_t* commonTime) {
- return mTimeServer.getCommonClock().localToCommon(localTime, commonTime);
-}
-
-status_t CommonClockService::getCommonTime(int64_t* commonTime) {
- return localTimeToCommonTime(mTimeServer.getLocalClock().getLocalTime(), commonTime);
-}
-
-status_t CommonClockService::getCommonFreq(uint64_t* freq) {
- *freq = mTimeServer.getCommonClock().getCommonFreq();
- return OK;
-}
-
-status_t CommonClockService::getLocalTime(int64_t* localTime) {
- *localTime = mTimeServer.getLocalClock().getLocalTime();
- return OK;
-}
-
-status_t CommonClockService::getLocalFreq(uint64_t* freq) {
- *freq = mTimeServer.getLocalClock().getLocalFreq();
- return OK;
-}
-
-status_t CommonClockService::getEstimatedError(int32_t* estimate) {
- *estimate = mTimeServer.getEstimatedError();
- return OK;
-}
-
-status_t CommonClockService::getTimelineID(uint64_t* id) {
- *id = mTimeServer.getTimelineID();
- return OK;
-}
-
-status_t CommonClockService::getState(State* state) {
- *state = mTimeServer.getState();
- return OK;
-}
-
-status_t CommonClockService::getMasterAddr(struct sockaddr_storage* addr) {
- return mTimeServer.getMasterAddr(addr);
-}
-
-status_t CommonClockService::registerListener(
- const sp<ICommonClockListener>& listener) {
- Mutex::Autolock lock(mRegistrationLock);
-
- { // scoping for autolock pattern
- Mutex::Autolock lock(mCallbackLock);
- // check whether this is a duplicate
- for (size_t i = 0; i < mListeners.size(); i++) {
- if (mListeners[i]->asBinder() == listener->asBinder())
- return ALREADY_EXISTS;
- }
- }
-
- mListeners.add(listener);
- mTimeServer.reevaluateAutoDisableState(0 != mListeners.size());
- return listener->asBinder()->linkToDeath(this);
-}
-
-status_t CommonClockService::unregisterListener(
- const sp<ICommonClockListener>& listener) {
- Mutex::Autolock lock(mRegistrationLock);
- status_t ret_val = NAME_NOT_FOUND;
-
- { // scoping for autolock pattern
- Mutex::Autolock lock(mCallbackLock);
- for (size_t i = 0; i < mListeners.size(); i++) {
- if (mListeners[i]->asBinder() == listener->asBinder()) {
- mListeners[i]->asBinder()->unlinkToDeath(this);
- mListeners.removeAt(i);
- ret_val = OK;
- break;
- }
- }
- }
-
- mTimeServer.reevaluateAutoDisableState(0 != mListeners.size());
- return ret_val;
-}
-
-void CommonClockService::binderDied(const wp<IBinder>& who) {
- Mutex::Autolock lock(mRegistrationLock);
-
- { // scoping for autolock pattern
- Mutex::Autolock lock(mCallbackLock);
- for (size_t i = 0; i < mListeners.size(); i++) {
- if (mListeners[i]->asBinder() == who) {
- mListeners.removeAt(i);
- break;
- }
- }
- }
-
- mTimeServer.reevaluateAutoDisableState(0 != mListeners.size());
-}
-
-void CommonClockService::notifyOnTimelineChanged(uint64_t timelineID) {
- Mutex::Autolock lock(mCallbackLock);
-
- for (size_t i = 0; i < mListeners.size(); i++) {
- mListeners[i]->onTimelineChanged(timelineID);
- }
-}
-
-}; // namespace android
diff --git a/services/common_time/common_clock_service.h b/services/common_time/common_clock_service.h
deleted file mode 100644
index bd663f0..0000000
--- a/services/common_time/common_clock_service.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_COMMON_CLOCK_SERVICE_H
-#define ANDROID_COMMON_CLOCK_SERVICE_H
-
-#include <sys/socket.h>
-#include <common_time/ICommonClock.h>
-
-namespace android {
-
-class CommonTimeServer;
-
-class CommonClockService : public BnCommonClock,
- public android::IBinder::DeathRecipient {
- public:
- static sp<CommonClockService> instantiate(CommonTimeServer& timeServer);
-
- virtual status_t dump(int fd, const Vector<String16>& args);
-
- virtual status_t isCommonTimeValid(bool* valid, uint32_t *timelineID);
- virtual status_t commonTimeToLocalTime(int64_t common_time,
- int64_t* local_time);
- virtual status_t localTimeToCommonTime(int64_t local_time,
- int64_t* common_time);
- virtual status_t getCommonTime(int64_t* common_time);
- virtual status_t getCommonFreq(uint64_t* freq);
- virtual status_t getLocalTime(int64_t* local_time);
- virtual status_t getLocalFreq(uint64_t* freq);
- virtual status_t getEstimatedError(int32_t* estimate);
- virtual status_t getTimelineID(uint64_t* id);
- virtual status_t getState(ICommonClock::State* state);
- virtual status_t getMasterAddr(struct sockaddr_storage* addr);
-
- virtual status_t registerListener(
- const sp<ICommonClockListener>& listener);
- virtual status_t unregisterListener(
- const sp<ICommonClockListener>& listener);
-
- void notifyOnTimelineChanged(uint64_t timelineID);
-
- private:
- CommonClockService(CommonTimeServer& timeServer)
- : mTimeServer(timeServer) { };
-
- virtual void binderDied(const wp<IBinder>& who);
-
- CommonTimeServer& mTimeServer;
-
- // locks used to synchronize access to the list of registered listeners.
- // The callback lock is held whenever the list is used to perform callbacks
- // or while the list is being modified. The registration lock used to
- // serialize access across registerListener, unregisterListener, and
- // binderDied.
- //
- // The reason for two locks is that registerListener, unregisterListener,
- // and binderDied each call into the core service and obtain the core
- // service thread lock when they call reevaluateAutoDisableState. The core
- // service thread obtains the main thread lock whenever its thread is
- // running, and sometimes needs to call notifyOnTimelineChanged which then
- // obtains the callback lock. If callers of registration functions were
- // holding the callback lock when they called into the core service, we
- // would have a classic A/B, B/A ordering deadlock. To avoid this, the
- // registration functions hold the registration lock for the duration of
- // their call, but hold the callback lock only while they mutate the list.
- // This way, the list's size cannot change (because of the registration
- // lock) during the call into reevaluateAutoDisableState, but the core work
- // thread can still safely call notifyOnTimelineChanged while holding the
- // main thread lock.
- Mutex mCallbackLock;
- Mutex mRegistrationLock;
-
- Vector<sp<ICommonClockListener> > mListeners;
-};
-
-}; // namespace android
-
-#endif // ANDROID_COMMON_CLOCK_SERVICE_H
diff --git a/services/common_time/common_time_config_service.cpp b/services/common_time/common_time_config_service.cpp
deleted file mode 100644
index 9585618..0000000
--- a/services/common_time/common_time_config_service.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <utils/String8.h>
-
-#include "common_time_config_service.h"
-#include "common_time_server.h"
-
-namespace android {
-
-sp<CommonTimeConfigService> CommonTimeConfigService::instantiate(
- CommonTimeServer& timeServer) {
- sp<CommonTimeConfigService> ctcs = new CommonTimeConfigService(timeServer);
- if (ctcs == NULL)
- return NULL;
-
- defaultServiceManager()->addService(ICommonTimeConfig::kServiceName, ctcs);
- return ctcs;
-}
-
-status_t CommonTimeConfigService::dump(int fd, const Vector<String16>& args) {
- return mTimeServer.dumpConfigInterface(fd, args);
-}
-
-status_t CommonTimeConfigService::getMasterElectionPriority(uint8_t *priority) {
- return mTimeServer.getMasterElectionPriority(priority);
-}
-
-status_t CommonTimeConfigService::setMasterElectionPriority(uint8_t priority) {
- return mTimeServer.setMasterElectionPriority(priority);
-}
-
-status_t CommonTimeConfigService::getMasterElectionEndpoint(
- struct sockaddr_storage *addr) {
- return mTimeServer.getMasterElectionEndpoint(addr);
-}
-
-status_t CommonTimeConfigService::setMasterElectionEndpoint(
- const struct sockaddr_storage *addr) {
- return mTimeServer.setMasterElectionEndpoint(addr);
-}
-
-status_t CommonTimeConfigService::getMasterElectionGroupId(uint64_t *id) {
- return mTimeServer.getMasterElectionGroupId(id);
-}
-
-status_t CommonTimeConfigService::setMasterElectionGroupId(uint64_t id) {
- return mTimeServer.setMasterElectionGroupId(id);
-}
-
-status_t CommonTimeConfigService::getInterfaceBinding(String16& ifaceName) {
- String8 tmp;
- status_t ret = mTimeServer.getInterfaceBinding(tmp);
- ifaceName = String16(tmp);
- return ret;
-}
-
-status_t CommonTimeConfigService::setInterfaceBinding(const String16& ifaceName) {
- String8 tmp(ifaceName);
- return mTimeServer.setInterfaceBinding(tmp);
-}
-
-status_t CommonTimeConfigService::getMasterAnnounceInterval(int *interval) {
- return mTimeServer.getMasterAnnounceInterval(interval);
-}
-
-status_t CommonTimeConfigService::setMasterAnnounceInterval(int interval) {
- return mTimeServer.setMasterAnnounceInterval(interval);
-}
-
-status_t CommonTimeConfigService::getClientSyncInterval(int *interval) {
- return mTimeServer.getClientSyncInterval(interval);
-}
-
-status_t CommonTimeConfigService::setClientSyncInterval(int interval) {
- return mTimeServer.setClientSyncInterval(interval);
-}
-
-status_t CommonTimeConfigService::getPanicThreshold(int *threshold) {
- return mTimeServer.getPanicThreshold(threshold);
-}
-
-status_t CommonTimeConfigService::setPanicThreshold(int threshold) {
- return mTimeServer.setPanicThreshold(threshold);
-}
-
-status_t CommonTimeConfigService::getAutoDisable(bool *autoDisable) {
- return mTimeServer.getAutoDisable(autoDisable);
-}
-
-status_t CommonTimeConfigService::setAutoDisable(bool autoDisable) {
- return mTimeServer.setAutoDisable(autoDisable);
-}
-
-status_t CommonTimeConfigService::forceNetworklessMasterMode() {
- return mTimeServer.forceNetworklessMasterMode();
-}
-
-}; // namespace android
diff --git a/services/common_time/common_time_config_service.h b/services/common_time/common_time_config_service.h
deleted file mode 100644
index 89806dd..0000000
--- a/services/common_time/common_time_config_service.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/* * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_COMMON_TIME_CONFIG_SERVICE_H
-#define ANDROID_COMMON_TIME_CONFIG_SERVICE_H
-
-#include <sys/socket.h>
-#include <common_time/ICommonTimeConfig.h>
-
-namespace android {
-
-class String16;
-class CommonTimeServer;
-
-class CommonTimeConfigService : public BnCommonTimeConfig {
- public:
- static sp<CommonTimeConfigService> instantiate(CommonTimeServer& timeServer);
-
- virtual status_t dump(int fd, const Vector<String16>& args);
-
- virtual status_t getMasterElectionPriority(uint8_t *priority);
- virtual status_t setMasterElectionPriority(uint8_t priority);
- virtual status_t getMasterElectionEndpoint(struct sockaddr_storage *addr);
- virtual status_t setMasterElectionEndpoint(const struct sockaddr_storage *addr);
- virtual status_t getMasterElectionGroupId(uint64_t *id);
- virtual status_t setMasterElectionGroupId(uint64_t id);
- virtual status_t getInterfaceBinding(String16& ifaceName);
- virtual status_t setInterfaceBinding(const String16& ifaceName);
- virtual status_t getMasterAnnounceInterval(int *interval);
- virtual status_t setMasterAnnounceInterval(int interval);
- virtual status_t getClientSyncInterval(int *interval);
- virtual status_t setClientSyncInterval(int interval);
- virtual status_t getPanicThreshold(int *threshold);
- virtual status_t setPanicThreshold(int threshold);
- virtual status_t getAutoDisable(bool *autoDisable);
- virtual status_t setAutoDisable(bool autoDisable);
- virtual status_t forceNetworklessMasterMode();
-
- private:
- CommonTimeConfigService(CommonTimeServer& timeServer)
- : mTimeServer(timeServer) { }
- CommonTimeServer& mTimeServer;
-
-};
-
-}; // namespace android
-
-#endif // ANDROID_COMMON_TIME_CONFIG_SERVICE_H
diff --git a/services/common_time/common_time_server.cpp b/services/common_time/common_time_server.cpp
deleted file mode 100644
index 21e706f..0000000
--- a/services/common_time/common_time_server.cpp
+++ /dev/null
@@ -1,1506 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * A service that exchanges time synchronization information between
- * a master that defines a timeline and clients that follow the timeline.
- */
-
-#define LOG_TAG "common_time"
-#include <utils/Log.h>
-
-#include <arpa/inet.h>
-#include <assert.h>
-#include <fcntl.h>
-#include <linux/if_ether.h>
-#include <net/if.h>
-#include <net/if_arp.h>
-#include <netinet/ip.h>
-#include <poll.h>
-#include <stdio.h>
-#include <sys/eventfd.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#include <common_time/local_clock.h>
-#include <binder/IPCThreadState.h>
-#include <binder/ProcessState.h>
-#include <utils/Timers.h>
-
-#include "common_clock_service.h"
-#include "common_time_config_service.h"
-#include "common_time_server.h"
-#include "common_time_server_packets.h"
-#include "clock_recovery.h"
-#include "common_clock.h"
-
-#define MAX_INT ((int)0x7FFFFFFF)
-
-namespace android {
-
-const char* CommonTimeServer::kDefaultMasterElectionAddr = "255.255.255.255";
-const uint16_t CommonTimeServer::kDefaultMasterElectionPort = 8886;
-const uint64_t CommonTimeServer::kDefaultSyncGroupID = 1;
-const uint8_t CommonTimeServer::kDefaultMasterPriority = 1;
-const uint32_t CommonTimeServer::kDefaultMasterAnnounceIntervalMs = 10000;
-const uint32_t CommonTimeServer::kDefaultSyncRequestIntervalMs = 1000;
-const uint32_t CommonTimeServer::kDefaultPanicThresholdUsec = 50000;
-const bool CommonTimeServer::kDefaultAutoDisable = true;
-const int CommonTimeServer::kSetupRetryTimeoutMs = 30000;
-const int64_t CommonTimeServer::kNoGoodDataPanicThresholdUsec = 600000000ll;
-const uint32_t CommonTimeServer::kRTTDiscardPanicThreshMultiplier = 5;
-
-// timeout value representing an infinite timeout
-const int CommonTimeServer::kInfiniteTimeout = -1;
-
-/*** Initial state constants ***/
-
-// number of WhoIsMaster attempts sent before giving up
-const int CommonTimeServer::kInitial_NumWhoIsMasterRetries = 6;
-
-// timeout used when waiting for a response to a WhoIsMaster request
-const int CommonTimeServer::kInitial_WhoIsMasterTimeoutMs = 500;
-
-/*** Client state constants ***/
-
-// number of sync requests that can fail before a client assumes its master
-// is dead
-const int CommonTimeServer::kClient_NumSyncRequestRetries = 10;
-
-/*** Master state constants ***/
-
-/*** Ronin state constants ***/
-
-// number of WhoIsMaster attempts sent before declaring ourselves master
-const int CommonTimeServer::kRonin_NumWhoIsMasterRetries = 20;
-
-// timeout used when waiting for a response to a WhoIsMaster request
-const int CommonTimeServer::kRonin_WhoIsMasterTimeoutMs = 500;
-
-/*** WaitForElection state constants ***/
-
-// how long do we wait for an announcement from a master before
-// trying another election?
-const int CommonTimeServer::kWaitForElection_TimeoutMs = 12500;
-
-CommonTimeServer::CommonTimeServer()
- : Thread(false)
- , mState(ICommonClock::STATE_INITIAL)
- , mClockRecovery(&mLocalClock, &mCommonClock)
- , mSocket(-1)
- , mLastPacketRxLocalTime(0)
- , mTimelineID(ICommonClock::kInvalidTimelineID)
- , mClockSynced(false)
- , mCommonClockHasClients(false)
- , mStateChangeLog("Recent State Change Events", 30)
- , mElectionLog("Recent Master Election Traffic", 30)
- , mBadPktLog("Recent Bad Packet RX Info", 8)
- , mInitial_WhoIsMasterRequestTimeouts(0)
- , mClient_MasterDeviceID(0)
- , mClient_MasterDevicePriority(0)
- , mRonin_WhoIsMasterRequestTimeouts(0) {
- // zero out sync stats
- resetSyncStats();
-
- // Setup the master election endpoint to use the default.
- struct sockaddr_in* meep =
- reinterpret_cast<struct sockaddr_in*>(&mMasterElectionEP);
- memset(&mMasterElectionEP, 0, sizeof(mMasterElectionEP));
- inet_aton(kDefaultMasterElectionAddr, &meep->sin_addr);
- meep->sin_family = AF_INET;
- meep->sin_port = htons(kDefaultMasterElectionPort);
-
- // Zero out the master endpoint.
- memset(&mMasterEP, 0, sizeof(mMasterEP));
- mMasterEPValid = false;
- mBindIfaceValid = false;
- setForceLowPriority(false);
-
- // Set all remaining configuration parameters to their defaults.
- mDeviceID = 0;
- mSyncGroupID = kDefaultSyncGroupID;
- mMasterPriority = kDefaultMasterPriority;
- mMasterAnnounceIntervalMs = kDefaultMasterAnnounceIntervalMs;
- mSyncRequestIntervalMs = kDefaultSyncRequestIntervalMs;
- mPanicThresholdUsec = kDefaultPanicThresholdUsec;
- mAutoDisable = kDefaultAutoDisable;
-
- // Create the eventfd we will use to signal our thread to wake up when
- // needed.
- mWakeupThreadFD = eventfd(0, EFD_NONBLOCK);
-
- // seed the random number generator (used to generated timeline IDs)
- srand48(static_cast<unsigned int>(systemTime()));
-}
-
-CommonTimeServer::~CommonTimeServer() {
- shutdownThread();
-
- // No need to grab the lock here. We are in the destructor; if the the user
- // has a thread in any of the APIs while the destructor is being called,
- // there is a threading problem a the application level we cannot reasonably
- // do anything about.
- cleanupSocket_l();
-
- if (mWakeupThreadFD >= 0) {
- close(mWakeupThreadFD);
- mWakeupThreadFD = -1;
- }
-}
-
-bool CommonTimeServer::startServices() {
- // start the ICommonClock service
- mICommonClock = CommonClockService::instantiate(*this);
- if (mICommonClock == NULL)
- return false;
-
- // start the ICommonTimeConfig service
- mICommonTimeConfig = CommonTimeConfigService::instantiate(*this);
- if (mICommonTimeConfig == NULL)
- return false;
-
- return true;
-}
-
-bool CommonTimeServer::threadLoop() {
- // Register our service interfaces.
- if (!startServices())
- return false;
-
- // Hold the lock while we are in the main thread loop. It will release the
- // lock when it blocks, and hold the lock at all other times.
- mLock.lock();
- runStateMachine_l();
- mLock.unlock();
-
- IPCThreadState::self()->stopProcess();
- return false;
-}
-
-bool CommonTimeServer::runStateMachine_l() {
- if (!mLocalClock.initCheck())
- return false;
-
- if (!mCommonClock.init(mLocalClock.getLocalFreq()))
- return false;
-
- // Enter the initial state.
- becomeInitial("startup");
-
- // run the state machine
- while (!exitPending()) {
- struct pollfd pfds[2];
- int rc, timeout;
- int eventCnt = 0;
- int64_t wakeupTime;
- uint32_t t1, t2;
- bool needHandleTimeout = false;
-
- // We are always interested in our wakeup FD.
- pfds[eventCnt].fd = mWakeupThreadFD;
- pfds[eventCnt].events = POLLIN;
- pfds[eventCnt].revents = 0;
- eventCnt++;
-
- // If we have a valid socket, then we are interested in what it has to
- // say as well.
- if (mSocket >= 0) {
- pfds[eventCnt].fd = mSocket;
- pfds[eventCnt].events = POLLIN;
- pfds[eventCnt].revents = 0;
- eventCnt++;
- }
-
- t1 = static_cast<uint32_t>(mCurTimeout.msecTillTimeout());
- t2 = static_cast<uint32_t>(mClockRecovery.applyRateLimitedSlew());
- timeout = static_cast<int>(t1 < t2 ? t1 : t2);
-
- // Note, we were holding mLock when this function was called. We
- // release it only while we are blocking and hold it at all other times.
- mLock.unlock();
- rc = poll(pfds, eventCnt, timeout);
- wakeupTime = mLocalClock.getLocalTime();
- mLock.lock();
-
- // Is it time to shutdown? If so, don't hesitate... just do it.
- if (exitPending())
- break;
-
- // Did the poll fail? This should never happen and is fatal if it does.
- if (rc < 0) {
- ALOGE("%s:%d poll failed", __PRETTY_FUNCTION__, __LINE__);
- return false;
- }
-
- if (rc == 0) {
- needHandleTimeout = !mCurTimeout.msecTillTimeout();
- if (needHandleTimeout)
- mCurTimeout.setTimeout(kInfiniteTimeout);
- }
-
- // Were we woken up on purpose? If so, clear the eventfd with a read.
- if (pfds[0].revents)
- clearPendingWakeupEvents_l();
-
- // Is out bind address dirty? If so, clean up our socket (if any).
- // Alternatively, do we have an active socket but should be auto
- // disabled? If so, release the socket and enter the proper sync state.
- bool droppedSocket = false;
- if (mBindIfaceDirty || ((mSocket >= 0) && shouldAutoDisable())) {
- cleanupSocket_l();
- mBindIfaceDirty = false;
- droppedSocket = true;
- }
-
- // Do we not have a socket but should have one? If so, try to set one
- // up.
- if ((mSocket < 0) && mBindIfaceValid && !shouldAutoDisable()) {
- if (setupSocket_l()) {
- // Success! We are now joining a new network (either coming
- // from no network, or coming from a potentially different
- // network). Force our priority to be lower so that we defer to
- // any other masters which may already be on the network we are
- // joining. Later, when we enter either the client or the
- // master state, we will clear this flag and go back to our
- // normal election priority.
- setForceLowPriority(true);
- switch (mState) {
- // If we were in initial (whether we had a immediately
- // before this network or not) we want to simply reset the
- // system and start again. Forcing a transition from
- // INITIAL to INITIAL should do the job.
- case CommonClockService::STATE_INITIAL:
- becomeInitial("bound interface");
- break;
-
- // If we were in the master state, then either we were the
- // master in a no-network situation, or we were the master
- // of a different network and have moved to a new interface.
- // In either case, immediately transition to Ronin at low
- // priority. If there is no one in the network we just
- // joined, we will become master soon enough. If there is,
- // we want to be certain to defer master status to the
- // existing timeline currently running on the network.
- //
- case CommonClockService::STATE_MASTER:
- becomeRonin("leaving networkless mode");
- break;
-
- // If we were in any other state (CLIENT, RONIN, or
- // WAIT_FOR_ELECTION) then we must be moving from one
- // network to another. We have lost our old master;
- // transition to RONIN in an attempt to find a new master.
- // If there are none out there, we will just assume
- // responsibility for the timeline we used to be a client
- // of.
- default:
- becomeRonin("bound interface");
- break;
- }
- } else {
- // That's odd... we failed to set up our socket. This could be
- // due to some transient network change which will work itself
- // out shortly; schedule a retry attempt in the near future.
- mCurTimeout.setTimeout(kSetupRetryTimeoutMs);
- }
-
- // One way or the other, we don't have any data to process at this
- // point (since we just tried to bulid a new socket). Loop back
- // around and wait for the next thing to do.
- continue;
- } else if (droppedSocket) {
- // We just lost our socket, and for whatever reason (either no
- // config, or auto disable engaged) we are not supposed to rebuild
- // one at this time. We are not going to rebuild our socket until
- // something about our config/auto-disabled status changes, so we
- // are basically in network-less mode. If we are already in either
- // INITIAL or MASTER, just stay there until something changes. If
- // we are in any other state (CLIENT, RONIN or WAIT_FOR_ELECTION),
- // then transition to either INITIAL or MASTER depending on whether
- // or not our timeline is valid.
- mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG,
- "Entering networkless mode interface is %s, "
- "shouldAutoDisable = %s",
- mBindIfaceValid ? "valid" : "invalid",
- shouldAutoDisable() ? "true" : "false");
- if ((mState != ICommonClock::STATE_INITIAL) &&
- (mState != ICommonClock::STATE_MASTER)) {
- if (mTimelineID == ICommonClock::kInvalidTimelineID)
- becomeInitial("network-less mode");
- else
- becomeMaster("network-less mode");
- }
-
- continue;
- }
-
- // Time to handle the timeouts?
- if (needHandleTimeout) {
- if (!handleTimeout())
- ALOGE("handleTimeout failed");
- continue;
- }
-
- // Does our socket have data for us (assuming we still have one, we
- // may have RXed a packet at the same time as a config change telling us
- // to shut our socket down)? If so, process its data.
- if ((mSocket >= 0) && (eventCnt > 1) && (pfds[1].revents)) {
- mLastPacketRxLocalTime = wakeupTime;
- if (!handlePacket())
- ALOGE("handlePacket failed");
- }
- }
-
- cleanupSocket_l();
- return true;
-}
-
-void CommonTimeServer::clearPendingWakeupEvents_l() {
- int64_t tmp;
- read(mWakeupThreadFD, &tmp, sizeof(tmp));
-}
-
-void CommonTimeServer::wakeupThread_l() {
- int64_t tmp = 1;
- write(mWakeupThreadFD, &tmp, sizeof(tmp));
-}
-
-void CommonTimeServer::cleanupSocket_l() {
- if (mSocket >= 0) {
- close(mSocket);
- mSocket = -1;
- }
-}
-
-void CommonTimeServer::shutdownThread() {
- // Flag the work thread for shutdown.
- this->requestExit();
-
- // Signal the thread in case its sleeping.
- mLock.lock();
- wakeupThread_l();
- mLock.unlock();
-
- // Wait for the thread to exit.
- this->join();
-}
-
-bool CommonTimeServer::setupSocket_l() {
- int rc;
- bool ret_val = false;
- struct sockaddr_in* ipv4_addr = NULL;
- char masterElectionEPStr[64];
- const int one = 1;
-
- // This should never be needed, but if we happened to have an old socket
- // lying around, be sure to not leak it before proceeding.
- cleanupSocket_l();
-
- // If we don't have a valid endpoint to bind to, then how did we get here in
- // the first place? Regardless, we know that we are going to fail to bind,
- // so don't even try.
- if (!mBindIfaceValid)
- return false;
-
- sockaddrToString(mMasterElectionEP, true, masterElectionEPStr,
- sizeof(masterElectionEPStr));
- mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG,
- "Building socket :: bind = %s master election = %s",
- mBindIface.string(), masterElectionEPStr);
-
- // TODO: add proper support for IPv6. Right now, we block IPv6 addresses at
- // the configuration interface level.
- if (AF_INET != mMasterElectionEP.ss_family) {
- mStateChangeLog.log(ANDROID_LOG_WARN, LOG_TAG,
- "TODO: add proper IPv6 support");
- goto bailout;
- }
-
- // open a UDP socket for the timeline serivce
- mSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- if (mSocket < 0) {
- mStateChangeLog.log(ANDROID_LOG_ERROR, LOG_TAG,
- "Failed to create socket (errno = %d)", errno);
- goto bailout;
- }
-
- // Bind to the selected interface using Linux's spiffy SO_BINDTODEVICE.
- struct ifreq ifr;
- memset(&ifr, 0, sizeof(ifr));
- snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", mBindIface.string());
- ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = 0;
- rc = setsockopt(mSocket, SOL_SOCKET, SO_BINDTODEVICE,
- (void *)&ifr, sizeof(ifr));
- if (rc) {
- mStateChangeLog.log(ANDROID_LOG_ERROR, LOG_TAG,
- "Failed to bind socket at to interface %s "
- "(errno = %d)", ifr.ifr_name, errno);
- goto bailout;
- }
-
- // Bind our socket to INADDR_ANY and the master election port. The
- // interface binding we made using SO_BINDTODEVICE should limit us to
- // traffic only on the interface we are interested in. We need to bind to
- // INADDR_ANY and the specific master election port in order to be able to
- // receive both unicast traffic and master election multicast traffic with
- // just a single socket.
- struct sockaddr_in bindAddr;
- ipv4_addr = reinterpret_cast<struct sockaddr_in*>(&mMasterElectionEP);
- memcpy(&bindAddr, ipv4_addr, sizeof(bindAddr));
- bindAddr.sin_addr.s_addr = INADDR_ANY;
- rc = bind(mSocket,
- reinterpret_cast<const sockaddr *>(&bindAddr),
- sizeof(bindAddr));
- if (rc) {
- mStateChangeLog.log(ANDROID_LOG_ERROR, LOG_TAG,
- "Failed to bind socket to port %hu (errno = %d)",
- ntohs(bindAddr.sin_port), errno);
- goto bailout;
- }
-
- if (0xE0000000 == (ntohl(ipv4_addr->sin_addr.s_addr) & 0xF0000000)) {
- // If our master election endpoint is a multicast address, be sure to join
- // the multicast group.
- struct ip_mreq mreq;
- mreq.imr_multiaddr = ipv4_addr->sin_addr;
- mreq.imr_interface.s_addr = htonl(INADDR_ANY);
- rc = setsockopt(mSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
- &mreq, sizeof(mreq));
- if (rc == -1) {
- ALOGE("Failed to join multicast group at %s. (errno = %d)",
- masterElectionEPStr, errno);
- goto bailout;
- }
-
- // disable loopback of multicast packets
- const int zero = 0;
- rc = setsockopt(mSocket, IPPROTO_IP, IP_MULTICAST_LOOP,
- &zero, sizeof(zero));
- if (rc == -1) {
- mStateChangeLog.log(ANDROID_LOG_ERROR, LOG_TAG,
- "Failed to disable multicast loopback "
- "(errno = %d)", errno);
- goto bailout;
- }
- } else
- if (ntohl(ipv4_addr->sin_addr.s_addr) == 0xFFFFFFFF) {
- // If the master election address is the broadcast address, then enable
- // the broadcast socket option
- rc = setsockopt(mSocket, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one));
- if (rc == -1) {
- mStateChangeLog.log(ANDROID_LOG_ERROR, LOG_TAG,
- "Failed to enable broadcast (errno = %d)",
- errno);
- goto bailout;
- }
- } else {
- // If the master election address is neither broadcast, nor multicast,
- // then we are misconfigured. The config API layer should prevent this
- // from ever happening.
- goto bailout;
- }
-
- // Set the TTL of sent packets to 1. (Time protocol sync should never leave
- // the local subnet)
- rc = setsockopt(mSocket, IPPROTO_IP, IP_TTL, &one, sizeof(one));
- if (rc == -1) {
- mStateChangeLog.log(ANDROID_LOG_ERROR, LOG_TAG,
- "Failed to set TTL to %d (errno = %d)", one, errno);
- goto bailout;
- }
-
- // get the device's unique ID
- if (!assignDeviceID())
- goto bailout;
-
- ret_val = true;
-
-bailout:
- if (!ret_val)
- cleanupSocket_l();
- return ret_val;
-}
-
-// generate a unique device ID that can be used for arbitration
-bool CommonTimeServer::assignDeviceID() {
- if (!mBindIfaceValid)
- return false;
-
- struct ifreq ifr;
- memset(&ifr, 0, sizeof(ifr));
- ifr.ifr_addr.sa_family = AF_INET;
- strlcpy(ifr.ifr_name, mBindIface.string(), IFNAMSIZ);
-
- int rc = ioctl(mSocket, SIOCGIFHWADDR, &ifr);
- if (rc) {
- ALOGE("%s:%d ioctl failed", __PRETTY_FUNCTION__, __LINE__);
- return false;
- }
-
- if (ifr.ifr_addr.sa_family != ARPHRD_ETHER) {
- ALOGE("%s:%d got non-Ethernet address", __PRETTY_FUNCTION__, __LINE__);
- return false;
- }
-
- mDeviceID = 0;
- for (int i = 0; i < ETH_ALEN; i++) {
- mDeviceID = (mDeviceID << 8) | ifr.ifr_hwaddr.sa_data[i];
- }
-
- return true;
-}
-
-// generate a new timeline ID
-void CommonTimeServer::assignTimelineID() {
- do {
- mTimelineID = (static_cast<uint64_t>(lrand48()) << 32)
- | static_cast<uint64_t>(lrand48());
- } while (mTimelineID == ICommonClock::kInvalidTimelineID);
-}
-
-// Select a preference between the device IDs of two potential masters.
-// Returns true if the first ID wins, or false if the second ID wins.
-bool CommonTimeServer::arbitrateMaster(
- uint64_t deviceID1, uint8_t devicePrio1,
- uint64_t deviceID2, uint8_t devicePrio2) {
- return ((devicePrio1 > devicePrio2) ||
- ((devicePrio1 == devicePrio2) && (deviceID1 > deviceID2)));
-}
-
-static void hexDumpToString(const uint8_t* src, size_t src_len,
- char* dst, size_t dst_len) {
- size_t offset = 0;
- size_t i;
-
- for (i = 0; (i < src_len) && (offset < dst_len); ++i) {
- int res;
- if (0 == (i % 16)) {
- res = snprintf(dst + offset, dst_len - offset, "\n%04x :", i);
- if (res < 0)
- break;
- offset += res;
- if (offset >= dst_len)
- break;
- }
-
- res = snprintf(dst + offset, dst_len - offset, " %02x", src[i]);
- if (res < 0)
- break;
- offset += res;
- }
-
- dst[dst_len - 1] = 0;
-}
-
-bool CommonTimeServer::handlePacket() {
- uint8_t buf[256];
- struct sockaddr_storage srcAddr;
- socklen_t srcAddrLen = sizeof(srcAddr);
-
- ssize_t recvBytes = recvfrom(
- mSocket, buf, sizeof(buf), 0,
- reinterpret_cast<const sockaddr *>(&srcAddr), &srcAddrLen);
-
- if (recvBytes < 0) {
- mBadPktLog.log(ANDROID_LOG_ERROR, LOG_TAG,
- "recvfrom failed (res %d, errno %d)",
- recvBytes, errno);
- return false;
- }
-
- UniversalTimeServicePacket pkt;
- if (pkt.deserializePacket(buf, recvBytes, mSyncGroupID) < 0) {
- char hex[256];
- char srcEPStr[64];
-
- hexDumpToString(buf, static_cast<size_t>(recvBytes), hex, sizeof(hex));
- sockaddrToString(srcAddr, true, srcEPStr, sizeof(srcEPStr));
-
- mBadPktLog.log("Failed to parse %d byte packet from %s.%s",
- recvBytes, srcEPStr, hex);
- return false;
- }
-
- bool result;
- switch (pkt.packetType) {
- case TIME_PACKET_WHO_IS_MASTER_REQUEST:
- result = handleWhoIsMasterRequest(&pkt.p.who_is_master_request,
- srcAddr);
- break;
-
- case TIME_PACKET_WHO_IS_MASTER_RESPONSE:
- result = handleWhoIsMasterResponse(&pkt.p.who_is_master_response,
- srcAddr);
- break;
-
- case TIME_PACKET_SYNC_REQUEST:
- result = handleSyncRequest(&pkt.p.sync_request, srcAddr);
- break;
-
- case TIME_PACKET_SYNC_RESPONSE:
- result = handleSyncResponse(&pkt.p.sync_response, srcAddr);
- break;
-
- case TIME_PACKET_MASTER_ANNOUNCEMENT:
- result = handleMasterAnnouncement(&pkt.p.master_announcement,
- srcAddr);
- break;
-
- default: {
- char srcEPStr[64];
- sockaddrToString(srcAddr, true, srcEPStr, sizeof(srcEPStr));
-
- mBadPktLog.log(ANDROID_LOG_WARN, LOG_TAG,
- "unknown packet type (%d) from %s",
- pkt.packetType, srcEPStr);
-
- result = false;
- } break;
- }
-
- return result;
-}
-
-bool CommonTimeServer::handleTimeout() {
- // If we have no socket, then this must be a timeout to retry socket setup.
- if (mSocket < 0)
- return true;
-
- switch (mState) {
- case ICommonClock::STATE_INITIAL:
- return handleTimeoutInitial();
- case ICommonClock::STATE_CLIENT:
- return handleTimeoutClient();
- case ICommonClock::STATE_MASTER:
- return handleTimeoutMaster();
- case ICommonClock::STATE_RONIN:
- return handleTimeoutRonin();
- case ICommonClock::STATE_WAIT_FOR_ELECTION:
- return handleTimeoutWaitForElection();
- }
-
- return false;
-}
-
-bool CommonTimeServer::handleTimeoutInitial() {
- if (++mInitial_WhoIsMasterRequestTimeouts ==
- kInitial_NumWhoIsMasterRetries) {
- // none of our attempts to discover a master succeeded, so make
- // this device the master
- return becomeMaster("initial timeout");
- } else {
- // retry the WhoIsMaster request
- return sendWhoIsMasterRequest();
- }
-}
-
-bool CommonTimeServer::handleTimeoutClient() {
- if (shouldPanicNotGettingGoodData())
- return becomeInitial("timeout panic, no good data");
-
- if (mClient_SyncRequestPending) {
- mClient_SyncRequestPending = false;
-
- if (++mClient_SyncRequestTimeouts < kClient_NumSyncRequestRetries) {
- // a sync request has timed out, so retry
- return sendSyncRequest();
- } else {
- // The master has failed to respond to a sync request for too many
- // times in a row. Assume the master is dead and start electing
- // a new master.
- return becomeRonin("master not responding");
- }
- } else {
- // initiate the next sync request
- return sendSyncRequest();
- }
-}
-
-bool CommonTimeServer::handleTimeoutMaster() {
- // send another announcement from the master
- return sendMasterAnnouncement();
-}
-
-bool CommonTimeServer::handleTimeoutRonin() {
- if (++mRonin_WhoIsMasterRequestTimeouts == kRonin_NumWhoIsMasterRetries) {
- // no other master is out there, so we won the election
- return becomeMaster("no better masters detected");
- } else {
- return sendWhoIsMasterRequest();
- }
-}
-
-bool CommonTimeServer::handleTimeoutWaitForElection() {
- return becomeRonin("timeout waiting for election conclusion");
-}
-
-bool CommonTimeServer::handleWhoIsMasterRequest(
- const WhoIsMasterRequestPacket* request,
- const sockaddr_storage& srcAddr) {
- // Skip our own messages which come back via broadcast loopback.
- if (request->senderDeviceID == mDeviceID)
- return true;
-
- char srcEPStr[64];
- sockaddrToString(srcAddr, true, srcEPStr, sizeof(srcEPStr));
- mElectionLog.log("RXed WhoIs master request while in state %s. "
- "src %s reqTID %016llx ourTID %016llx",
- stateToString(mState), srcEPStr,
- request->timelineID, mTimelineID);
-
- if (mState == ICommonClock::STATE_MASTER) {
- // is this request related to this master's timeline?
- if (request->timelineID != ICommonClock::kInvalidTimelineID &&
- request->timelineID != mTimelineID)
- return true;
-
- WhoIsMasterResponsePacket pkt;
- pkt.initHeader(mTimelineID, mSyncGroupID);
- pkt.deviceID = mDeviceID;
- pkt.devicePriority = effectivePriority();
-
- mElectionLog.log("TXing WhoIs master resp to %s while in state %s. "
- "ourTID %016llx ourGID %016llx ourDID %016llx "
- "ourPrio %u",
- srcEPStr, stateToString(mState),
- mTimelineID, mSyncGroupID,
- pkt.deviceID, pkt.devicePriority);
-
- uint8_t buf[256];
- ssize_t bufSz = pkt.serializePacket(buf, sizeof(buf));
- if (bufSz < 0)
- return false;
-
- ssize_t sendBytes = sendto(
- mSocket, buf, bufSz, 0,
- reinterpret_cast<const sockaddr *>(&srcAddr),
- sizeof(srcAddr));
- if (sendBytes == -1) {
- ALOGE("%s:%d sendto failed", __PRETTY_FUNCTION__, __LINE__);
- return false;
- }
- } else if (mState == ICommonClock::STATE_RONIN) {
- // if we hear a WhoIsMaster request from another device following
- // the same timeline and that device wins arbitration, then we will stop
- // trying to elect ourselves master and will instead wait for an
- // announcement from the election winner
- if (request->timelineID != mTimelineID)
- return true;
-
- if (arbitrateMaster(request->senderDeviceID,
- request->senderDevicePriority,
- mDeviceID,
- effectivePriority()))
- return becomeWaitForElection("would lose election");
-
- return true;
- } else if (mState == ICommonClock::STATE_INITIAL) {
- // If a group of devices booted simultaneously (e.g. after a power
- // outage) and all of them are in the initial state and there is no
- // master, then each device may time out and declare itself master at
- // the same time. To avoid this, listen for
- // WhoIsMaster(InvalidTimeline) requests from peers. If we would lose
- // arbitration against that peer, reset our timeout count so that the
- // peer has a chance to become master before we time out.
- if (request->timelineID == ICommonClock::kInvalidTimelineID &&
- arbitrateMaster(request->senderDeviceID,
- request->senderDevicePriority,
- mDeviceID,
- effectivePriority())) {
- mInitial_WhoIsMasterRequestTimeouts = 0;
- }
- }
-
- return true;
-}
-
-bool CommonTimeServer::handleWhoIsMasterResponse(
- const WhoIsMasterResponsePacket* response,
- const sockaddr_storage& srcAddr) {
- // Skip our own messages which come back via broadcast loopback.
- if (response->deviceID == mDeviceID)
- return true;
-
- char srcEPStr[64];
- sockaddrToString(srcAddr, true, srcEPStr, sizeof(srcEPStr));
- mElectionLog.log("RXed WhoIs master response while in state %s. "
- "src %s respTID %016llx respDID %016llx respPrio %u "
- "ourTID %016llx",
- stateToString(mState), srcEPStr,
- response->timelineID,
- response->deviceID,
- static_cast<uint32_t>(response->devicePriority),
- mTimelineID);
-
- if (mState == ICommonClock::STATE_INITIAL || mState == ICommonClock::STATE_RONIN) {
- return becomeClient(srcAddr,
- response->deviceID,
- response->devicePriority,
- response->timelineID,
- "heard whois response");
- } else if (mState == ICommonClock::STATE_CLIENT) {
- // if we get multiple responses because there are multiple devices
- // who believe that they are master, then follow the master that
- // wins arbitration
- if (arbitrateMaster(response->deviceID,
- response->devicePriority,
- mClient_MasterDeviceID,
- mClient_MasterDevicePriority)) {
- return becomeClient(srcAddr,
- response->deviceID,
- response->devicePriority,
- response->timelineID,
- "heard whois response");
- }
- }
-
- return true;
-}
-
-bool CommonTimeServer::handleSyncRequest(const SyncRequestPacket* request,
- const sockaddr_storage& srcAddr) {
- SyncResponsePacket pkt;
- pkt.initHeader(mTimelineID, mSyncGroupID);
-
- if ((mState == ICommonClock::STATE_MASTER) &&
- (mTimelineID == request->timelineID)) {
- int64_t rxLocalTime = mLastPacketRxLocalTime;
- int64_t rxCommonTime;
-
- // If we are master on an actual network and have actual clients, then
- // we are no longer low priority.
- setForceLowPriority(false);
-
- if (OK != mCommonClock.localToCommon(rxLocalTime, &rxCommonTime)) {
- return false;
- }
-
- int64_t txLocalTime = mLocalClock.getLocalTime();;
- int64_t txCommonTime;
- if (OK != mCommonClock.localToCommon(txLocalTime, &txCommonTime)) {
- return false;
- }
-
- pkt.nak = 0;
- pkt.clientTxLocalTime = request->clientTxLocalTime;
- pkt.masterRxCommonTime = rxCommonTime;
- pkt.masterTxCommonTime = txCommonTime;
- } else {
- pkt.nak = 1;
- pkt.clientTxLocalTime = 0;
- pkt.masterRxCommonTime = 0;
- pkt.masterTxCommonTime = 0;
- }
-
- uint8_t buf[256];
- ssize_t bufSz = pkt.serializePacket(buf, sizeof(buf));
- if (bufSz < 0)
- return false;
-
- ssize_t sendBytes = sendto(
- mSocket, &buf, bufSz, 0,
- reinterpret_cast<const sockaddr *>(&srcAddr),
- sizeof(srcAddr));
- if (sendBytes == -1) {
- ALOGE("%s:%d sendto failed", __PRETTY_FUNCTION__, __LINE__);
- return false;
- }
-
- return true;
-}
-
-bool CommonTimeServer::handleSyncResponse(
- const SyncResponsePacket* response,
- const sockaddr_storage& srcAddr) {
- if (mState != ICommonClock::STATE_CLIENT)
- return true;
-
- assert(mMasterEPValid);
- if (!sockaddrMatch(srcAddr, mMasterEP, true)) {
- char srcEP[64], expectedEP[64];
- sockaddrToString(srcAddr, true, srcEP, sizeof(srcEP));
- sockaddrToString(mMasterEP, true, expectedEP, sizeof(expectedEP));
- ALOGI("Dropping sync response from unexpected address."
- " Expected %s Got %s", expectedEP, srcEP);
- return true;
- }
-
- if (response->nak) {
- // if our master is no longer accepting requests, then we need to find
- // a new master
- return becomeRonin("master NAK'ed");
- }
-
- mClient_SyncRequestPending = 0;
- mClient_SyncRequestTimeouts = 0;
- mClient_PacketRTTLog.logRX(response->clientTxLocalTime,
- mLastPacketRxLocalTime);
-
- bool result;
- if (!(mClient_SyncRespsRXedFromCurMaster++)) {
- // the first request/response exchange between a client and a master
- // may take unusually long due to ARP, so discard it.
- result = true;
- } else {
- int64_t clientTxLocalTime = response->clientTxLocalTime;
- int64_t clientRxLocalTime = mLastPacketRxLocalTime;
- int64_t masterTxCommonTime = response->masterTxCommonTime;
- int64_t masterRxCommonTime = response->masterRxCommonTime;
-
- int64_t rtt = (clientRxLocalTime - clientTxLocalTime);
- int64_t avgLocal = (clientTxLocalTime + clientRxLocalTime) >> 1;
- int64_t avgCommon = (masterTxCommonTime + masterRxCommonTime) >> 1;
-
- // if the RTT of the packet is significantly larger than the panic
- // threshold, we should simply discard it. Its better to do nothing
- // than to take cues from a packet like that.
- int rttCommon = mCommonClock.localDurationToCommonDuration(rtt);
- if (rttCommon > (static_cast<int64_t>(mPanicThresholdUsec) *
- kRTTDiscardPanicThreshMultiplier)) {
- ALOGV("Dropping sync response with RTT of %lld uSec", rttCommon);
- mClient_ExpiredSyncRespsRXedFromCurMaster++;
- if (shouldPanicNotGettingGoodData())
- return becomeInitial("RX panic, no good data");
- } else {
- result = mClockRecovery.pushDisciplineEvent(avgLocal, avgCommon, rttCommon);
- mClient_LastGoodSyncRX = clientRxLocalTime;
-
- if (result) {
- // indicate to listeners that we've synced to the common timeline
- notifyClockSync();
- } else {
- ALOGE("Panic! Observed clock sync error is too high to tolerate,"
- " resetting state machine and starting over.");
- notifyClockSyncLoss();
- return becomeInitial("panic");
- }
- }
- }
-
- mCurTimeout.setTimeout(mSyncRequestIntervalMs);
- return result;
-}
-
-bool CommonTimeServer::handleMasterAnnouncement(
- const MasterAnnouncementPacket* packet,
- const sockaddr_storage& srcAddr) {
- uint64_t newDeviceID = packet->deviceID;
- uint8_t newDevicePrio = packet->devicePriority;
- uint64_t newTimelineID = packet->timelineID;
-
- // Skip our own messages which come back via broadcast loopback.
- if (newDeviceID == mDeviceID)
- return true;
-
- char srcEPStr[64];
- sockaddrToString(srcAddr, true, srcEPStr, sizeof(srcEPStr));
- mElectionLog.log("RXed master announcement while in state %s. "
- "src %s srcDevID %lld srcPrio %u srcTID %016llx",
- stateToString(mState), srcEPStr,
- newDeviceID, static_cast<uint32_t>(newDevicePrio),
- newTimelineID);
-
- if (mState == ICommonClock::STATE_INITIAL ||
- mState == ICommonClock::STATE_RONIN ||
- mState == ICommonClock::STATE_WAIT_FOR_ELECTION) {
- // if we aren't currently following a master, then start following
- // this new master
- return becomeClient(srcAddr,
- newDeviceID,
- newDevicePrio,
- newTimelineID,
- "heard master announcement");
- } else if (mState == ICommonClock::STATE_CLIENT) {
- // if the new master wins arbitration against our current master,
- // then become a client of the new master
- if (arbitrateMaster(newDeviceID,
- newDevicePrio,
- mClient_MasterDeviceID,
- mClient_MasterDevicePriority))
- return becomeClient(srcAddr,
- newDeviceID,
- newDevicePrio,
- newTimelineID,
- "heard master announcement");
- } else if (mState == ICommonClock::STATE_MASTER) {
- // two masters are competing - if the new one wins arbitration, then
- // cease acting as master
- if (arbitrateMaster(newDeviceID, newDevicePrio,
- mDeviceID, effectivePriority()))
- return becomeClient(srcAddr, newDeviceID,
- newDevicePrio, newTimelineID,
- "heard master announcement");
- }
-
- return true;
-}
-
-bool CommonTimeServer::sendWhoIsMasterRequest() {
- assert(mState == ICommonClock::STATE_INITIAL || mState == ICommonClock::STATE_RONIN);
-
- // If we have no socket, then we must be in the unconfigured initial state.
- // Don't report any errors, just don't try to send the initial who-is-master
- // query. Eventually, our network will either become configured, or we will
- // be forced into network-less master mode by higher level code.
- if (mSocket < 0) {
- assert(mState == ICommonClock::STATE_INITIAL);
- return true;
- }
-
- bool ret = false;
- WhoIsMasterRequestPacket pkt;
- pkt.initHeader(mSyncGroupID);
- pkt.senderDeviceID = mDeviceID;
- pkt.senderDevicePriority = effectivePriority();
-
- uint8_t buf[256];
- ssize_t bufSz = pkt.serializePacket(buf, sizeof(buf));
- if (bufSz >= 0) {
- char dstEPStr[64];
- sockaddrToString(mMasterElectionEP, true, dstEPStr, sizeof(dstEPStr));
- mElectionLog.log("TXing WhoIs master request to %s while in state %s. "
- "ourTID %016llx ourGID %016llx ourDID %016llx "
- "ourPrio %u",
- dstEPStr, stateToString(mState),
- mTimelineID, mSyncGroupID,
- pkt.senderDeviceID, pkt.senderDevicePriority);
-
- ssize_t sendBytes = sendto(
- mSocket, buf, bufSz, 0,
- reinterpret_cast<const sockaddr *>(&mMasterElectionEP),
- sizeof(mMasterElectionEP));
- if (sendBytes < 0)
- ALOGE("WhoIsMaster sendto failed (errno %d)", errno);
- ret = true;
- }
-
- if (mState == ICommonClock::STATE_INITIAL) {
- mCurTimeout.setTimeout(kInitial_WhoIsMasterTimeoutMs);
- } else {
- mCurTimeout.setTimeout(kRonin_WhoIsMasterTimeoutMs);
- }
-
- return ret;
-}
-
-bool CommonTimeServer::sendSyncRequest() {
- // If we are sending sync requests, then we must be in the client state and
- // we must have a socket (when we have no network, we are only supposed to
- // be in INITIAL or MASTER)
- assert(mState == ICommonClock::STATE_CLIENT);
- assert(mSocket >= 0);
-
- bool ret = false;
- SyncRequestPacket pkt;
- pkt.initHeader(mTimelineID, mSyncGroupID);
- pkt.clientTxLocalTime = mLocalClock.getLocalTime();
-
- if (!mClient_FirstSyncTX)
- mClient_FirstSyncTX = pkt.clientTxLocalTime;
-
- mClient_PacketRTTLog.logTX(pkt.clientTxLocalTime);
-
- uint8_t buf[256];
- ssize_t bufSz = pkt.serializePacket(buf, sizeof(buf));
- if (bufSz >= 0) {
- ssize_t sendBytes = sendto(
- mSocket, buf, bufSz, 0,
- reinterpret_cast<const sockaddr *>(&mMasterEP),
- sizeof(mMasterEP));
- if (sendBytes < 0)
- ALOGE("SyncRequest sendto failed (errno %d)", errno);
- ret = true;
- }
-
- mClient_SyncsSentToCurMaster++;
- mCurTimeout.setTimeout(mSyncRequestIntervalMs);
- mClient_SyncRequestPending = true;
-
- return ret;
-}
-
-bool CommonTimeServer::sendMasterAnnouncement() {
- bool ret = false;
- assert(mState == ICommonClock::STATE_MASTER);
-
- // If we are being asked to send a master announcement, but we have no
- // socket, we must be in network-less master mode. Don't bother to send the
- // announcement, and don't bother to schedule a timeout. When the network
- // comes up, the work thread will get poked and start the process of
- // figuring out who the current master should be.
- if (mSocket < 0) {
- mCurTimeout.setTimeout(kInfiniteTimeout);
- return true;
- }
-
- MasterAnnouncementPacket pkt;
- pkt.initHeader(mTimelineID, mSyncGroupID);
- pkt.deviceID = mDeviceID;
- pkt.devicePriority = effectivePriority();
-
- uint8_t buf[256];
- ssize_t bufSz = pkt.serializePacket(buf, sizeof(buf));
- if (bufSz >= 0) {
- char dstEPStr[64];
- sockaddrToString(mMasterElectionEP, true, dstEPStr, sizeof(dstEPStr));
- mElectionLog.log("TXing Master announcement to %s while in state %s. "
- "ourTID %016llx ourGID %016llx ourDID %016llx "
- "ourPrio %u",
- dstEPStr, stateToString(mState),
- mTimelineID, mSyncGroupID,
- pkt.deviceID, pkt.devicePriority);
-
- ssize_t sendBytes = sendto(
- mSocket, buf, bufSz, 0,
- reinterpret_cast<const sockaddr *>(&mMasterElectionEP),
- sizeof(mMasterElectionEP));
- if (sendBytes < 0)
- ALOGE("MasterAnnouncement sendto failed (errno %d)", errno);
- ret = true;
- }
-
- mCurTimeout.setTimeout(mMasterAnnounceIntervalMs);
- return ret;
-}
-
-bool CommonTimeServer::becomeClient(const sockaddr_storage& masterEP,
- uint64_t masterDeviceID,
- uint8_t masterDevicePriority,
- uint64_t timelineID,
- const char* cause) {
- char newEPStr[64], oldEPStr[64];
- sockaddrToString(masterEP, true, newEPStr, sizeof(newEPStr));
- sockaddrToString(mMasterEP, mMasterEPValid, oldEPStr, sizeof(oldEPStr));
-
- mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG,
- "%s --> CLIENT (%s) :%s"
- " OldMaster: %02x-%014llx::%016llx::%s"
- " NewMaster: %02x-%014llx::%016llx::%s",
- stateToString(mState), cause,
- (mTimelineID != timelineID) ? " (new timeline)" : "",
- mClient_MasterDevicePriority, mClient_MasterDeviceID,
- mTimelineID, oldEPStr,
- masterDevicePriority, masterDeviceID,
- timelineID, newEPStr);
-
- if (mTimelineID != timelineID) {
- // start following a new timeline
- mTimelineID = timelineID;
- mClockRecovery.reset(true, true);
- notifyClockSyncLoss();
- } else {
- // start following a new master on the existing timeline
- mClockRecovery.reset(false, true);
- }
-
- mMasterEP = masterEP;
- mMasterEPValid = true;
-
- // If we are on a real network as a client of a real master, then we should
- // no longer force low priority. If our master disappears, we should have
- // the high priority bit set during the election to replace the master
- // because this group was a real group and not a singleton created in
- // networkless mode.
- setForceLowPriority(false);
-
- mClient_MasterDeviceID = masterDeviceID;
- mClient_MasterDevicePriority = masterDevicePriority;
- resetSyncStats();
-
- setState(ICommonClock::STATE_CLIENT);
-
- // add some jitter to when the various clients send their requests
- // in order to reduce the likelihood that a group of clients overload
- // the master after receiving a master announcement
- usleep((lrand48() % 100) * 1000);
-
- return sendSyncRequest();
-}
-
-bool CommonTimeServer::becomeMaster(const char* cause) {
- uint64_t oldTimelineID = mTimelineID;
- if (mTimelineID == ICommonClock::kInvalidTimelineID) {
- // this device has not been following any existing timeline,
- // so it will create a new timeline and declare itself master
- assert(!mCommonClock.isValid());
-
- // set the common time basis
- mCommonClock.setBasis(mLocalClock.getLocalTime(), 0);
-
- // assign an arbitrary timeline iD
- assignTimelineID();
-
- // notify listeners that we've created a common timeline
- notifyClockSync();
- }
-
- mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG,
- "%s --> MASTER (%s) : %s timeline %016llx",
- stateToString(mState), cause,
- (oldTimelineID == mTimelineID) ? "taking ownership of"
- : "creating new",
- mTimelineID);
-
- memset(&mMasterEP, 0, sizeof(mMasterEP));
- mMasterEPValid = false;
- mClient_MasterDevicePriority = effectivePriority();
- mClient_MasterDeviceID = mDeviceID;
- mClockRecovery.reset(false, true);
- resetSyncStats();
-
- setState(ICommonClock::STATE_MASTER);
- return sendMasterAnnouncement();
-}
-
-bool CommonTimeServer::becomeRonin(const char* cause) {
- // If we were the client of a given timeline, but had never received even a
- // single time sync packet, then we transition back to Initial instead of
- // Ronin. If we transition to Ronin and end up becoming the new Master, we
- // will be unable to service requests for other clients because we never
- // actually knew what time it was. By going to initial, we ensure that
- // other clients who know what time it is, but would lose master arbitration
- // in the Ronin case, will step up and become the proper new master of the
- // old timeline.
-
- char oldEPStr[64];
- sockaddrToString(mMasterEP, mMasterEPValid, oldEPStr, sizeof(oldEPStr));
- memset(&mMasterEP, 0, sizeof(mMasterEP));
- mMasterEPValid = false;
-
- if (mCommonClock.isValid()) {
- mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG,
- "%s --> RONIN (%s) : lost track of previously valid timeline "
- "%02x-%014llx::%016llx::%s (%d TXed %d RXed %d RXExpired)",
- stateToString(mState), cause,
- mClient_MasterDevicePriority, mClient_MasterDeviceID,
- mTimelineID, oldEPStr,
- mClient_SyncsSentToCurMaster,
- mClient_SyncRespsRXedFromCurMaster,
- mClient_ExpiredSyncRespsRXedFromCurMaster);
-
- mRonin_WhoIsMasterRequestTimeouts = 0;
- setState(ICommonClock::STATE_RONIN);
- return sendWhoIsMasterRequest();
- } else {
- mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG,
- "%s --> INITIAL (%s) : never synced timeline "
- "%02x-%014llx::%016llx::%s (%d TXed %d RXed %d RXExpired)",
- stateToString(mState), cause,
- mClient_MasterDevicePriority, mClient_MasterDeviceID,
- mTimelineID, oldEPStr,
- mClient_SyncsSentToCurMaster,
- mClient_SyncRespsRXedFromCurMaster,
- mClient_ExpiredSyncRespsRXedFromCurMaster);
-
- return becomeInitial("ronin, no timeline");
- }
-}
-
-bool CommonTimeServer::becomeWaitForElection(const char* cause) {
- mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG,
- "%s --> WAIT_FOR_ELECTION (%s) : dropping out of election,"
- " waiting %d mSec for completion.",
- stateToString(mState), cause, kWaitForElection_TimeoutMs);
-
- setState(ICommonClock::STATE_WAIT_FOR_ELECTION);
- mCurTimeout.setTimeout(kWaitForElection_TimeoutMs);
- return true;
-}
-
-bool CommonTimeServer::becomeInitial(const char* cause) {
- mStateChangeLog.log(ANDROID_LOG_INFO, LOG_TAG,
- "Entering INITIAL (%s), total reset.",
- cause);
-
- setState(ICommonClock::STATE_INITIAL);
-
- // reset clock recovery
- mClockRecovery.reset(true, true);
-
- // reset internal state bookkeeping.
- mCurTimeout.setTimeout(kInfiniteTimeout);
- memset(&mMasterEP, 0, sizeof(mMasterEP));
- mMasterEPValid = false;
- mLastPacketRxLocalTime = 0;
- mTimelineID = ICommonClock::kInvalidTimelineID;
- mClockSynced = false;
- mInitial_WhoIsMasterRequestTimeouts = 0;
- mClient_MasterDeviceID = 0;
- mClient_MasterDevicePriority = 0;
- mRonin_WhoIsMasterRequestTimeouts = 0;
- resetSyncStats();
-
- // send the first request to discover the master
- return sendWhoIsMasterRequest();
-}
-
-void CommonTimeServer::notifyClockSync() {
- if (!mClockSynced) {
- mClockSynced = true;
- mICommonClock->notifyOnTimelineChanged(mTimelineID);
- }
-}
-
-void CommonTimeServer::notifyClockSyncLoss() {
- if (mClockSynced) {
- mClockSynced = false;
- mICommonClock->notifyOnTimelineChanged(
- ICommonClock::kInvalidTimelineID);
- }
-}
-
-void CommonTimeServer::setState(ICommonClock::State s) {
- mState = s;
-}
-
-const char* CommonTimeServer::stateToString(ICommonClock::State s) {
- switch(s) {
- case ICommonClock::STATE_INITIAL:
- return "INITIAL";
- case ICommonClock::STATE_CLIENT:
- return "CLIENT";
- case ICommonClock::STATE_MASTER:
- return "MASTER";
- case ICommonClock::STATE_RONIN:
- return "RONIN";
- case ICommonClock::STATE_WAIT_FOR_ELECTION:
- return "WAIT_FOR_ELECTION";
- default:
- return "unknown";
- }
-}
-
-void CommonTimeServer::sockaddrToString(const sockaddr_storage& addr,
- bool addrValid,
- char* buf, size_t bufLen) {
- if (!bufLen || !buf)
- return;
-
- if (addrValid) {
- switch (addr.ss_family) {
- case AF_INET: {
- const struct sockaddr_in* sa =
- reinterpret_cast<const struct sockaddr_in*>(&addr);
- unsigned long a = ntohl(sa->sin_addr.s_addr);
- uint16_t p = ntohs(sa->sin_port);
- snprintf(buf, bufLen, "%lu.%lu.%lu.%lu:%hu",
- ((a >> 24) & 0xFF), ((a >> 16) & 0xFF),
- ((a >> 8) & 0xFF), (a & 0xFF), p);
- } break;
-
- case AF_INET6: {
- const struct sockaddr_in6* sa =
- reinterpret_cast<const struct sockaddr_in6*>(&addr);
- const uint8_t* a = sa->sin6_addr.s6_addr;
- uint16_t p = ntohs(sa->sin6_port);
- snprintf(buf, bufLen,
- "%02X%02X:%02X%02X:%02X%02X:%02X%02X:"
- "%02X%02X:%02X%02X:%02X%02X:%02X%02X port %hd",
- a[0], a[1], a[ 2], a[ 3], a[ 4], a[ 5], a[ 6], a[ 7],
- a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15],
- p);
- } break;
-
- default:
- snprintf(buf, bufLen,
- "<unknown sockaddr family %d>", addr.ss_family);
- break;
- }
- } else {
- snprintf(buf, bufLen, "<none>");
- }
-
- buf[bufLen - 1] = 0;
-}
-
-bool CommonTimeServer::sockaddrMatch(const sockaddr_storage& a1,
- const sockaddr_storage& a2,
- bool matchAddressOnly) {
- if (a1.ss_family != a2.ss_family)
- return false;
-
- switch (a1.ss_family) {
- case AF_INET: {
- const struct sockaddr_in* sa1 =
- reinterpret_cast<const struct sockaddr_in*>(&a1);
- const struct sockaddr_in* sa2 =
- reinterpret_cast<const struct sockaddr_in*>(&a2);
-
- if (sa1->sin_addr.s_addr != sa2->sin_addr.s_addr)
- return false;
-
- return (matchAddressOnly || (sa1->sin_port == sa2->sin_port));
- } break;
-
- case AF_INET6: {
- const struct sockaddr_in6* sa1 =
- reinterpret_cast<const struct sockaddr_in6*>(&a1);
- const struct sockaddr_in6* sa2 =
- reinterpret_cast<const struct sockaddr_in6*>(&a2);
-
- if (memcmp(&sa1->sin6_addr, &sa2->sin6_addr, sizeof(sa2->sin6_addr)))
- return false;
-
- return (matchAddressOnly || (sa1->sin6_port == sa2->sin6_port));
- } break;
-
- // Huh? We don't deal in non-IPv[46] addresses. Not sure how we got
- // here, but we don't know how to comapre these addresses and simply
- // default to a no-match decision.
- default: return false;
- }
-}
-
-bool CommonTimeServer::shouldPanicNotGettingGoodData() {
- if (mClient_FirstSyncTX) {
- int64_t now = mLocalClock.getLocalTime();
- int64_t delta = now - (mClient_LastGoodSyncRX
- ? mClient_LastGoodSyncRX
- : mClient_FirstSyncTX);
- int64_t deltaUsec = mCommonClock.localDurationToCommonDuration(delta);
-
- if (deltaUsec >= kNoGoodDataPanicThresholdUsec)
- return true;
- }
-
- return false;
-}
-
-void CommonTimeServer::PacketRTTLog::logTX(int64_t txTime) {
- txTimes[wrPtr] = txTime;
- rxTimes[wrPtr] = 0;
- wrPtr = (wrPtr + 1) % RTT_LOG_SIZE;
- if (!wrPtr)
- logFull = true;
-}
-
-void CommonTimeServer::PacketRTTLog::logRX(int64_t txTime, int64_t rxTime) {
- if (!logFull && !wrPtr)
- return;
-
- uint32_t i = logFull ? wrPtr : 0;
- do {
- if (txTimes[i] == txTime) {
- rxTimes[i] = rxTime;
- break;
- }
- i = (i + 1) % RTT_LOG_SIZE;
- } while (i != wrPtr);
-}
-
-} // namespace android
diff --git a/services/common_time/common_time_server.h b/services/common_time/common_time_server.h
deleted file mode 100644
index 6e18050..0000000
--- a/services/common_time/common_time_server.h
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_COMMON_TIME_SERVER_H
-#define ANDROID_COMMON_TIME_SERVER_H
-
-#include <arpa/inet.h>
-#include <stdint.h>
-#include <sys/socket.h>
-
-#include <common_time/ICommonClock.h>
-#include <common_time/local_clock.h>
-#include <utils/String8.h>
-
-#include "clock_recovery.h"
-#include "common_clock.h"
-#include "common_time_server_packets.h"
-#include "utils.h"
-
-#define RTT_LOG_SIZE 30
-
-namespace android {
-
-class CommonClockService;
-class CommonTimeConfigService;
-
-/***** time service implementation *****/
-
-class CommonTimeServer : public Thread {
- public:
- CommonTimeServer();
- ~CommonTimeServer();
-
- bool startServices();
-
- // Common Clock API methods
- CommonClock& getCommonClock() { return mCommonClock; }
- LocalClock& getLocalClock() { return mLocalClock; }
- uint64_t getTimelineID();
- int32_t getEstimatedError();
- ICommonClock::State getState();
- status_t getMasterAddr(struct sockaddr_storage* addr);
- status_t isCommonTimeValid(bool* valid, uint32_t* timelineID);
-
- // Config API methods
- status_t getMasterElectionPriority(uint8_t *priority);
- status_t setMasterElectionPriority(uint8_t priority);
- status_t getMasterElectionEndpoint(struct sockaddr_storage *addr);
- status_t setMasterElectionEndpoint(const struct sockaddr_storage *addr);
- status_t getMasterElectionGroupId(uint64_t *id);
- status_t setMasterElectionGroupId(uint64_t id);
- status_t getInterfaceBinding(String8& ifaceName);
- status_t setInterfaceBinding(const String8& ifaceName);
- status_t getMasterAnnounceInterval(int *interval);
- status_t setMasterAnnounceInterval(int interval);
- status_t getClientSyncInterval(int *interval);
- status_t setClientSyncInterval(int interval);
- status_t getPanicThreshold(int *threshold);
- status_t setPanicThreshold(int threshold);
- status_t getAutoDisable(bool *autoDisable);
- status_t setAutoDisable(bool autoDisable);
- status_t forceNetworklessMasterMode();
-
- // Method used by the CommonClockService to notify the core service about
- // changes in the number of active common clock clients.
- void reevaluateAutoDisableState(bool commonClockHasClients);
-
- status_t dumpClockInterface(int fd, const Vector<String16>& args,
- size_t activeClients);
- status_t dumpConfigInterface(int fd, const Vector<String16>& args);
-
- private:
- class PacketRTTLog {
- public:
- PacketRTTLog() {
- resetLog();
- }
-
- void resetLog() {
- wrPtr = 0;
- logFull = 0;
- }
-
- void logTX(int64_t txTime);
- void logRX(int64_t txTime, int64_t rxTime);
- void dumpLog(int fd, const CommonClock& cclk);
-
- private:
- uint32_t wrPtr;
- bool logFull;
- int64_t txTimes[RTT_LOG_SIZE];
- int64_t rxTimes[RTT_LOG_SIZE];
- };
-
- bool threadLoop();
-
- bool runStateMachine_l();
- bool setupSocket_l();
-
- void assignTimelineID();
- bool assignDeviceID();
-
- static bool arbitrateMaster(uint64_t deviceID1, uint8_t devicePrio1,
- uint64_t deviceID2, uint8_t devicePrio2);
-
- bool handlePacket();
- bool handleWhoIsMasterRequest (const WhoIsMasterRequestPacket* request,
- const sockaddr_storage& srcAddr);
- bool handleWhoIsMasterResponse(const WhoIsMasterResponsePacket* response,
- const sockaddr_storage& srcAddr);
- bool handleSyncRequest (const SyncRequestPacket* request,
- const sockaddr_storage& srcAddr);
- bool handleSyncResponse (const SyncResponsePacket* response,
- const sockaddr_storage& srcAddr);
- bool handleMasterAnnouncement (const MasterAnnouncementPacket* packet,
- const sockaddr_storage& srcAddr);
-
- bool handleTimeout();
- bool handleTimeoutInitial();
- bool handleTimeoutClient();
- bool handleTimeoutMaster();
- bool handleTimeoutRonin();
- bool handleTimeoutWaitForElection();
-
- bool sendWhoIsMasterRequest();
- bool sendSyncRequest();
- bool sendMasterAnnouncement();
-
- bool becomeClient(const sockaddr_storage& masterAddr,
- uint64_t masterDeviceID,
- uint8_t masterDevicePriority,
- uint64_t timelineID,
- const char* cause);
- bool becomeMaster(const char* cause);
- bool becomeRonin(const char* cause);
- bool becomeWaitForElection(const char* cause);
- bool becomeInitial(const char* cause);
-
- void notifyClockSync();
- void notifyClockSyncLoss();
-
- ICommonClock::State mState;
- void setState(ICommonClock::State s);
-
- void clearPendingWakeupEvents_l();
- void wakeupThread_l();
- void cleanupSocket_l();
- void shutdownThread();
-
- inline uint8_t effectivePriority() const {
- return (mMasterPriority & 0x7F) |
- (mForceLowPriority ? 0x00 : 0x80);
- }
-
- inline bool shouldAutoDisable() const {
- return (mAutoDisable && !mCommonClockHasClients);
- }
-
- inline void resetSyncStats() {
- mClient_SyncRequestPending = false;
- mClient_SyncRequestTimeouts = 0;
- mClient_SyncsSentToCurMaster = 0;
- mClient_SyncRespsRXedFromCurMaster = 0;
- mClient_ExpiredSyncRespsRXedFromCurMaster = 0;
- mClient_FirstSyncTX = 0;
- mClient_LastGoodSyncRX = 0;
- mClient_PacketRTTLog.resetLog();
- }
-
- bool shouldPanicNotGettingGoodData();
-
- // Helper to keep track of the state machine's current timeout
- Timeout mCurTimeout;
-
- // common clock, local clock abstraction, and clock recovery loop
- CommonClock mCommonClock;
- LocalClock mLocalClock;
- ClockRecoveryLoop mClockRecovery;
-
- // implementation of ICommonClock
- sp<CommonClockService> mICommonClock;
-
- // implementation of ICommonTimeConfig
- sp<CommonTimeConfigService> mICommonTimeConfig;
-
- // UDP socket for the time sync protocol
- int mSocket;
-
- // eventfd used to wakeup the work thread in response to configuration
- // changes.
- int mWakeupThreadFD;
-
- // timestamp captured when a packet is received
- int64_t mLastPacketRxLocalTime;
-
- // ID of the timeline that this device is following
- uint64_t mTimelineID;
-
- // flag for whether the clock has been synced to a timeline
- bool mClockSynced;
-
- // flag used to indicate that clients should be considered to be lower
- // priority than all of their peers during elections. This flag is set and
- // cleared by the state machine. It is set when the client joins a new
- // network. If the client had been a master in the old network (or an
- // isolated master with no network connectivity) it should defer to any
- // masters which may already be on the network. It will be cleared whenever
- // the state machine transitions to the master state.
- bool mForceLowPriority;
- inline void setForceLowPriority(bool val) {
- mForceLowPriority = val;
- if (mState == ICommonClock::STATE_MASTER)
- mClient_MasterDevicePriority = effectivePriority();
- }
-
- // Lock to synchronize access to internal state and configuration.
- Mutex mLock;
-
- // Flag updated by the common clock service to indicate that it does or does
- // not currently have registered clients. When the the auto disable flag is
- // cleared on the common time service, the service will participate in
- // network synchronization whenever it has a valid network interface to bind
- // to. When the auto disable flag is set on the common time service, it
- // will only participate in network synchronization when it has both a valid
- // interface AND currently active common clock clients.
- bool mCommonClockHasClients;
-
- // Internal logs used for dumpsys.
- LogRing mStateChangeLog;
- LogRing mElectionLog;
- LogRing mBadPktLog;
-
- // Configuration info
- struct sockaddr_storage mMasterElectionEP; // Endpoint over which we conduct master election
- String8 mBindIface; // Endpoint for the service to bind to.
- bool mBindIfaceValid; // whether or not the bind Iface is valid.
- bool mBindIfaceDirty; // whether or not the bind Iface is valid.
- struct sockaddr_storage mMasterEP; // Endpoint of our current master (if any)
- bool mMasterEPValid;
- uint64_t mDeviceID; // unique ID of this device
- uint64_t mSyncGroupID; // synchronization group ID of this device.
- uint8_t mMasterPriority; // Priority of this device in master election.
- uint32_t mMasterAnnounceIntervalMs;
- uint32_t mSyncRequestIntervalMs;
- uint32_t mPanicThresholdUsec;
- bool mAutoDisable;
-
- // Config defaults.
- static const char* kDefaultMasterElectionAddr;
- static const uint16_t kDefaultMasterElectionPort;
- static const uint64_t kDefaultSyncGroupID;
- static const uint8_t kDefaultMasterPriority;
- static const uint32_t kDefaultMasterAnnounceIntervalMs;
- static const uint32_t kDefaultSyncRequestIntervalMs;
- static const uint32_t kDefaultPanicThresholdUsec;
- static const bool kDefaultAutoDisable;
-
- // Priority mask and shift fields.
- static const uint64_t kDeviceIDMask;
- static const uint8_t kDevicePriorityMask;
- static const uint8_t kDevicePriorityHiLowBit;
- static const uint32_t kDevicePriorityShift;
-
- // Unconfgurable constants
- static const int kSetupRetryTimeoutMs;
- static const int64_t kNoGoodDataPanicThresholdUsec;
- static const uint32_t kRTTDiscardPanicThreshMultiplier;
-
- /*** status while in the Initial state ***/
- int mInitial_WhoIsMasterRequestTimeouts;
- static const int kInitial_NumWhoIsMasterRetries;
- static const int kInitial_WhoIsMasterTimeoutMs;
-
- /*** status while in the Client state ***/
- uint64_t mClient_MasterDeviceID;
- uint8_t mClient_MasterDevicePriority;
- bool mClient_SyncRequestPending;
- int mClient_SyncRequestTimeouts;
- uint32_t mClient_SyncsSentToCurMaster;
- uint32_t mClient_SyncRespsRXedFromCurMaster;
- uint32_t mClient_ExpiredSyncRespsRXedFromCurMaster;
- int64_t mClient_FirstSyncTX;
- int64_t mClient_LastGoodSyncRX;
- PacketRTTLog mClient_PacketRTTLog;
- static const int kClient_NumSyncRequestRetries;
-
-
- /*** status while in the Master state ***/
- static const uint32_t kDefaultMaster_AnnouncementIntervalMs;
-
- /*** status while in the Ronin state ***/
- int mRonin_WhoIsMasterRequestTimeouts;
- static const int kRonin_NumWhoIsMasterRetries;
- static const int kRonin_WhoIsMasterTimeoutMs;
-
- /*** status while in the WaitForElection state ***/
- static const int kWaitForElection_TimeoutMs;
-
- static const int kInfiniteTimeout;
-
- static const char* stateToString(ICommonClock::State s);
- static void sockaddrToString(const sockaddr_storage& addr, bool addrValid,
- char* buf, size_t bufLen);
- static bool sockaddrMatch(const sockaddr_storage& a1,
- const sockaddr_storage& a2,
- bool matchAddressOnly);
-};
-
-} // namespace android
-
-#endif // ANDROID_COMMON_TIME_SERVER_H
diff --git a/services/common_time/common_time_server_api.cpp b/services/common_time/common_time_server_api.cpp
deleted file mode 100644
index e157071..0000000
--- a/services/common_time/common_time_server_api.cpp
+++ /dev/null
@@ -1,438 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * A service that exchanges time synchronization information between
- * a master that defines a timeline and clients that follow the timeline.
- */
-
-#define LOG_TAG "common_time"
-#include <utils/Log.h>
-
-#include <binder/IServiceManager.h>
-#include <binder/IPCThreadState.h>
-
-#include "common_time_server.h"
-
-namespace android {
-
-//
-// Clock API
-//
-uint64_t CommonTimeServer::getTimelineID() {
- AutoMutex _lock(&mLock);
- return mTimelineID;
-}
-
-ICommonClock::State CommonTimeServer::getState() {
- AutoMutex _lock(&mLock);
- return mState;
-}
-
-status_t CommonTimeServer::getMasterAddr(struct sockaddr_storage* addr) {
- AutoMutex _lock(&mLock);
- if (mMasterEPValid) {
- memcpy(addr, &mMasterEP, sizeof(*addr));
- return OK;
- }
-
- return UNKNOWN_ERROR;
-}
-
-int32_t CommonTimeServer::getEstimatedError() {
- AutoMutex _lock(&mLock);
-
- if (ICommonClock::STATE_MASTER == mState)
- return 0;
-
- if (!mClockSynced)
- return ICommonClock::kErrorEstimateUnknown;
-
- return mClockRecovery.getLastErrorEstimate();
-}
-
-status_t CommonTimeServer::isCommonTimeValid(bool* valid,
- uint32_t* timelineID) {
- AutoMutex _lock(&mLock);
- *valid = mCommonClock.isValid();
- *timelineID = mTimelineID;
- return OK;
-}
-
-//
-// Config API
-//
-status_t CommonTimeServer::getMasterElectionPriority(uint8_t *priority) {
- AutoMutex _lock(&mLock);
- *priority = mMasterPriority;
- return OK;
-}
-
-status_t CommonTimeServer::setMasterElectionPriority(uint8_t priority) {
- AutoMutex _lock(&mLock);
-
- if (priority > 0x7F)
- return BAD_VALUE;
-
- mMasterPriority = priority;
- return OK;
-}
-
-status_t CommonTimeServer::getMasterElectionEndpoint(
- struct sockaddr_storage *addr) {
- AutoMutex _lock(&mLock);
- memcpy(addr, &mMasterElectionEP, sizeof(*addr));
- return OK;
-}
-
-status_t CommonTimeServer::setMasterElectionEndpoint(
- const struct sockaddr_storage *addr) {
- AutoMutex _lock(&mLock);
-
- if (!addr)
- return BAD_VALUE;
-
- // TODO: add proper support for IPv6
- if (addr->ss_family != AF_INET)
- return BAD_VALUE;
-
- // Only multicast and broadcast endpoints with explicit ports are allowed.
- uint16_t ipv4Port = ntohs(
- reinterpret_cast<const struct sockaddr_in*>(addr)->sin_port);
- if (!ipv4Port)
- return BAD_VALUE;
-
- uint32_t ipv4Addr = ntohl(
- reinterpret_cast<const struct sockaddr_in*>(addr)->sin_addr.s_addr);
- if ((ipv4Addr != 0xFFFFFFFF) && (0xE0000000 != (ipv4Addr & 0xF0000000)))
- return BAD_VALUE;
-
- memcpy(&mMasterElectionEP, addr, sizeof(mMasterElectionEP));
-
- // Force a rebind in order to change election enpoints.
- mBindIfaceDirty = true;
- wakeupThread_l();
- return OK;
-}
-
-status_t CommonTimeServer::getMasterElectionGroupId(uint64_t *id) {
- AutoMutex _lock(&mLock);
- *id = mSyncGroupID;
- return OK;
-}
-
-status_t CommonTimeServer::setMasterElectionGroupId(uint64_t id) {
- AutoMutex _lock(&mLock);
- mSyncGroupID = id;
- return OK;
-}
-
-status_t CommonTimeServer::getInterfaceBinding(String8& ifaceName) {
- AutoMutex _lock(&mLock);
- if (!mBindIfaceValid)
- return INVALID_OPERATION;
- ifaceName = mBindIface;
- return OK;
-}
-
-status_t CommonTimeServer::setInterfaceBinding(const String8& ifaceName) {
- AutoMutex _lock(&mLock);
-
- mBindIfaceDirty = true;
- if (ifaceName.size()) {
- mBindIfaceValid = true;
- mBindIface = ifaceName;
- } else {
- mBindIfaceValid = false;
- mBindIface.clear();
- }
-
- wakeupThread_l();
- return OK;
-}
-
-status_t CommonTimeServer::getMasterAnnounceInterval(int *interval) {
- AutoMutex _lock(&mLock);
- *interval = mMasterAnnounceIntervalMs;
- return OK;
-}
-
-status_t CommonTimeServer::setMasterAnnounceInterval(int interval) {
- AutoMutex _lock(&mLock);
-
- if (interval > (6 *3600000)) // Max interval is once every 6 hrs
- return BAD_VALUE;
-
- if (interval < 500) // Min interval is once per 0.5 seconds
- return BAD_VALUE;
-
- mMasterAnnounceIntervalMs = interval;
- if (ICommonClock::STATE_MASTER == mState) {
- int pendingTimeout = mCurTimeout.msecTillTimeout();
- if ((kInfiniteTimeout == pendingTimeout) ||
- (pendingTimeout > interval)) {
- mCurTimeout.setTimeout(mMasterAnnounceIntervalMs);
- wakeupThread_l();
- }
- }
-
- return OK;
-}
-
-status_t CommonTimeServer::getClientSyncInterval(int *interval) {
- AutoMutex _lock(&mLock);
- *interval = mSyncRequestIntervalMs;
- return OK;
-}
-
-status_t CommonTimeServer::setClientSyncInterval(int interval) {
- AutoMutex _lock(&mLock);
-
- if (interval > (3600000)) // Max interval is once every 60 min
- return BAD_VALUE;
-
- if (interval < 250) // Min interval is once per 0.25 seconds
- return BAD_VALUE;
-
- mSyncRequestIntervalMs = interval;
- if (ICommonClock::STATE_CLIENT == mState) {
- int pendingTimeout = mCurTimeout.msecTillTimeout();
- if ((kInfiniteTimeout == pendingTimeout) ||
- (pendingTimeout > interval)) {
- mCurTimeout.setTimeout(mSyncRequestIntervalMs);
- wakeupThread_l();
- }
- }
-
- return OK;
-}
-
-status_t CommonTimeServer::getPanicThreshold(int *threshold) {
- AutoMutex _lock(&mLock);
- *threshold = mPanicThresholdUsec;
- return OK;
-}
-
-status_t CommonTimeServer::setPanicThreshold(int threshold) {
- AutoMutex _lock(&mLock);
-
- if (threshold < 1000) // Min threshold is 1mSec
- return BAD_VALUE;
-
- mPanicThresholdUsec = threshold;
- return OK;
-}
-
-status_t CommonTimeServer::getAutoDisable(bool *autoDisable) {
- AutoMutex _lock(&mLock);
- *autoDisable = mAutoDisable;
- return OK;
-}
-
-status_t CommonTimeServer::setAutoDisable(bool autoDisable) {
- AutoMutex _lock(&mLock);
- mAutoDisable = autoDisable;
- wakeupThread_l();
- return OK;
-}
-
-status_t CommonTimeServer::forceNetworklessMasterMode() {
- AutoMutex _lock(&mLock);
-
- // Can't force networkless master mode if we are currently bound to a
- // network.
- if (mSocket >= 0)
- return INVALID_OPERATION;
-
- becomeMaster("force networkless");
-
- return OK;
-}
-
-void CommonTimeServer::reevaluateAutoDisableState(bool commonClockHasClients) {
- AutoMutex _lock(&mLock);
- bool needWakeup = (mAutoDisable && mMasterEPValid &&
- (commonClockHasClients != mCommonClockHasClients));
-
- mCommonClockHasClients = commonClockHasClients;
-
- if (needWakeup) {
- ALOGI("Waking up service, auto-disable is engaged and service now has%s"
- " clients", mCommonClockHasClients ? "" : " no");
- wakeupThread_l();
- }
-}
-
-#define dump_printf(a, b...) do { \
- int res; \
- res = snprintf(buffer, sizeof(buffer), a, b); \
- buffer[sizeof(buffer) - 1] = 0; \
- if (res > 0) \
- write(fd, buffer, res); \
-} while (0)
-#define checked_percentage(a, b) ((0 == b) ? 0.0f : ((100.0f * a) / b))
-
-status_t CommonTimeServer::dumpClockInterface(int fd,
- const Vector<String16>& args,
- size_t activeClients) {
- AutoMutex _lock(&mLock);
- const size_t SIZE = 256;
- char buffer[SIZE];
-
- if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
- snprintf(buffer, SIZE, "Permission Denial: "
- "can't dump CommonClockService from pid=%d, uid=%d\n",
- IPCThreadState::self()->getCallingPid(),
- IPCThreadState::self()->getCallingUid());
- write(fd, buffer, strlen(buffer));
- } else {
- int64_t commonTime;
- int64_t localTime;
- bool synced;
- char maStr[64];
-
- localTime = mLocalClock.getLocalTime();
- synced = (OK == mCommonClock.localToCommon(localTime, &commonTime));
- sockaddrToString(mMasterEP, mMasterEPValid, maStr, sizeof(maStr));
-
- dump_printf("Common Clock Service Status\nLocal time : %lld\n",
- localTime);
-
- if (synced)
- dump_printf("Common time : %lld\n", commonTime);
- else
- dump_printf("Common time : %s\n", "not synced");
-
- dump_printf("Timeline ID : %016llx\n", mTimelineID);
- dump_printf("State : %s\n", stateToString(mState));
- dump_printf("Master Addr : %s\n", maStr);
-
-
- if (synced) {
- int32_t est = (ICommonClock::STATE_MASTER != mState)
- ? mClockRecovery.getLastErrorEstimate()
- : 0;
- dump_printf("Error Est. : %.3f msec\n",
- static_cast<float>(est) / 1000.0);
- } else {
- dump_printf("Error Est. : %s\n", "unknown");
- }
-
- dump_printf("Syncs TXes : %u\n", mClient_SyncsSentToCurMaster);
- dump_printf("Syncs RXes : %u (%.2f%%)\n",
- mClient_SyncRespsRXedFromCurMaster,
- checked_percentage(
- mClient_SyncRespsRXedFromCurMaster,
- mClient_SyncsSentToCurMaster));
- dump_printf("RXs Expired : %u (%.2f%%)\n",
- mClient_ExpiredSyncRespsRXedFromCurMaster,
- checked_percentage(
- mClient_ExpiredSyncRespsRXedFromCurMaster,
- mClient_SyncsSentToCurMaster));
-
- if (!mClient_LastGoodSyncRX) {
- dump_printf("Last Good RX : %s\n", "unknown");
- } else {
- int64_t localDelta, usecDelta;
- localDelta = localTime - mClient_LastGoodSyncRX;
- usecDelta = mCommonClock.localDurationToCommonDuration(localDelta);
- dump_printf("Last Good RX : %lld uSec ago\n", usecDelta);
- }
-
- dump_printf("Active Clients : %u\n", activeClients);
- mClient_PacketRTTLog.dumpLog(fd, mCommonClock);
- mStateChangeLog.dumpLog(fd);
- mElectionLog.dumpLog(fd);
- mBadPktLog.dumpLog(fd);
- }
-
- return NO_ERROR;
-}
-
-status_t CommonTimeServer::dumpConfigInterface(int fd,
- const Vector<String16>& args) {
- AutoMutex _lock(&mLock);
- const size_t SIZE = 256;
- char buffer[SIZE];
-
- if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
- snprintf(buffer, SIZE, "Permission Denial: "
- "can't dump CommonTimeConfigService from pid=%d, uid=%d\n",
- IPCThreadState::self()->getCallingPid(),
- IPCThreadState::self()->getCallingUid());
- write(fd, buffer, strlen(buffer));
- } else {
- char meStr[64];
-
- sockaddrToString(mMasterElectionEP, true, meStr, sizeof(meStr));
-
- dump_printf("Common Time Config Service Status\n"
- "Bound Interface : %s\n",
- mBindIfaceValid ? mBindIface.string() : "<unbound>");
- dump_printf("Master Election Endpoint : %s\n", meStr);
- dump_printf("Master Election Group ID : %016llx\n", mSyncGroupID);
- dump_printf("Master Announce Interval : %d mSec\n",
- mMasterAnnounceIntervalMs);
- dump_printf("Client Sync Interval : %d mSec\n",
- mSyncRequestIntervalMs);
- dump_printf("Panic Threshold : %d uSec\n",
- mPanicThresholdUsec);
- dump_printf("Base ME Prio : 0x%02x\n",
- static_cast<uint32_t>(mMasterPriority));
- dump_printf("Effective ME Prio : 0x%02x\n",
- static_cast<uint32_t>(effectivePriority()));
- dump_printf("Auto Disable Allowed : %s\n",
- mAutoDisable ? "yes" : "no");
- dump_printf("Auto Disable Engaged : %s\n",
- shouldAutoDisable() ? "yes" : "no");
- }
-
- return NO_ERROR;
-}
-
-void CommonTimeServer::PacketRTTLog::dumpLog(int fd, const CommonClock& cclk) {
- const size_t SIZE = 256;
- char buffer[SIZE];
- uint32_t avail = !logFull ? wrPtr : RTT_LOG_SIZE;
-
- if (!avail)
- return;
-
- dump_printf("\nPacket Log (%d entries)\n", avail);
-
- uint32_t ndx = 0;
- uint32_t i = logFull ? wrPtr : 0;
- do {
- if (rxTimes[i]) {
- int64_t delta = rxTimes[i] - txTimes[i];
- int64_t deltaUsec = cclk.localDurationToCommonDuration(delta);
- dump_printf("pkt[%2d] : localTX %12lld localRX %12lld "
- "(%.3f msec RTT)\n",
- ndx, txTimes[i], rxTimes[i],
- static_cast<float>(deltaUsec) / 1000.0);
- } else {
- dump_printf("pkt[%2d] : localTX %12lld localRX never\n",
- ndx, txTimes[i]);
- }
- i = (i + 1) % RTT_LOG_SIZE;
- ndx++;
- } while (i != wrPtr);
-}
-
-#undef dump_printf
-#undef checked_percentage
-
-} // namespace android
diff --git a/services/common_time/common_time_server_packets.cpp b/services/common_time/common_time_server_packets.cpp
deleted file mode 100644
index 9833c37..0000000
--- a/services/common_time/common_time_server_packets.cpp
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * A service that exchanges time synchronization information between
- * a master that defines a timeline and clients that follow the timeline.
- */
-
-#define LOG_TAG "common_time"
-#include <utils/Log.h>
-
-#include <arpa/inet.h>
-#include <stdint.h>
-
-#include "common_time_server_packets.h"
-
-namespace android {
-
-const uint32_t TimeServicePacketHeader::kMagic =
- (static_cast<uint32_t>('c') << 24) |
- (static_cast<uint32_t>('c') << 16) |
- (static_cast<uint32_t>('l') << 8) |
- static_cast<uint32_t>('k');
-
-const uint16_t TimeServicePacketHeader::kCurVersion = 1;
-
-#define SERIALIZE_FIELD(field_name, type, converter) \
- do { \
- if ((offset + sizeof(field_name)) > length) \
- return -1; \
- *((type*)(data + offset)) = converter(field_name); \
- offset += sizeof(field_name); \
- } while (0)
-#define SERIALIZE_INT16(field_name) SERIALIZE_FIELD(field_name, int16_t, htons)
-#define SERIALIZE_INT32(field_name) SERIALIZE_FIELD(field_name, int32_t, htonl)
-#define SERIALIZE_INT64(field_name) SERIALIZE_FIELD(field_name, int64_t, htonq)
-
-#define DESERIALIZE_FIELD(field_name, type, converter) \
- do { \
- if ((offset + sizeof(field_name)) > length) \
- return -1; \
- field_name = converter(*((type*)(data + offset))); \
- offset += sizeof(field_name); \
- } while (0)
-#define DESERIALIZE_INT16(field_name) DESERIALIZE_FIELD(field_name, int16_t, ntohs)
-#define DESERIALIZE_INT32(field_name) DESERIALIZE_FIELD(field_name, int32_t, ntohl)
-#define DESERIALIZE_INT64(field_name) DESERIALIZE_FIELD(field_name, int64_t, ntohq)
-
-#define kDevicePriorityShift 56
-#define kDeviceIDMask ((static_cast<uint64_t>(1) << kDevicePriorityShift) - 1)
-
-inline uint64_t packDeviceID(uint64_t devID, uint8_t prio) {
- return (devID & kDeviceIDMask) |
- (static_cast<uint64_t>(prio) << kDevicePriorityShift);
-}
-
-inline uint64_t unpackDeviceID(uint64_t packed) {
- return (packed & kDeviceIDMask);
-}
-
-inline uint8_t unpackDevicePriority(uint64_t packed) {
- return static_cast<uint8_t>(packed >> kDevicePriorityShift);
-}
-
-ssize_t TimeServicePacketHeader::serializeHeader(uint8_t* data,
- uint32_t length) {
- ssize_t offset = 0;
- int16_t pktType = static_cast<int16_t>(packetType);
- SERIALIZE_INT32(magic);
- SERIALIZE_INT16(version);
- SERIALIZE_INT16(pktType);
- SERIALIZE_INT64(timelineID);
- SERIALIZE_INT64(syncGroupID);
- return offset;
-}
-
-ssize_t TimeServicePacketHeader::deserializeHeader(const uint8_t* data,
- uint32_t length) {
- ssize_t offset = 0;
- int16_t tmp;
- DESERIALIZE_INT32(magic);
- DESERIALIZE_INT16(version);
- DESERIALIZE_INT16(tmp);
- DESERIALIZE_INT64(timelineID);
- DESERIALIZE_INT64(syncGroupID);
- packetType = static_cast<TimeServicePacketType>(tmp);
- return offset;
-}
-
-ssize_t TimeServicePacketHeader::serializePacket(uint8_t* data,
- uint32_t length) {
- ssize_t ret, tmp;
-
- ret = serializeHeader(data, length);
- if (ret < 0)
- return ret;
-
- data += ret;
- length -= ret;
-
- switch (packetType) {
- case TIME_PACKET_WHO_IS_MASTER_REQUEST:
- tmp =((WhoIsMasterRequestPacket*)(this))->serializePacket(data,
- length);
- break;
- case TIME_PACKET_WHO_IS_MASTER_RESPONSE:
- tmp =((WhoIsMasterResponsePacket*)(this))->serializePacket(data,
- length);
- break;
- case TIME_PACKET_SYNC_REQUEST:
- tmp =((SyncRequestPacket*)(this))->serializePacket(data, length);
- break;
- case TIME_PACKET_SYNC_RESPONSE:
- tmp =((SyncResponsePacket*)(this))->serializePacket(data, length);
- break;
- case TIME_PACKET_MASTER_ANNOUNCEMENT:
- tmp =((MasterAnnouncementPacket*)(this))->serializePacket(data,
- length);
- break;
- default:
- return -1;
- }
-
- if (tmp < 0)
- return tmp;
-
- return ret + tmp;
-}
-
-ssize_t UniversalTimeServicePacket::deserializePacket(
- const uint8_t* data,
- uint32_t length,
- uint64_t expectedSyncGroupID) {
- ssize_t ret;
- TimeServicePacketHeader* header;
- if (length < 8)
- return -1;
-
- packetType = ntohs(*((uint16_t*)(data + 6)));
- switch (packetType) {
- case TIME_PACKET_WHO_IS_MASTER_REQUEST:
- ret = p.who_is_master_request.deserializePacket(data, length);
- header = &p.who_is_master_request;
- break;
- case TIME_PACKET_WHO_IS_MASTER_RESPONSE:
- ret = p.who_is_master_response.deserializePacket(data, length);
- header = &p.who_is_master_response;
- break;
- case TIME_PACKET_SYNC_REQUEST:
- ret = p.sync_request.deserializePacket(data, length);
- header = &p.sync_request;
- break;
- case TIME_PACKET_SYNC_RESPONSE:
- ret = p.sync_response.deserializePacket(data, length);
- header = &p.sync_response;
- break;
- case TIME_PACKET_MASTER_ANNOUNCEMENT:
- ret = p.master_announcement.deserializePacket(data, length);
- header = &p.master_announcement;
- break;
- default:
- return -1;
- }
-
- if ((ret >= 0) && !header->checkPacket(expectedSyncGroupID))
- ret = -1;
-
- return ret;
-}
-
-ssize_t WhoIsMasterRequestPacket::serializePacket(uint8_t* data,
- uint32_t length) {
- ssize_t offset = serializeHeader(data, length);
- if (offset > 0) {
- uint64_t packed = packDeviceID(senderDeviceID, senderDevicePriority);
- SERIALIZE_INT64(packed);
- }
- return offset;
-}
-
-ssize_t WhoIsMasterRequestPacket::deserializePacket(const uint8_t* data,
- uint32_t length) {
- ssize_t offset = deserializeHeader(data, length);
- if (offset > 0) {
- uint64_t packed;
- DESERIALIZE_INT64(packed);
- senderDeviceID = unpackDeviceID(packed);
- senderDevicePriority = unpackDevicePriority(packed);
- }
- return offset;
-}
-
-ssize_t WhoIsMasterResponsePacket::serializePacket(uint8_t* data,
- uint32_t length) {
- ssize_t offset = serializeHeader(data, length);
- if (offset > 0) {
- uint64_t packed = packDeviceID(deviceID, devicePriority);
- SERIALIZE_INT64(packed);
- }
- return offset;
-}
-
-ssize_t WhoIsMasterResponsePacket::deserializePacket(const uint8_t* data,
- uint32_t length) {
- ssize_t offset = deserializeHeader(data, length);
- if (offset > 0) {
- uint64_t packed;
- DESERIALIZE_INT64(packed);
- deviceID = unpackDeviceID(packed);
- devicePriority = unpackDevicePriority(packed);
- }
- return offset;
-}
-
-ssize_t SyncRequestPacket::serializePacket(uint8_t* data,
- uint32_t length) {
- ssize_t offset = serializeHeader(data, length);
- if (offset > 0) {
- SERIALIZE_INT64(clientTxLocalTime);
- }
- return offset;
-}
-
-ssize_t SyncRequestPacket::deserializePacket(const uint8_t* data,
- uint32_t length) {
- ssize_t offset = deserializeHeader(data, length);
- if (offset > 0) {
- DESERIALIZE_INT64(clientTxLocalTime);
- }
- return offset;
-}
-
-ssize_t SyncResponsePacket::serializePacket(uint8_t* data,
- uint32_t length) {
- ssize_t offset = serializeHeader(data, length);
- if (offset > 0) {
- SERIALIZE_INT64(clientTxLocalTime);
- SERIALIZE_INT64(masterRxCommonTime);
- SERIALIZE_INT64(masterTxCommonTime);
- SERIALIZE_INT32(nak);
- }
- return offset;
-}
-
-ssize_t SyncResponsePacket::deserializePacket(const uint8_t* data,
- uint32_t length) {
- ssize_t offset = deserializeHeader(data, length);
- if (offset > 0) {
- DESERIALIZE_INT64(clientTxLocalTime);
- DESERIALIZE_INT64(masterRxCommonTime);
- DESERIALIZE_INT64(masterTxCommonTime);
- DESERIALIZE_INT32(nak);
- }
- return offset;
-}
-
-ssize_t MasterAnnouncementPacket::serializePacket(uint8_t* data,
- uint32_t length) {
- ssize_t offset = serializeHeader(data, length);
- if (offset > 0) {
- uint64_t packed = packDeviceID(deviceID, devicePriority);
- SERIALIZE_INT64(packed);
- }
- return offset;
-}
-
-ssize_t MasterAnnouncementPacket::deserializePacket(const uint8_t* data,
- uint32_t length) {
- ssize_t offset = deserializeHeader(data, length);
- if (offset > 0) {
- uint64_t packed;
- DESERIALIZE_INT64(packed);
- deviceID = unpackDeviceID(packed);
- devicePriority = unpackDevicePriority(packed);
- }
- return offset;
-}
-
-} // namespace android
-
diff --git a/services/common_time/common_time_server_packets.h b/services/common_time/common_time_server_packets.h
deleted file mode 100644
index 57ba8a2..0000000
--- a/services/common_time/common_time_server_packets.h
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_COMMON_TIME_SERVER_PACKETS_H
-#define ANDROID_COMMON_TIME_SERVER_PACKETS_H
-
-#include <stdint.h>
-#include <common_time/ICommonClock.h>
-
-namespace android {
-
-/***** time sync protocol packets *****/
-
-enum TimeServicePacketType {
- TIME_PACKET_WHO_IS_MASTER_REQUEST = 1,
- TIME_PACKET_WHO_IS_MASTER_RESPONSE,
- TIME_PACKET_SYNC_REQUEST,
- TIME_PACKET_SYNC_RESPONSE,
- TIME_PACKET_MASTER_ANNOUNCEMENT,
-};
-
-class TimeServicePacketHeader {
- public:
- friend class UniversalTimeServicePacket;
- // magic number identifying the protocol
- uint32_t magic;
-
- // protocol version of the packet
- uint16_t version;
-
- // type of the packet
- TimeServicePacketType packetType;
-
- // the timeline ID
- uint64_t timelineID;
-
- // synchronization group this packet belongs to (used to operate multiple
- // synchronization domains which all use the same master election endpoint)
- uint64_t syncGroupID;
-
- ssize_t serializePacket(uint8_t* data, uint32_t length);
-
- protected:
- void initHeader(TimeServicePacketType type,
- const uint64_t tlID,
- const uint64_t groupID) {
- magic = kMagic;
- version = kCurVersion;
- packetType = type;
- timelineID = tlID;
- syncGroupID = groupID;
- }
-
- bool checkPacket(uint64_t expectedSyncGroupID) const {
- return ((magic == kMagic) &&
- (version == kCurVersion) &&
- (!expectedSyncGroupID || (syncGroupID == expectedSyncGroupID)));
- }
-
- ssize_t serializeHeader(uint8_t* data, uint32_t length);
- ssize_t deserializeHeader(const uint8_t* data, uint32_t length);
-
- private:
- static const uint32_t kMagic;
- static const uint16_t kCurVersion;
-};
-
-// packet querying for a suitable master
-class WhoIsMasterRequestPacket : public TimeServicePacketHeader {
- public:
- uint64_t senderDeviceID;
- uint8_t senderDevicePriority;
-
- void initHeader(const uint64_t groupID) {
- TimeServicePacketHeader::initHeader(TIME_PACKET_WHO_IS_MASTER_REQUEST,
- ICommonClock::kInvalidTimelineID,
- groupID);
- }
-
- ssize_t serializePacket(uint8_t* data, uint32_t length);
- ssize_t deserializePacket(const uint8_t* data, uint32_t length);
-};
-
-// response to a WhoIsMaster request
-class WhoIsMasterResponsePacket : public TimeServicePacketHeader {
- public:
- uint64_t deviceID;
- uint8_t devicePriority;
-
- void initHeader(const uint64_t tlID, const uint64_t groupID) {
- TimeServicePacketHeader::initHeader(TIME_PACKET_WHO_IS_MASTER_RESPONSE,
- tlID, groupID);
- }
-
- ssize_t serializePacket(uint8_t* data, uint32_t length);
- ssize_t deserializePacket(const uint8_t* data, uint32_t length);
-};
-
-// packet sent by a client requesting correspondence between local
-// and common time
-class SyncRequestPacket : public TimeServicePacketHeader {
- public:
- // local time when this request was transmitted
- int64_t clientTxLocalTime;
-
- void initHeader(const uint64_t tlID, const uint64_t groupID) {
- TimeServicePacketHeader::initHeader(TIME_PACKET_SYNC_REQUEST,
- tlID, groupID);
- }
-
- ssize_t serializePacket(uint8_t* data, uint32_t length);
- ssize_t deserializePacket(const uint8_t* data, uint32_t length);
-};
-
-// response to a sync request sent by the master
-class SyncResponsePacket : public TimeServicePacketHeader {
- public:
- // local time when this request was transmitted by the client
- int64_t clientTxLocalTime;
-
- // common time when the master received the request
- int64_t masterRxCommonTime;
-
- // common time when the master transmitted the response
- int64_t masterTxCommonTime;
-
- // flag that is set if the recipient of the sync request is not acting
- // as a master for the requested timeline
- uint32_t nak;
-
- void initHeader(const uint64_t tlID, const uint64_t groupID) {
- TimeServicePacketHeader::initHeader(TIME_PACKET_SYNC_RESPONSE,
- tlID, groupID);
- }
-
- ssize_t serializePacket(uint8_t* data, uint32_t length);
- ssize_t deserializePacket(const uint8_t* data, uint32_t length);
-};
-
-// announcement of the master's presence
-class MasterAnnouncementPacket : public TimeServicePacketHeader {
- public:
- // the master's device ID
- uint64_t deviceID;
- uint8_t devicePriority;
-
- void initHeader(const uint64_t tlID, const uint64_t groupID) {
- TimeServicePacketHeader::initHeader(TIME_PACKET_MASTER_ANNOUNCEMENT,
- tlID, groupID);
- }
-
- ssize_t serializePacket(uint8_t* data, uint32_t length);
- ssize_t deserializePacket(const uint8_t* data, uint32_t length);
-};
-
-class UniversalTimeServicePacket {
- public:
- uint16_t packetType;
- union {
- WhoIsMasterRequestPacket who_is_master_request;
- WhoIsMasterResponsePacket who_is_master_response;
- SyncRequestPacket sync_request;
- SyncResponsePacket sync_response;
- MasterAnnouncementPacket master_announcement;
- } p;
-
- ssize_t deserializePacket(const uint8_t* data,
- uint32_t length,
- uint64_t expectedSyncGroupID);
-};
-
-}; // namespace android
-
-#endif // ANDROID_COMMON_TIME_SERVER_PACKETS_H
-
-
diff --git a/services/common_time/diag_thread.cpp b/services/common_time/diag_thread.cpp
deleted file mode 100644
index 4cb9551..0000000
--- a/services/common_time/diag_thread.cpp
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "common_time"
-#include <utils/Log.h>
-
-#include <fcntl.h>
-#include <linux/in.h>
-#include <linux/tcp.h>
-#include <poll.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <utils/Errors.h>
-#include <utils/misc.h>
-
-#include <common_time/local_clock.h>
-
-#include "common_clock.h"
-#include "diag_thread.h"
-
-#define kMaxEvents 16
-#define kListenPort 9876
-
-static bool setNonblocking(int fd) {
- int flags = fcntl(fd, F_GETFL);
- if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
- ALOGE("Failed to set socket (%d) to non-blocking mode (errno %d)",
- fd, errno);
- return false;
- }
-
- return true;
-}
-
-static bool setNodelay(int fd) {
- int tmp = 1;
- if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &tmp, sizeof(tmp)) < 0) {
- ALOGE("Failed to set socket (%d) to no-delay mode (errno %d)",
- fd, errno);
- return false;
- }
-
- return true;
-}
-
-namespace android {
-
-DiagThread::DiagThread(CommonClock* common_clock, LocalClock* local_clock) {
- common_clock_ = common_clock;
- local_clock_ = local_clock;
- listen_fd_ = -1;
- data_fd_ = -1;
- kernel_logID_basis_known_ = false;
- discipline_log_ID_ = 0;
-}
-
-DiagThread::~DiagThread() {
-}
-
-status_t DiagThread::startWorkThread() {
- status_t res;
- stopWorkThread();
- res = run("Diag");
-
- if (res != OK)
- ALOGE("Failed to start work thread (res = %d)", res);
-
- return res;
-}
-
-void DiagThread::stopWorkThread() {
- status_t res;
- res = requestExitAndWait(); // block until thread exit.
- if (res != OK)
- ALOGE("Failed to stop work thread (res = %d)", res);
-}
-
-bool DiagThread::openListenSocket() {
- bool ret = false;
- int flags;
- cleanupListenSocket();
-
- if ((listen_fd_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
- ALOGE("Socket failed.");
- goto bailout;
- }
-
- // Set non-blocking operation
- if (!setNonblocking(listen_fd_))
- goto bailout;
-
- struct sockaddr_in addr;
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = INADDR_ANY;
- addr.sin_port = htons(kListenPort);
-
- if (bind(listen_fd_, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
- ALOGE("Bind failed.");
- goto bailout;
- }
-
- if (listen(listen_fd_, 1) < 0) {
- ALOGE("Listen failed.");
- goto bailout;
- }
-
- ret = true;
-bailout:
- if (!ret)
- cleanupListenSocket();
-
- return ret;
-}
-
-void DiagThread::cleanupListenSocket() {
- if (listen_fd_ >= 0) {
- int res;
-
- struct linger l;
- l.l_onoff = 1;
- l.l_linger = 0;
-
- setsockopt(listen_fd_, SOL_SOCKET, SO_LINGER, &l, sizeof(l));
- shutdown(listen_fd_, SHUT_RDWR);
- close(listen_fd_);
- listen_fd_ = -1;
- }
-}
-
-void DiagThread::cleanupDataSocket() {
- if (data_fd_ >= 0) {
- int res;
-
- struct linger l;
- l.l_onoff = 1;
- l.l_linger = 0;
-
- setsockopt(data_fd_, SOL_SOCKET, SO_LINGER, &l, sizeof(l));
- shutdown(data_fd_, SHUT_RDWR);
- close(data_fd_);
- data_fd_ = -1;
- }
-}
-
-void DiagThread::resetLogIDs() {
- // Drain and discard all of the events from the kernel
- struct local_time_debug_event events[kMaxEvents];
- while(local_clock_->getDebugLog(events, kMaxEvents) > 0)
- ;
-
- {
- Mutex::Autolock lock(&discipline_log_lock_);
- discipline_log_.clear();
- discipline_log_ID_ = 0;
- }
-
- kernel_logID_basis_known_ = false;
-}
-
-void DiagThread::pushDisciplineEvent(int64_t observed_local_time,
- int64_t observed_common_time,
- int64_t nominal_common_time,
- int32_t total_correction,
- int32_t rtt) {
- Mutex::Autolock lock(&discipline_log_lock_);
-
- DisciplineEventRecord evt;
-
- evt.event_id = discipline_log_ID_++;
-
- evt.action_local_time = local_clock_->getLocalTime();
- common_clock_->localToCommon(evt.action_local_time,
- &evt.action_common_time);
-
- evt.observed_local_time = observed_local_time;
- evt.observed_common_time = observed_common_time;
- evt.nominal_common_time = nominal_common_time;
- evt.total_correction = total_correction;
- evt.rtt = rtt;
-
- discipline_log_.push_back(evt);
- while (discipline_log_.size() > kMaxDisciplineLogSize)
- discipline_log_.erase(discipline_log_.begin());
-}
-
-bool DiagThread::threadLoop() {
- struct pollfd poll_fds[1];
-
- if (!openListenSocket()) {
- ALOGE("Failed to open listen socket");
- goto bailout;
- }
-
- while (!exitPending()) {
- memset(&poll_fds, 0, sizeof(poll_fds));
-
- if (data_fd_ < 0) {
- poll_fds[0].fd = listen_fd_;
- poll_fds[0].events = POLLIN;
- } else {
- poll_fds[0].fd = data_fd_;
- poll_fds[0].events = POLLRDHUP | POLLIN;
- }
-
- int poll_res = poll(poll_fds, NELEM(poll_fds), 50);
- if (poll_res < 0) {
- ALOGE("Fatal error (%d,%d) while waiting on events",
- poll_res, errno);
- goto bailout;
- }
-
- if (exitPending())
- break;
-
- if (poll_fds[0].revents) {
- if (poll_fds[0].fd == listen_fd_) {
- data_fd_ = accept(listen_fd_, NULL, NULL);
-
- if (data_fd_ < 0) {
- ALOGW("Failed accept on socket %d with err %d",
- listen_fd_, errno);
- } else {
- if (!setNonblocking(data_fd_))
- cleanupDataSocket();
- if (!setNodelay(data_fd_))
- cleanupDataSocket();
- }
- } else
- if (poll_fds[0].fd == data_fd_) {
- if (poll_fds[0].revents & POLLRDHUP) {
- // Connection hung up; time to clean up.
- cleanupDataSocket();
- } else
- if (poll_fds[0].revents & POLLIN) {
- uint8_t cmd;
- if (read(data_fd_, &cmd, sizeof(cmd)) > 0) {
- switch(cmd) {
- case 'r':
- case 'R':
- resetLogIDs();
- break;
- }
- }
- }
- }
- }
-
- struct local_time_debug_event events[kMaxEvents];
- int amt = local_clock_->getDebugLog(events, kMaxEvents);
-
- if (amt > 0) {
- for (int i = 0; i < amt; i++) {
- struct local_time_debug_event& e = events[i];
-
- if (!kernel_logID_basis_known_) {
- kernel_logID_basis_ = e.local_timesync_event_id;
- kernel_logID_basis_known_ = true;
- }
-
- char buf[1024];
- int64_t common_time;
- status_t res = common_clock_->localToCommon(e.local_time,
- &common_time);
- snprintf(buf, sizeof(buf), "E,%lld,%lld,%lld,%d\n",
- e.local_timesync_event_id - kernel_logID_basis_,
- e.local_time,
- common_time,
- (OK == res) ? 1 : 0);
- buf[sizeof(buf) - 1] = 0;
-
- if (data_fd_ >= 0)
- write(data_fd_, buf, strlen(buf));
- }
- }
-
- { // scope for autolock pattern
- Mutex::Autolock lock(&discipline_log_lock_);
-
- while (discipline_log_.size() > 0) {
- char buf[1024];
- DisciplineEventRecord& e = *discipline_log_.begin();
- snprintf(buf, sizeof(buf),
- "D,%lld,%lld,%lld,%lld,%lld,%lld,%d,%d\n",
- e.event_id,
- e.action_local_time,
- e.action_common_time,
- e.observed_local_time,
- e.observed_common_time,
- e.nominal_common_time,
- e.total_correction,
- e.rtt);
- buf[sizeof(buf) - 1] = 0;
-
- if (data_fd_ >= 0)
- write(data_fd_, buf, strlen(buf));
-
- discipline_log_.erase(discipline_log_.begin());
- }
- }
- }
-
-bailout:
- cleanupDataSocket();
- cleanupListenSocket();
- return false;
-}
-
-} // namespace android
diff --git a/services/common_time/diag_thread.h b/services/common_time/diag_thread.h
deleted file mode 100644
index c630e0d..0000000
--- a/services/common_time/diag_thread.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __DIAG_THREAD_H__
-#define __DIAG_THREAD_H__
-
-#include <utils/List.h>
-#include <utils/threads.h>
-
-namespace android {
-
-class CommonClock;
-class LocalClock;
-
-class DiagThread : public Thread {
- public:
- DiagThread(CommonClock* common_clock, LocalClock* local_clock);
- ~DiagThread();
-
- status_t startWorkThread();
- void stopWorkThread();
- virtual bool threadLoop();
-
- void pushDisciplineEvent(int64_t observed_local_time,
- int64_t observed_common_time,
- int64_t nominal_common_time,
- int32_t total_correction,
- int32_t rtt);
-
- private:
- typedef struct {
- int64_t event_id;
- int64_t action_local_time;
- int64_t action_common_time;
- int64_t observed_local_time;
- int64_t observed_common_time;
- int64_t nominal_common_time;
- int32_t total_correction;
- int32_t rtt;
- } DisciplineEventRecord;
-
- bool openListenSocket();
- void cleanupListenSocket();
- void cleanupDataSocket();
- void resetLogIDs();
-
- CommonClock* common_clock_;
- LocalClock* local_clock_;
- int listen_fd_;
- int data_fd_;
-
- int64_t kernel_logID_basis_;
- bool kernel_logID_basis_known_;
-
- static const size_t kMaxDisciplineLogSize = 16;
- Mutex discipline_log_lock_;
- List<DisciplineEventRecord> discipline_log_;
- int64_t discipline_log_ID_;
-};
-
-} // namespace android
-
-#endif //__ DIAG_THREAD_H__
diff --git a/services/common_time/main.cpp b/services/common_time/main.cpp
deleted file mode 100644
index 49eb30a..0000000
--- a/services/common_time/main.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * A service that exchanges time synchronization information between
- * a master that defines a timeline and clients that follow the timeline.
- */
-
-#define LOG_TAG "common_time"
-#include <utils/Log.h>
-
-#include <binder/IPCThreadState.h>
-#include <binder/ProcessState.h>
-
-#include "common_time_server.h"
-
-int main(int argc, char *argv[]) {
- using namespace android;
-
- sp<CommonTimeServer> service = new CommonTimeServer();
- if (service == NULL)
- return 1;
-
- ProcessState::self()->startThreadPool();
- service->run("CommonTimeServer", ANDROID_PRIORITY_NORMAL);
-
- IPCThreadState::self()->joinThreadPool();
- return 0;
-}
-
diff --git a/services/common_time/utils.cpp b/services/common_time/utils.cpp
deleted file mode 100644
index ed2c77d..0000000
--- a/services/common_time/utils.cpp
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "common_time"
-#include <utils/Log.h>
-
-#include "utils.h"
-
-namespace android {
-
-void Timeout::setTimeout(int msec) {
- if (msec < 0) {
- mSystemEndTime = 0;
- return;
- }
-
- mSystemEndTime = systemTime() + (static_cast<nsecs_t>(msec) * 1000000);
-}
-
-int Timeout::msecTillTimeout(nsecs_t nowTime) {
- if (!mSystemEndTime) {
- return -1;
- }
-
- if (mSystemEndTime < nowTime) {
- return 0;
- }
-
- nsecs_t delta = mSystemEndTime - nowTime;
- delta += 999999;
- delta /= 1000000;
- if (delta > 0x7FFFFFFF) {
- return 0x7FFFFFFF;
- }
-
- return static_cast<int>(delta);
-}
-
-LogRing::LogRing(const char* header, size_t entries)
- : mSize(entries)
- , mWr(0)
- , mIsFull(false)
- , mHeader(header) {
- mRingBuffer = new Entry[mSize];
- if (NULL == mRingBuffer)
- ALOGE("Failed to allocate log ring with %u entries.", mSize);
-}
-
-LogRing::~LogRing() {
- if (NULL != mRingBuffer)
- delete[] mRingBuffer;
-}
-
-void LogRing::log(int prio, const char* tag, const char* fmt, ...) {
- va_list argp;
- va_start(argp, fmt);
- internalLog(prio, tag, fmt, argp);
- va_end(argp);
-}
-
-void LogRing::log(const char* fmt, ...) {
- va_list argp;
- va_start(argp, fmt);
- internalLog(0, NULL, fmt, argp);
- va_end(argp);
-}
-
-void LogRing::internalLog(int prio,
- const char* tag,
- const char* fmt,
- va_list argp) {
- if (NULL != mRingBuffer) {
- Mutex::Autolock lock(&mLock);
- String8 s(String8::formatV(fmt, argp));
- Entry* last = NULL;
-
- if (mIsFull || mWr)
- last = &(mRingBuffer[(mWr + mSize - 1) % mSize]);
-
-
- if ((NULL != last) && !last->s.compare(s)) {
- gettimeofday(&(last->last_ts), NULL);
- ++last->count;
- } else {
- gettimeofday(&mRingBuffer[mWr].first_ts, NULL);
- mRingBuffer[mWr].last_ts = mRingBuffer[mWr].first_ts;
- mRingBuffer[mWr].count = 1;
- mRingBuffer[mWr].s.setTo(s);
-
- mWr = (mWr + 1) % mSize;
- if (!mWr)
- mIsFull = true;
- }
- }
-
- if (NULL != tag)
- LOG_PRI_VA(prio, tag, fmt, argp);
-}
-
-void LogRing::dumpLog(int fd) {
- if (NULL == mRingBuffer)
- return;
-
- Mutex::Autolock lock(&mLock);
-
- if (!mWr && !mIsFull)
- return;
-
- char buf[1024];
- int res;
- size_t start = mIsFull ? mWr : 0;
- size_t count = mIsFull ? mSize : mWr;
- static const char* kTimeFmt = "%a %b %d %Y %H:%M:%S";
-
- res = snprintf(buf, sizeof(buf), "\n%s\n", mHeader);
- if (res > 0)
- write(fd, buf, res);
-
- for (size_t i = 0; i < count; ++i) {
- struct tm t;
- char timebuf[64];
- char repbuf[96];
- size_t ndx = (start + i) % mSize;
-
- if (1 != mRingBuffer[ndx].count) {
- localtime_r(&mRingBuffer[ndx].last_ts.tv_sec, &t);
- strftime(timebuf, sizeof(timebuf), kTimeFmt, &t);
- snprintf(repbuf, sizeof(repbuf),
- " (repeated %d times, last was %s.%03ld)",
- mRingBuffer[ndx].count,
- timebuf,
- mRingBuffer[ndx].last_ts.tv_usec / 1000);
- repbuf[sizeof(repbuf) - 1] = 0;
- } else {
- repbuf[0] = 0;
- }
-
- localtime_r(&mRingBuffer[ndx].first_ts.tv_sec, &t);
- strftime(timebuf, sizeof(timebuf), kTimeFmt, &t);
- res = snprintf(buf, sizeof(buf), "[%2d] %s.%03ld :: %s%s\n",
- i, timebuf,
- mRingBuffer[ndx].first_ts.tv_usec / 1000,
- mRingBuffer[ndx].s.string(),
- repbuf);
-
- if (res > 0)
- write(fd, buf, res);
- }
-}
-
-} // namespace android
diff --git a/services/common_time/utils.h b/services/common_time/utils.h
deleted file mode 100644
index c28cf0a..0000000
--- a/services/common_time/utils.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __UTILS_H__
-#define __UTILS_H__
-
-#include <stdint.h>
-#include <unistd.h>
-
-#include <utils/String8.h>
-#include <utils/threads.h>
-#include <utils/Timers.h>
-
-namespace android {
-
-class Timeout {
- public:
- Timeout() : mSystemEndTime(0) { }
-
- // Set a timeout which should occur msec milliseconds from now.
- // Negative values will cancel any current timeout;
- void setTimeout(int msec);
-
- // Return the number of milliseconds until the timeout occurs, or -1 if
- // no timeout is scheduled.
- int msecTillTimeout(nsecs_t nowTime);
- int msecTillTimeout() { return msecTillTimeout(systemTime()); }
-
- private:
- // The systemTime() at which the timeout will be complete, or 0 if no
- // timeout is currently scheduled.
- nsecs_t mSystemEndTime;
-};
-
-class LogRing {
- public:
- LogRing(const char* header, size_t entries);
- ~LogRing();
-
- // Send a log message to logcat as well as storing it in the ring buffer.
- void log(int prio, const char* tag, const char* fmt, ...);
-
- // Add a log message the ring buffer, do not send the message to logcat.
- void log(const char* fmt, ...);
-
- // Dump the log to an fd (dumpsys style)
- void dumpLog(int fd);
-
- private:
- class Entry {
- public:
- uint32_t count;
- struct timeval first_ts;
- struct timeval last_ts;
- String8 s;
- };
-
- Mutex mLock;
- Entry* mRingBuffer;
- size_t mSize;
- size_t mWr;
- bool mIsFull;
- const char* mHeader;
-
- void internalLog(int prio, const char* tag, const char* fmt, va_list va);
-};
-
-} // namespace android
-
-#endif // __UTILS_H__