Search in sources :

Example 1 with InstantRunGradleSupport

use of com.android.tools.idea.fd.gradle.InstantRunGradleSupport in project android by JetBrains.

the class AndroidRunConfigurationBase method getState.

@Override
public RunProfileState getState(@NotNull final Executor executor, @NotNull ExecutionEnvironment env) throws ExecutionException {
    validateBeforeRun(executor);
    final Module module = getConfigurationModule().getModule();
    assert module != null : "Enforced by fatal validation check in checkConfiguration.";
    final AndroidFacet facet = AndroidFacet.getInstance(module);
    assert facet != null : "Enforced by fatal validation check in checkConfiguration.";
    Project project = env.getProject();
    boolean forceColdswap = !InstantRunUtils.isInvokedViaHotswapAction(env);
    boolean couldHaveHotswapped = false;
    boolean debug = false;
    if (executor instanceof DefaultDebugExecutor) {
        if (!AndroidSdkUtils.activateDdmsIfNecessary(facet.getModule().getProject())) {
            throw new ExecutionException("Unable to obtain debug bridge. Please check if there is a different tool using adb that is active.");
        }
        debug = true;
    }
    DeviceFutures deviceFutures = null;
    AndroidSessionInfo info = AndroidSessionInfo.findOldSession(project, null, getUniqueID());
    if (info != null && supportsInstantRun()) {
        // if there is an existing previous session, then see if we can detect devices to fast deploy to
        deviceFutures = getFastDeployDevices(executor, facet, info);
        // that the ReRun is now a global action and doesn't really know much details about each run (and doing that seems like a hack too.)
        if (InstantRunUtils.isReRun(env)) {
            killSession(info);
            info = null;
        }
    }
    if (info != null && deviceFutures == null) {
        // If we should not be fast deploying, but there is an existing session, then terminate those sessions. Otherwise, we might end up
        // with 2 active sessions of the same launch, especially if we first think we can do a fast deploy, then end up doing a full launch
        boolean continueLaunch = promptAndKillSession(executor, project, info);
        if (!continueLaunch) {
            return null;
        }
    } else if (info != null && forceColdswap) {
        // the user could have invoked the hotswap action in this scenario, but they chose to force a coldswap (by pressing run)
        couldHaveHotswapped = true;
        // forcibly kill app in case of run action (which forces a cold swap)
        // normally, installing the apk will force kill the app, but we need to forcibly kill it in the case that there were no changes
        killSession(info);
    }
    // If we are not fast deploying, then figure out (prompting user if needed) where to deploy
    if (deviceFutures == null) {
        DeployTarget deployTarget = getDeployTarget(executor, env, debug, facet);
        if (deployTarget == null) {
            return null;
        }
        DeployTargetState deployTargetState = getDeployTargetContext().getCurrentDeployTargetState();
        if (deployTarget.hasCustomRunProfileState(executor)) {
            return deployTarget.getRunProfileState(executor, env, deployTargetState);
        }
        deviceFutures = deployTarget.getDevices(deployTargetState, facet, getDeviceCount(debug), debug, getUniqueID());
        if (deviceFutures == null) {
            // The user deliberately canceled, or some error was encountered and exposed by the chooser. Quietly exit.
            return null;
        }
    }
    if (deviceFutures.get().isEmpty()) {
        throw new ExecutionException(AndroidBundle.message("deployment.target.not.found"));
    }
    ApplicationIdProvider applicationIdProvider = getApplicationIdProvider(facet);
    InstantRunContext instantRunContext = null;
    if (supportsInstantRun() && InstantRunSettings.isInstantRunEnabled()) {
        InstantRunGradleSupport gradleSupport = canInstantRun(module, deviceFutures.getDevices());
        if (gradleSupport == TARGET_PLATFORM_NOT_INSTALLED) {
            AndroidVersion version = deviceFutures.getDevices().get(0).getVersion();
            String message = AndroidBundle.message("instant.run.quickfix.missing.platform", SdkVersionInfo.getVersionWithCodename(version));
            int result = Messages.showYesNoDialog(project, message, "Instant Run", // yes button
            "Install and Continue", // no button
            "Proceed without Instant Run", Messages.getQuestionIcon());
            if (result == Messages.OK) {
                // if ok, install platform and continue with instant run
                ModelWizardDialog dialog = SdkQuickfixUtils.createDialogForPaths(project, ImmutableList.of(DetailsTypes.getPlatformPath(version)));
                if (dialog == null) {
                    LOG.warn("Unable to get quick fix wizard to install missing platform required for instant run.");
                } else if (dialog.showAndGet()) {
                    gradleSupport = SUPPORTED;
                }
            }
        }
        if (gradleSupport == SUPPORTED) {
            if (!AndroidEnableAdbServiceAction.isAdbServiceEnabled()) {
                throw new ExecutionException("Instant Run requires 'Tools | Android | Enable ADB integration' to be enabled.");
            }
            InstantRunUtils.setInstantRunEnabled(env, true);
            instantRunContext = InstantRunGradleUtils.createGradleProjectContext(facet);
        } else {
            InstantRunManager.LOG.warn("Instant Run enabled, but not doing an instant run build since: " + gradleSupport);
            String notificationText = gradleSupport.getUserNotification();
            if (notificationText != null) {
                InstantRunNotificationTask.showNotification(env.getProject(), null, notificationText);
            }
        }
    } else {
        String msg = "Not using instant run for this launch: ";
        if (InstantRunSettings.isInstantRunEnabled()) {
            msg += getType().getDisplayName() + " does not support instant run";
        } else {
            msg += "instant run is disabled";
        }
        InstantRunManager.LOG.info(msg);
    }
    // Store the chosen target on the execution environment so before-run tasks can access it.
    AndroidRunConfigContext runConfigContext = new AndroidRunConfigContext();
    env.putCopyableUserData(AndroidRunConfigContext.KEY, runConfigContext);
    runConfigContext.setTargetDevices(deviceFutures);
    runConfigContext.setSameExecutorAsPreviousSession(info != null && executor.getId().equals(info.getExecutorId()));
    runConfigContext.setCleanRerun(InstantRunUtils.isCleanReRun(env));
    runConfigContext.setForceColdSwap(forceColdswap, couldHaveHotswapped);
    // Save the instant run context so that before-run task can access it
    env.putCopyableUserData(InstantRunContext.KEY, instantRunContext);
    if (debug) {
        String error = canDebug(deviceFutures, facet, module.getName());
        if (error != null) {
            throw new ExecutionException(error);
        }
    }
    LaunchOptions launchOptions = getLaunchOptions().setDebug(debug).build();
    ProcessHandler processHandler = null;
    if (info != null && info.getExecutorId().equals(executor.getId())) {
        processHandler = info.getProcessHandler();
    }
    ApkProvider apkProvider = getApkProvider(facet, applicationIdProvider);
    LaunchTasksProviderFactory providerFactory = new AndroidLaunchTasksProviderFactory(this, env, facet, applicationIdProvider, apkProvider, deviceFutures, launchOptions, processHandler, instantRunContext);
    InstantRunStatsService.get(project).notifyBuildStarted();
    return new AndroidRunState(env, getName(), module, applicationIdProvider, getConsoleProvider(), deviceFutures, providerFactory, processHandler);
}
Also used : LaunchTasksProviderFactory(com.android.tools.idea.run.tasks.LaunchTasksProviderFactory) InstantRunGradleSupport(com.android.tools.idea.fd.gradle.InstantRunGradleSupport) AndroidVersion(com.android.sdklib.AndroidVersion) AndroidFacet(org.jetbrains.android.facet.AndroidFacet) Project(com.intellij.openapi.project.Project) DefaultDebugExecutor(com.intellij.execution.executors.DefaultDebugExecutor) ProcessHandler(com.intellij.execution.process.ProcessHandler) Module(com.intellij.openapi.module.Module) ExecutionException(com.intellij.execution.ExecutionException) ModelWizardDialog(com.android.tools.idea.wizard.model.ModelWizardDialog)

