android: "launch ddms" action

This commit is contained in:
Eugene Kudelevsky
2012-03-15 22:35:33 +04:00
parent 2e8e0ba313
commit c3e1556326
7 changed files with 174 additions and 25 deletions
@@ -395,4 +395,7 @@ android.lint.inspections.wrong.view.cast=Mismatched view type
android.lint.inspections.unknown.id.in.layout=Reference to an id that is not in the current layout
android.lint.inspections.unknown.id=Reference to an unknown id
android.lint.inspections.suspicious.import='import android.R' statement
android.debug.sessions.will.be.closed=Following debug sessions will be closed\:\n
android.debug.sessions.will.be.closed=Following debug sessions will be closed\:\n{0}
android.launch.ddms.title=DDMS tool
android.launch.ddms.already.launched.error=DDMS is already launched
android.disable.adb.service.title=Disable ADB service
+3
View File
@@ -57,6 +57,9 @@
<add-to-group group-id="AndroidToolsGroup" anchor="last"/>
</action>
<action id="Android.EnableDdms" class="org.jetbrains.android.actions.AndroidEnableAdbServiceAction">
<add-to-group group-id="AndroidToolsGroup" anchor="last"/>
</action>
<action id="Android.RunDdms" class="org.jetbrains.android.actions.AndroidRunDdmsAction">
<add-to-group group-id="AndroidToolsGroup" anchor="first"/>
</action>
<!--<action id="GotoAndroidResourceDefinition" class="org.jetbrains.android.actions.GotoResourceAction">
@@ -22,8 +22,10 @@ import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.sdk.AndroidSdkUtils;
import org.jetbrains.annotations.Nullable;
/**
* @author Eugene.Kudelevsky
@@ -36,9 +38,13 @@ public class AndroidConnectDebuggerAction extends AnAction {
final Project project = e.getData(PlatformDataKeys.PROJECT);
assert project != null;
final AndroidDebugBridge debugBridge = AndroidSdkUtils.getDebugBridge(project);
if (!AndroidSdkUtils.activateDdmsIfNecessary(project, debugBridge)) {
if (!AndroidSdkUtils.activateDdmsIfNecessary(project, new Computable<AndroidDebugBridge>() {
@Nullable
@Override
public AndroidDebugBridge compute() {
return AndroidSdkUtils.getDebugBridge(project);
}
})) {
return;
}
@@ -25,6 +25,7 @@ import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.actionSystem.ToggleAction;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Pair;
import org.jetbrains.android.facet.AndroidFacet;
@@ -67,32 +68,45 @@ public class AndroidEnableAdbServiceAction extends ToggleAction {
@Override
public void setSelected(AnActionEvent e, boolean state) {
Project project = e.getData(PlatformDataKeys.PROJECT);
setAdbServiceEnabled(project, state);
if (state) {
setAdbServiceEnabled(project, true);
}
else {
disableAdbService(project);
}
}
public static boolean setAdbServiceEnabled(Project project, boolean state) {
public static boolean disableAdbService(Project project) {
ApplicationManager.getApplication().assertIsDispatchThread();
if (!state && !closeAndroidDebugSessions(project)) {
if (!askForClosingDebugSessions(project)) {
return false;
}
setAdbServiceEnabled(project, false);
return true;
}
public static void setAdbServiceEnabled(Project project, boolean state) {
boolean oldState = isAdbServiceEnabled();
PropertiesComponent.getInstance().setValue(ENABLE_ADB_SERVICE_PROPERTY_NAME, Boolean.toString(state));
if (oldState != state) {
AndroidSdkUtils.restartDdmlib(project);
}
return true;
}
private static boolean closeAndroidDebugSessions(@NotNull Project project) {
private static boolean askForClosingDebugSessions(@NotNull Project project) {
final List<Pair<ProcessHandler, RunContentDescriptor>> pairs = new ArrayList<Pair<ProcessHandler, RunContentDescriptor>>();
final ProcessHandler[] processes = ExecutionManager.getInstance(project).getRunningProcesses();
for (ProcessHandler process : processes) {
final RunContentDescriptor descriptor = process.getUserData(AndroidDebugRunner.ANDROID_PROCESS_HANDLER);
if (descriptor != null) {
pairs.add(Pair.create(process, descriptor));
for (Project p : ProjectManager.getInstance().getOpenProjects()) {
final ProcessHandler[] processes = ExecutionManager.getInstance(p).getRunningProcesses();
for (ProcessHandler process : processes) {
if (!process.isProcessTerminated()) {
final RunContentDescriptor descriptor = process.getUserData(AndroidDebugRunner.ANDROID_PROCESS_HANDLER);
if (descriptor != null) {
pairs.add(Pair.create(process, descriptor));
}
}
}
}
@@ -109,8 +123,8 @@ public class AndroidEnableAdbServiceAction extends ToggleAction {
s.append(pair.getSecond().getDisplayName());
}
final int r = Messages.showYesNoDialog(AndroidBundle.message("android.debug.sessions.will.be.closed") + s,
AndroidBundle.message("android.activate.adb.service.title"), Messages.getQuestionIcon());
final int r = Messages.showYesNoDialog(project, AndroidBundle.message("android.debug.sessions.will.be.closed", s),
AndroidBundle.message("android.disable.adb.service.title"), Messages.getQuestionIcon());
return r == Messages.YES;
}
@@ -0,0 +1,86 @@
package org.jetbrains.android.actions;
import com.intellij.CommonBundle;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.process.OSProcessHandler;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.SystemInfo;
import org.jetbrains.android.util.AndroidBundle;
import org.jetbrains.android.util.AndroidCommonUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
/**
* @author Eugene.Kudelevsky
*/
public class AndroidRunDdmsAction extends AndroidRunSdkToolAction {
private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.actions.AndroidRunDdmsAction");
private static volatile OSProcessHandler ourProcessHandler;
public AndroidRunDdmsAction() {
super(AndroidBundle.message("android.launch.ddms.title"));
}
@Override
protected void doRunTool(@NotNull final Project project, @NotNull final String sdkPath) {
if (getDdmsProcessHandler() != null) {
Messages.showErrorDialog(project, AndroidBundle.message("android.launch.ddms.already.launched.error"), CommonBundle.getErrorTitle());
return;
}
final boolean adbServiceEnabled = AndroidEnableAdbServiceAction.isAdbServiceEnabled();
if (adbServiceEnabled && !AndroidEnableAdbServiceAction.disableAdbService(project)) {
return;
}
final String toolPath = sdkPath + File.separator + AndroidCommonUtils.toolPath(getDdmsCmdName());
final GeneralCommandLine commandLine = new GeneralCommandLine();
commandLine.setExePath(toolPath);
LOG.info(commandLine.getCommandLineString());
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
@Override
public void run() {
doLaunchDdms(commandLine, project, adbServiceEnabled);
}
});
}
private static void doLaunchDdms(GeneralCommandLine commandLine, final Project project, final boolean adbServiceWasEnabled) {
try {
ourProcessHandler = new OSProcessHandler(commandLine.createProcess(), "");
ourProcessHandler.startNotify();
ourProcessHandler.waitFor();
}
catch (ExecutionException e) {
LOG.info(e);
}
finally {
ourProcessHandler = null;
if (adbServiceWasEnabled) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
AndroidEnableAdbServiceAction.setAdbServiceEnabled(project, true);
}
});
}
}
}
@Nullable
public static OSProcessHandler getDdmsProcessHandler() {
return ourProcessHandler;
}
@NotNull
private static String getDdmsCmdName() {
return SystemInfo.isWindows ? "ddms.bat" : "ddms";
}
}
@@ -16,6 +16,7 @@
package org.jetbrains.android.run;
import com.android.ddmlib.AndroidDebugBridge;
import com.android.ddmlib.Log;
import com.android.sdklib.internal.avd.AvdInfo;
import com.android.sdklib.internal.avd.AvdManager;
@@ -37,6 +38,7 @@ import com.intellij.openapi.roots.OrderEntry;
import com.intellij.openapi.roots.ui.configuration.ClasspathEditor;
import com.intellij.openapi.roots.ui.configuration.ModulesConfigurator;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.DefaultJDOMExternalizer;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
@@ -181,7 +183,7 @@ public abstract class AndroidRunConfigurationBase extends ModuleBasedConfigurati
if (module == null) {
throw new ExecutionException("Module is not found");
}
AndroidFacet facet = AndroidFacet.getInstance(module);
final AndroidFacet facet = AndroidFacet.getInstance(module);
if (facet == null) {
throw new ExecutionException(AndroidBundle.message("no.facet.error", module.getName()));
}
@@ -196,16 +198,21 @@ public abstract class AndroidRunConfigurationBase extends ModuleBasedConfigurati
return null;
}
if (platform.getSdkData().getDebugBridge(getProject()) == null) return null;
boolean debug = DefaultDebugExecutor.EXECUTOR_ID.equals(executor.getId());
if (debug) {
if (!AndroidSdkUtils.activateDdmsIfNecessary(facet.getModule().getProject(),
facet.getDebugBridge())) {
if (!AndroidSdkUtils.activateDdmsIfNecessary(facet.getModule().getProject(), new Computable<AndroidDebugBridge>() {
@Nullable
@Override
public AndroidDebugBridge compute() {
return facet.getDebugBridge();
}
})) {
return null;
}
}
if (platform.getSdkData().getDebugBridge(getProject()) == null) return null;
String aPackage = getPackageName(facet);
if (aPackage == null) return null;
@@ -24,11 +24,14 @@ import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.ISdkLog;
import com.android.sdklib.SdkConstants;
import com.intellij.CommonBundle;
import com.intellij.execution.process.OSProcessHandler;
import com.intellij.execution.process.OSProcessManager;
import com.intellij.facet.ProjectFacetManager;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.*;
import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil;
@@ -39,6 +42,7 @@ import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.roots.libraries.ui.OrderRoot;
import com.intellij.openapi.roots.ui.configuration.ProjectSettingsService;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.LocalFileSystem;
@@ -47,6 +51,7 @@ import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.util.containers.HashSet;
import org.jetbrains.android.actions.AndroidEnableAdbServiceAction;
import org.jetbrains.android.actions.AndroidRunDdmsAction;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.facet.AndroidRootUtil;
import org.jetbrains.android.logcat.AndroidLogcatToolWindowFactory;
@@ -464,23 +469,48 @@ public class AndroidSdkUtils {
return null;
}
public static boolean activateDdmsIfNecessary(@NotNull Project project, @Nullable AndroidDebugBridge bridge) {
public static boolean activateDdmsIfNecessary(@NotNull Project project, @NotNull Computable<AndroidDebugBridge> bridgeProvider) {
if (AndroidEnableAdbServiceAction.isAdbServiceEnabled()) {
final AndroidDebugBridge bridge = bridgeProvider.compute();
if (bridge != null && isDdmsCorrupted(bridge)) {
LOG.info("DDMLIB is corrupted and will be restarted");
restartDdmlib(project);
}
}
else {
final OSProcessHandler ddmsProcessHandler = AndroidRunDdmsAction.getDdmsProcessHandler();
if (ddmsProcessHandler != null) {
final int r = Messages
.showYesNoDialog(project, "DDMS will be closed to activate ADB service. Continue?", "ADB activation", Messages.getQuestionIcon());
if (r != Messages.YES) {
return false;
}
final Runnable destroyingRunnable = new Runnable() {
@Override
public void run() {
if (!ddmsProcessHandler.isProcessTerminated()) {
OSProcessManager.getInstance().killProcessTree(ddmsProcessHandler.getProcess());
ddmsProcessHandler.waitFor();
}
}
};
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(destroyingRunnable, "Closing DDMS", true, project)) {
return false;
}
AndroidEnableAdbServiceAction.setAdbServiceEnabled(project, true);
return true;
}
int result = Messages.showYesNoDialog(project, AndroidBundle.message("android.ddms.disabled.error"),
AndroidBundle.message("android.ddms.disabled.dialog.title"),
Messages.getQuestionIcon());
if (result != 0) {
return false;
}
if (!AndroidEnableAdbServiceAction.setAdbServiceEnabled(project, true)) {
return false;
}
AndroidEnableAdbServiceAction.setAdbServiceEnabled(project, true);
}
return true;
}