Merge "Move zygote start after loading persist properties"
diff --git a/adb/Android.bp b/adb/Android.bp
index 1469e77..6cff0be 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -174,12 +174,6 @@
"libdiagnose_usb",
"libmdnssd",
"libusb",
- "libandroidfw",
- "libziparchive",
- "libz",
- "libutils",
- "liblog",
- "libcutils",
],
}
@@ -262,12 +256,6 @@
"liblog",
"libmdnssd",
"libusb",
- "libandroidfw",
- "libziparchive",
- "libz",
- "libutils",
- "liblog",
- "libcutils",
],
stl: "libc++_static",
@@ -277,6 +265,10 @@
// will violate ODR
shared_libs: [],
+ required: [
+ "deploypatchgenerator",
+ ],
+
target: {
darwin: {
cflags: [
diff --git a/adb/adb_utils.cpp b/adb/adb_utils.cpp
index ffac315..35017f0 100644
--- a/adb/adb_utils.cpp
+++ b/adb/adb_utils.cpp
@@ -49,9 +49,9 @@
#if defined(_WIN32)
-constexpr char kNullFileName[] = "NUL";
+static constexpr char kNullFileName[] = "NUL";
#else
-constexpr char kNullFileName[] = "/dev/null";
+static constexpr char kNullFileName[] = "/dev/null";
#endif
void close_stdin() {
diff --git a/adb/client/adb_install.cpp b/adb/client/adb_install.cpp
index 95574ed..c0d09fd 100644
--- a/adb/client/adb_install.cpp
+++ b/adb/client/adb_install.cpp
@@ -40,6 +40,8 @@
#include <android-base/strings.h>
#include <android-base/test_utils.h>
+static constexpr int kFastDeployMinApi = 24;
+
static bool _use_legacy_install() {
FeatureSet features;
std::string error;
@@ -130,7 +132,7 @@
}
static int install_app_streamed(int argc, const char** argv, bool use_fastdeploy,
- bool use_localagent, const char* adb_path) {
+ bool use_localagent) {
printf("Performing Streamed Install\n");
// The last argument must be the APK file
@@ -152,8 +154,7 @@
printf("failed to extract metadata %d\n", metadata_len);
return 1;
} else {
- int create_patch_result = create_patch(file, metadataTmpFile.path, patchTmpFile.path,
- use_localagent, adb_path);
+ int create_patch_result = create_patch(file, metadataTmpFile.path, patchTmpFile.path);
if (create_patch_result != 0) {
printf("Patch creation failure, error code: %d\n", create_patch_result);
result = create_patch_result;
@@ -226,8 +227,8 @@
}
}
-static int install_app_legacy(int argc, const char** argv, bool use_fastdeploy, bool use_localagent,
- const char* adb_path) {
+static int install_app_legacy(int argc, const char** argv, bool use_fastdeploy,
+ bool use_localagent) {
static const char* const DATA_DEST = "/data/local/tmp/%s";
static const char* const SD_DEST = "/sdcard/tmp/%s";
const char* where = DATA_DEST;
@@ -269,8 +270,8 @@
printf("failed to extract metadata %d\n", metadata_len);
return 1;
} else {
- int create_patch_result = create_patch(apk_file[0], metadataTmpFile.path,
- patchTmpFile.path, use_localagent, adb_path);
+ int create_patch_result =
+ create_patch(apk_file[0], metadataTmpFile.path, patchTmpFile.path);
if (create_patch_result != 0) {
printf("Patch creation failure, error code: %d\n", create_patch_result);
result = create_patch_result;
@@ -380,14 +381,10 @@
}
}
- std::string adb_path = android::base::GetExecutablePath();
-
- if (adb_path.length() == 0) {
- return 1;
- }
if (use_fastdeploy == true) {
- bool agent_up_to_date =
- update_agent(agent_update_strategy, use_localagent, adb_path.c_str());
+ fastdeploy_set_local_agent(use_localagent);
+
+ bool agent_up_to_date = update_agent(agent_update_strategy);
if (agent_up_to_date == false) {
printf("Failed to update agent, exiting\n");
return 1;
@@ -397,10 +394,10 @@
switch (installMode) {
case INSTALL_PUSH:
return install_app_legacy(passthrough_argv.size(), passthrough_argv.data(),
- use_fastdeploy, use_localagent, adb_path.c_str());
+ use_fastdeploy, use_localagent);
case INSTALL_STREAM:
return install_app_streamed(passthrough_argv.size(), passthrough_argv.data(),
- use_fastdeploy, use_localagent, adb_path.c_str());
+ use_fastdeploy, use_localagent);
case INSTALL_DEFAULT:
default:
return 1;
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index 451422f..a5cfd7f 100644
--- a/adb/client/commandline.cpp
+++ b/adb/client/commandline.cpp
@@ -354,8 +354,7 @@
}
void copy_to_file(int inFd, int outFd) {
- constexpr size_t BUFSIZE = 32 * 1024;
- std::vector<char> buf(BUFSIZE);
+ std::vector<char> buf(32 * 1024);
int len;
long total = 0;
int old_stdin_mode = -1;
@@ -367,9 +366,9 @@
while (true) {
if (inFd == STDIN_FILENO) {
- len = unix_read(inFd, buf.data(), BUFSIZE);
+ len = unix_read(inFd, buf.data(), buf.size());
} else {
- len = adb_read(inFd, buf.data(), BUFSIZE);
+ len = adb_read(inFd, buf.data(), buf.size());
}
if (len == 0) {
D("copy_to_file() : read 0 bytes; exiting");
diff --git a/adb/client/fastdeploy.cpp b/adb/client/fastdeploy.cpp
index fda3889..2914836 100644
--- a/adb/client/fastdeploy.cpp
+++ b/adb/client/fastdeploy.cpp
@@ -14,26 +14,29 @@
* limitations under the License.
*/
-#include <androidfw/ResourceTypes.h>
-#include <androidfw/ZipFileRO.h>
#include <libgen.h>
#include <algorithm>
+#include <array>
+#include "android-base/file.h"
+#include "android-base/strings.h"
#include "client/file_sync_client.h"
#include "commandline.h"
#include "fastdeploy.h"
#include "fastdeploycallbacks.h"
#include "utils/String16.h"
-const long kRequiredAgentVersion = 0x00000001;
+static constexpr long kRequiredAgentVersion = 0x00000001;
-const char* kDeviceAgentPath = "/data/local/tmp/";
+static constexpr const char* kDeviceAgentPath = "/data/local/tmp/";
+
+static bool use_localagent = false;
long get_agent_version() {
std::vector<char> versionOutputBuffer;
std::vector<char> versionErrorBuffer;
- int statusCode = capture_shell_command("/data/local/tmp/deployagent.sh version",
+ int statusCode = capture_shell_command("/data/local/tmp/deployagent version",
&versionOutputBuffer, &versionErrorBuffer);
long version = -1;
@@ -58,13 +61,15 @@
return api_level;
}
+void fastdeploy_set_local_agent(bool set_use_localagent) {
+ use_localagent = set_use_localagent;
+}
+
// local_path - must start with a '/' and be relative to $ANDROID_PRODUCT_OUT
-static bool get_agent_component_host_path(bool use_localagent, const char* adb_path,
- const char* local_path, const char* sdk_path,
+static bool get_agent_component_host_path(const char* local_path, const char* sdk_path,
std::string* output_path) {
- std::string mutable_adb_path = adb_path;
- const char* adb_dir = dirname(&mutable_adb_path[0]);
- if (adb_dir == nullptr) {
+ std::string adb_dir = android::base::GetExecutableDirectory();
+ if (adb_dir.empty()) {
return false;
}
@@ -76,26 +81,24 @@
*output_path = android::base::StringPrintf("%s%s", product_out, local_path);
return true;
} else {
- *output_path = android::base::StringPrintf("%s%s", adb_dir, sdk_path);
+ *output_path = adb_dir + sdk_path;
return true;
}
return false;
}
-static bool deploy_agent(bool checkTimeStamps, bool use_localagent, const char* adb_path) {
+static bool deploy_agent(bool checkTimeStamps) {
std::vector<const char*> srcs;
-
std::string agent_jar_path;
- if (get_agent_component_host_path(use_localagent, adb_path, "/system/framework/deployagent.jar",
- "/deployagent.jar", &agent_jar_path)) {
+ if (get_agent_component_host_path("/system/framework/deployagent.jar", "/deployagent.jar",
+ &agent_jar_path)) {
srcs.push_back(agent_jar_path.c_str());
} else {
return false;
}
std::string agent_sh_path;
- if (get_agent_component_host_path(use_localagent, adb_path, "/system/bin/deployagent.sh",
- "/deployagent.sh", &agent_sh_path)) {
+ if (get_agent_component_host_path("/system/bin/deployagent", "/deployagent", &agent_sh_path)) {
srcs.push_back(agent_sh_path.c_str());
} else {
return false;
@@ -104,7 +107,7 @@
if (do_sync_push(srcs, kDeviceAgentPath, checkTimeStamps)) {
// on windows the shell script might have lost execute permission
// so need to set this explicitly
- const char* kChmodCommandPattern = "chmod 777 %sdeployagent.sh";
+ const char* kChmodCommandPattern = "chmod 777 %sdeployagent";
std::string chmodCommand =
android::base::StringPrintf(kChmodCommandPattern, kDeviceAgentPath);
int ret = send_shell_command(chmodCommand);
@@ -114,17 +117,16 @@
}
}
-bool update_agent(FastDeploy_AgentUpdateStrategy agentUpdateStrategy, bool use_localagent,
- const char* adb_path) {
+bool update_agent(FastDeploy_AgentUpdateStrategy agentUpdateStrategy) {
long agent_version = get_agent_version();
switch (agentUpdateStrategy) {
case FastDeploy_AgentUpdateAlways:
- if (deploy_agent(false, use_localagent, adb_path) == false) {
+ if (deploy_agent(false) == false) {
return false;
}
break;
case FastDeploy_AgentUpdateNewerTimeStamp:
- if (deploy_agent(true, use_localagent, adb_path) == false) {
+ if (deploy_agent(true) == false) {
return false;
}
break;
@@ -136,7 +138,7 @@
printf("Device agent version is (%ld), (%ld) is required, re-deploying\n",
agent_version, kRequiredAgentVersion);
}
- if (deploy_agent(false, use_localagent, adb_path) == false) {
+ if (deploy_agent(false) == false) {
return false;
}
}
@@ -147,91 +149,54 @@
return (agent_version == kRequiredAgentVersion);
}
-static std::string get_string_from_utf16(const char16_t* input, int input_len) {
- ssize_t utf8_length = utf16_to_utf8_length(input, input_len);
- if (utf8_length <= 0) {
- return {};
+static std::string get_aapt2_path() {
+ if (use_localagent) {
+ // This should never happen on a Windows machine
+ const char* host_out = getenv("ANDROID_HOST_OUT");
+ if (host_out == nullptr) {
+ fatal("Could not locate aapt2 because $ANDROID_HOST_OUT is not defined");
+ }
+ return android::base::StringPrintf("%s/bin/aapt2", host_out);
}
- std::string utf8;
- utf8.resize(utf8_length);
- utf16_to_utf8(input, input_len, &*utf8.begin(), utf8_length + 1);
- return utf8;
+ std::string adb_dir = android::base::GetExecutableDirectory();
+ if (adb_dir.empty()) {
+ fatal("Could not locate aapt2");
+ }
+ return adb_dir + "/aapt2";
+}
+
+static int system_capture(const char* cmd, std::string& output) {
+ FILE* pipe = popen(cmd, "re");
+ int fd = -1;
+
+ if (pipe != nullptr) {
+ fd = fileno(pipe);
+ }
+
+ if (fd == -1) {
+ fatal_errno("Could not create pipe for process '%s'", cmd);
+ }
+
+ if (!android::base::ReadFdToString(fd, &output)) {
+ fatal_errno("Error reading from process '%s'", cmd);
+ }
+
+ return pclose(pipe);
}
// output is required to point to a valid output string (non-null)
static bool get_packagename_from_apk(const char* apkPath, std::string* output) {
- using namespace android;
+ const char* kAapt2DumpNameCommandPattern = R"(%s dump packagename "%s")";
+ std::string aapt2_path_string = get_aapt2_path();
+ std::string getPackagenameCommand = android::base::StringPrintf(
+ kAapt2DumpNameCommandPattern, aapt2_path_string.c_str(), apkPath);
- ZipFileRO* zipFile = ZipFileRO::open(apkPath);
- if (zipFile == nullptr) {
- return false;
+ if (system_capture(getPackagenameCommand.c_str(), *output) == 0) {
+ // strip any line end characters from the output
+ *output = android::base::Trim(*output);
+ return true;
}
-
- ZipEntryRO entry = zipFile->findEntryByName("AndroidManifest.xml");
- if (entry == nullptr) {
- return false;
- }
-
- uint32_t manifest_len = 0;
- if (!zipFile->getEntryInfo(entry, NULL, &manifest_len, NULL, NULL, NULL, NULL)) {
- return false;
- }
-
- std::vector<char> manifest_data(manifest_len);
- if (!zipFile->uncompressEntry(entry, manifest_data.data(), manifest_len)) {
- return false;
- }
-
- ResXMLTree tree;
- status_t setto_status = tree.setTo(manifest_data.data(), manifest_len, true);
- if (setto_status != NO_ERROR) {
- return false;
- }
-
- ResXMLParser::event_code_t code;
- while ((code = tree.next()) != ResXMLParser::BAD_DOCUMENT &&
- code != ResXMLParser::END_DOCUMENT) {
- switch (code) {
- case ResXMLParser::START_TAG: {
- size_t element_name_length;
- const char16_t* element_name = tree.getElementName(&element_name_length);
- if (element_name == nullptr) {
- continue;
- }
-
- std::u16string element_name_string(element_name, element_name_length);
- if (element_name_string == u"manifest") {
- for (int i = 0; i < (int)tree.getAttributeCount(); i++) {
- size_t attribute_name_length;
- const char16_t* attribute_name_text =
- tree.getAttributeName(i, &attribute_name_length);
- if (attribute_name_text == nullptr) {
- continue;
- }
- std::u16string attribute_name_string(attribute_name_text,
- attribute_name_length);
-
- if (attribute_name_string == u"package") {
- size_t attribute_value_length;
- const char16_t* attribute_value_text =
- tree.getAttributeStringValue(i, &attribute_value_length);
- if (attribute_value_text == nullptr) {
- continue;
- }
- *output = get_string_from_utf16(attribute_value_text,
- attribute_value_length);
- return true;
- }
- }
- }
- break;
- }
- default:
- break;
- }
- }
-
return false;
}
@@ -241,7 +206,7 @@
return -1;
}
- const char* kAgentExtractCommandPattern = "/data/local/tmp/deployagent.sh extract %s";
+ const char* kAgentExtractCommandPattern = "/data/local/tmp/deployagent extract %s";
std::string extractCommand =
android::base::StringPrintf(kAgentExtractCommandPattern, packageName.c_str());
@@ -257,43 +222,30 @@
return ret;
}
-// output is required to point to a valid output string (non-null)
-static bool patch_generator_command(bool use_localagent, const char* adb_path,
- std::string* output) {
+static std::string get_patch_generator_command() {
if (use_localagent) {
// This should never happen on a Windows machine
- const char* kGeneratorCommandPattern = "java -jar %s/framework/deploypatchgenerator.jar";
const char* host_out = getenv("ANDROID_HOST_OUT");
if (host_out == nullptr) {
- return false;
+ fatal("Could not locate deploypatchgenerator.jar because $ANDROID_HOST_OUT is not "
+ "defined");
}
- *output = android::base::StringPrintf(kGeneratorCommandPattern, host_out, host_out);
- return true;
- } else {
- const char* kGeneratorCommandPattern = R"(java -jar "%s/deploypatchgenerator.jar")";
- std::string mutable_adb_path = adb_path;
- const char* adb_dir = dirname(&mutable_adb_path[0]);
- if (adb_dir == nullptr) {
- return false;
- }
-
- *output = android::base::StringPrintf(kGeneratorCommandPattern, adb_dir, adb_dir);
- return true;
+ return android::base::StringPrintf("java -jar %s/framework/deploypatchgenerator.jar",
+ host_out);
}
- return false;
+
+ std::string adb_dir = android::base::GetExecutableDirectory();
+ if (adb_dir.empty()) {
+ fatal("Could not locate deploypatchgenerator.jar");
+ }
+ return android::base::StringPrintf(R"(java -jar "%s/deploypatchgenerator.jar")",
+ adb_dir.c_str());
}
-int create_patch(const char* apkPath, const char* metadataPath, const char* patchPath,
- bool use_localagent, const char* adb_path) {
- const char* kGeneratePatchCommandPattern = R"(%s "%s" "%s" > "%s")";
- std::string patch_generator_command_string;
- if (patch_generator_command(use_localagent, adb_path, &patch_generator_command_string) ==
- false) {
- return 1;
- }
+int create_patch(const char* apkPath, const char* metadataPath, const char* patchPath) {
std::string generatePatchCommand = android::base::StringPrintf(
- kGeneratePatchCommandPattern, patch_generator_command_string.c_str(), apkPath,
- metadataPath, patchPath);
+ R"(%s "%s" "%s" > "%s")", get_patch_generator_command().c_str(), apkPath, metadataPath,
+ patchPath);
return system(generatePatchCommand.c_str());
}
@@ -302,19 +254,20 @@
if (get_packagename_from_apk(apkPath, &packageName) == false) {
return "";
}
+
std::string patchDevicePath =
android::base::StringPrintf("%s%s.patch", kDeviceAgentPath, packageName.c_str());
return patchDevicePath;
}
int apply_patch_on_device(const char* apkPath, const char* patchPath, const char* outputPath) {
- const std::string kAgentApplyCommandPattern =
- "/data/local/tmp/deployagent.sh apply %s %s -o %s";
+ const std::string kAgentApplyCommandPattern = "/data/local/tmp/deployagent apply %s %s -o %s";
std::string packageName;
if (get_packagename_from_apk(apkPath, &packageName) == false) {
return -1;
}
+
std::string patchDevicePath = get_patch_path(apkPath);
std::vector<const char*> srcs = {patchPath};
@@ -327,12 +280,12 @@
std::string applyPatchCommand =
android::base::StringPrintf(kAgentApplyCommandPattern.c_str(), packageName.c_str(),
patchDevicePath.c_str(), outputPath);
+
return send_shell_command(applyPatchCommand);
}
int install_patch(const char* apkPath, const char* patchPath, int argc, const char** argv) {
- const std::string kAgentApplyCommandPattern =
- "/data/local/tmp/deployagent.sh apply %s %s -pm %s";
+ const std::string kAgentApplyCommandPattern = "/data/local/tmp/deployagent apply %s %s -pm %s";
std::string packageName;
if (get_packagename_from_apk(apkPath, &packageName) == false) {
diff --git a/adb/client/fastdeploy.h b/adb/client/fastdeploy.h
index d8acd30..80f3875 100644
--- a/adb/client/fastdeploy.h
+++ b/adb/client/fastdeploy.h
@@ -18,20 +18,17 @@
#include "adb.h"
-typedef enum EFastDeploy_AgentUpdateStrategy {
+enum FastDeploy_AgentUpdateStrategy {
FastDeploy_AgentUpdateAlways,
FastDeploy_AgentUpdateNewerTimeStamp,
FastDeploy_AgentUpdateDifferentVersion
-} FastDeploy_AgentUpdateStrategy;
+};
-static constexpr int kFastDeployMinApi = 24;
-
+void fastdeploy_set_local_agent(bool use_localagent);
int get_device_api_level();
-bool update_agent(FastDeploy_AgentUpdateStrategy agentUpdateStrategy, bool use_localagent,
- const char* adb_path);
+bool update_agent(FastDeploy_AgentUpdateStrategy agentUpdateStrategy);
int extract_metadata(const char* apkPath, FILE* outputFp);
-int create_patch(const char* apkPath, const char* metadataPath, const char* patchPath,
- bool use_localagent, const char* adb_path);
+int create_patch(const char* apkPath, const char* metadataPath, const char* patchPath);
int apply_patch_on_device(const char* apkPath, const char* patchPath, const char* outputPath);
int install_patch(const char* apkPath, const char* patchPath, int argc, const char** argv);
std::string get_patch_path(const char* apkPath);
diff --git a/adb/fastdeploy/Android.bp b/adb/fastdeploy/Android.bp
index 30f4730..400b12f 100644
--- a/adb/fastdeploy/Android.bp
+++ b/adb/fastdeploy/Android.bp
@@ -14,24 +14,17 @@
// limitations under the License.
//
-java_library {
+java_binary {
name: "deployagent",
sdk_version: "24",
srcs: ["deployagent/src/**/*.java", "deploylib/src/**/*.java", "proto/**/*.proto"],
static_libs: ["apkzlib_zip"],
+ wrapper: "deployagent/deployagent.sh",
proto: {
type: "lite",
}
}
-cc_prebuilt_binary {
- name: "deployagent.sh",
-
- srcs: ["deployagent/deployagent.sh"],
- required: ["deployagent"],
- device_supported: true,
-}
-
java_binary_host {
name: "deploypatchgenerator",
srcs: ["deploypatchgenerator/src/**/*.java", "deploylib/src/**/*.java", "proto/**/*.proto"],
diff --git a/adb/test_adb.py b/adb/test_adb.py
index cde2b22..7e73818 100755
--- a/adb/test_adb.py
+++ b/adb/test_adb.py
@@ -490,6 +490,58 @@
self.assertEqual(_devices(server_port), [])
+@unittest.skipUnless(sys.platform == "win32", "requires Windows")
+class PowerTest(unittest.TestCase):
+ def test_resume_usb_kick(self):
+ """Resuming from sleep/hibernate should kick USB devices."""
+ try:
+ usb_serial = subprocess.check_output(["adb", "-d", "get-serialno"]).strip()
+ except subprocess.CalledProcessError:
+ # If there are multiple USB devices, we don't have a way to check whether the selected
+ # device is USB.
+ raise unittest.SkipTest('requires single USB device')
+
+ try:
+ serial = subprocess.check_output(["adb", "get-serialno"]).strip()
+ except subprocess.CalledProcessError:
+ # Did you forget to select a device with $ANDROID_SERIAL?
+ raise unittest.SkipTest('requires $ANDROID_SERIAL set to a USB device')
+
+ # Test only works with USB devices because adb _power_notification_thread does not kick
+ # non-USB devices on resume event.
+ if serial != usb_serial:
+ raise unittest.SkipTest('requires USB device')
+
+ # Run an adb shell command in the background that takes a while to complete.
+ proc = subprocess.Popen(['adb', 'shell', 'sleep', '5'])
+
+ # Wait for startup of adb server's _power_notification_thread.
+ time.sleep(0.1)
+
+ # Simulate resuming from sleep/hibernation by sending Windows message.
+ import ctypes
+ from ctypes import wintypes
+ HWND_BROADCAST = 0xffff
+ WM_POWERBROADCAST = 0x218
+ PBT_APMRESUMEAUTOMATIC = 0x12
+
+ PostMessageW = ctypes.windll.user32.PostMessageW
+ PostMessageW.restype = wintypes.BOOL
+ PostMessageW.argtypes = (wintypes.HWND, wintypes.UINT, wintypes.WPARAM, wintypes.LPARAM)
+ result = PostMessageW(HWND_BROADCAST, WM_POWERBROADCAST, PBT_APMRESUMEAUTOMATIC, 0)
+ if not result:
+ raise ctypes.WinError()
+
+ # Wait for connection to adb shell to be broken by _power_notification_thread detecting the
+ # Windows message.
+ start = time.time()
+ proc.wait()
+ end = time.time()
+
+ # If the power event was detected, the adb shell command should be broken very quickly.
+ self.assertLess(end - start, 2)
+
+
def main():
"""Main entrypoint."""
random.seed(0)
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 239403a..95df490 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -1040,12 +1040,6 @@
return max_payload;
}
-namespace {
-
-constexpr char kFeatureStringDelimiter = ',';
-
-} // namespace
-
const FeatureSet& supported_features() {
// Local static allocation to avoid global non-POD variables.
static const FeatureSet* features = new FeatureSet{
@@ -1059,7 +1053,7 @@
}
std::string FeatureSetToString(const FeatureSet& features) {
- return android::base::Join(features, kFeatureStringDelimiter);
+ return android::base::Join(features, ',');
}
FeatureSet StringToFeatureSet(const std::string& features_string) {
@@ -1067,7 +1061,7 @@
return FeatureSet();
}
- auto names = android::base::Split(features_string, {kFeatureStringDelimiter});
+ auto names = android::base::Split(features_string, ",");
return FeatureSet(names.begin(), names.end());
}
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index 4fd483b..8353d89 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -187,8 +187,8 @@
}
// Retry the disconnected local port for 60 times, and sleep 1 second between two retries.
-constexpr uint32_t LOCAL_PORT_RETRY_COUNT = 60;
-constexpr auto LOCAL_PORT_RETRY_INTERVAL = 1s;
+static constexpr uint32_t LOCAL_PORT_RETRY_COUNT = 60;
+static constexpr auto LOCAL_PORT_RETRY_INTERVAL = 1s;
struct RetryPort {
int port;
diff --git a/fastboot/constants.h b/fastboot/constants.h
index 063cd40..8a425ae 100644
--- a/fastboot/constants.h
+++ b/fastboot/constants.h
@@ -57,3 +57,4 @@
#define FB_VAR_SLOT_UNBOOTABLE "slot-unbootable"
#define FB_VAR_IS_LOGICAL "is-logical"
#define FB_VAR_IS_USERSPACE "is-userspace"
+#define FB_VAR_HW_REVISION "hw-revision"
diff --git a/fastboot/device/commands.cpp b/fastboot/device/commands.cpp
index b1c2958..771c288 100644
--- a/fastboot/device/commands.cpp
+++ b/fastboot/device/commands.cpp
@@ -89,7 +89,8 @@
{FB_VAR_SLOT_UNBOOTABLE, {GetSlotUnbootable, nullptr}},
{FB_VAR_PARTITION_SIZE, {GetPartitionSize, GetAllPartitionArgsWithSlot}},
{FB_VAR_IS_LOGICAL, {GetPartitionIsLogical, GetAllPartitionArgsWithSlot}},
- {FB_VAR_IS_USERSPACE, {GetIsUserspace, nullptr}}};
+ {FB_VAR_IS_USERSPACE, {GetIsUserspace, nullptr}},
+ {FB_VAR_HW_REVISION, {GetHardwareRevision, nullptr}}};
if (args.size() < 2) {
return device->WriteFail("Missing argument");
diff --git a/fastboot/device/flashing.cpp b/fastboot/device/flashing.cpp
index e3efbcb..a383c54 100644
--- a/fastboot/device/flashing.cpp
+++ b/fastboot/device/flashing.cpp
@@ -72,7 +72,7 @@
}
int FlashSparseData(int fd, std::vector<char>& downloaded_data) {
- struct sparse_file* file = sparse_file_import_buf(downloaded_data.data(), true, false);
+ struct sparse_file* file = sparse_file_import_buf(downloaded_data.data(), true, true);
if (!file) {
return -ENOENT;
}
diff --git a/fastboot/device/utility.cpp b/fastboot/device/utility.cpp
index 0157e7f..d78c809 100644
--- a/fastboot/device/utility.cpp
+++ b/fastboot/device/utility.cpp
@@ -80,7 +80,7 @@
std::optional<std::string> FindPhysicalPartition(const std::string& name) {
std::string path = "/dev/block/by-name/" + name;
- if (access(path.c_str(), R_OK | W_OK) < 0) {
+ if (access(path.c_str(), W_OK) < 0) {
return {};
}
return path;
diff --git a/fastboot/device/variables.cpp b/fastboot/device/variables.cpp
index 91e844a..a960189 100644
--- a/fastboot/device/variables.cpp
+++ b/fastboot/device/variables.cpp
@@ -139,7 +139,7 @@
bool GetMaxDownloadSize(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
std::string* message) {
- *message = std::to_string(kMaxDownloadSizeDefault);
+ *message = android::base::StringPrintf("0x%X", kMaxDownloadSizeDefault);
return true;
}
@@ -256,3 +256,9 @@
}
return args;
}
+
+bool GetHardwareRevision(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
+ std::string* message) {
+ *message = android::base::GetProperty("ro.revision", "");
+ return true;
+}
diff --git a/fastboot/device/variables.h b/fastboot/device/variables.h
index c3a64cf..a44e729 100644
--- a/fastboot/device/variables.h
+++ b/fastboot/device/variables.h
@@ -48,6 +48,8 @@
std::string* message);
bool GetIsUserspace(FastbootDevice* device, const std::vector<std::string>& args,
std::string* message);
+bool GetHardwareRevision(FastbootDevice* device, const std::vector<std::string>& args,
+ std::string* message);
// Helpers for getvar all.
std::vector<std::vector<std::string>> GetAllPartitionArgsWithSlot(FastbootDevice* device);
diff --git a/fastboot/engine.cpp b/fastboot/engine.cpp
index d80e986..0ac57af 100644
--- a/fastboot/engine.cpp
+++ b/fastboot/engine.cpp
@@ -44,43 +44,10 @@
#include "constants.h"
#include "transport.h"
-enum Op {
- OP_DOWNLOAD,
- OP_COMMAND,
- OP_QUERY,
- OP_NOTICE,
- OP_DOWNLOAD_SPARSE,
- OP_WAIT_FOR_DISCONNECT,
- OP_DOWNLOAD_FD,
- OP_UPLOAD,
-};
+using android::base::StringPrintf;
-struct Action {
- Action(Op op, const std::string& cmd) : op(op), cmd(cmd) {}
-
- Op op;
- std::string cmd;
- std::string msg;
-
- std::string product;
-
- void* data = nullptr;
- // The protocol only supports 32-bit sizes, so you'll have to break
- // anything larger into multiple chunks.
- uint32_t size = 0;
-
- int fd = -1;
-
- int (*func)(Action& a, int status, const char* resp) = nullptr;
-
- double start = -1;
-};
-
-static std::vector<std::unique_ptr<Action>> action_list;
static fastboot::FastBootDriver* fb = nullptr;
-static constexpr char kStatusFormat[] = "%-50s ";
-
void fb_init(fastboot::FastBootDriver& fbi) {
fb = &fbi;
auto cb = [](std::string& info) { fprintf(stderr, "(bootloader) %s\n", info.c_str()); };
@@ -101,81 +68,72 @@
return !fb->GetVar(key, value);
}
-static int cb_default(Action& a, int status, const char* resp) {
+static void HandleResult(double start, int status) {
if (status) {
- fprintf(stderr,"FAILED (%s)\n", resp);
+ fprintf(stderr, "FAILED (%s)\n", fb->Error().c_str());
+ die("Command failed");
} else {
double split = now();
- fprintf(stderr, "OKAY [%7.3fs]\n", (split - a.start));
- a.start = split;
+ fprintf(stderr, "OKAY [%7.3fs]\n", (split - start));
}
- return status;
}
-static Action& queue_action(Op op, const std::string& cmd) {
- std::unique_ptr<Action> a{new Action(op, cmd)};
- a->func = cb_default;
-
- action_list.push_back(std::move(a));
- return *action_list.back();
-}
+#define RUN_COMMAND(command) \
+ { \
+ double start = now(); \
+ auto status = (command); \
+ HandleResult(start, status); \
+ }
void fb_set_active(const std::string& slot) {
- Action& a = queue_action(OP_COMMAND, FB_CMD_SET_ACTIVE ":" + slot);
- a.msg = "Setting current slot to '" + slot + "'";
+ Status("Setting current slot to '" + slot + "'");
+ RUN_COMMAND(fb->SetActive(slot));
}
-void fb_queue_erase(const std::string& partition) {
- Action& a = queue_action(OP_COMMAND, FB_CMD_ERASE ":" + partition);
- a.msg = "Erasing '" + partition + "'";
+void fb_erase(const std::string& partition) {
+ Status("Erasing '" + partition + "'");
+ RUN_COMMAND(fb->Erase(partition));
}
-void fb_queue_flash_fd(const std::string& partition, int fd, uint32_t sz) {
- Action& a = queue_action(OP_DOWNLOAD_FD, "");
- a.fd = fd;
- a.size = sz;
- a.msg = android::base::StringPrintf("Sending '%s' (%u KB)", partition.c_str(), sz / 1024);
+void fb_flash_fd(const std::string& partition, int fd, uint32_t sz) {
+ Status(StringPrintf("Sending '%s' (%u KB)", partition.c_str(), sz / 1024));
+ RUN_COMMAND(fb->Download(fd, sz));
- Action& b = queue_action(OP_COMMAND, FB_CMD_FLASH ":" + partition);
- b.msg = "Writing '" + partition + "'";
+ Status("Writing '" + partition + "'");
+ RUN_COMMAND(fb->Flash(partition));
}
-void fb_queue_flash(const std::string& partition, void* data, uint32_t sz) {
- Action& a = queue_action(OP_DOWNLOAD, "");
- a.data = data;
- a.size = sz;
- a.msg = android::base::StringPrintf("Sending '%s' (%u KB)", partition.c_str(), sz / 1024);
+void fb_flash(const std::string& partition, void* data, uint32_t sz) {
+ Status(StringPrintf("Sending '%s' (%u KB)", partition.c_str(), sz / 1024));
+ RUN_COMMAND(fb->Download(static_cast<char*>(data), sz));
- Action& b = queue_action(OP_COMMAND, FB_CMD_FLASH ":" + partition);
- b.msg = "Writing '" + partition + "'";
+ Status("Writing '" + partition + "'");
+ RUN_COMMAND(fb->Flash(partition));
}
-void fb_queue_flash_sparse(const std::string& partition, struct sparse_file* s, uint32_t sz,
- size_t current, size_t total) {
- Action& a = queue_action(OP_DOWNLOAD_SPARSE, "");
- a.data = s;
- a.size = 0;
- a.msg = android::base::StringPrintf("Sending sparse '%s' %zu/%zu (%u KB)", partition.c_str(),
- current, total, sz / 1024);
+void fb_flash_sparse(const std::string& partition, struct sparse_file* s, uint32_t sz,
+ size_t current, size_t total) {
+ Status(StringPrintf("Sending sparse '%s' %zu/%zu (%u KB)", partition.c_str(), current, total,
+ sz / 1024));
+ RUN_COMMAND(fb->Download(s));
- Action& b = queue_action(OP_COMMAND, FB_CMD_FLASH ":" + partition);
- b.msg = android::base::StringPrintf("Writing sparse '%s' %zu/%zu", partition.c_str(), current,
- total);
+ Status(StringPrintf("Writing sparse '%s' %zu/%zu", partition.c_str(), current, total));
+ RUN_COMMAND(fb->Flash(partition));
}
-void fb_queue_create_partition(const std::string& partition, const std::string& size) {
- Action& a = queue_action(OP_COMMAND, FB_CMD_CREATE_PARTITION ":" + partition + ":" + size);
- a.msg = "Creating '" + partition + "'";
+void fb_create_partition(const std::string& partition, const std::string& size) {
+ Status("Creating '" + partition + "'");
+ RUN_COMMAND(fb->RawCommand(FB_CMD_CREATE_PARTITION ":" + partition + ":" + size));
}
-void fb_queue_delete_partition(const std::string& partition) {
- Action& a = queue_action(OP_COMMAND, FB_CMD_DELETE_PARTITION ":" + partition);
- a.msg = "Deleting '" + partition + "'";
+void fb_delete_partition(const std::string& partition) {
+ Status("Deleting '" + partition + "'");
+ RUN_COMMAND(fb->RawCommand(FB_CMD_DELETE_PARTITION ":" + partition));
}
-void fb_queue_resize_partition(const std::string& partition, const std::string& size) {
- Action& a = queue_action(OP_COMMAND, FB_CMD_RESIZE_PARTITION ":" + partition + ":" + size);
- a.msg = "Resizing '" + partition + "'";
+void fb_resize_partition(const std::string& partition, const std::string& size) {
+ Status("Resizing '" + partition + "'");
+ RUN_COMMAND(fb->RawCommand(FB_CMD_RESIZE_PARTITION ":" + partition + ":" + size));
}
static int match(const char* str, const char** value, unsigned count) {
@@ -199,193 +157,108 @@
return 0;
}
-static int cb_check(Action& a, int status, const char* resp, int invert) {
- const char** value = reinterpret_cast<const char**>(a.data);
- unsigned count = a.size;
- unsigned n;
+void fb_require(const std::string& product, const std::string& var, bool invert, size_t count,
+ const char** values) {
+ Status("Checking '" + var + "'");
+
+ double start = now();
+
+ std::string var_value;
+ auto status = fb->GetVar(var, &var_value);
if (status) {
- fprintf(stderr,"FAILED (%s)\n", resp);
- return status;
+ fprintf(stderr, "getvar:%s FAILED (%s)\n", var.c_str(), fb->Error().c_str());
+ die("requirements not met!");
}
- if (!a.product.empty()) {
- if (a.product != cur_product) {
+ if (!product.empty()) {
+ if (product != cur_product) {
double split = now();
fprintf(stderr, "IGNORE, product is %s required only for %s [%7.3fs]\n", cur_product,
- a.product.c_str(), (split - a.start));
- a.start = split;
- return 0;
+ product.c_str(), (split - start));
+ return;
}
}
- int yes = match(resp, value, count);
+ int yes = match(var_value.c_str(), values, count);
if (invert) yes = !yes;
if (yes) {
double split = now();
- fprintf(stderr, "OKAY [%7.3fs]\n", (split - a.start));
- a.start = split;
- return 0;
+ fprintf(stderr, "OKAY [%7.3fs]\n", (split - start));
+ return;
}
fprintf(stderr, "FAILED\n\n");
- fprintf(stderr, "Device %s is '%s'.\n", a.cmd.c_str() + 7, resp);
- fprintf(stderr, "Update %s '%s'", invert ? "rejects" : "requires", value[0]);
- for (n = 1; n < count; n++) {
- fprintf(stderr, " or '%s'", value[n]);
+ fprintf(stderr, "Device %s is '%s'.\n", var.c_str(), var_value.c_str());
+ fprintf(stderr, "Update %s '%s'", invert ? "rejects" : "requires", values[0]);
+ for (size_t n = 1; n < count; n++) {
+ fprintf(stderr, " or '%s'", values[n]);
}
fprintf(stderr, ".\n\n");
- return -1;
+ die("requirements not met!");
}
-static int cb_require(Action& a, int status, const char* resp) {
- return cb_check(a, status, resp, 0);
-}
+void fb_display(const std::string& label, const std::string& var) {
+ std::string value;
+ auto status = fb->GetVar(var, &value);
-static int cb_reject(Action& a, int status, const char* resp) {
- return cb_check(a, status, resp, 1);
-}
-
-void fb_queue_require(const std::string& product, const std::string& var, bool invert,
- size_t nvalues, const char** values) {
- Action& a = queue_action(OP_QUERY, FB_CMD_GETVAR ":" + var);
- a.product = product;
- a.data = values;
- a.size = nvalues;
- a.msg = "Checking " + var;
- a.func = invert ? cb_reject : cb_require;
- if (a.data == nullptr) die("out of memory");
-}
-
-static int cb_display(Action& a, int status, const char* resp) {
if (status) {
- fprintf(stderr, "%s FAILED (%s)\n", a.cmd.c_str(), resp);
- return status;
+ fprintf(stderr, "getvar:%s FAILED (%s)\n", var.c_str(), fb->Error().c_str());
+ return;
}
- fprintf(stderr, "%s: %s\n", static_cast<const char*>(a.data), resp);
- free(static_cast<char*>(a.data));
- return 0;
+ fprintf(stderr, "%s: %s\n", label.c_str(), value.c_str());
}
-void fb_queue_display(const std::string& label, const std::string& var) {
- Action& a = queue_action(OP_QUERY, FB_CMD_GETVAR ":" + var);
- a.data = xstrdup(label.c_str());
- a.func = cb_display;
-}
+void fb_query_save(const std::string& var, char* dest, uint32_t dest_size) {
+ std::string value;
+ auto status = fb->GetVar(var, &value);
-static int cb_save(Action& a, int status, const char* resp) {
if (status) {
- fprintf(stderr, "%s FAILED (%s)\n", a.cmd.c_str(), resp);
- return status;
+ fprintf(stderr, "getvar:%s FAILED (%s)\n", var.c_str(), fb->Error().c_str());
+ return;
}
- strncpy(reinterpret_cast<char*>(a.data), resp, a.size);
- return 0;
+
+ strncpy(dest, value.c_str(), dest_size);
}
-void fb_queue_query_save(const std::string& var, char* dest, uint32_t dest_size) {
- Action& a = queue_action(OP_QUERY, FB_CMD_GETVAR ":" + var);
- a.data = dest;
- a.size = dest_size;
- a.func = cb_save;
-}
-
-static int cb_do_nothing(Action&, int, const char*) {
+void fb_reboot() {
+ fprintf(stderr, "Rebooting");
+ fb->Reboot();
fprintf(stderr, "\n");
- return 0;
}
-void fb_queue_reboot() {
- Action& a = queue_action(OP_COMMAND, FB_CMD_REBOOT);
- a.func = cb_do_nothing;
- a.msg = "Rebooting";
+void fb_command(const std::string& cmd, const std::string& msg) {
+ Status(msg);
+ RUN_COMMAND(fb->RawCommand(cmd));
}
-void fb_queue_command(const std::string& cmd, const std::string& msg) {
- Action& a = queue_action(OP_COMMAND, cmd);
- a.msg = msg;
+void fb_download(const std::string& name, void* data, uint32_t size) {
+ Status("Downloading '" + name + "'");
+ RUN_COMMAND(fb->Download(static_cast<char*>(data), size));
}
-void fb_queue_download(const std::string& name, void* data, uint32_t size) {
- Action& a = queue_action(OP_DOWNLOAD, "");
- a.data = data;
- a.size = size;
- a.msg = "Downloading '" + name + "'";
+void fb_download_fd(const std::string& name, int fd, uint32_t sz) {
+ Status(StringPrintf("Sending '%s' (%u KB)", name.c_str(), sz / 1024));
+ RUN_COMMAND(fb->Download(fd, sz));
}
-void fb_queue_download_fd(const std::string& name, int fd, uint32_t sz) {
- Action& a = queue_action(OP_DOWNLOAD_FD, "");
- a.fd = fd;
- a.size = sz;
- a.msg = android::base::StringPrintf("Sending '%s' (%u KB)", name.c_str(), sz / 1024);
+void fb_upload(const std::string& outfile) {
+ Status("Uploading '" + outfile + "'");
+ RUN_COMMAND(fb->Upload(outfile));
}
-void fb_queue_upload(const std::string& outfile) {
- Action& a = queue_action(OP_UPLOAD, "");
- a.data = xstrdup(outfile.c_str());
- a.msg = "Uploading '" + outfile + "'";
+void fb_notice(const std::string& notice) {
+ Status(notice);
+ fprintf(stderr, "\n");
}
-void fb_queue_notice(const std::string& notice) {
- Action& a = queue_action(OP_NOTICE, "");
- a.msg = notice;
-}
-
-void fb_queue_wait_for_disconnect() {
- queue_action(OP_WAIT_FOR_DISCONNECT, "");
-}
-
-int64_t fb_execute_queue() {
- int64_t status = 0;
- for (auto& a : action_list) {
- a->start = now();
- if (!a->msg.empty()) {
- fprintf(stderr, kStatusFormat, a->msg.c_str());
- verbose("\n");
- }
- if (a->op == OP_DOWNLOAD) {
- char* cbuf = static_cast<char*>(a->data);
- status = fb->Download(cbuf, a->size);
- status = a->func(*a, status, status ? fb_get_error().c_str() : "");
- if (status) break;
- } else if (a->op == OP_DOWNLOAD_FD) {
- status = fb->Download(a->fd, a->size);
- status = a->func(*a, status, status ? fb_get_error().c_str() : "");
- if (status) break;
- } else if (a->op == OP_COMMAND) {
- status = fb->RawCommand(a->cmd);
- status = a->func(*a, status, status ? fb_get_error().c_str() : "");
- if (status) break;
- } else if (a->op == OP_QUERY) {
- std::string resp;
- status = fb->RawCommand(a->cmd, &resp);
- status = a->func(*a, status, status ? fb_get_error().c_str() : resp.c_str());
- if (status) break;
- } else if (a->op == OP_NOTICE) {
- // We already showed the notice because it's in `Action::msg`.
- fprintf(stderr, "\n");
- } else if (a->op == OP_DOWNLOAD_SPARSE) {
- status = fb->Download(reinterpret_cast<sparse_file*>(a->data));
- status = a->func(*a, status, status ? fb_get_error().c_str() : "");
- if (status) break;
- } else if (a->op == OP_WAIT_FOR_DISCONNECT) {
- fb->WaitForDisconnect();
- } else if (a->op == OP_UPLOAD) {
- status = fb->Upload(reinterpret_cast<const char*>(a->data));
- status = a->func(*a, status, status ? fb_get_error().c_str() : "");
- } else {
- die("unknown action: %d", a->op);
- }
- }
- action_list.clear();
- return status;
+void fb_wait_for_disconnect() {
+ fb->WaitForDisconnect();
}
bool fb_reboot_to_userspace() {
- // First ensure that the queue is flushed.
- fb_execute_queue();
-
- fprintf(stderr, kStatusFormat, "Rebooting to userspace fastboot");
+ Status("Rebooting to userspace fastboot");
verbose("\n");
if (fb->RebootTo("fastboot") != fastboot::RetCode::SUCCESS) {
diff --git a/fastboot/engine.h b/fastboot/engine.h
index f098ca7..d78cb13 100644
--- a/fastboot/engine.h
+++ b/fastboot/engine.h
@@ -44,36 +44,29 @@
const std::string fb_get_error();
-//#define FB_COMMAND_SZ (fastboot::FB_COMMAND_SZ)
-//#define FB_RESPONSE_SZ (fastboot::FB_RESPONSE_SZ)
-
-/* engine.c - high level command queue engine */
-
void fb_init(fastboot::FastBootDriver& fbi);
void fb_reinit(Transport* transport);
bool fb_getvar(const std::string& key, std::string* value);
-void fb_queue_flash(const std::string& partition, void* data, uint32_t sz);
-void fb_queue_flash_fd(const std::string& partition, int fd, uint32_t sz);
-void fb_queue_flash_sparse(const std::string& partition, struct sparse_file* s, uint32_t sz,
- size_t current, size_t total);
-void fb_queue_erase(const std::string& partition);
-void fb_queue_format(const std::string& partition, int skip_if_not_supported, int32_t max_chunk_sz);
-void fb_queue_require(const std::string& prod, const std::string& var, bool invert, size_t nvalues,
- const char** values);
-void fb_queue_display(const std::string& label, const std::string& var);
-void fb_queue_query_save(const std::string& var, char* dest, uint32_t dest_size);
-void fb_queue_reboot(void);
-void fb_queue_command(const std::string& cmd, const std::string& msg);
-void fb_queue_download(const std::string& name, void* data, uint32_t size);
-void fb_queue_download_fd(const std::string& name, int fd, uint32_t sz);
-void fb_queue_upload(const std::string& outfile);
-void fb_queue_notice(const std::string& notice);
-void fb_queue_wait_for_disconnect(void);
-void fb_queue_create_partition(const std::string& partition, const std::string& size);
-void fb_queue_delete_partition(const std::string& partition);
-void fb_queue_resize_partition(const std::string& partition, const std::string& size);
-int64_t fb_execute_queue();
+void fb_flash(const std::string& partition, void* data, uint32_t sz);
+void fb_flash_fd(const std::string& partition, int fd, uint32_t sz);
+void fb_flash_sparse(const std::string& partition, struct sparse_file* s, uint32_t sz,
+ size_t current, size_t total);
+void fb_erase(const std::string& partition);
+void fb_require(const std::string& prod, const std::string& var, bool invert, size_t nvalues,
+ const char** values);
+void fb_display(const std::string& label, const std::string& var);
+void fb_query_save(const std::string& var, char* dest, uint32_t dest_size);
+void fb_reboot();
+void fb_command(const std::string& cmd, const std::string& msg);
+void fb_download(const std::string& name, void* data, uint32_t size);
+void fb_download_fd(const std::string& name, int fd, uint32_t sz);
+void fb_upload(const std::string& outfile);
+void fb_notice(const std::string& notice);
+void fb_wait_for_disconnect(void);
+void fb_create_partition(const std::string& partition, const std::string& size);
+void fb_delete_partition(const std::string& partition);
+void fb_resize_partition(const std::string& partition, const std::string& size);
void fb_set_active(const std::string& slot);
bool fb_reboot_to_userspace();
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 1aef567..817afd0 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -688,7 +688,7 @@
out[i] = xstrdup(strip(val[i]));
}
- fb_queue_require(product, var, invert, count, out);
+ fb_require(product, var, invert, count, out);
}
static void check_requirements(char* data, int64_t sz) {
@@ -702,15 +702,14 @@
s++;
}
}
- if (fb_execute_queue()) die("requirements not met!");
}
-static void queue_info_dump() {
- fb_queue_notice("--------------------------------------------");
- fb_queue_display("Bootloader Version...", "version-bootloader");
- fb_queue_display("Baseband Version.....", "version-baseband");
- fb_queue_display("Serial Number........", "serialno");
- fb_queue_notice("--------------------------------------------");
+static void dump_info() {
+ fb_notice("--------------------------------------------");
+ fb_display("Bootloader Version...", "version-bootloader");
+ fb_display("Baseband Version.....", "version-baseband");
+ fb_display("Serial Number........", "serialno");
+ fb_notice("--------------------------------------------");
}
static struct sparse_file** load_sparse_files(int fd, int64_t max_size) {
@@ -883,12 +882,12 @@
for (size_t i = 0; i < sparse_files.size(); ++i) {
const auto& pair = sparse_files[i];
- fb_queue_flash_sparse(partition, pair.first, pair.second, i + 1, sparse_files.size());
+ fb_flash_sparse(partition, pair.first, pair.second, i + 1, sparse_files.size());
}
break;
}
case FB_BUFFER_FD:
- fb_queue_flash_fd(partition, buf->fd, buf->sz);
+ fb_flash_fd(partition, buf->fd, buf->sz);
break;
default:
die("unknown buffer type: %d", buf->type);
@@ -1145,7 +1144,7 @@
for (const auto& [image, slot] : os_images_) {
auto resize_partition = [](const std::string& partition) -> void {
if (is_logical(partition)) {
- fb_queue_resize_partition(partition, "0");
+ fb_resize_partition(partition, "0");
}
};
do_for_partitions(image->part_name, slot, resize_partition, false);
@@ -1223,12 +1222,12 @@
int64_t sz;
void* data = source_.ReadFile(image.sig_name, &sz);
if (data) {
- fb_queue_download("signature", data, sz);
- fb_queue_command("signature", "installing signature");
+ fb_download("signature", data, sz);
+ fb_command("signature", "installing signature");
}
if (is_logical(partition_name)) {
- fb_queue_resize_partition(partition_name, std::to_string(buf->image_size));
+ fb_resize_partition(partition_name, std::to_string(buf->image_size));
}
flash_buf(partition_name.c_str(), buf);
};
@@ -1247,17 +1246,13 @@
if (!is_userspace_fastboot()) {
reboot_to_userspace_fastboot();
}
- fb_queue_download_fd("super", fd, get_file_size(fd));
+ fb_download_fd("super", fd, get_file_size(fd));
std::string command = "update-super:super";
if (wipe_) {
command += ":wipe";
}
- fb_queue_command(command, "Updating super partition");
-
- // We need these commands to have finished before proceeding, since
- // otherwise "getvar is-logical" may not return a correct answer below.
- fb_execute_queue();
+ fb_command(command, "Updating super partition");
}
class ZipImageSource final : public ImageSource {
@@ -1279,9 +1274,9 @@
}
static void do_update(const char* filename, const std::string& slot_override, bool skip_secondary) {
- queue_info_dump();
+ dump_info();
- fb_queue_query_save("product", cur_product, sizeof(cur_product));
+ fb_query_save("product", cur_product, sizeof(cur_product));
ZipArchiveHandle zip;
int error = OpenArchive(filename, &zip);
@@ -1316,9 +1311,9 @@
static void do_flashall(const std::string& slot_override, bool skip_secondary, bool wipe) {
std::string fname;
- queue_info_dump();
+ dump_info();
- fb_queue_query_save("product", cur_product, sizeof(cur_product));
+ fb_query_save("product", cur_product, sizeof(cur_product));
FlashAllTool tool(LocalImageSource(), slot_override, skip_secondary, wipe);
tool.Flash();
@@ -1338,7 +1333,7 @@
while (!args->empty()) {
command += " " + next_arg(args);
}
- fb_queue_command(command, "");
+ fb_command(command, "");
}
static std::string fb_fix_numeric_var(std::string var) {
@@ -1641,7 +1636,7 @@
if (command == "getvar") {
std::string variable = next_arg(&args);
- fb_queue_display(variable, variable);
+ fb_display(variable, variable);
} else if (command == "erase") {
std::string partition = next_arg(&args);
auto erase = [&](const std::string& partition) {
@@ -1653,7 +1648,7 @@
partition_type.c_str());
}
- fb_queue_erase(partition);
+ fb_erase(partition);
};
do_for_partitions(partition, slot_override, erase, true);
} else if (android::base::StartsWith(command, "format")) {
@@ -1681,8 +1676,8 @@
data = load_file(filename.c_str(), &sz);
if (data == nullptr) die("could not load '%s': %s", filename.c_str(), strerror(errno));
if (sz != 256) die("signature must be 256 bytes (got %" PRId64 ")", sz);
- fb_queue_download("signature", data, sz);
- fb_queue_command("signature", "installing signature");
+ fb_download("signature", data, sz);
+ fb_command("signature", "installing signature");
} else if (command == "reboot") {
wants_reboot = true;
@@ -1710,7 +1705,7 @@
} else if (command == "reboot-fastboot") {
wants_reboot_fastboot = true;
} else if (command == "continue") {
- fb_queue_command("continue", "resuming boot");
+ fb_command("continue", "resuming boot");
} else if (command == "boot") {
std::string kernel = next_arg(&args);
std::string ramdisk;
@@ -1719,8 +1714,8 @@
if (!args.empty()) second_stage = next_arg(&args);
data = load_bootable_image(kernel, ramdisk, second_stage, &sz);
- fb_queue_download("boot.img", data, sz);
- fb_queue_command("boot", "booting");
+ fb_download("boot.img", data, sz);
+ fb_command("boot", "booting");
} else if (command == "flash") {
std::string pname = next_arg(&args);
@@ -1746,7 +1741,7 @@
data = load_bootable_image(kernel, ramdisk, second_stage, &sz);
auto flashraw = [&](const std::string& partition) {
- fb_queue_flash(partition, data, sz);
+ fb_flash(partition, data, sz);
};
do_for_partitions(partition, slot_override, flashraw, true);
} else if (command == "flashall") {
@@ -1778,10 +1773,10 @@
if (!load_buf(filename.c_str(), &buf) || buf.type != FB_BUFFER_FD) {
die("cannot load '%s'", filename.c_str());
}
- fb_queue_download_fd(filename, buf.fd, buf.sz);
+ fb_download_fd(filename, buf.fd, buf.sz);
} else if (command == "get_staged") {
std::string filename = next_arg(&args);
- fb_queue_upload(filename);
+ fb_upload(filename);
} else if (command == "oem") {
do_oem_command("oem", &args);
} else if (command == "flashing") {
@@ -1798,14 +1793,14 @@
} else if (command == "create-logical-partition") {
std::string partition = next_arg(&args);
std::string size = next_arg(&args);
- fb_queue_create_partition(partition, size);
+ fb_create_partition(partition, size);
} else if (command == "delete-logical-partition") {
std::string partition = next_arg(&args);
- fb_queue_delete_partition(partition);
+ fb_delete_partition(partition);
} else if (command == "resize-logical-partition") {
std::string partition = next_arg(&args);
std::string size = next_arg(&args);
- fb_queue_resize_partition(partition, size);
+ fb_resize_partition(partition, size);
} else {
syntax_error("unknown command %s", command.c_str());
}
@@ -1817,7 +1812,7 @@
std::string partition_type;
if (!fb_getvar(std::string{"partition-type:"} + partition, &partition_type)) continue;
if (partition_type.empty()) continue;
- fb_queue_erase(partition);
+ fb_erase(partition);
if (partition == "userdata" && set_fbe_marker) {
fprintf(stderr, "setting FBE marker on initial userdata...\n");
std::string initial_userdata_dir = create_fbemarker_tmpdir();
@@ -1832,26 +1827,25 @@
fb_set_active(next_active);
}
if (wants_reboot && !skip_reboot) {
- fb_queue_reboot();
- fb_queue_wait_for_disconnect();
+ fb_reboot();
+ fb_wait_for_disconnect();
} else if (wants_reboot_bootloader) {
- fb_queue_command("reboot-bootloader", "rebooting into bootloader");
- fb_queue_wait_for_disconnect();
+ fb_command("reboot-bootloader", "rebooting into bootloader");
+ fb_wait_for_disconnect();
} else if (wants_reboot_recovery) {
- fb_queue_command("reboot-recovery", "rebooting into recovery");
- fb_queue_wait_for_disconnect();
+ fb_command("reboot-recovery", "rebooting into recovery");
+ fb_wait_for_disconnect();
} else if (wants_reboot_fastboot) {
- fb_queue_command("reboot-fastboot", "rebooting into fastboot");
- fb_queue_wait_for_disconnect();
+ fb_command("reboot-fastboot", "rebooting into fastboot");
+ fb_wait_for_disconnect();
}
- int status = fb_execute_queue() ? EXIT_FAILURE : EXIT_SUCCESS;
fprintf(stderr, "Finished. Total time: %.3fs\n", (now() - start));
if (Transport* old_transport = fb.set_transport(nullptr)) {
delete old_transport;
}
- return status;
+ return 0;
}
void FastBootTool::ParseOsPatchLevel(boot_img_hdr_v1* hdr, const char* arg) {
diff --git a/fastboot/fastboot_driver.cpp b/fastboot/fastboot_driver.cpp
index f9e640a..4a14131 100644
--- a/fastboot/fastboot_driver.cpp
+++ b/fastboot/fastboot_driver.cpp
@@ -97,9 +97,9 @@
return RawCommand("reboot-" + target, response, info);
}
-RetCode FastBootDriver::SetActive(const std::string& part, std::string* response,
+RetCode FastBootDriver::SetActive(const std::string& slot, std::string* response,
std::vector<std::string>* info) {
- return RawCommand(Commands::SET_ACTIVE + part, response, info);
+ return RawCommand(Commands::SET_ACTIVE + slot, response, info);
}
RetCode FastBootDriver::FlashPartition(const std::string& part, const std::vector<char>& data) {
diff --git a/fastboot/fastboot_driver.h b/fastboot/fastboot_driver.h
index ca9003a..4d85ba0 100644
--- a/fastboot/fastboot_driver.h
+++ b/fastboot/fastboot_driver.h
@@ -89,7 +89,7 @@
RetCode Reboot(std::string* response = nullptr, std::vector<std::string>* info = nullptr);
RetCode RebootTo(std::string target, std::string* response = nullptr,
std::vector<std::string>* info = nullptr);
- RetCode SetActive(const std::string& part, std::string* response = nullptr,
+ RetCode SetActive(const std::string& slot, std::string* response = nullptr,
std::vector<std::string>* info = nullptr);
RetCode Upload(const std::string& outfile, std::string* response = nullptr,
std::vector<std::string>* info = nullptr);
diff --git a/fastboot/fuzzy_fastboot/main.cpp b/fastboot/fuzzy_fastboot/main.cpp
index dd64082..8fb5a6a 100644
--- a/fastboot/fuzzy_fastboot/main.cpp
+++ b/fastboot/fuzzy_fastboot/main.cpp
@@ -570,7 +570,6 @@
buf.back() = buf.back() ^ 0x01;
ASSERT_EQ(DownloadCommand(buf.size()), SUCCESS) << "Device rejected download command";
ASSERT_EQ(SendBuffer(buf), SUCCESS) << "Downloading payload failed";
- printf("%02x\n", (unsigned char)buf.back());
// It can either reject this download or reject it during flash
if (HandleResponse() != DEVICE_FAIL) {
EXPECT_EQ(fb->Flash("userdata"), DEVICE_FAIL)
diff --git a/fastboot/fuzzy_fastboot/usb_transport_sniffer.h b/fastboot/fuzzy_fastboot/usb_transport_sniffer.h
index 89cc009..8119aea 100644
--- a/fastboot/fuzzy_fastboot/usb_transport_sniffer.h
+++ b/fastboot/fuzzy_fastboot/usb_transport_sniffer.h
@@ -72,7 +72,7 @@
virtual ssize_t Read(void* data, size_t len) override;
virtual ssize_t Write(const void* data, size_t len) override;
- virtual int Close() override;
+ virtual int Close() override final; // note usage in destructor
virtual int Reset() override;
const std::vector<Event> Transfers();
diff --git a/fastboot/util.cpp b/fastboot/util.cpp
index 8f6e52a..125182d 100644
--- a/fastboot/util.cpp
+++ b/fastboot/util.cpp
@@ -70,6 +70,11 @@
fprintf(stderr, "\n");
}
+void Status(const std::string& message) {
+ static constexpr char kStatusFormat[] = "%-50s ";
+ fprintf(stderr, kStatusFormat, message.c_str());
+}
+
char* xstrdup(const char* s) {
char* result = strdup(s);
if (!result) die("out of memory");
diff --git a/fastboot/util.h b/fastboot/util.h
index 9033f93..20be461 100644
--- a/fastboot/util.h
+++ b/fastboot/util.h
@@ -12,6 +12,8 @@
char* xstrdup(const char*);
void set_verbose();
+void Status(const std::string& message);
+
// These printf-like functions are implemented in terms of vsnprintf, so they
// use the same attribute for compile-time format string checking.
void die(const char* fmt, ...) __attribute__((__noreturn__))
diff --git a/libsysutils/include/sysutils/FrameworkCommand.h b/libsysutils/include/sysutils/FrameworkCommand.h
index 3e6264b..db17ba7 100644
--- a/libsysutils/include/sysutils/FrameworkCommand.h
+++ b/libsysutils/include/sysutils/FrameworkCommand.h
@@ -16,8 +16,6 @@
#ifndef __FRAMEWORK_CMD_HANDLER_H
#define __FRAMEWORK_CMD_HANDLER_H
-#include "List.h"
-
class SocketClient;
class FrameworkCommand {
@@ -31,8 +29,7 @@
virtual int runCommand(SocketClient *c, int argc, char **argv) = 0;
- const char *getCommand() { return mCommand; }
+ const char* getCommand() const { return mCommand; }
};
-typedef android::sysutils::List<FrameworkCommand *> FrameworkCommandCollection;
#endif
diff --git a/libsysutils/include/sysutils/FrameworkListener.h b/libsysutils/include/sysutils/FrameworkListener.h
index d9a561a..93d99c4 100644
--- a/libsysutils/include/sysutils/FrameworkListener.h
+++ b/libsysutils/include/sysutils/FrameworkListener.h
@@ -17,8 +17,10 @@
#define _FRAMEWORKSOCKETLISTENER_H
#include "SocketListener.h"
-#include "FrameworkCommand.h"
+#include <vector>
+
+class FrameworkCommand;
class SocketClient;
class FrameworkListener : public SocketListener {
@@ -31,7 +33,7 @@
private:
int mCommandCount;
bool mWithSeq;
- FrameworkCommandCollection *mCommands;
+ std::vector<FrameworkCommand*> mCommands;
bool mSkipToNextNullByte;
public:
diff --git a/libsysutils/include/sysutils/List.h b/libsysutils/include/sysutils/List.h
deleted file mode 100644
index 31f7b37..0000000
--- a/libsysutils/include/sysutils/List.h
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * Copyright (C) 2005 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.
- */
-
-//
-// Templated list class. Normally we'd use STL, but we don't have that.
-// This class mimics STL's interfaces.
-//
-// Objects are copied into the list with the '=' operator or with copy-
-// construction, so if the compiler's auto-generated versions won't work for
-// you, define your own.
-//
-// The only class you want to use from here is "List".
-//
-#ifndef _SYSUTILS_LIST_H
-#define _SYSUTILS_LIST_H
-
-#include <stddef.h>
-#include <stdint.h>
-
-namespace android {
-namespace sysutils {
-
-/*
- * Doubly-linked list. Instantiate with "List<MyClass> myList".
- *
- * Objects added to the list are copied using the assignment operator,
- * so this must be defined.
- */
-template<typename T>
-class List
-{
-protected:
- /*
- * One element in the list.
- */
- class _Node {
- public:
- explicit _Node(const T& val) : mVal(val) {}
- ~_Node() {}
- inline T& getRef() { return mVal; }
- inline const T& getRef() const { return mVal; }
- inline _Node* getPrev() const { return mpPrev; }
- inline _Node* getNext() const { return mpNext; }
- inline void setVal(const T& val) { mVal = val; }
- inline void setPrev(_Node* ptr) { mpPrev = ptr; }
- inline void setNext(_Node* ptr) { mpNext = ptr; }
- private:
- friend class List;
- friend class _ListIterator;
- T mVal;
- _Node* mpPrev;
- _Node* mpNext;
- };
-
- /*
- * Iterator for walking through the list.
- */
-
- template <typename TYPE>
- struct CONST_ITERATOR {
- typedef _Node const * NodePtr;
- typedef const TYPE Type;
- };
-
- template <typename TYPE>
- struct NON_CONST_ITERATOR {
- typedef _Node* NodePtr;
- typedef TYPE Type;
- };
-
- template<
- typename U,
- template <class> class Constness
- >
- class _ListIterator {
- typedef _ListIterator<U, Constness> _Iter;
- typedef typename Constness<U>::NodePtr _NodePtr;
- typedef typename Constness<U>::Type _Type;
-
- explicit _ListIterator(_NodePtr ptr) : mpNode(ptr) {}
-
- public:
- _ListIterator() {}
- _ListIterator(const _Iter& rhs) : mpNode(rhs.mpNode) {}
- ~_ListIterator() {}
-
- // this will handle conversions from iterator to const_iterator
- // (and also all convertible iterators)
- // Here, in this implementation, the iterators can be converted
- // if the nodes can be converted
- template<typename V> explicit
- _ListIterator(const V& rhs) : mpNode(rhs.mpNode) {}
-
-
- /*
- * Dereference operator. Used to get at the juicy insides.
- */
- _Type& operator*() const { return mpNode->getRef(); }
- _Type* operator->() const { return &(mpNode->getRef()); }
-
- /*
- * Iterator comparison.
- */
- inline bool operator==(const _Iter& right) const {
- return mpNode == right.mpNode; }
-
- inline bool operator!=(const _Iter& right) const {
- return mpNode != right.mpNode; }
-
- /*
- * handle comparisons between iterator and const_iterator
- */
- template<typename OTHER>
- inline bool operator==(const OTHER& right) const {
- return mpNode == right.mpNode; }
-
- template<typename OTHER>
- inline bool operator!=(const OTHER& right) const {
- return mpNode != right.mpNode; }
-
- /*
- * Incr/decr, used to move through the list.
- */
- inline _Iter& operator++() { // pre-increment
- mpNode = mpNode->getNext();
- return *this;
- }
- const _Iter operator++(int) { // post-increment
- _Iter tmp(*this);
- mpNode = mpNode->getNext();
- return tmp;
- }
- inline _Iter& operator--() { // pre-increment
- mpNode = mpNode->getPrev();
- return *this;
- }
- const _Iter operator--(int) { // post-increment
- _Iter tmp(*this);
- mpNode = mpNode->getPrev();
- return tmp;
- }
-
- inline _NodePtr getNode() const { return mpNode; }
-
- _NodePtr mpNode; /* should be private, but older gcc fails */
- private:
- friend class List;
- };
-
-public:
- List() {
- prep();
- }
- List(const List<T>& src) { // copy-constructor
- prep();
- insert(begin(), src.begin(), src.end());
- }
- virtual ~List() {
- clear();
- delete[] (unsigned char*) mpMiddle;
- }
-
- typedef _ListIterator<T, NON_CONST_ITERATOR> iterator;
- typedef _ListIterator<T, CONST_ITERATOR> const_iterator;
-
- List<T>& operator=(const List<T>& right);
-
- /* returns true if the list is empty */
- inline bool empty() const { return mpMiddle->getNext() == mpMiddle; }
-
- /* return #of elements in list */
- size_t size() const {
- return size_t(distance(begin(), end()));
- }
-
- /*
- * Return the first element or one past the last element. The
- * _Node* we're returning is converted to an "iterator" by a
- * constructor in _ListIterator.
- */
- inline iterator begin() {
- return iterator(mpMiddle->getNext());
- }
- inline const_iterator begin() const {
- return const_iterator(const_cast<_Node const*>(mpMiddle->getNext()));
- }
- inline iterator end() {
- return iterator(mpMiddle);
- }
- inline const_iterator end() const {
- return const_iterator(const_cast<_Node const*>(mpMiddle));
- }
-
- /* add the object to the head or tail of the list */
- void push_front(const T& val) { insert(begin(), val); }
- void push_back(const T& val) { insert(end(), val); }
-
- /* insert before the current node; returns iterator at new node */
- iterator insert(iterator posn, const T& val)
- {
- _Node* newNode = new _Node(val); // alloc & copy-construct
- newNode->setNext(posn.getNode());
- newNode->setPrev(posn.getNode()->getPrev());
- posn.getNode()->getPrev()->setNext(newNode);
- posn.getNode()->setPrev(newNode);
- return iterator(newNode);
- }
-
- /* insert a range of elements before the current node */
- void insert(iterator posn, const_iterator first, const_iterator last) {
- for ( ; first != last; ++first)
- insert(posn, *first);
- }
-
- /* remove one entry; returns iterator at next node */
- iterator erase(iterator posn) {
- _Node* pNext = posn.getNode()->getNext();
- _Node* pPrev = posn.getNode()->getPrev();
- pPrev->setNext(pNext);
- pNext->setPrev(pPrev);
- delete posn.getNode();
- return iterator(pNext);
- }
-
- /* remove a range of elements */
- iterator erase(iterator first, iterator last) {
- while (first != last)
- erase(first++); // don't erase than incr later!
- return iterator(last);
- }
-
- /* remove all contents of the list */
- void clear() {
- _Node* pCurrent = mpMiddle->getNext();
- _Node* pNext;
-
- while (pCurrent != mpMiddle) {
- pNext = pCurrent->getNext();
- delete pCurrent;
- pCurrent = pNext;
- }
- mpMiddle->setPrev(mpMiddle);
- mpMiddle->setNext(mpMiddle);
- }
-
- /*
- * Measure the distance between two iterators. On exist, "first"
- * will be equal to "last". The iterators must refer to the same
- * list.
- *
- * FIXME: This is actually a generic iterator function. It should be a
- * template function at the top-level with specializations for things like
- * vector<>, which can just do pointer math). Here we limit it to
- * _ListIterator of the same type but different constness.
- */
- template<
- typename U,
- template <class> class CL,
- template <class> class CR
- >
- ptrdiff_t distance(
- _ListIterator<U, CL> first, _ListIterator<U, CR> last) const
- {
- ptrdiff_t count = 0;
- while (first != last) {
- ++first;
- ++count;
- }
- return count;
- }
-
-private:
- /*
- * I want a _Node but don't need it to hold valid data. More
- * to the point, I don't want T's constructor to fire, since it
- * might have side-effects or require arguments. So, we do this
- * slightly uncouth storage alloc.
- */
- void prep() {
- mpMiddle = (_Node*) new unsigned char[sizeof(_Node)];
- mpMiddle->setPrev(mpMiddle);
- mpMiddle->setNext(mpMiddle);
- }
-
- /*
- * This node plays the role of "pointer to head" and "pointer to tail".
- * It sits in the middle of a circular list of nodes. The iterator
- * runs around the circle until it encounters this one.
- */
- _Node* mpMiddle;
-};
-
-/*
- * Assignment operator.
- *
- * The simplest way to do this would be to clear out the target list and
- * fill it with the source. However, we can speed things along by
- * re-using existing elements.
- */
-template<class T>
-List<T>& List<T>::operator=(const List<T>& right)
-{
- if (this == &right)
- return *this; // self-assignment
- iterator firstDst = begin();
- iterator lastDst = end();
- const_iterator firstSrc = right.begin();
- const_iterator lastSrc = right.end();
- while (firstSrc != lastSrc && firstDst != lastDst)
- *firstDst++ = *firstSrc++;
- if (firstSrc == lastSrc) // ran out of elements in source?
- erase(firstDst, lastDst); // yes, erase any extras
- else
- insert(lastDst, firstSrc, lastSrc); // copy remaining over
- return *this;
-}
-
-}; // namespace sysutils
-}; // namespace android
-
-#endif // _SYSUTILS_LIST_H
diff --git a/libsysutils/src/FrameworkListener.cpp b/libsysutils/src/FrameworkListener.cpp
index 835e226..b07853a 100644
--- a/libsysutils/src/FrameworkListener.cpp
+++ b/libsysutils/src/FrameworkListener.cpp
@@ -28,8 +28,6 @@
static const int CMD_BUF_SIZE = 1024;
-#define UNUSED __attribute__((unused))
-
FrameworkListener::FrameworkListener(const char *socketName, bool withSeq) :
SocketListener(socketName, true, withSeq) {
init(socketName, withSeq);
@@ -45,8 +43,7 @@
init(nullptr, false);
}
-void FrameworkListener::init(const char *socketName UNUSED, bool withSeq) {
- mCommands = new FrameworkCommandCollection();
+void FrameworkListener::init(const char* /*socketName*/, bool withSeq) {
errorRate = 0;
mCommandCount = 0;
mWithSeq = withSeq;
@@ -91,11 +88,10 @@
}
void FrameworkListener::registerCmd(FrameworkCommand *cmd) {
- mCommands->push_back(cmd);
+ mCommands.push_back(cmd);
}
void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) {
- FrameworkCommandCollection::iterator i;
int argc = 0;
char *argv[FrameworkListener::CMD_ARGS_MAX];
char tmp[CMD_BUF_SIZE];
@@ -193,9 +189,7 @@
goto out;
}
- for (i = mCommands->begin(); i != mCommands->end(); ++i) {
- FrameworkCommand *c = *i;
-
+ for (auto* c : mCommands) {
if (!strcmp(argv[0], c->getCommand())) {
if (c->runCommand(cli, argc, argv)) {
SLOGW("Handler '%s' error (%s)", c->getCommand(), strerror(errno));
diff --git a/libsysutils/src/SocketListener_test.cpp b/libsysutils/src/SocketListener_test.cpp
index fed4546..d6bfd02 100644
--- a/libsysutils/src/SocketListener_test.cpp
+++ b/libsysutils/src/SocketListener_test.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <sysutils/FrameworkCommand.h>
#include <sysutils/FrameworkListener.h>
#include <poll.h>
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index 02534f2..ce2421e 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -31,6 +31,7 @@
#include <sys/socket.h>
#include <sys/sysinfo.h>
#include <sys/types.h>
+#include <time.h>
#include <unistd.h>
#include <cutils/properties.h>
@@ -38,6 +39,7 @@
#include <lmkd.h>
#include <log/log.h>
#include <log/log_event_list.h>
+#include <log/log_time.h>
#ifdef LMKD_LOG_STATS
#include "statslog.h"
@@ -83,6 +85,10 @@
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
#define EIGHT_MEGA (1 << 23)
+#define TARGET_UPDATE_MIN_INTERVAL_MS 1000
+
+#define NS_PER_MS (NS_PER_SEC / MS_PER_SEC)
+
/* Defined as ProcessList.SYSTEM_ADJ in ProcessList.java */
#define SYSTEM_ADJ (-900)
@@ -494,6 +500,12 @@
return true;
}
+static inline long get_time_diff_ms(struct timespec *from,
+ struct timespec *to) {
+ return (to->tv_sec - from->tv_sec) * (long)MS_PER_SEC +
+ (to->tv_nsec - from->tv_nsec) / (long)NS_PER_MS;
+}
+
static void cmd_procprio(LMKD_CTRL_PACKET packet) {
struct proc *procp;
char path[80];
@@ -604,18 +616,52 @@
static void cmd_target(int ntargets, LMKD_CTRL_PACKET packet) {
int i;
struct lmk_target target;
+ char minfree_str[PROPERTY_VALUE_MAX];
+ char *pstr = minfree_str;
+ char *pend = minfree_str + sizeof(minfree_str);
+ static struct timespec last_req_tm;
+ struct timespec curr_tm;
- if (ntargets > (int)ARRAY_SIZE(lowmem_adj))
+ if (ntargets < 1 || ntargets > (int)ARRAY_SIZE(lowmem_adj))
return;
+ /*
+ * Ratelimit minfree updates to once per TARGET_UPDATE_MIN_INTERVAL_MS
+ * to prevent DoS attacks
+ */
+ if (clock_gettime(CLOCK_MONOTONIC_COARSE, &curr_tm) != 0) {
+ ALOGE("Failed to get current time");
+ return;
+ }
+
+ if (get_time_diff_ms(&last_req_tm, &curr_tm) <
+ TARGET_UPDATE_MIN_INTERVAL_MS) {
+ ALOGE("Ignoring frequent updated to lmkd limits");
+ return;
+ }
+
+ last_req_tm = curr_tm;
+
for (i = 0; i < ntargets; i++) {
lmkd_pack_get_target(packet, i, &target);
lowmem_minfree[i] = target.minfree;
lowmem_adj[i] = target.oom_adj_score;
+
+ pstr += snprintf(pstr, pend - pstr, "%d:%d,", target.minfree,
+ target.oom_adj_score);
+ if (pstr >= pend) {
+ /* if no more space in the buffer then terminate the loop */
+ pstr = pend;
+ break;
+ }
}
lowmem_targets_size = ntargets;
+ /* Override the last extra comma */
+ pstr[-1] = '\0';
+ property_set("sys.lmk.minfree_levels", minfree_str);
+
if (has_inkernel_module) {
char minfreestr[128];
char killpriostr[128];
@@ -1228,12 +1274,6 @@
level - 1 : level);
}
-static inline unsigned long get_time_diff_ms(struct timeval *from,
- struct timeval *to) {
- return (to->tv_sec - from->tv_sec) * 1000 +
- (to->tv_usec - from->tv_usec) / 1000;
-}
-
static void mp_event_common(int data, uint32_t events __unused) {
int ret;
unsigned long long evcount;
@@ -1242,8 +1282,8 @@
enum vmpressure_level lvl;
union meminfo mi;
union zoneinfo zi;
- static struct timeval last_report_tm;
- static unsigned long skip_count = 0;
+ static struct timespec last_kill_tm;
+ static unsigned long kill_skip_count = 0;
enum vmpressure_level level = (enum vmpressure_level)data;
long other_free = 0, other_file = 0;
int min_score_adj;
@@ -1273,18 +1313,23 @@
}
if (kill_timeout_ms) {
- struct timeval curr_tm;
- gettimeofday(&curr_tm, NULL);
- if (get_time_diff_ms(&last_report_tm, &curr_tm) < kill_timeout_ms) {
- skip_count++;
+ struct timespec curr_tm;
+
+ if (clock_gettime(CLOCK_MONOTONIC_COARSE, &curr_tm) != 0) {
+ ALOGE("Failed to get current time");
+ return;
+ }
+
+ if (get_time_diff_ms(&last_kill_tm, &curr_tm) < kill_timeout_ms) {
+ kill_skip_count++;
return;
}
}
- if (skip_count > 0) {
+ if (kill_skip_count > 0) {
ALOGI("%lu memory pressure events were skipped after a kill!",
- skip_count);
- skip_count = 0;
+ kill_skip_count);
+ kill_skip_count = 0;
}
if (meminfo_parse(&mi) < 0 || zoneinfo_parse(&zi) < 0) {
@@ -1432,7 +1477,10 @@
} else {
ALOGI("Reclaimed enough memory (pages to free=%d, pages freed=%d)",
pages_to_free, pages_freed);
- gettimeofday(&last_report_tm, NULL);
+ if (clock_gettime(CLOCK_MONOTONIC_COARSE, &last_kill_tm) != 0) {
+ ALOGE("Failed to get current time");
+ return;
+ }
}
if (pages_freed > 0) {
meminfo_log(&mi);
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 0f56337..0f1badb 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -41,6 +41,7 @@
#include <atomic>
#include <memory>
#include <string>
+#include <utility>
#include <vector>
#include <android-base/file.h>
@@ -565,23 +566,14 @@
return android_log_setPrintFormat(context->logformat, format);
}
-static const char multipliers[][2] = { { "" }, { "K" }, { "M" }, { "G" } };
-
-static unsigned long value_of_size(unsigned long value) {
- for (unsigned i = 0;
- (i < sizeof(multipliers) / sizeof(multipliers[0])) && (value >= 1024);
- value /= 1024, ++i)
- ;
- return value;
-}
-
-static const char* multiplier_of_size(unsigned long value) {
- unsigned i;
+static std::pair<unsigned long, const char*> format_of_size(unsigned long value) {
+ static const char multipliers[][3] = {{""}, {"Ki"}, {"Mi"}, {"Gi"}};
+ size_t i;
for (i = 0;
(i < sizeof(multipliers) / sizeof(multipliers[0])) && (value >= 1024);
value /= 1024, ++i)
;
- return multipliers[i];
+ return std::make_pair(value, multipliers[i]);
}
// String to unsigned int, returns -1 if it fails
@@ -1472,12 +1464,14 @@
if ((size < 0) || (readable < 0)) {
reportErrorName(&getSizeFail, dev->device, allSelected);
} else {
+ auto size_format = format_of_size(size);
+ auto readable_format = format_of_size(readable);
std::string str = android::base::StringPrintf(
- "%s: ring buffer is %ld%sb (%ld%sb consumed),"
- " max entry is %db, max payload is %db\n",
+ "%s: ring buffer is %lu %sB (%lu %sB consumed),"
+ " max entry is %d B, max payload is %d B\n",
dev->device,
- value_of_size(size), multiplier_of_size(size),
- value_of_size(readable), multiplier_of_size(readable),
+ size_format.first, size_format.second,
+ readable_format.first, readable_format.second,
(int)LOGGER_ENTRY_MAX_LEN,
(int)LOGGER_ENTRY_MAX_PAYLOAD);
TEMP_FAILURE_RETRY(write(context->output_fd,
diff --git a/logcat/tests/logcat_test.cpp b/logcat/tests/logcat_test.cpp
index cc1632a..bebcc71 100644
--- a/logcat/tests/logcat_test.cpp
+++ b/logcat/tests/logcat_test.cpp
@@ -557,20 +557,17 @@
while (fgets(buffer, sizeof(buffer), fp)) {
int size, consumed, max, payload;
- char size_mult[3], consumed_mult[3];
+ char size_mult[4], consumed_mult[4];
long full_size, full_consumed;
size = consumed = max = payload = 0;
// NB: crash log can be very small, not hit a Kb of consumed space
// doubly lucky we are not including it.
- if (6 != sscanf(buffer,
- "%*s ring buffer is %d%2s (%d%2s consumed),"
- " max entry is %db, max payload is %db",
- &size, size_mult, &consumed, consumed_mult, &max,
- &payload)) {
- fprintf(stderr, "WARNING: Parse error: %s", buffer);
- continue;
- }
+ EXPECT_EQ(6, sscanf(buffer,
+ "%*s ring buffer is %d %3s (%d %3s consumed),"
+ " max entry is %d B, max payload is %d B",
+ &size, size_mult, &consumed, consumed_mult, &max, &payload))
+ << "Parse error on: " << buffer;
full_size = size;
switch (size_mult[0]) {
case 'G':
@@ -582,8 +579,10 @@
case 'K':
full_size *= 1024;
/* FALLTHRU */
- case 'b':
+ case 'B':
break;
+ default:
+ ADD_FAILURE() << "Parse error on multiplier: " << size_mult;
}
full_consumed = consumed;
switch (consumed_mult[0]) {
@@ -596,8 +595,10 @@
case 'K':
full_consumed *= 1024;
/* FALLTHRU */
- case 'b':
+ case 'B':
break;
+ default:
+ ADD_FAILURE() << "Parse error on multiplier: " << consumed_mult;
}
EXPECT_GT((full_size * 9) / 4, full_consumed);
EXPECT_GT(full_size, max);
@@ -1229,13 +1230,12 @@
}
int size, consumed, max, payload;
- char size_mult[3], consumed_mult[3];
+ char size_mult[4], consumed_mult[4];
size = consumed = max = payload = 0;
if (6 == sscanf(buffer,
- "events: ring buffer is %d%2s (%d%2s consumed),"
- " max entry is %db, max payload is %db",
- &size, size_mult, &consumed, consumed_mult, &max,
- &payload)) {
+ "events: ring buffer is %d %3s (%d %3s consumed),"
+ " max entry is %d B, max payload is %d B",
+ &size, size_mult, &consumed, consumed_mult, &max, &payload)) {
long full_size = size, full_consumed = consumed;
switch (size_mult[0]) {
@@ -1248,7 +1248,7 @@
case 'K':
full_size *= 1024;
/* FALLTHRU */
- case 'b':
+ case 'B':
break;
}
switch (consumed_mult[0]) {
@@ -1261,7 +1261,7 @@
case 'K':
full_consumed *= 1024;
/* FALLTHRU */
- case 'b':
+ case 'B':
break;
}
EXPECT_GT(full_size, full_consumed);