1 /* 2 * Copyright (C) 2025 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 @file:OptIn( 18 DelicateCoroutinesApi::class, 19 ExperimentalCoroutinesApi::class, 20 ExperimentalStdlibApi::class, 21 ) 22 23 package com.android.test.tracing.coroutines 24 25 import android.platform.test.annotations.EnableFlags 26 import com.android.app.tracing.coroutines.CoroutineTraceName 27 import com.android.app.tracing.coroutines.TraceContextElement 28 import com.android.app.tracing.coroutines.launchTraced 29 import com.android.app.tracing.coroutines.withContextTraced 30 import com.android.systemui.Flags.FLAG_COROUTINE_TRACING 31 import kotlin.coroutines.EmptyCoroutineContext 32 import kotlinx.coroutines.CoroutineDispatcher 33 import kotlinx.coroutines.DelicateCoroutinesApi 34 import kotlinx.coroutines.ExperimentalCoroutinesApi 35 import kotlinx.coroutines.Job 36 import kotlinx.coroutines.currentCoroutineContext 37 import kotlinx.coroutines.delay 38 import kotlinx.coroutines.plus 39 import org.junit.Assert.assertTrue 40 import org.junit.Test 41 42 @EnableFlags(FLAG_COROUTINE_TRACING) 43 class BackgroundThreadTracingTest : TestBase() { 44 45 @Test withContext_reuseOuterDispatchernull46 fun withContext_reuseOuterDispatcher() = 47 runTest(finalEvent = 5) { 48 val originalDispatcher = currentCoroutineContext()[CoroutineDispatcher]!! 49 val otherScope = scope.plus(bgThread1) 50 expect(1, "1^main") 51 otherScope 52 .launchTraced("AAA") { 53 expect(2, "2^AAA") 54 withContextTraced("inside-withContext", originalDispatcher) { 55 assertTrue(coroutineContext[CoroutineTraceName] is TraceContextElement) 56 expect(3, "2^AAA", "inside-withContext") 57 delay(1) 58 expect(4, "2^AAA", "inside-withContext") 59 } 60 expect(5, "2^AAA") 61 } 62 .join() 63 } 64 65 @Test withContext_reentryToSameContextnull66 fun withContext_reentryToSameContext() = 67 runTest(totalEvents = 10) { 68 val otherScope = scope.plus(bgThread1) 69 expect("1^main") 70 otherScope 71 .launchTraced("AAA") { 72 expect("2^AAA") 73 var job: Job? = null 74 launchTraced("BBB") { 75 expect("2^AAA:1^BBB") 76 job = 77 scope.launchTraced("CCC") { 78 withContextTraced("DDD", bgThread1) { 79 expect("3^CCC", "DDD") 80 delay(1) 81 expect("3^CCC", "DDD") 82 } 83 withContextTraced("EEE", EmptyCoroutineContext) { 84 expect("3^CCC", "EEE") 85 delay(1) 86 expect("3^CCC", "EEE") 87 } 88 } 89 expect("2^AAA:1^BBB") 90 } 91 .join() 92 job!!.join() 93 expect("2^AAA") 94 } 95 .join() 96 expect("1^main") 97 } 98 } 99