Skip to content

Commit

Permalink
recovery: Provide sideload cancellation
Browse files Browse the repository at this point in the history
We can't use InterruptWaitKey() as it hangs recovery
when called from the minadbd listener thread, so provide
our own 'CancelWaitKey' implementation.
[forkbomb: rework for Q]

Squashed:
  recovery: Move sideload (non)cancellation to its own key

   * We use KEY_REFRESH for actually refreshing menus, which is
     useful when handling hotpluggable storage.
     We don't want that to interact with the sideload menu.

  Change-Id: Id7f5c06385e613648b3f727fc5e91eb3206406cf

Change-Id: I13f0c9ae5444652a2141442ef24258679a78d320
Signed-off-by: Adithya R <[email protected]>
  • Loading branch information
tdm authored and xenxynon committed Dec 28, 2024
1 parent c7df3ff commit 717698f
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 2 deletions.
20 changes: 18 additions & 2 deletions install/adb_install.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ static auto AdbInstallPackageHandler(Device* device, InstallResult* result) {
break;
}
}
ui->CancelWaitKey();

auto package =
Package::CreateFilePackage(FUSE_SIDELOAD_HOST_PATHNAME,
Expand Down Expand Up @@ -277,7 +278,7 @@ static void ListenAndExecuteMinadbdCommands(
// b11. exit the listening loop
//
static void CreateMinadbdServiceAndExecuteCommands(
RecoveryUI* ui, const std::map<MinadbdCommand, CommandFunction>& command_map,
Device* device, const std::map<MinadbdCommand, CommandFunction>& command_map,
bool rescue_mode) {
signal(SIGPIPE, SIG_IGN);

Expand Down Expand Up @@ -317,8 +318,23 @@ static void CreateMinadbdServiceAndExecuteCommands(
return;
}

RecoveryUI* ui = device->GetUI();
std::thread listener_thread(ListenAndExecuteMinadbdCommands, ui, child,
std::move(recovery_socket), std::ref(command_map));

if (ui->IsTextVisible()) {
std::vector<std::string> headers{ rescue_mode ? "Rescue mode" : "ADB Sideload" };
std::vector<std::string> entries{ "Cancel" };
size_t chosen_item = ui->ShowMenu(
headers, entries, 0, true,
std::bind(&Device::HandleMenuKey, device, std::placeholders::_1, std::placeholders::_2));

if (chosen_item != Device::kDoSideload) {
// Kill minadbd if 'cancel' was selected, to abort sideload.
kill(child, SIGKILL);
}
}

if (listener_thread.joinable()) {
listener_thread.join();
}
Expand Down Expand Up @@ -377,7 +393,7 @@ InstallResult ApplyFromAdb(Device* device, bool rescue_mode, Device::BuiltinActi
ui->Print("\n\nWaiting for rescue commands...\n");
}

CreateMinadbdServiceAndExecuteCommands(ui, command_map, rescue_mode);
CreateMinadbdServiceAndExecuteCommands(device, command_map, rescue_mode);

// Clean up before switching to the older state, for example setting the state
// to none sets sys/class/android_usb/android0/enable to 0.
Expand Down
3 changes: 3 additions & 0 deletions recovery_ui/device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ int Device::HandleMenuKey(int key, bool visible) {
case KEY_POWER:
return kInvokeItem;

case KEY_AGAIN:
return kDoSideload;

default:
// If you have all of the above buttons, any other buttons
// are ignored. Otherwise, any button cycles the highlight.
Expand Down
1 change: 1 addition & 0 deletions recovery_ui/include/recovery_ui/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class Device {
static constexpr const int kHighlightUp = -2;
static constexpr const int kHighlightDown = -3;
static constexpr const int kInvokeItem = -4;
static constexpr const int kDoSideload = -5;

// ENTER vs REBOOT: The latter will trigger a reboot that goes through bootloader, which allows
// using a new bootloader / recovery image if applicable. For example, REBOOT_RESCUE goes from
Expand Down
1 change: 1 addition & 0 deletions recovery_ui/include/recovery_ui/ui.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ class RecoveryUI {
// KeyError::INTERRUPTED on a key interrupt.
virtual int WaitKey();

virtual void CancelWaitKey();
// Wakes up the UI if it is waiting on key input, causing WaitKey to return KeyError::INTERRUPTED.
virtual void InterruptKey();

Expand Down
6 changes: 6 additions & 0 deletions recovery_ui/screen_ui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1277,10 +1277,16 @@ size_t ScreenRecoveryUI::ShowMenu(std::unique_ptr<Menu>&& menu, bool menu_only,
break;
case Device::kNoAction:
break;
case Device::kDoSideload:
chosen_item = Device::kDoSideload;
break;
}
} else if (!menu_only) {
chosen_item = action;
}
if (chosen_item == Device::kDoSideload) {
break;
}
}

menu_.reset();
Expand Down
4 changes: 4 additions & 0 deletions recovery_ui/ui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,10 @@ int RecoveryUI::WaitKey() {
return key;
}

void RecoveryUI::CancelWaitKey() {
EnqueueKey(KEY_AGAIN);
}

void RecoveryUI::InterruptKey() {
{
std::lock_guard<std::mutex> lg(key_queue_mutex);
Expand Down

0 comments on commit 717698f

Please sign in to comment.