Merge "CTS tests for android.app.job" into lmp-dev
diff --git a/CtsBuild.mk b/CtsBuild.mk
index 12a9047..dbe93c7 100644
--- a/CtsBuild.mk
+++ b/CtsBuild.mk
@@ -47,7 +47,7 @@
 endef
 
 define cts-get-native-paths
-	$(foreach exe,$(1),$(call intermediates-dir-for,EXECUTABLES,$(exe))/$(exe))
+	$(foreach exe,$(1),$(call intermediates-dir-for,EXECUTABLES,$(exe),,,$(3))/$(exe)$(2))
 endef
 
 define cts-get-package-paths
diff --git a/CtsTestCaseList.mk b/CtsTestCaseList.mk
index 8894409..721b9d4 100644
--- a/CtsTestCaseList.mk
+++ b/CtsTestCaseList.mk
@@ -69,6 +69,7 @@
     CtsDeviceTaskswitchingControl \
     CtsDeviceUi \
     CtsIntentReceiverApp \
+    CtsIntentSenderApp \
     CtsManagedProfileApp \
     CtsMonkeyApp \
     CtsMonkeyApp2 \
@@ -178,13 +179,16 @@
     CtsSecurityHostTestCases \
     CtsUsbTests
 
-# Native test executables that need to have associated test XMLs.
-cts_native_exes := \
+# List of native tests. For 32 bit targets, assumes that there will be
+# one test executable, and it will end in 32. For 64 bit targets, assumes
+# that there will be two executables, one that ends in 32 for the 32
+# bit executable and one that ends in 64 for the 64 bit executable.
+cts_native_tests := \
     NativeMediaTest_SL \
     NativeMediaTest_XA \
 
 ifeq ($(HOST_OS)-$(HOST_ARCH),$(filter $(HOST_OS)-$(HOST_ARCH),linux-x86 linux-x86_64))
-cts_native_exes += bionic-unit-tests-cts
+cts_native_tests += bionic-unit-tests-cts
 endif
 
 cts_ui_tests := \
@@ -208,17 +212,27 @@
 # directory of the final CTS distribution.
 CTS_TEST_CASES := $(call cts-get-lib-paths,$(cts_host_libraries)) \
     $(call cts-get-package-paths,$(cts_test_packages)) \
-    $(call cts-get-native-paths,$(cts_native_exes)) \
     $(call cts-get-ui-lib-paths,$(cts_ui_tests)) \
     $(call cts-get-ui-lib-paths,$(cts_device_jars)) \
     $(call cts-get-ui-lib-paths,$(cts_target_junit_tests)) \
     $(call cts-get-executable-paths,$(cts_device_executables))
 
+# NOTE: If compiling on a 64 bit target, TARGET_2ND_ARCH will be non-empty
+# and will cause the function to expand to the secondary arch object
+# directory. If compiling on a 32 bit target, TARGET_2ND_ARCH will be
+# empty and will cause the function to expand to the primary arch object
+# directory.
+CTS_TEST_CASES += $(call cts-get-native-paths,$(cts_native_tests),32,$(TARGET_2ND_ARCH))
+
+ifeq ($(TARGET_IS_64_BIT),true)
+CTS_TEST_CASES += $(call cts-get-native-paths,$(cts_native_tests),64)
+endif
+
 # All the XMLs that will end up under the repository/testcases
 # and that need to be created before making the final CTS distribution.
 CTS_TEST_XMLS := $(call cts-get-test-xmls,$(cts_host_libraries)) \
     $(call cts-get-test-xmls,$(cts_test_packages)) \
-    $(call cts-get-test-xmls,$(cts_native_exes)) \
+    $(call cts-get-test-xmls,$(cts_native_tests)) \
     $(call cts-get-test-xmls,$(cts_target_junit_tests)) \
     $(call cts-get-test-xmls,$(cts_ui_tests)) \
     $(call cts-get-deqp-test-xmls,$(cts_deqp_test_apis))
diff --git a/apps/CtsVerifier/res/layout/pa_main.xml b/apps/CtsVerifier/res/layout/pa_main.xml
index b6b8e4b..76cb7d4 100644
--- a/apps/CtsVerifier/res/layout/pa_main.xml
+++ b/apps/CtsVerifier/res/layout/pa_main.xml
@@ -17,11 +17,15 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent" >
 
+    <include
+        android:id="@+id/pass_fail_buttons"
+        android:layout_gravity="top"
+        layout="@layout/pass_fail_buttons" />
+
     <TextureView
         android:id="@+id/texture_view"
         android:layout_width="match_parent"
-        android:layout_height="match_parent" />
-
-     <include layout="@layout/pass_fail_buttons" />
+        android:layout_height="match_parent"
+        android:layout_below="@id/pass_fail_buttons" />
 
 </RelativeLayout>
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index b203326..558a86d 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -482,7 +482,8 @@
     <string name="snsr_wait_to_begin">Press \'Next\' to begin.</string>
     <string name="snsr_on_complete_return">After completing the task, go back to this test.</string>
     <string name="snsr_movement_expected">Movement was expected during the test. Found=%1$b.</string>
-    <string name="snsr_sensor_feature_deactivation">Additionally, turn off any other features installed in the device, that register for sensors. Once you are done, you can continue the test.</string>
+    <string name="snsr_sensor_feature_deactivation">Turn off any special features installed in the
+        device that register for sensors. Once you are done, you can begin the test.</string>
     <string name="snsr_setting_mode_request">You will be redirected to set \'%1$s\' to: %2$s.</string>
     <string name="snsr_setting_mode_set">\'%1$s\' set to: %2$s.</string>
     <string name="snsr_setting_mode_not_set">\'%1$s\' not set to: %2$s.</string>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/offscreen/ProjectionOffscreenActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/offscreen/ProjectionOffscreenActivity.java
index f992618..510a03b 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/projection/offscreen/ProjectionOffscreenActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/offscreen/ProjectionOffscreenActivity.java
@@ -26,6 +26,9 @@
 import android.graphics.PixelFormat;
 import android.media.Image;
 import android.media.ImageReader;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
+import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -68,7 +71,7 @@
     protected TestStatus mTestStatus = TestStatus.RUNNING;
 
     private final Runnable sendKeyEventRunnable = new Runnable() {
-            @Override
+        @Override
         public void run() {
             try {
                 mService.onKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_DOWN));
@@ -79,15 +82,28 @@
         }
     };
 
+    private final Runnable playNotificationRunnable = new Runnable() {
+
+        @Override
+        public void run() {
+            Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
+            Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), notification);
+            r.play();
+        }
+    };
+
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
 
     @Override
     public void onReceive(Context context, Intent intent) {
         if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
-            new Handler(Looper.getMainLooper()).postDelayed(
+            Handler handler = new Handler(Looper.getMainLooper());
+            handler.postDelayed(
                     sendKeyEventRunnable, DELAYED_RUNNABLE_TIME);
             mStatusView.setText("Running test...");
             mTimeScreenTurnedOff = SystemClock.uptimeMillis();
+            // Notify user its safe to turn screen back on after 5s + fudge factor
+            handler.postDelayed(playNotificationRunnable, TIME_SCREEN_OFF + 500);
         } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
             if (SystemClock.uptimeMillis() - mTimeScreenTurnedOff < TIME_SCREEN_OFF) {
                 mStatusView.setText("ERROR: Turned on screen too early");
@@ -121,8 +137,9 @@
                     filter.addAction(Intent.ACTION_SCREEN_ON);
 
                     registerReceiver(mReceiver, filter);
-                    mStatusView.setText(
-                            "Please turn off your screen and turn it back on after 5 seconds");
+                    mStatusView.setText("Please turn off your screen and turn it back on after " +
+                            "5 seconds. A sound will be played when it is safe to turn the " +
+                            "screen back on");
                 }
 
             });
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorFeaturesDeactivator.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorFeaturesDeactivator.java
index 65a3a4d..82f8ae9 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorFeaturesDeactivator.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorFeaturesDeactivator.java
@@ -32,8 +32,6 @@
  */
 public class SensorFeaturesDeactivator {
 
-    private boolean mInitialStateCaptured;
-
     private final ISensorTestStateContainer mStateContainer;
 
     private final SensorSettingContainer mAirplaneMode = new AirplaneModeSettingContainer();
@@ -64,10 +62,6 @@
     }
 
     public synchronized void requestToRestoreFeatures() throws InterruptedException {
-        if (!isInitialStateCaptured()) {
-            return;
-        }
-
         if (Thread.currentThread().isInterrupted()) {
             // TODO: in the future, if the thread is interrupted, we might need to serialize the
             //       intermediate state we acquired so we can restore when we have a chance
@@ -82,21 +76,11 @@
     }
 
     private void captureInitialState() {
-        if (mInitialStateCaptured) {
-            return;
-        }
-
         mAirplaneMode.captureInitialState();
         mScreenBrightnessMode.captureInitialState();
         mAutoRotateScreenMode.captureInitialState();
         mLocationMode.captureInitialState();
         mKeepScreenOnMode.captureInitialState();
-
-        mInitialStateCaptured = true;
-    }
-
-    private boolean isInitialStateCaptured() {
-        return mInitialStateCaptured;
     }
 
     private class AirplaneModeSettingContainer extends SensorSettingContainer {
@@ -105,13 +89,15 @@
         }
 
         @Override
-        protected int getSettingMode() {
+        protected int getSettingMode(int defaultValue) {
             ContentResolver contentResolver = mStateContainer.getContentResolver();
             // Settings.System.AIRPLANE_MODE_ON is deprecated in API 17
             if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
-                return Settings.System.getInt(contentResolver, Settings.System.AIRPLANE_MODE_ON, 0);
+                return Settings.System
+                        .getInt(contentResolver, Settings.System.AIRPLANE_MODE_ON, defaultValue);
             } else {
-                return Settings.Global.getInt(contentResolver, Settings.Global.AIRPLANE_MODE_ON, 0);
+                return Settings.Global
+                        .getInt(contentResolver, Settings.Global.AIRPLANE_MODE_ON, defaultValue);
             }
         }
     }
@@ -122,11 +108,11 @@
         }
 
         @Override
-        public int getSettingMode() {
+        public int getSettingMode(int defaultValue) {
             return Settings.System.getInt(
                     mStateContainer.getContentResolver(),
                     Settings.System.SCREEN_BRIGHTNESS_MODE,
-                    Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
+                    defaultValue);
         }
     }
 
@@ -137,11 +123,11 @@
         }
 
         @Override
-        protected int getSettingMode() {
+        protected int getSettingMode(int defaultValue) {
             return Settings.System.getInt(
                     mStateContainer.getContentResolver(),
                     Settings.System.ACCELEROMETER_ROTATION,
-                    0 /* default */);
+                    defaultValue);
         }
     }
 
