ALooperRoster.cpp revision 5804a76ac5f9f3c311f1bbbcc5ebdc8f8568ae14
172961230a5890071bcca436eb5630172ce84ec41Andreas Huber/*
272961230a5890071bcca436eb5630172ce84ec41Andreas Huber * Copyright (C) 2010 The Android Open Source Project
372961230a5890071bcca436eb5630172ce84ec41Andreas Huber *
472961230a5890071bcca436eb5630172ce84ec41Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
572961230a5890071bcca436eb5630172ce84ec41Andreas Huber * you may not use this file except in compliance with the License.
672961230a5890071bcca436eb5630172ce84ec41Andreas Huber * You may obtain a copy of the License at
772961230a5890071bcca436eb5630172ce84ec41Andreas Huber *
872961230a5890071bcca436eb5630172ce84ec41Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
972961230a5890071bcca436eb5630172ce84ec41Andreas Huber *
1072961230a5890071bcca436eb5630172ce84ec41Andreas Huber * Unless required by applicable law or agreed to in writing, software
1172961230a5890071bcca436eb5630172ce84ec41Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
1272961230a5890071bcca436eb5630172ce84ec41Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1372961230a5890071bcca436eb5630172ce84ec41Andreas Huber * See the License for the specific language governing permissions and
1472961230a5890071bcca436eb5630172ce84ec41Andreas Huber * limitations under the License.
1572961230a5890071bcca436eb5630172ce84ec41Andreas Huber */
1672961230a5890071bcca436eb5630172ce84ec41Andreas Huber
1772961230a5890071bcca436eb5630172ce84ec41Andreas Huber//#define LOG_NDEBUG 0
1872961230a5890071bcca436eb5630172ce84ec41Andreas Huber#define LOG_TAG "ALooperRoster"
1972961230a5890071bcca436eb5630172ce84ec41Andreas Huber#include <utils/Log.h>
20f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen#include <utils/String8.h>
2172961230a5890071bcca436eb5630172ce84ec41Andreas Huber
2272961230a5890071bcca436eb5630172ce84ec41Andreas Huber#include "ALooperRoster.h"
2372961230a5890071bcca436eb5630172ce84ec41Andreas Huber
2472961230a5890071bcca436eb5630172ce84ec41Andreas Huber#include "ADebug.h"
2572961230a5890071bcca436eb5630172ce84ec41Andreas Huber#include "AHandler.h"
2672961230a5890071bcca436eb5630172ce84ec41Andreas Huber#include "AMessage.h"
2772961230a5890071bcca436eb5630172ce84ec41Andreas Huber
2872961230a5890071bcca436eb5630172ce84ec41Andreas Hubernamespace android {
2972961230a5890071bcca436eb5630172ce84ec41Andreas Huber
30f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissenstatic bool verboseStats = false;
31f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen
3272961230a5890071bcca436eb5630172ce84ec41Andreas HuberALooperRoster::ALooperRoster()
335df775d2f509c76e76a46615fca83dba95299f6eAndreas Huber    : mNextHandlerID(1),
345df775d2f509c76e76a46615fca83dba95299f6eAndreas Huber      mNextReplyID(1) {
3572961230a5890071bcca436eb5630172ce84ec41Andreas Huber}
3672961230a5890071bcca436eb5630172ce84ec41Andreas Huber
3772961230a5890071bcca436eb5630172ce84ec41Andreas HuberALooper::handler_id ALooperRoster::registerHandler(
3872961230a5890071bcca436eb5630172ce84ec41Andreas Huber        const sp<ALooper> looper, const sp<AHandler> &handler) {
3972961230a5890071bcca436eb5630172ce84ec41Andreas Huber    Mutex::Autolock autoLock(mLock);
4072961230a5890071bcca436eb5630172ce84ec41Andreas Huber
4172961230a5890071bcca436eb5630172ce84ec41Andreas Huber    if (handler->id() != 0) {
4272961230a5890071bcca436eb5630172ce84ec41Andreas Huber        CHECK(!"A handler must only be registered once.");
4372961230a5890071bcca436eb5630172ce84ec41Andreas Huber        return INVALID_OPERATION;
4472961230a5890071bcca436eb5630172ce84ec41Andreas Huber    }
4572961230a5890071bcca436eb5630172ce84ec41Andreas Huber
4672961230a5890071bcca436eb5630172ce84ec41Andreas Huber    HandlerInfo info;
4772961230a5890071bcca436eb5630172ce84ec41Andreas Huber    info.mLooper = looper;
4872961230a5890071bcca436eb5630172ce84ec41Andreas Huber    info.mHandler = handler;
4972961230a5890071bcca436eb5630172ce84ec41Andreas Huber    ALooper::handler_id handlerID = mNextHandlerID++;
5072961230a5890071bcca436eb5630172ce84ec41Andreas Huber    mHandlers.add(handlerID, info);
5172961230a5890071bcca436eb5630172ce84ec41Andreas Huber
525804a76ac5f9f3c311f1bbbcc5ebdc8f8568ae14Lajos Molnar    handler->setID(handlerID, looper);
5372961230a5890071bcca436eb5630172ce84ec41Andreas Huber
5472961230a5890071bcca436eb5630172ce84ec41Andreas Huber    return handlerID;
5572961230a5890071bcca436eb5630172ce84ec41Andreas Huber}
5672961230a5890071bcca436eb5630172ce84ec41Andreas Huber
5772961230a5890071bcca436eb5630172ce84ec41Andreas Hubervoid ALooperRoster::unregisterHandler(ALooper::handler_id handlerID) {
5872961230a5890071bcca436eb5630172ce84ec41Andreas Huber    Mutex::Autolock autoLock(mLock);
5972961230a5890071bcca436eb5630172ce84ec41Andreas Huber
6072961230a5890071bcca436eb5630172ce84ec41Andreas Huber    ssize_t index = mHandlers.indexOfKey(handlerID);
61f200777290d2e3e8b580c512cc0808eae9790705Andreas Huber
62f200777290d2e3e8b580c512cc0808eae9790705Andreas Huber    if (index < 0) {
63f200777290d2e3e8b580c512cc0808eae9790705Andreas Huber        return;
64f200777290d2e3e8b580c512cc0808eae9790705Andreas Huber    }
6572961230a5890071bcca436eb5630172ce84ec41Andreas Huber
6672961230a5890071bcca436eb5630172ce84ec41Andreas Huber    const HandlerInfo &info = mHandlers.valueAt(index);
6711cc270ac5fd522c9e6491a7933516a96da4f62eAndreas Huber
6811cc270ac5fd522c9e6491a7933516a96da4f62eAndreas Huber    sp<AHandler> handler = info.mHandler.promote();
6911cc270ac5fd522c9e6491a7933516a96da4f62eAndreas Huber
7011cc270ac5fd522c9e6491a7933516a96da4f62eAndreas Huber    if (handler != NULL) {
715804a76ac5f9f3c311f1bbbcc5ebdc8f8568ae14Lajos Molnar        handler->setID(0, NULL);
7211cc270ac5fd522c9e6491a7933516a96da4f62eAndreas Huber    }
7372961230a5890071bcca436eb5630172ce84ec41Andreas Huber
7472961230a5890071bcca436eb5630172ce84ec41Andreas Huber    mHandlers.removeItemsAt(index);
7572961230a5890071bcca436eb5630172ce84ec41Andreas Huber}
7672961230a5890071bcca436eb5630172ce84ec41Andreas Huber
7730873bfd08255e2c4e98ff5732ffff2838772617Andreas Hubervoid ALooperRoster::unregisterStaleHandlers() {
7830873bfd08255e2c4e98ff5732ffff2838772617Andreas Huber
7975c672fc376ef9b3ceff61a96513242b0e5ebd60Marco Nelissen    Vector<sp<ALooper> > activeLoopers;
8075c672fc376ef9b3ceff61a96513242b0e5ebd60Marco Nelissen    {
8175c672fc376ef9b3ceff61a96513242b0e5ebd60Marco Nelissen        Mutex::Autolock autoLock(mLock);
8275c672fc376ef9b3ceff61a96513242b0e5ebd60Marco Nelissen
8375c672fc376ef9b3ceff61a96513242b0e5ebd60Marco Nelissen        for (size_t i = mHandlers.size(); i-- > 0;) {
8475c672fc376ef9b3ceff61a96513242b0e5ebd60Marco Nelissen            const HandlerInfo &info = mHandlers.valueAt(i);
8575c672fc376ef9b3ceff61a96513242b0e5ebd60Marco Nelissen
8675c672fc376ef9b3ceff61a96513242b0e5ebd60Marco Nelissen            sp<ALooper> looper = info.mLooper.promote();
8775c672fc376ef9b3ceff61a96513242b0e5ebd60Marco Nelissen            if (looper == NULL) {
8875c672fc376ef9b3ceff61a96513242b0e5ebd60Marco Nelissen                ALOGV("Unregistering stale handler %d", mHandlers.keyAt(i));
8975c672fc376ef9b3ceff61a96513242b0e5ebd60Marco Nelissen                mHandlers.removeItemsAt(i);
9075c672fc376ef9b3ceff61a96513242b0e5ebd60Marco Nelissen            } else {
9175c672fc376ef9b3ceff61a96513242b0e5ebd60Marco Nelissen                // At this point 'looper' might be the only sp<> keeping
9275c672fc376ef9b3ceff61a96513242b0e5ebd60Marco Nelissen                // the object alive. To prevent it from going out of scope
9375c672fc376ef9b3ceff61a96513242b0e5ebd60Marco Nelissen                // and having ~ALooper call this method again recursively
9475c672fc376ef9b3ceff61a96513242b0e5ebd60Marco Nelissen                // and then deadlocking because of the Autolock above, add
9575c672fc376ef9b3ceff61a96513242b0e5ebd60Marco Nelissen                // it to a Vector which will go out of scope after the lock
9675c672fc376ef9b3ceff61a96513242b0e5ebd60Marco Nelissen                // has been released.
9775c672fc376ef9b3ceff61a96513242b0e5ebd60Marco Nelissen                activeLoopers.add(looper);
9875c672fc376ef9b3ceff61a96513242b0e5ebd60Marco Nelissen            }
9930873bfd08255e2c4e98ff5732ffff2838772617Andreas Huber        }
10030873bfd08255e2c4e98ff5732ffff2838772617Andreas Huber    }
10130873bfd08255e2c4e98ff5732ffff2838772617Andreas Huber}
10230873bfd08255e2c4e98ff5732ffff2838772617Andreas Huber
1035804a76ac5f9f3c311f1bbbcc5ebdc8f8568ae14Lajos Molnarvoid ALooperRoster::getHandlerAndLooper(
1045804a76ac5f9f3c311f1bbbcc5ebdc8f8568ae14Lajos Molnar        ALooper::handler_id handlerID, wp<AHandler> *handler, wp<ALooper> *looper) {
105e2b20987c2652a984d10520ef3542d50d91119c5Andreas Huber    Mutex::Autolock autoLock(mLock);
106e2b20987c2652a984d10520ef3542d50d91119c5Andreas Huber
107e2b20987c2652a984d10520ef3542d50d91119c5Andreas Huber    ssize_t index = mHandlers.indexOfKey(handlerID);
108e2b20987c2652a984d10520ef3542d50d91119c5Andreas Huber
109e2b20987c2652a984d10520ef3542d50d91119c5Andreas Huber    if (index < 0) {
1105804a76ac5f9f3c311f1bbbcc5ebdc8f8568ae14Lajos Molnar        handler->clear();
1115804a76ac5f9f3c311f1bbbcc5ebdc8f8568ae14Lajos Molnar        looper->clear();
1125804a76ac5f9f3c311f1bbbcc5ebdc8f8568ae14Lajos Molnar        return;
11311cc270ac5fd522c9e6491a7933516a96da4f62eAndreas Huber    }
11411cc270ac5fd522c9e6491a7933516a96da4f62eAndreas Huber
1155804a76ac5f9f3c311f1bbbcc5ebdc8f8568ae14Lajos Molnar    *handler = mHandlers.valueAt(index).mHandler;
1165804a76ac5f9f3c311f1bbbcc5ebdc8f8568ae14Lajos Molnar    *looper = mHandlers.valueAt(index).mLooper;
117e2b20987c2652a984d10520ef3542d50d91119c5Andreas Huber}
118e2b20987c2652a984d10520ef3542d50d91119c5Andreas Huber
1195df775d2f509c76e76a46615fca83dba95299f6eAndreas Huberstatus_t ALooperRoster::postAndAwaitResponse(
1205df775d2f509c76e76a46615fca83dba95299f6eAndreas Huber        const sp<AMessage> &msg, sp<AMessage> *response) {
1215df775d2f509c76e76a46615fca83dba95299f6eAndreas Huber    Mutex::Autolock autoLock(mLock);
1225df775d2f509c76e76a46615fca83dba95299f6eAndreas Huber
1235df775d2f509c76e76a46615fca83dba95299f6eAndreas Huber    uint32_t replyID = mNextReplyID++;
1245df775d2f509c76e76a46615fca83dba95299f6eAndreas Huber
1255df775d2f509c76e76a46615fca83dba95299f6eAndreas Huber    msg->setInt32("replyID", replyID);
1265df775d2f509c76e76a46615fca83dba95299f6eAndreas Huber
1275804a76ac5f9f3c311f1bbbcc5ebdc8f8568ae14Lajos Molnar    status_t err = msg->post(0 /* delayUs */);
1285804a76ac5f9f3c311f1bbbcc5ebdc8f8568ae14Lajos Molnar    if (err != OK) {
1295804a76ac5f9f3c311f1bbbcc5ebdc8f8568ae14Lajos Molnar        response->clear();
1305804a76ac5f9f3c311f1bbbcc5ebdc8f8568ae14Lajos Molnar        return err;
1315804a76ac5f9f3c311f1bbbcc5ebdc8f8568ae14Lajos Molnar    }
1325df775d2f509c76e76a46615fca83dba95299f6eAndreas Huber
1335df775d2f509c76e76a46615fca83dba95299f6eAndreas Huber    ssize_t index;
1345df775d2f509c76e76a46615fca83dba95299f6eAndreas Huber    while ((index = mReplies.indexOfKey(replyID)) < 0) {
1355df775d2f509c76e76a46615fca83dba95299f6eAndreas Huber        mRepliesCondition.wait(mLock);
1365df775d2f509c76e76a46615fca83dba95299f6eAndreas Huber    }
1375df775d2f509c76e76a46615fca83dba95299f6eAndreas Huber
1385df775d2f509c76e76a46615fca83dba95299f6eAndreas Huber    *response = mReplies.valueAt(index);
1395df775d2f509c76e76a46615fca83dba95299f6eAndreas Huber    mReplies.removeItemsAt(index);
1405df775d2f509c76e76a46615fca83dba95299f6eAndreas Huber
1415df775d2f509c76e76a46615fca83dba95299f6eAndreas Huber    return OK;
1425df775d2f509c76e76a46615fca83dba95299f6eAndreas Huber}
1435df775d2f509c76e76a46615fca83dba95299f6eAndreas Huber
1445df775d2f509c76e76a46615fca83dba95299f6eAndreas Hubervoid ALooperRoster::postReply(uint32_t replyID, const sp<AMessage> &reply) {
1455df775d2f509c76e76a46615fca83dba95299f6eAndreas Huber    Mutex::Autolock autoLock(mLock);
1465df775d2f509c76e76a46615fca83dba95299f6eAndreas Huber
1475df775d2f509c76e76a46615fca83dba95299f6eAndreas Huber    CHECK(mReplies.indexOfKey(replyID) < 0);
1485df775d2f509c76e76a46615fca83dba95299f6eAndreas Huber    mReplies.add(replyID, reply);
1495df775d2f509c76e76a46615fca83dba95299f6eAndreas Huber    mRepliesCondition.broadcast();
1505df775d2f509c76e76a46615fca83dba95299f6eAndreas Huber}
1515df775d2f509c76e76a46615fca83dba95299f6eAndreas Huber
152f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissenstatic void makeFourCC(uint32_t fourcc, char *s) {
153f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen    s[0] = (fourcc >> 24) & 0xff;
154f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen    if (s[0]) {
155f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen        s[1] = (fourcc >> 16) & 0xff;
156f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen        s[2] = (fourcc >> 8) & 0xff;
157f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen        s[3] = fourcc & 0xff;
158f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen        s[4] = 0;
159f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen    } else {
160f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen        sprintf(s, "%u", fourcc);
161f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen    }
162f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen}
163f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen
164f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissenvoid ALooperRoster::dump(int fd, const Vector<String16>& args) {
165f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen    bool clear = false;
166f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen    bool oldVerbose = verboseStats;
1675804a76ac5f9f3c311f1bbbcc5ebdc8f8568ae14Lajos Molnar    for (size_t i = 0; i < args.size(); i++) {
168f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen        if (args[i] == String16("-c")) {
169f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen            clear = true;
170f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen        } else if (args[i] == String16("-von")) {
171f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen            verboseStats = true;
172f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen        } else if (args[i] == String16("-voff")) {
173f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen            verboseStats = false;
174f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen        }
175f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen    }
176f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen    String8 s;
177f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen    if (verboseStats && !oldVerbose) {
178f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen        s.append("(verbose stats collection enabled, stats will be cleared)\n");
179f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen    }
180f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen
181f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen    Mutex::Autolock autoLock(mLock);
182f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen    size_t n = mHandlers.size();
1835804a76ac5f9f3c311f1bbbcc5ebdc8f8568ae14Lajos Molnar    s.appendFormat(" %zu registered handlers:\n", n);
184f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen
185f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen    for (size_t i = 0; i < n; i++) {
1865804a76ac5f9f3c311f1bbbcc5ebdc8f8568ae14Lajos Molnar        s.appendFormat("  %d: ", mHandlers.keyAt(i));
187f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen        HandlerInfo &info = mHandlers.editValueAt(i);
188f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen        sp<ALooper> looper = info.mLooper.promote();
189f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen        if (looper != NULL) {
1905804a76ac5f9f3c311f1bbbcc5ebdc8f8568ae14Lajos Molnar            s.append(looper->getName());
191f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen            sp<AHandler> handler = info.mHandler.promote();
192f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen            if (handler != NULL) {
1935804a76ac5f9f3c311f1bbbcc5ebdc8f8568ae14Lajos Molnar                handler->mVerboseStats = verboseStats;
194f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen                s.appendFormat(": %u messages processed", handler->mMessageCounter);
195f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen                if (verboseStats) {
196f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen                    for (size_t j = 0; j < handler->mMessages.size(); j++) {
197f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen                        char fourcc[15];
198f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen                        makeFourCC(handler->mMessages.keyAt(j), fourcc);
1995804a76ac5f9f3c311f1bbbcc5ebdc8f8568ae14Lajos Molnar                        s.appendFormat("\n    %s: %u",
200f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen                                fourcc,
201f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen                                handler->mMessages.valueAt(j));
202f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen                    }
203f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen                } else {
204f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen                    handler->mMessages.clear();
205f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen                }
206f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen                if (clear || (verboseStats && !oldVerbose)) {
207f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen                    handler->mMessageCounter = 0;
208f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen                    handler->mMessages.clear();
209f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen                }
210f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen            } else {
211f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen                s.append(": <stale handler>");
212f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen            }
213f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen        } else {
214f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen            s.append("<stale>");
215f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen        }
216f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen        s.append("\n");
217f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen    }
218f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen    write(fd, s.string(), s.size());
219f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen}
220f09611f2f33752afc28141e1bbaa897651c05d6fMarco Nelissen
22172961230a5890071bcca436eb5630172ce84ec41Andreas Huber}  // namespace android
222