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.app.job.JobParameters; 26 import android.os.SystemClock; 27 import android.util.Slog; 28 import android.util.jar.StrictJarFile; 29 30 import com.android.internal.art.ArtStatsLog; 31 import com.android.server.pm.BackgroundDexOptService; 32 import com.android.server.pm.PackageManagerService; 33 34 import java.io.IOException; 35 import java.util.Arrays; 36 import java.util.HashMap; 37 import java.util.Iterator; 38 import java.util.Map; 39 import java.util.regex.Matcher; 40 import java.util.regex.Pattern; 41 import java.util.zip.ZipEntry; 42 43 /** Utils class to report ART metrics to statsd. */ 44 public class ArtStatsLogUtils { 45 private static final String TAG = ArtStatsLogUtils.class.getSimpleName(); 46 private static final String PROFILE_DEX_METADATA = "primary.prof"; 47 private static final String VDEX_DEX_METADATA = "primary.vdex"; 48 49 private static final int ART_COMPILATION_REASON_INSTALL_BULK_SECONDARY = 50 ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_BULK_SECONDARY; 51 private static final int ART_COMPILATION_REASON_INSTALL_BULK_DOWNGRADED = 52 ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_BULK_DOWNGRADED; 53 private static final int ART_COMPILATION_REASON_INSTALL_BULK_SECONDARY_DOWNGRADED = 54 ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_BULK_SECONDARY_DOWNGRADED; 55 56 private static final int ART_COMPILATION_FILTER_FAKE_RUN_FROM_APK_FALLBACK = 57 ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_FAKE_RUN_FROM_APK_FALLBACK; 58 private static final int ART_COMPILATION_FILTER_FAKE_RUN_FROM_VDEX_FALLBACK = 59 ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_FAKE_RUN_FROM_VDEX_FALLBACK; 60 61 private static final Map<Integer, Integer> COMPILATION_REASON_MAP = new HashMap(); 62 63 static { COMPILATION_REASON_MAP.put(PackageManagerService.REASON_FIRST_BOOT, ArtStatsLog. ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_FIRST_BOOT)64 COMPILATION_REASON_MAP.put(PackageManagerService.REASON_FIRST_BOOT, ArtStatsLog. 65 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)66 COMPILATION_REASON_MAP.put(PackageManagerService.REASON_BOOT_AFTER_OTA, ArtStatsLog. 67 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)68 COMPILATION_REASON_MAP.put(PackageManagerService.REASON_POST_BOOT, ArtStatsLog. 69 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)70 COMPILATION_REASON_MAP.put(PackageManagerService.REASON_INSTALL, ArtStatsLog. 71 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)72 COMPILATION_REASON_MAP.put(PackageManagerService.REASON_INSTALL_FAST, ArtStatsLog. 73 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)74 COMPILATION_REASON_MAP.put(PackageManagerService.REASON_INSTALL_BULK, ArtStatsLog. 75 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)76 COMPILATION_REASON_MAP.put(PackageManagerService.REASON_INSTALL_BULK_SECONDARY, 77 ART_COMPILATION_REASON_INSTALL_BULK_SECONDARY); COMPILATION_REASON_MAP.put(PackageManagerService.REASON_INSTALL_BULK_DOWNGRADED, ART_COMPILATION_REASON_INSTALL_BULK_DOWNGRADED)78 COMPILATION_REASON_MAP.put(PackageManagerService.REASON_INSTALL_BULK_DOWNGRADED, 79 ART_COMPILATION_REASON_INSTALL_BULK_DOWNGRADED); COMPILATION_REASON_MAP.put(PackageManagerService.REASON_INSTALL_BULK_SECONDARY_DOWNGRADED, ART_COMPILATION_REASON_INSTALL_BULK_SECONDARY_DOWNGRADED)80 COMPILATION_REASON_MAP.put(PackageManagerService.REASON_INSTALL_BULK_SECONDARY_DOWNGRADED, 81 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)82 COMPILATION_REASON_MAP.put(PackageManagerService.REASON_BACKGROUND_DEXOPT, ArtStatsLog. 83 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)84 COMPILATION_REASON_MAP.put(PackageManagerService.REASON_AB_OTA, ArtStatsLog. 85 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)86 COMPILATION_REASON_MAP.put(PackageManagerService.REASON_INACTIVE_PACKAGE_DOWNGRADE, 87 ArtStatsLog. 88 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)89 COMPILATION_REASON_MAP.put(PackageManagerService.REASON_CMDLINE, 90 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)91 COMPILATION_REASON_MAP.put(PackageManagerService.REASON_SHARED, 92 ArtStatsLog.ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_SHARED); 93 } 94 95 private static final Map<String, Integer> COMPILE_FILTER_MAP = new HashMap(); 96 97 static { 98 COMPILE_FILTER_MAP.put("error", ArtStatsLog. 99 ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_ERROR); 100 COMPILE_FILTER_MAP.put("unknown", ArtStatsLog. 101 ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_UNKNOWN); 102 COMPILE_FILTER_MAP.put("assume-verified", ArtStatsLog. 103 ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_ASSUMED_VERIFIED); 104 COMPILE_FILTER_MAP.put("extract", ArtStatsLog. 105 ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_EXTRACT); 106 COMPILE_FILTER_MAP.put("verify", ArtStatsLog. 107 ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_VERIFY); 108 COMPILE_FILTER_MAP.put("quicken", ArtStatsLog. 109 ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_QUICKEN); 110 COMPILE_FILTER_MAP.put("space-profile", ArtStatsLog. 111 ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_SPACE_PROFILE); 112 COMPILE_FILTER_MAP.put("space", ArtStatsLog. 113 ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_SPACE); 114 COMPILE_FILTER_MAP.put("speed-profile", ArtStatsLog. 115 ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_SPEED_PROFILE); 116 COMPILE_FILTER_MAP.put("speed", ArtStatsLog. 117 ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_SPEED); 118 COMPILE_FILTER_MAP.put("everything-profile", ArtStatsLog. 119 ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_EVERYTHING_PROFILE); 120 COMPILE_FILTER_MAP.put("everything", ArtStatsLog. 121 ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_EVERYTHING); 122 COMPILE_FILTER_MAP.put("run-from-apk", ArtStatsLog. 123 ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_FAKE_RUN_FROM_APK); 124 COMPILE_FILTER_MAP.put("run-from-apk-fallback", 125 ART_COMPILATION_FILTER_FAKE_RUN_FROM_APK_FALLBACK); 126 COMPILE_FILTER_MAP.put("run-from-vdex-fallback", 127 ART_COMPILATION_FILTER_FAKE_RUN_FROM_VDEX_FALLBACK); 128 } 129 130 private static final Map<String, Integer> ISA_MAP = new HashMap(); 131 132 static { 133 ISA_MAP.put("arm", ArtStatsLog.ART_DATUM_REPORTED__ISA__ART_ISA_ARM); 134 ISA_MAP.put("arm64", ArtStatsLog.ART_DATUM_REPORTED__ISA__ART_ISA_ARM64); 135 ISA_MAP.put("x86", ArtStatsLog.ART_DATUM_REPORTED__ISA__ART_ISA_X86); 136 ISA_MAP.put("x86_64", ArtStatsLog.ART_DATUM_REPORTED__ISA__ART_ISA_X86_64); 137 ISA_MAP.put("mips", ArtStatsLog.ART_DATUM_REPORTED__ISA__ART_ISA_MIPS); 138 ISA_MAP.put("mips64", ArtStatsLog.ART_DATUM_REPORTED__ISA__ART_ISA_MIPS64); 139 } 140 writeStatsLog( ArtStatsLogger logger, long sessionId, String compilerFilter, int uid, long compileTime, String dexMetadataPath, int compilationReason, int result, int apkType, String isa, String apkPath)141 public static void writeStatsLog( 142 ArtStatsLogger logger, 143 long sessionId, 144 String compilerFilter, 145 int uid, 146 long compileTime, 147 String dexMetadataPath, 148 int compilationReason, 149 int result, 150 int apkType, 151 String isa, 152 String apkPath) { 153 int dexMetadataType = getDexMetadataType(dexMetadataPath); 154 logger.write( 155 sessionId, 156 uid, 157 compilationReason, 158 compilerFilter, 159 ArtStatsLog.ART_DATUM_REPORTED__KIND__ART_DATUM_DEX2OAT_RESULT_CODE, 160 result, 161 dexMetadataType, 162 apkType, 163 isa); 164 logger.write( 165 sessionId, 166 uid, 167 compilationReason, 168 compilerFilter, 169 ArtStatsLog.ART_DATUM_REPORTED__KIND__ART_DATUM_DEX2OAT_DEX_CODE_COUNTER_BYTES, 170 getDexBytes(apkPath), 171 dexMetadataType, 172 apkType, 173 isa); 174 logger.write( 175 sessionId, 176 uid, 177 compilationReason, 178 compilerFilter, 179 ArtStatsLog.ART_DATUM_REPORTED__KIND__ART_DATUM_DEX2OAT_TOTAL_TIME_COUNTER_MILLIS, 180 compileTime, 181 dexMetadataType, 182 apkType, 183 isa); 184 } 185 getApkType(String path, String baseApkPath, String[] splitApkPaths)186 public static int getApkType(String path, String baseApkPath, String[] splitApkPaths) { 187 if (path.equals(baseApkPath)) { 188 return ArtStatsLog.ART_DATUM_REPORTED__APK_TYPE__ART_APK_TYPE_BASE; 189 } else if(Arrays.stream(splitApkPaths).anyMatch(p->p.equals(path))) { 190 return ArtStatsLog.ART_DATUM_REPORTED__APK_TYPE__ART_APK_TYPE_SPLIT; 191 } else{ 192 return ArtStatsLog.ART_DATUM_REPORTED__APK_TYPE__ART_APK_TYPE_UNKNOWN; 193 } 194 } 195 getDexBytes(String apkPath)196 private static long getDexBytes(String apkPath) { 197 StrictJarFile jarFile = null; 198 long dexBytes = 0; 199 try { 200 jarFile = new StrictJarFile(apkPath, 201 /*verify=*/ false, 202 /*signatureSchemeRollbackProtectionsEnforced=*/ false); 203 Iterator<ZipEntry> it = jarFile.iterator(); 204 Pattern p = Pattern.compile("classes(\\d)*[.]dex"); 205 Matcher m = p.matcher(""); 206 while (it.hasNext()) { 207 ZipEntry entry = it.next(); 208 m.reset(entry.getName()); 209 if (m.matches()) { 210 dexBytes += entry.getSize(); 211 } 212 } 213 return dexBytes; 214 } catch (IOException ignore) { 215 Slog.e(TAG, "Error when parsing APK " + apkPath); 216 return -1L; 217 } finally { 218 try { 219 if (jarFile != null) { 220 jarFile.close(); 221 } 222 } catch (IOException ignore) { 223 } 224 } 225 } 226 getDexMetadataType(String dexMetadataPath)227 private static int getDexMetadataType(String dexMetadataPath) { 228 if (dexMetadataPath == null) { 229 return ArtStatsLog.ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_NONE; 230 } 231 StrictJarFile jarFile = null; 232 try { 233 jarFile = new StrictJarFile(dexMetadataPath, 234 /*verify=*/ false, 235 /*signatureSchemeRollbackProtectionsEnforced=*/false); 236 boolean hasProfile = findFileName(jarFile, PROFILE_DEX_METADATA); 237 boolean hasVdex = findFileName(jarFile, VDEX_DEX_METADATA); 238 if (hasProfile && hasVdex) { 239 return ArtStatsLog. 240 ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_PROFILE_AND_VDEX; 241 } else if (hasProfile) { 242 return ArtStatsLog. 243 ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_PROFILE; 244 } else if (hasVdex) { 245 return ArtStatsLog. 246 ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_VDEX; 247 } else { 248 return ArtStatsLog. 249 ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_UNKNOWN; 250 } 251 } catch (IOException ignore) { 252 Slog.e(TAG, "Error when parsing dex metadata " + dexMetadataPath); 253 return ArtStatsLog.ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_ERROR; 254 } finally { 255 try { 256 if (jarFile != null) { 257 jarFile.close(); 258 } 259 } catch (IOException ignore) { 260 } 261 } 262 } 263 findFileName(StrictJarFile jarFile, String filename)264 private static boolean findFileName(StrictJarFile jarFile, String filename) throws IOException { 265 Iterator<ZipEntry> it = jarFile.iterator(); 266 while (it.hasNext()) { 267 ZipEntry entry = it.next(); 268 if (entry.getName().equals(filename)) { 269 return true; 270 } 271 } 272 return false; 273 } 274 275 public static class ArtStatsLogger { write( long sessionId, int uid, int compilationReason, String compilerFilter, int kind, long value, int dexMetadataType, int apkType, String isa)276 public void write( 277 long sessionId, 278 int uid, 279 int compilationReason, 280 String compilerFilter, 281 int kind, 282 long value, 283 int dexMetadataType, 284 int apkType, 285 String isa) { 286 ArtStatsLog.write( 287 ArtStatsLog.ART_DATUM_REPORTED, 288 sessionId, 289 uid, 290 COMPILE_FILTER_MAP.getOrDefault(compilerFilter, ArtStatsLog. 291 ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_UNKNOWN), 292 COMPILATION_REASON_MAP.getOrDefault(compilationReason, ArtStatsLog. 293 ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_UNKNOWN), 294 /*timestamp_millis=*/ SystemClock.uptimeMillis(), 295 ArtStatsLog.ART_DATUM_REPORTED__THREAD_TYPE__ART_THREAD_MAIN, 296 kind, 297 value, 298 dexMetadataType, 299 apkType, 300 ISA_MAP.getOrDefault(isa, 301 ArtStatsLog.ART_DATUM_REPORTED__ISA__ART_ISA_UNKNOWN), 302 ArtStatsLog.ART_DATUM_REPORTED__GC__ART_GC_COLLECTOR_TYPE_UNKNOWN, 303 ArtStatsLog.ART_DATUM_REPORTED__UFFD_SUPPORT__ART_UFFD_SUPPORT_UNKNOWN); 304 } 305 } 306 307 private static final Map<Integer, Integer> STATUS_MAP = 308 Map.of(BackgroundDexOptService.STATUS_UNSPECIFIED, 309 ArtStatsLog.BACKGROUND_DEXOPT_JOB_ENDED__STATUS__STATUS_UNKNOWN, 310 BackgroundDexOptService.STATUS_OK, 311 ArtStatsLog.BACKGROUND_DEXOPT_JOB_ENDED__STATUS__STATUS_JOB_FINISHED, 312 BackgroundDexOptService.STATUS_ABORT_BY_CANCELLATION, 313 ArtStatsLog.BACKGROUND_DEXOPT_JOB_ENDED__STATUS__STATUS_ABORT_BY_CANCELLATION, 314 BackgroundDexOptService.STATUS_ABORT_NO_SPACE_LEFT, 315 ArtStatsLog.BACKGROUND_DEXOPT_JOB_ENDED__STATUS__STATUS_ABORT_NO_SPACE_LEFT, 316 BackgroundDexOptService.STATUS_ABORT_THERMAL, 317 ArtStatsLog.BACKGROUND_DEXOPT_JOB_ENDED__STATUS__STATUS_ABORT_THERMAL, 318 BackgroundDexOptService.STATUS_ABORT_BATTERY, 319 ArtStatsLog.BACKGROUND_DEXOPT_JOB_ENDED__STATUS__STATUS_ABORT_BATTERY, 320 BackgroundDexOptService.STATUS_DEX_OPT_FAILED, 321 ArtStatsLog.BACKGROUND_DEXOPT_JOB_ENDED__STATUS__STATUS_JOB_FINISHED, 322 BackgroundDexOptService.STATUS_FATAL_ERROR, 323 ArtStatsLog.BACKGROUND_DEXOPT_JOB_ENDED__STATUS__STATUS_FATAL_ERROR); 324 325 /** Helper class to write background dexopt job stats to statsd. */ 326 public static class BackgroundDexoptJobStatsLogger { 327 /** Writes background dexopt job stats to statsd. */ write(@ackgroundDexOptService.Status int status, @JobParameters.StopReason int cancellationReason, long durationMs)328 public void write(@BackgroundDexOptService.Status int status, 329 @JobParameters.StopReason int cancellationReason, 330 long durationMs) { 331 ArtStatsLog.write( 332 ArtStatsLog.BACKGROUND_DEXOPT_JOB_ENDED, 333 STATUS_MAP.getOrDefault(status, 334 ArtStatsLog.BACKGROUND_DEXOPT_JOB_ENDED__STATUS__STATUS_UNKNOWN), 335 cancellationReason, 336 durationMs, 337 0); // deprecated, used to be durationIncludingSleepMs 338 } 339 } 340 } 341