diff options
author | 2024-08-06 13:46:56 -0700 | |
---|---|---|
committer | 2024-08-14 14:12:19 -0700 | |
commit | 2f6086166956949bc5ab732795f671b1800cb613 (patch) | |
tree | 886f3dcfeda08675aed66ed77791b08aaf43db1b /java/src | |
parent | 6872117b988dbf42ab81f078c5c27f8182517d0a (diff) |
Add timeout for AppPredictor response.
Timeout AppPredictor callbacks and fallback to ShortcutManager.
Bug: 295956687
Bug: 343300158
Test: atest IntentResolver-tests-unit
Flag: com.android.intentresolver.fix_shortcuts_flashing
Change-Id: Ia6e5643451a840e10213f242c6c79364b0193e78
Diffstat (limited to 'java/src')
-rw-r--r-- | java/src/com/android/intentresolver/shortcuts/ShortcutLoader.kt | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/java/src/com/android/intentresolver/shortcuts/ShortcutLoader.kt b/java/src/com/android/intentresolver/shortcuts/ShortcutLoader.kt index 68412256..1fedee30 100644 --- a/java/src/com/android/intentresolver/shortcuts/ShortcutLoader.kt +++ b/java/src/com/android/intentresolver/shortcuts/ShortcutLoader.kt @@ -36,18 +36,22 @@ import androidx.annotation.OpenForTesting import androidx.annotation.VisibleForTesting import androidx.annotation.WorkerThread import com.android.intentresolver.Flags.fixShortcutLoaderJobLeak +import com.android.intentresolver.Flags.fixShortcutsFlashing import com.android.intentresolver.chooser.DisplayResolveInfo import com.android.intentresolver.measurements.Tracer import com.android.intentresolver.measurements.runTracing import java.util.concurrent.Executor import java.util.function.Consumer +import kotlinx.atomicfu.atomic import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.CoroutineStart import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.asExecutor import kotlinx.coroutines.cancel import kotlinx.coroutines.channels.BufferOverflow +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.filter @@ -80,6 +84,7 @@ constructor( if (fixShortcutLoaderJobLeak()) parentScope.createChildScope() else parentScope private val shortcutToChooserTargetConverter = ShortcutToChooserTargetConverter() private val userManager = context.getSystemService(Context.USER_SERVICE) as UserManager + private val appPredictorWatchdog = atomic<Job?>(null) private val appPredictorCallback = ScopedAppTargetListCallback(scope) { onAppPredictorCallback(it) }.toAppPredictorCallback() @@ -186,8 +191,29 @@ constructor( if (!skipAppPredictionService && appPredictor != null) { try { Log.d(TAG, "[$id] query AppPredictor for user $userHandle") + + val watchdogJob = + if (fixShortcutsFlashing()) { + scope + .launch(start = CoroutineStart.LAZY) { + delay(APP_PREDICTOR_RESPONSE_TIMEOUT_MS) + Log.w(TAG, "AppPredictor response timeout for user: $userHandle") + appPredictorCallback.onTargetsAvailable(emptyList()) + } + .also { job -> + appPredictorWatchdog.getAndSet(job)?.cancel() + job.invokeOnCompletion { + appPredictorWatchdog.compareAndSet(job, null) + } + } + } else { + null + } + Tracer.beginAppPredictorQueryTrace(userHandle) appPredictor.requestPredictionUpdate() + + watchdogJob?.start() return } catch (e: Throwable) { endAppPredictorQueryTrace(userHandle) @@ -230,6 +256,7 @@ constructor( @WorkerThread private fun onAppPredictorCallback(appPredictorTargets: List<AppTarget>) { + appPredictorWatchdog.value?.cancel() endAppPredictorQueryTrace(userHandle) Log.d(TAG, "[$id] receive app targets from AppPredictor") if (appPredictorTargets.isEmpty() && shouldQueryDirectShareTargets()) { @@ -378,6 +405,7 @@ constructor( } companion object { + @VisibleForTesting const val APP_PREDICTOR_RESPONSE_TIMEOUT_MS = 2_000L private const val TAG = "ShortcutLoader" private fun PackageManager.isPackageEnabled(packageName: String): Boolean { |