Merge "Merge "Remove logtags property" am: f2ed7683da am: 9367657b27 am: a7cfd1e93d"
diff --git a/tests/testables/src/android/testing/TestableContext.java b/tests/testables/src/android/testing/TestableContext.java
index 498d517..ffe7219 100644
--- a/tests/testables/src/android/testing/TestableContext.java
+++ b/tests/testables/src/android/testing/TestableContext.java
@@ -25,6 +25,7 @@
 import android.content.ServiceConnection;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
+import android.net.Uri;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.UserHandle;
@@ -69,6 +70,7 @@
     private LeakCheck.Tracker mService;
     private LeakCheck.Tracker mComponent;
     private TestableResources mTestableResources;
+    private TestablePermissions mTestablePermissions;
 
     public TestableContext(Context base) {
         this(base, null);
@@ -302,6 +304,159 @@
         super.unregisterComponentCallbacks(callback);
     }
 
+    public TestablePermissions getTestablePermissions() {
+        if (mTestablePermissions == null) {
+            mTestablePermissions = new TestablePermissions();
+        }
+        return mTestablePermissions;
+    }
+
+    @Override
+    public int checkCallingOrSelfPermission(String permission) {
+        if (mTestablePermissions != null && mTestablePermissions.wantsCall(permission)) {
+            return mTestablePermissions.check(permission);
+        }
+        return super.checkCallingOrSelfPermission(permission);
+    }
+
+    @Override
+    public int checkCallingPermission(String permission) {
+        if (mTestablePermissions != null && mTestablePermissions.wantsCall(permission)) {
+            return mTestablePermissions.check(permission);
+        }
+        return super.checkCallingPermission(permission);
+    }
+
+    @Override
+    public int checkPermission(String permission, int pid, int uid) {
+        if (mTestablePermissions != null && mTestablePermissions.wantsCall(permission)) {
+            return mTestablePermissions.check(permission);
+        }
+        return super.checkPermission(permission, pid, uid);
+    }
+
+    @Override
+    public int checkPermission(String permission, int pid, int uid, IBinder callerToken) {
+        if (mTestablePermissions != null && mTestablePermissions.wantsCall(permission)) {
+            return mTestablePermissions.check(permission);
+        }
+        return super.checkPermission(permission, pid, uid, callerToken);
+    }
+
+    @Override
+    public int checkSelfPermission(String permission) {
+        if (mTestablePermissions != null && mTestablePermissions.wantsCall(permission)) {
+            return mTestablePermissions.check(permission);
+        }
+        return super.checkSelfPermission(permission);
+    }
+
+    @Override
+    public void enforceCallingOrSelfPermission(String permission, String message) {
+        if (mTestablePermissions != null && mTestablePermissions.wantsCall(permission)) {
+            mTestablePermissions.enforce(permission);
+        } else {
+            super.enforceCallingOrSelfPermission(permission, message);
+        }
+    }
+
+    @Override
+    public void enforceCallingPermission(String permission, String message) {
+        if (mTestablePermissions != null && mTestablePermissions.wantsCall(permission)) {
+            mTestablePermissions.enforce(permission);
+        } else {
+            super.enforceCallingPermission(permission, message);
+        }
+    }
+
+    @Override
+    public void enforcePermission(String permission, int pid, int uid, String message) {
+        if (mTestablePermissions != null && mTestablePermissions.wantsCall(permission)) {
+            mTestablePermissions.enforce(permission);
+        } else {
+            super.enforcePermission(permission, pid, uid, message);
+        }
+    }
+
+    @Override
+    public int checkCallingOrSelfUriPermission(Uri uri, int modeFlags) {
+        if (mTestablePermissions != null && mTestablePermissions.wantsCall(uri)) {
+            return mTestablePermissions.check(uri, modeFlags);
+        }
+        return super.checkCallingOrSelfUriPermission(uri, modeFlags);
+    }
+
+    @Override
+    public int checkCallingUriPermission(Uri uri, int modeFlags) {
+        if (mTestablePermissions != null && mTestablePermissions.wantsCall(uri)) {
+            return mTestablePermissions.check(uri, modeFlags);
+        }
+        return super.checkCallingUriPermission(uri, modeFlags);
+    }
+
+    @Override
+    public void enforceCallingOrSelfUriPermission(Uri uri, int modeFlags, String message) {
+        if (mTestablePermissions != null && mTestablePermissions.wantsCall(uri)) {
+            mTestablePermissions.enforce(uri, modeFlags);
+        } else {
+            super.enforceCallingOrSelfUriPermission(uri, modeFlags, message);
+        }
+    }
+
+    @Override
+    public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
+        if (mTestablePermissions != null && mTestablePermissions.wantsCall(uri)) {
+            return mTestablePermissions.check(uri, modeFlags);
+        }
+        return super.checkUriPermission(uri, pid, uid, modeFlags);
+    }
+
+    @Override
+    public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags, IBinder callerToken) {
+        if (mTestablePermissions != null && mTestablePermissions.wantsCall(uri)) {
+            return mTestablePermissions.check(uri, modeFlags);
+        }
+        return super.checkUriPermission(uri, pid, uid, modeFlags, callerToken);
+    }
+
+    @Override
+    public int checkUriPermission(Uri uri, String readPermission, String writePermission, int pid,
+            int uid, int modeFlags) {
+        if (mTestablePermissions != null && mTestablePermissions.wantsCall(uri)) {
+            return mTestablePermissions.check(uri, modeFlags);
+        }
+        return super.checkUriPermission(uri, readPermission, writePermission, pid, uid, modeFlags);
+    }
+
+    @Override
+    public void enforceCallingUriPermission(Uri uri, int modeFlags, String message) {
+        if (mTestablePermissions != null && mTestablePermissions.wantsCall(uri)) {
+            mTestablePermissions.enforce(uri, modeFlags);
+        } else {
+            super.enforceCallingUriPermission(uri, modeFlags, message);
+        }
+    }
+
+    @Override
+    public void enforceUriPermission(Uri uri, int pid, int uid, int modeFlags, String message) {
+        if (mTestablePermissions != null && mTestablePermissions.wantsCall(uri)) {
+            mTestablePermissions.enforce(uri, modeFlags);
+        } else {
+            super.enforceUriPermission(uri, pid, uid, modeFlags, message);
+        }
+    }
+
+    @Override
+    public void enforceUriPermission(Uri uri, String readPermission, String writePermission,
+            int pid, int uid, int modeFlags, String message) {
+        if (mTestablePermissions != null && mTestablePermissions.wantsCall(uri)) {
+            mTestablePermissions.enforce(uri, modeFlags);
+        } else {
+            super.enforceUriPermission(uri, readPermission, writePermission, pid, uid, modeFlags,
+                    message);
+        }
+    }
+
     @Override
     public Statement apply(Statement base, Description description) {
         return new TestWatcher() {
diff --git a/tests/testables/src/android/testing/TestablePermissions.java b/tests/testables/src/android/testing/TestablePermissions.java
new file mode 100644
index 0000000..4f009e4
--- /dev/null
+++ b/tests/testables/src/android/testing/TestablePermissions.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package android.testing;
+
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.util.ArrayMap;
+
+/**
+ * Simple class for simulating basic permission states for tests.
+ *
+ * All enforce* and check* calls on TestableContext are considered the same
+ * and routed through the same check here. If more fine-grained control is
+ * required, then either a sub-class or spy on TestableContext is recommended.
+ */
+public class TestablePermissions {
+
+    private final ArrayMap<String, Integer> mPermissions = new ArrayMap<>();
+    private final ArrayMap<Uri, Integer> mUris = new ArrayMap<>();
+
+    /**
+     * Sets the return value for checkPermission* calls on TestableContext
+     * for a specific permission value. For all enforcePermission* calls
+     * they will throw a security exception if value != PERMISSION_GRANTED.
+     */
+    public void setPermission(String permission, int value) {
+        mPermissions.put(permission, value);
+    }
+
+    /**
+     * Sets the return value for checkUriPermission* calls on TestableContext
+     * for a specific permission value. For all enforceUriPermission* calls
+     * they will throw a security exception if value != PERMISSION_GRANTED.
+     */
+    public void setPermission(Uri uri, int value) {
+        // TODO: Support modeFlags
+        mUris.put(uri, value);
+    }
+
+    boolean wantsCall(String permission) {
+        return mPermissions.containsKey(permission);
+    }
+
+    boolean wantsCall(Uri uri) {
+        return mUris.containsKey(uri);
+    }
+
+    int check(String permission) {
+        return mPermissions.get(permission);
+    }
+
+    int check(Uri uri, int modeFlags) {
+        // TODO: Support modeFlags
+        return mUris.get(uri);
+    }
+
+    public void enforce(String permission) {
+        if (check(permission) != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException();
+        }
+    }
+
+    public void enforce(Uri uri, int modeFlags) {
+        if (check(uri, modeFlags) != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException();
+        }
+    }
+}
diff --git a/tests/testables/tests/src/android/testing/TestablePermissionsTest.java b/tests/testables/tests/src/android/testing/TestablePermissionsTest.java
new file mode 100644
index 0000000..c56146e
--- /dev/null
+++ b/tests/testables/tests/src/android/testing/TestablePermissionsTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package android.testing;
+
+import static android.content.pm.PackageManager.PERMISSION_DENIED;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+
+import static org.junit.Assert.assertEquals;
+
+import android.Manifest.permission;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.testing.TestableLooper.RunWithLooper;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class TestablePermissionsTest {
+
+    private static final Uri URI_1 = Uri.parse("content://my.authority/path1");
+    private static final Uri URI_2 = Uri.parse("content://my.authority/path2");
+
+    @Rule
+    public TestableContext mContext = new TestableContext(InstrumentationRegistry.getContext());
+
+    @Test
+    public void testCheck() {
+        mContext.getTestablePermissions().setPermission(permission.INTERACT_ACROSS_USERS,
+                PERMISSION_GRANTED);
+        mContext.getTestablePermissions().setPermission(permission.INTERACT_ACROSS_USERS_FULL,
+                PERMISSION_DENIED);
+        assertEquals(PERMISSION_GRANTED,
+                mContext.checkPermission(permission.INTERACT_ACROSS_USERS, 0, 0));
+        assertEquals(PERMISSION_DENIED,
+                mContext.checkPermission(permission.INTERACT_ACROSS_USERS_FULL, 0, 0));
+    }
+
+    @Test
+    public void testCheckUri() {
+        mContext.getTestablePermissions().setPermission(URI_1, PERMISSION_GRANTED);
+        mContext.getTestablePermissions().setPermission(URI_2, PERMISSION_DENIED);
+
+        assertEquals(PERMISSION_GRANTED, mContext.checkUriPermission(URI_1, 0, 0, 0));
+        assertEquals(PERMISSION_DENIED, mContext.checkUriPermission(URI_2, 0, 0, 0));
+    }
+
+    @Test
+    public void testEnforceNoException() {
+        mContext.getTestablePermissions().setPermission(permission.INTERACT_ACROSS_USERS,
+                PERMISSION_GRANTED);
+        mContext.enforceCallingOrSelfPermission(permission.INTERACT_ACROSS_USERS, "");
+    }
+
+    @Test(expected = SecurityException.class)
+    public void testEnforceWithException() {
+        mContext.getTestablePermissions().setPermission(permission.INTERACT_ACROSS_USERS,
+                PERMISSION_DENIED);
+        mContext.enforceCallingOrSelfPermission(permission.INTERACT_ACROSS_USERS, "");
+    }
+
+    @Test
+    public void testEnforceUriNoException() {
+        mContext.getTestablePermissions().setPermission(URI_1, PERMISSION_GRANTED);
+        mContext.enforceUriPermission(URI_1, 0, 0, 0, "");
+    }
+
+    @Test(expected = SecurityException.class)
+    public void testEnforceUriWithException() {
+        mContext.getTestablePermissions().setPermission(URI_1, PERMISSION_DENIED);
+        mContext.enforceUriPermission(URI_1, 0, 0, 0, "");
+    }
+
+}
\ No newline at end of file