Add fastboot mode to recovery
Add a fastboot mode to recovery that can be entered with command line args or with the ui. Add usb property triggers to switch between fastboot and adb configurations. Allow switching between fastboot and adb through usb commands by opening a unix socket. adbd/fastbootd writes to this socket, which interrupts the ui and switches to the new mode. Test: Use fastboot mode Bug: 78793464 Change-Id: I7891bb84427ec734a21a872036629b95ab3fb13c
This commit is contained in:
parent
337bd80b78
commit
20c81b308d
8 changed files with 325 additions and 42 deletions
24
Android.bp
24
Android.bp
|
@ -96,6 +96,29 @@ cc_library_static {
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cc_library_static {
|
||||||
|
name: "librecovery_fastboot",
|
||||||
|
recovery_available: true,
|
||||||
|
defaults: [
|
||||||
|
"recovery_defaults",
|
||||||
|
],
|
||||||
|
|
||||||
|
srcs: [
|
||||||
|
"fastboot/fastboot.cpp",
|
||||||
|
],
|
||||||
|
|
||||||
|
shared_libs: [
|
||||||
|
"libbase",
|
||||||
|
"libbootloader_message",
|
||||||
|
"libcutils",
|
||||||
|
"liblog",
|
||||||
|
],
|
||||||
|
|
||||||
|
static_libs: [
|
||||||
|
"librecovery_ui_default",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
cc_defaults {
|
cc_defaults {
|
||||||
name: "librecovery_defaults",
|
name: "librecovery_defaults",
|
||||||
|
|
||||||
|
@ -124,6 +147,7 @@ cc_defaults {
|
||||||
],
|
],
|
||||||
|
|
||||||
static_libs: [
|
static_libs: [
|
||||||
|
"librecovery_fastboot",
|
||||||
"libminui",
|
"libminui",
|
||||||
"libverifier",
|
"libverifier",
|
||||||
"libotautil",
|
"libotautil",
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
static std::vector<std::pair<std::string, Device::BuiltinAction>> g_menu_actions{
|
static std::vector<std::pair<std::string, Device::BuiltinAction>> g_menu_actions{
|
||||||
{ "Reboot system now", Device::REBOOT },
|
{ "Reboot system now", Device::REBOOT },
|
||||||
{ "Reboot to bootloader", Device::REBOOT_BOOTLOADER },
|
{ "Reboot to bootloader", Device::REBOOT_BOOTLOADER },
|
||||||
|
{ "Enter fastboot", Device::ENTER_FASTBOOT },
|
||||||
{ "Apply update from ADB", Device::APPLY_ADB_SIDELOAD },
|
{ "Apply update from ADB", Device::APPLY_ADB_SIDELOAD },
|
||||||
{ "Apply update from SD card", Device::APPLY_SDCARD },
|
{ "Apply update from SD card", Device::APPLY_SDCARD },
|
||||||
{ "Wipe data/factory reset", Device::WIPE_DATA },
|
{ "Wipe data/factory reset", Device::WIPE_DATA },
|
||||||
|
|
2
device.h
2
device.h
|
@ -48,6 +48,8 @@ class Device {
|
||||||
RUN_GRAPHICS_TEST = 11,
|
RUN_GRAPHICS_TEST = 11,
|
||||||
RUN_LOCALE_TEST = 12,
|
RUN_LOCALE_TEST = 12,
|
||||||
KEY_INTERRUPTED = 13,
|
KEY_INTERRUPTED = 13,
|
||||||
|
ENTER_FASTBOOT = 14,
|
||||||
|
ENTER_RECOVERY = 15,
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit Device(RecoveryUI* ui);
|
explicit Device(RecoveryUI* ui);
|
||||||
|
|
103
etc/init.rc
103
etc/init.rc
|
@ -6,6 +6,8 @@ on early-init
|
||||||
|
|
||||||
start ueventd
|
start ueventd
|
||||||
|
|
||||||
|
setprop sys.usb.configfs 0
|
||||||
|
|
||||||
on init
|
on init
|
||||||
export ANDROID_ROOT /system
|
export ANDROID_ROOT /system
|
||||||
export ANDROID_DATA /data
|
export ANDROID_DATA /data
|
||||||
|
@ -31,20 +33,6 @@ on init
|
||||||
write /proc/sys/kernel/panic_on_oops 1
|
write /proc/sys/kernel/panic_on_oops 1
|
||||||
write /proc/sys/vm/max_map_count 1000000
|
write /proc/sys/vm/max_map_count 1000000
|
||||||
|
|
||||||
on fs
|
|
||||||
write /sys/class/android_usb/android0/f_ffs/aliases adb
|
|
||||||
mkdir /dev/usb-ffs 0770 shell shell
|
|
||||||
mkdir /dev/usb-ffs/adb 0770 shell shell
|
|
||||||
mount functionfs adb /dev/usb-ffs/adb uid=2000,gid=2000
|
|
||||||
|
|
||||||
write /sys/class/android_usb/android0/enable 0
|
|
||||||
write /sys/class/android_usb/android0/idVendor 18D1
|
|
||||||
write /sys/class/android_usb/android0/idProduct D001
|
|
||||||
write /sys/class/android_usb/android0/functions adb
|
|
||||||
write /sys/class/android_usb/android0/iManufacturer ${ro.product.manufacturer}
|
|
||||||
write /sys/class/android_usb/android0/iProduct ${ro.product.model}
|
|
||||||
write /sys/class/android_usb/android0/iSerial ${ro.serialno}
|
|
||||||
|
|
||||||
on boot
|
on boot
|
||||||
ifup lo
|
ifup lo
|
||||||
hostname localhost
|
hostname localhost
|
||||||
|
@ -86,6 +74,7 @@ service charger /charger -r
|
||||||
seclabel u:r:charger:s0
|
seclabel u:r:charger:s0
|
||||||
|
|
||||||
service recovery /system/bin/recovery
|
service recovery /system/bin/recovery
|
||||||
|
socket recovery stream 422 system system
|
||||||
seclabel u:r:recovery:s0
|
seclabel u:r:recovery:s0
|
||||||
|
|
||||||
service adbd /system/bin/adbd --root_seclabel=u:r:su:s0 --device_banner=recovery
|
service adbd /system/bin/adbd --root_seclabel=u:r:su:s0 --device_banner=recovery
|
||||||
|
@ -93,13 +82,89 @@ service adbd /system/bin/adbd --root_seclabel=u:r:su:s0 --device_banner=recovery
|
||||||
socket adbd stream 660 system system
|
socket adbd stream 660 system system
|
||||||
seclabel u:r:adbd:s0
|
seclabel u:r:adbd:s0
|
||||||
|
|
||||||
# Always start adbd on userdebug and eng builds
|
service fastbootd /system/bin/fastbootd
|
||||||
on property:ro.debuggable=1
|
disabled
|
||||||
write /sys/class/android_usb/android0/enable 1
|
group system
|
||||||
start adbd
|
seclabel u:r:fastbootd:s0
|
||||||
|
|
||||||
# Restart adbd so it can run as root
|
# Restart adbd so it can run as root
|
||||||
on property:service.adb.root=1
|
on property:service.adb.root=1
|
||||||
write /sys/class/android_usb/android0/enable 0
|
|
||||||
restart adbd
|
restart adbd
|
||||||
|
|
||||||
|
# Always start adbd on userdebug and eng builds
|
||||||
|
on fs && property:ro.debuggable=1
|
||||||
|
setprop sys.usb.config adb
|
||||||
|
|
||||||
|
on fs && property:sys.usb.configfs=1
|
||||||
|
mount configfs none /config
|
||||||
|
mkdir /config/usb_gadget/g1 0770 shell shell
|
||||||
|
write /config/usb_gadget/g1/idVendor 0x18D1
|
||||||
|
mkdir /config/usb_gadget/g1/strings/0x409 0770
|
||||||
|
write /config/usb_gadget/g1/strings/0x409/serialnumber ${ro.serialno}
|
||||||
|
write /config/usb_gadget/g1/strings/0x409/manufacturer ${ro.product.manufacturer}
|
||||||
|
write /config/usb_gadget/g1/strings/0x409/product ${ro.product.model}
|
||||||
|
mkdir /config/usb_gadget/g1/functions/ffs.adb
|
||||||
|
mkdir /config/usb_gadget/g1/functions/ffs.fastboot
|
||||||
|
mkdir /config/usb_gadget/g1/configs/b.1 0777 shell shell
|
||||||
|
mkdir /config/usb_gadget/g1/configs/b.1/strings/0x409 0770 shell shell
|
||||||
|
|
||||||
|
on fs && property:sys.usb.configfs=0
|
||||||
|
write /sys/class/android_usb/android0/f_ffs/aliases adb,fastboot
|
||||||
|
write /sys/class/android_usb/android0/idVendor 18D1
|
||||||
|
write /sys/class/android_usb/android0/iManufacturer ${ro.product.manufacturer}
|
||||||
|
write /sys/class/android_usb/android0/iProduct ${ro.product.model}
|
||||||
|
write /sys/class/android_usb/android0/iSerial ${ro.serialno}
|
||||||
|
|
||||||
|
on fs
|
||||||
|
mkdir /dev/usb-ffs 0775 shell shell
|
||||||
|
mkdir /dev/usb-ffs/adb 0770 shell shell
|
||||||
|
mount functionfs adb /dev/usb-ffs/adb uid=2000,gid=2000
|
||||||
|
mkdir /dev/usb-ffs/fastboot 0770 system system
|
||||||
|
mount functionfs fastboot /dev/usb-ffs/fastboot rmode=0770,fmode=0660,uid=1000,gid=1000
|
||||||
|
|
||||||
|
on property:sys.usb.config=adb
|
||||||
|
start adbd
|
||||||
|
|
||||||
|
on property:sys.usb.config=fastboot
|
||||||
|
start fastbootd
|
||||||
|
|
||||||
|
on property:sys.usb.config=none
|
||||||
|
stop adbd
|
||||||
|
stop fastbootd
|
||||||
|
|
||||||
|
on property:sys.usb.config=none && property:sys.usb.configfs=0
|
||||||
|
write /sys/class/android_usb/android0/enable 0
|
||||||
|
setprop sys.usb.state ${sys.usb.config}
|
||||||
|
|
||||||
|
on property:sys.usb.config=adb && property:sys.usb.configfs=0
|
||||||
|
write /sys/class/android_usb/android0/idProduct D001
|
||||||
|
write /sys/class/android_usb/android0/functions adb
|
||||||
write /sys/class/android_usb/android0/enable 1
|
write /sys/class/android_usb/android0/enable 1
|
||||||
|
setprop sys.usb.state ${sys.usb.config}
|
||||||
|
|
||||||
|
on property:sys.usb.config=fastboot && property:sys.usb.configfs=0
|
||||||
|
write /sys/class/android_usb/android0/idProduct 4EE0
|
||||||
|
write /sys/class/android_usb/android0/functions fastboot
|
||||||
|
write /sys/class/android_usb/android0/enable 1
|
||||||
|
setprop sys.usb.state ${sys.usb.config}
|
||||||
|
|
||||||
|
# Configfs triggers
|
||||||
|
on property:sys.usb.config=none && property:sys.usb.configfs=1
|
||||||
|
write /config/usb_gadget/g1/UDC "none"
|
||||||
|
setprop sys.usb.ffs.ready 0
|
||||||
|
rm /config/usb_gadget/g1/configs/b.1/f1
|
||||||
|
setprop sys.usb.state ${sys.usb.config}
|
||||||
|
|
||||||
|
on property:sys.usb.config=adb && property:sys.usb.ffs.ready=1 && property:sys.usb.configfs=1
|
||||||
|
write /config/usb_gadget/g1/idProduct 0xD001
|
||||||
|
write /config/usb_gadget/g1/configs/b.1/strings/0x409/configuration "adb"
|
||||||
|
symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f1
|
||||||
|
write /config/usb_gadget/g1/UDC ${sys.usb.controller}
|
||||||
|
setprop sys.usb.state ${sys.usb.config}
|
||||||
|
|
||||||
|
on property:sys.usb.config=fastboot && property:sys.usb.ffs.ready=1 && property:sys.usb.configfs=1
|
||||||
|
write /config/usb_gadget/g1/idProduct 0x4EE0
|
||||||
|
write /config/usb_gadget/g1/configs/b.1/strings/0x409/configuration "fastboot"
|
||||||
|
symlink /config/usb_gadget/g1/functions/ffs.fastboot /config/usb_gadget/g1/configs/b.1/f1
|
||||||
|
write /config/usb_gadget/g1/UDC ${sys.usb.controller}
|
||||||
|
setprop sys.usb.state ${sys.usb.config}
|
||||||
|
|
82
fastboot/fastboot.cpp
Normal file
82
fastboot/fastboot.cpp
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2018 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "fastboot.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <android-base/logging.h>
|
||||||
|
#include <android-base/properties.h>
|
||||||
|
#include <bootloader_message/bootloader_message.h>
|
||||||
|
|
||||||
|
#include "device.h"
|
||||||
|
#include "ui.h"
|
||||||
|
|
||||||
|
static const std::vector<std::pair<std::string, Device::BuiltinAction>> kFastbootMenuActions{
|
||||||
|
{ "Reboot system now", Device::REBOOT },
|
||||||
|
{ "Enter recovery", Device::ENTER_RECOVERY },
|
||||||
|
{ "Reboot to bootloader", Device::REBOOT_BOOTLOADER },
|
||||||
|
{ "Power off", Device::SHUTDOWN },
|
||||||
|
};
|
||||||
|
|
||||||
|
Device::BuiltinAction StartFastboot(Device* device, const std::vector<std::string>& /* args */) {
|
||||||
|
RecoveryUI* ui = device->GetUI();
|
||||||
|
|
||||||
|
std::vector<std::string> title_lines = { "Android Fastboot" };
|
||||||
|
title_lines.push_back("Product name - " + android::base::GetProperty("ro.product.device", ""));
|
||||||
|
title_lines.push_back("Bootloader version - " + android::base::GetProperty("ro.bootloader", ""));
|
||||||
|
title_lines.push_back("Baseband version - " +
|
||||||
|
android::base::GetProperty("ro.build.expect.baseband", ""));
|
||||||
|
title_lines.push_back("Serial number - " + android::base::GetProperty("ro.serialno", ""));
|
||||||
|
title_lines.push_back(std::string("Secure boot - ") +
|
||||||
|
((android::base::GetProperty("ro.secure", "") == "1") ? "yes" : "no"));
|
||||||
|
title_lines.push_back("HW version - " + android::base::GetProperty("ro.revision", ""));
|
||||||
|
|
||||||
|
ui->ResetKeyInterruptStatus();
|
||||||
|
ui->SetTitle(title_lines);
|
||||||
|
ui->ShowText(true);
|
||||||
|
|
||||||
|
// Reset to normal system boot so recovery won't cycle indefinitely.
|
||||||
|
// TODO(b/112277594) Clear only if 'recovery' field of BCB is empty. If not,
|
||||||
|
// set the 'command' field of BCB to 'boot-recovery' so the next boot is into recovery
|
||||||
|
// to finish any interrupted tasks.
|
||||||
|
std::string err;
|
||||||
|
if (!clear_bootloader_message(&err)) {
|
||||||
|
LOG(ERROR) << "Failed to clear BCB message: " << err;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> fastboot_menu_items;
|
||||||
|
std::transform(kFastbootMenuActions.cbegin(), kFastbootMenuActions.cend(),
|
||||||
|
std::back_inserter(fastboot_menu_items),
|
||||||
|
[](const auto& entry) { return entry.first; });
|
||||||
|
|
||||||
|
auto chosen_item = ui->ShowMenu(
|
||||||
|
{}, fastboot_menu_items, 0, false,
|
||||||
|
std::bind(&Device::HandleMenuKey, device, std::placeholders::_1, std::placeholders::_2));
|
||||||
|
|
||||||
|
if (chosen_item == static_cast<size_t>(RecoveryUI::KeyError::INTERRUPTED)) {
|
||||||
|
return Device::KEY_INTERRUPTED;
|
||||||
|
}
|
||||||
|
if (chosen_item == static_cast<size_t>(RecoveryUI::KeyError::TIMED_OUT)) {
|
||||||
|
return Device::BuiltinAction::NO_ACTION;
|
||||||
|
}
|
||||||
|
return kFastbootMenuActions[chosen_item].second;
|
||||||
|
}
|
24
fastboot/fastboot.h
Normal file
24
fastboot/fastboot.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2018 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "device.h"
|
||||||
|
|
||||||
|
Device::BuiltinAction StartFastboot(Device* device, const std::vector<std::string>& args);
|
|
@ -779,6 +779,8 @@ static Device::BuiltinAction prompt_and_wait(Device* device, int status) {
|
||||||
case Device::REBOOT:
|
case Device::REBOOT:
|
||||||
case Device::SHUTDOWN:
|
case Device::SHUTDOWN:
|
||||||
case Device::REBOOT_BOOTLOADER:
|
case Device::REBOOT_BOOTLOADER:
|
||||||
|
case Device::ENTER_FASTBOOT:
|
||||||
|
case Device::ENTER_RECOVERY:
|
||||||
return chosen_action;
|
return chosen_action;
|
||||||
|
|
||||||
case Device::WIPE_DATA:
|
case Device::WIPE_DATA:
|
||||||
|
@ -1006,6 +1008,7 @@ static void log_failure_code(ErrorCode code, const std::string& update_package)
|
||||||
|
|
||||||
Device::BuiltinAction start_recovery(Device* device, const std::vector<std::string>& args) {
|
Device::BuiltinAction start_recovery(Device* device, const std::vector<std::string>& args) {
|
||||||
static constexpr struct option OPTIONS[] = {
|
static constexpr struct option OPTIONS[] = {
|
||||||
|
{ "fastboot", no_argument, nullptr, 0 },
|
||||||
{ "fsck_unshare_blocks", no_argument, nullptr, 0 },
|
{ "fsck_unshare_blocks", no_argument, nullptr, 0 },
|
||||||
{ "just_exit", no_argument, nullptr, 'x' },
|
{ "just_exit", no_argument, nullptr, 'x' },
|
||||||
{ "locale", required_argument, nullptr, 0 },
|
{ "locale", required_argument, nullptr, 0 },
|
||||||
|
@ -1060,7 +1063,7 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri
|
||||||
std::string option = OPTIONS[option_index].name;
|
std::string option = OPTIONS[option_index].name;
|
||||||
if (option == "fsck_unshare_blocks") {
|
if (option == "fsck_unshare_blocks") {
|
||||||
fsck_unshare_blocks = true;
|
fsck_unshare_blocks = true;
|
||||||
} else if (option == "locale") {
|
} else if (option == "locale" || option == "fastboot") {
|
||||||
// Handled in recovery_main.cpp
|
// Handled in recovery_main.cpp
|
||||||
} else if (option == "prompt_and_wipe_data") {
|
} else if (option == "prompt_and_wipe_data") {
|
||||||
should_prompt_and_wipe_data = true;
|
should_prompt_and_wipe_data = true;
|
||||||
|
|
|
@ -30,15 +30,19 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <thread>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <android-base/file.h>
|
#include <android-base/file.h>
|
||||||
#include <android-base/logging.h>
|
#include <android-base/logging.h>
|
||||||
#include <android-base/properties.h>
|
#include <android-base/properties.h>
|
||||||
#include <android-base/strings.h>
|
#include <android-base/strings.h>
|
||||||
|
#include <android-base/unique_fd.h>
|
||||||
#include <bootloader_message/bootloader_message.h>
|
#include <bootloader_message/bootloader_message.h>
|
||||||
#include <cutils/android_reboot.h>
|
#include <cutils/android_reboot.h>
|
||||||
|
#include <cutils/sockets.h>
|
||||||
#include <private/android_logger.h> /* private pmsg functions */
|
#include <private/android_logger.h> /* private pmsg functions */
|
||||||
#include <selinux/android.h>
|
#include <selinux/android.h>
|
||||||
#include <selinux/label.h>
|
#include <selinux/label.h>
|
||||||
|
@ -46,6 +50,7 @@
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
|
#include "fastboot/fastboot.h"
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
#include "minadbd/minadbd.h"
|
#include "minadbd/minadbd.h"
|
||||||
#include "otautil/paths.h"
|
#include "otautil/paths.h"
|
||||||
|
@ -162,6 +167,44 @@ static std::string load_locale_from_cache() {
|
||||||
return android::base::Trim(content);
|
return android::base::Trim(content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ListenRecoverySocket(RecoveryUI* ui, std::atomic<Device::BuiltinAction>& action) {
|
||||||
|
android::base::unique_fd sock_fd(android_get_control_socket("recovery"));
|
||||||
|
if (sock_fd < 0) {
|
||||||
|
PLOG(ERROR) << "Failed to open recovery socket";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
listen(sock_fd, 4);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
android::base::unique_fd connection_fd;
|
||||||
|
connection_fd.reset(accept(sock_fd, nullptr, nullptr));
|
||||||
|
if (connection_fd < 0) {
|
||||||
|
PLOG(ERROR) << "Failed to accept socket connection";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
char msg;
|
||||||
|
constexpr char kSwitchToFastboot = 'f';
|
||||||
|
constexpr char kSwitchToRecovery = 'r';
|
||||||
|
ssize_t ret = TEMP_FAILURE_RETRY(read(connection_fd, &msg, sizeof(msg)));
|
||||||
|
if (ret != sizeof(msg)) {
|
||||||
|
PLOG(ERROR) << "Couldn't read from socket";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
switch (msg) {
|
||||||
|
case kSwitchToRecovery:
|
||||||
|
action = Device::BuiltinAction::ENTER_RECOVERY;
|
||||||
|
break;
|
||||||
|
case kSwitchToFastboot:
|
||||||
|
action = Device::BuiltinAction::ENTER_FASTBOOT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOG(ERROR) << "Unrecognized char from socket " << msg;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ui->InterruptKey();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void redirect_stdio(const char* filename) {
|
static void redirect_stdio(const char* filename) {
|
||||||
int pipefd[2];
|
int pipefd[2];
|
||||||
if (pipe(pipefd) == -1) {
|
if (pipe(pipefd) == -1) {
|
||||||
|
@ -251,6 +294,11 @@ static void redirect_stdio(const char* filename) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool SetUsbConfig(const std::string& state) {
|
||||||
|
android::base::SetProperty("sys.usb.config", state);
|
||||||
|
return android::base::WaitForProperty("sys.usb.state", state);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
// We don't have logcat yet under recovery; so we'll print error on screen and log to stdout
|
// We don't have logcat yet under recovery; so we'll print error on screen and log to stdout
|
||||||
// (which is redirected to recovery.log) as we used to do.
|
// (which is redirected to recovery.log) as we used to do.
|
||||||
|
@ -281,8 +329,6 @@ int main(int argc, char** argv) {
|
||||||
// instances with different timestamps.
|
// instances with different timestamps.
|
||||||
redirect_stdio(Paths::Get().temporary_log_file().c_str());
|
redirect_stdio(Paths::Get().temporary_log_file().c_str());
|
||||||
|
|
||||||
printf("Starting recovery (pid %d) on %s", getpid(), ctime(&start));
|
|
||||||
|
|
||||||
load_volume_table();
|
load_volume_table();
|
||||||
has_cache = volume_for_mount_point(CACHE_ROOT) != nullptr;
|
has_cache = volume_for_mount_point(CACHE_ROOT) != nullptr;
|
||||||
|
|
||||||
|
@ -290,12 +336,14 @@ int main(int argc, char** argv) {
|
||||||
auto args_to_parse = StringVectorToNullTerminatedArray(args);
|
auto args_to_parse = StringVectorToNullTerminatedArray(args);
|
||||||
|
|
||||||
static constexpr struct option OPTIONS[] = {
|
static constexpr struct option OPTIONS[] = {
|
||||||
|
{ "fastboot", no_argument, nullptr, 0 },
|
||||||
{ "locale", required_argument, nullptr, 0 },
|
{ "locale", required_argument, nullptr, 0 },
|
||||||
{ "show_text", no_argument, nullptr, 't' },
|
{ "show_text", no_argument, nullptr, 't' },
|
||||||
{ nullptr, 0, nullptr, 0 },
|
{ nullptr, 0, nullptr, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
bool show_text = false;
|
bool show_text = false;
|
||||||
|
bool fastboot = false;
|
||||||
std::string locale;
|
std::string locale;
|
||||||
|
|
||||||
int arg;
|
int arg;
|
||||||
|
@ -310,6 +358,8 @@ int main(int argc, char** argv) {
|
||||||
std::string option = OPTIONS[option_index].name;
|
std::string option = OPTIONS[option_index].name;
|
||||||
if (option == "locale") {
|
if (option == "locale") {
|
||||||
locale = optarg;
|
locale = optarg;
|
||||||
|
} else if (option == "fastboot") {
|
||||||
|
fastboot = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -328,8 +378,6 @@ int main(int argc, char** argv) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("locale is [%s]\n", locale.c_str());
|
|
||||||
|
|
||||||
static constexpr const char* kDefaultLibRecoveryUIExt = "librecovery_ui_ext.so";
|
static constexpr const char* kDefaultLibRecoveryUIExt = "librecovery_ui_ext.so";
|
||||||
// Intentionally not calling dlclose(3) to avoid potential gotchas (e.g. `make_device` may have
|
// Intentionally not calling dlclose(3) to avoid potential gotchas (e.g. `make_device` may have
|
||||||
// handed out pointers to code or static [or thread-local] data and doesn't collect them all back
|
// handed out pointers to code or static [or thread-local] data and doesn't collect them all back
|
||||||
|
@ -374,33 +422,67 @@ int main(int argc, char** argv) {
|
||||||
ui->SetBackground(RecoveryUI::NONE);
|
ui->SetBackground(RecoveryUI::NONE);
|
||||||
if (show_text) ui->ShowText(true);
|
if (show_text) ui->ShowText(true);
|
||||||
|
|
||||||
|
LOG(INFO) << "Starting recovery (pid " << getpid() << ") on " << ctime(&start);
|
||||||
|
LOG(INFO) << "locale is [" << locale << "]";
|
||||||
|
|
||||||
sehandle = selinux_android_file_context_handle();
|
sehandle = selinux_android_file_context_handle();
|
||||||
selinux_android_set_sehandle(sehandle);
|
selinux_android_set_sehandle(sehandle);
|
||||||
if (!sehandle) {
|
if (!sehandle) {
|
||||||
ui->Print("Warning: No file_contexts\n");
|
ui->Print("Warning: No file_contexts\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
Device::BuiltinAction after = start_recovery(device, args);
|
std::atomic<Device::BuiltinAction> action;
|
||||||
|
std::thread listener_thread(ListenRecoverySocket, ui, std::ref(action));
|
||||||
|
listener_thread.detach();
|
||||||
|
|
||||||
switch (after) {
|
|
||||||
case Device::SHUTDOWN:
|
|
||||||
ui->Print("Shutting down...\n");
|
|
||||||
android::base::SetProperty(ANDROID_RB_PROPERTY, "shutdown,");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Device::REBOOT_BOOTLOADER:
|
|
||||||
ui->Print("Rebooting to bootloader...\n");
|
|
||||||
android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,bootloader");
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
ui->Print("Rebooting...\n");
|
|
||||||
reboot("reboot,");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
while (true) {
|
while (true) {
|
||||||
pause();
|
std::string usb_config = fastboot ? "fastboot" : is_ro_debuggable() ? "adb" : "none";
|
||||||
|
std::string usb_state = android::base::GetProperty("sys.usb.state", "none");
|
||||||
|
if (usb_config != usb_state) {
|
||||||
|
if (!SetUsbConfig("none")) {
|
||||||
|
LOG(ERROR) << "Failed to clear USB config";
|
||||||
|
}
|
||||||
|
if (!SetUsbConfig(usb_config)) {
|
||||||
|
LOG(ERROR) << "Failed to set USB config to " << usb_config;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ret = fastboot ? StartFastboot(device, args) : start_recovery(device, args);
|
||||||
|
|
||||||
|
if (ret == Device::KEY_INTERRUPTED) {
|
||||||
|
ret = action.exchange(ret);
|
||||||
|
if (ret == Device::NO_ACTION) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch (ret) {
|
||||||
|
case Device::SHUTDOWN:
|
||||||
|
ui->Print("Shutting down...\n");
|
||||||
|
android::base::SetProperty(ANDROID_RB_PROPERTY, "shutdown,");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Device::REBOOT_BOOTLOADER:
|
||||||
|
ui->Print("Rebooting to bootloader...\n");
|
||||||
|
android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,bootloader");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Device::ENTER_FASTBOOT:
|
||||||
|
LOG(INFO) << "Entering fastboot";
|
||||||
|
fastboot = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Device::ENTER_RECOVERY:
|
||||||
|
LOG(INFO) << "Entering recovery";
|
||||||
|
fastboot = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ui->Print("Rebooting...\n");
|
||||||
|
reboot("reboot,");
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Should be unreachable.
|
// Should be unreachable.
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue