1 /* 2 * Copyright 2015 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 17 //#define LOG_NDEBUG 0 18 #define LOG_TAG "ResourceManagerService_test" 19 #include <utils/Log.h> 20 21 #include <gtest/gtest.h> 22 23 #include "ResourceManagerService.h" 24 #include <media/IResourceManagerService.h> 25 #include <media/MediaResource.h> 26 #include <media/MediaResourcePolicy.h> 27 #include <media/stagefright/foundation/ADebug.h> 28 #include <media/stagefright/ProcessInfoInterface.h> 29 30 namespace android { 31 32 static int64_t getId(const sp<IResourceManagerClient>& client) { 33 return (int64_t) client.get(); 34 } 35 36 struct TestProcessInfo : public ProcessInfoInterface { 37 TestProcessInfo() {} 38 virtual ~TestProcessInfo() {} 39 40 virtual bool getPriority(int pid, int *priority) { 41 // For testing, use pid as priority. 42 // Lower the value higher the priority. 43 *priority = pid; 44 return true; 45 } 46 47 virtual bool isValidPid(int /* pid */) { 48 return true; 49 } 50 51 private: 52 DISALLOW_EVIL_CONSTRUCTORS(TestProcessInfo); 53 }; 54 55 struct TestClient : public BnResourceManagerClient { 56 TestClient(int pid, sp<ResourceManagerService> service) 57 : mReclaimed(false), mPid(pid), mService(service) {} 58 59 virtual bool reclaimResource() { 60 sp<IResourceManagerClient> client(this); 61 mService->removeResource(mPid, (int64_t) client.get()); 62 mReclaimed = true; 63 return true; 64 } 65 66 virtual String8 getName() { 67 return String8("test_client"); 68 } 69 70 bool reclaimed() const { 71 return mReclaimed; 72 } 73 74 void reset() { 75 mReclaimed = false; 76 } 77 78 protected: 79 virtual ~TestClient() {} 80 81 private: 82 bool mReclaimed; 83 int mPid; 84 sp<ResourceManagerService> mService; 85 DISALLOW_EVIL_CONSTRUCTORS(TestClient); 86 }; 87 88 static const int kTestPid1 = 30; 89 static const int kTestPid2 = 20; 90 91 static const int kLowPriorityPid = 40; 92 static const int kMidPriorityPid = 25; 93 static const int kHighPriorityPid = 10; 94 95 class ResourceManagerServiceTest : public ::testing::Test { 96 public: 97 ResourceManagerServiceTest() 98 : mService(new ResourceManagerService(new TestProcessInfo)), 99 mTestClient1(new TestClient(kTestPid1, mService)), 100 mTestClient2(new TestClient(kTestPid2, mService)), 101 mTestClient3(new TestClient(kTestPid2, mService)) { 102 } 103 104 protected: 105 static bool isEqualResources(const Vector<MediaResource> &resources1, 106 const Vector<MediaResource> &resources2) { 107 if (resources1.size() != resources2.size()) { 108 return false; 109 } 110 for (size_t i = 0; i < resources1.size(); ++i) { 111 if (resources1[i] != resources2[i]) { 112 return false; 113 } 114 } 115 return true; 116 } 117 118 static void expectEqResourceInfo(const ResourceInfo &info, sp<IResourceManagerClient> client, 119 const Vector<MediaResource> &resources) { 120 EXPECT_EQ(client, info.client); 121 EXPECT_TRUE(isEqualResources(resources, info.resources)); 122 } 123 124 void verifyClients(bool c1, bool c2, bool c3) { 125 TestClient *client1 = static_cast<TestClient*>(mTestClient1.get()); 126 TestClient *client2 = static_cast<TestClient*>(mTestClient2.get()); 127 TestClient *client3 = static_cast<TestClient*>(mTestClient3.get()); 128 129 EXPECT_EQ(c1, client1->reclaimed()); 130 EXPECT_EQ(c2, client2->reclaimed()); 131 EXPECT_EQ(c3, client3->reclaimed()); 132 133 client1->reset(); 134 client2->reset(); 135 client3->reset(); 136 } 137 138 // test set up 139 // --------------------------------------------------------------------------------- 140 // pid priority client type number 141 // --------------------------------------------------------------------------------- 142 // kTestPid1(30) 30 mTestClient1 secure codec 1 143 // graphic memory 200 144 // graphic memory 200 145 // --------------------------------------------------------------------------------- 146 // kTestPid2(20) 20 mTestClient2 non-secure codec 1 147 // graphic memory 300 148 // ------------------------------------------- 149 // mTestClient3 secure codec 1 150 // graphic memory 100 151 // --------------------------------------------------------------------------------- 152 void addResource() { 153 // kTestPid1 mTestClient1 154 Vector<MediaResource> resources1; 155 resources1.push_back(MediaResource(MediaResource::kSecureCodec, 1)); 156 mService->addResource(kTestPid1, getId(mTestClient1), mTestClient1, resources1); 157 resources1.push_back(MediaResource(MediaResource::kGraphicMemory, 200)); 158 Vector<MediaResource> resources11; 159 resources11.push_back(MediaResource(MediaResource::kGraphicMemory, 200)); 160 mService->addResource(kTestPid1, getId(mTestClient1), mTestClient1, resources11); 161 162 // kTestPid2 mTestClient2 163 Vector<MediaResource> resources2; 164 resources2.push_back(MediaResource(MediaResource::kNonSecureCodec, 1)); 165 resources2.push_back(MediaResource(MediaResource::kGraphicMemory, 300)); 166 mService->addResource(kTestPid2, getId(mTestClient2), mTestClient2, resources2); 167 168 // kTestPid2 mTestClient3 169 Vector<MediaResource> resources3; 170 mService->addResource(kTestPid2, getId(mTestClient3), mTestClient3, resources3); 171 resources3.push_back(MediaResource(MediaResource::kSecureCodec, 1)); 172 resources3.push_back(MediaResource(MediaResource::kGraphicMemory, 100)); 173 mService->addResource(kTestPid2, getId(mTestClient3), mTestClient3, resources3); 174 175 const PidResourceInfosMap &map = mService->mMap; 176 EXPECT_EQ(2u, map.size()); 177 ssize_t index1 = map.indexOfKey(kTestPid1); 178 ASSERT_GE(index1, 0); 179 const ResourceInfos &infos1 = map[index1]; 180 EXPECT_EQ(1u, infos1.size()); 181 expectEqResourceInfo(infos1[0], mTestClient1, resources1); 182 183 ssize_t index2 = map.indexOfKey(kTestPid2); 184 ASSERT_GE(index2, 0); 185 const ResourceInfos &infos2 = map[index2]; 186 EXPECT_EQ(2u, infos2.size()); 187 expectEqResourceInfo(infos2[0], mTestClient2, resources2); 188 expectEqResourceInfo(infos2[1], mTestClient3, resources3); 189 } 190 191 void testConfig() { 192 EXPECT_TRUE(mService->mSupportsMultipleSecureCodecs); 193 EXPECT_TRUE(mService->mSupportsSecureWithNonSecureCodec); 194 195 Vector<MediaResourcePolicy> policies1; 196 policies1.push_back( 197 MediaResourcePolicy( 198 String8(kPolicySupportsMultipleSecureCodecs), 199 String8("true"))); 200 policies1.push_back( 201 MediaResourcePolicy( 202 String8(kPolicySupportsSecureWithNonSecureCodec), 203 String8("false"))); 204 mService->config(policies1); 205 EXPECT_TRUE(mService->mSupportsMultipleSecureCodecs); 206 EXPECT_FALSE(mService->mSupportsSecureWithNonSecureCodec); 207 208 Vector<MediaResourcePolicy> policies2; 209 policies2.push_back( 210 MediaResourcePolicy( 211 String8(kPolicySupportsMultipleSecureCodecs), 212 String8("false"))); 213 policies2.push_back( 214 MediaResourcePolicy( 215 String8(kPolicySupportsSecureWithNonSecureCodec), 216 String8("true"))); 217 mService->config(policies2); 218 EXPECT_FALSE(mService->mSupportsMultipleSecureCodecs); 219 EXPECT_TRUE(mService->mSupportsSecureWithNonSecureCodec); 220 } 221 222 void testRemoveResource() { 223 addResource(); 224 225 mService->removeResource(kTestPid2, getId(mTestClient2)); 226 227 const PidResourceInfosMap &map = mService->mMap; 228 EXPECT_EQ(2u, map.size()); 229 const ResourceInfos &infos1 = map.valueFor(kTestPid1); 230 const ResourceInfos &infos2 = map.valueFor(kTestPid2); 231 EXPECT_EQ(1u, infos1.size()); 232 EXPECT_EQ(1u, infos2.size()); 233 // mTestClient2 has been removed. 234 EXPECT_EQ(mTestClient3, infos2[0].client); 235 } 236 237 void testGetAllClients() { 238 addResource(); 239 240 MediaResource::Type type = MediaResource::kSecureCodec; 241 Vector<sp<IResourceManagerClient> > clients; 242 EXPECT_FALSE(mService->getAllClients_l(kLowPriorityPid, type, &clients)); 243 // some higher priority process (e.g. kTestPid2) owns the resource, so getAllClients_l 244 // will fail. 245 EXPECT_FALSE(mService->getAllClients_l(kMidPriorityPid, type, &clients)); 246 EXPECT_TRUE(mService->getAllClients_l(kHighPriorityPid, type, &clients)); 247 248 EXPECT_EQ(2u, clients.size()); 249 EXPECT_EQ(mTestClient3, clients[0]); 250 EXPECT_EQ(mTestClient1, clients[1]); 251 } 252 253 void testReclaimResourceSecure() { 254 Vector<MediaResource> resources; 255 resources.push_back(MediaResource(MediaResource::kSecureCodec, 1)); 256 resources.push_back(MediaResource(MediaResource::kGraphicMemory, 150)); 257 258 // ### secure codec can't coexist and secure codec can coexist with non-secure codec ### 259 { 260 addResource(); 261 mService->mSupportsMultipleSecureCodecs = false; 262 mService->mSupportsSecureWithNonSecureCodec = true; 263 264 // priority too low 265 EXPECT_FALSE(mService->reclaimResource(kLowPriorityPid, resources)); 266 EXPECT_FALSE(mService->reclaimResource(kMidPriorityPid, resources)); 267 268 // reclaim all secure codecs 269 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources)); 270 verifyClients(true /* c1 */, false /* c2 */, true /* c3 */); 271 272 // call again should reclaim one largest graphic memory from lowest process 273 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources)); 274 verifyClients(false /* c1 */, true /* c2 */, false /* c3 */); 275 276 // nothing left 277 EXPECT_FALSE(mService->reclaimResource(kHighPriorityPid, resources)); 278 } 279 280 // ### secure codecs can't coexist and secure codec can't coexist with non-secure codec ### 281 { 282 addResource(); 283 mService->mSupportsMultipleSecureCodecs = false; 284 mService->mSupportsSecureWithNonSecureCodec = false; 285 286 // priority too low 287 EXPECT_FALSE(mService->reclaimResource(kLowPriorityPid, resources)); 288 EXPECT_FALSE(mService->reclaimResource(kMidPriorityPid, resources)); 289 290 // reclaim all secure and non-secure codecs 291 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources)); 292 verifyClients(true /* c1 */, true /* c2 */, true /* c3 */); 293 294 // nothing left 295 EXPECT_FALSE(mService->reclaimResource(kHighPriorityPid, resources)); 296 } 297 298 299 // ### secure codecs can coexist but secure codec can't coexist with non-secure codec ### 300 { 301 addResource(); 302 mService->mSupportsMultipleSecureCodecs = true; 303 mService->mSupportsSecureWithNonSecureCodec = false; 304 305 // priority too low 306 EXPECT_FALSE(mService->reclaimResource(kLowPriorityPid, resources)); 307 EXPECT_FALSE(mService->reclaimResource(kMidPriorityPid, resources)); 308 309 // reclaim all non-secure codecs 310 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources)); 311 verifyClients(false /* c1 */, true /* c2 */, false /* c3 */); 312 313 // call again should reclaim one largest graphic memory from lowest process 314 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources)); 315 verifyClients(true /* c1 */, false /* c2 */, false /* c3 */); 316 317 // call again should reclaim another largest graphic memory from lowest process 318 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources)); 319 verifyClients(false /* c1 */, false /* c2 */, true /* c3 */); 320 321 // nothing left 322 EXPECT_FALSE(mService->reclaimResource(kHighPriorityPid, resources)); 323 } 324 325 // ### secure codecs can coexist and secure codec can coexist with non-secure codec ### 326 { 327 addResource(); 328 mService->mSupportsMultipleSecureCodecs = true; 329 mService->mSupportsSecureWithNonSecureCodec = true; 330 331 // priority too low 332 EXPECT_FALSE(mService->reclaimResource(kLowPriorityPid, resources)); 333 334 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources)); 335 // one largest graphic memory from lowest process got reclaimed 336 verifyClients(true /* c1 */, false /* c2 */, false /* c3 */); 337 338 // call again should reclaim another graphic memory from lowest process 339 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources)); 340 verifyClients(false /* c1 */, true /* c2 */, false /* c3 */); 341 342 // call again should reclaim another graphic memory from lowest process 343 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources)); 344 verifyClients(false /* c1 */, false /* c2 */, true /* c3 */); 345 346 // nothing left 347 EXPECT_FALSE(mService->reclaimResource(kHighPriorityPid, resources)); 348 } 349 350 // ### secure codecs can coexist and secure codec can coexist with non-secure codec ### 351 { 352 addResource(); 353 mService->mSupportsMultipleSecureCodecs = true; 354 mService->mSupportsSecureWithNonSecureCodec = true; 355 356 Vector<MediaResource> resources; 357 resources.push_back(MediaResource(MediaResource::kSecureCodec, 1)); 358 359 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources)); 360 // secure codec from lowest process got reclaimed 361 verifyClients(true /* c1 */, false /* c2 */, false /* c3 */); 362 363 // call again should reclaim another secure codec from lowest process 364 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources)); 365 verifyClients(false /* c1 */, false /* c2 */, true /* c3 */); 366 367 // no more secure codec, non-secure codec will be reclaimed. 368 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources)); 369 verifyClients(false /* c1 */, true /* c2 */, false /* c3 */); 370 } 371 } 372 373 void testReclaimResourceNonSecure() { 374 Vector<MediaResource> resources; 375 resources.push_back(MediaResource(MediaResource::kNonSecureCodec, 1)); 376 resources.push_back(MediaResource(MediaResource::kGraphicMemory, 150)); 377 378 // ### secure codec can't coexist with non-secure codec ### 379 { 380 addResource(); 381 mService->mSupportsSecureWithNonSecureCodec = false; 382 383 // priority too low 384 EXPECT_FALSE(mService->reclaimResource(kLowPriorityPid, resources)); 385 EXPECT_FALSE(mService->reclaimResource(kMidPriorityPid, resources)); 386 387 // reclaim all secure codecs 388 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources)); 389 verifyClients(true /* c1 */, false /* c2 */, true /* c3 */); 390 391 // call again should reclaim one graphic memory from lowest process 392 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources)); 393 verifyClients(false /* c1 */, true /* c2 */, false /* c3 */); 394 395 // nothing left 396 EXPECT_FALSE(mService->reclaimResource(kHighPriorityPid, resources)); 397 } 398 399 400 // ### secure codec can coexist with non-secure codec ### 401 { 402 addResource(); 403 mService->mSupportsSecureWithNonSecureCodec = true; 404 405 // priority too low 406 EXPECT_FALSE(mService->reclaimResource(kLowPriorityPid, resources)); 407 408 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources)); 409 // one largest graphic memory from lowest process got reclaimed 410 verifyClients(true /* c1 */, false /* c2 */, false /* c3 */); 411 412 // call again should reclaim another graphic memory from lowest process 413 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources)); 414 verifyClients(false /* c1 */, true /* c2 */, false /* c3 */); 415 416 // call again should reclaim another graphic memory from lowest process 417 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources)); 418 verifyClients(false /* c1 */, false /* c2 */, true /* c3 */); 419 420 // nothing left 421 EXPECT_FALSE(mService->reclaimResource(kHighPriorityPid, resources)); 422 } 423 424 // ### secure codec can coexist with non-secure codec ### 425 { 426 addResource(); 427 mService->mSupportsSecureWithNonSecureCodec = true; 428 429 Vector<MediaResource> resources; 430 resources.push_back(MediaResource(MediaResource::kNonSecureCodec, 1)); 431 432 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources)); 433 // one non secure codec from lowest process got reclaimed 434 verifyClients(false /* c1 */, true /* c2 */, false /* c3 */); 435 436 // no more non-secure codec, secure codec from lowest priority process will be reclaimed 437 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources)); 438 verifyClients(true /* c1 */, false /* c2 */, false /* c3 */); 439 440 // clean up client 3 which still left 441 mService->removeResource(kTestPid2, getId(mTestClient3)); 442 } 443 } 444 445 void testGetLowestPriorityBiggestClient() { 446 MediaResource::Type type = MediaResource::kGraphicMemory; 447 sp<IResourceManagerClient> client; 448 EXPECT_FALSE(mService->getLowestPriorityBiggestClient_l(kHighPriorityPid, type, &client)); 449 450 addResource(); 451 452 EXPECT_FALSE(mService->getLowestPriorityBiggestClient_l(kLowPriorityPid, type, &client)); 453 EXPECT_TRUE(mService->getLowestPriorityBiggestClient_l(kHighPriorityPid, type, &client)); 454 455 // kTestPid1 is the lowest priority process with MediaResource::kGraphicMemory. 456 // mTestClient1 has the largest MediaResource::kGraphicMemory within kTestPid1. 457 EXPECT_EQ(mTestClient1, client); 458 } 459 460 void testGetLowestPriorityPid() { 461 int pid; 462 int priority; 463 TestProcessInfo processInfo; 464 465 MediaResource::Type type = MediaResource::kGraphicMemory; 466 EXPECT_FALSE(mService->getLowestPriorityPid_l(type, &pid, &priority)); 467 468 addResource(); 469 470 EXPECT_TRUE(mService->getLowestPriorityPid_l(type, &pid, &priority)); 471 EXPECT_EQ(kTestPid1, pid); 472 int priority1; 473 processInfo.getPriority(kTestPid1, &priority1); 474 EXPECT_EQ(priority1, priority); 475 476 type = MediaResource::kNonSecureCodec; 477 EXPECT_TRUE(mService->getLowestPriorityPid_l(type, &pid, &priority)); 478 EXPECT_EQ(kTestPid2, pid); 479 int priority2; 480 processInfo.getPriority(kTestPid2, &priority2); 481 EXPECT_EQ(priority2, priority); 482 } 483 484 void testGetBiggestClient() { 485 MediaResource::Type type = MediaResource::kGraphicMemory; 486 sp<IResourceManagerClient> client; 487 EXPECT_FALSE(mService->getBiggestClient_l(kTestPid2, type, &client)); 488 489 addResource(); 490 491 EXPECT_TRUE(mService->getBiggestClient_l(kTestPid2, type, &client)); 492 EXPECT_EQ(mTestClient2, client); 493 } 494 495 void testIsCallingPriorityHigher() { 496 EXPECT_FALSE(mService->isCallingPriorityHigher_l(101, 100)); 497 EXPECT_FALSE(mService->isCallingPriorityHigher_l(100, 100)); 498 EXPECT_TRUE(mService->isCallingPriorityHigher_l(99, 100)); 499 } 500 501 sp<ResourceManagerService> mService; 502 sp<IResourceManagerClient> mTestClient1; 503 sp<IResourceManagerClient> mTestClient2; 504 sp<IResourceManagerClient> mTestClient3; 505 }; 506 507 TEST_F(ResourceManagerServiceTest, config) { 508 testConfig(); 509 } 510 511 TEST_F(ResourceManagerServiceTest, addResource) { 512 addResource(); 513 } 514 515 TEST_F(ResourceManagerServiceTest, removeResource) { 516 testRemoveResource(); 517 } 518 519 TEST_F(ResourceManagerServiceTest, reclaimResource) { 520 testReclaimResourceSecure(); 521 testReclaimResourceNonSecure(); 522 } 523 524 TEST_F(ResourceManagerServiceTest, getAllClients_l) { 525 testGetAllClients(); 526 } 527 528 TEST_F(ResourceManagerServiceTest, getLowestPriorityBiggestClient_l) { 529 testGetLowestPriorityBiggestClient(); 530 } 531 532 TEST_F(ResourceManagerServiceTest, getLowestPriorityPid_l) { 533 testGetLowestPriorityPid(); 534 } 535 536 TEST_F(ResourceManagerServiceTest, getBiggestClient_l) { 537 testGetBiggestClient(); 538 } 539 540 TEST_F(ResourceManagerServiceTest, isCallingPriorityHigher_l) { 541 testIsCallingPriorityHigher(); 542 } 543 544 } // namespace android 545