1 /* 2 * Copyright (C) 2022 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 com.android.systemui.mediaprojection.appselector.data 18 19 import android.app.ActivityManager.RECENT_IGNORE_UNAVAILABLE 20 import com.android.systemui.dagger.qualifiers.Background 21 import com.android.systemui.settings.UserTracker 22 import com.android.systemui.util.kotlin.getOrNull 23 import com.android.wm.shell.recents.RecentTasks 24 import com.android.wm.shell.util.GroupedRecentTaskInfo 25 import java.util.Optional 26 import java.util.concurrent.Executor 27 import javax.inject.Inject 28 import kotlin.coroutines.resume 29 import kotlin.coroutines.suspendCoroutine 30 import kotlinx.coroutines.CoroutineDispatcher 31 import kotlinx.coroutines.withContext 32 33 interface RecentTaskListProvider { 34 /** Loads recent tasks, the returned task list is from the most-recent to least-recent order */ 35 suspend fun loadRecentTasks(): List<RecentTask> 36 } 37 38 class ShellRecentTaskListProvider 39 @Inject 40 constructor( 41 @Background private val coroutineDispatcher: CoroutineDispatcher, 42 @Background private val backgroundExecutor: Executor, 43 private val recentTasks: Optional<RecentTasks>, 44 private val userTracker: UserTracker 45 ) : RecentTaskListProvider { 46 47 private val recents by lazy { recentTasks.getOrNull() } 48 49 override suspend fun loadRecentTasks(): List<RecentTask> = 50 withContext(coroutineDispatcher) { 51 val rawRecentTasks: List<GroupedRecentTaskInfo> = recents?.getTasks() ?: emptyList() 52 53 rawRecentTasks 54 .flatMap { listOfNotNull(it.taskInfo1, it.taskInfo2) } 55 .map { 56 RecentTask( 57 it.taskId, 58 it.userId, 59 it.topActivity, 60 it.baseIntent?.component, 61 it.taskDescription?.backgroundColor 62 ) 63 } 64 } 65 66 private suspend fun RecentTasks.getTasks(): List<GroupedRecentTaskInfo> = 67 suspendCoroutine { continuation -> 68 getRecentTasks( 69 Integer.MAX_VALUE, 70 RECENT_IGNORE_UNAVAILABLE, 71 userTracker.userId, 72 backgroundExecutor 73 ) { tasks -> 74 continuation.resume(tasks) 75 } 76 } 77 } 78