xref: /aosp_15_r20/frameworks/base/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/util/Util.kt (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1 /*
<lambda>null2  * Copyright (C) 2024 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(ExperimentalCoroutinesApi::class)
18 
19 package com.android.systemui.kairos.internal.util
20 
21 import kotlin.coroutines.CoroutineContext
22 import kotlin.coroutines.EmptyCoroutineContext
23 import kotlinx.coroutines.CoroutineScope
24 import kotlinx.coroutines.CoroutineStart
25 import kotlinx.coroutines.Deferred
26 import kotlinx.coroutines.Dispatchers
27 import kotlinx.coroutines.ExperimentalCoroutinesApi
28 import kotlinx.coroutines.Job
29 import kotlinx.coroutines.async
30 import kotlinx.coroutines.awaitCancellation
31 import kotlinx.coroutines.launch
32 import kotlinx.coroutines.newCoroutineContext
33 
34 internal fun <A> CoroutineScope.asyncImmediate(
35     start: CoroutineStart = CoroutineStart.UNDISPATCHED,
36     context: CoroutineContext = EmptyCoroutineContext,
37     block: suspend CoroutineScope.() -> A,
38 ): Deferred<A> = async(start = start, context = Dispatchers.Unconfined + context, block = block)
39 
40 internal fun CoroutineScope.launchImmediate(
41     start: CoroutineStart = CoroutineStart.UNDISPATCHED,
42     context: CoroutineContext = EmptyCoroutineContext,
43     block: suspend CoroutineScope.() -> Unit,
44 ): Job = launch(start = start, context = Dispatchers.Unconfined + context, block = block)
45 
46 internal suspend fun awaitCancellationAndThen(block: suspend () -> Unit) {
47     try {
48         awaitCancellation()
49     } finally {
50         block()
51     }
52 }
53 
launchOnCancelnull54 internal fun CoroutineScope.launchOnCancel(
55     context: CoroutineContext = EmptyCoroutineContext,
56     block: () -> Unit,
57 ): Job =
58     launch(context = context, start = CoroutineStart.UNDISPATCHED) {
59         awaitCancellationAndThen(block)
60     }
61 
childScopenull62 internal fun CoroutineScope.childScope(
63     context: CoroutineContext = EmptyCoroutineContext
64 ): CoroutineScope {
65     val newContext = newCoroutineContext(context)
66     val newJob = Job(parent = newContext[Job])
67     return CoroutineScope(newContext + newJob)
68 }
69 
<lambda>null70 internal fun <A> Iterable<A>.associateByIndex(): Map<Int, A> = buildMap {
71     forEachIndexed { index, a -> put(index, a) }
72 }
73 
associateByIndexTonull74 internal fun <A, M : MutableMap<Int, A>> Iterable<A>.associateByIndexTo(destination: M): M =
75     destination.apply { forEachIndexed { index, a -> put(index, a) } }
76 
77 internal val Any.hashString: String
78     get() = Integer.toHexString(System.identityHashCode(this))
79