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 23 namespace android { 24 25 Mutex CCHelper::lock_; 26 sp<ICommonClock> CCHelper::common_clock_; 27 sp<ICommonClockListener> CCHelper::common_clock_listener_; 28 uint32_t CCHelper::ref_count_ = 0; 29 30 bool 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 52 bailout: 53 if (!ret) { 54 common_clock_listener_ = NULL; 55 common_clock_ = NULL; 56 } 57 return ret; 58 } 59 60 CCHelper::CCHelper() { 61 Mutex::Autolock lock(&lock_); 62 ref_count_++; 63 verifyClock_l(); 64 } 65 66 CCHelper::~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 83 void 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 114 CCHELPER_METHOD(isCommonTimeValid(bool* valid, uint32_t* timelineID), 115 isCommonTimeValid(valid, timelineID)) 116 CCHELPER_METHOD(commonTimeToLocalTime(int64_t commonTime, int64_t* localTime), 117 commonTimeToLocalTime(commonTime, localTime)) 118 CCHELPER_METHOD(localTimeToCommonTime(int64_t localTime, int64_t* commonTime), 119 localTimeToCommonTime(localTime, commonTime)) 120 CCHELPER_METHOD(getCommonTime(int64_t* commonTime), 121 getCommonTime(commonTime)) 122 CCHELPER_METHOD(getCommonFreq(uint64_t* freq), 123 getCommonFreq(freq)) 124 CCHELPER_METHOD(getLocalTime(int64_t* localTime), 125 getLocalTime(localTime)) 126 CCHELPER_METHOD(getLocalFreq(uint64_t* freq), 127 getLocalFreq(freq)) 128 129 } // namespace android 130