Merge "Add support to report ART metrics to statsd." am: 2d7f8bcdf4

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1619941

Change-Id: Ibecc47dd92ca8e098476fe9acac05bdeab46ce91
This commit is contained in:
Yan Wang
2021-03-15 21:19:01 +00:00
committed by Automerger Merge Worker
4 changed files with 589 additions and 0 deletions

View File

@@ -81,9 +81,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",

View File

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

View File

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

View File

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