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

Commit d6493f45 authored by Vinit Nayak's avatar Vinit Nayak
Browse files

Improve null safety for app pairs

- Improves crash safety in AppPairIcon.java. An app pair should never have more or fewer than 2 app members, but if it happens somehow and there is an app pair on the home screen, the device will enter a crash loop that is hard to recover from. Added some safety checks so that it doesn't happen.

Fixes: 317283244
Test: Manual and presubmit tested
Flag: ACONFIG com.android.wm.shell.enable_app_pairs TEAMFOOD
Change-Id: I2cbd90f028f7c31af6e832b5515502ba992f0b54
parent 0c2204dc
Loading
Loading
Loading
Loading
+22 −6
Original line number Diff line number Diff line
@@ -21,9 +21,11 @@ import android.graphics.Canvas
import android.graphics.Rect
import android.graphics.drawable.Drawable
import android.util.AttributeSet
import android.util.Log
import android.view.Gravity
import android.widget.FrameLayout
import com.android.launcher3.DeviceProfile
import com.android.launcher3.model.data.WorkspaceItemInfo

/**
 * A FrameLayout marking the area on an [AppPairIcon] where the visual icon will be drawn. One of
@@ -31,6 +33,8 @@ import com.android.launcher3.DeviceProfile
 */
class AppPairIconGraphic @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
    FrameLayout(context, attrs) {
    private val TAG = "AppPairIconGraphic"

    companion object {
        // Design specs -- the below ratios are in relation to the size of a standard app icon.
        private const val OUTER_PADDING_SCALE = 1 / 30f
@@ -61,8 +65,8 @@ class AppPairIconGraphic @JvmOverloads constructor(context: Context, attrs: Attr

    private lateinit var parentIcon: AppPairIcon
    private lateinit var appPairBackground: Drawable
    private lateinit var appIcon1: Drawable
    private lateinit var appIcon2: Drawable
    private var appIcon1: Drawable? = null
    private var appIcon2: Drawable? = null

    fun init(grid: DeviceProfile, icon: AppPairIcon) {
        // Calculate device-specific measurements
@@ -79,12 +83,24 @@ class AppPairIconGraphic @JvmOverloads constructor(context: Context, attrs: Attr

        appPairBackground = AppPairIconBackground(context, this)
        appPairBackground.setBounds(0, 0, backgroundSize.toInt(), backgroundSize.toInt())
        applyIcons(parentIcon.info.contents)
    }

    /** Sets up app pair member icons for drawing. */
    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())
            return
        }

        appIcon1 = parentIcon.info.contents[0].newIcon(context)
        appIcon2 = parentIcon.info.contents[1].newIcon(context)
        appIcon1.setBounds(0, 0, memberIconSize.toInt(), memberIconSize.toInt())
        appIcon2.setBounds(0, 0, memberIconSize.toInt(), memberIconSize.toInt())
        appIcon1?.setBounds(0, 0, memberIconSize.toInt(), memberIconSize.toInt())
        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())
@@ -118,7 +134,7 @@ class AppPairIconGraphic @JvmOverloads constructor(context: Context, attrs: Attr
        } else {
            canvas.translate(width / 2f - memberIconSize / 2f, innerPadding)
        }
        appIcon1.draw(canvas)
        appIcon1?.draw(canvas)
        canvas.restore()

        // Draw second icon
@@ -135,7 +151,7 @@ class AppPairIconGraphic @JvmOverloads constructor(context: Context, attrs: Attr
                height - (innerPadding + memberIconSize)
            )
        }
        appIcon2.draw(canvas)
        appIcon2?.draw(canvas)
        canvas.restore()
    }
}