From cfcf2255dc5abbddcafae334d42ca5e0790183a1 Mon Sep 17 00:00:00 2001 From: Jeremy Sim Date: Tue, 30 Jan 2024 17:30:51 +0800 Subject: [PATCH] Add error logging and better crash safety for app pairs This causes app pairs to log an error message if creation or icon inflation is attempted with contents != 2. App pairs with wrong numbers of members should not be created anymore. Fixes: 317283244 Fixes: 322892793 Test: Manual Flag: ACONFIG com.android.wm.shell.enable_app_pairs TEAMFOOD Change-Id: I5e454042719bb67187f900c546380bb44cfc34ac --- .../quickstep/util/AppPairsController.java | 15 ++++++++++++++- .../android/launcher3/apppairs/AppPairIcon.java | 15 ++++++++++++--- .../launcher3/apppairs/AppPairIconGraphic.kt | 3 +-- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/quickstep/src/com/android/quickstep/util/AppPairsController.java b/quickstep/src/com/android/quickstep/util/AppPairsController.java index 0f3c029a3b..839320ed3b 100644 --- a/quickstep/src/com/android/quickstep/util/AppPairsController.java +++ b/quickstep/src/com/android/quickstep/util/AppPairsController.java @@ -27,6 +27,7 @@ import static com.android.wm.shell.common.split.SplitScreenConstants.isPersisten import android.app.ActivityTaskManager; import android.content.Context; import android.content.Intent; +import android.util.Log; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; @@ -58,6 +59,8 @@ import java.util.Arrays; * ratio. */ public class AppPairsController { + private static final String TAG = "AppPairsController"; + // Used for encoding and decoding the "rank" attribute private static final int BITMASK_SIZE = 16; private static final int BITMASK_FOR_SNAP_POSITION = (1 << BITMASK_SIZE) - 1; @@ -89,13 +92,23 @@ public class AppPairsController { @PersistentSnapPosition int snapPosition = gtv.getSnapPosition(); if (!isPersistentSnapPosition(snapPosition)) { - throw new RuntimeException("tried to save an app pair with illegal snapPosition"); + // if we received an illegal snap position, log an error and do not create the app pair. + Log.wtf(TAG, "tried to save an app pair with illegal snapPosition " + snapPosition); + return; } app1.rank = encodeRank(SPLIT_POSITION_TOP_OR_LEFT, snapPosition); app2.rank = encodeRank(SPLIT_POSITION_BOTTOM_OR_RIGHT, snapPosition); FolderInfo newAppPair = FolderInfo.createAppPair(app1, app2); + if (newAppPair.contents.size() != 2) { + // if app pair doesn't have exactly 2 members, log an error and do not create the app + // pair. + Log.wtf(TAG, + "tried to save an app pair with " + newAppPair.contents.size() + " members"); + return; + } + IconCache iconCache = LauncherAppState.getInstance(mContext).getIconCache(); MODEL_EXECUTOR.execute(() -> { newAppPair.contents.forEach(member -> { diff --git a/src/com/android/launcher3/apppairs/AppPairIcon.java b/src/com/android/launcher3/apppairs/AppPairIcon.java index 1d73441b71..9b85a655e0 100644 --- a/src/com/android/launcher3/apppairs/AppPairIcon.java +++ b/src/com/android/launcher3/apppairs/AppPairIcon.java @@ -19,6 +19,7 @@ package com.android.launcher3.apppairs; import android.content.Context; import android.graphics.Rect; import android.util.AttributeSet; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -45,6 +46,8 @@ import java.util.Comparator; * member apps are set into these rectangles. */ public class AppPairIcon extends FrameLayout implements DraggableView, Reorderable { + private static final String TAG = "AppPairIcon"; + // A view that holds the app pair icon graphic. private AppPairIconGraphic mIconGraphic; // A view that holds the app pair's title. @@ -96,8 +99,7 @@ public class AppPairIcon extends FrameLayout implements DraggableView, Reorderab icon.mAppPairName.setText(appPairInfo.title); // Set up accessibility - icon.setContentDescription(icon.getAccessibilityTitle( - appPairInfo.contents.get(0).title, appPairInfo.contents.get(1).title)); + icon.setContentDescription(icon.getAccessibilityTitle(appPairInfo)); icon.setAccessibilityDelegate(activity.getAccessibilityDelegate()); return icon; @@ -106,7 +108,14 @@ public class AppPairIcon extends FrameLayout implements DraggableView, Reorderab /** * Returns a formatted accessibility title for app pairs. */ - public String getAccessibilityTitle(CharSequence app1, CharSequence app2) { + public String getAccessibilityTitle(FolderInfo appPairInfo) { + if (appPairInfo.contents.size() != 2) { + Log.wtf(TAG, "AppPair contents not 2, size: " + appPairInfo.contents.size()); + return ""; + } + + CharSequence app1 = appPairInfo.contents.get(0).title; + CharSequence app2 = appPairInfo.contents.get(1).title; return getContext().getString(R.string.app_pair_name_format, app1, app2); } diff --git a/src/com/android/launcher3/apppairs/AppPairIconGraphic.kt b/src/com/android/launcher3/apppairs/AppPairIconGraphic.kt index b2497a3050..6458eb0385 100644 --- a/src/com/android/launcher3/apppairs/AppPairIconGraphic.kt +++ b/src/com/android/launcher3/apppairs/AppPairIconGraphic.kt @@ -93,7 +93,7 @@ class AppPairIconGraphic @JvmOverloads constructor(context: Context, attrs: Attr private fun applyIcons(contents: ArrayList) { // App pair should always contain 2 members; if not 2, return to avoid a crash loop if (contents.size != 2) { - Log.w(TAG, "AppPair contents not 2, size: " + contents.size, Throwable()) + Log.wtf(TAG, "AppPair contents not 2, size: " + contents.size, Throwable()) return } @@ -112,7 +112,6 @@ class AppPairIconGraphic @JvmOverloads constructor(context: Context, attrs: Attr appIcon2?.setBounds(0, 0, memberIconSize.toInt(), memberIconSize.toInt()) } - /** Gets this icon graphic's bounds, with respect to the parent icon's coordinate system. */ fun getIconBounds(outBounds: Rect) { outBounds.set(0, 0, backgroundSize.toInt(), backgroundSize.toInt())