From 76ce2ccb191494ae1ec3cbdcf591183a5c8f4d55 Mon Sep 17 00:00:00 2001 From: Martijn Coenen Date: Tue, 12 May 2020 10:11:38 +0200 Subject: 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 --- core/java/android/app/ActivityThread.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'core/java/android/app/ActivityThread.java') diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index e97ebd7eee06..696f9acfabe2 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -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(), -- cgit v1.2.3