diff options
32 files changed, 1277 insertions, 809 deletions
diff --git a/Android.bp b/Android.bp index f8c6a4b71..6c04504ea 100644 --- a/Android.bp +++ b/Android.bp @@ -1,8 +1,143 @@ -subdirs = [ - "applypatch", - "bootloader_message", - "edify", - "otafault", - "otautil", - "uncrypt", -] +// 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. + +cc_defaults { + name: "recovery_defaults", + + cflags: [ + "-Wall", + "-Werror", + ], +} + +// Generic device that uses ScreenRecoveryUI. +cc_library_static { + name: "librecovery_ui_default", + + defaults: [ + "recovery_defaults", + ], + + srcs: [ + "default_device.cpp", + ], +} + +// The default wear device that uses WearRecoveryUI. +cc_library_static { + name: "librecovery_ui_wear", + + defaults: [ + "recovery_defaults", + ], + + srcs: [ + "wear_device.cpp", + ], +} + +// The default VR device that uses VrRecoveryUI. +cc_library_static { + name: "librecovery_ui_vr", + + defaults: [ + "recovery_defaults", + ], + + srcs: [ + "vr_device.cpp", + ], +} + +cc_library_static { + name: "libmounts", + + defaults: [ + "recovery_defaults", + ], + + srcs: [ + "mounts.cpp", + ], + + static_libs: [ + "libbase", + ], +} + +cc_library_static { + name: "libverifier", + + defaults: [ + "recovery_defaults", + ], + + srcs: [ + "asn1_decoder.cpp", + "verifier.cpp", + ], + + static_libs: [ + "libbase", + "libcrypto", + "libcrypto_utils", + "libotautil", + ], +} + +// The dynamic executable that runs after /data mounts. +cc_binary { + name: "recovery-persist", + + defaults: [ + "recovery_defaults", + ], + + srcs: [ + "recovery-persist.cpp", + "rotate_logs.cpp", + ], + + shared_libs: [ + "libbase", + "liblog", + ], + + init_rc: [ + "recovery-persist.rc", + ], +} + +// The dynamic executable that runs at init. +cc_binary { + name: "recovery-refresh", + + defaults: [ + "recovery_defaults", + ], + + srcs: [ + "recovery-refresh.cpp", + "rotate_logs.cpp", + ], + + shared_libs: [ + "libbase", + "liblog", + ], + + init_rc: [ + "recovery-refresh.rc", + ], +} diff --git a/Android.mk b/Android.mk index 7e0ad122e..ed09b4949 100644 --- a/Android.mk +++ b/Android.mk @@ -18,34 +18,18 @@ LOCAL_PATH := $(call my-dir) RECOVERY_API_VERSION := 3 RECOVERY_FSTAB_VERSION := 2 -# libfusesideload (static library) -# =============================== -include $(CLEAR_VARS) -LOCAL_SRC_FILES := fuse_sideload.cpp -LOCAL_CFLAGS := -Wall -Werror -LOCAL_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE -LOCAL_MODULE := libfusesideload -LOCAL_STATIC_LIBRARIES := \ - libcrypto \ - libbase -include $(BUILD_STATIC_LIBRARY) - -# libmounts (static library) -# =============================== -include $(CLEAR_VARS) -LOCAL_SRC_FILES := mounts.cpp -LOCAL_CFLAGS := \ - -Wall \ - -Werror -LOCAL_MODULE := libmounts -LOCAL_STATIC_LIBRARIES := libbase -include $(BUILD_STATIC_LIBRARY) +# TARGET_RECOVERY_UI_LIB should be one of librecovery_ui_{default,wear,vr} or a device-specific +# module that defines make_device() and the exact RecoveryUI class for the target. It defaults to +# librecovery_ui_default, which uses ScreenRecoveryUI. +TARGET_RECOVERY_UI_LIB ?= librecovery_ui_default # librecovery (static library) # =============================== include $(CLEAR_VARS) + LOCAL_SRC_FILES := \ install.cpp + LOCAL_CFLAGS := -Wall -Werror LOCAL_CFLAGS += -DRECOVERY_API_VERSION=$(RECOVERY_API_VERSION) @@ -54,6 +38,7 @@ ifeq ($(AB_OTA_UPDATER),true) endif LOCAL_MODULE := librecovery + LOCAL_STATIC_LIBRARIES := \ libminui \ libotautil \ @@ -65,36 +50,22 @@ LOCAL_STATIC_LIBRARIES := \ include $(BUILD_STATIC_LIBRARY) -# recovery (static executable) +# librecovery_ui (static library) # =============================== include $(CLEAR_VARS) - LOCAL_SRC_FILES := \ - adb_install.cpp \ - device.cpp \ - fuse_sdcard_provider.cpp \ - recovery.cpp \ - roots.cpp \ - rotate_logs.cpp \ screen_ui.cpp \ ui.cpp \ vr_ui.cpp \ - wear_ui.cpp \ - -LOCAL_MODULE := recovery + wear_ui.cpp -LOCAL_FORCE_STATIC_EXECUTABLE := true - -LOCAL_REQUIRED_MODULES := e2fsdroid_static mke2fs_static mke2fs.conf +LOCAL_CFLAGS := -Wall -Werror -ifeq ($(TARGET_USERIMAGES_USE_F2FS),true) -ifeq ($(HOST_OS),linux) -LOCAL_REQUIRED_MODULES += sload.f2fs mkfs.f2fs -endif -endif +LOCAL_MODULE := librecovery_ui -LOCAL_CFLAGS += -DRECOVERY_API_VERSION=$(RECOVERY_API_VERSION) -LOCAL_CFLAGS += -Wall -Werror +LOCAL_STATIC_LIBRARIES := \ + libminui \ + libbase ifneq ($(TARGET_RECOVERY_UI_MARGIN_HEIGHT),) LOCAL_CFLAGS += -DRECOVERY_UI_MARGIN_HEIGHT=$(TARGET_RECOVERY_UI_MARGIN_HEIGHT) @@ -144,6 +115,35 @@ else LOCAL_CFLAGS += -DRECOVERY_UI_VR_STEREO_OFFSET=0 endif +include $(BUILD_STATIC_LIBRARY) + +# recovery (static executable) +# =============================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + adb_install.cpp \ + device.cpp \ + fuse_sdcard_provider.cpp \ + recovery.cpp \ + roots.cpp \ + rotate_logs.cpp \ + +LOCAL_MODULE := recovery + +LOCAL_FORCE_STATIC_EXECUTABLE := true + +LOCAL_REQUIRED_MODULES := e2fsdroid_static mke2fs_static mke2fs.conf + +ifeq ($(TARGET_USERIMAGES_USE_F2FS),true) +ifeq ($(HOST_OS),linux) +LOCAL_REQUIRED_MODULES += sload.f2fs mkfs.f2fs +endif +endif + +LOCAL_CFLAGS += -DRECOVERY_API_VERSION=$(RECOVERY_API_VERSION) +LOCAL_CFLAGS += -Wall -Werror + LOCAL_C_INCLUDES += \ system/vold \ @@ -162,6 +162,7 @@ LOCAL_STATIC_LIBRARIES := \ LOCAL_STATIC_LIBRARIES += \ librecovery \ + $(TARGET_RECOVERY_UI_LIB) \ libverifier \ libbootloader_message \ libfs_mgr \ @@ -173,6 +174,7 @@ LOCAL_STATIC_LIBRARIES += \ libminadbd \ libasyncio \ libfusesideload \ + librecovery_ui \ libminui \ libpng \ libcrypto_utils \ @@ -196,84 +198,16 @@ endif LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin -ifeq ($(TARGET_RECOVERY_UI_LIB),) - LOCAL_SRC_FILES += default_device.cpp -else - LOCAL_STATIC_LIBRARIES += $(TARGET_RECOVERY_UI_LIB) -endif - ifeq ($(BOARD_CACHEIMAGE_PARTITION_SIZE),) LOCAL_REQUIRED_MODULES += recovery-persist recovery-refresh endif include $(BUILD_EXECUTABLE) -# recovery-persist (system partition dynamic executable run after /data mounts) -# =============================== -include $(CLEAR_VARS) -LOCAL_SRC_FILES := \ - recovery-persist.cpp \ - rotate_logs.cpp -LOCAL_MODULE := recovery-persist -LOCAL_SHARED_LIBRARIES := liblog libbase -LOCAL_CFLAGS := -Wall -Werror -LOCAL_INIT_RC := recovery-persist.rc -include $(BUILD_EXECUTABLE) - -# recovery-refresh (system partition dynamic executable run at init) -# =============================== -include $(CLEAR_VARS) -LOCAL_SRC_FILES := \ - recovery-refresh.cpp \ - rotate_logs.cpp -LOCAL_MODULE := recovery-refresh -LOCAL_SHARED_LIBRARIES := liblog libbase -LOCAL_CFLAGS := -Wall -Werror -LOCAL_INIT_RC := recovery-refresh.rc -include $(BUILD_EXECUTABLE) - -# libverifier (static library) -# =============================== -include $(CLEAR_VARS) -LOCAL_MODULE := libverifier -LOCAL_SRC_FILES := \ - asn1_decoder.cpp \ - verifier.cpp -LOCAL_STATIC_LIBRARIES := \ - libotautil \ - libcrypto_utils \ - libcrypto \ - libbase -LOCAL_CFLAGS := -Wall -Werror -include $(BUILD_STATIC_LIBRARY) - -# Wear default device -# =============================== -include $(CLEAR_VARS) -LOCAL_SRC_FILES := wear_device.cpp -LOCAL_CFLAGS := -Wall -Werror - -# Should match TARGET_RECOVERY_UI_LIB in BoardConfig.mk. -LOCAL_MODULE := librecovery_ui_wear - -include $(BUILD_STATIC_LIBRARY) - -# vr headset default device -# =============================== -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := vr_device.cpp -LOCAL_CFLAGS := -Wall -Werror - -# should match TARGET_RECOVERY_UI_LIB set in BoardConfig.mk -LOCAL_MODULE := librecovery_ui_vr - -include $(BUILD_STATIC_LIBRARY) - include \ $(LOCAL_PATH)/boot_control/Android.mk \ - $(LOCAL_PATH)/minadbd/Android.mk \ $(LOCAL_PATH)/minui/Android.mk \ + $(LOCAL_PATH)/sample_updater/Android.mk \ $(LOCAL_PATH)/tests/Android.mk \ $(LOCAL_PATH)/tools/Android.mk \ $(LOCAL_PATH)/updater/Android.mk \ diff --git a/applypatch/applypatch.cpp b/applypatch/applypatch.cpp index 7645a4005..6f6c187be 100644 --- a/applypatch/applypatch.cpp +++ b/applypatch/applypatch.cpp @@ -436,13 +436,13 @@ static size_t FileSink(const unsigned char* data, size_t len, int fd) { // Return the amount of free space (in bytes) on the filesystem // containing filename. filename must exist. Return -1 on error. -size_t FreeSpaceForFile(const char* filename) { - struct statfs sf; - if (statfs(filename, &sf) != 0) { - printf("failed to statfs %s: %s\n", filename, strerror(errno)); - return -1; - } - return sf.f_bsize * sf.f_bavail; +size_t FreeSpaceForFile(const std::string& filename) { + struct statfs sf; + if (statfs(filename.c_str(), &sf) != 0) { + printf("failed to statfs %s: %s\n", filename.c_str(), strerror(errno)); + return -1; + } + return sf.f_bsize * sf.f_bavail; } int CacheSizeCheck(size_t bytes) { diff --git a/applypatch/freecache.cpp b/applypatch/freecache.cpp index ea364d8e6..cfab0f6db 100644 --- a/applypatch/freecache.cpp +++ b/applypatch/freecache.cpp @@ -14,7 +14,10 @@ * limitations under the License. */ +#include <ctype.h> +#include <dirent.h> #include <errno.h> +#include <error.h> #include <libgen.h> #include <stdio.h> #include <stdlib.h> @@ -22,20 +25,22 @@ #include <sys/stat.h> #include <sys/statfs.h> #include <unistd.h> -#include <dirent.h> -#include <ctype.h> +#include <algorithm> +#include <limits> #include <memory> #include <set> #include <string> +#include <android-base/file.h> #include <android-base/parseint.h> #include <android-base/stringprintf.h> +#include <android-base/strings.h> #include "applypatch/applypatch.h" #include "otautil/cache_location.h" -static int EliminateOpenFiles(std::set<std::string>* files) { +static int EliminateOpenFiles(const std::string& dirname, std::set<std::string>* files) { std::unique_ptr<DIR, decltype(&closedir)> d(opendir("/proc"), closedir); if (!d) { printf("error opening /proc: %s\n", strerror(errno)); @@ -62,7 +67,7 @@ static int EliminateOpenFiles(std::set<std::string>* files) { int count = readlink(fd_path.c_str(), link, sizeof(link)-1); if (count >= 0) { link[count] = '\0'; - if (strncmp(link, "/cache/", 7) == 0) { + if (android::base::StartsWith(link, dirname)) { if (files->erase(link) > 0) { printf("%s is open by %s\n", link, de->d_name); } @@ -73,77 +78,138 @@ static int EliminateOpenFiles(std::set<std::string>* files) { return 0; } -static std::set<std::string> FindExpendableFiles() { +static std::vector<std::string> FindExpendableFiles( + const std::string& dirname, const std::function<bool(const std::string&)>& name_filter) { std::set<std::string> files; - // We're allowed to delete unopened regular files in any of these - // directories. - const char* dirs[2] = {"/cache", "/cache/recovery/otatest"}; - - for (size_t i = 0; i < sizeof(dirs)/sizeof(dirs[0]); ++i) { - std::unique_ptr<DIR, decltype(&closedir)> d(opendir(dirs[i]), closedir); - if (!d) { - printf("error opening %s: %s\n", dirs[i], strerror(errno)); + + std::unique_ptr<DIR, decltype(&closedir)> d(opendir(dirname.c_str()), closedir); + if (!d) { + printf("error opening %s: %s\n", dirname.c_str(), strerror(errno)); + return {}; + } + + // Look for regular files in the directory (not in any subdirectories). + struct dirent* de; + while ((de = readdir(d.get())) != 0) { + std::string path = dirname + "/" + de->d_name; + + // We can't delete cache_temp_source; if it's there we might have restarted during + // installation and could be depending on it to be there. + if (path == CacheLocation::location().cache_temp_source()) { continue; } - // Look for regular files in the directory (not in any subdirectories). - struct dirent* de; - while ((de = readdir(d.get())) != 0) { - std::string path = std::string(dirs[i]) + "/" + de->d_name; - - // We can't delete cache_temp_source; if it's there we might have restarted during - // installation and could be depending on it to be there. - if (path == CacheLocation::location().cache_temp_source()) { - continue; - } + // Do not delete the file if it doesn't have the expected format. + if (name_filter != nullptr && !name_filter(de->d_name)) { + continue; + } - struct stat st; - if (stat(path.c_str(), &st) == 0 && S_ISREG(st.st_mode)) { - files.insert(path); - } + struct stat st; + if (stat(path.c_str(), &st) == 0 && S_ISREG(st.st_mode)) { + files.insert(path); } } - printf("%zu regular files in deletable directories\n", files.size()); - if (EliminateOpenFiles(&files) < 0) { - return std::set<std::string>(); + printf("%zu regular files in deletable directory\n", files.size()); + if (EliminateOpenFiles(dirname, &files) < 0) { + return {}; + } + + return std::vector<std::string>(files.begin(), files.end()); +} + +// Parses the index of given log file, e.g. 3 for last_log.3; returns max number if the log name +// doesn't have the expected format so that we'll delete these ones first. +static unsigned int GetLogIndex(const std::string& log_name) { + if (log_name == "last_log" || log_name == "last_kmsg") { + return 0; + } + + unsigned int index; + if (sscanf(log_name.c_str(), "last_log.%u", &index) == 1 || + sscanf(log_name.c_str(), "last_kmsg.%u", &index) == 1) { + return index; } - return files; + + return std::numeric_limits<unsigned int>::max(); } int MakeFreeSpaceOnCache(size_t bytes_needed) { #ifndef __ANDROID__ // TODO (xunchang) implement a heuristic cache size check during host simulation. - printf("Skip making (%zu) bytes free space on cache; program is running on host\n", bytes_needed); + printf("Skip making (%zu) bytes free space on /cache; program is running on host\n", + bytes_needed); return 0; #endif - size_t free_now = FreeSpaceForFile("/cache"); - printf("%zu bytes free on /cache (%zu needed)\n", free_now, bytes_needed); + std::vector<std::string> dirs = { "/cache", CacheLocation::location().cache_log_directory() }; + for (const auto& dirname : dirs) { + if (RemoveFilesInDirectory(bytes_needed, dirname, FreeSpaceForFile)) { + return 0; + } + } - if (free_now >= bytes_needed) { - return 0; + return -1; +} + +bool RemoveFilesInDirectory(size_t bytes_needed, const std::string& dirname, + const std::function<size_t(const std::string&)>& space_checker) { + struct stat st; + if (stat(dirname.c_str(), &st) != 0) { + error(0, errno, "Unable to free space on %s", dirname.c_str()); + return false; } - std::set<std::string> files = FindExpendableFiles(); - if (files.empty()) { - // nothing we can delete to free up space! - printf("no files can be deleted to free space on /cache\n"); - return -1; + if (!S_ISDIR(st.st_mode)) { + printf("%s is not a directory\n", dirname.c_str()); + return false; + } + + size_t free_now = space_checker(dirname); + printf("%zu bytes free on %s (%zu needed)\n", free_now, dirname.c_str(), bytes_needed); + + if (free_now >= bytes_needed) { + return true; } - // We could try to be smarter about which files to delete: the - // biggest ones? the smallest ones that will free up enough space? - // the oldest? the newest? - // - // Instead, we'll be dumb. + std::vector<std::string> files; + if (dirname == CacheLocation::location().cache_log_directory()) { + // Deletes the log files only. + auto log_filter = [](const std::string& file_name) { + return android::base::StartsWith(file_name, "last_log") || + android::base::StartsWith(file_name, "last_kmsg"); + }; + + files = FindExpendableFiles(dirname, log_filter); + + // Older logs will come to the top of the queue. + auto comparator = [](const std::string& name1, const std::string& name2) -> bool { + unsigned int index1 = GetLogIndex(android::base::Basename(name1)); + unsigned int index2 = GetLogIndex(android::base::Basename(name2)); + if (index1 == index2) { + return name1 < name2; + } + + return index1 > index2; + }; + + std::sort(files.begin(), files.end(), comparator); + } else { + // We're allowed to delete unopened regular files in the directory. + files = FindExpendableFiles(dirname, nullptr); + } for (const auto& file : files) { - unlink(file.c_str()); - free_now = FreeSpaceForFile("/cache"); + if (unlink(file.c_str()) == -1) { + error(0, errno, "Failed to delete %s", file.c_str()); + continue; + } + + free_now = space_checker(dirname); printf("deleted %s; now %zu bytes free\n", file.c_str(), free_now); - if (free_now < bytes_needed) { - break; + if (free_now >= bytes_needed) { + return true; } } - return (free_now >= bytes_needed) ? 0 : -1; + + return false; } diff --git a/applypatch/include/applypatch/applypatch.h b/applypatch/include/applypatch/applypatch.h index 912ead1fa..021a28d05 100644 --- a/applypatch/include/applypatch/applypatch.h +++ b/applypatch/include/applypatch/applypatch.h @@ -39,7 +39,7 @@ using SinkFn = std::function<size_t(const unsigned char*, size_t)>; // applypatch.cpp int ShowLicenses(); -size_t FreeSpaceForFile(const char* filename); +size_t FreeSpaceForFile(const std::string& filename); int CacheSizeCheck(size_t bytes); int ParseSha1(const char* str, uint8_t* digest); @@ -79,5 +79,9 @@ int ApplyImagePatch(const unsigned char* old_data, size_t old_size, const Value& // freecache.cpp int MakeFreeSpaceOnCache(size_t bytes_needed); +// Removes the files in |dirname| until we have at least |bytes_needed| bytes of free space on +// the partition. The size of the free space is returned by calling |space_checker|. +bool RemoveFilesInDirectory(size_t bytes_needed, const std::string& dirname, + const std::function<size_t(const std::string&)>& space_checker); #endif diff --git a/fuse_sideload/Android.bp b/fuse_sideload/Android.bp new file mode 100644 index 000000000..76bc16df9 --- /dev/null +++ b/fuse_sideload/Android.bp @@ -0,0 +1,37 @@ +// 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. + +cc_library_static { + name: "libfusesideload", + + cflags: [ + "-D_XOPEN_SOURCE", + "-D_GNU_SOURCE", + "-Wall", + "-Werror", + ], + + srcs: [ + "fuse_sideload.cpp", + ], + + export_include_dirs: [ + "include", + ], + + static_libs: [ + "libbase", + "libcrypto", + ], +} diff --git a/fuse_sideload.cpp b/fuse_sideload/fuse_sideload.cpp index 1c7e98f01..1c7e98f01 100644 --- a/fuse_sideload.cpp +++ b/fuse_sideload/fuse_sideload.cpp diff --git a/fuse_sideload.h b/fuse_sideload/include/fuse_sideload.h index 1b34cbdb0..1b34cbdb0 100644 --- a/fuse_sideload.h +++ b/fuse_sideload/include/fuse_sideload.h diff --git a/minadbd/Android.bp b/minadbd/Android.bp new file mode 100644 index 000000000..432b2f0f5 --- /dev/null +++ b/minadbd/Android.bp @@ -0,0 +1,78 @@ +// 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. + +cc_defaults { + name: "minadbd_defaults", + + cflags: [ + "-DADB_HOST=0", + "-Wall", + "-Werror", + ], + + include_dirs: [ + "system/core/adb", + ], +} + +cc_library_static { + name: "libminadbd", + + defaults: [ + "minadbd_defaults", + ], + + srcs: [ + "fuse_adb_provider.cpp", + "minadbd.cpp", + "minadbd_services.cpp", + ], + + static_libs: [ + "libfusesideload", + "libbase", + "libcrypto", + ], + + whole_static_libs: [ + "libadbd", + ], +} + +cc_test { + name: "minadbd_test", + + defaults: [ + "minadbd_defaults", + ], + + srcs: [ + "fuse_adb_provider_test.cpp", + ], + + static_libs: [ + "libBionicGtestMain", + "libminadbd", + ], + + shared_libs: [ + "libbase", + "libcutils", + "liblog", + ], + + test_suites: [ + "device-tests", + ], +} diff --git a/minadbd/Android.mk b/minadbd/Android.mk deleted file mode 100644 index 50e3b34ef..000000000 --- a/minadbd/Android.mk +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright 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. - -LOCAL_PATH:= $(call my-dir) - -minadbd_cflags := \ - -Wall -Werror \ - -DADB_HOST=0 \ - -# libminadbd (static library) -# =============================== -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := \ - fuse_adb_provider.cpp \ - minadbd.cpp \ - minadbd_services.cpp \ - -LOCAL_MODULE := libminadbd -LOCAL_CFLAGS := $(minadbd_cflags) -LOCAL_C_INCLUDES := bootable/recovery system/core/adb -LOCAL_WHOLE_STATIC_LIBRARIES := libadbd -LOCAL_STATIC_LIBRARIES := libcrypto libbase - -include $(BUILD_STATIC_LIBRARY) - -# minadbd_test (native test) -# =============================== -include $(CLEAR_VARS) - -LOCAL_MODULE := minadbd_test -LOCAL_COMPATIBILITY_SUITE := device-tests -LOCAL_SRC_FILES := fuse_adb_provider_test.cpp -LOCAL_CFLAGS := $(minadbd_cflags) -LOCAL_C_INCLUDES := $(LOCAL_PATH) system/core/adb -LOCAL_STATIC_LIBRARIES := \ - libBionicGtestMain \ - libminadbd -LOCAL_SHARED_LIBRARIES := \ - liblog \ - libbase \ - libcutils - -include $(BUILD_NATIVE_TEST) diff --git a/minui/font_10x18.h b/minui/font_10x18.h deleted file mode 100644 index 30dfb9c56..000000000 --- a/minui/font_10x18.h +++ /dev/null @@ -1,214 +0,0 @@ -struct { - unsigned width; - unsigned height; - unsigned char_width; - unsigned char_height; - unsigned char rundata[2973]; -} font = { - .width = 960, - .height = 18, - .char_width = 10, - .char_height = 18, - .rundata = { -0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x55,0x82,0x06,0x82,0x02,0x82,0x10,0x82, -0x11,0x83,0x08,0x82,0x0a,0x82,0x04,0x82,0x46,0x82,0x08,0x82,0x07,0x84,0x06, -0x84,0x0a,0x81,0x03,0x88,0x04,0x84,0x04,0x88,0x04,0x84,0x06,0x84,0x1e,0x81, -0x0e,0x81,0x0a,0x84,0x06,0x84,0x07,0x82,0x05,0x85,0x07,0x84,0x04,0x86,0x04, -0x88,0x02,0x88,0x04,0x84,0x04,0x82,0x04,0x82,0x02,0x88,0x05,0x86,0x01,0x82, -0x04,0x82,0x02,0x82,0x08,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x04,0x84,0x04, -0x86,0x06,0x84,0x04,0x86,0x06,0x84,0x04,0x88,0x02,0x82,0x04,0x82,0x02,0x82, -0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02, -0x88,0x03,0x86,0x0e,0x86,0x06,0x82,0x11,0x82,0x10,0x82,0x18,0x82,0x0f,0x84, -0x0d,0x82,0x1c,0x82,0x09,0x84,0x7f,0x16,0x84,0x05,0x82,0x05,0x84,0x07,0x83, -0x02,0x82,0x19,0x82,0x06,0x82,0x02,0x82,0x06,0x82,0x01,0x82,0x03,0x86,0x04, -0x83,0x02,0x82,0x03,0x82,0x01,0x82,0x07,0x82,0x09,0x82,0x06,0x82,0x3e,0x82, -0x04,0x84,0x06,0x83,0x06,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x08,0x82,0x03, -0x82,0x09,0x82,0x02,0x82,0x09,0x82,0x03,0x82,0x02,0x82,0x04,0x82,0x02,0x82, -0x1c,0x82,0x0e,0x82,0x08,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x05,0x84,0x04, -0x82,0x02,0x82,0x05,0x82,0x02,0x82,0x03,0x82,0x03,0x82,0x03,0x82,0x08,0x82, -0x09,0x82,0x02,0x82,0x03,0x82,0x04,0x82,0x05,0x82,0x0a,0x82,0x03,0x82,0x04, -0x82,0x02,0x82,0x08,0x82,0x04,0x82,0x02,0x83,0x03,0x82,0x03,0x82,0x02,0x82, -0x03,0x82,0x03,0x82,0x04,0x82,0x02,0x82,0x03,0x82,0x03,0x82,0x04,0x82,0x02, -0x82,0x06,0x82,0x05,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82, -0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x08,0x82,0x03,0x82,0x08,0x82,0x0c, -0x82,0x05,0x84,0x11,0x82,0x0f,0x82,0x18,0x82,0x0e,0x82,0x02,0x82,0x0c,0x82, -0x1c,0x82,0x0b,0x82,0x7f,0x15,0x82,0x08,0x82,0x08,0x82,0x05,0x82,0x01,0x82, -0x01,0x82,0x19,0x82,0x06,0x82,0x02,0x82,0x06,0x82,0x01,0x82,0x02,0x82,0x01, -0x82,0x01,0x82,0x02,0x82,0x01,0x82,0x01,0x82,0x03,0x82,0x01,0x82,0x07,0x82, -0x08,0x82,0x08,0x82,0x3d,0x82,0x03,0x82,0x02,0x82,0x04,0x84,0x05,0x82,0x04, -0x82,0x02,0x82,0x04,0x82,0x06,0x83,0x03,0x82,0x08,0x82,0x04,0x81,0x09,0x82, -0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x1a,0x82,0x10,0x82,0x06,0x82,0x04, -0x82,0x02,0x82,0x04,0x82,0x03,0x82,0x02,0x82,0x03,0x82,0x03,0x82,0x03,0x82, -0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x08,0x82,0x08,0x82,0x04,0x82,0x02, -0x82,0x04,0x82,0x05,0x82,0x0a,0x82,0x03,0x82,0x03,0x82,0x03,0x82,0x08,0x83, -0x02,0x83,0x02,0x83,0x03,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02, -0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x05,0x82,0x05,0x82, -0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x03,0x82,0x02,0x82,0x04, -0x82,0x02,0x82,0x09,0x82,0x03,0x82,0x08,0x82,0x0c,0x82,0x04,0x82,0x02,0x82, -0x11,0x82,0x0e,0x82,0x18,0x82,0x0e,0x82,0x02,0x82,0x0c,0x82,0x0b,0x82,0x0b, -0x82,0x02,0x82,0x0b,0x82,0x4d,0x82,0x45,0x82,0x08,0x82,0x08,0x82,0x05,0x82, -0x02,0x83,0x1a,0x82,0x07,0x81,0x02,0x81,0x07,0x82,0x01,0x82,0x02,0x82,0x01, -0x82,0x05,0x82,0x01,0x84,0x04,0x82,0x01,0x82,0x07,0x82,0x08,0x82,0x08,0x82, -0x06,0x82,0x02,0x82,0x06,0x82,0x28,0x82,0x04,0x82,0x02,0x82,0x03,0x82,0x01, -0x82,0x05,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x05,0x84,0x03,0x82,0x08,0x82, -0x0d,0x82,0x03,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x19,0x82,0x12,0x82,0x05, -0x82,0x04,0x82,0x02,0x82,0x02,0x84,0x03,0x82,0x02,0x82,0x03,0x82,0x03,0x82, -0x03,0x82,0x08,0x82,0x04,0x82,0x02,0x82,0x08,0x82,0x08,0x82,0x08,0x82,0x04, -0x82,0x05,0x82,0x0a,0x82,0x03,0x82,0x03,0x82,0x03,0x82,0x08,0x83,0x02,0x83, -0x02,0x84,0x02,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04, -0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x0b,0x82,0x05,0x82,0x04,0x82,0x02,0x82, -0x04,0x82,0x02,0x82,0x04,0x82,0x03,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x08, -0x82,0x04,0x82,0x09,0x82,0x0b,0x82,0x03,0x82,0x04,0x82,0x20,0x82,0x18,0x82, -0x0e,0x82,0x10,0x82,0x0b,0x82,0x0b,0x82,0x02,0x82,0x0b,0x82,0x4d,0x82,0x45, -0x82,0x08,0x82,0x08,0x82,0x26,0x82,0x10,0x88,0x01,0x82,0x01,0x82,0x06,0x83, -0x01,0x82,0x04,0x84,0x08,0x81,0x08,0x82,0x0a,0x82,0x05,0x82,0x02,0x82,0x06, -0x82,0x28,0x82,0x03,0x82,0x04,0x82,0x05,0x82,0x0b,0x82,0x08,0x82,0x04,0x82, -0x01,0x82,0x03,0x82,0x08,0x82,0x0d,0x82,0x03,0x82,0x04,0x82,0x02,0x82,0x04, -0x82,0x18,0x82,0x06,0x88,0x06,0x82,0x04,0x82,0x04,0x82,0x02,0x82,0x01,0x85, -0x02,0x82,0x04,0x82,0x02,0x82,0x03,0x82,0x03,0x82,0x08,0x82,0x04,0x82,0x02, -0x82,0x08,0x82,0x08,0x82,0x08,0x82,0x04,0x82,0x05,0x82,0x0a,0x82,0x03,0x82, -0x02,0x82,0x04,0x82,0x08,0x88,0x02,0x84,0x02,0x82,0x02,0x82,0x04,0x82,0x02, -0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x0b,0x82, -0x05,0x82,0x04,0x82,0x03,0x82,0x02,0x82,0x03,0x82,0x04,0x82,0x04,0x84,0x06, -0x84,0x08,0x82,0x05,0x82,0x09,0x82,0x0b,0x82,0x2b,0x82,0x18,0x82,0x0e,0x82, -0x10,0x82,0x1c,0x82,0x0b,0x82,0x4d,0x82,0x45,0x82,0x08,0x82,0x08,0x82,0x26, -0x82,0x11,0x82,0x01,0x82,0x03,0x82,0x01,0x82,0x09,0x82,0x06,0x82,0x12,0x82, -0x0a,0x82,0x06,0x84,0x07,0x82,0x27,0x82,0x04,0x82,0x04,0x82,0x05,0x82,0x0b, -0x82,0x07,0x82,0x04,0x82,0x02,0x82,0x03,0x82,0x01,0x83,0x04,0x82,0x01,0x83, -0x08,0x82,0x05,0x82,0x02,0x82,0x03,0x82,0x04,0x82,0x05,0x83,0x07,0x83,0x05, -0x82,0x16,0x82,0x08,0x82,0x03,0x82,0x01,0x82,0x01,0x82,0x02,0x82,0x04,0x82, -0x02,0x82,0x02,0x82,0x04,0x82,0x08,0x82,0x04,0x82,0x02,0x82,0x08,0x82,0x08, -0x82,0x08,0x82,0x04,0x82,0x05,0x82,0x0a,0x82,0x03,0x82,0x02,0x82,0x04,0x82, -0x08,0x82,0x01,0x82,0x01,0x82,0x02,0x82,0x01,0x82,0x01,0x82,0x02,0x82,0x04, -0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x03,0x82, -0x0a,0x82,0x05,0x82,0x04,0x82,0x03,0x82,0x02,0x82,0x03,0x82,0x01,0x82,0x01, -0x82,0x04,0x84,0x06,0x84,0x08,0x82,0x05,0x82,0x0a,0x82,0x0a,0x82,0x23,0x85, -0x03,0x82,0x01,0x83,0x06,0x85,0x05,0x83,0x01,0x82,0x04,0x84,0x04,0x86,0x05, -0x85,0x01,0x81,0x02,0x82,0x01,0x83,0x05,0x84,0x09,0x84,0x02,0x82,0x03,0x82, -0x06,0x82,0x05,0x81,0x01,0x82,0x01,0x82,0x03,0x82,0x01,0x83,0x06,0x84,0x04, -0x82,0x01,0x83,0x06,0x83,0x01,0x82,0x02,0x82,0x01,0x84,0x04,0x86,0x03,0x86, -0x04,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04, -0x82,0x02,0x82,0x04,0x82,0x03,0x87,0x05,0x82,0x08,0x82,0x08,0x82,0x26,0x82, -0x11,0x82,0x01,0x82,0x04,0x86,0x07,0x82,0x05,0x83,0x12,0x82,0x0a,0x82,0x04, -0x88,0x02,0x88,0x0c,0x88,0x10,0x82,0x04,0x82,0x04,0x82,0x05,0x82,0x0a,0x82, -0x06,0x83,0x04,0x82,0x03,0x82,0x03,0x83,0x02,0x82,0x03,0x83,0x02,0x82,0x07, -0x82,0x06,0x84,0x05,0x82,0x02,0x83,0x05,0x83,0x07,0x83,0x04,0x82,0x18,0x82, -0x06,0x82,0x04,0x82,0x01,0x82,0x01,0x82,0x02,0x82,0x04,0x82,0x02,0x86,0x04, -0x82,0x08,0x82,0x04,0x82,0x02,0x86,0x04,0x86,0x04,0x82,0x02,0x84,0x02,0x88, -0x05,0x82,0x0a,0x82,0x03,0x85,0x05,0x82,0x08,0x82,0x01,0x82,0x01,0x82,0x02, -0x82,0x01,0x82,0x01,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x03,0x82,0x03,0x82, -0x04,0x82,0x02,0x82,0x03,0x82,0x05,0x84,0x07,0x82,0x05,0x82,0x04,0x82,0x03, -0x82,0x02,0x82,0x03,0x82,0x01,0x82,0x01,0x82,0x05,0x82,0x08,0x82,0x08,0x82, -0x06,0x82,0x0a,0x82,0x0a,0x82,0x22,0x82,0x03,0x82,0x02,0x83,0x02,0x82,0x04, -0x82,0x03,0x82,0x03,0x82,0x02,0x83,0x03,0x82,0x02,0x82,0x05,0x82,0x06,0x82, -0x03,0x83,0x02,0x83,0x02,0x82,0x06,0x82,0x0b,0x82,0x02,0x82,0x02,0x82,0x07, -0x82,0x05,0x88,0x02,0x83,0x02,0x82,0x04,0x82,0x02,0x82,0x03,0x83,0x02,0x82, -0x04,0x82,0x02,0x83,0x03,0x83,0x02,0x82,0x02,0x82,0x04,0x82,0x04,0x82,0x06, -0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x03,0x82,0x02,0x82, -0x03,0x82,0x04,0x82,0x08,0x82,0x02,0x84,0x09,0x82,0x09,0x84,0x23,0x82,0x11, -0x82,0x01,0x82,0x06,0x82,0x01,0x82,0x05,0x82,0x05,0x82,0x01,0x82,0x11,0x82, -0x0a,0x82,0x06,0x84,0x07,0x82,0x26,0x82,0x05,0x82,0x04,0x82,0x05,0x82,0x08, -0x83,0x09,0x82,0x03,0x82,0x03,0x82,0x09,0x82,0x02,0x82,0x04,0x82,0x05,0x82, -0x06,0x82,0x02,0x82,0x05,0x83,0x01,0x82,0x17,0x82,0x16,0x82,0x06,0x82,0x05, -0x82,0x01,0x82,0x01,0x82,0x02,0x88,0x02,0x82,0x03,0x82,0x03,0x82,0x08,0x82, -0x04,0x82,0x02,0x82,0x08,0x82,0x08,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x05, -0x82,0x0a,0x82,0x03,0x82,0x02,0x82,0x04,0x82,0x08,0x82,0x01,0x82,0x01,0x82, -0x02,0x82,0x02,0x84,0x02,0x82,0x04,0x82,0x02,0x86,0x04,0x82,0x04,0x82,0x02, -0x86,0x09,0x82,0x06,0x82,0x05,0x82,0x04,0x82,0x04,0x84,0x04,0x82,0x01,0x82, -0x01,0x82,0x04,0x84,0x07,0x82,0x07,0x82,0x07,0x82,0x0b,0x82,0x09,0x82,0x27, -0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x08,0x82,0x04,0x82,0x02,0x82,0x04,0x82, -0x04,0x82,0x06,0x82,0x03,0x82,0x03,0x82,0x04,0x82,0x05,0x82,0x0b,0x82,0x02, -0x82,0x01,0x82,0x08,0x82,0x05,0x82,0x01,0x82,0x01,0x82,0x02,0x82,0x04,0x82, -0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x03,0x82,0x07, -0x82,0x0a,0x82,0x06,0x82,0x04,0x82,0x03,0x82,0x02,0x82,0x03,0x82,0x04,0x82, -0x04,0x84,0x04,0x82,0x04,0x82,0x07,0x82,0x06,0x82,0x08,0x82,0x08,0x82,0x26, -0x82,0x0f,0x88,0x05,0x82,0x01,0x82,0x05,0x82,0x05,0x82,0x02,0x82,0x01,0x82, -0x0d,0x82,0x0a,0x82,0x05,0x82,0x02,0x82,0x06,0x82,0x26,0x82,0x05,0x82,0x04, -0x82,0x05,0x82,0x07,0x82,0x0c,0x82,0x02,0x88,0x08,0x82,0x02,0x82,0x04,0x82, -0x05,0x82,0x05,0x82,0x04,0x82,0x08,0x82,0x18,0x82,0x14,0x82,0x07,0x82,0x05, -0x82,0x01,0x84,0x03,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x08,0x82, -0x04,0x82,0x02,0x82,0x08,0x82,0x08,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x05, -0x82,0x0a,0x82,0x03,0x82,0x02,0x82,0x04,0x82,0x08,0x82,0x01,0x82,0x01,0x82, -0x02,0x82,0x02,0x84,0x02,0x82,0x04,0x82,0x02,0x82,0x08,0x82,0x04,0x82,0x02, -0x82,0x02,0x82,0x0a,0x82,0x05,0x82,0x05,0x82,0x04,0x82,0x04,0x84,0x04,0x82, -0x01,0x82,0x01,0x82,0x04,0x84,0x07,0x82,0x07,0x82,0x07,0x82,0x0b,0x82,0x09, -0x82,0x22,0x87,0x02,0x82,0x04,0x82,0x02,0x82,0x08,0x82,0x04,0x82,0x02,0x88, -0x04,0x82,0x06,0x82,0x03,0x82,0x03,0x82,0x04,0x82,0x05,0x82,0x0b,0x82,0x02, -0x84,0x09,0x82,0x05,0x82,0x01,0x82,0x01,0x82,0x02,0x82,0x04,0x82,0x02,0x82, -0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x03,0x82,0x08,0x86,0x05, -0x82,0x06,0x82,0x04,0x82,0x03,0x82,0x02,0x82,0x03,0x82,0x01,0x82,0x01,0x82, -0x05,0x82,0x05,0x82,0x04,0x82,0x06,0x82,0x07,0x82,0x08,0x82,0x08,0x82,0x26, -0x82,0x10,0x82,0x01,0x82,0x07,0x82,0x01,0x82,0x04,0x82,0x01,0x83,0x02,0x82, -0x03,0x83,0x0f,0x82,0x08,0x82,0x06,0x82,0x02,0x82,0x06,0x82,0x25,0x82,0x07, -0x82,0x02,0x82,0x06,0x82,0x06,0x82,0x07,0x82,0x04,0x82,0x07,0x82,0x09,0x82, -0x02,0x82,0x04,0x82,0x04,0x82,0x06,0x82,0x04,0x82,0x08,0x82,0x19,0x82,0x05, -0x88,0x05,0x82,0x08,0x82,0x05,0x82,0x02,0x82,0x04,0x82,0x04,0x82,0x02,0x82, -0x04,0x82,0x02,0x82,0x08,0x82,0x04,0x82,0x02,0x82,0x08,0x82,0x08,0x82,0x04, -0x82,0x02,0x82,0x04,0x82,0x05,0x82,0x05,0x82,0x03,0x82,0x03,0x82,0x03,0x82, -0x03,0x82,0x08,0x82,0x04,0x82,0x02,0x82,0x03,0x83,0x02,0x82,0x04,0x82,0x02, -0x82,0x08,0x82,0x01,0x82,0x01,0x82,0x02,0x82,0x03,0x82,0x09,0x82,0x05,0x82, -0x05,0x82,0x04,0x82,0x04,0x84,0x04,0x83,0x02,0x83,0x03,0x82,0x02,0x82,0x06, -0x82,0x06,0x82,0x08,0x82,0x0c,0x82,0x08,0x82,0x21,0x82,0x04,0x82,0x02,0x82, -0x04,0x82,0x02,0x82,0x08,0x82,0x04,0x82,0x02,0x82,0x0a,0x82,0x06,0x82,0x03, -0x82,0x03,0x82,0x04,0x82,0x05,0x82,0x0b,0x82,0x02,0x85,0x08,0x82,0x05,0x82, -0x01,0x82,0x01,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04, -0x82,0x02,0x82,0x04,0x82,0x03,0x82,0x0d,0x82,0x04,0x82,0x06,0x82,0x04,0x82, -0x04,0x84,0x04,0x82,0x01,0x82,0x01,0x82,0x05,0x82,0x05,0x82,0x04,0x82,0x05, -0x82,0x08,0x82,0x08,0x82,0x08,0x82,0x38,0x82,0x01,0x82,0x04,0x82,0x01,0x82, -0x01,0x82,0x04,0x84,0x01,0x82,0x01,0x82,0x03,0x82,0x10,0x82,0x08,0x82,0x30, -0x83,0x06,0x82,0x07,0x82,0x02,0x82,0x06,0x82,0x05,0x82,0x08,0x82,0x04,0x82, -0x07,0x82,0x03,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x04,0x82,0x06,0x82,0x04, -0x82,0x03,0x81,0x04,0x82,0x1a,0x82,0x10,0x82,0x10,0x82,0x08,0x82,0x04,0x82, -0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x08, -0x82,0x08,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x05,0x82,0x05,0x82,0x03,0x82, -0x03,0x82,0x03,0x82,0x03,0x82,0x08,0x82,0x04,0x82,0x02,0x82,0x03,0x83,0x02, -0x82,0x04,0x82,0x02,0x82,0x08,0x82,0x02,0x84,0x02,0x82,0x03,0x82,0x03,0x82, -0x04,0x82,0x05,0x82,0x05,0x82,0x04,0x82,0x05,0x82,0x05,0x83,0x02,0x83,0x03, -0x82,0x02,0x82,0x06,0x82,0x05,0x82,0x09,0x82,0x0c,0x82,0x08,0x82,0x21,0x82, -0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x08,0x82,0x04,0x82,0x02,0x82,0x0a, -0x82,0x07,0x85,0x04,0x82,0x04,0x82,0x05,0x82,0x0b,0x82,0x02,0x82,0x02,0x82, -0x07,0x82,0x05,0x82,0x01,0x82,0x01,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04, -0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x03,0x82,0x0d,0x82,0x04,0x82, -0x06,0x82,0x04,0x82,0x04,0x84,0x04,0x82,0x01,0x82,0x01,0x82,0x04,0x84,0x04, -0x82,0x04,0x82,0x04,0x82,0x09,0x82,0x08,0x82,0x08,0x82,0x26,0x82,0x10,0x82, -0x01,0x82,0x05,0x86,0x04,0x82,0x01,0x82,0x01,0x82,0x01,0x83,0x01,0x84,0x10, -0x82,0x06,0x82,0x1d,0x83,0x11,0x83,0x05,0x82,0x09,0x84,0x07,0x82,0x05,0x82, -0x09,0x82,0x02,0x82,0x08,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x04, -0x82,0x08,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x06,0x83,0x07,0x83,0x09,0x82, -0x0e,0x82,0x0a,0x82,0x06,0x82,0x03,0x82,0x02,0x82,0x04,0x82,0x02,0x82,0x03, -0x82,0x04,0x82,0x02,0x82,0x03,0x82,0x03,0x82,0x03,0x82,0x08,0x82,0x09,0x82, -0x02,0x83,0x02,0x82,0x04,0x82,0x05,0x82,0x06,0x82,0x01,0x82,0x04,0x82,0x04, -0x82,0x02,0x82,0x08,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x03,0x82,0x02,0x82, -0x03,0x82,0x09,0x82,0x02,0x82,0x03,0x82,0x04,0x82,0x03,0x82,0x02,0x82,0x06, -0x82,0x06,0x82,0x02,0x82,0x06,0x82,0x05,0x82,0x04,0x82,0x02,0x82,0x04,0x82, -0x05,0x82,0x05,0x82,0x09,0x82,0x0d,0x82,0x07,0x82,0x21,0x82,0x04,0x82,0x02, -0x83,0x02,0x82,0x04,0x82,0x03,0x82,0x03,0x82,0x02,0x83,0x03,0x82,0x03,0x82, -0x04,0x82,0x06,0x82,0x08,0x82,0x04,0x82,0x05,0x82,0x0b,0x82,0x02,0x82,0x03, -0x82,0x06,0x82,0x05,0x82,0x01,0x82,0x01,0x82,0x02,0x82,0x04,0x82,0x03,0x82, -0x02,0x82,0x03,0x83,0x02,0x82,0x04,0x82,0x02,0x83,0x03,0x82,0x07,0x82,0x04, -0x82,0x04,0x82,0x02,0x82,0x03,0x82,0x02,0x83,0x05,0x82,0x05,0x88,0x03,0x82, -0x02,0x82,0x04,0x82,0x02,0x83,0x03,0x82,0x0a,0x82,0x08,0x82,0x08,0x82,0x26, -0x82,0x1c,0x82,0x06,0x82,0x02,0x83,0x03,0x84,0x02,0x82,0x10,0x82,0x04,0x82, -0x1e,0x83,0x11,0x83,0x05,0x82,0x0a,0x82,0x05,0x88,0x02,0x88,0x04,0x84,0x09, -0x82,0x05,0x84,0x06,0x84,0x05,0x82,0x09,0x84,0x06,0x84,0x07,0x83,0x07,0x83, -0x0a,0x81,0x0e,0x81,0x0b,0x82,0x07,0x85,0x03,0x82,0x04,0x82,0x02,0x86,0x06, -0x84,0x04,0x86,0x04,0x88,0x02,0x82,0x0a,0x84,0x01,0x81,0x02,0x82,0x04,0x82, -0x02,0x88,0x04,0x83,0x05,0x82,0x04,0x82,0x02,0x88,0x02,0x82,0x04,0x82,0x02, -0x82,0x04,0x82,0x04,0x84,0x04,0x82,0x0a,0x85,0x03,0x82,0x04,0x82,0x04,0x84, -0x07,0x82,0x07,0x84,0x07,0x82,0x05,0x82,0x04,0x82,0x02,0x82,0x04,0x82,0x05, -0x82,0x05,0x88,0x03,0x86,0x09,0x82,0x03,0x86,0x22,0x85,0x01,0x81,0x02,0x82, -0x01,0x83,0x06,0x85,0x05,0x83,0x01,0x82,0x04,0x85,0x05,0x82,0x07,0x86,0x03, -0x82,0x04,0x82,0x02,0x88,0x08,0x82,0x02,0x82,0x04,0x82,0x02,0x88,0x02,0x82, -0x01,0x82,0x01,0x82,0x02,0x82,0x04,0x82,0x04,0x84,0x04,0x82,0x01,0x83,0x06, -0x83,0x01,0x82,0x03,0x82,0x08,0x86,0x06,0x84,0x05,0x83,0x01,0x82,0x05,0x82, -0x06,0x82,0x02,0x82,0x03,0x82,0x04,0x82,0x04,0x83,0x01,0x82,0x03,0x87,0x06, -0x84,0x05,0x82,0x05,0x84,0x7f,0x15,0x83,0x7f,0x14,0x83,0x7f,0x5e,0x82,0x7f, -0x05,0x89,0x47,0x82,0x04,0x82,0x17,0x82,0x03,0x82,0x34,0x82,0x0e,0x82,0x4e, -0x82,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x0a,0x82,0x04,0x82,0x17,0x82,0x03,0x82, -0x34,0x82,0x0e,0x82,0x48,0x82,0x04,0x82,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x0a, -0x82,0x04,0x82,0x17,0x82,0x03,0x82,0x34,0x82,0x0e,0x82,0x49,0x82,0x02,0x82, -0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x0c,0x86,0x19,0x85,0x35,0x82,0x0e,0x82,0x4a, -0x84,0x3f, -0x00, - } -}; diff --git a/minui/graphics.cpp b/minui/graphics.cpp index 56f471bce..202ce71fd 100644 --- a/minui/graphics.cpp +++ b/minui/graphics.cpp @@ -23,7 +23,6 @@ #include <memory> -#include "font_10x18.h" #include "graphics_adf.h" #include "graphics_drm.h" #include "graphics_fbdev.h" @@ -313,42 +312,16 @@ int gr_init_font(const char* name, GRFont** dest) { return 0; } -static void gr_init_font(void) { - int res = gr_init_font("font", &gr_font); - if (res == 0) { - return; - } - - printf("failed to read font: res=%d\n", res); - - // fall back to the compiled-in font. - gr_font = static_cast<GRFont*>(calloc(1, sizeof(*gr_font))); - gr_font->texture = static_cast<GRSurface*>(malloc(sizeof(*gr_font->texture))); - gr_font->texture->width = font.width; - gr_font->texture->height = font.height; - gr_font->texture->row_bytes = font.width; - gr_font->texture->pixel_bytes = 1; - - unsigned char* bits = static_cast<unsigned char*>(malloc(font.width * font.height)); - gr_font->texture->data = bits; - - unsigned char data; - unsigned char* in = font.rundata; - while ((data = *in++)) { - memset(bits, (data & 0x80) ? 255 : 0, data & 0x7f); - bits += (data & 0x7f); - } - - gr_font->char_width = font.char_width; - gr_font->char_height = font.char_height; -} - void gr_flip() { gr_draw = gr_backend->Flip(); } int gr_init() { - gr_init_font(); + int ret = gr_init_font("font", &gr_font); + if (ret != 0) { + printf("Failed to init font: %d\n", ret); + return -1; + } auto backend = std::unique_ptr<MinuiBackend>{ std::make_unique<MinuiBackendAdf>() }; gr_draw = backend->Init(); diff --git a/minui/mkfont.c b/minui/mkfont.c deleted file mode 100644 index 61a5edeb2..000000000 --- a/minui/mkfont.c +++ /dev/null @@ -1,54 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> - -int main(int argc, char *argv) -{ - unsigned n; - unsigned char *x; - unsigned m; - unsigned run_val; - unsigned run_count; - - n = gimp_image.width * gimp_image.height; - m = 0; - x = gimp_image.pixel_data; - - printf("struct {\n"); - printf(" unsigned width;\n"); - printf(" unsigned height;\n"); - printf(" unsigned cwidth;\n"); - printf(" unsigned cheight;\n"); - printf(" unsigned char rundata[];\n"); - printf("} font = {\n"); - printf(" .width = %d,\n .height = %d,\n .cwidth = %d,\n .cheight = %d,\n", gimp_image.width, gimp_image.height, - gimp_image.width / 96, gimp_image.height); - printf(" .rundata = {\n"); - - run_val = (*x ? 0 : 255); - run_count = 1; - n--; - x+=3; - - while(n-- > 0) { - unsigned val = (*x ? 0 : 255); - x+=3; - if((val == run_val) && (run_count < 127)) { - run_count++; - } else { -eject: - printf("0x%02x,",run_count | (run_val ? 0x80 : 0x00)); - run_val = val; - run_count = 1; - m += 5; - if(m >= 75) { - printf("\n"); - m = 0; - } - } - } - printf("0x%02x,",run_count | (run_val ? 0x80 : 0x00)); - printf("\n0x00,"); - printf("\n"); - printf(" }\n};\n"); - return 0; -} diff --git a/otautil/cache_location.cpp b/otautil/cache_location.cpp index 8ddefec5e..6139bf17b 100644 --- a/otautil/cache_location.cpp +++ b/otautil/cache_location.cpp @@ -19,6 +19,7 @@ constexpr const char kDefaultCacheTempSource[] = "/cache/saved.file"; constexpr const char kDefaultLastCommandFile[] = "/cache/recovery/last_command"; constexpr const char kDefaultStashDirectoryBase[] = "/cache/recovery"; +constexpr const char kDefaultCacheLogDirectory[] = "/cache/recovery"; CacheLocation& CacheLocation::location() { static CacheLocation cache_location; @@ -28,4 +29,5 @@ CacheLocation& CacheLocation::location() { CacheLocation::CacheLocation() : cache_temp_source_(kDefaultCacheTempSource), last_command_file_(kDefaultLastCommandFile), - stash_directory_base_(kDefaultStashDirectoryBase) {} + stash_directory_base_(kDefaultStashDirectoryBase), + cache_log_directory_(kDefaultCacheLogDirectory) {} diff --git a/otautil/include/otautil/cache_location.h b/otautil/include/otautil/cache_location.h index f2f663816..005395e5f 100644 --- a/otautil/include/otautil/cache_location.h +++ b/otautil/include/otautil/cache_location.h @@ -49,6 +49,13 @@ class CacheLocation { stash_directory_base_ = base; } + std::string cache_log_directory() const { + return cache_log_directory_; + } + void set_cache_log_directory(const std::string& log_dir) { + cache_log_directory_ = log_dir; + } + private: CacheLocation(); DISALLOW_COPY_AND_ASSIGN(CacheLocation); @@ -64,6 +71,9 @@ class CacheLocation { // The base directory to write stashes during update. std::string stash_directory_base_; + + // The location of last_log & last_kmsg. + std::string cache_log_directory_; }; #endif // _OTAUTIL_OTAUTIL_CACHE_LOCATION_H_ diff --git a/recovery.cpp b/recovery.cpp index d887d07fb..e266d9312 100644 --- a/recovery.cpp +++ b/recovery.cpp @@ -1557,14 +1557,14 @@ int main(int argc, char **argv) { // to log the update attempt since update_package is non-NULL. modified_flash = true; - if (!is_battery_ok()) { + if (retry_count == 0 && !is_battery_ok()) { ui->Print("battery capacity is not enough for installing package, needed is %d%%\n", BATTERY_OK_PERCENTAGE); // Log the error code to last_install when installation skips due to // low battery. log_failure_code(kLowBattery, update_package); status = INSTALL_SKIPPED; - } else if (bootreason_in_blacklist()) { + } else if (retry_count == 0 && bootreason_in_blacklist()) { // Skip update-on-reboot when bootreason is kernel_panic or similar ui->Print("bootreason is in the blacklist; skip OTA installation\n"); log_failure_code(kBootreasonInBlacklist, update_package); diff --git a/sample_updater/Android.mk b/sample_updater/Android.mk new file mode 100644 index 000000000..2b0fcbeec --- /dev/null +++ b/sample_updater/Android.mk @@ -0,0 +1,27 @@ +# +# 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. +# + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_PACKAGE_NAME := SystemUpdateApp +LOCAL_SDK_VERSION := system_current +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := $(call all-java-files-under, src) + +include $(BUILD_PACKAGE) diff --git a/sample_updater/AndroidManifest.xml b/sample_updater/AndroidManifest.xml new file mode 100644 index 000000000..66414b5d3 --- /dev/null +++ b/sample_updater/AndroidManifest.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + 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. + --> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.update"> + + <application android:label="Sample Updater"> + <activity android:name=".ui.SystemUpdateActivity" + android:label="Sample Updater"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + </application> + +</manifest> + diff --git a/sample_updater/README.md b/sample_updater/README.md new file mode 100644 index 000000000..a06c52d4b --- /dev/null +++ b/sample_updater/README.md @@ -0,0 +1 @@ +# System update sample app. diff --git a/sample_updater/res/layout/activity_main.xml b/sample_updater/res/layout/activity_main.xml new file mode 100644 index 000000000..bd7d68677 --- /dev/null +++ b/sample_updater/res/layout/activity_main.xml @@ -0,0 +1,20 @@ +<!-- + 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. + --> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" + android:layout_height="match_parent"> + +</LinearLayout> diff --git a/sample_updater/src/com/android/update/ui/SystemUpdateActivity.java b/sample_updater/src/com/android/update/ui/SystemUpdateActivity.java new file mode 100644 index 000000000..e57b1673c --- /dev/null +++ b/sample_updater/src/com/android/update/ui/SystemUpdateActivity.java @@ -0,0 +1,68 @@ +/* + * 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. + */ + +package com.android.update.ui; + +import android.app.Activity; +import android.os.UpdateEngine; +import android.os.UpdateEngineCallback; + +/** Main update activity. */ +public class SystemUpdateActivity extends Activity { + + private UpdateEngine updateEngine; + private UpdateEngineCallbackImpl updateEngineCallbackImpl = new UpdateEngineCallbackImpl(this); + + @Override + public void onResume() { + super.onResume(); + updateEngine = new UpdateEngine(); + updateEngine.bind(updateEngineCallbackImpl); + } + + @Override + public void onPause() { + updateEngine.unbind(); + super.onPause(); + } + + void onStatusUpdate(int i, float v) { + // Handle update engine status update + } + + void onPayloadApplicationComplete(int i) { + // Handle apply payload completion + } + + private static class UpdateEngineCallbackImpl extends UpdateEngineCallback { + + private final SystemUpdateActivity activity; + + public UpdateEngineCallbackImpl(SystemUpdateActivity activity) { + this.activity = activity; + } + + @Override + public void onStatusUpdate(int i, float v) { + activity.onStatusUpdate(i, v); + } + + @Override + public void onPayloadApplicationComplete(int i) { + activity.onPayloadApplicationComplete(i); + } + } +} diff --git a/screen_ui.cpp b/screen_ui.cpp index c8fb5aa75..317e5529c 100644 --- a/screen_ui.cpp +++ b/screen_ui.cpp @@ -53,7 +53,98 @@ static double now() { return tv.tv_sec + tv.tv_usec / 1000000.0; } -ScreenRecoveryUI::ScreenRecoveryUI() +Menu::Menu(bool scrollable, size_t max_items, size_t max_length) + : scrollable_(scrollable), + max_display_items_(max_items), + max_item_length_(max_length), + text_headers_(nullptr), + menu_start_(0), + selection_(0) { + CHECK_LE(max_items, static_cast<size_t>(std::numeric_limits<int>::max())); +} + +const char* const* Menu::text_headers() const { + return text_headers_; +} + +std::string Menu::TextItem(size_t index) const { + CHECK_LT(index, text_items_.size()); + + return text_items_[index]; +} + +size_t Menu::MenuStart() const { + return menu_start_; +} + +size_t Menu::MenuEnd() const { + return std::min(ItemsCount(), menu_start_ + max_display_items_); +} + +size_t Menu::ItemsCount() const { + return text_items_.size(); +} + +bool Menu::ItemsOverflow(std::string* cur_selection_str) const { + if (!scrollable_ || static_cast<size_t>(ItemsCount()) <= max_display_items_) { + return false; + } + + *cur_selection_str = + android::base::StringPrintf("Current item: %d/%zu", selection_ + 1, ItemsCount()); + return true; +} + +void Menu::Start(const char* const* headers, const char* const* items, int initial_selection) { + text_headers_ = headers; + + // It's fine to have more entries than text_rows_ if scrollable menu is supported. + size_t max_items_count = scrollable_ ? std::numeric_limits<int>::max() : max_display_items_; + for (size_t i = 0; i < max_items_count && items[i] != nullptr; ++i) { + text_items_.emplace_back(items[i], strnlen(items[i], max_item_length_)); + } + + CHECK(!text_items_.empty()); + selection_ = initial_selection; +} + +// TODO(xunchang) modify the function parameters to button up & down. +int Menu::Select(int sel) { + CHECK_LE(ItemsCount(), static_cast<size_t>(std::numeric_limits<int>::max())); + int count = ItemsCount(); + + // Wraps the selection at boundary if the menu is not scrollable. + if (!scrollable_) { + if (sel < 0) { + selection_ = count - 1; + } else if (sel >= count) { + selection_ = 0; + } else { + selection_ = sel; + } + + return selection_; + } + + if (sel < 0) { + selection_ = 0; + } else if (sel >= count) { + selection_ = count - 1; + } else { + if (static_cast<size_t>(sel) < menu_start_) { + menu_start_--; + } else if (static_cast<size_t>(sel) >= MenuEnd()) { + menu_start_++; + } + selection_ = sel; + } + + return selection_; +} + +ScreenRecoveryUI::ScreenRecoveryUI() : ScreenRecoveryUI(false) {} + +ScreenRecoveryUI::ScreenRecoveryUI(bool scrollable_menu) : kMarginWidth(RECOVERY_UI_MARGIN_WIDTH), kMarginHeight(RECOVERY_UI_MARGIN_HEIGHT), kAnimationFps(RECOVERY_UI_ANIMATION_FPS), @@ -71,10 +162,7 @@ ScreenRecoveryUI::ScreenRecoveryUI() text_row_(0), show_text(false), show_text_ever(false), - menu_headers_(nullptr), - show_menu(false), - menu_items(0), - menu_sel(0), + scrollable_menu_(scrollable_menu), file_viewer_text_(nullptr), intro_frames(0), loop_frames(0), @@ -407,13 +495,13 @@ int ScreenRecoveryUI::DrawWrappedTextLines(int x, int y, const char* const* line static const char* REGULAR_HELP[] = { "Use volume up/down and power.", - NULL + nullptr, }; static const char* LONG_PRESS_HELP[] = { "Any button cycles highlight.", "Long-press activates.", - NULL + nullptr, }; // Redraws everything on the screen. Does not flip pages. Should only be called with updateMutex @@ -428,8 +516,13 @@ void ScreenRecoveryUI::draw_screen_locked() { gr_color(0, 0, 0, 255); gr_clear(); + draw_menu_and_text_buffer_locked(HasThreeButtons() ? REGULAR_HELP : LONG_PRESS_HELP); +} + +// Draws the menu and text buffer on the screen. Should only be called with updateMutex locked. +void ScreenRecoveryUI::draw_menu_and_text_buffer_locked(const char* const* help_message) { int y = kMarginHeight; - if (show_menu) { + if (menu_) { static constexpr int kMenuIndent = 4; int x = kMarginWidth + kMenuIndent; @@ -440,26 +533,46 @@ void ScreenRecoveryUI::draw_screen_locked() { for (const auto& chunk : android::base::Split(recovery_fingerprint, ":")) { y += DrawTextLine(x, y, chunk.c_str(), false); } - y += DrawTextLines(x, y, HasThreeButtons() ? REGULAR_HELP : LONG_PRESS_HELP); + y += DrawTextLines(x, y, help_message); + + // Draw menu header. SetColor(HEADER); - // Ignore kMenuIndent, which is not taken into account by text_cols_. - y += DrawWrappedTextLines(kMarginWidth, y, menu_headers_); + if (!menu_->scrollable()) { + y += DrawWrappedTextLines(x, y, menu_->text_headers()); + } else { + y += DrawTextLines(x, y, menu_->text_headers()); + // Show the current menu item number in relation to total number if items don't fit on the + // screen. + std::string cur_selection_str; + if (menu_->ItemsOverflow(&cur_selection_str)) { + y += DrawTextLine(x, y, cur_selection_str.c_str(), true); + } + } + // Draw menu items. SetColor(MENU); - y += DrawHorizontalRule(y) + 4; - for (int i = 0; i < menu_items; ++i) { - if (i == menu_sel) { + // Do not draw the horizontal rule for wear devices. + if (!menu_->scrollable()) { + y += DrawHorizontalRule(y) + 4; + } + for (size_t i = menu_->MenuStart(); i < menu_->MenuEnd(); ++i) { + bool bold = false; + if (i == static_cast<size_t>(menu_->selection())) { // Draw the highlight bar. SetColor(IsLongPress() ? MENU_SEL_BG_ACTIVE : MENU_SEL_BG); - DrawHighlightBar(0, y - 2, ScreenWidth(), char_height_ + 4); + + int bar_height = char_height_ + 4; + DrawHighlightBar(0, y - 2, ScreenWidth(), bar_height); + // Bold white text for the selected item. SetColor(MENU_SEL_FG); - y += DrawTextLine(x, y, menu_[i].c_str(), true); - SetColor(MENU); - } else { - y += DrawTextLine(x, y, menu_[i].c_str(), false); + bold = true; } + + y += DrawTextLine(x, y, menu_->TextItem(i).c_str(), bold); + + SetColor(MENU); } y += DrawHorizontalRule(y); } @@ -864,15 +977,10 @@ void ScreenRecoveryUI::ShowFile(const char* filename) { void ScreenRecoveryUI::StartMenu(const char* const* headers, const char* const* items, int initial_selection) { pthread_mutex_lock(&updateMutex); - if (text_rows_ > 0 && text_cols_ > 0) { - menu_headers_ = headers; - menu_.clear(); - for (size_t i = 0; i < text_rows_ && items[i] != nullptr; ++i) { - menu_.emplace_back(std::string(items[i], strnlen(items[i], text_cols_ - 1))); - } - menu_items = static_cast<int>(menu_.size()); - show_menu = true; - menu_sel = initial_selection; + if (text_rows_ > 0 && text_cols_ > 1) { + menu_ = std::make_unique<Menu>(scrollable_menu_, text_rows_, text_cols_ - 1); + menu_->Start(headers, items, initial_selection); + update_screen_locked(); } pthread_mutex_unlock(&updateMutex); @@ -880,16 +988,13 @@ void ScreenRecoveryUI::StartMenu(const char* const* headers, const char* const* int ScreenRecoveryUI::SelectMenu(int sel) { pthread_mutex_lock(&updateMutex); - if (show_menu) { - int old_sel = menu_sel; - menu_sel = sel; - - // Wrap at top and bottom. - if (menu_sel < 0) menu_sel = menu_items - 1; - if (menu_sel >= menu_items) menu_sel = 0; + if (menu_) { + int old_sel = menu_->selection(); + sel = menu_->Select(sel); - sel = menu_sel; - if (menu_sel != old_sel) update_screen_locked(); + if (sel != old_sel) { + update_screen_locked(); + } } pthread_mutex_unlock(&updateMutex); return sel; @@ -897,8 +1002,8 @@ int ScreenRecoveryUI::SelectMenu(int sel) { void ScreenRecoveryUI::EndMenu() { pthread_mutex_lock(&updateMutex); - if (show_menu && text_rows_ > 0 && text_cols_ > 0) { - show_menu = false; + if (menu_) { + menu_.reset(); update_screen_locked(); } pthread_mutex_unlock(&updateMutex); diff --git a/screen_ui.h b/screen_ui.h index f05761c42..c1222a576 100644 --- a/screen_ui.h +++ b/screen_ui.h @@ -20,6 +20,7 @@ #include <pthread.h> #include <stdio.h> +#include <memory> #include <string> #include <vector> @@ -28,6 +29,70 @@ // From minui/minui.h. struct GRSurface; +// This class maintains the menu selection and display of the screen ui. +class Menu { + public: + Menu(bool scrollable, size_t max_items, size_t max_length); + + bool scrollable() const { + return scrollable_; + } + + int selection() const { + return selection_; + } + + // Returns count of menu items. + size_t ItemsCount() const; + // Returns the index of the first menu item. + size_t MenuStart() const; + // Returns the index of the last menu item + 1. + size_t MenuEnd() const; + + // Menu example: + // info: Android Recovery + // .... + // help messages: Swipe up/down to move + // Swipe left/right to select + // empty line (horizontal rule): + // menu headers: Select file to view + // menu items: /cache/recovery/last_log + // /cache/recovery/last_log.1 + // /cache/recovery/last_log.2 + // ... + const char* const* text_headers() const; + std::string TextItem(size_t index) const; + + // Checks if the menu items fit vertically on the screen. Returns true and set the + // |cur_selection_str| if the items exceed the screen limit. + bool ItemsOverflow(std::string* cur_selection_str) const; + + // Starts the menu with |headers| and |items| in text. Sets the default selection to + // |initial_selection|. + void Start(const char* const* headers, const char* const* items, int initial_selection); + + // Sets the current selection to |sel|. Handle the overflow cases depending on if the menu is + // scrollable. + int Select(int sel); + + private: + // The menu is scrollable to display more items. Used on wear devices who have smaller screens. + const bool scrollable_; + // The max number of menu items to fit vertically on a screen. + const size_t max_display_items_; + // The length of each item to fit horizontally on a screen. + const size_t max_item_length_; + + // Internal storage for the menu headers and items in text. + const char* const* text_headers_; + std::vector<std::string> text_items_; + + // The first item to display on the screen. + size_t menu_start_; + // Current menu selection. + int selection_; +}; + // Implementation of RecoveryUI appropriate for devices with a screen // (shows an icon + a progress bar, text logging, menu, etc.) class ScreenRecoveryUI : public RecoveryUI { @@ -44,6 +109,7 @@ class ScreenRecoveryUI : public RecoveryUI { }; ScreenRecoveryUI(); + explicit ScreenRecoveryUI(bool scrollable_menu); bool Init(const std::string& locale) override; @@ -101,6 +167,7 @@ class ScreenRecoveryUI : public RecoveryUI { virtual void draw_background_locked(); virtual void draw_foreground_locked(); virtual void draw_screen_locked(); + virtual void draw_menu_and_text_buffer_locked(const char* const* help_message); virtual void update_screen_locked(); virtual void update_progress_locked(); @@ -184,10 +251,8 @@ class ScreenRecoveryUI : public RecoveryUI { bool show_text; bool show_text_ever; // has show_text ever been true? - std::vector<std::string> menu_; - const char* const* menu_headers_; - bool show_menu; - int menu_items, menu_sel; + bool scrollable_menu_; + std::unique_ptr<Menu> menu_; // An alternate text screen, swapped with 'text_' when we're viewing a log file. char** file_viewer_text_; diff --git a/tests/Android.mk b/tests/Android.mk index b3584fe87..58cefd226 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -23,6 +23,7 @@ LOCAL_MODULE := recovery_unit_test LOCAL_COMPATIBILITY_SUITE := device-tests LOCAL_STATIC_LIBRARIES := \ libverifier \ + librecovery_ui \ libminui \ libotautil \ libupdater \ @@ -38,11 +39,14 @@ LOCAL_SRC_FILES := \ unit/dirutil_test.cpp \ unit/locale_test.cpp \ unit/rangeset_test.cpp \ + unit/screen_ui_test.cpp \ unit/sysutil_test.cpp \ - unit/zip_test.cpp \ + unit/zip_test.cpp LOCAL_C_INCLUDES := bootable/recovery LOCAL_SHARED_LIBRARIES := liblog +LOCAL_TEST_DATA := \ + $(call find-test-data-in-subdirs, $(LOCAL_PATH), "*", testdata) include $(BUILD_NATIVE_TEST) # Manual tests @@ -59,25 +63,8 @@ LOCAL_SHARED_LIBRARIES := \ liblog \ libpng -resource_files := $(call find-files-in-subdirs, bootable/recovery, \ - "*_text.png", \ - res-mdpi/images \ - res-hdpi/images \ - res-xhdpi/images \ - res-xxhdpi/images \ - res-xxxhdpi/images \ - ) - -# The resource image files that will go to $OUT/data/nativetest/recovery. -testimage_out_path := $(TARGET_OUT_DATA)/nativetest/recovery -GEN := $(addprefix $(testimage_out_path)/, $(resource_files)) - -$(GEN): PRIVATE_PATH := $(LOCAL_PATH) -$(GEN): PRIVATE_CUSTOM_TOOL = cp $< $@ -$(GEN): $(testimage_out_path)/% : bootable/recovery/% - $(transform-generated-source) -LOCAL_GENERATED_SOURCES += $(GEN) - +LOCAL_TEST_DATA := \ + $(call find-test-data-in-subdirs, bootable/recovery, "*_text.png", res-*) include $(BUILD_NATIVE_TEST) # Component tests @@ -169,29 +156,8 @@ LOCAL_STATIC_LIBRARIES := \ libBionicGtestMain \ $(tune2fs_static_libraries) -testdata_files := $(call find-subdir-files, testdata/*) - -# The testdata files that will go to $OUT/data/nativetest/recovery. -testdata_out_path := $(TARGET_OUT_DATA)/nativetest/recovery -GEN := $(addprefix $(testdata_out_path)/, $(testdata_files)) -$(GEN): PRIVATE_PATH := $(LOCAL_PATH) -$(GEN): PRIVATE_CUSTOM_TOOL = cp $< $@ -$(GEN): $(testdata_out_path)/% : $(LOCAL_PATH)/% - $(transform-generated-source) -LOCAL_GENERATED_SOURCES += $(GEN) - -# A copy of the testdata to be packed into continuous_native_tests.zip. -testdata_continuous_zip_prefix := \ - $(call intermediates-dir-for,PACKAGING,recovery_component_test)/DATA -testdata_continuous_zip_path := $(testdata_continuous_zip_prefix)/nativetest/recovery -GEN := $(addprefix $(testdata_continuous_zip_path)/, $(testdata_files)) -$(GEN): PRIVATE_PATH := $(LOCAL_PATH) -$(GEN): PRIVATE_CUSTOM_TOOL = cp $< $@ -$(GEN): $(testdata_continuous_zip_path)/% : $(LOCAL_PATH)/% - $(transform-generated-source) -LOCAL_GENERATED_SOURCES += $(GEN) -LOCAL_PICKUP_FILES := $(testdata_continuous_zip_prefix) - +LOCAL_TEST_DATA := \ + $(call find-test-data-in-subdirs, $(LOCAL_PATH), "*", testdata) include $(BUILD_NATIVE_TEST) # Host tests @@ -220,4 +186,6 @@ LOCAL_STATIC_LIBRARIES := \ libBionicGtestMain LOCAL_SHARED_LIBRARIES := \ liblog +LOCAL_TEST_DATA := \ + $(call find-test-data-in-subdirs, $(LOCAL_PATH), "*", testdata) include $(BUILD_HOST_NATIVE_TEST) diff --git a/tests/AndroidTest.xml b/tests/AndroidTest.xml index 3999aa57d..6b86085aa 100644 --- a/tests/AndroidTest.xml +++ b/tests/AndroidTest.xml @@ -16,16 +16,18 @@ <configuration description="Config for recovery_component_test and recovery_unit_test"> <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"> <option name="cleanup" value="true" /> - <option name="push" value="recovery_component_test->/data/local/tmp/recovery_component_test" /> - <option name="push" value="recovery_unit_test->/data/local/tmp/recovery_unit_test" /> + <option name="push" value="recovery_component_test->/data/local/tmp/recovery_component_test/recovery_component_test" /> + <option name="push" value="testdata->/data/local/tmp/recovery_component_test/testdata" /> + <option name="push" value="recovery_unit_test->/data/local/tmp/recovery_unit_test/recovery_unit_test" /> + <option name="push" value="testdata->/data/local/tmp/recovery_unit_test/testdata" /> </target_preparer> <option name="test-suite-tag" value="apct" /> <test class="com.android.tradefed.testtype.GTest" > - <option name="native-test-device-path" value="/data/local/tmp" /> + <option name="native-test-device-path" value="/data/local/tmp/recovery_component_test" /> <option name="module-name" value="recovery_component_test" /> </test> <test class="com.android.tradefed.testtype.GTest" > - <option name="native-test-device-path" value="/data/local/tmp" /> + <option name="native-test-device-path" value="/data/local/tmp/recovery_unit_test" /> <option name="module-name" value="recovery_unit_test" /> </test> </configuration> diff --git a/tests/common/test_constants.h b/tests/common/test_constants.h index 514818e0a..b6c27a754 100644 --- a/tests/common/test_constants.h +++ b/tests/common/test_constants.h @@ -17,10 +17,10 @@ #ifndef _OTA_TEST_CONSTANTS_H #define _OTA_TEST_CONSTANTS_H -#include <stdlib.h> - #include <string> +#include <android-base/file.h> + // Zip entries in ziptest_valid.zip. static const std::string kATxtContents("abcdefghabcdefgh\n"); static const std::string kBTxtContents("abcdefgh\n"); @@ -32,14 +32,9 @@ static const std::string kATxtSha1Sum("32c96a03dc8cd20097940f351bca6261ee5a1643" // echo -n -e "abcdefgh\n" | sha1sum static const std::string kBTxtSha1Sum("e414af7161c9554089f4106d6f1797ef14a73666"); -static std::string from_testdata_base(const std::string& fname) { -#ifdef __ANDROID__ - static std::string data_root = getenv("ANDROID_DATA"); -#else - static std::string data_root = std::string(getenv("ANDROID_PRODUCT_OUT")) + "/data"; -#endif - - return data_root + "/nativetest/recovery/testdata/" + fname; +[[maybe_unused]] static std::string from_testdata_base(const std::string& fname) { + static std::string exec_dir = android::base::GetExecutableDirectory(); + return exec_dir + "/testdata/" + fname; } #endif // _OTA_TEST_CONSTANTS_H diff --git a/tests/component/applypatch_test.cpp b/tests/component/applypatch_test.cpp index 61e06adb6..aa0959bf5 100644 --- a/tests/component/applypatch_test.cpp +++ b/tests/component/applypatch_test.cpp @@ -14,8 +14,10 @@ * limitations under the License. */ +#include <dirent.h> #include <fcntl.h> #include <gtest/gtest.h> +#include <libgen.h> #include <stdio.h> #include <stdlib.h> #include <sys/stat.h> @@ -23,6 +25,7 @@ #include <sys/types.h> #include <time.h> +#include <algorithm> #include <memory> #include <string> #include <vector> @@ -30,6 +33,7 @@ #include <android-base/file.h> #include <android-base/stringprintf.h> #include <android-base/test_utils.h> +#include <android-base/unique_fd.h> #include <bsdiff/bsdiff.h> #include <openssl/sha.h> @@ -110,6 +114,52 @@ class ApplyPatchModesTest : public ::testing::Test { TemporaryFile cache_source; }; +class FreeCacheTest : public ::testing::Test { + protected: + static constexpr size_t PARTITION_SIZE = 4096 * 10; + + // Returns a sorted list of files in |dirname|. + static std::vector<std::string> FindFilesInDir(const std::string& dirname) { + std::vector<std::string> file_list; + + std::unique_ptr<DIR, decltype(&closedir)> d(opendir(dirname.c_str()), closedir); + struct dirent* de; + while ((de = readdir(d.get())) != 0) { + std::string path = dirname + "/" + de->d_name; + + struct stat st; + if (stat(path.c_str(), &st) == 0 && S_ISREG(st.st_mode)) { + file_list.emplace_back(de->d_name); + } + } + + std::sort(file_list.begin(), file_list.end()); + return file_list; + } + + static void AddFilesToDir(const std::string& dir, const std::vector<std::string>& files) { + std::string zeros(4096, 0); + for (const auto& file : files) { + std::string path = dir + "/" + file; + ASSERT_TRUE(android::base::WriteStringToFile(zeros, path)); + } + } + + void SetUp() override { + CacheLocation::location().set_cache_log_directory(mock_log_dir.path); + } + + // A mock method to calculate the free space. It assumes the partition has a total size of 40960 + // bytes and all files are 4096 bytes in size. + size_t MockFreeSpaceChecker(const std::string& dirname) { + std::vector<std::string> files = FindFilesInDir(dirname); + return PARTITION_SIZE - 4096 * files.size(); + } + + TemporaryDir mock_cache; + TemporaryDir mock_log_dir; +}; + TEST_F(ApplyPatchTest, CheckModeSkip) { std::vector<std::string> sha1s; ASSERT_EQ(0, applypatch_check(&old_file[0], sha1s)); @@ -205,67 +255,96 @@ TEST_F(ApplyPatchModesTest, PatchModeEmmcTarget) { sha1sum(boot_img, &boot_img_sha1, &boot_img_size); std::string recovery_img = from_testdata_base("recovery.img"); - size_t size; + size_t recovery_img_size; std::string recovery_img_sha1; - sha1sum(recovery_img, &recovery_img_sha1, &size); - std::string recovery_img_size = std::to_string(size); + sha1sum(recovery_img, &recovery_img_sha1, &recovery_img_size); + std::string recovery_img_size_arg = std::to_string(recovery_img_size); std::string bonus_file = from_testdata_base("bonus.file"); // applypatch -b <bonus-file> <src-file> <tgt-file> <tgt-sha1> <tgt-size> <src-sha1>:<patch> - TemporaryFile tmp1; - std::string src_file = + std::string src_file_arg = "EMMC:" + boot_img + ":" + std::to_string(boot_img_size) + ":" + boot_img_sha1; - std::string tgt_file = "EMMC:" + std::string(tmp1.path); - std::string patch = boot_img_sha1 + ":" + from_testdata_base("recovery-from-boot.p"); - std::vector<const char*> args = { - "applypatch", - "-b", - bonus_file.c_str(), - src_file.c_str(), - tgt_file.c_str(), - recovery_img_sha1.c_str(), - recovery_img_size.c_str(), - patch.c_str() - }; + TemporaryFile tgt_file; + std::string tgt_file_arg = "EMMC:"s + tgt_file.path; + std::string patch_arg = boot_img_sha1 + ":" + from_testdata_base("recovery-from-boot.p"); + std::vector<const char*> args = { "applypatch", + "-b", + bonus_file.c_str(), + src_file_arg.c_str(), + tgt_file_arg.c_str(), + recovery_img_sha1.c_str(), + recovery_img_size_arg.c_str(), + patch_arg.c_str() }; ASSERT_EQ(0, applypatch_modes(args.size(), args.data())); +} + +// Tests patching the EMMC target without a separate bonus file (i.e. recovery-from-boot patch has +// everything). +TEST_F(ApplyPatchModesTest, PatchModeEmmcTargetWithoutBonusFile) { + std::string boot_img = from_testdata_base("boot.img"); + size_t boot_img_size; + std::string boot_img_sha1; + sha1sum(boot_img, &boot_img_sha1, &boot_img_size); + + std::string recovery_img = from_testdata_base("recovery.img"); + size_t recovery_img_size; + std::string recovery_img_sha1; + sha1sum(recovery_img, &recovery_img_sha1, &recovery_img_size); + std::string recovery_img_size_arg = std::to_string(recovery_img_size); // applypatch <src-file> <tgt-file> <tgt-sha1> <tgt-size> <src-sha1>:<patch> - TemporaryFile tmp2; - patch = boot_img_sha1 + ":" + from_testdata_base("recovery-from-boot-with-bonus.p"); - tgt_file = "EMMC:" + std::string(tmp2.path); - std::vector<const char*> args2 = { - "applypatch", - src_file.c_str(), - tgt_file.c_str(), - recovery_img_sha1.c_str(), - recovery_img_size.c_str(), - patch.c_str() - }; - ASSERT_EQ(0, applypatch_modes(args2.size(), args2.data())); + std::string src_file_arg = + "EMMC:" + boot_img + ":" + std::to_string(boot_img_size) + ":" + boot_img_sha1; + TemporaryFile tgt_file; + std::string tgt_file_arg = "EMMC:"s + tgt_file.path; + std::string patch_arg = + boot_img_sha1 + ":" + from_testdata_base("recovery-from-boot-with-bonus.p"); + std::vector<const char*> args = { "applypatch", + src_file_arg.c_str(), + tgt_file_arg.c_str(), + recovery_img_sha1.c_str(), + recovery_img_size_arg.c_str(), + patch_arg.c_str() }; + ASSERT_EQ(0, applypatch_modes(args.size(), args.data())); +} + +TEST_F(ApplyPatchModesTest, PatchModeEmmcTargetWithMultiplePatches) { + std::string boot_img = from_testdata_base("boot.img"); + size_t boot_img_size; + std::string boot_img_sha1; + sha1sum(boot_img, &boot_img_sha1, &boot_img_size); + + std::string recovery_img = from_testdata_base("recovery.img"); + size_t recovery_img_size; + std::string recovery_img_sha1; + sha1sum(recovery_img, &recovery_img_sha1, &recovery_img_size); + std::string recovery_img_size_arg = std::to_string(recovery_img_size); + + std::string bonus_file = from_testdata_base("bonus.file"); // applypatch -b <bonus-file> <src-file> <tgt-file> <tgt-sha1> <tgt-size> \ - // <src-sha1-fake>:<patch1> <src-sha1>:<patch2> - TemporaryFile tmp3; - tgt_file = "EMMC:" + std::string(tmp3.path); + // <src-sha1-fake1>:<patch1> <src-sha1>:<patch2> <src-sha1-fake2>:<patch3> + std::string src_file_arg = + "EMMC:" + boot_img + ":" + std::to_string(boot_img_size) + ":" + boot_img_sha1; + TemporaryFile tgt_file; + std::string tgt_file_arg = "EMMC:"s + tgt_file.path; std::string bad_sha1_a = android::base::StringPrintf("%040x", rand()); std::string bad_sha1_b = android::base::StringPrintf("%040x", rand()); std::string patch1 = bad_sha1_a + ":" + from_testdata_base("recovery-from-boot.p"); std::string patch2 = boot_img_sha1 + ":" + from_testdata_base("recovery-from-boot.p"); std::string patch3 = bad_sha1_b + ":" + from_testdata_base("recovery-from-boot.p"); - std::vector<const char*> args3 = { - "applypatch", - "-b", - bonus_file.c_str(), - src_file.c_str(), - tgt_file.c_str(), - recovery_img_sha1.c_str(), - recovery_img_size.c_str(), - patch1.c_str(), - patch2.c_str(), - patch3.c_str() - }; - ASSERT_EQ(0, applypatch_modes(args3.size(), args3.data())); + std::vector<const char*> args = { "applypatch", + "-b", + bonus_file.c_str(), + src_file_arg.c_str(), + tgt_file_arg.c_str(), + recovery_img_sha1.c_str(), + recovery_img_size_arg.c_str(), + patch1.c_str(), + patch2.c_str(), + patch3.c_str() }; + ASSERT_EQ(0, applypatch_modes(args.size(), args.data())); } // Ensures that applypatch works with a bsdiff based recovery-from-boot.p. @@ -385,3 +464,82 @@ TEST_F(ApplyPatchModesTest, CheckModeInvalidArgs) { TEST_F(ApplyPatchModesTest, ShowLicenses) { ASSERT_EQ(0, applypatch_modes(2, (const char* []){ "applypatch", "-l" })); } + +TEST_F(FreeCacheTest, FreeCacheSmoke) { + std::vector<std::string> files = { "file1", "file2", "file3" }; + AddFilesToDir(mock_cache.path, files); + ASSERT_EQ(files, FindFilesInDir(mock_cache.path)); + ASSERT_EQ(4096 * 7, MockFreeSpaceChecker(mock_cache.path)); + + ASSERT_TRUE(RemoveFilesInDirectory(4096 * 9, mock_cache.path, [&](const std::string& dir) { + return this->MockFreeSpaceChecker(dir); + })); + + ASSERT_EQ(std::vector<std::string>{ "file3" }, FindFilesInDir(mock_cache.path)); + ASSERT_EQ(4096 * 9, MockFreeSpaceChecker(mock_cache.path)); +} + +TEST_F(FreeCacheTest, FreeCacheOpenFile) { + std::vector<std::string> files = { "file1", "file2" }; + AddFilesToDir(mock_cache.path, files); + ASSERT_EQ(files, FindFilesInDir(mock_cache.path)); + ASSERT_EQ(4096 * 8, MockFreeSpaceChecker(mock_cache.path)); + + std::string file1_path = mock_cache.path + "/file1"s; + android::base::unique_fd fd(open(file1_path.c_str(), O_RDONLY)); + + // file1 can't be deleted as it's opened by us. + ASSERT_FALSE(RemoveFilesInDirectory(4096 * 10, mock_cache.path, [&](const std::string& dir) { + return this->MockFreeSpaceChecker(dir); + })); + + ASSERT_EQ(std::vector<std::string>{ "file1" }, FindFilesInDir(mock_cache.path)); +} + +TEST_F(FreeCacheTest, FreeCacheLogsSmoke) { + std::vector<std::string> log_files = { "last_log", "last_log.1", "last_kmsg.2", "last_log.5", + "last_log.10" }; + AddFilesToDir(mock_log_dir.path, log_files); + ASSERT_EQ(4096 * 5, MockFreeSpaceChecker(mock_log_dir.path)); + + ASSERT_TRUE(RemoveFilesInDirectory(4096 * 8, mock_log_dir.path, [&](const std::string& dir) { + return this->MockFreeSpaceChecker(dir); + })); + + // Logs with a higher index will be deleted first + std::vector<std::string> expected = { "last_log", "last_log.1" }; + ASSERT_EQ(expected, FindFilesInDir(mock_log_dir.path)); + ASSERT_EQ(4096 * 8, MockFreeSpaceChecker(mock_log_dir.path)); +} + +TEST_F(FreeCacheTest, FreeCacheLogsStringComparison) { + std::vector<std::string> log_files = { "last_log.1", "last_kmsg.1", "last_log.not_number", + "last_kmsgrandom" }; + AddFilesToDir(mock_log_dir.path, log_files); + ASSERT_EQ(4096 * 6, MockFreeSpaceChecker(mock_log_dir.path)); + + ASSERT_TRUE(RemoveFilesInDirectory(4096 * 9, mock_log_dir.path, [&](const std::string& dir) { + return this->MockFreeSpaceChecker(dir); + })); + + // Logs with incorrect format will be deleted first; and the last_kmsg with the same index is + // deleted before last_log. + std::vector<std::string> expected = { "last_log.1" }; + ASSERT_EQ(expected, FindFilesInDir(mock_log_dir.path)); + ASSERT_EQ(4096 * 9, MockFreeSpaceChecker(mock_log_dir.path)); +} + +TEST_F(FreeCacheTest, FreeCacheLogsOtherFiles) { + std::vector<std::string> log_files = { "last_install", "command", "block.map", "last_log", + "last_kmsg.1" }; + AddFilesToDir(mock_log_dir.path, log_files); + ASSERT_EQ(4096 * 5, MockFreeSpaceChecker(mock_log_dir.path)); + + ASSERT_FALSE(RemoveFilesInDirectory(4096 * 8, mock_log_dir.path, [&](const std::string& dir) { + return this->MockFreeSpaceChecker(dir); + })); + + // Non log files in /cache/recovery won't be deleted. + std::vector<std::string> expected = { "block.map", "command", "last_install" }; + ASSERT_EQ(expected, FindFilesInDir(mock_log_dir.path)); +} diff --git a/tests/manual/recovery_test.cpp b/tests/manual/recovery_test.cpp index 64e3b59e6..224ed5b68 100644 --- a/tests/manual/recovery_test.cpp +++ b/tests/manual/recovery_test.cpp @@ -34,7 +34,6 @@ static const std::string myFilename = "/data/misc/recovery/inject.txt"; static const std::string myContent = "Hello World\nWelcome to my recovery\n"; static const std::string kLocale = "zu"; -static const std::string kResourceTestDir = "/data/nativetest/recovery/"; // Failure is expected on systems that do not deliver either the // recovery-persist or recovery-refresh executables. Tests also require @@ -108,19 +107,20 @@ static int png_filter(const dirent* de) { return 1; } -// Find out all png files to test under /data/nativetest/recovery/. +// Find out all the PNG files to test, which stay under the same dir with the executable. static std::vector<std::string> add_files() { + std::string exec_dir = android::base::GetExecutableDirectory(); std::vector<std::string> files; - for (const std::string& str : image_dir) { - std::string dir_path = kResourceTestDir + str; + for (const std::string& image : image_dir) { + std::string dir_path = exec_dir + "/" + image; dirent** namelist; int n = scandir(dir_path.c_str(), &namelist, png_filter, alphasort); if (n == -1) { - printf("Failed to scan dir %s: %s\n", kResourceTestDir.c_str(), strerror(errno)); + printf("Failed to scan dir %s: %s\n", exec_dir.c_str(), strerror(errno)); return files; } if (n == 0) { - printf("No file is added for test in %s\n", kResourceTestDir.c_str()); + printf("No file is added for test in %s\n", exec_dir.c_str()); } while (n--) { diff --git a/tests/unit/screen_ui_test.cpp b/tests/unit/screen_ui_test.cpp new file mode 100644 index 000000000..be6799f2e --- /dev/null +++ b/tests/unit/screen_ui_test.cpp @@ -0,0 +1,198 @@ +/* + * 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 "screen_ui.h" + +#include <string> + +#include <gtest/gtest.h> + +constexpr const char* HEADER[] = { "header", nullptr }; +constexpr const char* ITEMS[] = { "items1", "items2", "items3", "items4", "1234567890", nullptr }; + +TEST(ScreenUITest, StartPhoneMenuSmoke) { + Menu menu(false, 10, 20); + ASSERT_FALSE(menu.scrollable()); + + menu.Start(HEADER, ITEMS, 0); + ASSERT_EQ(HEADER[0], menu.text_headers()[0]); + ASSERT_EQ(5u, menu.ItemsCount()); + + std::string message; + ASSERT_FALSE(menu.ItemsOverflow(&message)); + for (size_t i = 0; i < menu.ItemsCount(); i++) { + ASSERT_EQ(ITEMS[i], menu.TextItem(i)); + } + + ASSERT_EQ(0, menu.selection()); +} + +TEST(ScreenUITest, StartWearMenuSmoke) { + Menu menu(true, 10, 8); + ASSERT_TRUE(menu.scrollable()); + + menu.Start(HEADER, ITEMS, 1); + ASSERT_EQ(HEADER[0], menu.text_headers()[0]); + ASSERT_EQ(5u, menu.ItemsCount()); + + std::string message; + ASSERT_FALSE(menu.ItemsOverflow(&message)); + for (size_t i = 0; i < menu.ItemsCount() - 1; i++) { + ASSERT_EQ(ITEMS[i], menu.TextItem(i)); + } + // Test of the last item is truncated + ASSERT_EQ("12345678", menu.TextItem(4)); + ASSERT_EQ(1, menu.selection()); +} + +TEST(ScreenUITest, StartPhoneMenuItemsOverflow) { + Menu menu(false, 1, 20); + ASSERT_FALSE(menu.scrollable()); + + menu.Start(HEADER, ITEMS, 0); + ASSERT_EQ(1u, menu.ItemsCount()); + + std::string message; + ASSERT_FALSE(menu.ItemsOverflow(&message)); + for (size_t i = 0; i < menu.ItemsCount(); i++) { + ASSERT_EQ(ITEMS[i], menu.TextItem(i)); + } + + ASSERT_EQ(0u, menu.MenuStart()); + ASSERT_EQ(1u, menu.MenuEnd()); +} + +TEST(ScreenUITest, StartWearMenuItemsOverflow) { + Menu menu(true, 1, 20); + ASSERT_TRUE(menu.scrollable()); + + menu.Start(HEADER, ITEMS, 0); + ASSERT_EQ(5u, menu.ItemsCount()); + + std::string message; + ASSERT_TRUE(menu.ItemsOverflow(&message)); + ASSERT_EQ("Current item: 1/5", message); + + for (size_t i = 0; i < menu.ItemsCount(); i++) { + ASSERT_EQ(ITEMS[i], menu.TextItem(i)); + } + + ASSERT_EQ(0u, menu.MenuStart()); + ASSERT_EQ(1u, menu.MenuEnd()); +} + +TEST(ScreenUITest, PhoneMenuSelectSmoke) { + Menu menu(false, 10, 20); + + int sel = 0; + menu.Start(HEADER, ITEMS, sel); + // Mimic down button 10 times (2 * items size) + for (int i = 0; i < 10; i++) { + sel = menu.Select(++sel); + ASSERT_EQ(sel, menu.selection()); + + // Wraps the selection for unscrollable menu when it reaches the boundary. + int expected = (i + 1) % 5; + ASSERT_EQ(expected, menu.selection()); + + ASSERT_EQ(0u, menu.MenuStart()); + ASSERT_EQ(5u, menu.MenuEnd()); + } + + // Mimic up button 10 times + for (int i = 0; i < 10; i++) { + sel = menu.Select(--sel); + ASSERT_EQ(sel, menu.selection()); + + int expected = (9 - i) % 5; + ASSERT_EQ(expected, menu.selection()); + + ASSERT_EQ(0u, menu.MenuStart()); + ASSERT_EQ(5u, menu.MenuEnd()); + } +} + +TEST(ScreenUITest, WearMenuSelectSmoke) { + Menu menu(true, 10, 20); + + int sel = 0; + menu.Start(HEADER, ITEMS, sel); + // Mimic pressing down button 10 times (2 * items size) + for (int i = 0; i < 10; i++) { + sel = menu.Select(++sel); + ASSERT_EQ(sel, menu.selection()); + + // Stops the selection at the boundary if the menu is scrollable. + int expected = std::min(i + 1, 4); + ASSERT_EQ(expected, menu.selection()); + + ASSERT_EQ(0u, menu.MenuStart()); + ASSERT_EQ(5u, menu.MenuEnd()); + } + + // Mimic pressing up button 10 times + for (int i = 0; i < 10; i++) { + sel = menu.Select(--sel); + ASSERT_EQ(sel, menu.selection()); + + int expected = std::max(3 - i, 0); + ASSERT_EQ(expected, menu.selection()); + + ASSERT_EQ(0u, menu.MenuStart()); + ASSERT_EQ(5u, menu.MenuEnd()); + } +} + +TEST(ScreenUITest, WearMenuSelectItemsOverflow) { + Menu menu(true, 3, 20); + + int sel = 1; + menu.Start(HEADER, ITEMS, sel); + ASSERT_EQ(5u, menu.ItemsCount()); + + // Scroll the menu to the end, and check the start & end of menu. + for (int i = 0; i < 3; i++) { + sel = menu.Select(++sel); + ASSERT_EQ(i + 2, sel); + ASSERT_EQ(static_cast<size_t>(i), menu.MenuStart()); + ASSERT_EQ(static_cast<size_t>(i + 3), menu.MenuEnd()); + } + + // Press down button one more time won't change the MenuStart() and MenuEnd(). + sel = menu.Select(++sel); + ASSERT_EQ(4, sel); + ASSERT_EQ(2u, menu.MenuStart()); + ASSERT_EQ(5u, menu.MenuEnd()); + + // Scroll the menu to the top. + // The expected menu sel, start & ends are: + // sel 3, start 2, end 5 + // sel 2, start 2, end 5 + // sel 1, start 1, end 4 + // sel 0, start 0, end 3 + for (int i = 0; i < 4; i++) { + sel = menu.Select(--sel); + ASSERT_EQ(3 - i, sel); + ASSERT_EQ(static_cast<size_t>(std::min(3 - i, 2)), menu.MenuStart()); + ASSERT_EQ(static_cast<size_t>(std::min(6 - i, 5)), menu.MenuEnd()); + } + + // Press up button one more time won't change the MenuStart() and MenuEnd(). + sel = menu.Select(--sel); + ASSERT_EQ(0, sel); + ASSERT_EQ(0u, menu.MenuStart()); + ASSERT_EQ(3u, menu.MenuEnd()); +} diff --git a/uncrypt/uncrypt.cpp b/uncrypt/uncrypt.cpp index bb43c2c4a..16036f9ce 100644 --- a/uncrypt/uncrypt.cpp +++ b/uncrypt/uncrypt.cpp @@ -172,14 +172,15 @@ static struct fstab* read_fstab() { return fstab; } -static const char* find_block_device(const char* path, bool* encryptable, bool* encrypted, bool *f2fs_fs) { +static const char* find_block_device(const char* path, bool* encryptable, + bool* encrypted, bool* f2fs_fs) { // Look for a volume whose mount point is the prefix of path and // return its block device. Set encrypted if it's currently // encrypted. - // ensure f2fs_fs is set to 0 first. - if (f2fs_fs) - *f2fs_fs = false; + // ensure f2fs_fs is set to false first. + *f2fs_fs = false; + for (int i = 0; i < fstab->num_entries; ++i) { struct fstab_rec* v = &fstab->recs[i]; if (!v->mount_point) { @@ -196,8 +197,9 @@ static const char* find_block_device(const char* path, bool* encryptable, bool* *encrypted = true; } } - if (f2fs_fs && strcmp(v->fs_type, "f2fs") == 0) + if (strcmp(v->fs_type, "f2fs") == 0) { *f2fs_fs = true; + } return v->blk_device; } } @@ -313,15 +315,29 @@ static int produce_block_map(const char* path, const char* map_file, const char* } } -#ifndef F2FS_IOC_SET_DONTMOVE +// F2FS-specific ioctl +// It requires the below kernel commit merged in v4.16-rc1. +// 1ad71a27124c ("f2fs: add an ioctl to disable GC for specific file") +// In android-4.4, +// 56ee1e817908 ("f2fs: updates on v4.16-rc1") +// In android-4.9, +// 2f17e34672a8 ("f2fs: updates on v4.16-rc1") +// In android-4.14, +// ce767d9a55bc ("f2fs: updates on v4.16-rc1") +#ifndef F2FS_IOC_SET_PIN_FILE #ifndef F2FS_IOCTL_MAGIC #define F2FS_IOCTL_MAGIC 0xf5 #endif -#define F2FS_IOC_SET_DONTMOVE _IO(F2FS_IOCTL_MAGIC, 13) +#define F2FS_IOC_SET_PIN_FILE _IOW(F2FS_IOCTL_MAGIC, 13, __u32) +#define F2FS_IOC_GET_PIN_FILE _IOW(F2FS_IOCTL_MAGIC, 14, __u32) #endif - if (f2fs_fs && ioctl(fd, F2FS_IOC_SET_DONTMOVE) < 0) { - PLOG(ERROR) << "Failed to set non-movable file for f2fs: " << path << " on " << blk_dev; - return kUncryptIoctlError; + if (f2fs_fs) { + int error = ioctl(fd, F2FS_IOC_SET_PIN_FILE); + // Don't break the old kernels which don't support it. + if (error && errno != ENOTTY && errno != ENOTSUP) { + PLOG(ERROR) << "Failed to set pin_file for f2fs: " << path << " on " << blk_dev; + return kUncryptIoctlError; + } } off64_t pos = 0; diff --git a/wear_ui.cpp b/wear_ui.cpp index ca6b1b102..118e43508 100644 --- a/wear_ui.cpp +++ b/wear_ui.cpp @@ -17,7 +17,6 @@ #include "wear_ui.h" #include <pthread.h> -#include <stdio.h> // TODO: Remove after killing the call to sprintf(). #include <string.h> #include <string> @@ -27,7 +26,8 @@ #include <minui/minui.h> WearRecoveryUI::WearRecoveryUI() - : kProgressBarBaseline(RECOVERY_UI_PROGRESS_BAR_BASELINE), + : ScreenRecoveryUI(true), + kProgressBarBaseline(RECOVERY_UI_PROGRESS_BAR_BASELINE), kMenuUnusableRows(RECOVERY_UI_MENU_UNUSABLE_ROWS) { // TODO: kMenuUnusableRows should be computed based on the lines in draw_screen_locked(). @@ -65,13 +65,10 @@ static const char* SWIPE_HELP[] = { "Swipe up/down to move.", "Swipe left/right to select.", "", - NULL + nullptr, }; -// TODO merge drawing routines with screen_ui void WearRecoveryUI::draw_screen_locked() { - char cur_selection_str[50]; - draw_background_locked(); if (!show_text) { draw_foreground_locked(); @@ -79,68 +76,7 @@ void WearRecoveryUI::draw_screen_locked() { SetColor(TEXT_FILL); gr_fill(0, 0, gr_fb_width(), gr_fb_height()); - int y = kMarginHeight; - int x = kMarginWidth; - if (show_menu) { - std::string recovery_fingerprint = - android::base::GetProperty("ro.bootimage.build.fingerprint", ""); - SetColor(HEADER); - y += DrawTextLine(x + 4, y, "Android Recovery", true); - for (auto& chunk : android::base::Split(recovery_fingerprint, ":")) { - y += DrawTextLine(x + 4, y, chunk.c_str(), false); - } - - // This is actually the help strings. - y += DrawTextLines(x + 4, y, SWIPE_HELP); - SetColor(HEADER); - y += DrawTextLines(x + 4, y, menu_headers_); - - // Show the current menu item number in relation to total number if - // items don't fit on the screen. - if (menu_items > menu_end - menu_start) { - sprintf(cur_selection_str, "Current item: %d/%d", menu_sel + 1, menu_items); - gr_text(gr_sys_font(), x + 4, y, cur_selection_str, 1); - y += char_height_ + 4; - } - - // Menu begins here - SetColor(MENU); - - for (int i = menu_start; i < menu_end; ++i) { - if (i == menu_sel) { - // draw the highlight bar - SetColor(MENU_SEL_BG); - gr_fill(x, y - 2, gr_fb_width() - x, y + char_height_ + 2); - // white text of selected item - SetColor(MENU_SEL_FG); - if (menu_[i][0]) { - gr_text(gr_sys_font(), x + 4, y, menu_[i].c_str(), 1); - } - SetColor(MENU); - } else if (menu_[i][0]) { - gr_text(gr_sys_font(), x + 4, y, menu_[i].c_str(), 0); - } - y += char_height_ + 4; - } - SetColor(MENU); - y += 4; - gr_fill(0, y, gr_fb_width(), y + 2); - y += 4; - } - - SetColor(LOG); - - // display from the bottom up, until we hit the top of the - // screen, the bottom of the menu, or we've displayed the - // entire text buffer. - int row = text_row_; - size_t count = 0; - for (int ty = gr_fb_height() - char_height_ - kMarginHeight; ty > y + 2 && count < text_rows_; - ty -= char_height_, ++count) { - gr_text(gr_sys_font(), x + 4, ty, text_[row], 0); - --row; - if (row < 0) row = text_rows_ - 1; - } + draw_menu_and_text_buffer_locked(SWIPE_HELP); } } @@ -156,45 +92,11 @@ void WearRecoveryUI::StartMenu(const char* const* headers, const char* const* it int initial_selection) { pthread_mutex_lock(&updateMutex); if (text_rows_ > 0 && text_cols_ > 0) { - menu_headers_ = headers; - menu_.clear(); - // "i < text_rows_" is removed from the loop termination condition, - // which is different from the one in ScreenRecoveryUI::StartMenu(). - // Because WearRecoveryUI supports scrollable menu, it's fine to have - // more entries than text_rows_. The menu may be truncated otherwise. - // Bug: 23752519 - for (size_t i = 0; items[i] != nullptr; i++) { - menu_.emplace_back(std::string(items[i], strnlen(items[i], text_cols_ - 1))); - } - menu_items = static_cast<int>(menu_.size()); - show_menu = true; - menu_sel = initial_selection; - menu_start = 0; - menu_end = text_rows_ - 1 - kMenuUnusableRows; - if (menu_items <= menu_end) menu_end = menu_items; - update_screen_locked(); - } - pthread_mutex_unlock(&updateMutex); -} + menu_ = std::make_unique<Menu>(scrollable_menu_, text_rows_ - kMenuUnusableRows - 1, + text_cols_ - 1); + menu_->Start(headers, items, initial_selection); -int WearRecoveryUI::SelectMenu(int sel) { - int old_sel; - pthread_mutex_lock(&updateMutex); - if (show_menu) { - old_sel = menu_sel; - menu_sel = sel; - if (menu_sel < 0) menu_sel = 0; - if (menu_sel >= menu_items) menu_sel = menu_items - 1; - if (menu_sel < menu_start) { - menu_start--; - menu_end--; - } else if (menu_sel >= menu_end && menu_sel < menu_items) { - menu_end++; - menu_start++; - } - sel = menu_sel; - if (menu_sel != old_sel) update_screen_locked(); + update_screen_locked(); } pthread_mutex_unlock(&updateMutex); - return sel; -} +}
\ No newline at end of file @@ -25,10 +25,8 @@ class WearRecoveryUI : public ScreenRecoveryUI { void SetStage(int current, int max) override; - // menu display void StartMenu(const char* const* headers, const char* const* items, int initial_selection) override; - int SelectMenu(int sel) override; protected: // progress bar vertical position, it's centered horizontally @@ -45,8 +43,6 @@ class WearRecoveryUI : public ScreenRecoveryUI { private: void draw_background_locked() override; void draw_screen_locked() override; - - int menu_start, menu_end; }; #endif // RECOVERY_WEAR_UI_H |