Example 2 with InstantRunGradleSupport

use of com.android.tools.idea.fd.gradle.InstantRunGradleSupport in project android by JetBrains.

the class AndroidRunConfigurationBase method getFastDeployDevices.

@Nullable
private static DeviceFutures getFastDeployDevices(@NotNull Executor executor, @NotNull AndroidFacet facet, @NotNull AndroidSessionInfo info) {
    if (!InstantRunSettings.isInstantRunEnabled()) {
        InstantRunManager.LOG.info("Instant run not enabled in settings");
        return null;
    }
    if (!info.getExecutorId().equals(executor.getId())) {
        String msg = String.format("Cannot Instant Run since old executor (%1$s) doesn't match current executor (%2$s)", info.getExecutorId(), executor.getId());
        InstantRunManager.LOG.info(msg);
        return null;
    }
    List<IDevice> devices = info.getDevices();
    if (devices == null || devices.isEmpty()) {
        InstantRunManager.LOG.info("Cannot Instant Run since we could not locate the devices from the existing launch session");
        return null;
    }
    if (devices.size() > 1) {
        InstantRunManager.LOG.info("Last run was on > 1 device, not reusing devices and prompting again");
        return null;
    }
    AndroidModuleModel model = AndroidModuleModel.get(facet);
    AndroidVersion version = devices.get(0).getVersion();
    InstantRunGradleSupport status = InstantRunGradleUtils.getIrSupportStatus(model, version);
    if (status != SUPPORTED) {
        InstantRunManager.LOG.info("Cannot Instant Run: " + status);
        return null;
    }
    return DeviceFutures.forDevices(devices);
}
Also used : AndroidModuleModel(com.android.tools.idea.gradle.project.model.AndroidModuleModel) IDevice(com.android.ddmlib.IDevice) InstantRunGradleSupport(com.android.tools.idea.fd.gradle.InstantRunGradleSupport) AndroidVersion(com.android.sdklib.AndroidVersion) Nullable(org.jetbrains.annotations.Nullable)

