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

Commit 95f9a35e authored by Song Chun Fan's avatar Song Chun Fan Committed by Android (Google) Code Review
Browse files

Merge "[pm/metrics][1/n] generating atoms for successful apk installs"

parents e59a2e4c ec288c2d
Loading
Loading
Loading
Loading
+13 −7
Original line number Diff line number Diff line
@@ -427,7 +427,7 @@ final class InstallPackageHelper {
            mPm.snapshotComputer().checkPackageFrozen(pkgName);
        }

        final boolean isReplace = request.isReplace();
        final boolean isReplace = request.isInstallReplace();
        // Also need to kill any apps that are dependent on the library, except the case of
        // installation of new version static shared library.
        if (clientLibPkgs != null) {
@@ -814,6 +814,7 @@ final class InstallPackageHelper {
            for (InstallRequest request : requests) {
                try {
                    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "preparePackage");
                    request.onPrepareStarted();
                    preparePackageLI(request);
                } catch (PrepareFailure prepareFailure) {
                    request.setError(prepareFailure.error,
@@ -822,6 +823,7 @@ final class InstallPackageHelper {
                    request.setOriginPermission(prepareFailure.mConflictingPermission);
                    return;
                } finally {
                    request.onPrepareFinished();
                    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                }

@@ -834,11 +836,13 @@ final class InstallPackageHelper {
                request.setReturnCode(PackageManager.INSTALL_SUCCEEDED);
                final String packageName = packageToScan.getPackageName();
                try {
                    request.onScanStarted();
                    final ScanResult scanResult = scanPackageTracedLI(request.getParsedPackage(),
                            request.getParseFlags(), request.getScanFlags(),
                            System.currentTimeMillis(), request.getUser(),
                            request.getAbiOverride());
                    request.setScanResult(scanResult);
                    request.onScanFinished();
                    if (!scannedPackages.add(packageName)) {
                        request.setError(
                                PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE,
@@ -966,7 +970,7 @@ final class InstallPackageHelper {
        final boolean isRollback =
                request.getInstallReason() == PackageManager.INSTALL_REASON_ROLLBACK;
        @PackageManagerService.ScanFlags int scanFlags = SCAN_NEW_INSTALL | SCAN_UPDATE_SIGNATURE;
        if (request.isMoveInstall()) {
        if (request.isInstallMove()) {
            // moving a complete application; perform an initial scan on the new install location
            scanFlags |= SCAN_INITIAL;
        }
@@ -1349,7 +1353,7 @@ final class InstallPackageHelper {
            }
        }

        if (request.isMoveInstall()) {
        if (request.isInstallMove()) {
            // We did an in-place move, so dex is ready to roll
            scanFlags |= SCAN_NO_DEX;
            scanFlags |= SCAN_MOVE;
@@ -1668,7 +1672,7 @@ final class InstallPackageHelper {
            ParsedPackage parsedPackage) throws PrepareFailure {
        final int status = request.getReturnCode();
        final String statusMsg = request.getReturnMsg();
        if (request.isMoveInstall()) {
        if (request.isInstallMove()) {
            if (status != PackageManager.INSTALL_SUCCEEDED) {
                mRemovePackageHelper.cleanUpForMoveInstall(request.getMoveToUuid(),
                        request.getMovePackageName(), request.getMoveFromCodePath());
@@ -1888,7 +1892,8 @@ final class InstallPackageHelper {
            final RemovePackageHelper removePackageHelper = new RemovePackageHelper(mPm);
            final DeletePackageHelper deletePackageHelper = new DeletePackageHelper(mPm);

            if (installRequest.isReplace()) {
            installRequest.onCommitStarted();
            if (installRequest.isInstallReplace()) {
                AndroidPackage oldPackage = mPm.mPackages.get(packageName);

                // Set the update and install times
@@ -1905,7 +1910,7 @@ final class InstallPackageHelper {
                        mPm.mAppsFilter.getVisibilityAllowList(mPm.snapshotComputer(),
                                installRequest.getScannedPackageSetting(),
                                allUsers, mPm.mSettings.getPackagesLocked());
                if (installRequest.isSystem()) {
                if (installRequest.isInstallSystem()) {
                    // Remove existing system package
                    removePackageHelper.removePackage(oldPackage, true);
                    if (!disableSystemPackageLPw(oldPackage)) {
@@ -1973,6 +1978,7 @@ final class InstallPackageHelper {
                mPm.updateSequenceNumberLP(ps, installRequest.getNewUsers());
                mPm.updateInstantAppInstallerLocked(packageName);
            }
            installRequest.onCommitFinished();
        }
        ApplicationPackageManager.invalidateGetPackagesForUidCache();
    }
@@ -2223,7 +2229,7 @@ final class InstallPackageHelper {
                        FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL
                                | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
            }
            if (installRequest.isReplace()) {
            if (installRequest.isInstallReplace()) {
                mDexManager.notifyPackageUpdated(pkg.getPackageName(),
                        pkg.getBaseApkPath(), pkg.getSplitCodePaths());
            }
+85 −5
Original line number Diff line number Diff line
@@ -18,8 +18,10 @@ package com.android.server.pm;

import static android.content.pm.PackageManager.INSTALL_REASON_UNKNOWN;
import static android.content.pm.PackageManager.INSTALL_SCENARIO_DEFAULT;
import static android.content.pm.PackageManager.INSTALL_SUCCEEDED;
import static android.os.Process.INVALID_UID;

import static com.android.server.pm.PackageManagerService.SCAN_AS_INSTANT_APP;
import static com.android.server.pm.PackageManagerService.TAG;

import android.annotation.NonNull;
@@ -105,6 +107,12 @@ final class InstallRequest {
    @Nullable
    private ScanResult mScanResult;

    private boolean mIsInstallInherit;
    private boolean mIsInstallForUsers;

    @Nullable
    private final PackageMetrics mPackageMetrics;

    // New install
    InstallRequest(InstallingSession params) {
        mUserId = params.getUser().getIdentifier();
@@ -116,6 +124,8 @@ final class InstallRequest {
                params.mTraceMethod, params.mTraceCookie, params.mSigningDetails,
                params.mInstallReason, params.mInstallScenario, params.mForceQueryableOverride,
                params.mDataLoaderType, params.mPackageSource);
        mPackageMetrics = new PackageMetrics(this);
        mIsInstallInherit = params.mIsInherit;
    }

    // Install existing package as user
@@ -127,6 +137,8 @@ final class InstallRequest {
        mPkg = pkg;
        mNewUsers = newUsers;
        mPostInstallRunnable = runnable;
        mPackageMetrics = new PackageMetrics(this);
        mIsInstallForUsers = true;
    }

    // addForInit
@@ -143,6 +155,7 @@ final class InstallRequest {
        mParseFlags = parseFlags;
        mScanFlags = scanFlags;
        mScanResult = scanResult;
        mPackageMetrics = null; // No real logging from this code path
    }

    @Nullable
@@ -200,7 +213,7 @@ final class InstallRequest {
        return mInstallArgs == null ? null : mInstallArgs.mObserver;
    }

    public boolean isMoveInstall() {
    public boolean isInstallMove() {
        return mInstallArgs != null && mInstallArgs.mMoveInfo != null;
    }

@@ -278,7 +291,7 @@ final class InstallRequest {
        return mRemovedInfo != null ? mRemovedInfo.mRemovedPackage : null;
    }

    public boolean isInstallForExistingUser() {
    public boolean isInstallExistingForUser() {
        return mInstallArgs == null;
    }

@@ -406,14 +419,22 @@ final class InstallRequest {
        return mClearCodeCache;
    }

    public boolean isReplace() {
    public boolean isInstallReplace() {
        return mReplace;
    }

    public boolean isSystem() {
    public boolean isInstallSystem() {
        return mSystem;
    }

    public boolean isInstallInherit() {
        return mIsInstallInherit;
    }

    public boolean isInstallForUsers() {
        return mIsInstallForUsers;
    }

    @Nullable
    public PackageSetting getOriginalPackageSetting() {
        return mOriginalPs;
@@ -520,6 +541,10 @@ final class InstallRequest {
        return mScanResult.mRequest.mIsPlatformPackage;
    }

    public boolean isInstantInstall() {
        return (mScanFlags & SCAN_AS_INSTANT_APP) != 0;
    }

    public void assertScanResultExists() {
        if (mScanResult == null) {
            // Should not happen. This indicates a bug in the installation code flow
@@ -529,7 +554,6 @@ final class InstallRequest {
                Slog.e(TAG, "ScanResult is null and it should not happen");
            }
        }

    }

    public void setScanFlags(int scanFlags) {
@@ -658,4 +682,60 @@ final class InstallRequest {
            mRemovedInfo.mRemovedAppId = appId;
        }
    }

    public void onPrepareStarted() {
        if (mPackageMetrics != null) {
            mPackageMetrics.onStepStarted(PackageMetrics.STEP_PREPARE);
        }
    }

    public void onPrepareFinished() {
        if (mPackageMetrics != null) {
            mPackageMetrics.onStepFinished(PackageMetrics.STEP_PREPARE);
        }
    }

    public void onScanStarted() {
        if (mPackageMetrics != null) {
            mPackageMetrics.onStepStarted(PackageMetrics.STEP_SCAN);
        }
    }

    public void onScanFinished() {
        if (mPackageMetrics != null) {
            mPackageMetrics.onStepFinished(PackageMetrics.STEP_SCAN);
        }
    }

    public void onReconcileStarted() {
        if (mPackageMetrics != null) {
            mPackageMetrics.onStepStarted(PackageMetrics.STEP_RECONCILE);
        }
    }

    public void onReconcileFinished() {
        if (mPackageMetrics != null) {
            mPackageMetrics.onStepFinished(PackageMetrics.STEP_RECONCILE);
        }
    }

    public void onCommitStarted() {
        if (mPackageMetrics != null) {
            mPackageMetrics.onStepStarted(PackageMetrics.STEP_COMMIT);
        }
    }

    public void onCommitFinished() {
        if (mPackageMetrics != null) {
            mPackageMetrics.onStepFinished(PackageMetrics.STEP_COMMIT);
        }
    }

    public void onInstallCompleted() {
        if (getReturnCode() == INSTALL_SUCCEEDED) {
            if (mPackageMetrics != null) {
                mPackageMetrics.onInstallSucceed();
            }
        }
    }
}
+6 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.pm;

import static android.app.AppOpsManager.MODE_DEFAULT;
import static android.content.pm.PackageInstaller.SessionParams.MODE_INHERIT_EXISTING;
import static android.content.pm.PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
import static android.content.pm.PackageManager.INSTALL_STAGED;
import static android.content.pm.PackageManager.INSTALL_SUCCEEDED;
@@ -93,6 +94,7 @@ class InstallingSession {
    final PackageManagerService mPm;
    final InstallPackageHelper mInstallPackageHelper;
    final RemovePackageHelper mRemovePackageHelper;
    final boolean mIsInherit;

    InstallingSession(OriginInfo originInfo, MoveInfo moveInfo, IPackageInstallObserver2 observer,
            int installFlags, InstallSource installSource, String volumeUuid,
@@ -121,6 +123,7 @@ class InstallingSession {
        mRequiredInstalledVersionCode = PackageManager.VERSION_CODE_HIGHEST;
        mPackageSource = packageSource;
        mPackageLite = packageLite;
        mIsInherit = false;
    }

    InstallingSession(File stagedDir, IPackageInstallObserver2 observer,
@@ -151,6 +154,7 @@ class InstallingSession {
        mRequiredInstalledVersionCode = sessionParams.requiredInstalledVersionCode;
        mPackageSource = sessionParams.packageSource;
        mPackageLite = packageLite;
        mIsInherit = sessionParams.mode == MODE_INHERIT_EXISTING;
    }

    @Override
@@ -506,6 +510,7 @@ class InstallingSession {
            mInstallPackageHelper.installPackagesTraced(installRequests);

            for (InstallRequest request : installRequests) {
                request.onInstallCompleted();
                doPostInstall(request);
            }
        }
@@ -531,7 +536,7 @@ class InstallingSession {
    }

    private void cleanUpForFailedInstall(InstallRequest request) {
        if (request.isMoveInstall()) {
        if (request.isInstallMove()) {
            mRemovePackageHelper.cleanUpForMoveInstall(request.getMoveToUuid(),
                    request.getMovePackageName(), request.getMoveFromCodePath());
        } else {
+1 −1
Original line number Diff line number Diff line
@@ -95,7 +95,7 @@ final class PackageHandler extends Handler {

                request.closeFreezer();
                request.runPostInstallRunnable();
                if (!request.isInstallForExistingUser()) {
                if (!request.isInstallExistingForUser()) {
                    mInstallPackageHelper.handlePackagePostInstall(request, didRestore);
                } else if (DEBUG_INSTALL) {
                    // No post-install when we run restore from installExistingPackageForUser
+153 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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
 *
 *      http://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.server.pm;

import android.annotation.IntDef;
import android.os.UserManager;
import android.util.Pair;
import android.util.SparseArray;

import com.android.internal.util.FrameworkStatsLog;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;

/**
 * Metrics class for reporting stats to logging infrastructures like Westworld
 */
final class PackageMetrics {
    public static final int STEP_PREPARE = 1;
    public static final int STEP_SCAN = 2;
    public static final int STEP_RECONCILE = 3;
    public static final int STEP_COMMIT = 4;

    @IntDef(prefix = {"STEP_"}, value = {
            STEP_PREPARE,
            STEP_SCAN,
            STEP_RECONCILE,
            STEP_COMMIT,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface StepInt {}

    private final long mInstallStartTimestampMillis;
    private final SparseArray<InstallStep> mInstallSteps = new SparseArray<>();
    private final InstallRequest mInstallRequest;

    PackageMetrics(InstallRequest installRequest) {
        // New instance is used for tracking installation metrics only.
        // Other metrics should use static methods of this class.
        mInstallStartTimestampMillis = System.currentTimeMillis();
        mInstallRequest = installRequest;
    }

    public void onInstallSucceed() {
        final long installDurationMillis =
                System.currentTimeMillis() - mInstallStartTimestampMillis;
        // write to stats
        final Pair<int[], long[]> stepDurations = getInstallStepDurations();
        final int[] newUsers = mInstallRequest.getNewUsers();
        final int[] originalUsers = mInstallRequest.getOriginUsers();
        FrameworkStatsLog.write(FrameworkStatsLog.PACKAGE_INSTALLATION_SESSION_REPORTED,
                0 /* session_id */,
                null /* package_name */,
                mInstallRequest.getUid() /* uid */,
                newUsers /* user_ids */,
                getUserTypes(newUsers) /* user_types */,
                originalUsers /* original_user_ids */,
                getUserTypes(originalUsers) /* original_user_types */,
                mInstallRequest.getReturnCode() /* public_return_code */,
                0 /* internal_error_code */,
                0 /* apks_size_bytes */,
                0 /* version_code */,
                stepDurations.first /* install_steps */,
                stepDurations.second /* step_duration_millis */,
                installDurationMillis /* total_duration_millis */,
                mInstallRequest.getInstallFlags() /* install_flags */,
                -1 /* installer_package_uid */,
                -1 /* original_installer_package_uid */,
                mInstallRequest.getDataLoaderType() /* data_loader_type */,
                0 /* user_action_required_type */,
                mInstallRequest.isInstantInstall() /* is_instant */,
                mInstallRequest.isInstallReplace() /* is_replace */,
                mInstallRequest.isInstallSystem() /* is_system */,
                mInstallRequest.isInstallInherit() /* is_inherit */,
                mInstallRequest.isInstallForUsers() /* is_installing_existing_as_user */,
                mInstallRequest.isInstallMove() /* is_move_install */,
                false /* is_staged */
        );
    }

    public void onStepStarted(@StepInt int step) {
        mInstallSteps.put(step, new InstallStep());
    }

    public void onStepFinished(@StepInt int step) {
        final InstallStep installStep = mInstallSteps.get(step);
        if (installStep != null) {
            // Only valid if the start timestamp is set; otherwise no-op
            installStep.finish();
        }
    }

    // List of steps (e.g., 1, 2, 3) and corresponding list of durations (e.g., 200ms, 100ms, 150ms)
    private Pair<int[], long[]> getInstallStepDurations() {
        ArrayList<Integer> steps = new ArrayList<>();
        ArrayList<Long> durations = new ArrayList<>();
        for (int i = 0; i < mInstallSteps.size(); i++) {
            final long duration = mInstallSteps.valueAt(i).getDurationMillis();
            if (duration >= 0) {
                steps.add(mInstallSteps.keyAt(i));
                durations.add(mInstallSteps.valueAt(i).getDurationMillis());
            }
        }
        int[] stepsArray = new int[steps.size()];
        long[] durationsArray = new long[durations.size()];
        for (int i = 0; i < stepsArray.length; i++) {
            stepsArray[i] = steps.get(i);
            durationsArray[i] = durations.get(i);
        }
        return new Pair<>(stepsArray, durationsArray);
    }

    private static int[] getUserTypes(int[] userIds) {
        if (userIds == null) {
            return null;
        }
        final int[] userTypes = new int[userIds.length];
        for (int i = 0; i < userTypes.length; i++) {
            String userType = UserManagerService.getInstance().getUserInfo(userIds[i]).userType;
            userTypes[i] = UserManager.getUserTypeForStatsd(userType);
        }
        return userTypes;
    }

    private static class InstallStep {
        private final long mStartTimestampMillis;
        private long mDurationMillis = -1;
        InstallStep() {
            mStartTimestampMillis = System.currentTimeMillis();
        }
        void finish() {
            mDurationMillis = System.currentTimeMillis() - mStartTimestampMillis;
        }
        long getDurationMillis() {
            return mDurationMillis;
        }
    }
}
Loading