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

Commit 09175257 authored by Ivan Chiang's avatar Ivan Chiang
Browse files

[PM] Get the title of the installer outside of the lock

When the system execute the archived package installation, if we load
the label of the installer in the mLock, it causes deadlock. Get the
label outside of the mLock to avoid it.

Test: atest CtsPackageManagerTestCases
Test: atest CtsPackageUninstallTestCases:ArchiveTest
Test: atest PackageArchiverTest
Bug: 331676262
Change-Id: I0f85d9aac7bd085410d77b42ff3f9fb9065d5aa9
parent a55d0834
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ import static android.os.storage.StorageManager.FLAG_STORAGE_DE;
import static android.os.storage.StorageManager.FLAG_STORAGE_EXTERNAL;

import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
import static com.android.server.pm.PackageManagerException.INTERNAL_ERROR_ARCHIVE_NO_INSTALLER_TITLE;
import static com.android.server.pm.PackageManagerService.APP_METADATA_FILE_NAME;
import static com.android.server.pm.PackageManagerService.DEBUG_COMPRESSION;
import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
@@ -1050,6 +1051,20 @@ final class InstallPackageHelper {
                    request.setError("Scanning Failed.", e);
                    return;
                }
                if (request.isArchived()) {
                    final SparseArray<String> responsibleInstallerTitles =
                            PackageArchiver.getResponsibleInstallerTitles(mContext,
                                    mPm.snapshotComputer(), request.getInstallSource(),
                                    request.getUserId(), mPm.mUserManager.getUserIds());
                    if (responsibleInstallerTitles == null
                            || responsibleInstallerTitles.size() == 0) {
                        request.setError(PackageManagerException.ofInternalError(
                                "Failed to obtain the responsible installer info",
                                INTERNAL_ERROR_ARCHIVE_NO_INSTALLER_TITLE));
                        return;
                    }
                    request.setResponsibleInstallerTitles(responsibleInstallerTitles);
                }
            }

            List<ReconciledPackage> reconciledPackages;
