Home | History | Annotate | Download | only in common_time
      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