1 /* <lambda>null2 * Copyright (C) 2018 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 package android.app.appops.cts 18 19 import android.app.AppOpsManager 20 import android.app.AppOpsManager.HistoricalOp 21 import android.app.AppOpsManager.HistoricalOps 22 import android.app.AppOpsManager.OPSTR_REQUEST_DELETE_PACKAGES 23 import android.app.AppOpsManager.OP_FLAGS_ALL 24 import android.os.Process 25 import android.os.SystemClock 26 import androidx.test.InstrumentationRegistry 27 import androidx.test.rule.ActivityTestRule 28 import androidx.test.runner.AndroidJUnit4 29 import androidx.test.uiautomator.UiDevice 30 import com.google.common.truth.Truth.assertThat 31 import java.time.Instant 32 import java.util.concurrent.TimeUnit 33 import java.util.concurrent.locks.ReentrantLock 34 import java.util.function.Consumer 35 import org.junit.After 36 import org.junit.Before 37 import org.junit.Rule 38 import org.junit.Test 39 import org.junit.runner.RunWith 40 41 @RunWith(AndroidJUnit4::class) 42 class HistoricalAppopsTest { 43 private val uid = Process.myUid() 44 private lateinit var appOpsManager: AppOpsManager 45 private lateinit var packageName: String 46 47 // Start an activity to make sure this app counts as being in the foreground 48 @Rule @JvmField 49 var activityRule = ActivityTestRule(UidStateForceActivity::class.java) 50 51 @Before 52 fun wakeScreenUp() { 53 val uiDevice = UiDevice.getInstance(instrumentation) 54 uiDevice.wakeUp() 55 uiDevice.executeShellCommand("wm dismiss-keyguard") 56 } 57 58 @Before 59 fun setUpTest() { 60 appOpsManager = context.getSystemService(AppOpsManager::class.java)!! 61 packageName = context.packageName!! 62 runWithShellPermissionIdentity { 63 appOpsManager.clearHistory() 64 appOpsManager.resetHistoryParameters() 65 } 66 } 67 68 @After 69 fun tearDownTest() { 70 runWithShellPermissionIdentity { 71 appOpsManager.clearHistory() 72 appOpsManager.resetHistoryParameters() 73 } 74 } 75 76 @Test 77 fun testGetHistoricalPackageOpsForegroundAccessInMemoryBucket() { 78 testGetHistoricalPackageOpsForegroundAtDepth(0) 79 } 80 81 @Test 82 fun testGetHistoricalPackageOpsForegroundAccessFirstOnDiskBucket() { 83 testGetHistoricalPackageOpsForegroundAtDepth(1) 84 } 85 86 @Test 87 fun testHistoricalAggregationOneLevelsDeep() { 88 testHistoricalAggregationSomeLevelsDeep(0) 89 } 90 91 @Test 92 fun testHistoricalAggregationTwoLevelsDeep() { 93 testHistoricalAggregationSomeLevelsDeep(1) 94 } 95 96 @Test 97 fun testRebootHistory() { 98 // Configure historical registry behavior. 99 setHistoryParameters( 100 AppOpsManager.HISTORICAL_MODE_ENABLED_PASSIVE, 101 SNAPSHOT_INTERVAL_MILLIS, 102 INTERVAL_COMPRESSION_MULTIPLIER) 103 104 // Add the data to the history 105 val chunk = createDataChunk() 106 val chunkCount = (INTERVAL_COMPRESSION_MULTIPLIER * 2) + 3 107 for (i in 0 until chunkCount) { 108 addHistoricalOps(chunk) 109 } 110 111 // Validate the data for the first interval 112 val firstIntervalBeginMillis = computeIntervalBeginRawMillis(0) 113 val firstIntervalEndMillis = computeIntervalBeginRawMillis(1) 114 var firstOps = getHistoricalOpsFromDiskRaw(uid, packageName, null /*opNames*/, 115 firstIntervalBeginMillis, firstIntervalEndMillis) 116 assertHasCounts(firstOps!!, 197) 117 118 // Validate the data for the second interval 119 val secondIntervalBeginMillis = computeIntervalBeginRawMillis(1) 120 val secondIntervalEndMillis = computeIntervalBeginRawMillis(2) 121 var secondOps = getHistoricalOpsFromDiskRaw(uid, packageName, null /*opNames*/, 122 secondIntervalBeginMillis, secondIntervalEndMillis) 123 assertHasCounts(secondOps!!, 33) 124 125 // Validate the data for all intervals 126 val everythingIntervalBeginMillis = Instant.EPOCH.toEpochMilli() 127 val everythingIntervalEndMillis = Long.MAX_VALUE 128 var allOps = getHistoricalOpsFromDiskRaw(uid, packageName, null /*opNames*/, 129 everythingIntervalBeginMillis, everythingIntervalEndMillis) 130 assertHasCounts(allOps!!, 230) 131 132 // Now reboot the history 133 runWithShellPermissionIdentity { 134 appOpsManager.rebootHistory(firstIntervalEndMillis) 135 } 136 137 // Validate the data for the first interval 138 firstOps = getHistoricalOpsFromDiskRaw(uid, packageName, null /*opNames*/, 139 firstIntervalBeginMillis, firstIntervalEndMillis) 140 assertHasCounts(firstOps!!, 0) 141 142 // Validate the data for the second interval 143 secondOps = getHistoricalOpsFromDiskRaw(uid, packageName, null /*opNames*/, 144 secondIntervalBeginMillis, secondIntervalEndMillis) 145 assertHasCounts(secondOps!!, 230) 146 147 // Validate the data for all intervals 148 allOps = getHistoricalOpsFromDiskRaw(uid, packageName, null /*opNames*/, 149 everythingIntervalBeginMillis, everythingIntervalEndMillis) 150 assertHasCounts(allOps!!, 230) 151 152 // Write some more ops to the first interval 153 for (i in 0 until chunkCount) { 154 addHistoricalOps(chunk) 155 } 156 157 // Validate the data for the first interval 158 firstOps = getHistoricalOpsFromDiskRaw(uid, packageName, null /*opNames*/, 159 firstIntervalBeginMillis, firstIntervalEndMillis) 160 assertHasCounts(firstOps!!, 197) 161 162 // Validate the data for the second interval 163 secondOps = getHistoricalOpsFromDiskRaw(uid, packageName, null /*opNames*/, 164 secondIntervalBeginMillis, secondIntervalEndMillis) 165 assertHasCounts(secondOps!!, 263) 166 167 // Validate the data for all intervals 168 allOps = getHistoricalOpsFromDiskRaw(uid, packageName, null /*opNames*/, 169 everythingIntervalBeginMillis, everythingIntervalEndMillis) 170 assertHasCounts(allOps!!, 460) 171 } 172 173 @Test 174 fun testHistoricalAggregationOverflow() { 175 // Configure historical registry behavior. 176 setHistoryParameters( 177 AppOpsManager.HISTORICAL_MODE_ENABLED_PASSIVE, 178 SNAPSHOT_INTERVAL_MILLIS, 179 INTERVAL_COMPRESSION_MULTIPLIER) 180 181 // Add the data to the history 182 val chunk = createDataChunk() 183 val chunkCount = (INTERVAL_COMPRESSION_MULTIPLIER * 2) + 3 184 for (i in 0 until chunkCount) { 185 addHistoricalOps(chunk) 186 } 187 188 // Validate the data for the first interval 189 val firstIntervalBeginMillis = computeIntervalBeginRawMillis(0) 190 val firstIntervalEndMillis = computeIntervalBeginRawMillis(1) 191 val firstOps = getHistoricalOpsFromDiskRaw(uid, packageName, null /*opNames*/, 192 firstIntervalBeginMillis, firstIntervalEndMillis) 193 assertHasCounts(firstOps!!, 197) 194 195 // Validate the data for the second interval 196 val secondIntervalBeginMillis = computeIntervalBeginRawMillis(1) 197 val secondIntervalEndMillis = computeIntervalBeginRawMillis(2) 198 val secondOps = getHistoricalOpsFromDiskRaw(uid, packageName, null /*opNames*/, 199 secondIntervalBeginMillis, secondIntervalEndMillis) 200 assertHasCounts(secondOps!!, 33) 201 202 // Validate the data for both intervals 203 val thirdIntervalBeginMillis = firstIntervalEndMillis - SNAPSHOT_INTERVAL_MILLIS 204 val thirdIntervalEndMillis = secondIntervalBeginMillis + SNAPSHOT_INTERVAL_MILLIS 205 val thirdOps = getHistoricalOpsFromDiskRaw(uid, packageName, null /*opNames*/, 206 thirdIntervalBeginMillis, thirdIntervalEndMillis) 207 assertHasCounts(thirdOps!!, 33) 208 } 209 210 @Test 211 fun testHistoryTimeTravel() { 212 // Configure historical registry behavior. 213 setHistoryParameters( 214 AppOpsManager.HISTORICAL_MODE_ENABLED_PASSIVE, 215 SNAPSHOT_INTERVAL_MILLIS, 216 INTERVAL_COMPRESSION_MULTIPLIER) 217 218 // Fill the first two intervals with data 219 val chunk = createDataChunk() 220 val chunkCount = computeSlotCount(2) * SNAPSHOT_INTERVAL_MILLIS / chunk.endTimeMillis 221 for (i in 0 until chunkCount) { 222 addHistoricalOps(chunk) 223 } 224 225 // Move history in past with the first interval duration 226 val firstIntervalDurationMillis = computeIntervalDurationMillis(0) 227 runWithShellPermissionIdentity { 228 appOpsManager.offsetHistory(firstIntervalDurationMillis) 229 } 230 231 // Validate the data for the first interval 232 val firstIntervalBeginMillis = computeIntervalBeginRawMillis(0) 233 val firstIntervalEndMillis = firstIntervalBeginMillis + firstIntervalDurationMillis 234 val firstOps = getHistoricalOpsFromDiskRaw(uid, packageName, null /*opNames*/, 235 firstIntervalBeginMillis, firstIntervalEndMillis) 236 assertThat(firstOps).isNotNull() 237 assertThat(firstOps!!.uidCount).isEqualTo(0) 238 239 // Validate the data for the second interval 240 val secondIntervalBeginMillis = computeIntervalBeginRawMillis(1) 241 val secondIntervalDurationMillis = computeIntervalDurationMillis(1) 242 val secondIntervalEndMillis = secondIntervalBeginMillis + secondIntervalDurationMillis 243 val secondOps = getHistoricalOpsFromDiskRaw(uid, packageName, null /*opNames*/, 244 secondIntervalBeginMillis, secondIntervalEndMillis) 245 val secondChunkCount = ((computeSlotCount(2) - computeSlotCount(1)) 246 .times(SNAPSHOT_INTERVAL_MILLIS) / chunk.endTimeMillis) 247 assertHasCounts(secondOps!!, 10 * secondChunkCount) 248 249 // Validate the data for the third interval 250 val thirdIntervalBeginMillis = computeIntervalBeginRawMillis(2) 251 val thirdIntervalDurationMillis = computeIntervalDurationMillis(2) 252 val thirdIntervalEndMillis = thirdIntervalBeginMillis + thirdIntervalDurationMillis 253 val thirdOps = getHistoricalOpsFromDiskRaw(uid, packageName, null /*opNames*/, 254 thirdIntervalBeginMillis, thirdIntervalEndMillis) 255 val thirdChunkCount = secondChunkCount / INTERVAL_COMPRESSION_MULTIPLIER 256 assertHasCounts(thirdOps!!, 10 * thirdChunkCount) 257 258 // Move history in future with the first interval duration 259 runWithShellPermissionIdentity { 260 appOpsManager.offsetHistory(-(2.5f * firstIntervalDurationMillis).toLong()) 261 } 262 263 // Validate the data for the first interval 264 val fourthOps = getHistoricalOpsFromDiskRaw(uid, packageName, null /*opNames*/, 265 firstIntervalBeginMillis, firstIntervalEndMillis) 266 assertHasCounts(fourthOps!!, 194) 267 268 // Validate the data for the second interval 269 val fifthOps = getHistoricalOpsFromDiskRaw(uid, packageName, null /*opNames*/, 270 secondIntervalBeginMillis, secondIntervalEndMillis) 271 272 assertThat(fifthOps).isNotNull() 273 assertHasCounts(fifthOps!!, 1703) 274 } 275 276 @Test 277 fun testGetHistoricalAggregationOverAttributions() { 278 // Configure historical registry behavior. 279 setHistoryParameters( 280 AppOpsManager.HISTORICAL_MODE_ENABLED_ACTIVE, 281 SNAPSHOT_INTERVAL_MILLIS, 282 INTERVAL_COMPRESSION_MULTIPLIER) 283 284 setUidMode(OPSTR_REQUEST_DELETE_PACKAGES, uid, AppOpsManager.MODE_ALLOWED) 285 286 UidStateForceActivity.waitForResumed() 287 288 appOpsManager.noteOp(OPSTR_REQUEST_DELETE_PACKAGES, uid, packageName, "firstAttribution", 289 null) 290 appOpsManager.noteOp(OPSTR_REQUEST_DELETE_PACKAGES, uid, packageName, "secondAttribution", 291 null) 292 var memOps: AppOpsManager.HistoricalOps? = null 293 eventually(SNAPSHOT_INTERVAL_MILLIS / 2) { 294 memOps = getHistoricalOps(appOpsManager, uid = uid)!! 295 296 assertThat(memOps!!.getUidOpsAt(0).getPackageOpsAt(0) 297 .getOp(OPSTR_REQUEST_DELETE_PACKAGES)!!.getForegroundAccessCount(OP_FLAGS_ALL)) 298 .isEqualTo(2) 299 assertThat(memOps!!.getUidOpsAt(0).getPackageOpsAt(0) 300 .getAttributedOps("firstAttribution")!!.getOp(OPSTR_REQUEST_DELETE_PACKAGES)!! 301 .getForegroundAccessCount(OP_FLAGS_ALL)).isEqualTo(1) 302 assertThat(memOps!!.getUidOpsAt(0).getPackageOpsAt(0) 303 .getAttributedOps("secondAttribution")!!.getOp(OPSTR_REQUEST_DELETE_PACKAGES)!! 304 .getForegroundAccessCount(OP_FLAGS_ALL)).isEqualTo(1) 305 } 306 307 // Wait until data is on disk and verify no entry got lost 308 Thread.sleep(SNAPSHOT_INTERVAL_MILLIS) 309 310 val diskOps = getHistoricalOps(appOpsManager, uid = uid)!! 311 assertThat(diskOps.getUidOpsAt(0)).isEqualTo(memOps?.getUidOpsAt(0)) 312 } 313 314 private fun testHistoricalAggregationSomeLevelsDeep(depth: Int) { 315 // Configure historical registry behavior. 316 setHistoryParameters( 317 AppOpsManager.HISTORICAL_MODE_ENABLED_PASSIVE, 318 SNAPSHOT_INTERVAL_MILLIS, 319 INTERVAL_COMPRESSION_MULTIPLIER) 320 321 // Add the data to the history 322 val chunk = createDataChunk() 323 val chunkCount = (computeSlotCount(depth + 1) 324 .times(SNAPSHOT_INTERVAL_MILLIS) / chunk.endTimeMillis) 325 for (i in 0 until chunkCount) { 326 addHistoricalOps(chunk) 327 } 328 329 // Validate the data for the full interval 330 val intervalBeginMillis = computeIntervalBeginRawMillis(depth) 331 val intervalEndMillis = computeIntervalBeginRawMillis(depth + 1) 332 val ops = getHistoricalOpsFromDiskRaw(uid, packageName, null /*opNames*/, 333 intervalBeginMillis, intervalEndMillis) 334 val expectedOpCount = ((computeSlotCount(depth + 1) - computeSlotCount(depth)) 335 .times(SNAPSHOT_INTERVAL_MILLIS) / chunk.endTimeMillis) * 10 336 assertHasCounts(ops!!, expectedOpCount) 337 } 338 339 private fun testGetHistoricalPackageOpsForegroundAtDepth(depth: Int) { 340 // Configure historical registry behavior. 341 setHistoryParameters( 342 AppOpsManager.HISTORICAL_MODE_ENABLED_ACTIVE, 343 SNAPSHOT_INTERVAL_MILLIS, 344 INTERVAL_COMPRESSION_MULTIPLIER) 345 346 setUidMode(AppOpsManager.OPSTR_START_FOREGROUND, uid, 347 AppOpsManager.MODE_ALLOWED) 348 setUidMode(AppOpsManager.OPSTR_START_FOREGROUND, 2000, 349 AppOpsManager.MODE_ALLOWED) 350 351 UidStateForceActivity.waitForResumed() 352 353 try { 354 val noteCount = 5 355 356 var beginTimeMillis = 0L 357 var endTimeMillis = 0L 358 359 // Note ops such that we have data at all levels 360 for (d in depth downTo 0) { 361 for (i in 0 until noteCount) { 362 appOpsManager.noteOp(AppOpsManager.OPSTR_START_FOREGROUND, uid, packageName) 363 } 364 365 if (d > 0) { 366 val previousIntervalDuration = computeIntervalDurationMillis(d - 2) 367 val currentIntervalDuration = computeIntervalDurationMillis(d - 1) 368 369 endTimeMillis -= previousIntervalDuration 370 beginTimeMillis -= currentIntervalDuration 371 372 val sleepDurationMillis = currentIntervalDuration / 2 373 SystemClock.sleep(sleepDurationMillis) 374 } 375 } 376 377 val nowMillis = System.currentTimeMillis() 378 if (depth > 0) { 379 beginTimeMillis += nowMillis 380 endTimeMillis += nowMillis 381 } else { 382 beginTimeMillis = nowMillis - SNAPSHOT_INTERVAL_MILLIS 383 endTimeMillis = Long.MAX_VALUE 384 } 385 386 // Get all ops for the package 387 val allOps = getHistoricalOps(appOpsManager, uid, packageName, 388 null, beginTimeMillis, endTimeMillis) 389 390 assertThat(allOps).isNotNull() 391 assertThat(allOps!!.uidCount).isEqualTo(1) 392 assertThat(allOps.beginTimeMillis).isEqualTo(beginTimeMillis) 393 assertThat(allOps.endTimeMillis).isGreaterThan(beginTimeMillis) 394 395 val uidOps = allOps.getUidOpsAt(0) 396 assertThat(uidOps).isNotNull() 397 assertThat(uidOps.uid).isEqualTo(Process.myUid()) 398 assertThat(uidOps.packageCount).isEqualTo(1) 399 400 val packageOps = uidOps.getPackageOpsAt(0) 401 assertThat(packageOps).isNotNull() 402 assertThat(packageOps.packageName).isEqualTo(packageName) 403 assertThat(packageOps.opCount).isEqualTo(1) 404 405 val op = packageOps.getOpAt(0) 406 assertThat(op).isNotNull() 407 assertThat(op.opName).isEqualTo(AppOpsManager.OPSTR_START_FOREGROUND) 408 409 assertThat(op.getForegroundAccessCount(AppOpsManager.OP_FLAGS_ALL)) 410 .isEqualTo(noteCount) 411 assertThat(op.getBackgroundAccessCount(AppOpsManager.OP_FLAGS_ALL)).isEqualTo(0) 412 assertThat(getAccessCount(op, AppOpsManager.UID_STATE_PERSISTENT)).isEqualTo(0) 413 assertThat(getAccessCount(op, AppOpsManager.UID_STATE_TOP)).isEqualTo(noteCount) 414 assertThat(getAccessCount(op, AppOpsManager.UID_STATE_FOREGROUND_SERVICE_LOCATION)) 415 .isEqualTo(0) 416 assertThat(getAccessCount(op, AppOpsManager.UID_STATE_FOREGROUND_SERVICE)) 417 .isEqualTo(0) 418 assertThat(getAccessCount(op, AppOpsManager.UID_STATE_FOREGROUND)).isEqualTo(0) 419 assertThat(getAccessCount(op, AppOpsManager.UID_STATE_BACKGROUND)).isEqualTo(0) 420 assertThat(getAccessCount(op, AppOpsManager.UID_STATE_CACHED)).isEqualTo(0) 421 422 assertThat(op.getForegroundAccessDuration(AppOpsManager.OP_FLAGS_ALL)).isEqualTo(0) 423 assertThat(op.getBackgroundAccessDuration(AppOpsManager.OP_FLAGS_ALL)).isEqualTo(0) 424 assertThat(op.getAccessDuration(AppOpsManager.UID_STATE_TOP, 425 AppOpsManager.UID_STATE_BACKGROUND, AppOpsManager.OP_FLAGS_ALL)) 426 .isEqualTo(0) 427 assertThat(getAccessDuration(op, AppOpsManager.UID_STATE_PERSISTENT)).isEqualTo(0) 428 assertThat(getAccessDuration(op, AppOpsManager.UID_STATE_TOP)).isEqualTo(0) 429 assertThat(getAccessDuration(op, AppOpsManager.UID_STATE_FOREGROUND_SERVICE_LOCATION)) 430 .isEqualTo(0) 431 assertThat(getAccessDuration(op, AppOpsManager.UID_STATE_FOREGROUND_SERVICE)) 432 .isEqualTo(0) 433 assertThat(getAccessDuration(op, AppOpsManager.UID_STATE_FOREGROUND)).isEqualTo(0) 434 assertThat(getAccessDuration(op, AppOpsManager.UID_STATE_BACKGROUND)).isEqualTo(0) 435 assertThat(getAccessDuration(op, AppOpsManager.UID_STATE_CACHED)).isEqualTo(0) 436 437 assertThat(op.getForegroundRejectCount(AppOpsManager.OP_FLAGS_ALL)).isEqualTo(0) 438 assertThat(op.getBackgroundRejectCount(AppOpsManager.OP_FLAGS_ALL)).isEqualTo(0) 439 assertThat(op.getRejectCount(AppOpsManager.UID_STATE_TOP, 440 AppOpsManager.UID_STATE_BACKGROUND, AppOpsManager.OP_FLAGS_ALL)) 441 .isEqualTo(0) 442 assertThat(getRejectCount(op, AppOpsManager.UID_STATE_PERSISTENT)).isEqualTo(0) 443 assertThat(getRejectCount(op, AppOpsManager.UID_STATE_TOP)).isEqualTo(0) 444 assertThat(getRejectCount(op, AppOpsManager.UID_STATE_FOREGROUND_SERVICE_LOCATION)) 445 .isEqualTo(0) 446 assertThat(getRejectCount(op, AppOpsManager.UID_STATE_FOREGROUND_SERVICE)) 447 .isEqualTo(0) 448 assertThat(getRejectCount(op, AppOpsManager.UID_STATE_FOREGROUND)).isEqualTo(0) 449 assertThat(getRejectCount(op, AppOpsManager.UID_STATE_BACKGROUND)).isEqualTo(0) 450 assertThat(getRejectCount(op, AppOpsManager.UID_STATE_CACHED)).isEqualTo(0) 451 } finally { 452 setUidMode(AppOpsManager.OPSTR_START_FOREGROUND, uid, AppOpsManager.MODE_FOREGROUND) 453 setUidMode(AppOpsManager.OPSTR_START_FOREGROUND, 2000, AppOpsManager.MODE_FOREGROUND) 454 } 455 } 456 457 private fun createDataChunk(): HistoricalOps { 458 val chunk = HistoricalOps(SNAPSHOT_INTERVAL_MILLIS / 4, 459 SNAPSHOT_INTERVAL_MILLIS / 2) 460 chunk.increaseAccessCount(AppOpsManager.OP_START_FOREGROUND, uid, packageName, null, 461 AppOpsManager.UID_STATE_TOP, AppOpsManager.OP_FLAG_SELF, 10) 462 chunk.increaseAccessCount(AppOpsManager.OP_START_FOREGROUND, uid, packageName, null, 463 AppOpsManager.UID_STATE_BACKGROUND, AppOpsManager.OP_FLAG_SELF, 10) 464 chunk.increaseRejectCount(AppOpsManager.OP_START_FOREGROUND, uid, packageName, null, 465 AppOpsManager.UID_STATE_TOP, AppOpsManager.OP_FLAG_SELF, 10) 466 chunk.increaseRejectCount(AppOpsManager.OP_START_FOREGROUND, uid, packageName, null, 467 AppOpsManager.UID_STATE_BACKGROUND, AppOpsManager.OP_FLAG_SELF, 10) 468 chunk.increaseAccessDuration(AppOpsManager.OP_START_FOREGROUND, uid, packageName, null, 469 AppOpsManager.UID_STATE_TOP, AppOpsManager.OP_FLAG_SELF, 10) 470 chunk.increaseAccessDuration(AppOpsManager.OP_START_FOREGROUND, uid, packageName, null, 471 AppOpsManager.UID_STATE_BACKGROUND, AppOpsManager.OP_FLAG_SELF, 10) 472 return chunk 473 } 474 475 private fun setHistoryParameters( 476 mode: Int, 477 baseSnapshotInterval: Long, 478 compressionStep: Int 479 ) { 480 runWithShellPermissionIdentity { 481 appOpsManager.setHistoryParameters(mode, baseSnapshotInterval, compressionStep) 482 } 483 } 484 485 private fun setUidMode(appOp: String, uid: Int, mode: Int) { 486 runWithShellPermissionIdentity { 487 appOpsManager.setUidMode(appOp, uid, mode) 488 } 489 } 490 491 private fun addHistoricalOps(ops: AppOpsManager.HistoricalOps) { 492 runWithShellPermissionIdentity { 493 appOpsManager.addHistoricalOps(ops) 494 } 495 } 496 497 private fun getHistoricalOps( 498 appOpsManager: AppOpsManager, 499 uid: Int = Process.INVALID_UID, 500 packageName: String? = null, 501 opNames: List<String>? = null, 502 beginTimeMillis: Long = 0, 503 endTimeMillis: Long = Long.MAX_VALUE 504 ): HistoricalOps? { 505 uiAutomation.adoptShellPermissionIdentity() 506 val array = arrayOfNulls<HistoricalOps>(1) 507 val lock = ReentrantLock() 508 val condition = lock.newCondition() 509 try { 510 lock.lock() 511 val request = AppOpsManager.HistoricalOpsRequest.Builder( 512 beginTimeMillis, endTimeMillis) 513 .setUid(uid) 514 .setPackageName(packageName) 515 .setOpNames(opNames?.toList()) 516 .build() 517 appOpsManager.getHistoricalOps(request, context.mainExecutor, Consumer { ops -> 518 array[0] = ops 519 try { 520 lock.lock() 521 condition.signalAll() 522 } finally { 523 lock.unlock() 524 } 525 }) 526 condition.await(5, TimeUnit.SECONDS) 527 return array[0] 528 } finally { 529 lock.unlock() 530 uiAutomation.dropShellPermissionIdentity() 531 } 532 } 533 534 private fun assertHasCounts(ops: HistoricalOps, count: Long) { 535 assertThat(ops).isNotNull() 536 537 if (count <= 0) { 538 assertThat(ops.uidCount).isEqualTo(0) 539 return 540 } 541 542 assertThat(ops.uidCount).isEqualTo(1) 543 544 val uidOps = ops.getUidOpsAt(0) 545 assertThat(uidOps).isNotNull() 546 547 val packageOps = uidOps.getPackageOpsAt(0) 548 assertThat(packageOps).isNotNull() 549 550 val op = packageOps.getOpAt(0) 551 assertThat(op).isNotNull() 552 553 assertThat(op.getForegroundAccessCount(AppOpsManager.OP_FLAGS_ALL)).isEqualTo(count) 554 assertThat(op.getBackgroundAccessCount(AppOpsManager.OP_FLAGS_ALL)).isEqualTo(count) 555 assertThat(op.getForegroundRejectCount(AppOpsManager.OP_FLAGS_ALL)).isEqualTo(count) 556 assertThat(op.getBackgroundRejectCount(AppOpsManager.OP_FLAGS_ALL)).isEqualTo(count) 557 assertThat(op.getForegroundAccessDuration(AppOpsManager.OP_FLAGS_ALL)).isEqualTo(count) 558 assertThat(op.getBackgroundAccessDuration(AppOpsManager.OP_FLAGS_ALL)).isEqualTo(count) 559 } 560 561 private fun getAccessCount(op: HistoricalOp, uidState: Int): Long { 562 return op.getAccessCount(uidState, uidState, AppOpsManager.OP_FLAGS_ALL) 563 } 564 565 private fun getRejectCount(op: HistoricalOp, uidState: Int): Long { 566 return op.getRejectCount(uidState, uidState, AppOpsManager.OP_FLAGS_ALL) 567 } 568 569 private fun getAccessDuration(op: HistoricalOp, uidState: Int): Long { 570 return op.getAccessDuration(uidState, uidState, AppOpsManager.OP_FLAGS_ALL) 571 } 572 573 private fun getHistoricalOpsFromDiskRaw( 574 uid: Int, 575 packageName: String, 576 opNames: List<String>?, 577 beginTimeMillis: Long, 578 endTimeMillis: Long 579 ): HistoricalOps? { 580 uiAutomation.adoptShellPermissionIdentity() 581 val array = arrayOfNulls<HistoricalOps>(1) 582 val lock = ReentrantLock() 583 val condition = lock.newCondition() 584 try { 585 lock.lock() 586 val request = AppOpsManager.HistoricalOpsRequest.Builder( 587 beginTimeMillis, endTimeMillis) 588 .setUid(uid) 589 .setPackageName(packageName) 590 .setOpNames(opNames?.toList()) 591 .build() 592 appOpsManager.getHistoricalOpsFromDiskRaw(request, context.mainExecutor, 593 Consumer { ops -> 594 array[0] = ops 595 try { 596 lock.lock() 597 condition.signalAll() 598 } finally { 599 lock.unlock() 600 } 601 }) 602 condition.await(5, TimeUnit.SECONDS) 603 return array[0] 604 } finally { 605 lock.unlock() 606 uiAutomation.dropShellPermissionIdentity() 607 } 608 } 609 610 companion object { 611 const val INTERVAL_COMPRESSION_MULTIPLIER = 10 612 const val SNAPSHOT_INTERVAL_MILLIS = 1000L 613 614 val instrumentation get() = InstrumentationRegistry.getInstrumentation() 615 val context get() = instrumentation.context 616 val uiAutomation get() = instrumentation.uiAutomation 617 618 private fun computeIntervalDurationMillis(depth: Int): Long { 619 return Math.pow(INTERVAL_COMPRESSION_MULTIPLIER.toDouble(), 620 (depth + 1).toDouble()).toLong() * SNAPSHOT_INTERVAL_MILLIS 621 } 622 623 private fun computeSlotCount(depth: Int): Int { 624 var count = 0 625 for (i in 1..depth) { 626 count += Math.pow(INTERVAL_COMPRESSION_MULTIPLIER.toDouble(), i.toDouble()).toInt() 627 } 628 return count 629 } 630 631 private fun computeIntervalBeginRawMillis(depth: Int): Long { 632 var beginTimeMillis: Long = 0 633 for (i in 0 until depth + 1) { 634 beginTimeMillis += Math.pow(INTERVAL_COMPRESSION_MULTIPLIER.toDouble(), 635 i.toDouble()).toLong() 636 } 637 return beginTimeMillis * SNAPSHOT_INTERVAL_MILLIS 638 } 639 } 640 } 641