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

Commit 3e788c75 authored by Yalan Yiue's avatar Yalan Yiue Committed by Android (Google) Code Review
Browse files

Merge "[Partial Screensharing] Add accessibility labels to recent tasks" into tm-qpr-dev

parents b4937a3d 98cfeba4
Loading
Loading
Loading
Loading
+15 −9
Original line number Diff line number Diff line
@@ -24,9 +24,11 @@ import com.android.launcher3.icons.IconFactory
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.media.MediaProjectionAppSelectorActivity
import com.android.systemui.media.MediaProjectionAppSelectorActivity.Companion.EXTRA_HOST_APP_USER_HANDLE
import com.android.systemui.mediaprojection.appselector.data.ActivityTaskManagerLabelLoader
import com.android.systemui.mediaprojection.appselector.data.ActivityTaskManagerThumbnailLoader
import com.android.systemui.mediaprojection.appselector.data.AppIconLoader
import com.android.systemui.mediaprojection.appselector.data.IconLoaderLibAppIconLoader
import com.android.systemui.mediaprojection.appselector.data.RecentTaskLabelLoader
import com.android.systemui.mediaprojection.appselector.data.RecentTaskListProvider
import com.android.systemui.mediaprojection.appselector.data.RecentTaskThumbnailLoader
import com.android.systemui.mediaprojection.appselector.data.ShellRecentTaskListProvider
@@ -43,7 +45,6 @@ import dagger.Provides
import dagger.Subcomponent
import dagger.multibindings.ClassKey
import dagger.multibindings.IntoMap
import java.lang.IllegalArgumentException
import javax.inject.Qualifier
import javax.inject.Scope
import kotlinx.coroutines.CoroutineScope
@@ -69,9 +70,10 @@ interface MediaProjectionModule {
    ): Activity
}

/** Scoped values for [MediaProjectionAppSelectorComponent].
 *  We create a scope for the activity so certain dependencies like [TaskPreviewSizeProvider]
 *  could be reused. */
/**
 * Scoped values for [MediaProjectionAppSelectorComponent]. We create a scope for the activity so
 * certain dependencies like [TaskPreviewSizeProvider] could be reused.
 */
@Module
interface MediaProjectionAppSelectorModule {

@@ -81,6 +83,10 @@ interface MediaProjectionAppSelectorModule {
        impl: ActivityTaskManagerThumbnailLoader
    ): RecentTaskThumbnailLoader

    @Binds
    @MediaProjectionAppSelectorScope
    fun bindRecentTaskLabelLoader(impl: ActivityTaskManagerLabelLoader): RecentTaskLabelLoader

    @Binds
    @MediaProjectionAppSelectorScope
    fun bindRecentTaskListProvider(impl: ShellRecentTaskListProvider): RecentTaskListProvider
@@ -125,8 +131,10 @@ interface MediaProjectionAppSelectorModule {
                activity.intent.extras
                    ?: error("MediaProjectionAppSelectorActivity should be launched with extras")
            return extras.getParcelable(EXTRA_HOST_APP_USER_HANDLE)
                ?: error("MediaProjectionAppSelectorActivity should be provided with " +
                        "$EXTRA_HOST_APP_USER_HANDLE extra")
                ?: error(
                    "MediaProjectionAppSelectorActivity should be provided with " +
                        "$EXTRA_HOST_APP_USER_HANDLE extra"
                )
        }

        @Provides fun bindIconFactory(context: Context): IconFactory = IconFactory.obtain(context)
@@ -146,9 +154,7 @@ interface MediaProjectionAppSelectorComponent {
    /** Generates [MediaProjectionAppSelectorComponent]. */
    @Subcomponent.Factory
    interface Factory {
        /**
         * Create a factory to inject the activity into the graph
         */
        /** Create a factory to inject the activity into the graph */
        fun create(
            @BindsInstance activity: MediaProjectionAppSelectorActivity,
            @BindsInstance view: MediaProjectionAppSelectorView,
+53 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.mediaprojection.appselector.data

import android.annotation.UserIdInt
import android.content.ComponentName
import android.content.pm.PackageManager
import android.os.UserHandle
import com.android.systemui.dagger.qualifiers.Background
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.withContext

interface RecentTaskLabelLoader {
    suspend fun loadLabel(userId: Int, componentName: ComponentName): CharSequence?
}

class ActivityTaskManagerLabelLoader
@Inject
constructor(
    @Background private val coroutineDispatcher: CoroutineDispatcher,
    private val packageManager: PackageManager
) : RecentTaskLabelLoader {

    override suspend fun loadLabel(
        @UserIdInt userId: Int,
        componentName: ComponentName
    ): CharSequence? =
        withContext(coroutineDispatcher) {
            val userHandle = UserHandle(userId)
            val appInfo =
                packageManager.getApplicationInfo(
                    componentName.packageName,
                    PackageManager.ApplicationInfoFlags.of(0 /* no flags */)
                )
            val label = packageManager.getApplicationLabel(appInfo)
            return@withContext packageManager.getUserBadgedLabel(label, userHandle)
        }
}
+12 −6
Original line number Diff line number Diff line
@@ -20,11 +20,12 @@ import android.graphics.Rect
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.android.systemui.R
import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelector
import com.android.systemui.mediaprojection.appselector.data.AppIconLoader
import com.android.systemui.mediaprojection.appselector.data.RecentTask
import com.android.systemui.mediaprojection.appselector.data.RecentTaskLabelLoader
import com.android.systemui.mediaprojection.appselector.data.RecentTaskThumbnailLoader
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener
import dagger.assisted.Assisted
@@ -40,9 +41,10 @@ constructor(
    @Assisted private val root: ViewGroup,
    private val iconLoader: AppIconLoader,
    private val thumbnailLoader: RecentTaskThumbnailLoader,
    private val labelLoader: RecentTaskLabelLoader,
    private val taskViewSizeProvider: TaskPreviewSizeProvider,
    @MediaProjectionAppSelector private val scope: CoroutineScope
) : RecyclerView.ViewHolder(root), ConfigurationListener, TaskPreviewSizeProvider.TaskPreviewSizeListener {
) : ViewHolder(root), ConfigurationListener, TaskPreviewSizeProvider.TaskPreviewSizeListener {

    val thumbnailView: MediaProjectionTaskView = root.requireViewById(R.id.task_thumbnail)
    private val iconView: ImageView = root.requireViewById(R.id.task_icon)
@@ -64,6 +66,10 @@ constructor(
                        val icon = iconLoader.loadIcon(task.userId, component)
                        iconView.setImageDrawable(icon)
                    }
                    launch {
                        val label = labelLoader.loadLabel(task.userId, component)
                        root.contentDescription = label
                    }
                }
                launch {
                    val thumbnail = thumbnailLoader.loadThumbnail(task.taskId)