Merge "Add a CTS test for multinetwork features." into lmp-dev
diff --git a/tests/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java b/tests/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
index e953305..f62ac60 100644
--- a/tests/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
+++ b/tests/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
@@ -19,7 +19,9 @@
 import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.provider.Settings;
 import android.test.AndroidTestCase;
 import android.util.Log;
 
@@ -220,4 +222,198 @@
         assertFalse(mDevicePolicyManager.resetPassword("abcd", 0));
         assertTrue(mDevicePolicyManager.resetPassword("abcd123", 0));
     }
+
+    public void testCreateUser_failIfNotDeviceOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testCreateUser_failIfNotDeviceOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.createUser(mComponent, "user name");
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertDeviceOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testRemoveUser_failIfNotDeviceOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testRemoveUser_failIfNotDeviceOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.removeUser(mComponent, null);
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertDeviceOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testSetApplicationBlocked_failIfNotDeviceOrProfileOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testSetApplicationBlocked_failIfNotDeviceOrProfileOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.setApplicationBlocked(mComponent, "com.google.anything", true);
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertProfileOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testSetApplicationsBlocked_failIfNotDeviceOrProfileOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testSetApplicationsBlocked_failIfNotDeviceOrProfileOwner");
+            return;
+        }
+        try {
+            Intent pdfViewIntent = new Intent(Intent.ACTION_VIEW).setType("application/pdf");
+            mDevicePolicyManager.setApplicationsBlocked(mComponent, pdfViewIntent, true);
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertProfileOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testIsApplicationBlocked_failIfNotDeviceOrProfileOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testIsApplicationBlocked_failIfNotDeviceOrProfileOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.isApplicationBlocked(mComponent, "com.google.anything");
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertProfileOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testSetGlobalSetting_failIfNotDeviceOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testSetGlobalSetting_failIfNotDeviceOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.setGlobalSetting(mComponent,
+                    Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, "1");
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertDeviceOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testSetSecureSetting_failIfNotDeviceOrProfileOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testSetSecureSetting_failIfNotDeviceOrProfileOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.setSecureSetting(mComponent,
+                    Settings.Secure.INSTALL_NON_MARKET_APPS, "1");
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertProfileOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testSetMasterVolumeMuted_failIfNotDeviceOrProfileOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testSetMasterVolumeMuted_failIfNotDeviceOrProfileOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.setMasterVolumeMuted(mComponent, true);
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertProfileOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testIsMasterVolumeMuted_failIfNotDeviceOrProfileOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testSetMasterVolumeMuted_failIfNotDeviceOrProfileOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.isMasterVolumeMuted(mComponent);
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertProfileOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testSetRecommendedGlobalProxy_failIfNotDeviceOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testSetRecommendedGlobalProxy_failIfNotDeviceOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.setRecommendedGlobalProxy(mComponent, null);
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertDeviceOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testSetLockTaskPackages_failIfNotDeviceOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testSetLockTaskPackages_failIfNotDeviceOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.setLockTaskPackages(new String[] {"package"});
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+        }
+    }
+
+    public void testClearDeviceOwnerApp_failIfNotDeviceOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testClearDeviceOwnerApp_failIfNotDeviceOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.clearDeviceOwnerApp("android.deviceadmin.cts");
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertDeviceOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testSwitchUser_failIfNotDeviceOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testSwitchUser_failIfNotDeviceOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.switchUser(mComponent, null);
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertDeviceOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testCreateAndInitializeUser_failIfNotDeviceOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testCreateAndInitializeUser_failIfNotDeviceOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.createAndInitializeUser(mComponent, "name", "admin name",
+                        mComponent, null);
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertDeviceOwnerMessage(e.getMessage());
+        }
+    }
+
+    private void assertDeviceOwnerMessage(String message) {
+        assertTrue("message is: "+ message, message.contains("does not own the device")
+                || message.contains("can only be called by the device owner"));
+    }
+
+    private void assertProfileOwnerMessage(String message) {
+        assertTrue(message.contains("does not own the profile"));
+    }
 }
diff --git a/tests/tests/animation/src/android/animation/cts/AnimationActivity.java b/tests/tests/animation/src/android/animation/cts/AnimationActivity.java
index 555ab15..225a97e 100644
--- a/tests/tests/animation/src/android/animation/cts/AnimationActivity.java
+++ b/tests/tests/animation/src/android/animation/cts/AnimationActivity.java
@@ -145,6 +145,11 @@
         view.animateBall();
     }
 
