Search in sources :

Example 51 with IDevice

use of com.android.ddmlib.IDevice in project android by JetBrains.

the class AvdManagerConnection method startAvd.

/**
   * Launch the given AVD in the emulator.
   * @return a future with the device that was launched
   */
@NotNull
public ListenableFuture<IDevice> startAvd(@Nullable final Project project, @NotNull final AvdInfo info) {
    if (!initIfNecessary()) {
        return Futures.immediateFailedFuture(new RuntimeException("No Android SDK Found"));
    }
    AccelerationErrorCode error = checkAcceleration();
    ListenableFuture<IDevice> errorResult = handleAccelerationError(project, info, error);
    if (errorResult != null) {
        return errorResult;
    }
    final File emulatorBinary = getEmulatorBinary();
    if (!emulatorBinary.isFile()) {
        IJ_LOG.error("No emulator binary found!");
        return Futures.immediateFailedFuture(new RuntimeException("No emulator binary found"));
    }
    final String avdName = info.getName();
    // perform the same action here. If it is not stale, then we should show this error and if possible, bring that window to the front.
    if (myAvdManager.isAvdRunning(info, SDK_LOG)) {
        String baseFolder;
        try {
            baseFolder = myAvdManager.getBaseAvdFolder().getAbsolutePath();
        } catch (AndroidLocation.AndroidLocationException e) {
            baseFolder = "$HOME";
        }
        String message = String.format("AVD %1$s is already running.\n" + "If that is not the case, delete the files at\n" + "   %2$s/%1$s.avd/*.lock\n" + "and try again.", avdName, baseFolder);
        Messages.showErrorDialog(project, message, "AVD Manager");
        return Futures.immediateFailedFuture(new RuntimeException(message));
    }
    GeneralCommandLine commandLine = new GeneralCommandLine();
    commandLine.setExePath(emulatorBinary.getPath());
    addParameters(info, commandLine);
    EmulatorRunner runner = new EmulatorRunner(commandLine, info);
    EmulatorRunner.ProcessOutputCollector collector = new EmulatorRunner.ProcessOutputCollector();
    runner.addProcessListener(collector);
    final ProcessHandler processHandler;
    try {
        processHandler = runner.start();
    } catch (ExecutionException e) {
        IJ_LOG.error("Error launching emulator", e);
        return Futures.immediateFailedFuture(new RuntimeException(String.format("Error launching emulator %1$s ", avdName), e));
    }
    // If we're using qemu2, it has its own progress bar, so put ours in the background. Otherwise show it.
    final ProgressWindow p = hasQEMU2Installed() ? new BackgroundableProcessIndicator(project, "Launching Emulator", PerformInBackgroundOption.ALWAYS_BACKGROUND, "", "", false) : new ProgressWindow(false, true, project);
    p.setIndeterminate(false);
    p.setDelayInMillis(0);
    // It takes >= 8 seconds to start the Emulator. Display a small progress indicator otherwise it seems like
    // the action wasn't invoked and users tend to click multiple times on it, ending up with several instances of the emulator
    ApplicationManager.getApplication().executeOnPooledThread(() -> {
        try {
            p.start();
            p.setText("Starting AVD...");
            for (double d = 0; d < 1; d += 1.0 / 80) {
                p.setFraction(d);
                //noinspection BusyWait
                Thread.sleep(100);
                if (processHandler.isProcessTerminated()) {
                    break;
                }
            }
        } catch (InterruptedException ignore) {
        } finally {
            p.stop();
            p.processFinish();
        }
        processHandler.removeProcessListener(collector);
        String message = limitErrorMessage(collector.getText());
        if (message.toLowerCase(Locale.ROOT).contains("error") || processHandler.isProcessTerminated() && !message.trim().isEmpty()) {
            ApplicationManager.getApplication().invokeLater(() -> Messages.showErrorDialog(project, "Cannot launch AVD in emulator.\nOutput:\n" + message, avdName));
        }
    });
    return EmulatorConnectionListener.getDeviceForEmulator(project, info.getName(), processHandler, 5, TimeUnit.MINUTES);
}
Also used : IDevice(com.android.ddmlib.IDevice) ProgressWindow(com.intellij.openapi.progress.util.ProgressWindow) GeneralCommandLine(com.intellij.execution.configurations.GeneralCommandLine) BackgroundableProcessIndicator(com.intellij.openapi.progress.impl.BackgroundableProcessIndicator) CapturingAnsiEscapesAwareProcessHandler(com.intellij.execution.process.CapturingAnsiEscapesAwareProcessHandler) ProcessHandler(com.intellij.execution.process.ProcessHandler) ExecutionException(com.intellij.execution.ExecutionException) File(java.io.File) AndroidLocation(com.android.prefs.AndroidLocation) NotNull(org.jetbrains.annotations.NotNull)

