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 status_t ALooperRoster::postMessage(
     75         const sp<AMessage> &msg, int64_t delayUs) {
     76     Mutex::Autolock autoLock(mLock);
     77     return postMessage_l(msg, delayUs);
     78 }
     79 
     80 status_t ALooperRoster::postMessage_l(
     81         const sp<AMessage> &msg, int64_t delayUs) {
     82     ssize_t index = mHandlers.indexOfKey(msg->target());
     83 
     84     if (index < 0) {
     85         ALOGW("failed to post message '%s'. Target handler not registered.",
     86               msg->debugString().c_str());
     87         return -ENOENT;
     88     }
     89 
     90     const HandlerInfo &info = mHandlers.valueAt(index);
     91 
     92     sp<ALooper> looper = info.mLooper.promote();
     93 
     94     if (looper == NULL) {
     95         ALOGW("failed to post message. "
     96              "Target handler %d still registered, but object gone.",
     97              msg->target());
     98 
     99         mHandlers.removeItemsAt(index);
    100         return -ENOENT;
    101     }
    102 
    103     looper->post(msg, delayUs);
    104 
    105     return OK;
    106 }
    107 
    108 void ALooperRoster::deliverMessage(const sp<AMessage> &msg) {
    109     sp<AHandler> handler;
    110 
    111     {
    112         Mutex::Autolock autoLock(mLock);
    113 
    114         ssize_t index = mHandlers.indexOfKey(msg->target());
    115 
    116         if (index < 0) {
    117             ALOGW("failed to deliver message. Target handler not registered.");
    118             return;
    119         }
    120 
    121         const HandlerInfo &info = mHandlers.valueAt(index);
    122         handler = info.mHandler.promote();
    123 
    124         if (handler == NULL) {
    125             ALOGW("failed to deliver message. "
    126                  "Target handler %d registered, but object gone.",
    127                  msg->target());
    128 
    129             mHandlers.removeItemsAt(index);
    130             return;
    131         }
    132     }
    133 
    134     handler->onMessageReceived(msg);
    135 }
    136 
    137 sp<ALooper> ALooperRoster::findLooper(ALooper::handler_id handlerID) {
    138     Mutex::Autolock autoLock(mLock);
    139 
    140     ssize_t index = mHandlers.indexOfKey(handlerID);
    141 
    142     if (index < 0) {
    143         return NULL;
    144     }
    145 
    146     sp<ALooper> looper = mHandlers.valueAt(index).mLooper.promote();
    147 
    148     if (looper == NULL) {
    149         mHandlers.removeItemsAt(index);
    150         return NULL;
    151     }
    152 
    153     return looper;
    154 }
    155 
    156 status_t ALooperRoster::postAndAwaitResponse(
    157         const sp<AMessage> &msg, sp<AMessage> *response) {
    158     Mutex::Autolock autoLock(mLock);
    159 
    160     uint32_t replyID = mNextReplyID++;
    161 
    162     msg->setInt32("replyID", replyID);
    163 
    164     status_t err = postMessage_l(msg, 0 /* delayUs */);
    165 
    166     if (err != OK) {
    167         response->clear();
    168         return err;
    169     }
    170 
    171     ssize_t index;
    172     while ((index = mReplies.indexOfKey(replyID)) < 0) {
    173         mRepliesCondition.wait(mLock);
    174     }
    175 
    176     *response = mReplies.valueAt(index);
    177     mReplies.removeItemsAt(index);
    178 
    179     return OK;
    180 }
    181 
    182 void ALooperRoster::postReply(uint32_t replyID, const sp<AMessage> &reply) {
    183     Mutex::Autolock autoLock(mLock);
    184 
    185     CHECK(mReplies.indexOfKey(replyID) < 0);
    186     mReplies.add(replyID, reply);
    187     mRepliesCondition.broadcast();
    188 }
    189 
    190 }  // namespace android
    191