blob: 73fe82eb0d33424fe19d4ce1bd524ba8af813106 [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 com.android.tools.idea.run;
import com.android.ddmlib.AndroidDebugBridge;
import com.android.ddmlib.IDevice;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.sdk.AndroidPlatform;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
/**
* Utility methods for selecting a running device.
*/
public class DeviceSelectionUtils {
@NotNull private static final Logger LOG = Logger.getInstance(DeviceSelectionUtils.class);
// We remember what serials the user uses so we can pre-select them in the manual choosing dialog.
@NonNls private static final String ANDROID_TARGET_DEVICES_PROPERTY = "AndroidTargetDevices";
/**
* Returns a compatible, already-running device for launch.
* If no compatible devices are running, returns an empty list.
* If exactly one compatible device is running, returns it.
* If multiple compatible devices are running, prompt the user to select devices.
* If they select any, return them, but if they do not, return null.
*/
@Nullable
public static Collection<IDevice> chooseRunningDevice(@NotNull final AndroidFacet facet,
@NotNull final Predicate<IDevice> deviceFilter,
@NotNull final DeviceCount deviceCount) {
final Collection<IDevice> compatibleDevices = getAllCompatibleDevices(deviceFilter);
if (compatibleDevices.isEmpty()) {
return ImmutableList.of();
}
else if (compatibleDevices.size() == 1) {
return compatibleDevices;
}
else {
// Ask the user to pick one (or more) of the matching devices.
final AtomicReference<IDevice[]> devicesRef = new AtomicReference<IDevice[]>();
ApplicationManager.getApplication().invokeAndWait(new Runnable() {
@Override
public void run() {
devicesRef.set(chooseDevicesManually(facet, deviceFilter, deviceCount));
}
});
// Return the selected devices, or null if the user cancelled.
return devicesRef.get().length > 0 ? ImmutableList.copyOf(devicesRef.get()) : null;
}
}
@NotNull
public static List<IDevice> getAllCompatibleDevices(Predicate<IDevice> deviceFilter) {
final List<IDevice> compatibleDevices = new ArrayList<IDevice>();
final AndroidDebugBridge bridge = AndroidDebugBridge.getBridge();
if (bridge != null) {
IDevice[] devices = bridge.getDevices();
for (IDevice device : devices) {
if (deviceFilter.apply(device)) {
compatibleDevices.add(device);
}
}
}
return compatibleDevices;
}
@NotNull
public static Collection<IDevice> getOnlineDevices(@Nullable Collection<IDevice> devices) {
if (devices == null) {
return Collections.emptyList();
}
final List<IDevice> online = Lists.newArrayListWithExpectedSize(devices.size());
for (IDevice device : devices) {
if (device.isOnline()) {
online.add(device);
}
}
return online;
}
@NotNull
private static IDevice[] chooseDevicesManually(@NotNull AndroidFacet facet,
@NotNull Predicate<IDevice> filter,
@NotNull DeviceCount deviceCount) {
final Project project = facet.getModule().getProject();
String value = PropertiesComponent.getInstance(project).getValue(ANDROID_TARGET_DEVICES_PROPERTY);
String[] selectedSerials = value != null ? deserialize(value) : null;
AndroidPlatform platform = AndroidPlatform.getInstance(facet.getModule());
if (platform == null) {
LOG.error("Android platform not set for module: " + facet.getModule().getName());
return DeviceChooser.EMPTY_DEVICE_ARRAY;
}
DeviceChooserDialog chooser =
new DeviceChooserDialog(facet, platform.getTarget(), deviceCount.isMultiple(), selectedSerials, filter);
chooser.show();
IDevice[] devices = chooser.getSelectedDevices();
if (chooser.getExitCode() != DialogWrapper.OK_EXIT_CODE || devices.length == 0) {
return DeviceChooser.EMPTY_DEVICE_ARRAY;
}
PropertiesComponent.getInstance(project).setValue(ANDROID_TARGET_DEVICES_PROPERTY, serialize(devices));
return devices;
}
@NotNull
public static String serialize(@NotNull IDevice[] devices) {
StringBuilder builder = new StringBuilder();
for (int i = 0, n = devices.length; i < n; i++) {
builder.append(devices[i].getSerialNumber());
if (i < n - 1) {
builder.append(' ');
}
}
return builder.toString();
}
@NotNull
private static String[] deserialize(@NotNull String s) {
return s.split(" ");
}
}