@@ -2226,6 +2241,7 @@ final class InstallPackageHelper {
                // to figure out which users were changed.
                mPm.markPackageAsArchivedIfNeeded(ps,
                        installRequest.getArchivedPackage(),
                        installRequest.getResponsibleInstallerTitles(),
                        installRequest.getNewUsers());
                mPm.updateSequenceNumberLP(ps, installRequest.getNewUsers());
                mPm.updateInstantAppInstallerLocked(packageName);
+18 −0
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ExceptionUtils;
import android.util.Slog;
import android.util.SparseArray;

import com.android.internal.pm.parsing.pkg.ParsedPackage;
import com.android.internal.pm.pkg.parsing.ParsingPackageUtils;
@@ -130,6 +131,12 @@ final class InstallRequest {
    @Nullable
    private String mApexModuleName;

    /**
     * The title of the responsible installer for the archive behavior used
     */
    @Nullable
    private SparseArray<String> mResponsibleInstallerTitles;

    @Nullable
    private ScanResult mScanResult;

@@ -418,6 +425,12 @@ final class InstallRequest {
    public String getApexModuleName() {
        return mApexModuleName;
    }

    @Nullable
    public SparseArray<String> getResponsibleInstallerTitles() {
        return mResponsibleInstallerTitles;
    }

    public boolean isRollback() {
        return mInstallArgs != null
                && mInstallArgs.mInstallReason == PackageManager.INSTALL_REASON_ROLLBACK;
@@ -756,6 +769,11 @@ final class InstallRequest {
        mApexModuleName = apexModuleName;
    }

    public void setResponsibleInstallerTitles(
            @NonNull SparseArray<String> responsibleInstallerTitles) {
        mResponsibleInstallerTitles = responsibleInstallerTitles;
    }

    public void setPkg(AndroidPackage pkg) {
        mPkg = pkg;
    }
+62 −7
Original line number Diff line number Diff line
@@ -85,13 +85,13 @@ import android.os.ParcelableException;
import android.os.Process;
import android.os.RemoteException;
import android.os.SELinux;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.text.TextUtils;
import android.util.ExceptionUtils;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;

import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
@@ -476,7 +476,7 @@ public class PackageArchiver {

    @Nullable
    ArchiveState createArchiveState(@NonNull ArchivedPackageParcel archivedPackage,
            int userId, String installerPackage) {
            int userId, String installerPackage, String responsibleInstallerTitle) {
        ApplicationInfo installerInfo = mPm.snapshotComputer().getApplicationInfo(
                installerPackage, /* flags= */ 0, userId);
        if (installerInfo == null) {
@@ -484,6 +484,11 @@ public class PackageArchiver {
            Slog.e(TAG, "Couldn't find installer " + installerPackage);
            return null;
        }
        if (responsibleInstallerTitle == null) {
            Slog.e(TAG, "Couldn't get the title of the installer");
            return null;
        }

        final int iconSize = mContext.getSystemService(
                ActivityManager.class).getLauncherLargeIconSize();

@@ -508,8 +513,7 @@ public class PackageArchiver {
                archiveActivityInfos.add(activityInfo);
            }

            return new ArchiveState(archiveActivityInfos,
                    installerInfo.loadLabel(mContext.getPackageManager()).toString());
            return new ArchiveState(archiveActivityInfos, responsibleInstallerTitle);
        } catch (IOException e) {
            Slog.e(TAG, "Failed to create archive state", e);
            return null;
@@ -1106,10 +1110,61 @@ public class PackageArchiver {
        return DEFAULT_UNARCHIVE_FOREGROUND_TIMEOUT_MS;
    }

    private static String getResponsibleInstallerPackage(InstallSource installSource) {
        return TextUtils.isEmpty(installSource.mUpdateOwnerPackageName)
                ? installSource.mInstallerPackageName
                : installSource.mUpdateOwnerPackageName;
    }

    private static String getResponsibleInstallerTitle(Context context, ApplicationInfo appInfo,
            String responsibleInstallerPackage, int userId)
            throws PackageManager.NameNotFoundException {
        final Context userContext = context.createPackageContextAsUser(
                responsibleInstallerPackage, /* flags= */ 0, new UserHandle(userId));
        return appInfo.loadLabel(userContext.getPackageManager()).toString();
    }

    static String getResponsibleInstallerPackage(PackageStateInternal ps) {
        return TextUtils.isEmpty(ps.getInstallSource().mUpdateOwnerPackageName)
                ? ps.getInstallSource().mInstallerPackageName
                : ps.getInstallSource().mUpdateOwnerPackageName;
        return getResponsibleInstallerPackage(ps.getInstallSource());
    }

    @Nullable
    static SparseArray<String> getResponsibleInstallerTitles(Context context, Computer snapshot,
            InstallSource installSource, int requestUserId, int[] allUserIds) {
        final String responsibleInstallerPackage = getResponsibleInstallerPackage(installSource);
        final SparseArray<String> responsibleInstallerTitles = new SparseArray<>();
        try {
            if (requestUserId != UserHandle.USER_ALL) {
                final ApplicationInfo responsibleInstallerInfo = snapshot.getApplicationInfo(
                        responsibleInstallerPackage, /* flags= */ 0, requestUserId);
                if (responsibleInstallerInfo == null) {
                    return null;
                }

                final String title = getResponsibleInstallerTitle(context,
                        responsibleInstallerInfo, responsibleInstallerPackage, requestUserId);
                responsibleInstallerTitles.put(requestUserId, title);
            } else {
                // Go through all userIds.
                for (int i = 0; i < allUserIds.length; i++) {
                    final int userId = allUserIds[i];
                    final ApplicationInfo responsibleInstallerInfo = snapshot.getApplicationInfo(
                            responsibleInstallerPackage, /* flags= */ 0, userId);
                    // Can't get the applicationInfo on the user.
                    // Maybe the installer isn't installed on the user.
                    if (responsibleInstallerInfo == null) {
                        continue;
                    }

                    final String title = getResponsibleInstallerTitle(context,
                            responsibleInstallerInfo, responsibleInstallerPackage, userId);
                    responsibleInstallerTitles.put(userId, title);
                }
            }
        } catch (PackageManager.NameNotFoundException ex) {
            return null;
        }
        return responsibleInstallerTitles;
    }

    void notifyUnarchivalListener(int status, String installerPackageName, String appPackageName,
+3 −1
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ public class PackageManagerException extends Exception {
    public static final int INTERNAL_ERROR_APEX_NOT_DIRECTORY = -36;
    public static final int INTERNAL_ERROR_APEX_MORE_THAN_ONE_FILE = -37;
    public static final int INTERNAL_ERROR_MISSING_USER = -38;
    public static final int INTERNAL_ERROR_ARCHIVE_NO_INSTALLER_TITLE = -39;

    @IntDef(prefix = { "INTERNAL_ERROR_" }, value = {
            INTERNAL_ERROR_NATIVE_LIBRARY_COPY,
@@ -103,7 +104,8 @@ public class PackageManagerException extends Exception {
            INTERNAL_ERROR_STATIC_SHARED_LIB_OVERLAY_TARGETS,
            INTERNAL_ERROR_APEX_NOT_DIRECTORY,
            INTERNAL_ERROR_APEX_MORE_THAN_ONE_FILE,
            INTERNAL_ERROR_MISSING_USER
            INTERNAL_ERROR_MISSING_USER,
            INTERNAL_ERROR_ARCHIVE_NO_INSTALLER_TITLE
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface InternalErrorCode {}
+7 −4
Original line number Diff line number Diff line
@@ -1523,10 +1523,12 @@ public class PackageManagerService implements PackageSender, TestUtilityService
    }

    void markPackageAsArchivedIfNeeded(PackageSetting pkgSetting,
                                       ArchivedPackageParcel archivePackage, int[] userIds) {
            ArchivedPackageParcel archivePackage, SparseArray<String> responsibleInstallerTitles,
            int[] userIds) {
        if (pkgSetting == null || archivePackage == null
                || archivePackage.archivedActivities == null || userIds == null
                || userIds.length == 0) {
                || archivePackage.archivedActivities == null
                || responsibleInstallerTitles == null
                || userIds == null || userIds.length == 0) {
            return;
        }

@@ -1552,7 +1554,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService
        }
        for (int userId : userIds) {
            var archiveState = mInstallerService.mPackageArchiver.createArchiveState(
                    archivePackage, userId, responsibleInstallerPackage);
                    archivePackage, userId, responsibleInstallerPackage,
                    responsibleInstallerTitles.get(userId));
            if (archiveState != null) {
                pkgSetting
                    .modifyUserState(userId)