Merge "Check both permission and AppOp in pollForPermission"
diff --git a/tests/jni/FuseDaemonTest/legacy/src/com/android/tests/fused/legacy/LegacyFileAccessTest.java b/tests/jni/FuseDaemonTest/legacy/src/com/android/tests/fused/legacy/LegacyFileAccessTest.java
index 1b09f5e..2f897de 100644
--- a/tests/jni/FuseDaemonTest/legacy/src/com/android/tests/fused/legacy/LegacyFileAccessTest.java
+++ b/tests/jni/FuseDaemonTest/legacy/src/com/android/tests/fused/legacy/LegacyFileAccessTest.java
@@ -18,12 +18,13 @@
 
 import static com.android.tests.fused.lib.TestUtils.pollForExternalStorageState;
 
+import static com.android.tests.fused.lib.TestUtils.pollForPermission;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.junit.Assert.fail;
 
 import android.Manifest;
-import android.content.pm.PackageManager;
 import android.os.Environment;
 import android.system.ErrnoException;
 import android.system.Os;
@@ -56,9 +57,6 @@
 
     private static final String TAG = "LegacyFileAccessTest";
 
-    private static final long POLLING_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(10);
-    private static final long POLLING_SLEEP_MILLIS = 100;
-
     @Before
     public void setUp() throws Exception {
         pollForExternalStorageState();
@@ -396,20 +394,4 @@
         assertThat(oldPath.exists()).isFalse();
         assertThat(newPath.exists()).isTrue();
     }
-
-    private boolean isPermissionGranted(String perm) {
-        return InstrumentationRegistry.getContext().checkCallingOrSelfPermission(perm)
-                == PackageManager.PERMISSION_GRANTED;
-    }
-
-    private void pollForPermission(String perm, boolean granted) throws Exception {
-        for (int i = 0; i < POLLING_TIMEOUT_MILLIS / POLLING_SLEEP_MILLIS; i++) {
-            if (granted == isPermissionGranted(perm)) {
-                return;
-            }
-            Thread.sleep(POLLING_SLEEP_MILLIS);
-        }
-        fail("Timed out while waiting for permission " + perm + " to be "
-                + (granted ? "granted" : "revoked"));
-    }
 }
diff --git a/tests/jni/FuseDaemonTest/libs/FuseDaemonTestLib/src/com/android/tests/fused/lib/TestUtils.java b/tests/jni/FuseDaemonTest/libs/FuseDaemonTestLib/src/com/android/tests/fused/lib/TestUtils.java
index e564915..d451ece 100644
--- a/tests/jni/FuseDaemonTest/libs/FuseDaemonTestLib/src/com/android/tests/fused/lib/TestUtils.java
+++ b/tests/jni/FuseDaemonTest/libs/FuseDaemonTestLib/src/com/android/tests/fused/lib/TestUtils.java
@@ -36,11 +36,13 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.PackageManager;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Environment;
 import android.os.ParcelFileDescriptor;
 import android.provider.MediaStore;
+import android.system.Os;
 import android.util.Log;
 
 import androidx.annotation.NonNull;
@@ -76,7 +78,6 @@
     private static final long POLLING_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(10);
     private static final long POLLING_SLEEP_MILLIS = 100;
 
-
     private static final UiAutomation sUiAutomation = InstrumentationRegistry.getInstrumentation()
             .getUiAutomation();
 
@@ -396,6 +397,43 @@
         fail("Timed out while waiting for ExternalStorageState to be MEDIA_MOUNTED");
     }
 
+    public static void pollForPermission(String perm, boolean granted) throws Exception {
+        for (int i = 0; i < POLLING_TIMEOUT_MILLIS / POLLING_SLEEP_MILLIS; i++) {
+            if (granted == checkPermissionAndAppOp(perm)) {
+                return;
+            }
+            Thread.sleep(POLLING_SLEEP_MILLIS);
+        }
+        fail("Timed out while waiting for permission " + perm + " to be "
+                + (granted ? "granted" : "revoked"));
+    }
+
+    /**
+     * Checks if the given {@code permission} is granted and corresponding AppOp is MODE_ALLOWED.
+     */
+    private static boolean checkPermissionAndAppOp(String permission) {
+        final int pid  = Os.getpid();
+        final int uid = Os.getuid();
+        final Context context = getContext();
+        final String packageName = context.getPackageName();
+        if (context.checkPermission(permission, pid, uid) != PackageManager.PERMISSION_GRANTED) {
+            return false;
+        }
+
+        final String op = AppOpsManager.permissionToOp(permission);
+        // No AppOp associated with the given permission, skip AppOp check.
+        if (op == null) return true;
+
+        final AppOpsManager appOps = context.getSystemService(AppOpsManager.class);
+        try {
+            appOps.checkPackage(uid, packageName);
+        } catch (SecurityException e) {
+            return false;
+        }
+
+        return appOps.unsafeCheckOpNoThrow(op, uid, packageName) == AppOpsManager.MODE_ALLOWED;
+    }
+
     /**
      * <p>This method drops shell permission identity.
      */