Merge cherrypicks of ['googleplex-android-review.googlesource.com/27902855', 'googleplex-android-review.googlesource.com/27951519', 'googleplex-android-review.googlesource.com/27976521'] into 24Q3-release.
Change-Id: I700dccc620c1f24e25094d8bd240156d4459e877
diff --git a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
index fd141c3..d18c86e 100644
--- a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
@@ -492,18 +492,8 @@
TaskContainer taskContainer) {
boolean isTablet = container.getDeviceProfile().isTablet;
boolean isGridOnlyOverview = isTablet && Flags.enableGridOnlyOverview();
- // Extra conditions if it's not grid-only overview
if (!isGridOnlyOverview) {
- RecentsOrientedState orientedState = taskContainer.getTaskView().getOrientedState();
- boolean isFakeLandscape = !orientedState.isRecentsActivityRotationAllowed()
- && orientedState.getTouchRotation() != ROTATION_0;
- if (!isFakeLandscape) {
- return null;
- }
- // Disallow "Select" when swiping up from landscape due to rotated thumbnail.
- if (orientedState.getDisplayRotation() != ROTATION_0) {
- return null;
- }
+ return null;
}
SystemShortcut modalStateSystemShortcut =
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 4f802c9..6798676 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -31,6 +31,7 @@
import static com.android.app.animation.Interpolators.LINEAR;
import static com.android.app.animation.Interpolators.OVERSHOOT_0_75;
import static com.android.app.animation.Interpolators.clampToProgress;
+import static com.android.launcher3.AbstractFloatingView.TYPE_REBIND_SAFE;
import static com.android.launcher3.AbstractFloatingView.TYPE_TASK_MENU;
import static com.android.launcher3.AbstractFloatingView.getTopOpenViewWithType;
import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS;
@@ -130,6 +131,7 @@
import androidx.core.graphics.ColorUtils;
import com.android.internal.jank.Cuj;
+import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseActivity.MultiWindowModeChangedListener;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Flags;
@@ -2688,6 +2690,7 @@
}
private void animateRotation(int newRotation) {
+ AbstractFloatingView.closeAllOpenViewsExcept(mContainer, false, TYPE_REBIND_SAFE);
AnimatorSet pa = setRecentsChangedOrientation(true);
pa.addListener(AnimatorListeners.forSuccessCallback(() -> {
setLayoutRotation(newRotation, mOrientationState.getDisplayRotation());
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index dc6968c..312c6f4 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -209,7 +209,7 @@
mApp.getContext().getContentResolver(),
"launcher_broadcast_installed_apps",
/* def= */ 0);
- if (launcherBroadcastInstalledApps == 1) {
+ if (launcherBroadcastInstalledApps == 1 && mIsRestoreFromBackup) {
List<FirstScreenBroadcastModel> broadcastModels =
FirstScreenBroadcastHelper.createModelsForFirstScreenBroadcast(
mPmHelper,
diff --git a/tests/src/com/android/launcher3/model/LoaderTaskTest.kt b/tests/src/com/android/launcher3/model/LoaderTaskTest.kt
index 28a001f..d16674c 100644
--- a/tests/src/com/android/launcher3/model/LoaderTaskTest.kt
+++ b/tests/src/com/android/launcher3/model/LoaderTaskTest.kt
@@ -1,10 +1,13 @@
package com.android.launcher3.model
import android.appwidget.AppWidgetManager
+import android.content.Intent
import android.os.UserHandle
import android.platform.test.flag.junit.SetFlagsRule
+import android.provider.Settings
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
+import com.android.dx.mockito.inline.extended.ExtendedMockito
import com.android.launcher3.Flags
import com.android.launcher3.InvariantDeviceProfile
import com.android.launcher3.LauncherAppState
@@ -14,6 +17,7 @@
import com.android.launcher3.icons.cache.CachingLogic
import com.android.launcher3.icons.cache.IconCacheUpdateHandler
import com.android.launcher3.pm.UserCache
+import com.android.launcher3.provider.RestoreDbTask
import com.android.launcher3.ui.TestViewHelpers
import com.android.launcher3.util.Executors.MODEL_EXECUTOR
import com.android.launcher3.util.LauncherModelHelper.SandboxModelContext
@@ -21,21 +25,30 @@
import com.android.launcher3.util.UserIconInfo
import com.google.common.truth.Truth
import java.util.concurrent.CountDownLatch
+import junit.framework.Assert.assertEquals
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers.any
import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.anyList
+import org.mockito.ArgumentMatchers.anyMap
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.times
-import org.mockito.Mockito.verify
import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
+import org.mockito.MockitoSession
import org.mockito.Spy
+import org.mockito.kotlin.anyOrNull
import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.spy
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.whenever
+import org.mockito.quality.Strictness
private const val INSERTION_STATEMENT_FILE = "databases/workspace_items.sql"
@@ -43,6 +56,20 @@
@RunWith(AndroidJUnit4::class)
class LoaderTaskTest {
private var context = SandboxModelContext()
+ private val expectedBroadcastModel =
+ FirstScreenBroadcastModel(
+ installerPackage = "installerPackage",
+ pendingCollectionItems = mutableSetOf("pendingCollectionItem"),
+ pendingWidgetItems = mutableSetOf("pendingWidgetItem"),
+ pendingHotseatItems = mutableSetOf("pendingHotseatItem"),
+ pendingWorkspaceItems = mutableSetOf("pendingWorkspaceItem"),
+ installedHotseatItems = mutableSetOf("installedHotseatItem"),
+ installedWorkspaceItems = mutableSetOf("installedWorkspaceItem"),
+ firstScreenInstalledWidgets = mutableSetOf("installedFirstScreenWidget"),
+ secondaryScreenInstalledWidgets = mutableSetOf("installedSecondaryScreenWidget")
+ )
+ private lateinit var mockitoSession: MockitoSession
+
@Mock private lateinit var app: LauncherAppState
@Mock private lateinit var bgAllAppsList: AllAppsList
@Mock private lateinit var modelDelegate: ModelDelegate
@@ -61,7 +88,11 @@
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
-
+ mockitoSession =
+ ExtendedMockito.mockitoSession()
+ .strictness(Strictness.LENIENT)
+ .mockStatic(FirstScreenBroadcastHelper::class.java)
+ .startMocking()
val idp =
InvariantDeviceProfile().apply {
numRows = 5
@@ -90,6 +121,7 @@
@After
fun tearDown() {
context.onDestroy()
+ mockitoSession.finishMocking()
}
@Test
@@ -166,6 +198,141 @@
verify(bgAllAppsList, Mockito.never())
.setFlags(BgDataModel.Callbacks.FLAG_QUIET_MODE_ENABLED, true)
}
+
+ @Test
+ fun `When launcher_broadcast_installed_apps and is restore then send installed item broadcast`() {
+ // Given
+ val spyContext = spy(context)
+ `when`(app.context).thenReturn(spyContext)
+ whenever(
+ FirstScreenBroadcastHelper.createModelsForFirstScreenBroadcast(
+ anyOrNull(),
+ anyList(),
+ anyMap(),
+ anyList()
+ )
+ )
+ .thenReturn(listOf(expectedBroadcastModel))
+
+ whenever(
+ FirstScreenBroadcastHelper.sendBroadcastsForModels(
+ spyContext,
+ listOf(expectedBroadcastModel)
+ )
+ )
+ .thenCallRealMethod()
+
+ Settings.Secure.putInt(spyContext.contentResolver, "launcher_broadcast_installed_apps", 1)
+ RestoreDbTask.setPending(spyContext)
+
+ // When
+ LoaderTask(app, bgAllAppsList, BgDataModel(), modelDelegate, launcherBinder)
+ .runSyncOnBackgroundThread()
+
+ // Then
+ val argumentCaptor = ArgumentCaptor.forClass(Intent::class.java)
+ verify(spyContext).sendBroadcast(argumentCaptor.capture())
+ val actualBroadcastIntent = argumentCaptor.value
+ assertEquals(expectedBroadcastModel.installerPackage, actualBroadcastIntent.`package`)
+ assertEquals(
+ ArrayList(expectedBroadcastModel.installedWorkspaceItems),
+ actualBroadcastIntent.getStringArrayListExtra("workspaceInstalledItems")
+ )
+ assertEquals(
+ ArrayList(expectedBroadcastModel.installedHotseatItems),
+ actualBroadcastIntent.getStringArrayListExtra("hotseatInstalledItems")
+ )
+ assertEquals(
+ ArrayList(
+ expectedBroadcastModel.firstScreenInstalledWidgets +
+ expectedBroadcastModel.secondaryScreenInstalledWidgets
+ ),
+ actualBroadcastIntent.getStringArrayListExtra("widgetInstalledItems")
+ )
+ assertEquals(
+ ArrayList(expectedBroadcastModel.pendingCollectionItems),
+ actualBroadcastIntent.getStringArrayListExtra("folderItem")
+ )
+ assertEquals(
+ ArrayList(expectedBroadcastModel.pendingWorkspaceItems),
+ actualBroadcastIntent.getStringArrayListExtra("workspaceItem")
+ )
+ assertEquals(
+ ArrayList(expectedBroadcastModel.pendingHotseatItems),
+ actualBroadcastIntent.getStringArrayListExtra("hotseatItem")
+ )
+ assertEquals(
+ ArrayList(expectedBroadcastModel.pendingWidgetItems),
+ actualBroadcastIntent.getStringArrayListExtra("widgetItem")
+ )
+ }
+
+ @Test
+ fun `When not a restore then installed item broadcast not sent`() {
+ // Given
+ val spyContext = spy(context)
+ `when`(app.context).thenReturn(spyContext)
+ whenever(
+ FirstScreenBroadcastHelper.createModelsForFirstScreenBroadcast(
+ anyOrNull(),
+ anyList(),
+ anyMap(),
+ anyList()
+ )
+ )
+ .thenReturn(listOf(expectedBroadcastModel))
+
+ whenever(
+ FirstScreenBroadcastHelper.sendBroadcastsForModels(
+ spyContext,
+ listOf(expectedBroadcastModel)
+ )
+ )
+ .thenCallRealMethod()
+
+ Settings.Secure.putInt(spyContext.contentResolver, "launcher_broadcast_installed_apps", 1)
+
+ // When
+ LoaderTask(app, bgAllAppsList, BgDataModel(), modelDelegate, launcherBinder)
+ .runSyncOnBackgroundThread()
+
+ // Then
+ verify(spyContext, times(0)).sendBroadcast(any(Intent::class.java))
+ }
+
+ @Test
+ fun `When launcher_broadcast_installed_apps false then installed item broadcast not sent`() {
+ // Given
+ val spyContext = spy(context)
+ `when`(app.context).thenReturn(spyContext)
+ whenever(
+ FirstScreenBroadcastHelper.createModelsForFirstScreenBroadcast(
+ anyOrNull(),
+ anyList(),
+ anyMap(),
+ anyList()
+ )
+ )
+ .thenReturn(listOf(expectedBroadcastModel))
+
+ whenever(
+ FirstScreenBroadcastHelper.sendBroadcastsForModels(
+ spyContext,
+ listOf(expectedBroadcastModel)
+ )
+ )
+ .thenCallRealMethod()
+
+ Settings.Secure.putInt(spyContext.contentResolver, "launcher_broadcast_installed_apps", 0)
+ RestoreDbTask.setPending(spyContext)
+
+ // When
+ LoaderTask(app, bgAllAppsList, BgDataModel(), modelDelegate, launcherBinder)
+ .runSyncOnBackgroundThread()
+
+ // Then
+ verify(spyContext, times(0)).sendBroadcast(any(Intent::class.java))
+ }
}
private fun LoaderTask.runSyncOnBackgroundThread() {