blob: bd7c29cde772be1cfb8cf3ebfa5e55acbeef4886 [file] [log] [blame]
Tom Marshall292bd232019-01-04 14:37:31 -08001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 * Copyright (C) 2019 The LineageOS Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#include "VolumeBase.h"
19#include <volume_manager/ResponseCode.h>
20#include <volume_manager/VolumeManager.h>
21#include "Utils.h"
22
23#include <android-base/logging.h>
24#include <android-base/stringprintf.h>
25
26#include <fcntl.h>
27#include <stdlib.h>
28#include <sys/mount.h>
29#include <sys/stat.h>
30#include <sys/types.h>
31
32using android::base::StringPrintf;
33
34namespace android {
35namespace volmgr {
36
37VolumeBase::VolumeBase(Type type)
Tom Marshall0057c5f2019-07-24 21:12:07 +020038 : mType(type), mMountFlags(0), mCreated(false), mState(State::kUnmounted), mSilent(false), mMountable(false) {}
Tom Marshall292bd232019-01-04 14:37:31 -080039
40VolumeBase::~VolumeBase() {
41 CHECK(!mCreated);
42}
43
44void VolumeBase::setState(State state) {
45 mState = state;
46 VolumeManager::Instance()->notifyEvent(ResponseCode::VolumeStateChanged,
47 StringPrintf("%d", mState));
48}
49
50status_t VolumeBase::setDiskId(const std::string& diskId) {
51 if (mCreated) {
52 LOG(WARNING) << getId() << " diskId change requires destroyed";
53 return -EBUSY;
54 }
55
56 mDiskId = diskId;
57 return OK;
58}
59
60status_t VolumeBase::setPartGuid(const std::string& partGuid) {
61 if (mCreated) {
62 LOG(WARNING) << getId() << " partGuid change requires destroyed";
63 return -EBUSY;
64 }
65
66 mPartGuid = partGuid;
67 return OK;
68}
69
70status_t VolumeBase::setPartLabel(const std::string& partLabel) {
71 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
72 LOG(WARNING) << getId() << " partLabel change requires state unmounted or unmountable";
73 LOG(WARNING) << getId() << " state=" << (int)mState;
74 }
75
76 mPartLabel = partLabel;
77 return OK;
78}
79
80status_t VolumeBase::setMountFlags(int mountFlags) {
81 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
82 LOG(WARNING) << getId() << " flags change requires state unmounted or unmountable";
83 return -EBUSY;
84 }
85
86 mMountFlags = mountFlags;
87 return OK;
88}
89
90status_t VolumeBase::setSilent(bool silent) {
91 if (mCreated) {
92 LOG(WARNING) << getId() << " silence change requires destroyed";
93 return -EBUSY;
94 }
95
96 mSilent = silent;
97 return OK;
98}
99
100status_t VolumeBase::setId(const std::string& id) {
101 if (mCreated) {
102 LOG(WARNING) << getId() << " id change requires not created";
103 return -EBUSY;
104 }
105
106 mId = id;
107 return OK;
108}
109
110status_t VolumeBase::setPath(const std::string& path) {
111 mPath = path;
112 VolumeManager::Instance()->notifyEvent(ResponseCode::VolumePathChanged, mPath);
113 return OK;
114}
115
116status_t VolumeBase::create() {
117 if (mCreated) {
118 return BAD_VALUE;
119 }
120
121 mCreated = true;
122 std::vector<std::string> argv;
123 argv.push_back(StringPrintf("%d", mType));
124 argv.push_back(mDiskId);
125 argv.push_back(mPartGuid);
126 status_t res = doCreate();
127 if (res == OK) {
128 VolumeManager::Instance()->notifyEvent(ResponseCode::VolumeCreated, argv);
129 if (mPartLabel.size() > 0) {
130 VolumeManager::Instance()->notifyEvent(ResponseCode::VolumeFsLabelChanged, mPartLabel);
131 }
132 }
133 setState(State::kUnmounted);
Tom Marshall0057c5f2019-07-24 21:12:07 +0200134
135 mMountable = detectMountable();
136
Tom Marshall292bd232019-01-04 14:37:31 -0800137 return res;
138}
139
Tom Marshall0057c5f2019-07-24 21:12:07 +0200140bool VolumeBase::detectMountable() {
141 bool mountable = false;
142 if (doMount() == OK) {
143 mountable = true;
144 doUnmount();
145 }
146 return mountable;
147}
148
Tom Marshall292bd232019-01-04 14:37:31 -0800149status_t VolumeBase::doCreate() {
150 return OK;
151}
152
153status_t VolumeBase::destroy() {
154 if (!mCreated) {
155 return NO_INIT;
156 }
157
158 if (mState == State::kMounted) {
159 unmount(true /* detatch */);
160 setState(State::kBadRemoval);
161 } else {
162 setState(State::kRemoved);
163 }
164
165 VolumeManager::Instance()->notifyEvent(ResponseCode::VolumeDestroyed);
166 status_t res = doDestroy();
167 mCreated = false;
168 return res;
169}
170
171status_t VolumeBase::doDestroy() {
172 return OK;
173}
174
175status_t VolumeBase::mount() {
176 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
177 LOG(WARNING) << getId() << " mount requires state unmounted or unmountable";
178 return -EBUSY;
179 }
180
181 setState(State::kChecking);
182 status_t res = doMount();
183 if (res == OK) {
184 setState(State::kMounted);
185 } else {
186 setState(State::kUnmountable);
187 }
188
189 return res;
190}
191
192status_t VolumeBase::unmount(bool detach /* = false */) {
193 setState(State::kEjecting);
194
195 status_t res = doUnmount(detach);
196 setState(State::kUnmounted);
197 return res;
198}
199
200} // namespace volmgr
201} // namespace android