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

Commit 22636c38 authored by Nick Chameyev's avatar Nick Chameyev Committed by Automerger Merge Worker
Browse files

Merge "[Partial Screensharing] Add enterprise policies handling flag" into...

Merge "[Partial Screensharing] Add enterprise policies handling flag" into tm-qpr-dev am: cafbb75b am: 1c84da03

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20821101



Change-Id: I7d4c2e4c90af854bb9605e77279cb7434970eeaf
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 1406e403 1c84da03
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -411,6 +411,17 @@ object Flags {
    val WM_DESKTOP_WINDOWING_2 =
        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
    @Keep
    @JvmField
+44 −10
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.systemui.media
import android.app.ActivityOptions
import android.content.Intent
import android.content.res.Configuration
import android.content.res.Resources
import android.media.projection.IMediaProjection
import android.media.projection.MediaProjectionManager.EXTRA_MEDIA_PROJECTION
import android.os.Binder
@@ -27,6 +28,7 @@ import android.os.ResultReceiver
import android.os.UserHandle
import android.view.ViewGroup
import com.android.internal.annotations.VisibleForTesting
import com.android.internal.app.AbstractMultiProfilePagerAdapter.MyUserIdProvider
import com.android.internal.app.ChooserActivity
import com.android.internal.app.ResolverListController
import com.android.internal.app.chooser.NotSelectableTargetInfo
@@ -59,16 +61,12 @@ class MediaProjectionAppSelectorActivity(
    private lateinit var configurationController: ConfigurationController
    private lateinit var controller: MediaProjectionAppSelectorController
    private lateinit var recentsViewController: MediaProjectionRecentsViewController
    private lateinit var component: MediaProjectionAppSelectorComponent

    override fun getLayoutResource() = R.layout.media_projection_app_selector

    public override fun onCreate(bundle: Bundle?) {
        val component =
            componentFactory.create(
                activity = this,
                view = this,
                resultHandler = this
            )
        component = componentFactory.create(activity = this, view = this, resultHandler = this)

        // Create a separate configuration controller for this activity as the configuration
        // might be different from the global one
@@ -76,11 +74,12 @@ class MediaProjectionAppSelectorActivity(
        controller = component.controller
        recentsViewController = component.recentsViewController

        val queryIntent = Intent(Intent.ACTION_MAIN).apply { addCategory(Intent.CATEGORY_LAUNCHER) }
        intent.putExtra(Intent.EXTRA_INTENT, queryIntent)
        intent.configureChooserIntent(
            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)
        controller.init()
    }
@@ -183,6 +182,13 @@ class MediaProjectionAppSelectorActivity(

    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 =
        recentsViewController.createView(parent)

@@ -193,6 +199,34 @@ class MediaProjectionAppSelectorActivity(
         * instance through activity result.
         */
        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"

        /** 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)
        }
    }
}
+9 −1
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import static com.android.systemui.screenrecord.ScreenShareOptionKt.ENTIRE_SCREE
import static com.android.systemui.screenrecord.ScreenShareOptionKt.SINGLE_APP;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
@@ -35,6 +36,7 @@ import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.text.BidiFormatter;
import android.text.SpannableString;
import android.text.TextPaint;
@@ -208,8 +210,14 @@ public class MediaProjectionPermissionActivity extends Activity
                final Intent intent = new Intent(this, MediaProjectionAppSelectorActivity.class);
                intent.putExtra(MediaProjectionManager.EXTRA_MEDIA_PROJECTION,
                        projection.asBinder());
                intent.putExtra(MediaProjectionAppSelectorActivity.EXTRA_HOST_APP_USER_HANDLE,
                        UserHandle.getUserHandleForUid(getLaunchedFromUid()));
                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) {
            Log.e(TAG, "Error granting projection permission", e);
+40 −4
Original line number Diff line number Diff line
@@ -19,9 +19,11 @@ package com.android.systemui.mediaprojection.appselector
import android.app.Activity
import android.content.ComponentName
import android.content.Context
import android.os.UserHandle
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.ActivityTaskManagerThumbnailLoader
import com.android.systemui.mediaprojection.appselector.data.AppIconLoader
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.view.MediaProjectionRecentsViewController
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.policy.ConfigurationController
import dagger.Binds
@@ -39,6 +43,7 @@ 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
@@ -46,6 +51,12 @@ import kotlinx.coroutines.SupervisorJob

@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

@Module(subcomponents = [MediaProjectionAppSelectorComponent::class])
@@ -93,9 +104,32 @@ interface MediaProjectionAppSelectorModule {
        ): ConfigurationController = ConfigurationControllerImpl(activity)

        @Provides
        fun bindIconFactory(
            context: Context
        ): IconFactory = IconFactory.obtain(context)
        @PersonalProfile
        @MediaProjectionAppSelectorScope
        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
        @MediaProjectionAppSelector
@@ -124,6 +158,8 @@ interface MediaProjectionAppSelectorComponent {

    val controller: MediaProjectionAppSelectorController
    val recentsViewController: MediaProjectionRecentsViewController
    @get:HostUserHandle val hostUserHandle: UserHandle
    @get:PersonalProfile val personalProfileUserHandle: UserHandle

    @MediaProjectionAppSelector val configurationController: ConfigurationController
}
+30 −7
Original line number Diff line number Diff line
@@ -17,24 +17,36 @@
package com.android.systemui.mediaprojection.appselector

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.RecentTaskListProvider
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import javax.inject.Inject

@MediaProjectionAppSelectorScope
class MediaProjectionAppSelectorController @Inject constructor(
class MediaProjectionAppSelectorController
@Inject
constructor(
    private val recentTaskListProvider: RecentTaskListProvider,
    private val view: MediaProjectionAppSelectorView,
    private val flags: FeatureFlags,
    @HostUserHandle private val hostUserHandle: UserHandle,
    @MediaProjectionAppSelector private val scope: CoroutineScope,
    @MediaProjectionAppSelector private val appSelectorComponentName: ComponentName
) {

    fun init() {
        scope.launch {
            val tasks = recentTaskListProvider.loadRecentTasks().sortTasks()
            val recentTasks = recentTaskListProvider.loadRecentTasks()

            val tasks = recentTasks
                .filterDevicePolicyRestrictedTasks()
                .sortedTasks()

            view.bind(tasks)
        }
    }
@@ -43,8 +55,19 @@ class MediaProjectionAppSelectorController @Inject constructor(
        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
        it.topActivityComponent == appSelectorComponentName
    }
Loading