blob: a725387538ff316113bb3d34e3b4fb29037c0fc8 [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 Zhangad8fdfc2020-10-21 19:05:15 -070020#include <android/activity_manager.h>
Chong Zhang97d367b2020-09-16 12:53:14 -070021#include <android/binder_manager.h>
22#include <android/binder_process.h>
Chong Zhangacb33502020-04-20 11:04:48 -070023#include <inttypes.h>
24#include <media/TranscodingUidPolicy.h>
25#include <utils/Log.h>
26
27#include <utility>
28
29namespace android {
30
31constexpr static uid_t OFFLINE_UID = -1;
Chong Zhangad8fdfc2020-10-21 19:05:15 -070032constexpr static int32_t IMPORTANCE_UNKNOWN = INT32_MAX;
Chong Zhangacb33502020-04-20 11:04:48 -070033
34TranscodingUidPolicy::TranscodingUidPolicy()
Chong Zhangad8fdfc2020-10-21 19:05:15 -070035 : mUidObserver(nullptr),
Chong Zhangacb33502020-04-20 11:04:48 -070036 mRegistered(false),
Chong Zhangad8fdfc2020-10-21 19:05:15 -070037 mTopUidState(IMPORTANCE_UNKNOWN) {
Chong Zhangacb33502020-04-20 11:04:48 -070038 registerSelf();
39}
40
41TranscodingUidPolicy::~TranscodingUidPolicy() {
42 unregisterSelf();
43}
44
Chong Zhangad8fdfc2020-10-21 19:05:15 -070045void TranscodingUidPolicy::OnUidImportance(uid_t uid, int32_t uidImportance, void* cookie) {
46 TranscodingUidPolicy* owner = reinterpret_cast<TranscodingUidPolicy*>(cookie);
47 owner->onUidStateChanged(uid, uidImportance);
48}
49
Chong Zhangacb33502020-04-20 11:04:48 -070050void TranscodingUidPolicy::registerSelf() {
Chong Zhangad8fdfc2020-10-21 19:05:15 -070051 mUidObserver = AActivityManager_addUidImportanceListener(
52 &OnUidImportance, -1, (void*)this);
Chong Zhangacb33502020-04-20 11:04:48 -070053
Chong Zhangad8fdfc2020-10-21 19:05:15 -070054 if (mUidObserver == nullptr) {
55 ALOGE("Failed to register uid observer");
56 return;
Chong Zhangacb33502020-04-20 11:04:48 -070057 }
Chong Zhangad8fdfc2020-10-21 19:05:15 -070058
59 Mutex::Autolock _l(mUidLock);
60 mRegistered = true;
61 ALOGI("Registered uid observer");
Chong Zhangacb33502020-04-20 11:04:48 -070062}
63
64void TranscodingUidPolicy::unregisterSelf() {
Chong Zhangad8fdfc2020-10-21 19:05:15 -070065 AActivityManager_removeUidImportanceListener(mUidObserver);
66 mUidObserver = nullptr;
Chong Zhangacb33502020-04-20 11:04:48 -070067
68 Mutex::Autolock _l(mUidLock);
Chong Zhangacb33502020-04-20 11:04:48 -070069 mRegistered = false;
Chong Zhangad8fdfc2020-10-21 19:05:15 -070070 ALOGI("Unregistered uid observer");
Chong Zhangacb33502020-04-20 11:04:48 -070071}
72
73void TranscodingUidPolicy::setCallback(const std::shared_ptr<UidPolicyCallbackInterface>& cb) {
74 mUidPolicyCallback = cb;
75}
76
77void TranscodingUidPolicy::registerMonitorUid(uid_t uid) {
78 Mutex::Autolock _l(mUidLock);
79 if (uid == OFFLINE_UID) {
80 ALOGW("Ignoring the offline uid");
81 return;
82 }
83 if (mUidStateMap.find(uid) != mUidStateMap.end()) {
84 ALOGE("%s: Trying to register uid: %d which is already monitored!", __FUNCTION__, uid);
85 return;
86 }
87
Chong Zhangad8fdfc2020-10-21 19:05:15 -070088 int32_t state = IMPORTANCE_UNKNOWN;
89 if (mRegistered && AActivityManager_isUidActive(uid)) {
90 state = AActivityManager_getUidImportance(uid);
Chong Zhangacb33502020-04-20 11:04:48 -070091 }
92
93 ALOGV("%s: inserting new uid: %u, procState %d", __FUNCTION__, uid, state);
94
95 mUidStateMap.emplace(std::pair<uid_t, int32_t>(uid, state));
96 mStateUidMap[state].insert(uid);
97
98 updateTopUid_l();
99}
100
101void TranscodingUidPolicy::unregisterMonitorUid(uid_t uid) {
102 Mutex::Autolock _l(mUidLock);
103
104 auto it = mUidStateMap.find(uid);
105 if (it == mUidStateMap.end()) {
106 ALOGE("%s: Trying to unregister uid: %d which is not monitored!", __FUNCTION__, uid);
107 return;
108 }
109
110 auto stateIt = mStateUidMap.find(it->second);
111 if (stateIt != mStateUidMap.end()) {
112 stateIt->second.erase(uid);
113 if (stateIt->second.empty()) {
114 mStateUidMap.erase(stateIt);
115 }
116 }
117 mUidStateMap.erase(it);
118
119 updateTopUid_l();
120}
121
122bool TranscodingUidPolicy::isUidOnTop(uid_t uid) {
123 Mutex::Autolock _l(mUidLock);
124
Chong Zhangad8fdfc2020-10-21 19:05:15 -0700125 return mTopUidState != IMPORTANCE_UNKNOWN &&
Chong Zhangacb33502020-04-20 11:04:48 -0700126 mTopUidState == getProcState_l(uid);
127}
128
129std::unordered_set<uid_t> TranscodingUidPolicy::getTopUids() const {
130 Mutex::Autolock _l(mUidLock);
131
Chong Zhangad8fdfc2020-10-21 19:05:15 -0700132 if (mTopUidState == IMPORTANCE_UNKNOWN) {
Chong Zhangacb33502020-04-20 11:04:48 -0700133 return std::unordered_set<uid_t>();
134 }
135
136 return mStateUidMap.at(mTopUidState);
137}
138
139void TranscodingUidPolicy::onUidStateChanged(uid_t uid, int32_t procState) {
140 ALOGV("onUidStateChanged: %u, procState %d", uid, procState);
141
142 bool topUidSetChanged = false;
143 std::unordered_set<uid_t> topUids;
144 {
145 Mutex::Autolock _l(mUidLock);
146 auto it = mUidStateMap.find(uid);
147 if (it != mUidStateMap.end() && it->second != procState) {
148 // Top set changed if 1) the uid is in the current top uid set, or 2) the
149 // new procState is at least the same priority as the current top uid state.
Chong Zhangad8fdfc2020-10-21 19:05:15 -0700150 bool isUidCurrentTop =
151 mTopUidState != IMPORTANCE_UNKNOWN &&
152 mStateUidMap[mTopUidState].count(uid) > 0;
153 bool isNewStateHigherThanTop =
154 procState != IMPORTANCE_UNKNOWN &&
155 (procState <= mTopUidState ||
156 mTopUidState == IMPORTANCE_UNKNOWN);
Chong Zhangacb33502020-04-20 11:04:48 -0700157 topUidSetChanged = (isUidCurrentTop || isNewStateHigherThanTop);
158
159 // Move uid to the new procState.
160 mStateUidMap[it->second].erase(uid);
161 mStateUidMap[procState].insert(uid);
162 it->second = procState;
163
164 if (topUidSetChanged) {
165 updateTopUid_l();
166
167 // Make a copy of the uid set for callback.
168 topUids = mStateUidMap[mTopUidState];
169 }
170 }
171 }
172
173 ALOGV("topUidSetChanged: %d", topUidSetChanged);
174
175 if (topUidSetChanged) {
176 auto callback = mUidPolicyCallback.lock();
177 if (callback != nullptr) {
178 callback->onTopUidsChanged(topUids);
179 }
180 }
181}
182
183void TranscodingUidPolicy::updateTopUid_l() {
Chong Zhangad8fdfc2020-10-21 19:05:15 -0700184 mTopUidState = IMPORTANCE_UNKNOWN;
Chong Zhang75222182020-04-29 14:43:42 -0700185
186 // Find the lowest uid state (ignoring PROCESS_STATE_UNKNOWN) with some monitored uids.
Chong Zhangacb33502020-04-20 11:04:48 -0700187 for (auto stateIt = mStateUidMap.begin(); stateIt != mStateUidMap.end(); stateIt++) {
Chong Zhangad8fdfc2020-10-21 19:05:15 -0700188 if (stateIt->first != IMPORTANCE_UNKNOWN &&
189 !stateIt->second.empty()) {
Chong Zhangacb33502020-04-20 11:04:48 -0700190 mTopUidState = stateIt->first;
191 break;
192 }
193 }
194
195 ALOGV("%s: top uid state is %d", __FUNCTION__, mTopUidState);
196}
197
198int32_t TranscodingUidPolicy::getProcState_l(uid_t uid) {
199 auto it = mUidStateMap.find(uid);
200 if (it != mUidStateMap.end()) {
201 return it->second;
202 }
Chong Zhangad8fdfc2020-10-21 19:05:15 -0700203 return IMPORTANCE_UNKNOWN;
Chong Zhangacb33502020-04-20 11:04:48 -0700204}
205
206} // namespace android