Mirror was previously used for accessing the original file during
magic mount when we are using a tmpfs to cover the target. However,
since we introduce atomic mount, we switch all tmpfs mount in
worker and then move to the target at once. It means that we can
still access the original file when we are constructing the tmpfs
mount point. Thus we no longer need mirror.
Previous we hexpatch /init from /system/bin/init to /data/magiskinit
to redirect the second stage init. However, some devices like sony
has /init that does not directly invoke /system/bin/init, and thus
the hexpatch fails.
In this patch, we further make use of AOSP `SwitchRoot` to help us
bind mount /data/magisk to /system/bin/init after `SwitchRoot`.
Two important assumption about 2SI are i) that the second stage init
is always /system/bin/init and ii) that the /sdcard (path after
`SwitchRoot`) is always a symlink to `/storage/self/primary`. When
these assumptions hold, during first stage init (before `SwitchRoot`)
we can bind mount magiskinit to /sdcard, and create a symlink
/storage/self/primary to /system/system/bin/init. By these steps,
during `SwitchRoot`, AOSP init will try to mount move /sdcard to
/system/sdcard. And /system/sdcard is symlink to /storage/self/primary,
it will try to mount move /sdcard to /storage/self/primary. And
/storage/self/primary in ramfs is now a symlink that points to
/system/system/bin/init, thus AOSP will try to mount move /sdcard
(which is a bind mount to magiskinit) to /system/system/bin/init.
After chroot done by AOSP init, we then have a magiskinit bind mount
on /system/bin/init, which is the second stage init.
An edge case is that some devices (like meizu) use 2SI but
does not switch root. In this case, they must already have a /sdcard
in the ramfs, thus we can check if /sdcard exists and fallback to
hexpatch.