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

Commit 01fc9324 authored by Chris Göllner's avatar Chris Göllner Committed by Chris Göllner
Browse files

[Partial Screen Sharing] Fix app selector not animating out when the selected...

[Partial Screen Sharing] Fix app selector not animating out when the selected task is the foreground task

Test: MediaProjectionRecentsViewControllerTest
Test: Manual
Fixes: 314385883
Flag: ACONFIG com.android.systemui.pss_app_selector_abrupt_exit_fix DISABLED
Change-Id: Ic4a8f65c168a8a963502da8e71617732968e25a8
parent 09b53269
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -4364,6 +4364,7 @@
  <java-symbol type="dimen" name="seekbar_thumb_exclusion_max_size" />
  <java-symbol type="layout" name="chooser_az_label_row" />
  <java-symbol type="string" name="chooser_all_apps_button_label" />
  <java-symbol type="anim" name="resolver_close_anim" />
  <java-symbol type="anim" name="resolver_launch_anim" />
  <java-symbol type="style" name="Animation.DeviceDefault.Activity.Resolver" />

+11 −0
Original line number Diff line number Diff line
@@ -83,6 +83,17 @@ flag {
    bug: "308623704"
}

flag {
   name: "pss_app_selector_abrupt_exit_fix"
   namespace: "systemui"
   description: "Fixes the app selector abruptly disappearing without an animation, when the"
        "selected task is the foreground task."
   bug: "314385883"
   metadata {
        purpose: PURPOSE_BUGFIX
   }
}