Example 3 with InstantRunGradleSupport

use of com.android.tools.idea.fd.gradle.InstantRunGradleSupport in project android by JetBrains.

the class HotswapAction method doUpdate.

@Override
protected void doUpdate(@NotNull AnActionEvent e, @NotNull Project project) {
    Presentation presentation = e.getPresentation();
    presentation.setEnabled(false);
    if (!InstantRunSettings.isInstantRunEnabled()) {
        presentation.setText("Apply Changes: Instant Run has been disabled");
        return;
    }
    RunnerAndConfigurationSettings settings = RunManager.getInstance(project).getSelectedConfiguration();
    if (settings == null) {
        presentation.setText("Apply Changes: No run configuration selected");
        return;
    }
    AndroidSessionInfo session = getAndroidSessionInfo(project, settings);
    if (session == null) {
        presentation.setText(String.format("Apply Changes: No active '%1$s' launch", settings.getName()));
        return;
    }
    ProcessHandler processHandler = getActiveProcessHandler(project, settings);
    if (processHandler == null) {
        presentation.setText(String.format("Apply Changes: No active '%1$s' launch", settings.getName()));
        return;
    }
    RunConfiguration configuration = settings.getConfiguration();
    if (!(configuration instanceof ModuleBasedConfiguration)) {
        presentation.setText(String.format("Apply Changes: '%1$s' is not a module based configuration", settings.getName()));
        return;
    }
    Module module = ((ModuleBasedConfiguration) configuration).getConfigurationModule().getModule();
    if (module == null) {
        presentation.setText(String.format("Apply Changes: No module specified in '%1$s'", settings.getName()));
        return;
    }
    if (!(configuration instanceof AndroidRunConfigurationBase)) {
        presentation.setText(String.format("Apply Changes: '%1$s' is not an Android launch configuration", settings.getName()));
        return;
    }
    if (!((AndroidRunConfigurationBase) configuration).supportsInstantRun()) {
        presentation.setText(String.format("Apply Changes: Configuration '%1$s' does not support instant run", settings.getName()));
        return;
    }
    AndroidVersion androidVersion = InstantRunManager.getMinDeviceApiLevel(processHandler);
    if (androidVersion == null) {
        presentation.setText(String.format("Apply Changes: Cannot locate device from '%1$s'", settings.getName()));
        return;
    }
    if (!InstantRunManager.isInstantRunCapableDeviceVersion(androidVersion)) {
        presentation.setText(String.format("Apply Changes: Target device API level (%1$s) too low for Instant Run", androidVersion));
        return;
    }
    InstantRunGradleSupport status = InstantRunGradleUtils.getIrSupportStatus(InstantRunGradleUtils.getAppModel(module), androidVersion);
    if (status != SUPPORTED) {
        String notification = status.getUserNotification();
        if (notification == null) {
            notification = status.toString();
        }
        presentation.setText("Apply Changes: " + notification);
        return;
    }
    presentation.setText("Apply Changes" + getShortcutText());
    presentation.setEnabled(true);
}
Also used : RunConfiguration(com.intellij.execution.configurations.RunConfiguration) AndroidRunConfigurationBase(com.android.tools.idea.run.AndroidRunConfigurationBase) AndroidSessionInfo(com.android.tools.idea.run.AndroidSessionInfo) RunnerAndConfigurationSettings(com.intellij.execution.RunnerAndConfigurationSettings) ProcessHandler(com.intellij.execution.process.ProcessHandler) InstantRunGradleSupport(com.android.tools.idea.fd.gradle.InstantRunGradleSupport) Presentation(com.intellij.openapi.actionSystem.Presentation) ModuleBasedConfiguration(com.intellij.execution.configurations.ModuleBasedConfiguration) Module(com.intellij.openapi.module.Module) AndroidVersion(com.android.sdklib.AndroidVersion)

