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

Commit 579a409e authored by Sumedh Sen's avatar Sumedh Sen
Browse files

Implement update ownership for new UI

Bug: 274120822
Test: Follow Pia Manual Test Plan
Flag: android.content.pm.use_pia_v2
Change-Id: I0f90fee9e79028bf5cce1c9ce02fba457a444e57
parent 888cb8b8
Loading
Loading
Loading
Loading
+36 −25
Original line number Diff line number Diff line
@@ -647,10 +647,12 @@ class InstallRepository(private val context: Context) {
                return InstallAborted(ABORT_REASON_INTERNAL_ERROR)
            }
        }
        return InstallUserActionRequired(
            USER_ACTION_REASON_INSTALL_CONFIRMATION, appSnippet, isAppUpdating(newPackageInfo!!),
            getUpdateMessage(newPackageInfo!!, userActionReason)
        )
        val isAppUpdating = isAppUpdating(newPackageInfo)
        val (existingUpdateOwner, requestedUpdateOwner) =
            getUpdateOwners(newPackageInfo, userActionReason, isAppUpdating)

        return InstallUserActionRequired(USER_ACTION_REASON_INSTALL_CONFIRMATION, appSnippet,
            isAppUpdating, existingUpdateOwner, requestedUpdateOwner)
    }

    /**
@@ -662,32 +664,38 @@ class InstallRepository(private val context: Context) {
    private fun processSessionInfo(sessionInfo: SessionInfo, userActionReason: Int): InstallStage {
        newPackageInfo = generateStubPackageInfo(sessionInfo.getAppPackageName())
        appSnippet = getAppSnippet(context, sessionInfo)
        val isAppUpdating = isAppUpdating(newPackageInfo)
        val (existingUpdateOwner, requestedUpdateOwner) =
            getUpdateOwners(newPackageInfo, userActionReason, isAppUpdating)

        return InstallUserActionRequired(
            USER_ACTION_REASON_INSTALL_CONFIRMATION, appSnippet, isAppUpdating(newPackageInfo!!),
            getUpdateMessage(newPackageInfo!!, userActionReason)
        return InstallUserActionRequired(USER_ACTION_REASON_INSTALL_CONFIRMATION, appSnippet,
            isAppUpdating, existingUpdateOwner, requestedUpdateOwner)
    }

        )
    private fun getUpdateOwners(
        pkgInfo: PackageInfo?,
        userActionReason: Int,
        isAppUpdating: Boolean
    ): Pair<CharSequence?, CharSequence?> {
        if (pkgInfo == null) {
            return Pair(null, null)
        }

    private fun getUpdateMessage(pkgInfo: PackageInfo, userActionReason: Int): String? {
        if (isAppUpdating(pkgInfo)) {
        val existingUpdateOwnerLabel = getExistingUpdateOwnerLabel(pkgInfo)

        var requestedUpdateOwnerLabel: CharSequence? = if (
            isAppUpdating &&
            !TextUtils.isEmpty(existingUpdateOwnerLabel) &&
            userActionReason == PackageInstaller.REASON_REMIND_OWNERSHIP
        ) {
            val originatingPackageName =
                getPackageNameForUid(context, originatingUid, callingPackage)
            val requestedUpdateOwnerLabel = getApplicationLabel(originatingPackageName)

            if (!TextUtils.isEmpty(existingUpdateOwnerLabel)
                && userActionReason == PackageInstaller.REASON_REMIND_OWNERSHIP
            ) {
                return context.getString(
                    R.string.install_confirm_question_update_owner_reminder,
                    requestedUpdateOwnerLabel, existingUpdateOwnerLabel
                )
            }
            getApplicationLabel(originatingPackageName)
        } else {
            null
        }
        return null

        return Pair(existingUpdateOwnerLabel, requestedUpdateOwnerLabel)
    }

    private fun getExistingUpdateOwnerLabel(pkgInfo: PackageInfo): CharSequence? {
@@ -717,7 +725,10 @@ class InstallRepository(private val context: Context) {
        }
    }

    private fun isAppUpdating(newPkgInfo: PackageInfo): Boolean {
    private fun isAppUpdating(newPkgInfo: PackageInfo?): Boolean {
        if (newPkgInfo == null) {
            return false
        }
        var pkgName = newPkgInfo.packageName
        // Check if there is already a package on the device with this name
        // but it has been renamed to something else.
@@ -809,7 +820,7 @@ class InstallRepository(private val context: Context) {
                    val sourceAppSnippet = getAppSnippet(context, sourceInfo)
                    InstallUserActionRequired(
                        USER_ACTION_REASON_UNKNOWN_SOURCE, appSnippet = sourceAppSnippet,
                        sourceApp = requestInfo.originatingPackage
                        unknownSourcePackageName = requestInfo.originatingPackage
                    )
                } catch (e: PackageManager.NameNotFoundException) {
                    Log.e(LOG_TAG, "Did not find appInfo for " + requestInfo.originatingPackage)
+3 −4
Original line number Diff line number Diff line
@@ -44,10 +44,9 @@ data class InstallUserActionRequired(
    val actionReason: Int,
    val appSnippet: PackageUtil.AppSnippet? = null,
    val isAppUpdating: Boolean = false,
    /**
     * This holds either a package name or the app label of the install source.
     */
    val sourceApp: String? = null,
    val existingUpdateOwnerLabel: CharSequence? = null,
    val requestedUpdateOwnerLabel: CharSequence? = null,
    val unknownSourcePackageName: String? = null,
) : InstallStage(STAGE_USER_ACTION_REQUIRED) {

    val appIcon: Drawable?
+3 −1
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@ object PackageUtil {
    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_EXISTING_OWNER: String = "existing_owner"
    const val ARGS_INSTALLER_LABEL: String = "installer_label"
    const val ARGS_INSTALLER_PACKAGE: String = "installer_pkg"
    const val ARGS_IS_ARCHIVE: String = "is_archive"
@@ -67,11 +68,12 @@ object PackageUtil {
    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_NEW_OWNER: String = "new_owner"
    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_SOURCE_PKG: String = "source_pkg"
    const val ARGS_STATUS_CODE: String = "status_code"
    const val ARGS_TITLE: String = "title"
    const val ARGS_UNARCHIVAL_STATUS: String = "unarchival_status"
+6 −9
Original line number Diff line number Diff line
@@ -18,8 +18,7 @@ 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 static com.android.packageinstaller.v2.model.PackageUtil.ARGS_SOURCE_PKG;

import android.app.AlertDialog;
import android.app.Dialog;
@@ -71,8 +70,7 @@ public class ExternalSourcesBlockedFragment extends DialogFragment {
        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());
        args.putString(ARGS_SOURCE_PKG, dialogData.getUnknownSourcePackageName());

        ExternalSourcesBlockedFragment fragment = new ExternalSourcesBlockedFragment();
        fragment.setArguments(args);
@@ -107,7 +105,7 @@ public class ExternalSourcesBlockedFragment extends DialogFragment {
                .setView(dialogView)
                .setPositiveButton(R.string.external_sources_settings,
                        (dialog, which) -> mInstallActionListener.sendUnknownAppsIntent(
                                mDialogData.getSourceApp()))
                            mDialogData.getUnknownSourcePackageName()))
                .setNegativeButton(R.string.cancel,
                        (dialog, which) -> mInstallActionListener.onNegativeResponse(
                                mDialogData.getStageCode()))
@@ -144,10 +142,9 @@ public class ExternalSourcesBlockedFragment extends DialogFragment {
    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);
        String sourcePkg = args.getString(ARGS_SOURCE_PKG);

        mDialogData = new InstallUserActionRequired(actionReason, appSnippet, isUpdating,
                sourceApp);
        mDialogData = new InstallUserActionRequired(actionReason, appSnippet, false, null, null,
            sourcePkg);
    }
}
+28 −10
Original line number Diff line number Diff line
@@ -18,14 +18,17 @@ 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_EXISTING_OWNER;
import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_IS_UPDATING;
import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_SOURCE_APP;
import static com.android.packageinstaller.v2.model.PackageUtil.ARGS_NEW_OWNER;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.text.Html;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
@@ -69,7 +72,8 @@ public class InstallConfirmationFragment extends DialogFragment {
        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());
        args.putCharSequence(ARGS_EXISTING_OWNER, dialogData.getExistingUpdateOwnerLabel());
        args.putCharSequence(ARGS_NEW_OWNER, dialogData.getRequestedUpdateOwnerLabel());

        InstallConfirmationFragment fragment = new InstallConfirmationFragment();
        fragment.setArguments(args);