+    public void startSingleAnimation(Animator animator) {
+        animator.setTarget(view.newBall);
+        animator.start();
+    }
+
     public void startAnimation(ValueAnimator valueAnimator){
         view.bounceYAnimator = valueAnimator;
         view.startColorAnimator();
diff --git a/tests/tests/animation/src/android/animation/cts/PropertyValuesHolderTest.java b/tests/tests/animation/src/android/animation/cts/PropertyValuesHolderTest.java
index 26db933..200ebce 100644
--- a/tests/tests/animation/src/android/animation/cts/PropertyValuesHolderTest.java
+++ b/tests/tests/animation/src/android/animation/cts/PropertyValuesHolderTest.java
@@ -16,15 +16,21 @@
 package android.animation.cts;
 
 import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.animation.ArgbEvaluator;
+import android.animation.Keyframe;
 import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
 import android.animation.ValueAnimator;
+import android.graphics.drawable.ShapeDrawable;
 import android.test.ActivityInstrumentationTestCase2;
 import android.util.Property;
 import android.view.View;
 import android.view.animation.AccelerateInterpolator;
 
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
 public class PropertyValuesHolderTest extends
         ActivityInstrumentationTestCase2<AnimationActivity> {
     private AnimationActivity mActivity;
@@ -86,6 +92,113 @@
         assertResults(yArray, mStartY, mEndY);
     }
 
+    private ObjectAnimator createAnimator(Keyframe... keyframes) {
+        PropertyValuesHolder pVHolder = PropertyValuesHolder.ofKeyframe(mProperty, keyframes);
+        ObjectAnimator objAnimator = ObjectAnimator.ofPropertyValuesHolder(mObject,pVHolder);
+        objAnimator.setDuration(mDuration);
+        objAnimator.setInterpolator(new AccelerateInterpolator());
+        return objAnimator;
+    }
+
+    private void waitUntilFinished(ObjectAnimator objectAnimator, long timeoutMilliseconds)
+            throws InterruptedException {
+        final CountDownLatch latch = new CountDownLatch(1);
+        objectAnimator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                super.onAnimationEnd(animation);
+                latch.countDown();
+            }
+        });
+        latch.await(timeoutMilliseconds, TimeUnit.MILLISECONDS);
+        getInstrumentation().waitForIdleSync();
+    }
+
+    private void setTarget(final Animator animator, final Object target) throws Throwable {
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                animator.setTarget(target);
+            }
+        });
+    }
+
+    private void startSingleAnimation(final Animator animator) throws Throwable {
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mActivity.startSingleAnimation(animator);
+            }
+        });
+    }
+
+    public void testResetValues() throws Throwable {
+        final float initialY = mActivity.view.newBall.getY();
+        Keyframe emptyKeyframe1 = Keyframe.ofFloat(.0f);
+        ObjectAnimator objAnimator1 = createAnimator(emptyKeyframe1, Keyframe.ofFloat(1f, 100f));
+        startSingleAnimation(objAnimator1);
+        assertTrue("Keyframe should be assigned a value", emptyKeyframe1.hasValue());
+        assertEquals("Keyframe should get the value from the target", emptyKeyframe1.getValue(),
+                initialY);
+        waitUntilFinished(objAnimator1, mDuration * 2);
+        assertEquals(100f, mActivity.view.newBall.getY());
+        startSingleAnimation(objAnimator1);
+        waitUntilFinished(objAnimator1, mDuration * 2);
+
+        // run another ObjectAnimator that will move the Y value to something else
+        Keyframe emptyKeyframe2 = Keyframe.ofFloat(.0f);
+        ObjectAnimator objAnimator2 = createAnimator(emptyKeyframe2, Keyframe.ofFloat(1f, 200f));
+        startSingleAnimation(objAnimator2);
+        assertTrue("Keyframe should be assigned a value", emptyKeyframe2.hasValue());
+        assertEquals("Keyframe should get the value from the target", emptyKeyframe2.getValue(), 100f);
+        waitUntilFinished(objAnimator2, mDuration * 2);
+        assertEquals(200f, mActivity.view.newBall.getY());
+
+        // re-run first object animator. since its target did not change, it should have the same
+        // start value for kf1
+        startSingleAnimation(objAnimator1);
+        assertEquals(emptyKeyframe1.getValue(), initialY);
+        waitUntilFinished(objAnimator1, mDuration * 2);
+
+        Keyframe fullKeyframe = Keyframe.ofFloat(.0f, 333f);
+        ObjectAnimator objAnimator3 = createAnimator(fullKeyframe, Keyframe.ofFloat(1f, 500f));
+        startSingleAnimation(objAnimator3);
+        assertEquals("When keyframe has value, should not be assigned from the target object",
+                fullKeyframe.getValue(), 333f);
+        waitUntilFinished(objAnimator3, mDuration * 2);
+
+        // now, null out the target of the first animator
+        float updatedY = mActivity.view.newBall.getY();
+        setTarget(objAnimator1, null);
+        startSingleAnimation(objAnimator1);
+        assertTrue("Keyframe should get a value", emptyKeyframe1.hasValue());
+        assertEquals("Keyframe should get the updated Y value", emptyKeyframe1.getValue(), updatedY);
+        waitUntilFinished(objAnimator1, mDuration * 2);
+        assertEquals("Animation should run as expected", 100f, mActivity.view.newBall.getY());
+
+        // now, reset the target of the fully defined animation.
+        setTarget(objAnimator3, null);
+        startSingleAnimation(objAnimator3);
+        assertEquals("When keyframe is fully defined, its value should not change when target is"
+                + " reset", fullKeyframe.getValue(), 333f);
+        waitUntilFinished(objAnimator3, mDuration * 2);
+
+        // run the other one to change Y value
+        startSingleAnimation(objAnimator2);
+        waitUntilFinished(objAnimator2, mDuration * 2);
+        // now, set another target w/ the same View type. it should still reset
+        ShapeHolder view = new ShapeHolder(new ShapeDrawable());
+        updatedY = mActivity.view.newBall.getY();
+        setTarget(objAnimator1, view);
+        startSingleAnimation(objAnimator1);
+        assertTrue("Keyframe should get a value when target is set to another view of the same"
+                + " class", emptyKeyframe1.hasValue());
+        assertEquals("Keyframe should get the updated Y value when target is set to another view"
+                + " of the same class", emptyKeyframe1.getValue(), updatedY);
+        waitUntilFinished(objAnimator1, mDuration * 2);
+        assertEquals("Animation should run as expected", 100f, mActivity.view.newBall.getY());
+    }
+
     public void testOffloat() throws Throwable {
         float[] values = {mStartY, mEndY};
         PropertyValuesHolder pVHolder = PropertyValuesHolder.ofFloat(mProperty, values);
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/CanvasCompareActivityTest.java b/tests/tests/uirendering/src/android/uirendering/cts/CanvasCompareActivityTest.java
index c822ef2..0b205f5 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/CanvasCompareActivityTest.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/CanvasCompareActivityTest.java
@@ -61,7 +61,9 @@
     @Override
     public void setUp() {
         mDifferenceVisualizer = new PassFailVisualizer();
-        mRenderScript = RenderScript.create(getActivity().getApplicationContext());
+        if (USE_RS) {
+            mRenderScript = RenderScript.create(getActivity().getApplicationContext());
+        }
     }
 
     /**
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/DisplayModifier.java b/tests/tests/uirendering/src/android/uirendering/cts/DisplayModifier.java
index a884c5f..2f44e4a 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/DisplayModifier.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/DisplayModifier.java
@@ -18,6 +18,7 @@
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
 import android.graphics.PorterDuffXfermode;
 import android.graphics.RectF;
 
@@ -38,6 +39,9 @@
     };
     private static final int NUM_PARALLEL_LINES = 24;
     private static final float[] gLinePts = new float[NUM_PARALLEL_LINES * 8 + gTriPts.length];
+    private static final int FILTER_COLOR = 0xFFBB0000;
+    protected static final int MODIFIER_WIDTH = 180;
+    protected static final int MODIFIER_HEIGHT = 180;
 
     static {
         int index;
@@ -256,6 +260,25 @@
                                     paint.setShader(ResourceModifier.instance().scaledShader);
                                 }
                             });
+                            put("composeShader", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setShader(ResourceModifier.instance().composeShader);
+                                }
+                            });
+                            put("bad composeShader", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setShader(ResourceModifier.instance().nestedComposeShader);
+                                }
+                            });
+                            put("bad composeShader 2", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setShader(
+                                            ResourceModifier.instance().doubleGradientComposeShader);
+                                }
+                            });
                             put("horGradient", new DisplayModifier() {
                                 @Override
                                 public void modifyDrawing(Paint paint, Canvas canvas) {
@@ -286,25 +309,6 @@
                                     paint.setShader(ResourceModifier.instance().sweepGradient);
                                 }
                             });
-                            put("composeShader", new DisplayModifier() {
-                                @Override
-                                public void modifyDrawing(Paint paint, Canvas canvas) {
-                                    paint.setShader(ResourceModifier.instance().composeShader);
-                                }
-                            });
-                            put("bad composeShader", new DisplayModifier() {
-                                @Override
-                                public void modifyDrawing(Paint paint, Canvas canvas) {
-                                    paint.setShader(ResourceModifier.instance().nestedComposeShader);
-                                }
-                            });
-                            put("bad composeShader 2", new DisplayModifier() {
-                                @Override
-                                public void modifyDrawing(Paint paint, Canvas canvas) {
-                                    paint.setShader(
-                                            ResourceModifier.instance().doubleGradientComposeShader);
-                                }
-                            });
                         }
                     });
 
@@ -391,6 +395,102 @@
                         }
                     });
 
+                    put("colorfilters", new LinkedHashMap<String, DisplayModifier>() {
+                        {
+                            put("SRC", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setColorFilter(new PorterDuffColorFilter(FILTER_COLOR,
+                                            PorterDuff.Mode.SRC));
+                                }
+                            });
+                            put("DST", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setColorFilter(new PorterDuffColorFilter(FILTER_COLOR,
+                                            PorterDuff.Mode.DST));
+                                }
+                            });
+                            put("SRC_OVER", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setColorFilter(new PorterDuffColorFilter(FILTER_COLOR,
+                                            PorterDuff.Mode.SRC_OVER));
+                                }
+                            });
+                            put("DST_OVER", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setColorFilter(new PorterDuffColorFilter(FILTER_COLOR,
+                                            PorterDuff.Mode.DST_OVER));
+                                }
+                            });
+                            put("SRC_IN", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setColorFilter(new PorterDuffColorFilter(FILTER_COLOR,
+                                            PorterDuff.Mode.SRC_IN));
+                                }
+                            });
+                            put("DST_IN", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setColorFilter(new PorterDuffColorFilter(FILTER_COLOR,
+                                            PorterDuff.Mode.DST_IN));
+                                }
+                            });
+                            put("SRC_OUT", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setColorFilter(new PorterDuffColorFilter(FILTER_COLOR,
+                                            PorterDuff.Mode.SRC_OUT));
+                                }
+                            });
+                            put("DST_OUT", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setColorFilter(new PorterDuffColorFilter(FILTER_COLOR,
+                                            PorterDuff.Mode.DST_OUT));
+                                }
+                            });
+                            put("SRC_ATOP", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setColorFilter(new PorterDuffColorFilter(FILTER_COLOR,
+                                            PorterDuff.Mode.SRC_ATOP));
+                                }
+                            });
+                            put("DST_ATOP", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setColorFilter(new PorterDuffColorFilter(FILTER_COLOR,
+                                            PorterDuff.Mode.DST_ATOP));
+                                }
+                            });
+                            put("XOR", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setColorFilter(new PorterDuffColorFilter(FILTER_COLOR,
+                                            PorterDuff.Mode.XOR));
+                                }
+                            });
+                            put("MULTIPLY", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setColorFilter(new PorterDuffColorFilter(FILTER_COLOR,
+                                            PorterDuff.Mode.MULTIPLY));
+                                }
+                            });
+                            put("SCREEN", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setColorFilter(new PorterDuffColorFilter(FILTER_COLOR,
+                                            PorterDuff.Mode.SCREEN));
+                                }
+                            });
+                        }
+                    });
+
                     // FINAL MAP: DOES ACTUAL DRAWING
                     put("drawing", new LinkedHashMap<String, DisplayModifier>() {
                         {
@@ -474,17 +574,18 @@
     abstract public void modifyDrawing(Paint paint, Canvas canvas);
 
     public static class Accessor {
-        public final static int AA_MASK =           0x1 << 0;
-        public final static int STYLE_MASK =        0x1 << 1;
-        public final static int STROKE_WIDTH_MASK = 0x1 << 2;
-        public final static int STROKE_CAP_MASK =   0x1 << 3;
-        public final static int STROKE_JOIN_MASK =  0x1 << 4;
-        public final static int TRANSFORM_MASK =    0x1 << 5;
-        public final static int SHADER_MASK =       0x1 << 6;
-        public final static int XFERMODE_MASK =     0x1 << 7;
-        public final static int SHAPES_MASK =       0x1 << 8;
-        public final static int ALL_OPTIONS_MASK = 0x1FF;
-        public final static int SHAPES_INDEX = 8;
+        public final static int AA_MASK =               0x1 << 0;
+        public final static int STYLE_MASK =            0x1 << 1;
+        public final static int STROKE_WIDTH_MASK =     0x1 << 2;
+        public final static int STROKE_CAP_MASK =       0x1 << 3;
+        public final static int STROKE_JOIN_MASK =      0x1 << 4;
+        public final static int TRANSFORM_MASK =        0x1 << 5;
+        public final static int SHADER_MASK =           0x1 << 6;
+        public final static int XFERMODE_MASK =         0x1 << 7;
+        public final static int COLOR_FILTER_MASK =     0x1 << 8;
+        public final static int SHAPES_MASK =           0x1 << 9;
+        public final static int ALL_OPTIONS_MASK =      (0x1 << 10) - 1;
+        public final static int SHAPES_INDEX = 9;
         public final static int XFERMODE_INDEX = 7;
         private final int mMask;
 
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/SweepTests.java b/tests/tests/uirendering/src/android/uirendering/cts/SweepTests.java
index e92fc1e..1a9b6a1 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/SweepTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/SweepTests.java
@@ -18,14 +18,21 @@
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.LinearGradient;
 import android.graphics.Paint;
 import android.graphics.Point;
+import android.graphics.PorterDuff;
+import android.graphics.Rect;
 import android.graphics.RectF;
+import android.graphics.Shader;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.uirendering.cts.differencecalculators.DifferenceCalculator;
 import android.uirendering.cts.differencecalculators.MSSIMCalculator;
 import android.uirendering.cts.differencecalculators.SamplePointsCalculator;
 
+import java.util.LinkedHashMap;
+import java.util.Map;
+
 /**
  * Test cases of all combination of resource modifications.
  */
@@ -36,29 +43,11 @@
     public static final int MULTIPLY_COLOR = 0xFF668844;
     public static final int SCREEN_COLOR = 0xFFFFEEFF;
 
-    /**
-     * There are 4 locations we care about in XFermode testing.
-     *
-     * 1) Both empty
-     * 2) Only src, dst empty
-     * 3) Both src + dst
-     * 4) Only dst, src empty
-     */
-    private final int[][] XFERMODE_COLOR_ARRAYS = new int[][] {
-            {BG_COLOR, BG_COLOR, SRC_COLOR, SRC_COLOR},
-            {BG_COLOR, DST_COLOR, DST_COLOR, BG_COLOR},
-            {BG_COLOR, DST_COLOR, SRC_COLOR, SRC_COLOR},
-            {BG_COLOR, DST_COLOR, DST_COLOR, SRC_COLOR},
-            {BG_COLOR, BG_COLOR, SRC_COLOR, BG_COLOR},
-            {BG_COLOR, BG_COLOR, DST_COLOR, BG_COLOR},
-            {BG_COLOR, BG_COLOR, BG_COLOR, SRC_COLOR},
-            {BG_COLOR, DST_COLOR, BG_COLOR, BG_COLOR},
-            {BG_COLOR, DST_COLOR, SRC_COLOR, BG_COLOR},
-            {BG_COLOR, BG_COLOR, DST_COLOR, SRC_COLOR},
-            {BG_COLOR, DST_COLOR, BG_COLOR, SRC_COLOR},
-            {BG_COLOR, BG_COLOR, MULTIPLY_COLOR, BG_COLOR},
-            {BG_COLOR, DST_COLOR, SCREEN_COLOR, SRC_COLOR}
-    };
+    public static final int FILTER_COLOR = 0xFFBB0000;
+    public static final int RECT0_COLOR = 0x33808080;
+    public static final int RECT1_COLOR = 0x66808080;
+    public static final int RECT2_COLOR = 0x99808080;
+    public static final int RECT3_COLOR = 0xCC808080;
 
     // These points are in pairs, the first being the lower left corner, the second is only in the
     // Destination bitmap, the third is the intersection of the two bitmaps, and the fourth is in
@@ -67,9 +56,71 @@
             new Point(1, 160), new Point(50, 50), new Point(70, 70), new Point(140, 140)
     };
 
