Adding public volume mounts for clone user.
Public SdCard Volumes are mounted only for user 0 (foreground user). This gives ENONT if the cloned user tries to access the files in SdCard with paths like "/storage/AB02-G212/DCIM/" This change adds SdCard Volume mnt under /mnt/usr/<cloned-user>/ which allows cloned apps access to SdCard via direct file paths. Bug: 203395175 Test: Manual by building and flashing device. Change-Id: I091c40d3cb19915145cd5af40d1e79d5a9ecfa02
This commit is contained in:
parent
c2b3fefa01
commit
0ad0862159
3 changed files with 79 additions and 0 deletions
|
@ -68,6 +68,7 @@
|
|||
#include "model/EmulatedVolume.h"
|
||||
#include "model/ObbVolume.h"
|
||||
#include "model/PrivateVolume.h"
|
||||
#include "model/PublicVolume.h"
|
||||
#include "model/StubVolume.h"
|
||||
|
||||
using android::OK;
|
||||
|
@ -88,6 +89,7 @@ using android::vold::IsVirtioBlkDevice;
|
|||
using android::vold::PrepareAndroidDirs;
|
||||
using android::vold::PrepareAppDirFromRoot;
|
||||
using android::vold::PrivateVolume;
|
||||
using android::vold::PublicVolume;
|
||||
using android::vold::Symlink;
|
||||
using android::vold::Unlink;
|
||||
using android::vold::UnmountTree;
|
||||
|
@ -457,6 +459,31 @@ int VolumeManager::onUserStarted(userid_t userId) {
|
|||
|
||||
if (mStartedUsers.find(userId) == mStartedUsers.end()) {
|
||||
createEmulatedVolumesForUser(userId);
|
||||
std::list<std::string> public_vols;
|
||||
listVolumes(VolumeBase::Type::kPublic, public_vols);
|
||||
for (const std::string& id : public_vols) {
|
||||
PublicVolume* pvol = static_cast<PublicVolume*>(findVolume(id).get());
|
||||
if (pvol->getState() != VolumeBase::State::kMounted) {
|
||||
continue;
|
||||
}
|
||||
if (pvol->isVisible() == 0) {
|
||||
continue;
|
||||
}
|
||||
userid_t mountUserId = pvol->getMountUserId();
|
||||
if (userId == mountUserId) {
|
||||
// No need to bind mount for the user that owns the mount
|
||||
continue;
|
||||
}
|
||||
if (mountUserId != VolumeManager::Instance()->getSharedStorageUser(userId)) {
|
||||
// No need to bind if the user does not share storage with the mount owner
|
||||
continue;
|
||||
}
|
||||
auto bindMountStatus = pvol->bindMountForUser(userId);
|
||||
if (bindMountStatus != OK) {
|
||||
LOG(ERROR) << "Bind Mounting Public Volume: " << pvol << " for user: " << userId
|
||||
<< "Failed. Error: " << bindMountStatus;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mStartedUsers.insert(userId);
|
||||
|
|
|
@ -257,9 +257,45 @@ status_t PublicVolume::doMount() {
|
|||
// See comment in model/EmulatedVolume.cpp
|
||||
ConfigureMaxDirtyRatioForFuse(GetFuseMountPathForUser(user_id, stableName), 40u);
|
||||
|
||||
auto vol_manager = VolumeManager::Instance();
|
||||
// Create bind mounts for all running users
|
||||
for (userid_t started_user : vol_manager->getStartedUsers()) {
|
||||
userid_t mountUserId = getMountUserId();
|
||||
if (started_user == mountUserId) {
|
||||
// No need to bind mount for the user that owns the mount
|
||||
continue;
|
||||
}
|
||||
if (mountUserId != VolumeManager::Instance()->getSharedStorageUser(started_user)) {
|
||||
// No need to bind if the user does not share storage with the mount owner
|
||||
continue;
|
||||
}
|
||||
auto bindMountStatus = bindMountForUser(started_user);
|
||||
if (bindMountStatus != OK) {
|
||||
LOG(ERROR) << "Bind Mounting Public Volume: " << stableName
|
||||
<< " for user: " << started_user << "Failed. Error: " << bindMountStatus;
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
status_t PublicVolume::bindMountForUser(userid_t user_id) {
|
||||
userid_t mountUserId = getMountUserId();
|
||||
std::string stableName = getId();
|
||||
if (!mFsUuid.empty()) {
|
||||
stableName = mFsUuid;
|
||||
}
|
||||
|
||||
LOG(INFO) << "Bind Mounting Public Volume for user: " << user_id
|
||||
<< ".Mount owner: " << mountUserId;
|
||||
auto sourcePath = GetFuseMountPathForUser(mountUserId, stableName);
|
||||
auto destPath = GetFuseMountPathForUser(user_id, stableName);
|
||||
PrepareDir(destPath, 0770, AID_ROOT, AID_MEDIA_RW);
|
||||
auto mountRes = BindMount(sourcePath, destPath);
|
||||
LOG(INFO) << "Mount status: " << mountRes;
|
||||
|
||||
return mountRes;
|
||||
}
|
||||
|
||||
status_t PublicVolume::doUnmount() {
|
||||
// Unmount the storage before we kill the FUSE process. If we kill
|
||||
// the FUSE process first, most file system operations will return
|
||||
|
@ -274,6 +310,20 @@ status_t PublicVolume::doUnmount() {
|
|||
stableName = mFsUuid;
|
||||
}
|
||||
|
||||
// Unmount bind mounts for running users
|
||||
auto vol_manager = VolumeManager::Instance();
|
||||
int user_id = getMountUserId();
|
||||
for (int started_user : vol_manager->getStartedUsers()) {
|
||||
if (started_user == user_id) {
|
||||
// No need to remove bind mount for the user that owns the mount
|
||||
continue;
|
||||
}
|
||||
LOG(INFO) << "Removing Public Volume Bind Mount for: " << started_user;
|
||||
auto mountPath = GetFuseMountPathForUser(started_user, stableName);
|
||||
ForceUnmount(mountPath);
|
||||
rmdir(mountPath.c_str());
|
||||
}
|
||||
|
||||
if (UnmountUserFuse(getMountUserId(), getInternalPath(), stableName) != OK) {
|
||||
PLOG(INFO) << "UnmountUserFuse failed on public fuse volume";
|
||||
return -errno;
|
||||
|
|
|
@ -42,6 +42,8 @@ class PublicVolume : public VolumeBase {
|
|||
explicit PublicVolume(dev_t device);
|
||||
virtual ~PublicVolume();
|
||||
|
||||
status_t bindMountForUser(userid_t user_id);
|
||||
|
||||
protected:
|
||||
status_t doCreate() override;
|
||||
status_t doDestroy() override;
|
||||
|
|
Loading…
Reference in a new issue