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#include <stdint.h> 18 19#include <common_time/cc_helper.h> 20#include <common_time/ICommonClock.h> 21#include <utils/threads.h> 22 23namespace android { 24 25Mutex CCHelper::lock_; 26sp<ICommonClock> CCHelper::common_clock_; 27sp<ICommonClockListener> CCHelper::common_clock_listener_; 28uint32_t CCHelper::ref_count_ = 0; 29 30bool CCHelper::verifyClock_l() { 31 bool ret = false; 32 33 if (common_clock_ == NULL) { 34 common_clock_ = ICommonClock::getInstance(); 35 if (common_clock_ == NULL) 36 goto bailout; 37 } 38 39 if (ref_count_ > 0) { 40 if (common_clock_listener_ == NULL) { 41 common_clock_listener_ = new CommonClockListener(); 42 if (common_clock_listener_ == NULL) 43 goto bailout; 44 45 if (OK != common_clock_->registerListener(common_clock_listener_)) 46 goto bailout; 47 } 48 } 49 50 ret = true; 51 52bailout: 53 if (!ret) { 54 common_clock_listener_ = NULL; 55 common_clock_ = NULL; 56 } 57 return ret; 58} 59 60CCHelper::CCHelper() { 61 Mutex::Autolock lock(&lock_); 62 ref_count_++; 63 verifyClock_l(); 64} 65 66CCHelper::~CCHelper() { 67 Mutex::Autolock lock(&lock_); 68 69 assert(ref_count_ > 0); 70 ref_count_--; 71 72 // If we were the last CCHelper instance in the system, and we had 73 // previously register a listener, unregister it now so that the common time 74 // service has the chance to go into auto-disabled mode. 75 if (!ref_count_ && 76 (common_clock_ != NULL) && 77 (common_clock_listener_ != NULL)) { 78 common_clock_->unregisterListener(common_clock_listener_); 79 common_clock_listener_ = NULL; 80 } 81} 82 83void CCHelper::CommonClockListener::onTimelineChanged(uint64_t timelineID) { 84 // do nothing; listener is only really used as a token so the server can 85 // find out when clients die. 86} 87 88// Helper methods which attempts to make calls to the common time binder 89// service. If the first attempt fails with DEAD_OBJECT, the helpers will 90// attempt to make a connection to the service again (assuming that the process 91// hosting the service had crashed and the client proxy we are holding is dead) 92// If the second attempt fails, or no connection can be made, the we let the 93// error propagate up the stack and let the caller deal with the situation as 94// best they can. 95#define CCHELPER_METHOD(decl, call) \ 96 status_t CCHelper::decl { \ 97 Mutex::Autolock lock(&lock_); \ 98 \ 99 if (!verifyClock_l()) \ 100 return DEAD_OBJECT; \ 101 \ 102 status_t status = common_clock_->call; \ 103 if (DEAD_OBJECT == status) { \ 104 if (!verifyClock_l()) \ 105 return DEAD_OBJECT; \ 106 status = common_clock_->call; \ 107 } \ 108 \ 109 return status; \ 110 } 111 112#define VERIFY_CLOCK() 113 114CCHELPER_METHOD(isCommonTimeValid(bool* valid, uint32_t* timelineID), 115 isCommonTimeValid(valid, timelineID)) 116CCHELPER_METHOD(commonTimeToLocalTime(int64_t commonTime, int64_t* localTime), 117 commonTimeToLocalTime(commonTime, localTime)) 118CCHELPER_METHOD(localTimeToCommonTime(int64_t localTime, int64_t* commonTime), 119 localTimeToCommonTime(localTime, commonTime)) 120CCHELPER_METHOD(getCommonTime(int64_t* commonTime), 121 getCommonTime(commonTime)) 122CCHELPER_METHOD(getCommonFreq(uint64_t* freq), 123 getCommonFreq(freq)) 124CCHELPER_METHOD(getLocalTime(int64_t* localTime), 125 getLocalTime(localTime)) 126CCHELPER_METHOD(getLocalFreq(uint64_t* freq), 127 getLocalFreq(freq)) 128 129} // namespace android 130