platform_system_vold/vdc.cpp
Jeff Sharkey 4a53a9edb3 Be more aggressive about obtaining vold service.
vdc is typically invoked very early during boot, where it races with
vold starting up.  The default getService() implementation waits a
whole second between retrying, so write a local getServiceAggressive()
that only waits 10ms between attempts.

Test: builds, boots
Bug: 65737446
Change-Id: I581db3afcf7f81dd7cd9cc84dc03194759861669
2017-09-21 18:20:59 -06:00

114 lines
3.4 KiB
C++

/*
* 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 <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/un.h>
#include "android/os/IVold.h"
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <binder/IServiceManager.h>
#include <private/android_filesystem_config.h>
static void usage(char *progname);
static android::sp<android::IBinder> getServiceAggressive() {
android::sp<android::IBinder> res;
auto sm = android::defaultServiceManager();
auto name = android::String16("vold");
for (int i = 0; i < 500; i++) {
res = sm->checkService(name);
if (res) {
LOG(VERBOSE) << "Waited " << (i * 10) << "ms for vold";
break;
}
usleep(10000); // 10ms
}
return res;
}
int main(int argc, char **argv) {
int sock;
int wait;
char *progname;
progname = argv[0];
setenv("ANDROID_LOG_TAGS", "*:v", 1);
if (getppid() == 1) {
// If init is calling us then it's during boot and we should log to kmsg
android::base::InitLogging(argv, &android::base::KernelLogger);
} else {
android::base::InitLogging(argv, &android::base::StderrLogger);
}
wait = argc > 1 && strcmp(argv[1], "--wait") == 0;
if (wait) {
argv++;
argc--;
}
if (argc < 3) {
usage(progname);
exit(5);
}
std::string arg1 = argv[1];
std::string arg2 = argv[2];
android::sp<android::IBinder> binder = getServiceAggressive();
if (!binder) {
LOG(ERROR) << "Failed to obtain vold Binder";
exit(EINVAL);
}
auto vold = android::interface_cast<android::os::IVold>(binder);
if (arg1 == "cryptfs" && arg2 == "enablefilecrypto") {
exit(vold->fbeEnable().isOk() ? 0 : ENOTTY);
} else if (arg1 == "cryptfs" && arg2 == "init_user0") {
exit(vold->initUser0().isOk() ? 0 : ENOTTY);
} else if (arg1 == "cryptfs" && arg2 == "enablecrypto") {
int passwordType = android::os::IVold::PASSWORD_TYPE_DEFAULT;
int encryptionFlags = android::os::IVold::ENCRYPTION_FLAG_IN_PLACE
| android::os::IVold::ENCRYPTION_FLAG_NO_UI;
exit(vold->fdeEnable(passwordType, "", encryptionFlags).isOk() ? 0 : ENOTTY);
} else if (arg1 == "cryptfs" && arg2 == "mountdefaultencrypted") {
exit(vold->mountDefaultEncrypted().isOk() ? 0 : ENOTTY);
} else if (arg1 == "volume" && arg2 == "shutdown") {
exit(vold->shutdown().isOk() ? 0 : ENOTTY);
} else {
LOG(ERROR) << "Raw commands are no longer supported";
exit(EINVAL);
}
}
static void usage(char *progname) {
LOG(INFO) << "Usage: " << progname << " [--wait] <monitor>|<cmd> [arg1] [arg2...]";
}