@@ -96,18 +100,31 @@ public class InstallConfirmationFragment extends DialogFragment {
        ((TextView) dialogView.requireViewById(R.id.app_label)).setText(mDialogData.getAppLabel());

        int positiveBtnTextRes;
        int titleRes;
        String title;
        if (mDialogData.isAppUpdating()) {
            // TODO: handle update ownership case
            titleRes = R.string.title_update;
            if (mDialogData.getExistingUpdateOwnerLabel() != null
                    && mDialogData.getRequestedUpdateOwnerLabel() != null) {
                title = getString(R.string.title_update_ownership_change,
                    mDialogData.getRequestedUpdateOwnerLabel());
                positiveBtnTextRes = R.string.button_update_anyway;

                TextView customMessage = dialogView.requireViewById(R.id.custom_message);
                customMessage.setVisibility(View.VISIBLE);
                String updateOwnerString = getString(R.string.message_update_owner_change,
                        mDialogData.getExistingUpdateOwnerLabel());
                customMessage.setText(Html.fromHtml(updateOwnerString, Html.FROM_HTML_MODE_LEGACY));
                customMessage.setMovementMethod(new ScrollingMovementMethod());
            } else {
                title = getString(R.string.title_update);
                positiveBtnTextRes = R.string.button_update;
            }
        } else {
            titleRes = R.string.title_install;
            title = getString(R.string.title_install);
            positiveBtnTextRes = R.string.button_install;
        }

        mDialog = new AlertDialog.Builder(requireContext())
            .setTitle(titleRes)
            .setTitle(title)
            .setView(dialogView)
            .setPositiveButton(positiveBtnTextRes,
                (dialogInt, which) -> mInstallActionListener.onPositiveResponse(
@@ -150,9 +167,10 @@ public class InstallConfirmationFragment extends DialogFragment {
        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);
        CharSequence existingOwner = args.getCharSequence(ARGS_EXISTING_OWNER);
        CharSequence newOwner = args.getCharSequence(ARGS_NEW_OWNER);

        mDialogData = new InstallUserActionRequired(actionReason, appSnippet, isUpdating,
                sourceApp);
            existingOwner, newOwner, null);
    }
}