vold_decrypt: Add android 9.0 support

* build modified vdc_pie binary with 'checkpw' command support
  if building with Android 9.0 platform. That command and others
  we don't care about, are removed from Pie vdc. Our vdc_pie will
  run if system sdk version is > 27, otherwise system vdc is used.
  Code adapted from Android 9.0 system/vold/vdc.

* include prebuilt vdc_pie(arm, arm64) binary if building with lower
  than Android 9.0 platform - vdc_pie cannot be build from source
  with those platforms without additional imports from Android 9.0

* skip vdc "getpwtype" command for Pie - vds communicates with vold
  directly, no need for connection retries first

* add /system/bin/servicemanager to required services

* mount per-devive additional partitions needed for decryption
  listed with device BoardConfig.mk TW_CRYPTO_SYSTEM_VOLD_MOUNT
  flag like(space separated):
  TW_CRYPTO_SYSTEM_VOLD_MOUNT := vendor cust odm

* add function to backup crypto footer before running vdc commands
  and restore it after - on Xiaomi Mi Max 3 both Oreo and Pie stock
  roms vold alters cripto footer when decrypting data in recovery
  which causes system to ask for crypto password at next reboot
  although password stays unchanged. Crypto footer backup/restore
  added as workaround for systems whit ro.build.version.sdk > 25.
  Also to preserve crypto footer integrity decryption attempts are
  skipped if footer backup fails to ensure no data loss.
  Code adapted from
  https://gerrit.omnirom.org/#/c/android_bootable_recovery/+/31206/

Change-Id: I0a383f3843578fa55595cfea3b7c9c4431646a1a
diff --git a/crypto/vold_decrypt/vdc_pie.cpp b/crypto/vold_decrypt/vdc_pie.cpp
new file mode 100644
index 0000000..a840712
--- /dev/null
+++ b/crypto/vold_decrypt/vdc_pie.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2008 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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <poll.h>
+
+#include <cutils/properties.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/un.h>
+
+#include "android/os/IVold.h"
+
+#include <binder/IServiceManager.h>
+#include <binder/Status.h>
+
+#include <private/android_filesystem_config.h>
+
+static void usage();
+
+static android::sp<android::IBinder> getServiceAggressive() {
+    static char prop_value[PROPERTY_VALUE_MAX];
+    property_get("init.svc.sys_vold", prop_value, "error");
+    if (strncmp(prop_value, "running", strlen("running")) != 0) {
+        printf("vdc_pie: vold is not running, init.svc.sys_vold=%s\n", prop_value);
+        exit(EINVAL);
+    }
+
+    android::sp<android::IBinder> res;
+    auto sm = android::defaultServiceManager();
+    auto name = android::String16("vold");
+    for (int i = 0; i < 5000; i++) {
+        res = sm->checkService(name);
+        if (res) {
+            printf("vdc_pie: Got vold, waited %d ms\n", (i * 10));
+            break;
+        }
+        usleep(10000); // 10ms
+    }
+    return res;
+}
+
+static int checkStatus(android::binder::Status status) {
+    if (status.isOk()) return 0;
+    std::string ret = status.toString8().string();
+#ifdef TWRP_INCLUDE_LOGCAT
+    printf("vdc_pie: Decryption failed, vold service returned: %s,"
+		" see logcat for details\n", ret.c_str());
+#else
+	printf("vdc_pie: Decryption failed, vold service returned: %s\n", ret.c_str());
+#endif
+    return -1;
+}
+
+int main(int argc, char** argv) {
+    std::vector<std::string> args(argv + 1, argv + argc);
+
+    if (args.size() > 0 && args[0] == "--wait") {
+        // Just ignore the --wait flag
+        args.erase(args.begin());
+    }
+
+    if (args.size() < 2) {
+        usage();
+        exit(5);
+    }
+    android::sp<android::IBinder> binder = getServiceAggressive();
+    if (!binder) {
+        printf("vdc_pie: Failed to obtain vold Binder\n");
+        exit(EINVAL);
+    }
+    auto vold = android::interface_cast<android::os::IVold>(binder);
+
+    if (args[0] == "cryptfs" && args[1] == "checkpw" && args.size() == 3) {
+        return checkStatus(vold->fdeCheckPassword(args[2]));
+    } else {
+        usage();
+        exit(EINVAL);
+    }
+    return 0;
+}
+
+static void usage() {
+    printf("vdc_pie: Usage: vold_pie cryptfs checkpw <password>\n");
+}