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

Commit 03bb0fb6 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Implement an empty constructor for DialogFragments" into main

parents 42aa7bde 699df130
Loading
Loading
Loading
Loading
+22 −15
Original line number Diff line number Diff line
@@ -47,19 +47,21 @@ android_app {
    sdk_version: "system_current",
    rename_resources_package: false,
    static_libs: [
        "androidx.leanback_leanback",
        "android.content.pm.flags-aconfig-java",
        "android.multiuser.flags-aconfig-java",
        "android.os.flags-aconfig-java",
        "androidx.annotation_annotation",
        "androidx.fragment_fragment",
        "androidx.lifecycle_lifecycle-livedata",
        "androidx.leanback_leanback",
        "androidx.lifecycle_lifecycle-extensions",
        "android.content.pm.flags-aconfig-java",
        "android.os.flags-aconfig-java",
        "android.multiuser.flags-aconfig-java",
        "androidx.lifecycle_lifecycle-livedata",
        "kotlin-parcelize-runtime",
    ],

    lint: {
        error_checks: ["Recycle"],
    },
    kotlin_plugins: ["kotlin-parcelize-compiler-plugin"],
}

android_app {
@@ -79,19 +81,22 @@ android_app {
    overrides: ["PackageInstaller"],

    static_libs: [
        "androidx.leanback_leanback",
        "androidx.fragment_fragment",
        "androidx.lifecycle_lifecycle-livedata",
        "androidx.lifecycle_lifecycle-extensions",
        "android.content.pm.flags-aconfig-java",
        "android.os.flags-aconfig-java",
        "android.multiuser.flags-aconfig-java",
        "android.os.flags-aconfig-java",
        "androidx.annotation_annotation",
        "androidx.fragment_fragment",
        "androidx.leanback_leanback",
        "androidx.lifecycle_lifecycle-extensions",
        "androidx.lifecycle_lifecycle-livedata",
        "kotlin-parcelize-runtime",
    ],
    aaptflags: ["--product tablet"],

    lint: {
        error_checks: ["Recycle"],
    },
    kotlin_plugins: ["kotlin-parcelize-compiler-plugin"],
}

android_app {
@@ -111,18 +116,20 @@ android_app {
    overrides: ["PackageInstaller"],

    static_libs: [
        "androidx.leanback_leanback",
        "android.content.pm.flags-aconfig-java",
        "android.multiuser.flags-aconfig-java",
        "android.os.flags-aconfig-java",
        "androidx.annotation_annotation",
        "androidx.fragment_fragment",
        "androidx.lifecycle_lifecycle-livedata",
        "androidx.leanback_leanback",
        "androidx.lifecycle_lifecycle-extensions",
        "android.content.pm.flags-aconfig-java",
        "android.os.flags-aconfig-java",
        "android.multiuser.flags-aconfig-java",
        "androidx.lifecycle_lifecycle-livedata",
        "kotlin-parcelize-runtime",
    ],
    aaptflags: ["--product tv"],

    lint: {
        error_checks: ["Recycle"],
    },
    kotlin_plugins: ["kotlin-parcelize-compiler-plugin"],
}
+5 −5
Original line number Diff line number Diff line
@@ -18,8 +18,8 @@ package com.android.packageinstaller.v2.model

import android.app.Activity
import android.content.Intent
import android.content.pm.PackageManager
import android.content.pm.PackageInstaller
import android.content.pm.PackageManager
import android.graphics.drawable.Drawable

sealed class InstallStage(val stageCode: Int) {
@@ -42,7 +42,7 @@ class InstallReady : InstallStage(STAGE_READY)

data class InstallUserActionRequired(
    val actionReason: Int,
    private val appSnippet: PackageUtil.AppSnippet? = null,
    val appSnippet: PackageUtil.AppSnippet? = null,
    val isAppUpdating: Boolean = false,
    /**
     * This holds either a package name or the app label of the install source.
@@ -63,7 +63,7 @@ data class InstallUserActionRequired(
    }
}

data class InstallInstalling(private val appSnippet: PackageUtil.AppSnippet) :
data class InstallInstalling(val appSnippet: PackageUtil.AppSnippet) :
    InstallStage(STAGE_INSTALLING) {

    val appIcon: Drawable?
@@ -74,7 +74,7 @@ data class InstallInstalling(private val appSnippet: PackageUtil.AppSnippet) :
}

data class InstallSuccess(
    private val appSnippet: PackageUtil.AppSnippet,
    val appSnippet: PackageUtil.AppSnippet,
    val shouldReturnResult: Boolean = false,
    /**
     *
@@ -95,7 +95,7 @@ data class InstallSuccess(
}

data class InstallFailed(
    private val appSnippet: PackageUtil.AppSnippet? = null,
    val appSnippet: PackageUtil.AppSnippet? = null,
    val legacyCode: Int,
    val statusCode: Int,
    val message: String? = null,
+110 −6
Original line number Diff line number Diff line
@@ -17,21 +17,32 @@
package com.android.packageinstaller.v2.model

import android.Manifest
import android.annotation.SuppressLint
import android.app.ActivityManager
import android.content.Context
import android.content.pm.ApplicationInfo
import android.content.pm.PackageInfo
import android.content.pm.PackageInstaller
import android.content.pm.PackageManager
import android.content.res.Resources
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.Build
import android.os.Parcel
import android.os.Parcelable
import android.os.Process
import android.os.UserHandle
import android.os.UserManager
import android.util.Log
import com.android.packageinstaller.v2.model.PackageUtil.getAppSnippet
import java.io.ByteArrayOutputStream
import java.io.File
import kotlinx.parcelize.Parceler
import kotlinx.parcelize.Parcelize

object PackageUtil {
    private val LOG_TAG = InstallRepository::class.java.simpleName
@@ -39,6 +50,24 @@ object PackageUtil {
    private const val SPLIT_BASE_APK_SUFFIX = "base.apk"
    const val localLogv = false

    const val ARGS_ABORT_REASON: String = "abort_reason"
    const val ARGS_ACTION_REASON: String = "action_reason"
    const val ARGS_ACTIVITY_RESULT_CODE: String = "activity_result_code"
    const val ARGS_APP_DATA_SIZE: String = "app_data_size"
    const val ARGS_APP_LABEL: String = "app_label"
    const val ARGS_APP_SNIPPET: String = "app_snippet"
    const val ARGS_ERROR_DIALOG_TYPE: String = "error_dialog_type"
    const val ARGS_IS_ARCHIVE: String = "is_archive"
    const val ARGS_IS_CLONE_USER: String = "clone_user"
    const val ARGS_IS_UPDATING: String = "is_updating"
    const val ARGS_LEGACY_CODE: String = "legacy_code"
    const val ARGS_MESSAGE: String = "message"
    const val ARGS_RESULT_INTENT: String = "result_intent"
    const val ARGS_SHOULD_RETURN_RESULT: String = "should_return_result"
    const val ARGS_SOURCE_APP: String = "source_app"
    const val ARGS_STATUS_CODE: String = "status_code"
    const val ARGS_TITLE: String = "title"

    /**
     * Determines if the UID belongs to the system downloads provider and returns the
     * [ApplicationInfo] of the provider
@@ -238,7 +267,8 @@ object PackageUtil {
            context.resources,
            info.getAppIcon()
        ) else pm.defaultActivityIcon
        return AppSnippet(label, icon)
        val largeIconSize = getLargeIconSize(context)
        return AppSnippet(label, icon, largeIconSize)
    }

    /**
@@ -247,8 +277,11 @@ object PackageUtil {
     */
    @JvmStatic
    fun getAppSnippet(context: Context, pkgInfo: PackageInfo): AppSnippet {
        val largeIconSize = getLargeIconSize(context)
        return pkgInfo.applicationInfo?.let { getAppSnippet(context, it) } ?: run {
            AppSnippet(pkgInfo.packageName, context.packageManager.defaultActivityIcon)
            AppSnippet(
                pkgInfo.packageName, context.packageManager.defaultActivityIcon, largeIconSize
            )
        }
    }

@@ -261,7 +294,8 @@ object PackageUtil {
        val pm = context.packageManager
        val label = pm.getApplicationLabel(appInfo)
        val icon = pm.getApplicationIcon(appInfo)
        return AppSnippet(label, icon)
        val largeIconSize = getLargeIconSize(context)
        return AppSnippet(label, icon, largeIconSize)
    }

    /**
@@ -270,16 +304,24 @@ object PackageUtil {
     */
    @JvmStatic
    fun getAppSnippet(context: Context, pkgInfo: PackageInfo, sourceFile: File): AppSnippet {
        val largeIconSize = getLargeIconSize(context)
        pkgInfo.applicationInfo?.let {
            val appInfoFromFile = processAppInfoForFile(it, sourceFile)
            val label = getAppLabelFromFile(context, appInfoFromFile)
            val icon = getAppIconFromFile(context, appInfoFromFile)
            return AppSnippet(label, icon)
            return AppSnippet(label, icon, largeIconSize)
        } ?: run {
            return AppSnippet(pkgInfo.packageName, context.packageManager.defaultActivityIcon)
            return AppSnippet(
                pkgInfo.packageName, context.packageManager.defaultActivityIcon, largeIconSize
            )
        }
    }

    private fun getLargeIconSize(context: Context): Int {
        val am = context.getSystemService<ActivityManager>(ActivityManager::class.java)
        return am.launcherLargeIconSize
    }

    /**
     * Utility method to load application label
     *
@@ -438,7 +480,69 @@ object PackageUtil {
     * The class to hold an incoming package's icon and label.
     * See [getAppSnippet]
     */
    data class AppSnippet(var label: CharSequence?, var icon: Drawable?) {
    @Parcelize
    data class AppSnippet(
        var label: CharSequence?,
        var icon: Drawable?,
        var iconSize: Int,
    ) : Parcelable {
        private companion object : Parceler<AppSnippet> {
            override fun AppSnippet.write(dest: Parcel, flags: Int) {
                dest.writeString(label.toString())

                val bmp = getBitmapFromDrawable(icon!!)
                dest.writeBlob(getBytesFromBitmap(bmp))
                bmp.recycle()

                dest.writeInt(iconSize)
            }

            @SuppressLint("UseKtx")
            override fun create(parcel: Parcel): AppSnippet {
                val label = parcel.readString()

                val b: ByteArray = parcel.readBlob()!!
                val bmp: Bitmap? = BitmapFactory.decodeByteArray(b, 0, b.size)
                val icon = BitmapDrawable(Resources.getSystem(), bmp)

                val iconSize = parcel.readInt()

                return AppSnippet(label.toString(), icon, iconSize)
            }
        }

        @SuppressLint("UseKtx")
        private fun getBitmapFromDrawable(drawable: Drawable): Bitmap {
            // Create an empty bitmap with the dimensions of our drawable
            val bmp = Bitmap.createBitmap(
                drawable.intrinsicWidth,
                drawable.intrinsicHeight, Bitmap.Config.ARGB_8888
            )
            // Associate it with a canvas. This canvas will draw the icon on the bitmap
            val canvas = Canvas(bmp)
            // Draw the drawable in the canvas. The canvas will ultimately paint the drawable in the
            // bitmap held within
            drawable.draw(canvas)

            // Scale it down if the icon is too large
            if ((bmp.getWidth() > iconSize * 2) || (bmp.getHeight() > iconSize * 2)) {
                val scaledBitmap = Bitmap.createScaledBitmap(bmp, iconSize, iconSize, true)
                if (scaledBitmap != bmp) {
                    bmp.recycle()
                }
                return scaledBitmap
            }
            return bmp
        }

        private fun getBytesFromBitmap(bmp: Bitmap): ByteArray? {
            var baos = ByteArrayOutputStream()
            baos.use {
                bmp.compress(Bitmap.CompressFormat.PNG, 100, it)
            }
            return baos.toByteArray()
        }

        override fun toString(): String {
            return "AppSnippet[label = $label, hasIcon = ${icon != null}]"
        }
+10 −9
Original line number Diff line number Diff line
@@ -133,9 +133,10 @@ class InstallLaunch : FragmentActivity(), InstallActionListener {
                val aborted = installStage as InstallAborted
                when (aborted.abortReason) {
                    InstallAborted.ABORT_REASON_DONE,
                    InstallAborted.ABORT_REASON_INTERNAL_ERROR -> {
                    InstallAborted.ABORT_REASON_INTERNAL_ERROR,
                        -> {
                        if (aborted.errorDialogType == InstallAborted.DLG_PACKAGE_ERROR) {
                            val parseErrorDialog = ParseErrorFragment(aborted)
                            val parseErrorDialog = ParseErrorFragment.newInstance(aborted)
                            showDialogInner(parseErrorDialog)
                        } else {
                            setResult(aborted.activityResultCode, aborted.resultIntent, true)
@@ -151,12 +152,12 @@ class InstallLaunch : FragmentActivity(), InstallActionListener {
                val uar = installStage as InstallUserActionRequired
                when (uar.actionReason) {
                    InstallUserActionRequired.USER_ACTION_REASON_INSTALL_CONFIRMATION -> {
                        val actionDialog = InstallConfirmationFragment(uar)
                        val actionDialog = InstallConfirmationFragment.newInstance(uar)
                        showDialogInner(actionDialog)
                    }

                    InstallUserActionRequired.USER_ACTION_REASON_UNKNOWN_SOURCE -> {
                        val externalSourceDialog = ExternalSourcesBlockedFragment(uar)
                        val externalSourceDialog = ExternalSourcesBlockedFragment.newInstance(uar)
                        showDialogInner(externalSourceDialog)
                    }

@@ -169,7 +170,7 @@ class InstallLaunch : FragmentActivity(), InstallActionListener {

            InstallStage.STAGE_INSTALLING -> {
                val installing = installStage as InstallInstalling
                val installingDialog = InstallInstallingFragment(installing)
                val installingDialog = InstallInstallingFragment.newInstance(installing)
                showDialogInner(installingDialog)
            }

@@ -179,7 +180,7 @@ class InstallLaunch : FragmentActivity(), InstallActionListener {
                    val successIntent = success.resultIntent
                    setResult(RESULT_OK, successIntent, true)
                } else {
                    val successDialog = InstallSuccessFragment(success)
                    val successDialog = InstallSuccessFragment.newInstance(success)
                    showDialogInner(successDialog)
                }
            }
@@ -190,7 +191,7 @@ class InstallLaunch : FragmentActivity(), InstallActionListener {
                    val failureIntent = failed.resultIntent
                    setResult(RESULT_FIRST_USER, failureIntent, true)
                } else {
                    val failureDialog = InstallFailedFragment(failed)
                    val failureDialog = InstallFailedFragment.newInstance(failed)
                    showDialogInner(failureDialog)
                }
            }
@@ -242,11 +243,11 @@ class InstallLaunch : FragmentActivity(), InstallActionListener {
        }
        return when (restriction) {
            UserManager.DISALLOW_INSTALL_APPS ->
                SimpleErrorFragment(R.string.install_apps_user_restriction_dlg_text)
                SimpleErrorFragment.newInstance(R.string.install_apps_user_restriction_dlg_text)

            UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES,
            UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY ->
                SimpleErrorFragment(R.string.unknown_apps_user_restriction_dlg_text)
                SimpleErrorFragment.newInstance(R.string.unknown_apps_user_restriction_dlg_text)

            else -> null
        }
+3 −3
Original line number Diff line number Diff line
@@ -101,7 +101,7 @@ class UninstallLaunch : FragmentActivity(), UninstallActionListener {
                if (aborted.abortReason == UninstallAborted.ABORT_REASON_APP_UNAVAILABLE ||
                    aborted.abortReason == UninstallAborted.ABORT_REASON_USER_NOT_ALLOWED
                ) {
                    val errorDialog = UninstallErrorFragment(aborted)
                    val errorDialog = UninstallErrorFragment.newInstance(aborted)
                    showDialogInner(errorDialog)
                } else {
                    setResult(aborted.activityResultCode, null, true)
@@ -110,7 +110,7 @@ class UninstallLaunch : FragmentActivity(), UninstallActionListener {

            UninstallStage.STAGE_USER_ACTION_REQUIRED -> {
                val uar = uninstallStage as UninstallUserActionRequired
                val confirmationDialog = UninstallConfirmationFragment(uar)
                val confirmationDialog = UninstallConfirmationFragment.newInstance(uar)
                showDialogInner(confirmationDialog)
            }

@@ -120,7 +120,7 @@ class UninstallLaunch : FragmentActivity(), UninstallActionListener {
                //  And a fragment if the user requests a result back. Should we consolidate and
                //  show a fragment always?
                val uninstalling = uninstallStage as UninstallUninstalling
                val uninstallingDialog = UninstallUninstallingFragment(uninstalling)
                val uninstallingDialog = UninstallUninstallingFragment.newInstance(uninstalling)
                showDialogInner(uninstallingDialog)
            }

Loading