1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.pm.dex; 18 19 import static com.android.internal.art.ArtStatsLog.ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_BULK_DOWNGRADED; 20 import static com.android.internal.art.ArtStatsLog.ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_BULK_SECONDARY; 21 import static com.android.internal.art.ArtStatsLog.ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_BULK_SECONDARY_DOWNGRADED; 22 import static com.android.internal.art.ArtStatsLog.ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_FAKE_RUN_FROM_APK_FALLBACK; 23 import static com.android.internal.art.ArtStatsLog.ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_FAKE_RUN_FROM_VDEX_FALLBACK; 24 25 import android.os.SystemClock; 26 import android.util.Slog; 27 import android.util.jar.StrictJarFile; 28 29 import com.android.internal.art.ArtStatsLog; 30 import com.android.server.pm.PackageManagerService; 31 32 import java.io.IOException; 33 import java.util.Arrays; 34 import java.util.HashMap; 35 import java.util.Iterator; 36 import java.util.Map; 37 import java.util.regex.Matcher; 38 import java.util.regex.Pattern; 39 import java.util.zip.ZipEntry; 40 41 /** Utils class to report ART metrics to statsd. */ 42 public class ArtStatsLogUtils { 43 private static final String TAG = ArtStatsLogUtils.class.getSimpleName(); 44 private static final String PROFILE_DEX_METADATA = "primary.prof"; 45 private static final String VDEX_DEX_METADATA = "primary.vdex"; 46 47 private static final int ART_COMPILATION_REASON_INSTALL_BULK_SECONDARY = 48 ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_BULK_SECONDARY; 49 private static final int ART_COMPILATION_REASON_INSTALL_BULK_DOWNGRADED = 50 ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_BULK_DOWNGRADED; 51 private static final int ART_COMPILATION_REASON_INSTALL_BULK_SECONDARY_DOWNGRADED = 52 ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_BULK_SECONDARY_DOWNGRADED; 53 54 private static final int ART_COMPILATION_FILTER_FAKE_RUN_FROM_APK_FALLBACK = 55 ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_FAKE_RUN_FROM_APK_FALLBACK; 56 private static final int ART_COMPILATION_FILTER_FAKE_RUN_FROM_VDEX_FALLBACK = 57 ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_FAKE_RUN_FROM_VDEX_FALLBACK; 58 59 private static final Map<Integer, Integer> COMPILATION_REASON_MAP = new HashMap(); 60 61 static { COMPILATION_REASON_MAP.put(PackageManagerService.REASON_FIRST_BOOT, ArtStatsLog. ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_FIRST_BOOT)62 COMPILATION_REASON_MAP.put(PackageManagerService.REASON_FIRST_BOOT, ArtStatsLog. 63 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_AFTER_OTA)64 COMPILATION_REASON_MAP.put(PackageManagerService.REASON_BOOT_AFTER_OTA, ArtStatsLog. 65 ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_BOOT_AFTER_OTA); COMPILATION_REASON_MAP.put(PackageManagerService.REASON_POST_BOOT, ArtStatsLog. ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_POST_BOOT)66 COMPILATION_REASON_MAP.put(PackageManagerService.REASON_POST_BOOT, ArtStatsLog. 67 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)68 COMPILATION_REASON_MAP.put(PackageManagerService.REASON_INSTALL, ArtStatsLog. 69 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)70 COMPILATION_REASON_MAP.put(PackageManagerService.REASON_INSTALL_FAST, ArtStatsLog. 71 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)72 COMPILATION_REASON_MAP.put(PackageManagerService.REASON_INSTALL_BULK, ArtStatsLog. 73 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)74 COMPILATION_REASON_MAP.put(PackageManagerService.REASON_INSTALL_BULK_SECONDARY, 75 ART_COMPILATION_REASON_INSTALL_BULK_SECONDARY); COMPILATION_REASON_MAP.put(PackageManagerService.REASON_INSTALL_BULK_DOWNGRADED, ART_COMPILATION_REASON_INSTALL_BULK_DOWNGRADED)76 COMPILATION_REASON_MAP.put(PackageManagerService.REASON_INSTALL_BULK_DOWNGRADED, 77 ART_COMPILATION_REASON_INSTALL_BULK_DOWNGRADED); COMPILATION_REASON_MAP.put(PackageManagerService.REASON_INSTALL_BULK_SECONDARY_DOWNGRADED, ART_COMPILATION_REASON_INSTALL_BULK_SECONDARY_DOWNGRADED)78 COMPILATION_REASON_MAP.put(PackageManagerService.REASON_INSTALL_BULK_SECONDARY_DOWNGRADED, 79 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)80 COMPILATION_REASON_MAP.put(PackageManagerService.REASON_BACKGROUND_DEXOPT, ArtStatsLog. 81 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)82 COMPILATION_REASON_MAP.put(PackageManagerService.REASON_AB_OTA, ArtStatsLog. 83 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)84 COMPILATION_REASON_MAP.put(PackageManagerService.REASON_INACTIVE_PACKAGE_DOWNGRADE, 85 ArtStatsLog. 86 ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INACTIVE); COMPILATION_REASON_MAP.put(PackageManagerService.REASON_CMDLINE, ArtStatsLog.ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_CMDLINE)87 COMPILATION_REASON_MAP.put(PackageManagerService.REASON_CMDLINE, 88 ArtStatsLog.ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_CMDLINE); COMPILATION_REASON_MAP.put(PackageManagerService.REASON_SHARED, ArtStatsLog.ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_SHARED)89 COMPILATION_REASON_MAP.put(PackageManagerService.REASON_SHARED, 90 ArtStatsLog.ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_SHARED); 91 } 92 93 private static final Map<String, Integer> COMPILE_FILTER_MAP = new HashMap(); 94 95 static { 96 COMPILE_FILTER_MAP.put("error", ArtStatsLog. 97 ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_ERROR); 98 COMPILE_FILTER_MAP.put("unknown", ArtStatsLog. 99 ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_UNKNOWN); 100 COMPILE_FILTER_MAP.put("assume-verified", ArtStatsLog. 101 ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_ASSUMED_VERIFIED); 102 COMPILE_FILTER_MAP.put("extract", ArtStatsLog. 103 ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_EXTRACT); 104 COMPILE_FILTER_MAP.put("verify", ArtStatsLog. 105 ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_VERIFY); 106 COMPILE_FILTER_MAP.put("quicken", ArtStatsLog. 107 ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_QUICKEN); 108 COMPILE_FILTER_MAP.put("space-profile", ArtStatsLog. 109 ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_SPACE_PROFILE); 110 COMPILE_FILTER_MAP.put("space", ArtStatsLog. 111 ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_SPACE); 112 COMPILE_FILTER_MAP.put("speed-profile", ArtStatsLog. 113 ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_SPEED_PROFILE); 114 COMPILE_FILTER_MAP.put("speed", ArtStatsLog. 115 ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_SPEED); 116 COMPILE_FILTER_MAP.put("everything-profile", ArtStatsLog. 117 ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_EVERYTHING_PROFILE); 118 COMPILE_FILTER_MAP.put("everything", ArtStatsLog. 119 ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_EVERYTHING); 120 COMPILE_FILTER_MAP.put("run-from-apk", ArtStatsLog. 121 ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_FAKE_RUN_FROM_APK); 122 COMPILE_FILTER_MAP.put("run-from-apk-fallback", 123 ART_COMPILATION_FILTER_FAKE_RUN_FROM_APK_FALLBACK); 124 COMPILE_FILTER_MAP.put("run-from-vdex-fallback", 125 ART_COMPILATION_FILTER_FAKE_RUN_FROM_VDEX_FALLBACK); 126 } 127 128 private static final Map<String, Integer> ISA_MAP = new HashMap(); 129 130 static { 131 ISA_MAP.put("arm", ArtStatsLog.ART_DATUM_REPORTED__ISA__ART_ISA_ARM); 132 ISA_MAP.put("arm64", ArtStatsLog.ART_DATUM_REPORTED__ISA__ART_ISA_ARM64); 133 ISA_MAP.put("x86", ArtStatsLog.ART_DATUM_REPORTED__ISA__ART_ISA_X86); 134 ISA_MAP.put("x86_64", ArtStatsLog.ART_DATUM_REPORTED__ISA__ART_ISA_X86_64); 135 ISA_MAP.put("mips", ArtStatsLog.ART_DATUM_REPORTED__ISA__ART_ISA_MIPS); 136 ISA_MAP.put("mips64", ArtStatsLog.ART_DATUM_REPORTED__ISA__ART_ISA_MIPS64); 137 } 138 writeStatsLog( ArtStatsLogger logger, long sessionId, String compilerFilter, int uid, long compileTime, String dexMetadataPath, int compilationReason, int result, int apkType, String isa, String apkPath)139 public static void writeStatsLog( 140 ArtStatsLogger logger, 141 long sessionId, 142 String compilerFilter, 143 int uid, 144 long compileTime, 145 String dexMetadataPath, 146 int compilationReason, 147 int result, 148 int apkType, 149 String isa, 150 String apkPath) { 151 int dexMetadataType = getDexMetadataType(dexMetadataPath); 152 logger.write( 153 sessionId, 154 uid, 155 compilationReason, 156 compilerFilter, 157 ArtStatsLog.ART_DATUM_REPORTED__KIND__ART_DATUM_DEX2OAT_RESULT_CODE, 158 result, 159 dexMetadataType, 160 apkType, 161 isa); 162 logger.write( 163 sessionId, 164 uid, 165 compilationReason, 166 compilerFilter, 167 ArtStatsLog.ART_DATUM_REPORTED__KIND__ART_DATUM_DEX2OAT_DEX_CODE_COUNTER_BYTES, 168 getDexBytes(apkPath), 169 dexMetadataType, 170 apkType, 171 isa); 172 logger.write( 173 sessionId, 174 uid, 175 compilationReason, 176 compilerFilter, 177 ArtStatsLog.ART_DATUM_REPORTED__KIND__ART_DATUM_DEX2OAT_TOTAL_TIME_COUNTER_MILLIS, 178 compileTime, 179 dexMetadataType, 180 apkType, 181 isa); 182 } 183 getApkType(String path, String baseApkPath, String[] splitApkPaths)184 public static int getApkType(String path, String baseApkPath, String[] splitApkPaths) { 185 if (path.equals(baseApkPath)) { 186 return ArtStatsLog.ART_DATUM_REPORTED__APK_TYPE__ART_APK_TYPE_BASE; 187 } else if(Arrays.stream(splitApkPaths).anyMatch(p->p.equals(path))) { 188 return ArtStatsLog.ART_DATUM_REPORTED__APK_TYPE__ART_APK_TYPE_SPLIT; 189 } else{ 190 return ArtStatsLog.ART_DATUM_REPORTED__APK_TYPE__ART_APK_TYPE_UNKNOWN; 191 } 192 } 193 getDexBytes(String apkPath)194 private static long getDexBytes(String apkPath) { 195 StrictJarFile jarFile = null; 196 long dexBytes = 0; 197 try { 198 jarFile = new StrictJarFile(apkPath, 199 /*verify=*/ false, 200 /*signatureSchemeRollbackProtectionsEnforced=*/ false); 201 Iterator<ZipEntry> it = jarFile.iterator(); 202 Pattern p = Pattern.compile("classes(\\d)*[.]dex"); 203 Matcher m = p.matcher(""); 204 while (it.hasNext()) { 205 ZipEntry entry = it.next(); 206 m.reset(entry.getName()); 207 if (m.matches()) { 208 dexBytes += entry.getSize(); 209 } 210 } 211 return dexBytes; 212 } catch (IOException ignore) { 213 Slog.e(TAG, "Error when parsing APK " + apkPath); 214 return -1L; 215 } finally { 216 try { 217 if (jarFile != null) { 218 jarFile.close(); 219 } 220 } catch (IOException ignore) { 221 } 222 } 223 } 224 getDexMetadataType(String dexMetadataPath)225 private static int getDexMetadataType(String dexMetadataPath) { 226 if (dexMetadataPath == null) { 227 return ArtStatsLog.ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_NONE; 228 } 229 StrictJarFile jarFile = null; 230 try { 231 jarFile = new StrictJarFile(dexMetadataPath, 232 /*verify=*/ false, 233 /*signatureSchemeRollbackProtectionsEnforced=*/false); 234 boolean hasProfile = findFileName(jarFile, PROFILE_DEX_METADATA); 235 boolean hasVdex = findFileName(jarFile, VDEX_DEX_METADATA); 236 if (hasProfile && hasVdex) { 237 return ArtStatsLog. 238 ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_PROFILE_AND_VDEX; 239 } else if (hasProfile) { 240 return ArtStatsLog. 241 ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_PROFILE; 242 } else if (hasVdex) { 243 return ArtStatsLog. 244 ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_VDEX; 245 } else { 246 return ArtStatsLog. 247 ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_UNKNOWN; 248 } 249 } catch (IOException ignore) { 250 Slog.e(TAG, "Error when parsing dex metadata " + dexMetadataPath); 251 return ArtStatsLog.ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_ERROR; 252 } finally { 253 try { 254 if (jarFile != null) { 255 jarFile.close(); 256 } 257 } catch (IOException ignore) { 258 } 259 } 260 } 261 findFileName(StrictJarFile jarFile, String filename)262 private static boolean findFileName(StrictJarFile jarFile, String filename) throws IOException { 263 Iterator<ZipEntry> it = jarFile.iterator(); 264 while (it.hasNext()) { 265 ZipEntry entry = it.next(); 266 if (entry.getName().equals(filename)) { 267 return true; 268 } 269 } 270 return false; 271 } 272 273 public static class ArtStatsLogger { write( long sessionId, int uid, int compilationReason, String compilerFilter, int kind, long value, int dexMetadataType, int apkType, String isa)274 public void write( 275 long sessionId, 276 int uid, 277 int compilationReason, 278 String compilerFilter, 279 int kind, 280 long value, 281 int dexMetadataType, 282 int apkType, 283 String isa) { 284 ArtStatsLog.write( 285 ArtStatsLog.ART_DATUM_REPORTED, 286 sessionId, 287 uid, 288 COMPILE_FILTER_MAP.getOrDefault(compilerFilter, ArtStatsLog. 289 ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_UNKNOWN), 290 COMPILATION_REASON_MAP.getOrDefault(compilationReason, ArtStatsLog. 291 ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_UNKNOWN), 292 /*timestamp_millis=*/ SystemClock.uptimeMillis(), 293 ArtStatsLog.ART_DATUM_REPORTED__THREAD_TYPE__ART_THREAD_MAIN, 294 kind, 295 value, 296 dexMetadataType, 297 apkType, 298 ISA_MAP.getOrDefault(isa, 299 ArtStatsLog.ART_DATUM_REPORTED__ISA__ART_ISA_UNKNOWN), 300 ArtStatsLog.ART_DATUM_REPORTED__GC__ART_GC_COLLECTOR_TYPE_UNKNOWN, 301 ArtStatsLog.ART_DATUM_REPORTED__UFFD_SUPPORT__ART_UFFD_SUPPORT_UNKNOWN); 302 } 303 } 304 } 305