Compile update_engine_sideload as a static recovery program.

This patch converts update_engine_sideload to a statically linked
program and installs it in the recovery image. The resulting program
uses a statically linked boot_control HAL instead of relying in
libhardware to dynamically load it.

The static library or libraries needed for the boot_control HAL need to
be specified by the product with the new make variable
PRODUCT_STATIC_BOOT_CONTROL_HAL. Otherwise, a stub implementation is
included and update_engine_sideload will fail at runtime.

Bug: 27178350
TEST=`make dist` builds a recovery image with update_engine_sideload in it.

(cherry picked from commit 44348e01c0c66e6baf1376f0b712ecae26fc5595)

Change-Id: I34fd1514eecbb2ddd89802891ea606418f28a60f
diff --git a/Android.mk b/Android.mk
index dc5fd4a..c6b0f57 100644
--- a/Android.mk
+++ b/Android.mk
@@ -62,8 +62,8 @@
     external/gtest/include \
     system
 ue_common_shared_libraries := \
-    libbrillo \
     libbrillo-stream \
+    libbrillo \
     libchrome
 
 ifeq ($(local_use_dbus),1)
@@ -472,12 +472,11 @@
 # from a local file directly instead of running in the background.
 include $(CLEAR_VARS)
 LOCAL_MODULE := update_engine_sideload
-# TODO(deymo): Make this binary a static binary and move it to recovery.
-# LOCAL_FORCE_STATIC_EXECUTABLE := true
-# LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
+LOCAL_FORCE_STATIC_EXECUTABLE := true
+LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
 LOCAL_MODULE_CLASS := EXECUTABLES
 LOCAL_REQUIRED_MODULES := \
-    bspatch
+    bspatch_recovery
 LOCAL_CPP_EXTENSION := .cc
 LOCAL_CLANG := true
 LOCAL_CFLAGS := \
@@ -507,12 +506,40 @@
     update_metadata-protos \
     $(ue_libpayload_consumer_exported_static_libraries:-host=) \
     $(ue_update_metadata_protos_exported_static_libraries)
-LOCAL_SHARED_LIBRARIES := \
+# We add the static versions of the shared libraries since we are forcing this
+# binary to be a static binary, so we also need to include all the static
+# library dependencies of these static libraries.
+LOCAL_STATIC_LIBRARIES += \
     $(ue_common_shared_libraries) \
-    libhardware \
     libcutils \
     $(ue_libpayload_consumer_exported_shared_libraries:-host=) \
-    $(ue_update_metadata_protos_exported_shared_libraries)
+    $(ue_update_metadata_protos_exported_shared_libraries) \
+    libevent \
+    libmodpb64 \
+    libgtest_prod
+# libchrome requires these extra LDFLAGS which are not propagated through the
+# build system.
+LOCAL_LDFLAGS += \
+    -Wl,-wrap,calloc \
+    -Wl,-wrap,free \
+    -Wl,-wrap,malloc \
+    -Wl,-wrap,memalign \
+    -Wl,-wrap,realloc
+
+ifeq ($(strip $(PRODUCT_STATIC_BOOT_CONTROL_HAL)),)
+# No static boot_control HAL defined, so no sideload support. We use a fake
+# boot_control HAL to allow compiling update_engine_sideload for test purposes.
+ifeq ($(strip $(AB_OTA_UPDATER)),true)
+$(warning No PRODUCT_STATIC_BOOT_CONTROL_HAL configured but AB_OTA_UPDATER is \
+true, no update sideload support.)
+endif  # AB_OTA_UPDATER == true
+LOCAL_SRC_FILES += \
+    boot_control_recovery_stub.cc
+else  # PRODUCT_STATIC_BOOT_CONTROL_HAL != ""
+LOCAL_STATIC_LIBRARIES += \
+    $(PRODUCT_STATIC_BOOT_CONTROL_HAL)
+endif  # PRODUCT_STATIC_BOOT_CONTROL_HAL != ""
+
 include $(BUILD_EXECUTABLE)
 
 # libupdate_engine_client (type: shared_library)
diff --git a/boot_control_android.cc b/boot_control_android.cc
index ba6b559..d096a1b 100644
--- a/boot_control_android.cc
+++ b/boot_control_android.cc
@@ -28,6 +28,14 @@
 
 using std::string;
 
+#ifdef _UE_SIDELOAD
+// When called from update_engine_sideload, we don't attempt to dynamically load
+// the right boot_control HAL, instead we use the only HAL statically linked in
+// via the PRODUCT_STATIC_BOOT_CONTROL_HAL make variable and access the module
+// struct directly.
+extern const hw_module_t HAL_MODULE_INFO_SYM;
+#endif  // _UE_SIDELOAD
+
 namespace chromeos_update_engine {
 
 namespace boot_control {
@@ -47,7 +55,18 @@
   const hw_module_t* hw_module;
   int ret;
 
+#ifdef _UE_SIDELOAD
+  // For update_engine_sideload, we simulate the hw_get_module() by accessing it
+  // from the current process directly.
+  hw_module = &HAL_MODULE_INFO_SYM;
+  ret = 0;
+  if (!hw_module ||
+      strcmp(BOOT_CONTROL_HARDWARE_MODULE_ID, hw_module->id) != 0) {
+    ret = -EINVAL;
+  }
+#else  // !_UE_SIDELOAD
   ret = hw_get_module(BOOT_CONTROL_HARDWARE_MODULE_ID, &hw_module);
+#endif  // _UE_SIDELOAD
   if (ret != 0) {
     LOG(ERROR) << "Error loading boot_control HAL implementation.";
     return false;
diff --git a/boot_control_recovery_stub.cc b/boot_control_recovery_stub.cc
new file mode 100644
index 0000000..129c5d0
--- /dev/null
+++ b/boot_control_recovery_stub.cc
@@ -0,0 +1,21 @@
+//
+// Copyright (C) 2016 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 <hardware/hardware.h>
+
+hw_module_t HAL_MODULE_INFO_SYM = {
+  .id = "stub",
+};