common_clock.cpp revision 232f869c99b8b33276ddad8054fc3e89e44852e5
1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define __STDC_LIMIT_MACROS 18 19#define LOG_TAG "common_time" 20#include <utils/Log.h> 21 22#include <stdint.h> 23 24#include <utils/Errors.h> 25#include <utils/LinearTransform.h> 26 27#include "common_clock.h" 28 29namespace android { 30 31CommonClock::CommonClock() { 32 cur_slew_ = 0; 33 cur_trans_valid_ = false; 34 35 cur_trans_.a_zero = 0; 36 cur_trans_.b_zero = 0; 37 cur_trans_.a_to_b_numer = local_to_common_freq_numer_ = 1; 38 cur_trans_.a_to_b_denom = local_to_common_freq_denom_ = 1; 39} 40 41bool CommonClock::init(uint64_t local_freq) { 42 Mutex::Autolock lock(&lock_); 43 44 if (!local_freq) 45 return false; 46 47 uint64_t numer = kCommonFreq; 48 uint64_t denom = local_freq; 49 50 LinearTransform::reduce(&numer, &denom); 51 if ((numer > UINT32_MAX) || (denom > UINT32_MAX)) { 52 LOGE("Overflow in CommonClock::init while trying to reduce %lld/%lld", 53 kCommonFreq, local_freq); 54 return false; 55 } 56 57 cur_trans_.a_to_b_numer = local_to_common_freq_numer_ = 58 static_cast<uint32_t>(numer); 59 cur_trans_.a_to_b_denom = local_to_common_freq_denom_ = 60 static_cast<uint32_t>(denom); 61 62 return true; 63} 64 65status_t CommonClock::localToCommon(int64_t local, int64_t *common_out) const { 66 Mutex::Autolock lock(&lock_); 67 68 if (!cur_trans_valid_) 69 return INVALID_OPERATION; 70 71 if (!cur_trans_.doForwardTransform(local, common_out)) 72 return INVALID_OPERATION; 73 74 return OK; 75} 76 77status_t CommonClock::commonToLocal(int64_t common, int64_t *local_out) const { 78 Mutex::Autolock lock(&lock_); 79 80 if (!cur_trans_valid_) 81 return INVALID_OPERATION; 82 83 if (!cur_trans_.doReverseTransform(common, local_out)) 84 return INVALID_OPERATION; 85 86 return OK; 87} 88 89void CommonClock::setBasis(int64_t local, int64_t common) { 90 Mutex::Autolock lock(&lock_); 91 92 cur_trans_.a_zero = local; 93 cur_trans_.b_zero = common; 94 cur_trans_valid_ = true; 95} 96 97void CommonClock::resetBasis() { 98 Mutex::Autolock lock(&lock_); 99 100 cur_trans_.a_zero = 0; 101 cur_trans_.b_zero = 0; 102 cur_trans_valid_ = false; 103} 104 105status_t CommonClock::setSlew(int64_t change_time, int32_t ppm) { 106 Mutex::Autolock lock(&lock_); 107 108 int64_t new_local_basis; 109 int64_t new_common_basis; 110 111 if (cur_trans_valid_) { 112 new_local_basis = change_time; 113 if (!cur_trans_.doForwardTransform(change_time, &new_common_basis)) { 114 LOGE("Overflow when attempting to set slew rate to %d", ppm); 115 return INVALID_OPERATION; 116 } 117 } else { 118 new_local_basis = 0; 119 new_common_basis = 0; 120 } 121 122 cur_slew_ = ppm; 123 uint32_t n1 = local_to_common_freq_numer_; 124 uint32_t n2 = 1000000 + cur_slew_; 125 126 uint32_t d1 = local_to_common_freq_denom_; 127 uint32_t d2 = 1000000; 128 129 // n1/d1 has alredy been reduced, no need to do so here. 130 LinearTransform::reduce(&n1, &d2); 131 LinearTransform::reduce(&n2, &d1); 132 LinearTransform::reduce(&n2, &d2); 133 134 cur_trans_.a_zero = new_local_basis; 135 cur_trans_.b_zero = new_common_basis; 136 cur_trans_.a_to_b_numer = n1 * n2; 137 cur_trans_.a_to_b_denom = d1 * d2; 138 139 return OK; 140} 141 142} // namespace android 143