ResourceManagerService.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
  1. /*
  2. **
  3. ** Copyright 2015, The Android Open Source Project
  4. **
  5. ** Licensed under the Apache License, Version 2.0 (the "License");
  6. ** you may not use this file except in compliance with the License.
  7. ** You may obtain a copy of the License at
  8. **
  9. ** http://www.apache.org/licenses/LICENSE-2.0
  10. **
  11. ** Unless required by applicable law or agreed to in writing, software
  12. ** distributed under the License is distributed on an "AS IS" BASIS,
  13. ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. ** See the License for the specific language governing permissions and
  15. ** limitations under the License.
  16. */
  17. //#define LOG_NDEBUG 0
  18. #define LOG_TAG "ResourceManagerService"
  19. #include <utils/Log.h>
  20. #include <binder/IMediaResourceMonitor.h>
  21. #include <binder/IServiceManager.h>
  22. #include <cutils/sched_policy.h>
  23. #include <dirent.h>
  24. #include <media/stagefright/ProcessInfo.h>
  25. #include <mediautils/BatteryNotifier.h>
  26. #include <mediautils/SchedulingPolicyService.h>
  27. #include <string.h>
  28. #include <sys/types.h>
  29. #include <sys/stat.h>
  30. #include <sys/time.h>
  31. #include <unistd.h>
  32. #include "ResourceManagerService.h"
  33. #include "ServiceLog.h"
  34. namespace android {
  35. namespace {
  36. class DeathNotifier : public IBinder::DeathRecipient {
  37. public:
  38. DeathNotifier(const wp<ResourceManagerService> &service, int pid, int64_t clientId)
  39. : mService(service), mPid(pid), mClientId(clientId) {}
  40. virtual void binderDied(const wp<IBinder> & /* who */) override {
  41. // Don't check for pid validity since we know it's already dead.
  42. sp<ResourceManagerService> service = mService.promote();
  43. if (service == nullptr) {
  44. ALOGW("ResourceManagerService is dead as well.");
  45. return;
  46. }
  47. service->removeResource(mPid, mClientId, false);
  48. }
  49. private:
  50. wp<ResourceManagerService> mService;
  51. int mPid;
  52. int64_t mClientId;
  53. };
  54. } // namespace
  55. template <typename T>
  56. static String8 getString(const Vector<T> &items) {
  57. String8 itemsStr;
  58. for (size_t i = 0; i < items.size(); ++i) {
  59. itemsStr.appendFormat("%s ", items[i].toString().string());
  60. }
  61. return itemsStr;
  62. }
  63. static bool hasResourceType(MediaResource::Type type, const ResourceList& resources) {
  64. for (auto it = resources.begin(); it != resources.end(); it++) {
  65. if (it->second.mType == type) {
  66. return true;
  67. }
  68. }
  69. return false;
  70. }
  71. static bool hasResourceType(MediaResource::Type type, const ResourceInfos& infos) {
  72. for (size_t i = 0; i < infos.size(); ++i) {
  73. if (hasResourceType(type, infos[i].resources)) {
  74. return true;
  75. }
  76. }
  77. return false;
  78. }
  79. static ResourceInfos& getResourceInfosForEdit(
  80. int pid,
  81. PidResourceInfosMap& map) {
  82. ssize_t index = map.indexOfKey(pid);
  83. if (index < 0) {
  84. // new pid
  85. ResourceInfos infosForPid;
  86. map.add(pid, infosForPid);
  87. }
  88. return map.editValueFor(pid);
  89. }
  90. static ResourceInfo& getResourceInfoForEdit(
  91. uid_t uid,
  92. int64_t clientId,
  93. const sp<IResourceManagerClient>& client,
  94. ResourceInfos& infos) {
  95. ssize_t index = infos.indexOfKey(clientId);
  96. if (index < 0) {
  97. ResourceInfo info;
  98. info.uid = uid;
  99. info.clientId = clientId;
  100. info.client = client;
  101. index = infos.add(clientId, info);
  102. }
  103. return infos.editValueAt(index);
  104. }
  105. static void notifyResourceGranted(int pid, const Vector<MediaResource> &resources) {
  106. static const char* const kServiceName = "media_resource_monitor";
  107. sp<IBinder> binder = defaultServiceManager()->checkService(String16(kServiceName));
  108. if (binder != NULL) {
  109. sp<IMediaResourceMonitor> service = interface_cast<IMediaResourceMonitor>(binder);
  110. for (size_t i = 0; i < resources.size(); ++i) {
  111. if (resources[i].mSubType == MediaResource::kAudioCodec) {
  112. service->notifyResourceGranted(pid, IMediaResourceMonitor::TYPE_AUDIO_CODEC);
  113. } else if (resources[i].mSubType == MediaResource::kVideoCodec) {
  114. service->notifyResourceGranted(pid, IMediaResourceMonitor::TYPE_VIDEO_CODEC);
  115. }
  116. }
  117. }
  118. }
  119. status_t ResourceManagerService::dump(int fd, const Vector<String16>& /* args */) {
  120. String8 result;
  121. if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
  122. result.format("Permission Denial: "
  123. "can't dump ResourceManagerService from pid=%d, uid=%d\n",
  124. IPCThreadState::self()->getCallingPid(),
  125. IPCThreadState::self()->getCallingUid());
  126. write(fd, result.string(), result.size());
  127. return PERMISSION_DENIED;
  128. }
  129. PidResourceInfosMap mapCopy;
  130. bool supportsMultipleSecureCodecs;
  131. bool supportsSecureWithNonSecureCodec;
  132. String8 serviceLog;
  133. {
  134. Mutex::Autolock lock(mLock);
  135. mapCopy = mMap; // Shadow copy, real copy will happen on write.
  136. supportsMultipleSecureCodecs = mSupportsMultipleSecureCodecs;
  137. supportsSecureWithNonSecureCodec = mSupportsSecureWithNonSecureCodec;
  138. serviceLog = mServiceLog->toString(" " /* linePrefix */);
  139. }
  140. const size_t SIZE = 256;
  141. char buffer[SIZE];
  142. snprintf(buffer, SIZE, "ResourceManagerService: %p\n", this);
  143. result.append(buffer);
  144. result.append(" Policies:\n");
  145. snprintf(buffer, SIZE, " SupportsMultipleSecureCodecs: %d\n", supportsMultipleSecureCodecs);
  146. result.append(buffer);
  147. snprintf(buffer, SIZE, " SupportsSecureWithNonSecureCodec: %d\n",
  148. supportsSecureWithNonSecureCodec);
  149. result.append(buffer);
  150. result.append(" Processes:\n");
  151. for (size_t i = 0; i < mapCopy.size(); ++i) {
  152. snprintf(buffer, SIZE, " Pid: %d\n", mapCopy.keyAt(i));
  153. result.append(buffer);
  154. const ResourceInfos &infos = mapCopy.valueAt(i);
  155. for (size_t j = 0; j < infos.size(); ++j) {
  156. result.append(" Client:\n");
  157. snprintf(buffer, SIZE, " Id: %lld\n", (long long)infos[j].clientId);
  158. result.append(buffer);
  159. snprintf(buffer, SIZE, " Name: %s\n", infos[j].client->getName().string());
  160. result.append(buffer);
  161. const ResourceList &resources = infos[j].resources;
  162. result.append(" Resources:\n");
  163. for (auto it = resources.begin(); it != resources.end(); it++) {
  164. snprintf(buffer, SIZE, " %s\n", it->second.toString().string());
  165. result.append(buffer);
  166. }
  167. }
  168. }
  169. result.append(" Events logs (most recent at top):\n");
  170. result.append(serviceLog);
  171. write(fd, result.string(), result.size());
  172. return OK;
  173. }
  174. struct SystemCallbackImpl :
  175. public ResourceManagerService::SystemCallbackInterface {
  176. SystemCallbackImpl() {}
  177. virtual void noteStartVideo(int uid) override {
  178. BatteryNotifier::getInstance().noteStartVideo(uid);
  179. }
  180. virtual void noteStopVideo(int uid) override {
  181. BatteryNotifier::getInstance().noteStopVideo(uid);
  182. }
  183. virtual void noteResetVideo() override {
  184. BatteryNotifier::getInstance().noteResetVideo();
  185. }
  186. virtual bool requestCpusetBoost(
  187. bool enable, const sp<IInterface> &client) override {
  188. return android::requestCpusetBoost(enable, client);
  189. }
  190. protected:
  191. virtual ~SystemCallbackImpl() {}
  192. private:
  193. DISALLOW_EVIL_CONSTRUCTORS(SystemCallbackImpl);
  194. };
  195. ResourceManagerService::ResourceManagerService()
  196. : ResourceManagerService(new ProcessInfo(), new SystemCallbackImpl()) {}
  197. ResourceManagerService::ResourceManagerService(
  198. const sp<ProcessInfoInterface> &processInfo,
  199. const sp<SystemCallbackInterface> &systemResource)
  200. : mProcessInfo(processInfo),
  201. mSystemCB(systemResource),
  202. mServiceLog(new ServiceLog()),
  203. mSupportsMultipleSecureCodecs(true),
  204. mSupportsSecureWithNonSecureCodec(true),
  205. mCpuBoostCount(0) {
  206. mSystemCB->noteResetVideo();
  207. }
  208. ResourceManagerService::~ResourceManagerService() {}
  209. void ResourceManagerService::config(const Vector<MediaResourcePolicy> &policies) {
  210. String8 log = String8::format("config(%s)", getString(policies).string());
  211. mServiceLog->add(log);
  212. Mutex::Autolock lock(mLock);
  213. for (size_t i = 0; i < policies.size(); ++i) {
  214. String8 type = policies[i].mType;
  215. String8 value = policies[i].mValue;
  216. if (type == kPolicySupportsMultipleSecureCodecs) {
  217. mSupportsMultipleSecureCodecs = (value == "true");
  218. } else if (type == kPolicySupportsSecureWithNonSecureCodec) {
  219. mSupportsSecureWithNonSecureCodec = (value == "true");
  220. }
  221. }
  222. }
  223. void ResourceManagerService::onFirstAdded(
  224. const MediaResource& resource, const ResourceInfo& clientInfo) {
  225. // first time added
  226. if (resource.mType == MediaResource::kCpuBoost
  227. && resource.mSubType == MediaResource::kUnspecifiedSubType) {
  228. // Request it on every new instance of kCpuBoost, as the media.codec
  229. // could have died, if we only do it the first time subsequent instances
  230. // never gets the boost.
  231. if (mSystemCB->requestCpusetBoost(true, this) != OK) {
  232. ALOGW("couldn't request cpuset boost");
  233. }
  234. mCpuBoostCount++;
  235. } else if (resource.mType == MediaResource::kBattery
  236. && resource.mSubType == MediaResource::kVideoCodec) {
  237. mSystemCB->noteStartVideo(clientInfo.uid);
  238. }
  239. }
  240. void ResourceManagerService::onLastRemoved(
  241. const MediaResource& resource, const ResourceInfo& clientInfo) {
  242. if (resource.mType == MediaResource::kCpuBoost
  243. && resource.mSubType == MediaResource::kUnspecifiedSubType
  244. && mCpuBoostCount > 0) {
  245. if (--mCpuBoostCount == 0) {
  246. mSystemCB->requestCpusetBoost(false, this);
  247. }
  248. } else if (resource.mType == MediaResource::kBattery
  249. && resource.mSubType == MediaResource::kVideoCodec) {
  250. mSystemCB->noteStopVideo(clientInfo.uid);
  251. }
  252. }
  253. void ResourceManagerService::addResource(
  254. int pid,
  255. int uid,
  256. int64_t clientId,
  257. const sp<IResourceManagerClient> client,
  258. const Vector<MediaResource> &resources) {
  259. String8 log = String8::format("addResource(pid %d, clientId %lld, resources %s)",
  260. pid, (long long) clientId, getString(resources).string());
  261. mServiceLog->add(log);
  262. Mutex::Autolock lock(mLock);
  263. if (!mProcessInfo->isValidPid(pid)) {
  264. ALOGE("Rejected addResource call with invalid pid.");
  265. return;
  266. }
  267. ResourceInfos& infos = getResourceInfosForEdit(pid, mMap);
  268. ResourceInfo& info = getResourceInfoForEdit(uid, clientId, client, infos);
  269. for (size_t i = 0; i < resources.size(); ++i) {
  270. const auto resType = std::make_pair(resources[i].mType, resources[i].mSubType);
  271. if (info.resources.find(resType) == info.resources.end()) {
  272. onFirstAdded(resources[i], info);
  273. info.resources[resType] = resources[i];
  274. } else {
  275. info.resources[resType].mValue += resources[i].mValue;
  276. }
  277. }
  278. if (info.deathNotifier == nullptr) {
  279. info.deathNotifier = new DeathNotifier(this, pid, clientId);
  280. IInterface::asBinder(client)->linkToDeath(info.deathNotifier);
  281. }
  282. notifyResourceGranted(pid, resources);
  283. }
  284. void ResourceManagerService::removeResource(int pid, int64_t clientId,
  285. const Vector<MediaResource> &resources) {
  286. String8 log = String8::format("removeResource(pid %d, clientId %lld, resources %s)",
  287. pid, (long long) clientId, getString(resources).string());
  288. mServiceLog->add(log);
  289. Mutex::Autolock lock(mLock);
  290. if (!mProcessInfo->isValidPid(pid)) {
  291. ALOGE("Rejected removeResource call with invalid pid.");
  292. return;
  293. }
  294. ssize_t index = mMap.indexOfKey(pid);
  295. if (index < 0) {
  296. ALOGV("removeResource: didn't find pid %d for clientId %lld", pid, (long long) clientId);
  297. return;
  298. }
  299. ResourceInfos &infos = mMap.editValueAt(index);
  300. index = infos.indexOfKey(clientId);
  301. if (index < 0) {
  302. ALOGV("removeResource: didn't find clientId %lld", (long long) clientId);
  303. return;
  304. }
  305. ResourceInfo &info = infos.editValueAt(index);
  306. for (size_t i = 0; i < resources.size(); ++i) {
  307. const auto resType = std::make_pair(resources[i].mType, resources[i].mSubType);
  308. // ignore if we don't have it
  309. if (info.resources.find(resType) != info.resources.end()) {
  310. MediaResource &resource = info.resources[resType];
  311. if (resource.mValue > resources[i].mValue) {
  312. resource.mValue -= resources[i].mValue;
  313. } else {
  314. onLastRemoved(resources[i], info);
  315. info.resources.erase(resType);
  316. }
  317. }
  318. }
  319. }
  320. void ResourceManagerService::removeClient(int pid, int64_t clientId) {
  321. removeResource(pid, clientId, true);
  322. }
  323. void ResourceManagerService::removeResource(int pid, int64_t clientId, bool checkValid) {
  324. String8 log = String8::format(
  325. "removeResource(pid %d, clientId %lld)",
  326. pid, (long long) clientId);
  327. mServiceLog->add(log);
  328. Mutex::Autolock lock(mLock);
  329. if (checkValid && !mProcessInfo->isValidPid(pid)) {
  330. ALOGE("Rejected removeResource call with invalid pid.");
  331. return;
  332. }
  333. ssize_t index = mMap.indexOfKey(pid);
  334. if (index < 0) {
  335. ALOGV("removeResource: didn't find pid %d for clientId %lld", pid, (long long) clientId);
  336. return;
  337. }
  338. ResourceInfos &infos = mMap.editValueAt(index);
  339. index = infos.indexOfKey(clientId);
  340. if (index < 0) {
  341. ALOGV("removeResource: didn't find clientId %lld", (long long) clientId);
  342. return;
  343. }
  344. const ResourceInfo &info = infos[index];
  345. for (auto it = info.resources.begin(); it != info.resources.end(); it++) {
  346. onLastRemoved(it->second, info);
  347. }
  348. IInterface::asBinder(info.client)->unlinkToDeath(info.deathNotifier);
  349. infos.removeItemsAt(index);
  350. }
  351. void ResourceManagerService::getClientForResource_l(
  352. int callingPid, const MediaResource *res, Vector<sp<IResourceManagerClient>> *clients) {
  353. if (res == NULL) {
  354. return;
  355. }
  356. sp<IResourceManagerClient> client;
  357. if (getLowestPriorityBiggestClient_l(callingPid, res->mType, &client)) {
  358. clients->push_back(client);
  359. }
  360. }
  361. bool ResourceManagerService::reclaimResource(
  362. int callingPid, const Vector<MediaResource> &resources) {
  363. String8 log = String8::format("reclaimResource(callingPid %d, resources %s)",
  364. callingPid, getString(resources).string());
  365. mServiceLog->add(log);
  366. Vector<sp<IResourceManagerClient>> clients;
  367. {
  368. Mutex::Autolock lock(mLock);
  369. if (!mProcessInfo->isValidPid(callingPid)) {
  370. ALOGE("Rejected reclaimResource call with invalid callingPid.");
  371. return false;
  372. }
  373. const MediaResource *secureCodec = NULL;
  374. const MediaResource *nonSecureCodec = NULL;
  375. const MediaResource *graphicMemory = NULL;
  376. for (size_t i = 0; i < resources.size(); ++i) {
  377. MediaResource::Type type = resources[i].mType;
  378. if (resources[i].mType == MediaResource::kSecureCodec) {
  379. secureCodec = &resources[i];
  380. } else if (type == MediaResource::kNonSecureCodec) {
  381. nonSecureCodec = &resources[i];
  382. } else if (type == MediaResource::kGraphicMemory) {
  383. graphicMemory = &resources[i];
  384. }
  385. }
  386. // first pass to handle secure/non-secure codec conflict
  387. if (secureCodec != NULL) {
  388. if (!mSupportsMultipleSecureCodecs) {
  389. if (!getAllClients_l(callingPid, MediaResource::kSecureCodec, &clients)) {
  390. return false;
  391. }
  392. }
  393. if (!mSupportsSecureWithNonSecureCodec) {
  394. if (!getAllClients_l(callingPid, MediaResource::kNonSecureCodec, &clients)) {
  395. return false;
  396. }
  397. }
  398. }
  399. if (nonSecureCodec != NULL) {
  400. if (!mSupportsSecureWithNonSecureCodec) {
  401. if (!getAllClients_l(callingPid, MediaResource::kSecureCodec, &clients)) {
  402. return false;
  403. }
  404. }
  405. }
  406. if (clients.size() == 0) {
  407. // if no secure/non-secure codec conflict, run second pass to handle other resources.
  408. getClientForResource_l(callingPid, graphicMemory, &clients);
  409. }
  410. if (clients.size() == 0) {
  411. // if we are here, run the third pass to free one codec with the same type.
  412. getClientForResource_l(callingPid, secureCodec, &clients);
  413. getClientForResource_l(callingPid, nonSecureCodec, &clients);
  414. }
  415. if (clients.size() == 0) {
  416. // if we are here, run the fourth pass to free one codec with the different type.
  417. if (secureCodec != NULL) {
  418. MediaResource temp(MediaResource::kNonSecureCodec, 1);
  419. getClientForResource_l(callingPid, &temp, &clients);
  420. }
  421. if (nonSecureCodec != NULL) {
  422. MediaResource temp(MediaResource::kSecureCodec, 1);
  423. getClientForResource_l(callingPid, &temp, &clients);
  424. }
  425. }
  426. }
  427. if (clients.size() == 0) {
  428. return false;
  429. }
  430. sp<IResourceManagerClient> failedClient;
  431. for (size_t i = 0; i < clients.size(); ++i) {
  432. log = String8::format("reclaimResource from client %p", clients[i].get());
  433. mServiceLog->add(log);
  434. if (!clients[i]->reclaimResource()) {
  435. failedClient = clients[i];
  436. break;
  437. }
  438. }
  439. if (failedClient == NULL) {
  440. return true;
  441. }
  442. {
  443. Mutex::Autolock lock(mLock);
  444. bool found = false;
  445. for (size_t i = 0; i < mMap.size(); ++i) {
  446. ResourceInfos &infos = mMap.editValueAt(i);
  447. for (size_t j = 0; j < infos.size();) {
  448. if (infos[j].client == failedClient) {
  449. j = infos.removeItemsAt(j);
  450. found = true;
  451. } else {
  452. ++j;
  453. }
  454. }
  455. if (found) {
  456. break;
  457. }
  458. }
  459. if (!found) {
  460. ALOGV("didn't find failed client");
  461. }
  462. }
  463. return false;
  464. }
  465. bool ResourceManagerService::getAllClients_l(
  466. int callingPid, MediaResource::Type type, Vector<sp<IResourceManagerClient>> *clients) {
  467. Vector<sp<IResourceManagerClient>> temp;
  468. for (size_t i = 0; i < mMap.size(); ++i) {
  469. ResourceInfos &infos = mMap.editValueAt(i);
  470. for (size_t j = 0; j < infos.size(); ++j) {
  471. if (hasResourceType(type, infos[j].resources)) {
  472. if (!isCallingPriorityHigher_l(callingPid, mMap.keyAt(i))) {
  473. // some higher/equal priority process owns the resource,
  474. // this request can't be fulfilled.
  475. ALOGE("getAllClients_l: can't reclaim resource %s from pid %d",
  476. asString(type), mMap.keyAt(i));
  477. return false;
  478. }
  479. temp.push_back(infos[j].client);
  480. }
  481. }
  482. }
  483. if (temp.size() == 0) {
  484. ALOGV("getAllClients_l: didn't find any resource %s", asString(type));
  485. return true;
  486. }
  487. clients->appendVector(temp);
  488. return true;
  489. }
  490. bool ResourceManagerService::getLowestPriorityBiggestClient_l(
  491. int callingPid, MediaResource::Type type, sp<IResourceManagerClient> *client) {
  492. int lowestPriorityPid;
  493. int lowestPriority;
  494. int callingPriority;
  495. if (!mProcessInfo->getPriority(callingPid, &callingPriority)) {
  496. ALOGE("getLowestPriorityBiggestClient_l: can't get process priority for pid %d",
  497. callingPid);
  498. return false;
  499. }
  500. if (!getLowestPriorityPid_l(type, &lowestPriorityPid, &lowestPriority)) {
  501. return false;
  502. }
  503. if (lowestPriority <= callingPriority) {
  504. ALOGE("getLowestPriorityBiggestClient_l: lowest priority %d vs caller priority %d",
  505. lowestPriority, callingPriority);
  506. return false;
  507. }
  508. if (!getBiggestClient_l(lowestPriorityPid, type, client)) {
  509. return false;
  510. }
  511. return true;
  512. }
  513. bool ResourceManagerService::getLowestPriorityPid_l(
  514. MediaResource::Type type, int *lowestPriorityPid, int *lowestPriority) {
  515. int pid = -1;
  516. int priority = -1;
  517. for (size_t i = 0; i < mMap.size(); ++i) {
  518. if (mMap.valueAt(i).size() == 0) {
  519. // no client on this process.
  520. continue;
  521. }
  522. if (!hasResourceType(type, mMap.valueAt(i))) {
  523. // doesn't have the requested resource type
  524. continue;
  525. }
  526. int tempPid = mMap.keyAt(i);
  527. int tempPriority;
  528. if (!mProcessInfo->getPriority(tempPid, &tempPriority)) {
  529. ALOGV("getLowestPriorityPid_l: can't get priority of pid %d, skipped", tempPid);
  530. // TODO: remove this pid from mMap?
  531. continue;
  532. }
  533. if (pid == -1 || tempPriority > priority) {
  534. // initial the value
  535. pid = tempPid;
  536. priority = tempPriority;
  537. }
  538. }
  539. if (pid != -1) {
  540. *lowestPriorityPid = pid;
  541. *lowestPriority = priority;
  542. }
  543. return (pid != -1);
  544. }
  545. bool ResourceManagerService::isCallingPriorityHigher_l(int callingPid, int pid) {
  546. int callingPidPriority;
  547. if (!mProcessInfo->getPriority(callingPid, &callingPidPriority)) {
  548. return false;
  549. }
  550. int priority;
  551. if (!mProcessInfo->getPriority(pid, &priority)) {
  552. return false;
  553. }
  554. return (callingPidPriority < priority);
  555. }
  556. bool ResourceManagerService::getBiggestClient_l(
  557. int pid, MediaResource::Type type, sp<IResourceManagerClient> *client) {
  558. ssize_t index = mMap.indexOfKey(pid);
  559. if (index < 0) {
  560. ALOGE("getBiggestClient_l: can't find resource info for pid %d", pid);
  561. return false;
  562. }
  563. sp<IResourceManagerClient> clientTemp;
  564. uint64_t largestValue = 0;
  565. const ResourceInfos &infos = mMap.valueAt(index);
  566. for (size_t i = 0; i < infos.size(); ++i) {
  567. const ResourceList &resources = infos[i].resources;
  568. for (auto it = resources.begin(); it != resources.end(); it++) {
  569. const MediaResource &resource = it->second;
  570. if (resource.mType == type) {
  571. if (resource.mValue > largestValue) {
  572. largestValue = resource.mValue;
  573. clientTemp = infos[i].client;
  574. }
  575. }
  576. }
  577. }
  578. if (clientTemp == NULL) {
  579. ALOGE("getBiggestClient_l: can't find resource type %s for pid %d", asString(type), pid);
  580. return false;
  581. }
  582. *client = clientTemp;
  583. return true;
  584. }
  585. } // namespace android