Merge "[pm/metrics][2/n] pass snapshot to metrics when finish"

This commit is contained in:
Song Chun Fan
2022-11-14 16:43:14 +00:00
committed by Android (Google) Code Review
5 changed files with 88 additions and 83 deletions

View File

@@ -150,7 +150,6 @@ import android.util.SparseIntArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.content.F2fsUtils;
import com.android.internal.content.InstallLocationUtils;
import com.android.internal.security.VerityUtils;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.CollectionUtils;
@@ -875,7 +874,7 @@ final class InstallPackageHelper {
}
}
Map<String, ReconciledPackage> reconciledPackages;
List<ReconciledPackage> reconciledPackages;
synchronized (mPm.mLock) {
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "reconcilePackages");
@@ -1883,11 +1882,11 @@ final class InstallPackageHelper {
}
@GuardedBy("mPm.mLock")
private void commitPackagesLocked(Map<String, ReconciledPackage> reconciledPackages,
private void commitPackagesLocked(List<ReconciledPackage> reconciledPackages,
@NonNull int[] allUsers) {
// TODO: remove any expected failures from this method; this should only be able to fail due
// to unavoidable errors (I/O, etc.)
for (ReconciledPackage reconciledPkg : reconciledPackages.values()) {
for (ReconciledPackage reconciledPkg : reconciledPackages) {
final InstallRequest installRequest = reconciledPkg.mInstallRequest;
final ParsedPackage parsedPackage = installRequest.getParsedPackage();
final String packageName = parsedPackage.getPackageName();
@@ -2205,9 +2204,9 @@ final class InstallPackageHelper {
* locks on {@link com.android.server.pm.PackageManagerService.mLock}.
*/
@GuardedBy("mPm.mInstallLock")
private void executePostCommitStepsLIF(Map<String, ReconciledPackage> reconciledPackages) {
private void executePostCommitStepsLIF(List<ReconciledPackage> reconciledPackages) {
final ArraySet<IncrementalStorage> incrementalStorages = new ArraySet<>();
for (ReconciledPackage reconciledPkg : reconciledPackages.values()) {
for (ReconciledPackage reconciledPkg : reconciledPackages) {
final InstallRequest installRequest = reconciledPkg.mInstallRequest;
final boolean instantApp = ((installRequest.getScanFlags() & SCAN_AS_INSTANT_APP) != 0);
final boolean isApex = ((installRequest.getScanFlags() & SCAN_AS_APEX) != 0);
@@ -2338,45 +2337,6 @@ final class InstallPackageHelper {
incrementalStorages);
}
public int installLocationPolicy(PackageInfoLite pkgLite, int installFlags) {
String packageName = pkgLite.packageName;
int installLocation = pkgLite.installLocation;
// reader
synchronized (mPm.mLock) {
// Currently installed package which the new package is attempting to replace or
// null if no such package is installed.
AndroidPackage installedPkg = mPm.mPackages.get(packageName);
if (installedPkg != null) {
if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
// Check for updated system application.
if (installedPkg.isSystem()) {
return InstallLocationUtils.RECOMMEND_INSTALL_INTERNAL;
} else {
// If current upgrade specifies particular preference
if (installLocation == PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY) {
// Application explicitly specified internal.
return InstallLocationUtils.RECOMMEND_INSTALL_INTERNAL;
} else if (
installLocation == PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL) {
// App explicitly prefers external. Let policy decide
} else {
// Prefer previous location
if (installedPkg.isExternalStorage()) {
return InstallLocationUtils.RECOMMEND_INSTALL_EXTERNAL;
}
return InstallLocationUtils.RECOMMEND_INSTALL_INTERNAL;
}
}
} else {
// Invalid install. Return error code
return InstallLocationUtils.RECOMMEND_FAILED_ALREADY_EXISTS;
}
}
}
return pkgLite.recommendedInstallLocation;
}
Pair<Integer, String> verifyReplacingVersionCode(PackageInfoLite pkgLite,
long requiredInstalledVersionCode, int installFlags) {
if ((installFlags & PackageManager.INSTALL_APEX) != 0) {
@@ -3645,7 +3605,7 @@ final class InstallPackageHelper {
boolean appIdCreated = false;
try {
final String pkgName = scanResult.mPkgSetting.getPackageName();
final Map<String, ReconciledPackage> reconcileResult =
final List<ReconciledPackage> reconcileResult =
ReconcilePackageUtils.reconcilePackages(
Collections.singletonList(installRequest),
mPm.mPackages, Collections.singletonMap(pkgName,
@@ -3657,7 +3617,7 @@ final class InstallPackageHelper {
} else {
installRequest.setScannedPackageSettingAppId(Process.INVALID_UID);
}
commitReconciledScanResultLocked(reconcileResult.get(pkgName),
commitReconciledScanResultLocked(reconcileResult.get(0),
mPm.mUserManager.getUserIds());
} catch (PackageManagerException e) {
if (appIdCreated) {

View File

@@ -59,8 +59,10 @@ final class InstallRequest {
@Nullable
private PackageRemovedInfo mRemovedInfo;
private @PackageManagerService.ScanFlags int mScanFlags;
private @ParsingPackageUtils.ParseFlags int mParseFlags;
@PackageManagerService.ScanFlags
private int mScanFlags;
@ParsingPackageUtils.ParseFlags
private int mParseFlags;
private boolean mReplace;
@Nullable /* The original Package if it is being replaced, otherwise {@code null} */
@@ -155,7 +157,7 @@ final class InstallRequest {
mParseFlags = parseFlags;
mScanFlags = scanFlags;
mScanResult = scanResult;
mPackageMetrics = null; // No real logging from this code path
mPackageMetrics = null; // No logging from this code path
}
@Nullable
@@ -393,11 +395,13 @@ final class InstallRequest {
return mParsedPackage;
}
public @ParsingPackageUtils.ParseFlags int getParseFlags() {
@ParsingPackageUtils.ParseFlags
public int getParseFlags() {
return mParseFlags;
}
public @PackageManagerService.ScanFlags int getScanFlags() {
@PackageManagerService.ScanFlags
public int getScanFlags() {
return mScanFlags;
}
@@ -435,6 +439,11 @@ final class InstallRequest {
return mIsInstallForUsers;
}
public boolean isInstallFromAdb() {
return mInstallArgs != null
&& (mInstallArgs.mInstallFlags & PackageManager.INSTALL_FROM_ADB) != 0;
}
@Nullable
public PackageSetting getOriginalPackageSetting() {
return mOriginalPs;
@@ -731,10 +740,10 @@ final class InstallRequest {
}
}
public void onInstallCompleted() {
public void onInstallCompleted(Computer snapshot) {
if (getReturnCode() == INSTALL_SUCCEEDED) {
if (mPackageMetrics != null) {
mPackageMetrics.onInstallSucceed();
mPackageMetrics.onInstallSucceed(snapshot);
}
}
}

View File

@@ -510,7 +510,7 @@ class InstallingSession {
mInstallPackageHelper.installPackagesTraced(installRequests);
for (InstallRequest request : installRequests) {
request.onInstallCompleted();
request.onInstallCompleted(mPm.snapshotComputer());
doPostInstall(request);
}
}

View File

@@ -16,16 +16,26 @@
package com.android.server.pm;
import static android.os.Process.INVALID_UID;
import android.annotation.IntDef;
import android.content.pm.parsing.ApkLiteParseUtils;
import android.os.UserManager;
import android.util.Pair;
import android.util.SparseArray;
import com.android.internal.util.FrameworkStatsLog;
import com.android.server.pm.pkg.PackageStateInternal;
import java.io.File;
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Stream;
/**
* Metrics class for reporting stats to logging infrastructures like Westworld
@@ -43,7 +53,8 @@ final class PackageMetrics {
STEP_COMMIT,
})
@Retention(RetentionPolicy.SOURCE)
public @interface StepInt {}
public @interface StepInt {
}
private final long mInstallStartTimestampMillis;
private final SparseArray<InstallStep> mInstallSteps = new SparseArray<>();
@@ -56,16 +67,30 @@ final class PackageMetrics {
mInstallRequest = installRequest;
}
public void onInstallSucceed() {
public void onInstallSucceed(Computer snapshot) {
// TODO(b/239722919): report to SecurityLog if on work profile or managed device
reportInstallationStats(snapshot, true /* success */);
}
private void reportInstallationStats(Computer snapshot, boolean success) {
// TODO(b/249294752): do not log if adb
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();
final String packageName = mInstallRequest.getName();
final String installerPackageName = mInstallRequest.getInstallerPackageName();
final int installerUid = installerPackageName == null ? INVALID_UID
: snapshot.getPackageUid(installerPackageName, 0, 0);
final PackageStateInternal ps = snapshot.getPackageStateInternal(packageName);
final long versionCode = success ? 0 : ps.getVersionCode();
final long apksSize = getApksSize(ps.getPath());
FrameworkStatsLog.write(FrameworkStatsLog.PACKAGE_INSTALLATION_SESSION_REPORTED,
0 /* session_id */,
null /* package_name */,
success ? null : packageName /* not report package_name on success */,
mInstallRequest.getUid() /* uid */,
newUsers /* user_ids */,
getUserTypes(newUsers) /* user_types */,
@@ -73,13 +98,13 @@ final class PackageMetrics {
getUserTypes(originalUsers) /* original_user_types */,
mInstallRequest.getReturnCode() /* public_return_code */,
0 /* internal_error_code */,
0 /* apks_size_bytes */,
0 /* version_code */,
apksSize /* apks_size_bytes */,
versionCode /* version_code */,
stepDurations.first /* install_steps */,
stepDurations.second /* step_duration_millis */,
installDurationMillis /* total_duration_millis */,
mInstallRequest.getInstallFlags() /* install_flags */,
-1 /* installer_package_uid */,
installerUid /* installer_package_uid */,
-1 /* original_installer_package_uid */,
mInstallRequest.getDataLoaderType() /* data_loader_type */,
0 /* user_action_required_type */,
@@ -93,6 +118,19 @@ final class PackageMetrics {
);
}
private long getApksSize(File apkDir) {
// TODO(b/249294752): also count apk sizes for failed installs
final AtomicLong apksSize = new AtomicLong();
try (Stream<Path> walkStream = Files.walk(apkDir.toPath())) {
walkStream.filter(p -> p.toFile().isFile()
&& ApkLiteParseUtils.isApkFile(p.toFile())).forEach(
f -> apksSize.addAndGet(f.toFile().length()));
} catch (IOException e) {
// ignore
}
return apksSize.get();
}
public void onStepStarted(@StepInt int step) {
mInstallSteps.put(step, new InstallStep());
}
@@ -140,12 +178,15 @@ final class PackageMetrics {
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

@@ -35,6 +35,7 @@ import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
import com.android.server.utils.WatchedLongSparseArray;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -48,14 +49,14 @@ import java.util.Map;
* as install) led to the request.
*/
final class ReconcilePackageUtils {
public static Map<String, ReconciledPackage> reconcilePackages(
public static List<ReconciledPackage> reconcilePackages(
List<InstallRequest> installRequests,
Map<String, AndroidPackage> allPackages,
Map<String, Settings.VersionInfo> versionInfos,
SharedLibrariesImpl sharedLibraries,
KeySetManagerService ksms, Settings settings)
throws ReconcileFailure {
final Map<String, ReconciledPackage> result = new ArrayMap<>(installRequests.size());
final List<ReconciledPackage> result = new ArrayList<>(installRequests.size());
// make a copy of the existing set of packages so we can combine them with incoming packages
final ArrayMap<String, AndroidPackage> combinedPackages =
@@ -88,7 +89,6 @@ final class ReconcilePackageUtils {
}
final DeletePackageAction deletePackageAction;
// we only want to try to delete for non system apps
if (installRequest.isInstallReplace() && !installRequest.isInstallSystem()) {
@@ -257,13 +257,11 @@ final class ReconcilePackageUtils {
}
}
result.put(installPackageName,
final ReconciledPackage reconciledPackage =
new ReconciledPackage(installRequests, allPackages, installRequest,
deletePackageAction, allowedSharedLibInfos, signingDetails,
sharedUserSignaturesChanged, removeAppKeySetData));
}
sharedUserSignaturesChanged, removeAppKeySetData);
for (InstallRequest installRequest : installRequests) {
// Check all shared libraries and map to their actual file path.
// We only do this here for apps not on a system dir, because those
// are the only ones that can fail an install due to this. We
@@ -271,24 +269,21 @@ final class ReconcilePackageUtils {
// library paths after the scan is done. Also during the initial
// scan don't update any libs as we do this wholesale after all
// apps are scanned to avoid dependency based scanning.
if ((installRequest.getScanFlags() & SCAN_BOOTING) != 0
|| (installRequest.getParseFlags() & ParsingPackageUtils.PARSE_IS_SYSTEM_DIR)
!= 0) {
continue;
if ((installRequest.getScanFlags() & SCAN_BOOTING) == 0
&& (installRequest.getParseFlags() & ParsingPackageUtils.PARSE_IS_SYSTEM_DIR)
== 0) {
try {
reconciledPackage.mCollectedSharedLibraryInfos =
sharedLibraries.collectSharedLibraryInfos(
installRequest.getParsedPackage(), combinedPackages,
incomingSharedLibraries);
} catch (PackageManagerException e) {
throw new ReconcileFailure(e.error, e.getMessage());
}
}
final String installPackageName = installRequest.getParsedPackage().getPackageName();
try {
result.get(installPackageName).mCollectedSharedLibraryInfos =
sharedLibraries.collectSharedLibraryInfos(
installRequest.getParsedPackage(), combinedPackages,
incomingSharedLibraries);
} catch (PackageManagerException e) {
throw new ReconcileFailure(e.error, e.getMessage());
}
}
for (InstallRequest installRequest : installRequests) {
installRequest.onReconcileFinished();
result.add(reconciledPackage);
}
return result;