diff options
Diffstat (limited to '')
37 files changed, 1123 insertions, 642 deletions
diff --git a/Android.bp b/Android.bp index 22c90bd3e..53b74dca5 100644 --- a/Android.bp +++ b/Android.bp @@ -16,14 +16,48 @@ cc_defaults { name: "recovery_defaults", cflags: [ + "-D_FILE_OFFSET_BITS=64", + + // Must be the same as RECOVERY_API_VERSION. + "-DRECOVERY_API_VERSION=3", + "-Wall", "-Werror", ], } +cc_library { + name: "librecovery_ui", + recovery_available: true, + + defaults: [ + "recovery_defaults", + ], + + srcs: [ + "device.cpp", + "screen_ui.cpp", + "ui.cpp", + "vr_ui.cpp", + "wear_ui.cpp" + ], + + static_libs: [ + "libminui", + "libotautil", + ], + + shared_libs: [ + "libbase", + "libpng", + "libz", + ], +} + // Generic device that uses ScreenRecoveryUI. cc_library_static { name: "librecovery_ui_default", + recovery_available: true, defaults: [ "recovery_defaults", @@ -37,6 +71,7 @@ cc_library_static { // The default wear device that uses WearRecoveryUI. cc_library_static { name: "librecovery_ui_wear", + recovery_available: true, defaults: [ "recovery_defaults", @@ -50,6 +85,7 @@ cc_library_static { // The default VR device that uses VrRecoveryUI. cc_library_static { name: "librecovery_ui_vr", + recovery_available: true, defaults: [ "recovery_defaults", @@ -61,7 +97,94 @@ cc_library_static { } cc_library_static { + name: "librecovery_fastboot", + recovery_available: true, + defaults: [ + "recovery_defaults", + ], + + srcs: [ + "fastboot/fastboot.cpp", + ], + + shared_libs: [ + "libbase", + "libbootloader_message", + "libcutils", + "liblog", + ], + + static_libs: [ + "librecovery_ui_default", + ], +} + +cc_defaults { + name: "librecovery_defaults", + + defaults: [ + "recovery_defaults", + ], + + shared_libs: [ + "android.hardware.health@2.0", + "libbase", + "libbootloader_message", + "libcrypto", + "libcutils", + "libext4_utils", + "libfs_mgr", + "libfusesideload", + "libhidl-gen-utils", + "libhidlbase", + "libhidltransport", + "liblog", + "libpng", + "libselinux", + "libtinyxml2", + "libutils", + "libz", + "libziparchive", + ], + + static_libs: [ + "librecovery_fastboot", + "libminui", + "libverifier", + "libotautil", + + // external dependencies + "libhealthhalutils", + "libvintf_recovery", + "libvintf", + ], +} + +cc_library_static { + name: "librecovery", + recovery_available: true, + + defaults: [ + "librecovery_defaults", + ], + + srcs: [ + "adb_install.cpp", + "fsck_unshare_blocks.cpp", + "fuse_sdcard_provider.cpp", + "install.cpp", + "recovery.cpp", + "roots.cpp", + ], + + include_dirs: [ + "system/vold", + ], +} + +cc_library_static { name: "libverifier", + recovery_available: true, defaults: [ "recovery_defaults", @@ -72,14 +195,49 @@ cc_library_static { "verifier.cpp", ], - static_libs: [ + shared_libs: [ "libbase", "libcrypto", "libcrypto_utils", + ], + + static_libs: [ "libotautil", ], } +cc_binary { + name: "recovery", + recovery: true, + + defaults: [ + "librecovery_defaults", + ], + + srcs: [ + "logging.cpp", + "recovery_main.cpp", + ], + + shared_libs: [ + "libminadbd_services", + "librecovery_ui", + ], + + static_libs: [ + "librecovery", + "librecovery_ui_default", + ], + + required: [ + "e2fsdroid.recovery", + "librecovery_ui_ext", + "mke2fs.conf", + "mke2fs.recovery", + "recovery_deps", + ], +} + // The dynamic executable that runs after /data mounts. cc_binary { name: "recovery-persist", @@ -133,3 +291,11 @@ cc_binary { "recovery-refresh.rc", ], } + +filegroup { + name: "res-testdata", + + srcs: [ + "res-*/images/*_text.png", + ], +} diff --git a/Android.mk b/Android.mk index 9542080ca..80d107dc4 100644 --- a/Android.mk +++ b/Android.mk @@ -14,7 +14,7 @@ LOCAL_PATH := $(call my-dir) -# Needed by build/make/core/Makefile. +# Needed by build/make/core/Makefile. Must be consistent with the value in Android.bp. RECOVERY_API_VERSION := 3 RECOVERY_FSTAB_VERSION := 2 @@ -23,11 +23,6 @@ RECOVERY_FSTAB_VERSION := 2 # librecovery_ui_default, which uses ScreenRecoveryUI. TARGET_RECOVERY_UI_LIB ?= librecovery_ui_default -recovery_common_cflags := \ - -Wall \ - -Werror \ - -DRECOVERY_API_VERSION=$(RECOVERY_API_VERSION) - # librecovery_ui_ext (shared library) # =================================== include $(CLEAR_VARS) @@ -49,151 +44,16 @@ LOCAL_WHOLE_STATIC_LIBRARIES := \ LOCAL_SHARED_LIBRARIES := \ libbase \ liblog \ - librecovery_ui - -include $(BUILD_SHARED_LIBRARY) - -# librecovery_ui (shared library) -# =============================== -include $(CLEAR_VARS) -LOCAL_SRC_FILES := \ - device.cpp \ - screen_ui.cpp \ - ui.cpp \ - vr_ui.cpp \ - wear_ui.cpp - -LOCAL_MODULE := librecovery_ui - -LOCAL_CFLAGS := $(recovery_common_cflags) - -LOCAL_MULTILIB := first - -ifeq ($(TARGET_IS_64_BIT),true) -LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/system/lib64 -else -LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/system/lib -endif - -LOCAL_STATIC_LIBRARIES := \ - libminui \ - libotautil \ - -LOCAL_SHARED_LIBRARIES := \ - libbase \ - libpng \ - libz \ + librecovery_ui.recovery include $(BUILD_SHARED_LIBRARY) -# librecovery_ui (static library) -# =============================== +# recovery_deps: A phony target that's depended on by `recovery`, which +# builds additional modules conditionally based on Makefile variables. +# ====================================================================== include $(CLEAR_VARS) -LOCAL_SRC_FILES := \ - device.cpp \ - screen_ui.cpp \ - ui.cpp \ - vr_ui.cpp \ - wear_ui.cpp - -LOCAL_MODULE := librecovery_ui -LOCAL_CFLAGS := $(recovery_common_cflags) - -LOCAL_STATIC_LIBRARIES := \ - libminui \ - libotautil \ - -LOCAL_SHARED_LIBRARIES := \ - libbase \ - libpng \ - libz \ - -include $(BUILD_STATIC_LIBRARY) - -librecovery_static_libraries := \ - libbootloader_message \ - libfusesideload \ - libminadbd \ - libminui \ - libverifier \ - libotautil \ - libasyncio \ - libbatterymonitor \ - libcrypto_utils \ - libcrypto \ - libext4_utils \ - libfs_mgr \ - libpng \ - libsparse \ - libvintf_recovery \ - libvintf \ - libhidl-gen-utils \ - libtinyxml2 \ - libziparchive \ - libbase \ - libutils \ - libcutils \ - liblog \ - libselinux \ - libz \ - -# librecovery (static library) -# =============================== -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := \ - adb_install.cpp \ - fsck_unshare_blocks.cpp \ - fuse_sdcard_provider.cpp \ - install.cpp \ - recovery.cpp \ - roots.cpp \ - -LOCAL_C_INCLUDES := \ - system/vold \ - -LOCAL_CFLAGS := $(recovery_common_cflags) - -LOCAL_MODULE := librecovery - -LOCAL_STATIC_LIBRARIES := \ - $(librecovery_static_libraries) - -include $(BUILD_STATIC_LIBRARY) - -# recovery (static executable) -# =============================== -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := \ - logging.cpp \ - recovery_main.cpp \ - -LOCAL_MODULE := recovery - -LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/system/bin - -# Cannot link with LLD: undefined symbol: UsbNoPermissionsLongHelpText -# http://b/77543887, lld does not handle -Wl,--gc-sections as well as ld. -LOCAL_USE_CLANG_LLD := false - -LOCAL_CFLAGS := $(recovery_common_cflags) - -LOCAL_STATIC_LIBRARIES := \ - librecovery \ - librecovery_ui_default \ - $(librecovery_static_libraries) - -LOCAL_SHARED_LIBRARIES := \ - librecovery_ui \ - -LOCAL_HAL_STATIC_LIBRARIES := libhealthd - -LOCAL_REQUIRED_MODULES := \ - e2fsdroid.recovery \ - mke2fs.recovery \ - mke2fs.conf +LOCAL_MODULE := recovery_deps ifeq ($(TARGET_USERIMAGES_USE_F2FS),true) ifeq ($(HOST_OS),linux) @@ -206,7 +66,8 @@ endif # e2fsck is needed for adb remount -R. ifeq ($(BOARD_EXT4_SHARE_DUP_BLOCKS),true) ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT))) -LOCAL_REQUIRED_MODULES += e2fsck_static +LOCAL_REQUIRED_MODULES += \ + e2fsck_static endif endif @@ -216,21 +77,7 @@ LOCAL_REQUIRED_MODULES += \ recovery-refresh endif -LOCAL_REQUIRED_MODULES += \ - librecovery_ui_ext - -# TODO(b/110380063): Explicitly install the following shared libraries to recovery, until `recovery` -# module is built with Soong (with `recovery: true` flag). -LOCAL_REQUIRED_MODULES += \ - libbase.recovery \ - liblog.recovery \ - libpng.recovery \ - libz.recovery \ - -include $(BUILD_EXECUTABLE) +include $(BUILD_PHONY_PACKAGE) include \ - $(LOCAL_PATH)/boot_control/Android.mk \ - $(LOCAL_PATH)/tests/Android.mk \ $(LOCAL_PATH)/updater/Android.mk \ - $(LOCAL_PATH)/updater_sample/Android.mk \ diff --git a/boot_control/Android.bp b/boot_control/Android.bp new file mode 100644 index 000000000..7720ead50 --- /dev/null +++ b/boot_control/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_shared { + name: "bootctrl.default", + recovery_available: true, + relative_install_path: "hw", + + srcs: ["boot_control.cpp"], + + cflags: [ + "-D_FILE_OFFSET_BITS=64", + "-Werror", + "-Wall", + "-Wextra", + ], + + shared_libs: [ + "libbase", + "libbootloader_message", + "libfs_mgr", + "liblog", + ], +} diff --git a/boot_control/Android.mk b/boot_control/Android.mk deleted file mode 100644 index 9814d7122..000000000 --- a/boot_control/Android.mk +++ /dev/null @@ -1,33 +0,0 @@ -# -# Copyright (C) 2017 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -LOCAL_PATH := $(my-dir) - -include $(CLEAR_VARS) -LOCAL_MODULE := bootctrl.bcb -LOCAL_MODULE_RELATIVE_PATH := hw -LOCAL_SRC_FILES := boot_control.cpp -LOCAL_CFLAGS := \ - -D_FILE_OFFSET_BITS=64 \ - -Werror \ - -Wall \ - -Wextra -LOCAL_SHARED_LIBRARIES := liblog -LOCAL_STATIC_LIBRARIES := libbootloader_message libfs_mgr libbase -LOCAL_POST_INSTALL_CMD := \ - $(hide) mkdir -p $(TARGET_OUT_SHARED_LIBRARIES)/hw && \ - ln -sf bootctrl.bcb.so $(TARGET_OUT_SHARED_LIBRARIES)/hw/bootctrl.default.so -include $(BUILD_SHARED_LIBRARY) diff --git a/device.cpp b/device.cpp index 3c6334e5c..eec1932c2 100644 --- a/device.cpp +++ b/device.cpp @@ -28,6 +28,7 @@ static std::vector<std::pair<std::string, Device::BuiltinAction>> g_menu_actions{ { "Reboot system now", Device::REBOOT }, { "Reboot to bootloader", Device::REBOOT_BOOTLOADER }, + { "Enter fastboot", Device::ENTER_FASTBOOT }, { "Apply update from ADB", Device::APPLY_ADB_SIDELOAD }, { "Apply update from SD card", Device::APPLY_SDCARD }, { "Wipe data/factory reset", Device::WIPE_DATA }, @@ -48,6 +48,8 @@ class Device { RUN_GRAPHICS_TEST = 11, RUN_LOCALE_TEST = 12, KEY_INTERRUPTED = 13, + ENTER_FASTBOOT = 14, + ENTER_RECOVERY = 15, }; explicit Device(RecoveryUI* ui); diff --git a/etc/init.rc b/etc/init.rc index 8e18438b5..9add2494a 100644 --- a/etc/init.rc +++ b/etc/init.rc @@ -6,6 +6,8 @@ on early-init start ueventd + setprop sys.usb.configfs 0 + on init export ANDROID_ROOT /system export ANDROID_DATA /data @@ -31,20 +33,6 @@ on init write /proc/sys/kernel/panic_on_oops 1 write /proc/sys/vm/max_map_count 1000000 -on fs - write /sys/class/android_usb/android0/f_ffs/aliases adb - mkdir /dev/usb-ffs 0770 shell shell - mkdir /dev/usb-ffs/adb 0770 shell shell - mount functionfs adb /dev/usb-ffs/adb uid=2000,gid=2000 - - write /sys/class/android_usb/android0/enable 0 - write /sys/class/android_usb/android0/idVendor 18D1 - write /sys/class/android_usb/android0/idProduct D001 - write /sys/class/android_usb/android0/functions adb - write /sys/class/android_usb/android0/iManufacturer ${ro.product.manufacturer} - write /sys/class/android_usb/android0/iProduct ${ro.product.model} - write /sys/class/android_usb/android0/iSerial ${ro.serialno} - on boot ifup lo hostname localhost @@ -77,7 +65,7 @@ on late-init trigger early-boot trigger boot -service ueventd /sbin/ueventd +service ueventd /system/bin/ueventd critical seclabel u:r:ueventd:s0 @@ -86,6 +74,7 @@ service charger /charger -r seclabel u:r:charger:s0 service recovery /system/bin/recovery + socket recovery stream 422 system system seclabel u:r:recovery:s0 service adbd /system/bin/adbd --root_seclabel=u:r:su:s0 --device_banner=recovery @@ -93,13 +82,89 @@ service adbd /system/bin/adbd --root_seclabel=u:r:su:s0 --device_banner=recovery socket adbd stream 660 system system seclabel u:r:adbd:s0 -# Always start adbd on userdebug and eng builds -on property:ro.debuggable=1 - write /sys/class/android_usb/android0/enable 1 - start adbd +service fastbootd /system/bin/fastbootd + disabled + group system + seclabel u:r:fastbootd:s0 # Restart adbd so it can run as root on property:service.adb.root=1 - write /sys/class/android_usb/android0/enable 0 restart adbd + +# Always start adbd on userdebug and eng builds +on fs && property:ro.debuggable=1 + setprop sys.usb.config adb + +on fs && property:sys.usb.configfs=1 + mount configfs none /config + mkdir /config/usb_gadget/g1 0770 shell shell + write /config/usb_gadget/g1/idVendor 0x18D1 + mkdir /config/usb_gadget/g1/strings/0x409 0770 + write /config/usb_gadget/g1/strings/0x409/serialnumber ${ro.serialno} + write /config/usb_gadget/g1/strings/0x409/manufacturer ${ro.product.manufacturer} + write /config/usb_gadget/g1/strings/0x409/product ${ro.product.model} + mkdir /config/usb_gadget/g1/functions/ffs.adb + mkdir /config/usb_gadget/g1/functions/ffs.fastboot + mkdir /config/usb_gadget/g1/configs/b.1 0777 shell shell + mkdir /config/usb_gadget/g1/configs/b.1/strings/0x409 0770 shell shell + +on fs && property:sys.usb.configfs=0 + write /sys/class/android_usb/android0/f_ffs/aliases adb,fastboot + write /sys/class/android_usb/android0/idVendor 18D1 + write /sys/class/android_usb/android0/iManufacturer ${ro.product.manufacturer} + write /sys/class/android_usb/android0/iProduct ${ro.product.model} + write /sys/class/android_usb/android0/iSerial ${ro.serialno} + +on fs + mkdir /dev/usb-ffs 0775 shell shell + mkdir /dev/usb-ffs/adb 0770 shell shell + mount functionfs adb /dev/usb-ffs/adb uid=2000,gid=2000 + mkdir /dev/usb-ffs/fastboot 0770 system system + mount functionfs fastboot /dev/usb-ffs/fastboot rmode=0770,fmode=0660,uid=1000,gid=1000 + +on property:sys.usb.config=adb + start adbd + +on property:sys.usb.config=fastboot + start fastbootd + +on property:sys.usb.config=none + stop adbd + stop fastbootd + +on property:sys.usb.config=none && property:sys.usb.configfs=0 + write /sys/class/android_usb/android0/enable 0 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=adb && property:sys.usb.configfs=0 + write /sys/class/android_usb/android0/idProduct D001 + write /sys/class/android_usb/android0/functions adb + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=fastboot && property:sys.usb.configfs=0 + write /sys/class/android_usb/android0/idProduct 4EE0 + write /sys/class/android_usb/android0/functions fastboot write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +# Configfs triggers +on property:sys.usb.config=none && property:sys.usb.configfs=1 + write /config/usb_gadget/g1/UDC "none" + setprop sys.usb.ffs.ready 0 + rm /config/usb_gadget/g1/configs/b.1/f1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=adb && property:sys.usb.ffs.ready=1 && property:sys.usb.configfs=1 + write /config/usb_gadget/g1/idProduct 0xD001 + write /config/usb_gadget/g1/configs/b.1/strings/0x409/configuration "adb" + symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f1 + write /config/usb_gadget/g1/UDC ${sys.usb.controller} + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=fastboot && property:sys.usb.ffs.ready=1 && property:sys.usb.configfs=1 + write /config/usb_gadget/g1/idProduct 0x4EE0 + write /config/usb_gadget/g1/configs/b.1/strings/0x409/configuration "fastboot" + symlink /config/usb_gadget/g1/functions/ffs.fastboot /config/usb_gadget/g1/configs/b.1/f1 + write /config/usb_gadget/g1/UDC ${sys.usb.controller} + setprop sys.usb.state ${sys.usb.config} diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp new file mode 100644 index 000000000..8458c99dd --- /dev/null +++ b/fastboot/fastboot.cpp @@ -0,0 +1,82 @@ +/* + * 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 "fastboot.h" + +#include <stdio.h> +#include <stdlib.h> + +#include <algorithm> +#include <string> +#include <vector> + +#include <android-base/logging.h> +#include <android-base/properties.h> +#include <bootloader_message/bootloader_message.h> + +#include "device.h" +#include "ui.h" + +static const std::vector<std::pair<std::string, Device::BuiltinAction>> kFastbootMenuActions{ + { "Reboot system now", Device::REBOOT }, + { "Enter recovery", Device::ENTER_RECOVERY }, + { "Reboot to bootloader", Device::REBOOT_BOOTLOADER }, + { "Power off", Device::SHUTDOWN }, +}; + +Device::BuiltinAction StartFastboot(Device* device, const std::vector<std::string>& /* args */) { + RecoveryUI* ui = device->GetUI(); + + std::vector<std::string> title_lines = { "Android Fastboot" }; + title_lines.push_back("Product name - " + android::base::GetProperty("ro.product.device", "")); + title_lines.push_back("Bootloader version - " + android::base::GetProperty("ro.bootloader", "")); + title_lines.push_back("Baseband version - " + + android::base::GetProperty("ro.build.expect.baseband", "")); + title_lines.push_back("Serial number - " + android::base::GetProperty("ro.serialno", "")); + title_lines.push_back(std::string("Secure boot - ") + + ((android::base::GetProperty("ro.secure", "") == "1") ? "yes" : "no")); + title_lines.push_back("HW version - " + android::base::GetProperty("ro.revision", "")); + + ui->ResetKeyInterruptStatus(); + ui->SetTitle(title_lines); + ui->ShowText(true); + + // Reset to normal system boot so recovery won't cycle indefinitely. + // TODO(b/112277594) Clear only if 'recovery' field of BCB is empty. If not, + // set the 'command' field of BCB to 'boot-recovery' so the next boot is into recovery + // to finish any interrupted tasks. + std::string err; + if (!clear_bootloader_message(&err)) { + LOG(ERROR) << "Failed to clear BCB message: " << err; + } + + std::vector<std::string> fastboot_menu_items; + std::transform(kFastbootMenuActions.cbegin(), kFastbootMenuActions.cend(), + std::back_inserter(fastboot_menu_items), + [](const auto& entry) { return entry.first; }); + + auto chosen_item = ui->ShowMenu( + {}, fastboot_menu_items, 0, false, + std::bind(&Device::HandleMenuKey, device, std::placeholders::_1, std::placeholders::_2)); + + if (chosen_item == static_cast<size_t>(RecoveryUI::KeyError::INTERRUPTED)) { + return Device::KEY_INTERRUPTED; + } + if (chosen_item == static_cast<size_t>(RecoveryUI::KeyError::TIMED_OUT)) { + return Device::BuiltinAction::NO_ACTION; + } + return kFastbootMenuActions[chosen_item].second; +} diff --git a/fastboot/fastboot.h b/fastboot/fastboot.h new file mode 100644 index 000000000..53a2adcae --- /dev/null +++ b/fastboot/fastboot.h @@ -0,0 +1,24 @@ +/* + * 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. + */ + +#pragma once + +#include <string> +#include <vector> + +#include "device.h" + +Device::BuiltinAction StartFastboot(Device* device, const std::vector<std::string>& args); diff --git a/fuse_sideload/Android.bp b/fuse_sideload/Android.bp index 76bc16df9..90c4c22c3 100644 --- a/fuse_sideload/Android.bp +++ b/fuse_sideload/Android.bp @@ -12,8 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -cc_library_static { +cc_library { name: "libfusesideload", + recovery_available: true, cflags: [ "-D_XOPEN_SOURCE", @@ -30,7 +31,7 @@ cc_library_static { "include", ], - static_libs: [ + shared_libs: [ "libbase", "libcrypto", ], diff --git a/install.cpp b/install.cpp index 800847fdb..e379ef307 100644 --- a/install.cpp +++ b/install.cpp @@ -248,7 +248,7 @@ int SetUpAbUpdateCommands(const std::string& package, ZipArchiveHandle zip, int } long payload_offset = payload_entry.offset; *cmd = { - "/sbin/update_engine_sideload", + "/system/bin/update_engine_sideload", "--payload=file://" + package, android::base::StringPrintf("--offset=%ld", payload_offset), "--headers=" + std::string(payload_properties.begin(), payload_properties.end()), diff --git a/minadbd/Android.bp b/minadbd/Android.bp index 432b2f0f5..00244ee7e 100644 --- a/minadbd/Android.bp +++ b/minadbd/Android.bp @@ -26,8 +26,11 @@ cc_defaults { ], } -cc_library_static { - name: "libminadbd", +// `libminadbd_services` is analogous to the `libadbd_services` for regular `adbd`, but providing +// the sideload service only. +cc_library { + name: "libminadbd_services", + recovery_available: true, defaults: [ "minadbd_defaults", @@ -39,14 +42,11 @@ cc_library_static { "minadbd_services.cpp", ], - static_libs: [ - "libfusesideload", + shared_libs: [ + "libadbd", "libbase", "libcrypto", - ], - - whole_static_libs: [ - "libadbd", + "libfusesideload", ], } @@ -62,8 +62,9 @@ cc_test { ], static_libs: [ + "libminadbd_services", + "libadbd", "libBionicGtestMain", - "libminadbd", ], shared_libs: [ diff --git a/minui/Android.bp b/minui/Android.bp index 19d28be62..fff3a8ec9 100644 --- a/minui/Android.bp +++ b/minui/Android.bp @@ -14,6 +14,7 @@ cc_library { name: "libminui", + recovery_available: true, defaults: [ "recovery_defaults", @@ -35,7 +36,7 @@ cc_library { whole_static_libs: [ "libadf", "libdrm", - "libsync_recovery", + "libsync", ], shared_libs: [ diff --git a/minui/graphics_drm.cpp b/minui/graphics_drm.cpp index 9336a1e63..630b80180 100644 --- a/minui/graphics_drm.cpp +++ b/minui/graphics_drm.cpp @@ -117,12 +117,16 @@ GRSurfaceDrm* MinuiBackendDrm::DrmCreateSurface(int width, int height) { uint32_t format; PixelFormat pixel_format = gr_pixel_format(); + // PixelFormat comes in byte order, whereas DRM_FORMAT_* uses little-endian + // (external/libdrm/include/drm/drm_fourcc.h). Note that although drm_fourcc.h also defines a + // macro of DRM_FORMAT_BIG_ENDIAN, it doesn't seem to be actually supported (see the discussion + // in https://lists.freedesktop.org/archives/amd-gfx/2017-May/008560.html). if (pixel_format == PixelFormat::ABGR) { - format = DRM_FORMAT_ABGR8888; + format = DRM_FORMAT_RGBA8888; } else if (pixel_format == PixelFormat::BGRA) { - format = DRM_FORMAT_BGRA8888; + format = DRM_FORMAT_ARGB8888; } else if (pixel_format == PixelFormat::RGBX) { - format = DRM_FORMAT_RGBX8888; + format = DRM_FORMAT_XBGR8888; } else { format = DRM_FORMAT_RGB565; } diff --git a/otautil/Android.bp b/otautil/Android.bp index b058f7b35..56c7c9e89 100644 --- a/otautil/Android.bp +++ b/otautil/Android.bp @@ -16,6 +16,11 @@ cc_library_static { name: "libotautil", host_supported: true, + recovery_available: true, + + defaults: [ + "recovery_defaults", + ], // Minimal set of files to support host build. srcs: [ @@ -23,16 +28,10 @@ cc_library_static { "rangeset.cpp", ], - static_libs: [ + shared_libs: [ "libbase", ], - cflags: [ - "-D_FILE_OFFSET_BITS=64", - "-Werror", - "-Wall", - ], - export_include_dirs: [ "include", ], @@ -46,9 +45,9 @@ cc_library_static { "thermalutil.cpp", ], - static_libs: [ - "libselinux", + shared_libs: [ "libcutils", + "libselinux", ], }, }, diff --git a/recovery.cpp b/recovery.cpp index 3828e29b3..01bd83b5e 100644 --- a/recovery.cpp +++ b/recovery.cpp @@ -49,7 +49,7 @@ #include <android-base/unique_fd.h> #include <bootloader_message/bootloader_message.h> #include <cutils/properties.h> /* for property_list */ -#include <healthd/BatteryMonitor.h> +#include <healthhalutils/HealthHalUtils.h> #include <ziparchive/zip_archive.h> #include "adb_install.h" @@ -779,6 +779,8 @@ static Device::BuiltinAction prompt_and_wait(Device* device, int status) { case Device::REBOOT: case Device::SHUTDOWN: case Device::REBOOT_BOOTLOADER: + case Device::ENTER_FASTBOOT: + case Device::ENTER_RECOVERY: return chosen_action; case Device::WIPE_DATA: @@ -876,54 +878,63 @@ void ui_print(const char* format, ...) { } static bool is_battery_ok(int* required_battery_level) { - struct healthd_config healthd_config = { - .batteryStatusPath = android::String8(android::String8::kEmptyString), - .batteryHealthPath = android::String8(android::String8::kEmptyString), - .batteryPresentPath = android::String8(android::String8::kEmptyString), - .batteryCapacityPath = android::String8(android::String8::kEmptyString), - .batteryVoltagePath = android::String8(android::String8::kEmptyString), - .batteryTemperaturePath = android::String8(android::String8::kEmptyString), - .batteryTechnologyPath = android::String8(android::String8::kEmptyString), - .batteryCurrentNowPath = android::String8(android::String8::kEmptyString), - .batteryCurrentAvgPath = android::String8(android::String8::kEmptyString), - .batteryChargeCounterPath = android::String8(android::String8::kEmptyString), - .batteryFullChargePath = android::String8(android::String8::kEmptyString), - .batteryCycleCountPath = android::String8(android::String8::kEmptyString), - .energyCounter = nullptr, - .boot_min_cap = 0, - .screen_on = nullptr - }; - healthd_board_init(&healthd_config); + using android::hardware::health::V1_0::BatteryStatus; + using android::hardware::health::V2_0::get_health_service; + using android::hardware::health::V2_0::IHealth; + using android::hardware::health::V2_0::Result; + using android::hardware::health::V2_0::toString; - android::BatteryMonitor monitor; - monitor.init(&healthd_config); + android::sp<IHealth> health = get_health_service(); static constexpr int BATTERY_READ_TIMEOUT_IN_SEC = 10; int wait_second = 0; while (true) { - int charge_status = monitor.getChargeStatus(); + auto charge_status = BatteryStatus::UNKNOWN; + + if (health == nullptr) { + LOG(WARNING) << "no health implementation is found, assuming defaults"; + } else { + health + ->getChargeStatus([&charge_status](auto res, auto out_status) { + if (res == Result::SUCCESS) { + charge_status = out_status; + } + }) + .isOk(); // should not have transport error + } + // Treat unknown status as charged. - bool charged = (charge_status != android::BATTERY_STATUS_DISCHARGING && - charge_status != android::BATTERY_STATUS_NOT_CHARGING); - android::BatteryProperty capacity; - android::status_t status = monitor.getProperty(android::BATTERY_PROP_CAPACITY, &capacity); - ui_print("charge_status %d, charged %d, status %d, capacity %" PRId64 "\n", charge_status, - charged, status, capacity.valueInt64); + bool charged = (charge_status != BatteryStatus::DISCHARGING && + charge_status != BatteryStatus::NOT_CHARGING); + + Result res = Result::UNKNOWN; + int32_t capacity = INT32_MIN; + if (health != nullptr) { + health + ->getCapacity([&res, &capacity](auto out_res, auto out_capacity) { + res = out_res; + capacity = out_capacity; + }) + .isOk(); // should not have transport error + } + + LOG(INFO) << "charge_status " << toString(charge_status) << ", charged " << charged + << ", status " << toString(res) << ", capacity " << capacity; // At startup, the battery drivers in devices like N5X/N6P take some time to load // the battery profile. Before the load finishes, it reports value 50 as a fake // capacity. BATTERY_READ_TIMEOUT_IN_SEC is set that the battery drivers are expected // to finish loading the battery profile earlier than 10 seconds after kernel startup. - if (status == 0 && capacity.valueInt64 == 50) { + if (res == Result::SUCCESS && capacity == 50) { if (wait_second < BATTERY_READ_TIMEOUT_IN_SEC) { sleep(1); wait_second++; continue; } } - // If we can't read battery percentage, it may be a device without battery. In this situation, - // use 100 as a fake battery percentage. - if (status != 0) { - capacity.valueInt64 = 100; + // If we can't read battery percentage, it may be a device without battery. In this + // situation, use 100 as a fake battery percentage. + if (res != Result::SUCCESS) { + capacity = 100; } // GmsCore enters recovery mode to install package when having enough battery percentage. @@ -932,7 +943,7 @@ static bool is_battery_ok(int* required_battery_level) { static constexpr int BATTERY_OK_PERCENTAGE = 20; static constexpr int BATTERY_WITH_CHARGER_OK_PERCENTAGE = 15; *required_battery_level = charged ? BATTERY_WITH_CHARGER_OK_PERCENTAGE : BATTERY_OK_PERCENTAGE; - return capacity.valueInt64 >= *required_battery_level; + return capacity >= *required_battery_level; } } @@ -986,6 +997,7 @@ static void log_failure_code(ErrorCode code, const std::string& update_package) Device::BuiltinAction start_recovery(Device* device, const std::vector<std::string>& args) { static constexpr struct option OPTIONS[] = { + { "fastboot", no_argument, nullptr, 0 }, { "fsck_unshare_blocks", no_argument, nullptr, 0 }, { "just_exit", no_argument, nullptr, 'x' }, { "locale", required_argument, nullptr, 0 }, @@ -1040,7 +1052,7 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri std::string option = OPTIONS[option_index].name; if (option == "fsck_unshare_blocks") { fsck_unshare_blocks = true; - } else if (option == "locale") { + } else if (option == "locale" || option == "fastboot") { // Handled in recovery_main.cpp } else if (option == "prompt_and_wipe_data") { should_prompt_and_wipe_data = true; diff --git a/recovery_main.cpp b/recovery_main.cpp index 9a9890de0..99f965098 100644 --- a/recovery_main.cpp +++ b/recovery_main.cpp @@ -30,15 +30,19 @@ #include <time.h> #include <unistd.h> +#include <atomic> #include <string> +#include <thread> #include <vector> #include <android-base/file.h> #include <android-base/logging.h> #include <android-base/properties.h> #include <android-base/strings.h> +#include <android-base/unique_fd.h> #include <bootloader_message/bootloader_message.h> #include <cutils/android_reboot.h> +#include <cutils/sockets.h> #include <private/android_logger.h> /* private pmsg functions */ #include <selinux/android.h> #include <selinux/label.h> @@ -46,6 +50,7 @@ #include "common.h" #include "device.h" +#include "fastboot/fastboot.h" #include "logging.h" #include "minadbd/minadbd.h" #include "otautil/paths.h" @@ -162,6 +167,44 @@ static std::string load_locale_from_cache() { return android::base::Trim(content); } +static void ListenRecoverySocket(RecoveryUI* ui, std::atomic<Device::BuiltinAction>& action) { + android::base::unique_fd sock_fd(android_get_control_socket("recovery")); + if (sock_fd < 0) { + PLOG(ERROR) << "Failed to open recovery socket"; + return; + } + listen(sock_fd, 4); + + while (true) { + android::base::unique_fd connection_fd; + connection_fd.reset(accept(sock_fd, nullptr, nullptr)); + if (connection_fd < 0) { + PLOG(ERROR) << "Failed to accept socket connection"; + continue; + } + char msg; + constexpr char kSwitchToFastboot = 'f'; + constexpr char kSwitchToRecovery = 'r'; + ssize_t ret = TEMP_FAILURE_RETRY(read(connection_fd, &msg, sizeof(msg))); + if (ret != sizeof(msg)) { + PLOG(ERROR) << "Couldn't read from socket"; + continue; + } + switch (msg) { + case kSwitchToRecovery: + action = Device::BuiltinAction::ENTER_RECOVERY; + break; + case kSwitchToFastboot: + action = Device::BuiltinAction::ENTER_FASTBOOT; + break; + default: + LOG(ERROR) << "Unrecognized char from socket " << msg; + continue; + } + ui->InterruptKey(); + } +} + static void redirect_stdio(const char* filename) { int pipefd[2]; if (pipe(pipefd) == -1) { @@ -251,6 +294,11 @@ static void redirect_stdio(const char* filename) { } } +static bool SetUsbConfig(const std::string& state) { + android::base::SetProperty("sys.usb.config", state); + return android::base::WaitForProperty("sys.usb.state", state); +} + int main(int argc, char** argv) { // We don't have logcat yet under recovery; so we'll print error on screen and log to stdout // (which is redirected to recovery.log) as we used to do. @@ -281,8 +329,6 @@ int main(int argc, char** argv) { // instances with different timestamps. redirect_stdio(Paths::Get().temporary_log_file().c_str()); - printf("Starting recovery (pid %d) on %s", getpid(), ctime(&start)); - load_volume_table(); has_cache = volume_for_mount_point(CACHE_ROOT) != nullptr; @@ -290,12 +336,14 @@ int main(int argc, char** argv) { auto args_to_parse = StringVectorToNullTerminatedArray(args); static constexpr struct option OPTIONS[] = { + { "fastboot", no_argument, nullptr, 0 }, { "locale", required_argument, nullptr, 0 }, { "show_text", no_argument, nullptr, 't' }, { nullptr, 0, nullptr, 0 }, }; bool show_text = false; + bool fastboot = false; std::string locale; int arg; @@ -310,6 +358,8 @@ int main(int argc, char** argv) { std::string option = OPTIONS[option_index].name; if (option == "locale") { locale = optarg; + } else if (option == "fastboot") { + fastboot = true; } break; } @@ -328,8 +378,6 @@ int main(int argc, char** argv) { } } - printf("locale is [%s]\n", locale.c_str()); - static constexpr const char* kDefaultLibRecoveryUIExt = "librecovery_ui_ext.so"; // Intentionally not calling dlclose(3) to avoid potential gotchas (e.g. `make_device` may have // handed out pointers to code or static [or thread-local] data and doesn't collect them all back @@ -374,33 +422,67 @@ int main(int argc, char** argv) { ui->SetBackground(RecoveryUI::NONE); if (show_text) ui->ShowText(true); + LOG(INFO) << "Starting recovery (pid " << getpid() << ") on " << ctime(&start); + LOG(INFO) << "locale is [" << locale << "]"; + sehandle = selinux_android_file_context_handle(); selinux_android_set_sehandle(sehandle); if (!sehandle) { ui->Print("Warning: No file_contexts\n"); } - Device::BuiltinAction after = start_recovery(device, args); + std::atomic<Device::BuiltinAction> action; + std::thread listener_thread(ListenRecoverySocket, ui, std::ref(action)); + listener_thread.detach(); + + while (true) { + std::string usb_config = fastboot ? "fastboot" : is_ro_debuggable() ? "adb" : "none"; + std::string usb_state = android::base::GetProperty("sys.usb.state", "none"); + if (usb_config != usb_state) { + if (!SetUsbConfig("none")) { + LOG(ERROR) << "Failed to clear USB config"; + } + if (!SetUsbConfig(usb_config)) { + LOG(ERROR) << "Failed to set USB config to " << usb_config; + } + } - switch (after) { - case Device::SHUTDOWN: - ui->Print("Shutting down...\n"); - android::base::SetProperty(ANDROID_RB_PROPERTY, "shutdown,"); - break; + auto ret = fastboot ? StartFastboot(device, args) : start_recovery(device, args); - case Device::REBOOT_BOOTLOADER: - ui->Print("Rebooting to bootloader...\n"); - android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,bootloader"); - break; + if (ret == Device::KEY_INTERRUPTED) { + ret = action.exchange(ret); + if (ret == Device::NO_ACTION) { + continue; + } + } + switch (ret) { + case Device::SHUTDOWN: + ui->Print("Shutting down...\n"); + android::base::SetProperty(ANDROID_RB_PROPERTY, "shutdown,"); + break; - default: - ui->Print("Rebooting...\n"); - reboot("reboot,"); - break; - } - while (true) { - pause(); + case Device::REBOOT_BOOTLOADER: + ui->Print("Rebooting to bootloader...\n"); + android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,bootloader"); + break; + + case Device::ENTER_FASTBOOT: + LOG(INFO) << "Entering fastboot"; + fastboot = true; + break; + + case Device::ENTER_RECOVERY: + LOG(INFO) << "Entering recovery"; + fastboot = false; + break; + + default: + ui->Print("Rebooting...\n"); + reboot("reboot,"); + break; + } } + // Should be unreachable. return EXIT_SUCCESS; } @@ -327,6 +327,7 @@ int format_volume(const char* volume, const char* directory) { "-f", "-O", "encrypt", "-O", "quota", + "-O", "verity", "-w", std::to_string(kSectorSize), v->blk_device, }; diff --git a/tests/Android.bp b/tests/Android.bp new file mode 100644 index 000000000..d305e2560 --- /dev/null +++ b/tests/Android.bp @@ -0,0 +1,218 @@ +// 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_test_defaults", + + defaults: [ + "recovery_defaults", + ], + + include_dirs: [ + "bootable/recovery", + ], + + shared_libs: [ + "libbase", + "libcrypto", + "libcutils", + "liblog", + "libpng", + "libselinux", + "libz", + "libziparchive", + ], + + target: { + android: { + shared_libs: [ + "libutils", + ], + }, + + host: { + static_libs: [ + "libutils", + ], + } + }, +} + +// libapplypatch, libapplypatch_modes, libimgdiff, libimgpatch +libapplypatch_static_libs = [ + "libapplypatch_modes", + "libapplypatch", + "libedify", + "libimgdiff", + "libimgpatch", + "libotafault", + "libotautil", + "libbsdiff", + "libbspatch", + "libdivsufsort", + "libdivsufsort64", + "libutils", + "libbase", + "libbrotli", + "libbz", + "libcrypto", + "libz", + "libziparchive", +] + +// librecovery_defaults uses many shared libs that we want to avoid using in tests (e.g. we don't +// have 32-bit android.hardware.health@2.0.so or libbootloader_message.so on marlin). +librecovery_static_libs = [ + "librecovery", + "librecovery_fastboot", + "libminui", + "libverifier", + "libotautil", + + "libhealthhalutils", + "libvintf_recovery", + "libvintf", + + "android.hardware.health@2.0", + "android.hardware.health@1.0", + "libbootloader_message", + "libext4_utils", + "libfs_mgr", + "libfusesideload", + "libhidl-gen-utils", + "libhidlbase", + "libhidltransport", + "libhwbinder", + "libvndksupport", + "libtinyxml2", +] + +cc_test { + name: "recovery_unit_test", + + defaults: [ + "recovery_test_defaults", + ], + + test_suites: ["device-tests"], + + srcs: [ + "unit/asn1_decoder_test.cpp", + "unit/applypatch_test.cpp", + "unit/commands_test.cpp", + "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", + ], + + static_libs: libapplypatch_static_libs + [ + "librecovery_ui", + "libminui", + "libverifier", + "libotautil", + "libupdater", + "libgtest_prod", + "libBionicGtestMain", + ], + + data: ["testdata/*"], +} + +cc_test { + name: "recovery_manual_test", + + defaults: [ + "recovery_test_defaults", + ], + + test_suites: ["device-tests"], + + srcs: [ + "manual/recovery_test.cpp", + ], + + static_libs: [ + "libBionicGtestMain", + ], +} + +cc_test { + name: "recovery_component_test", + + defaults: [ + "recovery_test_defaults", + "libupdater_defaults", + ], + + test_suites: ["device-tests"], + + srcs: [ + "component/bootloader_message_test.cpp", + "component/edify_test.cpp", + "component/imgdiff_test.cpp", + "component/install_test.cpp", + "component/resources_test.cpp", + "component/sideload_test.cpp", + "component/uncrypt_test.cpp", + "component/updater_test.cpp", + "component/update_verifier_test.cpp", + "component/verifier_test.cpp", + ], + + static_libs: libapplypatch_static_libs + librecovery_static_libs + [ + "libupdater", + "libupdate_verifier", + "libprotobuf-cpp-lite", + "libBionicGtestMain", + ], + + data: [ + "testdata/*", + ":res-testdata", + ], +} + +cc_test_host { + name: "recovery_host_test", + + defaults: [ + "recovery_test_defaults", + ], + + srcs: [ + "component/imgdiff_test.cpp", + ], + + static_libs: [ + "libimgdiff", + "libimgpatch", + "libotautil", + "libbsdiff", + "libbspatch", + "libziparchive", + "libutils", + "libcrypto", + "libbrotli", + "libbz", + "libdivsufsort64", + "libdivsufsort", + "libz", + "libBionicGtestMain", + ], + + data: ["testdata/*"], +} diff --git a/tests/Android.mk b/tests/Android.mk deleted file mode 100644 index daf4853b9..000000000 --- a/tests/Android.mk +++ /dev/null @@ -1,230 +0,0 @@ -# -# Copyright (C) 2014 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) - -# libapplypatch, libapplypatch_modes, libimgdiff, libimgpatch. -libapplypatch_static_libraries := \ - libapplypatch_modes \ - libapplypatch \ - libedify \ - libimgdiff \ - libimgpatch \ - libotafault \ - libotautil \ - libbsdiff \ - libbspatch \ - libdivsufsort \ - libdivsufsort64 \ - libutils \ - libbase \ - libbrotli \ - libbz \ - libcrypto \ - libz \ - libziparchive \ - -# Unit tests -include $(CLEAR_VARS) -LOCAL_CFLAGS := -Wall -Werror -LOCAL_MODULE := recovery_unit_test -LOCAL_COMPATIBILITY_SUITE := device-tests -LOCAL_STATIC_LIBRARIES := \ - $(libapplypatch_static_libraries) \ - libverifier \ - librecovery_ui \ - libminui \ - libotautil \ - libupdater \ - libgtest_prod \ - libpng \ - libziparchive \ - libutils \ - libz \ - libselinux \ - libbase \ - libBionicGtestMain - -LOCAL_SRC_FILES := \ - unit/applypatch_test.cpp \ - unit/asn1_decoder_test.cpp \ - unit/commands_test.cpp \ - 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 - -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 -include $(CLEAR_VARS) -LOCAL_CFLAGS := -Wall -Werror -LOCAL_MODULE := recovery_manual_test -LOCAL_STATIC_LIBRARIES := \ - libbase \ - libBionicGtestMain - -LOCAL_SRC_FILES := manual/recovery_test.cpp -LOCAL_SHARED_LIBRARIES := \ - liblog - -include $(BUILD_NATIVE_TEST) - -# Component tests -include $(CLEAR_VARS) -LOCAL_CFLAGS := \ - -Wall \ - -Werror \ - -D_FILE_OFFSET_BITS=64 - -LOCAL_MODULE := recovery_component_test -LOCAL_COMPATIBILITY_SUITE := device-tests -LOCAL_C_INCLUDES := bootable/recovery -LOCAL_SRC_FILES := \ - component/applypatch_modes_test.cpp \ - component/bootloader_message_test.cpp \ - component/edify_test.cpp \ - component/imgdiff_test.cpp \ - component/install_test.cpp \ - component/resources_test.cpp \ - component/sideload_test.cpp \ - component/uncrypt_test.cpp \ - component/updater_test.cpp \ - component/update_verifier_test.cpp \ - component/verifier_test.cpp - -LOCAL_SHARED_LIBRARIES := \ - libhidlbase \ - libprotobuf-cpp-lite - -tune2fs_static_libraries := \ - libext2_com_err \ - libext2_blkid \ - libext2_quota \ - libext2_uuid \ - libext2_e2p \ - libext2fs - -libupdater_static_libraries := \ - libupdater \ - libapplypatch \ - libbspatch \ - libedify \ - libziparchive \ - libotautil \ - libbootloader_message \ - libutils \ - libotafault \ - libext4_utils \ - libfec \ - libfec_rs \ - libverity_tree \ - libfs_mgr \ - libgtest_prod \ - liblog \ - libselinux \ - libsparse \ - libsquashfs_utils \ - libbz \ - libz \ - libbase \ - libcrypto \ - libcrypto_utils \ - libcutils \ - libtune2fs \ - libbrotli \ - $(tune2fs_static_libraries) - -librecovery_static_libraries := \ - librecovery \ - libbootloader_message \ - libfusesideload \ - libminadbd \ - librecovery_ui_default \ - librecovery_ui \ - libminui \ - libverifier \ - libotautil \ - libasyncio \ - libbatterymonitor \ - libcrypto_utils \ - libcrypto \ - libext4_utils \ - libfs_mgr \ - libpng \ - libsparse \ - libvintf_recovery \ - libvintf \ - libhidl-gen-utils \ - libtinyxml2 \ - libziparchive \ - libbase \ - libutils \ - libcutils \ - liblog \ - libselinux \ - libz \ - -libupdate_verifier_static_libraries := \ - libupdate_verifier \ - -LOCAL_STATIC_LIBRARIES := \ - $(libapplypatch_static_libraries) \ - $(librecovery_static_libraries) \ - $(libupdate_verifier_static_libraries) \ - $(libupdater_static_libraries) \ - libBionicGtestMain - -LOCAL_TEST_DATA := \ - $(call find-test-data-in-subdirs, $(LOCAL_PATH), "*", testdata) \ - $(call find-test-data-in-subdirs, bootable/recovery, "*_text.png", res-*) -include $(BUILD_NATIVE_TEST) - -# Host tests -include $(CLEAR_VARS) -LOCAL_CFLAGS := -Wall -Werror -LOCAL_MODULE := recovery_host_test -LOCAL_MODULE_HOST_OS := linux -LOCAL_C_INCLUDES := bootable/recovery -LOCAL_SRC_FILES := \ - component/imgdiff_test.cpp -LOCAL_STATIC_LIBRARIES := \ - libimgdiff \ - libimgpatch \ - libotautil \ - libbsdiff \ - libbspatch \ - libziparchive \ - libutils \ - libbase \ - libcrypto \ - libbrotli \ - libbz \ - libdivsufsort64 \ - libdivsufsort \ - libz \ - 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/component/install_test.cpp b/tests/component/install_test.cpp index b9af0b18b..08b429000 100644 --- a/tests/component/install_test.cpp +++ b/tests/component/install_test.cpp @@ -305,7 +305,7 @@ static void VerifyAbUpdateCommands(const std::string& serialno, bool success = t if (success) { ASSERT_EQ(0, SetUpAbUpdateCommands(package, zip, status_fd, &cmd)); ASSERT_EQ(5U, cmd.size()); - ASSERT_EQ("/sbin/update_engine_sideload", cmd[0]); + ASSERT_EQ("/system/bin/update_engine_sideload", cmd[0]); ASSERT_EQ("--payload=file://" + package, cmd[1]); ASSERT_EQ("--offset=" + std::to_string(payload_entry.offset), cmd[2]); ASSERT_EQ("--headers=" + properties, cmd[3]); diff --git a/tests/component/resources_test.cpp b/tests/component/resources_test.cpp index 618d5a4dd..54329db22 100644 --- a/tests/component/resources_test.cpp +++ b/tests/component/resources_test.cpp @@ -32,10 +32,10 @@ static const std::string kLocale = "zu"; -static const std::vector<std::string> kResourceImagesDirs{ "res-mdpi/images/", "res-hdpi/images/", - "res-xhdpi/images/", - "res-xxhdpi/images/", - "res-xxxhdpi/images/" }; +static const std::vector<std::string> kResourceImagesDirs{ + "res-mdpi/images/", "res-hdpi/images/", "res-xhdpi/images/", + "res-xxhdpi/images/", "res-xxxhdpi/images/", +}; static int png_filter(const dirent* de) { if (de->d_type != DT_REG || !android::base::EndsWith(de->d_name, "_text.png")) { diff --git a/tests/unit/commands_test.cpp b/tests/unit/commands_test.cpp index 9679a9e73..19841d676 100644 --- a/tests/unit/commands_test.cpp +++ b/tests/unit/commands_test.cpp @@ -333,6 +333,25 @@ TEST(CommandsTest, Parse_ZERO) { ASSERT_EQ(PatchInfo(), command.patch()); } +TEST(CommandsTest, Parse_COMPUTE_HASH_TREE) { + const std::string input{ "compute_hash_tree 2,0,1 2,3,4 sha1 unknown-salt unknown-root-hash" }; + std::string err; + Command command = Command::Parse(input, 9, &err); + ASSERT_TRUE(command); + + ASSERT_EQ(Command::Type::COMPUTE_HASH_TREE, command.type()); + ASSERT_EQ(9, command.index()); + ASSERT_EQ(input, command.cmdline()); + + HashTreeInfo expected_info(RangeSet({ { 0, 1 } }), RangeSet({ { 3, 4 } }), "sha1", "unknown-salt", + "unknown-root-hash"); + ASSERT_EQ(expected_info, command.hash_tree_info()); + ASSERT_EQ(TargetInfo(), command.target()); + ASSERT_EQ(SourceInfo(), command.source()); + ASSERT_EQ(StashInfo(), command.stash()); + ASSERT_EQ(PatchInfo(), command.patch()); +} + TEST(CommandsTest, Parse_InvalidNumberOfArgs) { Command::abort_allowed_ = true; @@ -341,6 +360,7 @@ TEST(CommandsTest, Parse_InvalidNumberOfArgs) { std::vector<std::string> inputs{ "abort foo", "bsdiff", + "compute_hash_tree, 2,0,1 2,0,1 unknown-algorithm unknown-salt", "erase", "erase 4,3,5,10,12 hash1", "free", diff --git a/tools/recovery_l10n/res/values-as/strings.xml b/tools/recovery_l10n/res/values-as/strings.xml new file mode 100644 index 000000000..2624cebe4 --- /dev/null +++ b/tools/recovery_l10n/res/values-as/strings.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="recovery_installing" msgid="2013591905463558223">"আপডেইট ইনষ্টল কৰি থকা হৈছে"</string> + <string name="recovery_erasing" msgid="7334826894904037088">"মচি থকা হৈছে"</string> + <string name="recovery_no_command" msgid="4465476568623024327">"কোনো আদেশ নাই"</string> + <string name="recovery_error" msgid="5748178989622716736">"ত্ৰুটি!"</string> + <string name="recovery_installing_security" msgid="9184031299717114342">"সুৰক্ষা আপডেইট ইনষ্টল কৰি থকা হৈছে"</string> +</resources> diff --git a/tools/recovery_l10n/res/values-en-rCA/strings.xml b/tools/recovery_l10n/res/values-en-rCA/strings.xml new file mode 100644 index 000000000..dc75c2374 --- /dev/null +++ b/tools/recovery_l10n/res/values-en-rCA/strings.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="recovery_installing" msgid="2013591905463558223">"Installing system update"</string> + <string name="recovery_erasing" msgid="7334826894904037088">"Erasing"</string> + <string name="recovery_no_command" msgid="4465476568623024327">"No command"</string> + <string name="recovery_error" msgid="5748178989622716736">"Error!"</string> + <string name="recovery_installing_security" msgid="9184031299717114342">"Installing security update"</string> +</resources> diff --git a/tools/recovery_l10n/res/values-en-rXC/strings.xml b/tools/recovery_l10n/res/values-en-rXC/strings.xml new file mode 100644 index 000000000..2d528b3fb --- /dev/null +++ b/tools/recovery_l10n/res/values-en-rXC/strings.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="recovery_installing" msgid="2013591905463558223">"Installing system update"</string> + <string name="recovery_erasing" msgid="7334826894904037088">"Erasing"</string> + <string name="recovery_no_command" msgid="4465476568623024327">"No command"</string> + <string name="recovery_error" msgid="5748178989622716736">"Error!"</string> + <string name="recovery_installing_security" msgid="9184031299717114342">"Installing security update"</string> +</resources> diff --git a/tools/recovery_l10n/res/values-or/strings.xml b/tools/recovery_l10n/res/values-or/strings.xml new file mode 100644 index 000000000..2b0851cdd --- /dev/null +++ b/tools/recovery_l10n/res/values-or/strings.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="recovery_installing" msgid="2013591905463558223">"ସିଷ୍ଟମ ଅପଡେଟ ଇନଷ୍ଟଲ କରୁଛି"</string> + <string name="recovery_erasing" msgid="7334826894904037088">"ଲିଭାଉଛି"</string> + <string name="recovery_no_command" msgid="4465476568623024327">"କୌଣସି କମାଣ୍ଡ ନାହିଁ"</string> + <string name="recovery_error" msgid="5748178989622716736">"ତ୍ରୁଟି!"</string> + <string name="recovery_installing_security" msgid="9184031299717114342">"ସୁରକ୍ଷା ଅପ୍ଡେଟ୍ ଇନ୍ଷ୍ଟଲ୍ କରୁଛି"</string> +</resources> diff --git a/updater/Android.bp b/updater/Android.bp new file mode 100644 index 000000000..c77bac8fb --- /dev/null +++ b/updater/Android.bp @@ -0,0 +1,80 @@ +// 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: "libupdater_defaults", + + defaults: [ + "recovery_defaults", + ], + + static_libs: [ + "libapplypatch", + "libbootloader_message", + "libbspatch", + "libedify", + "libotafault", + "libotautil", + "libext4_utils", + "libfec", + "libfec_rs", + "libverity_tree", + "libfs_mgr", + "libgtest_prod", + "liblog", + "libselinux", + "libsparse", + "libsquashfs_utils", + "libbrotli", + "libbz", + "libziparchive", + "libz", + "libbase", + "libcrypto", + "libcrypto_utils", + "libcutils", + "libutils", + "libtune2fs", + + "libext2_com_err", + "libext2_blkid", + "libext2_quota", + "libext2_uuid", + "libext2_e2p", + "libext2fs", + ], +} + +cc_library_static { + name: "libupdater", + + defaults: [ + "recovery_defaults", + "libupdater_defaults", + ], + + srcs: [ + "blockimg.cpp", + "commands.cpp", + "install.cpp", + ], + + include_dirs: [ + "external/e2fsprogs/misc", + ], + + export_include_dirs: [ + "include", + ], +} diff --git a/updater/Android.mk b/updater/Android.mk index 78d0bd451..5478a7df6 100644 --- a/updater/Android.mk +++ b/updater/Android.mk @@ -25,12 +25,10 @@ tune2fs_static_libraries := \ updater_common_static_libraries := \ libapplypatch \ libbootloader_message \ + libbspatch \ libedify \ libotafault \ libotautil \ - libbspatch \ - libziparchive \ - libutils \ libext4_utils \ libfec \ libfec_rs \ @@ -41,43 +39,18 @@ updater_common_static_libraries := \ libselinux \ libsparse \ libsquashfs_utils \ + libbrotli \ libbz \ + libziparchive \ libz \ libbase \ libcrypto \ libcrypto_utils \ libcutils \ + libutils \ libtune2fs \ - libbrotli \ $(tune2fs_static_libraries) -# libupdater (static library) -# =============================== -include $(CLEAR_VARS) - -LOCAL_MODULE := libupdater - -LOCAL_SRC_FILES := \ - commands.cpp \ - install.cpp \ - blockimg.cpp - -LOCAL_C_INCLUDES := \ - $(LOCAL_PATH)/include \ - external/e2fsprogs/misc - -LOCAL_CFLAGS := \ - -Wall \ - -Werror - -LOCAL_EXPORT_C_INCLUDE_DIRS := \ - $(LOCAL_PATH)/include - -LOCAL_STATIC_LIBRARIES := \ - $(updater_common_static_libraries) - -include $(BUILD_STATIC_LIBRARY) - # updater (static executable) # =============================== include $(CLEAR_VARS) diff --git a/updater/commands.cpp b/updater/commands.cpp index 15a787c51..4a90ea873 100644 --- a/updater/commands.cpp +++ b/updater/commands.cpp @@ -31,6 +31,14 @@ using namespace std::string_literals; bool Command::abort_allowed_ = false; +Command::Command(Type type, size_t index, std::string cmdline, HashTreeInfo hash_tree_info) + : type_(type), + index_(index), + cmdline_(std::move(cmdline)), + hash_tree_info_(std::move(hash_tree_info)) { + CHECK(type == Type::COMPUTE_HASH_TREE); +} + Command::Type Command::ParseType(const std::string& type_str) { if (type_str == "abort") { if (!abort_allowed_) { @@ -177,7 +185,6 @@ Command Command::Parse(const std::string& line, size_t index, std::string* err) SourceInfo source_info; StashInfo stash_info; - // TODO(xunchang) add the parse code of compute_hash_tree if (op == Type::ZERO || op == Type::NEW || op == Type::ERASE) { // zero/new/erase <rangeset> if (pos + 1 != tokens.size()) { @@ -255,6 +262,39 @@ Command Command::Parse(const std::string& line, size_t index, std::string* err) tokens.size() - pos); return {}; } + } else if (op == Type::COMPUTE_HASH_TREE) { + // <hash_tree_ranges> <source_ranges> <hash_algorithm> <salt_hex> <root_hash> + if (pos + 5 != tokens.size()) { + *err = android::base::StringPrintf("invalid number of args: %zu (expected 5)", + tokens.size() - pos); + return {}; + } + + // Expects the hash_tree data to be contiguous. + RangeSet hash_tree_ranges = RangeSet::Parse(tokens[pos++]); + if (!hash_tree_ranges || hash_tree_ranges.size() != 1) { + *err = "invalid hash tree ranges in: " + line; + return {}; + } + + RangeSet source_ranges = RangeSet::Parse(tokens[pos++]); + if (!source_ranges) { + *err = "invalid source ranges in: " + line; + return {}; + } + + std::string hash_algorithm = tokens[pos++]; + std::string salt_hex = tokens[pos++]; + std::string root_hash = tokens[pos++]; + if (hash_algorithm.empty() || salt_hex.empty() || root_hash.empty()) { + *err = "invalid hash tree arguments in " + line; + return {}; + } + + HashTreeInfo hash_tree_info(std::move(hash_tree_ranges), std::move(source_ranges), + std::move(hash_algorithm), std::move(salt_hex), + std::move(root_hash)); + return Command(op, index, line, std::move(hash_tree_info)); } else { *err = "invalid op"; return {}; diff --git a/updater/include/private/commands.h b/updater/include/private/commands.h index 7f9dc79f4..85b52883b 100644 --- a/updater/include/private/commands.h +++ b/updater/include/private/commands.h @@ -166,6 +166,50 @@ class PatchInfo { size_t length_{ 0 }; }; +// The arguments to build a hash tree from blocks on the block device. +class HashTreeInfo { + public: + HashTreeInfo() = default; + + HashTreeInfo(RangeSet hash_tree_ranges, RangeSet source_ranges, std::string hash_algorithm, + std::string salt_hex, std::string root_hash) + : hash_tree_ranges_(std::move(hash_tree_ranges)), + source_ranges_(std::move(source_ranges)), + hash_algorithm_(std::move(hash_algorithm)), + salt_hex_(std::move(salt_hex)), + root_hash_(std::move(root_hash)) {} + + const RangeSet& hash_tree_ranges() const { + return hash_tree_ranges_; + } + const RangeSet& source_ranges() const { + return source_ranges_; + } + + const std::string& hash_algorithm() const { + return hash_algorithm_; + } + const std::string& salt_hex() const { + return salt_hex_; + } + const std::string& root_hash() const { + return root_hash_; + } + + bool operator==(const HashTreeInfo& other) const { + return hash_tree_ranges_ == other.hash_tree_ranges_ && source_ranges_ == other.source_ranges_ && + hash_algorithm_ == other.hash_algorithm_ && salt_hex_ == other.salt_hex_ && + root_hash_ == other.root_hash_; + } + + private: + RangeSet hash_tree_ranges_; + RangeSet source_ranges_; + std::string hash_algorithm_; + std::string salt_hex_; + std::string root_hash_; +}; + // Command class holds the info for an update command that performs block-based OTA (BBOTA). Each // command consists of one or several args, namely TargetInfo, SourceInfo, StashInfo and PatchInfo. // The currently used BBOTA version is v4. @@ -248,6 +292,8 @@ class Command { source_(std::move(source)), stash_(std::move(stash)) {} + Command(Type type, size_t index, std::string cmdline, HashTreeInfo hash_tree_info); + // Parses the given command 'line' into a Command object and returns it. The 'index' is specified // by the caller to index the object. On parsing error, it returns an empty Command object that // evaluates to false, and the specific error message will be set in 'err'. @@ -284,6 +330,10 @@ class Command { return stash_; } + const HashTreeInfo& hash_tree_info() const { + return hash_tree_info_; + } + constexpr explicit operator bool() const { return type_ != Type::LAST; } @@ -325,6 +375,8 @@ class Command { // The stash info. Only meaningful for STASH and FREE commands. Note that although SourceInfo may // also load data from stash, such info will be owned and managed by SourceInfo (i.e. in source_). StashInfo stash_; + // The hash_tree info. Only meaningful for COMPUTE_HASH_TREE. + HashTreeInfo hash_tree_info_; }; std::ostream& operator<<(std::ostream& os, const Command& command); diff --git a/updater/install.cpp b/updater/install.cpp index 088d24b31..f9333459b 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -497,12 +497,10 @@ Value* FormatFn(const char* name, State* state, const std::vector<std::unique_pt const char* f2fs_argv[] = { "mkfs.f2fs", "-d1", "-f", - "-O", - "encrypt", - "-O", - "quota", - "-w", - "512", + "-O", "encrypt", + "-O", "quota", + "-O", "verity", + "-w", "512", location.c_str(), (size < 512) ? nullptr : num_sectors.c_str(), nullptr }; diff --git a/updater_sample/Android.bp b/updater_sample/Android.bp new file mode 100644 index 000000000..845e07b70 --- /dev/null +++ b/updater_sample/Android.bp @@ -0,0 +1,33 @@ +// 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. + +android_app { + name: "SystemUpdaterSample", + sdk_version: "system_current", + privileged: true, + + srcs: ["src/**/*.java"], + + static_libs: [ + "guava", + ], + + optimize: { + proguard_flags_files: [ + "proguard.flags", + ], + }, + + resource_dirs: ["res"], +} diff --git a/updater_sample/Android.mk b/updater_sample/Android.mk deleted file mode 100644 index cff5b0c1f..000000000 --- a/updater_sample/Android.mk +++ /dev/null @@ -1,35 +0,0 @@ -# -# 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 := SystemUpdaterSample -LOCAL_SDK_VERSION := system_current -LOCAL_PRIVILEGED_MODULE := true - -LOCAL_PROGUARD_FLAG_FILES := proguard.flags - -LOCAL_SRC_FILES := $(call all-java-files-under, src) - -LOCAL_STATIC_JAVA_LIBRARIES += guava - -LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res - -include $(BUILD_PACKAGE) - -# Use the following include to make our test apk. -include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/updater_sample/README.md b/updater_sample/README.md index 306e71e5b..69e8e244f 100644 --- a/updater_sample/README.md +++ b/updater_sample/README.md @@ -227,7 +227,7 @@ privileged system app, so it's granted the required permissions to access 1. Build `mmma bootable/recovery/updater_sample/` 2. Install app - `adb install $OUT/system/app/SystemUpdaterSample/SystemUpdaterSample.apk` + `adb install $OUT/system/priv-app/SystemUpdaterSample/SystemUpdaterSample.apk` 3. Install tests `adb install $OUT/testcases/SystemUpdaterSampleTests/SystemUpdaterSampleTests.apk` 4. Run tests diff --git a/updater_sample/tests/Android.bp b/updater_sample/tests/Android.bp new file mode 100644 index 000000000..c2783ef88 --- /dev/null +++ b/updater_sample/tests/Android.bp @@ -0,0 +1,40 @@ +// 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. + +android_test { + name: "SystemUpdaterSampleTests", + sdk_version: "system_current", + + libs: [ + "android.test.base.stubs", + "android.test.runner.stubs", + "SystemUpdaterSample", + ], + + static_libs: [ + "android-support-test", + "mockito-target-minus-junit4", + "guava", + ], + + instrumentation_for: "com.example.android.systemupdatersample", + + optimize: { + enabled: false, + }, + + resource_dirs: ["res"], + + srcs: ["src/**/*.java"], +} diff --git a/updater_sample/tests/Android.mk b/updater_sample/tests/Android.mk deleted file mode 100644 index 415760454..000000000 --- a/updater_sample/tests/Android.mk +++ /dev/null @@ -1,36 +0,0 @@ -# -# 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 := SystemUpdaterSampleTests -LOCAL_SDK_VERSION := system_current -LOCAL_MODULE_TAGS := tests -LOCAL_JAVA_LIBRARIES := \ - android.test.base.stubs \ - android.test.runner.stubs -LOCAL_STATIC_JAVA_LIBRARIES := android-support-test \ - mockito-target-minus-junit4 \ - guava -LOCAL_INSTRUMENTATION_FOR := SystemUpdaterSample -LOCAL_PROGUARD_ENABLED := disabled - -LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res - -LOCAL_SRC_FILES := $(call all-java-files-under, src) - -include $(BUILD_PACKAGE) |