@@ -152,11 +138,11 @@
         }
 
         @Override
-        protected int getSettingMode() {
+        protected int getSettingMode(int defaultValue) {
             return Settings.Global.getInt(
                     mStateContainer.getContentResolver(),
                     Settings.Global.STAY_ON_WHILE_PLUGGED_IN,
-                    0);
+                    defaultValue);
         }
     }
 
@@ -166,11 +152,11 @@
         }
 
         @Override
-        protected int getSettingMode() {
+        protected int getSettingMode(int defaultValue) {
             return Settings.Secure.getInt(
                     mStateContainer.getContentResolver(),
                     Settings.Secure.LOCATION_MODE,
-                    Settings.Secure.LOCATION_MODE_OFF);
+                    defaultValue);
         }
     }
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorSettingContainer.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorSettingContainer.java
index 82df502..2d44d8d 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorSettingContainer.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorSettingContainer.java
@@ -24,12 +24,18 @@
  * A helper class for {@link SensorFeaturesDeactivator}. It abstracts the responsibility of handling
  * device settings that affect sensors.
  *
- * This class is not thread safe. It is meant to be used only by {@link SensorFeaturesDeactivator}.
+ * This class is meant to be used only by {@link SensorFeaturesDeactivator}.
+ * To keep things simple, this class synchronizes access to its internal state on public methods.
+ * This approach is fine, because there is no need for concurrent access.
  */
 abstract class SensorSettingContainer {
+    private static final int DEFAULT_SETTING_VALUE = -1;
+
     private final String mAction;
     private final int mSettingNameResId;
 
+    private boolean mInitialized;
+    private boolean mSettingAvailable;
     private boolean mCapturedModeOn;
 
     public SensorSettingContainer(String action, int settingNameResId) {
@@ -37,13 +43,21 @@
         mSettingNameResId = settingNameResId;
     }
 
-    public void captureInitialState() {
+    public synchronized void captureInitialState() {
+        if (mInitialized) {
+            return;
+        }
+        mSettingAvailable = getSettingMode(DEFAULT_SETTING_VALUE) != DEFAULT_SETTING_VALUE;
         mCapturedModeOn = getCurrentSettingMode();
+        mInitialized = true;
     }
 
     public synchronized void requestToSetMode(
             ISensorTestStateContainer stateContainer,
-            boolean modeOn) throws  InterruptedException {
+            boolean modeOn) throws InterruptedException {
+        if (!isSettingAvailable()) {
+            return;
+        }
         trySetMode(stateContainer, modeOn);
         if (getCurrentSettingMode() != modeOn) {
             String message = stateContainer.getString(
@@ -56,6 +70,9 @@
 
     public synchronized void requestToResetMode(ISensorTestStateContainer stateContainer)
             throws InterruptedException {
+        if (!isSettingAvailable()) {
+            return;
+        }
         trySetMode(stateContainer, mCapturedModeOn);
     }
 
@@ -75,12 +92,20 @@
     }
 
     private boolean getCurrentSettingMode() {
-        return getSettingMode() != 0;
+        return getSettingMode(DEFAULT_SETTING_VALUE) != 0;
     }
 
     private String getSettingName(ISensorTestStateContainer stateContainer) {
         return stateContainer.getString(mSettingNameResId);
     }
 
-    protected abstract int getSettingMode();
+    private boolean isSettingAvailable() {
+        if (!mInitialized) {
+            throw new IllegalStateException(
+                    "Object must be initialized first by invoking #captureInitialState.");
+        }
+        return mSettingAvailable;
+    }
+
+    protected abstract int getSettingMode(int defaultValue);
 }
diff --git a/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTest.java b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTest.java
index 83187c7..6720dff 100644
--- a/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTest.java
+++ b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTest.java
@@ -54,6 +54,7 @@
         mDevice = UiDevice.getInstance(getInstrumentation());
         mActivity = launchActivity(getInstrumentation().getTargetContext().getPackageName(),
                 MyActivity.class, null);
+        mDevice.waitForIdle();
     }
 
     @Override
@@ -78,6 +79,7 @@
         mActivity.startActivityForResult(intent, 42);
 
         // Ensure that we see both of our roots
+        mDevice.waitForIdle();
         assertTrue("CtsLocal root", new UiObject(new UiSelector().text("CtsLocal")).exists());
         assertTrue("CtsCreate root", new UiObject(new UiSelector().text("CtsCreate")).exists());
         assertFalse("CtsGetContent", new UiObject(new UiSelector().text("CtsGetContent")).exists());
@@ -86,8 +88,6 @@
         mDevice.waitForIdle();
         new UiObject(new UiSelector().text("CtsLocal")).click();
 
-        // make sure drawer is expanded?
-
         mDevice.waitForIdle();
         new UiObject(new UiSelector().text("FILE1")).click();
 
@@ -148,6 +148,7 @@
         mDevice.waitForIdle();
         new UiObject(new UiSelector().text("FILE1")).click();
 
+        mDevice.waitForIdle();
         new UiObject(new UiSelector().resourceId("com.android.documentsui:id/container_save")
                 .childSelector(new UiSelector().resourceId("android:id/button1"))).click();
 
@@ -237,16 +238,15 @@
         intent.setType("*/*");
         mActivity.startActivityForResult(intent, 42);
 
-        mDevice.waitForIdle();
-
         // Look around, we should be able to see both DocumentsProviders and
         // other GET_CONTENT sources.
+        mDevice.waitForIdle();
         assertTrue("CtsLocal root", new UiObject(new UiSelector().text("CtsLocal")).exists());
         assertTrue("CtsCreate root", new UiObject(new UiSelector().text("CtsCreate")).exists());
         assertTrue("CtsGetContent", new UiObject(new UiSelector().text("CtsGetContent")).exists());
 
-        new UiObject(new UiSelector().text("CtsGetContent")).click();
         mDevice.waitForIdle();
+        new UiObject(new UiSelector().text("CtsGetContent")).click();
 
         final Result result = mActivity.getResult();
         assertEquals("ReSuLt", result.data.getAction());
diff --git a/hostsidetests/devicepolicy/app/IntentReceiver/src/com/android/cts/intent/receiver/IntentReceiverActivity.java b/hostsidetests/devicepolicy/app/IntentReceiver/src/com/android/cts/intent/receiver/IntentReceiverActivity.java
index 17dc3f1..59f0752 100644
--- a/hostsidetests/devicepolicy/app/IntentReceiver/src/com/android/cts/intent/receiver/IntentReceiverActivity.java
+++ b/hostsidetests/devicepolicy/app/IntentReceiver/src/com/android/cts/intent/receiver/IntentReceiverActivity.java
@@ -22,12 +22,11 @@
 import android.util.Log;
 
 import java.io.BufferedReader;
+import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
-import java.io.IOException;
 import java.io.OutputStreamWriter;
 
-
 /**
  * Class to receive intents sent across profile boundaries, and read/write to content uri specified
  * in these intents to test cross-profile content uris.
diff --git a/hostsidetests/devicepolicy/app/IntentSender/Android.mk b/hostsidetests/devicepolicy/app/IntentSender/Android.mk
new file mode 100644
index 0000000..e45ec31
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/IntentSender/Android.mk
@@ -0,0 +1,33 @@
+# Copyright (C) 2014 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsIntentSenderApp
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/devicepolicy/app/IntentSender/AndroidManifest.xml b/hostsidetests/devicepolicy/app/IntentSender/AndroidManifest.xml
new file mode 100644
index 0000000..070ef40
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/IntentSender/AndroidManifest.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.cts.intent.sender">
+
+    <uses-sdk android:minSdkVersion="19" />
+
+    <permission
+        android:name="com.android.cts.intent.sender.permission.SAMPLE"
+        android:label="Sample Permission" />
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+
+        <activity android:name=".IntentSenderActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+            </intent-filter>
+        </activity>
+
+        <provider
+            android:name="android.support.v4.content.FileProvider"
+            android:authorities="com.android.cts.intent.sender.fileprovider"
+            android:grantUriPermissions="true"
+            android:exported="false">
+            <meta-data
+                android:name="android.support.FILE_PROVIDER_PATHS"
+                android:resource="@xml/filepaths" />
+        </provider>
+
+        <provider
+            android:name=".BasicContentProvider"
+            android:authorities="com.android.cts.intent.sender.provider"
+            android:grantUriPermissions="true"
+            android:exported="true"
+            android:permission="com.android.cts.intent.sender.permission.SAMPLE" />
+
+    </application>
+
+    <instrumentation
+        android:name="android.test.InstrumentationTestRunner"
+        android:targetPackage="com.android.cts.intent.sender"
+        android:label="Intent Sender CTS Tests" />
+
+</manifest>
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/res/xml/filepaths.xml b/hostsidetests/devicepolicy/app/IntentSender/res/xml/filepaths.xml
similarity index 100%
rename from hostsidetests/devicepolicy/app/ManagedProfile/res/xml/filepaths.xml
rename to hostsidetests/devicepolicy/app/IntentSender/res/xml/filepaths.xml
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/BasicContentProvider.java b/hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/BasicContentProvider.java
similarity index 96%
rename from hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/BasicContentProvider.java
rename to hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/BasicContentProvider.java
index f91d404..183ab9f 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/BasicContentProvider.java
+++ b/hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/BasicContentProvider.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.cts.managedprofile.crossprofilecontent;
+package com.android.cts.intent.sender;
 
 import android.content.ContentProvider;
 import android.content.ContentValues;
@@ -69,4 +69,3 @@
                 new File("/dev/null"), ParcelFileDescriptor.MODE_READ_ONLY);
     }
 }
-
diff --git a/hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/IntentSenderActivity.java b/hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/IntentSenderActivity.java
new file mode 100644
index 0000000..00fa6b7
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/IntentSenderActivity.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2014 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 com.android.cts.intent.sender;
+
+import android.app.Activity;
+import android.content.Intent;
+
+import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.TimeUnit;
+
+public class IntentSenderActivity extends Activity {
+
+    private final SynchronousQueue<Result> mResult = new SynchronousQueue<>();
+
+    public static class Result {
+        public final int resultCode;
+        public final Intent data;
+
+        public Result(int resultCode, Intent data) {
+            this.resultCode = resultCode;
+            this.data = data;
+        }
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        if (resultCode == Activity.RESULT_OK) {
+            try {
+                mResult.offer(new Result(resultCode, data), 5, TimeUnit.SECONDS);
+            } catch (InterruptedException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    public Intent getResult(Intent intent) throws Exception {
+        startActivityForResult(intent, 42);
+        final Result result = mResult.poll(30, TimeUnit.SECONDS);
+        return (result != null) ? result.data : null;
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/CrossProfileContentTest.java b/hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/IntentSenderTest.java
similarity index 76%
rename from hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/CrossProfileContentTest.java
rename to hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/IntentSenderTest.java
index 85e7d1b..47de0da 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/CrossProfileContentTest.java
+++ b/hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/IntentSenderTest.java
@@ -13,30 +13,26 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.cts.managedprofile.crossprofilecontent;
 
-import static com.android.cts.managedprofile.BaseManagedProfileTest.ADMIN_RECEIVER_COMPONENT;
+package com.android.cts.intent.sender;
 
-import android.app.admin.DevicePolicyManager;
 import android.content.ClipData;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
-import android.content.IntentFilter;
 import android.net.Uri;
 import android.support.v4.content.FileProvider;
-import android.test.ActivityInstrumentationTestCase2;
+import android.test.InstrumentationTestCase;
 import android.util.Log;
 
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileWriter;
+import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
-import java.io.IOException;
 
-public class CrossProfileContentTest extends
-        ActivityInstrumentationTestCase2<IntentSenderActivity> {
+public class IntentSenderTest extends InstrumentationTestCase {
 
     private static final String MESSAGE = "Sample Message";
 
@@ -49,35 +45,20 @@
 
     private static final String TAG = "CrossProfileContentTest";
 
-    private static final String BASIC_CONTENT_PROVIDER_AUTHORITY =
-            "com.android.cts.managedprofile.basiccontentProvider";
-
-
-    private DevicePolicyManager mDpm;
-
     private Context mContext;
-
-    public CrossProfileContentTest() {
-        super(IntentSenderActivity.class);
-    }
+    private IntentSenderActivity mActivity;
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
         mContext = getInstrumentation().getTargetContext();
-        mDpm = (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
-        IntentFilter intentFilter = new IntentFilter();
-        intentFilter.addAction(ACTION_READ_FROM_URI);
-        intentFilter.addAction(ACTION_WRITE_TO_URI);
-        intentFilter.addAction(ACTION_TAKE_PERSISTABLE_URI_PERMISSION);
-        mDpm.addCrossProfileIntentFilter(ADMIN_RECEIVER_COMPONENT, intentFilter,
-                DevicePolicyManager.FLAG_PARENT_CAN_ACCESS_MANAGED);
+        mActivity = launchActivity(mContext.getPackageName(), IntentSenderActivity.class, null);
     }
 
     @Override
-    protected void tearDown() throws Exception {
-        mDpm.clearCrossProfileIntentFilters(ADMIN_RECEIVER_COMPONENT);
+    public void tearDown() throws Exception {
         super.tearDown();
+        mActivity.finish();
     }
 
     /**
@@ -85,14 +66,15 @@
      * This intent will have, in the ClipData, a uri whose associated file stores a message.
      * The receiver will read the message from the uri, and put it inside the result intent.
      */
-    public void testReceiverCanRead() {
+    public void testReceiverCanRead() throws Exception {
         Uri uri = getUriWithTextInFile("reading_test", MESSAGE);
         assertTrue(uri != null);
         Intent intent = new Intent(ACTION_READ_FROM_URI);
         intent.setClipData(ClipData.newRawUri("", uri));
         intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-        Intent result = getActivity().getResultForIntent(intent);
-        assertTrue(result != null);
+
+        final Intent result = mActivity.getResult(intent);
+        assertNotNull(result);
         assertEquals(MESSAGE, result.getStringExtra("extra_response"));
     }
 
@@ -102,7 +84,7 @@
      * The receiver will read the message from the extra, and write it to the uri in
      * the ClipData.
      */
-    public void testReceiverCanWrite() {
+    public void testReceiverCanWrite() throws Exception {
         // It's the receiver of the intent that should write to the uri, not us. So, for now, we
         // write an empty string.
         Uri uri = getUriWithTextInFile("writing_test", "");
@@ -112,19 +94,21 @@
         intent.putExtra("extra_message", MESSAGE);
         intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION
                 | Intent.FLAG_GRANT_READ_URI_PERMISSION);
-        getActivity().getResultForIntent(intent);
+
+        mActivity.getResult(intent);
         assertEquals(MESSAGE, getFirstLineFromUri(uri));
     }
 
-    public void testPersistablePermission() {
+    public void testPersistablePermission() throws Exception {
         Uri uri = getUriWithTextInFile("persistable_test", MESSAGE);
         grantPersistableReadPermission(uri);
 
         // Now checking if the receiver can read this uri, without re-granting the read permission.
         Intent intent = new Intent(ACTION_READ_FROM_URI);
         intent.setClipData(ClipData.newRawUri("", uri));
-        Intent result = getActivity().getResultForIntent(intent);
-        assertTrue(result != null);
+
+        final Intent result = mActivity.getResult(intent);
+        assertNotNull(result);
         assertEquals(MESSAGE, result.getStringExtra("extra_response"));
     }
 
@@ -138,7 +122,7 @@
      * uriNotGranted), to enforce that even if an app has permission to one uri of a
      * ContentProvider, it still cannot access a uri it does not have access to.
      */
-    public void testAppPermissionsDontWorkAcrossProfiles() {
+    public void testAppPermissionsDontWorkAcrossProfiles() throws Exception {
         // The FileProvider does not allow to use app permissions. So we need to use another
         // ContentProvider.
         Uri uriGranted = getBasicContentProviderUri("uri_granted");
@@ -152,19 +136,41 @@
         Intent notGrant = new Intent(ACTION_READ_FROM_URI);
         notGrant.setClipData(ClipData.newRawUri("", uriNotGranted));
 
-        Intent result = getActivity().getResultForIntent(notGrant);
-        assertTrue(result != null);
+        final Intent result = mActivity.getResult(notGrant);
+        assertNotNull(result);
         // The receiver did not have permission to read the uri. So it should have caught a security
         // exception.
         assertTrue(result.getBooleanExtra("extra_caught_security_exception", false));
     }
 
-    private void grantPersistableReadPermission(Uri uri) {
+    /**
+     * Ensure that sender is only able to send data that it has access to.
+     */
+    public void testSecurity() throws Exception {
+        // Pick a URI that neither of us have access to; it doens't matter if
+        // its missing, since we expect a SE before a FNFE.
+        final Uri uri = Uri.parse("content://media/external/images/media/10240");
+        final Intent intent = new Intent(ACTION_READ_FROM_URI);
+        intent.setClipData(ClipData.newRawUri("", uri));
+        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+
+        // We're expecting to run into a security exception
+        final Intent result = mActivity.getResult(intent);
+        if (result == null) {
+            // This is fine; probably of a SecurityException when off in the
+            // system somewhere.
+        } else {
+            // But if we somehow came through, make sure they threw.
+            assertTrue(result.getBooleanExtra("extra_caught_security_exception", false));
+        }
+    }
+
+    private void grantPersistableReadPermission(Uri uri) throws Exception {
         Intent grantPersistable = new Intent(ACTION_TAKE_PERSISTABLE_URI_PERMISSION);
         grantPersistable.setClipData(ClipData.newRawUri("", uri));
         grantPersistable.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
                 | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
-        getActivity().getResultForIntent(grantPersistable);
+        mActivity.getResult(grantPersistable);
     }
 
     private Uri getBasicContentProviderUri(String path) {
@@ -172,7 +178,7 @@
         // granting these uris to other apps, or these apps from trying to access these uris.
         return new Uri.Builder()
                 .scheme(ContentResolver.SCHEME_CONTENT)
-                .authority(BASIC_CONTENT_PROVIDER_AUTHORITY)
+                .authority("com.android.cts.intent.sender.provider")
                 .path(path)
                 .build();
     }
@@ -191,7 +197,7 @@
             Log.e(TAG, "Could not create file " + filename + " with text " + text);
             return null;
         }
-        return FileProvider.getUriForFile(mContext, "com.android.cts.managedprofile.fileprovider",
+        return FileProvider.getUriForFile(mContext, "com.android.cts.intent.sender.fileprovider",
                 file);
     }
 
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml b/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
index 56b3671..008ed38 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
@@ -19,9 +19,6 @@
 
     <uses-sdk android:minSdkVersion="20"/>
 
-    <permission android:name="com.android.cts.managedprofile.permission.SAMPLE"
-                android:label="Sample Permission"/>
-
     <application>
         <uses-library android:name="android.test.runner" />
         <receiver
@@ -65,11 +62,6 @@
                 <action android:name="com.android.cts.managedprofile.ACTION_TEST_ALL_ACTIVITY" />
             </intent-filter>
         </activity>
-        <activity android:name=".crossprofilecontent.IntentSenderActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN"/>
-            </intent-filter>
-        </activity>
         <activity android:name=".UserRestrictionActivity" >
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
@@ -77,22 +69,6 @@
             </intent-filter>
         </activity>
         <activity android:name=".TestActivity" />
-        <provider
-            android:name="android.support.v4.content.FileProvider"
-            android:authorities="com.android.cts.managedprofile.fileprovider"
-            android:grantUriPermissions="true"
-            android:exported="false">
-            <meta-data
-                android:name="android.support.FILE_PROVIDER_PATHS"
-                android:resource="@xml/filepaths" />
-        </provider>
-        <provider
-            android:name="com.android.cts.managedprofile.crossprofilecontent.BasicContentProvider"
-            android:authorities="com.android.cts.managedprofile.basiccontentProvider"
-            android:grantUriPermissions="true"
-            android:exported="true"
-            android:permission="com.android.cts.managedprofile.permission.SAMPLE"
-            />
     </application>
 
     <instrumentation android:name="android.test.InstrumentationTestRunner"
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/AllUsersActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/AllUsersActivity.java
similarity index 100%
rename from hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/AllUsersActivity.java
rename to hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/AllUsersActivity.java
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/ComponentDisablingActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ComponentDisablingActivity.java
similarity index 100%
rename from hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/ComponentDisablingActivity.java
rename to hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ComponentDisablingActivity.java
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/CrossProfileUtils.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/CrossProfileUtils.java
new file mode 100644
index 0000000..9615991
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/CrossProfileUtils.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2014 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 com.android.cts.managedprofile;
+
+import static com.android.cts.managedprofile.BaseManagedProfileTest.ADMIN_RECEIVER_COMPONENT;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.IntentFilter;
+import android.test.AndroidTestCase;
+
+public class CrossProfileUtils extends AndroidTestCase {
+    private static final String ACTION_READ_FROM_URI = "com.android.cts.action.READ_FROM_URI";
+
+    private static final String ACTION_WRITE_TO_URI = "com.android.cts.action.WRITE_TO_URI";
+
+    private static final String ACTION_TAKE_PERSISTABLE_URI_PERMISSION =
+            "com.android.cts.action.TAKE_PERSISTABLE_URI_PERMISSION";
+
+    public void addParentCanAccessManagedFilters() {
+        removeAllFilters();
+
+        final DevicePolicyManager dpm = (DevicePolicyManager) getContext().getSystemService(
+                Context.DEVICE_POLICY_SERVICE);
+        IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(ACTION_READ_FROM_URI);
+        intentFilter.addAction(ACTION_WRITE_TO_URI);
+        intentFilter.addAction(ACTION_TAKE_PERSISTABLE_URI_PERMISSION);
+        dpm.addCrossProfileIntentFilter(ADMIN_RECEIVER_COMPONENT, intentFilter,
+                DevicePolicyManager.FLAG_PARENT_CAN_ACCESS_MANAGED);
+    }
+
+    public void addManagedCanAccessParentFilters() {
+        removeAllFilters();
+
+        final DevicePolicyManager dpm = (DevicePolicyManager) getContext().getSystemService(
+                Context.DEVICE_POLICY_SERVICE);
+        IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(ACTION_READ_FROM_URI);
+        intentFilter.addAction(ACTION_WRITE_TO_URI);
+        intentFilter.addAction(ACTION_TAKE_PERSISTABLE_URI_PERMISSION);
+        dpm.addCrossProfileIntentFilter(ADMIN_RECEIVER_COMPONENT, intentFilter,
+                DevicePolicyManager.FLAG_MANAGED_CAN_ACCESS_PARENT);
+    }
+
+    public void removeAllFilters() {
+        final DevicePolicyManager dpm = (DevicePolicyManager) getContext().getSystemService(
+                Context.DEVICE_POLICY_SERVICE);
+        dpm.clearCrossProfileIntentFilters(ADMIN_RECEIVER_COMPONENT);
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/ManagedProfileActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ManagedProfileActivity.java
similarity index 100%
rename from hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/ManagedProfileActivity.java
rename to hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ManagedProfileActivity.java
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/ManagedProfileTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ManagedProfileTest.java
similarity index 100%
rename from hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/ManagedProfileTest.java
rename to hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ManagedProfileTest.java
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/PrimaryUserActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserActivity.java
similarity index 99%
rename from hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/PrimaryUserActivity.java
rename to hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserActivity.java
index 35f70be..b0e84ae 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/PrimaryUserActivity.java
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserActivity.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package com.android.cts.managedprofile;
 
 import android.app.Activity;
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/PrimaryUserFilterSetterActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserFilterSetterActivity.java
similarity index 100%
rename from hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/PrimaryUserFilterSetterActivity.java
rename to hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserFilterSetterActivity.java
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/PrimaryUserTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserTest.java
similarity index 99%
rename from hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/PrimaryUserTest.java
rename to hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserTest.java
index 7098d9e..40ff6c5 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/PrimaryUserTest.java
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserTest.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package com.android.cts.managedprofile;
 
 import android.app.admin.DevicePolicyManager;
@@ -55,7 +56,7 @@
     public void testAddCrossProfileIntentFilter_all() {
         assertEquals(2, mPackageManager.queryIntentActivities(
                 new Intent(AllUsersActivity.ACTION), /* flags = */ 0).size());
-        
+
         // If we used startActivity(), the user would have a disambiguation dialog presented which
         // requires human intervention, so we won't be testing like that
     }
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/TestActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/TestActivity.java
similarity index 100%
rename from hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/TestActivity.java
rename to hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/TestActivity.java
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/IntentSenderActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/IntentSenderActivity.java
deleted file mode 100644
index e4c8ddf..0000000
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/IntentSenderActivity.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2014 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 com.android.cts.managedprofile.crossprofilecontent;
-
-import static com.android.cts.managedprofile.BaseManagedProfileTest.ADMIN_RECEIVER_COMPONENT;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.util.Log;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-public class IntentSenderActivity extends Activity {
-
-    private CountDownLatch mLatch;
-
-    private static final int WAIT_FOR_RESPONSE_TIMEOUT_SECONDS = 5;
-
-    private Intent mResult;
-
-    Intent getResultForIntent(Intent intent) {
-        mLatch = new CountDownLatch(1);
-        mResult = null;
-        startActivityForResult(intent, 0);
-        try {
-            mLatch.await(WAIT_FOR_RESPONSE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
-        } catch (InterruptedException e) {
-        }
-        return mResult;
-    }
-
-    @Override
-    protected void onActivityResult(int requestCode, int resultCode, Intent result) {
-        if (resultCode == Activity.RESULT_OK) {
-            mResult = result;
-        }
-        mLatch.countDown();
-    }
-}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
index 15c7725..544ddff 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
@@ -17,6 +17,7 @@
 package com.android.cts.devicepolicy;
 
 import com.android.cts.tradefed.build.CtsBuildHelper;
+import com.android.cts.util.AbiUtils;
 import com.android.ddmlib.Log.LogLevel;
 import com.android.ddmlib.testrunner.InstrumentationResultParser;
 import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
@@ -26,11 +27,13 @@
 import com.android.ddmlib.testrunner.TestRunResult;
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.log.LogUtil.CLog;
 import com.android.tradefed.result.CollectingTestListener;
 import com.android.tradefed.testtype.DeviceTestCase;
 import com.android.tradefed.testtype.IBuildReceiver;
 
+import java.io.File;
 import java.io.FileNotFoundException;
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -74,6 +77,21 @@
                 installResult);
     }
 
+    protected void installAppAsUser(String appFileName, int userId) throws FileNotFoundException,
+            DeviceNotAvailableException {
+        final ITestDevice device = getDevice();
+
+        final File apk = mCtsBuild.getTestApp(appFileName);
+        final String remotePath = "/data/local/tmp/" + apk.getName();
+        if (!device.pushFile(apk, remotePath)) {
+            throw new IllegalStateException("Failed to push " + apk);
+        }
+
+        final String result = device.executeShellCommand(
+                "pm install --user " + userId + " " + remotePath);
+        assertTrue(result, result.contains("\nSuccess"));
+    }
+
     /** Initializes the user with the given id. This is required so that apps can run on it. */
     protected void startUser(int userId) throws DeviceNotAvailableException {
         String command = "am start-user " + userId;
@@ -135,7 +153,17 @@
     protected boolean runDeviceTestsAsUser(
             String pkgName, @Nullable String testClassName, int userId)
             throws DeviceNotAvailableException {
-        return runDeviceTests(pkgName, testClassName, null /*testMethodName*/, userId);
+        return runDeviceTestsAsUser(pkgName, testClassName, null, userId);
+    }
+
+    /** Returns true if the specified tests passed. Tests are run as given user. */
+    protected boolean runDeviceTestsAsUser(
+            String pkgName, @Nullable String testClassName, String testMethodName, int userId)
+            throws DeviceNotAvailableException {
+        if (testClassName.startsWith(".")) {
+            testClassName = pkgName + testClassName;
+        }
+        return runDeviceTests(pkgName, testClassName, testMethodName, userId);
     }
 
     private boolean runDeviceTests(String pkgName, @Nullable String testClassName,
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
index 88a3b70..6ece85c 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
@@ -28,6 +28,9 @@
     private static final String MANAGED_PROFILE_PKG = "com.android.cts.managedprofile";
     private static final String MANAGED_PROFILE_APK = "CtsManagedProfileApp.apk";
 
+    private static final String INTENT_SENDER_PKG = "com.android.cts.intent.sender";
+    private static final String INTENT_SENDER_APK = "CtsIntentSenderApp.apk";
+
     private static final String INTENT_RECEIVER_PKG = "com.android.cts.intent.receiver";
     private static final String INTENT_RECEIVER_APK = "CtsIntentReceiverApp.apk";
 
@@ -110,16 +113,30 @@
         if (!mHasFeature) {
             return;
         }
+
         try {
-            installApp(INTENT_RECEIVER_APK);
+            getDevice().uninstallPackage(INTENT_SENDER_PKG);
+            getDevice().uninstallPackage(INTENT_RECEIVER_PKG);
+            installAppAsUser(INTENT_SENDER_APK, 0);
+            installAppAsUser(INTENT_RECEIVER_APK, mUserId);
 
-            String command = "pm uninstall --user " + mUserId + " " + INTENT_RECEIVER_PKG;
-            CLog.logAndDisplay(LogLevel.INFO, "Output for command " + command + ": "
-                    + getDevice().executeShellCommand(command));
+            // Test from parent to managed
+            assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".CrossProfileUtils",
+                    "addManagedCanAccessParentFilters", mUserId));
+            assertTrue(runDeviceTestsAsUser(INTENT_SENDER_PKG, ".IntentSenderTest", 0));
 
-            assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG,
-                    MANAGED_PROFILE_PKG + ".crossprofilecontent.CrossProfileContentTest", mUserId));
+            getDevice().uninstallPackage(INTENT_SENDER_PKG);
+            getDevice().uninstallPackage(INTENT_RECEIVER_PKG);
+            installAppAsUser(INTENT_SENDER_APK, mUserId);
+            installAppAsUser(INTENT_RECEIVER_APK, 0);
+
+            // Test from managed to parent
+            assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".CrossProfileUtils",
+                    "addParentCanAccessManagedFilters", mUserId));
+            assertTrue(runDeviceTestsAsUser(INTENT_SENDER_PKG, ".IntentSenderTest", mUserId));
+
         } finally {
+            getDevice().uninstallPackage(INTENT_SENDER_PKG);
             getDevice().uninstallPackage(INTENT_RECEIVER_PKG);
         }
     }
