/* * Copyright (C) 2015 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.build.gradle.internal.profile; import com.android.build.gradle.internal.tasks.DefaultAndroidTask; import com.android.builder.profile.ExecutionRecord; import com.android.builder.profile.ExecutionType; import com.android.builder.profile.Recorder; import com.google.common.base.CaseFormat; import org.gradle.api.Task; import org.gradle.api.execution.TaskExecutionListener; import org.gradle.api.tasks.TaskState; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * Implementation of the {@link TaskExecutionListener} that records the execution span of * tasks execution and records such spans using the {@link Recorder} facilities. */ public class RecordingBuildListener implements TaskExecutionListener { private static final class TaskRecord { private final long recordId; private final long startTime; TaskRecord(long recordId, long startTime) { this.startTime = startTime; this.recordId = recordId; } } private final Recorder mRecorder; public RecordingBuildListener(Recorder recorder) { mRecorder = recorder; } // map of outstanding tasks executing, keyed by their name. final Map<String, TaskRecord> taskRecords = new ConcurrentHashMap<String, TaskRecord>(); @Override public void beforeExecute(Task task) { taskRecords.put(task.getName(), new TaskRecord( mRecorder.allocationRecordId(), System.currentTimeMillis())); } @Override public void afterExecute(Task task, TaskState taskState) { // find the right ExecutionType. String taskImpl = task.getClass().getSimpleName(); if (taskImpl.endsWith("_Decorated")) { taskImpl = taskImpl.substring(0, taskImpl.length() - "_Decorated".length()); } String potentialExecutionTypeName = "TASK_" + CaseFormat.LOWER_CAMEL.converterTo(CaseFormat.UPPER_UNDERSCORE). convert(taskImpl); ExecutionType executionType; try { executionType = ExecutionType.valueOf(potentialExecutionTypeName); } catch (IllegalArgumentException ignored) { executionType = ExecutionType.GENERIC_TASK_EXECUTION; } List<Recorder.Property> properties = new ArrayList<Recorder.Property>(); properties.add(new Recorder.Property("project", task.getProject().getName())); properties.add(new Recorder.Property("task", task.getName())); if (task instanceof DefaultAndroidTask) { String variantName = ((DefaultAndroidTask) task).getVariantName(); if (variantName == null) { throw new IllegalStateException("Task with type " + task.getClass().getName() + " does not include a variantName"); } if (!variantName.isEmpty()) { properties.add(new Recorder.Property("variant", variantName)); } } TaskRecord taskRecord = taskRecords.get(task.getName()); mRecorder.closeRecord(new ExecutionRecord( taskRecord.recordId, 0 /* parentId */, taskRecord.startTime, System.currentTimeMillis() - taskRecord.startTime, executionType, properties)); } }