1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker * Copyright (C) 2010 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker *
4*ec779b8eSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker *
8*ec779b8eSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker *
10*ec779b8eSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker */
16*ec779b8eSAndroid Build Coastguard Worker
17*ec779b8eSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
18*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "ALooperRoster"
19*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
20*ec779b8eSAndroid Build Coastguard Worker #include <utils/String8.h>
21*ec779b8eSAndroid Build Coastguard Worker
22*ec779b8eSAndroid Build Coastguard Worker #include <inttypes.h>
23*ec779b8eSAndroid Build Coastguard Worker
24*ec779b8eSAndroid Build Coastguard Worker #include "ALooperRoster.h"
25*ec779b8eSAndroid Build Coastguard Worker
26*ec779b8eSAndroid Build Coastguard Worker #include "ADebug.h"
27*ec779b8eSAndroid Build Coastguard Worker #include "AHandler.h"
28*ec779b8eSAndroid Build Coastguard Worker #include "AMessage.h"
29*ec779b8eSAndroid Build Coastguard Worker
30*ec779b8eSAndroid Build Coastguard Worker namespace android {
31*ec779b8eSAndroid Build Coastguard Worker
32*ec779b8eSAndroid Build Coastguard Worker static bool verboseStats = false;
33*ec779b8eSAndroid Build Coastguard Worker
ALooperRoster()34*ec779b8eSAndroid Build Coastguard Worker ALooperRoster::ALooperRoster()
35*ec779b8eSAndroid Build Coastguard Worker : mNextHandlerID(1) {
36*ec779b8eSAndroid Build Coastguard Worker }
37*ec779b8eSAndroid Build Coastguard Worker
registerHandler(const sp<ALooper> & looper,const sp<AHandler> & handler)38*ec779b8eSAndroid Build Coastguard Worker ALooper::handler_id ALooperRoster::registerHandler(
39*ec779b8eSAndroid Build Coastguard Worker const sp<ALooper> &looper, const sp<AHandler> &handler) {
40*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
41*ec779b8eSAndroid Build Coastguard Worker
42*ec779b8eSAndroid Build Coastguard Worker if (handler->id() != 0) {
43*ec779b8eSAndroid Build Coastguard Worker CHECK(!"A handler must only be registered once.");
44*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
45*ec779b8eSAndroid Build Coastguard Worker }
46*ec779b8eSAndroid Build Coastguard Worker
47*ec779b8eSAndroid Build Coastguard Worker HandlerInfo info;
48*ec779b8eSAndroid Build Coastguard Worker info.mLooper = looper;
49*ec779b8eSAndroid Build Coastguard Worker info.mHandler = handler;
50*ec779b8eSAndroid Build Coastguard Worker ALooper::handler_id handlerID = mNextHandlerID++;
51*ec779b8eSAndroid Build Coastguard Worker mHandlers.add(handlerID, info);
52*ec779b8eSAndroid Build Coastguard Worker
53*ec779b8eSAndroid Build Coastguard Worker handler->setID(handlerID, looper);
54*ec779b8eSAndroid Build Coastguard Worker
55*ec779b8eSAndroid Build Coastguard Worker return handlerID;
56*ec779b8eSAndroid Build Coastguard Worker }
57*ec779b8eSAndroid Build Coastguard Worker
unregisterHandler(ALooper::handler_id handlerID)58*ec779b8eSAndroid Build Coastguard Worker void ALooperRoster::unregisterHandler(ALooper::handler_id handlerID) {
59*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
60*ec779b8eSAndroid Build Coastguard Worker
61*ec779b8eSAndroid Build Coastguard Worker ssize_t index = mHandlers.indexOfKey(handlerID);
62*ec779b8eSAndroid Build Coastguard Worker
63*ec779b8eSAndroid Build Coastguard Worker if (index < 0) {
64*ec779b8eSAndroid Build Coastguard Worker return;
65*ec779b8eSAndroid Build Coastguard Worker }
66*ec779b8eSAndroid Build Coastguard Worker
67*ec779b8eSAndroid Build Coastguard Worker const HandlerInfo &info = mHandlers.valueAt(index);
68*ec779b8eSAndroid Build Coastguard Worker
69*ec779b8eSAndroid Build Coastguard Worker sp<AHandler> handler = info.mHandler.promote();
70*ec779b8eSAndroid Build Coastguard Worker
71*ec779b8eSAndroid Build Coastguard Worker if (handler != NULL) {
72*ec779b8eSAndroid Build Coastguard Worker handler->setID(0, NULL);
73*ec779b8eSAndroid Build Coastguard Worker }
74*ec779b8eSAndroid Build Coastguard Worker
75*ec779b8eSAndroid Build Coastguard Worker mHandlers.removeItemsAt(index);
76*ec779b8eSAndroid Build Coastguard Worker }
77*ec779b8eSAndroid Build Coastguard Worker
unregisterStaleHandlers()78*ec779b8eSAndroid Build Coastguard Worker void ALooperRoster::unregisterStaleHandlers() {
79*ec779b8eSAndroid Build Coastguard Worker
80*ec779b8eSAndroid Build Coastguard Worker Vector<sp<ALooper> > activeLoopers;
81*ec779b8eSAndroid Build Coastguard Worker {
82*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
83*ec779b8eSAndroid Build Coastguard Worker
84*ec779b8eSAndroid Build Coastguard Worker for (size_t i = mHandlers.size(); i > 0;) {
85*ec779b8eSAndroid Build Coastguard Worker i--;
86*ec779b8eSAndroid Build Coastguard Worker const HandlerInfo &info = mHandlers.valueAt(i);
87*ec779b8eSAndroid Build Coastguard Worker
88*ec779b8eSAndroid Build Coastguard Worker sp<ALooper> looper = info.mLooper.promote();
89*ec779b8eSAndroid Build Coastguard Worker if (looper == NULL) {
90*ec779b8eSAndroid Build Coastguard Worker ALOGV("Unregistering stale handler %d", mHandlers.keyAt(i));
91*ec779b8eSAndroid Build Coastguard Worker mHandlers.removeItemsAt(i);
92*ec779b8eSAndroid Build Coastguard Worker } else {
93*ec779b8eSAndroid Build Coastguard Worker // At this point 'looper' might be the only sp<> keeping
94*ec779b8eSAndroid Build Coastguard Worker // the object alive. To prevent it from going out of scope
95*ec779b8eSAndroid Build Coastguard Worker // and having ~ALooper call this method again recursively
96*ec779b8eSAndroid Build Coastguard Worker // and then deadlocking because of the Autolock above, add
97*ec779b8eSAndroid Build Coastguard Worker // it to a Vector which will go out of scope after the lock
98*ec779b8eSAndroid Build Coastguard Worker // has been released.
99*ec779b8eSAndroid Build Coastguard Worker activeLoopers.add(looper);
100*ec779b8eSAndroid Build Coastguard Worker }
101*ec779b8eSAndroid Build Coastguard Worker }
102*ec779b8eSAndroid Build Coastguard Worker }
103*ec779b8eSAndroid Build Coastguard Worker }
104*ec779b8eSAndroid Build Coastguard Worker
makeFourCC(uint32_t fourcc,char * s,size_t bufsz)105*ec779b8eSAndroid Build Coastguard Worker static void makeFourCC(uint32_t fourcc, char *s, size_t bufsz) {
106*ec779b8eSAndroid Build Coastguard Worker s[0] = (fourcc >> 24) & 0xff;
107*ec779b8eSAndroid Build Coastguard Worker if (s[0]) {
108*ec779b8eSAndroid Build Coastguard Worker s[1] = (fourcc >> 16) & 0xff;
109*ec779b8eSAndroid Build Coastguard Worker s[2] = (fourcc >> 8) & 0xff;
110*ec779b8eSAndroid Build Coastguard Worker s[3] = fourcc & 0xff;
111*ec779b8eSAndroid Build Coastguard Worker s[4] = 0;
112*ec779b8eSAndroid Build Coastguard Worker } else {
113*ec779b8eSAndroid Build Coastguard Worker snprintf(s, bufsz, "%u", fourcc);
114*ec779b8eSAndroid Build Coastguard Worker }
115*ec779b8eSAndroid Build Coastguard Worker }
116*ec779b8eSAndroid Build Coastguard Worker
dump(int fd,const Vector<String16> & args)117*ec779b8eSAndroid Build Coastguard Worker void ALooperRoster::dump(int fd, const Vector<String16>& args) {
118*ec779b8eSAndroid Build Coastguard Worker bool clear = false;
119*ec779b8eSAndroid Build Coastguard Worker bool oldVerbose = verboseStats;
120*ec779b8eSAndroid Build Coastguard Worker for (size_t i = 0; i < args.size(); i++) {
121*ec779b8eSAndroid Build Coastguard Worker if (args[i] == String16("-c")) {
122*ec779b8eSAndroid Build Coastguard Worker clear = true;
123*ec779b8eSAndroid Build Coastguard Worker } else if (args[i] == String16("-von")) {
124*ec779b8eSAndroid Build Coastguard Worker verboseStats = true;
125*ec779b8eSAndroid Build Coastguard Worker } else if (args[i] == String16("-voff")) {
126*ec779b8eSAndroid Build Coastguard Worker verboseStats = false;
127*ec779b8eSAndroid Build Coastguard Worker }
128*ec779b8eSAndroid Build Coastguard Worker }
129*ec779b8eSAndroid Build Coastguard Worker String8 s;
130*ec779b8eSAndroid Build Coastguard Worker if (verboseStats && !oldVerbose) {
131*ec779b8eSAndroid Build Coastguard Worker s.append("(verbose stats collection enabled, stats will be cleared)\n");
132*ec779b8eSAndroid Build Coastguard Worker }
133*ec779b8eSAndroid Build Coastguard Worker
134*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock autoLock(mLock);
135*ec779b8eSAndroid Build Coastguard Worker size_t n = mHandlers.size();
136*ec779b8eSAndroid Build Coastguard Worker s.appendFormat(" %zu registered handlers:\n", n);
137*ec779b8eSAndroid Build Coastguard Worker
138*ec779b8eSAndroid Build Coastguard Worker for (size_t i = 0; i < n; i++) {
139*ec779b8eSAndroid Build Coastguard Worker s.appendFormat(" %d: ", mHandlers.keyAt(i));
140*ec779b8eSAndroid Build Coastguard Worker HandlerInfo &info = mHandlers.editValueAt(i);
141*ec779b8eSAndroid Build Coastguard Worker sp<ALooper> looper = info.mLooper.promote();
142*ec779b8eSAndroid Build Coastguard Worker if (looper != NULL) {
143*ec779b8eSAndroid Build Coastguard Worker s.append(looper->getName());
144*ec779b8eSAndroid Build Coastguard Worker sp<AHandler> handler = info.mHandler.promote();
145*ec779b8eSAndroid Build Coastguard Worker if (handler != NULL) {
146*ec779b8eSAndroid Build Coastguard Worker bool deliveringMessages;
147*ec779b8eSAndroid Build Coastguard Worker uint32_t currentMessageWhat;
148*ec779b8eSAndroid Build Coastguard Worker int64_t currentDeliveryDurationUs;
149*ec779b8eSAndroid Build Coastguard Worker handler->getDeliveryStatus(deliveringMessages,
150*ec779b8eSAndroid Build Coastguard Worker currentMessageWhat,
151*ec779b8eSAndroid Build Coastguard Worker currentDeliveryDurationUs);
152*ec779b8eSAndroid Build Coastguard Worker handler->mVerboseStats = verboseStats;
153*ec779b8eSAndroid Build Coastguard Worker s.appendFormat(": %" PRIu64 " messages processed, delivering "
154*ec779b8eSAndroid Build Coastguard Worker "%d, current msg %" PRIu32 ", current msg "
155*ec779b8eSAndroid Build Coastguard Worker "durationUs %" PRIu64 "",
156*ec779b8eSAndroid Build Coastguard Worker handler->mMessageCounter,
157*ec779b8eSAndroid Build Coastguard Worker deliveringMessages,
158*ec779b8eSAndroid Build Coastguard Worker currentMessageWhat,
159*ec779b8eSAndroid Build Coastguard Worker currentDeliveryDurationUs);
160*ec779b8eSAndroid Build Coastguard Worker if (verboseStats) {
161*ec779b8eSAndroid Build Coastguard Worker for (size_t j = 0; j < handler->mMessages.size(); j++) {
162*ec779b8eSAndroid Build Coastguard Worker char fourcc[15];
163*ec779b8eSAndroid Build Coastguard Worker makeFourCC(handler->mMessages.keyAt(j), fourcc, sizeof(fourcc));
164*ec779b8eSAndroid Build Coastguard Worker s.appendFormat("\n %s: %u",
165*ec779b8eSAndroid Build Coastguard Worker fourcc,
166*ec779b8eSAndroid Build Coastguard Worker handler->mMessages.valueAt(j));
167*ec779b8eSAndroid Build Coastguard Worker }
168*ec779b8eSAndroid Build Coastguard Worker } else {
169*ec779b8eSAndroid Build Coastguard Worker handler->mMessages.clear();
170*ec779b8eSAndroid Build Coastguard Worker }
171*ec779b8eSAndroid Build Coastguard Worker if (clear || (verboseStats && !oldVerbose)) {
172*ec779b8eSAndroid Build Coastguard Worker handler->mMessageCounter = 0;
173*ec779b8eSAndroid Build Coastguard Worker handler->mMessages.clear();
174*ec779b8eSAndroid Build Coastguard Worker }
175*ec779b8eSAndroid Build Coastguard Worker } else {
176*ec779b8eSAndroid Build Coastguard Worker s.append(": <stale handler>");
177*ec779b8eSAndroid Build Coastguard Worker }
178*ec779b8eSAndroid Build Coastguard Worker } else {
179*ec779b8eSAndroid Build Coastguard Worker s.append("<stale>");
180*ec779b8eSAndroid Build Coastguard Worker }
181*ec779b8eSAndroid Build Coastguard Worker s.append("\n");
182*ec779b8eSAndroid Build Coastguard Worker }
183*ec779b8eSAndroid Build Coastguard Worker (void)write(fd, s.c_str(), s.size());
184*ec779b8eSAndroid Build Coastguard Worker }
185*ec779b8eSAndroid Build Coastguard Worker
186*ec779b8eSAndroid Build Coastguard Worker } // namespace android
187