+    /**
+     * There are 4 locations we care about in any filter testing.
+     *
+     * 1) Both empty
+     * 2) Only src, dst empty
+     * 3) Both src + dst
+     * 4) Only dst, src empty
+     */
+    private final Map<PorterDuff.Mode, int[]> XFERMODE_COLOR_MAP = new LinkedHashMap<PorterDuff.Mode, int[]>() {
+        {
+            put(PorterDuff.Mode.SRC, new int[] {
+                    BG_COLOR, BG_COLOR, SRC_COLOR, SRC_COLOR
+            });
+
+            put(PorterDuff.Mode.DST, new int[] {
+                    BG_COLOR, DST_COLOR, DST_COLOR, BG_COLOR
+            });
+
+            put(PorterDuff.Mode.SRC_OVER, new int[] {
+                    BG_COLOR, DST_COLOR, SRC_COLOR, SRC_COLOR
+            });
+
+            put(PorterDuff.Mode.DST_OVER, new int[] {
+                    BG_COLOR, DST_COLOR, DST_COLOR, SRC_COLOR
+            });
+
+            put(PorterDuff.Mode.SRC_IN, new int[] {
+                    BG_COLOR, BG_COLOR, SRC_COLOR, BG_COLOR
+            });
+
+            put(PorterDuff.Mode.DST_IN, new int[] {
+                    BG_COLOR, BG_COLOR, DST_COLOR, BG_COLOR
+            });
+
+            put(PorterDuff.Mode.SRC_OUT, new int[] {
+                    BG_COLOR, BG_COLOR, BG_COLOR, SRC_COLOR
+            });
+
+            put(PorterDuff.Mode.DST_OUT, new int[] {
+                    BG_COLOR, DST_COLOR, BG_COLOR, BG_COLOR
+            });
+
+            put(PorterDuff.Mode.SRC_ATOP, new int[] {
+                    BG_COLOR, DST_COLOR, SRC_COLOR, BG_COLOR
+            });
+
+            put(PorterDuff.Mode.DST_ATOP, new int[] {
+                    BG_COLOR, BG_COLOR, DST_COLOR, SRC_COLOR
+            });
+
+            put(PorterDuff.Mode.XOR, new int[] {
+                    BG_COLOR, DST_COLOR, BG_COLOR, SRC_COLOR
+            });
+
+            put(PorterDuff.Mode.MULTIPLY, new int[] {
+                    BG_COLOR, BG_COLOR, MULTIPLY_COLOR, BG_COLOR
+            });
+
+            put(PorterDuff.Mode.SCREEN, new int[] {
+                    BG_COLOR, DST_COLOR, SCREEN_COLOR, SRC_COLOR
+            });
+        }
+    };
+
     private final static DisplayModifier XFERMODE_MODIFIER = new DisplayModifier() {
-        private final static int mWidth = 180;
-        private final static int mHeight = 180;
         private final RectF mSrcRect = new RectF(60, 60, 160, 160);
         private final RectF mDstRect = new RectF(20, 20, 120, 120);
         private final Bitmap mSrcBitmap = createSrc();
@@ -80,14 +131,13 @@
             // Draw the background
             canvas.drawColor(Color.WHITE);
 
-            int sc = canvas.saveLayer(0, 0, mWidth, mHeight, null);
             canvas.drawBitmap(mDstBitmap, 0, 0, null);
             canvas.drawBitmap(mSrcBitmap, 0, 0, paint);
-            canvas.restoreToCount(sc);
         }
 
         private Bitmap createSrc() {
-            Bitmap srcB = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
+            Bitmap srcB = Bitmap.createBitmap(MODIFIER_WIDTH, MODIFIER_HEIGHT,
+                    Bitmap.Config.ARGB_8888);
             Canvas srcCanvas = new Canvas(srcB);
             Paint srcPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
             srcPaint.setColor(SRC_COLOR);
@@ -96,7 +146,8 @@
         }
 
         private Bitmap createDst() {
-            Bitmap dstB = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
+            Bitmap dstB = Bitmap.createBitmap(MODIFIER_WIDTH, MODIFIER_HEIGHT,
+                    Bitmap.Config.ARGB_8888);
             Canvas dstCanvas = new Canvas(dstB);
             Paint dstPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
             dstPaint.setColor(DST_COLOR);
@@ -105,6 +156,120 @@
         }
     };
 