Example 4 with InstantRunGradleSupport

use of com.android.tools.idea.fd.gradle.InstantRunGradleSupport in project android by JetBrains.

the class AndroidRunConfigurationBase method canInstantRun.

@NotNull
private InstantRunGradleSupport canInstantRun(@NotNull Module module, @NotNull List<AndroidDevice> targetDevices) {
    if (targetDevices.size() != 1) {
        return CANNOT_BUILD_FOR_MULTIPLE_DEVICES;
    }
    AndroidDevice device = targetDevices.get(0);
    AndroidVersion version = device.getVersion();
    if (!InstantRunManager.isInstantRunCapableDeviceVersion(version)) {
        return API_TOO_LOW_FOR_INSTANT_RUN;
    }
    IDevice targetDevice = MakeBeforeRunTaskProvider.getLaunchedDevice(device);
    if (targetDevice != null) {
        if (MultiUserUtils.hasMultipleUsers(targetDevice, 200, TimeUnit.MILLISECONDS, false)) {
            if (// run config explicitly specifies launching as a different user
            getUserIdFromAmParameters() != MultiUserUtils.PRIMARY_USERID || !MultiUserUtils.isCurrentUserThePrimaryUser(targetDevice, 200, TimeUnit.MILLISECONDS, true)) {
                // activity manager says current user is not primary
                return CANNOT_DEPLOY_FOR_SECONDARY_USER;
            }
        }
    }
    InstantRunGradleSupport irSupportStatus = InstantRunGradleUtils.getIrSupportStatus(InstantRunGradleUtils.getAppModel(module), version);
    if (irSupportStatus != SUPPORTED) {
        return irSupportStatus;
    }
    // Gradle will instrument against the runtime android.jar (see commit 353f46cbc7363e3fca44c53a6dc0b4d17347a6ac).
    // This means that the SDK platform corresponding to the device needs to be installed, otherwise the build will fail.
    // We do this as the last check because it is actually possible to recover from this failure. In the future, maybe issues
    // that have fixes will have to be handled in a more generic way.
    AndroidPlatform platform = AndroidPlatform.getInstance(module);
    if (platform == null) {
        return SUPPORTED;
    }
    IAndroidTarget[] targets = platform.getSdkData().getTargets();
    for (int i = targets.length - 1; i >= 0; i--) {
        if (!targets[i].isPlatform()) {
            continue;
        }
        if (targets[i].getVersion().equals(version)) {
            return SUPPORTED;
        }
    }
    return TARGET_PLATFORM_NOT_INSTALLED;
}
Also used : IDevice(com.android.ddmlib.IDevice) AndroidPlatform(org.jetbrains.android.sdk.AndroidPlatform) InstantRunGradleSupport(com.android.tools.idea.fd.gradle.InstantRunGradleSupport) IAndroidTarget(com.android.sdklib.IAndroidTarget) AndroidVersion(com.android.sdklib.AndroidVersion) NotNull(org.jetbrains.annotations.NotNull)

Aggregations

AndroidVersion (com.android.sdklib.AndroidVersion)4 InstantRunGradleSupport (com.android.tools.idea.fd.gradle.InstantRunGradleSupport)4 IDevice (com.android.ddmlib.IDevice)2 ProcessHandler (com.intellij.execution.process.ProcessHandler)2 Module (com.intellij.openapi.module.Module)2 IAndroidTarget (com.android.sdklib.IAndroidTarget)1 AndroidModuleModel (com.android.tools.idea.gradle.project.model.AndroidModuleModel)1 AndroidRunConfigurationBase (com.android.tools.idea.run.AndroidRunConfigurationBase)1 AndroidSessionInfo (com.android.tools.idea.run.AndroidSessionInfo)1 LaunchTasksProviderFactory (com.android.tools.idea.run.tasks.LaunchTasksProviderFactory)1 ModelWizardDialog (com.android.tools.idea.wizard.model.ModelWizardDialog)1 ExecutionException (com.intellij.execution.ExecutionException)1 RunnerAndConfigurationSettings (com.intellij.execution.RunnerAndConfigurationSettings)1 ModuleBasedConfiguration (com.intellij.execution.configurations.ModuleBasedConfiguration)1 RunConfiguration (com.intellij.execution.configurations.RunConfiguration)1 DefaultDebugExecutor (com.intellij.execution.executors.DefaultDebugExecutor)1 Presentation (com.intellij.openapi.actionSystem.Presentation)1 Project (com.intellij.openapi.project.Project)1 AndroidFacet (org.jetbrains.android.facet.AndroidFacet)1 AndroidPlatform (org.jetbrains.android.sdk.AndroidPlatform)1