flag {
    name: "notifications_background_media_icons"
    namespace: "systemui"
+25 −9
Original line number Diff line number Diff line
@@ -26,12 +26,13 @@ import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.android.systemui.res.R
import com.android.systemui.Flags.pssAppSelectorAbruptExitFix
import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorResultHandler
import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorScope
import com.android.systemui.mediaprojection.appselector.data.RecentTask
import com.android.systemui.mediaprojection.appselector.view.RecentTasksAdapter.RecentTaskClickListener
import com.android.systemui.mediaprojection.appselector.view.TaskPreviewSizeProvider.TaskPreviewSizeListener
import com.android.systemui.res.R
import com.android.systemui.util.recycler.HorizontalSpacerItemDecoration
import javax.inject.Inject

@@ -122,14 +123,7 @@ constructor(

    override fun onRecentAppClicked(task: RecentTask, view: View) {
        val launchCookie = LaunchCookie()
        val activityOptions =
            ActivityOptions.makeScaleUpAnimation(
                view,
                /* startX= */ 0,
                /* startY= */ 0,
                view.width,
                view.height
            )
        val activityOptions = createAnimation(task, view)
        activityOptions.pendingIntentBackgroundActivityStartMode =
            MODE_BACKGROUND_ACTIVITY_START_ALLOWED
        activityOptions.setLaunchCookie(launchCookie)
@@ -139,6 +133,28 @@ constructor(
        resultHandler.returnSelectedApp(launchCookie)
    }

    private fun createAnimation(task: RecentTask, view: View): ActivityOptions =
        if (pssAppSelectorAbruptExitFix() && task.isForegroundTask) {
            // When the selected task is in the foreground, the scale up animation doesn't work.
            // We fallback to the default close animation.
            ActivityOptions.makeCustomTaskAnimation(
                view.context,
                /* enterResId= */ 0,
                /* exitResId= */ com.android.internal.R.anim.resolver_close_anim,
                /* handler = */ null,
                /* startedListener = */ null,
                /* finishedListener = */ null
            )
        } else {
            ActivityOptions.makeScaleUpAnimation(
                view,
                /* startX= */ 0,
                /* startY= */ 0,
                view.width,
                view.height
            )
        }

    override fun onTaskSizeChanged(size: Rect) {
        views?.recentsContainer?.setTaskHeightSize()
    }
+129 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.view

import android.app.ActivityOptions
import android.app.IActivityTaskManager
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import androidx.test.filters.SmallTest
import com.android.systemui.Flags.FLAG_PSS_APP_SELECTOR_ABRUPT_EXIT_FIX
import com.android.systemui.SysuiTestCase
import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorResultHandler
import com.android.systemui.mediaprojection.appselector.data.RecentTask
import com.android.systemui.util.mockito.mock
import com.google.common.truth.Expect
import com.google.common.truth.Truth.assertThat
import org.junit.Rule
import org.junit.Test
import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers.eq
import org.mockito.Mockito.any
import org.mockito.Mockito.verify

@SmallTest
class MediaProjectionRecentsViewControllerTest : SysuiTestCase() {

    @get:Rule val expect: Expect = Expect.create()

    private val recentTasksAdapter = mock<RecentTasksAdapter>()
    private val tasksAdapterFactory = RecentTasksAdapter.Factory { _, _ -> recentTasksAdapter }
    private val taskViewSizeProvider = mock<TaskPreviewSizeProvider>()
    private val activityTaskManager = mock<IActivityTaskManager>()
    private val resultHandler = mock<MediaProjectionAppSelectorResultHandler>()
    private val bundleCaptor = ArgumentCaptor.forClass(Bundle::class.java)

    private val task =
        RecentTask(
            taskId = 123,
            displayId = 456,
            userId = 789,
            topActivityComponent = null,
            baseIntentComponent = null,
            colorBackground = null,
            isForegroundTask = false
        )

    private val taskView =
        View(context).apply {
            layoutParams = ViewGroup.LayoutParams(/* width = */ 100, /* height = */ 200)
        }

    private val controller =
        MediaProjectionRecentsViewController(
            tasksAdapterFactory,
            taskViewSizeProvider,
            activityTaskManager,
            resultHandler
        )

    @Test
    fun onRecentAppClicked_taskWithSameIdIsStartedFromRecents() {
        controller.onRecentAppClicked(task, taskView)

        verify(activityTaskManager).startActivityFromRecents(eq(task.taskId), any())
    }

    @Test
    fun onRecentAppClicked_launchDisplayIdIsSet() {
        controller.onRecentAppClicked(task, taskView)

        assertThat(getStartedTaskActivityOptions().launchDisplayId).isEqualTo(task.displayId)
    }

    @Test
    fun onRecentAppClicked_taskNotInForeground_usesScaleUpAnimation() {
        controller.onRecentAppClicked(task, taskView)

        assertThat(getStartedTaskActivityOptions().animationType)
            .isEqualTo(ActivityOptions.ANIM_SCALE_UP)
    }

    @Test
    fun onRecentAppClicked_taskInForeground_flagOff_usesScaleUpAnimation() {
        mSetFlagsRule.disableFlags(FLAG_PSS_APP_SELECTOR_ABRUPT_EXIT_FIX)

        controller.onRecentAppClicked(task, taskView)

        assertThat(getStartedTaskActivityOptions().animationType)
            .isEqualTo(ActivityOptions.ANIM_SCALE_UP)
    }

    @Test
    fun onRecentAppClicked_taskInForeground_flagOn_usesDefaultAnimation() {
        mSetFlagsRule.enableFlags(FLAG_PSS_APP_SELECTOR_ABRUPT_EXIT_FIX)
        val foregroundTask = task.copy(isForegroundTask = true)

        controller.onRecentAppClicked(foregroundTask, taskView)

        expect
            .that(getStartedTaskActivityOptions().animationType)
            .isEqualTo(ActivityOptions.ANIM_CUSTOM)
        expect.that(getStartedTaskActivityOptions().overrideTaskTransition).isTrue()
        expect
            .that(getStartedTaskActivityOptions().customExitResId)
            .isEqualTo(com.android.internal.R.anim.resolver_close_anim)
        expect.that(getStartedTaskActivityOptions().customEnterResId).isEqualTo(0)
    }

    private fun getStartedTaskActivityOptions(): ActivityOptions {
        verify(activityTaskManager)
            .startActivityFromRecents(eq(task.taskId), bundleCaptor.capture())
        return ActivityOptions.fromBundle(bundleCaptor.value)
    }
}