Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4370a27d authored by Chris Göllner's avatar Chris Göllner
Browse files

PSS: Make sure recent task thumbnails are up to date

Task thumbnails are usually only updated when opening them, closing
them, or when going to overview.
This was causing PSS app selector to show an out of date thumbnail
for the last foreground task.
The solution is to make sure to take a new thumbnail when the app
selector starts.

Fixes: 304442979
Test: Manual
Test: MediaProjectionAppSelectorControllerTest
Test: ShellRecentTaskListProviderTest
Test: MediaProjectionAppSelectorScreenshotTest
Change-Id: Id82c0cf47a9be7a610095e6c669fc5aa634d2327
parent 67863693
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -155,6 +155,26 @@ public class ActivityManagerWrapper {
        }
    }


    /**
     * Requests for a new snapshot to be taken for the given task, stores it in the cache, and
     * returns a {@link ThumbnailData} with the result.
     */
    @NonNull
    public ThumbnailData takeTaskThumbnail(int taskId) {
        TaskSnapshot snapshot = null;
        try {
            snapshot = getService().takeTaskSnapshot(taskId, /* updateCache= */ true);
        } catch (RemoteException e) {
            Log.w(TAG, "Failed to take task snapshot", e);
        }
        if (snapshot != null) {
            return new ThumbnailData(snapshot);
        } else {
            return new ThumbnailData();
        }
    }

    /**
     * Removes the outdated snapshot of home task.
     *
+22 −1
Original line number Diff line number Diff line
@@ -20,10 +20,15 @@ import android.content.ComponentName
import android.os.UserHandle
import com.android.systemui.mediaprojection.appselector.data.RecentTask
import com.android.systemui.mediaprojection.appselector.data.RecentTaskListProvider
import com.android.systemui.mediaprojection.appselector.data.RecentTaskThumbnailLoader
import com.android.systemui.mediaprojection.devicepolicy.ScreenCaptureDevicePolicyResolver
import com.android.systemui.shared.recents.model.ThumbnailData
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.async
import kotlinx.coroutines.cancel
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch

@MediaProjectionAppSelectorScope
@@ -36,7 +41,8 @@ constructor(
    @HostUserHandle private val hostUserHandle: UserHandle,
    @MediaProjectionAppSelector private val scope: CoroutineScope,
    @MediaProjectionAppSelector private val appSelectorComponentName: ComponentName,
    @MediaProjectionAppSelector private val callerPackageName: String?
    @MediaProjectionAppSelector private val callerPackageName: String?,
    private val thumbnailLoader: RecentTaskThumbnailLoader,
) {

    fun init() {
@@ -46,6 +52,11 @@ constructor(
            val tasks =
                recentTasks.filterDevicePolicyRestrictedTasks().filterAppSelector().sortedTasks()

            // Thumbnails are not fresh for the foreground task(s). They are only refreshed at
            // launch, going to home, or going to overview.
            // For this reason, we need to refresh them here.
            refreshForegroundTaskThumbnails(tasks)

            view.bind(tasks)
        }
    }
@@ -54,6 +65,16 @@ constructor(
        scope.cancel()
    }

    private suspend fun refreshForegroundTaskThumbnails(tasks: List<RecentTask>) {
        coroutineScope {
            val thumbnails: List<Deferred<ThumbnailData?>> =
                tasks
                    .filter { it.isForegroundTask }
                    .map { async { thumbnailLoader.captureThumbnail(it.taskId) } }
            thumbnails.forEach { thumbnail -> thumbnail.await() }
        }
    }

    /** Removes all recent tasks that should be blocked according to the policy */
    private fun List<RecentTask>.filterDevicePolicyRestrictedTasks(): List<RecentTask> = filter {
        devicePolicyResolver.isScreenCaptureAllowed(
+2 −1
Original line number Diff line number Diff line
@@ -25,5 +25,6 @@ data class RecentTask(
    @UserIdInt val userId: Int,
    val topActivityComponent: ComponentName?,
    val baseIntentComponent: ComponentName?,
    @ColorInt val colorBackground: Int?
    @ColorInt val colorBackground: Int?,
    val isForegroundTask: Boolean,
)
+10 −4
Original line number Diff line number Diff line
@@ -48,9 +48,14 @@ constructor(

    override suspend fun loadRecentTasks(): List<RecentTask> =
        withContext(coroutineDispatcher) {
            val rawRecentTasks: List<GroupedRecentTaskInfo> = recents?.getTasks() ?: emptyList()

            rawRecentTasks
            val groupedTasks: List<GroupedRecentTaskInfo> = recents?.getTasks() ?: emptyList()
            // Note: the returned task list is from the most-recent to least-recent order.
            // The last foreground task is at index 1, because at index 0 will be our app selector.
            val foregroundGroup = groupedTasks.elementAtOrNull(1)
            val foregroundTaskId1 = foregroundGroup?.taskInfo1?.taskId
            val foregroundTaskId2 = foregroundGroup?.taskInfo2?.taskId
            val foregroundTaskIds = listOfNotNull(foregroundTaskId1, foregroundTaskId2)
            groupedTasks
                .flatMap { listOfNotNull(it.taskInfo1, it.taskInfo2) }
                .map {
                    RecentTask(
@@ -58,7 +63,8 @@ constructor(
                        it.userId,
                        it.topActivity,
                        it.baseIntent?.component,
                        it.taskDescription?.backgroundColor
                        it.taskDescription?.backgroundColor,
                        isForegroundTask = it.taskId in foregroundTaskIds
                    )
                }
        }
+10 −3
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@ import kotlinx.coroutines.withContext

interface RecentTaskThumbnailLoader {
    suspend fun loadThumbnail(taskId: Int): ThumbnailData?

    suspend fun captureThumbnail(taskId: Int): ThumbnailData?
}

class ActivityTaskManagerThumbnailLoader
@@ -36,8 +38,13 @@ constructor(

    override suspend fun loadThumbnail(taskId: Int): ThumbnailData? =
        withContext(coroutineDispatcher) {
            val thumbnailData =
                activityManager.getTaskThumbnail(taskId, /* isLowResolution= */ false)
            if (thumbnailData.thumbnail == null) null else thumbnailData
            activityManager.getTaskThumbnail(taskId, /* isLowResolution= */ false).takeIf {
                it.thumbnail != null
            }
        }

    override suspend fun captureThumbnail(taskId: Int): ThumbnailData? =
        withContext(coroutineDispatcher) {
            activityManager.takeTaskThumbnail(taskId).takeIf { it.thumbnail != null }
        }
}
Loading