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

Commit fb778cf7 authored by William Loh's avatar William Loh
Browse files

Remove File.exists() checks for app metadata files

File.exists() is expensive especially when the file does not exist.
Instead of doing this check we will cache whether or not the file was
sucessfully written to the session.

Bug: 338174039
Test: atest InstallAppMetadataTest
Change-Id: I43a30bd1dc46a2169c591ab65458b8e79b0caec5
parent 61e25300
Loading
Loading
Loading
Loading
+6 −7
Original line number Diff line number Diff line
@@ -511,14 +511,13 @@ final class InstallPackageHelper {
        // metadata file on the system image. Do not reset the path and source if this is the
        // case.
        if (pkgSetting.getAppMetadataFilePath() == null) {
            File dir = new File(pkg.getPath());
            String dir = pkg.getPath();
            if (pkgSetting.isSystem()) {
                dir = new File(Environment.getDataDirectory(),
                        "app-metadata/" + pkg.getPackageName());
                dir = Environment.getDataDirectoryPath() + "/app-metadata/" + pkg.getPackageName();
            }
            File appMetadataFile = new File(dir, APP_METADATA_FILE_NAME);
            if (appMetadataFile.exists()) {
                pkgSetting.setAppMetadataFilePath(appMetadataFile.getAbsolutePath());
            String appMetadataFilePath = dir + "/" + APP_METADATA_FILE_NAME;
            if (request.hasAppMetadataFile()) {
                pkgSetting.setAppMetadataFilePath(appMetadataFilePath);
                if (Flags.aslInApkAppMetadataSource()) {
                    pkgSetting.setAppMetadataSource(APP_METADATA_SOURCE_INSTALLER);
                }
@@ -526,7 +525,7 @@ final class InstallPackageHelper {
                Map<String, PackageManager.Property> properties = pkg.getProperties();
                if (properties.containsKey(PROPERTY_ANDROID_SAFETY_LABEL)) {
                    // ASL file extraction is done in post-install
                    pkgSetting.setAppMetadataFilePath(appMetadataFile.getAbsolutePath());
                    pkgSetting.setAppMetadataFilePath(appMetadataFilePath);
                    pkgSetting.setAppMetadataSource(APP_METADATA_SOURCE_APK);
                }
            }
+9 −0
Original line number Diff line number Diff line
@@ -167,6 +167,8 @@ final class InstallRequest {

    private int mInstallerUidForInstallExisting = INVALID_UID;

    private final boolean mHasAppMetadataFileFromInstaller;

    // New install
    InstallRequest(InstallingSession params) {
        mUserId = params.getUser().getIdentifier();
@@ -185,6 +187,7 @@ final class InstallRequest {
        mSessionId = params.mSessionId;
        mRequireUserAction = params.mRequireUserAction;
        mPreVerifiedDomains = params.mPreVerifiedDomains;
        mHasAppMetadataFileFromInstaller = params.mHasAppMetadataFile;
    }

    // Install existing package as user
@@ -203,6 +206,7 @@ final class InstallRequest {
        mAppId = appId;
        mInstallerUidForInstallExisting = installerUid;
        mSystem = isSystem;
        mHasAppMetadataFileFromInstaller = false;
    }

    // addForInit
@@ -224,6 +228,7 @@ final class InstallRequest {
        mSessionId = -1;
        mRequireUserAction = USER_ACTION_UNSPECIFIED;
        mDisabledPs = disabledPs;
        mHasAppMetadataFileFromInstaller = false;
    }

    @Nullable
@@ -371,6 +376,10 @@ final class InstallRequest {
        return PackageInstallerSession.isArchivedInstallation(getInstallFlags());
    }

    public boolean hasAppMetadataFile() {
        return mHasAppMetadataFileFromInstaller;
    }

    @Nullable
    public String getRemovedPackage() {
        return mRemovedInfo != null ? mRemovedInfo.mRemovedPackage : null;
+5 −1
Original line number Diff line number Diff line
@@ -101,6 +101,7 @@ class InstallingSession {
    final boolean mApplicationEnabledSettingPersistent;
    @Nullable
    final DomainSet mPreVerifiedDomains;
    final boolean mHasAppMetadataFile;

    // For move install
    InstallingSession(OriginInfo originInfo, MoveInfo moveInfo, IPackageInstallObserver2 observer,
@@ -134,12 +135,14 @@ class InstallingSession {
        mRequireUserAction = USER_ACTION_UNSPECIFIED;
        mApplicationEnabledSettingPersistent = false;
        mPreVerifiedDomains = null;
        mHasAppMetadataFile = false;
    }

    InstallingSession(int sessionId, File stagedDir, IPackageInstallObserver2 observer,
            PackageInstaller.SessionParams sessionParams, InstallSource installSource,
            UserHandle user, SigningDetails signingDetails, int installerUid,
            PackageLite packageLite, DomainSet preVerifiedDomains, PackageManagerService pm) {
            PackageLite packageLite, DomainSet preVerifiedDomains, PackageManagerService pm,
            boolean hasAppMetadatafile) {
        mPm = pm;
        mUser = user;
        mOriginInfo = OriginInfo.fromStagedFile(stagedDir);
@@ -168,6 +171,7 @@ class InstallingSession {
        mRequireUserAction = sessionParams.requireUserAction;
        mApplicationEnabledSettingPersistent = sessionParams.applicationEnabledSettingPersistent;
        mPreVerifiedDomains = preVerifiedDomains;
        mHasAppMetadataFile = hasAppMetadatafile;
    }

    @Override
+37 −19
Original line number Diff line number Diff line
@@ -601,6 +601,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
    @GuardedBy("mLock")
    private String mSessionErrorMessage;

    @GuardedBy("mLock")
    private boolean mHasAppMetadataFile = false;

    @Nullable
    final StagedSession mStagedSession;

@@ -1814,7 +1817,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
        assertCallerIsOwnerOrRoot();
        synchronized (mLock) {
            assertPreparedAndNotCommittedOrDestroyedLocked("getAppMetadataFd");
            if (!getStagedAppMetadataFile().exists()) {
            if (!mHasAppMetadataFile) {
                return null;
            }
            try {
@@ -1827,9 +1830,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {

    @Override
    public void removeAppMetadata() {
        File file = getStagedAppMetadataFile();
        if (file.exists()) {
            file.delete();
        synchronized (mLock) {
            if (mHasAppMetadataFile) {
                getStagedAppMetadataFile().delete();
                mHasAppMetadataFile = false;
            }
        }
    }

@@ -1850,8 +1855,12 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
            assertPreparedAndNotSealedLocked("openWriteAppMetadata");
        }
        try {
            return doWriteInternal(APP_METADATA_FILE_NAME, /* offsetBytes= */ 0,
            ParcelFileDescriptor fd = doWriteInternal(APP_METADATA_FILE_NAME, /* offsetBytes= */ 0,
                    /* lengthBytes= */ -1, null);
            synchronized (mLock) {
                mHasAppMetadataFile = true;
            }
            return fd;
        } catch (IOException e) {
            throw ExceptionUtils.wrap(e);
        }
@@ -2145,11 +2154,13 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
            }
        }

        synchronized (mLock) {
            if (mHasAppMetadataFile) {
                File appMetadataFile = getStagedAppMetadataFile();
        if (appMetadataFile.exists()) {
                long sizeLimit = getAppMetadataSizeLimit();
                if (appMetadataFile.length() > sizeLimit) {
                    appMetadataFile.delete();
                    mHasAppMetadataFile = false;
                    throw new IllegalArgumentException(
                            "App metadata size exceeds the maximum allowed limit of " + sizeLimit);
                }
@@ -2159,6 +2170,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
                    appMetadataFile.renameTo(getTmpAppMetadataFile());
                }
            }
        }

        dispatchSessionSealed();
    }
@@ -3207,7 +3219,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {

        synchronized (mLock) {
            return new InstallingSession(sessionId, stageDir, localObserver, params, mInstallSource,
                    user, mSigningDetails, mInstallerUid, mPackageLite, mPreVerifiedDomains, mPm);
                    user, mSigningDetails, mInstallerUid, mPackageLite, mPreVerifiedDomains, mPm,
                    mHasAppMetadataFile);
        }
    }

@@ -3445,9 +3458,14 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
            }
        }

        if (mHasAppMetadataFile && !getStagedAppMetadataFile().exists()) {
            throw new PackageManagerException(INSTALL_FAILED_VERIFICATION_FAILURE,
                    "App metadata file expected but not found in " + stageDir.getAbsolutePath());
        }

        final List<ApkLite> addedFiles = getAddedApkLitesLocked();
        if (addedFiles.isEmpty()
                && (removeSplitList.size() == 0 || getStagedAppMetadataFile().exists())) {
                && (removeSplitList.size() == 0 || mHasAppMetadataFile)) {
            throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
                    TextUtils.formatSimple("Session: %d. No packages staged in %s", sessionId,
                          stageDir.getAbsolutePath()));