Merge "adb: properly calculate packet size on Mac."
diff --git a/adb/Android.bp b/adb/Android.bp
index d81bb4b..46bc02b 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -191,6 +191,35 @@
},
}
+cc_benchmark {
+ name: "adb_benchmark",
+ defaults: ["adb_defaults"],
+
+ srcs: ["transport_benchmark.cpp"],
+ target: {
+ android: {
+ static_libs: [
+ "libadbd",
+ ],
+ },
+ host: {
+ static_libs: [
+ "libadb_host",
+ ],
+ },
+ },
+
+ static_libs: [
+ "libbase",
+ "libcutils",
+ "libcrypto_utils",
+ "libcrypto",
+ "libdiagnose_usb",
+ "liblog",
+ "libusb",
+ ],
+}
+
cc_binary_host {
name: "adb",
tags: ["debug"],
diff --git a/adb/adb.bash b/adb/adb.bash
new file mode 100644
index 0000000..d36bec3
--- /dev/null
+++ b/adb/adb.bash
@@ -0,0 +1,499 @@
+# /* vim: set ai ts=4 ft=sh: */
+#
+# Copyright 2011, 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.
+#
+
+_adb() {
+ if ! type -t "$1" >/dev/null; then
+ return
+ fi
+
+ if type -t _init_completion >/dev/null; then
+ _init_completion || return
+ fi
+
+ local where i cur serial
+ COMPREPLY=()
+
+ serial="${ANDROID_SERIAL:-none}"
+ where=OPTIONS
+ for ((i=1; i <= COMP_CWORD; i++)); do
+ cur="${COMP_WORDS[i]}"
+ case "${cur}" in
+ -s)
+ where=OPT_SERIAL
+ ;;
+ -p)
+ where=OPT_PATH
+ ;;
+ -*)
+ where=OPTIONS
+ ;;
+ *)
+ if [[ $where == OPT_SERIAL ]]; then
+ where=OPT_SERIAL_ARG
+ serial=${cur}
+ else
+ where=COMMAND
+ break
+ fi
+ ;;
+ esac
+ done
+
+ if [[ $where == COMMAND && $i -ge $COMP_CWORD ]]; then
+ where=OPTIONS
+ fi
+
+ OPTIONS="-d -e -s -p"
+ COMMAND="devices connect disconnect push pull sync shell emu logcat lolcat forward jdwp install uninstall bugreport help version start-server kill-server get-state get-serialno status-window remount reboot reboot-bootloader root usb tcpip disable-verity"
+
+ case $where in
+ OPTIONS|OPT_SERIAL|OPT_PATH)
+ COMPREPLY=( $(compgen -W "$OPTIONS $COMMAND" -- "$cur") )
+ ;;
+ OPT_SERIAL_ARG)
+ local devices=$(command adb devices 2> /dev/null | grep -v "List of devices" | awk '{ print $1 }')
+ COMPREPLY=( $(compgen -W "${devices}" -- ${cur}) )
+ ;;
+ COMMAND)
+ if [[ $i -eq $COMP_CWORD ]]; then
+ COMPREPLY=( $(compgen -W "$COMMAND" -- "$cur") )
+ else
+ i=$((i+1))
+ case "${cur}" in
+ install)
+ _adb_cmd_install "$serial" $i
+ ;;
+ sideload)
+ _adb_cmd_sideload "$serial" $i
+ ;;
+ pull)
+ _adb_cmd_pull "$serial" $i
+ ;;
+ push)
+ _adb_cmd_push "$serial" $i
+ ;;
+ reboot)
+ if [[ $COMP_CWORD == $i ]]; then
+ args="bootloader recovery"
+ COMPREPLY=( $(compgen -W "${args}" -- "${COMP_WORDS[i]}") )
+ fi
+ ;;
+ shell)
+ _adb_cmd_shell "$serial" $i
+ ;;
+ uninstall)
+ _adb_cmd_uninstall "$serial" $i
+ ;;
+ esac
+ fi
+ ;;
+ esac
+
+ return 0
+}
+
+_adb_cmd_install() {
+ local serial i cur where
+
+ serial=$1
+ i=$2
+
+ where=OPTIONS
+ for ((; i <= COMP_CWORD; i++)); do
+ cur="${COMP_WORDS[i]}"
+ case "${cur}" in
+ -*)
+ where=OPTIONS
+ ;;
+ *)
+ where=FILE
+ break
+ ;;
+ esac
+ done
+
+ cur="${COMP_WORDS[COMP_CWORD]}"
+ if [[ $where == OPTIONS ]]; then
+ COMPREPLY=( $(compgen -W "-d -l -r -s" -- "${cur}") )
+ return
+ fi
+
+ _adb_util_complete_local_file "${cur}" '!*.apk'
+}
+
+_adb_cmd_sideload() {
+ local serial i cur
+
+ serial=$1
+ i=$2
+
+ cur="${COMP_WORDS[COMP_CWORD]}"
+
+ _adb_util_complete_local_file "${cur}" '!*.zip'
+}
+
+_adb_cmd_push() {
+ local serial IFS=$'\n' i cur
+
+ serial=$1
+ i=$2
+
+ cur="${COMP_WORDS[COMP_CWORD]}"
+
+ if [[ $COMP_CWORD == $i ]]; then
+ _adb_util_complete_local_file "${cur}"
+ elif [[ $COMP_CWORD == $(($i+1)) ]]; then
+ if [ "${cur}" == "" ]; then
+ cur="/"
+ fi
+ _adb_util_list_files $serial "${cur}"
+ fi
+}
+
+_adb_cmd_pull() {
+ local serial IFS=$'\n' i cur
+
+ serial=$1
+ i=$2
+
+ cur="${COMP_WORDS[COMP_CWORD]}"
+
+ if [[ $COMP_CWORD == $i ]]; then
+ if [ "${cur}" == "" ]; then
+ cur="/"
+ fi
+ _adb_util_list_files $serial "${cur}"
+ elif [[ $COMP_CWORD == $(($i+1)) ]]; then
+ _adb_util_complete_local_file "${cur}"
+ fi
+}
+
+_adb_cmd_shell() {
+ local serial IFS=$'\n' i cur
+ local -a args
+
+ serial=$1
+ i=$2
+
+ cur="${COMP_WORDS[i]}"
+ if [ "$serial" != "none" ]; then
+ args=(-s $serial)
+ fi
+
+ if [[ $i -eq $COMP_CWORD && ${cur:0:1} != "/" ]]; then
+ paths=$(command adb ${args[@]} shell echo '$'PATH 2> /dev/null | tr -d '\r' | tr : '\n')
+ COMMAND=$(command adb ${args[@]} shell ls $paths '2>' /dev/null | tr -d '\r' | {
+ while read -r tmp; do
+ command=${tmp##*/}
+ printf '%s\n' "$command"
+ done
+ })
+ COMPREPLY=( $(compgen -W "$COMMAND" -- "$cur") )
+ return 0
+ fi
+
+ i=$((i+1))
+ case "$cur" in
+ ls)
+ _adb_shell_file_command $serial $i "--color -A -C -F -H -L -R -S -Z -a -c -d -f -h -i -k -l -m -n -p -q -r -s -t -u -x -1"
+ ;;
+ cat)
+ _adb_shell_file_command $serial $i "-h -e -t -u -v"
+ ;;
+ dumpsys)
+ _adb_cmd_shell_dumpsys "$serial" $i
+ ;;
+ am)
+ _adb_cmd_shell_am "$serial" $i
+ ;;
+ pm)
+ _adb_cmd_shell_pm "$serial" $i
+ ;;
+ /*)
+ _adb_util_list_files $serial "$cur"
+ ;;
+ *)
+ COMPREPLY=( )
+ ;;
+ esac
+
+ return 0
+}
+
+_adb_cmd_shell_dumpsys() {
+ local serial i cur
+ local -a args
+ local candidates
+
+ unset IFS
+
+ serial=$1
+ i=$2
+
+ if [ "$serial" != "none" ]; then
+ args=(-s $serial)
+ fi
+
+ if (( $i == $COMP_CWORD )) ; then
+ cur="${COMP_WORDS[COMP_CWORD]}"
+ # First line is a header, so need "1d".
+ candidates=$(command adb ${args[@]} shell dumpsys -l 2> /dev/null | sed -e '1d;s/^ *//' | tr -d '\r')
+ candidates="-l $candidates"
+ COMPREPLY=( $(compgen -W "$candidates" -- "$cur") )
+ return 0
+ fi
+
+ COMPREPLY=( )
+ return 0
+}
+
+_adb_cmd_shell_am() {
+ local serial i cur
+ local candidates
+
+ unset IFS
+
+ serial=$1
+ i=$2
+
+ if (( $i == $COMP_CWORD )) ; then
+ cur="${COMP_WORDS[COMP_CWORD]}"
+ candidates="broadcast clear-debug-app clear-watch-heap dumpheap force-stop get-config get-inactive hang idle-maintenance instrument kill kill-all monitor package-importance profile restart screen-compat send-trim-memory set-debug-app set-inactive set-watch-heap stack start startservice start-user stopservice stop-user suppress-resize-config-changes switch-user task to-app-uri to-intent-uri to-uri"
+ COMPREPLY=( $(compgen -W "$candidates" -- "$cur") )
+ return 0
+ fi
+
+ COMPREPLY=( )
+ return 0
+}
+
+
+_adb_cmd_shell_pm() {
+ local serial i cur
+ local candidates
+
+ unset IFS
+
+ serial=$1
+ i=$2
+
+ if (( $i == $COMP_CWORD )) ; then
+ cur="${COMP_WORDS[COMP_CWORD]}"
+ candidates="-l -lf -p clear create-user default-state disable"
+ candidates+=" disable-until-used disable-user dump enable"
+ candidates+=" get-app-link get-install-location get-max-users"
+ candidates+=" get-max-running-users grant hide install"
+ candidates+=" install-abandon install-commit install-create"
+ candidates+=" install-write list move-package"
+ candidates+=" move-primary-storage path remove-user"
+ candidates+=" reset-permissions revoke set-app-link"
+ candidates+=" set-installer set-install-location"
+ candidates+=" set-permission-enforced trim-caches unhide"
+ candidates+=" uninstall"
+ COMPREPLY=( $(compgen -W "$candidates" -- "$cur") )
+ return 0
+ fi
+
+ if (( $i + 1 == $COMP_CWORD )) && [[ "${COMP_WORDS[COMP_CWORD -1]}" == "list" ]] ; then
+ cur="${COMP_WORDS[COMP_CWORD]}"
+ candidates="packages permission-groups permissions instrumentation features libraries users"
+ COMPREPLY=( $(compgen -W "$candidates" -- "$cur") )
+ return 0
+ fi
+
+ COMPREPLY=( )
+ return 0
+}
+
+_adb_cmd_uninstall() {
+ local serial i where cur packages
+
+ serial=$1
+ i=$2
+ if [ "$serial" != "none" ]; then
+ args=(-s $serial)
+ fi
+
+ where=OPTIONS
+ for ((; i <= COMP_CWORD; i++)); do
+ cur="${COMP_WORDS[i]}"
+ case "${cur}" in
+ -*)
+ where=OPTIONS
+ ;;
+ *)
+ where=FILE
+ break
+ ;;
+ esac
+ done
+
+ cur="${COMP_WORDS[COMP_CWORD]}"
+ if [[ $where == OPTIONS ]]; then
+ COMPREPLY=( $(compgen -W "-k" -- "${cur}") )
+ fi
+
+ packages="$(
+ command adb ${args[@]} shell pm list packages '2>' /dev/null 2> /dev/null | tr -d '\r' | {
+ while read -r tmp; do
+ local package=${tmp#package:}
+ echo -n "${package} "
+ done
+ }
+ )"
+
+ COMPREPLY=( ${COMPREPLY[@]:-} $(compgen -W "${packages}" -- "${cur}") )
+}
+
+_adb_shell_file_command() {
+ local serial i cur file options
+ local -a args
+
+ serial=$1
+ i=$2
+ if [ "$serial" != "none" ]; then
+ args=(-s $serial)
+ fi
+ options=$3
+
+ where=OPTIONS
+ for ((; i <= COMP_CWORD; i++)); do
+ cur="${COMP_WORDS[i]}"
+ case "${cur}" in
+ -*)
+ where=OPTIONS
+ ;;
+ *)
+ where=FILE
+ break
+ ;;
+ esac
+ done
+
+ file="${COMP_WORDS[COMP_CWORD]}"
+ if [[ ${file} == "" ]]; then
+ file="/"
+ fi
+
+ case $where in
+ OPTIONS)
+ unset IFS
+ COMPREPLY=( $(compgen -W "$options" -- "$cur") )
+ ;;
+ FILE)
+ _adb_util_list_files $serial "$file"
+ ;;
+ esac
+
+ return 0
+}
+
+_adb_util_list_files() {
+ local serial dir IFS=$'\n'
+ local -a toks
+ local -a args
+
+ serial="$1"
+ file="$2"
+
+ if [ "$serial" != "none" ]; then
+ args=(-s $serial)
+ fi
+
+ if [[ $( command adb ${args[@]} shell ls -dF / '2>/dev/null' | tr -d '\r' ) == "d /" ]] ; then
+ toks=( ${toks[@]-} $(
+ command adb ${args[@]} shell ls -dF ${file}"*" '2>' /dev/null 2> /dev/null | tr -d '\r' | {
+ while read -r tmp; do
+ filetype=${tmp%% *}
+ filename=${tmp:${#filetype}+1}
+ if [[ ${filetype:${#filetype}-1:1} == d ]]; then
+ printf '%s/\n' "$filename"
+ else
+ printf '%s\n' "$filename"
+ fi
+ done
+ }
+ ))
+ else
+ toks=( ${toks[@]-} $(
+ command adb ${args[@]} shell ls -dp ${file}"*" '2>/dev/null' 2> /dev/null | tr -d '\r'
+ ))
+ fi
+
+ # Since we're probably doing file completion here, don't add a space after.
+ if [[ $(type -t compopt) = "builtin" ]]; then
+ compopt -o nospace
+ fi
+
+ COMPREPLY=( ${COMPREPLY[@]:-} "${toks[@]}" )
+}
+
+_adb_util_complete_local_file()
+{
+ local file xspec i j IFS=$'\n'
+ local -a dirs files
+
+ file=$1
+ xspec=$2
+
+ # Since we're probably doing file completion here, don't add a space after.
+ if [[ $(type -t compopt) = "builtin" ]]; then
+ compopt -o plusdirs
+ if [[ "${xspec}" == "" ]]; then
+ COMPREPLY=( ${COMPREPLY[@]:-} $(compgen -f -- "${cur}") )
+ else
+ compopt +o filenames
+ COMPREPLY=( ${COMPREPLY[@]:-} $(compgen -f -X "${xspec}" -- "${cur}") )
+ fi
+ else
+ # Work-around for shells with no compopt
+
+ dirs=( $(compgen -d -- "${cur}" ) )
+
+ if [[ "${xspec}" == "" ]]; then
+ files=( ${COMPREPLY[@]:-} $(compgen -f -- "${cur}") )
+ else
+ files=( ${COMPREPLY[@]:-} $(compgen -f -X "${xspec}" -- "${cur}") )
+ fi
+
+ COMPREPLY=( $(
+ for i in "${files[@]}"; do
+ local skip=
+ for j in "${dirs[@]}"; do
+ if [[ $i == $j ]]; then
+ skip=1
+ break
+ fi
+ done
+ [[ -n $skip ]] || printf "%s\n" "$i"
+ done
+ ))
+
+ COMPREPLY=( ${COMPREPLY[@]:-} $(
+ for i in "${dirs[@]}"; do
+ printf "%s/\n" "$i"
+ done
+ ))
+ fi
+}
+
+
+if [[ $(type -t compopt) = "builtin" ]]; then
+ complete -F _adb adb
+else
+ complete -o nospace -F _adb adb
+fi
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index 34930c6..e476e07 100644
--- a/adb/client/commandline.cpp
+++ b/adb/client/commandline.cpp
@@ -73,13 +73,13 @@
DefaultStandardStreamsCallback DEFAULT_STANDARD_STREAMS_CALLBACK(nullptr, nullptr);
-static std::string product_file(const char* file) {
+static std::string product_file(const std::string& file) {
const char* ANDROID_PRODUCT_OUT = getenv("ANDROID_PRODUCT_OUT");
if (ANDROID_PRODUCT_OUT == nullptr) {
fprintf(stderr, "adb: product directory not specified; set $ANDROID_PRODUCT_OUT\n");
exit(1);
}
- return android::base::StringPrintf("%s%s%s", ANDROID_PRODUCT_OUT, OS_PATH_SEPARATOR_STR, file);
+ return std::string{ANDROID_PRODUCT_OUT} + OS_PATH_SEPARATOR_STR + file;
}
static void help() {
@@ -134,7 +134,7 @@
" pull [-a] REMOTE... LOCAL\n"
" copy files/dirs from device\n"
" -a: preserve file timestamp and mode\n"
- " sync [system|vendor|oem|data|all]\n"
+ " sync [all|data|odm|oem|product|system|vendor]\n"
" sync a local build from $ANDROID_PRODUCT_OUT to the device (default all)\n"
" -l: list but don't copy\n"
"\n"
@@ -189,8 +189,7 @@
" get-state print offline | bootloader | device\n"
" get-serialno print <serial-number>\n"
" get-devpath print <device-path>\n"
- " remount\n"
- " remount /system, /vendor, and /oem partitions read-write\n"
+ " remount remount partitions read-write\n"
" reboot [bootloader|recovery|sideload|sideload-auto-reboot]\n"
" reboot the device; defaults to booting system image but\n"
" supports bootloader and recovery too. sideload reboots\n"
@@ -1731,48 +1730,28 @@
std::string src;
bool list_only = false;
if (argc < 2) {
- // No local path was specified.
- src = "";
+ // No partition specified: sync all of them.
} else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
list_only = true;
- if (argc == 3) {
- src = argv[2];
- } else {
- src = "";
- }
+ if (argc == 3) src = argv[2];
} else if (argc == 2) {
- // A local path or "android"/"data" arg was specified.
src = argv[1];
} else {
return syntax_error("adb sync [-l] [PARTITION]");
}
- if (src == "all") src = "";
-
- if (src != "" &&
- src != "system" && src != "data" && src != "vendor" && src != "oem") {
- return syntax_error("don't know how to sync %s partition", src.c_str());
+ if (src.empty()) src = "all";
+ std::vector<std::string> partitions{"data", "odm", "oem", "product", "system", "vendor"};
+ bool found = false;
+ for (const auto& partition : partitions) {
+ if (src == "all" || src == partition) {
+ std::string src_dir{product_file(partition)};
+ if (!directory_exists(src_dir)) continue;
+ found = true;
+ if (!do_sync_sync(src_dir, "/" + partition, list_only)) return 1;
+ }
}
-
- std::string system_src_path = product_file("system");
- std::string data_src_path = product_file("data");
- std::string vendor_src_path = product_file("vendor");
- std::string oem_src_path = product_file("oem");
-
- bool okay = true;
- if (okay && (src.empty() || src == "system")) {
- okay = do_sync_sync(system_src_path, "/system", list_only);
- }
- if (okay && (src.empty() || src == "vendor") && directory_exists(vendor_src_path)) {
- okay = do_sync_sync(vendor_src_path, "/vendor", list_only);
- }
- if (okay && (src.empty() || src == "oem") && directory_exists(oem_src_path)) {
- okay = do_sync_sync(oem_src_path, "/oem", list_only);
- }
- if (okay && (src.empty() || src == "data")) {
- okay = do_sync_sync(data_src_path, "/data", list_only);
- }
- return okay ? 0 : 1;
+ return found ? 0 : syntax_error("don't know how to sync %s partition", src.c_str());
}
/* passthrough commands */
else if (!strcmp(argv[0],"get-state") ||
diff --git a/adb/daemon/file_sync_service.cpp b/adb/daemon/file_sync_service.cpp
index 9a87931..1128993 100644
--- a/adb/daemon/file_sync_service.cpp
+++ b/adb/daemon/file_sync_service.cpp
@@ -48,10 +48,8 @@
using android::base::StringPrintf;
static bool should_use_fs_config(const std::string& path) {
- // TODO: use fs_config to configure permissions on /data.
- return android::base::StartsWith(path, "/system/") ||
- android::base::StartsWith(path, "/vendor/") ||
- android::base::StartsWith(path, "/oem/");
+ // TODO: use fs_config to configure permissions on /data too.
+ return !android::base::StartsWith(path, "/data/");
}
static bool update_capabilities(const char* path, uint64_t capabilities) {
diff --git a/adb/daemon/main.cpp b/adb/daemon/main.cpp
index 4314dae..232d9c5 100644
--- a/adb/daemon/main.cpp
+++ b/adb/daemon/main.cpp
@@ -19,10 +19,12 @@
#include "sysdeps.h"
#include <errno.h>
+#include <getopt.h>
+#include <malloc.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
-#include <getopt.h>
+#include <sys/capability.h>
#include <sys/prctl.h>
#include <memory>
@@ -49,13 +51,13 @@
static const char* root_seclabel = nullptr;
-static void drop_capabilities_bounding_set_if_needed(struct minijail *j) {
+static bool should_drop_capabilities_bounding_set() {
#if defined(ALLOW_ADBD_ROOT)
if (__android_log_is_debuggable()) {
- return;
+ return false;
}
#endif
- minijail_capbset_drop(j, CAP_TO_MASK(CAP_SETUID) | CAP_TO_MASK(CAP_SETGID));
+ return true;
}
static bool should_drop_privileges() {
@@ -116,13 +118,37 @@
// Don't listen on a port (default 5037) if running in secure mode.
// Don't run as root if running in secure mode.
if (should_drop_privileges()) {
- drop_capabilities_bounding_set_if_needed(jail.get());
+ const bool should_drop_caps = should_drop_capabilities_bounding_set();
+
+ if (should_drop_caps) {
+ minijail_use_caps(jail.get(), CAP_TO_MASK(CAP_SETUID) | CAP_TO_MASK(CAP_SETGID));
+ }
minijail_change_gid(jail.get(), AID_SHELL);
minijail_change_uid(jail.get(), AID_SHELL);
// minijail_enter() will abort if any priv-dropping step fails.
minijail_enter(jail.get());
+ // Whenever ambient capabilities are being used, minijail cannot
+ // simultaneously drop the bounding capability set to just
+ // CAP_SETUID|CAP_SETGID while clearing the inheritable, effective,
+ // and permitted sets. So we need to do that in two steps.
+ using ScopedCaps =
+ std::unique_ptr<std::remove_pointer<cap_t>::type, std::function<void(cap_t)>>;
+ ScopedCaps caps(cap_get_proc(), &cap_free);
+ if (cap_clear_flag(caps.get(), CAP_INHERITABLE) == -1) {
+ PLOG(FATAL) << "cap_clear_flag(INHERITABLE) failed";
+ }
+ if (cap_clear_flag(caps.get(), CAP_EFFECTIVE) == -1) {
+ PLOG(FATAL) << "cap_clear_flag(PEMITTED) failed";
+ }
+ if (cap_clear_flag(caps.get(), CAP_PERMITTED) == -1) {
+ PLOG(FATAL) << "cap_clear_flag(PEMITTED) failed";
+ }
+ if (cap_set_proc(caps.get()) != 0) {
+ PLOG(FATAL) << "cap_set_proc() failed";
+ }
+
D("Local port disabled");
} else {
// minijail_enter() will abort if any priv-dropping step fails.
@@ -213,6 +239,9 @@
}
int main(int argc, char** argv) {
+ // Set M_DECAY_TIME so that our allocations aren't immediately purged on free.
+ mallopt(M_DECAY_TIME, 1);
+
while (true) {
static struct option opts[] = {
{"root_seclabel", required_argument, nullptr, 's'},
diff --git a/adb/daemon/remount_service.cpp b/adb/daemon/remount_service.cpp
index a4c7a5a..d679a6d 100644
--- a/adb/daemon/remount_service.cpp
+++ b/adb/daemon/remount_service.cpp
@@ -145,8 +145,10 @@
} else {
success &= remount_partition(fd, "/system");
}
- success &= remount_partition(fd, "/vendor");
+ success &= remount_partition(fd, "/odm");
success &= remount_partition(fd, "/oem");
+ success &= remount_partition(fd, "/product");
+ success &= remount_partition(fd, "/vendor");
WriteFdExactly(fd, success ? "remount succeeded\n" : "remount failed\n");
diff --git a/adb/transport_benchmark.cpp b/adb/transport_benchmark.cpp
new file mode 100644
index 0000000..da24aa7
--- /dev/null
+++ b/adb/transport_benchmark.cpp
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <malloc.h>
+#include <stdio.h>
+
+#include <android-base/logging.h>
+#include <benchmark/benchmark.h>
+
+#include "adb_trace.h"
+#include "sysdeps.h"
+#include "transport.h"
+
+#define ADB_CONNECTION_BENCHMARK(benchmark_name, ...) \
+ BENCHMARK_TEMPLATE(benchmark_name, FdConnection, ##__VA_ARGS__) \
+ ->Arg(1) \
+ ->Arg(16384) \
+ ->Arg(MAX_PAYLOAD) \
+ ->UseRealTime()
+
+template <typename ConnectionType>
+std::unique_ptr<Connection> MakeConnection(unique_fd fd);
+
+template <>
+std::unique_ptr<Connection> MakeConnection<FdConnection>(unique_fd fd) {
+ auto fd_connection = std::make_unique<FdConnection>(std::move(fd));
+ return std::make_unique<BlockingConnectionAdapter>(std::move(fd_connection));
+}
+
+template <typename ConnectionType>
+void BM_Connection_Unidirectional(benchmark::State& state) {
+ int fds[2];
+ if (adb_socketpair(fds) != 0) {
+ LOG(FATAL) << "failed to create socketpair";
+ }
+
+ auto client = MakeConnection<ConnectionType>(unique_fd(fds[0]));
+ auto server = MakeConnection<ConnectionType>(unique_fd(fds[1]));
+
+ std::atomic<size_t> received_bytes;
+
+ client->SetReadCallback([](Connection*, std::unique_ptr<apacket>) -> bool { return true; });
+ server->SetReadCallback([&received_bytes](Connection*, std::unique_ptr<apacket> packet) -> bool {
+ received_bytes += packet->payload.size();
+ return true;
+ });
+
+ client->SetErrorCallback(
+ [](Connection*, const std::string& error) { LOG(INFO) << "client closed: " << error; });
+ server->SetErrorCallback(
+ [](Connection*, const std::string& error) { LOG(INFO) << "server closed: " << error; });
+
+ client->Start();
+ server->Start();
+
+ for (auto _ : state) {
+ size_t data_size = state.range(0);
+ std::unique_ptr<apacket> packet = std::make_unique<apacket>();
+ memset(&packet->msg, 0, sizeof(packet->msg));
+ packet->msg.command = A_WRTE;
+ packet->msg.data_length = data_size;
+ packet->payload.resize(data_size);
+
+ memset(&packet->payload[0], 0xff, data_size);
+
+ received_bytes = 0;
+ client->Write(std::move(packet));
+ while (received_bytes < data_size) {
+ continue;
+ }
+ }
+ state.SetBytesProcessed(static_cast<int64_t>(state.iterations()) * state.range(0));
+
+ client->Stop();
+ server->Stop();
+}
+
+ADB_CONNECTION_BENCHMARK(BM_Connection_Unidirectional);
+
+enum class ThreadPolicy {
+ MainThread,
+ SameThread,
+};
+
+template <typename ConnectionType, enum ThreadPolicy Policy>
+void BM_Connection_Echo(benchmark::State& state) {
+ int fds[2];
+ if (adb_socketpair(fds) != 0) {
+ LOG(FATAL) << "failed to create socketpair";
+ }
+
+ auto client = MakeConnection<ConnectionType>(unique_fd(fds[0]));
+ auto server = MakeConnection<ConnectionType>(unique_fd(fds[1]));
+
+ std::atomic<size_t> received_bytes;
+
+ fdevent_reset();
+ std::thread fdevent_thread([]() { fdevent_loop(); });
+
+ client->SetReadCallback([&received_bytes](Connection*, std::unique_ptr<apacket> packet) -> bool {
+ received_bytes += packet->payload.size();
+ return true;
+ });
+
+ static const auto handle_packet = [](Connection* connection, std::unique_ptr<apacket> packet) {
+ connection->Write(std::move(packet));
+ };
+
+ server->SetReadCallback([](Connection* connection, std::unique_ptr<apacket> packet) -> bool {
+ if (Policy == ThreadPolicy::MainThread) {
+ auto raw_packet = packet.release();
+ fdevent_run_on_main_thread([connection, raw_packet]() {
+ std::unique_ptr<apacket> packet(raw_packet);
+ handle_packet(connection, std::move(packet));
+ });
+ } else {
+ handle_packet(connection, std::move(packet));
+ }
+ return true;
+ });
+
+ client->SetErrorCallback(
+ [](Connection*, const std::string& error) { LOG(INFO) << "client closed: " << error; });
+ server->SetErrorCallback(
+ [](Connection*, const std::string& error) { LOG(INFO) << "server closed: " << error; });
+
+ client->Start();
+ server->Start();
+
+ for (auto _ : state) {
+ size_t data_size = state.range(0);
+ std::unique_ptr<apacket> packet = std::make_unique<apacket>();
+ memset(&packet->msg, 0, sizeof(packet->msg));
+ packet->msg.command = A_WRTE;
+ packet->msg.data_length = data_size;
+ packet->payload.resize(data_size);
+
+ memset(&packet->payload[0], 0xff, data_size);
+
+ received_bytes = 0;
+ client->Write(std::move(packet));
+ while (received_bytes < data_size) {
+ continue;
+ }
+ }
+ state.SetBytesProcessed(static_cast<int64_t>(state.iterations()) * state.range(0));
+
+ client->Stop();
+ server->Stop();
+
+ // TODO: Make it so that you don't need to poke the fdevent loop to make it terminate?
+ fdevent_terminate_loop();
+ fdevent_run_on_main_thread([]() {});
+
+ fdevent_thread.join();
+}
+
+ADB_CONNECTION_BENCHMARK(BM_Connection_Echo, ThreadPolicy::SameThread);
+ADB_CONNECTION_BENCHMARK(BM_Connection_Echo, ThreadPolicy::MainThread);
+
+int main(int argc, char** argv) {
+ // Set M_DECAY_TIME so that our allocations aren't immediately purged on free.
+ mallopt(M_DECAY_TIME, 1);
+
+ android::base::SetMinimumLogSeverity(android::base::WARNING);
+ adb_trace_init(argv);
+ ::benchmark::Initialize(&argc, argv);
+ if (::benchmark::ReportUnrecognizedArguments(argc, argv)) return 1;
+ ::benchmark::RunSpecifiedBenchmarks();
+}
diff --git a/base/logging.cpp b/base/logging.cpp
index 30d7f8d..a33da22 100644
--- a/base/logging.cpp
+++ b/base/logging.cpp
@@ -54,6 +54,7 @@
#endif
#include <android-base/macros.h>
+#include <android-base/parseint.h>
#include <android-base/strings.h>
#include <android-base/threads.h>
@@ -82,6 +83,23 @@
return progname;
}
#endif
+
+#if defined(__linux__)
+int OpenKmsg() {
+#if defined(__ANDROID__)
+ // pick up 'file w /dev/kmsg' environment from daemon's init rc file
+ const auto val = getenv("ANDROID_FILE__dev_kmsg");
+ if (val != nullptr) {
+ int fd;
+ if (android::base::ParseInt(val, &fd, 0)) {
+ auto flags = fcntl(fd, F_GETFL);
+ if ((flags != -1) && ((flags & O_ACCMODE) == O_WRONLY)) return fd;
+ }
+ }
+#endif
+ return TEMP_FAILURE_RETRY(open("/dev/kmsg", O_WRONLY | O_CLOEXEC));
+}
+#endif
} // namespace
namespace android {
@@ -150,7 +168,7 @@
static_assert(arraysize(kLogSeverityToKernelLogLevel) == android::base::FATAL + 1,
"Mismatch in size of kLogSeverityToKernelLogLevel and values in LogSeverity");
- static int klog_fd = TEMP_FAILURE_RETRY(open("/dev/kmsg", O_WRONLY | O_CLOEXEC));
+ static int klog_fd = OpenKmsg();
if (klog_fd == -1) return;
int level = kLogSeverityToKernelLogLevel[severity];
diff --git a/fastboot/Android.mk b/fastboot/Android.mk
index 944b00b..a142b3e 100644
--- a/fastboot/Android.mk
+++ b/fastboot/Android.mk
@@ -16,14 +16,35 @@
include $(LOCAL_PATH)/../platform_tools_tool_version.mk
+fastboot_cflags := -Wall -Wextra -Werror -Wunreachable-code
+fastboot_cflags += -DFASTBOOT_VERSION="\"$(tool_version)\""
+fastboot_cflags_darwin := -Wno-unused-parameter
+fastboot_ldlibs_darwin := -lpthread -framework CoreFoundation -framework IOKit -framework Carbon
+fastboot_ldlibs_windows := -lws2_32
+# Don't add anything here, we don't want additional shared dependencies
+# on the host fastboot tool, and shared libraries that link against libc++
+# will violate ODR.
+fastboot_shared_libs :=
+fastboot_static_libs := \
+ libziparchive \
+ libsparse \
+ libutils \
+ liblog \
+ libz \
+ libdiagnose_usb \
+ libbase \
+ libcutils \
+ libgtest_host \
+
+fastboot_stl := libc++_static
+
+#
+# Build host libfastboot.
+#
+
include $(CLEAR_VARS)
-
-LOCAL_CFLAGS += -DFASTBOOT_VERSION="\"$(tool_version)\""
-
-LOCAL_C_INCLUDES := \
- $(LOCAL_PATH)/../adb \
-
-LOCAL_HEADER_LIBRARIES := bootimg_headers
+LOCAL_MODULE := libfastboot
+LOCAL_MODULE_HOST_OS := darwin linux windows
LOCAL_SRC_FILES := \
bootimg_utils.cpp \
@@ -36,49 +57,51 @@
udp.cpp \
util.cpp \
-LOCAL_MODULE := fastboot
-LOCAL_MODULE_TAGS := debug
-LOCAL_MODULE_HOST_OS := darwin linux windows
-LOCAL_CFLAGS += -Wall -Wextra -Werror -Wunreachable-code
-LOCAL_REQUIRED_MODULES := mke2fs make_f2fs
-
-LOCAL_SRC_FILES_linux := usb_linux.cpp
-LOCAL_STATIC_LIBRARIES_linux := libselinux
-LOCAL_REQUIRED_MODULES_linux := e2fsdroid mke2fs.conf sload_f2fs
-
LOCAL_SRC_FILES_darwin := usb_osx.cpp
-LOCAL_STATIC_LIBRARIES_darwin := libselinux
-LOCAL_REQUIRED_MODULES_darwin := e2fsdroid mke2fs.conf sload_f2fs
-LOCAL_LDLIBS_darwin := -lpthread -framework CoreFoundation -framework IOKit -framework Carbon
-LOCAL_CFLAGS_darwin := -Wno-unused-parameter
-
+LOCAL_SRC_FILES_linux := usb_linux.cpp
LOCAL_SRC_FILES_windows := usb_windows.cpp
-LOCAL_SHARED_LIBRARIES_windows := AdbWinApi
-LOCAL_REQUIRED_MODULES_windows := AdbWinUsbApi
-LOCAL_LDLIBS_windows := -lws2_32
+
LOCAL_C_INCLUDES_windows := development/host/windows/usb/api
+LOCAL_CFLAGS := $(fastboot_cflags)
+LOCAL_CFLAGS_darwin := $(fastboot_cflags_darwin)
+LOCAL_CXX_STL := $(fastboot_stl)
+LOCAL_HEADER_LIBRARIES := bootimg_headers
+LOCAL_LDLIBS_darwin := $(fastboot_ldflags_darwin)
+LOCAL_LDLIBS_windows := $(fastboot_ldlibs_windows)
+LOCAL_SHARED_LIBRARIES := $(fastboot_shared_libs)
+LOCAL_STATIC_LIBRARIES := $(fastboot_static_libs)
+include $(BUILD_HOST_STATIC_LIBRARY)
-LOCAL_STATIC_LIBRARIES := \
- libziparchive \
- libsparse \
- libutils \
- liblog \
- libz \
- libdiagnose_usb \
- libbase \
- libcutils \
- libgtest_host \
+#
+# Build host fastboot / fastboot.exe
+#
-LOCAL_CXX_STL := libc++_static
+include $(CLEAR_VARS)
+LOCAL_MODULE := fastboot
+LOCAL_MODULE_HOST_OS := darwin linux windows
-# Don't add anything here, we don't want additional shared dependencies
-# on the host fastboot tool, and shared libraries that link against libc++
-# will violate ODR
-LOCAL_SHARED_LIBRARIES :=
-
+LOCAL_CFLAGS := $(fastboot_cflags)
+LOCAL_CFLAGS_darwin := $(fastboot_cflags_darwin)
+LOCAL_CXX_STL := $(fastboot_stl)
+LOCAL_LDLIBS_darwin := $(fastboot_ldflags_darwin)
+LOCAL_LDLIBS_windows := $(fastboot_ldlibs_windows)
+LOCAL_REQUIRED_MODULES := mke2fs make_f2fs
+LOCAL_REQUIRED_MODULES_darwin := e2fsdroid mke2fs.conf sload_f2fs
+LOCAL_REQUIRED_MODULES_linux := e2fsdroid mke2fs.conf sload_f2fs
+LOCAL_REQUIRED_MODULES_windows := AdbWinUsbApi
+LOCAL_SRC_FILES := main.cpp
+LOCAL_SHARED_LIBRARIES := $(fastboot_shared_libs)
+LOCAL_SHARED_LIBRARIES_windows := AdbWinApi
+LOCAL_STATIC_LIBRARIES := libfastboot $(fastboot_static_libs)
+LOCAL_STATIC_LIBRARIES_darwin := libselinux
+LOCAL_STATIC_LIBRARIES_linux := libselinux
include $(BUILD_HOST_EXECUTABLE)
-my_dist_files := $(LOCAL_BUILT_MODULE)
+#
+# Package fastboot-related executables.
+#
+
+my_dist_files := $(HOST_OUT_EXECUTABLES)/fastboot
my_dist_files += $(HOST_OUT_EXECUTABLES)/mke2fs$(HOST_EXECUTABLE_SUFFIX)
my_dist_files += $(HOST_OUT_EXECUTABLES)/e2fsdroid$(HOST_EXECUTABLE_SUFFIX)
my_dist_files += $(HOST_OUT_EXECUTABLES)/make_f2fs$(HOST_EXECUTABLE_SUFFIX)
@@ -90,38 +113,24 @@
endif
my_dist_files :=
-ifeq ($(HOST_OS),linux)
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := usbtest.cpp usb_linux.cpp util.cpp
-LOCAL_MODULE := usbtest
-LOCAL_CFLAGS := -Werror
-LOCAL_STATIC_LIBRARIES := libbase
-include $(BUILD_HOST_EXECUTABLE)
-endif
+#
+# Build host fastboot_test.
+#
-# fastboot_test
-# =========================================================
include $(CLEAR_VARS)
-
LOCAL_MODULE := fastboot_test
LOCAL_MODULE_HOST_OS := darwin linux windows
LOCAL_SRC_FILES := \
- socket.cpp \
socket_mock.cpp \
socket_test.cpp \
- tcp.cpp \
tcp_test.cpp \
- udp.cpp \
udp_test.cpp \
-LOCAL_STATIC_LIBRARIES := libbase libcutils
-
-LOCAL_CFLAGS += -Wall -Wextra -Werror -Wunreachable-code
-
-LOCAL_LDLIBS_darwin := -lpthread -framework CoreFoundation -framework IOKit -framework Carbon
-LOCAL_CFLAGS_darwin := -Wno-unused-parameter
-
-LOCAL_LDLIBS_windows := -lws2_32
-
+LOCAL_CFLAGS := $(fastboot_cflags)
+LOCAL_CFLAGS_darwin := $(fastboot_cflags_darwin)
+LOCAL_CXX_STL := $(fastboot_stl)
+LOCAL_LDLIBS_darwin := $(fastboot_ldflags_darwin)
+LOCAL_LDLIBS_windows := $(fastboot_ldlibs_windows)
+LOCAL_STATIC_LIBRARIES := libfastboot $(fastboot_static_libs)
include $(BUILD_HOST_NATIVE_TEST)
diff --git a/fastboot/bootimg_utils.cpp b/fastboot/bootimg_utils.cpp
index 23443ec..feacaa1 100644
--- a/fastboot/bootimg_utils.cpp
+++ b/fastboot/bootimg_utils.cpp
@@ -34,16 +34,15 @@
#include <stdlib.h>
#include <string.h>
-void bootimg_set_cmdline(boot_img_hdr_v1* h, const char* cmdline) {
- if (strlen(cmdline) >= sizeof(h->cmdline)) die("command line too large: %zu", strlen(cmdline));
- strcpy(reinterpret_cast<char*>(h->cmdline), cmdline);
+void bootimg_set_cmdline(boot_img_hdr_v1* h, const std::string& cmdline) {
+ if (cmdline.size() >= sizeof(h->cmdline)) die("command line too large: %zu", cmdline.size());
+ strcpy(reinterpret_cast<char*>(h->cmdline), cmdline.c_str());
}
-boot_img_hdr_v1* mkbootimg(void* kernel, int64_t kernel_size, off_t kernel_offset, void* ramdisk,
- int64_t ramdisk_size, off_t ramdisk_offset, void* second,
- int64_t second_size, off_t second_offset, size_t page_size, size_t base,
- off_t tags_offset, uint32_t header_version, int64_t* bootimg_size) {
- size_t page_mask = page_size - 1;
+boot_img_hdr_v1* mkbootimg(void* kernel, int64_t kernel_size, void* ramdisk, int64_t ramdisk_size,
+ void* second, int64_t second_size, size_t base,
+ const boot_img_hdr_v1& src, int64_t* bootimg_size) {
+ const size_t page_mask = src.page_size - 1;
int64_t header_actual = sizeof(boot_img_hdr_v1) & (~page_mask);
int64_t kernel_actual = (kernel_size + page_mask) & (~page_mask);
@@ -53,30 +52,26 @@
*bootimg_size = header_actual + kernel_actual + ramdisk_actual + second_actual;
boot_img_hdr_v1* hdr = reinterpret_cast<boot_img_hdr_v1*>(calloc(*bootimg_size, 1));
- if (hdr == nullptr) {
- return hdr;
- }
+ if (hdr == nullptr) die("couldn't allocate boot image: %" PRId64 " bytes", *bootimg_size);
+ *hdr = src;
memcpy(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE);
hdr->kernel_size = kernel_size;
hdr->ramdisk_size = ramdisk_size;
hdr->second_size = second_size;
- hdr->kernel_addr = base + kernel_offset;
- hdr->ramdisk_addr = base + ramdisk_offset;
- hdr->second_addr = base + second_offset;
- hdr->tags_addr = base + tags_offset;
+ hdr->kernel_addr += base;
+ hdr->ramdisk_addr += base;
+ hdr->second_addr += base;
+ hdr->tags_addr += base;
- hdr->page_size = page_size;
-
- if (header_version) {
- hdr->header_version = header_version;
+ if (hdr->header_version != 0) {
hdr->header_size = sizeof(boot_img_hdr_v1);
}
- memcpy(hdr->magic + page_size, kernel, kernel_size);
- memcpy(hdr->magic + page_size + kernel_actual, ramdisk, ramdisk_size);
- memcpy(hdr->magic + page_size + kernel_actual + ramdisk_actual, second, second_size);
+ memcpy(hdr->magic + hdr->page_size, kernel, kernel_size);
+ memcpy(hdr->magic + hdr->page_size + kernel_actual, ramdisk, ramdisk_size);
+ memcpy(hdr->magic + hdr->page_size + kernel_actual + ramdisk_actual, second, second_size);
return hdr;
}
diff --git a/fastboot/bootimg_utils.h b/fastboot/bootimg_utils.h
index d3993f5..fe805b0 100644
--- a/fastboot/bootimg_utils.h
+++ b/fastboot/bootimg_utils.h
@@ -26,17 +26,15 @@
* SUCH DAMAGE.
*/
-#ifndef _FASTBOOT_BOOTIMG_UTILS_H_
-#define _FASTBOOT_BOOTIMG_UTILS_H_
+#pragma once
#include <bootimg.h>
#include <inttypes.h>
#include <sys/types.h>
-void bootimg_set_cmdline(boot_img_hdr_v1* h, const char* cmdline);
-boot_img_hdr_v1* mkbootimg(void* kernel, int64_t kernel_size, off_t kernel_offset, void* ramdisk,
- int64_t ramdisk_size, off_t ramdisk_offset, void* second,
- int64_t second_size, off_t second_offset, size_t page_size, size_t base,
- off_t tags_offset, uint32_t header_version, int64_t* bootimg_size);
+#include <string>
-#endif
+boot_img_hdr_v1* mkbootimg(void* kernel, int64_t kernel_size, void* ramdisk, int64_t ramdisk_size,
+ void* second, int64_t second_size, size_t base,
+ const boot_img_hdr_v1& src, int64_t* bootimg_size);
+void bootimg_set_cmdline(boot_img_hdr_v1* h, const std::string& cmdline);
diff --git a/fastboot/engine.cpp b/fastboot/engine.cpp
index 551ddba..f271d09 100644
--- a/fastboot/engine.cpp
+++ b/fastboot/engine.cpp
@@ -42,6 +42,8 @@
#include <android-base/stringprintf.h>
+#include "transport.h"
+
enum Op {
OP_DOWNLOAD,
OP_COMMAND,
diff --git a/fastboot/fastboot.bash b/fastboot/fastboot.bash
new file mode 100644
index 0000000..dca3b4e
--- /dev/null
+++ b/fastboot/fastboot.bash
@@ -0,0 +1,182 @@
+# /* vim: set ai ts=4 ft=sh: */
+#
+# Copyright 2017, 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.
+#
+
+_fastboot() {
+ if ! type -t "$1" >/dev/null; then
+ return
+ fi
+
+ if type -t _init_completion >/dev/null; then
+ _init_completion || return
+ fi
+
+ local where i cur serial
+ COMPREPLY=()
+
+ serial="${ANDROID_SERIAL:-none}"
+ where=OPTIONS
+ for ((i=1; i <= COMP_CWORD; i++)); do
+ cur="${COMP_WORDS[i]}"
+ case "${cur}" in
+ -s)
+ where=OPT_SERIAL
+ ;;
+ --slot)
+ where=OPT_SLOT
+ ;;
+ -*)
+ where=OPTIONS
+ ;;
+ *)
+ if [[ $where == OPT_SERIAL ]]; then
+ where=OPT_SERIAL_ARG
+ serial=${cur}
+ elif [[ $where == OPT_SLOT ]]; then
+ where=OPT_SLOT_ARG
+ else
+ where=COMMAND
+ break
+ fi
+ ;;
+ esac
+ done
+
+ if [[ $where == COMMAND && $i -ge $COMP_CWORD ]]; then
+ where=OPTIONS
+ fi
+
+ OPTIONS="-a -c --disable-verification --disable-verity -h --help -s --set-active --skip-secondary --skip-reboot --slot -u --version -w"
+ COMMAND="continue devices erase flash flashall flashing format getvar get_staged help oem reboot stage update"
+
+ case $where in
+ OPTIONS|OPT_SERIAL)
+ COMPREPLY=( $(compgen -W "$OPTIONS $COMMAND" -- "$cur") )
+ ;;
+ OPT_SERIAL_ARG)
+ local devices=$(command fastboot devices 2> /dev/null | awk '{ print $1 }')
+ COMPREPLY=( $(compgen -W "${devices}" -- ${cur}) )
+ ;;
+ OPT_SLOT_ARG)
+ local slots="a all b other"
+ COMPREPLY=( $(compgen -W "${slots}" -- ${cur}) )
+ ;;
+ COMMAND)
+ if [[ $i -eq $COMP_CWORD ]]; then
+ COMPREPLY=( $(compgen -W "$COMMAND" -- "$cur") )
+ else
+ i=$((i+1))
+ case "${cur}" in
+ flash)
+ _fastboot_cmd_flash "$serial" $i
+ ;;
+ reboot)
+ if [[ $COMP_CWORD == $i ]]; then
+ args="bootloader"
+ COMPREPLY=( $(compgen -W "${args}" -- "${COMP_WORDS[i]}") )
+ fi
+ ;;
+ update)
+ _fastboot_cmd_update "$serial" $i
+ ;;
+ esac
+ fi
+ ;;
+ esac
+
+ return 0
+}
+
+_fastboot_cmd_flash() {
+ local serial i cur
+ local partitions
+
+ serial=$1
+ i=$2
+
+ cur="${COMP_WORDS[COMP_CWORD]}"
+ if [[ $i -eq $COMP_CWORD ]]; then
+ partitions="boot bootloader dtbo modem odm oem product radio recovery system vbmeta vendor"
+ COMPREPLY=( $(compgen -W "$partitions" -- $cur) )
+ else
+ _fastboot_util_complete_local_file "${cur}" '!*.img'
+ fi
+}
+
+_fastboot_cmd_update() {
+ local serial i cur
+
+ serial=$1
+ i=$2
+
+ cur="${COMP_WORDS[COMP_CWORD]}"
+
+ _fastboot_util_complete_local_file "${cur}" '!*.zip'
+}
+
+_fastboot_util_complete_local_file() {
+ local file xspec i j IFS=$'\n'
+ local -a dirs files
+
+ file=$1
+ xspec=$2
+
+ # Since we're probably doing file completion here, don't add a space after.
+ if [[ $(type -t compopt) = "builtin" ]]; then
+ compopt -o plusdirs
+ if [[ "${xspec}" == "" ]]; then
+ COMPREPLY=( ${COMPREPLY[@]:-} $(compgen -f -- "${cur}") )
+ else
+ compopt +o filenames
+ COMPREPLY=( ${COMPREPLY[@]:-} $(compgen -f -X "${xspec}" -- "${cur}") )
+ fi
+ else
+ # Work-around for shells with no compopt
+
+ dirs=( $(compgen -d -- "${cur}" ) )
+
+ if [[ "${xspec}" == "" ]]; then
+ files=( ${COMPREPLY[@]:-} $(compgen -f -- "${cur}") )
+ else
+ files=( ${COMPREPLY[@]:-} $(compgen -f -X "${xspec}" -- "${cur}") )
+ fi
+
+ COMPREPLY=( $(
+ for i in "${files[@]}"; do
+ local skip=
+ for j in "${dirs[@]}"; do
+ if [[ $i == $j ]]; then
+ skip=1
+ break
+ fi
+ done
+ [[ -n $skip ]] || printf "%s\n" "$i"
+ done
+ ))
+
+ COMPREPLY=( ${COMPREPLY[@]:-} $(
+ for i in "${dirs[@]}"; do
+ printf "%s/\n" "$i"
+ done
+ ))
+ fi
+}
+
+if [[ $(type -t compopt) = "builtin" ]]; then
+ complete -F _fastboot fastboot
+else
+ complete -o nospace -F _fastboot fastboot
+fi
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index c5b357c..42f4fbb 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -76,9 +76,9 @@
char cur_product[FB_RESPONSE_SZ + 1];
static const char* serial = nullptr;
-static const char* cmdline = nullptr;
+
static unsigned short vendor_id = 0;
-static int long_listing = 0;
+static bool g_long_listing = false;
// Don't resparse files in too-big chunks.
// libsparse will support INT_MAX, but this results in large allocations, so
// let's keep it at 1GB to avoid memory pressure on the host.
@@ -86,12 +86,9 @@
static int64_t sparse_limit = -1;
static int64_t target_sparse_limit = -1;
-static unsigned page_size = 2048;
-static unsigned base_addr = 0x10000000;
-static unsigned kernel_offset = 0x00008000;
-static unsigned ramdisk_offset = 0x01000000;
-static unsigned second_offset = 0x00f00000;
-static unsigned tags_offset = 0x00000100;
+static unsigned g_base_addr = 0x10000000;
+static boot_img_hdr_v1 g_boot_img_hdr = {};
+static std::string g_cmdline;
static bool g_disable_verity = false;
static bool g_disable_verification = false;
@@ -223,7 +220,7 @@
serial = "????????????";
}
// output compatible with "adb devices"
- if (!long_listing) {
+ if (!g_long_listing) {
printf("%s\tfastboot", serial.c_str());
} else {
printf("%-22s fastboot", serial.c_str());
@@ -326,126 +323,89 @@
// clang-format off
fprintf(stdout,
/* 1234567890123456789012345678901234567890123456789012345678901234567890123456 */
- "usage: fastboot [ <option> ] <command>\n"
+ "usage: fastboot [OPTION...] COMMAND...\n"
"\n"
- "commands:\n"
- " update <filename> Reflash device from update.zip.\n"
- " Sets the flashed slot as active.\n"
- " flashall Flash boot, system, vendor, and --\n"
- " if found -- recovery. If the device\n"
- " supports slots, the slot that has\n"
- " been flashed to is set as active.\n"
- " Secondary images may be flashed to\n"
- " an inactive slot.\n"
- " flash <partition> [ <filename> ] Write a file to a flash partition.\n"
- " flashing lock Locks the device. Prevents flashing.\n"
- " flashing unlock Unlocks the device. Allows flashing\n"
- " any partition except\n"
- " bootloader-related partitions.\n"
- " flashing lock_critical Prevents flashing bootloader-related\n"
- " partitions.\n"
- " flashing unlock_critical Enables flashing bootloader-related\n"
- " partitions.\n"
- " flashing get_unlock_ability Queries bootloader to see if the\n"
- " device is unlocked.\n"
- " flashing get_unlock_bootloader_nonce Queries the bootloader to get the\n"
- " unlock nonce.\n"
- " flashing unlock_bootloader <request> Issue unlock bootloader using request.\n"
- " flashing lock_bootloader Locks the bootloader to prevent\n"
- " bootloader version rollback.\n"
- " erase <partition> Erase a flash partition.\n"
- " format[:[<fs type>][:[<size>]] <partition>\n"
- " Format a flash partition. Can\n"
- " override the fs type and/or size\n"
- " the bootloader reports.\n"
- " getvar <variable> Display a bootloader variable.\n"
- " set_active <slot> Sets the active slot. If slots are\n"
- " not supported, this does nothing.\n"
- " boot <kernel> [ <ramdisk> [ <second> ] ] Download and boot kernel.\n"
- " flash:raw <bootable-partition> <kernel> [ <ramdisk> [ <second> ] ]\n"
- " Create bootimage and flash it.\n"
- " devices [-l] List all connected devices [with\n"
- " device paths].\n"
- " continue Continue with autoboot.\n"
- " reboot [bootloader|emergency] Reboot device [into bootloader or emergency mode].\n"
- " reboot-bootloader Reboot device into bootloader.\n"
- " oem <parameter1> ... <parameterN> Executes oem specific command.\n"
- " stage <infile> Sends contents of <infile> to stage for\n"
- " the next command. Supported only on\n"
- " Android Things devices.\n"
- " get_staged <outfile> Receives data to <outfile> staged by the\n"
- " last command. Supported only on Android\n"
- " Things devices.\n"
- " help Show this help message.\n"
+ "flashing:\n"
+ " update ZIP Flash all partitions from an update.zip package.\n"
+ " flashall Flash all partitions from $ANDROID_PRODUCT_OUT.\n"
+ " On A/B devices, flashed slot is set as active.\n"
+ " Secondary images may be flashed to inactive slot.\n"
+ " flash PARTITION [FILENAME]\n"
+ " Flash given partition only.\n"
+ "\n"
+ "basics:\n"
+ " devices [-l] List devices in bootloader (-l: with device paths).\n"
+ " getvar NAME Display given bootloader variable.\n"
+ " reboot [bootloader] Reboot device.\n"
+ "\n"
+ "locking/unlocking:\n"
+ " flashing lock|unlock Lock/unlock partitions for flashing\n"
+ " flashing lock_critical|unlock_critical\n"
+ " Lock/unlock 'critical' bootloader partitions.\n"
+ " flashing get_unlock_ability\n"
+ " Check whether unlocking is allowed (1) or not(0).\n"
+ "\n"
+ "advanced:\n"
+ " erase PARTITION Erase a flash partition.\n"
+ " format[:FS_TYPE[:SIZE]] PARTITION\n"
+ " Format a flash partition.\n"
+ " set_active SLOT Set the active slot.\n"
+ " oem [COMMAND...] Execute OEM-specific command.\n"
+ "\n"
+ "boot image:\n"
+ " boot KERNEL [RAMDISK [SECOND]]\n"
+ " Download and boot kernel from RAM.\n"
+ " flash:raw PARTITION KERNEL [RAMDISK [SECOND]]\n"
+ " Create boot image and flash it.\n"
+ " --cmdline CMDLINE Override kernel command line.\n"
+ " --base ADDRESS Set kernel base address (default: 0x10000000).\n"
+ " --kernel-offset Set kernel offset (default: 0x00008000).\n"
+ " --ramdisk-offset Set ramdisk offset (default: 0x01000000).\n"
+ " --tags-offset Set tags offset (default: 0x00000100).\n"
+ " --page-size BYTES Set flash page size (default: 2048).\n"
+ " --header-version VERSION Set boot image header version.\n"
+ " --os-version MAJOR[.MINOR[.PATCH]]\n"
+ " Set boot image OS version (default: 0.0.0).\n"
+ " --os-patch-level YYYY-MM-DD\n"
+ " Set boot image OS security patch level.\n"
+ // TODO: still missing: `second_addr`, `name`, `id`, `recovery_dtbo_*`.
+ "\n"
+ // TODO: what device(s) used this? is there any documentation?
+ //" continue Continue with autoboot.\n"
+ //"\n"
+ "Android Things:\n"
+ " stage IN_FILE Sends given file to stage for the next command.\n"
+ " get_staged OUT_FILE Writes data staged by the last command to a file.\n"
"\n"
"options:\n"
- " -w Erase userdata and cache (and format\n"
- " if supported by partition type).\n"
- " -u Do not erase partition before\n"
- " formatting.\n"
- " -s <specific device> Specify a device. For USB, provide either\n"
- " a serial number or path to device port.\n"
- " For ethernet, provide an address in the\n"
- " form <protocol>:<hostname>[:port] where\n"
- " <protocol> is either tcp or udp.\n"
- " -c <cmdline> Override kernel commandline.\n"
- " -i <vendor id> Specify a custom USB vendor id.\n"
- " -b, --base <base_addr> Specify a custom kernel base\n"
- " address (default: 0x10000000).\n"
- " --kernel-offset Specify a custom kernel offset.\n"
- " (default: 0x00008000)\n"
- " --ramdisk-offset Specify a custom ramdisk offset.\n"
- " (default: 0x01000000)\n"
- " --tags-offset Specify a custom tags offset.\n"
- " (default: 0x00000100)\n"
- " -n, --page-size <page size> Specify the nand page size\n"
- " (default: 2048).\n"
- " -S <size>[K|M|G] Automatically sparse files greater\n"
- " than 'size'. 0 to disable.\n"
- " --slot <slot> Specify slot name to be used if the\n"
- " device supports slots. All operations\n"
- " on partitions that support slots will\n"
- " be done on the slot specified.\n"
- " 'all' can be given to refer to all slots.\n"
- " 'other' can be given to refer to a\n"
- " non-current slot. If this flag is not\n"
- " used, slotted partitions will default\n"
- " to the current active slot.\n"
- " -a, --set-active[=<slot>] Sets the active slot. If no slot is\n"
- " provided, this will default to the value\n"
- " given by --slot. If slots are not\n"
- " supported, this does nothing. This will\n"
- " run after all non-reboot commands.\n"
- " --skip-secondary Will not flash secondary slots when\n"
- " performing a flashall or update. This\n"
- " will preserve data on other slots.\n"
- " --skip-reboot Will not reboot the device when\n"
- " performing commands that normally\n"
- " trigger a reboot.\n"
- " --disable-verity Set the disable-verity flag in the\n"
- " the vbmeta image being flashed.\n"
- " --disable-verification Set the disable-verification flag in\n"
- " the vbmeta image being flashed.\n"
+ " -w Wipe userdata.\n"
+ " -s SERIAL Specify a USB device.\n"
+ " -s tcp|udp:HOST[:PORT] Specify a network device.\n"
+ // TODO: remove -i?
+ " -i VENDOR_ID Filter devices by USB vendor id.\n"
+ " -S SIZE[K|M|G] Use sparse files above this limit (0 to disable).\n"
+ " --slot SLOT Use SLOT; 'all' for both slots, 'other' for\n"
+ " non-current slot (default: current active slot).\n"
+ " --set-active[=SLOT] Sets the active slot before rebooting.\n"
+ " --skip-secondary Don't flash secondary slots in flashall/update.\n"
+ " --skip-reboot Don't reboot device after flashing.\n"
+ " --disable-verity Sets disable-verity when flashing vbmeta.\n"
+ " --disable-verification Sets disable-verification when flashing vbmeta.\n"
#if !defined(_WIN32)
- " --wipe-and-use-fbe On devices which support it,\n"
- " erase userdata and cache, and\n"
- " enable file-based encryption\n"
+ " --wipe-and-use-fbe Enable file-based encryption, wiping userdata.\n"
#endif
- " --unbuffered Do not buffer input or output.\n"
- " -v, --verbose Verbose output.\n"
- " --version Display version.\n"
- " --header-version Set boot image header version while\n"
- " using flash:raw and boot commands to \n"
- " to create a boot image.\n"
- " -h, --help show this message.\n"
+ // TODO: remove --unbuffered?
+ " --unbuffered Don't buffer input or output.\n"
+ " --verbose, -v Verbose output.\n"
+ " --version Display version.\n"
+ " --help, -h Show this message.\n"
);
// clang-format off
return 0;
}
static void* load_bootable_image(const std::string& kernel, const std::string& ramdisk,
- const std::string& second_stage, int64_t* sz,
- const char* cmdline, uint32_t header_version) {
+ const std::string& second_stage, int64_t* sz) {
int64_t ksize;
void* kdata = load_file(kernel.c_str(), &ksize);
if (kdata == nullptr) die("cannot load '%s': %s", kernel.c_str(), strerror(errno));
@@ -455,12 +415,14 @@
die("cannot load '%s': too short", kernel.c_str());
}
if (!memcmp(kdata, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
- if (cmdline) bootimg_set_cmdline(reinterpret_cast<boot_img_hdr_v1*>(kdata), cmdline);
+ if (!g_cmdline.empty()) {
+ bootimg_set_cmdline(reinterpret_cast<boot_img_hdr_v1*>(kdata), g_cmdline);
+ }
uint32_t header_version_existing =
reinterpret_cast<boot_img_hdr_v1*>(kdata)->header_version;
- if (header_version != header_version_existing) {
+ if (g_boot_img_hdr.header_version != header_version_existing) {
die("header version mismatch, expected: %" PRIu32 " found %" PRIu32 "",
- header_version, header_version_existing);
+ g_boot_img_hdr.header_version, header_version_existing);
}
if (!ramdisk.empty()) die("cannot boot a boot.img *and* ramdisk");
@@ -484,16 +446,12 @@
}
fprintf(stderr,"creating boot image...\n");
- int64_t bsize = 0;
- boot_img_hdr_v1* bdata = mkbootimg(kdata, ksize, kernel_offset,
- rdata, rsize, ramdisk_offset,
- sdata, ssize, second_offset,
- page_size, base_addr, tags_offset, header_version, &bsize);
+ boot_img_hdr_v1* bdata = mkbootimg(kdata, ksize, rdata, rsize, sdata, ssize,
+ g_base_addr, g_boot_img_hdr, sz);
if (bdata == nullptr) die("failed to create boot.img");
- if (cmdline) bootimg_set_cmdline(bdata, cmdline);
- fprintf(stderr, "creating boot image - %" PRId64 " bytes\n", bsize);
- *sz = bsize;
+ if (!g_cmdline.empty()) bootimg_set_cmdline(bdata, g_cmdline);
+ fprintf(stderr, "creating boot image - %" PRId64 " bytes\n", *sz);
return bdata;
}
@@ -810,17 +768,6 @@
return 0;
}
-// Until we get lazy inode table init working in make_ext4fs, we need to
-// erase partitions of type ext4 before flashing a filesystem so no stale
-// inodes are left lying around. Otherwise, e2fsck gets very upset.
-static bool needs_erase(Transport* transport, const char* partition) {
- std::string partition_type;
- if (!fb_getvar(transport, std::string("partition-type:") + partition, &partition_type)) {
- return false;
- }
- return partition_type == "ext4";
-}
-
static bool load_buf_fd(Transport* transport, int fd, struct fastboot_buffer* buf) {
int64_t sz = get_file_size(fd);
if (sz == -1) {
@@ -1134,7 +1081,7 @@
}
}
-static void do_update(Transport* transport, const char* filename, const std::string& slot_override, bool erase_first, bool skip_secondary) {
+static void do_update(Transport* transport, const char* filename, const std::string& slot_override, bool skip_secondary) {
queue_info_dump();
fb_queue_query_save("product", cur_product, sizeof(cur_product));
@@ -1192,9 +1139,6 @@
auto update = [&](const std::string& partition) {
do_update_signature(zip, images[i].sig_name);
- if (erase_first && needs_erase(transport, partition.c_str())) {
- fb_queue_erase(partition);
- }
flash_buf(partition.c_str(), &buf);
/* not closing the fd here since the sparse code keeps the fd around
* but hasn't mmaped data yet. The temporary file will get cleaned up when the
@@ -1227,7 +1171,7 @@
fb_queue_command("signature", "installing signature");
}
-static void do_flashall(Transport* transport, const std::string& slot_override, int erase_first, bool skip_secondary) {
+static void do_flashall(Transport* transport, const std::string& slot_override, bool skip_secondary) {
std::string fname;
queue_info_dump();
@@ -1274,9 +1218,6 @@
auto flashall = [&](const std::string &partition) {
do_send_signature(fname.c_str());
- if (erase_first && needs_erase(transport, partition.c_str())) {
- fb_queue_erase(partition);
- }
flash_buf(partition.c_str(), &buf);
};
do_for_partitions(transport, images[i].part_name, slot, flashall, false);
@@ -1296,18 +1237,6 @@
return result;
}
-static void do_bypass_unlock_command(std::vector<std::string>* args) {
- if (args->empty()) syntax_error("missing unlock_bootloader request");
-
- std::string filename = next_arg(args);
-
- int64_t sz;
- void* data = load_file(filename.c_str(), &sz);
- if (data == nullptr) die("could not load '%s': %s", filename.c_str(), strerror(errno));
- fb_queue_download("unlock_message", data, sz);
- fb_queue_command("flashing unlock_bootloader", "unlocking bootloader");
-}
-
static void do_oem_command(const std::string& cmd, std::vector<std::string>* args) {
if (args->empty()) syntax_error("empty oem command");
@@ -1481,46 +1410,46 @@
fprintf(stderr, "FAILED (%s)\n", fb_get_error().c_str());
}
-int main(int argc, char **argv)
-{
+int FastBoot::Main(int argc, char* argv[]) {
bool wants_wipe = false;
bool wants_reboot = false;
bool wants_reboot_bootloader = false;
- bool wants_reboot_emergency = false;
bool skip_reboot = false;
bool wants_set_active = false;
bool skip_secondary = false;
- bool erase_first = true;
bool set_fbe_marker = false;
void *data;
- uint32_t header_version = 0;
int64_t sz;
int longindex;
std::string slot_override;
std::string next_active;
+ g_boot_img_hdr.kernel_addr = 0x00008000;
+ g_boot_img_hdr.ramdisk_addr = 0x01000000;
+ g_boot_img_hdr.second_addr = 0x00f00000;
+ g_boot_img_hdr.tags_addr = 0x00000100;
+ g_boot_img_hdr.page_size = 2048;
+
const struct option longopts[] = {
- {"base", required_argument, 0, 'b'},
- {"kernel_offset", required_argument, 0, 'k'},
- {"kernel-offset", required_argument, 0, 'k'},
- {"page_size", required_argument, 0, 'n'},
- {"page-size", required_argument, 0, 'n'},
- {"ramdisk_offset", required_argument, 0, 'r'},
- {"ramdisk-offset", required_argument, 0, 'r'},
- {"tags_offset", required_argument, 0, 't'},
- {"tags-offset", required_argument, 0, 't'},
+ {"base", required_argument, 0, 0},
+ {"cmdline", required_argument, 0, 0},
+ {"disable-verification", no_argument, 0, 0},
+ {"disable-verity", no_argument, 0, 0},
+ {"header-version", required_argument, 0, 0},
{"help", no_argument, 0, 'h'},
- {"unbuffered", no_argument, 0, 0},
- {"slot", required_argument, 0, 0},
- {"set_active", optional_argument, 0, 'a'},
+ {"kernel-offset", required_argument, 0, 0},
+ {"os-patch-level", required_argument, 0, 0},
+ {"os-version", required_argument, 0, 0},
+ {"page-size", required_argument, 0, 0},
+ {"ramdisk-offset", required_argument, 0, 0},
{"set-active", optional_argument, 0, 'a'},
- {"skip-secondary", no_argument, 0, 0},
{"skip-reboot", no_argument, 0, 0},
+ {"skip-secondary", no_argument, 0, 0},
+ {"slot", required_argument, 0, 0},
+ {"tags-offset", required_argument, 0, 0},
+ {"unbuffered", no_argument, 0, 0},
{"verbose", no_argument, 0, 'v'},
{"version", no_argument, 0, 0},
- {"disable-verity", no_argument, 0, 0},
- {"disable-verification", no_argument, 0, 0},
- {"header-version", required_argument, 0, 0},
#if !defined(_WIN32)
{"wipe-and-use-fbe", no_argument, 0, 0},
#endif
@@ -1529,101 +1458,108 @@
serial = getenv("ANDROID_SERIAL");
- while (1) {
- int c = getopt_long(argc, argv, "vwub:k:n:r:t:s:S:lc:i:m:ha::", longopts, &longindex);
- if (c < 0) {
- break;
- }
- /* Alphabetical cases */
- switch (c) {
- case 'a':
- wants_set_active = true;
- if (optarg)
- next_active = optarg;
- break;
- case 'b':
- base_addr = strtoul(optarg, 0, 16);
- break;
- case 'c':
- cmdline = optarg;
- break;
- case 'h':
- return show_help();
- case 'i': {
- char *endptr = nullptr;
- unsigned long val;
-
- val = strtoul(optarg, &endptr, 0);
- if (!endptr || *endptr != '\0' || (val & ~0xffff))
- die("invalid vendor id '%s'", optarg);
- vendor_id = (unsigned short)val;
- break;
- }
- case 'k':
- kernel_offset = strtoul(optarg, 0, 16);
- break;
- case 'l':
- long_listing = 1;
- break;
- case 'n':
- page_size = (unsigned)strtoul(optarg, nullptr, 0);
- if (!page_size) die("invalid page size");
- break;
- case 'r':
- ramdisk_offset = strtoul(optarg, 0, 16);
- break;
- case 't':
- tags_offset = strtoul(optarg, 0, 16);
- break;
- case 's':
- serial = optarg;
- break;
- case 'S':
- sparse_limit = parse_num(optarg);
- if (sparse_limit < 0) die("invalid sparse limit");
- break;
- case 'u':
- erase_first = false;
- break;
- case 'v':
- set_verbose();
- break;
- case 'w':
- wants_wipe = true;
- break;
- case '?':
- return 1;
- case 0:
- if (strcmp("unbuffered", longopts[longindex].name) == 0) {
+ int c;
+ while ((c = getopt_long(argc, argv, "a::hi:ls:S:vw", longopts, &longindex)) != -1) {
+ if (c == 0) {
+ std::string name{longopts[longindex].name};
+ if (name == "base") {
+ g_base_addr = strtoul(optarg, 0, 16);
+ } else if (name == "cmdline") {
+ g_cmdline = optarg;
+ } else if (name == "disable-verification") {
+ g_disable_verification = true;
+ } else if (name == "disable-verity") {
+ g_disable_verity = true;
+ } else if (name == "header-version") {
+ g_boot_img_hdr.header_version = strtoul(optarg, nullptr, 0);
+ } else if (name == "kernel-offset") {
+ g_boot_img_hdr.kernel_addr = strtoul(optarg, 0, 16);
+ } else if (name == "os-patch-level") {
+ unsigned year, month, day;
+ if (sscanf(optarg, "%u-%u-%u", &year, &month, &day) != 3) {
+ syntax_error("OS patch level should be YYYY-MM-DD: %s", optarg);
+ }
+ if (year < 2000 || year >= 2128) syntax_error("year out of range: %d", year);
+ if (month < 1 || month > 12) syntax_error("month out of range: %d", month);
+ g_boot_img_hdr.SetOsPatchLevel(year, month);
+ } else if (name == "os-version") {
+ unsigned major = 0, minor = 0, patch = 0;
+ std::vector<std::string> versions = android::base::Split(optarg, ".");
+ if (versions.size() < 1 || versions.size() > 3 ||
+ (versions.size() >= 1 && !android::base::ParseUint(versions[0], &major)) ||
+ (versions.size() >= 2 && !android::base::ParseUint(versions[1], &minor)) ||
+ (versions.size() == 3 && !android::base::ParseUint(versions[2], &patch)) ||
+ (major > 0x7f || minor > 0x7f || patch > 0x7f)) {
+ syntax_error("bad OS version: %s", optarg);
+ }
+ g_boot_img_hdr.SetOsVersion(major, minor, patch);
+ } else if (name == "page-size") {
+ g_boot_img_hdr.page_size = strtoul(optarg, nullptr, 0);
+ if (g_boot_img_hdr.page_size == 0) die("invalid page size");
+ } else if (name == "ramdisk-offset") {
+ g_boot_img_hdr.ramdisk_addr = strtoul(optarg, 0, 16);
+ } else if (name == "skip-reboot") {
+ skip_reboot = true;
+ } else if (name == "skip-secondary") {
+ skip_secondary = true;
+ } else if (name == "slot") {
+ slot_override = optarg;
+ } else if (name == "tags-offset") {
+ g_boot_img_hdr.tags_addr = strtoul(optarg, 0, 16);
+ } else if (name == "unbuffered") {
setvbuf(stdout, nullptr, _IONBF, 0);
setvbuf(stderr, nullptr, _IONBF, 0);
- } else if (strcmp("version", longopts[longindex].name) == 0) {
+ } else if (name == "version") {
fprintf(stdout, "fastboot version %s\n", FASTBOOT_VERSION);
fprintf(stdout, "Installed as %s\n", android::base::GetExecutablePath().c_str());
return 0;
- } else if (strcmp("slot", longopts[longindex].name) == 0) {
- slot_override = std::string(optarg);
- } else if (strcmp("skip-secondary", longopts[longindex].name) == 0 ) {
- skip_secondary = true;
- } else if (strcmp("skip-reboot", longopts[longindex].name) == 0 ) {
- skip_reboot = true;
- } else if (strcmp("disable-verity", longopts[longindex].name) == 0 ) {
- g_disable_verity = true;
- } else if (strcmp("disable-verification", longopts[longindex].name) == 0 ) {
- g_disable_verification = true;
#if !defined(_WIN32)
- } else if (strcmp("wipe-and-use-fbe", longopts[longindex].name) == 0) {
+ } else if (name == "wipe-and-use-fbe") {
wants_wipe = true;
set_fbe_marker = true;
#endif
- } else if (strcmp("header-version", longopts[longindex].name) == 0) {
- header_version = strtoul(optarg, nullptr, 0);
} else {
die("unknown option %s", longopts[longindex].name);
}
- break;
- default:
- abort();
+ } else {
+ switch (c) {
+ case 'a':
+ wants_set_active = true;
+ if (optarg) next_active = optarg;
+ break;
+ case 'h':
+ return show_help();
+ case 'i':
+ {
+ char *endptr = nullptr;
+ unsigned long val = strtoul(optarg, &endptr, 0);
+ if (!endptr || *endptr != '\0' || (val & ~0xffff)) {
+ die("invalid vendor id '%s'", optarg);
+ }
+ vendor_id = (unsigned short)val;
+ break;
+ }
+ case 'l':
+ g_long_listing = true;
+ break;
+ case 's':
+ serial = optarg;
+ break;
+ case 'S':
+ sparse_limit = parse_num(optarg);
+ if (sparse_limit < 0) die("invalid sparse limit");
+ break;
+ case 'v':
+ set_verbose();
+ break;
+ case 'w':
+ wants_wipe = true;
+ break;
+ case '?':
+ return 1;
+ default:
+ abort();
+ }
}
}
@@ -1707,9 +1643,6 @@
std::string partition = next_arg(&args);
auto format = [&](const std::string& partition) {
- if (erase_first && needs_erase(transport, partition.c_str())) {
- fb_queue_erase(partition);
- }
fb_perform_format(transport, partition, 0, type_override, size_override, "");
};
do_for_partitions(transport, partition.c_str(), slot_override, format, true);
@@ -1728,9 +1661,6 @@
if (what == "bootloader") {
wants_reboot = false;
wants_reboot_bootloader = true;
- } else if (what == "emergency") {
- wants_reboot = false;
- wants_reboot_emergency = true;
} else {
syntax_error("unknown reboot target %s", what.c_str());
}
@@ -1748,7 +1678,7 @@
std::string second_stage;
if (!args.empty()) second_stage = next_arg(&args);
- data = load_bootable_image(kernel, ramdisk, second_stage, &sz, cmdline, header_version);
+ data = load_bootable_image(kernel, ramdisk, second_stage, &sz);
fb_queue_download("boot.img", data, sz);
fb_queue_command("boot", "booting");
} else if (command == "flash") {
@@ -1763,9 +1693,6 @@
if (fname.empty()) die("cannot determine image filename for '%s'", pname.c_str());
auto flash = [&](const std::string &partition) {
- if (erase_first && needs_erase(transport, partition.c_str())) {
- fb_queue_erase(partition);
- }
do_flash(transport, partition.c_str(), fname.c_str());
};
do_for_partitions(transport, pname.c_str(), slot_override, flash, true);
@@ -1777,7 +1704,7 @@
std::string second_stage;
if (!args.empty()) second_stage = next_arg(&args);
- data = load_bootable_image(kernel, ramdisk, second_stage, &sz, cmdline, header_version);
+ data = load_bootable_image(kernel, ramdisk, second_stage, &sz);
auto flashraw = [&](const std::string& partition) {
fb_queue_flash(partition, data, sz);
};
@@ -1785,9 +1712,9 @@
} else if (command == "flashall") {
if (slot_override == "all") {
fprintf(stderr, "Warning: slot set to 'all'. Secondary slots will not be flashed.\n");
- do_flashall(transport, slot_override, erase_first, true);
+ do_flashall(transport, slot_override, true);
} else {
- do_flashall(transport, slot_override, erase_first, skip_secondary);
+ do_flashall(transport, slot_override, skip_secondary);
}
wants_reboot = true;
} else if (command == "update") {
@@ -1799,8 +1726,7 @@
if (!args.empty()) {
filename = next_arg(&args);
}
- do_update(transport, filename.c_str(), slot_override, erase_first,
- skip_secondary || slot_all);
+ do_update(transport, filename.c_str(), slot_override, skip_secondary || slot_all);
wants_reboot = true;
} else if (command == "set_active") {
std::string slot = verify_slot(transport, next_arg(&args), false);
@@ -1833,12 +1759,8 @@
} else if (args.size() == 1 && (args[0] == "unlock" || args[0] == "lock" ||
args[0] == "unlock_critical" ||
args[0] == "lock_critical" ||
- args[0] == "get_unlock_ability" ||
- args[0] == "get_unlock_bootloader_nonce" ||
- args[0] == "lock_bootloader")) {
+ args[0] == "get_unlock_ability")) {
do_oem_command("flashing", &args);
- } else if (args.size() == 2 && args[0] == "unlock_bootloader") {
- do_bypass_unlock_command(&args);
} else {
syntax_error("unknown 'flashing' command %s", args[0].c_str());
}
@@ -1873,9 +1795,6 @@
} else if (wants_reboot_bootloader) {
fb_queue_command("reboot-bootloader", "rebooting into bootloader");
fb_queue_wait_for_disconnect();
- } else if (wants_reboot_emergency) {
- fb_queue_command("reboot-emergency", "rebooting into emergency download (EDL) mode");
- fb_queue_wait_for_disconnect();
}
int status = fb_execute_queue(transport) ? EXIT_FAILURE : EXIT_SUCCESS;
diff --git a/fastboot/fastboot.h b/fastboot/fastboot.h
index 005ba5a..3d5a261 100644
--- a/fastboot/fastboot.h
+++ b/fastboot/fastboot.h
@@ -34,8 +34,7 @@
#include <string>
-#include "transport.h"
-
+class Transport;
struct sparse_file;
/* protocol.c - fastboot protocol */
@@ -97,4 +96,9 @@
/* Current product */
extern char cur_product[FB_RESPONSE_SZ + 1];
+class FastBoot {
+ public:
+ int Main(int argc, char* argv[]);
+};
+
#endif
diff --git a/fastboot/main.cpp b/fastboot/main.cpp
new file mode 100644
index 0000000..f1c8afb
--- /dev/null
+++ b/fastboot/main.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "fastboot.h"
+
+int main(int argc, char* argv[]) {
+ FastBoot fb;
+ return fb.Main(argc, argv);
+}
diff --git a/fastboot/usbtest.cpp b/fastboot/usbtest.cpp
deleted file mode 100644
index 9423c6d..0000000
--- a/fastboot/usbtest.cpp
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#include <sys/time.h>
-
-#include "usb.h"
-
-static unsigned arg_size = 4096;
-static unsigned arg_count = 4096;
-
-long long NOW(void)
-{
- struct timeval tv;
- gettimeofday(&tv, 0);
-
- return (((long long) tv.tv_sec) * ((long long) 1000000)) +
- (((long long) tv.tv_usec));
-}
-
-int printifc(usb_ifc_info *info)
-{
- printf("dev: csp=%02x/%02x/%02x v=%04x p=%04x ",
- info->dev_class, info->dev_subclass, info->dev_protocol,
- info->dev_vendor, info->dev_product);
- printf("ifc: csp=%02x/%02x/%02x%s%s\n",
- info->ifc_class, info->ifc_subclass, info->ifc_protocol,
- info->has_bulk_in ? " in" : "",
- info->has_bulk_out ? " out" : "");
- return -1;
-}
-
-int match_null(usb_ifc_info *info)
-{
- if(info->dev_vendor != 0x18d1) return -1;
- if(info->ifc_class != 0xff) return -1;
- if(info->ifc_subclass != 0xfe) return -1;
- if(info->ifc_protocol != 0x01) return -1;
- return 0;
-}
-
-int match_zero(usb_ifc_info *info)
-{
- if(info->dev_vendor != 0x18d1) return -1;
- if(info->ifc_class != 0xff) return -1;
- if(info->ifc_subclass != 0xfe) return -1;
- if(info->ifc_protocol != 0x02) return -1;
- return 0;
-}
-
-int match_loop(usb_ifc_info *info)
-{
- if(info->dev_vendor != 0x18d1) return -1;
- if(info->ifc_class != 0xff) return -1;
- if(info->ifc_subclass != 0xfe) return -1;
- if(info->ifc_protocol != 0x03) return -1;
- return 0;
-}
-
-int test_null(Transport* usb)
-{
- unsigned i;
- unsigned char buf[4096];
- memset(buf, 0xee, 4096);
- long long t0, t1;
-
- t0 = NOW();
- for (i = 0; i < arg_count; i++) {
- if (usb->Write(buf, arg_size) != static_cast<int>(arg_size)) {
- fprintf(stderr,"write failed (%s)\n", strerror(errno));
- return -1;
- }
- }
- t1 = NOW();
- fprintf(stderr,"%d bytes in %lld uS\n", arg_count * arg_size, (t1 - t0));
- return 0;
-}
-
-int test_zero(Transport* usb)
-{
- unsigned i;
- unsigned char buf[4096];
- long long t0, t1;
-
- t0 = NOW();
- for (i = 0; i < arg_count; i++) {
- if (usb->Read(buf, arg_size) != static_cast<int>(arg_size)) {
- fprintf(stderr,"read failed (%s)\n", strerror(errno));
- return -1;
- }
- }
- t1 = NOW();
- fprintf(stderr,"%d bytes in %lld uS\n", arg_count * arg_size, (t1 - t0));
- return 0;
-}
-
-struct
-{
- const char *cmd;
- ifc_match_func match;
- int (*test)(Transport* usb);
- const char *help;
-} tests[] = {
- { "list", printifc, NULL, "list interfaces" },
- { "send", match_null, test_null, "send to null interface" },
- { "recv", match_zero, test_zero, "recv from zero interface" },
- { "loop", match_loop, NULL, "exercise loopback interface" },
- { NULL, NULL, NULL, NULL },
-};
-
-int usage(void)
-{
- int i;
-
- fprintf(stderr,"usage: usbtest <testname>\n\navailable tests:\n");
- for(i = 0; tests[i].cmd; i++) {
- fprintf(stderr," %-8s %s\n", tests[i].cmd, tests[i].help);
- }
- return -1;
-}
-
-int process_args(int argc, char **argv)
-{
- while(argc-- > 0) {
- char *arg = *argv++;
- if(!strncmp(arg,"count=",6)) {
- arg_count = atoi(arg + 6);
- } else if(!strncmp(arg,"size=",5)) {
- arg_size = atoi(arg + 5);
- } else {
- fprintf(stderr,"unknown argument: %s\n", arg);
- return -1;
- }
- }
-
- if(arg_count == 0) {
- fprintf(stderr,"count may not be zero\n");
- return -1;
- }
-
- if(arg_size > 4096) {
- fprintf(stderr,"size may not be greater than 4096\n");
- return -1;
- }
-
- return 0;
-}
-
-int main(int argc, char **argv)
-{
- Transport* usb;
- int i;
-
- if(argc < 2)
- return usage();
-
- if(argc > 2) {
- if(process_args(argc - 2, argv + 2))
- return -1;
- }
-
- for(i = 0; tests[i].cmd; i++) {
- if(!strcmp(argv[1], tests[i].cmd)) {
- usb = usb_open(tests[i].match);
- if(tests[i].test) {
- if(usb == 0) {
- fprintf(stderr,"usbtest: %s: could not find interface\n",
- tests[i].cmd);
- return -1;
- }
- if(tests[i].test(usb)) {
- fprintf(stderr,"usbtest: %s: FAIL\n", tests[i].cmd);
- return -1;
- } else {
- fprintf(stderr,"usbtest: %s: OKAY\n", tests[i].cmd);
- }
- }
- return 0;
- }
- }
-
- return usage();
-}
diff --git a/fs_mgr/fs_mgr_format.cpp b/fs_mgr/fs_mgr_format.cpp
index 85a593f..63a6839 100644
--- a/fs_mgr/fs_mgr_format.cpp
+++ b/fs_mgr/fs_mgr_format.cpp
@@ -114,8 +114,19 @@
}
std::string size_str = std::to_string(dev_sz / 4096);
+ // clang-format off
const char* const args[] = {
- "/system/bin/make_f2fs", "-f", "-O", "encrypt", fs_blkdev, size_str.c_str(), nullptr};
+ "/system/bin/make_f2fs",
+ "-d1",
+ "-f",
+ "-O", "encrypt",
+ "-O", "quota",
+ "-w", "4096",
+ fs_blkdev,
+ size_str.c_str(),
+ nullptr
+ };
+ // clang-format on
return android_fork_execvp_ext(arraysize(args), const_cast<char**>(args), NULL, true,
LOG_KLOG, true, nullptr, nullptr, 0);
diff --git a/init/stable_properties.h b/init/stable_properties.h
index 4714b57..cc25607 100644
--- a/init/stable_properties.h
+++ b/init/stable_properties.h
@@ -31,6 +31,7 @@
static const std::set<std::string> kExportedActionableProperties = {
"init.svc.console",
"init.svc.mediadrm",
+ "init.svc.surfaceflinger",
"init.svc.zygote",
"persist.bluetooth.btsnoopenable",
"persist.sys.crash_rcu",
@@ -50,6 +51,7 @@
"sys.user.0.ce_available",
"sys.vdso",
"vts.native_server.on",
+ "wlan.driver.status",
};
} // namespace init
diff --git a/libbinderwrapper/Android.bp b/libbinderwrapper/Android.bp
index 6fac0d8..d2487e2 100644
--- a/libbinderwrapper/Android.bp
+++ b/libbinderwrapper/Android.bp
@@ -38,6 +38,7 @@
cc_library_shared {
name: "libbinderwrapper",
defaults: ["libbinderwrapper_defaults"],
+ vendor_available: true,
srcs: [
"binder_wrapper.cc",
diff --git a/libcutils/fs_config.cpp b/libcutils/fs_config.cpp
index f6f7128..0f2b460 100644
--- a/libcutils/fs_config.cpp
+++ b/libcutils/fs_config.cpp
@@ -122,6 +122,12 @@
{odm_conf_file, odm_conf_dir},
};
+// Do not use android_files to grant Linux capabilities. Use ambient capabilities in their
+// associated init.rc file instead. See https://source.android.com/devices/tech/config/ambient.
+
+// Do not place any new vendor/, data/vendor/, etc entries in android_files.
+// Vendor entries should be done via a vendor or device specific config.fs.
+// See https://source.android.com/devices/tech/config/filesystem#using-file-system-capabilities
static const struct fs_path_config android_files[] = {
// clang-format off
{ 00644, AID_SYSTEM, AID_SYSTEM, 0, "data/app/*" },
@@ -185,24 +191,6 @@
// Support FIFO scheduling mode in SurfaceFlinger.
{ 00755, AID_SYSTEM, AID_GRAPHICS, CAP_MASK_LONG(CAP_SYS_NICE),
"system/bin/surfaceflinger" },
-
- // Support hostapd administering a network interface.
- { 00755, AID_WIFI, AID_WIFI, CAP_MASK_LONG(CAP_NET_ADMIN) |
- CAP_MASK_LONG(CAP_NET_RAW),
- "vendor/bin/hostapd" },
-
- // Support Bluetooth legacy hal accessing /sys/class/rfkill
- // Support RT scheduling in Bluetooth
- { 00700, AID_BLUETOOTH, AID_BLUETOOTH, CAP_MASK_LONG(CAP_NET_ADMIN) |
- CAP_MASK_LONG(CAP_SYS_NICE),
- "vendor/bin/hw/android.hardware.bluetooth@1.0-service" },
-
- // Support wifi_hal_legacy administering a network interface.
- { 00755, AID_WIFI, AID_WIFI, CAP_MASK_LONG(CAP_NET_ADMIN) |
- CAP_MASK_LONG(CAP_NET_RAW) |
- CAP_MASK_LONG(CAP_SYS_MODULE),
- "vendor/bin/hw/android.hardware.wifi@1.0-service" },
-
// generic defaults
{ 00755, AID_ROOT, AID_ROOT, 0, "bin/*" },
{ 00640, AID_ROOT, AID_SHELL, 0, "fstab.*" },
diff --git a/lmkd/Android.bp b/lmkd/Android.bp
index d172755..2efda86 100644
--- a/lmkd/Android.bp
+++ b/lmkd/Android.bp
@@ -3,8 +3,8 @@
srcs: ["lmkd.c"],
shared_libs: [
- "liblog",
"libcutils",
+ "liblog",
],
local_include_dirs: ["include"],
cflags: ["-Werror"],
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index 72f9f7b..f7c90ec 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -29,8 +29,8 @@
#include <sys/eventfd.h>
#include <sys/mman.h>
#include <sys/socket.h>
-#include <sys/types.h>
#include <sys/sysinfo.h>
+#include <sys/types.h>
#include <unistd.h>
#include <cutils/properties.h>
@@ -77,7 +77,7 @@
#define SYSTEM_ADJ (-900)
/* default to old in-kernel interface if no memory pressure events */
-static int use_inkernel_interface = 1;
+static bool use_inkernel_interface = true;
static bool has_inkernel_module;
/* memory pressure levels */
@@ -326,8 +326,9 @@
return;
}
- if (use_inkernel_interface)
+ if (use_inkernel_interface) {
return;
+ }
if (params.oomadj >= 900) {
soft_limit_mult = 0;
@@ -393,8 +394,9 @@
static void cmd_procremove(LMKD_CTRL_PACKET packet) {
struct lmk_procremove params;
- if (use_inkernel_interface)
+ if (use_inkernel_interface) {
return;
+ }
lmkd_pack_get_procremove(packet, ¶ms);
pid_remove(params.pid);
@@ -1205,21 +1207,28 @@
kill_timeout_ms =
(unsigned long)property_get_int32("ro.lmk.kill_timeout_ms", 0);
- // MCL_ONFAULT pins pages as they fault instead of loading
- // everything immediately all at once. (Which would be bad,
- // because as of this writing, we have a lot of mapped pages we
- // never use.) Old kernels will see MCL_ONFAULT and fail with
- // EINVAL; we ignore this failure.
- //
- // N.B. read the man page for mlockall. MCL_CURRENT | MCL_ONFAULT
- // pins ⊆ MCL_CURRENT, converging to just MCL_CURRENT as we fault
- // in pages.
- if (mlockall(MCL_CURRENT | MCL_FUTURE | MCL_ONFAULT) && errno != EINVAL)
- ALOGW("mlockall failed: errno=%d", errno);
+ if (!init()) {
+ if (!use_inkernel_interface) {
+ /*
+ * MCL_ONFAULT pins pages as they fault instead of loading
+ * everything immediately all at once. (Which would be bad,
+ * because as of this writing, we have a lot of mapped pages we
+ * never use.) Old kernels will see MCL_ONFAULT and fail with
+ * EINVAL; we ignore this failure.
+ *
+ * N.B. read the man page for mlockall. MCL_CURRENT | MCL_ONFAULT
+ * pins ⊆ MCL_CURRENT, converging to just MCL_CURRENT as we fault
+ * in pages.
+ */
+ if (mlockall(MCL_CURRENT | MCL_FUTURE | MCL_ONFAULT) && (errno != EINVAL)) {
+ ALOGW("mlockall failed %s", strerror(errno));
+ }
- sched_setscheduler(0, SCHED_FIFO, ¶m);
- if (!init())
+ sched_setscheduler(0, SCHED_FIFO, ¶m);
+ }
+
mainloop();
+ }
ALOGI("exiting");
return 0;
diff --git a/lmkd/tests/lmkd_test.cpp b/lmkd/tests/lmkd_test.cpp
index f17512d..8c7a75f 100644
--- a/lmkd/tests/lmkd_test.cpp
+++ b/lmkd/tests/lmkd_test.cpp
@@ -210,6 +210,13 @@
pid_t pid;
uid_t uid = getuid();
+ // check if in-kernel LMK driver is present
+ if (!access(INKERNEL_MINFREE_PATH, W_OK)) {
+ GTEST_LOG_(INFO) << "Must not have kernel lowmemorykiller driver,"
+ << " terminating test";
+ return;
+ }
+
ASSERT_FALSE((sock = lmkd_connect()) < 0)
<< "Failed to connect to lmkd process, err=" << strerror(errno);
@@ -282,12 +289,6 @@
GTEST_LOG_(INFO) << "Must be userdebug build, terminating test";
return;
}
- // check if in-kernel LMK driver is present
- if (!access(INKERNEL_MINFREE_PATH, W_OK)) {
- GTEST_LOG_(INFO) << "Must not have kernel lowmemorykiller driver,"
- << " terminating test";
- return;
- }
// if respawned test process then run the test and exit (no analysis)
if (getenv(LMKDTEST_RESPAWN_FLAG) != NULL) {
diff --git a/mkbootimg/include/bootimg/bootimg.h b/mkbootimg/include/bootimg/bootimg.h
index 4311b46..406e208 100644
--- a/mkbootimg/include/bootimg/bootimg.h
+++ b/mkbootimg/include/bootimg/bootimg.h
@@ -1,37 +1,33 @@
-/* tools/mkbootimg/bootimg.h
-**
-** Copyright 2007, 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.
-*/
+/*
+ * Copyright (C) 2007 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 <stdint.h>
-#ifndef _BOOT_IMAGE_H_
-#define _BOOT_IMAGE_H_
-
#define BOOT_MAGIC "ANDROID!"
#define BOOT_MAGIC_SIZE 8
#define BOOT_NAME_SIZE 16
#define BOOT_ARGS_SIZE 512
#define BOOT_EXTRA_ARGS_SIZE 1024
-#define BOOT_HEADER_VERSION_ZERO 0
-/*
- * Bootloader expects the structure of boot_img_hdr with header version
- * BOOT_HEADER_VERSION_ZERO to be as follows:
- */
+// The bootloader expects the structure of boot_img_hdr with header
+// version 0 to be as follows:
struct boot_img_hdr_v0 {
+ // Must be BOOT_MAGIC.
uint8_t magic[BOOT_MAGIC_SIZE];
uint32_t kernel_size; /* size in bytes */
@@ -45,26 +41,36 @@
uint32_t tags_addr; /* physical addr for kernel tags */
uint32_t page_size; /* flash page size we assume */
- /*
- * version for the boot image header.
- */
+
+ // Version of the boot image header.
uint32_t header_version;
- /* operating system version and security patch level; for
- * version "A.B.C" and patch level "Y-M-D":
- * ver = A << 14 | B << 7 | C (7 bits for each of A, B, C)
- * lvl = ((Y - 2000) & 127) << 4 | M (7 bits for Y, 4 bits for M)
- * os_version = ver << 11 | lvl */
+ // Operating system version and security patch level.
+ // For version "A.B.C" and patch level "Y-M-D":
+ // (7 bits for each of A, B, C; 7 bits for (Y-2000), 4 bits for M)
+ // os_version = A[31:25] B[24:18] C[17:11] (Y-2000)[10:4] M[3:0]
uint32_t os_version;
+#if __cplusplus
+ void SetOsVersion(unsigned major, unsigned minor, unsigned patch) {
+ os_version &= ((1 << 11) - 1);
+ os_version |= (((major & 0x7f) << 25) | ((minor & 0x7f) << 18) | ((patch & 0x7f) << 11));
+ }
+
+ void SetOsPatchLevel(unsigned year, unsigned month) {
+ os_version &= ~((1 << 11) - 1);
+ os_version |= (((year - 2000) & 0x7f) << 4) | ((month & 0xf) << 0);
+ }
+#endif
+
uint8_t name[BOOT_NAME_SIZE]; /* asciiz product name */
uint8_t cmdline[BOOT_ARGS_SIZE];
uint32_t id[8]; /* timestamp / checksum / sha1 / etc */
- /* Supplemental command line data; kept here to maintain
- * binary compatibility with older versions of mkbootimg */
+ // Supplemental command line data; kept here to maintain
+ // binary compatibility with older versions of mkbootimg.
uint8_t extra_cmdline[BOOT_EXTRA_ARGS_SIZE];
} __attribute__((packed));
@@ -74,7 +80,7 @@
*/
typedef struct boot_img_hdr_v0 boot_img_hdr;
-/* When a boot header is of version BOOT_HEADER_VERSION_ZERO, the structure of boot image is as
+/* When a boot header is of version 0, the structure of boot image is as
* follows:
*
* +-----------------+
@@ -103,15 +109,13 @@
* else: jump to kernel_addr
*/
-#define BOOT_HEADER_VERSION_ONE 1
-
struct boot_img_hdr_v1 : public boot_img_hdr_v0 {
uint32_t recovery_dtbo_size; /* size in bytes for recovery DTBO image */
uint64_t recovery_dtbo_offset; /* physical load addr */
uint32_t header_size;
} __attribute__((packed));
-/* When the boot image header has a version of BOOT_HEADER_VERSION_ONE, the structure of the boot
+/* When the boot image header has a version of 1, the structure of the boot
* image is as follows:
*
* +-----------------+
@@ -142,23 +146,3 @@
* 7. if second_size != 0: jump to second_addr
* else: jump to kernel_addr
*/
-
-#if 0
-typedef struct ptentry ptentry;
-
-struct ptentry {
- char name[16]; /* asciiz partition name */
- unsigned start; /* starting block number */
- unsigned length; /* length in blocks */
- unsigned flags; /* set to zero */
-};
-
-/* MSM Partition Table ATAG
-**
-** length: 2 + 7 * n
-** atag: 0x4d534d70
-** <ptentry> x n
-*/
-#endif
-
-#endif
diff --git a/storaged/main.cpp b/storaged/main.cpp
index 6b82904..72ec58f 100644
--- a/storaged/main.cpp
+++ b/storaged/main.cpp
@@ -21,9 +21,6 @@
#include <getopt.h>
#include <pthread.h>
#include <stdio.h>
-#include <sys/capability.h>
-#include <sys/prctl.h>
-#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <vector>