blob: f0d494502f1212622e1e49ef49fc24bb3f98f77c [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 <aidl/android/media/BnResourceManagerClient.h>
21#include <aidl/android/media/IResourceManagerService.h>
22#include <android/binder_manager.h>
23#include <android/binder_process.h>
Chong Zhang0579c6f2020-10-05 12:03:34 -070024#include <android/content/pm/IPackageManagerNative.h>
Chong Zhangacb33502020-04-20 11:04:48 -070025#include <binder/ActivityManager.h>
Chong Zhang0579c6f2020-10-05 12:03:34 -070026#include <binder/IServiceManager.h>
Chong Zhangacb33502020-04-20 11:04:48 -070027#include <cutils/misc.h> // FIRST_APPLICATION_UID
28#include <inttypes.h>
29#include <media/TranscodingUidPolicy.h>
30#include <utils/Log.h>
31
32#include <utility>
33
34namespace android {
35
36constexpr static uid_t OFFLINE_UID = -1;
37constexpr static const char* kTranscodingTag = "transcoding";
38
Chong Zhang97d367b2020-09-16 12:53:14 -070039/*
40 * The OOM score we're going to ask ResourceManager to use for our native transcoding
41 * service. ResourceManager issues reclaims based on these scores. It gets the scores
42 * from ActivityManagerService, which doesn't track native services. The values of the
43 * OOM scores are defined in:
44 * frameworks/base/services/core/java/com/android/server/am/ProcessList.java
45 * We use SERVICE_ADJ which is lower priority than an app possibly visible to the
46 * user, but higher priority than a cached app (which could be killed without disruption
47 * to the user).
48 */
49constexpr static int32_t SERVICE_ADJ = 500;
50
51using Status = ::ndk::ScopedAStatus;
52using aidl::android::media::BnResourceManagerClient;
53using aidl::android::media::IResourceManagerService;
54
55/*
56 * Placeholder ResourceManagerClient for registering process info override
57 * with the IResourceManagerService. This is only used as a token by the service
58 * to get notifications about binder death, not used for reclaiming resources.
59 */
60struct TranscodingUidPolicy::ResourceManagerClient : public BnResourceManagerClient {
61 explicit ResourceManagerClient() = default;
62
63 Status reclaimResource(bool* _aidl_return) override {
64 *_aidl_return = false;
65 return Status::ok();
66 }
67
68 Status getName(::std::string* _aidl_return) override {
69 _aidl_return->clear();
70 return Status::ok();
71 }
72
73 virtual ~ResourceManagerClient() = default;
74};
75
Chong Zhangacb33502020-04-20 11:04:48 -070076struct TranscodingUidPolicy::UidObserver : public BnUidObserver,
77 public virtual IBinder::DeathRecipient {
78 explicit UidObserver(TranscodingUidPolicy* owner) : mOwner(owner) {}
79
80 // IUidObserver
81 void onUidGone(uid_t uid, bool disabled) override;
82 void onUidActive(uid_t uid) override;
83 void onUidIdle(uid_t uid, bool disabled) override;
84 void onUidStateChanged(uid_t uid, int32_t procState, int64_t procStateSeq,
85 int32_t capability) override;
86
87 // IBinder::DeathRecipient implementation
88 void binderDied(const wp<IBinder>& who) override;
89
90 TranscodingUidPolicy* mOwner;
91};
92
93void TranscodingUidPolicy::UidObserver::onUidGone(uid_t uid __unused, bool disabled __unused) {}
94
95void TranscodingUidPolicy::UidObserver::onUidActive(uid_t uid __unused) {}
96
97void TranscodingUidPolicy::UidObserver::onUidIdle(uid_t uid __unused, bool disabled __unused) {}
98
99void TranscodingUidPolicy::UidObserver::onUidStateChanged(uid_t uid, int32_t procState,
100 int64_t procStateSeq __unused,
101 int32_t capability __unused) {
102 mOwner->onUidStateChanged(uid, procState);
103}
104
105void TranscodingUidPolicy::UidObserver::binderDied(const wp<IBinder>& /*who*/) {
106 ALOGW("TranscodingUidPolicy: ActivityManager has died");
107 // TODO(chz): this is a rare event (since if the AMS is dead, the system is
108 // probably dead as well). But we should try to reconnect.
109 mOwner->setUidObserverRegistered(false);
110}
111
112////////////////////////////////////////////////////////////////////////////
113
Chong Zhang0579c6f2020-10-05 12:03:34 -0700114//static
115bool TranscodingUidPolicy::getNamesForUids(const std::vector<int32_t>& uids,
116 std::vector<std::string>* names) {
117 names->clear();
118 sp<IServiceManager> sm(defaultServiceManager());
119 sp<IBinder> binder(sm->getService(String16("package_native")));
120 if (binder == nullptr) {
121 ALOGE("getService package_native failed");
122 return false;
123 }
124
125 sp<content::pm::IPackageManagerNative> packageMgr =
126 interface_cast<content::pm::IPackageManagerNative>(binder);
127 binder::Status status = packageMgr->getNamesForUids(uids, names);
128
129 if (!status.isOk() || names->size() != uids.size()) {
130 names->clear();
131 return false;
132 }
133 return true;
134}
135
Chong Zhangacb33502020-04-20 11:04:48 -0700136TranscodingUidPolicy::TranscodingUidPolicy()
137 : mAm(std::make_shared<ActivityManager>()),
138 mUidObserver(new UidObserver(this)),
139 mRegistered(false),
140 mTopUidState(ActivityManager::PROCESS_STATE_UNKNOWN) {
141 registerSelf();
Chong Zhang97d367b2020-09-16 12:53:14 -0700142 setProcessInfoOverride();
Chong Zhangacb33502020-04-20 11:04:48 -0700143}
144
145TranscodingUidPolicy::~TranscodingUidPolicy() {
146 unregisterSelf();
147}
148
149void TranscodingUidPolicy::registerSelf() {
150 status_t res = mAm->linkToDeath(mUidObserver.get());
151 mAm->registerUidObserver(
152 mUidObserver.get(),
153 ActivityManager::UID_OBSERVER_GONE | ActivityManager::UID_OBSERVER_IDLE |
154 ActivityManager::UID_OBSERVER_ACTIVE | ActivityManager::UID_OBSERVER_PROCSTATE,
155 ActivityManager::PROCESS_STATE_UNKNOWN, String16(kTranscodingTag));
156
157 if (res == OK) {
158 Mutex::Autolock _l(mUidLock);
159
160 mRegistered = true;
161 ALOGI("TranscodingUidPolicy: Registered with ActivityManager");
162 } else {
163 mAm->unregisterUidObserver(mUidObserver.get());
164 }
165}
166
167void TranscodingUidPolicy::unregisterSelf() {
168 mAm->unregisterUidObserver(mUidObserver.get());
169 mAm->unlinkToDeath(mUidObserver.get());
170
171 Mutex::Autolock _l(mUidLock);
172
173 mRegistered = false;
174
175 ALOGI("TranscodingUidPolicy: Unregistered with ActivityManager");
176}
177
Chong Zhang97d367b2020-09-16 12:53:14 -0700178void TranscodingUidPolicy::setProcessInfoOverride() {
179 ::ndk::SpAIBinder binder(AServiceManager_getService("media.resource_manager"));
180 std::shared_ptr<IResourceManagerService> service = IResourceManagerService::fromBinder(binder);
181 if (service == nullptr) {
182 ALOGE("Failed to get IResourceManagerService");
183 return;
184 }
185
186 mProcInfoOverrideClient = ::ndk::SharedRefBase::make<ResourceManagerClient>();
187 Status status = service->overrideProcessInfo(
188 mProcInfoOverrideClient, getpid(), ActivityManager::PROCESS_STATE_SERVICE, SERVICE_ADJ);
189 if (!status.isOk()) {
190 ALOGW("Failed to setProcessInfoOverride.");
191 }
192}
193
Chong Zhangacb33502020-04-20 11:04:48 -0700194void TranscodingUidPolicy::setUidObserverRegistered(bool registered) {
195 Mutex::Autolock _l(mUidLock);
196
197 mRegistered = registered;
198}
199
200void TranscodingUidPolicy::setCallback(const std::shared_ptr<UidPolicyCallbackInterface>& cb) {
201 mUidPolicyCallback = cb;
202}
203
204void TranscodingUidPolicy::registerMonitorUid(uid_t uid) {
205 Mutex::Autolock _l(mUidLock);
206 if (uid == OFFLINE_UID) {
207 ALOGW("Ignoring the offline uid");
208 return;
209 }
210 if (mUidStateMap.find(uid) != mUidStateMap.end()) {
211 ALOGE("%s: Trying to register uid: %d which is already monitored!", __FUNCTION__, uid);
212 return;
213 }
214
215 int32_t state = ActivityManager::PROCESS_STATE_UNKNOWN;
Hui Yu799ba4f2020-05-05 17:04:15 -0700216 if (mRegistered && mAm->isUidActive(uid, String16(kTranscodingTag))) {
Chong Zhangacb33502020-04-20 11:04:48 -0700217 state = mAm->getUidProcessState(uid, String16(kTranscodingTag));
218 }
219
220 ALOGV("%s: inserting new uid: %u, procState %d", __FUNCTION__, uid, state);
221
222 mUidStateMap.emplace(std::pair<uid_t, int32_t>(uid, state));
223 mStateUidMap[state].insert(uid);
224
225 updateTopUid_l();
226}
227
228void TranscodingUidPolicy::unregisterMonitorUid(uid_t uid) {
229 Mutex::Autolock _l(mUidLock);
230
231 auto it = mUidStateMap.find(uid);
232 if (it == mUidStateMap.end()) {
233 ALOGE("%s: Trying to unregister uid: %d which is not monitored!", __FUNCTION__, uid);
234 return;
235 }
236
237 auto stateIt = mStateUidMap.find(it->second);
238 if (stateIt != mStateUidMap.end()) {
239 stateIt->second.erase(uid);
240 if (stateIt->second.empty()) {
241 mStateUidMap.erase(stateIt);
242 }
243 }
244 mUidStateMap.erase(it);
245
246 updateTopUid_l();
247}
248
249bool TranscodingUidPolicy::isUidOnTop(uid_t uid) {
250 Mutex::Autolock _l(mUidLock);
251
252 return mTopUidState != ActivityManager::PROCESS_STATE_UNKNOWN &&
253 mTopUidState == getProcState_l(uid);
254}
255
256std::unordered_set<uid_t> TranscodingUidPolicy::getTopUids() const {
257 Mutex::Autolock _l(mUidLock);
258
259 if (mTopUidState == ActivityManager::PROCESS_STATE_UNKNOWN) {
260 return std::unordered_set<uid_t>();
261 }
262
263 return mStateUidMap.at(mTopUidState);
264}
265
266void TranscodingUidPolicy::onUidStateChanged(uid_t uid, int32_t procState) {
267 ALOGV("onUidStateChanged: %u, procState %d", uid, procState);
268
269 bool topUidSetChanged = false;
270 std::unordered_set<uid_t> topUids;
271 {
272 Mutex::Autolock _l(mUidLock);
273 auto it = mUidStateMap.find(uid);
274 if (it != mUidStateMap.end() && it->second != procState) {
275 // Top set changed if 1) the uid is in the current top uid set, or 2) the
276 // new procState is at least the same priority as the current top uid state.
277 bool isUidCurrentTop = mTopUidState != ActivityManager::PROCESS_STATE_UNKNOWN &&
278 mStateUidMap[mTopUidState].count(uid) > 0;
279 bool isNewStateHigherThanTop = procState != ActivityManager::PROCESS_STATE_UNKNOWN &&
280 (procState <= mTopUidState ||
281 mTopUidState == ActivityManager::PROCESS_STATE_UNKNOWN);
282 topUidSetChanged = (isUidCurrentTop || isNewStateHigherThanTop);
283
284 // Move uid to the new procState.
285 mStateUidMap[it->second].erase(uid);
286 mStateUidMap[procState].insert(uid);
287 it->second = procState;
288
289 if (topUidSetChanged) {
290 updateTopUid_l();
291
292 // Make a copy of the uid set for callback.
293 topUids = mStateUidMap[mTopUidState];
294 }
295 }
296 }
297
298 ALOGV("topUidSetChanged: %d", topUidSetChanged);
299
300 if (topUidSetChanged) {
301 auto callback = mUidPolicyCallback.lock();
302 if (callback != nullptr) {
303 callback->onTopUidsChanged(topUids);
304 }
305 }
306}
307
308void TranscodingUidPolicy::updateTopUid_l() {
Chong Zhangacb33502020-04-20 11:04:48 -0700309 mTopUidState = ActivityManager::PROCESS_STATE_UNKNOWN;
Chong Zhang75222182020-04-29 14:43:42 -0700310
311 // Find the lowest uid state (ignoring PROCESS_STATE_UNKNOWN) with some monitored uids.
Chong Zhangacb33502020-04-20 11:04:48 -0700312 for (auto stateIt = mStateUidMap.begin(); stateIt != mStateUidMap.end(); stateIt++) {
313 if (stateIt->first != ActivityManager::PROCESS_STATE_UNKNOWN && !stateIt->second.empty()) {
314 mTopUidState = stateIt->first;
315 break;
316 }
317 }
318
319 ALOGV("%s: top uid state is %d", __FUNCTION__, mTopUidState);
320}
321
322int32_t TranscodingUidPolicy::getProcState_l(uid_t uid) {
323 auto it = mUidStateMap.find(uid);
324 if (it != mUidStateMap.end()) {
325 return it->second;
326 }
327 return ActivityManager::PROCESS_STATE_UNKNOWN;
328}
329
330} // namespace android