Home | History | Annotate | Download | only in foundation
      1 /*
      2  * Copyright (C) 2010 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 LOG_NDEBUG 0
     18 #define LOG_TAG "ALooperRoster"
     19 #include <utils/Log.h>
     20 
     21 #include "ALooperRoster.h"
     22 
     23 #include "ADebug.h"
     24 #include "AHandler.h"
     25 #include "AMessage.h"
     26 
     27 namespace android {
     28 
     29 ALooperRoster::ALooperRoster()
     30     : mNextHandlerID(1),
     31       mNextReplyID(1) {
     32 }
     33 
     34 ALooper::handler_id ALooperRoster::registerHandler(
     35         const sp<ALooper> looper, const sp<AHandler> &handler) {
     36     Mutex::Autolock autoLock(mLock);
     37 
     38     if (handler->id() != 0) {
     39         CHECK(!"A handler must only be registered once.");
     40         return INVALID_OPERATION;
     41     }
     42 
     43     HandlerInfo info;
     44     info.mLooper = looper;
     45     info.mHandler = handler;
     46     ALooper::handler_id handlerID = mNextHandlerID++;
     47     mHandlers.add(handlerID, info);
     48 
     49     handler->setID(handlerID);
     50 
     51     return handlerID;
     52 }
     53 
     54 void ALooperRoster::unregisterHandler(ALooper::handler_id handlerID) {
     55     Mutex::Autolock autoLock(mLock);
     56 
     57     ssize_t index = mHandlers.indexOfKey(handlerID);
     58 
     59     if (index < 0) {
     60         return;
     61     }
     62 
     63     const HandlerInfo &info = mHandlers.valueAt(index);
     64 
     65     sp<AHandler> handler = info.mHandler.promote();
     66 
     67     if (handler != NULL) {
     68         handler->setID(0);
     69     }
     70 
     71     mHandlers.removeItemsAt(index);
     72 }
     73 
     74 void ALooperRoster::unregisterStaleHandlers() {
     75     Mutex::Autolock autoLock(mLock);
     76 
     77     for (size_t i = mHandlers.size(); i-- > 0;) {
     78         const HandlerInfo &info = mHandlers.valueAt(i);
     79 
     80         sp<ALooper> looper = info.mLooper.promote();
     81         if (looper == NULL) {
     82             ALOGV("Unregistering stale handler %d", mHandlers.keyAt(i));
     83             mHandlers.removeItemsAt(i);
     84         }
     85     }
     86 }
     87 
     88 status_t ALooperRoster::postMessage(
     89         const sp<AMessage> &msg, int64_t delayUs) {
     90     Mutex::Autolock autoLock(mLock);
     91     return postMessage_l(msg, delayUs);
     92 }
     93 
     94 status_t ALooperRoster::postMessage_l(
     95         const sp<AMessage> &msg, int64_t delayUs) {
     96     ssize_t index = mHandlers.indexOfKey(msg->target());
     97 
     98     if (index < 0) {
     99         ALOGW("failed to post message '%s'. Target handler not registered.",
    100               msg->debugString().c_str());
    101         return -ENOENT;
    102     }
    103 
    104     const HandlerInfo &info = mHandlers.valueAt(index);
    105 
    106     sp<ALooper> looper = info.mLooper.promote();
    107 
    108     if (looper == NULL) {
    109         ALOGW("failed to post message. "
    110              "Target handler %d still registered, but object gone.",
    111              msg->target());
    112 
    113         mHandlers.removeItemsAt(index);
    114         return -ENOENT;
    115     }
    116 
    117     looper->post(msg, delayUs);
    118 
    119     return OK;
    120 }
    121 
    122 void ALooperRoster::deliverMessage(const sp<AMessage> &msg) {
    123     sp<AHandler> handler;
    124 
    125     {
    126         Mutex::Autolock autoLock(mLock);
    127 
    128         ssize_t index = mHandlers.indexOfKey(msg->target());
    129 
    130         if (index < 0) {
    131             ALOGW("failed to deliver message. Target handler not registered.");
    132             return;
    133         }
    134 
    135         const HandlerInfo &info = mHandlers.valueAt(index);
    136         handler = info.mHandler.promote();
    137 
    138         if (handler == NULL) {
    139             ALOGW("failed to deliver message. "
    140                  "Target handler %d registered, but object gone.",
    141                  msg->target());
    142 
    143             mHandlers.removeItemsAt(index);
    144             return;
    145         }
    146     }
    147 
    148     handler->onMessageReceived(msg);
    149 }
    150 
    151 sp<ALooper> ALooperRoster::findLooper(ALooper::handler_id handlerID) {
    152     Mutex::Autolock autoLock(mLock);
    153 
    154     ssize_t index = mHandlers.indexOfKey(handlerID);
    155 
    156     if (index < 0) {
    157         return NULL;
    158     }
    159 
    160     sp<ALooper> looper = mHandlers.valueAt(index).mLooper.promote();
    161 
    162     if (looper == NULL) {
    163         mHandlers.removeItemsAt(index);
    164         return NULL;
    165     }
    166 
    167     return looper;
    168 }
    169 
    170 status_t ALooperRoster::postAndAwaitResponse(
    171         const sp<AMessage> &msg, sp<AMessage> *response) {
    172     Mutex::Autolock autoLock(mLock);
    173 
    174     uint32_t replyID = mNextReplyID++;
    175 
    176     msg->setInt32("replyID", replyID);
    177 
    178     status_t err = postMessage_l(msg, 0 /* delayUs */);
    179 
    180     if (err != OK) {
    181         response->clear();
    182         return err;
    183     }
    184 
    185     ssize_t index;
    186     while ((index = mReplies.indexOfKey(replyID)) < 0) {
    187         mRepliesCondition.wait(mLock);
    188     }
    189 
    190     *response = mReplies.valueAt(index);
    191     mReplies.removeItemsAt(index);
    192 
    193     return OK;
    194 }
    195 
    196 void ALooperRoster::postReply(uint32_t replyID, const sp<AMessage> &reply) {
    197     Mutex::Autolock autoLock(mLock);
    198 
    199     CHECK(mReplies.indexOfKey(replyID) < 0);
    200     mReplies.add(replyID, reply);
    201     mRepliesCondition.broadcast();
    202 }
    203 
    204 }  // namespace android
    205