+
+    // We care about one point in each of the four rectangles of different alpha values, as well as
+    // the area outside the rectangles
+    private final static Point[] COLOR_FILTER_ALPHA_POINTS = new Point[] {
+            new Point(15, 90), new Point(45, 90), new Point(75, 90), new Point(105, 90),
+            new Point(135, 90)
+    };
+
+    private final Map<PorterDuff.Mode, int[]> COLOR_FILTER_ALPHA_MAP = new LinkedHashMap<PorterDuff.Mode, int[]>() {
+        {
+            put(PorterDuff.Mode.SRC, new int[] {
+                FILTER_COLOR, FILTER_COLOR, FILTER_COLOR, FILTER_COLOR, FILTER_COLOR
+            });
+
+            put(PorterDuff.Mode.DST, new int[] {
+                    0xFFE6E6E6, 0xFFCCCCCC, 0xFFB3B3B3, 0xFF999999, 0xFFFFFFFF
+            });
+
+            put(PorterDuff.Mode.SRC_OVER, new int[] {
+                    0xFFBB0000, 0xFFBB0000, 0xFFBB0000, 0xFFBB0000, 0xFFBB0000
+            });
+
+            put(PorterDuff.Mode.DST_OVER, new int[] {
+                    0xFFAF1A1A, 0xFFA33333, 0xFF984D4D, 0xFF8B6666, 0xFFBB0000
+            });
+
+            put(PorterDuff.Mode.SRC_IN, new int[] {
+                    0xFFF1CCCC, 0xFFE49999, 0xFFD66666, 0xFFC83333, 0xFFFFFFFF
+            });
+
+            put(PorterDuff.Mode.DST_IN, new int[] {
+                    0xFFE6E6E6, 0xFFCCCCCC, 0xFFB3B3B3, 0xFF999999, 0xFFFFFFFF
+            });
+
+            put(PorterDuff.Mode.SRC_OUT, new int[] {
+                    0xFFC83333, 0xFFD66666, 0xFFE49999, 0xFFF1CCCC, 0xFFBB0000
+            });
+
+            put(PorterDuff.Mode.DST_OUT, new int[] {
+                    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
+            });
+
+            put(PorterDuff.Mode.SRC_ATOP, new int[] {
+                    0xFFF1CCCC, 0xFFE49999, 0xFFD66666, 0xFFC93333, 0xFFFFFFFF
+            });
+
+            put(PorterDuff.Mode.DST_ATOP, new int[] {
+                    0xFFB01A1A, 0xFFA33333, 0xFF984D4D, 0xFF8B6666, 0xFFBB0000
+            });
+
+            put(PorterDuff.Mode.XOR, new int[] {
+                    0xFFC93333, 0xFFD66666, 0xFFE49999, 0xFFF1CCCC, 0xFFBB0000
+            });
+
+            put(PorterDuff.Mode.MULTIPLY, new int[] {
+                    0xFFDFCCCC, 0xFFBE9999, 0xFF9E6666, 0xFF7E3333, 0xFFFFFFFF
+            });
+
+            put(PorterDuff.Mode.SCREEN, new int[] {
+                    0xFFC21A1A, 0xFFC93333, 0xFFD04D4D, 0xFFD66666, 0xFFBB0000
+            });
+        }
+    };
+
+    private final static DisplayModifier COLOR_FILTER_ALPHA_MODIFIER = new DisplayModifier() {
+        private final static int mBlockWidths = 30;
+        private final int[] mColorValues = new int[] {RECT0_COLOR, RECT1_COLOR, RECT2_COLOR,
+                RECT3_COLOR};
+
+        private final Bitmap mBitmap = createQuadRectBitmap();
+
+        public void modifyDrawing(Paint paint, Canvas canvas) {
+            canvas.drawBitmap(mBitmap, 0, 0, paint);
+        }
+
+        private Bitmap createQuadRectBitmap() {
+            Bitmap bitmap = Bitmap.createBitmap(MODIFIER_WIDTH, MODIFIER_HEIGHT,
+                    Bitmap.Config.ARGB_8888);
+            Canvas canvas = new Canvas(bitmap);
+            Paint paint = new Paint();
+            for (int i = 0 ; i < 4 ; i++) {
+                paint.setColor(mColorValues[i]);
+                canvas.drawRect(i * mBlockWidths, 0, (i + 1) * mBlockWidths, MODIFIER_HEIGHT, paint);
+            }
+            return bitmap;
+        }
+    };
+
+    private final static DisplayModifier COLOR_FILTER_GRADIENT_MODIFIER = new DisplayModifier() {
+        private final Rect mBounds = new Rect(30, 30, 150, 150);
+        private final int[] mColors = new int[] {
+                Color.RED, Color.GREEN, Color.BLUE
+        };
+
+        private final Bitmap mBitmap = createGradient();
+
+        @Override
+        public void modifyDrawing(Paint paint, Canvas canvas) {
+            canvas.drawBitmap(mBitmap, 0, 0, paint);
+        }
+
+        private Bitmap createGradient() {
+            LinearGradient gradient = new LinearGradient(30, 90, 150, 90, mColors, null,
+                    Shader.TileMode.REPEAT);
+            Bitmap bitmap = Bitmap.createBitmap(MODIFIER_WIDTH, MODIFIER_HEIGHT,
+                    Bitmap.Config.ARGB_8888);
+            Paint p = new Paint();
+            p.setShader(gradient);
+            Canvas c = new Canvas(bitmap);
+            c.drawRect(mBounds, p);
+            return bitmap;
+        }
+    };
+
     /**
      * In this case, a lower number would mean it is easier to pass the test. In terms of MSSIM,
      * a 1 would indicate that the images are exactly the same, where as 0.1 is vastly different.
@@ -128,19 +293,44 @@
     }
 
     @SmallTest
-    public void testShaderDraws() {
+    public void testBasicShaders() {
         DifferenceCalculator[] calculators = new DifferenceCalculator[1];
         calculators[0] = new MSSIMCalculator(HIGH_THRESHOLD);
         sweepModifiersForMask(DisplayModifier.Accessor.SHADER_MASK, mCircleDrawModifier,
-            calculators);
+                calculators);
+    }
+
+    @SmallTest
+    public void testColorFilterUsingGradient() {
+        DifferenceCalculator[] calculators = new DifferenceCalculator[1];
+        calculators[0] = new MSSIMCalculator(HIGH_THRESHOLD);
+        sweepModifiersForMask(DisplayModifier.Accessor.COLOR_FILTER_MASK,
+                COLOR_FILTER_GRADIENT_MODIFIER, calculators);
+    }
+
+    @SmallTest
+    public void testColorFiltersAlphas() {
+        DifferenceCalculator[] calculators =
+                new DifferenceCalculator[COLOR_FILTER_ALPHA_MAP.keySet().size()];
+        int index = 0;
+        for (PorterDuff.Mode mode: COLOR_FILTER_ALPHA_MAP.keySet()) {
+            calculators[index] = new SamplePointsCalculator(COLOR_FILTER_ALPHA_POINTS,
+                    COLOR_FILTER_ALPHA_MAP.get(mode));
+            index++;
+        }
+        sweepModifiersForMask(DisplayModifier.Accessor.COLOR_FILTER_MASK,
+                COLOR_FILTER_ALPHA_MODIFIER, calculators);
     }
 
     @SmallTest
     public void testXfermodes() {
-        DifferenceCalculator[] calculators = new DifferenceCalculator[XFERMODE_COLOR_ARRAYS.length];
-        for (int i = 0 ; i < XFERMODE_COLOR_ARRAYS.length ; i++) {
-            calculators[i] = new SamplePointsCalculator(XFERMODE_TEST_POINTS,
-                XFERMODE_COLOR_ARRAYS[i]);
+        DifferenceCalculator[] calculators =
+                new DifferenceCalculator[XFERMODE_COLOR_MAP.keySet().size()];
+        int index = 0;
+        for (PorterDuff.Mode mode: XFERMODE_COLOR_MAP.keySet()) {
+            calculators[index] = new SamplePointsCalculator(XFERMODE_TEST_POINTS,
+                    XFERMODE_COLOR_MAP.get(mode));
+            index++;
         }
         sweepModifiersForMask(DisplayModifier.Accessor.XFERMODE_MASK, XFERMODE_MODIFIER,
             calculators);
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/MSSIMCalculator.java b/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/MSSIMCalculator.java
index 9e6a0c1..3facdd9 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/MSSIMCalculator.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/differencecalculators/MSSIMCalculator.java
@@ -33,13 +33,13 @@
 public class MSSIMCalculator extends BaseRenderScriptCalculator{
     // These values were taken from the publication
     public static final boolean DEBUG = false;
-    public static final String TAG = "MSSIM";
+    public static final String TAG_NAME = "MSSIM";
     public static final double CONSTANT_L = 254;
     public static final double CONSTANT_K1 = 0.00001;
     public static final double CONSTANT_K2 = 0.00003;
     public static final double CONSTANT_C1 = Math.pow(CONSTANT_L * CONSTANT_K1, 2);
     public static final double CONSTANT_C2 = Math.pow(CONSTANT_L * CONSTANT_K2, 2);
-    public static final int WINDOW_SIZE = 3;
+    public static final int WINDOW_SIZE = 10;
 
     private double mThreshold;
     private ScriptC_MSSIMCalculator mScript;
@@ -73,13 +73,16 @@
             }
         }
 
-        if (windows == 0) { //if they were both white screens then we are good
+        if (windows == 0) {
             return true;
         }
 
         SSIMTotal /= windows;
 
-        Log.d(TAG, "MSSIM : " + SSIMTotal);
+        if (DEBUG) {
+            Log.d(TAG_NAME, "MSSIM = " + SSIMTotal);
+            Log.d(TAG_NAME, "Number of Windows : " + windows);
+        }
 
         return (SSIMTotal >= mThreshold);
     }
@@ -105,7 +108,9 @@
         float MSSIM = sum1DFloatAllocation(outputAllocation);
         MSSIM /= height;
 
-        Log.d(TAG, "MSSIM RS : " + MSSIM);
+        if (DEBUG) {
+            Log.d(TAG_NAME, "MSSIM RS : " + MSSIM);
+        }
 
         return (MSSIM >= mThreshold);
     }