Android P Vold分析 VolumeBase::create()中的setState(State::kUnmounted)

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的处理

  • H_SYSTEM_READY消息由systemReady发出
        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();
            }
        }
  • H_DAEMON_CONNECTED由onDaemonConnected发出
        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,会挂载失败,
如有不对之出,敬请指教。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值