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