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