Merge "logcat: add 'device shut down' to error message upon EOF"
diff --git a/adb/adb_mdns.h b/adb/adb_mdns.h
index 2e544d7..6b37355 100644
--- a/adb/adb_mdns.h
+++ b/adb/adb_mdns.h
@@ -17,6 +17,72 @@
#ifndef _ADB_MDNS_H_
#define _ADB_MDNS_H_
+#include <android-base/macros.h>
+
const char* kADBServiceType = "_adb._tcp";
+const char* kADBSecurePairingServiceType = "_adb_secure_pairing._tcp";
+const char* kADBSecureConnectServiceType = "_adb_secure_connect._tcp";
+
+const int kADBTransportServiceRefIndex = 0;
+const int kADBSecurePairingServiceRefIndex = 1;
+const int kADBSecureConnectServiceRefIndex = 2;
+
+// Each ADB Secure service advertises with a TXT record indicating the version
+// using a key/value pair per RFC 6763 (https://tools.ietf.org/html/rfc6763).
+//
+// The first key/value pair is always the version of the protocol.
+// There may be more key/value pairs added after.
+//
+// The version is purposely represented as the single letter "v" due to the
+// need to minimize DNS traffic. The version starts at 1. With each breaking
+// protocol change, the version is incremented by 1.
+//
+// Newer adb clients/daemons need to recognize and either reject
+// or be backward-compatible with older verseions if there is a mismatch.
+//
+// Relevant sections:
+//
+// """
+// 6.4. Rules for Keys in DNS-SD Key/Value Pairs
+//
+// The key MUST be at least one character. DNS-SD TXT record strings
+// beginning with an '=' character (i.e., the key is missing) MUST be
+// silently ignored.
+//
+// ...
+//
+// 6.5. Rules for Values in DNS-SD Key/Value Pairs
+//
+// If there is an '=' in a DNS-SD TXT record string, then everything
+// after the first '=' to the end of the string is the value. The value
+// can contain any eight-bit values including '='.
+// """
+
+#define ADB_SECURE_SERVICE_VERSION_TXT_RECORD(ver) ("v=" #ver)
+
+// Client/service versions are initially defined to be matching,
+// but may go out of sync as different clients and services
+// try to talk to each other.
+#define ADB_SECURE_SERVICE_VERSION 1
+#define ADB_SECURE_CLIENT_VERSION ADB_SECURE_SERVICE_VERSION
+
+const char* kADBSecurePairingServiceTxtRecord =
+ ADB_SECURE_SERVICE_VERSION_TXT_RECORD(ADB_SECURE_SERVICE_VERSION);
+const char* kADBSecureConnectServiceTxtRecord =
+ ADB_SECURE_SERVICE_VERSION_TXT_RECORD(ADB_SECURE_SERVICE_VERSION);
+
+const char* kADBDNSServices[] = {
+ kADBServiceType,
+ kADBSecurePairingServiceType,
+ kADBSecureConnectServiceType,
+};
+
+const char* kADBDNSServiceTxtRecords[] = {
+ nullptr,
+ kADBSecurePairingServiceTxtRecord,
+ kADBSecureConnectServiceTxtRecord,
+};
+
+const int kNumADBDNSServices = arraysize(kADBDNSServices);
#endif
diff --git a/adb/client/adb_client.h b/adb/client/adb_client.h
index ba53041..758fcab 100644
--- a/adb/client/adb_client.h
+++ b/adb/client/adb_client.h
@@ -16,6 +16,7 @@
#pragma once
+#include <functional>
#include <optional>
#include <string>
@@ -86,3 +87,16 @@
// Globally acccesible argv/envp, for the purpose of re-execing adb.
extern const char* _Nullable * _Nullable __adb_argv;
extern const char* _Nullable * _Nullable __adb_envp;
+
+// ADB Secure DNS service interface. Used to query what ADB Secure DNS services have been
+// resolved, and to run some kind of callback for each one.
+using adb_secure_foreach_service_callback = std::function<void(
+ const char* _Nonnull host_name, const char* _Nonnull ip_address, uint16_t port)>;
+
+// Queries pairing/connect services that have been discovered and resolved.
+// If |host_name| is not null, run |cb| only for services
+// matching |host_name|. Otherwise, run for all services.
+void adb_secure_foreach_pairing_service(const char* _Nullable host_name,
+ adb_secure_foreach_service_callback cb);
+void adb_secure_foreach_connect_service(const char* _Nullable host_name,
+ adb_secure_foreach_service_callback cb);
diff --git a/adb/client/transport_mdns.cpp b/adb/client/transport_mdns.cpp
index 1a34384..f5811a4 100644
--- a/adb/client/transport_mdns.cpp
+++ b/adb/client/transport_mdns.cpp
@@ -25,17 +25,33 @@
#endif
#include <thread>
+#include <vector>
#include <android-base/stringprintf.h>
#include <dns_sd.h>
+#include "adb_client.h"
#include "adb_mdns.h"
#include "adb_trace.h"
#include "fdevent/fdevent.h"
#include "sysdeps.h"
-static DNSServiceRef service_ref;
-static fdevent* service_ref_fde;
+static DNSServiceRef service_refs[kNumADBDNSServices];
+static fdevent* service_ref_fdes[kNumADBDNSServices];
+
+static int adb_DNSServiceIndexByName(const char* regType) {
+ for (int i = 0; i < kNumADBDNSServices; ++i) {
+ if (!strncmp(regType, kADBDNSServices[i], strlen(kADBDNSServices[i]))) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+static bool adb_DNSServiceShouldConnect(const char* regType) {
+ int index = adb_DNSServiceIndexByName(regType);
+ return index == kADBTransportServiceRefIndex;
+}
// Use adb_DNSServiceRefSockFD() instead of calling DNSServiceRefSockFD()
// directly so that the socket is put through the appropriate compatibility
@@ -94,10 +110,16 @@
public:
virtual ~ResolvedService() = default;
- ResolvedService(std::string name, uint32_t interfaceIndex,
- const char* hosttarget, uint16_t port) :
- name_(name),
- port_(port) {
+ ResolvedService(std::string serviceName, std::string regType, uint32_t interfaceIndex,
+ const char* hosttarget, uint16_t port, int version)
+ : serviceName_(serviceName),
+ regType_(regType),
+ hosttarget_(hosttarget),
+ port_(port),
+ sa_family_(0),
+ ip_addr_data_(NULL),
+ serviceVersion_(version) {
+ memset(ip_addr_, 0, sizeof(ip_addr_));
/* TODO: We should be able to get IPv6 support by adding
* kDNSServiceProtocol_IPv6 to the flags below. However, when we do
@@ -116,45 +138,135 @@
} else {
Initialize();
}
+
+ D("Client version: %d Service version: %d\n", clientVersion_, serviceVersion_);
}
void Connect(const sockaddr* address) {
- char ip_addr[INET6_ADDRSTRLEN];
- const void* ip_addr_data;
+ sa_family_ = address->sa_family;
const char* addr_format;
- if (address->sa_family == AF_INET) {
- ip_addr_data =
- &reinterpret_cast<const sockaddr_in*>(address)->sin_addr;
+ if (sa_family_ == AF_INET) {
+ ip_addr_data_ = &reinterpret_cast<const sockaddr_in*>(address)->sin_addr;
addr_format = "%s:%hu";
- } else if (address->sa_family == AF_INET6) {
- ip_addr_data =
- &reinterpret_cast<const sockaddr_in6*>(address)->sin6_addr;
+ } else if (sa_family_ == AF_INET6) {
+ ip_addr_data_ = &reinterpret_cast<const sockaddr_in6*>(address)->sin6_addr;
addr_format = "[%s]:%hu";
- } else { // Should be impossible
+ } else { // Should be impossible
D("mDNS resolved non-IP address.");
return;
}
// Winsock version requires the const cast Because Microsoft.
- if (!inet_ntop(address->sa_family, const_cast<void*>(ip_addr_data),
- ip_addr, INET6_ADDRSTRLEN)) {
+ if (!inet_ntop(sa_family_, const_cast<void*>(ip_addr_data_), ip_addr_, sizeof(ip_addr_))) {
D("Could not convert IP address to string.");
return;
}
- std::string response;
- connect_device(android::base::StringPrintf(addr_format, ip_addr, port_),
- &response);
- D("Connect to %s (%s:%hu) : %s", name_.c_str(), ip_addr, port_,
- response.c_str());
+ // adb secure service needs to do something different from just
+ // connecting here.
+ if (adb_DNSServiceShouldConnect(regType_.c_str())) {
+ std::string response;
+ connect_device(android::base::StringPrintf(addr_format, ip_addr_, port_), &response);
+ D("Connect to %s regtype %s (%s:%hu) : %s", serviceName_.c_str(), regType_.c_str(),
+ ip_addr_, port_, response.c_str());
+ } else {
+ D("Not immediately connecting to serviceName=[%s], regtype=[%s] ipaddr=(%s:%hu)",
+ serviceName_.c_str(), regType_.c_str(), ip_addr_, port_);
+ }
+
+ int adbSecureServiceType = serviceIndex();
+ switch (adbSecureServiceType) {
+ case kADBSecurePairingServiceRefIndex:
+ sAdbSecurePairingServices->push_back(this);
+ break;
+ case kADBSecureConnectServiceRefIndex:
+ sAdbSecureConnectServices->push_back(this);
+ break;
+ default:
+ break;
+ }
}
+ int serviceIndex() const { return adb_DNSServiceIndexByName(regType_.c_str()); }
+
+ std::string hostTarget() const { return hosttarget_; }
+
+ std::string ipAddress() const { return ip_addr_; }
+
+ uint16_t port() const { return port_; }
+
+ using ServiceRegistry = std::vector<ResolvedService*>;
+
+ static ServiceRegistry* sAdbSecurePairingServices;
+ static ServiceRegistry* sAdbSecureConnectServices;
+
+ static void initAdbSecure();
+
+ static void forEachService(const ServiceRegistry& services, const std::string& hostname,
+ adb_secure_foreach_service_callback cb);
+
private:
- std::string name_;
+ int clientVersion_ = ADB_SECURE_CLIENT_VERSION;
+ std::string serviceName_;
+ std::string regType_;
+ std::string hosttarget_;
const uint16_t port_;
+ int sa_family_;
+ const void* ip_addr_data_;
+ char ip_addr_[INET6_ADDRSTRLEN];
+ int serviceVersion_;
};
+// static
+std::vector<ResolvedService*>* ResolvedService::sAdbSecurePairingServices = NULL;
+
+// static
+std::vector<ResolvedService*>* ResolvedService::sAdbSecureConnectServices = NULL;
+
+// static
+void ResolvedService::initAdbSecure() {
+ if (!sAdbSecurePairingServices) {
+ sAdbSecurePairingServices = new ServiceRegistry;
+ }
+ if (!sAdbSecureConnectServices) {
+ sAdbSecureConnectServices = new ServiceRegistry;
+ }
+}
+
+// static
+void ResolvedService::forEachService(const ServiceRegistry& services,
+ const std::string& wanted_host,
+ adb_secure_foreach_service_callback cb) {
+ initAdbSecure();
+
+ for (auto service : services) {
+ auto hostname = service->hostTarget();
+ auto ip = service->ipAddress();
+ auto port = service->port();
+
+ if (wanted_host == "") {
+ cb(hostname.c_str(), ip.c_str(), port);
+ } else if (hostname == wanted_host) {
+ cb(hostname.c_str(), ip.c_str(), port);
+ }
+ }
+}
+
+// static
+void adb_secure_foreach_pairing_service(const char* host_name,
+ adb_secure_foreach_service_callback cb) {
+ ResolvedService::forEachService(*ResolvedService::sAdbSecurePairingServices,
+ host_name ? host_name : "", cb);
+}
+
+// static
+void adb_secure_foreach_connect_service(const char* host_name,
+ adb_secure_foreach_service_callback cb) {
+ ResolvedService::forEachService(*ResolvedService::sAdbSecureConnectServices,
+ host_name ? host_name : "", cb);
+}
+
static void DNSSD_API register_service_ip(DNSServiceRef /*sdRef*/,
DNSServiceFlags /*flags*/,
uint32_t /*interfaceIndex*/,
@@ -167,6 +279,12 @@
std::unique_ptr<ResolvedService> data(
reinterpret_cast<ResolvedService*>(context));
data->Connect(address);
+
+ // For ADB Secure services, keep those ResolvedService's around
+ // for later processing with secure connection establishment.
+ if (data->serviceIndex() != kADBTransportServiceRefIndex) {
+ data.release();
+ }
}
static void DNSSD_API register_resolved_mdns_service(DNSServiceRef sdRef,
@@ -182,18 +300,23 @@
class DiscoveredService : public AsyncServiceRef {
public:
- DiscoveredService(uint32_t interfaceIndex, const char* serviceName,
- const char* regtype, const char* domain)
- : serviceName_(serviceName) {
-
+ DiscoveredService(uint32_t interfaceIndex, const char* serviceName, const char* regtype,
+ const char* domain)
+ : serviceName_(serviceName), regType_(regtype) {
DNSServiceErrorType ret =
DNSServiceResolve(&sdRef_, 0, interfaceIndex, serviceName, regtype,
domain, register_resolved_mdns_service,
reinterpret_cast<void*>(this));
- if (ret != kDNSServiceErr_NoError) {
- D("Got %d from DNSServiceResolve.", ret);
- } else {
+ D("DNSServiceResolve for "
+ "interfaceIndex %u "
+ "serviceName %s "
+ "regtype %s "
+ "domain %s "
+ ": %d",
+ interfaceIndex, serviceName, regtype, domain, ret);
+
+ if (ret == kDNSServiceErr_NoError) {
Initialize();
}
}
@@ -202,20 +325,62 @@
return serviceName_.c_str();
}
+ const char* RegType() { return regType_.c_str(); }
+
private:
std::string serviceName_;
+ std::string regType_;
};
-static void DNSSD_API register_resolved_mdns_service(DNSServiceRef sdRef,
- DNSServiceFlags flags,
- uint32_t interfaceIndex,
- DNSServiceErrorType errorCode,
- const char* fullname,
- const char* hosttarget,
- uint16_t port,
- uint16_t /*txtLen*/,
- const unsigned char* /*txtRecord*/,
- void* context) {
+// Returns the version the device wanted to advertise,
+// or -1 if parsing fails.
+static int parse_version_from_txt_record(uint16_t txtLen, const unsigned char* txtRecord) {
+ if (!txtLen) return -1;
+ if (!txtRecord) return -1;
+
+ // https://tools.ietf.org/html/rfc6763
+ // """
+ // 6.1. General Format Rules for DNS TXT Records
+ //
+ // A DNS TXT record can be up to 65535 (0xFFFF) bytes long. The total
+ // length is indicated by the length given in the resource record header
+ // in the DNS message. There is no way to tell directly from the data
+ // alone how long it is (e.g., there is no length count at the start, or
+ // terminating NULL byte at the end).
+ // """
+
+ // Let's trust the TXT record's length byte
+ // Worst case, it wastes 255 bytes
+ std::vector<char> recordAsString(txtLen + 1, '\0');
+ char* str = recordAsString.data();
+
+ memcpy(str, txtRecord + 1 /* skip the length byte */, txtLen);
+
+ // Check if it's the version key
+ static const char* versionKey = "v=";
+ size_t versionKeyLen = strlen(versionKey);
+
+ if (strncmp(versionKey, str, versionKeyLen)) return -1;
+
+ auto valueStart = str + versionKeyLen;
+
+ long parsedNumber = strtol(valueStart, 0, 10);
+
+ // No valid conversion. Also, 0
+ // is not a valid version.
+ if (!parsedNumber) return -1;
+
+ // Outside bounds of long.
+ if (parsedNumber == LONG_MIN || parsedNumber == LONG_MAX) return -1;
+
+ // Possibly valid version
+ return static_cast<int>(parsedNumber);
+}
+
+static void DNSSD_API register_resolved_mdns_service(
+ DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode, const char* fullname, const char* hosttarget, uint16_t port,
+ uint16_t txtLen, const unsigned char* txtRecord, void* context) {
D("Resolved a service.");
std::unique_ptr<DiscoveredService> discovered(
reinterpret_cast<DiscoveredService*>(context));
@@ -225,10 +390,14 @@
return;
}
+ // TODO: Reject certain combinations of invalid or mismatched client and
+ // service versions here before creating anything.
+ // At the moment, there is nothing to reject, so accept everything
+ // as an optimistic default.
+ auto serviceVersion = parse_version_from_txt_record(txtLen, txtRecord);
- auto resolved =
- new ResolvedService(discovered->ServiceName(),
- interfaceIndex, hosttarget, ntohs(port));
+ auto resolved = new ResolvedService(discovered->ServiceName(), discovered->RegType(),
+ interfaceIndex, hosttarget, ntohs(port), serviceVersion);
if (! resolved->Initialized()) {
delete resolved;
@@ -239,19 +408,18 @@
}
}
-static void DNSSD_API register_mdns_transport(DNSServiceRef sdRef,
- DNSServiceFlags flags,
- uint32_t interfaceIndex,
- DNSServiceErrorType errorCode,
- const char* serviceName,
- const char* regtype,
- const char* domain,
- void* /*context*/) {
+static void DNSSD_API on_service_browsed(DNSServiceRef sdRef, DNSServiceFlags flags,
+ uint32_t interfaceIndex, DNSServiceErrorType errorCode,
+ const char* serviceName, const char* regtype,
+ const char* domain, void* /*context*/) {
D("Registering a transport.");
if (errorCode != kDNSServiceErr_NoError) {
D("Got error %d during mDNS browse.", errorCode);
DNSServiceRefDeallocate(sdRef);
- fdevent_destroy(service_ref_fde);
+ int serviceIndex = adb_DNSServiceIndexByName(regtype);
+ if (serviceIndex != -1) {
+ fdevent_destroy(service_ref_fdes[serviceIndex]);
+ }
return;
}
@@ -262,21 +430,27 @@
}
void init_mdns_transport_discovery_thread(void) {
- DNSServiceErrorType errorCode = DNSServiceBrowse(&service_ref, 0, 0, kADBServiceType, nullptr,
- register_mdns_transport, nullptr);
+ int errorCodes[kNumADBDNSServices];
- if (errorCode != kDNSServiceErr_NoError) {
- D("Got %d initiating mDNS browse.", errorCode);
- return;
+ for (int i = 0; i < kNumADBDNSServices; ++i) {
+ errorCodes[i] = DNSServiceBrowse(&service_refs[i], 0, 0, kADBDNSServices[i], nullptr,
+ on_service_browsed, nullptr);
+
+ if (errorCodes[i] != kDNSServiceErr_NoError) {
+ D("Got %d browsing for mDNS service %s.", errorCodes[i], kADBDNSServices[i]);
+ }
+
+ if (errorCodes[i] == kDNSServiceErr_NoError) {
+ fdevent_run_on_main_thread([i]() {
+ service_ref_fdes[i] = fdevent_create(adb_DNSServiceRefSockFD(service_refs[i]),
+ pump_service_ref, &service_refs[i]);
+ fdevent_set(service_ref_fdes[i], FDE_READ);
+ });
+ }
}
-
- fdevent_run_on_main_thread([]() {
- service_ref_fde =
- fdevent_create(adb_DNSServiceRefSockFD(service_ref), pump_service_ref, &service_ref);
- fdevent_set(service_ref_fde, FDE_READ);
- });
}
void init_mdns_transport_discovery(void) {
+ ResolvedService::initAdbSecure();
std::thread(init_mdns_transport_discovery_thread).detach();
}
diff --git a/adb/daemon/mdns.cpp b/adb/daemon/mdns.cpp
index 3530f48..fa98340 100644
--- a/adb/daemon/mdns.cpp
+++ b/adb/daemon/mdns.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include "mdns.h"
#include "adb_mdns.h"
#include "sysdeps.h"
@@ -32,8 +33,8 @@
static std::mutex& mdns_lock = *new std::mutex();
static int port;
-static DNSServiceRef mdns_ref;
-static bool mdns_registered = false;
+static DNSServiceRef mdns_refs[kNumADBDNSServices];
+static bool mdns_registered[kNumADBDNSServices];
static void start_mdns() {
if (android::base::GetProperty("init.svc.mdnsd", "") == "running") {
@@ -60,34 +61,86 @@
}
}
-static void setup_mdns_thread() {
- start_mdns();
+static void register_mdns_service(int index, int port) {
std::lock_guard<std::mutex> lock(mdns_lock);
std::string hostname = "adb-";
hostname += android::base::GetProperty("ro.serialno", "unidentified");
- auto error = DNSServiceRegister(&mdns_ref, 0, 0, hostname.c_str(),
- kADBServiceType, nullptr, nullptr,
- htobe16((uint16_t)port), 0, nullptr,
- mdns_callback, nullptr);
+ // https://tools.ietf.org/html/rfc6763
+ // """
+ // The format of the data within a DNS TXT record is one or more
+ // strings, packed together in memory without any intervening gaps or
+ // padding bytes for word alignment.
+ //
+ // The format of each constituent string within the DNS TXT record is a
+ // single length byte, followed by 0-255 bytes of text data.
+ // """
+ //
+ // Therefore:
+ // 1. Begin with the string length
+ // 2. No null termination
+
+ std::vector<char> txtRecord;
+
+ if (kADBDNSServiceTxtRecords[index]) {
+ size_t txtRecordStringLength = strlen(kADBDNSServiceTxtRecords[index]);
+
+ txtRecord.resize(1 + // length byte
+ txtRecordStringLength // string bytes
+ );
+
+ txtRecord[0] = (char)txtRecordStringLength;
+ memcpy(txtRecord.data() + 1, kADBDNSServiceTxtRecords[index], txtRecordStringLength);
+ }
+
+ auto error = DNSServiceRegister(
+ &mdns_refs[index], 0, 0, hostname.c_str(), kADBDNSServices[index], nullptr, nullptr,
+ htobe16((uint16_t)port), (uint16_t)txtRecord.size(),
+ txtRecord.empty() ? nullptr : txtRecord.data(), mdns_callback, nullptr);
if (error != kDNSServiceErr_NoError) {
- LOG(ERROR) << "Could not register mDNS service (" << error << ").";
- return;
+ LOG(ERROR) << "Could not register mDNS service " << kADBDNSServices[index] << ", error ("
+ << error << ").";
+ mdns_registered[index] = false;
}
- mdns_registered = true;
+ mdns_registered[index] = true;
+
+ LOG(INFO) << "adbd mDNS service " << kADBDNSServices[index]
+ << " registered: " << mdns_registered[index];
}
-static void teardown_mdns() {
+static void unregister_mdns_service(int index) {
std::lock_guard<std::mutex> lock(mdns_lock);
- if (mdns_registered) {
- DNSServiceRefDeallocate(mdns_ref);
+ if (mdns_registered[index]) {
+ DNSServiceRefDeallocate(mdns_refs[index]);
}
}
+static void register_base_mdns_transport() {
+ register_mdns_service(kADBTransportServiceRefIndex, port);
+}
+
+static void setup_mdns_thread() {
+ start_mdns();
+
+ // We will now only set up the normal transport mDNS service
+ // instead of registering all the adb secure mDNS services
+ // in the beginning. This is to provide more privacy/security.
+ register_base_mdns_transport();
+}
+
+// This also tears down any adb secure mDNS services, if they exist.
+static void teardown_mdns() {
+ for (int i = 0; i < kNumADBDNSServices; ++i) {
+ unregister_mdns_service(i);
+ }
+}
+
+// Public interface/////////////////////////////////////////////////////////////
+
void setup_mdns(int port_in) {
port = port_in;
std::thread(setup_mdns_thread).detach();
@@ -95,3 +148,33 @@
// TODO: Make this more robust against a hard kill.
atexit(teardown_mdns);
}
+
+void register_adb_secure_pairing_service(int port) {
+ std::thread([port]() {
+ register_mdns_service(kADBSecurePairingServiceRefIndex, port);
+ }).detach();
+}
+
+void unregister_adb_secure_pairing_service() {
+ std::thread([]() { unregister_mdns_service(kADBSecurePairingServiceRefIndex); }).detach();
+}
+
+bool is_adb_secure_pairing_service_registered() {
+ std::lock_guard<std::mutex> lock(mdns_lock);
+ return mdns_registered[kADBSecurePairingServiceRefIndex];
+}
+
+void register_adb_secure_connect_service(int port) {
+ std::thread([port]() {
+ register_mdns_service(kADBSecureConnectServiceRefIndex, port);
+ }).detach();
+}
+
+void unregister_adb_secure_connect_service() {
+ std::thread([]() { unregister_mdns_service(kADBSecureConnectServiceRefIndex); }).detach();
+}
+
+bool is_adb_secure_connect_service_registered() {
+ std::lock_guard<std::mutex> lock(mdns_lock);
+ return mdns_registered[kADBSecureConnectServiceRefIndex];
+}
diff --git a/adb/daemon/mdns.h b/adb/daemon/mdns.h
index 4c6b1ca..a18093b 100644
--- a/adb/daemon/mdns.h
+++ b/adb/daemon/mdns.h
@@ -19,4 +19,12 @@
void setup_mdns(int port);
+void register_adb_secure_pairing_service(int port);
+void unregister_adb_secure_pairing_service(int port);
+bool is_adb_secure_pairing_service_registered();
+
+void register_adb_secure_connect_service(int port);
+void unregister_adb_secure_connect_service(int port);
+bool is_adb_secure_connect_service_registered();
+
#endif // _DAEMON_MDNS_H_
diff --git a/base/include/android-base/result.h b/base/include/android-base/result.h
index 4a59552..5e65876 100644
--- a/base/include/android-base/result.h
+++ b/base/include/android-base/result.h
@@ -191,11 +191,6 @@
return ErrorCode(code, args...);
}
-// TODO(tomcherry): Remove this once we've removed all `using android::base::Errorf` and `using
-// android::base::ErrnoErrorf` lines.
-enum Errorf {};
-enum ErrnoErrorf {};
-
template <typename T, typename... Args>
inline Error ErrorfImpl(const T&& fmt, const Args&... args) {
return Error(false, ErrorCode(0, args...), fmt::format(fmt, args...));
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index 9ffe5dd..a9c1676 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -870,6 +870,7 @@
const char system_reboot_reason_property[] = "sys.boot.reason";
const char last_reboot_reason_property[] = LAST_REBOOT_REASON_PROPERTY;
+const char last_reboot_reason_file[] = LAST_REBOOT_REASON_FILE;
const char last_last_reboot_reason_property[] = "sys.boot.reason.last";
constexpr size_t history_reboot_reason_size = 4;
const char history_reboot_reason_property[] = LAST_REBOOT_REASON_PROPERTY ".history";
@@ -1059,7 +1060,9 @@
if (isBluntRebootReason(ret)) {
// Content buffer no longer will have console data. Beware if more
// checks added below, that depend on parsing console content.
- content = android::base::GetProperty(last_reboot_reason_property, "");
+ if (!android::base::ReadFileToString(last_reboot_reason_file, &content)) {
+ content = android::base::GetProperty(last_reboot_reason_property, "");
+ }
transformReason(content);
// Anything in last is better than 'super-blunt' reboot or shutdown.
@@ -1233,7 +1236,10 @@
// Record the scrubbed system_boot_reason to the property
BootReasonAddToHistory(system_boot_reason);
// Shift last_reboot_reason_property to last_last_reboot_reason_property
- auto last_boot_reason = android::base::GetProperty(last_reboot_reason_property, "");
+ std::string last_boot_reason;
+ if (!android::base::ReadFileToString(last_reboot_reason_file, &last_boot_reason)) {
+ last_boot_reason = android::base::GetProperty(last_reboot_reason_property, "");
+ }
if (last_boot_reason.empty() || isKernelRebootReason(system_boot_reason)) {
last_boot_reason = system_boot_reason;
} else {
@@ -1241,6 +1247,7 @@
}
android::base::SetProperty(last_last_reboot_reason_property, last_boot_reason);
android::base::SetProperty(last_reboot_reason_property, "");
+ unlink(last_reboot_reason_file);
}
// Gets the boot time offset. This is useful when Android is running in a
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index b27126b..3a6eb2d 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -234,10 +234,11 @@
LINFO << "Running " << E2FSCK_BIN << " on " << realpath(blk_device);
if (should_force_check(*fs_stat)) {
ret = logwrap_fork_execvp(ARRAY_SIZE(e2fsck_forced_argv), e2fsck_forced_argv,
- &status, false, LOG_KLOG | LOG_FILE, true, FSCK_LOG_FILE);
+ &status, false, LOG_KLOG | LOG_FILE, false,
+ FSCK_LOG_FILE);
} else {
ret = logwrap_fork_execvp(ARRAY_SIZE(e2fsck_argv), e2fsck_argv, &status, false,
- LOG_KLOG | LOG_FILE, true, FSCK_LOG_FILE);
+ LOG_KLOG | LOG_FILE, false, FSCK_LOG_FILE);
}
if (ret < 0) {
@@ -256,11 +257,11 @@
if (should_force_check(*fs_stat)) {
LINFO << "Running " << F2FS_FSCK_BIN << " -f " << realpath(blk_device);
ret = logwrap_fork_execvp(ARRAY_SIZE(f2fs_fsck_forced_argv), f2fs_fsck_forced_argv,
- &status, false, LOG_KLOG | LOG_FILE, true, FSCK_LOG_FILE);
+ &status, false, LOG_KLOG | LOG_FILE, false, FSCK_LOG_FILE);
} else {
LINFO << "Running " << F2FS_FSCK_BIN << " -a " << realpath(blk_device);
ret = logwrap_fork_execvp(ARRAY_SIZE(f2fs_fsck_argv), f2fs_fsck_argv, &status, false,
- LOG_KLOG | LOG_FILE, true, FSCK_LOG_FILE);
+ LOG_KLOG | LOG_FILE, false, FSCK_LOG_FILE);
}
if (ret < 0) {
/* No need to check for error in fork, we can't really handle it now */
@@ -338,7 +339,7 @@
static bool run_tune2fs(const char* argv[], int argc) {
int ret;
- ret = logwrap_fork_execvp(argc, argv, nullptr, false, LOG_KLOG, true, nullptr);
+ ret = logwrap_fork_execvp(argc, argv, nullptr, false, LOG_KLOG, false, nullptr);
return ret == 0;
}
diff --git a/fs_mgr/fs_mgr_format.cpp b/fs_mgr/fs_mgr_format.cpp
index a8c2cc1..5aefb7e 100644
--- a/fs_mgr/fs_mgr_format.cpp
+++ b/fs_mgr/fs_mgr_format.cpp
@@ -86,8 +86,8 @@
mke2fs_args.push_back(fs_blkdev.c_str());
mke2fs_args.push_back(size_str.c_str());
- rc = logwrap_fork_execvp(mke2fs_args.size(), mke2fs_args.data(), nullptr, false, LOG_KLOG, true,
- nullptr);
+ rc = logwrap_fork_execvp(mke2fs_args.size(), mke2fs_args.data(), nullptr, false, LOG_KLOG,
+ false, nullptr);
if (rc) {
LERROR << "mke2fs returned " << rc;
return rc;
@@ -97,7 +97,7 @@
"/system/bin/e2fsdroid", "-e", "-a", fs_mnt_point.c_str(), fs_blkdev.c_str(), nullptr};
rc = logwrap_fork_execvp(arraysize(e2fsdroid_args), e2fsdroid_args, nullptr, false, LOG_KLOG,
- true, nullptr);
+ false, nullptr);
if (rc) {
LERROR << "e2fsdroid returned " << rc;
}
@@ -135,7 +135,7 @@
args.push_back(fs_blkdev.c_str());
args.push_back(size_str.c_str());
- return logwrap_fork_execvp(args.size(), args.data(), nullptr, false, LOG_KLOG, true, nullptr);
+ return logwrap_fork_execvp(args.size(), args.data(), nullptr, false, LOG_KLOG, false, nullptr);
}
int fs_mgr_do_format(const FstabEntry& entry, bool crypt_footer) {
diff --git a/fs_mgr/fs_mgr_remount.cpp b/fs_mgr/fs_mgr_remount.cpp
index 93bba68..24cbad7 100644
--- a/fs_mgr/fs_mgr_remount.cpp
+++ b/fs_mgr/fs_mgr_remount.cpp
@@ -80,9 +80,13 @@
return &(*it);
}
+auto verbose = false;
+
void MyLogger(android::base::LogId id, android::base::LogSeverity severity, const char* tag,
const char* file, unsigned int line, const char* message) {
- fprintf(stderr, "%s\n", message);
+ if (verbose || severity == android::base::ERROR || message[0] != '[') {
+ fprintf(stderr, "%s\n", message);
+ }
static auto logd = android::base::LogdLogger();
logd(id, severity, tag, file, line, message);
}
@@ -131,10 +135,14 @@
{"fstab", required_argument, nullptr, 'T'},
{"help", no_argument, nullptr, 'h'},
{"reboot", no_argument, nullptr, 'R'},
+ {"verbose", no_argument, nullptr, 'v'},
{0, 0, nullptr, 0},
};
- for (int opt; (opt = ::getopt_long(argc, argv, "hRT:", longopts, nullptr)) != -1;) {
+ for (int opt; (opt = ::getopt_long(argc, argv, "hRT:v", longopts, nullptr)) != -1;) {
switch (opt) {
+ case 'h':
+ usage(SUCCESS);
+ break;
case 'R':
can_reboot = true;
break;
@@ -145,13 +153,13 @@
}
fstab_file = optarg;
break;
+ case 'v':
+ verbose = true;
+ break;
default:
LOG(ERROR) << "Bad Argument -" << char(opt);
usage(BADARG);
break;
- case 'h':
- usage(SUCCESS);
- break;
}
}
diff --git a/fs_mgr/libsnapshot/Android.bp b/fs_mgr/libsnapshot/Android.bp
index adfee1d..d274ba4 100644
--- a/fs_mgr/libsnapshot/Android.bp
+++ b/fs_mgr/libsnapshot/Android.bp
@@ -72,6 +72,7 @@
"android/snapshot/snapshot.proto",
"device_info.cpp",
"snapshot.cpp",
+ "snapshot_stats.cpp",
"snapshot_metadata_updater.cpp",
"partition_cow_creator.cpp",
"return.cpp",
diff --git a/fs_mgr/libsnapshot/android/snapshot/snapshot.proto b/fs_mgr/libsnapshot/android/snapshot/snapshot.proto
index a3a518d..2ac0c44 100644
--- a/fs_mgr/libsnapshot/android/snapshot/snapshot.proto
+++ b/fs_mgr/libsnapshot/android/snapshot/snapshot.proto
@@ -131,3 +131,13 @@
// Sectors allocated for metadata in all the snapshot devices.
uint64 metadata_sectors = 4;
}
+
+// Next: 2
+message SnapshotMergeReport {
+ // Status of the update after the merge attempts.
+ UpdateState state = 1;
+
+ // Number of reboots that occurred after issuing and before completeing the
+ // merge of all the snapshot devices.
+ int32 resume_count = 2;
+}
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
index ed92dd7..b440c71 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
@@ -91,6 +91,8 @@
using MergeStatus = android::hardware::boot::V1_1::MergeStatus;
using FiemapStatus = android::fiemap::FiemapStatus;
+ friend class SnapshotMergeStats;
+
public:
// Dependency injection for testing.
class IDeviceInfo {
@@ -177,7 +179,7 @@
// - Unverified if called on the source slot
// - MergeCompleted if merge is completed
// - other states indicating an error has occurred
- UpdateState InitiateMergeAndWait();
+ UpdateState InitiateMergeAndWait(SnapshotMergeReport* report = nullptr);
// Wait for the merge if rebooted into the new slot. Does NOT initiate a
// merge. If the merge has not been initiated (but should be), wait.
@@ -395,6 +397,10 @@
bool WriteSnapshotUpdateStatus(LockedFile* file, const SnapshotUpdateStatus& status);
std::string GetStateFilePath() const;
+ // Interact with /metadata/ota/merge_state.
+ // This file contains information related to the snapshot merge process.
+ std::string GetMergeStateFilePath() const;
+
// Helpers for merging.
bool SwitchSnapshotToMerge(LockedFile* lock, const std::string& name);
bool RewriteSnapshotDeviceTable(const std::string& dm_name);
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index ba53615..2fe06fb 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -46,6 +46,7 @@
#include "device_info.h"
#include "partition_cow_creator.h"
#include "snapshot_metadata_updater.h"
+#include "snapshot_stats.h"
#include "utility.h"
namespace android {
@@ -1739,6 +1740,10 @@
return metadata_dir_ + "/state"s;
}
+std::string SnapshotManager::GetMergeStateFilePath() const {
+ return metadata_dir_ + "/merge_state"s;
+}
+
std::string SnapshotManager::GetLockPath() const {
return metadata_dir_;
}
@@ -2383,7 +2388,7 @@
return AutoUnmountDevice::New(device_->GetMetadataDir());
}
-UpdateState SnapshotManager::InitiateMergeAndWait() {
+UpdateState SnapshotManager::InitiateMergeAndWait(SnapshotMergeReport* stats_report) {
{
auto lock = LockExclusive();
// Sync update state from file with bootloader.
@@ -2393,6 +2398,8 @@
}
}
+ SnapshotMergeStats merge_stats(*this);
+
unsigned int last_progress = 0;
auto callback = [&]() -> void {
double progress;
@@ -2405,7 +2412,9 @@
LOG(INFO) << "Waiting for any previous merge request to complete. "
<< "This can take up to several minutes.";
+ merge_stats.Resume();
auto state = ProcessUpdateState(callback);
+ merge_stats.set_state(state);
if (state == UpdateState::None) {
LOG(INFO) << "Can't find any snapshot to merge.";
return state;
@@ -2415,6 +2424,11 @@
LOG(INFO) << "Cannot merge until device reboots.";
return state;
}
+
+ // This is the first snapshot merge that is requested after OTA. We can
+ // initialize the merge duration statistics.
+ merge_stats.Start();
+
if (!InitiateMerge()) {
LOG(ERROR) << "Failed to initiate merge.";
return state;
@@ -2423,9 +2437,13 @@
LOG(INFO) << "Waiting for merge to complete. This can take up to several minutes.";
last_progress = 0;
state = ProcessUpdateState(callback);
+ merge_stats.set_state(state);
}
LOG(INFO) << "Merge finished with state \"" << state << "\".";
+ if (stats_report) {
+ *stats_report = merge_stats.GetReport();
+ }
return state;
}
diff --git a/fs_mgr/libsnapshot/snapshot_stats.cpp b/fs_mgr/libsnapshot/snapshot_stats.cpp
new file mode 100644
index 0000000..c48509e
--- /dev/null
+++ b/fs_mgr/libsnapshot/snapshot_stats.cpp
@@ -0,0 +1,80 @@
+// 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 "snapshot_stats.h"
+
+#include <sstream>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include "utility.h"
+
+namespace android {
+namespace snapshot {
+
+SnapshotMergeStats::SnapshotMergeStats(SnapshotManager& parent) : parent_(parent) {
+ init_time_ = std::chrono::steady_clock::now();
+}
+
+SnapshotMergeStats::~SnapshotMergeStats() {
+ std::string error;
+ auto file_path = parent_.GetMergeStateFilePath();
+ if (!android::base::RemoveFileIfExists(file_path, &error)) {
+ LOG(ERROR) << "Failed to remove merge statistics file " << file_path << ": " << error;
+ return;
+ }
+}
+
+void SnapshotMergeStats::Start() {
+ SnapshotMergeReport report;
+ report.set_resume_count(0);
+ report.set_state(UpdateState::None);
+
+ std::string contents;
+ if (!report.SerializeToString(&contents)) {
+ LOG(ERROR) << "Unable to serialize SnapshotMergeStats.";
+ return;
+ }
+ auto file_path = parent_.GetMergeStateFilePath();
+ if (!WriteStringToFileAtomic(contents, file_path)) {
+ PLOG(ERROR) << "Could not write to merge statistics file";
+ return;
+ }
+}
+
+void SnapshotMergeStats::Resume() {
+ std::string contents;
+ if (!android::base::ReadFileToString(parent_.GetMergeStateFilePath(), &contents)) {
+ PLOG(INFO) << "Read merge statistics file failed";
+ return;
+ }
+
+ if (!report_.ParseFromString(contents)) {
+ LOG(ERROR) << "Unable to parse merge statistics file as SnapshotMergeReport";
+ return;
+ }
+
+ report_.set_resume_count(report_.resume_count() + 1);
+}
+
+void SnapshotMergeStats::set_state(android::snapshot::UpdateState state) {
+ report_.set_state(state);
+}
+
+SnapshotMergeReport SnapshotMergeStats::GetReport() {
+ return report_;
+}
+
+} // namespace snapshot
+} // namespace android
diff --git a/fs_mgr/libsnapshot/snapshot_stats.h b/fs_mgr/libsnapshot/snapshot_stats.h
new file mode 100644
index 0000000..1ca9156
--- /dev/null
+++ b/fs_mgr/libsnapshot/snapshot_stats.h
@@ -0,0 +1,42 @@
+// 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.
+
+#pragma once
+
+#include <chrono>
+
+#include <android/snapshot/snapshot.pb.h>
+#include <libsnapshot/snapshot.h>
+
+namespace android {
+namespace snapshot {
+
+class SnapshotMergeStats {
+ public:
+ SnapshotMergeStats(SnapshotManager& parent);
+ ~SnapshotMergeStats();
+ void Start();
+ void Resume();
+ void set_state(android::snapshot::UpdateState state);
+ SnapshotMergeReport GetReport();
+
+ private:
+ const SnapshotManager& parent_;
+ SnapshotMergeReport report_;
+ std::chrono::time_point<std::chrono::steady_clock> init_time_;
+ std::chrono::time_point<std::chrono::steady_clock> end_time_;
+};
+
+} // namespace snapshot
+} // namespace android
diff --git a/fs_mgr/libsnapshot/snapshot_test.cpp b/fs_mgr/libsnapshot/snapshot_test.cpp
index d87274d..5d2840f 100644
--- a/fs_mgr/libsnapshot/snapshot_test.cpp
+++ b/fs_mgr/libsnapshot/snapshot_test.cpp
@@ -1767,6 +1767,7 @@
protected:
void SetUp() override {
if (!is_virtual_ab_) GTEST_SKIP() << "Test for Virtual A/B devices only";
+ GTEST_SKIP() << "WIP failure b/149738928";
SnapshotTest::SetUp();
userdata_ = std::make_unique<LowSpaceUserdata>();
@@ -1774,6 +1775,7 @@
}
void TearDown() override {
if (!is_virtual_ab_) return;
+ return; // BUG(149738928)
EXPECT_TRUE(!image_manager_->BackingImageExists(kImageName) ||
image_manager_->DeleteBackingImage(kImageName));
@@ -1808,10 +1810,6 @@
std::vector<uint64_t> ret;
for (uint64_t size = 1_MiB; size <= 512_MiB; size *= 2) {
ret.push_back(size);
-#ifdef SKIP_TEST_IN_PRESUBMIT
- // BUG(148889015);
- break;
-#endif
}
return ret;
}
diff --git a/fs_mgr/tests/adb-remount-test.sh b/fs_mgr/tests/adb-remount-test.sh
index e364436..cf324fe 100755
--- a/fs_mgr/tests/adb-remount-test.sh
+++ b/fs_mgr/tests/adb-remount-test.sh
@@ -902,7 +902,11 @@
done
# If reboot too soon after fresh flash, could trip device update failure logic
-wait_for_screen
+if ! wait_for_screen && ${screen_wait}; then
+ screen_wait=false
+ echo "${ORANGE}[ WARNING ]${NORMAL} not healthy, no launcher, skipping wait for screen" >&2
+fi
+
# Can we test remount -R command?
OVERLAYFS_BACKING="cache mnt/scratch"
overlayfs_supported=true
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 38e8227..97d40b7 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -548,6 +548,7 @@
skip = strlen("reboot,");
}
SetProperty(LAST_REBOOT_REASON_PROPERTY, reason.c_str() + skip);
+ WriteStringToFile(reason.c_str() + skip, LAST_REBOOT_REASON_FILE);
sync();
bool is_thermal_shutdown = cmd == ANDROID_RB_THERMOFF;
diff --git a/libcutils/include/cutils/android_reboot.h b/libcutils/include/cutils/android_reboot.h
index cd27eef..24e32d5 100644
--- a/libcutils/include/cutils/android_reboot.h
+++ b/libcutils/include/cutils/android_reboot.h
@@ -31,6 +31,7 @@
/* Android reboot reason stored in this property */
#define LAST_REBOOT_REASON_PROPERTY "persist.sys.boot.reason"
+#define LAST_REBOOT_REASON_FILE "/metadata/bootstat/" LAST_REBOOT_REASON_PROPERTY
/* Reboot or shutdown the system.
* This call uses ANDROID_RB_PROPERTY to request reboot to init process.
diff --git a/libprocessgroup/include/processgroup/processgroup.h b/libprocessgroup/include/processgroup/processgroup.h
index 0b38b6b..4aa439a 100644
--- a/libprocessgroup/include/processgroup/processgroup.h
+++ b/libprocessgroup/include/processgroup/processgroup.h
@@ -30,8 +30,7 @@
bool CgroupGetAttributePathForTask(const std::string& attr_name, int tid, std::string* path);
bool SetTaskProfiles(int tid, const std::vector<std::string>& profiles, bool use_fd_cache = false);
-bool SetProcessProfiles(uid_t uid, pid_t pid, const std::vector<std::string>& profiles,
- bool use_fd_cache = false);
+bool SetProcessProfiles(uid_t uid, pid_t pid, const std::vector<std::string>& profiles);
#ifndef __ANDROID_VNDK__
diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp
index 6272664..d669ebe 100644
--- a/libprocessgroup/processgroup.cpp
+++ b/libprocessgroup/processgroup.cpp
@@ -115,9 +115,8 @@
TaskProfiles::GetInstance().DropResourceCaching();
}
-bool SetProcessProfiles(uid_t uid, pid_t pid, const std::vector<std::string>& profiles,
- bool use_fd_cache) {
- return TaskProfiles::GetInstance().SetProcessProfiles(uid, pid, profiles, use_fd_cache);
+bool SetProcessProfiles(uid_t uid, pid_t pid, const std::vector<std::string>& profiles) {
+ return TaskProfiles::GetInstance().SetProcessProfiles(uid, pid, profiles);
}
bool SetTaskProfiles(int tid, const std::vector<std::string>& profiles, bool use_fd_cache) {
diff --git a/libprocessgroup/task_profiles.cpp b/libprocessgroup/task_profiles.cpp
index 72f01af..4af4589 100644
--- a/libprocessgroup/task_profiles.cpp
+++ b/libprocessgroup/task_profiles.cpp
@@ -201,22 +201,6 @@
}
bool SetCgroupAction::ExecuteForProcess(uid_t uid, pid_t pid) const {
- std::lock_guard<std::mutex> lock(fd_mutex_);
- if (IsFdValid()) {
- // fd is cached, reuse it
- if (!AddTidToCgroup(pid, fd_)) {
- LOG(ERROR) << "Failed to add task into cgroup";
- return false;
- }
- return true;
- }
-
- if (fd_ == FDS_INACCESSIBLE) {
- // no permissions to access the file, ignore
- return true;
- }
-
- // this is app-dependent path and fd is not cached or cached fd can't be used
std::string procs_path = controller()->GetProcsFilePath(path_, uid, pid);
unique_fd tmp_fd(TEMP_FAILURE_RETRY(open(procs_path.c_str(), O_WRONLY | O_CLOEXEC)));
if (tmp_fd < 0) {
@@ -270,7 +254,6 @@
bool ApplyProfileAction::ExecuteForProcess(uid_t uid, pid_t pid) const {
for (const auto& profile : profiles_) {
- profile->EnableResourceCaching();
if (!profile->ExecuteForProcess(uid, pid)) {
PLOG(WARNING) << "ExecuteForProcess failed for aggregate profile";
}
@@ -280,7 +263,6 @@
bool ApplyProfileAction::ExecuteForTask(int tid) const {
for (const auto& profile : profiles_) {
- profile->EnableResourceCaching();
if (!profile->ExecuteForTask(tid)) {
PLOG(WARNING) << "ExecuteForTask failed for aggregate profile";
}
@@ -288,6 +270,18 @@
return true;
}
+void ApplyProfileAction::EnableResourceCaching() {
+ for (const auto& profile : profiles_) {
+ profile->EnableResourceCaching();
+ }
+}
+
+void ApplyProfileAction::DropResourceCaching() {
+ for (const auto& profile : profiles_) {
+ profile->DropResourceCaching();
+ }
+}
+
void TaskProfile::MoveTo(TaskProfile* profile) {
profile->elements_ = std::move(elements_);
profile->res_cached_ = res_cached_;
@@ -527,13 +521,10 @@
}
bool TaskProfiles::SetProcessProfiles(uid_t uid, pid_t pid,
- const std::vector<std::string>& profiles, bool use_fd_cache) {
+ const std::vector<std::string>& profiles) {
for (const auto& name : profiles) {
TaskProfile* profile = GetProfile(name);
if (profile != nullptr) {
- if (use_fd_cache) {
- profile->EnableResourceCaching();
- }
if (!profile->ExecuteForProcess(uid, pid)) {
PLOG(WARNING) << "Failed to apply " << name << " process profile";
}
diff --git a/libprocessgroup/task_profiles.h b/libprocessgroup/task_profiles.h
index a64ca50..28bc00c 100644
--- a/libprocessgroup/task_profiles.h
+++ b/libprocessgroup/task_profiles.h
@@ -163,6 +163,8 @@
virtual bool ExecuteForProcess(uid_t uid, pid_t pid) const;
virtual bool ExecuteForTask(int tid) const;
+ virtual void EnableResourceCaching();
+ virtual void DropResourceCaching();
private:
std::vector<std::shared_ptr<TaskProfile>> profiles_;
@@ -176,8 +178,7 @@
TaskProfile* GetProfile(const std::string& name) const;
const ProfileAttribute* GetAttribute(const std::string& name) const;
void DropResourceCaching() const;
- bool SetProcessProfiles(uid_t uid, pid_t pid, const std::vector<std::string>& profiles,
- bool use_fd_cache);
+ bool SetProcessProfiles(uid_t uid, pid_t pid, const std::vector<std::string>& profiles);
bool SetTaskProfiles(int tid, const std::vector<std::string>& profiles, bool use_fd_cache);
private:
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 782f967..91dd7a5 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -386,6 +386,10 @@
# Start logd before any other services run to ensure we capture all of their logs.
start logd
# Start lmkd before any other services run so that it can register them
+ chown root system /sys/module/lowmemorykiller/parameters/adj
+ chmod 0664 /sys/module/lowmemorykiller/parameters/adj
+ chown root system /sys/module/lowmemorykiller/parameters/minfree
+ chmod 0664 /sys/module/lowmemorykiller/parameters/minfree
start lmkd
# Start essential services.
@@ -496,6 +500,7 @@
mkdir /metadata/vold
chmod 0700 /metadata/vold
mkdir /metadata/password_slots 0771 root system
+ mkdir /metadata/bootstat 0750 system log
mkdir /metadata/ota 0700 root system
mkdir /metadata/ota/snapshots 0700 root system
@@ -824,10 +829,6 @@
# parameters to match how it is managing things.
write /proc/sys/vm/overcommit_memory 1
write /proc/sys/vm/min_free_order_shift 4
- chown root system /sys/module/lowmemorykiller/parameters/adj
- chmod 0664 /sys/module/lowmemorykiller/parameters/adj
- chown root system /sys/module/lowmemorykiller/parameters/minfree
- chmod 0664 /sys/module/lowmemorykiller/parameters/minfree
# System server manages zram writeback
chown root system /sys/block/zram0/idle