Change containsMount() to look for any user-id.

On devices with app cloning, we may be responsible for storage paths
that represent a different user-id than the one that we are running as.
Change containsMount() to accept any user-id.

Bug: 200134631
Test: TEST_MAPPING, atest FuseUtilsTest
Change-Id: I4387beeed5925b9e43c4f45d0f5e9ed2f6a196d5
Merged-In: I4387beeed5925b9e43c4f45d0f5e9ed2f6a196d5
diff --git a/jni/FuseDaemon.cpp b/jni/FuseDaemon.cpp
index 21e752c..1e2a82b 100755
--- a/jni/FuseDaemon.cpp
+++ b/jni/FuseDaemon.cpp
@@ -392,7 +392,7 @@
 // deadlocking the kernel
 static void fuse_inval(fuse_session* se, fuse_ino_t parent_ino, fuse_ino_t child_ino,
                        const string& child_name, const string& path) {
-    if (mediaprovider::fuse::containsMount(path, MY_USER_ID_STRING)) {
+    if (mediaprovider::fuse::containsMount(path)) {
         LOG(WARNING) << "Ignoring attempt to invalidate dentry for FUSE mounts";
         return;
     }
@@ -536,7 +536,7 @@
         ino_t ino = e->attr.st_ino;
         node = ::node::Create(parent, name, io_path, should_invalidate, transforms_complete,
                               transforms, transforms_reason, &fuse->lock, ino, &fuse->tracker);
-    } else if (!mediaprovider::fuse::containsMount(path, std::to_string(getuid() / PER_USER_RANGE))) {
+    } else if (!mediaprovider::fuse::containsMount(path)) {
         // Only invalidate a path if it does not contain mount.
         // Invalidate both names to ensure there's no dentry left in the kernel after the following
         // operations:
diff --git a/jni/FuseUtils.cpp b/jni/FuseUtils.cpp
index 7829888..9f30440 100644
--- a/jni/FuseUtils.cpp
+++ b/jni/FuseUtils.cpp
@@ -26,7 +26,7 @@
 namespace mediaprovider {
 namespace fuse {
 
-bool containsMount(const string& path, const string& userid) {
+bool containsMount(const string& path) {
     // This method is called from lookup, so it's called rather frequently.
     // Hence, we avoid concatenating the strings and we use 3 separate suffixes.
 
@@ -35,16 +35,20 @@
         return false;
     }
 
-    const string& rest_of_path = path.substr(prefix.length());
-    if (!android::base::StartsWithIgnoreCase(rest_of_path, userid)) {
+    // Skip over the user-id by finding the next '/'
+    size_t pos = path.find_first_of("/", prefix.length());
+    // If we can't find another '/', or the '/' immediately follows the previous,
+    // ('/storage/emulated//'), not a valid mount.
+    if (pos == std::string::npos || pos == prefix.length()) {
         return false;
     }
 
+    const string& path_suffix = path.substr(pos);
+
     static const string android_suffix = "/Android";
     static const string data_suffix = "/Android/data";
     static const string obb_suffix = "/Android/obb";
 
-    const string& path_suffix = rest_of_path.substr(userid.length());
     return android::base::EqualsIgnoreCase(path_suffix, android_suffix) ||
            android::base::EqualsIgnoreCase(path_suffix, data_suffix) ||
            android::base::EqualsIgnoreCase(path_suffix, obb_suffix);
diff --git a/jni/FuseUtilsTest.cpp b/jni/FuseUtilsTest.cpp
index d9d28e6..dede692 100644
--- a/jni/FuseUtilsTest.cpp
+++ b/jni/FuseUtilsTest.cpp
@@ -23,44 +23,41 @@
 using namespace mediaprovider::fuse;
 
 TEST(FuseUtilsTest, testContainsMount_isTrueForAndroidDataObb) {
-    EXPECT_TRUE(containsMount("/storage/emulated/1234/Android", "1234"));
-    EXPECT_TRUE(containsMount("/storage/emulated/1234/Android/data", "1234"));
-    EXPECT_TRUE(containsMount("/storage/emulated/1234/Android/obb", "1234"));
+    EXPECT_TRUE(containsMount("/storage/emulated/1234/Android"));
+    EXPECT_TRUE(containsMount("/storage/emulated/5678/Android"));
+    EXPECT_TRUE(containsMount("/storage/emulated/1234/Android/data"));
+    EXPECT_TRUE(containsMount("/storage/emulated/5678/Android/obb"));
+    EXPECT_TRUE(containsMount("/storage/emulated/1234/Android/obb"));
+    EXPECT_TRUE(containsMount("/storage/emulated/5678/Android/obb"));
 }
 
 TEST(FuseUtilsTest, testContainsMount) {
-    EXPECT_FALSE(containsMount("/random/path", "1234"));
-    EXPECT_FALSE(containsMount("/storage/abc-123", "1234"));
-    EXPECT_FALSE(containsMount("/storage/emulated/1234/Android/data/and/more", "1234"));
+    EXPECT_FALSE(containsMount("/random/path"));
+    EXPECT_FALSE(containsMount("/storage/abc-123"));
+    EXPECT_FALSE(containsMount("/storage/emulated/1234/Android/data/and/more"));
+    EXPECT_FALSE(containsMount("/storage/emulated"));
+    EXPECT_FALSE(containsMount("/storage/emulated/"));
+    EXPECT_FALSE(containsMount("/storage/emulated//"));
+    EXPECT_FALSE(containsMount("/storage/emulated/0/"));
+    EXPECT_FALSE(containsMount("/storage/emulated/1234/"));
 }
 
 TEST(FuseUtilsTest, testContainsMount_isCaseInsensitive) {
-    EXPECT_TRUE(containsMount("/storage/emulated/1234/android", "1234"));
-    EXPECT_TRUE(containsMount("/storage/emulated/1234/Android/Data", "1234"));
-    EXPECT_TRUE(containsMount("/storage/emulated/1234/ANDroid/dATa", "1234"));
-    EXPECT_TRUE(containsMount("/storage/emulated/1234/ANDROID/OBB", "1234"));
-    EXPECT_TRUE(containsMount("/Storage/EMULATED/1234/Android/obb", "1234"));
-}
-
-TEST(FuseUtilsTest, testContainsMount_isCaseInsensitiveForUserid) {
-    EXPECT_TRUE(containsMount("/storage/emulated/UserId/Android", "UserId"));
-    EXPECT_TRUE(containsMount("/storage/emulated/userid/Android/obb", "Userid"));
-    EXPECT_TRUE(containsMount("/storage/emulated/Userid/Android/obb", "userid"));
+    EXPECT_TRUE(containsMount("/storage/emulated/1234/android"));
+    EXPECT_TRUE(containsMount("/storage/emulated/1234/Android/Data"));
+    EXPECT_TRUE(containsMount("/storage/emulated/1234/ANDroid/dATa"));
+    EXPECT_TRUE(containsMount("/storage/emulated/1234/ANDROID/OBB"));
+    EXPECT_TRUE(containsMount("/Storage/EMULATED/1234/Android/obb"));
 }
 
 TEST(FuseUtilsTest, testContainsMount_isFalseForPathWithAdditionalSlash) {
-    EXPECT_FALSE(containsMount("/storage/emulated/1234/Android/", "1234"));
-    EXPECT_FALSE(containsMount("/storage/emulated/1234/Android/data/", "1234"));
-    EXPECT_FALSE(containsMount("/storage/emulated/1234/Android/obb/", "1234"));
+    EXPECT_FALSE(containsMount("/storage/emulated//Android/data"));
 
-    EXPECT_FALSE(containsMount("//storage/emulated/1234/Android", "1234"));
-    EXPECT_FALSE(containsMount("/storage/emulated//1234/Android/data", "1234"));
-    EXPECT_FALSE(containsMount("/storage/emulated/1234//Android/data", "1234"));
-}
+    EXPECT_FALSE(containsMount("/storage/emulated/1234/Android/"));
+    EXPECT_FALSE(containsMount("/storage/emulated/1234/Android/data/"));
+    EXPECT_FALSE(containsMount("/storage/emulated/1234/Android/obb/"));
 
-TEST(FuseUtilsTest, testContainsMount_isFalseForPathWithWrongUserid) {
-    EXPECT_FALSE(containsMount("/storage/emulated/11234/Android", "1234"));
-    EXPECT_FALSE(containsMount("/storage/emulated/0/Android/data", "1234"));
-    EXPECT_FALSE(containsMount("/storage/emulated/12345/Android/obb", "1234"));
-    EXPECT_FALSE(containsMount("/storage/emulated/1234/Android/obb", "5678"));
+    EXPECT_FALSE(containsMount("//storage/emulated/1234/Android"));
+    EXPECT_FALSE(containsMount("/storage/emulated//1234/Android/data"));
+    EXPECT_FALSE(containsMount("/storage/emulated/1234//Android/data"));
 }
diff --git a/jni/include/libfuse_jni/FuseUtils.h b/jni/include/libfuse_jni/FuseUtils.h
index 88044db..0e35099 100644
--- a/jni/include/libfuse_jni/FuseUtils.h
+++ b/jni/include/libfuse_jni/FuseUtils.h
@@ -23,13 +23,13 @@
 namespace fuse {
 
 /**
- * Returns true if the given path (ignoring case) is mounted for the given
+ * Returns true if the given path (ignoring case) is mounted for any
  * userid. Mounted paths are:
  * "/storage/emulated/<userid>/Android"
  * "/storage/emulated/<userid>/Android/data"
  * "/storage/emulated/<userid>/Android/obb" *
  */
-bool containsMount(const std::string& path, const std::string& userid);
+bool containsMount(const std::string& path);
 
 }  // namespace fuse
 }  // namespace mediaprovider