diff --git a/libs/commonutil/Android.mk b/libs/commonutil/Android.mk
new file mode 100644
index 0000000..9c131b0
--- /dev/null
+++ b/libs/commonutil/Android.mk
@@ -0,0 +1,27 @@
+#
+# Copyright (C) 2014 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.
+#
+
+include $(call all-subdir-makefiles)
+
+# ======================================================
+# Build a static host library for the AbiUtils
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := src/com/android/cts/util/AbiUtils.java
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE := ctsabiutilslib
+include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/libs/commonutil/src/com/android/cts/util/AbiUtils.java b/libs/commonutil/src/com/android/cts/util/AbiUtils.java
index 4a34c6f..6f47d52 100644
--- a/libs/commonutil/src/com/android/cts/util/AbiUtils.java
+++ b/libs/commonutil/src/com/android/cts/util/AbiUtils.java
@@ -163,4 +163,22 @@
     public static String getBitness(String name) {
         return ABIS_32BIT.contains(name) ? "32" : "64";
     }
+
+    /**
+     * @param abilistString A comma separated string containing abis.
+     * @return A List of Strings containing valid ABIs.
+     */
+    public static Set<String> parseAbiList(String unsupportedAbiDescription) {
+        Set<String> abiSet = new HashSet<>();
+        String[] descSegments = unsupportedAbiDescription.split(":");
+        if (descSegments.length == 2) {
+            for (String abi : descSegments[1].split(",")) {
+                String trimmedAbi = abi.trim();
+                if (isAbiSupportedByCts(trimmedAbi)) {
+                    abiSet.add(trimmedAbi);
+                }
+            }
+        }
+        return abiSet;
+    }
 }