Example 52 with IDevice

use of com.android.ddmlib.IDevice in project android by JetBrains.

the class AndroidLogcatView method updateLogConsole.

private void updateLogConsole() {
    IDevice device = getSelectedDevice();
    if (myDevice != device) {
        AndroidLogcatService androidLogcatService = AndroidLogcatService.getInstance();
        if (myDevice != null) {
            androidLogcatService.removeListener(myDevice, myLogcatReceiver);
        }
        // We check for null, because myLogConsole.clear() depends on myLogConsole.getConsole() not being null
        if (myLogConsole.getConsole() != null) {
            myLogConsole.clear();
        }
        myLogFilterModel.processingStarted();
        myDevice = device;
        androidLogcatService.addListener(myDevice, myLogcatReceiver, true);
    }
}
Also used : IDevice(com.android.ddmlib.IDevice)

Example 53 with IDevice

use of com.android.ddmlib.IDevice in project android by JetBrains.

the class DevicePanel method updateDeviceCombo.

private void updateDeviceCombo() {
    myIgnoreActionEvents = true;
    boolean update = true;
    IDevice selected = (IDevice) myDeviceCombo.getSelectedItem();
    myDeviceCombo.removeAllItems();
    boolean shouldAddSelected = true;
    if (myBridge != null) {
        for (IDevice device : myBridge.getDevices()) {
            myDeviceCombo.addItem(device);
            // If we reattach an actual device into Studio, "device" will be the connected IDevice and "selected" will be the disconnected one.
            boolean isSelectedReattached = selected != null && !selected.isEmulator() && selected.getSerialNumber().equals(device.getSerialNumber());
            if (selected == device || isSelectedReattached) {
                myDeviceCombo.setSelectedItem(device);
                shouldAddSelected = false;
                update = selected != device;
            }
        }
    }
    if (selected != null && shouldAddSelected) {
        myDeviceCombo.addItem(selected);
        myDeviceCombo.setSelectedItem(selected);
    }
    if (update) {
        myDeviceContext.fireDeviceSelected((IDevice) myDeviceCombo.getSelectedItem());
        updateClientCombo();
    }
    myIgnoreActionEvents = false;
}
Also used : IDevice(com.android.ddmlib.IDevice)

Example 54 with IDevice

use of com.android.ddmlib.IDevice in project android by JetBrains.

the class DeviceRenderer method renderDeviceName.

