Implement an empty constructor for DialogFragments
Without an empty constructor, Pia crashes when a configuration change
takes palce. Data required by these dialogFragments are now set to
fragment arguments. This means that AppSnippet is now required to be
parcellable.
Bug: 394724957
Test: atest CtsPackageInstallTestCases CtsPackageUninstallTestCases CtsPackageInstallerCUJInstallationTestCases
Flag: android.content.pm.use_pia_v2
Change-Id: If1ff2de6f4ad286619fc40bb10c0b24ec6be5a31
diff --git a/packages/PackageInstaller/Android.bp b/packages/PackageInstaller/Android.bp
index a30c0c3..8b1828c 100644
--- a/packages/PackageInstaller/Android.bp
+++ b/packages/PackageInstaller/Android.bp
@@ -47,19 +47,21 @@
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 @@
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 @@
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"],
}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/model/InstallStages.kt b/packages/PackageInstaller/src/com/android/packageinstaller/v2/model/InstallStages.kt
index 8de8fbb..a8dad09 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/model/InstallStages.kt
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/model/InstallStages.kt
@@ -18,8 +18,8 @@
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 @@
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 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 InstallSuccess(
- private val appSnippet: PackageUtil.AppSnippet,
+ val appSnippet: PackageUtil.AppSnippet,
val shouldReturnResult: Boolean = false,
/**
*
@@ -95,7 +95,7 @@
}
data class InstallFailed(
- private val appSnippet: PackageUtil.AppSnippet? = null,
+ val appSnippet: PackageUtil.AppSnippet? = null,
val legacyCode: Int,
val statusCode: Int,
val message: String? = null,
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/model/PackageUtil.kt b/packages/PackageInstaller/src/com/android/packageinstaller/v2/model/PackageUtil.kt
index 828a95f..e8477ef 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/model/PackageUtil.kt
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/model/PackageUtil.kt
@@ -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 @@
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 @@
context.resources,
info.getAppIcon()
) else pm.defaultActivityIcon
- return AppSnippet(label, icon)
+ val largeIconSize = getLargeIconSize(context)
+ return AppSnippet(label, icon, largeIconSize)
}
/**
@@ -247,8 +277,11 @@
*/
@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 @@
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 @@
*/
@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 @@
* 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}]"
}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/InstallLaunch.kt b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/InstallLaunch.kt
index 481023e..4a8be8d 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/InstallLaunch.kt
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/InstallLaunch.kt
@@ -133,9 +133,10 @@
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 @@
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 @@
InstallStage.STAGE_INSTALLING -> {
val installing = installStage as InstallInstalling
- val installingDialog = InstallInstallingFragment(installing)
+ val installingDialog = InstallInstallingFragment.newInstance(installing)
showDialogInner(installingDialog)
}
@@ -179,7 +180,7 @@
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 @@
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 @@
}
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
}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/UninstallLaunch.kt b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/UninstallLaunch.kt
index 0a02845e..08bc766 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/UninstallLaunch.kt
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/UninstallLaunch.kt
@@ -101,7 +101,7 @@
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 @@
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 @@
// 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)
}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/ExternalSourcesBlockedFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/ExternalSourcesBlockedFragment.java
index 343a213..4c69b9d 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/ExternalSourcesBlockedFragment.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/ExternalSourcesBlockedFragment.java
@@ -16,17 +16,25 @@
package com.android.packageinstaller.v2.ui.fragments;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_ACTION_REASON;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_APP_SNIPPET;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_IS_UPDATING;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_SOURCE_APP;
+
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;
+
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
+
import com.android.packageinstaller.R;
import com.android.packageinstaller.v2.model.InstallUserActionRequired;
+import com.android.packageinstaller.v2.model.PackageUtil.AppSnippet;
import com.android.packageinstaller.v2.ui.InstallActionListener;
/**
@@ -37,14 +45,34 @@
private static final String LOG_TAG = ExternalSourcesBlockedFragment.class.getSimpleName();
@NonNull
- private final InstallUserActionRequired mDialogData;
+ private InstallUserActionRequired mDialogData;
@NonNull
private InstallActionListener mInstallActionListener;
@NonNull
private AlertDialog mDialog;
- public ExternalSourcesBlockedFragment(InstallUserActionRequired dialogData) {
- mDialogData = dialogData;
+ public ExternalSourcesBlockedFragment() {
+ // Required for DialogFragment
+ }
+
+ /**
+ * Creates a new instance of this fragment with necessary data set as fragment arguments
+ *
+ * @param dialogData {@link InstallUserActionRequired} object containing data to display
+ * in the dialog
+ * @return an instance of the fragment
+ */
+ public static ExternalSourcesBlockedFragment newInstance(
+ @NonNull InstallUserActionRequired dialogData) {
+ Bundle args = new Bundle();
+ args.putInt(ARGS_ACTION_REASON, dialogData.getActionReason());
+ args.putParcelable(ARGS_APP_SNIPPET, dialogData.getAppSnippet());
+ args.putBoolean(ARGS_IS_UPDATING, dialogData.isAppUpdating());
+ args.putString(ARGS_SOURCE_APP, dialogData.getSourceApp());
+
+ ExternalSourcesBlockedFragment fragment = new ExternalSourcesBlockedFragment();
+ fragment.setArguments(args);
+ return fragment;
}
@Override
@@ -56,6 +84,8 @@
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
+ setDialogData(requireArguments());
+
Log.i(LOG_TAG, "Creating " + LOG_TAG + "\n" + mDialogData);
mDialog = new AlertDialog.Builder(requireContext())
.setTitle(mDialogData.getAppLabel())
@@ -96,4 +126,14 @@
super.onResume();
mDialog.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(true);
}
+
+ private void setDialogData(Bundle args) {
+ int actionReason = args.getInt(ARGS_ACTION_REASON);
+ AppSnippet appSnippet = args.getParcelable(ARGS_APP_SNIPPET, AppSnippet.class);
+ boolean isUpdating = args.getBoolean(ARGS_IS_UPDATING);
+ String sourceApp = args.getString(ARGS_SOURCE_APP);
+
+ mDialogData = new InstallUserActionRequired(actionReason, appSnippet, isUpdating,
+ sourceApp);
+ }
}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/InstallConfirmationFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/InstallConfirmationFragment.java
index e186590..03768fb 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/InstallConfirmationFragment.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/InstallConfirmationFragment.java
@@ -16,6 +16,11 @@
package com.android.packageinstaller.v2.ui.fragments;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_ACTION_REASON;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_APP_SNIPPET;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_IS_UPDATING;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_SOURCE_APP;
+
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
@@ -26,11 +31,14 @@
import android.util.Log;
import android.view.View;
import android.widget.TextView;
+
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
+
import com.android.packageinstaller.R;
import com.android.packageinstaller.v2.model.InstallUserActionRequired;
+import com.android.packageinstaller.v2.model.PackageUtil.AppSnippet;
import com.android.packageinstaller.v2.ui.InstallActionListener;
/**
@@ -39,15 +47,34 @@
public class InstallConfirmationFragment extends DialogFragment {
public static final String LOG_TAG = InstallConfirmationFragment.class.getSimpleName();
- @NonNull
- private final InstallUserActionRequired mDialogData;
+ private InstallUserActionRequired mDialogData;
@NonNull
private InstallActionListener mInstallActionListener;
@NonNull
private AlertDialog mDialog;
- public InstallConfirmationFragment(@NonNull InstallUserActionRequired dialogData) {
- mDialogData = dialogData;
+ public InstallConfirmationFragment() {
+ // Required for DialogFragment
+ }
+
+ /**
+ * Creates a new instance of this fragment with necessary data set as fragment arguments
+ *
+ * @param dialogData {@link InstallUserActionRequired} object containing data to display
+ * in the dialog
+ * @return an instance of the fragment
+ */
+ public static InstallConfirmationFragment newInstance(
+ @NonNull InstallUserActionRequired dialogData) {
+ Bundle args = new Bundle();
+ args.putInt(ARGS_ACTION_REASON, dialogData.getActionReason());
+ args.putParcelable(ARGS_APP_SNIPPET, dialogData.getAppSnippet());
+ args.putBoolean(ARGS_IS_UPDATING, dialogData.isAppUpdating());
+ args.putString(ARGS_SOURCE_APP, dialogData.getSourceApp());
+
+ InstallConfirmationFragment fragment = new InstallConfirmationFragment();
+ fragment.setArguments(args);
+ return fragment;
}
@Override
@@ -59,6 +86,8 @@
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
+ setDialogData(requireArguments());
+
Log.i(LOG_TAG, "Creating " + LOG_TAG + "\n" + mDialogData);
View dialogView = getLayoutInflater().inflate(R.layout.install_content_view, null);
@@ -127,4 +156,14 @@
super.onResume();
mDialog.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(true);
}
+
+ private void setDialogData(Bundle args) {
+ int actionReason = args.getInt(ARGS_ACTION_REASON);
+ AppSnippet appSnippet = args.getParcelable(ARGS_APP_SNIPPET, AppSnippet.class);
+ boolean isUpdating = args.getBoolean(ARGS_IS_UPDATING);
+ String sourceApp = args.getString(ARGS_SOURCE_APP);
+
+ mDialogData = new InstallUserActionRequired(actionReason, appSnippet, isUpdating,
+ sourceApp);
+ }
}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/InstallFailedFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/InstallFailedFragment.java
index 7c9d98d..6f65441 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/InstallFailedFragment.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/InstallFailedFragment.java
@@ -16,19 +16,30 @@
package com.android.packageinstaller.v2.ui.fragments;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_APP_SNIPPET;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_LEGACY_CODE;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_MESSAGE;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_RESULT_INTENT;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_SHOULD_RETURN_RESULT;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_STATUS_CODE;
+
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
+import android.content.Intent;
import android.content.pm.PackageInstaller;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
+
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
+
import com.android.packageinstaller.R;
import com.android.packageinstaller.v2.model.InstallFailed;
+import com.android.packageinstaller.v2.model.PackageUtil.AppSnippet;
import com.android.packageinstaller.v2.ui.InstallActionListener;
/**
@@ -39,11 +50,32 @@
public class InstallFailedFragment extends DialogFragment {
private static final String LOG_TAG = InstallFailedFragment.class.getSimpleName();
- private final InstallFailed mDialogData;
+ private InstallFailed mDialogData;
private InstallActionListener mInstallActionListener;
- public InstallFailedFragment(InstallFailed dialogData) {
- mDialogData = dialogData;
+ public InstallFailedFragment() {
+ // Required for DialogFragment
+ }
+
+ /**
+ * Creates a new instance of this fragment with necessary data set as fragment arguments
+ *
+ * @param dialogData {@link InstallFailed} object containing data to display in the
+ * dialog
+ * @return an instance of the fragment
+ */
+ public static InstallFailedFragment newInstance(@NonNull InstallFailed dialogData) {
+ Bundle args = new Bundle();
+ args.putParcelable(ARGS_APP_SNIPPET, dialogData.getAppSnippet());
+ args.putInt(ARGS_LEGACY_CODE, dialogData.getLegacyCode());
+ args.putInt(ARGS_STATUS_CODE, dialogData.getStatusCode());
+ args.putString(ARGS_MESSAGE, dialogData.getMessage());
+ args.putBoolean(ARGS_SHOULD_RETURN_RESULT, dialogData.getShouldReturnResult());
+ args.putParcelable(ARGS_RESULT_INTENT, dialogData.getResultIntent());
+
+ InstallFailedFragment fragment = new InstallFailedFragment();
+ fragment.setArguments(args);
+ return fragment;
}
@Override
@@ -55,6 +87,8 @@
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
+ setDialogData(requireArguments());
+
Log.i(LOG_TAG, "Creating " + LOG_TAG + "\n" + mDialogData);
View dialogView = getLayoutInflater().inflate(R.layout.install_content_view, null);
AlertDialog dialog = new AlertDialog.Builder(requireContext())
@@ -105,4 +139,16 @@
super.onCancel(dialog);
mInstallActionListener.onNegativeResponse(mDialogData.getStageCode());
}
+
+ private void setDialogData(Bundle args) {
+ AppSnippet appSnippet = args.getParcelable(ARGS_APP_SNIPPET, AppSnippet.class);
+ int legacyCode = args.getInt(ARGS_LEGACY_CODE);
+ int statusCode = args.getInt(ARGS_STATUS_CODE);
+ String message = args.getString(ARGS_MESSAGE);
+ boolean shouldReturnResult = args.getBoolean(ARGS_SHOULD_RETURN_RESULT);
+ Intent resultIntent = args.getParcelable(ARGS_RESULT_INTENT, Intent.class);
+
+ mDialogData = new InstallFailed(appSnippet, legacyCode, statusCode, message,
+ shouldReturnResult, resultIntent);
+ }
}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/InstallInstallingFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/InstallInstallingFragment.java
index 27210b7..17093cf 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/InstallInstallingFragment.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/InstallInstallingFragment.java
@@ -16,17 +16,22 @@
package com.android.packageinstaller.v2.ui.fragments;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_APP_SNIPPET;
+
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
+
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
+
import com.android.packageinstaller.R;
import com.android.packageinstaller.v2.model.InstallInstalling;
+import com.android.packageinstaller.v2.model.PackageUtil.AppSnippet;
/**
* Dialog to show when an install is in progress.
@@ -34,16 +39,34 @@
public class InstallInstallingFragment extends DialogFragment {
private static final String LOG_TAG = InstallInstallingFragment.class.getSimpleName();
- private final InstallInstalling mDialogData;
+ private InstallInstalling mDialogData;
private AlertDialog mDialog;
- public InstallInstallingFragment(InstallInstalling dialogData) {
- mDialogData = dialogData;
+ public InstallInstallingFragment() {
+ // Required for DialogFragment
+ }
+
+ /**
+ * Creates a new instance of this fragment with necessary data set as fragment arguments
+ *
+ * @param dialogData {@link InstallInstalling} object containing data to display in the
+ * dialog
+ * @return an instance of the fragment
+ */
+ public static InstallInstallingFragment newInstance(@NonNull InstallInstalling dialogData) {
+ Bundle args = new Bundle();
+ args.putParcelable(ARGS_APP_SNIPPET, dialogData.getAppSnippet());
+
+ InstallInstallingFragment fragment = new InstallInstallingFragment();
+ fragment.setArguments(args);
+ return fragment;
}
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
+ setDialogData(requireArguments());
+
Log.i(LOG_TAG, "Creating " + LOG_TAG + "\n" + mDialogData);
View dialogView = getLayoutInflater().inflate(R.layout.install_content_view, null);
mDialog = new AlertDialog.Builder(requireContext())
@@ -64,4 +87,9 @@
super.onStart();
mDialog.getButton(DialogInterface.BUTTON_NEGATIVE).setEnabled(false);
}
+
+ private void setDialogData(Bundle args) {
+ AppSnippet appSnippet = args.getParcelable(ARGS_APP_SNIPPET, AppSnippet.class);
+ mDialogData = new InstallInstalling(appSnippet);
+ }
}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/InstallSuccessFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/InstallSuccessFragment.java
index 28b5423b..5696afa 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/InstallSuccessFragment.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/InstallSuccessFragment.java
@@ -16,22 +16,31 @@
package com.android.packageinstaller.v2.ui.fragments;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_APP_SNIPPET;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_RESULT_INTENT;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_SHOULD_RETURN_RESULT;
+
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
+import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
+
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
+
import com.android.packageinstaller.R;
import com.android.packageinstaller.v2.model.InstallSuccess;
+import com.android.packageinstaller.v2.model.PackageUtil.AppSnippet;
import com.android.packageinstaller.v2.ui.InstallActionListener;
+
import java.util.List;
/**
@@ -41,13 +50,31 @@
public class InstallSuccessFragment extends DialogFragment {
private static final String LOG_TAG = InstallSuccessFragment.class.getSimpleName();
- private final InstallSuccess mDialogData;
+ private InstallSuccess mDialogData;
private AlertDialog mDialog;
private InstallActionListener mInstallActionListener;
private PackageManager mPm;
- public InstallSuccessFragment(InstallSuccess dialogData) {
- mDialogData = dialogData;
+ public InstallSuccessFragment() {
+ // Required for DialogFragment
+ }
+
+ /**
+ * Create a new instance of this fragment with necessary data set as fragment arguments
+ *
+ * @param dialogData {@link InstallSuccess} object containing data to display in the
+ * dialog
+ * @return an instance of the fragment
+ */
+ public static InstallSuccessFragment newInstance(@NonNull InstallSuccess dialogData) {
+ Bundle args = new Bundle();
+ args.putParcelable(ARGS_APP_SNIPPET, dialogData.getAppSnippet());
+ args.putBoolean(ARGS_SHOULD_RETURN_RESULT, dialogData.getShouldReturnResult());
+ args.putParcelable(ARGS_RESULT_INTENT, dialogData.getResultIntent());
+
+ InstallSuccessFragment fragment = new InstallSuccessFragment();
+ fragment.setArguments(args);
+ return fragment;
}
@Override
@@ -60,6 +87,8 @@
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
+ setDialogData(requireArguments());
+
Log.i(LOG_TAG, "Creating " + LOG_TAG + "\n" + mDialogData);
View dialogView = getLayoutInflater().inflate(R.layout.install_content_view, null);
mDialog = new AlertDialog.Builder(requireContext())
@@ -105,4 +134,12 @@
Log.i(LOG_TAG, "Finished installing " + mDialogData.getAppLabel());
mInstallActionListener.onNegativeResponse(mDialogData.getStageCode());
}
+
+ private void setDialogData(Bundle args) {
+ AppSnippet appSnippet = args.getParcelable(ARGS_APP_SNIPPET, AppSnippet.class);
+ boolean shouldReturnResult = args.getBoolean(ARGS_SHOULD_RETURN_RESULT);
+ Intent resultIntent = args.getParcelable(ARGS_RESULT_INTENT, Intent.class);
+
+ mDialogData = new InstallSuccess(appSnippet, shouldReturnResult, resultIntent);
+ }
}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/ParseErrorFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/ParseErrorFragment.java
index cde3d8d..6834f44 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/ParseErrorFragment.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/ParseErrorFragment.java
@@ -16,14 +16,23 @@
package com.android.packageinstaller.v2.ui.fragments;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_ABORT_REASON;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_ACTIVITY_RESULT_CODE;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_ERROR_DIALOG_TYPE;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_MESSAGE;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_RESULT_INTENT;
+
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
+import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
+
import androidx.annotation.NonNull;
import androidx.fragment.app.DialogFragment;
+
import com.android.packageinstaller.R;
import com.android.packageinstaller.v2.model.InstallAborted;
import com.android.packageinstaller.v2.ui.InstallActionListener;
@@ -31,11 +40,31 @@
public class ParseErrorFragment extends DialogFragment {
private static final String LOG_TAG = ParseErrorFragment.class.getSimpleName();
- private final InstallAborted mDialogData;
+ private InstallAborted mDialogData;
private InstallActionListener mInstallActionListener;
- public ParseErrorFragment(InstallAborted dialogData) {
- mDialogData = dialogData;
+ public ParseErrorFragment() {
+ // Required for DialogFragment
+ }
+
+ /**
+ * Create a new instance of this fragment with necessary data set as fragment arguments
+ *
+ * @param dialogData {@link InstallAborted} object containing data to display in the
+ * dialog
+ * @return an instance of the fragment
+ */
+ public static ParseErrorFragment newInstance(@NonNull InstallAborted dialogData) {
+ Bundle args = new Bundle();
+ args.putInt(ARGS_ABORT_REASON, dialogData.getAbortReason());
+ args.putString(ARGS_MESSAGE, dialogData.getMessage());
+ args.putParcelable(ARGS_RESULT_INTENT, dialogData.getResultIntent());
+ args.putInt(ARGS_ACTIVITY_RESULT_CODE, dialogData.getActivityResultCode());
+ args.putInt(ARGS_ERROR_DIALOG_TYPE, dialogData.getErrorDialogType());
+
+ ParseErrorFragment fragment = new ParseErrorFragment();
+ fragment.setArguments(args);
+ return fragment;
}
@Override
@@ -47,6 +76,8 @@
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
+ setDialogData(requireArguments());
+
Log.i(LOG_TAG, "Creating " + LOG_TAG + "\n" + mDialogData);
return new AlertDialog.Builder(requireContext())
.setMessage(R.string.Parse_error_dlg_text)
@@ -63,4 +94,15 @@
mInstallActionListener.onNegativeResponse(
mDialogData.getActivityResultCode(), mDialogData.getResultIntent());
}
+
+ private void setDialogData(Bundle args) {
+ int abortReason = args.getInt(ARGS_ABORT_REASON);
+ String message = args.getString(ARGS_MESSAGE);
+ Intent resultIntent = args.getParcelable(ARGS_RESULT_INTENT, Intent.class);
+ int activityResultCode = args.getInt(ARGS_ACTIVITY_RESULT_CODE);
+ int errorDialogType = args.getInt(ARGS_ERROR_DIALOG_TYPE);
+
+ mDialogData = new InstallAborted(abortReason, message, resultIntent, activityResultCode,
+ errorDialogType);
+ }
}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/SimpleErrorFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/SimpleErrorFragment.java
index 66a353a..8b1ccd8 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/SimpleErrorFragment.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/SimpleErrorFragment.java
@@ -16,14 +16,18 @@
package com.android.packageinstaller.v2.ui.fragments;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_MESSAGE;
+
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;
+
import androidx.annotation.NonNull;
import androidx.fragment.app.DialogFragment;
+
import com.android.packageinstaller.R;
import com.android.packageinstaller.v2.model.InstallStage;
import com.android.packageinstaller.v2.ui.InstallActionListener;
@@ -31,11 +35,25 @@
public class SimpleErrorFragment extends DialogFragment {
private static final String LOG_TAG = SimpleErrorFragment.class.getSimpleName();
- private final int mMessageResId;
+ private int mMessageResId;
private InstallActionListener mInstallActionListener;
- public SimpleErrorFragment(int messageResId) {
- mMessageResId = messageResId;
+ public SimpleErrorFragment() {
+ // Required for DialogFragment
+ }
+
+ /**
+ * Create a new instance of this fragment with necessary data set as fragment arguments
+ *
+ * @return an instance of the fragment
+ */
+ public static SimpleErrorFragment newInstance(int messageResId) {
+ Bundle args = new Bundle();
+ args.putInt(ARGS_MESSAGE, messageResId);
+
+ SimpleErrorFragment fragment = new SimpleErrorFragment();
+ fragment.setArguments(args);
+ return fragment;
}
@Override
@@ -47,6 +65,8 @@
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
+ mMessageResId = requireArguments().getInt(ARGS_MESSAGE);
+
Log.i(LOG_TAG, "Creating " + LOG_TAG + "\n" +
"Dialog message: " + requireContext().getString(mMessageResId));
return new AlertDialog.Builder(requireContext())
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/UninstallConfirmationFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/UninstallConfirmationFragment.java
index 524b4e6..860f6a0 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/UninstallConfirmationFragment.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/UninstallConfirmationFragment.java
@@ -18,6 +18,11 @@
import static android.text.format.Formatter.formatFileSize;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_APP_DATA_SIZE;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_IS_ARCHIVE;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_MESSAGE;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_TITLE;
+
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
@@ -27,9 +32,11 @@
import android.view.View;
import android.widget.CheckBox;
import android.widget.TextView;
+
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
+
import com.android.packageinstaller.R;
import com.android.packageinstaller.v2.model.UninstallUserActionRequired;
import com.android.packageinstaller.v2.ui.UninstallActionListener;
@@ -38,14 +45,34 @@
* Dialog to show while requesting user confirmation for uninstalling an app.
*/
public class UninstallConfirmationFragment extends DialogFragment {
- private static final String LOG_TAG = UninstallConfirmationFragment.class.getSimpleName();
- private final UninstallUserActionRequired mDialogData;
- private UninstallActionListener mUninstallActionListener;
+ private static final String LOG_TAG = UninstallConfirmationFragment.class.getSimpleName();
+ private UninstallUserActionRequired mDialogData;
+ private UninstallActionListener mUninstallActionListener;
private CheckBox mKeepData;
- public UninstallConfirmationFragment(UninstallUserActionRequired dialogData) {
- mDialogData = dialogData;
+ public UninstallConfirmationFragment() {
+ // Required for DialogFragment
+ }
+
+ /**
+ * Create a new instance of this fragment with necessary data set as fragment arguments
+ *
+ * @param dialogData {@link UninstallUserActionRequired} object containing data to
+ * display in the dialog
+ * @return an instance of the fragment
+ */
+ public static UninstallConfirmationFragment newInstance(
+ @NonNull UninstallUserActionRequired dialogData) {
+ Bundle args = new Bundle();
+ args.putLong(ARGS_APP_DATA_SIZE, dialogData.getAppDataSize());
+ args.putBoolean(ARGS_IS_ARCHIVE, dialogData.isArchive());
+ args.putString(ARGS_TITLE, dialogData.getTitle());
+ args.putString(ARGS_MESSAGE, dialogData.getMessage());
+
+ UninstallConfirmationFragment fragment = new UninstallConfirmationFragment();
+ fragment.setArguments(args);
+ return fragment;
}
@Override
@@ -57,6 +84,8 @@
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
+ setDialogData(requireArguments());
+
Log.i(LOG_TAG, "Creating " + LOG_TAG + "\n" + mDialogData);
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext())
.setTitle(mDialogData.getTitle())
@@ -88,4 +117,13 @@
super.onCancel(dialog);
mUninstallActionListener.onNegativeResponse();
}
+
+ private void setDialogData(Bundle args) {
+ long appDataSize = args.getLong(ARGS_APP_DATA_SIZE);
+ boolean isArchive = args.getBoolean(ARGS_IS_ARCHIVE);
+ String title = args.getString(ARGS_TITLE);
+ String message = args.getString(ARGS_MESSAGE);
+
+ mDialogData = new UninstallUserActionRequired(title, message, appDataSize, isArchive);
+ }
}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/UninstallErrorFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/UninstallErrorFragment.java
index 51e16cb..9ed6412 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/UninstallErrorFragment.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/UninstallErrorFragment.java
@@ -16,15 +16,19 @@
package com.android.packageinstaller.v2.ui.fragments;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_ABORT_REASON;
+
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;
+
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
+
import com.android.packageinstaller.R;
import com.android.packageinstaller.v2.model.UninstallAborted;
import com.android.packageinstaller.v2.ui.UninstallActionListener;
@@ -35,11 +39,27 @@
public class UninstallErrorFragment extends DialogFragment {
private static final String LOG_TAG = UninstallErrorFragment.class.getSimpleName();
- private final UninstallAborted mDialogData;
+ private UninstallAborted mDialogData;
private UninstallActionListener mUninstallActionListener;
- public UninstallErrorFragment(UninstallAborted dialogData) {
- mDialogData = dialogData;
+ public UninstallErrorFragment() {
+ // Required for DialogFragment
+ }
+
+ /**
+ * Create a new instance of this fragment with necessary data set as fragment arguments
+ *
+ * @param dialogData {@link UninstallAborted} object containing data to display in the
+ * dialog
+ * @return an instance of the fragment
+ */
+ public static UninstallErrorFragment newInstance(UninstallAborted dialogData) {
+ Bundle args = new Bundle();
+ args.putInt(ARGS_ABORT_REASON, dialogData.getAbortReason());
+
+ UninstallErrorFragment fragment = new UninstallErrorFragment();
+ fragment.setArguments(args);
+ return fragment;
}
@Override
@@ -51,6 +71,8 @@
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
+ setDialogData(requireArguments());
+
Log.i(LOG_TAG, "Creating " + LOG_TAG + "\n" + mDialogData);
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext())
.setMessage(mDialogData.getDialogTextResource())
@@ -68,4 +90,9 @@
super.onCancel(dialog);
mUninstallActionListener.onNegativeResponse();
}
+
+ private void setDialogData(Bundle args) {
+ int abortReason = args.getInt(ARGS_ABORT_REASON);
+ mDialogData = new UninstallAborted(abortReason);
+ }
}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/UninstallUninstallingFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/UninstallUninstallingFragment.java
index 626ff6b..ae56c4d 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/UninstallUninstallingFragment.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/UninstallUninstallingFragment.java
@@ -16,12 +16,17 @@
package com.android.packageinstaller.v2.ui.fragments;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_APP_LABEL;
+import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_IS_CLONE_USER;
+
import android.app.AlertDialog;
import android.app.Dialog;
import android.os.Bundle;
import android.util.Log;
+
import androidx.annotation.NonNull;
import androidx.fragment.app.DialogFragment;
+
import com.android.packageinstaller.R;
import com.android.packageinstaller.v2.model.UninstallUninstalling;
@@ -33,13 +38,32 @@
private static final String LOG_TAG = UninstallUninstallingFragment.class.getSimpleName();
UninstallUninstalling mDialogData;
- public UninstallUninstallingFragment(UninstallUninstalling dialogData) {
- mDialogData = dialogData;
+ UninstallUninstallingFragment() {
+ // Required for DialogFragment
+ }
+
+ /**
+ * Create a new instance of this fragment with necessary data set as fragment arguments
+ *
+ * @param dialogData {@link UninstallUninstalling} object containing data to display in
+ * the dialog
+ * @return an instance of the fragment
+ */
+ public static UninstallUninstallingFragment newInstance(UninstallUninstalling dialogData) {
+ Bundle args = new Bundle();
+ args.putCharSequence(ARGS_APP_LABEL, dialogData.getAppLabel());
+ args.putBoolean(ARGS_IS_CLONE_USER, dialogData.isCloneUser());
+
+ UninstallUninstallingFragment fragment = new UninstallUninstallingFragment();
+ fragment.setArguments(args);
+ return fragment;
}
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
+ setDialogData(requireArguments());
+
Log.i(LOG_TAG, "Creating " + LOG_TAG + "\n" + mDialogData);
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext())
.setCancelable(false);
@@ -55,4 +79,11 @@
return dialog;
}
+
+ private void setDialogData(Bundle args) {
+ CharSequence label = args.getCharSequence(ARGS_APP_LABEL);
+ boolean isCloneUser = args.getBoolean(ARGS_IS_CLONE_USER);
+
+ mDialogData = new UninstallUninstalling(label, isCloneUser);
+ }
}