ALooperRoster.cpp revision 6e4c5c499999c04c2477b987f9e64f3ff2bf1a06
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        LOGW("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        LOGW("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            LOGW("failed to deliver message. Target handler not registered.");
106            return;
107        }
108
109        const HandlerInfo &info = mHandlers.valueAt(index);
110        handler = info.mHandler.promote();
111
112        if (handler == NULL) {
113            LOGW("failed to deliver message. "
114                 "Target handler registered, but object gone.");
115
116            mHandlers.removeItemsAt(index);
117            return;
118        }
119    }
120
121    handler->onMessageReceived(msg);
122}
123
124sp<ALooper> ALooperRoster::findLooper(ALooper::handler_id handlerID) {
125    Mutex::Autolock autoLock(mLock);
126
127    ssize_t index = mHandlers.indexOfKey(handlerID);
128
129    if (index < 0) {
130        return NULL;
131    }
132
133    sp<ALooper> looper = mHandlers.valueAt(index).mLooper.promote();
134
135    if (looper == NULL) {
136        mHandlers.removeItemsAt(index);
137        return NULL;
138    }
139
140    return looper;
141}
142
143}  // namespace android
144