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

This commit is contained in:
Song Chun Fan
2022-11-07 16:33:05 +00:00
committed by Android (Google) Code Review
6 changed files with 264 additions and 15 deletions

View File

@@ -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());
}

View File

@@ -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();
}
}
}
}

View File

@@ -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 {

View File

@@ -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

View File

@@ -0,0 +1,153 @@
/*
* 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;
}
}
}

View File

@@ -67,6 +67,7 @@ final class ReconcilePackageUtils {
new ArrayMap<>();
for (InstallRequest installRequest : installRequests) {
installRequest.onReconcileStarted();
final String installPackageName = installRequest.getParsedPackage().getPackageName();
// add / replace existing with incoming packages
@@ -90,7 +91,7 @@ final class ReconcilePackageUtils {
final DeletePackageAction deletePackageAction;
// we only want to try to delete for non system apps
if (installRequest.isReplace() && !installRequest.isSystem()) {
if (installRequest.isInstallReplace() && !installRequest.isInstallSystem()) {
final boolean killApp = (installRequest.getScanFlags() & SCAN_DONT_KILL_APP) == 0;
final int deleteFlags = PackageManager.DELETE_KEEP_DATA
| (killApp ? 0 : PackageManager.DELETE_DONT_KILL_APP);
@@ -286,6 +287,10 @@ final class ReconcilePackageUtils {
}
}
for (InstallRequest installRequest : installRequests) {
installRequest.onReconcileFinished();
}
return result;
}