1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker * Copyright (C) 2020 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 "TranscodingUidPolicy"
19*ec779b8eSAndroid Build Coastguard Worker
20*ec779b8eSAndroid Build Coastguard Worker #include <android/activity_manager.h>
21*ec779b8eSAndroid Build Coastguard Worker #include <android/binder_manager.h>
22*ec779b8eSAndroid Build Coastguard Worker #include <android/binder_process.h>
23*ec779b8eSAndroid Build Coastguard Worker #include <inttypes.h>
24*ec779b8eSAndroid Build Coastguard Worker #include <media/TranscodingDefs.h>
25*ec779b8eSAndroid Build Coastguard Worker #include <media/TranscodingUidPolicy.h>
26*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
27*ec779b8eSAndroid Build Coastguard Worker
28*ec779b8eSAndroid Build Coastguard Worker #include <utility>
29*ec779b8eSAndroid Build Coastguard Worker
30*ec779b8eSAndroid Build Coastguard Worker namespace android {
31*ec779b8eSAndroid Build Coastguard Worker
32*ec779b8eSAndroid Build Coastguard Worker constexpr static uid_t OFFLINE_UID = -1;
33*ec779b8eSAndroid Build Coastguard Worker constexpr static int32_t IMPORTANCE_UNKNOWN = INT32_MAX;
34*ec779b8eSAndroid Build Coastguard Worker
TranscodingUidPolicy()35*ec779b8eSAndroid Build Coastguard Worker TranscodingUidPolicy::TranscodingUidPolicy()
36*ec779b8eSAndroid Build Coastguard Worker : mUidObserver(nullptr), mRegistered(false), mTopUidState(IMPORTANCE_UNKNOWN) {
37*ec779b8eSAndroid Build Coastguard Worker registerSelf();
38*ec779b8eSAndroid Build Coastguard Worker }
39*ec779b8eSAndroid Build Coastguard Worker
~TranscodingUidPolicy()40*ec779b8eSAndroid Build Coastguard Worker TranscodingUidPolicy::~TranscodingUidPolicy() {
41*ec779b8eSAndroid Build Coastguard Worker unregisterSelf();
42*ec779b8eSAndroid Build Coastguard Worker }
43*ec779b8eSAndroid Build Coastguard Worker
OnUidImportance(uid_t uid,int32_t uidImportance,void * cookie)44*ec779b8eSAndroid Build Coastguard Worker void TranscodingUidPolicy::OnUidImportance(uid_t uid, int32_t uidImportance, void* cookie) {
45*ec779b8eSAndroid Build Coastguard Worker TranscodingUidPolicy* owner = reinterpret_cast<TranscodingUidPolicy*>(cookie);
46*ec779b8eSAndroid Build Coastguard Worker owner->onUidStateChanged(uid, uidImportance);
47*ec779b8eSAndroid Build Coastguard Worker }
48*ec779b8eSAndroid Build Coastguard Worker
registerSelf()49*ec779b8eSAndroid Build Coastguard Worker void TranscodingUidPolicy::registerSelf() {
50*ec779b8eSAndroid Build Coastguard Worker if (__builtin_available(android __TRANSCODING_MIN_API__, *)) {
51*ec779b8eSAndroid Build Coastguard Worker mUidObserver = AActivityManager_addUidImportanceListener(&OnUidImportance, -1, (void*)this);
52*ec779b8eSAndroid Build Coastguard Worker }
53*ec779b8eSAndroid Build Coastguard Worker
54*ec779b8eSAndroid Build Coastguard Worker if (mUidObserver == nullptr) {
55*ec779b8eSAndroid Build Coastguard Worker ALOGE("Failed to register uid observer");
56*ec779b8eSAndroid Build Coastguard Worker return;
57*ec779b8eSAndroid Build Coastguard Worker }
58*ec779b8eSAndroid Build Coastguard Worker
59*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l(mUidLock);
60*ec779b8eSAndroid Build Coastguard Worker mRegistered = true;
61*ec779b8eSAndroid Build Coastguard Worker ALOGI("Registered uid observer");
62*ec779b8eSAndroid Build Coastguard Worker }
63*ec779b8eSAndroid Build Coastguard Worker
unregisterSelf()64*ec779b8eSAndroid Build Coastguard Worker void TranscodingUidPolicy::unregisterSelf() {
65*ec779b8eSAndroid Build Coastguard Worker if (__builtin_available(android __TRANSCODING_MIN_API__, *)) {
66*ec779b8eSAndroid Build Coastguard Worker AActivityManager_removeUidImportanceListener(mUidObserver);
67*ec779b8eSAndroid Build Coastguard Worker mUidObserver = nullptr;
68*ec779b8eSAndroid Build Coastguard Worker
69*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l(mUidLock);
70*ec779b8eSAndroid Build Coastguard Worker mRegistered = false;
71*ec779b8eSAndroid Build Coastguard Worker ALOGI("Unregistered uid observer");
72*ec779b8eSAndroid Build Coastguard Worker } else {
73*ec779b8eSAndroid Build Coastguard Worker ALOGE("Failed to unregister uid observer");
74*ec779b8eSAndroid Build Coastguard Worker }
75*ec779b8eSAndroid Build Coastguard Worker }
76*ec779b8eSAndroid Build Coastguard Worker
setCallback(const std::shared_ptr<UidPolicyCallbackInterface> & cb)77*ec779b8eSAndroid Build Coastguard Worker void TranscodingUidPolicy::setCallback(const std::shared_ptr<UidPolicyCallbackInterface>& cb) {
78*ec779b8eSAndroid Build Coastguard Worker mUidPolicyCallback = cb;
79*ec779b8eSAndroid Build Coastguard Worker }
80*ec779b8eSAndroid Build Coastguard Worker
registerMonitorUid(uid_t uid)81*ec779b8eSAndroid Build Coastguard Worker void TranscodingUidPolicy::registerMonitorUid(uid_t uid) {
82*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l(mUidLock);
83*ec779b8eSAndroid Build Coastguard Worker if (uid == OFFLINE_UID) {
84*ec779b8eSAndroid Build Coastguard Worker ALOGW("Ignoring the offline uid");
85*ec779b8eSAndroid Build Coastguard Worker return;
86*ec779b8eSAndroid Build Coastguard Worker }
87*ec779b8eSAndroid Build Coastguard Worker if (mUidStateMap.find(uid) != mUidStateMap.end()) {
88*ec779b8eSAndroid Build Coastguard Worker ALOGE("%s: Trying to register uid: %d which is already monitored!", __FUNCTION__, uid);
89*ec779b8eSAndroid Build Coastguard Worker return;
90*ec779b8eSAndroid Build Coastguard Worker }
91*ec779b8eSAndroid Build Coastguard Worker
92*ec779b8eSAndroid Build Coastguard Worker int32_t state = IMPORTANCE_UNKNOWN;
93*ec779b8eSAndroid Build Coastguard Worker if (__builtin_available(android __TRANSCODING_MIN_API__, *)) {
94*ec779b8eSAndroid Build Coastguard Worker if (mRegistered && AActivityManager_isUidActive(uid)) {
95*ec779b8eSAndroid Build Coastguard Worker state = AActivityManager_getUidImportance(uid);
96*ec779b8eSAndroid Build Coastguard Worker }
97*ec779b8eSAndroid Build Coastguard Worker }
98*ec779b8eSAndroid Build Coastguard Worker
99*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s: inserting new uid: %u, procState %d", __FUNCTION__, uid, state);
100*ec779b8eSAndroid Build Coastguard Worker
101*ec779b8eSAndroid Build Coastguard Worker mUidStateMap.emplace(std::pair<uid_t, int32_t>(uid, state));
102*ec779b8eSAndroid Build Coastguard Worker mStateUidMap[state].insert(uid);
103*ec779b8eSAndroid Build Coastguard Worker
104*ec779b8eSAndroid Build Coastguard Worker updateTopUid_l();
105*ec779b8eSAndroid Build Coastguard Worker }
106*ec779b8eSAndroid Build Coastguard Worker
unregisterMonitorUid(uid_t uid)107*ec779b8eSAndroid Build Coastguard Worker void TranscodingUidPolicy::unregisterMonitorUid(uid_t uid) {
108*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l(mUidLock);
109*ec779b8eSAndroid Build Coastguard Worker
110*ec779b8eSAndroid Build Coastguard Worker auto it = mUidStateMap.find(uid);
111*ec779b8eSAndroid Build Coastguard Worker if (it == mUidStateMap.end()) {
112*ec779b8eSAndroid Build Coastguard Worker ALOGE("%s: Trying to unregister uid: %d which is not monitored!", __FUNCTION__, uid);
113*ec779b8eSAndroid Build Coastguard Worker return;
114*ec779b8eSAndroid Build Coastguard Worker }
115*ec779b8eSAndroid Build Coastguard Worker
116*ec779b8eSAndroid Build Coastguard Worker auto stateIt = mStateUidMap.find(it->second);
117*ec779b8eSAndroid Build Coastguard Worker if (stateIt != mStateUidMap.end()) {
118*ec779b8eSAndroid Build Coastguard Worker stateIt->second.erase(uid);
119*ec779b8eSAndroid Build Coastguard Worker if (stateIt->second.empty()) {
120*ec779b8eSAndroid Build Coastguard Worker mStateUidMap.erase(stateIt);
121*ec779b8eSAndroid Build Coastguard Worker }
122*ec779b8eSAndroid Build Coastguard Worker }
123*ec779b8eSAndroid Build Coastguard Worker mUidStateMap.erase(it);
124*ec779b8eSAndroid Build Coastguard Worker
125*ec779b8eSAndroid Build Coastguard Worker updateTopUid_l();
126*ec779b8eSAndroid Build Coastguard Worker }
127*ec779b8eSAndroid Build Coastguard Worker
isUidOnTop(uid_t uid)128*ec779b8eSAndroid Build Coastguard Worker bool TranscodingUidPolicy::isUidOnTop(uid_t uid) {
129*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l(mUidLock);
130*ec779b8eSAndroid Build Coastguard Worker
131*ec779b8eSAndroid Build Coastguard Worker return mTopUidState != IMPORTANCE_UNKNOWN && mTopUidState == getProcState_l(uid);
132*ec779b8eSAndroid Build Coastguard Worker }
133*ec779b8eSAndroid Build Coastguard Worker
getTopUids() const134*ec779b8eSAndroid Build Coastguard Worker std::unordered_set<uid_t> TranscodingUidPolicy::getTopUids() const {
135*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l(mUidLock);
136*ec779b8eSAndroid Build Coastguard Worker
137*ec779b8eSAndroid Build Coastguard Worker if (mTopUidState == IMPORTANCE_UNKNOWN) {
138*ec779b8eSAndroid Build Coastguard Worker return std::unordered_set<uid_t>();
139*ec779b8eSAndroid Build Coastguard Worker }
140*ec779b8eSAndroid Build Coastguard Worker
141*ec779b8eSAndroid Build Coastguard Worker return mStateUidMap.at(mTopUidState);
142*ec779b8eSAndroid Build Coastguard Worker }
143*ec779b8eSAndroid Build Coastguard Worker
onUidStateChanged(uid_t uid,int32_t procState)144*ec779b8eSAndroid Build Coastguard Worker void TranscodingUidPolicy::onUidStateChanged(uid_t uid, int32_t procState) {
145*ec779b8eSAndroid Build Coastguard Worker ALOGV("onUidStateChanged: uid %u, procState %d", uid, procState);
146*ec779b8eSAndroid Build Coastguard Worker
147*ec779b8eSAndroid Build Coastguard Worker bool topUidSetChanged = false;
148*ec779b8eSAndroid Build Coastguard Worker bool isUidGone = false;
149*ec779b8eSAndroid Build Coastguard Worker std::unordered_set<uid_t> topUids;
150*ec779b8eSAndroid Build Coastguard Worker {
151*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l(mUidLock);
152*ec779b8eSAndroid Build Coastguard Worker auto it = mUidStateMap.find(uid);
153*ec779b8eSAndroid Build Coastguard Worker if (it != mUidStateMap.end() && it->second != procState) {
154*ec779b8eSAndroid Build Coastguard Worker isUidGone = (procState == AACTIVITYMANAGER_IMPORTANCE_GONE);
155*ec779b8eSAndroid Build Coastguard Worker
156*ec779b8eSAndroid Build Coastguard Worker topUids = mStateUidMap[mTopUidState];
157*ec779b8eSAndroid Build Coastguard Worker
158*ec779b8eSAndroid Build Coastguard Worker // Move uid to the new procState.
159*ec779b8eSAndroid Build Coastguard Worker mStateUidMap[it->second].erase(uid);
160*ec779b8eSAndroid Build Coastguard Worker mStateUidMap[procState].insert(uid);
161*ec779b8eSAndroid Build Coastguard Worker it->second = procState;
162*ec779b8eSAndroid Build Coastguard Worker
163*ec779b8eSAndroid Build Coastguard Worker updateTopUid_l();
164*ec779b8eSAndroid Build Coastguard Worker if (topUids != mStateUidMap[mTopUidState]) {
165*ec779b8eSAndroid Build Coastguard Worker // Make a copy of the uid set for callback.
166*ec779b8eSAndroid Build Coastguard Worker topUids = mStateUidMap[mTopUidState];
167*ec779b8eSAndroid Build Coastguard Worker topUidSetChanged = true;
168*ec779b8eSAndroid Build Coastguard Worker }
169*ec779b8eSAndroid Build Coastguard Worker }
170*ec779b8eSAndroid Build Coastguard Worker }
171*ec779b8eSAndroid Build Coastguard Worker
172*ec779b8eSAndroid Build Coastguard Worker ALOGV("topUidSetChanged: %d, isUidGone %d", topUidSetChanged, isUidGone);
173*ec779b8eSAndroid Build Coastguard Worker
174*ec779b8eSAndroid Build Coastguard Worker if (topUidSetChanged) {
175*ec779b8eSAndroid Build Coastguard Worker auto callback = mUidPolicyCallback.lock();
176*ec779b8eSAndroid Build Coastguard Worker if (callback != nullptr) {
177*ec779b8eSAndroid Build Coastguard Worker callback->onTopUidsChanged(topUids);
178*ec779b8eSAndroid Build Coastguard Worker }
179*ec779b8eSAndroid Build Coastguard Worker }
180*ec779b8eSAndroid Build Coastguard Worker if (isUidGone) {
181*ec779b8eSAndroid Build Coastguard Worker auto callback = mUidPolicyCallback.lock();
182*ec779b8eSAndroid Build Coastguard Worker if (callback != nullptr) {
183*ec779b8eSAndroid Build Coastguard Worker callback->onUidGone(uid);
184*ec779b8eSAndroid Build Coastguard Worker }
185*ec779b8eSAndroid Build Coastguard Worker }
186*ec779b8eSAndroid Build Coastguard Worker }
187*ec779b8eSAndroid Build Coastguard Worker
updateTopUid_l()188*ec779b8eSAndroid Build Coastguard Worker void TranscodingUidPolicy::updateTopUid_l() {
189*ec779b8eSAndroid Build Coastguard Worker mTopUidState = IMPORTANCE_UNKNOWN;
190*ec779b8eSAndroid Build Coastguard Worker
191*ec779b8eSAndroid Build Coastguard Worker // Find the lowest uid state (ignoring PROCESS_STATE_UNKNOWN) with some monitored uids.
192*ec779b8eSAndroid Build Coastguard Worker for (auto stateIt = mStateUidMap.begin(); stateIt != mStateUidMap.end(); stateIt++) {
193*ec779b8eSAndroid Build Coastguard Worker if (stateIt->first != IMPORTANCE_UNKNOWN && !stateIt->second.empty()) {
194*ec779b8eSAndroid Build Coastguard Worker mTopUidState = stateIt->first;
195*ec779b8eSAndroid Build Coastguard Worker break;
196*ec779b8eSAndroid Build Coastguard Worker }
197*ec779b8eSAndroid Build Coastguard Worker }
198*ec779b8eSAndroid Build Coastguard Worker
199*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s: top uid state is %d", __FUNCTION__, mTopUidState);
200*ec779b8eSAndroid Build Coastguard Worker }
201*ec779b8eSAndroid Build Coastguard Worker
getProcState_l(uid_t uid)202*ec779b8eSAndroid Build Coastguard Worker int32_t TranscodingUidPolicy::getProcState_l(uid_t uid) {
203*ec779b8eSAndroid Build Coastguard Worker auto it = mUidStateMap.find(uid);
204*ec779b8eSAndroid Build Coastguard Worker if (it != mUidStateMap.end()) {
205*ec779b8eSAndroid Build Coastguard Worker return it->second;
206*ec779b8eSAndroid Build Coastguard Worker }
207*ec779b8eSAndroid Build Coastguard Worker return IMPORTANCE_UNKNOWN;
208*ec779b8eSAndroid Build Coastguard Worker }
209*ec779b8eSAndroid Build Coastguard Worker
210*ec779b8eSAndroid Build Coastguard Worker } // namespace android
211