diff --git a/Android.bp b/Android.bp index 8f2ba34..44e2317 100644 --- a/Android.bp +++ b/Android.bp @@ -129,6 +129,7 @@ cc_library_static { "model/PrivateVolume.cpp", "model/PublicVolume.cpp", "model/VolumeBase.cpp", + "model/StubVolume.cpp", "secontext.cpp", ], product_variables: { diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp index 5987849..a06b357 100644 --- a/VoldNativeService.cpp +++ b/VoldNativeService.cpp @@ -479,6 +479,29 @@ binder::Status VoldNativeService::destroyObb(const std::string& volId) { return translate(VolumeManager::Instance()->destroyObb(volId)); } +binder::Status VoldNativeService::createStubVolume( + const std::string& sourcePath, const std::string& mountPath, const std::string& fsType, + const std::string& fsUuid, const std::string& fsLabel, std::string* _aidl_return) { + ENFORCE_UID(AID_SYSTEM); + CHECK_ARGUMENT_PATH(sourcePath); + CHECK_ARGUMENT_PATH(mountPath); + CHECK_ARGUMENT_HEX(fsUuid); + // Label limitation seems to be different between fs (including allowed characters), so checking + // is quite meaningless. + ACQUIRE_LOCK; + + return translate(VolumeManager::Instance()->createStubVolume(sourcePath, mountPath, fsType, + fsUuid, fsLabel, _aidl_return)); +} + +binder::Status VoldNativeService::destroyStubVolume(const std::string& volId) { + ENFORCE_UID(AID_SYSTEM); + CHECK_ARGUMENT_ID(volId); + ACQUIRE_LOCK; + + return translate(VolumeManager::Instance()->destroyStubVolume(volId)); +} + binder::Status VoldNativeService::fstrim( int32_t fstrimFlags, const android::sp& listener) { ENFORCE_UID(AID_SYSTEM); diff --git a/VoldNativeService.h b/VoldNativeService.h index 40ce3a4..a02fa70 100644 --- a/VoldNativeService.h +++ b/VoldNativeService.h @@ -65,6 +65,11 @@ class VoldNativeService : public BinderService, public os::Bn int32_t ownerGid, std::string* _aidl_return); binder::Status destroyObb(const std::string& volId); + binder::Status createStubVolume(const std::string& sourcePath, const std::string& mountPath, + const std::string& fsType, const std::string& fsUuid, + const std::string& fsLabel, std::string* _aidl_return); + binder::Status destroyStubVolume(const std::string& volId); + binder::Status fstrim(int32_t fstrimFlags, const android::sp& listener); binder::Status runIdleMaint(const android::sp& listener); diff --git a/VolumeManager.cpp b/VolumeManager.cpp index f5eea7e..1fb7ce7 100644 --- a/VolumeManager.cpp +++ b/VolumeManager.cpp @@ -63,6 +63,7 @@ #include "fs/Vfat.h" #include "model/EmulatedVolume.h" #include "model/ObbVolume.h" +#include "model/StubVolume.h" using android::base::StartsWith; using android::base::StringPrintf; @@ -90,6 +91,7 @@ VolumeManager* VolumeManager::Instance() { VolumeManager::VolumeManager() { mDebug = false; mNextObbId = 0; + mNextStubVolumeId = 0; // For security reasons, assume that a secure keyguard is // showing until we hear otherwise mSecureKeyguardShowing = true; @@ -303,6 +305,11 @@ std::shared_ptr VolumeManager::findVolume(const std:: return vol; } } + for (const auto& vol : mStubVolumes) { + if (vol->getId() == id) { + return vol; + } + } for (const auto& vol : mObbVolumes) { if (vol->getId() == id) { return vol; @@ -558,6 +565,7 @@ int VolumeManager::shutdown() { for (const auto& disk : mDisks) { disk->destroy(); } + mStubVolumes.clear(); mDisks.clear(); mPendingDisks.clear(); android::vold::sSleepOnUnmount = true; @@ -572,6 +580,9 @@ int VolumeManager::unmountAll() { if (mInternalEmulated != nullptr) { mInternalEmulated->unmount(); } + for (const auto& stub : mStubVolumes) { + stub->unmount(); + } for (const auto& disk : mDisks) { disk->unmountAll(); } @@ -785,6 +796,32 @@ int VolumeManager::destroyObb(const std::string& volId) { return android::OK; } +int VolumeManager::createStubVolume(const std::string& sourcePath, const std::string& mountPath, + const std::string& fsType, const std::string& fsUuid, + const std::string& fsLabel, std::string* outVolId) { + int id = mNextStubVolumeId++; + auto vol = std::shared_ptr( + new android::vold::StubVolume(id, sourcePath, mountPath, fsType, fsUuid, fsLabel)); + vol->create(); + + mStubVolumes.push_back(vol); + *outVolId = vol->getId(); + return android::OK; +} + +int VolumeManager::destroyStubVolume(const std::string& volId) { + auto i = mStubVolumes.begin(); + while (i != mStubVolumes.end()) { + if ((*i)->getId() == volId) { + (*i)->destroy(); + i = mStubVolumes.erase(i); + } else { + ++i; + } + } + return android::OK; +} + int VolumeManager::mountAppFuse(uid_t uid, pid_t pid, int mountId, unique_fd* device_fd) { std::string name = std::to_string(mountId); diff --git a/VolumeManager.h b/VolumeManager.h index eedb1cb..2f76ddc 100644 --- a/VolumeManager.h +++ b/VolumeManager.h @@ -124,6 +124,11 @@ class VolumeManager { std::string* outVolId); int destroyObb(const std::string& volId); + int createStubVolume(const std::string& sourcePath, const std::string& mountPath, + const std::string& fsType, const std::string& fsUuid, + const std::string& fsLabel, std::string* outVolId); + int destroyStubVolume(const std::string& volId); + int mountAppFuse(uid_t uid, pid_t pid, int mountId, android::base::unique_fd* device_fd); int unmountAppFuse(uid_t uid, pid_t pid, int mountId); @@ -146,6 +151,7 @@ class VolumeManager { std::list> mDisks; std::list> mPendingDisks; std::list> mObbVolumes; + std::list> mStubVolumes; std::unordered_map mAddedUsers; std::unordered_set mStartedUsers; @@ -156,6 +162,7 @@ class VolumeManager { std::shared_ptr mPrimary; int mNextObbId; + int mNextStubVolumeId; bool mSecureKeyguardShowing; }; diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl index 4ed861f..ea98450 100644 --- a/binder/android/os/IVold.aidl +++ b/binder/android/os/IVold.aidl @@ -105,6 +105,11 @@ interface IVold { void restoreCheckpoint(@utf8InCpp String device); void markBootAttempt(); + @utf8InCpp String createStubVolume(@utf8InCpp String sourcePath, + @utf8InCpp String mountPath, @utf8InCpp String fsType, + @utf8InCpp String fsUuid, @utf8InCpp String fsLabel); + void destroyStubVolume(@utf8InCpp String volId); + const int ENCRYPTION_FLAG_NO_UI = 4; const int ENCRYPTION_STATE_NONE = 1; @@ -151,4 +156,5 @@ interface IVold { const int VOLUME_TYPE_EMULATED = 2; const int VOLUME_TYPE_ASEC = 3; const int VOLUME_TYPE_OBB = 4; + const int VOLUME_TYPE_STUB = 5; } diff --git a/model/StubVolume.cpp b/model/StubVolume.cpp new file mode 100644 index 0000000..edd0861 --- /dev/null +++ b/model/StubVolume.cpp @@ -0,0 +1,67 @@ +/* + * 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 "StubVolume.h" + +#include +#include + +using android::base::StringPrintf; + +namespace android { +namespace vold { + +StubVolume::StubVolume(int id, const std::string& sourcePath, const std::string& mountPath, + const std::string& fsType, const std::string& fsUuid, + const std::string& fsLabel) + : VolumeBase(Type::kStub), + mSourcePath(sourcePath), + mMountPath(mountPath), + mFsType(fsType), + mFsUuid(fsUuid), + mFsLabel(fsLabel) { + setId(StringPrintf("stub:%d", id)); +} + +StubVolume::~StubVolume() {} + +status_t StubVolume::doCreate() { + return OK; +} + +status_t StubVolume::doDestroy() { + return OK; +} + +status_t StubVolume::doMount() { + auto listener = getListener(); + if (listener) listener->onVolumeMetadataChanged(getId(), mFsType, mFsUuid, mFsLabel); + setInternalPath(mSourcePath); + setPath(mMountPath); + return OK; +} + +status_t StubVolume::doUnmount() { + return OK; +} + +// TODO: return error instead. +status_t StubVolume::doFormat(const std::string& fsType) { + return OK; +} + +} // namespace vold +} // namespace android diff --git a/model/StubVolume.h b/model/StubVolume.h new file mode 100644 index 0000000..538cae9 --- /dev/null +++ b/model/StubVolume.h @@ -0,0 +1,58 @@ +/* + * 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. + */ + +#ifndef ANDROID_VOLD_STUB_VOLUME_H +#define ANDROID_VOLD_STUB_VOLUME_H + +#include "VolumeBase.h" + +namespace android { +namespace vold { + +/* + * A vold representation of volumes managed from outside Android (e.g., ARC++). + * + * Used for the case when events such that mounting and unmounting are + * actually handled from outside vold, and vold only need to keep track on those + * vents instead of talking to kernel directly. + */ +class StubVolume : public VolumeBase { + public: + StubVolume(int id, const std::string& sourcePath, const std::string& mountPath, + const std::string& fsType, const std::string& fsUuid, const std::string& fsLabel); + virtual ~StubVolume(); + + protected: + status_t doCreate() override; + status_t doDestroy() override; + status_t doMount() override; + status_t doUnmount() override; + status_t doFormat(const std::string& fsType) override; + + private: + const std::string mSourcePath; + const std::string mMountPath; + const std::string mFsType; + const std::string mFsUuid; + const std::string mFsLabel; + + DISALLOW_COPY_AND_ASSIGN(StubVolume); +}; + +} // namespace vold +} // namespace android + +#endif diff --git a/model/VolumeBase.h b/model/VolumeBase.h index 6532a80..92a83f0 100644 --- a/model/VolumeBase.h +++ b/model/VolumeBase.h @@ -54,6 +54,7 @@ class VolumeBase { kEmulated, kAsec, kObb, + kStub, }; enum MountFlags {