ALooperRoster.cpp revision d68cda472a3646966a203338ccac04f0783293b7
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
58    if (index < 0) {
59        return;
60    }
61
62    const HandlerInfo &info = mHandlers.valueAt(index);
63
64    sp<AHandler> handler = info.mHandler.promote();
65
66    if (handler != NULL) {
67        handler->setID(0);
68    }
69
70    mHandlers.removeItemsAt(index);
71}
72
73void ALooperRoster::postMessage(
74        const sp<AMessage> &msg, int64_t delayUs) {
75    Mutex::Autolock autoLock(mLock);
76
77    ssize_t index = mHandlers.indexOfKey(msg->target());
78
79    if (index < 0) {
80        LOGW("failed to post message. Target handler not registered.");
81        return;
82    }
83
84    const HandlerInfo &info = mHandlers.valueAt(index);
85
86    sp<ALooper> looper = info.mLooper.promote();
87
88    if (looper == NULL) {
89        LOGW("failed to post message. "
90             "Target handler %d still registered, but object gone.",
91             msg->target());
92
93        mHandlers.removeItemsAt(index);
94        return;
95    }
96
97    looper->post(msg, delayUs);
98}
99
100void ALooperRoster::deliverMessage(const sp<AMessage> &msg) {
101    sp<AHandler> handler;
102
103    {
104        Mutex::Autolock autoLock(mLock);
105
106        ssize_t index = mHandlers.indexOfKey(msg->target());
107
108        if (index < 0) {
109            LOGW("failed to deliver message. Target handler not registered.");
110            return;
111        }
112
113        const HandlerInfo &info = mHandlers.valueAt(index);
114        handler = info.mHandler.promote();
115
116        if (handler == NULL) {
117            LOGW("failed to deliver message. "
118                 "Target handler %d registered, but object gone.",
119                 msg->target());
120
121            mHandlers.removeItemsAt(index);
122            return;
123        }
124    }
125
126    handler->onMessageReceived(msg);
127}
128
129sp<ALooper> ALooperRoster::findLooper(ALooper::handler_id handlerID) {
130    Mutex::Autolock autoLock(mLock);
131
132    ssize_t index = mHandlers.indexOfKey(handlerID);
133
134    if (index < 0) {
135        return NULL;
136    }
137
138    sp<ALooper> looper = mHandlers.valueAt(index).mLooper.promote();
139
140    if (looper == NULL) {
141        mHandlers.removeItemsAt(index);
142        return NULL;
143    }
144
145    return looper;
146}
147
148}  // namespace android
149