static void renderDeviceName(@NotNull IDevice d, @NotNull ColoredTextContainer component, @Nullable AvdManager avdManager) {
    component.setIcon(d.isEmulator() ? AndroidIcons.Ddms.Emulator2 : AndroidIcons.Ddms.RealDevice);
    String name;
    if (d.isEmulator()) {
        String avdName = d.getAvdName();
        if (avdManager != null) {
            AvdInfo info = avdManager.getAvd(avdName, true);
            if (info != null) {
                avdName = info.getProperties().get(AvdManager.AVD_INI_DISPLAY_NAME);
            }
        }
        if (avdName == null) {
            avdName = "unknown";
        }
        name = String.format("%1$s %2$s ", AndroidBundle.message("android.emulator"), avdName);
    } else {
        name = String.format("%1$s %2$s ", DevicePropertyUtil.getManufacturer(d, ""), DevicePropertyUtil.getModel(d, ""));
    }
    component.append(name, SimpleTextAttributes.REGULAR_ATTRIBUTES);
    IDevice.DeviceState deviceState = d.getState();
    if (deviceState != IDevice.DeviceState.ONLINE) {
        String state = String.format("%1$s [%2$s] ", d.getSerialNumber(), d.getState());
        component.append(state, SimpleTextAttributes.GRAYED_BOLD_ATTRIBUTES);
    }
    if (deviceState != IDevice.DeviceState.DISCONNECTED && deviceState != IDevice.DeviceState.OFFLINE) {
        component.append(DevicePropertyUtil.getBuild(d), SimpleTextAttributes.GRAY_ATTRIBUTES);
    }
}
Also used : AvdInfo(com.android.sdklib.internal.avd.AvdInfo) IDevice(com.android.ddmlib.IDevice)

Example 55 with IDevice

use of com.android.ddmlib.IDevice in project android by JetBrains.

the class ConnectJavaDebuggerTask method launchDebugger.

@Override
public ProcessHandler launchDebugger(@NotNull LaunchInfo currentLaunchInfo, @NotNull final Client client, @NotNull ProcessHandlerLaunchStatus launchStatus, @NotNull ProcessHandlerConsolePrinter printer) {
    String debugPort = Integer.toString(client.getDebuggerListenPort());
    final int pid = client.getClientData().getPid();
    Logger.getInstance(ConnectJavaDebuggerTask.class).info(String.format(Locale.US, "Attempting to connect debugger to port %1$s [client %2$d]", debugPort, pid));
    // detach old process handler
    RunContentDescriptor descriptor = currentLaunchInfo.env.getContentToReuse();
    // reach here before the EDT gets around to creating the descriptor?
    assert descriptor != null : "ConnectJavaDebuggerTask expects an existing descriptor that will be reused";
    final ProcessHandler processHandler = descriptor.getProcessHandler();
    assert processHandler != null;
    // create a new process handler
    RemoteConnection connection = new RemoteConnection(true, "localhost", debugPort, false);
    final AndroidRemoteDebugProcessHandler debugProcessHandler = new AndroidRemoteDebugProcessHandler(myProject, myMonitorRemoteProcess);
    // switch the launch status and console printers to point to the new process handler
    // this is required, esp. for AndroidTestListener which holds a reference to the launch status and printers, and those should
    // be updated to point to the new process handlers, otherwise test results will not be forwarded appropriately
    launchStatus.setProcessHandler(debugProcessHandler);
    printer.setProcessHandler(debugProcessHandler);
    // detach after the launch status has been updated to point to the new process handler
    processHandler.detachProcess();
    AndroidDebugState debugState = new AndroidDebugState(myProject, debugProcessHandler, connection, currentLaunchInfo.consoleProvider);
    RunContentDescriptor debugDescriptor;
    try {
        // @formatter:off
        ExecutionEnvironment debugEnv = new ExecutionEnvironmentBuilder(currentLaunchInfo.env).executor(currentLaunchInfo.executor).runner(currentLaunchInfo.runner).contentToReuse(descriptor).build();
        debugDescriptor = DebuggerPanelsManager.getInstance(myProject).attachVirtualMachine(debugEnv, debugState, connection, false);
    // @formatter:on
    } catch (ExecutionException e) {
        processHandler.notifyTextAvailable("ExecutionException: " + e.getMessage() + '.', STDERR);
        return null;
    }
    if (debugDescriptor == null) {
        processHandler.notifyTextAvailable("Unable to connect debugger to Android application", STDERR);
        return null;
    }
    // re-run the collected text from the old process handler to the new
    // TODO: is there a race between messages received once the debugger has been connected, and these messages that are printed out?
    final AndroidProcessText oldText = AndroidProcessText.get(processHandler);
    if (oldText != null) {
        oldText.printTo(debugProcessHandler);
    }
    RunProfile runProfile = currentLaunchInfo.env.getRunProfile();
    int uniqueId = runProfile instanceof RunConfigurationBase ? ((RunConfigurationBase) runProfile).getUniqueID() : -1;
    AndroidSessionInfo value = new AndroidSessionInfo(debugProcessHandler, debugDescriptor, uniqueId, currentLaunchInfo.executor.getId(), InstantRunUtils.isInstantRunEnabled(currentLaunchInfo.env));
    debugProcessHandler.putUserData(AndroidSessionInfo.KEY, value);
    debugProcessHandler.putUserData(AndroidSessionInfo.ANDROID_DEBUG_CLIENT, client);
    debugProcessHandler.putUserData(AndroidSessionInfo.ANDROID_DEVICE_API_LEVEL, client.getDevice().getVersion());
    final String pkgName = client.getClientData().getClientDescription();
    final IDevice device = client.getDevice();
    // kill the process when the debugger is stopped
    debugProcessHandler.addProcessListener(new ProcessAdapter() {

        @Override
        public void processTerminated(ProcessEvent event) {
            debugProcessHandler.removeProcessListener(this);
            Client currentClient = device.getClient(pkgName);
            if (currentClient != null && currentClient.getClientData().getPid() != pid) {
                // a new process has been launched for the same package name, we aren't interested in killing this
                return;
            }
            Logger.getInstance(ConnectJavaDebuggerTask.class).info("Debugger terminating, so terminating process: " + pkgName);
            // Note: client.kill() doesn't work when the debugger is attached, we explicitly stop by package id..
            try {
                device.executeShellCommand("am force-stop " + pkgName, new NullOutputReceiver());
            } catch (Exception e) {
            // don't care..
            }
        }
    });
    return debugProcessHandler;
}
Also used : ExecutionEnvironment(com.intellij.execution.runners.ExecutionEnvironment) RunContentDescriptor(com.intellij.execution.ui.RunContentDescriptor) ProcessAdapter(com.intellij.execution.process.ProcessAdapter) ProcessEvent(com.intellij.execution.process.ProcessEvent) IDevice(com.android.ddmlib.IDevice) RunProfile(com.intellij.execution.configurations.RunProfile) ExecutionException(com.intellij.execution.ExecutionException) RunConfigurationBase(com.intellij.execution.configurations.RunConfigurationBase) ProcessHandler(com.intellij.execution.process.ProcessHandler) RemoteConnection(com.intellij.execution.configurations.RemoteConnection) ExecutionEnvironmentBuilder(com.intellij.execution.runners.ExecutionEnvironmentBuilder) ExecutionException(com.intellij.execution.ExecutionException) Client(com.android.ddmlib.Client) NullOutputReceiver(com.android.ddmlib.NullOutputReceiver)

