Merge "[Partial Screensharing] Add enterprise policies handling flag" into tm-qpr-dev am: cafbb75bfa
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20821101 Change-Id: I146ed06ba9a514e29fbc7b1b2b19b9fadc95267a Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -413,6 +413,17 @@ object Flags {
|
|||||||
val WM_DESKTOP_WINDOWING_2 =
|
val WM_DESKTOP_WINDOWING_2 =
|
||||||
sysPropBooleanFlag(1112, "persist.wm.debug.desktop_mode_2", default = false)
|
sysPropBooleanFlag(1112, "persist.wm.debug.desktop_mode_2", default = false)
|
||||||
|
|
||||||
|
// TODO(b/254513207): Tracking Bug to delete
|
||||||
|
@Keep
|
||||||
|
@JvmField
|
||||||
|
val WM_ENABLE_PARTIAL_SCREEN_SHARING_ENTERPRISE_POLICIES =
|
||||||
|
unreleasedFlag(
|
||||||
|
1113,
|
||||||
|
name = "screen_record_enterprise_policies",
|
||||||
|
namespace = DeviceConfig.NAMESPACE_WINDOW_MANAGER,
|
||||||
|
teamfood = false
|
||||||
|
)
|
||||||
|
|
||||||
// 1200 - predictive back
|
// 1200 - predictive back
|
||||||
@Keep
|
@Keep
|
||||||
@JvmField
|
@JvmField
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package com.android.systemui.media
|
|||||||
import android.app.ActivityOptions
|
import android.app.ActivityOptions
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
|
import android.content.res.Resources
|
||||||
import android.media.projection.IMediaProjection
|
import android.media.projection.IMediaProjection
|
||||||
import android.media.projection.MediaProjectionManager.EXTRA_MEDIA_PROJECTION
|
import android.media.projection.MediaProjectionManager.EXTRA_MEDIA_PROJECTION
|
||||||
import android.os.Binder
|
import android.os.Binder
|
||||||
@@ -27,6 +28,7 @@ import android.os.ResultReceiver
|
|||||||
import android.os.UserHandle
|
import android.os.UserHandle
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import com.android.internal.annotations.VisibleForTesting
|
import com.android.internal.annotations.VisibleForTesting
|
||||||
|
import com.android.internal.app.AbstractMultiProfilePagerAdapter.MyUserIdProvider
|
||||||
import com.android.internal.app.ChooserActivity
|
import com.android.internal.app.ChooserActivity
|
||||||
import com.android.internal.app.ResolverListController
|
import com.android.internal.app.ResolverListController
|
||||||
import com.android.internal.app.chooser.NotSelectableTargetInfo
|
import com.android.internal.app.chooser.NotSelectableTargetInfo
|
||||||
@@ -59,16 +61,12 @@ class MediaProjectionAppSelectorActivity(
|
|||||||
private lateinit var configurationController: ConfigurationController
|
private lateinit var configurationController: ConfigurationController
|
||||||
private lateinit var controller: MediaProjectionAppSelectorController
|
private lateinit var controller: MediaProjectionAppSelectorController
|
||||||
private lateinit var recentsViewController: MediaProjectionRecentsViewController
|
private lateinit var recentsViewController: MediaProjectionRecentsViewController
|
||||||
|
private lateinit var component: MediaProjectionAppSelectorComponent
|
||||||
|
|
||||||
override fun getLayoutResource() = R.layout.media_projection_app_selector
|
override fun getLayoutResource() = R.layout.media_projection_app_selector
|
||||||
|
|
||||||
public override fun onCreate(bundle: Bundle?) {
|
public override fun onCreate(bundle: Bundle?) {
|
||||||
val component =
|
component = componentFactory.create(activity = this, view = this, resultHandler = this)
|
||||||
componentFactory.create(
|
|
||||||
activity = this,
|
|
||||||
view = this,
|
|
||||||
resultHandler = this
|
|
||||||
)
|
|
||||||
|
|
||||||
// Create a separate configuration controller for this activity as the configuration
|
// Create a separate configuration controller for this activity as the configuration
|
||||||
// might be different from the global one
|
// might be different from the global one
|
||||||
@@ -76,11 +74,12 @@ class MediaProjectionAppSelectorActivity(
|
|||||||
controller = component.controller
|
controller = component.controller
|
||||||
recentsViewController = component.recentsViewController
|
recentsViewController = component.recentsViewController
|
||||||
|
|
||||||
val queryIntent = Intent(Intent.ACTION_MAIN).apply { addCategory(Intent.CATEGORY_LAUNCHER) }
|
intent.configureChooserIntent(
|
||||||
intent.putExtra(Intent.EXTRA_INTENT, queryIntent)
|
resources,
|
||||||
|
component.hostUserHandle,
|
||||||
|
component.personalProfileUserHandle
|
||||||
|
)
|
||||||
|
|
||||||
val title = getString(R.string.media_projection_permission_app_selector_title)
|
|
||||||
intent.putExtra(Intent.EXTRA_TITLE, title)
|
|
||||||
super.onCreate(bundle)
|
super.onCreate(bundle)
|
||||||
controller.init()
|
controller.init()
|
||||||
}
|
}
|
||||||
@@ -183,6 +182,13 @@ class MediaProjectionAppSelectorActivity(
|
|||||||
|
|
||||||
override fun shouldShowContentPreview() = true
|
override fun shouldShowContentPreview() = true
|
||||||
|
|
||||||
|
override fun shouldShowContentPreviewWhenEmpty(): Boolean = true
|
||||||
|
|
||||||
|
override fun createMyUserIdProvider(): MyUserIdProvider =
|
||||||
|
object : MyUserIdProvider() {
|
||||||
|
override fun getMyUserId(): Int = component.hostUserHandle.identifier
|
||||||
|
}
|
||||||
|
|
||||||
override fun createContentPreviewView(parent: ViewGroup): ViewGroup =
|
override fun createContentPreviewView(parent: ViewGroup): ViewGroup =
|
||||||
recentsViewController.createView(parent)
|
recentsViewController.createView(parent)
|
||||||
|
|
||||||
@@ -193,6 +199,34 @@ class MediaProjectionAppSelectorActivity(
|
|||||||
* instance through activity result.
|
* instance through activity result.
|
||||||
*/
|
*/
|
||||||
const val EXTRA_CAPTURE_REGION_RESULT_RECEIVER = "capture_region_result_receiver"
|
const val EXTRA_CAPTURE_REGION_RESULT_RECEIVER = "capture_region_result_receiver"
|
||||||
|
|
||||||
|
/** UID of the app that originally launched the media projection flow (host app user) */
|
||||||
|
const val EXTRA_HOST_APP_USER_HANDLE = "launched_from_user_handle"
|
||||||
const val KEY_CAPTURE_TARGET = "capture_region"
|
const val KEY_CAPTURE_TARGET = "capture_region"
|
||||||
|
|
||||||
|
/** Set up intent for the [ChooserActivity] */
|
||||||
|
private fun Intent.configureChooserIntent(
|
||||||
|
resources: Resources,
|
||||||
|
hostUserHandle: UserHandle,
|
||||||
|
personalProfileUserHandle: UserHandle
|
||||||
|
) {
|
||||||
|
// Specify the query intent to show icons for all apps on the chooser screen
|
||||||
|
val queryIntent =
|
||||||
|
Intent(Intent.ACTION_MAIN).apply { addCategory(Intent.CATEGORY_LAUNCHER) }
|
||||||
|
putExtra(Intent.EXTRA_INTENT, queryIntent)
|
||||||
|
|
||||||
|
// Update the title of the chooser
|
||||||
|
val title = resources.getString(R.string.media_projection_permission_app_selector_title)
|
||||||
|
putExtra(Intent.EXTRA_TITLE, title)
|
||||||
|
|
||||||
|
// Select host app's profile tab by default
|
||||||
|
val selectedProfile =
|
||||||
|
if (hostUserHandle == personalProfileUserHandle) {
|
||||||
|
PROFILE_PERSONAL
|
||||||
|
} else {
|
||||||
|
PROFILE_WORK
|
||||||
|
}
|
||||||
|
putExtra(EXTRA_SELECTED_PROFILE, selectedProfile)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import static com.android.systemui.screenrecord.ScreenShareOptionKt.ENTIRE_SCREE
|
|||||||
import static com.android.systemui.screenrecord.ScreenShareOptionKt.SINGLE_APP;
|
import static com.android.systemui.screenrecord.ScreenShareOptionKt.SINGLE_APP;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.app.ActivityManager;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@@ -35,6 +36,7 @@ import android.os.Bundle;
|
|||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.ServiceManager;
|
import android.os.ServiceManager;
|
||||||
|
import android.os.UserHandle;
|
||||||
import android.text.BidiFormatter;
|
import android.text.BidiFormatter;
|
||||||
import android.text.SpannableString;
|
import android.text.SpannableString;
|
||||||
import android.text.TextPaint;
|
import android.text.TextPaint;
|
||||||
@@ -208,8 +210,14 @@ public class MediaProjectionPermissionActivity extends Activity
|
|||||||
final Intent intent = new Intent(this, MediaProjectionAppSelectorActivity.class);
|
final Intent intent = new Intent(this, MediaProjectionAppSelectorActivity.class);
|
||||||
intent.putExtra(MediaProjectionManager.EXTRA_MEDIA_PROJECTION,
|
intent.putExtra(MediaProjectionManager.EXTRA_MEDIA_PROJECTION,
|
||||||
projection.asBinder());
|
projection.asBinder());
|
||||||
|
intent.putExtra(MediaProjectionAppSelectorActivity.EXTRA_HOST_APP_USER_HANDLE,
|
||||||
|
UserHandle.getUserHandleForUid(getLaunchedFromUid()));
|
||||||
intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
|
intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
|
||||||
startActivity(intent);
|
|
||||||
|
// Start activity from the current foreground user to avoid creating a separate
|
||||||
|
// SystemUI process without access to recent tasks because it won't have
|
||||||
|
// WM Shell running inside.
|
||||||
|
startActivityAsUser(intent, UserHandle.of(ActivityManager.getCurrentUser()));
|
||||||
}
|
}
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.e(TAG, "Error granting projection permission", e);
|
Log.e(TAG, "Error granting projection permission", e);
|
||||||
|
|||||||
@@ -19,9 +19,11 @@ package com.android.systemui.mediaprojection.appselector
|
|||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.os.UserHandle
|
||||||
import com.android.launcher3.icons.IconFactory
|
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.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
|
||||||
@@ -30,6 +32,8 @@ import com.android.systemui.mediaprojection.appselector.data.RecentTaskThumbnail
|
|||||||
import com.android.systemui.mediaprojection.appselector.data.ShellRecentTaskListProvider
|
import com.android.systemui.mediaprojection.appselector.data.ShellRecentTaskListProvider
|
||||||
import com.android.systemui.mediaprojection.appselector.view.MediaProjectionRecentsViewController
|
import com.android.systemui.mediaprojection.appselector.view.MediaProjectionRecentsViewController
|
||||||
import com.android.systemui.mediaprojection.appselector.view.TaskPreviewSizeProvider
|
import com.android.systemui.mediaprojection.appselector.view.TaskPreviewSizeProvider
|
||||||
|
import com.android.systemui.settings.UserTracker
|
||||||
|
import com.android.systemui.shared.system.ActivityManagerWrapper
|
||||||
import com.android.systemui.statusbar.phone.ConfigurationControllerImpl
|
import com.android.systemui.statusbar.phone.ConfigurationControllerImpl
|
||||||
import com.android.systemui.statusbar.policy.ConfigurationController
|
import com.android.systemui.statusbar.policy.ConfigurationController
|
||||||
import dagger.Binds
|
import dagger.Binds
|
||||||
@@ -39,6 +43,7 @@ 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
|
||||||
@@ -46,6 +51,12 @@ import kotlinx.coroutines.SupervisorJob
|
|||||||
|
|
||||||
@Qualifier @Retention(AnnotationRetention.BINARY) annotation class MediaProjectionAppSelector
|
@Qualifier @Retention(AnnotationRetention.BINARY) annotation class MediaProjectionAppSelector
|
||||||
|
|
||||||
|
@Qualifier @Retention(AnnotationRetention.BINARY) annotation class HostUserHandle
|
||||||
|
|
||||||
|
@Qualifier @Retention(AnnotationRetention.BINARY) annotation class PersonalProfile
|
||||||
|
|
||||||
|
@Qualifier @Retention(AnnotationRetention.BINARY) annotation class WorkProfile
|
||||||
|
|
||||||
@Retention(AnnotationRetention.RUNTIME) @Scope annotation class MediaProjectionAppSelectorScope
|
@Retention(AnnotationRetention.RUNTIME) @Scope annotation class MediaProjectionAppSelectorScope
|
||||||
|
|
||||||
@Module(subcomponents = [MediaProjectionAppSelectorComponent::class])
|
@Module(subcomponents = [MediaProjectionAppSelectorComponent::class])
|
||||||
@@ -93,9 +104,32 @@ interface MediaProjectionAppSelectorModule {
|
|||||||
): ConfigurationController = ConfigurationControllerImpl(activity)
|
): ConfigurationController = ConfigurationControllerImpl(activity)
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
fun bindIconFactory(
|
@PersonalProfile
|
||||||
context: Context
|
@MediaProjectionAppSelectorScope
|
||||||
): IconFactory = IconFactory.obtain(context)
|
fun personalUserHandle(activityManagerWrapper: ActivityManagerWrapper): UserHandle {
|
||||||
|
// Current foreground user is the 'personal' profile
|
||||||
|
return UserHandle.of(activityManagerWrapper.currentUserId)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@WorkProfile
|
||||||
|
@MediaProjectionAppSelectorScope
|
||||||
|
fun workProfileUserHandle(userTracker: UserTracker): UserHandle? =
|
||||||
|
userTracker.userProfiles.find { it.isManagedProfile }?.userHandle
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@HostUserHandle
|
||||||
|
@MediaProjectionAppSelectorScope
|
||||||
|
fun hostUserHandle(activity: MediaProjectionAppSelectorActivity): UserHandle {
|
||||||
|
val extras =
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides fun bindIconFactory(context: Context): IconFactory = IconFactory.obtain(context)
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@MediaProjectionAppSelector
|
@MediaProjectionAppSelector
|
||||||
@@ -124,6 +158,8 @@ interface MediaProjectionAppSelectorComponent {
|
|||||||
|
|
||||||
val controller: MediaProjectionAppSelectorController
|
val controller: MediaProjectionAppSelectorController
|
||||||
val recentsViewController: MediaProjectionRecentsViewController
|
val recentsViewController: MediaProjectionRecentsViewController
|
||||||
|
@get:HostUserHandle val hostUserHandle: UserHandle
|
||||||
|
@get:PersonalProfile val personalProfileUserHandle: UserHandle
|
||||||
|
|
||||||
@MediaProjectionAppSelector val configurationController: ConfigurationController
|
@MediaProjectionAppSelector val configurationController: ConfigurationController
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,24 +17,36 @@
|
|||||||
package com.android.systemui.mediaprojection.appselector
|
package com.android.systemui.mediaprojection.appselector
|
||||||
|
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
|
import android.os.UserHandle
|
||||||
|
import com.android.systemui.flags.FeatureFlags
|
||||||
|
import com.android.systemui.flags.Flags
|
||||||
import com.android.systemui.mediaprojection.appselector.data.RecentTask
|
import com.android.systemui.mediaprojection.appselector.data.RecentTask
|
||||||
import com.android.systemui.mediaprojection.appselector.data.RecentTaskListProvider
|
import com.android.systemui.mediaprojection.appselector.data.RecentTaskListProvider
|
||||||
|
import javax.inject.Inject
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.cancel
|
import kotlinx.coroutines.cancel
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
@MediaProjectionAppSelectorScope
|
@MediaProjectionAppSelectorScope
|
||||||
class MediaProjectionAppSelectorController @Inject constructor(
|
class MediaProjectionAppSelectorController
|
||||||
|
@Inject
|
||||||
|
constructor(
|
||||||
private val recentTaskListProvider: RecentTaskListProvider,
|
private val recentTaskListProvider: RecentTaskListProvider,
|
||||||
private val view: MediaProjectionAppSelectorView,
|
private val view: MediaProjectionAppSelectorView,
|
||||||
|
private val flags: FeatureFlags,
|
||||||
|
@HostUserHandle private val hostUserHandle: UserHandle,
|
||||||
@MediaProjectionAppSelector private val scope: CoroutineScope,
|
@MediaProjectionAppSelector private val scope: CoroutineScope,
|
||||||
@MediaProjectionAppSelector private val appSelectorComponentName: ComponentName
|
@MediaProjectionAppSelector private val appSelectorComponentName: ComponentName
|
||||||
) {
|
) {
|
||||||
|
|
||||||
fun init() {
|
fun init() {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
val tasks = recentTaskListProvider.loadRecentTasks().sortTasks()
|
val recentTasks = recentTaskListProvider.loadRecentTasks()
|
||||||
|
|
||||||
|
val tasks = recentTasks
|
||||||
|
.filterDevicePolicyRestrictedTasks()
|
||||||
|
.sortedTasks()
|
||||||
|
|
||||||
view.bind(tasks)
|
view.bind(tasks)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -43,8 +55,19 @@ class MediaProjectionAppSelectorController @Inject constructor(
|
|||||||
scope.cancel()
|
scope.cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun List<RecentTask>.sortTasks(): List<RecentTask> =
|
/**
|
||||||
sortedBy {
|
* Removes all recent tasks that are different from the profile of the host app to avoid any
|
||||||
|
* cross-profile sharing
|
||||||
|
*/
|
||||||
|
private fun List<RecentTask>.filterDevicePolicyRestrictedTasks(): List<RecentTask> =
|
||||||
|
if (flags.isEnabled(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING_ENTERPRISE_POLICIES)) {
|
||||||
|
// TODO(b/263950746): filter tasks based on the enterprise policies
|
||||||
|
this
|
||||||
|
} else {
|
||||||
|
filter { UserHandle.of(it.userId) == hostUserHandle }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun List<RecentTask>.sortedTasks(): List<RecentTask> = sortedBy {
|
||||||
// Show normal tasks first and only then tasks with opened app selector
|
// Show normal tasks first and only then tasks with opened app selector
|
||||||
it.topActivityComponent == appSelectorComponentName
|
it.topActivityComponent == appSelectorComponentName
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,11 +17,12 @@
|
|||||||
package com.android.systemui.mediaprojection.appselector.data
|
package com.android.systemui.mediaprojection.appselector.data
|
||||||
|
|
||||||
import android.annotation.ColorInt
|
import android.annotation.ColorInt
|
||||||
|
import android.annotation.UserIdInt
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
|
|
||||||
data class RecentTask(
|
data class RecentTask(
|
||||||
val taskId: Int,
|
val taskId: Int,
|
||||||
val userId: Int,
|
@UserIdInt val userId: Int,
|
||||||
val topActivityComponent: ComponentName?,
|
val topActivityComponent: ComponentName?,
|
||||||
val baseIntentComponent: ComponentName?,
|
val baseIntentComponent: ComponentName?,
|
||||||
@ColorInt val colorBackground: Int?
|
@ColorInt val colorBackground: Int?
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import android.os.Bundle
|
|||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.os.ResultReceiver
|
import android.os.ResultReceiver
|
||||||
|
import android.os.UserHandle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.View.GONE
|
import android.view.View.GONE
|
||||||
import android.view.View.VISIBLE
|
import android.view.View.VISIBLE
|
||||||
@@ -77,6 +78,14 @@ class ScreenRecordPermissionDialog(
|
|||||||
MediaProjectionAppSelectorActivity.EXTRA_CAPTURE_REGION_RESULT_RECEIVER,
|
MediaProjectionAppSelectorActivity.EXTRA_CAPTURE_REGION_RESULT_RECEIVER,
|
||||||
CaptureTargetResultReceiver()
|
CaptureTargetResultReceiver()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Send SystemUI's user handle as the host app user handle because SystemUI
|
||||||
|
// is the 'host app' (the app that receives screen capture data)
|
||||||
|
intent.putExtra(
|
||||||
|
MediaProjectionAppSelectorActivity.EXTRA_HOST_APP_USER_HANDLE,
|
||||||
|
UserHandle.of(UserHandle.myUserId())
|
||||||
|
)
|
||||||
|
|
||||||
val animationController = dialogLaunchAnimator.createActivityLaunchController(v!!)
|
val animationController = dialogLaunchAnimator.createActivityLaunchController(v!!)
|
||||||
if (animationController == null) {
|
if (animationController == null) {
|
||||||
dismiss()
|
dismiss()
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
package com.android.systemui.mediaprojection.appselector
|
package com.android.systemui.mediaprojection.appselector
|
||||||
|
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
|
import android.os.UserHandle
|
||||||
import android.testing.AndroidTestingRunner
|
import android.testing.AndroidTestingRunner
|
||||||
import androidx.test.filters.SmallTest
|
import androidx.test.filters.SmallTest
|
||||||
import com.android.systemui.SysuiTestCase
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import com.android.systemui.flags.FeatureFlags
|
||||||
|
import com.android.systemui.flags.Flags
|
||||||
import com.android.systemui.mediaprojection.appselector.data.RecentTask
|
import com.android.systemui.mediaprojection.appselector.data.RecentTask
|
||||||
import com.android.systemui.mediaprojection.appselector.data.RecentTaskListProvider
|
import com.android.systemui.mediaprojection.appselector.data.RecentTaskListProvider
|
||||||
import com.android.systemui.util.mockito.mock
|
import com.android.systemui.util.mockito.mock
|
||||||
|
import com.android.systemui.util.mockito.whenever
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
@@ -21,11 +25,17 @@ class MediaProjectionAppSelectorControllerTest : SysuiTestCase() {
|
|||||||
private val scope = CoroutineScope(Dispatchers.Unconfined)
|
private val scope = CoroutineScope(Dispatchers.Unconfined)
|
||||||
private val appSelectorComponentName = ComponentName("com.test", "AppSelector")
|
private val appSelectorComponentName = ComponentName("com.test", "AppSelector")
|
||||||
|
|
||||||
|
private val hostUserHandle = UserHandle.of(123)
|
||||||
|
private val otherUserHandle = UserHandle.of(456)
|
||||||
|
|
||||||
private val view: MediaProjectionAppSelectorView = mock()
|
private val view: MediaProjectionAppSelectorView = mock()
|
||||||
|
private val featureFlags: FeatureFlags = mock()
|
||||||
|
|
||||||
private val controller = MediaProjectionAppSelectorController(
|
private val controller = MediaProjectionAppSelectorController(
|
||||||
taskListProvider,
|
taskListProvider,
|
||||||
view,
|
view,
|
||||||
|
featureFlags,
|
||||||
|
hostUserHandle,
|
||||||
scope,
|
scope,
|
||||||
appSelectorComponentName
|
appSelectorComponentName
|
||||||
)
|
)
|
||||||
@@ -98,15 +108,72 @@ class MediaProjectionAppSelectorControllerTest : SysuiTestCase() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun initRecentTasksWithAppSelectorTasks_enterprisePoliciesDisabled_bindsOnlyTasksWithHostProfile() {
|
||||||
|
givenEnterprisePoliciesFeatureFlag(enabled = false)
|
||||||
|
|
||||||
|
val tasks = listOf(
|
||||||
|
createRecentTask(taskId = 1, userId = hostUserHandle.identifier),
|
||||||
|
createRecentTask(taskId = 2, userId = otherUserHandle.identifier),
|
||||||
|
createRecentTask(taskId = 3, userId = hostUserHandle.identifier),
|
||||||
|
createRecentTask(taskId = 4, userId = otherUserHandle.identifier),
|
||||||
|
createRecentTask(taskId = 5, userId = hostUserHandle.identifier),
|
||||||
|
)
|
||||||
|
taskListProvider.tasks = tasks
|
||||||
|
|
||||||
|
controller.init()
|
||||||
|
|
||||||
|
verify(view).bind(
|
||||||
|
listOf(
|
||||||
|
createRecentTask(taskId = 1, userId = hostUserHandle.identifier),
|
||||||
|
createRecentTask(taskId = 3, userId = hostUserHandle.identifier),
|
||||||
|
createRecentTask(taskId = 5, userId = hostUserHandle.identifier),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun initRecentTasksWithAppSelectorTasks_enterprisePoliciesEnabled_bindsAllTasks() {
|
||||||
|
givenEnterprisePoliciesFeatureFlag(enabled = true)
|
||||||
|
|
||||||
|
val tasks = listOf(
|
||||||
|
createRecentTask(taskId = 1, userId = hostUserHandle.identifier),
|
||||||
|
createRecentTask(taskId = 2, userId = otherUserHandle.identifier),
|
||||||
|
createRecentTask(taskId = 3, userId = hostUserHandle.identifier),
|
||||||
|
createRecentTask(taskId = 4, userId = otherUserHandle.identifier),
|
||||||
|
createRecentTask(taskId = 5, userId = hostUserHandle.identifier),
|
||||||
|
)
|
||||||
|
taskListProvider.tasks = tasks
|
||||||
|
|
||||||
|
controller.init()
|
||||||
|
|
||||||
|
// TODO(b/233348916) should filter depending on the policies
|
||||||
|
verify(view).bind(
|
||||||
|
listOf(
|
||||||
|
createRecentTask(taskId = 1, userId = hostUserHandle.identifier),
|
||||||
|
createRecentTask(taskId = 2, userId = otherUserHandle.identifier),
|
||||||
|
createRecentTask(taskId = 3, userId = hostUserHandle.identifier),
|
||||||
|
createRecentTask(taskId = 4, userId = otherUserHandle.identifier),
|
||||||
|
createRecentTask(taskId = 5, userId = hostUserHandle.identifier),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun givenEnterprisePoliciesFeatureFlag(enabled: Boolean) {
|
||||||
|
whenever(featureFlags.isEnabled(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING_ENTERPRISE_POLICIES))
|
||||||
|
.thenReturn(enabled)
|
||||||
|
}
|
||||||
|
|
||||||
private fun createRecentTask(
|
private fun createRecentTask(
|
||||||
taskId: Int,
|
taskId: Int,
|
||||||
topActivityComponent: ComponentName? = null
|
topActivityComponent: ComponentName? = null,
|
||||||
|
userId: Int = hostUserHandle.identifier
|
||||||
): RecentTask {
|
): RecentTask {
|
||||||
return RecentTask(
|
return RecentTask(
|
||||||
taskId = taskId,
|
taskId = taskId,
|
||||||
topActivityComponent = topActivityComponent,
|
topActivityComponent = topActivityComponent,
|
||||||
baseIntentComponent = ComponentName("com", "Test"),
|
baseIntentComponent = ComponentName("com", "Test"),
|
||||||
userId = 0,
|
userId = userId,
|
||||||
colorBackground = 0
|
colorBackground = 0
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user