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

Commit cfcf2255 authored by Jeremy Sim's avatar Jeremy Sim
Browse files

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
parent 7b1858cb
Loading
Loading
Loading
Loading
+14 −1
Original line number Diff line number Diff line
@@ -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 -> {
+12 −3
Original line number Diff line number Diff line
@@ -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);
    }

+1 −2
Original line number Diff line number Diff line
@@ -93,7 +93,7 @@ class AppPairIconGraphic @JvmOverloads constructor(context: Context, attrs: Attr
    private fun applyIcons(contents: ArrayList<WorkspaceItemInfo>) {
        // 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())