author | Tellen Yu <tellen.yu@amlogic.com> | 2017-11-01 03:23:43 (GMT) |
---|---|---|
committer | Gerrit Code Review <gituser@scgit.amlogic.com> | 2017-11-01 03:23:43 (GMT) |
commit | 56c6c8a49dfa6cbb99e90caf7acc38839771cbe3 (patch) | |
tree | 6ab53ef866d141d5ee46c197b375e5a35b80d4c6 | |
parent | 2b8856b245eb72372053501ab73e6d0aab1953b2 (diff) | |
parent | 799c298e1dd1d0a4490555a720e99450c2abb717 (diff) | |
download | droidvold-ref-o-20171115.zip droidvold-ref-o-20171115.tar.gz droidvold-ref-o-20171115.tar.bz2 |
Merge "droidvold: as hwbinder service [2/4]" into o-amlogic
-rw-r--r-- | Android.mk | 36 | ||||
-rw-r--r-- | CommandListener.cpp | 224 | ||||
-rw-r--r-- | CommandListener.h | 50 | ||||
-rw-r--r-- | Disk.cpp | 144 | ||||
-rw-r--r-- | Disk.h | 16 | ||||
-rw-r--r-- | DroidVold.cpp | 166 | ||||
-rw-r--r-- | DroidVold.h | 76 | ||||
-rw-r--r-- | NetlinkManager.h | 10 | ||||
-rw-r--r-- | PublicVolume.cpp | 88 | ||||
-rw-r--r-- | PublicVolume.h | 3 | ||||
-rw-r--r-- | Utils.cpp | 148 | ||||
-rw-r--r-- | Utils.h | 9 | ||||
-rw-r--r-- | VoldCommand.cpp | 21 | ||||
-rw-r--r-- | VoldCommand.h | 28 | ||||
-rw-r--r-- | VolumeBase.cpp | 26 | ||||
-rw-r--r-- | VolumeBase.h | 6 | ||||
-rw-r--r-- | VolumeManager.cpp | 172 | ||||
-rw-r--r-- | VolumeManager.h | 12 | ||||
-rw-r--r-- | droidvold.rc | 5 | ||||
-rw-r--r-- | dvdc.cpp | 178 | ||||
-rw-r--r-- | main.cpp | 138 | ||||
-rw-r--r-- | secontext.cpp | 22 | ||||
-rw-r--r-- | secontext.h | 25 | ||||
-rw-r--r-- | sehandle.h | 24 |
24 files changed, 655 insertions, 972 deletions
@@ -2,8 +2,7 @@ LOCAL_PATH:= $(call my-dir) common_src_files := \ VolumeManager.cpp \ - CommandListener.cpp \ - VoldCommand.cpp \ + DroidVold.cpp \ NetlinkManager.cpp \ NetlinkHandler.cpp \ Process.cpp \ @@ -17,10 +16,16 @@ common_src_files := \ VolumeBase.cpp \ PublicVolume.cpp \ ResponseCode.cpp \ - Utils.cpp \ - secontext.cpp \ + Utils.cpp + +common_c_includes := \ + system/libhidl/transport/include/hidl \ + external/libcxx/include common_shared_libraries := \ + vendor.amlogic.hardware.droidvold@1.0_vendor \ + libhidlbase \ + libhidltransport \ libsysutils \ libcutils \ liblog \ @@ -28,13 +33,19 @@ common_shared_libraries := \ libext4_utils \ libselinux \ libutils \ - libbase + libbinder \ + libbase \ + libext2_blkid \ + libext2fs \ + libext2_com_err \ + libext2_e2p + common_static_libraries := \ libfs_mgr \ vold_conlyflags := -std=c11 -vold_cflags := -Werror -Wall -Wno-missing-field-initializers -Wno-unused-variable -Wno-unused-parameter +vold_cflags := -W -Wall -Wno-missing-field-initializers -Wno-unused-variable -Wno-unused-parameter include $(CLEAR_VARS) @@ -54,20 +65,7 @@ LOCAL_CONLYFLAGS := $(vold_conlyflags) LOCAL_SHARED_LIBRARIES := $(common_shared_libraries) LOCAL_STATIC_LIBRARIES := $(common_static_libraries) -LOCAL_REQUIRED_MODULES := $(required_modules) -LOCAL_PROPRIETARY_MODULE := true -include $(BUILD_EXECUTABLE) - -include $(CLEAR_VARS) - -LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk -LOCAL_CLANG := true -LOCAL_SRC_FILES := dvdc.cpp -LOCAL_MODULE := dvdc -LOCAL_SHARED_LIBRARIES := libcutils libbase -LOCAL_CFLAGS := $(vold_cflags) -LOCAL_CONLYFLAGS := $(vold_conlyflags) LOCAL_PROPRIETARY_MODULE := true include $(BUILD_EXECUTABLE) diff --git a/CommandListener.cpp b/CommandListener.cpp deleted file mode 100644 index 18eddfc..0000000 --- a/CommandListener.cpp +++ b/dev/null @@ -1,224 +0,0 @@ -/* - * 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 <stdlib.h> -#include <sys/mount.h> -#include <sys/socket.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <dirent.h> -#include <errno.h> -#include <fcntl.h> -#include <fs_mgr.h> -#include <stdio.h> -#include <string.h> -#include <stdint.h> -#include <inttypes.h> -#include <ctype.h> - -#define LOG_TAG "DroidVoldCmdListener" - -#include <android-base/logging.h> -#include <android-base/stringprintf.h> -#include <cutils/fs.h> -#include <cutils/log.h> - -#include <sysutils/SocketClient.h> -#include <private/android_filesystem_config.h> - -#include "CommandListener.h" -#include "VolumeManager.h" -#include "VolumeBase.h" -#include "ResponseCode.h" -#include "Process.h" - -#define DUMP_ARGS 0 - -CommandListener::CommandListener() : - FrameworkListener("droidvold", true) { - registerCmd(new VolumeCmd()); -#ifdef HAS_VIRTUAL_CDROM - registerCmd(new LoopCmd()); -#endif -} - -#if DUMP_ARGS -void CommandListener::dumpArgs(int argc, char **argv, int argObscure) { - char buffer[4096]; - char *p = buffer; - - memset(buffer, 0, sizeof(buffer)); - int i; - for (i = 0; i < argc; i++) { - unsigned int len = strlen(argv[i]) + 1; // Account for space - if (i == argObscure) { - len += 2; // Account for {} - } - if (((p - buffer) + len) < (long)(sizeof(buffer)-1)) { - if (i == argObscure) { - *p++ = '{'; - *p++ = '}'; - *p++ = ' '; - continue; - } - strcpy(p, argv[i]); - p+= strlen(argv[i]); - if (i != (argc -1)) { - *p++ = ' '; - } - } - } - SLOGD("%s", buffer); -} -#else -void CommandListener::dumpArgs(int /*argc*/, char ** /*argv*/, int /*argObscure*/) { } -#endif - -int CommandListener::sendGenericOkFail(SocketClient *cli, int cond) { - if (!cond) { - return cli->sendMsg(ResponseCode::CommandOkay, "Command succeeded", false); - } else { - return cli->sendMsg(ResponseCode::OperationFailed, "Command failed", false); - } -} - -CommandListener::VolumeCmd::VolumeCmd() : - VoldCommand("volume") { -} - -int CommandListener::VolumeCmd::runCommand(SocketClient *cli, - int argc, char **argv) { - dumpArgs(argc, argv, -1); - - if (argc < 2) { - cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false); - return 0; - } - - VolumeManager *vm = VolumeManager::Instance(); - std::lock_guard<std::mutex> lock(vm->getLock()); - - // TODO: tease out methods not directly related to volumes - - std::string cmd(argv[1]); - if (cmd == "reset") { - return sendGenericOkFail(cli, vm->reset()); - - } else if (cmd == "shutdown") { - return sendGenericOkFail(cli, vm->shutdown()); - - } else if (cmd == "debug") { - return sendGenericOkFail(cli, vm->setDebug(true)); - - } else if (cmd == "mkdirs" && argc > 2) { - // mkdirs [path] - return sendGenericOkFail(cli, vm->mkdirs(argv[2])); - - } else if (cmd == "mount" && argc > 2) { - // mount [volId] [flags] [user] - std::string id(argv[2]); - auto vol = vm->findVolume(id); - if (vol == nullptr) { - return cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown volume", false); - } - - int mountFlags = (argc > 3) ? atoi(argv[3]) : 0; - userid_t mountUserId = (argc > 4) ? atoi(argv[4]) : -1; - - vol->setMountFlags(mountFlags); - vol->setMountUserId(mountUserId); - - int res = vol->mount(); - - return sendGenericOkFail(cli, res); - - } else if (cmd == "unmount" && argc > 2) { - // unmount [volId] - std::string id(argv[2]); - auto vol = vm->findVolume(id); - if (vol == nullptr) { - return cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown volume", false); - } - - return sendGenericOkFail(cli, vol->unmount()); - - } else if (cmd == "format" && argc > 3) { - // format [volId] [fsType|auto] - std::string id(argv[2]); - std::string fsType(argv[3]); - auto vol = vm->findVolume(id); - if (vol == nullptr) { - return cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown volume", false); - } - - return sendGenericOkFail(cli, vol->format(fsType)); - - } - - return cli->sendMsg(ResponseCode::CommandSyntaxError, nullptr, false); -} - -#ifdef HAS_VIRTUAL_CDROM -CommandListener::LoopCmd::LoopCmd() : - VoldCommand("loop") { -} - -int CommandListener::LoopCmd::runCommand(SocketClient *cli, - int argc, char **argv) { - dumpArgs(argc, argv, -1); - if (argc < 2) { - cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false); - return 0; - } - - VolumeManager *vm = VolumeManager::Instance(); - int rc = 0; - if (!strcmp(argv[1], "mount")) { - if (argc != 3) { - cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: loop mount <path>", false); - return 0; - } - rc = vm->mountloop(argv[2]); - } else if (!strcmp(argv[1], "unmount")) { - if (argc < 2 || argc > 3) { - cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: loop unmount [force]", false); - return 0; - } - - bool force = false; - if (argc == 3 && !strcmp(argv[2], "force")) { - force = true; - } - rc = vm->unmountloop(force); - } else { - cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown loop cmd", false); - return 0; - } - - if (!rc) { - cli->sendMsg(ResponseCode::CommandOkay, "loop operation succeeded", false); - } else { - int erno = errno; - rc = ResponseCode::convertFromErrno(); - cli->sendMsg(rc, "loop operation failed", true); - } - - return 0; -} -#endif diff --git a/CommandListener.h b/CommandListener.h deleted file mode 100644 index 437b99c..0000000 --- a/CommandListener.h +++ b/dev/null @@ -1,50 +0,0 @@ -/* - * 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. - */ - -#ifndef _COMMANDLISTENER_H__ -#define _COMMANDLISTENER_H__ - -#include <sysutils/FrameworkListener.h> -#include <utils/Errors.h> -#include "VoldCommand.h" - -class CommandListener : public FrameworkListener { -public: - CommandListener(); - virtual ~CommandListener() {} - -private: - static void dumpArgs(int argc, char **argv, int argObscure); - static int sendGenericOkFail(SocketClient *cli, int cond); - - class VolumeCmd : public VoldCommand { - public: - VolumeCmd(); - virtual ~VolumeCmd() {} - int runCommand(SocketClient *c, int argc, char ** argv); - }; - -#ifdef HAS_VIRTUAL_CDROM - class LoopCmd : public VoldCommand { - public: - LoopCmd(); - virtual ~LoopCmd() {} - int runCommand(SocketClient *c, int argc, char ** argv); - }; -#endif -}; - -#endif @@ -105,21 +105,20 @@ static bool isVirtioBlkDevice(unsigned int major) { } Disk::Disk(const std::string& eventPath, dev_t device, - const std::string& nickname, int flags) : + const std::string& nickname, const std::string& eventName, int flags): mDevice(device), mSize(-1), mNickname(nickname), mFlags(flags), mCreated( false), mJustPartitioned(false) { mId = StringPrintf("disk:%u,%u", major(device), minor(device)); mEventPath = eventPath; + mDevName = eventName; mSysPath = StringPrintf("/sys/%s", eventPath.c_str()); - mDevPath = StringPrintf("/dev/block/droidvold/%s", mId.c_str()); + mDevPath = StringPrintf("/dev/block/%s", mDevName.c_str()); mSrdisk = (!strncmp(nickname.c_str(), "sr", 2)) ? true : false; - CreateDeviceNode(mDevPath, mDevice); } Disk::~Disk() { CHECK(!mCreated); - DestroyDeviceNode(mDevPath); } std::shared_ptr<VolumeBase> Disk::findVolume(const std::string& id) { @@ -148,11 +147,56 @@ status_t Disk::create() { CHECK(!mCreated); mCreated = true; notifyEvent(ResponseCode::DiskCreated, StringPrintf("%d", mFlags)); + // do nothing when srdisk is created - if (!mSrdisk) { - readMetadata(); - readPartitions(); + if (mSrdisk) + return OK; + + readDiskMetadata(); + // sleep 10ms + usleep(10000); + + std::string fsType; + std::string unused; + + // if no partition, handle here + if (ReadPartMetadata(mDevPath, fsType, unused, unused) == OK) { + if (!fsType.empty()) { + if (VolumeManager::Instance()->getDebug()) + LOG(DEBUG) << "treat entire disk as partition, devPath=" << mDevPath; + createPublicVolume(mDevName, true, 0); + } + } + + return OK; +} + +status_t Disk::reset() { + CHECK(!mCreated); + mCreated = true; + notifyEvent(ResponseCode::DiskCreated, StringPrintf("%d", mFlags)); + + // do nothing when srdisk is created + if (mSrdisk) + return OK; + + readDiskMetadata(); + + if (mPartNo.size() == 0) { + createPublicVolume(mDevName, true, 0); + } else { + std::string partDevName; + for (auto part : mPartNo) { + if (mFlags & Flags::kUsb) + partDevName = StringPrintf("%s%d", mDevName.c_str(), part); + else if (mFlags & Flags::kSd) + partDevName = StringPrintf("%sp%d", mDevName.c_str(), part); + + createPublicVolume(partDevName, false, part); + } } + + return OK; } @@ -166,7 +210,7 @@ status_t Disk::destroy() { void Disk::handleJustPublicPhysicalDevice( const std::string& physicalDevName) { - auto vol = std::shared_ptr<VolumeBase>(new PublicVolume(physicalDevName)); + auto vol = std::shared_ptr<VolumeBase>(new PublicVolume(physicalDevName, true)); if (mJustPartitioned) { LOG(DEBUG) << "Device just partitioned; silently formatting"; vol->setSilent(true); @@ -183,8 +227,9 @@ void Disk::handleJustPublicPhysicalDevice( //vol->mount(); } -void Disk::createPublicVolume(dev_t device) { - auto vol = std::shared_ptr<VolumeBase>(new PublicVolume(device)); +void Disk::createPublicVolume(const std::string& partDevName, + const bool isPhysical, int part) { + auto vol = std::shared_ptr<VolumeBase>(new PublicVolume(partDevName, isPhysical)); if (mJustPartitioned) { LOG(DEBUG) << "Device just partitioned; silently formatting"; vol->setSilent(true); @@ -197,6 +242,9 @@ void Disk::createPublicVolume(dev_t device) { mVolumes.push_back(vol); vol->setDiskId(getId()); vol->setSysPath(getSysPath()); + vol->setDiskFlags(mFlags); + vol->setPartNo(part); + vol->create(); //vol->mount(); } @@ -208,7 +256,7 @@ void Disk::destroyAllVolumes() { mVolumes.clear(); } -status_t Disk::readMetadata() { +status_t Disk::readDiskMetadata() { mSize = -1; mLabel.clear(); @@ -273,11 +321,60 @@ status_t Disk::readMetadata() { return OK; } +void Disk::handleBlockEvent(NetlinkEvent *evt) { + std::string eventPath(evt->findParam("DEVPATH")?evt->findParam("DEVPATH"):""); + std::string devName(evt->findParam("DEVNAME")?evt->findParam("DEVNAME"):""); + std::string devType(evt->findParam("DEVTYPE")?evt->findParam("DEVTYPE"):""); + + // can we handle this event + if (eventPath.find(mEventPath) == std::string::npos) { + LOG(DEBUG) << "evt will handle by other disk " << mEventPath; + return; + } + + if (devType != "partition") { + LOG(DEBUG) << "evt type is not partition " << devType; + evt->dump(); + return; + } + + std::string partDevName; + switch (evt->getAction()) { + case NetlinkEvent::Action::kAdd: { + int part = atoi(evt->findParam("PARTN")); + + mPartNo.push_back(part); + if (mFlags & Flags::kUsb) + partDevName = StringPrintf("%s%d", mDevName.c_str(), part); + else if (mFlags & Flags::kSd) + partDevName = StringPrintf("%sp%d", mDevName.c_str(), part); + + LOG(INFO) << " partDevName =" << partDevName; + createPublicVolume(partDevName, false, part); + break; + } + case NetlinkEvent::Action::kChange: { + // ignore + LOG(DEBUG) << "Disk at " << mDevPath << " changed"; + break; + } + case NetlinkEvent::Action::kRemove: { + // will handle by vm + break; + } + default: { + LOG(WARNING) << "Unexpected block event action " << (int) evt->getAction(); + break; + } + } +} + +#if 0 status_t Disk::readPartitions() { if (mSrdisk) { // srdisk has no partiton concept. LOG(INFO) << "srdisk try entire disk as fake partition"; - createPublicVolume(mDevice); + //createPublicVolume(mDevice); return OK; } @@ -306,7 +403,7 @@ status_t Disk::readPartitions() { Table table = Table::kUnknown; bool foundParts = false; - std::string physicalDevName; + std::string physicalDevName, partDevName; for (auto line : output) { char* cline = (char*) line.c_str(); char* token = strtok(cline, kSgdiskToken); @@ -329,6 +426,12 @@ status_t Disk::readPartitions() { } dev_t partDevice = makedev(major(mDevice), minor(mDevice) + i); + if (mFlags & Flags::kUsb) + partDevName = StringPrintf("%s%d", mDevName.c_str(), i); + else if (mFlags & Flags::kSd) + partDevName = StringPrintf("%sp%d", mDevName.c_str(), i); + LOG(INFO) << " partDevName =" << partDevName; + if (table == Table::kMbr) { const char* type = strtok(nullptr, kSgdiskToken); @@ -349,14 +452,14 @@ status_t Disk::readPartitions() { case 0x0e: // W95 FAT16 (LBA) case 0x07: // NTFS & EXFAT - createPublicVolume(partDevice); + createPublicVolume(partDevName, false); break; default: // We should still create public volume here // cause some disk table types are not matched above // but can be mounted successfully - createPublicVolume(partDevice); + createPublicVolume(partDevName, false); LOG(WARNING) << "unsupported table kMbr type " << type; break; } @@ -365,7 +468,7 @@ status_t Disk::readPartitions() { const char* partGuid = strtok(nullptr, kSgdiskToken); if (!strcasecmp(typeGuid, kGptBasicData)) { - createPublicVolume(partDevice); + createPublicVolume(partDevName, false); } } } @@ -377,11 +480,11 @@ status_t Disk::readPartitions() { std::string fsType; std::string unused; - if (ReadMetadataUntrusted(mDevPath, fsType, unused, unused) == OK) { + if (ReadPartMetadata(mDevPath, fsType, unused, unused) == OK) { if (IsJustPhysicalDevice(mSysPath, physicalDevName)) { handleJustPublicPhysicalDevice(physicalDevName); } else { - createPublicVolume(mDevice); + createPublicVolume(partDevName, false); } } else { LOG(WARNING) << mId << " failed to identify, giving up"; @@ -392,6 +495,7 @@ status_t Disk::readPartitions() { mJustPartitioned = false; return OK; } +#endif status_t Disk::unmountAll() { for (auto vol : mVolumes) { @@ -402,12 +506,12 @@ status_t Disk::unmountAll() { void Disk::notifyEvent(int event) { VolumeManager::Instance()->getBroadcaster()->sendBroadcast(event, - getId().c_str(), false); + getId()); } void Disk::notifyEvent(int event, const std::string& value) { VolumeManager::Instance()->getBroadcaster()->sendBroadcast(event, - StringPrintf("%s %s", getId().c_str(), value.c_str()).c_str(), false); + StringPrintf("%s %s", getId().c_str(), value.c_str())); } @@ -21,6 +21,7 @@ #include "VolumeBase.h" #include <utils/Errors.h> +#include <sysutils/NetlinkEvent.h> #include <vector> @@ -37,7 +38,8 @@ class VolumeBase; */ class Disk { public: - Disk(const std::string& eventPath, dev_t device, const std::string& nickname, int flags); + Disk(const std::string& eventPath, dev_t device, const std::string& nickname, + const std::string& eventName, int flags); virtual ~Disk(); enum Flags { @@ -70,7 +72,7 @@ public: status_t create(); status_t destroy(); - status_t readMetadata(); + status_t readDiskMetadata(); status_t readPartitions(); status_t unmountAll(); @@ -80,6 +82,9 @@ public: void notifyEvent(int msg, const std::string& value); void destroyAllVolumes(); + void handleBlockEvent(NetlinkEvent *evt); + status_t reset(); + private: /* ID that uniquely references this disk */ std::string mId; @@ -89,6 +94,8 @@ private: std::string mSysPath; /* Device path under dev */ std::string mDevPath; + + std::string mDevName; /* Kernel device representing disk */ dev_t mDevice; /* Size of disk, in bytes */ @@ -108,7 +115,10 @@ private: /* Flag indicating is srdisk or not */ bool mSrdisk; - void createPublicVolume(dev_t device); + std::vector<int> mPartNo; + + void createPublicVolume(const std::string& partDevName, + const bool isPhysical, int part); void createPrivateVolume(dev_t device, const std::string& partGuid); void handleJustPublicPhysicalDevice(const std::string& physicalDevName); void getPhysicalDev(dev_t &device, const std:: string& sysPath, int part); diff --git a/DroidVold.cpp b/DroidVold.cpp new file mode 100644 index 0000000..e64ff0c --- a/dev/null +++ b/DroidVold.cpp @@ -0,0 +1,166 @@ +/* + * 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 "DroidVold.h" + +#define LOG_TAG "DroidVold" + +#include <android-base/logging.h> +#include <android-base/stringprintf.h> +#include <cutils/fs.h> +#include <cutils/log.h> + +#include "VolumeManager.h" + +namespace vendor { +namespace amlogic { +namespace hardware { +namespace droidvold { +namespace V1_0 { +namespace implementation { + +DroidVold *sInstance; + +DroidVold *DroidVold::Instance() { + if (!sInstance) + sInstance = new DroidVold(); + return sInstance; +} + +DroidVold::DroidVold() { + mCallback = NULL; +} + +DroidVold::~DroidVold() { +} + +Return<void> DroidVold::setCallback(const sp<IDroidVoldCallback>& callback) { + if (VolumeManager::Instance()->getDebug()) + LOG(DEBUG) << "setCallback =" << callback.get(); + + /* + if (callback != NULL) { + mClients.push_back(callback); + } + */ + + mCallback = callback; + return Void(); +} + +Return<Result> DroidVold::reset() { + VolumeManager *vm = VolumeManager::Instance(); + vm->reset(); + return Result::OK; +} + +Return<Result> DroidVold::shutdown() { + VolumeManager *vm = VolumeManager::Instance(); + vm->shutdown(); + return Result::OK; +} + +Return<Result> DroidVold::mount(const hidl_string& id, uint32_t flag, uint32_t uid) { + // mount [volId] [flags] + if (VolumeManager::Instance()->getDebug()) + LOG(DEBUG) << "mount id=" << id << " flag=" << flag; + + VolumeManager *vm = VolumeManager::Instance(); + std::string vid = id; + auto vol = vm->findVolume(vid); + if (vol == nullptr) { + LOG(ERROR) << "mount ,count not find volume id=" << vid; + return Result::FAIL; + } + + vol->setMountFlags(flag); + vol->setMountUserId(uid); + + int res = vol->mount(); + if (res != 0) { + LOG(ERROR) << "failed to mount volume=" << vol; + return Result::FAIL; + } + + return Result::OK; +} + +Return<Result> DroidVold::unmount(const hidl_string& id) { + // unmount [volId] + VolumeManager *vm = VolumeManager::Instance(); + std::string vid = id; + auto vol = vm->findVolume(vid); + if (vol == nullptr) { + LOG(ERROR) << "unmount, count not find volume id=" << vid; + return Result::FAIL; + } + + int res = vol->unmount(); + + if (res != 0) { + LOG(ERROR) << "failed to unmount volume=" << vol; + return Result::FAIL; + } + + return Result::OK; +} + +Return<Result> DroidVold::format(const hidl_string& id, const hidl_string& type) { + // format [volId] [fsType|auto] + VolumeManager *vm = VolumeManager::Instance(); + std::string vid = id; + std::string fsType= type; + auto vol = vm->findVolume(id); + + if (vol == nullptr) { + LOG(ERROR) << "format, count not find volume id=" << vid; + return Result::FAIL; + } + + int res = vol->format(fsType); + + if (res != 0) { + LOG(ERROR) << "failed to unmount volume=" << vol; + return Result::FAIL; + } + + return Result::OK; +} + +void DroidVold::sendBroadcast(int event, const std::string& message) { + if (VolumeManager::Instance()->getDebug()) + LOG(DEBUG) << "event=" << event << " message=" << message; + + hidl_string mss = message; + if (mCallback != NULL) + mCallback->onEvent(event, mss); + + /* + for (int i = 0; i < clientSize; i++) { + mClients[i]->onEvent(event, mss); + } + for (auto client : mClients) { + client->onEvent(event, mss); + } + */ +} + +} // namespace implementation +} // namespace V1_0 +} // namespace droidvold +} // namespace hardware +} // namespace amlogic +} // namespace vendor diff --git a/DroidVold.h b/DroidVold.h new file mode 100644 index 0000000..346742f --- a/dev/null +++ b/DroidVold.h @@ -0,0 +1,76 @@ +/* + * 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. + */ + +#ifndef VENDOR_AMLOGIC_HARDWARE_DROIDVOLD_V1_0_DROIDVOLD_H +#define VENDOR_AMLOGIC_HARDWARE_DROIDVOLD_V1_0_DROIDVOLD_H + +#include <vendor/amlogic/hardware/droidvold/1.0/IDroidVold.h> +#include <hidl/MQDescriptor.h> +#include <hidl/Status.h> + +#include <utils/Mutex.h> +#include <vector> + +namespace vendor { +namespace amlogic { +namespace hardware { +namespace droidvold { +namespace V1_0 { +namespace implementation { + +using ::android::hidl::base::V1_0::DebugInfo; +using ::android::hidl::base::V1_0::IBase; +using ::vendor::amlogic::hardware::droidvold::V1_0::IDroidVold; +using ::vendor::amlogic::hardware::droidvold::V1_0::IDroidVoldCallback; +using ::vendor::amlogic::hardware::droidvold::V1_0::Result; +using ::android::hardware::hidl_array; +using ::android::hardware::hidl_memory; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::sp; + +class DroidVold : public IDroidVold { +public: + DroidVold(); + virtual ~DroidVold(); + + // Methods from ::vendor::amlogic::hardware::droidvold::V1_0::IDroidVold follow. + Return<void> setCallback(const sp<IDroidVoldCallback>& callback) override; + Return<Result> reset() override; + Return<Result> shutdown() override; + Return<Result> mount(const hidl_string& id, uint32_t flag, uint32_t uid) override; + Return<Result> unmount(const hidl_string& id) override; + Return<Result> format(const hidl_string& id, const hidl_string& type) override; + + static DroidVold *Instance(); + void sendBroadcast(int event, const std::string& message); + +private: + //std::vector<sp<IDroidVoldCallback>> mClients; + sp<IDroidVoldCallback> mCallback; + mutable android::Mutex mLock; +}; + +} // namespace implementation +} // namespace V1_0 +} // namespace droidvold +} // namespace hardware +} // namespace amlogic +} // namespace vendor + +#endif // VENDOR_AMLOGIC_HARDWARE_DROIDVOLD_V1_0_DROIDVOLD_H diff --git a/NetlinkManager.h b/NetlinkManager.h index 9c7ba11..f123fa0 100644 --- a/NetlinkManager.h +++ b/NetlinkManager.h @@ -19,6 +19,10 @@ #include <sysutils/SocketListener.h> #include <sysutils/NetlinkListener.h> +#include "DroidVold.h" + +using namespace android; +using ::vendor::amlogic::hardware::droidvold::V1_0::implementation::DroidVold; class NetlinkHandler; @@ -27,7 +31,7 @@ private: static NetlinkManager *sInstance; private: - SocketListener *mBroadcaster; + DroidVold *mBroadcaster; NetlinkHandler *mHandler; int mSock; @@ -37,8 +41,8 @@ public: int start(); int stop(); - void setBroadcaster(SocketListener *sl) { mBroadcaster = sl; } - SocketListener *getBroadcaster() { return mBroadcaster; } + void setBroadcaster(DroidVold *sl) { mBroadcaster = sl; } + DroidVold *getBroadcaster() { return mBroadcaster; } static NetlinkManager *Instance(); diff --git a/PublicVolume.cpp b/PublicVolume.cpp index 663c351..3e24663 100644 --- a/PublicVolume.cpp +++ b/PublicVolume.cpp @@ -42,19 +42,10 @@ using android::base::StringPrintf; namespace android { namespace droidvold { -static const char* kFusePath = "/system/bin/sdcard"; - static const char* kChownPath = "/system/bin/chown"; -PublicVolume::PublicVolume(dev_t device) : - VolumeBase(Type::kPublic), mDevice(device), mFusePid(0), mJustPhysicalDev(false) { - setId(StringPrintf("public:%u,%u", major(device), minor(device))); - mDevPath = StringPrintf("/dev/block/droidvold/%s", getId().c_str()); - mSrMounted = false; -} - -PublicVolume::PublicVolume(const std::string& physicalDevName) : - VolumeBase(Type::kPublic), mFusePid(0), mJustPhysicalDev(true) { +PublicVolume::PublicVolume(const std::string& physicalDevName, const bool isPhysical) : + VolumeBase(Type::kPublic), mFusePid(0), mJustPhysicalDev(isPhysical) { setId(physicalDevName); mDevPath = StringPrintf("/dev/block/%s", getId().c_str()); } @@ -63,8 +54,13 @@ PublicVolume::~PublicVolume() { } status_t PublicVolume::readMetadata() { - status_t res = ReadMetadataUntrusted(mDevPath, mFsType, mFsUuid, mFsLabel); + status_t res = ReadPartMetadata(mDevPath, mFsType, mFsUuid, mFsLabel); + + if (VolumeManager::Instance()->getDebug()) + LOG(DEBUG) << "blkid get devPath=" << mDevPath << " fsType= " << mFsType; + notifyEvent(ResponseCode::VolumeFsTypeChanged, mFsType); + // TODO: find the Uuid of srdisk // If mFsUuid of publicVolume is empty, // it will cause systemUi crash when it is mounted @@ -77,17 +73,16 @@ status_t PublicVolume::readMetadata() { notifyEvent(ResponseCode::VolumeFsUuidChanged, mFsUuid); notifyEvent(ResponseCode::VolumeFsLabelChanged, mFsLabel); - return res; + + return OK; } status_t PublicVolume::doCreate() { - if (mJustPhysicalDev) return 0; - return CreateDeviceNode(mDevPath, mDevice); + return 0; } status_t PublicVolume::doDestroy() { - if (mJustPhysicalDev) return 0; - return DestroyDeviceNode(mDevPath); + return 0; } status_t PublicVolume::doMount() { @@ -105,11 +100,6 @@ status_t PublicVolume::doMount() { return -EIO; } - if (!mJustPhysicalDev && mFsType == "vfat") { - LOG(DEBUG) << getId() << " vfat will handle by vold"; - return 0; - } - // Use UUID as stable name, if available std::string stableName = getId(); if (!mFsUuid.empty()) { @@ -118,36 +108,20 @@ status_t PublicVolume::doMount() { mRawPath = StringPrintf("/mnt/media_rw/%s", stableName.c_str()); VolumeManager *vm = VolumeManager::Instance(); - if (vm->isMountpointMounted(mRawPath.c_str())) { - LOG(ERROR) << " path:" << mRawPath << " is already mounted"; - return -EIO; - } - - // Check filesystems - status_t checkStatus = -1; + //if (!mJustPhysicalDev && mFsType == "vfat") { if (mFsType == "vfat") { - checkStatus = vfat::Check(mDevPath); - } else if (mFsType == "ntfs") { - checkStatus = ntfs::Check(mDevPath.c_str()); - } else if (mFsType == "exfat") { - checkStatus = exfat::Check(mDevPath.c_str()); - } else if (!strncmp(mFsType.c_str(), "ext", 3)) { - // ext2/3/4 check later - checkStatus = 0; - } else if (mFsType == "hfs") { - checkStatus = hfsplus::Check(mDevPath.c_str()); - } else if (mFsType == "iso9660" || mFsType == "udf") { - // iso needn't check - checkStatus = iso9660::Check(mDevPath.c_str()); + sleep(2); + if (vm->isMountpointMounted(mRawPath.c_str())) { + LOG(DEBUG) << getId() << " vfat will handle by vold"; + return 0; + } } - - if (checkStatus) { - LOG(ERROR) << getId() << " failed to check filesystem " << mFsType; + if (vm->isMountpointMounted(mRawPath.c_str())) { + LOG(ERROR) << " path:" << mRawPath << " is already mounted"; return -EIO; } - setInternalPath(mRawPath); setPath(mRawPath); @@ -158,34 +132,18 @@ status_t PublicVolume::doMount() { // Mount device status_t mountStatus = -1; - std::string logicPartDevPath = mDevPath; - if (!mJustPhysicalDev && - (mFsType == "ntfs" || mFsType == "exfat")) { - if (GetLogicalPartitionDevice(mDevice, getSysPath(), logicPartDevPath) != OK) { - LOG(ERROR) << "failed to get logical partition device for fstype " << mFsType; - return -errno; - } - } if (mFsType == "vfat") { mountStatus = vfat::Mount(mDevPath, mRawPath, false, false, false, AID_MEDIA_RW, AID_MEDIA_RW, 0007, true); } else if (mFsType == "ntfs") { - mountStatus = ntfs::Mount(logicPartDevPath.c_str(), mRawPath.c_str(), false, false, + mountStatus = ntfs::Mount(mDevPath.c_str(), mRawPath.c_str(), false, false, AID_MEDIA_RW, AID_MEDIA_RW, 0007, true); } else if (mFsType == "exfat") { - mountStatus = exfat::Mount(logicPartDevPath.c_str(), mRawPath.c_str(), false, false, + mountStatus = exfat::Mount(mDevPath.c_str(), mRawPath.c_str(), false, false, AID_MEDIA_RW, AID_MEDIA_RW, 0007, true); } else if (!strncmp(mFsType.c_str(), "ext", 3)) { - int res = ext4::Check(logicPartDevPath, mRawPath); - if (res == 0 || res == 1) { - LOG(DEBUG) << getId() << " passed filesystem check"; - } else { - PLOG(ERROR) << getId() << " failed filesystem check"; - // return -EIO; - } - - mountStatus = ext4::Mount(logicPartDevPath, mRawPath, false, false, true, mFsType); + mountStatus = ext4::Mount(mDevPath, mRawPath, false, false, true, mFsType); } else if (mFsType == "hfs") { mountStatus = hfsplus::Mount(mDevPath.c_str(), mRawPath.c_str(), false, false, AID_MEDIA_RW, AID_MEDIA_RW, 0007, true); diff --git a/PublicVolume.h b/PublicVolume.h index 6d3f7f5..787776c 100644 --- a/PublicVolume.h +++ b/PublicVolume.h @@ -39,8 +39,7 @@ namespace droidvold { */ class PublicVolume : public VolumeBase { public: - explicit PublicVolume(dev_t device); - explicit PublicVolume(const std::string& physicalDevName); + explicit PublicVolume(const std::string& physicalDevName, const bool isPhysical); virtual ~PublicVolume(); protected: @@ -14,7 +14,6 @@ * limitations under the License. */ -#include "sehandle.h" #include "Utils.h" #include "Process.h" @@ -32,11 +31,19 @@ #include <linux/fs.h> #include <stdlib.h> #include <sys/mount.h> -#include <sys/types.h> +//#include <sys/types.h> #include <sys/stat.h> #include <sys/wait.h> #include <sys/statvfs.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> + + +#include "ext2fs/ext2fs.h" +#include "blkid/blkid.h" + #ifndef UMOUNT_NOFOLLOW #define UMOUNT_NOFOLLOW 0x00000008 /* Don't follow symlink on umount */ #endif @@ -47,75 +54,17 @@ using android::base::StringPrintf; namespace android { namespace droidvold { -security_context_t sBlkidContext = nullptr; security_context_t sBlkidUntrustedContext = nullptr; -security_context_t sFsckContext = nullptr; -security_context_t sFsckUntrustedContext = nullptr; static const char* kBlkidPath = "/system/bin/blkid"; static const char* kKeyPath = "/data/misc/vold"; static const char* kProcFilesystems = "/proc/filesystems"; -status_t CreateDeviceNode(const std::string& path, dev_t dev) { - const char* cpath = path.c_str(); - status_t res = 0; - - char* secontext = nullptr; - if (sehandle) { - if (!selabel_lookup(sehandle, &secontext, cpath, S_IFBLK)) { - setfscreatecon(secontext); - } - } - - if (access(cpath, F_OK) == 0) { - LOG(DEBUG) << "path: " << path << " already exist"; - return res; - } - - mode_t mode = 0660 | S_IFBLK; - if (mknod(cpath, mode, dev) < 0) { - if (errno != EEXIST) { - PLOG(ERROR) << "Failed to create device node for " << major(dev) - << ":" << minor(dev) << " at " << path; - res = -errno; - } - } - - if (secontext) { - setfscreatecon(nullptr); - freecon(secontext); - } - - return res; -} - -status_t DestroyDeviceNode(const std::string& path) { - const char* cpath = path.c_str(); - if (TEMP_FAILURE_RETRY(unlink(cpath))) { - return -errno; - } else { - return OK; - } -} - status_t PrepareDir(const std::string& path, mode_t mode, uid_t uid, gid_t gid) { const char* cpath = path.c_str(); - - char* secontext = nullptr; - if (sehandle) { - if (!selabel_lookup(sehandle, &secontext, cpath, S_IFDIR)) { - setfscreatecon(secontext); - } - } - int res = fs_prepare_dir(cpath, mode, uid, gid); - if (secontext) { - setfscreatecon(nullptr); - freecon(secontext); - } - if (res == 0) { return OK; } else { @@ -187,63 +136,40 @@ status_t BindMount(const std::string& source, const std::string& target) { return OK; } -static status_t readMetadata(const std::string& path, std::string& fsType, - std::string& fsUuid, std::string& fsLabel, bool untrusted) { - fsType.clear(); - fsUuid.clear(); - fsLabel.clear(); - - std::vector<std::string> cmd; - cmd.push_back(kBlkidPath); - cmd.push_back("-c"); - cmd.push_back("/dev/null"); - cmd.push_back("-s"); - cmd.push_back("TYPE"); - cmd.push_back("-s"); - cmd.push_back("UUID"); - cmd.push_back("-s"); - cmd.push_back("LABEL"); - cmd.push_back(path); - - std::vector<std::string> output; - status_t res = ForkExecvp(cmd, output, untrusted ? sBlkidUntrustedContext : sBlkidContext); - if (res != OK) { - LOG(WARNING) << "blkid failed to identify " << path; - return res; - } - - char value[128]; - for (auto line : output) { - // Extract values from blkid output, if defined - const char* cline = line.c_str(); - const char* start = strstr(cline, "TYPE="); - if (start != nullptr && sscanf(start + 5, "\"%127[^\"]\"", value) == 1) { - fsType = value; - } - - start = strstr(cline, "UUID="); - if (start != nullptr && sscanf(start + 5, "\"%127[^\"]\"", value) == 1) { - fsUuid = value; - } - - start = strstr(cline, "LABEL="); - if (start != nullptr && sscanf(start + 6, "\"%127[^\"]\"", value) == 1) { - fsLabel = value; +status_t ReadPartMetadata(const std::string& path, std::string& fsType, + std::string& fsUuid, std::string& fsLabel) { + blkid_cache cache = NULL; + const char *devices = path.c_str(); + + if (blkid_get_cache(&cache, "/dev/null") < 0) { + PLOG(ERROR) << "blkid get cache failed path=" << path; + blkid_put_cache(cache); + return -errno; + } + + blkid_dev dev = blkid_get_dev(cache, devices, BLKID_DEV_NORMAL); + if (dev) { + blkid_tag_iterate iter; + const char *type, *value; + + iter = blkid_tag_iterate_begin(dev); + while (blkid_tag_next(iter, &type, &value) == 0) { + LOG(DEBUG) << "type=" << type << " value=" << value; + + if (!strcmp(type, "TYPE")) { + fsType = StringPrintf("%s", value); + } else if (!strcmp(type, "UUID")) { + fsUuid = StringPrintf("%s", value); + } else if (!strcmp(type, "LABEL")) { + fsLabel = StringPrintf("%s", value); + } } + blkid_tag_iterate_end(iter); } return OK; } -status_t ReadMetadata(const std::string& path, std::string& fsType, - std::string& fsUuid, std::string& fsLabel) { - return readMetadata(path, fsType, fsUuid, fsLabel, false); -} - -status_t ReadMetadataUntrusted(const std::string& path, std::string& fsType, - std::string& fsUuid, std::string& fsLabel) { - return readMetadata(path, fsType, fsUuid, fsLabel, true); -} status_t ForkExecvp(const std::vector<std::string>& args) { return ForkExecvp(args, nullptr); @@ -43,9 +43,6 @@ extern security_context_t sBlkidUntrustedContext; extern security_context_t sFsckContext; extern security_context_t sFsckUntrustedContext; -status_t CreateDeviceNode(const std::string& path, dev_t dev); -status_t DestroyDeviceNode(const std::string& path); - /* fs_prepare_dir wrapper that creates with SELinux context */ status_t PrepareDir(const std::string& path, mode_t mode, uid_t uid, gid_t gid); @@ -58,12 +55,8 @@ status_t KillProcessesUsingPath(const std::string& path); /* Creates bind mount from source to target */ status_t BindMount(const std::string& source, const std::string& target); -/* Reads filesystem metadata from device at path */ -status_t ReadMetadata(const std::string& path, std::string& fsType, - std::string& fsUuid, std::string& fsLabel); - /* Reads filesystem metadata from untrusted device at path */ -status_t ReadMetadataUntrusted(const std::string& path, std::string& fsType, +status_t ReadPartMetadata(const std::string& path, std::string& fsType, std::string& fsUuid, std::string& fsLabel); /* Returns either WEXITSTATUS() status, or a negative errno */ diff --git a/VoldCommand.cpp b/VoldCommand.cpp deleted file mode 100644 index 3c0d58d..0000000 --- a/VoldCommand.cpp +++ b/dev/null @@ -1,21 +0,0 @@ -/* - * 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 "VoldCommand.h" - -VoldCommand::VoldCommand(const char *cmd) : - FrameworkCommand(cmd) { -} diff --git a/VoldCommand.h b/VoldCommand.h deleted file mode 100644 index 5ddc666..0000000 --- a/VoldCommand.h +++ b/dev/null @@ -1,28 +0,0 @@ -/* - * 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. - */ - -#ifndef _VOLD_COMMAND_H -#define _VOLD_COMMAND_H - -#include <sysutils/FrameworkCommand.h> - -class VoldCommand : public FrameworkCommand { -public: - VoldCommand(const char *cmd); - virtual ~VoldCommand() {} -}; - -#endif diff --git a/VolumeBase.cpp b/VolumeBase.cpp index 2bcef32..e2e53b9 100644 --- a/VolumeBase.cpp +++ b/VolumeBase.cpp @@ -35,7 +35,7 @@ namespace droidvold { VolumeBase::VolumeBase(Type type) : mType(type), mMountFlags(0), mMountUserId(-1), mCreated(false), mState( - State::kUnmounted), mSilent(false) { + State::kUnmounted), mSilent(false), mDiskFlags(0), mPartNo(0) { } VolumeBase::~VolumeBase() { @@ -77,6 +77,26 @@ status_t VolumeBase::setMountFlags(int mountFlags) { return OK; } +status_t VolumeBase::setDiskFlags(int diskFlags) { + if (mCreated) { + LOG(WARNING) << getId() << " Diskflags change requires destroyed"; + return -EBUSY; + } + + mDiskFlags = diskFlags; + return OK; +} + +status_t VolumeBase::setPartNo(int part) { + if (mCreated) { + LOG(WARNING) << getId() << " partNo change requires destroyed"; + return -EBUSY; + } + + mPartNo = part; + return OK; +} + status_t VolumeBase::setMountUserId(userid_t mountUserId) { if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) { LOG(WARNING) << getId() << " user change requires state unmounted or unmountable"; @@ -132,13 +152,13 @@ status_t VolumeBase::setInternalPath(const std::string& internalPath) { void VolumeBase::notifyEvent(int event) { if (mSilent) return; VolumeManager::Instance()->getBroadcaster()->sendBroadcast(event, - getId().c_str(), false); + getId()); } void VolumeBase::notifyEvent(int event, const std::string& value) { if (mSilent) return; VolumeManager::Instance()->getBroadcaster()->sendBroadcast(event, - StringPrintf("%s %s", getId().c_str(), value.c_str()).c_str(), false); + StringPrintf("%s %s", getId().c_str(), value.c_str())); } diff --git a/VolumeBase.h b/VolumeBase.h index 8438396..28a2cfe 100644 --- a/VolumeBase.h +++ b/VolumeBase.h @@ -84,6 +84,8 @@ public: const std::string& getPath() { return mPath; } const std::string& getSysPath() { return mSysPath; } const std::string& getInternalPath() { return mInternalPath; } + int getDiskFlags() { return mDiskFlags; } + int getPartNo() { return mPartNo; } status_t setDiskId(const std::string& diskId); status_t setPartGuid(const std::string& partGuid); @@ -91,6 +93,8 @@ public: status_t setMountUserId(userid_t mountUserId); status_t setSilent(bool silent); void setSysPath(const std::string& sysPath) { mSysPath = sysPath; } + status_t setDiskFlags(int diskFlags); + status_t setPartNo(int part); void addVolume(const std::shared_ptr<VolumeBase>& volume); void removeVolume(const std::shared_ptr<VolumeBase>& volume); @@ -144,6 +148,8 @@ private: std::string mInternalPath; /* Flag indicating that volume should emit no events */ bool mSilent; + int mDiskFlags; + int mPartNo; /* Volumes stacked on top of this volume */ std::list<std::shared_ptr<VolumeBase>> mVolumes; diff --git a/VolumeManager.cpp b/VolumeManager.cpp index fc9da65..bc1c80f 100644 --- a/VolumeManager.cpp +++ b/VolumeManager.cpp @@ -44,6 +44,8 @@ #include "VolumeManager.h" #include "NetlinkManager.h" +#include "DroidVold.h" + #include "fs/Ext4.h" #include "fs/Vfat.h" #include "Utils.h" @@ -106,74 +108,83 @@ void VolumeManager::handleBlockEvent(NetlinkEvent *evt) { evt->dump(); } - std::string eventPath(evt->findParam("DEVPATH")?evt->findParam("DEVPATH"):""); std::string devType(evt->findParam("DEVTYPE")?evt->findParam("DEVTYPE"):""); - if (devType != "disk") return; - - int major = atoi(evt->findParam("MAJOR")); - int minor = atoi(evt->findParam("MINOR")); - dev_t device = makedev(major, minor); - - switch (evt->getAction()) { - case NetlinkEvent::Action::kAdd: { - for (auto source : mDiskSources) { - if (source->matches(eventPath)) { - // For now, assume that MMC and virtio-blk (the latter is - // emulator-specific; see Disk.cpp for details) devices are SD, - // and that everything else is USB - int flags = source->getFlags(); - if (major == kMajorBlockMmc - || (android::droidvold::IsRunningInEmulator() - && major >= (int) kMajorBlockExperimentalMin - && major <= (int) kMajorBlockExperimentalMax)) { - flags |= android::droidvold::Disk::Flags::kSd; - } else { - flags |= android::droidvold::Disk::Flags::kUsb; - } - auto disk = new android::droidvold::Disk(eventPath, device, - source->getNickname(), flags); - disk->create(); - mDisks.push_back(std::shared_ptr<android::droidvold::Disk>(disk)); - break; + if (devType == "disk") { + std::string eventPath(evt->findParam("DEVPATH")?evt->findParam("DEVPATH"):""); + std::string devName(evt->findParam("DEVNAME")?evt->findParam("DEVNAME"):""); + + int major = atoi(evt->findParam("MAJOR")); + int minor = atoi(evt->findParam("MINOR")); + dev_t device = makedev(major, minor); + + switch (evt->getAction()) { + case NetlinkEvent::Action::kAdd: { + for (auto source : mDiskSources) { + if (source->matches(eventPath)) { + // For now, assume that MMC and virtio-blk (the latter is + // emulator-specific; see Disk.cpp for details) devices are SD, + // and that everything else is USB + int flags = source->getFlags(); + if (major == kMajorBlockMmc + || (android::droidvold::IsRunningInEmulator() + && major >= (int) kMajorBlockExperimentalMin + && major <= (int) kMajorBlockExperimentalMax)) { + flags |= android::droidvold::Disk::Flags::kSd; + } else { + flags |= android::droidvold::Disk::Flags::kUsb; + } + + auto disk = new android::droidvold::Disk(eventPath, device, + source->getNickname(), devName, flags); + disk->create(); + mDisks.push_back(std::shared_ptr<android::droidvold::Disk>(disk)); + break; + } } + break; } - break; - } - case NetlinkEvent::Action::kChange: { - LOG(DEBUG) << "Disk at " << major << ":" << minor << " changed"; - for (auto disk : mDisks) { - if (disk->getDevice() == device) { - if (disk->isSrdiskMounted()) { - LOG(DEBUG) << "srdisk ejected"; - disk->destroyAllVolumes(); - break; + case NetlinkEvent::Action::kChange: { + LOG(DEBUG) << "Disk at " << major << ":" << minor << " changed"; + for (auto disk : mDisks) { + if (disk->getDevice() == device) { + if (disk->isSrdiskMounted()) { + LOG(DEBUG) << "srdisk ejected"; + disk->destroyAllVolumes(); + break; + } + + //disk->readMetadata(); + //disk->readPartitions(); } - - disk->readMetadata(); - disk->readPartitions(); } + break; } - break; - } - case NetlinkEvent::Action::kRemove: { - auto i = mDisks.begin(); - while (i != mDisks.end()) { - if ((*i)->getDevice() == device) { - (*i)->destroy(); - i = mDisks.erase(i); - } else { - ++i; + case NetlinkEvent::Action::kRemove: { + auto i = mDisks.begin(); + while (i != mDisks.end()) { + if ((*i)->getDevice() == device) { + (*i)->destroy(); + i = mDisks.erase(i); + } else { + ++i; + } } + break; + } + default: { + LOG(WARNING) << "Unexpected block event action " << (int) evt->getAction(); + break; + } + } + + } else { + for (auto disk : mDisks) { + disk->handleBlockEvent(evt); } - break; - } - default: { - LOG(WARNING) << "Unexpected block event action " << (int) evt->getAction(); - break; - } } + } void VolumeManager::addDiskSource(const std::shared_ptr<DiskSource>& diskSource) { @@ -341,8 +352,9 @@ int VolumeManager::reset() { // newly connected framework hears all events. for (auto disk : mDisks) { disk->destroy(); - disk->create(); + disk->reset(); } + return 0; } @@ -364,3 +376,47 @@ int VolumeManager::mkdirs(char* path) { return -EINVAL; } } + +static void do_coldboot(DIR *d, int lvl) { + struct dirent *de; + int dfd, fd; + + dfd = dirfd(d); + + fd = openat(dfd, "uevent", O_WRONLY | O_CLOEXEC); + if (fd >= 0) { + write(fd, "add\n", 4); + close(fd); + } + + while ((de = readdir(d))) { + DIR *d2; + + if (de->d_name[0] == '.') + continue; + + if (de->d_type != DT_DIR && lvl > 0) + continue; + + fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY); + if (fd < 0) + continue; + + d2 = fdopendir(fd); + if (d2 == 0) + close(fd); + else { + do_coldboot(d2, lvl + 1); + closedir(d2); + } + } +} + +void VolumeManager::coldboot(const char *path) { + DIR *d = opendir(path); + + if (d) { + do_coldboot(d, 0); + closedir(d); + } +} diff --git a/VolumeManager.h b/VolumeManager.h index 715e68b..73b5b2b 100644 --- a/VolumeManager.h +++ b/VolumeManager.h @@ -34,6 +34,10 @@ #include "Disk.h" #include "VolumeBase.h" +#include "DroidVold.h" + +using namespace android; +using ::vendor::amlogic::hardware::droidvold::V1_0::implementation::DroidVold; class VolumeManager { public: @@ -44,7 +48,7 @@ public: private: static VolumeManager *sInstance; - SocketListener *mBroadcaster; + DroidVold *mBroadcaster; bool mDebug; @@ -99,13 +103,15 @@ public: #endif int setDebug(bool enable); + bool getDebug() { return mDebug; } - void setBroadcaster(SocketListener *sl) { mBroadcaster = sl; } - SocketListener *getBroadcaster() { return mBroadcaster; } + void setBroadcaster(DroidVold *sl) { mBroadcaster = sl; } + DroidVold *getBroadcaster() { return mBroadcaster; } static VolumeManager *Instance(); bool isMountpointMounted(const char *mp); int mkdirs(char* path); + void coldboot(const char *path); private: VolumeManager(); diff --git a/droidvold.rc b/droidvold.rc index 0511135..d8192a5 100644 --- a/droidvold.rc +++ b/droidvold.rc @@ -1,7 +1,4 @@ -service droidvold /vendor/bin/droidvold \ - --blkid_context=u:r:blkid:s0 --blkid_untrusted_context=u:r:blkid_untrusted:s0 \ - --fsck_context=u:r:fsck:s0 --fsck_untrusted_context=u:r:fsck_untrusted:s0 +service droidvold /vendor/bin/droidvold class core - socket droidvold stream 0660 root system ioprio be 2 writepid /dev/cpuset/foreground/tasks diff --git a/dvdc.cpp b/dvdc.cpp deleted file mode 100644 index 31b6ff8..0000000 --- a/dvdc.cpp +++ b/dev/null @@ -1,178 +0,0 @@ -/* - * 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/socket.h> -#include <sys/select.h> -#include <sys/time.h> -#include <sys/types.h> -#include <sys/un.h> - -#include <android-base/logging.h> -#include <android-base/stringprintf.h> - -#include <cutils/sockets.h> -#include <private/android_filesystem_config.h> - -static void usage(char *progname); -static int do_monitor(int sock, int stop_after_cmd); -static int do_cmd(int sock, int argc, char **argv); - -static constexpr int kCommandTimeoutMs = 20 * 1000; - -int main(int argc, char **argv) { - int sock; - int wait_for_socket; - char *progname; - - progname = argv[0]; - - 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_for_socket = argc > 1 && strcmp(argv[1], "--wait") == 0; - if (wait_for_socket) { - argv++; - argc--; - } - - if (argc < 2) { - usage(progname); - exit(5); - } - - const char* sockname = "droidvold"; - - while ((sock = socket_local_client(sockname, - ANDROID_SOCKET_NAMESPACE_RESERVED, - SOCK_STREAM)) < 0) { - if (!wait_for_socket) { - PLOG(ERROR) << "Error connecting to " << sockname; - exit(4); - } else { - usleep(10000); - } - } - - if (!strcmp(argv[1], "monitor")) { - exit(do_monitor(sock, 0)); - } else { - exit(do_cmd(sock, argc, argv)); - } -} - -static int do_cmd(int sock, int argc, char **argv) { - int seq = getpid(); - - std::string cmd(android::base::StringPrintf("%d ", seq)); - for (int i = 1; i < argc; i++) { - if (!strchr(argv[i], ' ')) { - cmd.append(argv[i]); - } else { - cmd.push_back('\"'); - cmd.append(argv[i]); - cmd.push_back('\"'); - } - - if (i < argc - 1) { - cmd.push_back(' '); - } - } - - if (TEMP_FAILURE_RETRY(write(sock, cmd.c_str(), cmd.length() + 1)) < 0) { - PLOG(ERROR) << "Failed to write command"; - return errno; - } - - return do_monitor(sock, seq); -} - -static int do_monitor(int sock, int stop_after_seq) { - char buffer[4096]; - int timeout = kCommandTimeoutMs; - - if (stop_after_seq == 0) { - LOG(INFO) << "Connected to vold"; - timeout = -1; - } - - while (1) { - struct pollfd poll_sock = { sock, POLLIN, 0 }; - int rc = TEMP_FAILURE_RETRY(poll(&poll_sock, 1, timeout)); - if (rc == 0) { - LOG(ERROR) << "Timeout waiting for " << stop_after_seq; - return ETIMEDOUT; - } else if (rc < 0) { - PLOG(ERROR) << "Failed during poll"; - return errno; - } - - if (!(poll_sock.revents & POLLIN)) { - LOG(INFO) << "No data; trying again"; - continue; - } - - memset(buffer, 0, sizeof(buffer)); - rc = TEMP_FAILURE_RETRY(read(sock, buffer, sizeof(buffer))); - if (rc == 0) { - LOG(ERROR) << "Lost connection, did vold crash?"; - return ECONNRESET; - } else if (rc < 0) { - PLOG(ERROR) << "Error reading data"; - return errno; - } - - int offset = 0; - for (int i = 0; i < rc; i++) { - if (buffer[i] == '\0') { - char* res = buffer + offset; - fprintf(stdout, "%s\n", res); - - int code = atoi(strtok(res, " ")); - if (code >= 200 && code < 600) { - int seq = atoi(strtok(nullptr, " ")); - if (seq == stop_after_seq) { - if (code == 200) { - return 0; - } else { - return code; - } - } - } - - offset = i + 1; - } - } - } - return EIO; -} - -static void usage(char *progname) { - LOG(INFO) << "Usage: " << progname << " [--wait] <monitor>|<cmd> [arg1] [arg2...]"; -} @@ -16,9 +16,10 @@ #include "Disk.h" #include "VolumeManager.h" -#include "CommandListener.h" #include "NetlinkManager.h" -#include "sehandle.h" +#include "DroidVold.h" + +#define LOG_TAG "droidVold" #include <android-base/logging.h> #include <android-base/stringprintf.h> @@ -26,6 +27,11 @@ #include <cutils/properties.h> #include <cutils/sockets.h> +#include <binder/IPCThreadState.h> +#include <binder/ProcessState.h> +#include <binder/IServiceManager.h> +#include <HidlTransportSupport.h> + #include <stdio.h> #include <stdlib.h> #include <errno.h> @@ -37,23 +43,23 @@ #include <dirent.h> #include <fs_mgr.h> -#define LOG_TAG "droidVold" - #include "cutils/klog.h" #include "cutils/log.h" #include "cutils/properties.h" static int process_config(VolumeManager *vm, bool* has_adoptable); -static void coldboot(const char *path); -static void parse_args(int argc, char** argv); static void set_media_poll_time(void); struct fstab *fstab; -struct selabel_handle *sehandle; - -using android::base::StringPrintf; +using namespace android; +using ::android::base::StringPrintf; +using ::android::hardware::configureRpcThreadpool; +using ::android::hardware::joinRpcThreadpool; +using ::vendor::amlogic::hardware::droidvold::V1_0::implementation::DroidVold; +using ::vendor::amlogic::hardware::droidvold::V1_0::IDroidVold; +using ::vendor::amlogic::hardware::droidvold::V1_0::Result; int main(int argc, char** argv) { setenv("ANDROID_LOG_TAGS", "*:v", 1); @@ -61,18 +67,12 @@ int main(int argc, char** argv) { LOG(INFO) << "doildVold 1.0 firing up"; + android::ProcessState::initWithDriver("/dev/hwbinder"); + configureRpcThreadpool(4, true); + VolumeManager *vm; NetlinkManager *nm; - CommandListener *cl; - - parse_args(argc, argv); - - sehandle = selinux_android_file_context_handle(); - if (sehandle) { - selinux_android_set_sehandle(sehandle); - } - - mkdir("/dev/block/droidvold", 0755); + DroidVold *dv; /* Create our singleton managers */ if (!(vm = VolumeManager::Instance())) { @@ -89,9 +89,13 @@ int main(int argc, char** argv) { vm->setDebug(true); } - cl = new CommandListener(); - vm->setBroadcaster((SocketListener *) cl); - nm->setBroadcaster((SocketListener *) cl); + if (!(dv= DroidVold::Instance())) { + LOG(ERROR) << "Unable to create DroidVold"; + exit(1); + } + + vm->setBroadcaster(dv); + nm->setBroadcaster(dv); if (vm->start()) { PLOG(ERROR) << "Unable to start VolumeManager"; @@ -109,21 +113,21 @@ int main(int argc, char** argv) { exit(1); } + sp<IDroidVold> idv = DroidVold::Instance(); + if (idv == nullptr) + ALOGE("Cannot create IDroidVold service"); + else if (idv->registerAsService() != OK) + ALOGE("Cannot register IDroidVold service."); + else + ALOGI("IDroidVold service created."); + set_media_poll_time(); - coldboot("/sys/block"); + vm->coldboot("/sys/block"); /* - * Now that we're up, we can respond to commands + * This thread is just going to process Binder transactions. */ - if (cl->startListener()) { - PLOG(ERROR) << "Unable to start CommandListener"; - exit(1); - } - - // Eventually we'll become the monitoring thread - while (1) { - sleep(1000); - } + joinRpcThreadpool(); LOG(ERROR) << "droidVold exiting"; exit(0); @@ -141,74 +145,6 @@ static void set_media_poll_time(void) { } } -static void parse_args(int argc, char** argv) { - static struct option opts[] = { - {"blkid_context", required_argument, 0, 'b' }, - {"blkid_untrusted_context", required_argument, 0, 'B' }, - {"fsck_context", required_argument, 0, 'f' }, - {"fsck_untrusted_context", required_argument, 0, 'F' }, - }; - - int c; - while ((c = getopt_long(argc, argv, "", opts, nullptr)) != -1) { - switch (c) { - case 'b': android::droidvold::sBlkidContext = optarg; break; - case 'B': android::droidvold::sBlkidUntrustedContext = optarg; break; - case 'f': android::droidvold::sFsckContext = optarg; break; - case 'F': android::droidvold::sFsckUntrustedContext = optarg; break; - } - } - - CHECK(android::droidvold::sBlkidContext != nullptr); - CHECK(android::droidvold::sBlkidUntrustedContext != nullptr); - CHECK(android::droidvold::sFsckContext != nullptr); - CHECK(android::droidvold::sFsckUntrustedContext != nullptr); -} - -static void do_coldboot(DIR *d, int lvl) { - struct dirent *de; - int dfd, fd; - - dfd = dirfd(d); - - fd = openat(dfd, "uevent", O_WRONLY | O_CLOEXEC); - if (fd >= 0) { - write(fd, "add\n", 4); - close(fd); - } - - while ((de = readdir(d))) { - DIR *d2; - - if (de->d_name[0] == '.') - continue; - - if (de->d_type != DT_DIR && lvl > 0) - continue; - - fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY); - if (fd < 0) - continue; - - d2 = fdopendir(fd); - if (d2 == 0) - close(fd); - else { - do_coldboot(d2, lvl + 1); - closedir(d2); - } - } -} - -static void coldboot(const char *path) { - DIR *d = opendir(path); - - if (d) { - do_coldboot(d, 0); - closedir(d); - } -} - static int process_config(VolumeManager *vm, bool* has_adoptable) { std::string path(android::droidvold::DefaultFstabPath()); fstab = fs_mgr_read_fstab(path.c_str()); diff --git a/secontext.cpp b/secontext.cpp deleted file mode 100644 index 1465a11..0000000 --- a/secontext.cpp +++ b/dev/null @@ -1,22 +0,0 @@ -/* - * 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 <Utils.h> -#include "secontext.h" - -security_context_t secontextFsck() -{ - return android::droidvold::sFsckContext; -} diff --git a/secontext.h b/secontext.h deleted file mode 100644 index 08ad48e..0000000 --- a/secontext.h +++ b/dev/null @@ -1,25 +0,0 @@ -/* - * 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. - */ -#ifndef _SECONTEXT_H_ -#define _SECONTEXT_H_ - -#include <selinux/selinux.h> - -__BEGIN_DECLS -security_context_t secontextFsck(); -__END_DECLS - -#endif diff --git a/sehandle.h b/sehandle.h deleted file mode 100644 index f59d7eb..0000000 --- a/sehandle.h +++ b/dev/null @@ -1,24 +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. - */ - -#ifndef _SEHANDLE_H -#define _SEHANDLE_H - -#include <selinux/android.h> - -extern struct selabel_handle *sehandle; - -#endif |