summaryrefslogtreecommitdiff
path: root/packages/SystemUI/src/com/android/systemui/ChooserSelector.kt
blob: 227f0ace33dd712eab1edfd57d87a9c8ad438a3f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package com.android.systemui

import android.content.ComponentName
import android.content.Context
import android.content.pm.PackageManager
import android.util.Log
import com.android.internal.R
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.FlagListenable
import com.android.systemui.flags.Flags
import com.android.systemui.settings.UserTracker
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withContext
import javax.inject.Inject

@SysUISingleton
class ChooserSelector @Inject constructor(
        private val context: Context,
        private val userTracker: UserTracker,
        private val featureFlags: FeatureFlags,
        @Application private val coroutineScope: CoroutineScope,
        @Background private val bgDispatcher: CoroutineDispatcher,
) : CoreStartable {

    private val chooserComponent = ComponentName.unflattenFromString(
            context.resources.getString(R.string.config_chooserActivity))

    override fun start() {
        coroutineScope.launch {
            val listener = FlagListenable.Listener { event ->
                if (event.flagName == Flags.CHOOSER_UNBUNDLED.name) {
                    launch { updateUnbundledChooserEnabled() }
                    event.requestNoRestart()
                }
            }
            featureFlags.addListener(Flags.CHOOSER_UNBUNDLED, listener)
            updateUnbundledChooserEnabled()

            awaitCancellationAndThen { featureFlags.removeListener(listener) }
        }
    }

    private suspend fun updateUnbundledChooserEnabled() {
        setUnbundledChooserEnabled(withContext(bgDispatcher) {
            featureFlags.isEnabled(Flags.CHOOSER_UNBUNDLED)
        })
    }

    private fun setUnbundledChooserEnabled(enabled: Boolean) {
        val newState = if (enabled) {
            PackageManager.COMPONENT_ENABLED_STATE_ENABLED
        } else {
            PackageManager.COMPONENT_ENABLED_STATE_DISABLED
        }
        userTracker.userProfiles.forEach {
            try {
                context.createContextAsUser(it.userHandle, /* flags = */ 0).packageManager
                        .setComponentEnabledSetting(chooserComponent, newState, /* flags = */ 0)
            } catch (e: IllegalArgumentException) {
                Log.w(
                        "ChooserSelector",
                        "Unable to set IntentResolver enabled=$enabled for user ${it.id}",
                        e,
                )
            }
        }
    }

    suspend inline fun awaitCancellation(): Nothing = suspendCancellableCoroutine { }
    suspend inline fun awaitCancellationAndThen(block: () -> Unit): Nothing = try {
        awaitCancellation()
    } finally {
        block()
    }
}