Merge "Add EthernetDevice to manage ethernet connection." am: 78c41b6414

Change-Id: Ia776436b4f62db1e6c21125ca2d064a500f4ed06
This commit is contained in:
Treehugger Robot 2020-05-18 17:26:15 +00:00 committed by Automerger Merge Worker
commit f9712d6d40
8 changed files with 244 additions and 3 deletions

View file

@ -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)

View file

@ -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,

View file

@ -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";

View file

@ -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"],
}

View file

@ -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*>(&current_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);
}

View file

@ -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;
}

View file

@ -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

View file

@ -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