ALooperRoster.cpp revision 11cc270ac5fd522c9e6491a7933516a96da4f62e
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
27namespace android {
28
29ALooperRoster::ALooperRoster()
30    : mNextHandlerID(1) {
31}
32
33ALooper::handler_id ALooperRoster::registerHandler(
34        const sp<ALooper> looper, const sp<AHandler> &handler) {
35    Mutex::Autolock autoLock(mLock);
36
37    if (handler->id() != 0) {
38        CHECK(!"A handler must only be registered once.");
39        return INVALID_OPERATION;
40    }
41
42    HandlerInfo info;
43    info.mLooper = looper;
44    info.mHandler = handler;
45    ALooper::handler_id handlerID = mNextHandlerID++;
46    mHandlers.add(handlerID, info);
47
48    handler->setID(handlerID);
49
50    return handlerID;
51}
52
53void ALooperRoster::unregisterHandler(ALooper::handler_id handlerID) {
54    Mutex::Autolock autoLock(mLock);
55
56    ssize_t index = mHandlers.indexOfKey(handlerID);
57    CHECK_GE(index, 0);
58
59    const HandlerInfo &info = mHandlers.valueAt(index);
60
61    sp<AHandler> handler = info.mHandler.promote();
62
63    if (handler != NULL) {
64        handler->setID(0);
65    }
66
67    mHandlers.removeItemsAt(index);
68}
69
70void ALooperRoster::postMessage(
71        const sp<AMessage> &msg, int64_t delayUs) {
72    Mutex::Autolock autoLock(mLock);
73
74    ssize_t index = mHandlers.indexOfKey(msg->target());
75
76    if (index < 0) {
77        LOG(WARNING) << "failed to post message. Target handler not registered.";
78        return;
79    }
80
81    const HandlerInfo &info = mHandlers.valueAt(index);
82
83    sp<ALooper> looper = info.mLooper.promote();
84
85    if (looper == NULL) {
86        LOG(WARNING) << "failed to post message. "
87                        "Target handler still registered, but object gone.";
88
89        mHandlers.removeItemsAt(index);
90        return;
91    }
92
93    looper->post(msg, delayUs);
94}
95
96void ALooperRoster::deliverMessage(const sp<AMessage> &msg) {
97    sp<AHandler> handler;
98
99    {
100        Mutex::Autolock autoLock(mLock);
101
102        ssize_t index = mHandlers.indexOfKey(msg->target());
103
104        if (index < 0) {
105            LOG(WARNING) << "failed to deliver message. "
106                         << "Target handler not registered.";
107            return;
108        }
109
110        const HandlerInfo &info = mHandlers.valueAt(index);
111        handler = info.mHandler.promote();
112
113        if (handler == NULL) {
114            LOG(WARNING) << "failed to deliver message. "
115                            "Target handler registered, but object gone.";
116
117            mHandlers.removeItemsAt(index);
118            return;
119        }
120    }
121
122    handler->onMessageReceived(msg);
123}
124
125sp<ALooper> ALooperRoster::findLooper(ALooper::handler_id handlerID) {
126    Mutex::Autolock autoLock(mLock);
127
128    ssize_t index = mHandlers.indexOfKey(handlerID);
129
130    if (index < 0) {
131        return NULL;
132    }
133
134    sp<ALooper> looper = mHandlers.valueAt(index).mLooper.promote();
135
136    if (looper == NULL) {
137        mHandlers.removeItemsAt(index);
138        return NULL;
139    }
140
141    return looper;
142}
143
144}  // namespace android
145