1 /* <lambda>null2 * 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 android.content.pm.UserInfo 21 import android.os.UserManager 22 import com.android.systemui.dagger.qualifiers.Background 23 import com.android.systemui.settings.UserTracker 24 import com.android.systemui.util.kotlin.getOrNull 25 import com.android.wm.shell.recents.RecentTasks 26 import com.android.wm.shell.shared.GroupedTaskInfo 27 import java.util.Optional 28 import java.util.concurrent.Executor 29 import javax.inject.Inject 30 import kotlin.coroutines.resume 31 import kotlin.coroutines.suspendCoroutine 32 import kotlinx.coroutines.CoroutineDispatcher 33 import kotlinx.coroutines.withContext 34 35 interface RecentTaskListProvider { 36 /** Loads recent tasks, the returned task list is from the most-recent to least-recent order */ 37 suspend fun loadRecentTasks(): List<RecentTask> 38 } 39 40 class ShellRecentTaskListProvider 41 @Inject 42 constructor( 43 @Background private val coroutineDispatcher: CoroutineDispatcher, 44 @Background private val backgroundExecutor: Executor, 45 private val recentTasks: Optional<RecentTasks>, 46 private val userTracker: UserTracker, 47 private val userManager: UserManager, 48 ) : RecentTaskListProvider { 49 <lambda>null50 private val recents by lazy { recentTasks.getOrNull() } 51 loadRecentTasksnull52 override suspend fun loadRecentTasks(): List<RecentTask> = 53 withContext(coroutineDispatcher) { 54 val groupedTasks: List<GroupedTaskInfo> = recents?.getTasks() ?: emptyList() 55 // Note: the returned task list is from the most-recent to least-recent order. 56 // When opening the app selector in full screen, index 0 will be just the app selector 57 // activity and a null second task, so the foreground task will be index 1, but when 58 // opening the app selector in split screen mode, the foreground task will be the second 59 // task in index 0. 60 // TODO(346588978): This needs to be updated for mixed groups 61 val foregroundGroup = 62 if (groupedTasks.firstOrNull()?.splitBounds != null) groupedTasks.first() 63 else groupedTasks.elementAtOrNull(1) 64 val foregroundTaskId1 = foregroundGroup?.taskInfo1?.taskId 65 val foregroundTaskId2 = foregroundGroup?.taskInfo2?.taskId 66 val foregroundTaskIds = listOfNotNull(foregroundTaskId1, foregroundTaskId2) 67 groupedTasks.flatMap { 68 val task1 = 69 RecentTask( 70 it.taskInfo1, 71 it.taskInfo1.taskId in foregroundTaskIds && it.taskInfo1.isVisible, 72 userManager.getUserInfo(it.taskInfo1.userId).toUserType(), 73 it.splitBounds, 74 ) 75 76 val task2 = 77 if (it.taskInfo2 != null) { 78 RecentTask( 79 it.taskInfo2!!, 80 it.taskInfo2!!.taskId in foregroundTaskIds && it.taskInfo2!!.isVisible, 81 userManager.getUserInfo(it.taskInfo2!!.userId).toUserType(), 82 it.splitBounds, 83 ) 84 } else null 85 86 listOfNotNull(task1, task2) 87 } 88 } 89 getTasksnull90 private suspend fun RecentTasks.getTasks(): List<GroupedTaskInfo> = 91 suspendCoroutine { continuation -> 92 getRecentTasks( 93 Integer.MAX_VALUE, 94 RECENT_IGNORE_UNAVAILABLE, 95 userTracker.userId, 96 backgroundExecutor, 97 ) { tasks -> 98 continuation.resume(tasks) 99 } 100 } 101 UserInfonull102 private fun UserInfo.toUserType(): RecentTask.UserType = 103 if (isCloneProfile) { 104 RecentTask.UserType.CLONED 105 } else if (isManagedProfile) { 106 RecentTask.UserType.WORK 107 } else if (isPrivateProfile) { 108 RecentTask.UserType.PRIVATE 109 } else { 110 RecentTask.UserType.STANDARD 111 } 112 } 113