Show user prompt for uninstall

Get user confirmation to proceed with the uninstall.

Bug: 182205982
Test: builds successfully
Test: No CTS Tests. Flag to use new app is turned off by default

Change-Id: Ic6669fbd4ed8dadf3bcc2791d8cfbe7bf9a544ef
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/UninstallActionListener.java b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/UninstallActionListener.java
index 3d535ae..b8a9355 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/UninstallActionListener.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/UninstallActionListener.java
@@ -18,7 +18,7 @@
 
 public interface UninstallActionListener {
 
-    void onPositiveResponse();
+    void onPositiveResponse(boolean keepData);
 
     void onNegativeResponse();
 }
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/UninstallLaunch.java b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/UninstallLaunch.java
index 1f5bbf1..e22a59e 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/UninstallLaunch.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/UninstallLaunch.java
@@ -32,6 +32,8 @@
 import com.android.packageinstaller.v2.model.UninstallRepository.CallerInfo;
 import com.android.packageinstaller.v2.model.uninstallstagedata.UninstallAborted;
 import com.android.packageinstaller.v2.model.uninstallstagedata.UninstallStage;
+import com.android.packageinstaller.v2.model.uninstallstagedata.UninstallUserActionRequired;
+import com.android.packageinstaller.v2.ui.fragments.UninstallConfirmationFragment;
 import com.android.packageinstaller.v2.ui.fragments.UninstallErrorFragment;
 import com.android.packageinstaller.v2.viewmodel.UninstallViewModel;
 import com.android.packageinstaller.v2.viewmodel.UninstallViewModelFactory;
@@ -88,6 +90,11 @@
             } else {
                 setResult(aborted.getActivityResultCode(), null, true);
             }
+        } else if (uninstallStage.getStageCode() == UninstallStage.STAGE_USER_ACTION_REQUIRED) {
+            UninstallUserActionRequired uar = (UninstallUserActionRequired) uninstallStage;
+            UninstallConfirmationFragment confirmationDialog = new UninstallConfirmationFragment(
+                uar);
+            showDialogInner(confirmationDialog);
         } else {
             Log.e(TAG, "Invalid stage: " + uninstallStage.getStageCode());
             showDialogInner(null);
@@ -118,7 +125,7 @@
     }
 
     @Override
-    public void onPositiveResponse() {
+    public void onPositiveResponse(boolean keepData) {
     }
 
     @Override
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
new file mode 100644
index 0000000..1b0885e
--- /dev/null
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/fragments/UninstallConfirmationFragment.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.packageinstaller.v2.ui.fragments;
+
+import static android.text.format.Formatter.formatFileSize;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Bundle;
+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.uninstallstagedata.UninstallUserActionRequired;
+import com.android.packageinstaller.v2.ui.UninstallActionListener;
+
+/**
+ * Dialog to show while requesting user confirmation for uninstalling an app.
+ */
+public class UninstallConfirmationFragment extends DialogFragment {
+
+    private final UninstallUserActionRequired mDialogData;
+    private UninstallActionListener mUninstallActionListener;
+
+    private CheckBox mKeepData;
+
+    public UninstallConfirmationFragment(UninstallUserActionRequired dialogData) {
+        mDialogData = dialogData;
+    }
+
+    @Override
+    public void onAttach(@NonNull Context context) {
+        super.onAttach(context);
+        mUninstallActionListener = (UninstallActionListener) context;
+    }
+
+    @NonNull
+    @Override
+    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
+        AlertDialog.Builder builder = new AlertDialog.Builder(requireContext())
+            .setTitle(mDialogData.getTitle())
+            .setPositiveButton(R.string.ok,
+                (dialogInt, which) -> mUninstallActionListener.onPositiveResponse(
+                    mKeepData != null && mKeepData.isChecked()))
+            .setNegativeButton(R.string.cancel,
+                (dialogInt, which) -> mUninstallActionListener.onNegativeResponse());
+
+        long appDataSize = mDialogData.getAppDataSize();
+        if (appDataSize == 0) {
+            builder.setMessage(mDialogData.getMessage());
+        } else {
+            View dialogView = getLayoutInflater().inflate(R.layout.uninstall_content_view, null);
+
+            ((TextView) dialogView.requireViewById(R.id.message)).setText(mDialogData.getMessage());
+            mKeepData = dialogView.requireViewById(R.id.keepData);
+            mKeepData.setVisibility(View.VISIBLE);
+            mKeepData.setText(getString(R.string.uninstall_keep_data,
+                formatFileSize(getContext(), appDataSize)));
+
+            builder.setView(dialogView);
+        }
+        return builder.create();
+    }
+
+    @Override
+    public void onCancel(@NonNull DialogInterface dialog) {
+        super.onCancel(dialog);
+        mUninstallActionListener.onNegativeResponse();
+    }
+}