blob: 51554b26a1857d000fcbbb6ffd3cade97a467f6b [file] [log] [blame]
/*
* Copyright 2016 The Bazel Authors. All rights reserved.
*
* 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.google.idea.blaze.android.run.binary.instantrun;
import com.android.builder.model.AndroidProject;
import com.android.tools.idea.gradle.invoker.GradleInvocationResult;
import com.android.tools.idea.gradle.invoker.GradleInvoker;
import com.android.tools.idea.gradle.run.GradleTaskRunner;
import com.android.tools.idea.gradle.util.AndroidGradleSettings;
import com.android.tools.idea.gradle.util.BuildMode;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.idea.blaze.base.scope.BlazeContext;
import com.google.idea.blaze.base.scope.output.PrintOutput;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId;
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListenerAdapter;
import com.intellij.openapi.project.Project;
import com.intellij.util.concurrency.Semaphore;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import static com.android.tools.idea.gradle.util.GradleUtil.GRADLE_SYSTEM_ID;
import static com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskType.EXECUTE_TASK;
public class BlazeInstantRunGradleTaskRunner implements GradleTaskRunner {
private final Project project;
private final BlazeContext context;
private final File instantRunGradleBuildFile;
public BlazeInstantRunGradleTaskRunner(Project project, BlazeContext context, File instantRunGradleBuildFile) {
this.project = project;
this.context = context;
this.instantRunGradleBuildFile = instantRunGradleBuildFile;
}
@Override
public boolean run(@NotNull List<String> tasks, @Nullable BuildMode buildMode, @NotNull List<String> commandLineArguments)
throws InvocationTargetException, InterruptedException {
assert !ApplicationManager.getApplication().isDispatchThread();
final GradleInvoker gradleInvoker = GradleInvoker.getInstance(project);
final AtomicBoolean success = new AtomicBoolean();
final Semaphore done = new Semaphore();
done.down();
final GradleInvoker.AfterGradleInvocationTask afterTask = new GradleInvoker.AfterGradleInvocationTask() {
@Override
public void execute(@NotNull GradleInvocationResult result) {
success.set(result.isBuildSuccessful());
gradleInvoker.removeAfterGradleInvocationTask(this);
done.up();
}
};
ExternalSystemTaskId taskId = ExternalSystemTaskId.create(GRADLE_SYSTEM_ID, EXECUTE_TASK, project);
List<String> jvmArguments = ImmutableList.of();
// https://code.google.com/p/android/issues/detail?id=213040 - make split apks only available if an env var is set
List<String> args = new ArrayList<>(commandLineArguments);
if (!Boolean.valueOf(System.getenv(GradleTaskRunner.USE_SPLIT_APK))) {
// force multi dex when the env var is not set to true
args.add(AndroidGradleSettings.createProjectProperty(AndroidProject.PROPERTY_SIGNING_COLDSWAP_MODE, "MULTIDEX"));
}
// To ensure that the "Run Configuration" waits for the Gradle tasks to be executed, we use SwingUtilities.invokeAndWait. I tried
// using Application.invokeAndWait but it never worked. IDEA also uses SwingUtilities in this scenario (see CompileStepBeforeRun.)
SwingUtilities.invokeAndWait(() -> {
gradleInvoker.addAfterGradleInvocationTask(afterTask);
gradleInvoker.executeTasks(
tasks,
jvmArguments,
args,
taskId,
new GradleNotificationListener(),
instantRunGradleBuildFile,
false,
true
);
});
done.waitFor();
return success.get();
}
class GradleNotificationListener extends ExternalSystemTaskNotificationListenerAdapter {
@Override
public void onTaskOutput(@NotNull ExternalSystemTaskId id, @NotNull String text, boolean stdOut) {
super.onTaskOutput(id, text, stdOut);
String toPrint = text.trim();
if (!Strings.isNullOrEmpty(toPrint)) {
context.output(new PrintOutput(toPrint, stdOut ? PrintOutput.OutputType.NORMAL : PrintOutput.OutputType.ERROR));
}
}
}
}