• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "VolumeBase.h"
18 #include "Utils.h"
19 #include "VolumeManager.h"
20 
21 #include <android-base/logging.h>
22 #include <android-base/stringprintf.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 
VolumeBase(Type type)35 VolumeBase::VolumeBase(Type type)
36     : mType(type),
37       mMountFlags(0),
38       mMountUserId(USER_UNKNOWN),
39       mCreated(false),
40       mState(State::kUnmounted),
41       mSilent(false) {}
42 
~VolumeBase()43 VolumeBase::~VolumeBase() {
44     CHECK(!mCreated);
45 }
46 
setState(State state)47 void VolumeBase::setState(State state) {
48     mState = state;
49 
50     auto listener = getListener();
51     if (listener) {
52         listener->onVolumeStateChanged(getId(), static_cast<int32_t>(mState));
53     }
54 }
55 
setDiskId(const std::string & diskId)56 status_t VolumeBase::setDiskId(const std::string& diskId) {
57     if (mCreated) {
58         LOG(WARNING) << getId() << " diskId change requires destroyed";
59         return -EBUSY;
60     }
61 
62     mDiskId = diskId;
63     return OK;
64 }
65 
setPartGuid(const std::string & partGuid)66 status_t VolumeBase::setPartGuid(const std::string& partGuid) {
67     if (mCreated) {
68         LOG(WARNING) << getId() << " partGuid change requires destroyed";
69         return -EBUSY;
70     }
71 
72     mPartGuid = partGuid;
73     return OK;
74 }
75 
setMountFlags(int mountFlags)76 status_t VolumeBase::setMountFlags(int mountFlags) {
77     if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
78         LOG(WARNING) << getId() << " flags change requires state unmounted or unmountable";
79         return -EBUSY;
80     }
81 
82     mMountFlags = mountFlags;
83     return OK;
84 }
85 
setMountUserId(userid_t mountUserId)86 status_t VolumeBase::setMountUserId(userid_t mountUserId) {
87     if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
88         LOG(WARNING) << getId() << " user change requires state unmounted or unmountable";
89         return -EBUSY;
90     }
91 
92     mMountUserId = mountUserId;
93     return OK;
94 }
95 
setSilent(bool silent)96 status_t VolumeBase::setSilent(bool silent) {
97     if (mCreated) {
98         LOG(WARNING) << getId() << " silence change requires destroyed";
99         return -EBUSY;
100     }
101 
102     mSilent = silent;
103     return OK;
104 }
105 
setId(const std::string & id)106 status_t VolumeBase::setId(const std::string& id) {
107     if (mCreated) {
108         LOG(WARNING) << getId() << " id change requires not created";
109         return -EBUSY;
110     }
111 
112     mId = id;
113     return OK;
114 }
115 
setPath(const std::string & path)116 status_t VolumeBase::setPath(const std::string& path) {
117     if (mState != State::kChecking) {
118         LOG(WARNING) << getId() << " path change requires state checking";
119         return -EBUSY;
120     }
121 
122     mPath = path;
123 
124     auto listener = getListener();
125     if (listener) listener->onVolumePathChanged(getId(), mPath);
126 
127     return OK;
128 }
129 
setInternalPath(const std::string & internalPath)130 status_t VolumeBase::setInternalPath(const std::string& internalPath) {
131     if (mState != State::kChecking) {
132         LOG(WARNING) << getId() << " internal path change requires state checking";
133         return -EBUSY;
134     }
135 
136     mInternalPath = internalPath;
137 
138     auto listener = getListener();
139     if (listener) {
140         listener->onVolumeInternalPathChanged(getId(), mInternalPath);
141     }
142 
143     return OK;
144 }
145 
setMountCallback(const android::sp<android::os::IVoldMountCallback> & callback)146 status_t VolumeBase::setMountCallback(
147         const android::sp<android::os::IVoldMountCallback>& callback) {
148     mMountCallback = callback;
149     return OK;
150 }
151 
getMountCallback() const152 sp<android::os::IVoldMountCallback> VolumeBase::getMountCallback() const {
153     return mMountCallback;
154 }
155 
getListener() const156 android::sp<android::os::IVoldListener> VolumeBase::getListener() const {
157     if (mSilent) {
158         return nullptr;
159     } else {
160         return VolumeManager::Instance()->getListener();
161     }
162 }
163 
addVolume(const std::shared_ptr<VolumeBase> & volume)164 void VolumeBase::addVolume(const std::shared_ptr<VolumeBase>& volume) {
165     mVolumes.push_back(volume);
166 }
167 
removeVolume(const std::shared_ptr<VolumeBase> & volume)168 void VolumeBase::removeVolume(const std::shared_ptr<VolumeBase>& volume) {
169     mVolumes.remove(volume);
170 }
171 
findVolume(const std::string & id)172 std::shared_ptr<VolumeBase> VolumeBase::findVolume(const std::string& id) {
173     for (auto vol : mVolumes) {
174         if (vol->getId() == id) {
175             return vol;
176         }
177     }
178     return nullptr;
179 }
180 
create()181 status_t VolumeBase::create() {
182     CHECK(!mCreated);
183 
184     mCreated = true;
185     status_t res = doCreate();
186 
187     auto listener = getListener();
188     if (listener) {
189         listener->onVolumeCreated(getId(), static_cast<int32_t>(mType), mDiskId, mPartGuid,
190                                   mMountUserId);
191     }
192 
193     setState(State::kUnmounted);
194     return res;
195 }
196 
doCreate()197 status_t VolumeBase::doCreate() {
198     return OK;
199 }
200 
destroy()201 status_t VolumeBase::destroy() {
202     CHECK(mCreated);
203 
204     if (mState == State::kMounted) {
205         unmount();
206         setState(State::kBadRemoval);
207     } else {
208         setState(State::kRemoved);
209     }
210 
211     auto listener = getListener();
212     if (listener) {
213         listener->onVolumeDestroyed(getId());
214     }
215 
216     status_t res = doDestroy();
217     mCreated = false;
218     return res;
219 }
220 
doDestroy()221 status_t VolumeBase::doDestroy() {
222     return OK;
223 }
224 
mount()225 status_t VolumeBase::mount() {
226     if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
227         LOG(WARNING) << getId() << " mount requires state unmounted or unmountable";
228         return -EBUSY;
229     }
230 
231     setState(State::kChecking);
232     status_t res = doMount();
233     setState(res == OK ? State::kMounted : State::kUnmountable);
234 
235     if (res == OK) {
236         doPostMount();
237     }
238     return res;
239 }
240 
doPostMount()241 void VolumeBase::doPostMount() {}
242 
unmount()243 status_t VolumeBase::unmount() {
244     if (mState != State::kMounted) {
245         LOG(WARNING) << getId() << " unmount requires state mounted";
246         return -EBUSY;
247     }
248 
249     setState(State::kEjecting);
250     for (const auto& vol : mVolumes) {
251         if (vol->destroy()) {
252             LOG(WARNING) << getId() << " failed to destroy " << vol->getId() << " stacked above";
253         }
254     }
255     mVolumes.clear();
256 
257     status_t res = doUnmount();
258     setState(State::kUnmounted);
259     return res;
260 }
261 
format(const std::string & fsType)262 status_t VolumeBase::format(const std::string& fsType) {
263     if (mState == State::kMounted) {
264         unmount();
265     }
266 
267     if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
268         LOG(WARNING) << getId() << " format requires state unmounted or unmountable";
269         return -EBUSY;
270     }
271 
272     setState(State::kFormatting);
273     status_t res = doFormat(fsType);
274     setState(State::kUnmounted);
275     return res;
276 }
277 
doFormat(const std::string & fsType)278 status_t VolumeBase::doFormat(const std::string& fsType) {
279     return -ENOTSUP;
280 }
281 
getRootPath() const282 std::string VolumeBase::getRootPath() const {
283     // Usually the same as the internal path, except for emulated volumes.
284     return getInternalPath();
285 }
286 
operator <<(std::ostream & stream) const287 std::ostream& VolumeBase::operator<<(std::ostream& stream) const {
288     return stream << " VolumeBase{id=" << mId << ",mountFlags=" << mMountFlags
289                   << ",mountUserId=" << mMountUserId << "}";
290 }
291 
292 }  // namespace vold
293 }  // namespace android
294