blob: 8a74d5d8a99f37755b4301060392e3c9e6a94246 [file] [log] [blame]
Chong Zhangacb33502020-04-20 11:04:48 -07001/*
2 * Copyright (C) 2020 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
Chong Zhang75222182020-04-29 14:43:42 -070017//#define LOG_NDEBUG 0
Chong Zhangacb33502020-04-20 11:04:48 -070018#define LOG_TAG "TranscodingUidPolicy"
19
Chong Zhang97d367b2020-09-16 12:53:14 -070020#include <android/binder_manager.h>
21#include <android/binder_process.h>
Chong Zhangacb33502020-04-20 11:04:48 -070022#include <binder/ActivityManager.h>
23#include <cutils/misc.h> // FIRST_APPLICATION_UID
Chong Zhangc37bdfe2020-10-06 13:54:09 -070024#include <cutils/multiuser.h>
Chong Zhangacb33502020-04-20 11:04:48 -070025#include <inttypes.h>
26#include <media/TranscodingUidPolicy.h>
27#include <utils/Log.h>
28
29#include <utility>
30
31namespace android {
32
33constexpr static uid_t OFFLINE_UID = -1;
34constexpr static const char* kTranscodingTag = "transcoding";
35
36struct TranscodingUidPolicy::UidObserver : public BnUidObserver,
37 public virtual IBinder::DeathRecipient {
38 explicit UidObserver(TranscodingUidPolicy* owner) : mOwner(owner) {}
39
40 // IUidObserver
41 void onUidGone(uid_t uid, bool disabled) override;
42 void onUidActive(uid_t uid) override;
43 void onUidIdle(uid_t uid, bool disabled) override;
44 void onUidStateChanged(uid_t uid, int32_t procState, int64_t procStateSeq,
45 int32_t capability) override;
46
47 // IBinder::DeathRecipient implementation
48 void binderDied(const wp<IBinder>& who) override;
49
50 TranscodingUidPolicy* mOwner;
51};
52
53void TranscodingUidPolicy::UidObserver::onUidGone(uid_t uid __unused, bool disabled __unused) {}
54
55void TranscodingUidPolicy::UidObserver::onUidActive(uid_t uid __unused) {}
56
57void TranscodingUidPolicy::UidObserver::onUidIdle(uid_t uid __unused, bool disabled __unused) {}
58
59void TranscodingUidPolicy::UidObserver::onUidStateChanged(uid_t uid, int32_t procState,
60 int64_t procStateSeq __unused,
61 int32_t capability __unused) {
62 mOwner->onUidStateChanged(uid, procState);
63}
64
65void TranscodingUidPolicy::UidObserver::binderDied(const wp<IBinder>& /*who*/) {
66 ALOGW("TranscodingUidPolicy: ActivityManager has died");
67 // TODO(chz): this is a rare event (since if the AMS is dead, the system is
68 // probably dead as well). But we should try to reconnect.
69 mOwner->setUidObserverRegistered(false);
70}
71
72////////////////////////////////////////////////////////////////////////////
73
74TranscodingUidPolicy::TranscodingUidPolicy()
75 : mAm(std::make_shared<ActivityManager>()),
76 mUidObserver(new UidObserver(this)),
77 mRegistered(false),
78 mTopUidState(ActivityManager::PROCESS_STATE_UNKNOWN) {
79 registerSelf();
80}
81
82TranscodingUidPolicy::~TranscodingUidPolicy() {
83 unregisterSelf();
84}
85
86void TranscodingUidPolicy::registerSelf() {
87 status_t res = mAm->linkToDeath(mUidObserver.get());
88 mAm->registerUidObserver(
89 mUidObserver.get(),
90 ActivityManager::UID_OBSERVER_GONE | ActivityManager::UID_OBSERVER_IDLE |
91 ActivityManager::UID_OBSERVER_ACTIVE | ActivityManager::UID_OBSERVER_PROCSTATE,
92 ActivityManager::PROCESS_STATE_UNKNOWN, String16(kTranscodingTag));
93
94 if (res == OK) {
95 Mutex::Autolock _l(mUidLock);
96
97 mRegistered = true;
98 ALOGI("TranscodingUidPolicy: Registered with ActivityManager");
99 } else {
100 mAm->unregisterUidObserver(mUidObserver.get());
101 }
102}
103
104void TranscodingUidPolicy::unregisterSelf() {
105 mAm->unregisterUidObserver(mUidObserver.get());
106 mAm->unlinkToDeath(mUidObserver.get());
107
108 Mutex::Autolock _l(mUidLock);
109
110 mRegistered = false;
111
112 ALOGI("TranscodingUidPolicy: Unregistered with ActivityManager");
113}
114
115void TranscodingUidPolicy::setUidObserverRegistered(bool registered) {
116 Mutex::Autolock _l(mUidLock);
117
118 mRegistered = registered;
119}
120
121void TranscodingUidPolicy::setCallback(const std::shared_ptr<UidPolicyCallbackInterface>& cb) {
122 mUidPolicyCallback = cb;
123}
124
125void TranscodingUidPolicy::registerMonitorUid(uid_t uid) {
126 Mutex::Autolock _l(mUidLock);
127 if (uid == OFFLINE_UID) {
128 ALOGW("Ignoring the offline uid");
129 return;
130 }
131 if (mUidStateMap.find(uid) != mUidStateMap.end()) {
132 ALOGE("%s: Trying to register uid: %d which is already monitored!", __FUNCTION__, uid);
133 return;
134 }
135
136 int32_t state = ActivityManager::PROCESS_STATE_UNKNOWN;
Hui Yu799ba4f2020-05-05 17:04:15 -0700137 if (mRegistered && mAm->isUidActive(uid, String16(kTranscodingTag))) {
Chong Zhangacb33502020-04-20 11:04:48 -0700138 state = mAm->getUidProcessState(uid, String16(kTranscodingTag));
139 }
140
141 ALOGV("%s: inserting new uid: %u, procState %d", __FUNCTION__, uid, state);
142
143 mUidStateMap.emplace(std::pair<uid_t, int32_t>(uid, state));
144 mStateUidMap[state].insert(uid);
145
146 updateTopUid_l();
147}
148
149void TranscodingUidPolicy::unregisterMonitorUid(uid_t uid) {
150 Mutex::Autolock _l(mUidLock);
151
152 auto it = mUidStateMap.find(uid);
153 if (it == mUidStateMap.end()) {
154 ALOGE("%s: Trying to unregister uid: %d which is not monitored!", __FUNCTION__, uid);
155 return;
156 }
157
158 auto stateIt = mStateUidMap.find(it->second);
159 if (stateIt != mStateUidMap.end()) {
160 stateIt->second.erase(uid);
161 if (stateIt->second.empty()) {
162 mStateUidMap.erase(stateIt);
163 }
164 }
165 mUidStateMap.erase(it);
166
167 updateTopUid_l();
168}
169
170bool TranscodingUidPolicy::isUidOnTop(uid_t uid) {
171 Mutex::Autolock _l(mUidLock);
172
173 return mTopUidState != ActivityManager::PROCESS_STATE_UNKNOWN &&
174 mTopUidState == getProcState_l(uid);
175}
176
177std::unordered_set<uid_t> TranscodingUidPolicy::getTopUids() const {
178 Mutex::Autolock _l(mUidLock);
179
180 if (mTopUidState == ActivityManager::PROCESS_STATE_UNKNOWN) {
181 return std::unordered_set<uid_t>();
182 }
183
184 return mStateUidMap.at(mTopUidState);
185}
186
187void TranscodingUidPolicy::onUidStateChanged(uid_t uid, int32_t procState) {
188 ALOGV("onUidStateChanged: %u, procState %d", uid, procState);
189
190 bool topUidSetChanged = false;
191 std::unordered_set<uid_t> topUids;
192 {
193 Mutex::Autolock _l(mUidLock);
194 auto it = mUidStateMap.find(uid);
195 if (it != mUidStateMap.end() && it->second != procState) {
196 // Top set changed if 1) the uid is in the current top uid set, or 2) the
197 // new procState is at least the same priority as the current top uid state.
198 bool isUidCurrentTop = mTopUidState != ActivityManager::PROCESS_STATE_UNKNOWN &&
199 mStateUidMap[mTopUidState].count(uid) > 0;
200 bool isNewStateHigherThanTop = procState != ActivityManager::PROCESS_STATE_UNKNOWN &&
201 (procState <= mTopUidState ||
202 mTopUidState == ActivityManager::PROCESS_STATE_UNKNOWN);
203 topUidSetChanged = (isUidCurrentTop || isNewStateHigherThanTop);
204
205 // Move uid to the new procState.
206 mStateUidMap[it->second].erase(uid);
207 mStateUidMap[procState].insert(uid);
208 it->second = procState;
209
210 if (topUidSetChanged) {
211 updateTopUid_l();
212
213 // Make a copy of the uid set for callback.
214 topUids = mStateUidMap[mTopUidState];
215 }
216 }
217 }
218
219 ALOGV("topUidSetChanged: %d", topUidSetChanged);
220
221 if (topUidSetChanged) {
222 auto callback = mUidPolicyCallback.lock();
223 if (callback != nullptr) {
224 callback->onTopUidsChanged(topUids);
225 }
226 }
227}
228
229void TranscodingUidPolicy::updateTopUid_l() {
Chong Zhangacb33502020-04-20 11:04:48 -0700230 mTopUidState = ActivityManager::PROCESS_STATE_UNKNOWN;
Chong Zhang75222182020-04-29 14:43:42 -0700231
232 // Find the lowest uid state (ignoring PROCESS_STATE_UNKNOWN) with some monitored uids.
Chong Zhangacb33502020-04-20 11:04:48 -0700233 for (auto stateIt = mStateUidMap.begin(); stateIt != mStateUidMap.end(); stateIt++) {
234 if (stateIt->first != ActivityManager::PROCESS_STATE_UNKNOWN && !stateIt->second.empty()) {
235 mTopUidState = stateIt->first;
236 break;
237 }
238 }
239
240 ALOGV("%s: top uid state is %d", __FUNCTION__, mTopUidState);
241}
242
243int32_t TranscodingUidPolicy::getProcState_l(uid_t uid) {
244 auto it = mUidStateMap.find(uid);
245 if (it != mUidStateMap.end()) {
246 return it->second;
247 }
248 return ActivityManager::PROCESS_STATE_UNKNOWN;
249}
250
251} // namespace android