Adding more properties in LaunchCookie, instead of just itemId
This allows better matching of items who do not have a fixed id
Bug: 364363493
Flag: EXEMPT bug fix
Test: Manual- Verified app launch and back animation
Change-Id: I4f9deba89399b89974686b64226b99f91a3d46be
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index bafb528..961651e 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -241,6 +241,7 @@
import com.android.launcher3.util.ScreenOnTracker;
import com.android.launcher3.util.ScreenOnTracker.ScreenOnListener;
import com.android.launcher3.util.SettingsCache;
+import com.android.launcher3.util.StableViewInfo;
import com.android.launcher3.util.SystemUiController;
import com.android.launcher3.util.Themes;
import com.android.launcher3.util.Thunk;
@@ -2424,17 +2425,16 @@
* Similar to {@link #getFirstMatch} but optimized to finding a suitable view for the app close
* animation.
*
- * @param preferredItemId The id of the preferred item to match to if it exists,
- * or ItemInfo#NO_MATCHING_ID if you want to not match by item id
+ * @param svi The StableViewInfo of the preferred item to match to if it exists or null
* @param packageName The package name of the app to match.
* @param user The user of the app to match.
* @param supportsAllAppsState If true and we are in All Apps state, looks for view in All Apps.
* Else we only looks on the workspace.
*/
- public @Nullable View getFirstMatchForAppClose(int preferredItemId, String packageName,
+ public @Nullable View getFirstMatchForAppClose(
+ @Nullable StableViewInfo svi, String packageName,
UserHandle user, boolean supportsAllAppsState) {
- final Predicate<ItemInfo> preferredItem = info ->
- info != null && info.id == preferredItemId;
+ final Predicate<ItemInfo> preferredItem = svi == null ? i -> false : svi::matches;
final Predicate<ItemInfo> packageAndUserAndApp = info ->
info != null
&& info.itemType == ITEM_TYPE_APPLICATION
@@ -2525,6 +2525,9 @@
final int itemCount = container.getChildCount();
for (int itemIdx = 0; itemIdx < itemCount; itemIdx++) {
View item = container.getChildAt(itemIdx);
+ if (item.getVisibility() != View.VISIBLE) {
+ continue;
+ }
if (item instanceof ViewGroup viewGroup) {
View view = mapOverViewGroup(viewGroup, op);
if (view != null) {
diff --git a/src/com/android/launcher3/model/data/ItemInfo.java b/src/com/android/launcher3/model/data/ItemInfo.java
index 62198cb..b706d24 100644
--- a/src/com/android/launcher3/model/data/ItemInfo.java
+++ b/src/com/android/launcher3/model/data/ItemInfo.java
@@ -81,8 +81,6 @@
public static final boolean DEBUG = false;
public static final int NO_ID = -1;
- // An id that doesn't match any item, including predicted apps with have an id=NO_ID
- public static final int NO_MATCHING_ID = Integer.MIN_VALUE;
/** Hidden field Settings.Secure.NAV_BAR_KIDS_MODE */
private static final Uri NAV_BAR_KIDS_MODE = Settings.Secure.getUriFor("nav_bar_kids_mode");
@@ -545,6 +543,14 @@
this.title = title;
}
+ /**
+ * Returns a string ID that is stable for a user session, but may not be persisted
+ */
+ @Nullable
+ public Object getStableId() {
+ return getComponentKey();
+ }
+
private int getUserType(UserIconInfo info) {
if (info == null) {
return SysUiStatsLog.LAUNCHER_UICHANGED__USER_TYPE__TYPE_UNKNOWN;
diff --git a/src/com/android/launcher3/util/StableViewInfo.kt b/src/com/android/launcher3/util/StableViewInfo.kt
new file mode 100644
index 0000000..29dcd59
--- /dev/null
+++ b/src/com/android/launcher3/util/StableViewInfo.kt
@@ -0,0 +1,56 @@
+/*
+ * 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.launcher3.util
+
+import android.os.IBinder
+import com.android.launcher3.model.data.ItemInfo
+import com.android.launcher3.model.data.ItemInfo.NO_ID
+
+/** Info parameters that can be used to identify a Launcher object */
+data class StableViewInfo(val itemId: Int, val containerId: Int, val stableId: Any) {
+
+ fun matches(info: ItemInfo?) =
+ info != null &&
+ itemId == info.id &&
+ containerId == info.container &&
+ stableId == info.stableId
+
+ companion object {
+
+ private fun ItemInfo.toStableViewInfo() =
+ stableId?.let { sId ->
+ if (id != NO_ID || container != NO_ID) StableViewInfo(id, container, sId) else null
+ }
+
+ /**
+ * Return a new launch cookie for the activity launch if supported.
+ *
+ * @param info the item info for the launch
+ */
+ @JvmStatic
+ fun toLaunchCookie(info: ItemInfo?) =
+ info?.toStableViewInfo()?.let { ObjectWrapper.wrap(it) }
+
+ /**
+ * Unwraps the binder and returns the first non-null StableViewInfo in the list or null if
+ * none can be found
+ */
+ @JvmStatic
+ fun fromLaunchCookies(launchCookies: List<IBinder>) =
+ launchCookies.firstNotNullOfOrNull { ObjectWrapper.unwrap<StableViewInfo>(it) }
+ }
+}
diff --git a/src/com/android/launcher3/views/FloatingSurfaceView.java b/src/com/android/launcher3/views/FloatingSurfaceView.java
index 7fa7517..5f8e2c0 100644
--- a/src/com/android/launcher3/views/FloatingSurfaceView.java
+++ b/src/com/android/launcher3/views/FloatingSurfaceView.java
@@ -15,7 +15,6 @@
*/
package com.android.launcher3.views;
-import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID;
import static com.android.launcher3.views.FloatingIconView.getLocationBoundsForView;
import static com.android.launcher3.views.FloatingIconViewCompanion.setPropertiesVisible;
@@ -160,7 +159,7 @@
if (mContract == null) {
return;
}
- View icon = mLauncher.getFirstMatchForAppClose(NO_MATCHING_ID,
+ View icon = mLauncher.getFirstMatchForAppClose(null /* StableViewInfo */,
mContract.componentName.getPackageName(), mContract.user,
false /* supportsAllAppsState */);