VolumeBase在构造时,已经将状态设置为Unmounted,为什么在create里还要再次设置呢?
下面是VolumeBase的构造
VolumeBase::VolumeBase(Type type) :
mType(type), mMountFlags(0), mMountUserId(-1), mCreated(false), mState(
State::kUnmounted), mSilent(false) {
}
下面是create函数
status_t VolumeBase::create() {
CHECK(!mCreated);
mCreated = true;
status_t res = doCreate();
auto listener = getListener();
if (listener) listener->onVolumeCreated(getId(),
static_cast<int32_t>(mType), mDiskId, mPartGuid);
setState(State::kUnmounted);
return res;
}
可以看到,这里create中,再次将状态设置为Unmounted,难道在这之前会有人改变这一状态吗?
对于这个问题,我思考了几天不得其解。
但是把这句话去掉,就会报错,大意为挂载EmulatedVolume 挂载失败
11-19 19:11:39.729 2197 2203 W vold : emulated flags change requires state unmounted or unmountable
11-19 19:11:39.729 2197 2203 W vold : emulated user change requires state unmounted or unmountable
11-19 19:11:39.729 2197 2203 W vold : emulated mount requires state unmounted or unmountable
失败的原因是Emulated卷状态不是unmounted或unmountable。
是谁改了它的状态,添加log
发现Emulated会Volume会create两次,第一次create前,状态是unmounted,第二次却变成removed,
查看源码,只有一个地方会将状态改变成removed,那就是卷的销毁,所以必然有人调用了此函数,这肯定和create两次有关
。
status_t VolumeBase::destroy() {
CHECK(mCreated);
if (mState == State::kMounted) {
unmount();
setState(State::kBadRemoval);
} else {
setState(State::kRemoved);
}
auto listener = getListener();
if (listener) listener->onVolumeDestroyed(getId());
status_t res = doDestroy();
mCreated = false;
return res;
}
Volume 卸载时,会调用此函数
status_t VolumeBase::unmount() {
if (mState != State::kMounted) {
LOG(WARNING) << getId() << " unmount requires state mounted";
return -EBUSY;
}
setState(State::kEjecting);
for (const auto& vol : mVolumes) {
if (vol->destroy()) {
LOG(WARNING) << getId() << " failed to destroy " << vol->getId()
<< " stacked above";
}
}
mVolumes.clear();
status_t res = doUnmount();
setState(State::kUnmounted);
return res;
}
Disk中函数也会调用到,但是我们现在没有插U盘,所以只考虑EmulatedVolume就可以了,所以我们查看是谁调用了EmulatedVolume的destroy。不过我经过查看log,发现了两句关键的log,所以我们现在不需要一点点看代码了。
11-20 08:59:40.795 2521 2673 D StorageManagerService: Thinking about init, mSystemReady=true, mDaemonConnected=true
11-20 08:59:40.795 2521 2673 D StorageManagerService: Thinking about reset, mSystemReady=true, mDaemonConnected=true
11-20 08:59:40.795 2521 2548 I ActivityManager: Force stopping com.android.providers.media appid=10001 user=-1: vold reset
从上面的可以看出,StorageManagerService对vold重新进行了init和reset
,代码如下
private void initIfReadyAndConnected() {
Slog.d(TAG, "Thinking about init, mSystemReady=" + mSystemReady
+ ", mDaemonConnected=" + mDaemonConnected);
if (mSystemReady && mDaemonConnected
&& !StorageManager.isFileEncryptedNativeOnly()) {
// When booting a device without native support, make sure that our
// user directories are locked or unlocked based on the current
// emulation status.
final boolean initLocked = StorageManager.isFileEncryptedEmulatedOnly();
Slog.d(TAG, "Setting up emulation state, initlocked=" + initLocked);
final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
for (UserInfo user : users) {
try {
if (initLocked) {
mVold.lockUserKey(user.id);
} else {
mVold.unlockUserKey(user.id, user.serialNumber, encodeBytes(null),
encodeBytes(null));
}
} catch (Exception e) {
Slog.wtf(TAG, e);
}
}
}
}
private void resetIfReadyAndConnected() {
Slog.d(TAG, "Thinking about reset, mSystemReady=" + mSystemReady
+ ", mDaemonConnected=" + mDaemonConnected);
if (mSystemReady && mDaemonConnected) {
final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
killMediaProvider(users);
final int[] systemUnlockedUsers;
synchronized (mLock) {
systemUnlockedUsers = mSystemUnlockedUsers;
mDisks.clear();
mVolumes.clear();
addInternalVolumeLocked();
}
try {
mVold.reset();
// Tell vold about all existing and started users
for (UserInfo user : users) {
mVold.onUserAdded(user.id, user.serialNumber);
}
for (int userId : systemUnlockedUsers) {
mVold.onUserStarted(userId);
mStoraged.onUserStarted(userId);
}
Log.i(TAG, "resetIfReadyAndConnected() -> mVold.onSecureKeyguardStateChanged(false)");
mVold.onSecureKeyguardStateChanged(false);
// mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
} catch (Exception e) {
Slog.wtf(TAG, e);
}
}
}
这两个函数在下面两个函数中调用
private void handleDaemonConnected() {
initIfReadyAndConnected();
resetIfReadyAndConnected();
// On an encrypted device we can't see system properties yet, so pull
// the system locale out of the mount service.
if ("".equals(SystemProperties.get("vold.encrypt_progress"))) {
copyLocaleFromMountService();
}
}
private void handleSystemReady() {
initIfReadyAndConnected();
resetIfReadyAndConnected();
// Start scheduling nominally-daily fstrim operations
MountServiceIdler.scheduleIdlePass(mContext);
// Toggle zram-enable system property in response to settings
mContext.getContentResolver().registerContentObserver(
Settings.Global.getUriFor(Settings.Global.ZRAM_ENABLED),
false /*notifyForDescendants*/,
new ContentObserver(null /* current thread */) {
@Override
public void onChange(boolean selfChange) {
refreshZramSettings();
}
});
refreshZramSettings();
}
handleSystemReady和handleDaemonConnected 在handleMessage中调用
public void handleMessage(Message msg) {
switch (msg.what) {
case H_SYSTEM_READY: {
handleSystemReady();
break;
}
case H_DAEMON_CONNECTED: {
handleDaemonConnected();
break;
}
case H_FST
是对H_SYSTEM_READY和H_DAEMON_CONNECTED的处理
private void systemReady() {
LocalServices.getService(ActivityManagerInternal.class)
.registerScreenObserver(this);
mSystemReady = true;
mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget();
}
systemready由StorageManagerService的onBootPhase调用 public void onBootPhase(int phase) {
if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
mStorageManagerService.systemReady();
} else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
mStorageManagerService.bootCompleted();
}
}
public void onDaemonConnected() {
mDaemonConnected = true;
mHandler.obtainMessage(H_DAEMON_CONNECTED).sendToTarget();
}
onDaemonConnected由connect调用 private void connect() {
IBinder binder = ServiceManager.getService("storaged");
if (binder != null) {
try {
binder.linkToDeath(new DeathRecipient() {
@Override
public void binderDied() {
Slog.w(TAG, "storaged died; reconnecting");
mStoraged = null;
connect();
}
}, 0);
} catch (RemoteException e) {
binder = null;
}
}
if (binder != null) {
mStoraged = IStoraged.Stub.asInterface(binder);
} else {
Slog.w(TAG, "storaged not found; trying again");
}
binder = ServiceManager.getService("vold");
if (binder != null) {
try {
binder.linkToDeath(new DeathRecipient() {
@Override
public void binderDied() {
Slog.w(TAG, "vold died; reconnecting");
mVold = null;
connect();
}
}, 0);
} catch (RemoteException e) {
binder = null;
}
}
if (binder != null) {
mVold = IVold.Stub.asInterface(binder);
try {
mVold.setListener(mListener);
Log.i(TAG, "connect() -> mVold.onSecureKeyguardStateChanged(false)");
mVold.onSecureKeyguardStateChanged(false);
} catch (RemoteException e) {
mVold = null;
Slog.w(TAG, "vold listener rejected; trying again", e);
}
} else {
Slog.w(TAG, "vold not found; trying again");
}
if (mStoraged == null || mVold == null) {
BackgroundThread.getHandler().postDelayed(() -> {
connect();
}, DateUtils.SECOND_IN_MILLIS);
} else {
onDaemonConnected();
}
}
connect由StorageManagerService的start调用
private void start() {
connect();
}
start是由onStart调用的
public static class Lifecycle extends SystemService {
private StorageManagerService mStorageManagerService;
public Lifecycle(Context context) {
super(context);
}
@Override
public void onStart() {
mStorageManagerService = new StorageManagerService(getContext());
publishBinderService("mount", mStorageManagerService);
mStorageManagerService.start();
}
那到底是onStart还是onBootPhase最终reset的vold,经过添加log,发现是onStart和onBootPhase会依次调用的vold的reset,vold的rest内容如下
binder::Status VoldNativeService::reset() {
ENFORCE_UID(AID_SYSTEM);
ACQUIRE_LOCK;
return translate(VolumeManager::Instance()->reset());
}
int VolumeManager::reset() {
// Tear down all existing disks/volumes and start from a blank slate so
// newly connected framework hears all events.
if (mInternalEmulated != nullptr) {
mInternalEmulated->destroy();
mInternalEmulated->create();
}
for (const auto& disk : mDisks) {
disk->destroy();
disk->create();
}
updateVirtualDisk();
mAddedUsers.clear();
mStartedUsers.clear();
return 0;
}
可以看出确实调用了destroy。
总结下来:StorageManagerService启动后,会reset vold,会将将所有卷都卸载,设置removed,并重新create,如果不在create时,设置状态为Unmounted,会挂载失败,
如有不对之出,敬请指教。