1 #include <errno.h> 2 #include <sched.h> 3 #include <stdio.h> 4 #include <sys/types.h> 5 #include <unistd.h> 6 7 #include <condition_variable> 8 #include <cstdlib> 9 #include <iostream> 10 #include <mutex> 11 #include <sstream> 12 #include <thread> 13 #include <utility> 14 15 #include <android-base/unique_fd.h> 16 #include <dvr/performance_client_api.h> 17 #include <gtest/gtest.h> 18 #include <private/android_filesystem_config.h> 19 20 #include "stdio_filebuf.h" 21 #include "string_trim.h" 22 #include "unique_file.h" 23 24 using android::dvr::Trim; 25 using android::dvr::UniqueFile; 26 using android::dvr::stdio_filebuf; 27 28 namespace { 29 30 const char kTrustedUidEnvironmentVariable[] = "GTEST_TRUSTED_UID"; 31 32 const char kProcBase[] = "/proc"; 33 34 std::pair<UniqueFile, int> OpenTaskFile(pid_t task_id, 35 const std::string& name) { 36 std::ostringstream stream; 37 stream << kProcBase << "/" << task_id << "/" << name; 38 39 UniqueFile file{fopen(stream.str().c_str(), "r")}; 40 const int error = file ? 0 : errno; 41 return {std::move(file), error}; 42 } 43 44 std::string GetTaskCpuSet(pid_t task_id) { 45 int error; 46 UniqueFile file; 47 48 std::tie(file, error) = OpenTaskFile(task_id, "cpuset"); 49 if (!file) 50 return std::string("errno:") + strerror(error); 51 52 stdio_filebuf<char> filebuf(file.get()); 53 std::istream file_stream(&filebuf); 54 55 std::string line; 56 std::getline(file_stream, line); 57 return Trim(line); 58 } 59 60 } // anonymous namespace 61 62 TEST(PerformanceTest, SetCpuPartition) { 63 int error; 64 65 // Test setting the the partition for the current task. 66 error = dvrSetCpuPartition(0, "/application/background"); 67 EXPECT_EQ(0, error); 68 69 error = dvrSetCpuPartition(0, "/application/performance"); 70 EXPECT_EQ(0, error); 71 72 // Test setting the partition for one of our tasks. 73 bool done = false; 74 pid_t task_id = 0; 75 std::mutex mutex; 76 std::condition_variable done_condition, id_condition; 77 78 std::thread thread([&] { 79 std::unique_lock<std::mutex> lock(mutex); 80 81 task_id = gettid(); 82 id_condition.notify_one(); 83 84 done_condition.wait(lock, [&done] { return done; }); 85 }); 86 87 { 88 std::unique_lock<std::mutex> lock(mutex); 89 id_condition.wait(lock, [&task_id] { return task_id != 0; }); 90 } 91 EXPECT_NE(0, task_id); 92 93 error = dvrSetCpuPartition(task_id, "/application"); 94 EXPECT_EQ(0, error); 95 96 { 97 std::lock_guard<std::mutex> lock(mutex); 98 done = true; 99 done_condition.notify_one(); 100 } 101 thread.join(); 102 103 // Test setting the partition for a task that doesn't belong to us. 104 error = dvrSetCpuPartition(1, "/application"); 105 EXPECT_EQ(-EINVAL, error); 106 107 // Test setting the partition to one that doesn't exist. 108 error = dvrSetCpuPartition(0, "/foobar"); 109 EXPECT_EQ(-ENOENT, error); 110 111 // Set the test back to the root partition. 112 error = dvrSetCpuPartition(0, "/"); 113 EXPECT_EQ(0, error); 114 } 115 116 TEST(PerformanceTest, SetSchedulerClass) { 117 int error; 118 119 // TODO(eieio): Test all supported scheduler classes and priority levels. 120 121 error = dvrSetSchedulerClass(0, "background"); 122 EXPECT_EQ(0, error); 123 EXPECT_EQ(SCHED_BATCH, sched_getscheduler(0)); 124 125 error = dvrSetSchedulerClass(0, "audio:low"); 126 EXPECT_EQ(0, error); 127 EXPECT_EQ(SCHED_FIFO | SCHED_RESET_ON_FORK, sched_getscheduler(0)); 128 129 error = dvrSetSchedulerClass(0, "normal"); 130 EXPECT_EQ(0, error); 131 EXPECT_EQ(SCHED_NORMAL, sched_getscheduler(0)); 132 133 error = dvrSetSchedulerClass(0, "foobar"); 134 EXPECT_EQ(-EINVAL, error); 135 } 136 137 TEST(PerformanceTest, SetSchedulerPolicy) { 138 int error; 139 140 error = dvrSetSchedulerPolicy(0, "background"); 141 EXPECT_EQ(0, error); 142 EXPECT_EQ(SCHED_BATCH, sched_getscheduler(0)); 143 144 error = dvrSetSchedulerPolicy(0, "audio:low"); 145 EXPECT_EQ(0, error); 146 EXPECT_EQ(SCHED_FIFO | SCHED_RESET_ON_FORK, sched_getscheduler(0)); 147 148 error = dvrSetSchedulerPolicy(0, "normal"); 149 EXPECT_EQ(0, error); 150 EXPECT_EQ(SCHED_NORMAL, sched_getscheduler(0)); 151 152 error = dvrSetSchedulerPolicy(0, "foobar"); 153 EXPECT_EQ(-EINVAL, error); 154 155 // Set the test back to the root partition. 156 error = dvrSetCpuPartition(0, "/"); 157 EXPECT_EQ(0, error); 158 159 const std::string original_cpuset = GetTaskCpuSet(gettid()); 160 EXPECT_EQ("/", original_cpuset); 161 162 error = dvrSetSchedulerPolicy(0, "vr:system:arp"); 163 EXPECT_EQ(0, error); 164 EXPECT_EQ(SCHED_FIFO | SCHED_RESET_ON_FORK, sched_getscheduler(0)); 165 166 const std::string new_cpuset = GetTaskCpuSet(gettid()); 167 EXPECT_NE(original_cpuset, new_cpuset); 168 169 // The cpuset for the thread group is now new_cpuset. Scheduler profiles that 170 // do not specify a cpuset should not change the cpuset of a thread, except to 171 // restore it to the thread group cpuset. 172 std::string thread_original_cpuset; 173 std::string thread_new_cpuset; 174 std::string thread_final_cpuset; 175 176 std::thread thread{ 177 [&thread_original_cpuset, &thread_new_cpuset, &thread_final_cpuset]() { 178 thread_original_cpuset = GetTaskCpuSet(gettid()); 179 180 int error = dvrSetSchedulerPolicy(0, "vr:app:render"); 181 EXPECT_EQ(0, error); 182 183 thread_new_cpuset = GetTaskCpuSet(gettid()); 184 185 error = dvrSetSchedulerPolicy(0, "normal"); 186 EXPECT_EQ(0, error); 187 188 thread_final_cpuset = GetTaskCpuSet(gettid()); 189 }}; 190 thread.join(); 191 192 EXPECT_EQ(new_cpuset, thread_original_cpuset); 193 EXPECT_NE(new_cpuset, thread_new_cpuset); 194 EXPECT_EQ(new_cpuset, thread_final_cpuset); 195 196 error = dvrSetCpuPartition(0, original_cpuset.c_str()); 197 EXPECT_EQ(0, error); 198 } 199 200 TEST(PerformanceTest, SchedulerClassResetOnFork) { 201 int error; 202 203 error = dvrSetSchedulerClass(0, "graphics:high"); 204 EXPECT_EQ(0, error); 205 EXPECT_EQ(SCHED_FIFO | SCHED_RESET_ON_FORK, sched_getscheduler(0)); 206 207 int scheduler = -1; 208 std::thread thread([&]() { scheduler = sched_getscheduler(0); }); 209 thread.join(); 210 211 EXPECT_EQ(SCHED_NORMAL, scheduler); 212 213 // Return to SCHED_NORMAL. 214 error = dvrSetSchedulerClass(0, "normal"); 215 EXPECT_EQ(0, error); 216 EXPECT_EQ(SCHED_NORMAL, sched_getscheduler(0)); 217 } 218 219 TEST(PerformanceTest, GetCpuPartition) { 220 int error; 221 char partition[PATH_MAX + 1]; 222 223 error = dvrSetCpuPartition(0, "/"); 224 ASSERT_EQ(0, error); 225 226 error = dvrGetCpuPartition(0, partition, sizeof(partition)); 227 EXPECT_EQ(0, error); 228 EXPECT_EQ("/", std::string(partition)); 229 230 error = dvrSetCpuPartition(0, "/application"); 231 EXPECT_EQ(0, error); 232 233 error = dvrGetCpuPartition(0, partition, sizeof(partition)); 234 EXPECT_EQ(0, error); 235 EXPECT_EQ("/application", std::string(partition)); 236 237 // Test passing a buffer that is too short. 238 error = dvrGetCpuPartition(0, partition, 5); 239 EXPECT_EQ(-ENOBUFS, error); 240 241 // Test getting the partition for a task that doesn't belong to us. 242 error = dvrGetCpuPartition(1, partition, sizeof(partition)); 243 EXPECT_EQ(-EINVAL, error); 244 245 // Test passing a nullptr value for partition buffer. 246 error = dvrGetCpuPartition(0, nullptr, sizeof(partition)); 247 EXPECT_EQ(-EINVAL, error); 248 } 249 250 TEST(PerformanceTest, Permissions) { 251 int error; 252 253 const int original_uid = getuid(); 254 const int original_gid = getgid(); 255 int trusted_uid = -1; 256 257 // See if the environment variable GTEST_TRUSTED_UID is set. If it is enable 258 // testing the ActivityManager trusted uid permission checks using that uid. 259 const char* trusted_uid_env = std::getenv(kTrustedUidEnvironmentVariable); 260 if (trusted_uid_env) 261 trusted_uid = std::atoi(trusted_uid_env); 262 263 ASSERT_EQ(AID_ROOT, original_uid) 264 << "This test must run as root to function correctly!"; 265 266 // Test unprivileged policies on a task that does not belong to this process. 267 // Use the init process (task_id=1) as the target. 268 error = dvrSetSchedulerPolicy(1, "batch"); 269 EXPECT_EQ(-EINVAL, error); 270 error = dvrSetSchedulerPolicy(1, "background"); 271 EXPECT_EQ(-EINVAL, error); 272 error = dvrSetSchedulerPolicy(1, "foreground"); 273 EXPECT_EQ(-EINVAL, error); 274 error = dvrSetSchedulerPolicy(1, "normal"); 275 EXPECT_EQ(-EINVAL, error); 276 277 // Switch the uid/gid to an id that should not have permission to access any 278 // privileged actions. 279 ASSERT_EQ(0, setresgid(AID_NOBODY, AID_NOBODY, -1)) 280 << "Failed to set gid: " << strerror(errno); 281 ASSERT_EQ(0, setresuid(AID_NOBODY, AID_NOBODY, -1)) 282 << "Failed to set uid: " << strerror(errno); 283 284 // Unprivileged policies. 285 error = dvrSetSchedulerPolicy(0, "batch"); 286 EXPECT_EQ(0, error); 287 error = dvrSetSchedulerPolicy(0, "background"); 288 EXPECT_EQ(0, error); 289 error = dvrSetSchedulerPolicy(0, "foreground"); 290 EXPECT_EQ(0, error); 291 error = dvrSetSchedulerPolicy(0, "normal"); 292 EXPECT_EQ(0, error); 293 294 // Privileged policies. 295 error = dvrSetSchedulerPolicy(0, "audio:low"); 296 EXPECT_EQ(-EINVAL, error); 297 error = dvrSetSchedulerPolicy(0, "audio:high"); 298 EXPECT_EQ(-EINVAL, error); 299 error = dvrSetSchedulerPolicy(0, "graphics"); 300 EXPECT_EQ(-EINVAL, error); 301 error = dvrSetSchedulerPolicy(0, "graphics:low"); 302 EXPECT_EQ(-EINVAL, error); 303 error = dvrSetSchedulerPolicy(0, "graphics:high"); 304 EXPECT_EQ(-EINVAL, error); 305 error = dvrSetSchedulerPolicy(0, "sensors"); 306 EXPECT_EQ(-EINVAL, error); 307 error = dvrSetSchedulerPolicy(0, "sensors:low"); 308 EXPECT_EQ(-EINVAL, error); 309 error = dvrSetSchedulerPolicy(0, "sensors:high"); 310 EXPECT_EQ(-EINVAL, error); 311 error = dvrSetSchedulerPolicy(0, "vr:system:arp"); 312 EXPECT_EQ(-EINVAL, error); 313 error = dvrSetSchedulerPolicy(0, "vr:app:render"); 314 EXPECT_EQ(-EINVAL, error); 315 316 // uid=AID_SYSTEM / gid=AID_NOBODY 317 ASSERT_EQ(0, setresuid(original_uid, original_uid, -1)) 318 << "Failed to restore uid: " << strerror(errno); 319 ASSERT_EQ(0, setresuid(AID_SYSTEM, AID_SYSTEM, -1)) 320 << "Failed to set uid: " << strerror(errno); 321 322 // Unprivileged policies. 323 error = dvrSetSchedulerPolicy(0, "batch"); 324 EXPECT_EQ(0, error); 325 error = dvrSetSchedulerPolicy(0, "background"); 326 EXPECT_EQ(0, error); 327 error = dvrSetSchedulerPolicy(0, "foreground"); 328 EXPECT_EQ(0, error); 329 error = dvrSetSchedulerPolicy(0, "normal"); 330 EXPECT_EQ(0, error); 331 332 // Privileged policies. 333 error = dvrSetSchedulerPolicy(0, "audio:low"); 334 EXPECT_EQ(0, error); 335 error = dvrSetSchedulerPolicy(0, "audio:high"); 336 EXPECT_EQ(0, error); 337 error = dvrSetSchedulerPolicy(0, "graphics"); 338 EXPECT_EQ(0, error); 339 error = dvrSetSchedulerPolicy(0, "graphics:low"); 340 EXPECT_EQ(0, error); 341 error = dvrSetSchedulerPolicy(0, "graphics:high"); 342 EXPECT_EQ(0, error); 343 error = dvrSetSchedulerPolicy(0, "sensors"); 344 EXPECT_EQ(0, error); 345 error = dvrSetSchedulerPolicy(0, "sensors:low"); 346 EXPECT_EQ(0, error); 347 error = dvrSetSchedulerPolicy(0, "sensors:high"); 348 EXPECT_EQ(0, error); 349 error = dvrSetSchedulerPolicy(0, "vr:system:arp"); 350 EXPECT_EQ(0, error); 351 error = dvrSetSchedulerPolicy(0, "vr:app:render"); 352 EXPECT_EQ(0, error); 353 354 // uid=AID_NOBODY / gid=AID_SYSTEM 355 ASSERT_EQ(0, setresuid(original_uid, original_uid, -1)) 356 << "Failed to restore uid: " << strerror(errno); 357 ASSERT_EQ(0, setresgid(original_gid, original_gid, -1)) 358 << "Failed to restore gid: " << strerror(errno); 359 ASSERT_EQ(0, setresgid(AID_SYSTEM, AID_SYSTEM, -1)) 360 << "Failed to set gid: " << strerror(errno); 361 ASSERT_EQ(0, setresuid(AID_SYSTEM, AID_NOBODY, -1)) 362 << "Failed to set uid: " << strerror(errno); 363 364 // Unprivileged policies. 365 error = dvrSetSchedulerPolicy(0, "batch"); 366 EXPECT_EQ(0, error); 367 error = dvrSetSchedulerPolicy(0, "background"); 368 EXPECT_EQ(0, error); 369 error = dvrSetSchedulerPolicy(0, "foreground"); 370 EXPECT_EQ(0, error); 371 error = dvrSetSchedulerPolicy(0, "normal"); 372 EXPECT_EQ(0, error); 373 374 // Privileged policies. 375 error = dvrSetSchedulerPolicy(0, "audio:low"); 376 EXPECT_EQ(0, error); 377 error = dvrSetSchedulerPolicy(0, "audio:high"); 378 EXPECT_EQ(0, error); 379 error = dvrSetSchedulerPolicy(0, "graphics"); 380 EXPECT_EQ(0, error); 381 error = dvrSetSchedulerPolicy(0, "graphics:low"); 382 EXPECT_EQ(0, error); 383 error = dvrSetSchedulerPolicy(0, "graphics:high"); 384 EXPECT_EQ(0, error); 385 error = dvrSetSchedulerPolicy(0, "sensors"); 386 EXPECT_EQ(0, error); 387 error = dvrSetSchedulerPolicy(0, "sensors:low"); 388 EXPECT_EQ(0, error); 389 error = dvrSetSchedulerPolicy(0, "sensors:high"); 390 EXPECT_EQ(0, error); 391 error = dvrSetSchedulerPolicy(0, "vr:system:arp"); 392 EXPECT_EQ(0, error); 393 error = dvrSetSchedulerPolicy(0, "vr:app:render"); 394 EXPECT_EQ(0, error); 395 396 // uid=AID_GRAPHICS / gid=AID_NOBODY 397 ASSERT_EQ(0, setresuid(original_uid, original_uid, -1)) 398 << "Failed to restore uid: " << strerror(errno); 399 ASSERT_EQ(0, setresgid(original_gid, original_gid, -1)) 400 << "Failed to restore gid: " << strerror(errno); 401 ASSERT_EQ(0, setresgid(AID_NOBODY, AID_NOBODY, -1)) 402 << "Failed to set gid: " << strerror(errno); 403 ASSERT_EQ(0, setresuid(AID_GRAPHICS, AID_GRAPHICS, -1)) 404 << "Failed to set uid: " << strerror(errno); 405 406 // Unprivileged policies. 407 error = dvrSetSchedulerPolicy(0, "batch"); 408 EXPECT_EQ(0, error); 409 error = dvrSetSchedulerPolicy(0, "background"); 410 EXPECT_EQ(0, error); 411 error = dvrSetSchedulerPolicy(0, "foreground"); 412 EXPECT_EQ(0, error); 413 error = dvrSetSchedulerPolicy(0, "normal"); 414 EXPECT_EQ(0, error); 415 416 // Privileged policies. 417 error = dvrSetSchedulerPolicy(0, "audio:low"); 418 EXPECT_EQ(-EINVAL, error); 419 error = dvrSetSchedulerPolicy(0, "audio:high"); 420 EXPECT_EQ(-EINVAL, error); 421 error = dvrSetSchedulerPolicy(0, "graphics"); 422 EXPECT_EQ(0, error); 423 error = dvrSetSchedulerPolicy(0, "graphics:low"); 424 EXPECT_EQ(0, error); 425 error = dvrSetSchedulerPolicy(0, "graphics:high"); 426 EXPECT_EQ(0, error); 427 error = dvrSetSchedulerPolicy(0, "sensors"); 428 EXPECT_EQ(-EINVAL, error); 429 error = dvrSetSchedulerPolicy(0, "sensors:low"); 430 EXPECT_EQ(-EINVAL, error); 431 error = dvrSetSchedulerPolicy(0, "sensors:high"); 432 EXPECT_EQ(-EINVAL, error); 433 error = dvrSetSchedulerPolicy(0, "vr:system:arp"); 434 EXPECT_EQ(-EINVAL, error); 435 error = dvrSetSchedulerPolicy(0, "vr:app:render"); 436 EXPECT_EQ(-EINVAL, error); 437 438 // uid=AID_NOBODY / gid=AID_GRAPHICS 439 ASSERT_EQ(0, setresuid(original_uid, original_uid, -1)) 440 << "Failed to restore uid: " << strerror(errno); 441 ASSERT_EQ(0, setresgid(original_gid, original_gid, -1)) 442 << "Failed to restore gid: " << strerror(errno); 443 ASSERT_EQ(0, setresgid(AID_GRAPHICS, AID_GRAPHICS, -1)) 444 << "Failed to set gid: " << strerror(errno); 445 ASSERT_EQ(0, setresuid(AID_NOBODY, AID_NOBODY, -1)) 446 << "Failed to set uid: " << strerror(errno); 447 448 // Unprivileged policies. 449 error = dvrSetSchedulerPolicy(0, "batch"); 450 EXPECT_EQ(0, error); 451 error = dvrSetSchedulerPolicy(0, "background"); 452 EXPECT_EQ(0, error); 453 error = dvrSetSchedulerPolicy(0, "foreground"); 454 EXPECT_EQ(0, error); 455 error = dvrSetSchedulerPolicy(0, "normal"); 456 EXPECT_EQ(0, error); 457 458 // Privileged policies. 459 error = dvrSetSchedulerPolicy(0, "audio:low"); 460 EXPECT_EQ(-EINVAL, error); 461 error = dvrSetSchedulerPolicy(0, "audio:high"); 462 EXPECT_EQ(-EINVAL, error); 463 error = dvrSetSchedulerPolicy(0, "graphics"); 464 EXPECT_EQ(0, error); 465 error = dvrSetSchedulerPolicy(0, "graphics:low"); 466 EXPECT_EQ(0, error); 467 error = dvrSetSchedulerPolicy(0, "graphics:high"); 468 EXPECT_EQ(0, error); 469 error = dvrSetSchedulerPolicy(0, "sensors"); 470 EXPECT_EQ(-EINVAL, error); 471 error = dvrSetSchedulerPolicy(0, "sensors:low"); 472 EXPECT_EQ(-EINVAL, error); 473 error = dvrSetSchedulerPolicy(0, "sensors:high"); 474 EXPECT_EQ(-EINVAL, error); 475 error = dvrSetSchedulerPolicy(0, "vr:system:arp"); 476 EXPECT_EQ(-EINVAL, error); 477 error = dvrSetSchedulerPolicy(0, "vr:app:render"); 478 EXPECT_EQ(-EINVAL, error); 479 480 if (trusted_uid != -1) { 481 // uid=<trusted uid> / gid=AID_NOBODY 482 ASSERT_EQ(0, setresuid(original_uid, original_uid, -1)) 483 << "Failed to restore uid: " << strerror(errno); 484 ASSERT_EQ(0, setresgid(original_gid, original_gid, -1)) 485 << "Failed to restore gid: " << strerror(errno); 486 ASSERT_EQ(0, setresgid(AID_NOBODY, AID_NOBODY, -1)) 487 << "Failed to set gid: " << strerror(errno); 488 ASSERT_EQ(0, setresuid(trusted_uid, trusted_uid, -1)) 489 << "Failed to set uid: " << strerror(errno); 490 491 // Unprivileged policies. 492 error = dvrSetSchedulerPolicy(0, "batch"); 493 EXPECT_EQ(0, error); 494 error = dvrSetSchedulerPolicy(0, "background"); 495 EXPECT_EQ(0, error); 496 error = dvrSetSchedulerPolicy(0, "foreground"); 497 EXPECT_EQ(0, error); 498 error = dvrSetSchedulerPolicy(0, "normal"); 499 EXPECT_EQ(0, error); 500 501 // Privileged policies. 502 error = dvrSetSchedulerPolicy(0, "audio:low"); 503 EXPECT_EQ(-EINVAL, error); 504 error = dvrSetSchedulerPolicy(0, "audio:high"); 505 EXPECT_EQ(-EINVAL, error); 506 error = dvrSetSchedulerPolicy(0, "graphics"); 507 EXPECT_EQ(-EINVAL, error); 508 error = dvrSetSchedulerPolicy(0, "graphics:low"); 509 EXPECT_EQ(-EINVAL, error); 510 error = dvrSetSchedulerPolicy(0, "graphics:high"); 511 EXPECT_EQ(-EINVAL, error); 512 error = dvrSetSchedulerPolicy(0, "sensors"); 513 EXPECT_EQ(-EINVAL, error); 514 error = dvrSetSchedulerPolicy(0, "sensors:low"); 515 EXPECT_EQ(-EINVAL, error); 516 error = dvrSetSchedulerPolicy(0, "sensors:high"); 517 EXPECT_EQ(-EINVAL, error); 518 error = dvrSetSchedulerPolicy(0, "vr:system:arp"); 519 EXPECT_EQ(0, error); 520 error = dvrSetSchedulerPolicy(0, "vr:app:render"); 521 EXPECT_EQ(0, error); 522 } 523 524 // Restore original effective uid/gid. 525 ASSERT_EQ(0, setresgid(original_gid, original_gid, -1)) 526 << "Failed to restore gid: " << strerror(errno); 527 ASSERT_EQ(0, setresuid(original_uid, original_uid, -1)) 528 << "Failed to restore uid: " << strerror(errno); 529 } 530