Home | History | Annotate | Download | only in model
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "Utils.h"
     18 #include "VolumeBase.h"
     19 #include "VolumeManager.h"
     20 
     21 #include <android-base/stringprintf.h>
     22 #include <android-base/logging.h>
     23 
     24 #include <fcntl.h>
     25 #include <stdlib.h>
     26 #include <sys/mount.h>
     27 #include <sys/stat.h>
     28 #include <sys/types.h>
     29 
     30 using android::base::StringPrintf;
     31 
     32 namespace android {
     33 namespace vold {
     34 
     35 VolumeBase::VolumeBase(Type type) :
     36         mType(type), mMountFlags(0), mMountUserId(-1), mCreated(false), mState(
     37                 State::kUnmounted), mSilent(false) {
     38 }
     39 
     40 VolumeBase::~VolumeBase() {
     41     CHECK(!mCreated);
     42 }
     43 
     44 void VolumeBase::setState(State state) {
     45     mState = state;
     46 
     47     auto listener = getListener();
     48     if (listener) listener->onVolumeStateChanged(getId(), static_cast<int32_t>(mState));
     49 }
     50 
     51 status_t VolumeBase::setDiskId(const std::string& diskId) {
     52     if (mCreated) {
     53         LOG(WARNING) << getId() << " diskId change requires destroyed";
     54         return -EBUSY;
     55     }
     56 
     57     mDiskId = diskId;
     58     return OK;
     59 }
     60 
     61 status_t VolumeBase::setPartGuid(const std::string& partGuid) {
     62     if (mCreated) {
     63         LOG(WARNING) << getId() << " partGuid change requires destroyed";
     64         return -EBUSY;
     65     }
     66 
     67     mPartGuid = partGuid;
     68     return OK;
     69 }
     70 
     71 status_t VolumeBase::setMountFlags(int mountFlags) {
     72     if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
     73         LOG(WARNING) << getId() << " flags change requires state unmounted or unmountable";
     74         return -EBUSY;
     75     }
     76 
     77     mMountFlags = mountFlags;
     78     return OK;
     79 }
     80 
     81 status_t VolumeBase::setMountUserId(userid_t mountUserId) {
     82     if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
     83         LOG(WARNING) << getId() << " user change requires state unmounted or unmountable";
     84         return -EBUSY;
     85     }
     86 
     87     mMountUserId = mountUserId;
     88     return OK;
     89 }
     90 
     91 status_t VolumeBase::setSilent(bool silent) {
     92     if (mCreated) {
     93         LOG(WARNING) << getId() << " silence change requires destroyed";
     94         return -EBUSY;
     95     }
     96 
     97     mSilent = silent;
     98     return OK;
     99 }
    100 
    101 status_t VolumeBase::setId(const std::string& id) {
    102     if (mCreated) {
    103         LOG(WARNING) << getId() << " id change requires not created";
    104         return -EBUSY;
    105     }
    106 
    107     mId = id;
    108     return OK;
    109 }
    110 
    111 status_t VolumeBase::setPath(const std::string& path) {
    112     if (mState != State::kChecking) {
    113         LOG(WARNING) << getId() << " path change requires state checking";
    114         return -EBUSY;
    115     }
    116 
    117     mPath = path;
    118 
    119     auto listener = getListener();
    120     if (listener) listener->onVolumePathChanged(getId(), mPath);
    121 
    122     return OK;
    123 }
    124 
    125 status_t VolumeBase::setInternalPath(const std::string& internalPath) {
    126     if (mState != State::kChecking) {
    127         LOG(WARNING) << getId() << " internal path change requires state checking";
    128         return -EBUSY;
    129     }
    130 
    131     mInternalPath = internalPath;
    132 
    133     auto listener = getListener();
    134     if (listener) listener->onVolumeInternalPathChanged(getId(), mInternalPath);
    135 
    136     return OK;
    137 }
    138 
    139 android::sp<android::os::IVoldListener> VolumeBase::getListener() {
    140     if (mSilent) {
    141         return nullptr;
    142     } else {
    143         return VolumeManager::Instance()->getListener();
    144     }
    145 }
    146 
    147 void VolumeBase::addVolume(const std::shared_ptr<VolumeBase>& volume) {
    148     mVolumes.push_back(volume);
    149 }
    150 
    151 void VolumeBase::removeVolume(const std::shared_ptr<VolumeBase>& volume) {
    152     mVolumes.remove(volume);
    153 }
    154 
    155 std::shared_ptr<VolumeBase> VolumeBase::findVolume(const std::string& id) {
    156     for (auto vol : mVolumes) {
    157         if (vol->getId() == id) {
    158             return vol;
    159         }
    160     }
    161     return nullptr;
    162 }
    163 
    164 status_t VolumeBase::create() {
    165     CHECK(!mCreated);
    166 
    167     mCreated = true;
    168     status_t res = doCreate();
    169 
    170     auto listener = getListener();
    171     if (listener) listener->onVolumeCreated(getId(),
    172             static_cast<int32_t>(mType), mDiskId, mPartGuid);
    173 
    174     setState(State::kUnmounted);
    175     return res;
    176 }
    177 
    178 status_t VolumeBase::doCreate() {
    179     return OK;
    180 }
    181 
    182 status_t VolumeBase::destroy() {
    183     CHECK(mCreated);
    184 
    185     if (mState == State::kMounted) {
    186         unmount();
    187         setState(State::kBadRemoval);
    188     } else {
    189         setState(State::kRemoved);
    190     }
    191 
    192 
    193     auto listener = getListener();
    194     if (listener) listener->onVolumeDestroyed(getId());
    195 
    196     status_t res = doDestroy();
    197     mCreated = false;
    198     return res;
    199 }
    200 
    201 status_t VolumeBase::doDestroy() {
    202     return OK;
    203 }
    204 
    205 status_t VolumeBase::mount() {
    206     if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
    207         LOG(WARNING) << getId() << " mount requires state unmounted or unmountable";
    208         return -EBUSY;
    209     }
    210 
    211     setState(State::kChecking);
    212     status_t res = doMount();
    213     if (res == OK) {
    214         setState(State::kMounted);
    215     } else {
    216         setState(State::kUnmountable);
    217     }
    218 
    219     return res;
    220 }
    221 
    222 status_t VolumeBase::unmount() {
    223     if (mState != State::kMounted) {
    224         LOG(WARNING) << getId() << " unmount requires state mounted";
    225         return -EBUSY;
    226     }
    227 
    228     setState(State::kEjecting);
    229     for (const auto& vol : mVolumes) {
    230         if (vol->destroy()) {
    231             LOG(WARNING) << getId() << " failed to destroy " << vol->getId()
    232                     << " stacked above";
    233         }
    234     }
    235     mVolumes.clear();
    236 
    237     status_t res = doUnmount();
    238     setState(State::kUnmounted);
    239     return res;
    240 }
    241 
    242 status_t VolumeBase::format(const std::string& fsType) {
    243     if (mState == State::kMounted) {
    244         unmount();
    245     }
    246 
    247     if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
    248         LOG(WARNING) << getId() << " format requires state unmounted or unmountable";
    249         return -EBUSY;
    250     }
    251 
    252     setState(State::kFormatting);
    253     status_t res = doFormat(fsType);
    254     setState(State::kUnmounted);
    255     return res;
    256 }
    257 
    258 status_t VolumeBase::doFormat(const std::string& fsType) {
    259     return -ENOTSUP;
    260 }
    261 
    262 }  // namespace vold
    263 }  // namespace android
    264