diff --git a/suite/cts/deviceTests/browserbench/src/com/android/cts/browser/BrowserBenchTest.java b/suite/cts/deviceTests/browserbench/src/com/android/cts/browser/BrowserBenchTest.java
index 997f730..d74ddb2 100644
--- a/suite/cts/deviceTests/browserbench/src/com/android/cts/browser/BrowserBenchTest.java
+++ b/suite/cts/deviceTests/browserbench/src/com/android/cts/browser/BrowserBenchTest.java
@@ -17,6 +17,7 @@
 package com.android.cts.browser;
 
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.cts.util.WatchDog;
 import android.net.Uri;
 import android.provider.Browser;
@@ -70,10 +71,12 @@
     private volatile int mRunIndex;
     /** stores results for each runs. last entry will be the final score. */
     private LinkedHashMap<String, double[]> mResultsMap;
+    private PackageManager mPackageManager;
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+        mPackageManager = getInstrumentation().getContext().getPackageManager();
         mWebServer = new CtsTestServer(getContext()) {
             @Override
             protected HttpResponse onPost(HttpRequest request) throws Exception {
@@ -124,6 +127,10 @@
 
     @TimeoutReq(minutes = 60)
     public void testOctane() throws InterruptedException {
+        if (!isBrowserSupported()) {
+            Log.i(TAG, "Skipping test for device with no supported browser");
+            return;
+        }
         String url = mWebServer.getAssetUrl(OCTANE_START_FILE) + "?auto=1";
         final int kRepeat = 5;
         doTest(url, ResultType.LOWER_BETTER, ResultUnit.MS,
@@ -167,4 +174,13 @@
             numberToProcess++;
         }
     }
+
+    /**
+     * @return true iff this device is has a working browser.
+     */
+    private boolean isBrowserSupported() {
+        return !(mPackageManager.hasSystemFeature("android.hardware.type.television")
+                 || mPackageManager.hasSystemFeature("android.software.leanback")
+                 || mPackageManager.hasSystemFeature("android.hardware.type.watch"));
+    }
 }
diff --git a/tests/expectations/knownfailures.txt b/tests/expectations/knownfailures.txt
index 8adf345..9ae041c 100644
--- a/tests/expectations/knownfailures.txt
+++ b/tests/expectations/knownfailures.txt
@@ -1,5 +1,13 @@
 [
 {
+  description: "tests a fragile by nature as they rely on hardcoded behavior",
+  names: [
+    "android.accessibilityservice.cts.AccessibilityTextTraversalTest#testActionNextAndPreviousAtGranularityPageOverText",
+    "android.accessibilityservice.cts.AccessibilityTextTraversalTest#testActionNextAndPreviousAtGranularityPageOverTextExtend"
+  ],
+  bug: 17595050
+},
+{
   description: "signature test stil needs more work",
   names: [
     "android.signature.cts.SignatureTest#testSignature"
@@ -37,6 +45,26 @@
   bug: 16720689
 },
 {
+  description: "test can only run properly on a user build device when the bug is resolved",
+  names: [
+    "android.appwidget.cts.AppWidgetTest#testAppWidgetProviderCallbacks",
+    "android.appwidget.cts.AppWidgetTest#testBindAppWidget",
+    "android.appwidget.cts.AppWidgetTest#testCollectionWidgets",
+    "android.appwidget.cts.AppWidgetTest#testDeleteHost",
+    "android.appwidget.cts.AppWidgetTest#testDeleteHosts",
+    "android.appwidget.cts.AppWidgetTest#testGetAppWidgetIds",
+    "android.appwidget.cts.AppWidgetTest#testGetAppWidgetInfo",
+    "android.appwidget.cts.AppWidgetTest#testGetAppWidgetOptions",
+    "android.appwidget.cts.AppWidgetTest#testPartiallyUpdateAppWidgetViaWidgetId",
+    "android.appwidget.cts.AppWidgetTest#testPartiallyUpdateAppWidgetViaWidgetIds",
+    "android.appwidget.cts.AppWidgetTest#testTwoAppWidgetProviderCallbacks",
+    "android.appwidget.cts.AppWidgetTest#testUpdateAppWidgetViaComponentName",
+    "android.appwidget.cts.AppWidgetTest#testUpdateAppWidgetViaWidgetId",
+    "android.appwidget.cts.AppWidgetTest#testUpdateAppWidgetViaWidgetIds"
+  ],
+  bug: 17993121
+},
+{
   description: "A few WebGL tests are known to fail in WebView",
   names: [
     "android.webgl.cts.WebGLTest#test_conformance_extensions_oes_texture_float_with_video_html",
@@ -74,6 +102,13 @@
   bug: 17530117
 },
 {
+  description: "this test removes the stay-awake option, causing the screen to turn off during the execution of subsequent tests",
+  names: [
+    "android.admin.cts.DevicePolicyManagerTest#testMaximumTimeToLock"
+  ],
+  bug: 18002490
+},
+{
   description: "these tests locks the screen with an emtpy password or swipe-to-unlock, blocking subsequent test to dismiss keyguard",
   names: [
     "android.admin.cts.DevicePolicyManagerTest#testPasswordQuality_something",
diff --git a/tests/expectations/unsupportedabis.txt b/tests/expectations/unsupportedabis.txt
index 520d750..817179b 100644
--- a/tests/expectations/unsupportedabis.txt
+++ b/tests/expectations/unsupportedabis.txt
@@ -2,6 +2,14 @@
 {
   description: "Tests not supporting: arm64-v8a, x86_64, mips64",
   names: [
+    "android.bionic.malloc#pvalloc_overflow",
+    "android.bionic.malloc#pvalloc_std",
+    "android.bionic.malloc#valloc_overflow",
+    "android.bionic.malloc#valloc_std",
+    "android.renderscriptlegacy.cts.LeakTest",
+    "android.renderscriptlegacy.cts.RSBase",
+    "android.renderscriptlegacy.cts.RSBaseCompute",
+    "android.renderscriptlegacy.cts.VersionTest",
     "android.sample.cts.SampleDeviceResultTest",
     "android.sample.cts.SampleDeviceTest",
     "android.sample.cts.SampleHostResultTest",
diff --git a/tests/tests/bionic/Android.mk b/tests/tests/bionic/Android.mk
index 1a048c6..e1afd50 100644
--- a/tests/tests/bionic/Android.mk
+++ b/tests/tests/bionic/Android.mk
@@ -8,6 +8,9 @@
 LOCAL_MODULE := $(test_executable)
 LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativetest
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
 
 LOCAL_ADDITION_DEPENDENCIES := \
     $(LOCAL_PATH)/Android.mk \
@@ -31,6 +34,10 @@
 
 LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE := $(list_executable)
+LOCAL_MULTILIB := both
+# Use the 32 bit list executable since it will include some 32 bit only tests.
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
 
 LOCAL_ADDITION_DEPENDENCIES := \
     $(LOCAL_PATH)/Android.mk \
diff --git a/tests/tests/graphics/res/drawable/vector_icon_delete.xml b/tests/tests/graphics/res/drawable/vector_icon_delete.xml
index 7b8f2aa..8d9c21c 100644
--- a/tests/tests/graphics/res/drawable/vector_icon_delete.xml
+++ b/tests/tests/graphics/res/drawable/vector_icon_delete.xml
@@ -24,6 +24,6 @@
 
     <path
         android:fillColor="#FF000000"
-        android:pathData="M6.0,19.0c0.0,1.104 896e-3,2.0 2.0,2.0l8.0,0.0c1.104,0.0 2.0-896e-3 2.0-2.0l0.0-12.0L6.0,7.0L6.0,19.0zM18.0,4.0l-2.5,0.0l-1.0-1.0l-5.0,0.0l-1.0,1.0L6.0,4.0C5.4469986,4.0 5.0,4.4469986 5.0,5.0l0.0,1.0l14.0,0.0l0.0-1.0C19.0,4.4469986 18.552002,4.0 18.0,4.0z" />
+        android:pathData="M6.0,19.0c0.0,1.104 0.896,2.0 2.0,2.0l8.0,0.0c1.104,0.0 2.0-0.896 2.0-2.0l0.0-12.0L6.0,7.0L6.0,19.0zM18.0,4.0l-2.5,0.0l-1.0-1.0l-5.0,0.0l-1.0,1.0L6.0,4.0C5.4469986,4.0 5.0,4.4469986 5.0,5.0l0.0,1.0l14.0,0.0l0.0-1.0C19.0,4.4469986 18.552002,4.0 18.0,4.0z" />
 
 </vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/vector_icon_heart.xml b/tests/tests/graphics/res/drawable/vector_icon_heart.xml
index ad991c9..ff55fe5 100644
--- a/tests/tests/graphics/res/drawable/vector_icon_heart.xml
+++ b/tests/tests/graphics/res/drawable/vector_icon_heart.xml
@@ -24,6 +24,6 @@
 
     <path
         android:fillColor="#FF000000"
-        android:pathData="M16.0,5.0c-1.955.0 -3.83,1.268 -4.5,3.0c-0.67-1.732 -2.547-3.0 -4.5-3.0C4.4570007,5.0 2.5,6.931999 2.5,9.5c0.0,3.529 3.793,6.258 9.0,11.5c5.207-5.242 9.0-7.971 9.0-11.5C20.5,6.931999 18.543,5.0 16.0,5.0z" />
+        android:pathData="M16.0,5.0c-1.955,0.0 -3.83,1.268 -4.5,3.0c-0.67-1.732 -2.547-3.0 -4.5-3.0C4.4570007,5.0 2.5,6.931999 2.5,9.5c0.0,3.529 3.793,6.258 9.0,11.5c5.207-5.242 9.0-7.971 9.0-11.5C20.5,6.931999 18.543,5.0 16.0,5.0z" />
 
 </vector>
\ No newline at end of file
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/RecordingTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/RecordingTest.java
index ea15c19..27becef 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/RecordingTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/RecordingTest.java
@@ -548,6 +548,8 @@
      */
     private void videoSnapshotTestByCamera(boolean burstTest)
             throws Exception {
+        final int NUM_SINGLE_SHOT_TEST = 5;
+        final int FRAMEDROP_TOLERANCE = 8;
         for (int profileId : mCamcorderProfileList) {
             int cameraId = Integer.valueOf(mCamera.getId());
             if (!CamcorderProfile.hasProfile(cameraId, profileId) ||
@@ -603,70 +605,89 @@
                         + videoSz.toString() + ".mp4";
             }
 
-            prepareRecordingWithProfile(profile);
+            int numTestIterations = burstTest ? 1 : NUM_SINGLE_SHOT_TEST;
+            int totalDroppedFrames = 0;
 
-            // prepare video snapshot
-            SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
-            SimpleImageReaderListener imageListener = new SimpleImageReaderListener();
-            CaptureRequest.Builder videoSnapshotRequestBuilder =
-                    mCamera.createCaptureRequest((mStaticInfo.isHardwareLevelLegacy()) ?
-                            CameraDevice.TEMPLATE_RECORD : CameraDevice.TEMPLATE_VIDEO_SNAPSHOT);
+            for (int numTested = 0; numTested < numTestIterations; numTested++) {
+                prepareRecordingWithProfile(profile);
 
-            // prepare preview surface by using video size.
-            updatePreviewSurfaceWithVideoSize(videoSz);
+                // prepare video snapshot
+                SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
+                SimpleImageReaderListener imageListener = new SimpleImageReaderListener();
+                CaptureRequest.Builder videoSnapshotRequestBuilder =
+                        mCamera.createCaptureRequest((mStaticInfo.isHardwareLevelLegacy()) ?
+                                CameraDevice.TEMPLATE_RECORD :
+                                CameraDevice.TEMPLATE_VIDEO_SNAPSHOT);
 
-            prepareVideoSnapshot(videoSnapshotRequestBuilder, imageListener);
+                // prepare preview surface by using video size.
+                updatePreviewSurfaceWithVideoSize(videoSz);
 
-            // Start recording
-            startRecording(/* useMediaRecorder */true, resultListener);
-            long startTime = SystemClock.elapsedRealtime();
+                prepareVideoSnapshot(videoSnapshotRequestBuilder, imageListener);
+                CaptureRequest request = videoSnapshotRequestBuilder.build();
 
-            // Record certain duration.
-            SystemClock.sleep(RECORDING_DURATION_MS / 2);
+                // Start recording
+                startRecording(/* useMediaRecorder */true, resultListener);
+                long startTime = SystemClock.elapsedRealtime();
 
-            // take a video snapshot
-            CaptureRequest request = videoSnapshotRequestBuilder.build();
-            if (burstTest) {
-                List<CaptureRequest> requests =
-                        new ArrayList<CaptureRequest>(BURST_VIDEO_SNAPSHOT_NUM);
-                for (int i = 0; i < BURST_VIDEO_SNAPSHOT_NUM; i++) {
-                    requests.add(request);
+                // Record certain duration.
+                SystemClock.sleep(RECORDING_DURATION_MS / 2);
+
+                // take video snapshot
+                if (burstTest) {
+                    List<CaptureRequest> requests =
+                            new ArrayList<CaptureRequest>(BURST_VIDEO_SNAPSHOT_NUM);
+                    for (int i = 0; i < BURST_VIDEO_SNAPSHOT_NUM; i++) {
+                        requests.add(request);
+                    }
+                    mSession.captureBurst(requests, resultListener, mHandler);
+                } else {
+                    mSession.capture(request, resultListener, mHandler);
                 }
-                mSession.captureBurst(requests, resultListener, mHandler);
-            } else {
-                mSession.capture(request, resultListener, mHandler);
-            }
 
-            // make sure recording is still going after video snapshot
-            SystemClock.sleep(RECORDING_DURATION_MS / 2);
+                // make sure recording is still going after video snapshot
+                SystemClock.sleep(RECORDING_DURATION_MS / 2);
 
-            // Stop recording and preview
-            stopRecording(/* useMediaRecorder */true);
-            int duration = (int) (SystemClock.elapsedRealtime() - startTime);
+                // Stop recording and preview
+                stopRecording(/* useMediaRecorder */true);
+                int duration = (int) (SystemClock.elapsedRealtime() - startTime);
 
-            // Validation recorded video
-            validateRecording(videoSz, duration);
+                // Validation recorded video
+                validateRecording(videoSz, duration);
 
-            if (burstTest) {
-                for (int i = 0; i < BURST_VIDEO_SNAPSHOT_NUM; i++) {
+                if (burstTest) {
+                    for (int i = 0; i < BURST_VIDEO_SNAPSHOT_NUM; i++) {
+                        Image image = imageListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS);
+                        validateVideoSnapshotCapture(image, videoSnapshotSz);
+                        image.close();
+                    }
+                } else {
+                    // validate video snapshot image
                     Image image = imageListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS);
                     validateVideoSnapshotCapture(image, videoSnapshotSz);
+
+                    // validate if there is framedrop around video snapshot
+                    totalDroppedFrames +=  validateFrameDropAroundVideoSnapshot(
+                            resultListener, image.getTimestamp());
+
+                    //TODO: validate jittering. Should move to PTS
+                    //validateJittering(resultListener);
+
                     image.close();
                 }
-            } else {
-                // validate video snapshot image
-                Image image = imageListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS);
-                validateVideoSnapshotCapture(image, videoSnapshotSz);
-
-                // validate if there is framedrop around video snapshot
-                validateFrameDropAroundVideoSnapshot(resultListener, image.getTimestamp());
-
-                //TODO: validate jittering. Should move to PTS
-                //validateJittering(resultListener);
-
-                image.close();
             }
 
+            if (!burstTest) {
+                Log.w(TAG, String.format("Camera %d Video size %s: Number of dropped frames " +
+                        "detected in %d trials is %d frames.", cameraId, videoSz.toString(),
+                        numTestIterations, totalDroppedFrames));
+                mCollector.expectLessOrEqual(
+                        String.format(
+                                "Camera %d Video size %s: Number of dropped frames %d must not"
+                                + " be larger than %d",
+                                cameraId, videoSz.toString(), totalDroppedFrames,
+                                FRAMEDROP_TOLERANCE),
+                        FRAMEDROP_TOLERANCE, totalDroppedFrames);
+            }
             closeImageReader();
         }
     }
@@ -867,8 +888,9 @@
     /**
      * Validate if video snapshot causes frame drop.
      * Here frame drop is defined as frame duration >= 2 * expected frame duration.
+     * Return the estimated number of frames dropped during video snapshot
      */
-    private void validateFrameDropAroundVideoSnapshot(
+    private int validateFrameDropAroundVideoSnapshot(
             SimpleCaptureCallback resultListener, long imageTimeStamp) {
         int expectedDurationMs = 1000 / mVideoFrameRate;
         CaptureResult prevResult = resultListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
@@ -883,6 +905,7 @@
                         resultListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
                 long nextTS = getValueNotNull(nextResult, CaptureResult.SENSOR_TIMESTAMP);
                 int durationMs = (int) (currentTS - prevTS) / 1000000;
+                int totalFramesDropped = 0;
 
                 // Snapshots in legacy mode pause the preview briefly.  Skip the duration
                 // requirements for legacy mode unless this is fixed.
@@ -925,8 +948,18 @@
                                 durationMs, expectedDurationMs
                         ));
                     }
+
+                    int totalDurationMs = (int) (nextTS - prevTS) / 1000000;
+                    // Rounding and minus 2 for the expected 2 frames interval
+                    totalFramesDropped =
+                            (totalDurationMs + expectedDurationMs / 2) /expectedDurationMs - 2;
+                    if (totalFramesDropped < 0) {
+                        Log.w(TAG, "totalFrameDropped is " + totalFramesDropped +
+                                ". Video frame rate might be too fast.");
+                    }
+                    totalFramesDropped = Math.max(0, totalFramesDropped);
                 }
-                return;
+                return totalFramesDropped;
             }
             prevTS = currentTS;
         }
diff --git a/tests/tests/nativemedia/sl/Android.mk b/tests/tests/nativemedia/sl/Android.mk
index 5b34b3d..48b816c 100644
--- a/tests/tests/nativemedia/sl/Android.mk
+++ b/tests/tests/nativemedia/sl/Android.mk
@@ -10,6 +10,9 @@
 LOCAL_MODULE := $(test_executable)
 LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativetest
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
 
 LOCAL_C_INCLUDES := \
     bionic \
diff --git a/tests/tests/nativemedia/xa/Android.mk b/tests/tests/nativemedia/xa/Android.mk
index 6995bc0..ace315a 100644
--- a/tests/tests/nativemedia/xa/Android.mk
+++ b/tests/tests/nativemedia/xa/Android.mk
@@ -10,6 +10,9 @@
 LOCAL_MODULE:= $(test_executable)
 LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativetest
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
 
 LOCAL_C_INCLUDES := \
     bionic \
diff --git a/tests/tests/widget/res/layout/popupwindow.xml b/tests/tests/widget/res/layout/popupwindow.xml
index 2508115..f93f965 100644
--- a/tests/tests/widget/res/layout/popupwindow.xml
+++ b/tests/tests/widget/res/layout/popupwindow.xml
@@ -14,37 +14,36 @@
      limitations under the License.
 -->
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:orientation="vertical">
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
 
-    <TextView android:id="@+id/anchor_upper"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:text="@string/text_view_hint" />
+    <View android:id="@+id/anchor_upper"
+        android:layout_width="10dp"
+        android:layout_height="10dp"
+        android:layout_alignParentTop="true"
+        android:layout_centerHorizontal="true"
+        android:background="#f00" />
 
-    <LinearLayout android:layout_width="match_parent"
-                android:layout_height="0dp"
-                android:layout_weight="1">
+    <View android:id="@+id/anchor_lower"
+        android:layout_width="10dp"
+        android:layout_height="10dp"
+        android:layout_alignParentBottom="true"
+        android:layout_centerHorizontal="true"
+        android:background="#0f0" />
 
-        <TextView android:id="@+id/anchor_middle_left"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:text="@string/text_view_hint"
-            android:layout_weight="1"/>
+    <View android:id="@+id/anchor_middle_left"
+        android:layout_width="10dp"
+        android:layout_height="10dp"
+        android:layout_alignParentLeft="true"
+        android:layout_centerVertical="true"
+        android:background="#00f" />
 
-        <TextView android:id="@+id/anchor_middle_right"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:text="@string/text_view_hint"
-            android:layout_weight="1"/>
+    <View android:id="@+id/anchor_middle_right"
+        android:layout_width="10dp"
+        android:layout_height="10dp"
+        android:layout_alignParentRight="true"
+        android:layout_centerVertical="true"
+        android:background="#ff0" />
 
-    </LinearLayout>
-
-    <TextView android:id="@+id/anchor_lower"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:text="@string/text_view_hint" />
-
-</LinearLayout>
+</RelativeLayout>
diff --git a/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java b/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
index 4a14d2b..e1742c8 100644
--- a/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
+++ b/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
@@ -25,6 +25,7 @@
 import android.graphics.Color;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
+import android.os.Debug;
 import android.os.SystemClock;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
@@ -580,7 +581,8 @@
         assertEquals(50, mPopupWindow.getHeight());
 
         mPopupWindow.getContentView().getLocationOnScreen(viewXY);
-        // the position should be changed
+
+        // The popup should appear below and to right with an offset.
         assertEquals(anchorXY[0] + 20 + viewInWindowOff[0], viewXY[0]);
         assertEquals(anchorXY[1] + anchorView.getHeight() + 50 + viewInWindowOff[1], viewXY[1]);
 
@@ -597,14 +599,15 @@
         assertEquals(50, mPopupWindow.getHeight());
 
         mPopupWindow.getContentView().getLocationOnScreen(viewXY);
-        // the position should be changed
+
+        // The popup should appear below and to right with an offset.
         assertEquals(anchorXY[0] + 10 + viewInWindowOff[0], viewXY[0]);
         assertEquals(anchorXY[1] + anchorView.getHeight() + 50 + viewInWindowOff[1], viewXY[1]);
 
-        final View anthoterView = mActivity.findViewById(R.id.anchor_middle_right);
+        final View anotherView = mActivity.findViewById(R.id.anchor_middle_left);
         mInstrumentation.runOnMainSync(new Runnable() {
             public void run() {
-                mPopupWindow.update(anthoterView, 0, 0, 60, 60);
+                mPopupWindow.update(anotherView, 0, 0, 60, 60);
             }
         });
         mInstrumentation.waitForIdleSync();
@@ -614,11 +617,12 @@
         assertEquals(60, mPopupWindow.getHeight());
 
         int[] newXY = new int[2];
-        anthoterView.getLocationOnScreen(newXY);
+        anotherView.getLocationOnScreen(newXY);
         mPopupWindow.getContentView().getLocationOnScreen(viewXY);
-        // the position should be changed
+
+        // The popup should appear below and to the right.
         assertEquals(newXY[0] + viewInWindowOff[0], viewXY[0]);
-        assertEquals(newXY[1] + anthoterView.getHeight() + viewInWindowOff[1], viewXY[1]);
+        assertEquals(newXY[1] + anotherView.getHeight() + viewInWindowOff[1], viewXY[1]);
 
         dismissPopup();
     }
@@ -815,8 +819,7 @@
     }
 
     private View createPopupContent() {
-        TextView popupView = new TextView(mActivity);
-        popupView.setText("Popup");
+        View popupView = new View(mActivity);
         popupView.setLayoutParams(new ViewGroup.LayoutParams(50, 50));
         popupView.setBackgroundColor(Color.WHITE);
 
diff --git a/tools/cts-xml-generator/src/com/android/cts/xmlgenerator/XmlGenerator.java b/tools/cts-xml-generator/src/com/android/cts/xmlgenerator/XmlGenerator.java
index 1680cae..833bf69 100644
--- a/tools/cts-xml-generator/src/com/android/cts/xmlgenerator/XmlGenerator.java
+++ b/tools/cts-xml-generator/src/com/android/cts/xmlgenerator/XmlGenerator.java
@@ -205,7 +205,8 @@
             String className = nameCollector.toString();
             nameCollector.append('#').append(test.getName());
             writer.append("<Test name=\"").append(test.getName()).append("\"");
-            String abis = getSupportedAbis(mUnsupportedAbis, mArchitecture, className).toString();
+            String abis = getSupportedAbis(mUnsupportedAbis, mArchitecture,
+                    className, nameCollector.toString()).toString();
             writer.append(" abis=\"" + abis.substring(1, abis.length() - 1) + "\"");
             if (isKnownFailure(mKnownFailures, nameCollector.toString())) {
                 writer.append(" expectation=\"failure\"");
@@ -232,23 +233,36 @@
 
     // Returns the list of ABIs supported by this TestCase on this architecture.
     public static Set<String> getSupportedAbis(ExpectationStore expectationStore,
-            String architecture, String className) {
+            String architecture, String className, String testName) {
         Set<String> supportedAbis = AbiUtils.getAbisForArch(architecture);
-        Expectation e = (expectationStore == null) ? null : expectationStore.get(className);
-        if (e != null && !e.getDescription().isEmpty()) {
-            // Description should be written in the form "blah blah: abi1, abi2..."
-            String description = e.getDescription().split(":")[1];
-            String[] unsupportedAbis = description.split(",");
-            for (String a : unsupportedAbis) {
-                String abi = a.trim();
-                if (!AbiUtils.isAbiSupportedByCts(abi)) {
-                    throw new RuntimeException(
-                            String.format("Unrecognised ABI %s in %s", abi, e.getDescription()));
-                }
-                supportedAbis.remove(abi);
-            }
+        if (expectationStore == null) {
+            return supportedAbis;
         }
+
+        removeUnsupportedAbis(expectationStore.get(className), supportedAbis);
+        removeUnsupportedAbis(expectationStore.get(testName), supportedAbis);
         return supportedAbis;
     }
 
+    public static void removeUnsupportedAbis(Expectation expectation, Set<String> supportedAbis) {
+        if (expectation == null) {
+            return;
+        }
+
+        String description = expectation.getDescription();
+        if (description.isEmpty()) {
+            return;
+        }
+
+        String[] unsupportedAbis = description.split(":")[1].split(",");
+        for (String a : unsupportedAbis) {
+            String abi = a.trim();
+            if (!AbiUtils.isAbiSupportedByCts(abi)) {
+                throw new RuntimeException(
+                        String.format("Unrecognised ABI %s in %s", abi, description));
+            }
+            supportedAbis.remove(abi);
+        }
+    }
+
 }
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/CtsTest.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/CtsTest.java
index 6d617ea..7aed84d 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/CtsTest.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/CtsTest.java
@@ -762,15 +762,26 @@
      */
     private void installPrerequisiteApks(Collection<String> prerequisiteApks)
             throws DeviceNotAvailableException {
+        Log.logAndDisplay(LogLevel.INFO, LOG_TAG, "Installing prerequisites");
+        Set<String> supportedAbiSet = getAbis();
         for (String apkName : prerequisiteApks) {
             try {
                 File apkFile = mCtsBuild.getTestApp(apkName);
-                String errorCode = null;
-                String abi = AbiFormatter.getDefaultAbi(getDevice(), mForceAbi);
-                String[] options = {AbiUtils.createAbiFlag(abi)};
-                errorCode = getDevice().installPackage(apkFile, true, options);
-                if (errorCode != null) {
-                    CLog.e("Failed to install %s. Reason: %s", apkName, errorCode);
+                // As a workaround for multi arch support, try to install the APK
+                // for all device supported ABIs. This will generate warning messages
+                // until the above FIXME is resolved.
+                int installFailCount = 0;
+                for (String abi : supportedAbiSet) {
+                    String[] options = {AbiUtils.createAbiFlag(abi)};
+                    String errorCode = getDevice().installPackage(apkFile, true, options);
+                    if (errorCode != null) {
+                        installFailCount++;
+                        CLog.w("Failed to install %s. Reason: %s", apkName, errorCode);
+                    }
+
+                }
+                if (installFailCount >= supportedAbiSet.size()) {
+                    CLog.e("Failed to install %s. See warning messages.", apkName);
                 }
             } catch (FileNotFoundException e) {
                 CLog.e("Could not find test apk %s", apkName);
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/GeeTest.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/GeeTest.java
index 9bfe151..6c2ed65 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/GeeTest.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/GeeTest.java
@@ -49,9 +49,9 @@
     private CtsBuildHelper mCtsBuild;
     private ITestDevice mDevice;
     private IAbi mAbi;
+    private String mExeName;
 
     private final String mPackageName;
-    private final String mExeName;
 
     public GeeTest(String packageName, String exeName) {
         mPackageName = packageName;
@@ -63,6 +63,7 @@
      */
     public void setAbi(IAbi abi) {
         mAbi = abi;
+        mExeName += mAbi.getBitness();
     }
 
     @Override
diff --git a/tools/utils/Android.mk b/tools/utils/Android.mk
index 36081ca..0ba5cf4 100644
--- a/tools/utils/Android.mk
+++ b/tools/utils/Android.mk
@@ -25,6 +25,6 @@
 LOCAL_CLASSPATH := $(HOST_JDK_TOOLS_JAR)
 
 LOCAL_JAVA_LIBRARIES := junit
-LOCAL_STATIC_JAVA_LIBRARIES := vogarexpectlib
+LOCAL_STATIC_JAVA_LIBRARIES := ctsabiutilslib vogarexpectlib
 
 include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/tools/utils/CollectAllTests.java b/tools/utils/CollectAllTests.java
index 367fb93..ed74824 100644
--- a/tools/utils/CollectAllTests.java
+++ b/tools/utils/CollectAllTests.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+import com.android.cts.util.AbiUtils;
 
 import org.junit.runner.RunWith;
 import org.w3c.dom.Document;
@@ -20,6 +21,7 @@
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 
+import vogar.Expectation;
 import vogar.ExpectationStore;
 
 import java.io.BufferedReader;
@@ -61,9 +63,9 @@
     private static final String TEST_TYPE = "LOCAL_TEST_TYPE :";
 
     public static void main(String[] args) {
-        if (args.length < 4 || args.length > 6) {
+        if (args.length < 5 || args.length > 7) {
             System.err.println("usage: CollectAllTests <output-file> <manifest-file> <jar-file> "
-                               + "<java-package> [expectation-dir [makefile-file]]");
+                               + "<java-package> <architecture> [expectation-dir [makefile-file]]");
             if (args.length != 0) {
                 System.err.println("received:");
                 for (String arg : args) {
@@ -86,8 +88,14 @@
                 return;
             }
         }
-        String libcoreExpectationDir = (args.length > 4) ? args[4] : null;
-        String androidMakeFile = (args.length > 5) ? args[5] : null;
+        String architecture = args[4];
+        if (architecture == null || architecture.equals("")) {
+            System.err.println("Invalid architecture");
+            System.exit(1);
+            return;
+        }
+        String libcoreExpectationDir = (args.length > 5) ? args[5] : null;
+        String androidMakeFile = (args.length > 6) ? args[6] : null;
 
         final TestType testType = TestType.getTestType(androidMakeFile);
 
@@ -207,7 +215,7 @@
 
                 try {
                     klass.getConstructor(new Class<?>[] { String.class } );
-                    addToTests(expectations, testCases, klass);
+                    addToTests(expectations, architecture, testCases, klass);
                     continue;
                 } catch (NoSuchMethodException e) {
                 } catch (SecurityException e) {
@@ -218,7 +226,7 @@
 
                 try {
                     klass.getConstructor(new Class<?>[0]);
-                    addToTests(expectations, testCases, klass);
+                    addToTests(expectations, architecture, testCases, klass);
                     continue;
                 } catch (NoSuchMethodException e) {
                 } catch (SecurityException e) {
@@ -356,6 +364,7 @@
     }
 
     private static void addToTests(ExpectationStore[] expectations,
+                                   String architecture,
                                    Map<String,TestClass> testCases,
                                    Class<?> testClass) {
         Set<String> testNames = new HashSet<String>();
@@ -386,11 +395,12 @@
             }
 
             testNames.add(testName);
-            addToTests(expectations, testCases, testClass, testName);
+            addToTests(expectations, architecture, testCases, testClass, testName);
         }
     }
 
     private static void addToTests(ExpectationStore[] expectations,
+                                   String architecture,
                                    Map<String,TestClass> testCases,
                                    Class<?> test,
                                    String testName) {
@@ -412,6 +422,10 @@
             return;
         }
 
+        Set<String> supportedAbis = VogarUtils.extractSupportedAbis(architecture,
+                                                                    expectations,
+                                                                    testClassName,
+                                                                    testName);
         TestClass testClass;
         if (testCases.containsKey(testClassName)) {
             testClass = testCases.get(testClassName);
@@ -420,7 +434,8 @@
             testCases.put(testClassName, testClass);
         }
 
-        testClass.mCases.add(new TestMethod(testName, "", "", knownFailure, false, false));
+        testClass.mCases.add(new TestMethod(testName, "", "", supportedAbis,
+              knownFailure, false, false));
     }
 
     private static boolean isJunit3Test(Class<?> klass) {
diff --git a/tools/utils/DescriptionGenerator.java b/tools/utils/DescriptionGenerator.java
index 607d2e5..09e1118 100644
--- a/tools/utils/DescriptionGenerator.java
+++ b/tools/utils/DescriptionGenerator.java
@@ -22,6 +22,7 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Iterator;
+import java.util.Set;
 
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
@@ -38,6 +39,7 @@
 import org.w3c.dom.NodeList;
 
 import vogar.ExpectationStore;
+import vogar.Expectation;
 
 import com.sun.javadoc.AnnotationDesc;
 import com.sun.javadoc.AnnotationTypeDoc;
@@ -82,11 +84,13 @@
     static final String ATTRIBUTE_VALUE_FRAMEWORK = "Android 1.0";
 
     static final String ATTRIBUTE_NAME = "name";
+    static final String ATTRIBUTE_ABIS = "abis";
     static final String ATTRIBUTE_HOST_CONTROLLER = "HostController";
 
     static final String XML_OUTPUT_PATH = "./description.xml";
 
     static final String OUTPUT_PATH_OPTION = "-o";
+    static final String ARCHITECTURE_OPTION = "-a";
 
     /**
      * Start to parse the classes passed in by javadoc, and generate
@@ -103,12 +107,21 @@
         }
 
         String outputPath = XML_OUTPUT_PATH;
+        String architecture = null;
         String[][] options = root.options();
         for (String[] option : options) {
-            if (option.length == 2 && option[0].equals(OUTPUT_PATH_OPTION)) {
-                outputPath = option[1];
+            if (option.length == 2) {
+                if (option[0].equals(OUTPUT_PATH_OPTION)) {
+                    outputPath = option[1];
+                } else if (option[0].equals(ARCHITECTURE_OPTION)) {
+                    architecture = option[1];
+                }
             }
         }
+        if (architecture == null || architecture.equals("")) {
+            Log.e("Missing architecture!", null);
+            return false;
+        }
 
         XMLGenerator xmlGenerator = null;
         try {
@@ -128,7 +141,7 @@
 
         for (ClassDoc clazz : classes) {
             if ((!clazz.isAbstract()) && (isValidJUnitTestCase(clazz))) {
-                xmlGenerator.addTestClass(new TestClass(clazz, ctsExpectationStore));
+                xmlGenerator.addTestClass(new TestClass(clazz, ctsExpectationStore, architecture));
             }
         }
 
@@ -420,6 +433,8 @@
                     Node caseNode = elem.appendChild(mDoc.createElement(TAG_TEST));
 
                     setAttribute(caseNode, ATTRIBUTE_NAME, caze.mName);
+                    String abis = caze.mAbis.toString();
+                    setAttribute(caseNode, ATTRIBUTE_ABIS, abis.substring(1, abis.length() - 1));
                     if ((caze.mController != null) && (caze.mController.length() != 0)) {
                         setAttribute(caseNode, ATTRIBUTE_HOST_CONTROLLER, caze.mController);
                     }
@@ -509,9 +524,9 @@
          *
          * @param clazz The specified ClassDoc.
          */
-        TestClass(ClassDoc clazz, ExpectationStore expectationStore) {
+        TestClass(ClassDoc clazz, ExpectationStore expectationStore, String architecture) {
             mName = clazz.toString();
-            mCases = getTestMethods(expectationStore, clazz);
+            mCases = getTestMethods(expectationStore, architecture, clazz);
         }
 
         /**
@@ -520,7 +535,8 @@
          * @param clazz The specified ClassDoc.
          * @return A collection of TestMethod.
          */
-        Collection<TestMethod> getTestMethods(ExpectationStore expectationStore, ClassDoc clazz) {
+        Collection<TestMethod> getTestMethods(ExpectationStore expectationStore,
+                String architecture, ClassDoc clazz) {
             Collection<MethodDoc> methods = getAllMethods(clazz);
 
             ArrayList<TestMethod> cases = new ArrayList<TestMethod>();
@@ -553,8 +569,13 @@
                 }
 
                 if (name.startsWith("test")) {
-                    cases.add(new TestMethod(name, method.commentText(), controller, knownFailure,
-                            isBroken, isSuppressed));
+                    Expectation expectation = expectationStore.get(
+                            VogarUtils.buildFullTestName(clazz.toString(), name));
+                    Set<String> supportedAbis =
+                            VogarUtils.extractSupportedAbis(architecture, expectation);
+                    cases.add(new TestMethod(
+                            name, method.commentText(), controller, supportedAbis,
+                                    knownFailure, isBroken, isSuppressed));
                 }
             }
 
@@ -610,6 +631,7 @@
         String mName;
         String mDescription;
         String mController;
+        Set<String> mAbis;
         String mKnownFailure;
         boolean mIsBroken;
         boolean mIsSuppressed;
@@ -621,11 +643,12 @@
          * @param description The description of the test case.
          * @param knownFailure The reason of known failure.
          */
-        TestMethod(String name, String description, String controller, String knownFailure,
-                boolean isBroken, boolean isSuppressed) {
+        TestMethod(String name, String description, String controller, Set<String> abis,
+                String knownFailure, boolean isBroken, boolean isSuppressed) {
             mName = name;
             mDescription = description;
             mController = controller;
+            mAbis = abis;
             mKnownFailure = knownFailure;
             mIsBroken = isBroken;
             mIsSuppressed = isSuppressed;
diff --git a/tools/utils/VogarUtils.java b/tools/utils/VogarUtils.java
index c7070a5..5e8b944 100644
--- a/tools/utils/VogarUtils.java
+++ b/tools/utils/VogarUtils.java
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+import com.android.cts.util.AbiUtils;
+
 import vogar.Expectation;
 import vogar.ExpectationStore;
 import vogar.ModeId;
@@ -38,12 +40,26 @@
         return false;
     }
 
+    /**
+     * @return true iff the class/name is found in the vogar known failure list and it is not
+     * a known failure that is a result of an unsupported abi.
+     */
     public static boolean isVogarKnownFailure(ExpectationStore expectationStore,
             final String testClassName,
             final String testMethodName) {
-        String fullTestName = String.format("%s#%s", testClassName, testMethodName);
-        return expectationStore != null
-                && expectationStore.get(fullTestName) != Expectation.SUCCESS;
+        if (expectationStore == null) {
+            return false;
+        }
+        String fullTestName = buildFullTestName(testClassName, testMethodName);
+        Expectation expectation = expectationStore.get(fullTestName);
+        if (expectation == Expectation.SUCCESS) {
+            return false;
+        }
+
+        String description = expectation.getDescription();
+        boolean foundAbi = AbiUtils.parseAbiList(description).size() > 0;
+
+        return expectation != Expectation.SUCCESS && !foundAbi;
     }
 
     public static ExpectationStore provideExpectationStore(String dir) throws IOException {
@@ -67,4 +83,49 @@
         }
         return expectSet;
     }
+
+    /** @return the test name in the form of com.android.myclass.TestClass#testMyMethod */
+    public static String buildFullTestName(String testClass, String testMethodName) {
+        return String.format("%s#%s", testClass, testMethodName);
+    }
+
+    /**
+     * This method looks in the description field of the Vogar entry for the ABI_LIST_MARKER
+     * and returns the list of abis found there.
+     *
+     * @return The Set of supported abis parsed from the {@code expectation}'s description.
+     */
+    public static Set<String> extractSupportedAbis(String architecture, Expectation expectation) {
+        Set<String> supportedAbiSet = AbiUtils.getAbisForArch(architecture);
+        if (expectation == null || expectation.getDescription().isEmpty()) {
+            // Include all abis since there was no limitation found in the description
+            return supportedAbiSet;
+        }
+
+        // Remove any abis that are not supported for the test.
+        supportedAbiSet.removeAll(AbiUtils.parseAbiList(expectation.getDescription()));
+
+        return supportedAbiSet;
+    }
+
+    /**
+     * Determine the correct set of ABIs for the given className/testName.
+     *
+     * @return the set of ABIs that can be expected to pass for the given combination of
+     * {@code architecture}, {@code className} and {@code testName}.
+     */
+    public static Set<String> extractSupportedAbis(String architecture,
+                                                   ExpectationStore[] expectationStores,
+                                                   String className,
+                                                   String testName) {
+
+        String fullTestName = VogarUtils.buildFullTestName(className, testName);
+        Set<String> supportedAbiSet = AbiUtils.getAbisForArch(architecture);
+        for (ExpectationStore expectationStore : expectationStores) {
+            Expectation expectation = expectationStore.get(fullTestName);
+            supportedAbiSet.retainAll(extractSupportedAbis(architecture, expectation));
+        }
+
+        return supportedAbiSet;
+    }
 }