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

Commit d7a7d53a authored by Sumedh Sen's avatar Sumedh Sen
Browse files

Migrate Unarchive Error to Pia V2

Bug: 398032488
Test: atest CtsPackageUninstallTestCases:ArchiveTest
Flag: android.content.pm.use_pia_v2
Change-Id: I71a625e93abe92d7ebbbfcd80a6a71f95359ef51
parent 0e00cf71
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -16,6 +16,10 @@

package com.android.packageinstaller;

import static android.content.pm.Flags.usePiaV2;

import static com.android.packageinstaller.PackageUtil.getReasonForDebug;

import android.app.Activity;
import android.app.DialogFragment;
import android.app.Fragment;
@@ -24,11 +28,16 @@ import android.app.PendingIntent;
import android.content.Intent;
import android.content.pm.PackageInstaller;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;

import com.android.packageinstaller.v2.ui.UnarchiveLaunch;

import java.util.Objects;

public class UnarchiveErrorActivity extends Activity {

    static final String LOG_TAG = UnarchiveErrorActivity.class.getSimpleName();
    static final String EXTRA_REQUIRED_BYTES =
            "com.android.content.pm.extra.UNARCHIVE_EXTRA_REQUIRED_BYTES";
    static final String EXTRA_INSTALLER_PACKAGE_NAME =
@@ -40,6 +49,23 @@ public class UnarchiveErrorActivity extends Activity {
    public void onCreate(Bundle icicle) {
        super.onCreate(null);

        boolean testOverrideForPiaV2 = Settings.System.getInt(getContentResolver(),
                "use_pia_v2", 0) == 1;
        boolean usePiaV2aConfig = usePiaV2();

        if (usePiaV2aConfig || testOverrideForPiaV2) {
            Log.d(LOG_TAG, getReasonForDebug(usePiaV2aConfig, testOverrideForPiaV2));

            Intent piaV2 = new Intent(getIntent());
            piaV2.putExtra(UnarchiveLaunch.EXTRA_CALLING_PKG_NAME, getLaunchedFromPackage());
            piaV2.putExtra(UnarchiveLaunch.EXTRA_CALLING_PKG_UID, getLaunchedFromUid());
            piaV2.setClass(this, UnarchiveLaunch.class);
            piaV2.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
            startActivity(piaV2);
            finish();
            return;
        }

        Bundle extras = getIntent().getExtras();
        int unarchivalStatus = extras.getInt(PackageInstaller.EXTRA_UNARCHIVE_STATUS);
        long requiredBytes = extras.getLong(EXTRA_REQUIRED_BYTES);
+4 −0
Original line number Diff line number Diff line
@@ -58,16 +58,20 @@ object PackageUtil {
    const val ARGS_APP_SNIPPET: String = "app_snippet"
    const val ARGS_ERROR_DIALOG_TYPE: String = "error_dialog_type"
    const val ARGS_INSTALLER_LABEL: String = "installer_label"
    const val ARGS_INSTALLER_PACKAGE: String = "installer_pkg"
    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_PENDING_INTENT: String = "pending_intent"
    const val ARGS_REQUIRED_BYTES: String = "required_bytes"
    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"
    const val ARGS_UNARCHIVAL_STATUS: String = "unarchival_status"

    /**
     * Determines if the UID belongs to the system downloads provider and returns the
+63 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.packageinstaller.v2.model
import android.Manifest
import android.annotation.SuppressLint
import android.app.Activity
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.content.IntentSender
@@ -27,9 +28,11 @@ import android.content.pm.PackageManager
import android.content.pm.PackageManager.NameNotFoundException
import android.os.Process
import android.util.Log

import com.android.packageinstaller.v2.model.PackageUtil.getPackageNameForUid
import com.android.packageinstaller.v2.model.PackageUtil.isPermissionGranted
import com.android.packageinstaller.v2.model.PackageUtil.isUidRequestingPermission

import java.io.IOException

class UnarchiveRepository(private val context: Context) {
@@ -131,10 +134,70 @@ class UnarchiveRepository(private val context: Context) {
        return UnarchiveAborted(UnarchiveAborted.ABORT_REASON_UNARCHIVE_DONE, Activity.RESULT_OK)
    }

    fun showUnarchiveError(intent: Intent): UnarchiveStage {
        val unarchivalStatus = intent.getIntExtra(PackageInstaller.EXTRA_UNARCHIVE_STATUS, -1)
        val requiredBytes = intent.getLongExtra(EXTRA_REQUIRED_BYTES, 0L)
        val installerPackageName = intent.getStringExtra(EXTRA_INSTALLER_PACKAGE_NAME)
        // We cannot derive installerAppTitle from the package name because the installer might
        // not be installed anymore.
        val installerAppTitle = intent.getStringExtra(EXTRA_INSTALLER_TITLE)
        val pendingIntent = intent.getParcelableExtra<PendingIntent?>(
            Intent.EXTRA_INTENT,
            PendingIntent::class.java
        )
        when (unarchivalStatus) {
            PackageInstaller.UNARCHIVAL_ERROR_USER_ACTION_NEEDED ->
                if (pendingIntent == null) {
                    Log.e(
                        LOG_TAG,
                        "A PendingIntent is required for unarchive error code " +
                                "${PackageInstaller.UNARCHIVAL_ERROR_USER_ACTION_NEEDED}"
                    )
                    return UnarchiveAborted(UnarchiveAborted.ABORT_REASON_GENERIC_ERROR)
                }

            PackageInstaller.UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE -> {
                if (requiredBytes == 0L) {
                    Log.w(
                        LOG_TAG,
                        "Required bytes not specified for unarchive error code " +
                                "${PackageInstaller.UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE}"
                    )
                    // It's ok to still show the error dialog even though requiredBytes == 0
                }
            }

            PackageInstaller.UNARCHIVAL_ERROR_INSTALLER_DISABLED -> {
                if (installerPackageName == null) {
                    Log.e(
                        LOG_TAG,
                        "installerPackageName not specified for unarchive error code " +
                                "${PackageInstaller.UNARCHIVAL_ERROR_INSTALLER_DISABLED}"
                    )
                    return UnarchiveAborted(UnarchiveAborted.ABORT_REASON_GENERIC_ERROR)
                }
            }
        }

        return UnarchiveError(
            unarchivalStatus,
            installerPackageName,
            installerAppTitle,
            requiredBytes,
            pendingIntent
        )
    }

    companion object {
        private val LOG_TAG = UnarchiveRepository::class.java.simpleName
        private const val EXTRA_UNARCHIVE_INTENT_SENDER =
            "android.content.pm.extra.UNARCHIVE_INTENT_SENDER"
        private const val EXTRA_REQUIRED_BYTES: String =
            "com.android.content.pm.extra.UNARCHIVE_EXTRA_REQUIRED_BYTES"
        private const val EXTRA_INSTALLER_PACKAGE_NAME: String =
            "com.android.content.pm.extra.UNARCHIVE_INSTALLER_PACKAGE_NAME"
        private const val EXTRA_INSTALLER_TITLE: String =
            "com.android.content.pm.extra.UNARCHIVE_INSTALLER_TITLE"
    }

    data class CallerInfo(val packageName: String?, val uid: Int)
+10 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.packageinstaller.v2.model

import android.app.Activity
import android.app.PendingIntent

sealed class UnarchiveStage(val stageCode: Int) {

@@ -25,6 +26,7 @@ sealed class UnarchiveStage(val stageCode: Int) {
        const val STAGE_ABORTED = 0
        const val STAGE_READY = 1
        const val STAGE_USER_ACTION_REQUIRED = 2
        const val STAGE_ERROR = 3
    }
}

@@ -42,3 +44,11 @@ class UnarchiveReady() : UnarchiveStage(STAGE_READY)

data class UnarchiveUserActionRequired(val appTitle: String, val installerTitle: String) :
    UnarchiveStage(STAGE_USER_ACTION_REQUIRED)

data class UnarchiveError(
    val unarchivalStatus: Int,
    val installerPackageName: String?,
    val installerAppTitle: String?,
    val requiredBytes: Long,
    val pendingIntent: PendingIntent?
) : UnarchiveStage(STAGE_ERROR)
+7 −0
Original line number Diff line number Diff line
@@ -16,9 +16,16 @@

package com.android.packageinstaller.v2.ui

import android.app.PendingIntent

interface UnarchiveActionListener {
    /**
     * Indicates that the user has confirmed proceeding with app unarchival
     */
    fun beginUnarchive()

    /**
     * Handle positive button click even from UnarchivalError dialogs
     */
    fun handleUnarchiveErrorAction(unarchiveStatus: Int, installerPkg: String?, pi: PendingIntent?)
}
Loading