Tests to verify writing of Uri grants.

Bug: 8275867
Change-Id: I035568c3a6feed9d48f72b004c7a729a92c987ea
diff --git a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProvider.java b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProvider.java
index 900664f..aea874b 100644
--- a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProvider.java
+++ b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProvider.java
@@ -20,6 +20,10 @@
 import android.content.ContentValues;
 import android.database.Cursor;
 import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+
+import java.io.File;
+import java.io.FileNotFoundException;
 
 /**
  * Empty content provider, all permissions are enforced in manifest
@@ -58,4 +62,10 @@
             String[] selectionArgs) {
         return 0;
     }
+
+    @Override
+    public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
+        return ParcelFileDescriptor.open(
+                new File("/dev/null"), ParcelFileDescriptor.MODE_READ_ONLY);
+    }
 }
diff --git a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderGranting.java b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderGranting.java
index 97bd827..bb88c34b 100644
--- a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderGranting.java
+++ b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderGranting.java
@@ -20,6 +20,10 @@
 import android.content.ContentValues;
 import android.database.Cursor;
 import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+
+import java.io.File;
+import java.io.FileNotFoundException;
 
 /**
  * Empty content provider, all permissions are enforced in manifest
@@ -58,4 +62,10 @@
             String[] selectionArgs) {
         return 0;
     }
+
+    @Override
+    public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
+        return ParcelFileDescriptor.open(
+                new File("/dev/null"), ParcelFileDescriptor.MODE_READ_ONLY);
+    }
 }
diff --git a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderPath.java b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderPath.java
index 4f301a3..13151f5 100644
--- a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderPath.java
+++ b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderPath.java
@@ -4,6 +4,10 @@
 import android.content.ContentValues;
 import android.database.Cursor;
 import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+
+import java.io.File;
+import java.io.FileNotFoundException;
 
 /**
  * Empty content provider, all permissions are enforced in manifest
@@ -42,4 +46,10 @@
             String[] selectionArgs) {
         return 0;
     }
+
+    @Override
+    public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
+        return ParcelFileDescriptor.open(
+                new File("/dev/null"), ParcelFileDescriptor.MODE_READ_ONLY);
+    }
 }
diff --git a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderPathRestricting.java b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderPathRestricting.java
index 3206206..41dd889 100644
--- a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderPathRestricting.java
+++ b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderPathRestricting.java
@@ -20,6 +20,10 @@
 import android.content.ContentValues;
 import android.database.Cursor;
 import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+
+import java.io.File;
+import java.io.FileNotFoundException;
 
 /**
  * Empty content provider, all permissions are enforced in manifest
@@ -58,4 +62,10 @@
             String[] selectionArgs) {
         return 0;
     }
+
+    @Override
+    public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
+        return ParcelFileDescriptor.open(
+                new File("/dev/null"), ParcelFileDescriptor.MODE_READ_ONLY);
+    }
 }
diff --git a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PrivateContentProvider.java b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PrivateContentProvider.java
index 64ec6e7..6ce5239 100644
--- a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PrivateContentProvider.java
+++ b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PrivateContentProvider.java
@@ -20,6 +20,10 @@
 import android.content.ContentValues;
 import android.database.Cursor;
 import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+
+import java.io.File;
+import java.io.FileNotFoundException;
 
 /**
  * Empty content provider, all permissions are enforced in manifest
@@ -58,4 +62,10 @@
             String[] selectionArgs) {
         return 0;
     }
+
+    @Override
+    public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
+        return ParcelFileDescriptor.open(
+                new File("/dev/null"), ParcelFileDescriptor.MODE_READ_ONLY);
+    }
 }
diff --git a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PrivateContentProviderGranting.java b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PrivateContentProviderGranting.java
index f9ae96b..372b399 100644
--- a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PrivateContentProviderGranting.java
+++ b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PrivateContentProviderGranting.java
@@ -20,6 +20,10 @@
 import android.content.ContentValues;
 import android.database.Cursor;
 import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+
+import java.io.File;
+import java.io.FileNotFoundException;
 
 /**
  * Empty content provider, all permissions are enforced in manifest
@@ -58,4 +62,10 @@
             String[] selectionArgs) {
         return 0;
     }
+
+    @Override
+    public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
+        return ParcelFileDescriptor.open(
+                new File("/dev/null"), ParcelFileDescriptor.MODE_READ_ONLY);
+    }
 }
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java b/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
index 41cddf5..f1022ff 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
@@ -19,6 +19,7 @@
 import android.content.BroadcastReceiver;
 import android.content.ClipData;
 import android.content.ComponentName;
+import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
@@ -28,6 +29,8 @@
 import android.test.AndroidTestCase;
 import android.util.Log;
 
+import java.io.IOException;
+
 /**
  * Tests that signature-enforced permissions cannot be accessed by apps signed
  * with different certs than app that declares the permission.
@@ -85,18 +88,71 @@
         }
     }
 
-    public void assertWritingContentUriNotAllowed(Uri uri, String msg) {
+    private void assertOpenFileDescriptorModeNotAllowed(Uri uri, String msg, String mode) {
         try {
-            getContext().getContentResolver().insert(uri, new ContentValues());
+            getContext().getContentResolver().openFileDescriptor(uri, mode).close();
             fail("expected SecurityException writing " + uri + ": " + msg);
+        } catch (IOException e) {
+            throw new IllegalStateException(e);
         } catch (SecurityException expected) {
             assertNotNull("security exception's error message.", expected.getMessage());
         }
     }
 
-    public void assertWritingContentUriAllowed(Uri uri) {
+    public void assertWritingContentUriNotAllowed(Uri uri, String msg) {
+        final ContentResolver resolver = getContext().getContentResolver();
         try {
-            getContext().getContentResolver().insert(uri, new ContentValues());
+            resolver.insert(uri, new ContentValues());
+            fail("expected SecurityException inserting " + uri + ": " + msg);
+        } catch (SecurityException expected) {
+            assertNotNull("security exception's error message.", expected.getMessage());
+        }
+
+        try {
+            resolver.update(uri, new ContentValues(), null, null);
+            fail("expected SecurityException updating " + uri + ": " + msg);
+        } catch (SecurityException expected) {
+            assertNotNull("security exception's error message.", expected.getMessage());
+        }
+
+        try {
+            resolver.delete(uri, null, null);
+            fail("expected SecurityException deleting " + uri + ": " + msg);
+        } catch (SecurityException expected) {
+            assertNotNull("security exception's error message.", expected.getMessage());
+        }
+
+        try {
+            getContext().getContentResolver().openOutputStream(uri).close();
+            fail("expected SecurityException writing " + uri + ": " + msg);
+        } catch (IOException e) {
+            throw new IllegalStateException(e);
+        } catch (SecurityException expected) {
+            assertNotNull("security exception's error message.", expected.getMessage());
+        }
+
+        assertOpenFileDescriptorModeNotAllowed(uri, msg, "w");
+        assertOpenFileDescriptorModeNotAllowed(uri, msg, "wt");
+        assertOpenFileDescriptorModeNotAllowed(uri, msg, "wa");
+        assertOpenFileDescriptorModeNotAllowed(uri, msg, "rw");
+        assertOpenFileDescriptorModeNotAllowed(uri, msg, "rwt");
+    }
+
+    public void assertWritingContentUriAllowed(Uri uri) {
+        final ContentResolver resolver = getContext().getContentResolver();
+        try {
+            resolver.insert(uri, new ContentValues());
+            resolver.update(uri, new ContentValues(), null, null);
+            resolver.delete(uri, null, null);
+
+            resolver.openOutputStream(uri).close();
+            resolver.openFileDescriptor(uri, "w").close();
+            resolver.openFileDescriptor(uri, "wt").close();
+            resolver.openFileDescriptor(uri, "wa").close();
+            resolver.openFileDescriptor(uri, "rw").close();
+            resolver.openFileDescriptor(uri, "rwt").close();
+        } catch (IOException e) {
+            fail("unexpected IOException writing " + uri + ": " + e.getMessage());
         } catch (SecurityException e) {
             fail("unexpected SecurityException writing " + uri);
         }