Aggregations

IDevice (com.android.ddmlib.IDevice)75 Test (org.junit.Test)17 AndroidDebugBridge (com.android.ddmlib.AndroidDebugBridge)11 AdbOptions (com.facebook.buck.step.AdbOptions)11 TargetDeviceOptions (com.facebook.buck.step.TargetDeviceOptions)11 NotNull (org.jetbrains.annotations.NotNull)10 Client (com.android.ddmlib.Client)6 AndroidVersion (com.android.sdklib.AndroidVersion)5 SuppressForbidden (com.facebook.buck.annotations.SuppressForbidden)5 TIntArrayList (gnu.trove.TIntArrayList)5 File (java.io.File)5 Nullable (org.jetbrains.annotations.Nullable)5 InstallException (com.android.ddmlib.InstallException)4 AvdInfo (com.android.sdklib.internal.avd.AvdInfo)4 ExecutionException (java.util.concurrent.ExecutionException)4 AdbCommandRejectedException (com.android.ddmlib.AdbCommandRejectedException)3 ShellCommandUnresponsiveException (com.android.ddmlib.ShellCommandUnresponsiveException)3 TimeoutException (com.android.ddmlib.TimeoutException)3 BuckEventBus (com.facebook.buck.event.BuckEventBus)3 TestConsole (com.facebook.buck.testutil.TestConsole)3