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

52394 ワード

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に設定しているのが見えますが、その前にこの状態を変える人はいますか?この問題について、私は何日も考えていたが、理解できなかった.しかし、この言葉を消してしまうと、間違いを報告してしまいます.
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,を追加してソースコードを表示し、1つの場所だけが状態を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を呼び出したのかを確認します.しかし、私はロゴを見て、2つの重要なロゴを見つけたので、コードを少し見る必要はありません.
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);
            }
        }
    }

この2つの関数は次の2つの関数で呼び出されます.
    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

はい、そうです.SYSTEM_READYとH_DAEMON_CONNECTEDの処理
  • H_SYSTEM_READYメッセージは、システムReadyによって発行する
        private void systemReady() {
        LocalServices.getService(ActivityManagerInternal.class)
                .registerScreenObserver(this);
    
        mSystemReady = true;
        mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget();
    }
    システムreadyは、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();
        }
    }
  • です.
    接続は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, ,間違いがあったら、ご指導ください.