blob: cab803d77fffc703129cd8d60078e938a5580275 [file] [log] [blame]
/*
* 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 org.jetbrains.android.run;
import com.android.build.OutputFile;
import com.android.builder.model.AndroidArtifact;
import com.android.builder.model.AndroidArtifactOutput;
import com.android.builder.model.BaseArtifact;
import com.android.builder.model.Variant;
import com.android.ddmlib.IDevice;
import com.android.ide.common.build.SplitOutputMatcher;
import com.android.tools.idea.gradle.IdeaAndroidProject;
import com.android.tools.idea.gradle.util.GradleUtil;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.intellij.openapi.diagnostic.Logger;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.util.AndroidBundle;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
/**
* Provides the information on APKs to install for run configurations in Gradle projects.
*/
public class GradleApkProvider implements ApkProvider {
private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.run.GradleApkProvider");
/** Default suffix for test packages (as added by Android Gradle plugin) */
private static final String DEFAULT_TEST_PACKAGE_SUFFIX = ".test";
@NotNull
private final AndroidFacet myFacet;
private final boolean myTest;
public GradleApkProvider(@NotNull AndroidFacet facet, boolean test) {
myFacet = facet;
myTest = test;
}
@Override
@NotNull
public Collection<ApkInfo> getApks(@NotNull IDevice device) throws ApkProvisionException {
IdeaAndroidProject androidModel = myFacet.getAndroidModel();
assert androidModel != null; // This is a Gradle project, there must be an IdeaAndroidProject.
Variant selectedVariant = androidModel.getSelectedVariant();
List<ApkInfo> apkList = new ArrayList<ApkInfo>();
// install apk (note that variant.getOutputFile() will point to a .aar in the case of a library)
if (!androidModel.getAndroidProject().isLibrary()) {
File apk = getApk(selectedVariant, device);
if (apk == null) {
String message = AndroidBundle.message("deployment.failed.cannot.determine.apk", selectedVariant.getDisplayName(), device.getName());
throw new ApkProvisionException(message);
}
apkList.add(new ApkInfo(apk, getPackageName()));
}
if (myTest) {
BaseArtifact testArtifactInfo = androidModel.findSelectedTestArtifactInSelectedVariant();
if (testArtifactInfo instanceof AndroidArtifact) {
AndroidArtifactOutput output = GradleUtil.getOutput((AndroidArtifact)testArtifactInfo);
File testApk = output.getMainOutputFile().getOutputFile();
String testPackageName = getTestPackageName();
assert testPackageName != null; // Cannot be null if initialized.
apkList.add(new ApkInfo(testApk, testPackageName));
}
}
return apkList;
}
@Override
@NotNull
public String getPackageName() throws ApkProvisionException {
return ApkProviderUtil.computePackageName(myFacet);
}
@Override
public String getTestPackageName() throws ApkProvisionException {
IdeaAndroidProject androidModel = myFacet.getAndroidModel();
assert androidModel != null; // This is a Gradle project, there must be an IdeaAndroidProject.
// In the case of Gradle projects, either the merged flavor provides a test package name,
// or we just append ".test" to the source package name
Variant selectedVariant = androidModel.getSelectedVariant();
String testPackageName = selectedVariant.getMergedFlavor().getTestApplicationId();
return (testPackageName != null) ? testPackageName : getPackageName() + DEFAULT_TEST_PACKAGE_SUFFIX;
}
static File getApk(@NotNull Variant variant, @NotNull IDevice device) {
AndroidArtifact mainArtifact = variant.getMainArtifact();
List<AndroidArtifactOutput> outputs = Lists.newArrayList(mainArtifact.getOutputs());
if (outputs.isEmpty()) {
LOG.info("No outputs for the main artifact of variant: " + variant.getDisplayName());
return null;
}
List<String> abis = device.getAbis();
int density = device.getDensity();
Set<String> variantAbiFilters = mainArtifact.getAbiFilters();
List<OutputFile> apkFiles = SplitOutputMatcher.computeBestOutput(outputs, variantAbiFilters, density, abis);
if (apkFiles.isEmpty()) {
String message = AndroidBundle.message("deployment.failed.splitapk.nomatch", outputs.size(), density, Joiner.on(", ").join(abis));
LOG.error(message);
return null;
}
return apkFiles.get(0).getOutputFile();
}
}