diff options
author | Hongguang Chen <hgchen@google.com> | 2020-04-22 05:58:04 +0200 |
---|---|---|
committer | Hongguang Chen <hgchen@google.com> | 2020-05-19 21:11:13 +0200 |
commit | 4d0df88d88db381422ee912f2609258d72eca4cf (patch) | |
tree | 959cfb41f4a1a056fc8d08f6f301e43ca3e9e9da | |
parent | Merge changes from topic "nonab_on_vab_r" into rvc-dev (diff) | |
download | android_bootable_recovery-4d0df88d88db381422ee912f2609258d72eca4cf.tar android_bootable_recovery-4d0df88d88db381422ee912f2609258d72eca4cf.tar.gz android_bootable_recovery-4d0df88d88db381422ee912f2609258d72eca4cf.tar.bz2 android_bootable_recovery-4d0df88d88db381422ee912f2609258d72eca4cf.tar.lz android_bootable_recovery-4d0df88d88db381422ee912f2609258d72eca4cf.tar.xz android_bootable_recovery-4d0df88d88db381422ee912f2609258d72eca4cf.tar.zst android_bootable_recovery-4d0df88d88db381422ee912f2609258d72eca4cf.zip |
-rw-r--r-- | Android.mk | 6 | ||||
-rw-r--r-- | fastboot/fastboot.cpp | 1 | ||||
-rw-r--r-- | recovery_main.cpp | 5 | ||||
-rw-r--r-- | recovery_ui/Android.bp | 21 | ||||
-rw-r--r-- | recovery_ui/ethernet_device.cpp | 136 | ||||
-rw-r--r-- | recovery_ui/ethernet_ui.cpp | 32 | ||||
-rw-r--r-- | recovery_ui/include/recovery_ui/device.h | 12 | ||||
-rw-r--r-- | recovery_ui/include/recovery_ui/ethernet_ui.h | 34 |
8 files changed, 244 insertions, 3 deletions
diff --git a/Android.mk b/Android.mk index 9806d1091..9f691531c 100644 --- a/Android.mk +++ b/Android.mk @@ -18,9 +18,9 @@ LOCAL_PATH := $(call my-dir) RECOVERY_API_VERSION := 3 RECOVERY_FSTAB_VERSION := 2 -# TARGET_RECOVERY_UI_LIB should be one of librecovery_ui_{default,wear,vr} or a device-specific -# module that defines make_device() and the exact RecoveryUI class for the target. It defaults to -# librecovery_ui_default, which uses ScreenRecoveryUI. +# TARGET_RECOVERY_UI_LIB should be one of librecovery_ui_{default,wear,vr,ethernet} or a +# device-specific module that defines make_device() and the exact RecoveryUI class for the +# target. It defaults to librecovery_ui_default, which uses ScreenRecoveryUI. TARGET_RECOVERY_UI_LIB ?= librecovery_ui_default # librecovery_ui_ext (shared library) diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp index 202334997..a0930087c 100644 --- a/fastboot/fastboot.cpp +++ b/fastboot/fastboot.cpp @@ -52,6 +52,7 @@ Device::BuiltinAction StartFastboot(Device* device, const std::vector<std::strin ui->ResetKeyInterruptStatus(); ui->SetTitle(title_lines); ui->ShowText(true); + device->StartFastboot(); // 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, diff --git a/recovery_main.cpp b/recovery_main.cpp index 30a1fc0a4..80cba61d3 100644 --- a/recovery_main.cpp +++ b/recovery_main.cpp @@ -471,6 +471,11 @@ int main(int argc, char** argv) { std::string usb_config = fastboot ? "fastboot" : IsRoDebuggable() || IsDeviceUnlocked() ? "adb" : "none"; std::string usb_state = android::base::GetProperty("sys.usb.state", "none"); + if (fastboot) { + device->PreFastboot(); + } else { + device->PreRecovery(); + } if (usb_config != usb_state) { if (!SetUsbConfig("none")) { LOG(ERROR) << "Failed to clear USB config"; diff --git a/recovery_ui/Android.bp b/recovery_ui/Android.bp index 149ef8acc..9dfee5fd5 100644 --- a/recovery_ui/Android.bp +++ b/recovery_ui/Android.bp @@ -22,6 +22,7 @@ cc_library { srcs: [ "device.cpp", + "ethernet_ui.cpp", "screen_ui.cpp", "stub_ui.cpp", "ui.cpp", @@ -90,3 +91,23 @@ cc_library_static { export_include_dirs: ["include"], } + +// The default device that uses EthernetRecoveryUI. +cc_library_static { + name: "librecovery_ui_ethernet", + recovery_available: true, + + defaults: [ + "recovery_defaults", + ], + + srcs: [ + "ethernet_device.cpp", + ], + + shared_libs: [ + "libbase", + ], + + export_include_dirs: ["include"], +} diff --git a/recovery_ui/ethernet_device.cpp b/recovery_ui/ethernet_device.cpp new file mode 100644 index 000000000..39ec65dc4 --- /dev/null +++ b/recovery_ui/ethernet_device.cpp @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2020 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 <android-base/logging.h> +#include <android-base/properties.h> +#include <android-base/strings.h> +#include <android-base/unique_fd.h> +#include <arpa/inet.h> +#include <ifaddrs.h> +#include <linux/if.h> +#include <string.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <sys/types.h> + +#include "recovery_ui/device.h" +#include "recovery_ui/ethernet_ui.h" + +class EthernetDevice : public Device { + public: + explicit EthernetDevice(EthernetRecoveryUI* ui); + + void PreRecovery() override; + void PreFastboot() override; + + private: + int SetInterfaceFlags(const unsigned set, const unsigned clr); + void SetTitleIPv6LinkLocalAddress(const bool interface_up); + + android::base::unique_fd ctl_sock_; + static const std::string interface; +}; + +const std::string EthernetDevice::interface = "eth0"; + +EthernetDevice::EthernetDevice(EthernetRecoveryUI* ui) + : Device(ui), ctl_sock_(socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0)) { + if (ctl_sock_ < 0) { + PLOG(ERROR) << "Failed to open socket"; + } +} + +void EthernetDevice::PreRecovery() { + SetInterfaceFlags(0, IFF_UP); + SetTitleIPv6LinkLocalAddress(false); +} + +void EthernetDevice::PreFastboot() { + android::base::SetProperty("fastbootd.protocol", "tcp"); + + if (SetInterfaceFlags(IFF_UP, 0) < 0) { + LOG(ERROR) << "Failed to bring up interface"; + return; + } + + SetTitleIPv6LinkLocalAddress(true); +} + +int EthernetDevice::SetInterfaceFlags(const unsigned set, const unsigned clr) { + struct ifreq ifr; + + if (ctl_sock_ < 0) { + return -1; + } + + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_name, interface.c_str(), IFNAMSIZ); + ifr.ifr_name[IFNAMSIZ - 1] = 0; + + if (ioctl(ctl_sock_, SIOCGIFFLAGS, &ifr) < 0) { + PLOG(ERROR) << "Failed to get interface active flags"; + return -1; + } + ifr.ifr_flags = (ifr.ifr_flags & (~clr)) | set; + + if (ioctl(ctl_sock_, SIOCSIFFLAGS, &ifr) < 0) { + PLOG(ERROR) << "Failed to set interface active flags"; + return -1; + } + + return 0; +} + +void EthernetDevice::SetTitleIPv6LinkLocalAddress(const bool interface_up) { + auto recovery_ui = reinterpret_cast<EthernetRecoveryUI*>(GetUI()); + if (!interface_up) { + recovery_ui->SetIPv6LinkLocalAddress(); + return; + } + + struct ifaddrs* ifaddr; + if (getifaddrs(&ifaddr) == -1) { + PLOG(ERROR) << "Failed to get interface addresses"; + recovery_ui->SetIPv6LinkLocalAddress(); + return; + } + + std::unique_ptr<struct ifaddrs, decltype(&freeifaddrs)> guard{ ifaddr, freeifaddrs }; + for (struct ifaddrs* ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) { + if (ifa->ifa_addr->sa_family != AF_INET6 || interface != ifa->ifa_name) { + continue; + } + + auto current_addr = reinterpret_cast<struct sockaddr_in6*>(ifa->ifa_addr); + if (!IN6_IS_ADDR_LINKLOCAL(&(current_addr->sin6_addr))) { + continue; + } + + char addrstr[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET6, reinterpret_cast<const void*>(¤t_addr->sin6_addr), addrstr, + INET6_ADDRSTRLEN); + LOG(INFO) << "Our IPv6 link-local address is " << addrstr; + recovery_ui->SetIPv6LinkLocalAddress(addrstr); + return; + } + + recovery_ui->SetIPv6LinkLocalAddress(); +} + +// ----------------------------------------------------------------------------------------- +Device* make_device() { + return new EthernetDevice(new EthernetRecoveryUI); +} diff --git a/recovery_ui/ethernet_ui.cpp b/recovery_ui/ethernet_ui.cpp new file mode 100644 index 000000000..535d407f9 --- /dev/null +++ b/recovery_ui/ethernet_ui.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2020 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 "recovery_ui/ethernet_ui.h" + +#include <android-base/logging.h> + +void EthernetRecoveryUI::SetTitle(const std::vector<std::string>& lines) { + ScreenRecoveryUI::SetTitle(lines); + + // Append IP address, if any + if (!address_.empty()) { + title_lines_.push_back("IPv6 link-local address - " + address_); + } +} + +void EthernetRecoveryUI::SetIPv6LinkLocalAddress(const std::string& address) { + address_ = address; +} diff --git a/recovery_ui/include/recovery_ui/device.h b/recovery_ui/include/recovery_ui/device.h index f4f993638..76166f09d 100644 --- a/recovery_ui/include/recovery_ui/device.h +++ b/recovery_ui/include/recovery_ui/device.h @@ -79,10 +79,22 @@ class Device { ui_.reset(ui); } + // Called before recovery mode started up, to perform whatever device-specific recovery mode + // preparation as needed. + virtual void PreRecovery() {} + // Called when recovery starts up (after the UI has been obtained and initialized and after the // arguments have been parsed, but before anything else). virtual void StartRecovery() {} + // Called before fastboot mode is started up, to perform whatever device-specific fastboot mode + // preparation as needed. + virtual void PreFastboot() {} + + // Called when fastboot starts up (after the UI has been obtained and initialized and after the + // arguments have been parsed, but before anything else). + virtual void StartFastboot() {} + // Called from the main thread when recovery is at the main menu and waiting for input, and a key // is pressed. (Note that "at" the main menu does not necessarily mean the menu is visible; // recovery will be at the main menu with it invisible after an unsuccessful operation, such as diff --git a/recovery_ui/include/recovery_ui/ethernet_ui.h b/recovery_ui/include/recovery_ui/ethernet_ui.h new file mode 100644 index 000000000..f40c73f69 --- /dev/null +++ b/recovery_ui/include/recovery_ui/ethernet_ui.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2020 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. + */ + +#ifndef RECOVERY_ETHERNET_UI_H +#define RECOVERY_ETHERNET_UI_H + +#include "screen_ui.h" + +class EthernetRecoveryUI : public ScreenRecoveryUI { + public: + EthernetRecoveryUI() {} + void SetTitle(const std::vector<std::string>& lines) override; + + // For EthernetDevice + void SetIPv6LinkLocalAddress(const std::string& address = ""); + + private: + std::string address_; +}; + +#endif // RECOVERY_ETHERNET_UI_H |