Merge "Add support to report ART metrics to statsd." am: 2d7f8bcdf4 am: 29d87fc490
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1619941 Change-Id: I58e5d0dc4694e2deacfd1865fe5796c1b3387b4c
This commit is contained in:
@@ -88,9 +88,18 @@ genrule {
|
||||
out: ["services.core.protolog.json"],
|
||||
}
|
||||
|
||||
genrule {
|
||||
name: "statslog-art-java-gen",
|
||||
tools: ["stats-log-api-gen"],
|
||||
cmd: "$(location stats-log-api-gen) --java $(out) --module art" +
|
||||
" --javaPackage com.android.internal.art --javaClass ArtStatsLog --worksource",
|
||||
out: ["com/android/internal/art/ArtStatsLog.java"],
|
||||
}
|
||||
|
||||
java_library_static {
|
||||
name: "services.core.unboosted",
|
||||
srcs: [
|
||||
":statslog-art-java-gen",
|
||||
":services.core.protologsrc",
|
||||
":dumpstate_aidl",
|
||||
":framework_native_aidl",
|
||||
|
||||
@@ -52,6 +52,7 @@ import android.os.PowerManager;
|
||||
import android.os.SystemClock;
|
||||
import android.os.SystemProperties;
|
||||
import android.os.UserHandle;
|
||||
import android.os.Trace;
|
||||
import android.os.WorkSource;
|
||||
import android.os.storage.StorageManager;
|
||||
import android.util.Log;
|
||||
@@ -62,6 +63,8 @@ import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.util.IndentingPrintWriter;
|
||||
import com.android.server.pm.Installer.InstallerException;
|
||||
import com.android.server.pm.dex.ArtManagerService;
|
||||
import com.android.server.pm.dex.ArtStatsLogUtils;
|
||||
import com.android.server.pm.dex.ArtStatsLogUtils.ArtStatsLogger;
|
||||
import com.android.server.pm.dex.DexManager;
|
||||
import com.android.server.pm.dex.DexoptOptions;
|
||||
import com.android.server.pm.dex.DexoptUtils;
|
||||
@@ -99,6 +102,8 @@ public class PackageDexOptimizer {
|
||||
private final PowerManager.WakeLock mDexoptWakeLock;
|
||||
private volatile boolean mSystemReady;
|
||||
|
||||
private final ArtStatsLogger mArtStatsLogger = new ArtStatsLogger();
|
||||
|
||||
PackageDexOptimizer(Installer installer, Object installLock, Context context,
|
||||
String wakeLockTag) {
|
||||
this.mInstaller = installer;
|
||||
@@ -252,6 +257,28 @@ public class PackageDexOptimizer {
|
||||
profileUpdated, classLoaderContexts[i], dexoptFlags, sharedGid,
|
||||
packageStats, options.isDowngrade(), profileName, dexMetadataPath,
|
||||
options.getCompilationReason());
|
||||
|
||||
// Only report metrics for base apk for now.
|
||||
// TODO: add ISA and APK type to metrics.
|
||||
if (pkg.getBaseCodePath().equals(path)) {
|
||||
Trace.traceBegin(Trace.TRACE_TAG_PACKAGE_MANAGER, "dex2oat-metrics");
|
||||
try {
|
||||
long sessionId = Math.randomLongInternal();
|
||||
ArtStatsLogUtils.writeStatsLog(
|
||||
mArtStatsLogger,
|
||||
sessionId,
|
||||
path,
|
||||
compilerFilter,
|
||||
sharedGid,
|
||||
packageStats.getCompileTime(path),
|
||||
dexMetadataPath,
|
||||
options.getCompilationReason(),
|
||||
newResult);
|
||||
} finally {
|
||||
Trace.traceEnd(Trace.TRACE_TAG_PACKAGE_MANAGER);
|
||||
}
|
||||
}
|
||||
|
||||
// The end result is:
|
||||
// - FAILED if any path failed,
|
||||
// - PERFORMED if at least one path needed compilation,
|
||||
|
||||
@@ -0,0 +1,258 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.dex;
|
||||
|
||||
import static com.android.internal.art.ArtStatsLog.ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_BULK_DOWNGRADED;
|
||||
import static com.android.internal.art.ArtStatsLog.ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_BULK_SECONDARY;
|
||||
import static com.android.internal.art.ArtStatsLog.ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_BULK_SECONDARY_DOWNGRADED;
|
||||
import static com.android.internal.art.ArtStatsLog.ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_FAKE_RUN_FROM_APK_FALLBACK;
|
||||
import static com.android.internal.art.ArtStatsLog.ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_FAKE_RUN_FROM_VDEX_FALLBACK;
|
||||
|
||||
import android.util.jar.StrictJarFile;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.art.ArtStatsLog;
|
||||
import com.android.server.pm.PackageManagerService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
/** Utils class to report ART metrics to statsd. */
|
||||
public class ArtStatsLogUtils {
|
||||
private static final String TAG = ArtStatsLogUtils.class.getSimpleName();
|
||||
private static final String PROFILE_DEX_METADATA = "primary.prof";
|
||||
private static final String VDEX_DEX_METADATA = "primary.vdex";
|
||||
|
||||
|
||||
private static final int ART_COMPILATION_REASON_INSTALL_BULK_SECONDARY =
|
||||
ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_BULK_SECONDARY;
|
||||
private static final int ART_COMPILATION_REASON_INSTALL_BULK_DOWNGRADED =
|
||||
ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_BULK_DOWNGRADED;
|
||||
private static final int ART_COMPILATION_REASON_INSTALL_BULK_SECONDARY_DOWNGRADED =
|
||||
ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_BULK_SECONDARY_DOWNGRADED;
|
||||
|
||||
private static final int ART_COMPILATION_FILTER_FAKE_RUN_FROM_APK_FALLBACK =
|
||||
ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_FAKE_RUN_FROM_APK_FALLBACK;
|
||||
private static final int ART_COMPILATION_FILTER_FAKE_RUN_FROM_VDEX_FALLBACK =
|
||||
ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_FAKE_RUN_FROM_VDEX_FALLBACK;
|
||||
|
||||
private static final Map<Integer, Integer> COMPILATION_REASON_MAP = new HashMap();
|
||||
|
||||
static {
|
||||
COMPILATION_REASON_MAP.put(PackageManagerService.REASON_UNKNOWN, ArtStatsLog.
|
||||
ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_UNKNOWN);
|
||||
COMPILATION_REASON_MAP.put(PackageManagerService.REASON_FIRST_BOOT, ArtStatsLog.
|
||||
ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_FIRST_BOOT);
|
||||
COMPILATION_REASON_MAP.put(PackageManagerService.REASON_BOOT_AFTER_OTA, ArtStatsLog.
|
||||
ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_BOOT);
|
||||
COMPILATION_REASON_MAP.put(PackageManagerService.REASON_POST_BOOT, ArtStatsLog.
|
||||
ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_POST_BOOT);
|
||||
COMPILATION_REASON_MAP.put(PackageManagerService.REASON_INSTALL, ArtStatsLog.
|
||||
ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL);
|
||||
COMPILATION_REASON_MAP.put(PackageManagerService.REASON_INSTALL_FAST, ArtStatsLog.
|
||||
ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_FAST);
|
||||
COMPILATION_REASON_MAP.put(PackageManagerService.REASON_INSTALL_BULK, ArtStatsLog.
|
||||
ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_BULK);
|
||||
COMPILATION_REASON_MAP.put(PackageManagerService.REASON_INSTALL_BULK_SECONDARY,
|
||||
ART_COMPILATION_REASON_INSTALL_BULK_SECONDARY);
|
||||
COMPILATION_REASON_MAP.put(PackageManagerService.REASON_INSTALL_BULK_DOWNGRADED,
|
||||
ART_COMPILATION_REASON_INSTALL_BULK_DOWNGRADED);
|
||||
COMPILATION_REASON_MAP.put(PackageManagerService.REASON_INSTALL_BULK_SECONDARY_DOWNGRADED,
|
||||
ART_COMPILATION_REASON_INSTALL_BULK_SECONDARY_DOWNGRADED);
|
||||
COMPILATION_REASON_MAP.put(PackageManagerService.REASON_BACKGROUND_DEXOPT, ArtStatsLog.
|
||||
ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_BG_DEXOPT);
|
||||
COMPILATION_REASON_MAP.put(PackageManagerService.REASON_AB_OTA, ArtStatsLog.
|
||||
ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_AB_OTA);
|
||||
COMPILATION_REASON_MAP.put(PackageManagerService.REASON_INACTIVE_PACKAGE_DOWNGRADE,
|
||||
ArtStatsLog.
|
||||
ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INACTIVE);
|
||||
COMPILATION_REASON_MAP.put(PackageManagerService.REASON_SHARED,
|
||||
ArtStatsLog.ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_SHARED);
|
||||
}
|
||||
|
||||
private static final Map<String, Integer> COMPILE_FILTER_MAP = new HashMap();
|
||||
|
||||
static {
|
||||
COMPILE_FILTER_MAP.put("error", ArtStatsLog.
|
||||
ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_ERROR);
|
||||
COMPILE_FILTER_MAP.put("unknown", ArtStatsLog.
|
||||
ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_UNKNOWN);
|
||||
COMPILE_FILTER_MAP.put("assume-verified", ArtStatsLog.
|
||||
ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_ASSUMED_VERIFIED);
|
||||
COMPILE_FILTER_MAP.put("extract", ArtStatsLog.
|
||||
ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_EXTRACT);
|
||||
COMPILE_FILTER_MAP.put("verify", ArtStatsLog.
|
||||
ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_VERIFY);
|
||||
COMPILE_FILTER_MAP.put("quicken", ArtStatsLog.
|
||||
ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_QUICKEN);
|
||||
COMPILE_FILTER_MAP.put("space-profile", ArtStatsLog.
|
||||
ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_SPACE_PROFILE);
|
||||
COMPILE_FILTER_MAP.put("space", ArtStatsLog.
|
||||
ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_SPACE);
|
||||
COMPILE_FILTER_MAP.put("speed-profile", ArtStatsLog.
|
||||
ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_SPEED_PROFILE);
|
||||
COMPILE_FILTER_MAP.put("speed", ArtStatsLog.
|
||||
ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_SPEED);
|
||||
COMPILE_FILTER_MAP.put("everything-profile", ArtStatsLog.
|
||||
ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_EVERYTHING_PROFILE);
|
||||
COMPILE_FILTER_MAP.put("everything", ArtStatsLog.
|
||||
ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_EVERYTHING);
|
||||
COMPILE_FILTER_MAP.put("run-from-apk", ArtStatsLog.
|
||||
ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_FAKE_RUN_FROM_APK);
|
||||
COMPILE_FILTER_MAP.put("run-from-apk-fallback",
|
||||
ART_COMPILATION_FILTER_FAKE_RUN_FROM_APK_FALLBACK);
|
||||
COMPILE_FILTER_MAP.put("run-from-vdex-fallback",
|
||||
ART_COMPILATION_FILTER_FAKE_RUN_FROM_VDEX_FALLBACK);
|
||||
}
|
||||
|
||||
public static void writeStatsLog(
|
||||
ArtStatsLogger logger,
|
||||
long sessionId,
|
||||
String path,
|
||||
String compilerFilter,
|
||||
int uid,
|
||||
long compileTime,
|
||||
String dexMetadataPath,
|
||||
int compilationReason,
|
||||
int result) {
|
||||
int dexMetadataType = getDexMetadataType(dexMetadataPath);
|
||||
logger.write(
|
||||
sessionId,
|
||||
uid,
|
||||
compilationReason,
|
||||
compilerFilter,
|
||||
ArtStatsLog.ART_DATUM_REPORTED__KIND__ART_DATUM_DEX2OAT_RESULT_CODE,
|
||||
result,
|
||||
dexMetadataType);
|
||||
logger.write(
|
||||
sessionId,
|
||||
uid,
|
||||
compilationReason,
|
||||
compilerFilter,
|
||||
ArtStatsLog.ART_DATUM_REPORTED__KIND__ART_DATUM_DEX2OAT_DEX_CODE_BYTES,
|
||||
getDexBytes(path),
|
||||
dexMetadataType);
|
||||
logger.write(
|
||||
sessionId,
|
||||
uid,
|
||||
compilationReason,
|
||||
compilerFilter,
|
||||
ArtStatsLog.ART_DATUM_REPORTED__KIND__ART_DATUM_DEX2OAT_TOTAL_TIME,
|
||||
compileTime,
|
||||
dexMetadataType);
|
||||
}
|
||||
|
||||
private static long getDexBytes(String apkPath) {
|
||||
StrictJarFile jarFile = null;
|
||||
long dexBytes = 0;
|
||||
try {
|
||||
jarFile = new StrictJarFile(apkPath,
|
||||
/*verify=*/ false,
|
||||
/*signatureSchemeRollbackProtectionsEnforced=*/ false);
|
||||
Iterator<ZipEntry> it = jarFile.iterator();
|
||||
while (it.hasNext()) {
|
||||
ZipEntry entry = it.next();
|
||||
if (entry.getName().matches("classes(\\d)*[.]dex")) {
|
||||
dexBytes += entry.getSize();
|
||||
}
|
||||
}
|
||||
return dexBytes;
|
||||
} catch (IOException ignore) {
|
||||
Slog.e(TAG, "Error when parsing APK " + apkPath);
|
||||
return -1L;
|
||||
} finally {
|
||||
try {
|
||||
if (jarFile != null) {
|
||||
jarFile.close();
|
||||
}
|
||||
} catch (IOException ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int getDexMetadataType(String dexMetadataPath) {
|
||||
if (dexMetadataPath == null) {
|
||||
return ArtStatsLog.ART_DATUM_REPORTED__DEX_METADATA_TYPE__NONE_DEX_METADATA;
|
||||
}
|
||||
StrictJarFile jarFile = null;
|
||||
try {
|
||||
jarFile = new StrictJarFile(dexMetadataPath,
|
||||
/*verify=*/ false,
|
||||
/*signatureSchemeRollbackProtectionsEnforced=*/false);
|
||||
boolean hasProfile = findFileName(jarFile, PROFILE_DEX_METADATA);
|
||||
boolean hasVdex = findFileName(jarFile, VDEX_DEX_METADATA);
|
||||
if (hasProfile && hasVdex) {
|
||||
return ArtStatsLog.ART_DATUM_REPORTED__DEX_METADATA_TYPE__PROFILE_AND_VDEX;
|
||||
} else if (hasProfile) {
|
||||
return ArtStatsLog.ART_DATUM_REPORTED__DEX_METADATA_TYPE__PROFILE;
|
||||
} else if (hasVdex) {
|
||||
return ArtStatsLog.ART_DATUM_REPORTED__DEX_METADATA_TYPE__VDEX;
|
||||
} else {
|
||||
return ArtStatsLog.ART_DATUM_REPORTED__DEX_METADATA_TYPE__UNKNOWN_DEX_METADATA;
|
||||
}
|
||||
} catch (IOException ignore) {
|
||||
Slog.e(TAG, "Error when parsing dex metadata " + dexMetadataPath);
|
||||
return ArtStatsLog.ART_DATUM_REPORTED__DEX_METADATA_TYPE__ERROR_DEX_METADATA;
|
||||
} finally {
|
||||
try {
|
||||
if (jarFile != null) {
|
||||
jarFile.close();
|
||||
}
|
||||
} catch (IOException ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean findFileName(StrictJarFile jarFile, String filename) throws IOException {
|
||||
Iterator<ZipEntry> it = jarFile.iterator();
|
||||
while (it.hasNext()) {
|
||||
ZipEntry entry = it.next();
|
||||
if (entry.getName().equals(filename)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static class ArtStatsLogger {
|
||||
public void write(
|
||||
long sessionId,
|
||||
int uid,
|
||||
int compilationReason,
|
||||
String compilerFilter,
|
||||
int kind,
|
||||
long value,
|
||||
int dexMetadataType) {
|
||||
ArtStatsLog.write(
|
||||
ArtStatsLog.ART_DATUM_REPORTED,
|
||||
sessionId,
|
||||
uid,
|
||||
COMPILE_FILTER_MAP.getOrDefault(compilerFilter, ArtStatsLog.
|
||||
ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_UNKNOWN),
|
||||
COMPILATION_REASON_MAP.getOrDefault(compilationReason, ArtStatsLog.
|
||||
ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_UNKNOWN),
|
||||
/*timestamp_millis=*/ 0L,
|
||||
ArtStatsLog.ART_DATUM_REPORTED__THREAD_TYPE__ART_THREAD_MAIN,
|
||||
kind,
|
||||
value,
|
||||
dexMetadataType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,295 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.dex;
|
||||
|
||||
import static org.mockito.Mockito.inOrder;
|
||||
|
||||
import com.android.internal.art.ArtStatsLog;
|
||||
import com.android.server.pm.dex.ArtStatsLogUtils.ArtStatsLogger;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.InOrder;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link com.android.server.pm.dex.ArtStatsLogUtils}.
|
||||
*
|
||||
* Run with "atest ArtStatsLogUtilsTest".
|
||||
*/
|
||||
@RunWith(JUnit4.class)
|
||||
public final class ArtStatsLogUtilsTest {
|
||||
private static final String TAG = ArtStatsLogUtilsTest.class.getSimpleName();
|
||||
private static final String COMPILER_FILTER = "space-profile";
|
||||
private static final String PROFILE_DEX_METADATA = "primary.prof";
|
||||
private static final String VDEX_DEX_METADATA = "primary.vdex";
|
||||
private static final byte[] DEX_CONTENT = "dexData".getBytes();
|
||||
private static final int COMPILATION_REASON = 1;
|
||||
private static final int RESULT_CODE = 222;
|
||||
private static final int UID = 111;
|
||||
private static final long COMPILE_TIME = 333L;
|
||||
private static final long SESSION_ID = 444L;
|
||||
|
||||
@Mock
|
||||
ArtStatsLogger mockLogger;
|
||||
|
||||
private static Path TEST_DIR;
|
||||
private static Path DEX;
|
||||
private static Path NON_DEX;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpAll() throws IOException {
|
||||
TEST_DIR = Files.createTempDirectory(null);
|
||||
DEX = Files.createFile(TEST_DIR.resolve("classes.dex"));
|
||||
NON_DEX = Files.createFile(TEST_DIR.resolve("test.dex"));
|
||||
Files.write(DEX, DEX_CONTENT);
|
||||
Files.write(NON_DEX, "empty".getBytes());
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearnDownAll() {
|
||||
deleteSliently(DEX);
|
||||
deleteSliently(NON_DEX);
|
||||
deleteSliently(TEST_DIR);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProfileAndVdexDexMetadata() throws IOException {
|
||||
// Setup
|
||||
Path dexMetadataPath = null;
|
||||
Path apk = null;
|
||||
try {
|
||||
dexMetadataPath = createDexMetadata(PROFILE_DEX_METADATA, VDEX_DEX_METADATA);
|
||||
apk = zipFiles(".apk", DEX, NON_DEX, dexMetadataPath);
|
||||
|
||||
// Act
|
||||
ArtStatsLogUtils.writeStatsLog(
|
||||
mockLogger,
|
||||
SESSION_ID,
|
||||
apk.toString(),
|
||||
COMPILER_FILTER,
|
||||
UID,
|
||||
COMPILE_TIME,
|
||||
dexMetadataPath.toString(),
|
||||
COMPILATION_REASON,
|
||||
RESULT_CODE);
|
||||
|
||||
// Assert
|
||||
verifyWrites(ArtStatsLog.ART_DATUM_REPORTED__DEX_METADATA_TYPE__PROFILE_AND_VDEX);
|
||||
} finally {
|
||||
deleteSliently(dexMetadataPath);
|
||||
deleteSliently(apk);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProfileOnlyDexMetadata() throws IOException {
|
||||
// Setup
|
||||
Path dexMetadataPath = null;
|
||||
Path apk = null;
|
||||
try {
|
||||
dexMetadataPath = createDexMetadata(PROFILE_DEX_METADATA);
|
||||
apk = zipFiles(".apk", DEX, NON_DEX, dexMetadataPath);
|
||||
|
||||
// Act
|
||||
ArtStatsLogUtils.writeStatsLog(
|
||||
mockLogger,
|
||||
SESSION_ID,
|
||||
apk.toString(),
|
||||
COMPILER_FILTER,
|
||||
UID,
|
||||
COMPILE_TIME,
|
||||
dexMetadataPath.toString(),
|
||||
COMPILATION_REASON,
|
||||
RESULT_CODE);
|
||||
|
||||
// Assert
|
||||
verifyWrites(ArtStatsLog.ART_DATUM_REPORTED__DEX_METADATA_TYPE__PROFILE);
|
||||
} finally {
|
||||
deleteSliently(dexMetadataPath);
|
||||
deleteSliently(apk);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVdexOnlyDexMetadata() throws IOException {
|
||||
// Setup
|
||||
Path dexMetadataPath = null;
|
||||
Path apk = null;
|
||||
try {
|
||||
dexMetadataPath = createDexMetadata(VDEX_DEX_METADATA);
|
||||
apk = zipFiles(".apk", DEX, NON_DEX, dexMetadataPath);
|
||||
|
||||
// Act
|
||||
ArtStatsLogUtils.writeStatsLog(
|
||||
mockLogger,
|
||||
SESSION_ID,
|
||||
apk.toString(),
|
||||
COMPILER_FILTER,
|
||||
UID,
|
||||
COMPILE_TIME,
|
||||
dexMetadataPath.toString(),
|
||||
COMPILATION_REASON,
|
||||
RESULT_CODE);
|
||||
|
||||
// Assert
|
||||
verifyWrites(ArtStatsLog.ART_DATUM_REPORTED__DEX_METADATA_TYPE__VDEX);
|
||||
} finally {
|
||||
deleteSliently(dexMetadataPath);
|
||||
deleteSliently(apk);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoneDexMetadata() throws IOException {
|
||||
// Setup
|
||||
Path apk = null;
|
||||
try {
|
||||
apk = zipFiles(".apk", DEX, NON_DEX);
|
||||
|
||||
// Act
|
||||
ArtStatsLogUtils.writeStatsLog(
|
||||
mockLogger,
|
||||
SESSION_ID,
|
||||
apk.toString(),
|
||||
COMPILER_FILTER,
|
||||
UID,
|
||||
COMPILE_TIME,
|
||||
/*dexMetadataPath=*/ null,
|
||||
COMPILATION_REASON,
|
||||
RESULT_CODE);
|
||||
|
||||
// Assert
|
||||
verifyWrites(ArtStatsLog.ART_DATUM_REPORTED__DEX_METADATA_TYPE__NONE_DEX_METADATA);
|
||||
} finally {
|
||||
deleteSliently(apk);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnKnownDexMetadata() throws IOException {
|
||||
// Setup
|
||||
Path dexMetadataPath = null;
|
||||
Path apk = null;
|
||||
try {
|
||||
dexMetadataPath = createDexMetadata("unknown");
|
||||
apk = zipFiles(".apk", DEX, NON_DEX, dexMetadataPath);
|
||||
|
||||
// Act
|
||||
ArtStatsLogUtils.writeStatsLog(
|
||||
mockLogger,
|
||||
SESSION_ID,
|
||||
apk.toString(),
|
||||
COMPILER_FILTER,
|
||||
UID,
|
||||
COMPILE_TIME,
|
||||
dexMetadataPath.toString(),
|
||||
COMPILATION_REASON,
|
||||
RESULT_CODE);
|
||||
|
||||
// Assert
|
||||
verifyWrites(ArtStatsLog.ART_DATUM_REPORTED__DEX_METADATA_TYPE__UNKNOWN_DEX_METADATA);
|
||||
} finally {
|
||||
deleteSliently(dexMetadataPath);
|
||||
deleteSliently(apk);
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyWrites(int dexMetadataType) {
|
||||
InOrder inorder = inOrder(mockLogger);
|
||||
inorder.verify(mockLogger).write(
|
||||
SESSION_ID, UID,
|
||||
COMPILATION_REASON,
|
||||
COMPILER_FILTER,
|
||||
ArtStatsLog.ART_DATUM_REPORTED__KIND__ART_DATUM_DEX2OAT_RESULT_CODE,
|
||||
RESULT_CODE,
|
||||
dexMetadataType);
|
||||
inorder.verify(mockLogger).write(
|
||||
SESSION_ID,
|
||||
UID,
|
||||
COMPILATION_REASON,
|
||||
COMPILER_FILTER,
|
||||
ArtStatsLog.ART_DATUM_REPORTED__KIND__ART_DATUM_DEX2OAT_DEX_CODE_BYTES,
|
||||
DEX_CONTENT.length,
|
||||
dexMetadataType);
|
||||
inorder.verify(mockLogger).write(
|
||||
SESSION_ID,
|
||||
UID,
|
||||
COMPILATION_REASON,
|
||||
COMPILER_FILTER,
|
||||
ArtStatsLog.ART_DATUM_REPORTED__KIND__ART_DATUM_DEX2OAT_TOTAL_TIME,
|
||||
COMPILE_TIME,
|
||||
dexMetadataType);
|
||||
}
|
||||
|
||||
private Path zipFiles(String suffix, Path... files) throws IOException {
|
||||
Path zipFile = Files.createTempFile(null, suffix);
|
||||
try (final OutputStream os = Files.newOutputStream(zipFile)) {
|
||||
try (final ZipOutputStream zos = new ZipOutputStream(os)) {
|
||||
for (Path file : files) {
|
||||
ZipEntry zipEntry = new ZipEntry(file.getFileName().toString());
|
||||
zos.putNextEntry(zipEntry);
|
||||
zos.write(Files.readAllBytes(file));
|
||||
zos.closeEntry();
|
||||
}
|
||||
}
|
||||
}
|
||||
return zipFile;
|
||||
}
|
||||
|
||||
private Path createDexMetadata(String... entryNames) throws IOException {
|
||||
Path zipFile = Files.createTempFile(null, ".dm");
|
||||
try (final OutputStream os = Files.newOutputStream(zipFile)) {
|
||||
try (final ZipOutputStream zos = new ZipOutputStream(os)) {
|
||||
for (String entryName : entryNames) {
|
||||
ZipEntry zipEntry = new ZipEntry(entryName);
|
||||
zos.putNextEntry(zipEntry);
|
||||
zos.write(entryName.getBytes());
|
||||
zos.closeEntry();
|
||||
}
|
||||
}
|
||||
}
|
||||
return zipFile;
|
||||
}
|
||||
|
||||
private static void deleteSliently(Path file) {
|
||||
if (file != null) {
|
||||
try {
|
||||
Files.deleteIfExists(file);
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user