Merge "[Partial Screensharing] Add accessibility labels to recent tasks" into tm-qpr-dev
This commit is contained in:
@@ -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,
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user