diff options
author | Hannah Chu <hanchu@google.com> | 2022-07-21 15:00:20 -0700 |
---|---|---|
committer | Hannah Chu <hanchu@google.com> | 2022-07-27 20:26:18 +0000 |
commit | 4ee8cf5b57c2728ee645198c1243bf943a0e94b5 (patch) | |
tree | fcf196dc58e690d606ddd2c817418c85ce1bf465 | |
parent | 1c1d04dabc36ec5e42009675fcbad6aa2624339b (diff) | |
download | idea-4ee8cf5b57c2728ee645198c1243bf943a0e94b5.tar.gz |
[DM] Add dialog and refresh when AVD deletion fails
Bug: 239499702
Test: DeleteItemTest
Change-Id: I2ae496dca20740ceaa37071fb67962dc334e20ac
3 files changed, 38 insertions, 6 deletions
diff --git a/device-manager/src/com/android/tools/idea/devicemanager/virtualtab/DeleteItem.java b/device-manager/src/com/android/tools/idea/devicemanager/virtualtab/DeleteItem.java index 661929db5d1..380e918ccd1 100644 --- a/device-manager/src/com/android/tools/idea/devicemanager/virtualtab/DeleteItem.java +++ b/device-manager/src/com/android/tools/idea/devicemanager/virtualtab/DeleteItem.java @@ -15,13 +15,17 @@ */ package com.android.tools.idea.devicemanager.virtualtab; +import com.android.tools.idea.devicemanager.DeviceManagerFutureCallback; import com.android.tools.idea.devicemanager.DeviceManagerUsageTracker; import com.google.common.annotations.VisibleForTesting; +import com.google.common.util.concurrent.Futures; import com.google.wireless.android.sdk.stats.DeviceManagerEvent; import com.google.wireless.android.sdk.stats.DeviceManagerEvent.EventKind; +import com.intellij.ide.actions.RevealFileAction; import com.intellij.openapi.ui.JBMenuItem; import com.intellij.openapi.ui.MessageDialogBuilder; import com.intellij.openapi.ui.Messages; +import com.intellij.util.concurrency.EdtExecutorService; import java.awt.Component; import java.util.function.BiPredicate; import java.util.function.Consumer; @@ -58,7 +62,19 @@ final class DeleteItem extends JBMenuItem { return; } - table.getModel().remove(device); + // It's possible for an incomplete AVD deletion to occur. On Windows, this can happen where all the files get deleted, except for the + // empty AVD folder. AvdManagerConnection returns this as a failed deletion, but the AVD .ini file did get deleted, so it's no + // longer a valid AVD. We refresh the whole table in the case of failed deletion to make sure we show correct AVDs. + DeviceManagerFutureCallback<Boolean> callback = new DeviceManagerFutureCallback<>(DeleteItem.class, deletionSuccessful -> { + if (!deletionSuccessful) { + table.refreshAvds(); + if (showUnsuccessfulDeletionDialog(table) == Messages.OK) { + RevealFileAction.openDirectory(device.getAvdInfo().getDataFolderPath()); + } + } + }); + + Futures.addCallback(table.getModel().remove(device), callback, EdtExecutorService.getInstance()); }); } @@ -72,4 +88,14 @@ final class DeleteItem extends JBMenuItem { private static boolean showConfirmDeleteDialog(@NotNull Object device, @NotNull Component component) { return MessageDialogBuilder.yesNo("Confirm Deletion", "Do you really want to delete " + device + "?").ask(component); } + + private static int showUnsuccessfulDeletionDialog(@NotNull Component component) { + return Messages.showOkCancelDialog(component, + "There may be additional files remaining in the AVD directory. Open the directory, " + + "manually delete the files, and refresh AVD list.", + "Could Not Delete All AVD Files", + "Open Directory", + "OK", + Messages.getInformationIcon()); + } } diff --git a/device-manager/src/com/android/tools/idea/devicemanager/virtualtab/VirtualDeviceTableModel.java b/device-manager/src/com/android/tools/idea/devicemanager/virtualtab/VirtualDeviceTableModel.java index 1f2059b75b6..20abc7db57e 100644 --- a/device-manager/src/com/android/tools/idea/devicemanager/virtualtab/VirtualDeviceTableModel.java +++ b/device-manager/src/com/android/tools/idea/devicemanager/virtualtab/VirtualDeviceTableModel.java @@ -36,8 +36,10 @@ import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.wireless.android.sdk.stats.DeviceManagerEvent; import com.google.wireless.android.sdk.stats.DeviceManagerEvent.EventKind; +import com.intellij.ide.actions.RevealFileAction; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.Messages; import com.intellij.util.concurrency.AppExecutorUtil; import com.intellij.util.concurrency.EdtExecutorService; import java.util.ArrayList; @@ -158,14 +160,16 @@ final class VirtualDeviceTableModel extends AbstractTableModel { fireTableRowsUpdated(modelRowIndex, modelRowIndex); } - void remove(@NotNull VirtualDevice device) { + @SuppressWarnings("UnstableApiUsage") + @NotNull ListenableFuture<Boolean> remove(@NotNull VirtualDevice device) { FutureCallback<Boolean> callback = new DeviceManagerFutureCallback<>(VirtualDeviceTableModel.class, deletionSuccessful -> remove(deletionSuccessful, device)); - // noinspection UnstableApiUsage - FluentFuture.from(getDefaultAvdManagerConnection()) - .transform(connection -> connection.deleteAvd(device.getAvdInfo()), AppExecutorUtil.getAppExecutorService()) - .addCallback(callback, EdtExecutorService.getInstance()); + ListenableFuture<Boolean> future = FluentFuture.from(getDefaultAvdManagerConnection()) + .transform(connection -> connection.deleteAvd(device.getAvdInfo()), AppExecutorUtil.getAppExecutorService()); + + Futures.addCallback(future, callback, EdtExecutorService.getInstance()); + return future; } private void remove(boolean deletionSuccessful, @NotNull VirtualDevice device) { diff --git a/device-manager/testSrc/com/android/tools/idea/devicemanager/virtualtab/DeleteItemTest.java b/device-manager/testSrc/com/android/tools/idea/devicemanager/virtualtab/DeleteItemTest.java index d9b4cd30560..93c994d3ffb 100644 --- a/device-manager/testSrc/com/android/tools/idea/devicemanager/virtualtab/DeleteItemTest.java +++ b/device-manager/testSrc/com/android/tools/idea/devicemanager/virtualtab/DeleteItemTest.java @@ -16,6 +16,7 @@ package com.android.tools.idea.devicemanager.virtualtab; import com.android.sdklib.internal.avd.AvdInfo; +import com.google.common.util.concurrent.Futures; import java.awt.Component; import javax.swing.AbstractButton; import org.jetbrains.annotations.NotNull; @@ -79,6 +80,7 @@ public final class DeleteItemTest { // Arrange VirtualDevice virtualDevice = TestVirtualDevices.pixel5Api31(myAvd); Mockito.when(myEditor.getDevice()).thenReturn(virtualDevice); + Mockito.when(myModel.remove(virtualDevice)).thenReturn(Futures.immediateFuture(true)); AbstractButton item = new DeleteItem(myEditor, DeleteItemTest::showCannotDeleteRunningAvdDialog, (device, component) -> true); |