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 #include <utils/String8.h>
     21 
     22 #include "ALooperRoster.h"
     23 
     24 #include "ADebug.h"
     25 #include "AHandler.h"
     26 #include "AMessage.h"
     27 
     28 namespace android {
     29 
     30 static bool verboseStats = false;
     31 
     32 ALooperRoster::ALooperRoster()
     33     : mNextHandlerID(1) {
     34 }
     35 
     36 ALooper::handler_id ALooperRoster::registerHandler(
     37         const sp<ALooper> &looper, const sp<AHandler> &handler) {
     38     Mutex::Autolock autoLock(mLock);
     39 
     40     if (handler->id() != 0) {
     41         CHECK(!"A handler must only be registered once.");
     42         return INVALID_OPERATION;
     43     }
     44 
     45     HandlerInfo info;
     46     info.mLooper = looper;
     47     info.mHandler = handler;
     48     ALooper::handler_id handlerID = mNextHandlerID++;
     49     mHandlers.add(handlerID, info);
     50 
     51     handler->setID(handlerID, looper);
     52 
     53     return handlerID;
     54 }
     55 
     56 void ALooperRoster::unregisterHandler(ALooper::handler_id handlerID) {
     57     Mutex::Autolock autoLock(mLock);
     58 
     59     ssize_t index = mHandlers.indexOfKey(handlerID);
     60 
     61     if (index < 0) {
     62         return;
     63     }
     64 
     65     const HandlerInfo &info = mHandlers.valueAt(index);
     66 
     67     sp<AHandler> handler = info.mHandler.promote();
     68 
     69     if (handler != NULL) {
     70         handler->setID(0, NULL);
     71     }
     72 
     73     mHandlers.removeItemsAt(index);
     74 }
     75 
     76 void ALooperRoster::unregisterStaleHandlers() {
     77 
     78     Vector<sp<ALooper> > activeLoopers;
     79     {
     80         Mutex::Autolock autoLock(mLock);
     81 
     82         for (size_t i = mHandlers.size(); i > 0;) {
     83             i--;
     84             const HandlerInfo &info = mHandlers.valueAt(i);
     85 
     86             sp<ALooper> looper = info.mLooper.promote();
     87             if (looper == NULL) {
     88                 ALOGV("Unregistering stale handler %d", mHandlers.keyAt(i));
     89                 mHandlers.removeItemsAt(i);
     90             } else {
     91                 // At this point 'looper' might be the only sp<> keeping
     92                 // the object alive. To prevent it from going out of scope
     93                 // and having ~ALooper call this method again recursively
     94                 // and then deadlocking because of the Autolock above, add
     95                 // it to a Vector which will go out of scope after the lock
     96                 // has been released.
     97                 activeLoopers.add(looper);
     98             }
     99         }
    100     }
    101 }
    102 
    103 static void makeFourCC(uint32_t fourcc, char *s, size_t bufsz) {
    104     s[0] = (fourcc >> 24) & 0xff;
    105     if (s[0]) {
    106         s[1] = (fourcc >> 16) & 0xff;
    107         s[2] = (fourcc >> 8) & 0xff;
    108         s[3] = fourcc & 0xff;
    109         s[4] = 0;
    110     } else {
    111         snprintf(s, bufsz, "%u", fourcc);
    112     }
    113 }
    114 
    115 void ALooperRoster::dump(int fd, const Vector<String16>& args) {
    116     bool clear = false;
    117     bool oldVerbose = verboseStats;
    118     for (size_t i = 0; i < args.size(); i++) {
    119         if (args[i] == String16("-c")) {
    120             clear = true;
    121         } else if (args[i] == String16("-von")) {
    122             verboseStats = true;
    123         } else if (args[i] == String16("-voff")) {
    124             verboseStats = false;
    125         }
    126     }
    127     String8 s;
    128     if (verboseStats && !oldVerbose) {
    129         s.append("(verbose stats collection enabled, stats will be cleared)\n");
    130     }
    131 
    132     Mutex::Autolock autoLock(mLock);
    133     size_t n = mHandlers.size();
    134     s.appendFormat(" %zu registered handlers:\n", n);
    135 
    136     for (size_t i = 0; i < n; i++) {
    137         s.appendFormat("  %d: ", mHandlers.keyAt(i));
    138         HandlerInfo &info = mHandlers.editValueAt(i);
    139         sp<ALooper> looper = info.mLooper.promote();
    140         if (looper != NULL) {
    141             s.append(looper->getName());
    142             sp<AHandler> handler = info.mHandler.promote();
    143             if (handler != NULL) {
    144                 handler->mVerboseStats = verboseStats;
    145                 s.appendFormat(": %u messages processed", handler->mMessageCounter);
    146                 if (verboseStats) {
    147                     for (size_t j = 0; j < handler->mMessages.size(); j++) {
    148                         char fourcc[15];
    149                         makeFourCC(handler->mMessages.keyAt(j), fourcc, sizeof(fourcc));
    150                         s.appendFormat("\n    %s: %u",
    151                                 fourcc,
    152                                 handler->mMessages.valueAt(j));
    153                     }
    154                 } else {
    155                     handler->mMessages.clear();
    156                 }
    157                 if (clear || (verboseStats && !oldVerbose)) {
    158                     handler->mMessageCounter = 0;
    159                     handler->mMessages.clear();
    160                 }
    161             } else {
    162                 s.append(": <stale handler>");
    163             }
    164         } else {
    165             s.append("<stale>");
    166         }
    167         s.append("\n");
    168     }
    169     write(fd, s.string(), s.size());
    170 }
    171 
    172 }  // namespace android
    173