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