Android P Vold分析VolumeBase::create()のsetState(State::kUnmounted)
VolumeBaseは構造時に状態をUnmountedに設定していますが、なぜcreateで再設定するのでしょうか.次はVolumeBaseの構造です
次はcreate関数です
ここでcreateで再び状態をUnmountedに設定しているのが見えますが、その前にこの状態を変える人はいますか?この問題について、私は何日も考えていたが、理解できなかった.しかし、この言葉を消してしまうと、間違いを報告してしまいます.
失敗した理由は、Emulatedボリュームのステータスがunmountedまたはunmountableではないためです.誰がその状態を変更したのか、log
Volumeがアンインストールされると、この関数が呼び出されます.
Diskでは関数も呼び出されますが、私たちは今Uディスクを挿入していないので、EmulatedVolumeだけを考慮すればいいので、誰がEmulatedVolumeのdestroyを呼び出したのかを確認します.しかし、私はロゴを見て、2つの重要なロゴを見つけたので、コードを少し見る必要はありません.
上記から分かるように、
この2つの関数は次の2つの関数で呼び出されます.
handleSystemReadyとhandleDaemonConnectedがhandleMessageで呼び出されます
はい、そうです.SYSTEM_READYとH_DAEMON_CONNECTEDの処理 H_SYSTEM_READYメッセージは、システムReadyによって発行する である. H_DAEMON_CONNECTEDは、onDaemonConnectedから発行された です.
接続はStorageManagerServiceのstartによって呼び出されます
startはonStartによって呼び出されます
それがonStartなのかonBootPhase最終resetのvoldなのか、logを追加するとonStartとonBootPhaseが順次呼び出すvoldのresetなのか、voldのrestの内容は以下の通りです
destroyが呼び出されたことがわかります.まとめ:
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の処理
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();
}
}
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, ,
間違いがあったら、ご指導ください.