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

This commit is contained in:
Yalan Yiue
2023-01-24 06:00:33 +00:00
committed by Android (Google) Code Review
3 changed files with 80 additions and 15 deletions

View File

@@ -24,9 +24,11 @@ import com.android.launcher3.icons.IconFactory
import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.media.MediaProjectionAppSelectorActivity import com.android.systemui.media.MediaProjectionAppSelectorActivity
import com.android.systemui.media.MediaProjectionAppSelectorActivity.Companion.EXTRA_HOST_APP_USER_HANDLE 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.ActivityTaskManagerThumbnailLoader
import com.android.systemui.mediaprojection.appselector.data.AppIconLoader import com.android.systemui.mediaprojection.appselector.data.AppIconLoader
import com.android.systemui.mediaprojection.appselector.data.IconLoaderLibAppIconLoader 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.RecentTaskListProvider
import com.android.systemui.mediaprojection.appselector.data.RecentTaskThumbnailLoader import com.android.systemui.mediaprojection.appselector.data.RecentTaskThumbnailLoader
import com.android.systemui.mediaprojection.appselector.data.ShellRecentTaskListProvider import com.android.systemui.mediaprojection.appselector.data.ShellRecentTaskListProvider
@@ -43,7 +45,6 @@ import dagger.Provides
import dagger.Subcomponent import dagger.Subcomponent
import dagger.multibindings.ClassKey import dagger.multibindings.ClassKey
import dagger.multibindings.IntoMap import dagger.multibindings.IntoMap
import java.lang.IllegalArgumentException
import javax.inject.Qualifier import javax.inject.Qualifier
import javax.inject.Scope import javax.inject.Scope
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@@ -69,9 +70,10 @@ interface MediaProjectionModule {
): Activity ): Activity
} }
/** Scoped values for [MediaProjectionAppSelectorComponent]. /**
* We create a scope for the activity so certain dependencies like [TaskPreviewSizeProvider] * Scoped values for [MediaProjectionAppSelectorComponent]. We create a scope for the activity so
* could be reused. */ * certain dependencies like [TaskPreviewSizeProvider] could be reused.
*/
@Module @Module
interface MediaProjectionAppSelectorModule { interface MediaProjectionAppSelectorModule {
@@ -81,6 +83,10 @@ interface MediaProjectionAppSelectorModule {
impl: ActivityTaskManagerThumbnailLoader impl: ActivityTaskManagerThumbnailLoader
): RecentTaskThumbnailLoader ): RecentTaskThumbnailLoader
@Binds
@MediaProjectionAppSelectorScope
fun bindRecentTaskLabelLoader(impl: ActivityTaskManagerLabelLoader): RecentTaskLabelLoader
@Binds @Binds
@MediaProjectionAppSelectorScope @MediaProjectionAppSelectorScope
fun bindRecentTaskListProvider(impl: ShellRecentTaskListProvider): RecentTaskListProvider fun bindRecentTaskListProvider(impl: ShellRecentTaskListProvider): RecentTaskListProvider
@@ -125,8 +131,10 @@ interface MediaProjectionAppSelectorModule {
activity.intent.extras activity.intent.extras
?: error("MediaProjectionAppSelectorActivity should be launched with extras") ?: error("MediaProjectionAppSelectorActivity should be launched with extras")
return extras.getParcelable(EXTRA_HOST_APP_USER_HANDLE) return extras.getParcelable(EXTRA_HOST_APP_USER_HANDLE)
?: error("MediaProjectionAppSelectorActivity should be provided with " + ?: error(
"$EXTRA_HOST_APP_USER_HANDLE extra") "MediaProjectionAppSelectorActivity should be provided with " +
"$EXTRA_HOST_APP_USER_HANDLE extra"
)
} }
@Provides fun bindIconFactory(context: Context): IconFactory = IconFactory.obtain(context) @Provides fun bindIconFactory(context: Context): IconFactory = IconFactory.obtain(context)
@@ -146,9 +154,7 @@ interface MediaProjectionAppSelectorComponent {
/** Generates [MediaProjectionAppSelectorComponent]. */ /** Generates [MediaProjectionAppSelectorComponent]. */
@Subcomponent.Factory @Subcomponent.Factory
interface 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( fun create(
@BindsInstance activity: MediaProjectionAppSelectorActivity, @BindsInstance activity: MediaProjectionAppSelectorActivity,
@BindsInstance view: MediaProjectionAppSelectorView, @BindsInstance view: MediaProjectionAppSelectorView,

View File

@@ -0,0 +1,53 @@
/*
* 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)
}
}

View File

@@ -20,11 +20,12 @@ import android.graphics.Rect
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ImageView import android.widget.ImageView
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.android.systemui.R import com.android.systemui.R
import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelector import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelector
import com.android.systemui.mediaprojection.appselector.data.AppIconLoader import com.android.systemui.mediaprojection.appselector.data.AppIconLoader
import com.android.systemui.mediaprojection.appselector.data.RecentTask 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.mediaprojection.appselector.data.RecentTaskThumbnailLoader
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener
import dagger.assisted.Assisted import dagger.assisted.Assisted
@@ -40,9 +41,10 @@ constructor(
@Assisted private val root: ViewGroup, @Assisted private val root: ViewGroup,
private val iconLoader: AppIconLoader, private val iconLoader: AppIconLoader,
private val thumbnailLoader: RecentTaskThumbnailLoader, private val thumbnailLoader: RecentTaskThumbnailLoader,
private val labelLoader: RecentTaskLabelLoader,
private val taskViewSizeProvider: TaskPreviewSizeProvider, private val taskViewSizeProvider: TaskPreviewSizeProvider,
@MediaProjectionAppSelector private val scope: CoroutineScope @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) val thumbnailView: MediaProjectionTaskView = root.requireViewById(R.id.task_thumbnail)
private val iconView: ImageView = root.requireViewById(R.id.task_icon) private val iconView: ImageView = root.requireViewById(R.id.task_icon)
@@ -64,6 +66,10 @@ constructor(
val icon = iconLoader.loadIcon(task.userId, component) val icon = iconLoader.loadIcon(task.userId, component)
iconView.setImageDrawable(icon) iconView.setImageDrawable(icon)
} }
launch {
val label = labelLoader.loadLabel(task.userId, component)
root.contentDescription = label
}
} }
launch { launch {
val thumbnail = thumbnailLoader.loadThumbnail(task.taskId) val thumbnail = thumbnailLoader.loadThumbnail(task.taskId)
@@ -88,10 +94,10 @@ constructor(
private fun updateThumbnailSize() { private fun updateThumbnailSize() {
thumbnailView.layoutParams = thumbnailView.layoutParams =
thumbnailView.layoutParams.apply { thumbnailView.layoutParams.apply {
width = taskViewSizeProvider.size.width() width = taskViewSizeProvider.size.width()
height = taskViewSizeProvider.size.height() height = taskViewSizeProvider.size.height()
} }
} }
@AssistedFactory @AssistedFactory