Limit rename() workaround to /storage/emulated.
This workaround was intended to silently fix EXDEV move failures due to the /Android/data and /Android/obb bind mounts. However, the workaround should be limited to moves to *and* from the emulated filesystem. For moves from the emulated filesystem to another filesystem (or vice-versa), this would never have worked in the first place, and we want to give the app this feedback, so it knows it needs to do a more expensive copy operation and can show this in the UI. We know some apps (like DocsUI) already handle this. Public volumes (eg /storage/ABCD-1234) don't need this workaround, since they don't have the bind mounts. Private volumes that aren't primary don't have these bind mounts either. Bug: 146430607 Test: N/A Change-Id: I7bfe88e07708fe044ce8df02000a97cfad19bdee
This commit is contained in:
@@ -7455,7 +7455,15 @@ public final class ActivityThread extends ClientTransactionHandler {
|
||||
try {
|
||||
super.rename(oldPath, newPath);
|
||||
} catch (ErrnoException e) {
|
||||
if (e.errno == OsConstants.EXDEV && oldPath.startsWith("/storage/")) {
|
||||
// On emulated volumes, we have bind mounts for /Android/data and
|
||||
// /Android/obb, which prevents move from working across those directories
|
||||
// and other directories on the filesystem. To work around that, try to
|
||||
// recover by doing a copy instead.
|
||||
// Note that we only do this for "/storage/emulated", because public volumes
|
||||
// don't have these bind mounts, neither do private volumes that are not
|
||||
// the primary storage.
|
||||
if (e.errno == OsConstants.EXDEV && oldPath.startsWith("/storage/emulated")
|
||||
&& newPath.startsWith("/storage/emulated")) {
|
||||
Log.v(TAG, "Recovering failed rename " + oldPath + " to " + newPath);
|
||||
try {
|
||||
Files.move(new File(oldPath).toPath(), new File(newPath).toPath(),
|
||||
|
||||
Reference in New Issue
Block a user